Who am I?
Hamradio interests
Microwave contest
Ham IRC usermanual
Hamradio projects
Landslides control
My job
Buy online remote control duplicators, receivers, door openers
Remote controls, Receivers and door openers shop
Server ham
Software ham
SV Telemetric board
SV PacketCam
Utils SuperVozelj
Unsorted software
OpenOffice.org Tests
Electronic devices
ElectroMagnetic Compatiblity
Something about HTML
Linux publications
What's Linux?
Kernel hacking
AX.25 installation
EMail antivirus
Linux/Compaq EVO n115
Show QTH Locators on GoogleMaps
Travel photos
Humor about engineers
S53MV Homepage
A good lawyer in Italy
A nice photo

Linux server
Compressed with mod_gzip

Hosted on
Ir3ip Hamradio Server

Visualizza questa pagina in italiano

Kiss driver modification to immediately start in FLEX_CRC mode

Kiss driver (mkiss.c source in /usr/src/linux/driver/net/hamradio) is programmed to start in normal kiss mode.
As soon as it receive a frame, it analyze the first byte of encapsulated kiss frame to detect if a CRC have been used: possible CRC are Flexnet (RMNC) and SMACK.

Why a modification to the driver is needed?
In my case, i'm using a SuperVozelj node as TNC, which has the Flexnet_CRC capability to stat if a frame is good or corrupted, so the SuperVozelj RS232 port is configured in this mode.
Without the driver modification suggested below, as soon as i boot my Linux PC the KISS driver start in normal KISS mode, without CRC, so every frame to the SuperVozelj will be transmitted in KISS mode: all frames will be rejected by the SuperVozelj because they don't contains Flexnet CRC!.
This problem occurred until a frame will be received by the Linux driver (for example the beacon transmitted by the SuperVozelj every 5 minutes): in this case, mkiss driver stats that this is a Flexnet_CRC frame, and it switch to operate in this CRC mode.

The modification applied (in the source /usr/src/linux/driver/net/hamradio/mkiss.c) permit to start, by default, in Flexnet CRC mode: only one line must be added to the source!.
/* Initialize the driver.  Called by network startup. */
static int ax25_init(struct net_device *dev)
        struct ax_disp *ax = (struct ax_disp *) dev->priv;

        static char ax25_bcast[AX25_ADDR_LEN] =
                {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
        static char ax25_test[AX25_ADDR_LEN] =
                {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};

        if (ax == NULL)         /* Allocation failed ?? */
                return -ENODEV;

        /* Set up the "AX25 Control Block". (And clear statistics) */
        memset(ax, 0, sizeof (struct ax_disp));
        ax->magic  = AX25_MAGIC;
        ax->dev    = dev;
        ax->crcmode = CRC_MODE_FLEX;    // added by iw3grx to setup CRC_MODE

        /* Finish setting up the DEVICE info. */
        dev->mtu             = AX_MTU;
        dev->hard_start_xmit = ax_xmit;
        dev->open            = ax_open_dev;

Linux kernel modifications to get iso-interface ip-forwarding

Amateur radio network is not easy connectable: sometimes in the same lan there are hamradio hosts from several countries, which are connected to a central ip router throught our AX.25 level2 network using several bridges (here we are using SuperVozelj nodes, with 38400/1228800bps links, and very often i see ham hosts from Italy, Slovenia and Croatia).
Now is clear that our Local Area Network is not so local as we see in normal cabled LANs, and usually each host in the lan uses the nearest router as gateway to reach other hosts in the LAN.
With 2.0.x kernel there were no problems, but in the 2.2.x kernel the iso-interface ip forwarding was disabled.
Ivan 9a3wn suggest me the modifications for the Linux 2.2.x kernel, which now i will explain.
Enter linux kernel directory (usually with
cd /usr/src/linux
command), and then edit the file net/ax25/ax25_in.c, for example with the command
joe net/ax25/ax25_in.c
You must add 3 lines, marked below in bold font:

        if (pid == AX25_P_IP) {
                /* working around a TCP bug to keep additional listeners
                 * happy. TCP re-uses the buffer and destroys the original
                 * content.
                struct sk_buff *skbn = skb_copy(skb, GFP_ATOMIC);
                if (skbn != NULL) {
                        skb = skbn;

                skb_pull(skb, 1);       /* Remove PID */
                skb->h.raw    = skb->data;
                skb->nh.raw   = skb->data;
                skb->dev      = ax25->ax25_dev->dev;
                skb->pkt_type = PACKET_HOST;
                skb->protocol = __constant_htons(ETH_P_IP); // added for iso-interface forwarding
                ip_rcv(skb, skb->dev, NULL);    /* Wrong ptype */
                return 1;


                        case AX25_P_IP:
                                skb_pull(skb,2);                /* drop PID/CTRL */
                                skb->h.raw    = skb->data;
                                skb->nh.raw   = skb->data;
                                skb->dev      = dev;
                                skb->pkt_type = PACKET_HOST;
                                skb->protocol = __constant_htons(ETH_P_IP); // added for iso-iface fwd
                                ip_rcv(skb, dev, ptype);        /* Note ptype here is the wrong one, fix me later */

                        case AX25_P_ARP:
                                skb->h.raw    = skb->data;
                                skb->nh.raw   = skb->data;
                                skb->dev      = dev;
                                skb->pkt_type = PACKET_HOST;
                                skb->protocol = __constant_htons(ETH_P_ARP); // added for iso-iface fwd
                                arp_rcv(skb, dev, ptype);       /* Note ptype here is wrong... */


Modifications to ax25 route daemon

This modification is intended to permit ax25 route daemon to automatically add route/arp entries in the route/arp tables for hosts that are not inside the network mask.
Infact, in the normal configuration ax25rtd only update route/arp table for hosts that are inside the netmask of the interface which receive the ip datagrams, but this is not a good solution for routers that receive datagrams from Italy, Slovenia and Croatia as my router does, because the radio interface netmask must be as closed as possible: infact many hosts are connectable throught the internet ham gateway
The modification to the ax25rtd is very simple: at the bootstrap, the daemon must NOT load the interface netmask, but the netmask (which cover all the amateur radio hosts): the silly modification is indicated below in bold font, and must be made in the ax25-apps-0.0.4/ax25rtd/config.c file:


                for (config = Config; config; config = config->next)
                        if (!memcmp(&config->mycalls[0], ifr.ifr_hwaddr.sa_data, AXLEN) && !*config->dev)
                                strcpy(config->dev, ifr.ifr_name);
                                ioctl(fd, SIOCGIFADDR, &ifr);
                                config->ip = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
                                strcpy(ifr.ifr_name, config->dev);
                                ioctl(fd, SIOCGIFNETMASK, &ifr);
// instead of loading interface netmask, load to cover all the network!
//                              config->netmask = ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr;
                                config->netmask = 0x0000ff;

        config = cfg = Config;


Modifications to the kernel mkiss driver

Why? Because i need to know how many bytes of data was RXed and TXed by kiss/crckiss ports.
This is useful for certain statistics programs, like MRTG, a very nice port load statistics report for the web.

First, cd to /usr/src/linux/driver/net/hamradio and then add the lines indicated with bold font to the file mkiss.h:
        /* SLIP interface statistics. */
        unsigned long      rx_packets;          /* inbound frames counter       */
        unsigned long      tx_packets;          /* outbound frames counter      */
        unsigned long      rx_bytes;            // inbound octets counter
        unsigned long      tx_bytes;            // outbound octets counter
        unsigned long      rx_errors;           /* Parity, etc. errors          */
        unsigned long      tx_errors;           /* Planned stuff                */
        unsigned long      rx_dropped;          /* No memory for skb            */
        unsigned long      tx_dropped;          /* When MTU change              */
        unsigned long      rx_over_errors;      /* Frame bigger then SLIP buf.  */
Then, add 4 lines to the source file mkiss.c:
static void ax_bump(struct ax_disp *ax)
        count = ax->rcount;

        if ((skb = dev_alloc_skb(count)) == NULL) {
                printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name);

/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
static int ax_xmit(struct sk_buff *skb, struct device *dev)
        /* We were not busy, so we are now... :-) */
        if (skb != NULL) {
                if (tmp_ax != NULL)
                ax_encaps(ax, skb->data, skb->len);

        return 0;

static struct net_device_stats *ax_get_stats(struct device *dev)
        static struct net_device_stats stats;
        struct ax_disp *ax = (struct ax_disp*)(dev->priv);

        memset(&stats, 0, sizeof(struct net_device_stats));

        stats.rx_packets     = ax->rx_packets;
        stats.tx_packets     = ax->tx_packets;
        stats.rx_bytes       = ax->rx_bytes;
        stats.tx_bytes       = ax->tx_bytes;
        stats.rx_dropped     = ax->rx_dropped;
        stats.tx_dropped     = ax->tx_dropped;
        stats.tx_errors      = ax->tx_errors;
        stats.rx_errors      = ax->rx_errors;
        stats.rx_over_errors = ax->rx_over_errors;

        return &stats;

Finally, recompile the kernel!
cd /usr/src/linux && make dep && make bzImage && make modules && make modules_install

Modifications to netromd daemon to permit routing with X-Net

Xnet nodes send netrom broadcasts to the callsign of the neighbour node, instead to NODES. This is the reason why netromd does not store in its nodes list the nodes received from a X-Net neighbour.
To avoid this problem there are two solutions:
  1. X-Net should be modified to send broadcasts to NODES, but this is quite difficult because X-Net is a closed source product
  2. Modify netromd to listen to every broadcast with PID=0xCF. The latter is the simpler solution, just download the ax25-tools sources, and modify the file netrom/netromd.c: here is the original part which should be modified
          if (ax25_cmp((ax25_address *)(buffer + 1), &node_call) == 0 &&
              ax25_cmp((ax25_address *)(buffer + 8), &my_call)   != 0 &&
              buffer[16] == NETROM_PID && buffer[17] == NODES_SIG) {
            for (i = 0; i < port_count; i++) {
    and here is the modified version, which permit to receive broadcasts from X-Net:
          if (/* ax25_cmp((ax25_address *)(buffer + 1), &node_call) == 0 && */ 
              ax25_cmp((ax25_address *)(buffer + 8), &my_call)   != 0 &&
              buffer[16] == NETROM_PID && buffer[17] == NODES_SIG) {
            for (i = 0; i < port_count; i++) {