Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.4.1 /net/ipx/af_ipx.c

Filename:/net/ipx/af_ipx.c
Lines Added:576
Lines Deleted:718
Also changed in: (Previous) 2.4.1-pre12  2.4.1-pre11  2.4.1-pre10  2.4.0-ac12  2.4.0-ac11  2.4.0-ac10 
(Following) 2.4.1-ac10  2.4.1-ac11  2.4.1-ac12  2.4.1-ac13  2.4.1-ac14  2.4.1-ac15 

Location
[  2.4.1
  [  net
    [  ipx
       o  af_ipx.c

Patch

diff -u --recursive --new-file v2.4.0/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.4.0/linux/net/ipx/af_ipx.c   Sun Dec  3 18:01:01 2000
+++ linux/net/ipx/af_ipx.c   Mon Jan 22 13:32:10 2001
@@ -61,6 +61,9 @@
  *         suggestions and guidance.
  *         Arnaldo Carvalho de Melo <acme@conectiva.com.br>,
  *         November, 2000
+ *   Revision 043:   Shared SKBs, don't mangle packets, some cleanups
+ *         Arnaldo Carvalho de Melo <acme@conectiva.com.br>,
+ *         December, 2000
  *
  *   Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
  *   pair. Also, now usage count is managed this way
@@ -140,28 +143,23 @@
 atomic_t ipx_sock_nr;
 #endif
 
-static int ipxcfg_set_auto_create(char val)
+static void ipxcfg_set_auto_create(char val)
 {
-   if(ipxcfg_auto_create_interfaces != val)
-   {
-      if(val)
+   if (ipxcfg_auto_create_interfaces != val) {
+      if (val)
          MOD_INC_USE_COUNT;
       else
          MOD_DEC_USE_COUNT;
 
       ipxcfg_auto_create_interfaces = val;
    }
-
-   return (0);
 }
 
-static int ipxcfg_set_auto_select(char val)
+static void ipxcfg_set_auto_select(char val)
 {
    ipxcfg_auto_select_primary = val;
-   if(val && (ipx_primary_net == NULL))
+   if (val && !ipx_primary_net)
       ipx_primary_net = ipx_interfaces;
-
-   return (0);
 }
 
 static int ipxcfg_get_config_data(ipx_config_data *arg)
@@ -171,7 +169,7 @@
    vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
    vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary;
 
-   return (copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0);
+   return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0;
 }
 
 /**************************************************************************\
@@ -213,22 +211,19 @@
 
    /* Determine interface with which socket is associated */
    intrfc = sk->protinfo.af_ipx.intrfc;
-   if(intrfc == NULL)
+   if (!intrfc)
       return;
 
    ipxitf_hold(intrfc);
    spin_lock_bh(&intrfc->if_sklist_lock);
    s = intrfc->if_sklist;
-   if(s == sk)
-   {
+   if (s == sk) {
       intrfc->if_sklist = s->next;
       goto out;
    }
 
-   while(s && s->next)
-   {
-      if(s->next == sk)
-      {
+   while (s && s->next) {
+      if (s->next == sk) {
          s->next = sk->next;
          goto out;
       }
@@ -264,7 +259,7 @@
 
 static void ipxitf_clear_primary_net(void)
 {
-   if(ipxcfg_auto_select_primary && (ipx_interfaces != NULL))
+   if (ipxcfg_auto_select_primary && ipx_interfaces)
       ipx_primary_net = ipx_interfaces;
    else
       ipx_primary_net = NULL;
@@ -273,14 +268,14 @@
 static ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
                   unsigned short datalink)
 {
-   ipx_interface   *i;
+   ipx_interface *i;
 
-   for(i = ipx_interfaces;
-      i && ((i->if_dev != dev) || (i->if_dlink_type != datalink));
+   for (i = ipx_interfaces;
+      i && (i->if_dev != dev || i->if_dlink_type != datalink);
       i = i->if_next)
       ;
 
-   return (i);
+   return i;
 }
 
 static ipx_interface *ipxitf_find_using_phys(struct net_device *dev,
@@ -298,12 +293,12 @@
 
 static ipx_interface *ipxitf_find_using_net(__u32 net)
 {
-   ipx_interface   *i;
+   ipx_interface *i;
 
    spin_lock_bh(&ipx_interfaces_lock);
-   if(net)
-      for(i = ipx_interfaces; i && (i->if_netnum != net);
-         i = i->if_next)
+   if (net)
+      for (i = ipx_interfaces; i && i->if_netnum != net;
+           i = i->if_next)
       ;
    else
       i = ipx_primary_net;
@@ -311,7 +306,7 @@
       ipxitf_hold(i);
    spin_unlock_bh(&ipx_interfaces_lock);
 
-   return (i);
+   return i;
 }
 
 /* Sockets are bound to a particular IPX interface. */
@@ -324,11 +319,10 @@
    spin_lock_bh(&intrfc->if_sklist_lock);
    sk->protinfo.af_ipx.intrfc = intrfc;
    sk->next = NULL;
-   if(intrfc->if_sklist == NULL)
+   if (!intrfc->if_sklist)
       intrfc->if_sklist = sk;
-   else
-   {
-      for (s = intrfc->if_sklist; s->next != NULL; s = s->next)
+   else {
+      for (s = intrfc->if_sklist; s->next; s = s->next)
          ;
       s->next = sk;
    }
@@ -337,19 +331,21 @@
 }
 
 /* caller must hold intrfc->if_sklist_lock */
-static struct sock *__ipxitf_find_socket(ipx_interface *intrfc, unsigned short port)
+static struct sock *__ipxitf_find_socket(ipx_interface *intrfc,
+                unsigned short port)
 {
    struct sock *s;
 
-   for(s = intrfc->if_sklist;
-      (s != NULL) && (s->protinfo.af_ipx.port != port);
-      s = s->next)
+   for (s = intrfc->if_sklist;
+        s && s->protinfo.af_ipx.port != port;
+        s = s->next)
       ;
    return s;
 }
 
 /* caller must hold a reference to intrfc */
-static struct sock *ipxitf_find_socket(ipx_interface *intrfc, unsigned short port)
+static struct sock *ipxitf_find_socket(ipx_interface *intrfc,
+               unsigned short port)
 {
    struct sock *s;
 
@@ -359,11 +355,10 @@
       sock_hold(s);
    spin_unlock_bh(&intrfc->if_sklist_lock);
 
-   return (s);
+   return s;
 }
 
 #ifdef CONFIG_IPX_INTERN
-
 static struct sock *ipxitf_find_internal_socket(ipx_interface *intrfc,
              unsigned char *node, unsigned short port)
 {
@@ -373,19 +368,16 @@
    spin_lock_bh(&intrfc->if_sklist_lock);
    s = intrfc->if_sklist;
 
-   while(s != NULL)
-   {
-      if((s->protinfo.af_ipx.port == port)
-          && (memcmp(node, s->protinfo.af_ipx.node, IPX_NODE_LEN) == 0))
-      {
+   while (s) {
+      if (s->protinfo.af_ipx.port == port &&
+          !memcmp(node, s->protinfo.af_ipx.node, IPX_NODE_LEN))
          break;
-      }
       s = s->next;
    }
    spin_unlock_bh(&intrfc->if_sklist_lock);
    ipxitf_put(intrfc);
 
-   return (s);
+   return s;
 }
 #endif
 
@@ -401,8 +393,7 @@
 
    spin_lock_bh(&intrfc->if_sklist_lock);
    /* error sockets */
-   for(s = intrfc->if_sklist; s != NULL; )
-   {
+   for (s = intrfc->if_sklist; s; ) {
       s->err = ENOLINK;
       s->error_report(s);
       s->protinfo.af_ipx.intrfc = NULL;
@@ -416,30 +407,27 @@
    spin_unlock_bh(&intrfc->if_sklist_lock);
 
    /* remove this interface from list */
-   if(intrfc == ipx_interfaces)
+   if (intrfc == ipx_interfaces)
       ipx_interfaces = intrfc->if_next;
-   else
-   {
-      for(i = ipx_interfaces;
-         (i != NULL) && (i->if_next != intrfc);
-         i = i->if_next)
+   else {
+      for (i = ipx_interfaces;
+           i && i->if_next != intrfc;
+           i = i->if_next)
          ;
-      if((i != NULL) && (i->if_next == intrfc))
+      if (i && i->if_next == intrfc)
          i->if_next = intrfc->if_next;
    }
 
    /* remove this interface from *special* networks */
-   if(intrfc == ipx_primary_net)
+   if (intrfc == ipx_primary_net)
       ipxitf_clear_primary_net();
-   if(intrfc == ipx_internal_net)
+   if (intrfc == ipx_internal_net)
       ipx_internal_net = NULL;
 
    if (intrfc->if_dev)
       dev_put(intrfc->if_dev);
    kfree(intrfc);
    MOD_DEC_USE_COUNT;
-
-   return;
 }
 
 static void ipxitf_down(ipx_interface *intrfc)
@@ -449,36 +437,31 @@
    spin_unlock_bh(&ipx_interfaces_lock);
 }
 
-static int ipxitf_device_event(struct notifier_block *notifier, unsigned long event, void *ptr)
+static int ipxitf_device_event(struct notifier_block *notifier,
+            unsigned long event, void *ptr)
 {
    struct net_device *dev = ptr;
    ipx_interface *i, *tmp;
 
-   if(event != NETDEV_DOWN)
+   if (event != NETDEV_DOWN)
       return NOTIFY_DONE;
 
    spin_lock_bh(&ipx_interfaces_lock);
-   for(i = ipx_interfaces; i != NULL;)
-   {
+   for (i = ipx_interfaces; i;) {
       tmp = i->if_next;
-      if(i->if_dev == dev)
+      if (i->if_dev == dev)
          __ipxitf_put(i);
       i = tmp;
 
    }
    spin_unlock_bh(&ipx_interfaces_lock);
-
-   return (NOTIFY_DONE);
+   return NOTIFY_DONE;
 }
 
-static int ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
+static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
 {
-   int retval;
-
-   if((retval = sock_queue_rcv_skb(sock, skb)) < 0)
+   if (sock_queue_rcv_skb(sock, skb) < 0)
       kfree_skb(skb);
-
-   return (retval);
 }
 
 /*
@@ -500,57 +483,50 @@
    spin_lock_bh(&intrfc->if_sklist_lock);
    s = intrfc->if_sklist;
 
-   while(s != NULL)
-   {
-      if((s->protinfo.af_ipx.port == ipx->ipx_dest.sock)
-          && (is_broadcast
-         || (memcmp(ipx->ipx_dest.node, s->protinfo.af_ipx.node,
-               IPX_NODE_LEN) == 0)))
-      {
+   while (s) {
+      if (s->protinfo.af_ipx.port == ipx->ipx_dest.sock &&
+          (is_broadcast || !memcmp(ipx->ipx_dest.node,
+                    s->protinfo.af_ipx.node,
+                    IPX_NODE_LEN))) {
          /* We found a socket to which to send */
          struct sk_buff *skb1;
 
-         if(copy != 0)
-         {
+         if (copy) {
             skb1 = skb_clone(skb, GFP_ATOMIC);
             ret = -ENOMEM;
-            if (skb1 == NULL)
+            if (!skb1)
                goto out;
-         }
-         else
-         {
+         } else {
             skb1 = skb;
             copy = 1; /* skb may only be used once */
          }
          ipxitf_def_skb_handler(s, skb1);
 
          /* On an external interface, one socket can listen */
-         if(intrfc != ipx_internal_net)
+         if (intrfc != ipx_internal_net)
             break;
       }
       s = s->next;
    }
 
    /* skb was solely for us, and we did not make a copy, so free it. */
-   if(copy == 0)
+   if (!copy)
       kfree_skb(skb);
 
    ret = 0;
 out:   spin_unlock_bh(&intrfc->if_sklist_lock);
    return ret;
 }
-
 #else
-
-static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
+static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb,
+            int copy)
 {
    struct ipxhdr *ipx = skb->nh.ipxh;
    struct sock *sock1 = NULL, *sock2 = NULL;
    struct sk_buff *skb1 = NULL, *skb2 = NULL;
    int ret;
 
-   if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451) 
-   {
+   if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451) {
       /* 
         * The packet's target is a NCP connection handler. We want to
         * hand it to the correct socket directly within the kernel,
@@ -562,48 +538,34 @@
         * VERY fast as well.
         */
        int connection = 0;
+      u8 *ncphdr = (u8 *)(ipx + 1);
 
-       if (*((char*)(ipx+1)) == 0x22 &&  *((char*)(ipx+1)+1) == 0x22) 
-      {
-           /*
-          * The packet is a NCP request
-          */
-         connection = ( ((int) *((char*)(ipx+1)+5)) << 8 )
-                 | (int) *((char*)(ipx+1)+3);
-      } 
-      else if (*((char*)(ipx+1))== 0x77 &&  *((char*)(ipx+1)+1) == 0x77) 
-      {
-         /*
-          * The packet is a BURST packet
-          */
-         connection = ( ((int) *((char*)(ipx+1)+9)) << 8 )
-                 | (int) *((char*)(ipx+1)+8);
-      }
-
-           if (connection) 
-      {
-         /*
-          * Now we have to look for a special NCP connection handling
-          * socket. Only these sockets have ipx_ncp_conn != 0, set
-          * by SIOCIPXNCPCONN.
-          */
+       if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22)
+           /* The packet is a NCP request */
+         connection = (((int) *(ncphdr + 5)) << 8) |
+               (int) *(ncphdr+3);
+      else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77)
+         /* The packet is a BURST packet */
+         connection = (((int) *(ncphdr+9)) << 8) |
+               (int) *(ncphdr+8);
+
+           if (connection) {
+         /* Now we have to look for a special NCP connection
+          * handling socket. Only these sockets have
+          * ipx_ncp_conn != 0, set by SIOCIPXNCPCONN. */
          spin_lock_bh(&intrfc->if_sklist_lock);
-         for (sock1=intrfc->if_sklist;
-            (sock1 != NULL) &&
-            (sock1->protinfo.af_ipx.ipx_ncp_conn != connection);
-               sock1=sock1->next);
+         for (sock1 = intrfc->if_sklist;
+              sock1 &&
+              sock1->protinfo.af_ipx.ipx_ncp_conn != connection;
+              sock1 = sock1->next);
          if (sock1)
             sock_hold(sock1);
          spin_unlock_bh(&intrfc->if_sklist_lock);
       }
         }
-        if (sock1 == NULL) 
-   {
-      /* No special socket found, forward the packet the
-       * normal way.
-       */
+        if (!sock1)
+      /* No special socket found, forward the packet the normal way */
       sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
-   }
 
    /*
     * We need to check if there is a primary net and if
@@ -613,10 +575,8 @@
     * 0x456(Diagnostic).
     */
 
-   if(ipx_primary_net && (intrfc != ipx_primary_net))
-   {
-      switch(ntohs(ipx->ipx_dest.sock))
-      {
+   if (ipx_primary_net && intrfc != ipx_primary_net) {
+      switch (ntohs(ipx->ipx_dest.sock)) {
          case 0x452:
          case 0x453:
          case 0x456:
@@ -637,11 +597,10 @@
    /*
     * If there is nothing to do return. The kfree will cancel any charging.
     */
-   if(sock1 == NULL && sock2 == NULL)
-   {
-      if(!copy)
+   if (!sock1 && !sock2) {
+      if (!copy)
          kfree_skb(skb);
-      return (0);
+      return 0;
    }
 
    /*
@@ -652,30 +611,30 @@
     * copies, we do as much as is possible.
     */
 
-   if(copy)
+   if (copy)
       skb1 = skb_clone(skb, GFP_ATOMIC);
    else
       skb1 = skb;
 
    ret = -ENOMEM;
-   if(skb1 == NULL)
+   if (!skb1)
       goto out;
 
    /* Do we need 2 SKBs? */
-   if(sock1 && sock2)
+   if (sock1 && sock2)
       skb2 = skb_clone(skb1, GFP_ATOMIC);
    else
       skb2 = skb1;
 
-   if(sock1)
-      (void) ipxitf_def_skb_handler(sock1, skb1);
+   if (sock1)
+      ipxitf_def_skb_handler(sock1, skb1);
 
    ret = -ENOMEM;
-   if(skb2 == NULL)
+   if (!skb2)
       goto out;
 
-   if(sock2)
-      (void) ipxitf_def_skb_handler(sock2, skb2);
+   if (sock2)
+      ipxitf_def_skb_handler(sock2, skb2);
 
    ret = 0;
 out:   if (sock1)
@@ -686,7 +645,8 @@
 }
 #endif   /* CONFIG_IPX_INTERN */
 
-static struct sk_buff *ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buff *skb)
+static struct sk_buff *ipxitf_adjust_skbuff(ipx_interface *intrfc,
+                   struct sk_buff *skb)
 {
    struct sk_buff *skb2;
    int in_offset = skb->h.raw - skb->head;
@@ -694,21 +654,21 @@
    int len;
 
    /* Hopefully, most cases */
-   if(in_offset >= out_offset)
-      return (skb);
+   if (in_offset >= out_offset)
+      return skb;
 
    /* Need new SKB */
    len  = skb->len + out_offset;
    skb2 = alloc_skb(len, GFP_ATOMIC);
-   if(skb2 != NULL)
-   {
+   if (skb2) {
       skb_reserve(skb2, out_offset);
       skb2->nh.raw =
       skb2->h.raw = skb_put(skb2,skb->len);
       memcpy(skb2->h.raw, skb->h.raw, skb->len);
+      memcpy(skb2->cb, skb->cb, sizeof(skb->cb));
    }
    kfree_skb(skb);
-   return (skb2);
+   return skb2;
 }
 
 /* caller must hold a reference to intrfc */
@@ -716,6 +676,7 @@
 static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
 {
    struct ipxhdr *ipx = skb->nh.ipxh;
+   struct ipx_cb *cb = (struct ipx_cb *) skb->cb;
    struct net_device *dev = intrfc->if_dev;
    struct datalink_proto *dl = intrfc->if_dlink;
    char dest_node[IPX_NODE_LEN];
@@ -727,7 +688,7 @@
     * packet to avoid unnecessary copies.
     */
     
-   if((dl == NULL) || (dev == NULL) || (dev->flags & IFF_LOOPBACK)) 
+   if (!dl || !dev || dev->flags & IFF_LOOPBACK) 
       send_to_wire = 0;   /* No non looped */
 
    /*
@@ -737,30 +698,27 @@
     * up clones.
     */
     
-   if(ipx->ipx_dest.net == intrfc->if_netnum) 
-   {
+   if (cb->ipx_dest_net == intrfc->if_netnum) {
       /*
        * To our own node, loop and free the original.
        * The internal net will receive on all node address.
        */
-      if((intrfc == ipx_internal_net)
-          || memcmp(intrfc->if_node, node, IPX_NODE_LEN) == 0) 
-      {
+      if (intrfc == ipx_internal_net ||
+          !memcmp(intrfc->if_node, node, IPX_NODE_LEN)) {
          /* Don't charge sender */
          skb_orphan(skb);
 
          /* Will charge receiver */
-         return (ipxitf_demux_socket(intrfc, skb, 0));
+         return ipxitf_demux_socket(intrfc, skb, 0);
       }
 
       /* Broadcast, loop and possibly keep to send on. */
-      if(memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0)
-      {
-         if(!send_to_wire)
+      if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN)) {
+         if (!send_to_wire)
             skb_orphan(skb);
          ipxitf_demux_socket(intrfc, skb, send_to_wire);
-         if(!send_to_wire)
-            return (0);
+         if (!send_to_wire)
+            return 0;
       }
    }
 
@@ -769,36 +727,45 @@
     * We are still charging the sender. Which is right - the driver
     * free will handle this fairly.
     */
-   if(ipx->ipx_source.net != intrfc->if_netnum)
-   {
+   if (cb->ipx_source_net != intrfc->if_netnum) {
       /*
        * Unshare the buffer before modifying the count in
        * case its a flood or tcpdump
        */
       skb = skb_unshare(skb, GFP_ATOMIC);
-      if(!skb)
-         return (0);
-      if(++(ipx->ipx_tctrl) > ipxcfg_max_hops)
+      if (!skb)
+         return 0;
+      if (++(cb->ipx_tctrl) > ipxcfg_max_hops)
          send_to_wire = 0;
    }
 
-   if(!send_to_wire)
-   {
+   if (!send_to_wire) {
       kfree_skb(skb);
-      return (0);
+      return 0;
    }
 
    /* Determine the appropriate hardware address */
    addr_len = dev->addr_len;
-   if(memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0)
+   if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN))
       memcpy(dest_node, dev->broadcast, addr_len);
    else
       memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len);
 
    /* Make any compensation for differing physical/data link size */
    skb = ipxitf_adjust_skbuff(intrfc, skb);
-   if(skb == NULL)
-      return (0);
+   if (!skb)
+      return 0;
+
+   ipx->ipx_tctrl = cb->ipx_tctrl;
+   ipx->ipx_dest.net = cb->ipx_dest_net;
+   ipx->ipx_source.net = cb->ipx_source_net;
+   /* see if we need to include the netnum in the route list */
+   if (cb->last_hop_index >= 0) {
+      u32 *last_hop = (u32 *)(((u8 *) skb->data) +
+            sizeof(struct ipxhdr) + cb->last_hop_index *
+            sizeof(u32));
+      *last_hop = intrfc->if_netnum;
+   }
 
    /* set up data link and physical headers */
    skb->dev = dev;
@@ -807,15 +774,14 @@
 
    /* Send it out */
    dev_queue_xmit(skb);
-
-   return (0);
+   return 0;
 }
 
 static int ipxrtr_add_route(__u32, ipx_interface *, unsigned char *);
 
 static int ipxitf_add_local_route(ipx_interface *intrfc)
 {
-   return (ipxrtr_add_route(intrfc->if_netnum, intrfc, NULL));
+   return ipxrtr_add_route(intrfc->if_netnum, intrfc, NULL);
 }
 
 static const char * ipx_frame_name(unsigned short);
@@ -824,29 +790,26 @@
 static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
 {
    struct ipxhdr   *ipx = skb->nh.ipxh;
-   ipx_interface   *i;
+   struct ipx_cb *cb = (struct ipx_cb *) skb->cb;
    int ret = 0;
 
    ipxitf_hold(intrfc);
 
    /* See if we should update our network number */
-   if(!intrfc->if_netnum  /* net number of intrfc not known yet (== 0) */
-      && (ipx->ipx_source.net == ipx->ipx_dest.net) /* intra packet */
-      && ipx->ipx_source.net)  /* source net number of packet != 0 */
-   {
+   if (!intrfc->if_netnum && /* net number of intrfc not known yet */
+      cb->ipx_source_net == cb->ipx_dest_net && /* intra packet */
+      cb->ipx_source_net) {
+      ipx_interface *i = ipxitf_find_using_net(cb->ipx_source_net);
       /* NB: NetWare servers lie about their hop count so we
        * dropped the test based on it.  This is the best way
        * to determine this is a 0 hop count packet.
        */
-      if((i=ipxitf_find_using_net(ipx->ipx_source.net)) == NULL)
-      {
-         intrfc->if_netnum = ipx->ipx_source.net;
-         (void) ipxitf_add_local_route(intrfc);
-      }
-      else
-      {
+      if (!i) {
+         intrfc->if_netnum = cb->ipx_source_net;
+         ipxitf_add_local_route(intrfc);
+      } else {
          printk(KERN_WARNING "IPX: Network number collision %lx\n        %s %s and %s %s\n",
-            (long unsigned int) htonl(ipx->ipx_source.net),
+            (long unsigned int) htonl(cb->ipx_source_net),
             ipx_device_name(i),
             ipx_frame_name(i->if_dlink_type),
             ipx_device_name(intrfc),
@@ -854,75 +817,63 @@
          ipxitf_put(i);
       }
    }
+   
+   cb->last_hop_index = -1;
 
-   if(ipx->ipx_type == IPX_TYPE_PPROP
-      && ipx->ipx_tctrl < 8 
-      && skb->pkt_type != PACKET_OTHERHOST
-         /* header + 8 network numbers */ 
-      && ntohs(ipx->ipx_pktsize) >= sizeof(struct ipxhdr) + 8 * 4) 
-   {
+   if (ipx->ipx_type == IPX_TYPE_PPROP && cb->ipx_tctrl < 8 &&
+       skb->pkt_type != PACKET_OTHERHOST &&
+       /* header + 8 network numbers */ 
+       ntohs(ipx->ipx_pktsize) >= sizeof(struct ipxhdr) + 8 * 4) {
       int i;
            ipx_interface *ifcs;
       struct sk_buff *skb2;
-        __u32 *l;
-      char *c;
-      
-      c = (char *) skb->data;
-      c += sizeof(struct ipxhdr);
-      l = (__u32 *) c;
-
-      i = 0;
+      char *c = ((char *) skb->data) + sizeof(struct ipxhdr);
+        u32 *l = (u32 *) c;
 
       /* Dump packet if already seen this net */
-      for( ; i < ipx->ipx_tctrl; i++)
-         if(*l++ == intrfc->if_netnum)
+      for (i = 0; i < cb->ipx_tctrl; i++)
+         if (*l++ == intrfc->if_netnum)
             break;
 
-      if(i == ipx->ipx_tctrl) 
-      { 
+      if (i == cb->ipx_tctrl) {
          /* < 8 hops && input itfc not in list */
-         *l = intrfc->if_netnum; /* insert recvd netnum into list */
-         ipx->ipx_tctrl++;
+          /* insert recvd netnum into list */
+         cb->last_hop_index = i;
+         cb->ipx_tctrl++;
          /* xmit on all other interfaces... */
          spin_lock_bh(&ipx_interfaces_lock);
-         for(ifcs = ipx_interfaces; ifcs != NULL; ifcs = ifcs->if_next) 
-         {
+         for (ifcs = ipx_interfaces; ifcs;
+              ifcs = ifcs->if_next) {
             /* Except unconfigured interfaces */
-            if(ifcs->if_netnum == 0)
+            if (!ifcs->if_netnum)
                continue;
                
             /* That aren't in the list */
             l = (__u32 *) c;
-            for(i = 0; i <= ipx->ipx_tctrl; i++)
-               if(ifcs->if_netnum == *l++)
+            for (i = 0; i <= cb->ipx_tctrl; i++)
+               if (ifcs->if_netnum == *l++)
                   break;
-            if(i - 1 == ipx->ipx_tctrl) 
-            {
-               ipx->ipx_dest.net = ifcs->if_netnum;
+            if (i - 1 == cb->ipx_tctrl) {
+               cb->ipx_dest_net = ifcs->if_netnum;
                skb2=skb_clone(skb, GFP_ATOMIC);
                if (skb2)
                   ipxrtr_route_skb(skb2);
             }
          }
          spin_unlock_bh(&ipx_interfaces_lock);
-
-         /* Reset network number in packet */
-         ipx->ipx_dest.net = intrfc->if_netnum;
       }
    }
 
-   if(!ipx->ipx_dest.net)
-      ipx->ipx_dest.net = intrfc->if_netnum;
-   if(!ipx->ipx_source.net)
-      ipx->ipx_source.net = intrfc->if_netnum;
+   if (!cb->ipx_dest_net)
+      cb->ipx_dest_net = intrfc->if_netnum;
+   if (!cb->ipx_source_net)
+      cb->ipx_source_net = intrfc->if_netnum;
 
-   if(intrfc->if_netnum != ipx->ipx_dest.net)
-   {
+   if (intrfc->if_netnum != cb->ipx_dest_net) {
       /* We only route point-to-point packets. */
-      if(skb->pkt_type == PACKET_HOST)
-      {
+      if (skb->pkt_type == PACKET_HOST) {
          skb=skb_unshare(skb, GFP_ATOMIC);
-         if(skb)
+         if (skb)
             ret = ipxrtr_route_skb(skb);
          goto out_intrfc;
       }
@@ -931,9 +882,8 @@
    }
 
    /* see if we should keep it */
-   if((memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0)
-      || (memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0))
-   {
+   if (!memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) ||
+       !memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN)) {
       ret = ipxitf_demux_socket(intrfc, skb, 0);
       goto out_intrfc;
    }
@@ -952,20 +902,17 @@
 
    intrfc->if_next = NULL;
    spin_lock_bh(&ipx_interfaces_lock);
-   if(ipx_interfaces == NULL)
+   if (!ipx_interfaces)
       ipx_interfaces = intrfc;
-   else
-   {
-      for(i = ipx_interfaces; i->if_next != NULL; i = i->if_next)
+   else {
+      for (i = ipx_interfaces; i->if_next; i = i->if_next)
          ;
       i->if_next = intrfc;
    }
    spin_unlock_bh(&ipx_interfaces_lock);
 
-   if(ipxcfg_auto_select_primary && (ipx_primary_net == NULL))
+   if (ipxcfg_auto_select_primary && !ipx_primary_net)
       ipx_primary_net = intrfc;
-
-   return;
 }
 
 static int ipxitf_create_internal(ipx_interface_definition *idef)
@@ -974,21 +921,21 @@
    int ret;
 
    /* Only one primary network allowed */
-   if(ipx_primary_net != NULL)
-      return (-EEXIST);
+   if (ipx_primary_net)
+      return -EEXIST;
 
    /* Must have a valid network number */
-   if(!idef->ipx_network)
-      return (-EADDRNOTAVAIL);
+   if (!idef->ipx_network)
+      return -EADDRNOTAVAIL;
    intrfc = ipxitf_find_using_net(idef->ipx_network);
-   if(intrfc != NULL) {
+   if (intrfc) {
       ipxitf_put(intrfc);
-      return (-EADDRINUSE);
+      return -EADDRINUSE;
    }
 
-   intrfc = (ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
-   if(intrfc == NULL)
-      return (-EAGAIN);
+   intrfc = kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
+   if (!intrfc)
+      return -EAGAIN;
    intrfc->if_dev      = NULL;
    intrfc->if_netnum   = idef->ipx_network;
    intrfc->if_dlink_type    = 0;
@@ -998,8 +945,7 @@
    intrfc->if_ipx_offset    = 0;
    intrfc->if_sknum    = IPX_MIN_EPHEMERAL_SOCKET;
    memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN);
-   ipx_internal_net    = intrfc;
-   ipx_primary_net    = intrfc;
+   ipx_internal_net = ipx_primary_net = intrfc;
    spin_lock_init(&intrfc->if_sklist_lock);
    atomic_set(&intrfc->refcnt, 1);
    MOD_INC_USE_COUNT;
@@ -1013,22 +959,21 @@
 
 static int ipx_map_frame_type(unsigned char type)
 {
-   switch(type) 
-   {
+   switch (type) {
       case IPX_FRAME_ETHERII:
-         return (htons(ETH_P_IPX));
+         return htons(ETH_P_IPX);
 
       case IPX_FRAME_8022:
-         return (htons(ETH_P_802_2));
+         return htons(ETH_P_802_2);
 
       case IPX_FRAME_SNAP:
-         return (htons(ETH_P_SNAP));
+         return htons(ETH_P_SNAP);
 
       case IPX_FRAME_8023:
-         return (htons(ETH_P_802_3));
+         return htons(ETH_P_802_3);
    }
 
-   return (0);
+   return 0;
 }
 
 static int ipxitf_create(ipx_interface_definition *idef)
@@ -1039,29 +984,29 @@
    ipx_interface *intrfc;
    int err;
 
-   if(idef->ipx_special == IPX_INTERNAL)
-      return (ipxitf_create_internal(idef));
+   if (idef->ipx_special == IPX_INTERNAL)
+      return ipxitf_create_internal(idef);
 
-   if((idef->ipx_special == IPX_PRIMARY) && (ipx_primary_net != NULL))
-      return (-EEXIST);
+   if (idef->ipx_special == IPX_PRIMARY && ipx_primary_net)
+      return -EEXIST;
 
    intrfc = ipxitf_find_using_net(idef->ipx_network);
-   if(idef->ipx_network && intrfc != NULL) {
+   if (idef->ipx_network && intrfc) {
       ipxitf_put(intrfc);
-      return (-EADDRINUSE);
+      return -EADDRINUSE;
    }
 
    if (intrfc)
       ipxitf_put(intrfc);
 
    dev = dev_get_by_name(idef->ipx_device);
-   if(dev == NULL)
-      return (-ENODEV);
+   if (!dev)
+      return -ENODEV;
 
-   switch(idef->ipx_dlink_type) 
-   {
+   switch (idef->ipx_dlink_type) {
       case IPX_FRAME_TR_8022:
-         printk("IPX frame type 802.2TR is obsolete. Use 802.2 instead.\n");
+         printk(KERN_WARNING "IPX frame type 802.2TR is "
+            "obsolete Use 802.2 instead.\n");
          /* fall through */
 
       case IPX_FRAME_8022:
@@ -1070,14 +1015,14 @@
          break;
 
       case IPX_FRAME_ETHERII:
-         if (dev->type != ARPHRD_IEEE802)
-         {
+         if (dev->type != ARPHRD_IEEE802) {
             dlink_type    = htons(ETH_P_IPX);
             datalink    = pEII_datalink;
             break;
-         }
-         else 
-            printk("IPX frame type EtherII over token-ring is obsolete. Use SNAP instead.\n");
+         } else 
+            printk(KERN_WARNING "IPX frame type EtherII "
+               "over token-ring is obsolete. Use SNAP "
+               "instead.\n");
          /* fall through */
 
       case IPX_FRAME_SNAP:
@@ -1096,24 +1041,24 @@
    }
 
    err = -ENETDOWN;
-   if(!(dev->flags & IFF_UP))
+   if (!(dev->flags & IFF_UP))
       goto out_dev;
 
    /* Check addresses are suitable */
    err = -EINVAL;
-   if(dev->addr_len > IPX_NODE_LEN)
+   if (dev->addr_len > IPX_NODE_LEN)
       goto out_dev;
 
    err = -EPROTONOSUPPORT;
-   if(datalink == NULL)
+   if (!datalink)
       goto out_dev;
 
-   if((intrfc = ipxitf_find_using_phys(dev, dlink_type)) == NULL)
-   {
+   intrfc = ipxitf_find_using_phys(dev, dlink_type);
+   if (!intrfc) {
       /* Ok now create */
-      intrfc = (ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
+      intrfc = kmalloc(sizeof(ipx_interface), GFP_ATOMIC);
       err = -EAGAIN;
-      if(intrfc == NULL)
+      if (!intrfc)
          goto out_dev;
       intrfc->if_dev      = dev;
       intrfc->if_netnum    = idef->ipx_network;
@@ -1122,17 +1067,16 @@
       intrfc->if_sklist    = NULL;
       intrfc->if_sknum    = IPX_MIN_EPHEMERAL_SOCKET;
       /* Setup primary if necessary */
-      if((idef->ipx_special == IPX_PRIMARY))
+      if ((idef->ipx_special == IPX_PRIMARY))
          ipx_primary_net = intrfc;
       intrfc->if_internal    = 0;
       intrfc->if_ipx_offset    = dev->hard_header_len + datalink->header_length;
-      if(memcmp(idef->ipx_node, "\000\000\000\000\000\000", IPX_NODE_LEN) == 0)
-      {
+      if (!memcmp(idef->ipx_node, "\000\000\000\000\000\000",
+             IPX_NODE_LEN)) {
          memset(intrfc->if_node, 0, IPX_NODE_LEN);
          memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
             dev->dev_addr, dev->addr_len);
-      }
-      else
+      } else
          memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN);
       spin_lock_init(&intrfc->if_sklist_lock);
       atomic_set(&intrfc->refcnt, 1);
@@ -1144,7 +1088,7 @@
 
    /* If the network number is known, add a route */
    err = 0;
-   if(!intrfc->if_netnum)
+   if (!intrfc->if_netnum)
       goto out_intrfc;
 
    err = ipxitf_add_local_route(intrfc);
@@ -1164,10 +1108,8 @@
    int ret = 0;
 
    spin_lock_bh(&ipx_interfaces_lock);
-   if(idef->ipx_special == IPX_INTERNAL) 
-   {
-      if(ipx_internal_net != NULL) 
-      {
+   if (idef->ipx_special == IPX_INTERNAL) {
+      if (ipx_internal_net) {
          __ipxitf_put(ipx_internal_net);
          goto out;
       }
@@ -1176,19 +1118,19 @@
    }
 
    dlink_type = ipx_map_frame_type(idef->ipx_dlink_type);
-   if(dlink_type == 0) {
+   if (!dlink_type) {
       ret = -EPROTONOSUPPORT;
       goto out;
    }
 
    dev = __dev_get_by_name(idef->ipx_device);
-   if(dev == NULL) {
+   if (!dev) {
       ret = -ENODEV;
       goto out;
    }
 
    intrfc = __ipxitf_find_using_phys(dev, dlink_type);
-   if(intrfc != NULL)
+   if (intrfc)
       __ipxitf_put(intrfc);
    else
       ret = -EINVAL;
@@ -1198,13 +1140,12 @@
 }
 
 static ipx_interface *ipxitf_auto_create(struct net_device *dev, 
-   unsigned short dlink_type)
+                unsigned short dlink_type)
 {
    struct datalink_proto *datalink = NULL;
    ipx_interface *intrfc;
 
-   switch(htons(dlink_type)) 
-   {
+   switch (htons(dlink_type)) {
       case ETH_P_IPX:
          datalink = pEII_datalink;
          break;
@@ -1222,19 +1163,18 @@
          break;
 
       default:
-         return (NULL);
+         return NULL;
    }
 
-   if(dev == NULL)
-      return (NULL);
+   if (!dev)
+      return NULL;
 
    /* Check addresses are suitable */
-   if(dev->addr_len>IPX_NODE_LEN)
-      return (NULL);
+   if (dev->addr_len > IPX_NODE_LEN)
+      return NULL;
 
-   intrfc = (ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
-   if(intrfc != NULL) 
-   {
+   intrfc = kmalloc(sizeof(ipx_interface), GFP_ATOMIC);
+   if (intrfc) {
       intrfc->if_dev      = dev;
       intrfc->if_netnum   = 0;
       intrfc->if_dlink_type    = dlink_type;
@@ -1253,27 +1193,25 @@
       ipxitf_insert(intrfc);
    }
 
-   return (intrfc);
+   return intrfc;
 }
 
 static int ipxitf_ioctl(unsigned int cmd, void *arg)
 {
    struct ifreq ifr;
-   int err, val;
+   int err = 0, val;
 
-   switch(cmd)
-   {
-      case SIOCSIFADDR: 
-      {
+   switch (cmd) {
+      case SIOCSIFADDR: {
          struct sockaddr_ipx *sipx;
          ipx_interface_definition f;
 
-         if(copy_from_user(&ifr, arg, sizeof(ifr)))
-            return (-EFAULT);
+         if (copy_from_user(&ifr, arg, sizeof(ifr)))
+            return -EFAULT;
 
          sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
-         if(sipx->sipx_family != AF_IPX)
-            return (-EINVAL);
+         if (sipx->sipx_family != AF_IPX)
+            return -EINVAL;
 
          f.ipx_network = sipx->sipx_network;
          memcpy(f.ipx_device,ifr.ifr_name,sizeof(f.ipx_device));
@@ -1281,10 +1219,10 @@
          f.ipx_dlink_type = sipx->sipx_type;
          f.ipx_special = sipx->sipx_special;
 
-         if(sipx->sipx_action == IPX_DLTITF)
-            return (ipxitf_delete(&f));
+         if (sipx->sipx_action == IPX_DLTITF)
+            return ipxitf_delete(&f);
          else
-            return (ipxitf_create(&f));
+            return ipxitf_create(&f);
       }
 
       case SIOCGIFADDR: 
@@ -1293,50 +1231,46 @@
          ipx_interface *ipxif;
          struct net_device *dev;
 
-         if(copy_from_user(&ifr, arg, sizeof(ifr)))
-            return (-EFAULT);
+         if (copy_from_user(&ifr, arg, sizeof(ifr)))
+            return -EFAULT;
 
          sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
          dev = __dev_get_by_name(ifr.ifr_name);
-         if(!dev)
-            return (-ENODEV);
+         if (!dev)
+            return -ENODEV;
 
          ipxif = ipxitf_find_using_phys(dev, ipx_map_frame_type(sipx->sipx_type));
-         if(ipxif == NULL)
-            return (-EADDRNOTAVAIL);
+         if (!ipxif)
+            return -EADDRNOTAVAIL;
 
          sipx->sipx_family   = AF_IPX;
          sipx->sipx_network   = ipxif->if_netnum;
-         memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node));
-         err = -EFAULT;
-         if(!copy_to_user(arg, &ifr, sizeof(ifr)))
-            err = 0;
+         memcpy(sipx->sipx_node, ipxif->if_node,
+            sizeof(sipx->sipx_node));
+         if (copy_to_user(arg, &ifr, sizeof(ifr)))
+            err = -EFAULT;
 
          ipxitf_put(ipxif);
-         return (err);
+         return err;
       }
 
       case SIOCAIPXITFCRT: 
-      {
-         err = get_user(val, (unsigned char *) arg);
-         if(err)
-            return (err);
-
-         return (ipxcfg_set_auto_create(val));
-      }
+         if (get_user(val, (unsigned char *) arg))
+            return -EFAULT;
+         ipxcfg_set_auto_create(val);
+         break;
 
       case SIOCAIPXPRISLT: 
-      {
-         err = get_user(val, (unsigned char *) arg);
-         if(err)
-            return (err);
-
-         return (ipxcfg_set_auto_select(val));
-      }
+         if (get_user(val, (unsigned char *) arg))
+            return -EFAULT;
+         ipxcfg_set_auto_select(val);
+         break;
 
       default:
-         return (-EINVAL);
+         return -EINVAL;
    }
+
+   return 0;
 }
 
 /**************************************************************************\
@@ -1350,11 +1284,11 @@
    ipx_route *r;
 
    read_lock_bh(&ipx_routes_lock);
-   for(r = ipx_routes; (r != NULL) && (r->ir_net != net); r = r->ir_next)
+   for (r = ipx_routes; r && r->ir_net != net; r = r->ir_next)
       ;
    read_unlock_bh(&ipx_routes_lock);
 
-   return (r);
+   return r;
 }
 
 /* caller must hold a reference to intrfc */
@@ -1365,34 +1299,30 @@
 
    /* Get a route structure; either existing or create */
    rt = ipxrtr_lookup(network);
-   if(rt == NULL) 
-   {
-      rt = (ipx_route *)kmalloc(sizeof(ipx_route),GFP_ATOMIC);
-      if(rt == NULL)
-         return (-EAGAIN);
+   if (!rt) {
+      rt = kmalloc(sizeof(ipx_route),GFP_ATOMIC);
+      if (!rt)
+         return -EAGAIN;
 
       write_lock_bh(&ipx_routes_lock);
       rt->ir_next   = ipx_routes;
       ipx_routes   = rt;
       write_unlock_bh(&ipx_routes_lock);
    }
-   else if(intrfc == ipx_internal_net)
-      return (-EEXIST);
+   else if (intrfc == ipx_internal_net)
+      return -EEXIST;
 
    rt->ir_net    = network;
    rt->ir_intrfc    = intrfc;
-   if(node == NULL)
-   {
+   if (!node) {
       memset(rt->ir_router_node, '\0', IPX_NODE_LEN);
       rt->ir_routed = 0;
-   }
-   else
-   {
+   } else {
       memcpy(rt->ir_router_node, node, IPX_NODE_LEN);
       rt->ir_routed = 1;
    }
 
-   return (0);
+   return 0;
 }
 
 static void ipxrtr_del_routes(ipx_interface *intrfc)
@@ -1400,14 +1330,11 @@
    ipx_route **r, *tmp;
 
    write_lock_bh(&ipx_routes_lock);
-   for(r = &ipx_routes; (tmp = *r) != NULL;)
-   {
-      if(tmp->ir_intrfc == intrfc)
-      {
+   for (r = &ipx_routes; (tmp = *r) != NULL;) {
+      if (tmp->ir_intrfc == intrfc) {
          *r = tmp->ir_next;
          kfree(tmp);
-      }
-      else
+      } else
          r = &(tmp->ir_next);
    }
    write_unlock_bh(&ipx_routes_lock);
@@ -1420,8 +1347,8 @@
 
    /* Find the appropriate interface */
    intrfc = ipxitf_find_using_net(rd->ipx_router_network);
-   if(intrfc == NULL)
-      return (-ENETUNREACH);
+   if (!intrfc)
+      return -ENETUNREACH;
    ret = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node);
    ipxitf_put(intrfc);
    return ret;
@@ -1434,13 +1361,11 @@
    int err;
 
    write_lock_bh(&ipx_routes_lock);
-   for(r = &ipx_routes; (tmp = *r) != NULL;) 
-   {
-      if(tmp->ir_net == net) 
-      {
+   for (r = &ipx_routes; (tmp = *r) != NULL;) {
+      if (tmp->ir_net == net) {
          /* Directly connected; can't lose route */
          err = -EPERM;
-         if(!(tmp->ir_routed))
+         if (!tmp->ir_routed)
             goto out;
 
          *r = tmp->ir_next;
@@ -1461,45 +1386,38 @@
  */
  
 /* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
+/* This functions should *not* mess with packet contents */
 
-static __u16 ipx_set_checksum(struct ipxhdr *packet,int length) 
+static __u16 ipx_cksum(struct ipxhdr *packet,int length) 
 {
    /* 
     *   NOTE: sum is a net byte order quantity, which optimizes the 
     *   loop. This only works on big and little endian machines. (I
     *   don't know of a machine that isn't.)
     */
-
-   __u32 sum = 0;
-
-   /* Pointer to second word - We skip the checksum field */
-   __u16 *p = (__u16 *)&packet->ipx_pktsize;
-
-   /* Number of complete words */
-   __u32 i = length >> 1;
-   char hops = packet->ipx_tctrl;
-
-   /* Hop count excluded from checksum calc */
-   packet->ipx_tctrl = 0;
-
-   /* Loop through all complete words except the checksum field */
-   while(--i)
+   /* start at ipx_dest - We skip the checksum field and start with
+    * ipx_type before the loop, not considering ipx_tctrl in the calc */
+   __u16 *p = (__u16 *)&packet->ipx_dest;
+   __u32 i = (length >> 1) - 1; /* Number of complete words */
+   __u32 sum = packet->ipx_type << sizeof(packet->ipx_tctrl); 
+
+   /* Loop through all complete words except the checksum field,
+    * ipx_type (accounted above) and ipx_tctrl (not used in the cksum) */
+   while (--i)
       sum += *p++;
 
    /* Add on the last part word if it exists */
-   if(packet->ipx_pktsize & htons(1))
+   if (packet->ipx_pktsize & htons(1))
       sum += ntohs(0xff00) & *p;
 
-   packet->ipx_tctrl = hops;
-
    /* Do final fixup */
    sum = (sum & 0xffff) + (sum >> 16);
 
    /* It's a pity there's no concept of carry in C */
-   if(sum >= 0x10000)
+   if (sum >= 0x10000)
       sum++;
 
-   return (~sum);
+   return ~sum;
 }
 
 /*
@@ -1510,80 +1428,76 @@
    struct sk_buff *skb;
    ipx_interface *intrfc;
    struct ipxhdr *ipx;
+   struct ipx_cb *cb;
    int size;
    int ipx_offset;
    ipx_route *rt = NULL;
    int err;
 
    /* Find the appropriate interface on which to send packet */
-   if(!usipx->sipx_network && (ipx_primary_net != NULL))
-   {
+   if (!usipx->sipx_network && ipx_primary_net) {
       usipx->sipx_network = ipx_primary_net->if_netnum;
       intrfc = ipx_primary_net;
-   }
-   else
-   {
+   } else {
       rt = ipxrtr_lookup(usipx->sipx_network);
-      if(rt == NULL)
-         return (-ENETUNREACH);
+      if (!rt)
+         return -ENETUNREACH;
 
       intrfc = rt->ir_intrfc;
    }
 
    ipxitf_hold(intrfc);
    ipx_offset = intrfc->if_ipx_offset;
-   size   = sizeof(struct ipxhdr) + len;
-   size    += ipx_offset;
+   size = sizeof(struct ipxhdr) + len + ipx_offset;
 
    skb = sock_alloc_send_skb(sk, size, 0, noblock, &err);
-   if(skb == NULL)
+   if (!skb)
       goto out;
 
    skb_reserve(skb,ipx_offset);
    skb->sk = sk;
+   cb = (struct ipx_cb *) skb->cb;
 
    /* Fill in IPX header */
    ipx = (struct ipxhdr *)skb_put(skb, sizeof(struct ipxhdr));
    ipx->ipx_pktsize= htons(len + sizeof(struct ipxhdr));
-   ipx->ipx_tctrl    = 0;
+   cb->ipx_tctrl = 0;
    ipx->ipx_type    = usipx->sipx_type;
    skb->h.raw    = (void *)skb->nh.ipxh = ipx;
 
-   ipx->ipx_source.net = sk->protinfo.af_ipx.intrfc->if_netnum;
+   cb->last_hop_index = -1;
 
 #ifdef CONFIG_IPX_INTERN
+   cb->ipx_source_net = sk->protinfo.af_ipx.intrfc->if_netnum;
    memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);
 #else
-   if((err = ntohs(sk->protinfo.af_ipx.port)) == 0x453 || err == 0x452)
-   {
+   err = ntohs(sk->protinfo.af_ipx.port);
+   if (err == 0x453 || err == 0x452) {
       /* RIP/SAP special handling for mars_nwe */
-      ipx->ipx_source.net = intrfc->if_netnum;
+      cb->ipx_source_net = intrfc->if_netnum;
       memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN);
-   }
-   else
-   {
-      ipx->ipx_source.net = sk->protinfo.af_ipx.intrfc->if_netnum;
+   } else {
+      cb->ipx_source_net = sk->protinfo.af_ipx.intrfc->if_netnum;
       memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
    }
 #endif   /* CONFIG_IPX_INTERN */
 
    ipx->ipx_source.sock    = sk->protinfo.af_ipx.port;
-   ipx->ipx_dest.net   = usipx->sipx_network;
+   cb->ipx_dest_net = usipx->sipx_network;
    memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
    ipx->ipx_dest.sock   = usipx->sipx_port;
 
    err = memcpy_fromiovec(skb_put(skb,len),iov,len);
-   if(err)
-   {
+   if (err) {
       kfree_skb(skb);
       goto out;
    }   
 
    /* Apply checksum. Not allowed on 802.3 links. */
-   if(sk->no_check || intrfc->if_dlink_type == IPX_FRAME_8023)
+   if (sk->no_check || intrfc->if_dlink_type == IPX_FRAME_8023)
       ipx->ipx_checksum=0xFFFF;
    else
-      ipx->ipx_checksum = ipx_set_checksum(ipx, len + sizeof(struct ipxhdr));
+      ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
 
    err = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ? 
             rt->ir_router_node : ipx->ipx_dest.node);
@@ -1594,21 +1508,20 @@
 int ipxrtr_route_skb(struct sk_buff *skb)
 {
    struct ipxhdr *ipx = skb->nh.ipxh;
-   ipx_route *r;
+   struct ipx_cb *cb = (struct ipx_cb *) skb->cb;
+   ipx_route *r = ipxrtr_lookup(cb->ipx_dest_net);
 
-   r = ipxrtr_lookup(ipx->ipx_dest.net);
-   if(r == NULL)   /* no known route */
-   {
+   if (!r) {   /* no known route */
       kfree_skb(skb);
-      return (0);
+      return 0;
    }
 
    ipxitf_hold(r->ir_intrfc);
-   (void)ipxitf_send(r->ir_intrfc, skb, (r->ir_routed) ?
+   ipxitf_send(r->ir_intrfc, skb, (r->ir_routed) ?
          r->ir_router_node : ipx->ipx_dest.node);
    ipxitf_put(r->ir_intrfc);
 
-   return (0);
+   return 0;
 }
 
 /*
@@ -1621,23 +1534,22 @@
    int err;
 
    err = copy_from_user(&rt,arg,sizeof(rt));
-   if(err)
-      return (-EFAULT);
+   if (err)
+      return -EFAULT;
 
    sg = (struct sockaddr_ipx *)&rt.rt_gateway;
    st = (struct sockaddr_ipx *)&rt.rt_dst;
 
-   if(!(rt.rt_flags & RTF_GATEWAY))
-      return (-EINVAL);   /* Direct routes are fixed */
-   if(sg->sipx_family != AF_IPX)
-      return (-EINVAL);
-   if(st->sipx_family != AF_IPX)
-      return (-EINVAL);
+   if (!(rt.rt_flags & RTF_GATEWAY))
+      return -EINVAL;   /* Direct routes are fixed */
+   if (sg->sipx_family != AF_IPX)
+      return -EINVAL;
+   if (st->sipx_family != AF_IPX)
+      return -EINVAL;
 
-   switch(cmd)
-   {
+   switch (cmd) {
       case SIOCDELRT:
-         return (ipxrtr_delete(st->sipx_network));
+         return ipxrtr_delete(st->sipx_network);
 
       case SIOCADDRT:
       {
@@ -1645,42 +1557,40 @@
          f.ipx_network=st->sipx_network;
          f.ipx_router_network=sg->sipx_network;
          memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN);
-         return (ipxrtr_create(&f));
+         return ipxrtr_create(&f);
       }
-
-      default:
-         return (-EINVAL);
    }
+
+   return -EINVAL;
 }
 
 static const char *ipx_frame_name(unsigned short frame)
 {
-   switch(ntohs(frame)) 
-   {
+   switch (ntohs(frame)) {
       case ETH_P_IPX:
-         return ("EtherII");
+         return "EtherII";
 
       case ETH_P_802_2:
-         return ("802.2");
+         return "802.2";
 
       case ETH_P_SNAP:
-         return ("SNAP");
+         return "SNAP";
 
       case ETH_P_802_3:
-         return ("802.3");
+         return "802.3";
 
       case ETH_P_TR_802_2:
-         return ("802.2TR");
+         return "802.2TR";
 
       default:
-         return ("None");
+         return "None";
    }
 }
 
 static const char *ipx_device_name(ipx_interface *intrfc)
 {
-   return (intrfc->if_internal ? "Internal" :
-      (intrfc->if_dev ? intrfc->if_dev->name : "Unknown"));
+   return intrfc->if_internal ? "Internal" :
+      intrfc->if_dev ? intrfc->if_dev->name : "Unknown";
 }
 
 /* Called from proc fs */
@@ -1700,13 +1610,12 @@
 #endif
    strcat(buffer+len++, "\n");
    spin_lock_bh(&ipx_interfaces_lock);
-   for(i = ipx_interfaces; i != NULL; i = i->if_next)
-   {
+   for (i = ipx_interfaces; i; i = i->if_next) {
       len += sprintf(buffer+len, "%08lX   ", (long unsigned int)ntohl(i->if_netnum));
       len += sprintf(buffer+len,"%02X%02X%02X%02X%02X%02X   ",
             i->if_node[0], i->if_node[1], i->if_node[2],
             i->if_node[3], i->if_node[4], i->if_node[5]);
-      len += sprintf(buffer+len, "%-9s", (i == ipx_primary_net) ?
+      len += sprintf(buffer+len, "%-9s", i == ipx_primary_net ?
          "Yes" : "No");
       len += sprintf(buffer+len, "%-11s", ipx_device_name(i));
       len += sprintf(buffer+len, "%-9s",
@@ -1718,12 +1627,11 @@
       /* Are we still dumping unwanted data then discard the record */
       pos = begin + len;
 
-      if(pos < offset)
-      {
+      if (pos < offset) {
          len   = 0;   /* Keep dumping into the buffer start */
          begin = pos;
       }
-      if(pos > offset + length)   /* We have dumped enough */
+      if (pos > offset + length)   /* We have dumped enough */
          break;
    }
    spin_unlock_bh(&ipx_interfaces_lock);
@@ -1731,10 +1639,10 @@
    /* The data in question runs from begin to begin+len */
    *start = buffer + (offset - begin);   /* Start of wanted data */
    len -= (offset - begin); /* Remove unwanted header data from length */
-   if(len > length)
+   if (len > length)
       len = length;   /* Remove unwanted tail data from length */
 
-   return (len);
+   return len;
 }
 
 static int ipx_get_info(char *buffer, char **start, off_t offset, int length)
@@ -1755,12 +1663,10 @@
          "State", "Uid");
 
    spin_lock_bh(&ipx_interfaces_lock);
-   for(i = ipx_interfaces; i != NULL; i = i->if_next)
-   {
+   for (i = ipx_interfaces; i; i = i->if_next) {
       ipxitf_hold(i);
       spin_lock_bh(&i->if_sklist_lock);
-      for(s = i->if_sklist; s != NULL; s = s->next)
-      {
+      for (s = i->if_sklist; s; s = s->next) {
 #ifdef CONFIG_IPX_INTERN
          len += sprintf(buffer+len,
                    "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
@@ -1778,10 +1684,9 @@
                    htons(s->protinfo.af_ipx.port));
 #endif   /* CONFIG_IPX_INTERN */
 
-         if(s->state != TCP_ESTABLISHED)
+         if (s->state != TCP_ESTABLISHED)
             len += sprintf(buffer+len, "%-28s", "Not_Connected");
-         else
-         {
+         else {
             len += sprintf(buffer+len,
                "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
                (unsigned long) htonl(s->protinfo.af_ipx.dest_addr.net),
@@ -1801,13 +1706,12 @@
             s->state, SOCK_INODE(s->socket)->i_uid);
 
          pos = begin + len;
-         if(pos < offset)
-         {
+         if (pos < offset) {
             len   = 0;
             begin = pos;
          }
 
-         if(pos > offset + length)  /* We have dumped enough */
+         if (pos > offset + length)  /* We have dumped enough */
             break;
       }
       spin_unlock_bh(&i->if_sklist_lock);
@@ -1818,10 +1722,10 @@
    /* The data in question runs from begin to begin+len */
    *start = buffer + (offset-begin);
    len -= (offset - begin);
-   if(len > length)
+   if (len > length)
       len = length;
 
-   return (len);
+   return len;
 }
 
 static int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length)
@@ -1833,41 +1737,36 @@
    len += sprintf(buffer,"%-11s%-13s%s\n",
          "Network", "Router_Net", "Router_Node");
    read_lock_bh(&ipx_routes_lock);
-   for(rt = ipx_routes; rt != NULL; rt = rt->ir_next)
-   {
+   for (rt = ipx_routes; rt; rt = rt->ir_next) {
       len += sprintf(buffer+len,"%08lX   ", (long unsigned int) ntohl(rt->ir_net));
-      if(rt->ir_routed)
-      {
+      if (rt->ir_routed) {
          len += sprintf(buffer+len,"%08lX     %02X%02X%02X%02X%02X%02X\n",
             (long unsigned int) ntohl(rt->ir_intrfc->if_netnum),
             rt->ir_router_node[0], rt->ir_router_node[1],
             rt->ir_router_node[2], rt->ir_router_node[3],
             rt->ir_router_node[4], rt->ir_router_node[5]);
-      }
-      else
-      {
+      } else {
          len += sprintf(buffer+len, "%-13s%s\n",
                "Directly", "Connected");
       }
 
       pos = begin + len;
-      if(pos < offset)
-      {
-         len   = 0;
+      if (pos < offset) {
+         len = 0;
          begin = pos;
       }
 
-      if(pos > offset + length)
+      if (pos > offset + length)
          break;
    }
    read_unlock_bh(&ipx_routes_lock);
 
    *start = buffer + (offset - begin);
    len -= (offset - begin);
-   if(len > length)
+   if (len > length)
       len = length;
 
-   return (len);
+   return len;
 }
 
 /**************************************************************************\
@@ -1877,89 +1776,80 @@
 *                                                                          *
 \**************************************************************************/
 
-static int ipx_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
+static int ipx_setsockopt(struct socket *sock, int level, int optname,
+           char *optval, int optlen)
 {
-   struct sock *sk;
-   int err, opt;
-
-   sk = sock->sk;
+   struct sock *sk = sock->sk;
+   int opt;
 
-   if(optlen != sizeof(int))
-      return (-EINVAL);
+   if (optlen != sizeof(int))
+      return -EINVAL;
 
-   err = get_user(opt, (unsigned int *)optval);
-   if(err)
-      return (err);
+   if (get_user(opt, (unsigned int *)optval))
+      return -EFAULT;
 
-   switch(level)
-   {
+   switch (level) {
       case SOL_IPX:
-         switch(optname)
-         {
+         switch (optname) {
             case IPX_TYPE:
                sk->protinfo.af_ipx.type = opt;
-               return (0);
+               return 0;
 
             default:
-               return (-ENOPROTOOPT);
+               return -ENOPROTOOPT;
          }
          break;
 
       default:
-         return (-ENOPROTOOPT);
+         return -ENOPROTOOPT;
    }
 }
 
 static int ipx_getsockopt(struct socket *sock, int level, int optname,
    char *optval, int *optlen)
 {
-   struct sock *sk;
-   int val=0;
+   struct sock *sk = sock->sk;
+   int val = 0;
    int len;
 
-   sk = sock->sk;
-
-   switch(level)
-   {
+   switch (level) {
       case SOL_IPX:
-         switch(optname)
-         {
+         switch (optname) {
             case IPX_TYPE:
                val = sk->protinfo.af_ipx.type;
                break;
 
             default:
-               return (-ENOPROTOOPT);
+               return -ENOPROTOOPT;
          }
          break;
 
       default:
-         return (-ENOPROTOOPT);
+         return -ENOPROTOOPT;
    }
 
-   if(get_user(len, optlen))
-      return (-EFAULT);
+   if (get_user(len, optlen))
+      return -EFAULT;
 
    len = min(len, sizeof(int));
-   if(put_user(len, optlen))
-      return (-EFAULT);
+   if (put_user(len, optlen))
+      return -EFAULT;
 
-   if(copy_to_user(optval, &val, len))
-      return (-EFAULT);
+   if (copy_to_user(optval, &val, len))
+      return -EFAULT;
 
-   return (0);
+   return 0;
 }
 
 static int ipx_create(struct socket *sock, int protocol)
 {
    struct sock *sk;
 
-   switch(sock->type)
-   {
+   switch (sock->type) {
       case SOCK_DGRAM:
          sk = sk_alloc(PF_IPX, GFP_KERNEL, 1);
-         if(sk == NULL)
-                      return (-ENOMEM);
+         if (!sk)
+                      return -ENOMEM;
                         sock->ops = &ipx_dgram_ops;
                         break;
 
@@ -1968,12 +1858,12 @@
           * From this point on SPX sockets are handled
           * by af_spx.c and the methods replaced.
           */
-         if(spx_family_ops)
-            return (spx_family_ops->create(sock,protocol));
+         if (spx_family_ops)
+            return spx_family_ops->create(sock,protocol);
          /* Fall through if SPX is not loaded */
       case SOCK_STREAM:       /* Allow higher levels to piggyback */
       default:
-         return (-ESOCKTNOSUPPORT);
+         return -ESOCKTNOSUPPORT;
    }
 #ifdef IPX_REFCNT_DEBUG
         atomic_inc(&ipx_sock_nr);
@@ -1985,31 +1875,30 @@
    sk->no_check    = 1;      /* Checksum off by default */
 
    MOD_INC_USE_COUNT;
-
-   return (0);
+   return 0;
 }
 
 static int ipx_release(struct socket *sock)
 {
    struct sock *sk = sock->sk;
 
-   if(sk == NULL)
-      return (0);
+   if (!sk)
+      return 0;
 
-   if(!sk->dead)
+   if (!sk->dead)
       sk->state_change(sk);
 
    sk->dead = 1;
    sock->sk = NULL;
    ipx_destroy_socket(sk);
 
-   if(sock->type == SOCK_DGRAM)
+   if (sock->type == SOCK_DGRAM)
       MOD_DEC_USE_COUNT;
 
-   return (0);
+   return 0;
 }
 
-/* caller must hold a referente to intrfc */
+/* caller must hold a reference to intrfc */
 
 static unsigned short ipx_first_free_socketnum(ipx_interface *intrfc)
 {
@@ -2017,91 +1906,80 @@
 
    spin_lock_bh(&intrfc->if_sklist_lock);
 
-   if(socketNum < IPX_MIN_EPHEMERAL_SOCKET)
+   if (socketNum < IPX_MIN_EPHEMERAL_SOCKET)
       socketNum = IPX_MIN_EPHEMERAL_SOCKET;
 
-   while(__ipxitf_find_socket(intrfc, ntohs(socketNum)) != NULL)
-   {
-      if(socketNum > IPX_MAX_EPHEMERAL_SOCKET)
+   while (__ipxitf_find_socket(intrfc, ntohs(socketNum)))
+      if (socketNum > IPX_MAX_EPHEMERAL_SOCKET)
          socketNum = IPX_MIN_EPHEMERAL_SOCKET;
       else
          socketNum++;
-   }
 
    spin_unlock_bh(&intrfc->if_sklist_lock);
    intrfc->if_sknum = socketNum;
 
-   return (ntohs(socketNum));
+   return ntohs(socketNum);
 }
 
 static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
-   struct sock *sk;
+   struct sock *sk = sock->sk;
    ipx_interface *intrfc;
    struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr;
    int ret;
 
-   sk = sock->sk;
+   if (!sk->zapped)
+      return -EINVAL;
 
-   if(sk->zapped == 0)
-      return (-EINVAL);
-
-   if(addr_len != sizeof(struct sockaddr_ipx))
-      return (-EINVAL);
+   if (addr_len != sizeof(struct sockaddr_ipx))
+      return -EINVAL;
 
    intrfc = ipxitf_find_using_net(addr->sipx_network);
-   if(intrfc == NULL)
-      return (-EADDRNOTAVAIL);
+   if (!intrfc)
+      return -EADDRNOTAVAIL;
 
-   if(addr->sipx_port == 0)
-   {
+   if (!addr->sipx_port) {
       addr->sipx_port = ipx_first_free_socketnum(intrfc);
       ret = -EINVAL;
-      if(addr->sipx_port == 0)
+      if (!addr->sipx_port)
          goto out;
    }
 
    /* protect IPX system stuff like routing/sap */
    ret = -EACCES;
-   if(ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET && !capable(CAP_NET_ADMIN))
+   if (ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET &&
+       !capable(CAP_NET_ADMIN))
       goto out;
 
    sk->protinfo.af_ipx.port = addr->sipx_port;
 
 #ifdef CONFIG_IPX_INTERN
-   if(intrfc == ipx_internal_net)
-   {
+   if (intrfc == ipx_internal_net) {
       /* The source address is to be set explicitly if the
        * socket is to be bound on the internal network. If a
        * node number 0 was specified, the default is used.
        */
 
       ret = -EINVAL;
-      if(memcmp(addr->sipx_node,ipx_broadcast_node,IPX_NODE_LEN) == 0)
+      if (!memcmp(addr->sipx_node,ipx_broadcast_node,IPX_NODE_LEN))
          goto out;
-      if(memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN) == 0)
-      {
+      if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN))
          memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,
                 IPX_NODE_LEN);
-      }
       else
-      {
-         memcpy(sk->protinfo.af_ipx.node, addr->sipx_node, IPX_NODE_LEN);
-      }
+         memcpy(sk->protinfo.af_ipx.node, addr->sipx_node,
+            IPX_NODE_LEN);
 
       ret = -EADDRINUSE;
-      if(ipxitf_find_internal_socket(intrfc,
-         sk->protinfo.af_ipx.node,
-         sk->protinfo.af_ipx.port) != NULL)
-      {
+      if (ipxitf_find_internal_socket(intrfc,
+                  sk->protinfo.af_ipx.node,
+                  sk->protinfo.af_ipx.port)) {
          SOCK_DEBUG(sk,
             "IPX: bind failed because port %X in use.\n",
             ntohs((int)addr->sipx_port));
          goto out;
       }
-   }
-   else
-   {
+   } else {
       /* Source addresses are easy. It must be our
        * network:node pair for an interface routed to IPX
        * with the ipx routing ioctl()
@@ -2111,8 +1989,7 @@
          IPX_NODE_LEN);
 
       ret = -EADDRINUSE;
-      if(ipxitf_find_socket(intrfc, addr->sipx_port) != NULL)
-      {
+      if (ipxitf_find_socket(intrfc, addr->sipx_port)) {
          SOCK_DEBUG(sk,
             "IPX: bind failed because port %X in use.\n",
             ntohs((int)addr->sipx_port));
@@ -2126,8 +2003,7 @@
       an interface routed to IPX with the ipx routing ioctl() */
 
    ret = -EADDRINUSE;
-   if(ipxitf_find_socket(intrfc, addr->sipx_port) != NULL)
-   {
+   if (ipxitf_find_socket(intrfc, addr->sipx_port)) {
       SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n",
             ntohs((int)addr->sipx_port));
       goto out;
@@ -2153,13 +2029,12 @@
    sk->state   = TCP_CLOSE;
    sock->state    = SS_UNCONNECTED;
 
-   if(addr_len != sizeof(*addr))
-      return (-EINVAL);
+   if (addr_len != sizeof(*addr))
+      return -EINVAL;
    addr = (struct sockaddr_ipx *)uaddr;
 
    /* put the autobinding in */
-   if(sk->protinfo.af_ipx.port == 0)
-   {
+   if (!sk->protinfo.af_ipx.port) {
       struct sockaddr_ipx uaddr;
       int ret;
 
@@ -2167,7 +2042,7 @@
       uaddr.sipx_network    = 0;
 
 #ifdef CONFIG_IPX_INTERN
-      if(sk->protinfo.af_ipx.intrfc)
+      if (sk->protinfo.af_ipx.intrfc)
          memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,IPX_NODE_LEN);
       else
          return -ENETDOWN;      /* Someone zonked the iface */
@@ -2175,13 +2050,15 @@
 
       ret = ipx_bind(sock, (struct sockaddr *)&uaddr,
             sizeof(struct sockaddr_ipx));
-      if(ret != 0)
-         return (ret);
+      if (ret)
+         return ret;
    }
 
-        /* We can either connect to primary network or somewhere we can route to */
-   if( !(addr->sipx_network == 0 && ipx_primary_net != NULL) && ipxrtr_lookup(addr->sipx_network) == NULL)
-      return (-ENETUNREACH);
+        /* We can either connect to primary network or somewhere
+    * we can route to */
+   if (!(!addr->sipx_network && ipx_primary_net) &&
+       !ipxrtr_lookup(addr->sipx_network))
+      return -ENETUNREACH;
 
    sk->protinfo.af_ipx.dest_addr.net  = addr->sipx_network;
    sk->protinfo.af_ipx.dest_addr.sock = addr->sipx_port;
@@ -2189,41 +2066,34 @@
       addr->sipx_node,IPX_NODE_LEN);
    sk->protinfo.af_ipx.type = addr->sipx_type;
 
-   if(sock->type == SOCK_DGRAM )
-   {
+   if (sock->type == SOCK_DGRAM) {
       sock->state    = SS_CONNECTED;
       sk->state    = TCP_ESTABLISHED;
    }
 
-   return (0);
+   return 0;
 }
 
 
 static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
-   int *uaddr_len, int peer)
+         int *uaddr_len, int peer)
 {
    ipx_address *addr;
    struct sockaddr_ipx sipx;
-   struct sock *sk;
-
-   sk = sock->sk;
+   struct sock *sk = sock->sk;
 
    *uaddr_len = sizeof(struct sockaddr_ipx);
 
-   if(peer)
-   {
-      if(sk->state != TCP_ESTABLISHED)
-         return (-ENOTCONN);
+   if (peer) {
+      if (sk->state != TCP_ESTABLISHED)
+         return -ENOTCONN;
 
       addr = &sk->protinfo.af_ipx.dest_addr;
       sipx.sipx_network = addr->net;
       memcpy(sipx.sipx_node,addr->node,IPX_NODE_LEN);
       sipx.sipx_port = addr->sock;
-   }
-   else
-   {
-      if(sk->protinfo.af_ipx.intrfc != NULL)
-      {
+   } else {
+      if (sk->protinfo.af_ipx.intrfc) {
          sipx.sipx_network=sk->protinfo.af_ipx.intrfc->if_netnum;
 #ifdef CONFIG_IPX_INTERN
          memcpy(sipx.sipx_node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);
@@ -2231,9 +2101,7 @@
          memcpy(sipx.sipx_node, sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
 #endif   /* CONFIG_IPX_INTERN */
 
-      }
-      else
-      {
+      } else {
          sipx.sipx_network = 0;
          memset(sipx.sipx_node, '\0', IPX_NODE_LEN);
       }
@@ -2242,10 +2110,10 @@
    }
 
    sipx.sipx_family = AF_IPX;
-   sipx.sipx_type   = sk->protinfo.af_ipx.type;
+   sipx.sipx_type = sk->protinfo.af_ipx.type;
    memcpy(uaddr,&sipx,sizeof(sipx));
 
-   return (0);
+   return 0;
 }
 
 int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
@@ -2253,97 +2121,96 @@
    /* NULL here for pt means the packet was looped back */
    ipx_interface *intrfc;
    struct ipxhdr *ipx;
+   struct ipx_cb *cb;
+   u16 ipx_pktsize;
    int ret;
-
-   ipx = skb->nh.ipxh;
-   
-   /* Too small? */
-   if(ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr))
-      goto drop;
-
-   /* Invalid header */
-   if(ntohs(ipx->ipx_pktsize) > skb->len)
-      goto drop;
       
    /* Not ours */   
         if (skb->pkt_type == PACKET_OTHERHOST)
            goto drop;
+
+   if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+      goto out;
+
+   ipx = skb->nh.ipxh;
+   ipx_pktsize = ntohs(ipx->ipx_pktsize);
+   
+   /* Too small or invalid header? */
+   if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len)
+      goto drop;
                         
-   if(ipx->ipx_checksum != IPX_NO_CHECKSUM) 
-   {
-      if(ipx_set_checksum(ipx, ntohs(ipx->ipx_pktsize)) != ipx->ipx_checksum)
-         goto drop;
-   }
+   if (ipx->ipx_checksum != IPX_NO_CHECKSUM &&
+      ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))
+      goto drop;
+
+   cb = (struct ipx_cb *) skb->cb;
+   cb->ipx_tctrl = ipx->ipx_tctrl;
+   cb->ipx_dest_net = ipx->ipx_dest.net;
+   cb->ipx_source_net = ipx->ipx_source.net;
 
    /* Determine what local ipx endpoint this is */
    intrfc = ipxitf_find_using_phys(dev, pt->type);
-   if(intrfc == NULL)
-   {
-      if(ipxcfg_auto_create_interfaces
-          && ntohl(ipx->ipx_dest.net) != 0L)
-      {
+   if (!intrfc) {
+      if (ipxcfg_auto_create_interfaces &&
+         ntohl(cb->ipx_dest_net)) {
          intrfc = ipxitf_auto_create(dev, pt->type);
          ipxitf_hold(intrfc);
       }
 
-      if(intrfc == NULL)   /* Not one of ours */
+      if (!intrfc)   /* Not one of ours */
          goto drop;
    }
 
    ret = ipxitf_rcv(intrfc, skb);
    ipxitf_put(intrfc);
    return ret;
-drop:
-   kfree_skb(skb);
-   return (0);
+drop:   kfree_skb(skb);
+out:   return 0;
 }
 
 static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
    struct scm_cookie *scm)
 {
    struct sock *sk = sock->sk;
-   struct sockaddr_ipx *usipx=(struct sockaddr_ipx *)msg->msg_name;
+   struct sockaddr_ipx *usipx = (struct sockaddr_ipx *)msg->msg_name;
    struct sockaddr_ipx local_sipx;
    int retval;
    int flags = msg->msg_flags;
 
    /* Socket gets bound below anyway */
-/*   if(sk->zapped)
-      return (-EIO); */   /* Socket not bound */
-   if(flags & ~MSG_DONTWAIT)
-      return (-EINVAL);
-
-   if(usipx)
-   {
-      if(sk->protinfo.af_ipx.port == 0)
-      {
+/*   if (sk->zapped)
+      return -EIO; */   /* Socket not bound */
+   if (flags & ~MSG_DONTWAIT)
+      return -EINVAL;
+
+   if (usipx) {
+      if (!sk->protinfo.af_ipx.port) {
          struct sockaddr_ipx uaddr;
          int ret;
 
          uaddr.sipx_port = 0;
          uaddr.sipx_network = 0L;
 #ifdef CONFIG_IPX_INTERN
-         if(sk->protinfo.af_ipx.intrfc)
-            memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc
-                  ->if_node,IPX_NODE_LEN);
+         if (sk->protinfo.af_ipx.intrfc)
+            memcpy(uaddr.sipx_node,
+               sk->protinfo.af_ipx.intrfc->if_node,
+               IPX_NODE_LEN);
          else
             return -ENETDOWN;               /* Someone zonked the iface */
 #endif
          ret = ipx_bind(sock, (struct sockaddr *)&uaddr,
                sizeof(struct sockaddr_ipx));
-         if(ret != 0)
-            return (ret);
+         if (ret)
+            return ret;
       }
 
-      if(msg->msg_namelen < sizeof(*usipx))
-         return (-EINVAL);
-      if(usipx->sipx_family != AF_IPX)
-         return (-EINVAL);
-   }
-   else
-   {
-      if(sk->state != TCP_ESTABLISHED)
-         return (-ENOTCONN);
+      if (msg->msg_namelen < sizeof(*usipx))
+         return -EINVAL;
+      if (usipx->sipx_family != AF_IPX)
+         return -EINVAL;
+   } else {
+      if (sk->state != TCP_ESTABLISHED)
+         return -ENOTCONN;
 
       usipx=&local_sipx;
       usipx->sipx_family    = AF_IPX;
@@ -2353,11 +2220,12 @@
       memcpy(usipx->sipx_node,sk->protinfo.af_ipx.dest_addr.node,IPX_NODE_LEN);
    }
 
-   retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len, flags&MSG_DONTWAIT);
-   if(retval < 0)
-      return (retval);
+   retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len,
+                 flags & MSG_DONTWAIT);
+   if (retval < 0)
+      return retval;
 
-   return (len);
+   return len;
 }
 
 
@@ -2371,8 +2239,7 @@
    int copied, err;
 
    /* put the autobinding in */
-   if(sk->protinfo.af_ipx.port == 0)
-   {
+   if (!sk->protinfo.af_ipx.port) {
       struct sockaddr_ipx uaddr;
       int ret;
 
@@ -2380,7 +2247,7 @@
       uaddr.sipx_network    = 0;
 
 #ifdef CONFIG_IPX_INTERN
-      if(sk->protinfo.af_ipx.intrfc)
+      if (sk->protinfo.af_ipx.intrfc)
          memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,IPX_NODE_LEN);
       else
          return -ENETDOWN;      /* Someone zonked the iface */
@@ -2388,47 +2255,45 @@
 
       ret = ipx_bind(sock, (struct sockaddr *)&uaddr,
             sizeof(struct sockaddr_ipx));
-      if(ret != 0)
-         return (ret);
+      if (ret)
+         return ret;
    }
    
-   if(sk->zapped)
-      return (-ENOTCONN);
+   if (sk->zapped)
+      return -ENOTCONN;
 
    skb = skb_recv_datagram(sk,flags&~MSG_DONTWAIT,flags&MSG_DONTWAIT,&err);
-   if(!skb)
+   if (!skb)
       goto out;
 
    ipx    = skb->nh.ipxh;
    copied    = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);
-   if(copied > size)
-   {
+   if (copied > size) {
       copied=size;
       msg->msg_flags |= MSG_TRUNC;
    }
 
    err = skb_copy_datagram_iovec(skb, sizeof(struct ipxhdr), msg->msg_iov,
                copied);
-   if(err)
+   if (err)
       goto out_free;
    sk->stamp = skb->stamp;
 
    msg->msg_namelen = sizeof(*sipx);
 
-   if(sipx)
-   {
+   if (sipx) {
+      struct ipx_cb *cb = (struct ipx_cb *) skb->cb;
       sipx->sipx_family   = AF_IPX;
       sipx->sipx_port      = ipx->ipx_source.sock;
       memcpy(sipx->sipx_node,ipx->ipx_source.node,IPX_NODE_LEN);
-      sipx->sipx_network   = ipx->ipx_source.net;
+      sipx->sipx_network   = cb->ipx_source_net;
       sipx->sipx_type    = ipx->ipx_type;
    }
    err = copied;
 
 out_free:
    skb_free_datagram(sk, skb);
-out:
-   return (err);
+out:   return err;
 }
 
 
@@ -2437,40 +2302,39 @@
    long amount = 0;
    struct sock *sk = sock->sk;
 
-   switch(cmd)
-   {
+   switch (cmd) {
       case TIOCOUTQ:
          amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
-         if(amount < 0)
+         if (amount < 0)
             amount = 0;
-         return (put_user(amount, (int *)arg));
+         return put_user(amount, (int *)arg);
 
       case TIOCINQ:
       {
-         struct sk_buff *skb;
+         struct sk_buff *skb = skb_peek(&sk->receive_queue);
          /* These two are safe on a single CPU system as only user tasks fiddle here */
-         if((skb = skb_peek(&sk->receive_queue)) != NULL)
+         if (skb)
             amount = skb->len - sizeof(struct ipxhdr);
-         return (put_user(amount, (int *)arg));
+         return put_user(amount, (int *)arg);
       }
 
       case SIOCADDRT:
       case SIOCDELRT:
-         if(!capable(CAP_NET_ADMIN))
-            return (-EPERM);
-         return (ipxrtr_ioctl(cmd,(void *)arg));
+         if (!capable(CAP_NET_ADMIN))
+            return -EPERM;
+         return ipxrtr_ioctl(cmd,(void *)arg);
 
       case SIOCSIFADDR:
       case SIOCAIPXITFCRT:
       case SIOCAIPXPRISLT:
-         if(!capable(CAP_NET_ADMIN))
-            return (-EPERM);
+         if (!capable(CAP_NET_ADMIN))
+            return -EPERM;
 
       case SIOCGIFADDR:
-         return (ipxitf_ioctl(cmd,(void *)arg));
+         return ipxitf_ioctl(cmd,(void *)arg);
 
       case SIOCIPXCFGDATA:
-         return (ipxcfg_get_config_data((void *)arg));
+         return ipxcfg_get_config_data((void *)arg);
 
       case SIOCIPXNCPCONN:
                 {
@@ -2479,24 +2343,24 @@
           * handed to us in arg.
           */
                    if (!capable(CAP_NET_ADMIN))
-                      return(-EPERM);
-         return get_user(sk->protinfo.af_ipx.ipx_ncp_conn, (const unsigned short *)(arg));
+                      return -EPERM;
+         return get_user(sk->protinfo.af_ipx.ipx_ncp_conn,
+               (const unsigned short *)(arg));
                 }
 
       case SIOCGSTAMP:
       {
          int ret = -EINVAL;
-         if(sk)
-         {
-            if(sk->stamp.tv_sec == 0)
-               return (-ENOENT);
+         if (sk) {
+            if (!sk->stamp.tv_sec)
+               return -ENOENT;
             ret = -EFAULT;
-            if(!copy_to_user((void *)arg, &sk->stamp,
+            if (!copy_to_user((void *)arg, &sk->stamp,
                   sizeof(struct timeval)))
                ret = 0;
          }
 
-         return (ret);
+         return ret;
       }
 
       case SIOCGIFDSTADDR:
@@ -2505,14 +2369,14 @@
       case SIOCSIFBRDADDR:
       case SIOCGIFNETMASK:
       case SIOCSIFNETMASK:
-         return (-EINVAL);
+         return -EINVAL;
 
       default:
-         return (dev_ioctl(cmd,(void *) arg));
+         return dev_ioctl(cmd,(void *) arg);
    }
 
    /*NOT REACHED*/
-   return (0);
+   return 0;
 }
 
 /*
@@ -2521,19 +2385,19 @@
 
 int ipx_register_spx(struct proto_ops **p, struct net_proto_family *spx)
 {
-        if(spx_family_ops!=NULL)
+        if (spx_family_ops)
                 return -EBUSY;
         cli();
         MOD_INC_USE_COUNT;
-        *p=&ipx_dgram_ops;
-        spx_family_ops=spx;
+        *p = &ipx_dgram_ops;
+        spx_family_ops = spx;
         sti();
         return 0;
 }
 
 int ipx_unregister_spx(void)
 {
-        spx_family_ops=NULL;
+        spx_family_ops = NULL;
         MOD_DEC_USE_COUNT;
         return 0;
 }
@@ -2576,7 +2440,7 @@
    __constant_htons(ETH_P_802_3),
    NULL,      /* All devices */
    ipx_rcv,
-   NULL,
+   (void *) 1,   /* yap, I understand shared skbs :-) */
    NULL,
 };
 
@@ -2585,7 +2449,7 @@
    __constant_htons(ETH_P_IPX),
    NULL,      /* All devices */
    ipx_rcv,
-   NULL,
+   (void *) 1,   /* yap, I understand shared skbs :-) */
    NULL,
 };
 
@@ -2604,12 +2468,9 @@
 static unsigned char ipx_8022_type = 0xE0;
 static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
 
-
-
-
 static int __init ipx_init(void)
 {
-   (void) sock_register(&ipx_family_ops);
+   sock_register(&ipx_family_ops);
 
    pEII_datalink = make_EII_client();
    dev_add_pack(&ipx_dix_packet_type);
@@ -2617,35 +2478,34 @@
    p8023_datalink = make_8023_client();
    dev_add_pack(&ipx_8023_packet_type);
 
-   if((p8022_datalink = register_8022_client(ipx_8022_type,ipx_rcv)) == NULL)
+   p8022_datalink = register_8022_client(ipx_8022_type,ipx_rcv);
+   if (!p8022_datalink)
       printk(KERN_CRIT "IPX: Unable to register with 802.2\n");
 
-   if((pSNAP_datalink = register_snap_client(ipx_snap_id,ipx_rcv)) == NULL)
+   pSNAP_datalink = register_snap_client(ipx_snap_id,ipx_rcv);
+   if (!pSNAP_datalink)
       printk(KERN_CRIT "IPX: Unable to register with SNAP\n");
 
    register_netdevice_notifier(&ipx_dev_notifier);
-
 #ifdef CONFIG_PROC_FS
    proc_net_create("ipx", 0, ipx_get_info);
    proc_net_create("ipx_interface", 0, ipx_interface_get_info);
    proc_net_create("ipx_route", 0, ipx_rt_get_info);
 #endif
-
-   printk(KERN_INFO "NET4: Linux IPX 0.42v4 for NET4.0\n");
+   printk(KERN_INFO "NET4: Linux IPX 0.43 for NET4.0\n");
    printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
    printk(KERN_INFO "IPX Portions Copyright (c) 2000 Conectiva, Inc.\n");
    return 0;
 }
+
 module_init(ipx_init);
 
 /* Higher layers need this info to prep tx pkts */
 int ipx_if_offset(unsigned long ipx_net_number)
 {
-   ipx_route *rt = NULL;
-
-   rt = ipxrtr_lookup(ipx_net_number);
+   ipx_route *rt = ipxrtr_lookup(ipx_net_number);
 
-   return (rt ? rt->ir_intrfc->if_ipx_offset : -ENETUNREACH);
+   return rt ? rt->ir_intrfc->if_ipx_offset : -ENETUNREACH;
 }
 
 /* Export symbols for higher layers */
@@ -2683,24 +2543,22 @@
    unregister_netdevice_notifier(&ipx_dev_notifier);
 
    unregister_snap_client(ipx_snap_id);
-   pSNAP_datalink    = NULL;
+   pSNAP_datalink = NULL;
 
    unregister_8022_client(ipx_8022_type);
-   p8022_datalink    = NULL;
+   p8022_datalink = NULL;
 
    dev_remove_pack(&ipx_8023_packet_type);
    destroy_8023_client(p8023_datalink);
-   p8023_datalink    = NULL;
+   p8023_datalink = NULL;
 
    dev_remove_pack(&ipx_dix_packet_type);
    destroy_EII_client(pEII_datalink);
-   pEII_datalink    = NULL;
-
-   (void) sock_unregister(ipx_family_ops.family);
+   pEII_datalink = NULL;
 
-   return;
+   sock_unregister(ipx_family_ops.family);
 }
+
 module_exit(ipx_proto_finito);
 #endif /* MODULE */
-
 #endif /* CONFIG_IPX || CONFIG_IPX_MODULE */


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.