diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-01-31 22:22:27 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-01-31 22:22:27 +0000 |
commit | 825423e4c4f18289df2393951cfd2a7a31fc0464 (patch) | |
tree | 4ad80e981c3d9effa910d2247d118d254f9a5d09 /net | |
parent | c4693dc4856ab907a5c02187a8d398861bebfc7e (diff) |
Merge with Linux 2.4.1.
Diffstat (limited to 'net')
54 files changed, 2376 insertions, 2517 deletions
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index c67e3fdd0..ce5fc6d0d 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -25,6 +25,7 @@ * Jaume Grau - flush caches on AARP_PROBE * Rob Newberry - Added proxy AARP and AARP proc fs, * moved probing from DDP module. + * Arnaldo C. Melo - don't mangle rx packets * */ @@ -58,16 +59,12 @@ #include <linux/init.h> #include <linux/proc_fs.h> - int sysctl_aarp_expiry_time = AARP_EXPIRY_TIME; int sysctl_aarp_tick_time = AARP_TICK_TIME; int sysctl_aarp_retransmit_limit = AARP_RETRANSMIT_LIMIT; int sysctl_aarp_resolve_time = AARP_RESOLVE_TIME; -/* - * Lists of aarp entries - */ - +/* Lists of aarp entries */ struct aarp_entry { /* These first two are only used for unresolved entries */ unsigned long last_sent; /* Last time we xmitted the aarp request */ @@ -81,22 +78,16 @@ struct aarp_entry { struct aarp_entry *next; /* Next entry in chain */ }; -/* - * Hashed list of resolved, unresolved and proxy entries - */ - +/* Hashed list of resolved, unresolved and proxy entries */ static struct aarp_entry *resolved[AARP_HASH_SIZE]; static struct aarp_entry *unresolved[AARP_HASH_SIZE]; static struct aarp_entry *proxies[AARP_HASH_SIZE]; -static int unresolved_count = 0; +static int unresolved_count; /* One lock protects it all. */ static spinlock_t aarp_lock = SPIN_LOCK_UNLOCKED; -/* - * Used to walk the list and purge/kick entries. - */ - +/* Used to walk the list and purge/kick entries. */ static struct timer_list aarp_timer; /* @@ -108,7 +99,7 @@ static void __aarp_expire(struct aarp_entry *a) { struct sk_buff *skb; - while ((skb=skb_dequeue(&a->packet_queue)) != NULL) + while ((skb = skb_dequeue(&a->packet_queue)) != NULL) kfree_skb(skb); kfree(a); @@ -125,33 +116,29 @@ static void __aarp_send_query(struct aarp_entry *a) static char aarp_eth_multicast[ETH_ALEN] = { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; struct net_device *dev = a->dev; - int len = dev->hard_header_len + sizeof(struct elapaarp) + aarp_dl->header_length; + int len = dev->hard_header_len + sizeof(struct elapaarp) + + aarp_dl->header_length; struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); - struct elapaarp *eah; struct at_addr *sat = atalk_find_dev_addr(dev); + struct elapaarp *eah; - if (skb == NULL) + if (!skb) return; - if (sat == NULL) { + if (!sat) { kfree_skb(skb); return; } - /* - * Set up the buffer. - */ - + /* Set up the buffer */ skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); - eah = (struct elapaarp *)skb_put(skb, sizeof(struct elapaarp)); + eah = (struct elapaarp *)skb_put(skb, + sizeof(struct elapaarp)); skb->protocol = htons(ETH_P_ATALK); skb->nh.raw = skb->h.raw = (void *) eah; skb->dev = dev; - /* - * Set up the ARP. - */ - + /* Set up the ARP */ eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); eah->pa_type = htons(ETH_P_ATALK); eah->hw_len = ETH_ALEN; @@ -170,52 +157,37 @@ static void __aarp_send_query(struct aarp_entry *a) eah->pa_dst_net = a->target_addr.s_net; eah->pa_dst_node= a->target_addr.s_node; - /* - * Add ELAP headers and set target to the AARP multicast. - */ - + /* Add ELAP headers and set target to the AARP multicast */ aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast); - /* - * Send it. - */ - + /* Send it */ dev_queue_xmit(skb); - - /* - * Update the sending count - */ - + /* Update the sending count */ a->xmit_count++; } -/* This runs under aarp_lock and in softint context, so only - * atomic memory allocations can be used. - */ +/* This runs under aarp_lock and in softint context, so only atomic memory + * allocations can be used. */ static void aarp_send_reply(struct net_device *dev, struct at_addr *us, struct at_addr *them, unsigned char *sha) { - int len = dev->hard_header_len + sizeof(struct elapaarp) + aarp_dl->header_length; + int len = dev->hard_header_len + sizeof(struct elapaarp) + + aarp_dl->header_length; struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); struct elapaarp *eah; - if (skb == NULL) + if (!skb) return; - /* - * Set up the buffer. - */ - + /* Set up the buffer */ skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); - eah = (struct elapaarp *)skb_put(skb, sizeof(struct elapaarp)); + eah = (struct elapaarp *)skb_put(skb, + sizeof(struct elapaarp)); skb->protocol = htons(ETH_P_ATALK); skb->nh.raw = skb->h.raw = (void *) eah; skb->dev = dev; - /* - * Set up the ARP. - */ - + /* Set up the ARP */ eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); eah->pa_type = htons(ETH_P_ATALK); eah->hw_len = ETH_ALEN; @@ -228,7 +200,7 @@ static void aarp_send_reply(struct net_device *dev, struct at_addr *us, eah->pa_src_net = us->s_net; eah->pa_src_node= us->s_node; - if (sha == NULL) + if (!sha) memset(eah->hw_dst, '\0', ETH_ALEN); else memcpy(eah->hw_dst, sha, ETH_ALEN); @@ -237,47 +209,38 @@ static void aarp_send_reply(struct net_device *dev, struct at_addr *us, eah->pa_dst_net = them->s_net; eah->pa_dst_node= them->s_node; - /* - * Add ELAP headers and set target to the AARP multicast. - */ - + /* Add ELAP headers and set target to the AARP multicast */ aarp_dl->datalink_header(aarp_dl, skb, sha); - - /* - * Send it. - */ + /* Send it */ dev_queue_xmit(skb); } /* - * Send probe frames. Called from aarp_probe_network and aarp_proxy_probe_network. + * Send probe frames. Called from aarp_probe_network and + * aarp_proxy_probe_network. */ void aarp_send_probe(struct net_device *dev, struct at_addr *us) { - int len = dev->hard_header_len + sizeof(struct elapaarp) + aarp_dl->header_length; + int len = dev->hard_header_len + sizeof(struct elapaarp) + + aarp_dl->header_length; struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); - struct elapaarp *eah; static char aarp_eth_multicast[ETH_ALEN] = { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; + struct elapaarp *eah; - if (skb == NULL) + if (!skb) return; - /* - * Set up the buffer. - */ - + /* Set up the buffer */ skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); - eah = (struct elapaarp *)skb_put(skb, sizeof(struct elapaarp)); + eah = (struct elapaarp *)skb_put(skb, + sizeof(struct elapaarp)); skb->protocol = htons(ETH_P_ATALK); skb->nh.raw = skb->h.raw = (void *) eah; skb->dev = dev; - /* - * Set up the ARP. - */ - + /* Set up the ARP */ eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); eah->pa_type = htons(ETH_P_ATALK); eah->hw_len = ETH_ALEN; @@ -296,15 +259,9 @@ void aarp_send_probe(struct net_device *dev, struct at_addr *us) eah->pa_dst_net = us->s_net; eah->pa_dst_node= us->s_node; - /* - * Add ELAP headers and set target to the AARP multicast. - */ - + /* Add ELAP headers and set target to the AARP multicast */ aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast); - - /* - * Send it. - */ + /* Send it */ dev_queue_xmit(skb); } @@ -318,16 +275,14 @@ static void __aarp_expire_timer(struct aarp_entry **n) { struct aarp_entry *t; - while ((*n) != NULL) { + while (*n) /* Expired ? */ - if(time_after(jiffies, (*n)->expires_at)) { + if (time_after(jiffies, (*n)->expires_at)) { t = *n; *n = (*n)->next; __aarp_expire(t); - } else { + } else n = &((*n)->next); - } - } } /* @@ -340,10 +295,8 @@ static void __aarp_kick(struct aarp_entry **n) { struct aarp_entry *t; - while ((*n) != NULL) { - /* Expired - if this will be the 11th transmit, we delete - * instead. - */ + while (*n) + /* Expired: if this will be the 11th tx, we delete instead. */ if ((*n)->xmit_count >= sysctl_aarp_retransmit_limit) { t = *n; *n = (*n)->next; @@ -352,7 +305,6 @@ static void __aarp_kick(struct aarp_entry **n) __aarp_send_query(*n); n = &((*n)->next); } - } } /* @@ -366,21 +318,16 @@ static void __aarp_expire_device(struct aarp_entry **n, struct net_device *dev) { struct aarp_entry *t; - while ((*n) != NULL) { + while (*n) if ((*n)->dev == dev) { t = *n; *n = (*n)->next; __aarp_expire(t); - } else { + } else n = &((*n)->next); - } - } } -/* - * Handle the timer event - */ - +/* Handle the timer event */ static void aarp_expire_timeout(unsigned long unused) { int ct; @@ -395,17 +342,14 @@ static void aarp_expire_timeout(unsigned long unused) } spin_unlock_bh(&aarp_lock); - mod_timer(&aarp_timer, jiffies + - (unresolved_count ? sysctl_aarp_tick_time: + (unresolved_count ? sysctl_aarp_tick_time : sysctl_aarp_expiry_time)); } -/* - * Network device notifier chain handler. - */ - -static int aarp_device_event(struct notifier_block *this, unsigned long event, void *ptr) +/* Network device notifier chain handler. */ +static int aarp_device_event(struct notifier_block *this, unsigned long event, + void *ptr) { int ct; @@ -432,11 +376,8 @@ static struct aarp_entry *aarp_alloc(void) { struct aarp_entry *a = kmalloc(sizeof(struct aarp_entry), GFP_ATOMIC); - if (a == NULL) - return NULL; - - skb_queue_head_init(&a->packet_queue); - + if (a) + skb_queue_head_init(&a->packet_queue); return a; } @@ -464,10 +405,8 @@ static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list, /* Called from the DDP code, and thus must be exported. */ void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa) { + int hash = sa->s_node % (AARP_HASH_SIZE - 1); struct aarp_entry *a; - int hash; - - hash = sa->s_node % (AARP_HASH_SIZE-1); spin_lock_bh(&aarp_lock); @@ -479,23 +418,15 @@ void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa) } /* This must run under aarp_lock. */ -static struct at_addr *__aarp_proxy_find(struct net_device *dev, struct at_addr *sa) +static struct at_addr *__aarp_proxy_find(struct net_device *dev, + struct at_addr *sa) { - struct at_addr *retval; - struct aarp_entry *a; - int hash; + int hash = sa->s_node % (AARP_HASH_SIZE - 1); + struct aarp_entry *a = __aarp_find_entry(proxies[hash], dev, sa); - hash = sa->s_node % (AARP_HASH_SIZE-1); - - retval = NULL; - a = __aarp_find_entry(proxies[hash], dev, sa); - if (a != NULL) - retval = sa; - - return retval; + return a ? sa : NULL; } - /* * Probe a Phase 1 device or a device that requires its Net:Node to * be set via an ioctl. @@ -506,13 +437,13 @@ void aarp_send_probe_phase1(struct atalk_iface *iface) struct sockaddr_at *sa = (struct sockaddr_at *)&atreq.ifr_addr; sa->sat_addr.s_node = iface->address.s_node; - sa->sat_addr.s_net = ntohs(iface->address.s_net); + sa->sat_addr.s_net = ntohs(iface->address.s_net); /* We pass the Net:Node to the drivers/cards by a Device ioctl. */ if (!(iface->dev->do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) { (void)iface->dev->do_ioctl(iface->dev, &atreq, SIOCGIFADDR); - if ((iface->address.s_net != htons(sa->sat_addr.s_net)) || - (iface->address.s_node != sa->sat_addr.s_node)) + if (iface->address.s_net != htons(sa->sat_addr.s_net) || + iface->address.s_node != sa->sat_addr.s_node) iface->status |= ATIF_PROBE_FAIL; iface->address.s_net = htons(sa->sat_addr.s_net); @@ -523,17 +454,16 @@ void aarp_send_probe_phase1(struct atalk_iface *iface) void aarp_probe_network(struct atalk_iface *atif) { - if(atif->dev->type == ARPHRD_LOCALTLK || atif->dev->type == ARPHRD_PPP) { + if (atif->dev->type == ARPHRD_LOCALTLK || + atif->dev->type == ARPHRD_PPP) aarp_send_probe_phase1(atif); - } else { + else { unsigned int count; for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) { aarp_send_probe(atif->dev, &atif->address); - /* - * Defer 1/10th - */ + /* Defer 1/10th */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ/10); @@ -545,9 +475,9 @@ void aarp_probe_network(struct atalk_iface *atif) int aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa) { - struct aarp_entry *entry; + int hash, retval = 1; + struct aarp_entry *entry; unsigned int count; - int hash, retval; /* * we don't currently support LocalTalk or PPP for proxy AARP; @@ -564,7 +494,7 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa) * we need this one to hang around even if it's in use */ entry = aarp_alloc(); - if (entry == NULL) + if (!entry) return -ENOMEM; entry->expires_at = -1; @@ -582,56 +512,38 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa) for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) { aarp_send_probe(atif->dev, sa); - /* - * Defer 1/10th - */ + /* Defer 1/10th */ current->state = TASK_INTERRUPTIBLE; - spin_unlock_bh(&aarp_lock); - schedule_timeout(HZ/10); - spin_lock_bh(&aarp_lock); if (entry->status & ATIF_PROBE_FAIL) break; } - retval = 1; - if (entry->status & ATIF_PROBE_FAIL) { - /* free the entry */ - entry->expires_at = jiffies - 1; - - /* return network full */ - retval = -EADDRINUSE; - } else { - /* clear the probing flag */ + entry->expires_at = jiffies - 1; /* free the entry */ + retval = -EADDRINUSE; /* return network full */ + } else /* clear the probing flag */ entry->status &= ~ATIF_PROBE; - } spin_unlock_bh(&aarp_lock); - return retval; } - -/* - * Send a DDP frame - */ -int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr) +/* Send a DDP frame */ +int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, + struct at_addr *sa, void *hwaddr) { - static char ddp_eth_multicast[ETH_ALEN] = { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; + static char ddp_eth_multicast[ETH_ALEN] = + { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; int hash; struct aarp_entry *a; skb->nh.raw = skb->data; - /* - * Check for LocalTalk first - */ - - + /* Check for LocalTalk first */ if (dev->type == ARPHRD_LOCALTLK) { struct at_addr *at = atalk_find_dev_addr(dev); struct ddpehdr *ddp = (struct ddpehdr *)skb->data; @@ -644,8 +556,8 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa * (zero matches anything) */ - if( ( ddp->deh_snet==0 || at->s_net==ddp->deh_snet) && - ( ddp->deh_dnet==0 || at->s_net==ddp->deh_dnet) ) { + if ((!ddp->deh_snet || at->s_net == ddp->deh_snet) && + (!ddp->deh_dnet || at->s_net == ddp->deh_dnet)) { skb_pull(skb, sizeof(struct ddpehdr) - 4); /* @@ -665,104 +577,58 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa skb->data[0] = sa->s_node; skb->data[1] = at->s_node; skb->data[2] = ft; - - if (skb->sk) - skb->priority = skb->sk->priority; skb->dev = dev; - dev_queue_xmit(skb); - return 1; + goto sendit; } - /* - * On a PPP link we neither compress nor aarp. - */ + /* On a PPP link we neither compress nor aarp. */ if (dev->type == ARPHRD_PPP) { skb->protocol = htons(ETH_P_PPPTALK); - if (skb->sk) - skb->priority = skb->sk->priority; skb->dev = dev; - dev_queue_xmit(skb); - return 1; + goto sendit; } - /* - * Non ELAP we cannot do. - */ - + /* Non ELAP we cannot do. */ if (dev->type != ARPHRD_ETHER) return -1; skb->dev = dev; skb->protocol = htons(ETH_P_ATALK); - hash = sa->s_node % (AARP_HASH_SIZE - 1); - /* - * Do we have a resolved entry ? - */ - + /* Do we have a resolved entry? */ if (sa->s_node == ATADDR_BCAST) { ddp_dl->datalink_header(ddp_dl, skb, ddp_eth_multicast); - - if (skb->sk) - skb->priority = skb->sk->priority; - dev_queue_xmit(skb); - return 1; + goto sendit; } spin_lock_bh(&aarp_lock); - a = __aarp_find_entry(resolved[hash], dev, sa); - if (a != NULL) { - /* - * Return 1 and fill in the address - */ - + if (a) { /* Return 1 and fill in the address */ a->expires_at = jiffies + (sysctl_aarp_expiry_time * 10); ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr); - if(skb->sk) - skb->priority = skb->sk->priority; - dev_queue_xmit(skb); - spin_unlock_bh(&aarp_lock); - return 1; + goto sendit; } - /* - * Do we have an unresolved entry: This is the less common path - */ - + /* Do we have an unresolved entry: This is the less common path */ a = __aarp_find_entry(unresolved[hash], dev, sa); - if (a != NULL) { - /* - * Queue onto the unresolved queue - */ - + if (a) { /* Queue onto the unresolved queue */ skb_queue_tail(&a->packet_queue, skb); - spin_unlock_bh(&aarp_lock); return 0; } - /* - * Allocate a new entry - */ - + /* Allocate a new entry */ a = aarp_alloc(); - if (a == NULL) { - /* - * Whoops slipped... good job it's an unreliable - * protocol 8) - */ + if (!a) { + /* Whoops slipped... good job it's an unreliable protocol 8) */ spin_unlock_bh(&aarp_lock); return -1; } - /* - * Set up the queue - */ - + /* Set up the queue */ skb_queue_tail(&a->packet_queue, skb); a->expires_at = jiffies + sysctl_aarp_resolve_time; a->dev = dev; @@ -772,10 +638,7 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa unresolved[hash] = a; unresolved_count++; - /* - * Send an initial request for the address - */ - + /* Send an initial request for the address */ __aarp_send_query(a); /* @@ -786,18 +649,16 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa if (unresolved_count == 1) mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time); - - /* - * Now finally, it is safe to drop the lock. - */ - + /* Now finally, it is safe to drop the lock. */ spin_unlock_bh(&aarp_lock); - /* - * Tell the ddp layer we have taken over for this frame. - */ - + /* Tell the ddp layer we have taken over for this frame. */ return 0; + +sendit: if (skb->sk) + skb->priority = skb->sk->priority; + dev_queue_xmit(skb); + return 1; } /* @@ -806,170 +667,112 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa * * Must run under aarp_lock. */ -static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a, int hash) +static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a, + int hash) { struct sk_buff *skb; - while (*list != NULL) { + while (*list) if (*list == a) { unresolved_count--; - *list = a->next; - /* - * Move into the resolved list - */ - + /* Move into the resolved list */ a->next = resolved[hash]; resolved[hash] = a; - /* - * Kick frames off - */ - + /* Kick frames off */ while ((skb = skb_dequeue(&a->packet_queue)) != NULL) { - a->expires_at = jiffies + (sysctl_aarp_expiry_time*10); + a->expires_at = jiffies + + sysctl_aarp_expiry_time * 10; ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr); if (skb->sk) skb->priority = skb->sk->priority; dev_queue_xmit(skb); } - } else { + } else list = &((*list)->next); - } - } } /* * This is called by the SNAP driver whenever we see an AARP SNAP * frame. We currently only support Ethernet. */ -static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) +static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt) { - struct elapaarp *ea=(struct elapaarp *)skb->h.raw; + struct elapaarp *ea = (struct elapaarp *)skb->h.raw; + int hash, ret = 0; + __u16 function; struct aarp_entry *a; struct at_addr sa, *ma, da; - int hash; struct atalk_iface *ifa; - /* - * We only do Ethernet SNAP AARP. - */ - - if (dev->type != ARPHRD_ETHER) { - kfree_skb(skb); - return 0; - } - - /* - * Frame size ok ? - */ - - if (!skb_pull(skb, sizeof(*ea))) { - kfree_skb(skb); - return 0; - } - - ea->function = ntohs(ea->function); + /* We only do Ethernet SNAP AARP. */ + if (dev->type != ARPHRD_ETHER) + goto out0; - /* - * Sanity check fields. - */ + /* Frame size ok? */ + if (!skb_pull(skb, sizeof(*ea))) + goto out0; - if (ea->function < AARP_REQUEST || - ea->function > AARP_PROBE || - ea->hw_len != ETH_ALEN || - ea->pa_len != AARP_PA_ALEN || - ea->pa_src_zero != 0 || - ea->pa_dst_zero != 0) { - kfree_skb(skb); - return 0; - } + function = ntohs(ea->function); - /* - * Looks good. - */ + /* Sanity check fields. */ + if (function < AARP_REQUEST || function > AARP_PROBE || + ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN || + ea->pa_src_zero || ea->pa_dst_zero) + goto out0; + /* Looks good. */ hash = ea->pa_src_node % (AARP_HASH_SIZE - 1); - /* - * Build an address. - */ - + /* Build an address. */ sa.s_node = ea->pa_src_node; sa.s_net = ea->pa_src_net; - /* - * Process the packet. - * Check for replies of me. - */ - + /* Process the packet. Check for replies of me. */ ifa = atalk_find_dev(dev); - if (ifa == NULL) { - kfree_skb(skb); - return 1; - } - - if (ifa->status & ATIF_PROBE) { - if (ifa->address.s_node == ea->pa_dst_node && - ifa->address.s_net == ea->pa_dst_net) { - /* - * Fail the probe (in use) - */ - - ifa->status |= ATIF_PROBE_FAIL; - kfree_skb(skb); - return 1; - } + if (!ifa) + goto out1; + + if (ifa->status & ATIF_PROBE && + ifa->address.s_node == ea->pa_dst_node && + ifa->address.s_net == ea->pa_dst_net) { + ifa->status |= ATIF_PROBE_FAIL; /* Fail the probe (in use) */ + goto out1; } - /* - * Check for replies of proxy AARP entries - */ - + /* Check for replies of proxy AARP entries */ da.s_node = ea->pa_dst_node; da.s_net = ea->pa_dst_net; spin_lock_bh(&aarp_lock); - a = __aarp_find_entry(proxies[hash], dev, &da); - if (a != NULL) { - if (a->status & ATIF_PROBE) { - a->status |= ATIF_PROBE_FAIL; - - spin_unlock_bh(&aarp_lock); - - /* - * we do not respond to probe or request packets for - * this address while we are probing this address - */ - kfree_skb(skb); - - return 1; - } + if (a && a->status & ATIF_PROBE) { + a->status |= ATIF_PROBE_FAIL; + /* + * we do not respond to probe or request packets for + * this address while we are probing this address + */ + goto unlock; } - switch (ea->function) { + switch (function) { case AARP_REPLY: - if (unresolved_count == 0) /* Speed up */ + if (!unresolved_count) /* Speed up */ break; - /* - * Find the entry. - */ - - if ((a = __aarp_find_entry(unresolved[hash],dev,&sa)) == NULL || - (dev != a->dev)) + /* Find the entry. */ + a = __aarp_find_entry(unresolved[hash],dev,&sa); + if (!a || dev != a->dev) break; - /* - * We can fill one in - this is good. - */ - + /* We can fill one in - this is good. */ memcpy(a->hwaddr,ea->hw_src,ETH_ALEN); __aarp_resolved(&unresolved[hash],a,hash); - if (unresolved_count == 0) + if (!unresolved_count) mod_timer(&aarp_timer, jiffies + sysctl_aarp_expiry_time); break; @@ -977,49 +780,45 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_t case AARP_REQUEST: case AARP_PROBE: /* - * If it is my address set ma to my address and reply. We can treat probe and - * request the same. Probe simply means we shouldn't cache the querying host, - * as in a probe they are proposing an address not using one. + * If it is my address set ma to my address and + * reply. We can treat probe and request the + * same. Probe simply means we shouldn't cache + * the querying host, as in a probe they are + * proposing an address not using one. * - * Support for proxy-AARP added. We check if the address is one - * of our proxies before we toss the packet out. + * Support for proxy-AARP added. We check if the + * address is one of our proxies before we toss + * the packet out. */ sa.s_node = ea->pa_dst_node; sa.s_net = ea->pa_dst_net; - /* - * See if we have a matching proxy. - */ + /* See if we have a matching proxy. */ ma = __aarp_proxy_find(dev, &sa); - if (!ma) { + if (!ma) ma = &ifa->address; - } else { - /* - * We need to make a copy of the entry. - */ + else { /* We need to make a copy of the entry. */ da.s_node = sa.s_node; da.s_net = da.s_net; ma = &da; } - if (ea->function == AARP_PROBE) { + if (function == AARP_PROBE) { /* A probe implies someone trying to get an * address. So as a precaution flush any - * entries we have for this address. - */ + * entries we have for this address. */ struct aarp_entry *a = __aarp_find_entry( - resolved[sa.s_node%(AARP_HASH_SIZE-1)], - skb->dev, - &sa); + resolved[sa.s_node%(AARP_HASH_SIZE-1)], + skb->dev, &sa); /* Make it expire next tick - that avoids us - * getting into a probe/flush/learn/probe/flush/learn - * cycle during probing of a slow to respond host addr. - */ - if (a != NULL) - { + * getting into a probe/flush/learn/probe/ + * flush/learn cycle during probing of a slow + * to respond host addr. */ + if (a) { a->expires_at = jiffies - 1; - mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time); + mod_timer(&aarp_timer, jiffies + + sysctl_aarp_tick_time); } } @@ -1032,18 +831,16 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_t sa.s_node = ea->pa_src_node; sa.s_net = ea->pa_src_net; - /* - * aarp_my_address has found the address to use for us. - */ - + /* aarp_my_address has found the address to use for us. + */ aarp_send_reply(dev, ma, &sa, ea->hw_src); break; - }; - - spin_unlock_bh(&aarp_lock); + } - kfree_skb(skb); - return 1; +unlock: spin_unlock_bh(&aarp_lock); +out1: ret = 1; +out0: kfree_skb(skb); + return ret; } static struct notifier_block aarp_notifier = { @@ -1054,10 +851,10 @@ static struct notifier_block aarp_notifier = { static char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; - void __init aarp_proto_init(void) { - if ((aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv)) == NULL) + aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv); + if (!aarp_dl) printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); init_timer(&aarp_timer); aarp_timer.function = aarp_expire_timeout; @@ -1067,9 +864,7 @@ void __init aarp_proto_init(void) register_netdevice_notifier(&aarp_notifier); } -/* - * Remove the AARP entries associated with a device. - */ +/* Remove the AARP entries associated with a device. */ void aarp_device_down(struct net_device *dev) { int ct; @@ -1085,14 +880,12 @@ void aarp_device_down(struct net_device *dev) spin_unlock_bh(&aarp_lock); } -/* - * Called from proc fs - */ +/* Called from proc fs */ static int aarp_get_info(char *buffer, char **start, off_t offset, int length) { /* we should dump all our AARP entries */ - struct aarp_entry *entry; - int len, ct; + struct aarp_entry *entry; + int len, ct; len = sprintf(buffer, "%-10.10s ""%-10.10s""%-18.18s""%12.12s""%12.12s"" xmit_count status\n", @@ -1171,25 +964,19 @@ static int aarp_get_info(char *buffer, char **start, off_t offset, int length) } spin_unlock_bh(&aarp_lock); - return len; } #ifdef MODULE -/* - * General module cleanup. Called from cleanup_module() in ddp.c. - */ +/* General module cleanup. Called from cleanup_module() in ddp.c. */ void aarp_cleanup_module(void) { del_timer(&aarp_timer); unregister_netdevice_notifier(&aarp_notifier); unregister_snap_client(aarp_snap_id); } - #endif /* MODULE */ - #ifdef CONFIG_PROC_FS - void aarp_register_proc_fs(void) { proc_net_create("aarp", 0, aarp_get_info); @@ -1199,7 +986,5 @@ void aarp_unregister_proc_fs(void) { proc_net_remove("aarp"); } - #endif - #endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */ diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index e7784dabd..0e514faae 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -29,15 +29,17 @@ * driver file. (ipddp.c & ipddp.h) * Jay Schulist : Made work as module with * AppleTalk drivers, cleaned it. - * Rob Newberry : Added proxy AARP and AARP proc fs, - * moved probing to AARP module. + * Rob Newberry : Added proxy AARP and AARP + * procfs, moved probing to AARP + * module. * Adrian Sun/ * Michael Zuelsdorff : fix for net.0 packets. don't * allow illegal ether/tokentalk * port assignment. we lose a * valid localtalk port as a * result. - * + * Arnaldo C. de Melo : Cleanup, in preparation for + * shared skb support 8) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -84,19 +86,19 @@ #include <linux/stat.h> #include <linux/init.h> - #ifdef CONFIG_PROC_FS extern void aarp_register_proc_fs(void); extern void aarp_unregister_proc_fs(void); #endif +extern void aarp_cleanup_module(void); + extern void aarp_probe_network(struct atalk_iface *atif); -extern int aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa); +extern int aarp_proxy_probe_network(struct atalk_iface *atif, + struct at_addr *sa); extern void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa); - #undef APPLETALK_DEBUG - #ifdef APPLETALK_DEBUG #define DPRINT(x) print(x) #else @@ -119,13 +121,14 @@ static struct proto_ops atalk_dgram_ops; * * \**************************************************************************/ -static struct sock *atalk_sockets = NULL; +static struct sock *atalk_sockets; static spinlock_t atalk_sockets_lock = SPIN_LOCK_UNLOCKED; extern inline void atalk_insert_socket(struct sock *sk) { spin_lock_bh(&atalk_sockets_lock); - if ((sk->next = atalk_sockets) != NULL) + sk->next = atalk_sockets; + if (sk->next) atalk_sockets->pprev = &sk->next; atalk_sockets = sk; sk->pprev = &atalk_sockets; @@ -135,7 +138,7 @@ extern inline void atalk_insert_socket(struct sock *sk) extern inline void atalk_remove_socket(struct sock *sk) { spin_lock_bh(&atalk_sockets_lock); - if (sk->pprev != NULL) { + if (sk->pprev) { if (sk->next) sk->next->pprev = sk->pprev; *sk->pprev = sk->next; @@ -144,12 +147,13 @@ extern inline void atalk_remove_socket(struct sock *sk) spin_unlock_bh(&atalk_sockets_lock); } -static struct sock *atalk_search_socket(struct sockaddr_at *to, struct atalk_iface *atif) +static struct sock *atalk_search_socket(struct sockaddr_at *to, + struct atalk_iface *atif) { struct sock *s; spin_lock_bh(&atalk_sockets_lock); - for (s = atalk_sockets; s != NULL; s = s->next) { + for (s = atalk_sockets; s; s = s->next) { if (to->sat_port != s->protinfo.af_at.src_port) continue; @@ -174,7 +178,6 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to, struct atalk_ifa } } spin_unlock_bh(&atalk_sockets_lock); - return s; } @@ -185,29 +188,28 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to, struct atalk_ifa * * This entire operation must execute atomically. */ -static struct sock *atalk_find_or_insert_socket(struct sock *sk, struct sockaddr_at *sat) +static struct sock *atalk_find_or_insert_socket(struct sock *sk, + struct sockaddr_at *sat) { struct sock *s; spin_lock_bh(&atalk_sockets_lock); - - for (s = atalk_sockets; s != NULL; s = s->next) { + for (s = atalk_sockets; s; s = s->next) if (s->protinfo.af_at.src_net == sat->sat_addr.s_net && s->protinfo.af_at.src_node == sat->sat_addr.s_node && s->protinfo.af_at.src_port == sat->sat_port) break; - } if (!s) { /* Wheee, it's free, assign and insert. */ - if ((sk->next = atalk_sockets) != NULL) + sk->next = atalk_sockets; + if (sk->next) atalk_sockets->pprev = &sk->next; atalk_sockets = sk; sk->pprev = &atalk_sockets; } spin_unlock_bh(&atalk_sockets_lock); - return s; } @@ -215,9 +217,8 @@ static void atalk_destroy_timer(unsigned long data) { struct sock *sk = (struct sock *) data; - if (atomic_read(&sk->wmem_alloc) == 0 && - atomic_read(&sk->rmem_alloc) == 0 && - sk->dead) { + if (!atomic_read(&sk->wmem_alloc) && + !atomic_read(&sk->rmem_alloc) && sk->dead) { sock_put(sk); MOD_DEC_USE_COUNT; } else { @@ -228,16 +229,11 @@ static void atalk_destroy_timer(unsigned long data) extern inline void atalk_destroy_socket(struct sock *sk) { - struct sk_buff *skb; - atalk_remove_socket(sk); + skb_queue_purge(&sk->receive_queue); - while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) - kfree_skb(skb); - - if (atomic_read(&sk->wmem_alloc) == 0 && - atomic_read(&sk->rmem_alloc) == 0 && - sk->dead) { + if (!atomic_read(&sk->wmem_alloc) && + !atomic_read(&sk->rmem_alloc) && sk->dead) { sock_put(sk); MOD_DEC_USE_COUNT; } else { @@ -249,37 +245,31 @@ extern inline void atalk_destroy_socket(struct sock *sk) } } -/* - * Called from proc fs - */ +/* Called from proc fs */ static int atalk_get_info(char *buffer, char **start, off_t offset, int length) { - struct sock *s; - int len = 0; off_t pos = 0; off_t begin = 0; - - /* - * Output the AppleTalk data for the /proc filesystem. - */ - - len += sprintf(buffer,"Type local_addr remote_addr tx_queue rx_queue st uid\n"); + int len = sprintf(buffer, "Type local_addr remote_addr tx_queue " + "rx_queue st uid\n"); + struct sock *s; + /* Output the AppleTalk data for the /proc filesystem */ spin_lock_bh(&atalk_sockets_lock); - for (s = atalk_sockets; s != NULL; s = s->next) { - len += sprintf(buffer+len,"%02X ", s->type); - len += sprintf(buffer+len,"%04X:%02X:%02X ", + for (s = atalk_sockets; s; s = s->next) { + len += sprintf(buffer + len,"%02X ", s->type); + len += sprintf(buffer + len,"%04X:%02X:%02X ", ntohs(s->protinfo.af_at.src_net), s->protinfo.af_at.src_node, s->protinfo.af_at.src_port); - len += sprintf(buffer+len,"%04X:%02X:%02X ", + len += sprintf(buffer + len,"%04X:%02X:%02X ", ntohs(s->protinfo.af_at.dest_net), s->protinfo.af_at.dest_node, s->protinfo.af_at.dest_port); - len += sprintf(buffer+len,"%08X:%08X ", + len += sprintf(buffer + len,"%08X:%08X ", atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc)); - len += sprintf(buffer+len,"%02X %d\n", s->state, + len += sprintf(buffer + len,"%02X %d\n", s->state, SOCK_INODE(s->socket)->i_uid); /* Are we still dumping unwanted data then discard the record */ @@ -295,8 +285,8 @@ static int atalk_get_info(char *buffer, char **start, off_t offset, int length) spin_unlock_bh(&atalk_sockets_lock); /* 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 */ + *start = buffer + offset - begin; /* Start of wanted data */ + len -= offset - begin; /* Remove unwanted header data from length */ if (len > length) len = length; /* Remove unwanted tail data from length */ @@ -310,18 +300,16 @@ static int atalk_get_info(char *buffer, char **start, off_t offset, int length) \**************************************************************************/ /* Anti-deadlock ordering is router_lock --> iface_lock -DaveM */ -static struct atalk_route *atalk_router_list = NULL; +static struct atalk_route *atalk_router_list; static rwlock_t atalk_router_lock = RW_LOCK_UNLOCKED; -static struct atalk_iface *atalk_iface_list = NULL; +static struct atalk_iface *atalk_iface_list; static spinlock_t atalk_iface_lock = SPIN_LOCK_UNLOCKED; -static struct atalk_route atrtr_default; /* For probing devices or in a routerless network */ - -/* - * AppleTalk interface control - */ +/* For probing devices or in a routerless network */ +static struct atalk_route atrtr_default; +/* AppleTalk interface control */ /* * Drop a device. Doesn't drop any of its routes - that is the caller's * problem. Called when we down the interface or delete the address. @@ -344,12 +332,12 @@ static void atif_drop_device(struct net_device *dev) spin_unlock_bh(&atalk_iface_lock); } -static struct atalk_iface *atif_add_device(struct net_device *dev, struct at_addr *sa) +static struct atalk_iface *atif_add_device(struct net_device *dev, + struct at_addr *sa) { - struct atalk_iface *iface = (struct atalk_iface *) - kmalloc(sizeof(*iface), GFP_KERNEL); + struct atalk_iface *iface = kmalloc(sizeof(*iface), GFP_KERNEL); - if (iface == NULL) + if (!iface) return NULL; iface->dev = dev; @@ -363,51 +351,37 @@ static struct atalk_iface *atif_add_device(struct net_device *dev, struct at_add spin_unlock_bh(&atalk_iface_lock); MOD_INC_USE_COUNT; - return iface; } - -/* - * Perform phase 2 AARP probing on our tentative address. - */ +/* Perform phase 2 AARP probing on our tentative address */ static int atif_probe_device(struct atalk_iface *atif) { - int netrange = ntohs(atif->nets.nr_lastnet) - ntohs(atif->nets.nr_firstnet) + 1; + int netrange = ntohs(atif->nets.nr_lastnet) - + ntohs(atif->nets.nr_firstnet) + 1; int probe_net = ntohs(atif->address.s_net); int probe_node = atif->address.s_node; int netct, nodect; - /* - * Offset the network we start probing with. - */ - + /* Offset the network we start probing with */ if (probe_net == ATADDR_ANYNET) { - if (!netrange) - probe_net = ntohs(atif->nets.nr_firstnet); - else - probe_net = ntohs(atif->nets.nr_firstnet) + (jiffies % netrange); + probe_net = ntohs(atif->nets.nr_firstnet); + if (netrange) + probe_net += jiffies % netrange; } - if (probe_node == ATADDR_ANYNODE) probe_node = jiffies & 0xFF; - /* - * Scan the networks. - */ + /* Scan the networks */ atif->status |= ATIF_PROBE; for (netct = 0; netct <= netrange; netct++) { - /* - * Sweep the available nodes from a given start. - */ - + /* Sweep the available nodes from a given start */ atif->address.s_net = htons(probe_net); for (nodect = 0; nodect < 256; nodect++) { atif->address.s_node = ((nodect+probe_node) & 0xFF); - if (atif->address.s_node > 0 && atif->address.s_node < 254) { - /* - * Probe a proposed address. - */ + if (atif->address.s_node > 0 && + atif->address.s_node < 254) { + /* Probe a proposed address */ aarp_probe_network(atif); if (!(atif->status & ATIF_PROBE_FAIL)) { @@ -427,58 +401,45 @@ static int atif_probe_device(struct atalk_iface *atif) } -/* - * Perform AARP probing for a proxy address - */ -static int atif_proxy_probe_device(struct atalk_iface *atif, struct at_addr* proxy_addr) +/* Perform AARP probing for a proxy address */ +static int atif_proxy_probe_device(struct atalk_iface *atif, + struct at_addr* proxy_addr) { - int netrange = ntohs(atif->nets.nr_lastnet) - ntohs(atif->nets.nr_firstnet) + 1; - int probe_net = ntohs(atif->address.s_net); /* we probe the interface's network */ + int netrange = ntohs(atif->nets.nr_lastnet) - + ntohs(atif->nets.nr_firstnet) + 1; + /* we probe the interface's network */ + int probe_net = ntohs(atif->address.s_net); int probe_node = ATADDR_ANYNODE; /* we'll take anything */ int netct, nodect; - /* - * Offset the network we start probing with. - */ - + /* Offset the network we start probing with */ if (probe_net == ATADDR_ANYNET) { - if (!netrange) - probe_net = ntohs(atif->nets.nr_firstnet); - else - probe_net = ntohs(atif->nets.nr_firstnet) + (jiffies % netrange); + probe_net = ntohs(atif->nets.nr_firstnet); + if (netrange) + probe_net += jiffies % netrange; } if (probe_node == ATADDR_ANYNODE) probe_node = jiffies & 0xFF; - /* - * Scan the networks. - */ - + /* Scan the networks */ for (netct = 0; netct <= netrange; netct++) { - /* - * Sweep the available nodes from a given start. - */ - + /* Sweep the available nodes from a given start */ proxy_addr->s_net = htons(probe_net); for (nodect = 0; nodect < 256; nodect++) { proxy_addr->s_node = ((nodect + probe_node) & 0xFF); - if ((proxy_addr->s_node > 0) && (proxy_addr->s_node < 254)) { - /* - * Tell AARP to probe a proposed address. - */ - int probe_result = aarp_proxy_probe_network(atif, - proxy_addr); - - if (probe_result == 0) - return 0; - - if (probe_result != -EADDRINUSE) - return probe_result; + if (proxy_addr->s_node > 0 && + proxy_addr->s_node < 254) { + /* Tell AARP to probe a proposed address */ + int ret = aarp_proxy_probe_network(atif, + proxy_addr); + + if (ret != -EADDRINUSE) + return ret; } } probe_net++; - if(probe_net > ntohs(atif->nets.nr_lastnet)) + if (probe_net > ntohs(atif->nets.nr_lastnet)) probe_net = ntohs(atif->nets.nr_firstnet); } @@ -489,25 +450,21 @@ static int atif_proxy_probe_device(struct atalk_iface *atif, struct at_addr* pro struct at_addr *atalk_find_dev_addr(struct net_device *dev) { struct atalk_iface *iface = dev->atalk_ptr; - - if(iface) - return &iface->address; - - return NULL; + return iface ? &iface->address : NULL; } static struct at_addr *atalk_find_primary(void) { + struct atalk_iface *fiface = NULL; struct at_addr *retval; struct atalk_iface *iface; - struct atalk_iface *fiface = NULL; /* * Return a point-to-point interface only if * there is no non-ptp interface available. */ spin_lock_bh(&atalk_iface_lock); - for (iface = atalk_iface_list; iface != NULL; iface = iface->next) { + for (iface = atalk_iface_list; iface; iface = iface->next) { if (!fiface && !(iface->dev->flags & IFF_LOOPBACK)) fiface = iface; if (!(iface->dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) { @@ -516,16 +473,13 @@ static struct at_addr *atalk_find_primary(void) } } - if (fiface) { + if (fiface) retval = &fiface->address; - } else if (atalk_iface_list != NULL) { + else if (atalk_iface_list) retval = &atalk_iface_list->address; - } else { + else retval = NULL; - } -out: - spin_unlock_bh(&atalk_iface_lock); - +out: spin_unlock_bh(&atalk_iface_lock); return retval; } @@ -535,9 +489,9 @@ out: */ static struct atalk_iface *atalk_find_anynet(int node, struct net_device *dev) { - struct atalk_iface *iface=dev->atalk_ptr; + struct atalk_iface *iface = dev->atalk_ptr; - if (iface==NULL || (iface->status & ATIF_PROBE)) + if (!iface || iface->status & ATIF_PROBE) return NULL; if (node == ATADDR_BCAST || @@ -548,15 +502,13 @@ static struct atalk_iface *atalk_find_anynet(int node, struct net_device *dev) return NULL; } -/* - * Find a match for a specific network:node pair - */ +/* Find a match for a specific network:node pair */ static struct atalk_iface *atalk_find_interface(int net, int node) { struct atalk_iface *iface; spin_lock_bh(&atalk_iface_lock); - for (iface = atalk_iface_list; iface != NULL; iface = iface->next) { + for (iface = atalk_iface_list; iface; iface = iface->next) { if ((node == ATADDR_BCAST || node == ATADDR_ANYNODE || iface->address.s_node == node) && @@ -565,13 +517,12 @@ static struct atalk_iface *atalk_find_interface(int net, int node) break; /* XXXX.0 -- net.0 returns the iface associated with net */ - if ((node == ATADDR_ANYNODE) && (net != ATADDR_ANYNET) && - (ntohs(iface->nets.nr_firstnet) <= ntohs(net)) && - (ntohs(net) <= ntohs(iface->nets.nr_lastnet))) + if (node == ATADDR_ANYNODE && net != ATADDR_ANYNET && + ntohs(iface->nets.nr_firstnet) <= ntohs(net) && + ntohs(net) <= ntohs(iface->nets.nr_lastnet)) break; } spin_unlock_bh(&atalk_iface_lock); - return iface; } @@ -588,11 +539,11 @@ static struct atalk_route *atrtr_find(struct at_addr *target) * host route, because some host routes might overlap * network routes */ - struct atalk_route *r; struct atalk_route *net_route = NULL; + struct atalk_route *r; read_lock_bh(&atalk_router_lock); - for (r = atalk_router_list; r != NULL; r = r->next) { + for (r = atalk_router_list; r; r = r->next) { if (!(r->flags & RTF_UP)) continue; @@ -604,13 +555,12 @@ static struct atalk_route *atrtr_find(struct at_addr *target) */ if (r->target.s_node == target->s_node) goto out; - } else { + } else /* * this route will work if there isn't a * direct host route, so cache it */ net_route = r; - } } } @@ -618,19 +568,13 @@ static struct atalk_route *atrtr_find(struct at_addr *target) * if we found a network route but not a direct host * route, then return it */ - if (net_route != NULL) { + if (net_route) r = net_route; - } else if (atrtr_default.dev) { + else if (atrtr_default.dev) r = &atrtr_default; - } else { - /* - * No route can be found. - */ + else /* No route can be found */ r = NULL; - } - -out: - read_unlock_bh(&atalk_router_lock); +out: read_unlock_bh(&atalk_router_lock); return r; } @@ -642,16 +586,10 @@ out: struct net_device *atrtr_get_dev(struct at_addr *sa) { struct atalk_route *atr = atrtr_find(sa); - - if (atr == NULL) - return NULL; - else - return atr->dev; + return atr ? atr->dev : NULL; } -/* - * Set up a default router. - */ +/* Set up a default router */ static void atrtr_set_default(struct net_device *dev) { atrtr_default.dev = dev; @@ -678,20 +616,16 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint) * operations. */ - /* - * Validate the request - */ + /* Validate the request */ if (ta->sat_family != AF_APPLETALK) return -EINVAL; - if (devhint == NULL && ga->sat_family != AF_APPLETALK) + if (!devhint && ga->sat_family != AF_APPLETALK) return -EINVAL; - /* - * Now walk the routing table and make our decisions. - */ + /* Now walk the routing table and make our decisions */ write_lock_bh(&atalk_router_lock); - for (rt = atalk_router_list; rt != NULL; rt = rt->next) { + for (rt = atalk_router_list; rt; rt = rt->next) { if (r->rt_flags != rt->flags) continue; @@ -703,65 +637,59 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint) } } - if(devhint == NULL) { + if (!devhint) { riface = NULL; spin_lock_bh(&atalk_iface_lock); for (iface = atalk_iface_list; iface; iface = iface->next) { - if (riface == NULL && - ntohs(ga->sat_addr.s_net) >= ntohs(iface->nets.nr_firstnet) && - ntohs(ga->sat_addr.s_net) <= ntohs(iface->nets.nr_lastnet)) + if (!riface && + ntohs(ga->sat_addr.s_net) >= + ntohs(iface->nets.nr_firstnet) && + ntohs(ga->sat_addr.s_net) <= + ntohs(iface->nets.nr_lastnet)) riface = iface; - if (ga->sat_addr.s_net == iface->address.s_net && + if (ga->sat_addr.s_net == iface->address.s_net && ga->sat_addr.s_node == iface->address.s_node) riface = iface; } spin_unlock_bh(&atalk_iface_lock); retval = -ENETUNREACH; - if (riface == NULL) + if (!riface) goto out; devhint = riface->dev; } - if (rt == NULL) { - rt = (struct atalk_route *) - kmalloc(sizeof(struct atalk_route), GFP_ATOMIC); + if (!rt) { + rt = kmalloc(sizeof(struct atalk_route), GFP_ATOMIC); retval = -ENOBUFS; - if (rt == NULL) + if (!rt) goto out; rt->next = atalk_router_list; atalk_router_list = rt; } - /* - * Fill in the routing entry. - */ + /* Fill in the routing entry */ rt->target = ta->sat_addr; rt->dev = devhint; rt->flags = r->rt_flags; rt->gateway = ga->sat_addr; retval = 0; - -out: - write_unlock_bh(&atalk_router_lock); - +out: write_unlock_bh(&atalk_router_lock); return retval; } -/* - * Delete a route. Find it and discard it. - */ +/* Delete a route. Find it and discard it */ static int atrtr_delete(struct at_addr * addr) { struct atalk_route **r = &atalk_router_list; - struct atalk_route *tmp; int retval = 0; + struct atalk_route *tmp; write_lock_bh(&atalk_router_lock); while ((tmp = *r) != NULL) { @@ -775,8 +703,7 @@ static int atrtr_delete(struct at_addr * addr) r = &tmp->next; } retval = -ENOENT; -out: - write_unlock_bh(&atalk_router_lock); +out: write_unlock_bh(&atalk_router_lock); return retval; } @@ -794,9 +721,8 @@ void atrtr_device_down(struct net_device *dev) if (tmp->dev == dev) { *r = tmp->next; kfree(tmp); - } else { + } else r = &tmp->next; - } } write_unlock_bh(&atalk_router_lock); @@ -804,9 +730,7 @@ void atrtr_device_down(struct net_device *dev) atrtr_set_default(NULL); } -/* - * Actually down the interface. - */ +/* Actually down the interface */ static inline void atalk_dev_down(struct net_device *dev) { atrtr_device_down(dev); /* Remove all routes for the device */ @@ -818,27 +742,22 @@ static inline void atalk_dev_down(struct net_device *dev) * A device event has occurred. Watch for devices going down and * delete our use of them (iface and route). */ -static int ddp_device_event(struct notifier_block *this, unsigned long event, void *ptr) +static int ddp_device_event(struct notifier_block *this, unsigned long event, + void *ptr) { - if (event == NETDEV_DOWN) { + if (event == NETDEV_DOWN) /* Discard any use of this */ atalk_dev_down((struct net_device *) ptr); - } return NOTIFY_DONE; } -/* - * ioctl calls. Shouldn't even need touching. - */ - -/* - * Device configuration ioctl calls. - */ +/* ioctl calls. Shouldn't even need touching */ +/* Device configuration ioctl calls */ int atif_ioctl(int cmd, void *arg) { - struct ifreq atreq; static char aarp_mcast[6] = {0x09, 0x00, 0x00, 0xFF, 0xFF, 0xFF}; + struct ifreq atreq; struct netrange *nr; struct sockaddr_at *sa; struct net_device *dev; @@ -846,12 +765,13 @@ int atif_ioctl(int cmd, void *arg) int ct; int limit; struct rtentry rtdef; - int add_route; + int add_route; if (copy_from_user(&atreq, arg, sizeof(atreq))) return -EFAULT; - if ((dev = __dev_get_by_name(atreq.ifr_name)) == NULL) + dev = __dev_get_by_name(atreq.ifr_name); + if (!dev) return -ENODEV; sa = (struct sockaddr_at*) &atreq.ifr_addr; @@ -870,16 +790,19 @@ int atif_ioctl(int cmd, void *arg) return -EPROTONOSUPPORT; nr = (struct netrange *) &sa->sat_zero[0]; - add_route = 1; /* - * if this is a point-to-point iface, and we already have an - * iface for this AppleTalk address, then we should not add a route + * if this is a point-to-point iface, and we already + * have an iface for this AppleTalk address, then we + * should not add a route */ if ((dev->flags & IFF_POINTOPOINT) && - atalk_find_interface(sa->sat_addr.s_net, sa->sat_addr.s_node)) { - printk(KERN_DEBUG "AppleTalk: point-to-point interface added with existing address\n"); + atalk_find_interface(sa->sat_addr.s_net, + sa->sat_addr.s_node)) { + printk(KERN_DEBUG "AppleTalk: point-to-point " + "interface added with " + "existing address\n"); add_route = 0; } @@ -889,13 +812,11 @@ int atif_ioctl(int cmd, void *arg) */ if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2) return -EPROTONOSUPPORT; - if (sa->sat_addr.s_node == ATADDR_BCAST || + if (sa->sat_addr.s_node == ATADDR_BCAST || sa->sat_addr.s_node == 254) return -EINVAL; if (atif) { - /* - * Already setting address. - */ + /* Already setting address */ if (atif->status & ATIF_PROBE) return -EBUSY; @@ -904,7 +825,7 @@ int atif_ioctl(int cmd, void *arg) atrtr_device_down(dev); /* Flush old routes */ } else { atif = atif_add_device(dev, &sa->sat_addr); - if (atif == NULL) + if (!atif) return -ENOMEM; } atif->nets = *nr; @@ -921,10 +842,7 @@ int atif_ioctl(int cmd, void *arg) return -EADDRINUSE; } - /* - * Hey it worked - add the direct routes. - */ - + /* Hey it worked - add the direct routes */ sa = (struct sockaddr_at *) &rtdef.rt_gateway; sa->sat_family = AF_APPLETALK; sa->sat_addr.s_net = atif->address.s_net; @@ -933,13 +851,11 @@ int atif_ioctl(int cmd, void *arg) rtdef.rt_flags = RTF_UP; sa->sat_family = AF_APPLETALK; sa->sat_addr.s_node = ATADDR_ANYNODE; - if ((dev->flags & IFF_LOOPBACK) || - (dev->flags & IFF_POINTOPOINT)) + if (dev->flags & IFF_LOOPBACK || + dev->flags & IFF_POINTOPOINT) rtdef.rt_flags |= RTF_HOST; - /* - * Routerless initial state. - */ + /* Routerless initial state */ if (nr->nr_firstnet == htons(0) && nr->nr_lastnet == htons(0xFFFE)) { sa->sat_addr.s_net = atif->address.s_net; @@ -948,37 +864,35 @@ int atif_ioctl(int cmd, void *arg) } else { limit = ntohs(nr->nr_lastnet); if (limit - ntohs(nr->nr_firstnet) > 4096) { - printk(KERN_WARNING "Too many routes/iface.\n"); + printk(KERN_WARNING "Too many routes/" + "iface.\n"); return -EINVAL; } - if (add_route) { - for(ct = ntohs(nr->nr_firstnet);ct <= limit; ct++) { + if (add_route) + for (ct = ntohs(nr->nr_firstnet); + ct <= limit; ct++) { sa->sat_addr.s_net = htons(ct); atrtr_create(&rtdef, dev); } - } } dev_mc_add(dev, aarp_mcast, 6, 1); return 0; case SIOCGIFADDR: - if (atif == NULL) + if (!atif) return -EADDRNOTAVAIL; - ((struct sockaddr_at *)(&atreq.ifr_addr))->sat_family = - AF_APPLETALK; - ((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr = - atif->address; + + sa->sat_family = AF_APPLETALK; + sa->sat_addr = atif->address; break; case SIOCGIFBRDADDR: - if (atif == NULL) + if (!atif) return -EADDRNOTAVAIL; - ((struct sockaddr_at *)(&atreq.ifr_addr))->sat_family = - AF_APPLETALK; - ((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr.s_net = - atif->address.s_net; - ((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr.s_node = - ATADDR_BCAST; + + sa->sat_family = AF_APPLETALK; + sa->sat_addr.s_net = atif->address.s_net; + sa->sat_addr.s_node = ATADDR_BCAST; break; case SIOCATALKDIFADDR: @@ -995,7 +909,7 @@ int atif_ioctl(int cmd, void *arg) return -EPERM; if (sa->sat_family != AF_APPLETALK) return -EINVAL; - if (atif == NULL) + if (!atif) return -EADDRNOTAVAIL; /* @@ -1007,9 +921,10 @@ int atif_ioctl(int cmd, void *arg) /* * atif points to the current interface on this network; - * we aren't concerned about its current status (at least for now), - * but it has all the settings about the network we're going - * to probe. consequently, it must exist. + * we aren't concerned about its current status (at + * least for now), but it has all the settings about + * the network we're going to probe. Consequently, it + * must exist. */ if (!atif) return -EADDRNOTAVAIL; @@ -1034,10 +949,10 @@ int atif_ioctl(int cmd, void *arg) return -EADDRINUSE; /* - * We now have an address on the local network, and the AARP - * code will defend it for us until we take it down. - * We don't set up any routes right now, because ATCP will - * install them manually via SIOCADDRT. + * We now have an address on the local network, and + * the AARP code will defend it for us until we take it + * down. We don't set up any routes right now, because + * ATCP will install them manually via SIOCADDRT. */ break; @@ -1046,30 +961,22 @@ int atif_ioctl(int cmd, void *arg) return -EPERM; if (sa->sat_family != AF_APPLETALK) return -EINVAL; - if (atif == NULL) + if (!atif) return -EADDRNOTAVAIL; - /* - * give to aarp module to remove proxy entry - */ + /* give to aarp module to remove proxy entry */ aarp_proxy_remove(atif->dev, &(sa->sat_addr)); - return 0; - }; - - if (copy_to_user(arg, &atreq, sizeof(atreq))) - return -EFAULT; + } - return 0; + return copy_to_user(arg, &atreq, sizeof(atreq)) ? -EFAULT : 0; } -/* - * Routing ioctl() calls - */ +/* Routing ioctl() calls */ static int atrtr_ioctl(unsigned int cmd, void *arg) { - struct rtentry rt; struct net_device *dev = NULL; + struct rtentry rt; if (copy_from_user(&rt, arg, sizeof(rt))) return -EFAULT; @@ -1078,37 +985,38 @@ static int atrtr_ioctl(unsigned int cmd, void *arg) case SIOCDELRT: if (rt.rt_dst.sa_family != AF_APPLETALK) return -EINVAL; - return atrtr_delete(&((struct sockaddr_at *)&rt.rt_dst)->sat_addr); + return atrtr_delete(&((struct sockaddr_at *) + &rt.rt_dst)->sat_addr); case SIOCADDRT: - /* FIX ME: the name of the device is still in user space, isn't it? */ - if (rt.rt_dev != NULL) { - if ((dev = __dev_get_by_name(rt.rt_dev)) == NULL) + /* FIXME: the name of the device is still in user + * space, isn't it? */ + if (rt.rt_dev) { + dev = __dev_get_by_name(rt.rt_dev); + if (!dev) return -ENODEV; } return atrtr_create(&rt, dev); - - default: - return -EINVAL; - }; + } + return -EINVAL; } /* Called from proc fs - just make it print the ifaces neatly */ - -static int atalk_if_get_info(char *buffer, char **start, off_t offset, int length) +static int atalk_if_get_info(char *buffer, char **start, off_t offset, + int length) { - struct atalk_iface *iface; - int len = 0; off_t pos = 0; off_t begin = 0; - - len += sprintf(buffer,"Interface Address Networks Status\n"); + struct atalk_iface *iface; + int len = sprintf(buffer, "Interface Address " + "Networks Status\n"); spin_lock_bh(&atalk_iface_lock); - for (iface = atalk_iface_list; iface != NULL; iface = iface->next) { + for (iface = atalk_iface_list; iface; iface = iface->next) { len += sprintf(buffer+len,"%-16s %04X:%02X %04X-%04X %d\n", iface->dev->name, ntohs(iface->address.s_net), - iface->address.s_node, ntohs(iface->nets.nr_firstnet), + iface->address.s_node, + ntohs(iface->nets.nr_firstnet), ntohs(iface->nets.nr_lastnet), iface->status); pos = begin + len; if (pos < offset) { @@ -1124,33 +1032,32 @@ static int atalk_if_get_info(char *buffer, char **start, off_t offset, int lengt len -= (offset - begin); if (len > length) len = length; - - return (len); + return len; } /* Called from proc fs - just make it print the routes neatly */ - -static int atalk_rt_get_info(char *buffer, char **start, off_t offset, int length) +static int atalk_rt_get_info(char *buffer, char **start, off_t offset, + int length) { - struct atalk_route *rt; - int len = 0; off_t pos = 0; off_t begin = 0; + int len = sprintf(buffer, "Target Router Flags Dev\n"); + struct atalk_route *rt; - len += sprintf(buffer,"Target Router Flags Dev\n"); if (atrtr_default.dev) { rt = &atrtr_default; - len += sprintf(buffer+len,"Default %04X:%02X %-4d %s\n", + len += sprintf(buffer + len,"Default %04X:%02X %-4d %s\n", ntohs(rt->gateway.s_net), rt->gateway.s_node, rt->flags, rt->dev->name); } read_lock_bh(&atalk_router_lock); - for (rt = atalk_router_list; rt != NULL; rt = rt->next) { - len += sprintf(buffer+len,"%04X:%02X %04X:%02X %-4d %s\n", + for (rt = atalk_router_list; rt; rt = rt->next) { + len += sprintf(buffer + len, + "%04X:%02X %04X:%02X %-4d %s\n", ntohs(rt->target.s_net), rt->target.s_node, - ntohs(rt->gateway.s_net), rt->gateway.s_node, rt->flags, - rt->dev->name); + ntohs(rt->gateway.s_net), rt->gateway.s_node, + rt->flags, rt->dev->name); pos = begin + len; if (pos < offset) { len = 0; @@ -1165,7 +1072,6 @@ static int atalk_rt_get_info(char *buffer, char **start, off_t offset, int lengt len -= (offset - begin); if (len > length) len = length; - return len; } @@ -1198,11 +1104,8 @@ unsigned short atalk_checksum(struct ddpehdr *ddp, int len) } data++; } - - if (sum) - return htons((unsigned short) sum); - - return 0xFFFF; /* Use 0xFFFF for 0. 0 itself means none */ + /* Use 0xFFFF for 0. 0 itself means none */ + return sum ? htons((unsigned short) sum) : 0xFFFF; } /* @@ -1211,10 +1114,9 @@ unsigned short atalk_checksum(struct ddpehdr *ddp, int len) */ static int atalk_create(struct socket *sock, int protocol) { - struct sock *sk; + struct sock *sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1); - sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1); - if (sk == NULL) + if (!sk) return -ENOMEM; switch (sock->type) { @@ -1230,36 +1132,32 @@ static int atalk_create(struct socket *sock, int protocol) case SOCK_STREAM: /* - * TO DO: if you want to implement ADSP, here's the place to start + * TODO: if you want to implement ADSP, here's the + * place to start */ /* sock->ops = &atalk_stream_ops; break; */ default: - sk_free((void *) sk); + sk_free(sk); return -ESOCKTNOSUPPORT; - }; + } MOD_INC_USE_COUNT; - sock_init_data(sock, sk); - sk->destruct = NULL; /* Checksums on by default */ sk->zapped = 1; - return 0; } -/* - * Free a socket. No work needed - */ +/* Free a socket. No work needed */ static int atalk_release(struct socket *sock) { - struct sock *sk=sock->sk; + struct sock *sk = sock->sk; - if (sk == NULL) + if (!sk) return 0; if (!sk->dead) @@ -1268,7 +1166,6 @@ static int atalk_release(struct socket *sock) sk->dead = 1; sock->sk = NULL; atalk_destroy_socket(sk); - return 0; } @@ -1289,21 +1186,21 @@ static int atalk_pick_and_bind_port(struct sock *sk, struct sockaddr_at *sat) for (sat->sat_port = ATPORT_RESERVED; sat->sat_port < ATPORT_LAST; sat->sat_port++) { - for (s = atalk_sockets; s != NULL; s = s->next) { + for (s = atalk_sockets; s; s = s->next) { if (s->protinfo.af_at.src_net == sat->sat_addr.s_net && - s->protinfo.af_at.src_node == sat->sat_addr.s_node && + s->protinfo.af_at.src_node == + sat->sat_addr.s_node && s->protinfo.af_at.src_port == sat->sat_port) goto try_next_port; } /* Wheee, it's free, assign and insert. */ - if ((sk->next = atalk_sockets) != NULL) + sk->next = atalk_sockets; + if (sk->next) atalk_sockets->pprev = &sk->next; atalk_sockets = sk; sk->pprev = &atalk_sockets; - sk->protinfo.af_at.src_port = sat->sat_port; - retval = 0; goto out; @@ -1312,61 +1209,53 @@ static int atalk_pick_and_bind_port(struct sock *sk, struct sockaddr_at *sat) } retval = -EBUSY; -out: - spin_unlock_bh(&atalk_sockets_lock); - +out: spin_unlock_bh(&atalk_sockets_lock); return retval; } static int atalk_autobind(struct sock *sk) { - struct at_addr *ap = atalk_find_primary(); struct sockaddr_at sat; int n; + struct at_addr *ap = atalk_find_primary(); - if (ap == NULL || ap->s_net == htons(ATADDR_ANYNET)) + if (!ap || ap->s_net == htons(ATADDR_ANYNET)) return -EADDRNOTAVAIL; sk->protinfo.af_at.src_net = sat.sat_addr.s_net = ap->s_net; sk->protinfo.af_at.src_node = sat.sat_addr.s_node = ap->s_node; - if ((n = atalk_pick_and_bind_port(sk, &sat)) < 0) + n = atalk_pick_and_bind_port(sk, &sat); + if (n < 0) return n; sk->zapped = 0; - return 0; } -/* - * Set the address 'our end' of the connection. - */ +/* Set the address 'our end' of the connection */ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { - struct sock *sk; struct sockaddr_at *addr = (struct sockaddr_at *)uaddr; + struct sock *sk = sock->sk; - sk = sock->sk; - - if(sk->zapped == 0) - return -EINVAL; - - if(addr_len != sizeof(struct sockaddr_at)) + if (!sk->zapped || addr_len != sizeof(struct sockaddr_at)) return -EINVAL; - if(addr->sat_family != AF_APPLETALK) + if (addr->sat_family != AF_APPLETALK) return -EAFNOSUPPORT; - if(addr->sat_addr.s_net == htons(ATADDR_ANYNET)) { + if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) { struct at_addr *ap = atalk_find_primary(); - if(ap == NULL) + if (!ap) return -EADDRNOTAVAIL; sk->protinfo.af_at.src_net = addr->sat_addr.s_net = ap->s_net; sk->protinfo.af_at.src_node = addr->sat_addr.s_node= ap->s_node; } else { - if (atalk_find_interface(addr->sat_addr.s_net, addr->sat_addr.s_node) == NULL) + if (!atalk_find_interface(addr->sat_addr.s_net, + addr->sat_addr.s_node)) return -EADDRNOTAVAIL; sk->protinfo.af_at.src_net = addr->sat_addr.s_net; @@ -1381,18 +1270,15 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) } else { sk->protinfo.af_at.src_port = addr->sat_port; - if (atalk_find_or_insert_socket(sk, addr) != NULL) + if (atalk_find_or_insert_socket(sk, addr)) return -EADDRINUSE; } sk->zapped = 0; - return 0; } -/* - * Set the address we talk to. - */ +/* Set the address we talk to */ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { @@ -1412,19 +1298,20 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, if (addr->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) { #if 1 - printk(KERN_WARNING "%s is broken and did not set SO_BROADCAST. It will break when 2.2 is released.\n", + printk(KERN_WARNING "%s is broken and did not set " + "SO_BROADCAST. It will break when 2.2 is " + "released.\n", current->comm); #else return -EACCES; #endif } - if (sk->zapped) { + if (sk->zapped) if (atalk_autobind(sk) < 0) return -EBUSY; - } - if (atrtr_get_dev(&addr->sat_addr) == NULL) + if (!atrtr_get_dev(&addr->sat_addr)) return -ENETUNREACH; sk->protinfo.af_at.dest_port = addr->sat_port; @@ -1433,7 +1320,6 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, sock->state = SS_CONNECTED; sk->state = TCP_ESTABLISHED; - return 0; } @@ -1446,13 +1332,11 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sockaddr_at sat; - struct sock *sk; + struct sock *sk = sock->sk; - sk = sock->sk; - if (sk->zapped) { + if (sk->zapped) if (atalk_autobind(sk) < 0) return -ENOBUFS; - } *uaddr_len = sizeof(struct sockaddr_at); @@ -1471,7 +1355,6 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, sat.sat_family = AF_APPLETALK; memcpy(uaddr, &sat, sizeof(sat)); - return 0; } @@ -1482,20 +1365,19 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, * extracted. PPP should probably pass frames marked as for this layer. * [ie ARPHRD_ETHERTALK] */ -static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) +static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt) { - struct sock *sock; struct ddpehdr *ddp = (void *) skb->h.raw; + struct sock *sock; struct atalk_iface *atif; struct sockaddr_at tosat; int origlen; struct ddpebits ddphv; /* Size check */ - if (skb->len < sizeof(*ddp)) { - kfree_skb(skb); - return 0; - } + if (skb->len < sizeof(*ddp)) + goto freeit; /* * Fix up the length field [Ok this is horrible but otherwise @@ -1506,15 +1388,10 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ * happens to be safe BUT.. (Its safe as user space will not * run until we put it back) */ - *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp)); - /* - * Trim buffer in case of stray trailing data - */ - + /* Trim buffer in case of stray trailing data */ origlen = skb->len; - skb_trim(skb, min(skb->len, ddphv.deh_len)); /* @@ -1522,32 +1399,26 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ * (Otherwise we'll detonate most spectacularly * in the middle of recvmsg()). */ - if (skb->len < sizeof(*ddp)) { - kfree_skb(skb); - return 0; - } + if (skb->len < sizeof(*ddp)) + goto freeit; /* * Any checksums. Note we don't do htons() on this == is assumed to be * valid for net byte orders all over the networking code... */ - if (ddp->deh_sum && atalk_checksum(ddp, ddphv.deh_len) != ddp->deh_sum) { + if (ddp->deh_sum && + atalk_checksum(ddp, ddphv.deh_len) != ddp->deh_sum) /* Not a valid AppleTalk frame - dustbin time */ - kfree_skb(skb); - return 0; - } + goto freeit; /* Check the packet is aimed at us */ - - if (ddp->deh_dnet == 0) /* Net 0 is 'this network' */ + if (!ddp->deh_dnet) /* Net 0 is 'this network' */ atif = atalk_find_anynet(ddp->deh_dnode, dev); else atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode); - /* - * Not ours, so we route the packet via the correct AppleTalk interface. - */ - if (atif == NULL) { + /* Not ours, so we route the packet via the correct AppleTalk iface */ + if (!atif) { struct atalk_route *rt; struct at_addr ta; @@ -1555,16 +1426,16 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ * Don't route multicast, etc., packets, or packets * sent to "this network" */ - if (skb->pkt_type != PACKET_HOST || ddp->deh_dnet == 0) { - /* - * FIX ME: - * Can it ever happen that a packet is from a PPP iface and needs to be broadcast onto the default network? - */ + if (skb->pkt_type != PACKET_HOST || !ddp->deh_dnet) { + /* FIXME: + * Can it ever happen that a packet is from a PPP + * iface and needs to be broadcast onto the default + * network? */ if (dev->type == ARPHRD_PPP) - printk(KERN_DEBUG "AppleTalk: didn't forward broadcast packet received from PPP iface\n"); - - kfree_skb(skb); - return 0; + printk(KERN_DEBUG "AppleTalk: didn't forward " + "broadcast packet received " + "from PPP iface\n"); + goto freeit; } ta.s_net = ddp->deh_dnet; @@ -1572,10 +1443,8 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ /* Route the packet */ rt = atrtr_find(&ta); - if (rt == NULL || ddphv.deh_hops == DDP_MAXHOPS) { - kfree_skb(skb); - return 0; - } + if (!rt || ddphv.deh_hops == DDP_MAXHOPS) + goto freeit; ddphv.deh_hops++; /* @@ -1606,40 +1475,33 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ * * Note. ddp-> becomes invalid at the realloc. */ - if (skb_headroom(skb) < 22) - { - struct sk_buff *newskb; + if (skb_headroom(skb) < 22) { /* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */ - newskb = skb_realloc_headroom(skb, 32); + struct sk_buff *nskb = skb_realloc_headroom(skb, 32); kfree_skb(skb); - if (!newskb) - return 0; - skb = newskb; - } - else + if (!nskb) + goto out; + skb = nskb; + } else skb = skb_unshare(skb, GFP_ATOMIC); /* * If the buffer didn't vanish into the lack of * space bitbucket we can send it. */ - if (skb) { - if (aarp_send_ddp(rt->dev, skb, &ta, NULL) == -1) - kfree_skb(skb); - } - - return 0; + if (skb && aarp_send_ddp(rt->dev, skb, &ta, NULL) == -1) + goto freeit; + goto out; } #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE) - /* - * Check if IP-over-DDP - */ + /* Check if IP-over-DDP */ if (skb->data[12] == 22) { - struct net_device *dev; + struct net_device *dev = __dev_get_by_name("ipddp0"); + struct net_device_stats *stats; /* This needs to be able to handle ipddp"N" devices */ - if ((dev = __dev_get_by_name("ipddp0")) == NULL) + if (!dev) return -ENODEV; skb->protocol = htons(ETH_P_IP); @@ -1647,14 +1509,13 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ skb->dev = dev; skb->h.raw = skb->data; - ((struct net_device_stats *)dev->priv)->rx_packets++; - ((struct net_device_stats *)dev->priv)->rx_bytes += skb->len + 13; + stats = dev->priv; + stats->rx_packets++; + stats->rx_bytes += skb->len + 13; netif_rx(skb); /* Send the SKB up to a higher place. */ - - return 0; + goto out; } #endif - /* * Which socket - atalk_search_socket() looks for a *full match* * of the <net,node,port> tuple. @@ -1664,23 +1525,17 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ tosat.sat_port = ddp->deh_dport; sock = atalk_search_socket(&tosat, atif); - - if (sock == NULL) { - /* But not one of our sockets */ - kfree_skb(skb); - return 0; - } + if (!sock) /* But not one of our sockets */ + goto freeit; - /* - * Queue packet (standard) - */ - + /* Queue packet (standard) */ skb->sk = sock; if (sock_queue_rcv_skb(sock, skb) < 0) - kfree_skb(skb); - - return 0; + goto freeit; + goto out; +freeit: kfree_skb(skb); +out: return 0; } /* @@ -1688,21 +1543,18 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ * Caller must provide enough headroom on the packet to pull the short * header and append a long one. */ -static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) +static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt) { struct ddpehdr *ddp; struct at_addr *ap; - /* - * Expand any short form frames. - */ + /* Expand any short form frames */ if (skb->mac.raw[2] == 1) { - /* - * Find our address. - */ + /* Find our address */ ap = atalk_find_dev_addr(dev); - if (ap == NULL || skb->len < sizeof(struct ddpshdr)) { + if (!ap || skb->len < sizeof(struct ddpshdr)) { kfree_skb(skb); return 0; } @@ -1715,9 +1567,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ skb_push(skb, sizeof(*ddp) - 4); ddp = (struct ddpehdr *)skb->data; - /* - * Now fill in the long header. - */ + /* Now fill in the long header */ /* * These two first. The mac overlays the new source/dest @@ -1737,7 +1587,6 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ ddp->deh_len = skb->len; ddp->deh_hops = DDP_MAXHOPS; /* Non routable, so force a drop if we slip up later */ - /* Mend the byte order */ *((__u16 *)ddp) = htons(*((__u16 *)ddp)); } @@ -1746,19 +1595,20 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ return atalk_rcv(skb, dev, pt); } -static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) +static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, + struct scm_cookie *scm) { struct sock *sk = sock->sk; struct sockaddr_at *usat = (struct sockaddr_at *)msg->msg_name; + int flags = msg->msg_flags; + int loopback = 0; struct sockaddr_at local_satalk, gsat; struct sk_buff *skb; struct net_device *dev; struct ddpehdr *ddp; int size; struct atalk_route *rt; - int loopback = 0; int err; - int flags = msg->msg_flags; if (flags & ~MSG_DONTWAIT) return -EINVAL; @@ -1767,19 +1617,18 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, struc return -EMSGSIZE; if (usat) { - if(sk->zapped) { + if (sk->zapped) if (atalk_autobind(sk) < 0) return -EBUSY; - } - if (msg->msg_namelen < sizeof(*usat)) - return -EINVAL; - if (usat->sat_family != AF_APPLETALK) + if (msg->msg_namelen < sizeof(*usat) || + usat->sat_family != AF_APPLETALK) return -EINVAL; /* netatalk doesn't implement this check */ if (usat->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) { - printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as it will break before 2.2\n"); + printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as " + "it will break before 2.2\n"); #if 0 return -EPERM; #endif @@ -1795,15 +1644,14 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, struc } /* Build a packet */ - SOCK_DEBUG(sk, "SK %p: Got address.\n", sk); /* For headers */ size = sizeof(struct ddpehdr) + len + ddp_dl->header_length; - if (usat->sat_addr.s_net != 0 || usat->sat_addr.s_node == ATADDR_ANYNODE) { + if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { rt = atrtr_find(&usat->sat_addr); - if (rt == NULL) + if (!rt) return -ENETUNREACH; dev = rt->dev; @@ -1814,24 +1662,23 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, struc at_hint.s_net = sk->protinfo.af_at.src_net; rt = atrtr_find(&at_hint); - if (rt == NULL) + if (!rt) return -ENETUNREACH; dev = rt->dev; } - SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", sk, size, dev->name); + SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", + sk, size, dev->name); size += dev->hard_header_len; - skb = sock_alloc_send_skb(sk, size, 0, (flags & MSG_DONTWAIT), &err); - if (skb == NULL) + if (!skb) return err; skb->sk = sk; skb_reserve(skb, ddp_dl->header_length); skb_reserve(skb, dev->hard_header_len); - skb->dev = dev; SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk); @@ -1871,28 +1718,30 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, struc * Loopback broadcast packets to non gateway targets (ie routes * to group we are in) */ - if (ddp->deh_dnode == ATADDR_BCAST) { - if ((!(rt->flags&RTF_GATEWAY)) && (!(dev->flags&IFF_LOOPBACK))) { - struct sk_buff *skb2 = skb_copy(skb, GFP_KERNEL); - if (skb2) { - loopback = 1; - SOCK_DEBUG(sk, "SK %p: send out(copy).\n", sk); - if (aarp_send_ddp(dev, skb2, &usat->sat_addr, NULL) == -1) - kfree_skb(skb2); + if (ddp->deh_dnode == ATADDR_BCAST && + !(rt->flags & RTF_GATEWAY) && !(dev->flags & IFF_LOOPBACK)) { + struct sk_buff *skb2 = skb_copy(skb, GFP_KERNEL); + + if (skb2) { + loopback = 1; + SOCK_DEBUG(sk, "SK %p: send out(copy).\n", sk); + if (aarp_send_ddp(dev, skb2, + &usat->sat_addr, NULL) == -1) + kfree_skb(skb2); /* else queued/sent above in the aarp queue */ - } } } - if ((dev->flags & IFF_LOOPBACK) || loopback) { + if (dev->flags & IFF_LOOPBACK || loopback) { SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); /* loop back */ skb_orphan(skb); ddp_dl->datalink_header(ddp_dl, skb, dev->dev_addr); skb->mac.raw = skb->data; - skb->h.raw = skb->data + ddp_dl->header_length + dev->hard_header_len; - skb_pull(skb,dev->hard_header_len); - skb_pull(skb,ddp_dl->header_length); + skb->h.raw = skb->data + ddp_dl->header_length + + dev->hard_header_len; + skb_pull(skb, dev->hard_header_len); + skb_pull(skb, ddp_dl->header_length); atalk_rcv(skb, dev, NULL); } else { SOCK_DEBUG(sk, "SK %p: send out.\n", sk); @@ -1915,15 +1764,15 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, { struct sock *sk = sock->sk; struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name; - struct ddpehdr *ddp = NULL; - struct ddpebits ddphv; + struct ddpehdr *ddp = NULL; int copied = 0; - struct sk_buff *skb; int err = 0; + struct ddpebits ddphv; + struct sk_buff *skb; - skb = skb_recv_datagram(sk, (flags & ~MSG_DONTWAIT), - (flags & MSG_DONTWAIT), &err); - if (skb == NULL) + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &err); + if (!skb) return err; ddp = (struct ddpehdr *)(skb->h.raw); @@ -1943,7 +1792,8 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, copied = size; msg->msg_flags |= MSG_TRUNC; } - err = skb_copy_datagram_iovec(skb, sizeof(*ddp), msg->msg_iov, copied); + err = skb_copy_datagram_iovec(skb, sizeof(*ddp), + msg->msg_iov, copied); } if (!err) { @@ -1957,7 +1807,6 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, } skb_free_datagram(sk, skb); /* Free the datagram. */ - return err ? err : copied; } @@ -1967,50 +1816,40 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, */ static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg) { - long amount=0; - struct sock *sk=sock->sk; + long amount = 0; + struct sock *sk = sock->sk; - switch(cmd) - { - /* - * Protocol layer - */ + switch (cmd) { + /* Protocol layer */ case TIOCOUTQ: amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); - if(amount < 0) + if (amount < 0) amount = 0; break; - case TIOCINQ: { - struct sk_buff *skb; - /* These two are safe on a single CPU system as only user tasks fiddle here */ - if((skb = skb_peek(&sk->receive_queue)) != NULL) + /* These two are safe on a single CPU system as only + * user tasks fiddle here */ + struct sk_buff *skb = skb_peek(&sk->receive_queue); + + if (skb) amount = skb->len-sizeof(struct ddpehdr); break; } - case SIOCGSTAMP: - if(sk) - { - if(sk->stamp.tv_sec == 0) - return -ENOENT; - return (copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval)) ? -EFAULT : 0); - } - return (-EINVAL); - - /* - * Routing - */ + if (!sk) + return -EINVAL; + if (!sk->stamp.tv_sec) + return -ENOENT; + return copy_to_user((void *)arg, &sk->stamp, + sizeof(struct timeval)) ? -EFAULT : 0; + /* Routing */ case SIOCADDRT: case SIOCDELRT: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - return (atrtr_ioctl(cmd,(void *)arg)); - - /* - * Interface - */ + return atrtr_ioctl(cmd, (void *)arg); + /* Interface */ case SIOCGIFADDR: case SIOCSIFADDR: case SIOCGIFBRDADDR: @@ -2018,11 +1857,8 @@ static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg) case SIOCDIFADDR: case SIOCSARP: /* proxy AARP */ case SIOCDARP: /* proxy AARP */ - return (atif_ioctl(cmd,(void *)arg)); - - /* - * Physical layer ioctl calls - */ + return atif_ioctl(cmd, (void *)arg); + /* Physical layer ioctl calls */ case SIOCSIFLINK: case SIOCGIFHWADDR: case SIOCSIFHWADDR: @@ -2035,8 +1871,7 @@ static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg) case SIOCGIFCOUNT: case SIOCGIFINDEX: case SIOCGIFNAME: - return ((dev_ioctl(cmd,(void *) arg))); - + return dev_ioctl(cmd,(void *) arg); case SIOCSIFMETRIC: case SIOCSIFBRDADDR: case SIOCGIFNETMASK: @@ -2045,16 +1880,15 @@ static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg) case SIOCSIFMEM: case SIOCGIFDSTADDR: case SIOCSIFDSTADDR: - return (-EINVAL); - + return -EINVAL; default: - return (-EINVAL); + return -EINVAL; } - return (put_user(amount, (int *)arg)); + return put_user(amount, (int *)arg); } -static struct net_proto_family atalk_family_ops= +static struct net_proto_family atalk_family_ops = { PF_APPLETALK, atalk_create @@ -2111,19 +1945,17 @@ struct packet_type ppptalk_packet_type= static char ddp_snap_id[] = {0x08, 0x00, 0x07, 0x80, 0x9B}; -/* - * Export symbols for use by drivers when AppleTalk is a module. - */ +/* Export symbols for use by drivers when AppleTalk is a module */ EXPORT_SYMBOL(aarp_send_ddp); EXPORT_SYMBOL(atrtr_get_dev); EXPORT_SYMBOL(atalk_find_dev_addr); /* Called by proto.c on kernel start up */ - static int __init atalk_init(void) { (void) sock_register(&atalk_family_ops); - if((ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv)) == NULL) + ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv); + if (!ddp_dl) printk(KERN_CRIT "Unable to register DDP with SNAP.\n"); ltalk_packet_type.type = htons(ETH_P_LOCALTALK); @@ -2135,19 +1967,16 @@ static int __init atalk_init(void) register_netdevice_notifier(&ddp_notifier); aarp_proto_init(); -#ifdef CONFIG_PROC_FS proc_net_create("appletalk", 0, atalk_get_info); proc_net_create("atalk_route", 0, atalk_rt_get_info); proc_net_create("atalk_iface", 0, atalk_if_get_info); - +#ifdef CONFIG_PROC_FS aarp_register_proc_fs(); #endif /* CONFIG_PROC_FS */ - #ifdef CONFIG_SYSCTL atalk_register_sysctl(); #endif /* CONFIG_SYSCTL */ - - printk(KERN_INFO "NET4: AppleTalk 0.18 for Linux NET4.0\n"); + printk(KERN_INFO "NET4: AppleTalk 0.18a for Linux NET4.0\n"); return 0; } module_init(atalk_init); @@ -2165,32 +1994,24 @@ module_init(atalk_init); * Ergo, before the AppleTalk module can be removed, all AppleTalk * sockets be closed from user space. */ - static void __exit atalk_exit(void) { #ifdef CONFIG_SYSCTL atalk_unregister_sysctl(); #endif /* CONFIG_SYSCTL */ - -#ifdef CONFIG_PROC_FS proc_net_remove("appletalk"); proc_net_remove("atalk_route"); proc_net_remove("atalk_iface"); - +#ifdef CONFIG_PROC_FS aarp_unregister_proc_fs(); #endif /* CONFIG_PROC_FS */ - aarp_cleanup_module(); /* General aarp clean-up. */ - unregister_netdevice_notifier(&ddp_notifier); dev_remove_pack(<alk_packet_type); dev_remove_pack(&ppptalk_packet_type); unregister_snap_client(ddp_snap_id); sock_unregister(PF_APPLETALK); - - return; } module_exit(atalk_exit); #endif /* MODULE */ - #endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */ diff --git a/net/atm/lec.c b/net/atm/lec.c index 51be9f077..ec0dc2671 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -51,6 +51,11 @@ static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00}; #define DPRINTK(format,args...) #endif +struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, + unsigned char *addr); +void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); + + #define DUMP_PACKETS 0 /* 0 = None, * 1 = 30 first bytes * 2 = Whole packet @@ -853,8 +858,11 @@ static void __exit lane_module_cleanup(void) if (dev_lec[i] != NULL) { priv = (struct lec_priv *)dev_lec[i]->priv; #if defined(CONFIG_TR) - unregister_trdev(dev_lec[i]); + if (priv->is_trdev) + unregister_trdev(dev_lec[i]); + else #endif + unregister_netdev(dev_lec[i]); kfree(dev_lec[i]); dev_lec[i] = NULL; } diff --git a/net/atm/lec.h b/net/atm/lec.h index f40a37fa3..5dd0494e9 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h @@ -16,9 +16,9 @@ #if defined (CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) #include <linux/if_bridge.h> -struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, +extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, unsigned char *addr); -void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); +extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ #define LEC_HEADER_LEN 16 diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 940d69be0..8fcfe3fe4 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -4,7 +4,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_private.h,v 1.3 2000/05/05 02:17:17 davem Exp $ + * $Id: br_private.h,v 1.4 2001/01/19 04:51:48 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -112,8 +112,8 @@ struct net_bridge int gc_interval; }; -struct notifier_block br_device_notifier; -unsigned char bridge_ula[6]; +extern struct notifier_block br_device_notifier; +extern unsigned char bridge_ula[6]; /* br.c */ void br_dec_use_count(void); diff --git a/net/core/netfilter.c b/net/core/netfilter.c index f4bb62818..b12e1d5ec 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c @@ -442,7 +442,6 @@ static void nf_queue(struct sk_buff *skb, } } -/* We have BR_NETPROTO_LOCK here */ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, struct net_device *indev, struct net_device *outdev, @@ -452,6 +451,9 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, unsigned int verdict; int ret = 0; + /* We may already have this, but read-locks nest anyway */ + br_read_lock_bh(BR_NETPROTO_LOCK); + #ifdef CONFIG_NETFILTER_DEBUG if (skb->nf_debug & (1 << hook)) { printk("nf_hook: hook %i already set.\n", hook); @@ -479,6 +481,7 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, break; } + br_read_unlock_bh(BR_NETPROTO_LOCK); return ret; } diff --git a/net/decnet/Makefile b/net/decnet/Makefile index ac7a1a462..11f7c8b08 100644 --- a/net/decnet/Makefile +++ b/net/decnet/Makefile @@ -11,5 +11,3 @@ obj-y += sysctl_net_decnet.o include $(TOPDIR)/Rules.make -tar: - tar -cvf /dev/f1 . diff --git a/net/decnet/TODO b/net/decnet/TODO index 1607d6d1b..c8ea8178d 100644 --- a/net/decnet/TODO +++ b/net/decnet/TODO @@ -43,15 +43,15 @@ Steve's quick list of things that need finishing off: o Hello messages should be generated for each primary address on each interface. - o Add more information into /proc/net/decnet and finalise the format to - allow DECnet support in netstat. - - o Make sure that returned connect messages are generated when they should - be, and that the correct error messages are sent too. - o Add the routing message grabbing netfilter module [written, tested, awaiting merge] o Add perfect socket hashing - an idea suggested by Paul Koning [part written, awaiting debugging and merge] + o Add session control message flow control + + o Add NSP message flow control + + o DECnet sendpages() function + diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index bc51b636d..b930878c2 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -35,6 +35,7 @@ * Arnaldo C. Melo: use capable, not suser * Steve Whitehouse: Removed unused code. Fix to use sk->allocation * when required. + * Patrick Caulfield: /proc/net/decnet now has object name/number */ @@ -128,8 +129,6 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat #include <net/dn_fib.h> #include <net/dn_neigh.h> -#define MAX(a,b) ((a)>(b)?(a):(b)) - static void dn_keepalive(struct sock *sk); /* @@ -141,15 +140,15 @@ unsigned char decnet_ether_address[ETH_ALEN] = { 0xAA, 0x00, 0x04, 0x00, 0x00, 0 static struct proto_ops dn_proto_ops; rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED; -static struct sock *dn_sklist = NULL; -static struct sock *dn_wild_sk = NULL; +static struct sock *dn_sklist; +static struct sock *dn_wild_sk; static int __dn_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen, int flags); static int __dn_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen, int flags); static struct sock **dn_find_list(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); if (scp->addr.sdn_flags & SDF_WILD) return dn_wild_sk ? NULL : &dn_wild_sk; @@ -159,7 +158,7 @@ static struct sock **dn_find_list(struct sock *sk) static unsigned short port_alloc(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); static unsigned short port = 0x2000; if (port == 0) @@ -177,12 +176,17 @@ static unsigned short port = 0x2000; */ static int dn_hash_sock(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); struct sock **skp; int rv = -EUSERS; - write_lock_bh(&dn_hash_lock); + if (sk->next) + BUG(); + if (sk->pprev) + BUG(); + write_lock_bh(&dn_hash_lock); + if (!scp->addrloc && !port_alloc(sk)) goto out; @@ -327,7 +331,7 @@ struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr) read_lock(&dn_hash_lock); for(sk = dn_sklist; sk != NULL; sk = sk->next) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); if (sk->state != TCP_LISTEN) continue; if (scp->addr.sdn_objnum) { @@ -355,13 +359,13 @@ struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr) struct sock *dn_find_by_skb(struct sk_buff *skb) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); struct sock *sk; struct dn_scp *scp; read_lock(&dn_hash_lock); for(sk = dn_sklist; sk != NULL; sk = sk->next) { - scp = &sk->protinfo.dn; + scp = DN_SK(sk); if (cb->src != dn_saddr2dn(&scp->peer)) continue; if (cb->dst_port != scp->addrloc) @@ -383,7 +387,7 @@ struct sock *dn_find_by_skb(struct sk_buff *skb) static void dn_destruct(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); skb_queue_purge(&scp->data_xmit_queue); skb_queue_purge(&scp->other_xmit_queue); @@ -394,25 +398,26 @@ static void dn_destruct(struct sock *sk) MOD_DEC_USE_COUNT; } -struct sock *dn_alloc_sock(struct socket *sock, int flags) +struct sock *dn_alloc_sock(struct socket *sock, int gfp) { struct sock *sk; struct dn_scp *scp; - if ((sk = sk_alloc(PF_DECnet, flags, 1)) == NULL) + if ((sk = sk_alloc(PF_DECnet, gfp, 1)) == NULL) goto no_sock; if (sock) { sock->ops = &dn_proto_ops; } sock_init_data(sock,sk); - scp = &sk->protinfo.dn; + scp = DN_SK(sk); sk->backlog_rcv = dn_nsp_backlog_rcv; sk->destruct = dn_destruct; sk->no_check = 1; sk->family = PF_DECnet; sk->protocol = 0; + sk->allocation = gfp; /* Initialization of DECnet Session Control Port */ scp->state = DN_O; /* Open */ @@ -424,13 +429,25 @@ struct sock *dn_alloc_sock(struct socket *sock, int flags) scp->ackrcv_oth = 0; /* Last oth data ack rec*/ scp->flowrem_sw = DN_SEND; scp->flowloc_sw = DN_SEND; + scp->flowrem_dat = 0; + scp->flowrem_oth = 1; + scp->flowloc_dat = 0; + scp->flowloc_oth = 1; + scp->services_rem = 0; + scp->services_loc = 1 | NSP_FC_NONE; + scp->info_rem = 0; + scp->info_loc = 0x03; /* NSP version 4.1 */ + scp->segsize_rem = 230; /* Default: Updated by remote segsize */ + scp->segsize_loc = 1450; /* Best guess for ethernet */ + scp->nonagle = 0; + scp->multi_ireq = 1; scp->accept_mode = ACC_IMMED; scp->addr.sdn_family = AF_DECnet; scp->peer.sdn_family = AF_DECnet; scp->accessdata.acc_accl = 5; memcpy(scp->accessdata.acc_acc, "LINUX", 5); - scp->mss = 1460; + scp->max_window = NSP_MAX_WINDOW; scp->snd_window = NSP_MIN_WINDOW; scp->nsp_srtt = NSP_INITIAL_SRTT; scp->nsp_rttvar = NSP_INITIAL_RTTVAR; @@ -464,7 +481,7 @@ no_sock: */ static void dn_keepalive(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); /* * By checking the other_data transmit queue is empty @@ -472,7 +489,7 @@ static void dn_keepalive(struct sock *sk) * many of these keepalive frames. */ if (skb_queue_len(&scp->other_xmit_queue) == 0) - dn_nsp_send_lnk(sk, DN_NOCHANGE); + dn_nsp_send_link(sk, DN_NOCHANGE, 0); } @@ -485,7 +502,7 @@ static void dn_keepalive(struct sock *sk) */ int dn_destroy_timer(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); scp->persist = dn_nsp_persist(sk); @@ -527,7 +544,7 @@ int dn_destroy_timer(struct sock *sk) static void dn_destroy_sock(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); scp->nsp_rxtshift = 0; /* reset back off */ @@ -674,7 +691,7 @@ dn_release(struct socket *sock) static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr; struct net_device *dev; int rv; @@ -722,11 +739,8 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) memcpy(&scp->addr, saddr, addr_len); sk->zapped = 0; - if ((rv = dn_hash_sock(sk)) == 0) - goto out; - - sk->zapped = 1; -out: + if ((rv = dn_hash_sock(sk)) != 0) + sk->zapped = 1; return rv; } @@ -735,7 +749,7 @@ out: static int dn_auto_bind(struct socket *sock) { struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); sk->zapped = 0; @@ -769,7 +783,7 @@ static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, { struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr; struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); int err = -EISCONN; lock_sock(sk); @@ -788,7 +802,7 @@ static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, } err = -EINVAL; - if (sk->protinfo.dn.state != DN_O) + if (DN_SK(sk)->state != DN_O) goto out; if (addr_len != sizeof(struct sockaddr_dn)) @@ -812,7 +826,7 @@ static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, sk->state = TCP_SYN_SENT; sock->state = SS_CONNECTING; - sk->protinfo.dn.state = DN_CI; + DN_SK(sk)->state = DN_CI; dn_nsp_send_conninit(sk, NSP_CI); @@ -853,7 +867,7 @@ out: return err; } -static int dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc) +static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc) { unsigned char *ptr = skb->data; @@ -870,10 +884,9 @@ static int dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc) skb_pull(skb, acc->acc_accl + acc->acc_passl + acc->acc_userl + 3); - return 0; } -static int dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt) +static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt) { unsigned char *ptr = skb->data; @@ -882,7 +895,6 @@ static int dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt) memcpy(opt->opt_data, ptr, opt->opt_optl); skb_pull(skb, opt->opt_optl + 1); - return 0; } @@ -910,7 +922,7 @@ static int dn_wait_accept(struct socket *sock, int flags) return -ERESTARTSYS; /* But of course you don't! */ } - if ((sk->protinfo.dn.state != DN_RUN) && (sk->protinfo.dn.state != DN_DRC)) { + if ((DN_SK(sk)->state != DN_RUN) && (DN_SK(sk)->state != DN_DRC)) { sock->state = SS_UNCONNECTED; return sock_error(sk); } @@ -937,7 +949,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) return -EINVAL; } - if (sk->protinfo.dn.state != DN_O) { + if (DN_SK(sk)->state != DN_O) { release_sock(sk); return -EINVAL; } @@ -967,7 +979,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) } } while (skb == NULL); - cb = (struct dn_skb_cb *)skb->cb; + cb = DN_SKB_CB(skb); if ((newsk = dn_alloc_sock(newsock, sk->allocation)) == NULL) { release_sock(sk); @@ -980,50 +992,52 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) dst_release(xchg(&newsk->dst_cache, skb->dst)); skb->dst = NULL; - newsk->protinfo.dn.state = DN_CR; - newsk->protinfo.dn.addrrem = cb->src_port; - newsk->protinfo.dn.mss = cb->segsize; - newsk->protinfo.dn.accept_mode = sk->protinfo.dn.accept_mode; + DN_SK(newsk)->state = DN_CR; + DN_SK(newsk)->addrrem = cb->src_port; + DN_SK(newsk)->services_rem = cb->services; + DN_SK(newsk)->info_rem = cb->info; + DN_SK(newsk)->segsize_rem = cb->segsize; + DN_SK(newsk)->accept_mode = DN_SK(sk)->accept_mode; - if (newsk->protinfo.dn.mss < 230) - newsk->protinfo.dn.mss = 230; + if (DN_SK(newsk)->segsize_rem < 230) + DN_SK(newsk)->segsize_rem = 230; newsk->state = TCP_LISTEN; newsk->zapped = 0; - memcpy(&newsk->protinfo.dn.addr, &sk->protinfo.dn.addr, sizeof(struct sockaddr_dn)); + memcpy(&(DN_SK(newsk)->addr), &(DN_SK(sk)->addr), sizeof(struct sockaddr_dn)); /* * If we are listening on a wild socket, we don't want * the newly created socket on the wrong hash queue. */ - newsk->protinfo.dn.addr.sdn_flags &= ~SDF_WILD; + DN_SK(newsk)->addr.sdn_flags &= ~SDF_WILD; - skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &newsk->protinfo.dn.addr, &type)); - skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &newsk->protinfo.dn.peer, &type)); - *(dn_address *)newsk->protinfo.dn.peer.sdn_add.a_addr = cb->src; - *(dn_address *)newsk->protinfo.dn.addr.sdn_add.a_addr = cb->dst; + skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->addr), &type)); + skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->peer), &type)); + *(dn_address *)(DN_SK(newsk)->peer.sdn_add.a_addr) = cb->src; + *(dn_address *)(DN_SK(newsk)->addr.sdn_add.a_addr) = cb->dst; menuver = *skb->data; skb_pull(skb, 1); if (menuver & DN_MENUVER_ACC) - dn_access_copy(skb, &newsk->protinfo.dn.accessdata); + dn_access_copy(skb, &(DN_SK(newsk)->accessdata)); if (menuver & DN_MENUVER_USR) - dn_user_copy(skb, &newsk->protinfo.dn.conndata_in); + dn_user_copy(skb, &(DN_SK(newsk)->conndata_in)); if (menuver & DN_MENUVER_PRX) - newsk->protinfo.dn.peer.sdn_flags |= SDF_PROXY; + DN_SK(newsk)->peer.sdn_flags |= SDF_PROXY; if (menuver & DN_MENUVER_UIC) - newsk->protinfo.dn.peer.sdn_flags |= SDF_UICPROXY; + DN_SK(newsk)->peer.sdn_flags |= SDF_UICPROXY; kfree_skb(skb); - memcpy(&newsk->protinfo.dn.conndata_out, &sk->protinfo.dn.conndata_out, + memcpy(&(DN_SK(newsk)->conndata_out), &(DN_SK(sk)->conndata_out), sizeof(struct optdata_dn)); - memcpy(&newsk->protinfo.dn.discdata_out, &sk->protinfo.dn.discdata_out, + memcpy(&(DN_SK(newsk)->discdata_out), &(DN_SK(sk)->discdata_out), sizeof(struct optdata_dn)); lock_sock(newsk); @@ -1031,9 +1045,13 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) dn_send_conn_ack(newsk); - if (newsk->protinfo.dn.accept_mode == ACC_IMMED) { - newsk->protinfo.dn.state = DN_CC; - dn_send_conn_conf(newsk, newsk->allocation); + /* + * Here we use sk->allocation since although the conn conf is + * for the newsk, the context is the old socket. + */ + if (DN_SK(newsk)->accept_mode == ACC_IMMED) { + DN_SK(newsk)->state = DN_CC; + dn_send_conn_conf(newsk, sk->allocation); err = dn_wait_accept(newsock, flags); } @@ -1046,7 +1064,7 @@ static int dn_getname(struct socket *sock, struct sockaddr *uaddr,int *uaddr_len { struct sockaddr_dn *sa = (struct sockaddr_dn *)uaddr; struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); *uaddr_len = sizeof(struct sockaddr_dn); @@ -1070,7 +1088,7 @@ static int dn_getname(struct socket *sock, struct sockaddr *uaddr,int *uaddr_len static unsigned int dn_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); int mask = datagram_poll(file, sock, wait); if (skb_queue_len(&scp->other_receive_queue)) @@ -1082,100 +1100,32 @@ static unsigned int dn_poll(struct file *file, struct socket *sock, poll_table static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); int err = -EOPNOTSUPP; unsigned long amount = 0; struct sk_buff *skb; + int val; -#if 0 - struct dn_naddr dnaddr; -#endif switch(cmd) { case SIOCGIFADDR: case SIOCSIFADDR: return dn_dev_ioctl(cmd, (void *)arg); + case SIOCATMARK: + lock_sock(sk); + val = (skb_queue_len(&scp->other_receive_queue) != 0); + if (scp->state != DN_RUN) + val = -ENOTCONN; + release_sock(sk); + return val; + #ifdef CONFIG_DECNET_ROUTER case SIOCADDRT: case SIOCDELRT: return dn_fib_ioctl(sock, cmd, arg); #endif /* CONFIG_DECNET_ROUTER */ -#if 0 - case SIOCSIFADDR: - if (!capable(CAP_NET_ADMIN)) return -EPERM; - - if ((err = copy_from_user(devname, ioarg->devname, 5)) != 0) - break; - if ((err = copy_from_user(addr, ioarg->exec_addr, 6)) != 0) - break; - if ((dev = dev_get(devname)) == NULL) { - err = -ENODEV; - break; - } - if (dev->dn_ptr == NULL) { - err = -ENODEV; - break; - } - - dn_dev_devices_off(); - - decnet_default_device = dev; - memcpy(decnet_ether_address, addr, ETH_ALEN); - decnet_address = dn_htons(dn_eth2dn(decnet_ether_address)); - - dn_dev_devices_on(); - - break; - - case SIOCGIFADDR: - if (decnet_default_device) - strcpy(devname, decnet_default_device->name); - else - memset(devname, 0, 6); - - if ((err = copy_to_user(ioarg->devname, devname, 5)) != 0) - break; - - if ((err = copy_to_user(ioarg->exec_addr, decnet_ether_address, 6)) != 0) - break; - - break; -#endif - -#if 0 - case SIOCSNETADDR: - if (!capable(CAP_NET_ADMIN)) { - err = -EPERM; - break; - } - - if ((err = copy_from_user(&dnaddr, (void *)arg, sizeof(struct dn_naddr))) != 0) - break; - - if (dnaddr.a_len != ETH_ALEN) { - err = -EINVAL; - break; - } - - dn_dev_devices_off(); - - memcpy(decnet_ether_address, dnaddr.a_addr, ETH_ALEN); - decnet_address = dn_htons(dn_eth2dn(decnet_ether_address)); - - dn_dev_devices_on(); - break; - - case SIOCGNETADDR: - dnaddr.a_len = ETH_ALEN; - memcpy(dnaddr.a_addr, decnet_ether_address, ETH_ALEN); - - if ((err = copy_to_user((void *)arg, &dnaddr, sizeof(struct dn_naddr))) != 0) - break; - - break; -#endif case OSIOCSNETADDR: if (!capable(CAP_NET_ADMIN)) { err = -EPERM; @@ -1237,7 +1187,7 @@ static int dn_listen(struct socket *sock, int backlog) if (sk->zapped) goto out; - if ((sk->protinfo.dn.state != DN_O) || (sk->state == TCP_LISTEN)) + if ((DN_SK(sk)->state != DN_O) || (sk->state == TCP_LISTEN)) goto out; sk->max_ack_backlog = backlog; @@ -1255,7 +1205,7 @@ out: static int dn_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); int err = -ENOTCONN; lock_sock(sk); @@ -1300,14 +1250,27 @@ static int dn_setsockopt(struct socket *sock, int level, int optname, char *optv static int __dn_setsockopt(struct socket *sock, int level,int optname, char *optval, int optlen, int flags) { struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; - struct optdata_dn opt; - struct accessdata_dn acc; + struct dn_scp *scp = DN_SK(sk); + union { + struct optdata_dn opt; + struct accessdata_dn acc; + int mode; + unsigned long win; + int val; + unsigned char services; + unsigned char info; + } u; int err; if (optlen && !optval) return -EINVAL; + if (optlen > sizeof(u)) + return -EINVAL; + + if (copy_from_user(&u, optval, optlen)) + return -EFAULT; + switch(optname) { case DSO_CONDATA: if (sock->state == SS_CONNECTED) @@ -1318,29 +1281,23 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt if (optlen != sizeof(struct optdata_dn)) return -EINVAL; - if (copy_from_user(&opt, optval, optlen)) - return -EFAULT; - - if (opt.opt_optl > 16) + if (u.opt.opt_optl > 16) return -EINVAL; - memcpy(&scp->conndata_out, &opt, sizeof(struct optdata_dn)); + memcpy(&scp->conndata_out, &u.opt, optlen); break; case DSO_DISDATA: - if (sock->state != SS_CONNECTED && sk->protinfo.dn.accept_mode == ACC_IMMED) + if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED) return -ENOTCONN; if (optlen != sizeof(struct optdata_dn)) return -EINVAL; - if (copy_from_user(&opt, optval, sizeof(struct optdata_dn))) - return -EFAULT; - - if (opt.opt_optl > 16) + if (u.opt.opt_optl > 16) return -EINVAL; - memcpy(&scp->discdata_out, &opt, sizeof(struct optdata_dn)); + memcpy(&scp->discdata_out, &u.opt, optlen); break; case DSO_CONACCESS: @@ -1352,15 +1309,12 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt if (optlen != sizeof(struct accessdata_dn)) return -EINVAL; - if (copy_from_user(&acc, optval, sizeof(struct accessdata_dn))) - return -EFAULT; - - if ((acc.acc_accl > DN_MAXACCL) || - (acc.acc_passl > DN_MAXACCL) || - (acc.acc_userl > DN_MAXACCL)) + if ((u.acc.acc_accl > DN_MAXACCL) || + (u.acc.acc_passl > DN_MAXACCL) || + (u.acc.acc_userl > DN_MAXACCL)) return -EINVAL; - memcpy(&scp->accessdata, &acc, sizeof(struct accessdata_dn)); + memcpy(&scp->accessdata, &u.acc, optlen); break; case DSO_ACCEPTMODE: @@ -1372,16 +1326,10 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt if (optlen != sizeof(int)) return -EINVAL; - { - int mode; - - if (get_user(mode, optval)) - return -EFAULT; - if ((mode != ACC_IMMED) && (mode != ACC_DEFER)) - return -EINVAL; + if ((u.mode != ACC_IMMED) && (u.mode != ACC_DEFER)) + return -EINVAL; - scp->accept_mode = (unsigned char)mode; - } + scp->accept_mode = (unsigned char)u.mode; break; case DSO_CONACCEPT: @@ -1411,8 +1359,55 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt case DSO_LINKINFO: case DSO_STREAM: case DSO_SEQPACKET: - return -ENOPROTOOPT; + + case DSO_MAXWINDOW: + if (optlen != sizeof(unsigned long)) + return -EINVAL; + if (u.win > NSP_MAX_WINDOW) + u.win = NSP_MAX_WINDOW; + if (u.win == 0) + return -EINVAL; + scp->max_window = u.win; + if (scp->snd_window > u.win) + scp->snd_window = u.win; + break; + + case DSO_NODELAY: + if (optlen != sizeof(int)) + return -EINVAL; + if (scp->nonagle == 2) + return -EINVAL; + scp->nonagle = (u.val == 0) ? 0 : 1; + /* if (scp->nonagle == 1) { Push pending frames } */ + break; + + case DSO_CORK: + if (optlen != sizeof(int)) + return -EINVAL; + if (scp->nonagle == 1) + return -EINVAL; + scp->nonagle = (u.val == 0) ? 0 : 2; + /* if (scp->nonagle == 0) { Push pending frames } */ + break; + + case DSO_SERVICES: + if (optlen != sizeof(unsigned char)) + return -EINVAL; + if ((u.services & ~NSP_FC_MASK) != 0x01) + return -EINVAL; + if ((u.services & NSP_FC_MASK) == NSP_FC_MASK) + return -EINVAL; + scp->services_loc = u.services; + break; + + case DSO_INFO: + if (optlen != sizeof(unsigned char)) + return -EINVAL; + if (u.info & 0xfc) + return -EINVAL; + scp->info_loc = u.info; + break; } return 0; @@ -1433,44 +1428,40 @@ static int dn_getsockopt(struct socket *sock, int level, int optname, char *optv static int __dn_getsockopt(struct socket *sock, int level,int optname, char *optval,int *optlen, int flags) { struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); struct linkinfo_dn link; - int mode = scp->accept_mode; + int r_len = *optlen; + void *r_data = NULL; + int val; switch(optname) { case DSO_CONDATA: - if (*optlen != sizeof(struct optdata_dn)) - return -EINVAL; - - if (copy_to_user(optval, &scp->conndata_in, sizeof(struct optdata_dn))) - return -EFAULT; + if (r_len > sizeof(struct optdata_dn)) + r_len = sizeof(struct optdata_dn); + r_data = &scp->conndata_in; break; case DSO_DISDATA: - if (*optlen != sizeof(struct optdata_dn)) - return -EINVAL; - - if (copy_to_user(optval, &scp->discdata_in, sizeof(struct optdata_dn))) - return -EFAULT; - + if (r_len > sizeof(struct optdata_dn)) + r_len = sizeof(struct optdata_dn); + r_data = &scp->discdata_in; break; case DSO_CONACCESS: - if (*optlen != sizeof(struct accessdata_dn)) - return -EINVAL; - - if (copy_to_user(optval, &scp->accessdata, sizeof(struct accessdata_dn))) - return -EFAULT; + if (r_len > sizeof(struct accessdata_dn)) + r_len = sizeof(struct accessdata_dn); + r_data = &scp->accessdata; break; case DSO_ACCEPTMODE: - if (put_user(mode, optval)) - return -EFAULT; + if (r_len > sizeof(unsigned char)) + r_len = sizeof(unsigned char); + r_data = &scp->accept_mode; break; case DSO_LINKINFO: - if (*optlen != sizeof(struct linkinfo_dn)) - return -EINVAL; + if (r_len > sizeof(struct linkinfo_dn)) + r_len = sizeof(struct linkinfo_dn); switch(sock->state) { case SS_CONNECTING: @@ -1486,10 +1477,8 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char *opt link.idn_linkstate = LL_INACTIVE; } - link.idn_segsize = scp->mss; - - if (copy_to_user(optval, &link, sizeof(struct linkinfo_dn))) - return -EFAULT; + link.idn_segsize = scp->segsize_rem; + r_data = &link; break; default: @@ -1508,6 +1497,45 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char *opt case DSO_CONACCEPT: case DSO_CONREJECT: return -ENOPROTOOPT; + + case DSO_MAXWINDOW: + if (r_len > sizeof(unsigned long)) + r_len = sizeof(unsigned long); + r_data = &scp->max_window; + break; + + case DSO_NODELAY: + if (r_len > sizeof(int)) + r_len = sizeof(int); + val = (scp->nonagle == 1); + r_data = &val; + break; + + case DSO_CORK: + if (r_len > sizeof(int)) + r_len = sizeof(int); + val = (scp->nonagle == 2); + r_data = &val; + break; + + case DSO_SERVICES: + if (r_len > sizeof(unsigned char)) + r_len = sizeof(unsigned char); + r_data = &scp->services_rem; + break; + + case DSO_INFO: + if (r_len > sizeof(unsigned char)) + r_len = sizeof(unsigned char); + r_data = &scp->info_rem; + break; + } + + if (r_data) { + if (copy_to_user(optval, r_data, r_len)) + return -EFAULT; + if (put_user(r_len, optlen)) + return -EFAULT; } return 0; @@ -1520,7 +1548,7 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char *opt */ static int dn_wait_run(struct sock *sk, int flags) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); int err = 0; switch(scp->state) { @@ -1572,7 +1600,7 @@ static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int return skb_queue_len(q) ? 1 : 0; while(skb != (struct sk_buff *)q) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); len += skb->len; if (cb->nsp_flags & 0x40) { @@ -1599,7 +1627,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm) { struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); struct sk_buff_head *queue = &sk->receive_queue; int target = size > 1 ? 1 : 0; int copied = 0; @@ -1681,7 +1709,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size, for(skb = queue->next; skb != (struct sk_buff *)queue; skb = nskb) { int chunk = skb->len; - cb = (struct dn_skb_cb *)skb->cb; + cb = DN_SKB_CB(skb); if ((chunk + copied) > size) chunk = size - copied; @@ -1693,7 +1721,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size, copied += chunk; if (!(flags & MSG_PEEK)) - skb->len -= chunk; + skb_pull(skb, chunk); eor = cb->nsp_flags & 0x40; nskb = skb->next; @@ -1707,7 +1735,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size, */ if ((scp->flowloc_sw == DN_DONTSEND) && !dn_congested(sk)) { scp->flowloc_sw = DN_SEND; - dn_nsp_send_lnk(sk, DN_SEND); + dn_nsp_send_link(sk, DN_SEND, 0); } } @@ -1727,6 +1755,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size, rv = copied; + if (eor && (sk->type == SOCK_SEQPACKET)) msg->msg_flags |= MSG_EOR; @@ -1745,16 +1774,31 @@ out: } +static inline int dn_queue_too_long(struct dn_scp *scp, struct sk_buff_head *queue, int flags) +{ + unsigned char fctype = scp->services_rem & NSP_FC_MASK; + if (skb_queue_len(queue) >= scp->snd_window) + return 1; + if (fctype != NSP_FC_NONE) { + if (flags & MSG_OOB) { + if (scp->flowrem_oth == 0) + return 1; + } else { + if (scp->flowrem_dat == 0) + return 1; + } + } + return 0; +} + static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, struct scm_cookie *scm) { struct sock *sk = sock->sk; - struct dn_scp *scp = &sk->protinfo.dn; - int mss = scp->mss; - int mtu = 230 - 11; /* maximum value thats always safe */ + struct dn_scp *scp = DN_SK(sk); + int mss; struct sk_buff_head *queue = &scp->data_xmit_queue; int flags = msg->msg_flags; - unsigned short numseg = 0; int err = 0; int sent = 0; int addr_len = msg->msg_namelen; @@ -1765,6 +1809,7 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, unsigned char *ptr; unsigned short ack; int len; + unsigned char fctype; if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR)) return -EOPNOTSUPP; @@ -1801,16 +1846,19 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, if ((flags & MSG_TRYHARD) && sk->dst_cache) dst_negative_advice(&sk->dst_cache); + mss = scp->segsize_rem; + fctype = scp->services_rem & NSP_FC_MASK; + if (sk->dst_cache && sk->dst_cache->neighbour) { struct dn_neigh *dn = (struct dn_neigh *)sk->dst_cache->neighbour; - if (dn->blksize > 230) - mtu = dn->blksize - 11; + if (dn->blksize < (mss + 11)) + mss = dn->blksize - 11; } /* * The only difference between SEQPACKET & STREAM sockets under DECnet - * AFAIK is that SEQPACKET sockets set the MSG_EOR flag for the last - * session control message segment. + * is that SEQPACKET sockets set the MSG_EOR flag for the last + * session control message segment. */ if (flags & MSG_OOB) { @@ -1822,9 +1870,6 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, } } - if (mss < mtu) - mtu = mss; - scp->persist_fxn = dn_nsp_xmit_timeout; while(sent < size) { @@ -1842,14 +1887,14 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, */ len = size - sent; - if (len > mtu) - len = mtu; + if (len > mss) + len = mss; /* * Wait for queue size to go down below the window * size. */ - if (skb_queue_len(queue) >= scp->snd_window) { + if (dn_queue_too_long(scp, queue, flags)) { if (flags & MSG_DONTWAIT) { err = -EWOULDBLOCK; goto out; @@ -1857,7 +1902,7 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, SOCK_SLEEP_PRE(sk) - if (skb_queue_len(queue) >= scp->snd_window) + if (dn_queue_too_long(scp, queue, flags)) schedule(); SOCK_SLEEP_POST(sk) @@ -1876,7 +1921,7 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, if (!skb) continue; - cb = (struct dn_skb_cb *)skb->cb; + cb = DN_SKB_CB(skb); ptr = skb_put(skb, 9); @@ -1886,26 +1931,34 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, } if (flags & MSG_OOB) { - cb->segnum = scp->numoth++; - scp->numoth &= 0x0fff; + cb->segnum = scp->numoth; + seq_add(&scp->numoth, 1); msgflg = 0x30; - ack = scp->ackxmt_oth | 0x8000; + ack = (scp->numoth_rcv & 0x0FFF) | 0x8000; + scp->ackxmt_oth = scp->numoth_rcv; + if (fctype != NSP_FC_NONE) + scp->flowrem_oth--; } else { - cb->segnum = scp->numdat++; - scp->numdat &= 0x0fff; + cb->segnum = scp->numdat; + seq_add(&scp->numdat, 1); msgflg = 0x00; if (sock->type == SOCK_STREAM) msgflg = 0x60; - if (scp->seg_size == 0) + if (scp->seg_total == 0) msgflg |= 0x20; - scp->seg_size += len; + scp->seg_total += len; if (((sent + len) == size) && (flags & MSG_EOR)) { msgflg |= 0x40; - scp->seg_size = 0; + scp->seg_total = 0; + if (fctype == NSP_FC_SCMC) + scp->flowrem_dat--; } - ack = scp->ackxmt_dat | 0x8000; + ack = (scp->numdat_rcv & 0x0FFF) | 0x8000; + scp->ackxmt_dat = scp->numdat_rcv; + if (fctype == NSP_FC_SRC) + scp->flowrem_dat--; } *ptr++ = msgflg; @@ -1918,8 +1971,7 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, *(__u16 *)ptr = dn_htons(cb->segnum); sent += len; - dn_nsp_queue_xmit(sk, skb, flags & MSG_OOB); - numseg++; + dn_nsp_queue_xmit(sk, skb, sk->allocation, flags & MSG_OOB); skb = NULL; scp->persist = dn_nsp_persist(sk); @@ -1955,21 +2007,38 @@ static int dn_device_event(struct notifier_block *this, unsigned long event, } static struct notifier_block dn_dev_notifier = { - dn_device_event, - 0 + notifier_call: dn_device_event, }; extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *); -static struct packet_type dn_dix_packet_type = -{ - __constant_htons(ETH_P_DNA_RT), - NULL, /* All devices */ - dn_route_rcv, - (void*)1, - NULL, +static struct packet_type dn_dix_packet_type = { + type: __constant_htons(ETH_P_DNA_RT), + dev: NULL, /* All devices */ + func: dn_route_rcv, + data: (void*)1, }; +#define IS_NOT_PRINTABLE(x) ((x) < 32 || (x) > 126) + +static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf) +{ + int i; + + switch (dn_ntohs(dn->sdn_objnamel)) { + case 0: + sprintf(buf, "%d", dn->sdn_objnum); + break; + default: + for (i = 0; i < dn_ntohs(dn->sdn_objnamel); i++) { + buf[i] = dn->sdn_objname[i]; + if (IS_NOT_PRINTABLE(buf[i])) + buf[i] = '.'; + } + buf[i] = 0; + } +} + static int dn_get_info(char *buffer, char **start, off_t offset, int length) { struct sock *sk; @@ -1979,15 +2048,20 @@ static int dn_get_info(char *buffer, char **start, off_t offset, int length) off_t begin = 0; char buf1[DN_ASCBUF_LEN]; char buf2[DN_ASCBUF_LEN]; + char local_object[DN_MAXOBJL+3]; + char remote_object[DN_MAXOBJL+3]; - len += sprintf(buffer + len, "Local Remote\n"); + len += sprintf(buffer + len, "Local Remote\n"); read_lock(&dn_hash_lock); for(sk = dn_sklist; sk != NULL; sk = sk->next) { - scp = &sk->protinfo.dn; + scp = DN_SK(sk); + + dn_printable_object(&scp->addr, local_object); + dn_printable_object(&scp->peer, remote_object); len += sprintf(buffer + len, - "%6s/%04X %04d:%04d %04d:%04d %01d %6s/%04X %04d:%04d %04d:%04d %01d %4s %s\n", + "%6s/%04X %04d:%04d %04d:%04d %01d %-16s %6s/%04X %04d:%04d %04d:%04d %01d %-16s %4s %s\n", dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->addr)), buf1), scp->addrloc, scp->numdat, @@ -1995,6 +2069,7 @@ static int dn_get_info(char *buffer, char **start, off_t offset, int length) scp->ackxmt_dat, scp->ackxmt_oth, scp->flowloc_sw, + local_object, dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->peer)), buf2), scp->addrrem, scp->numdat_rcv, @@ -2002,6 +2077,7 @@ static int dn_get_info(char *buffer, char **start, off_t offset, int length) scp->ackrcv_dat, scp->ackrcv_oth, scp->flowrem_sw, + remote_object, dn_state2asc(scp->state), ((scp->accept_mode == ACC_IMMED) ? "IMMED" : "DEFER")); @@ -2026,8 +2102,8 @@ static int dn_get_info(char *buffer, char **start, off_t offset, int length) static struct net_proto_family dn_family_ops = { - AF_DECnet, - dn_create + family: AF_DECnet, + create: dn_create, }; static struct proto_ops dn_proto_ops = { @@ -2067,6 +2143,7 @@ MODULE_PARM(addr, "2i"); MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node"); #endif +static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.4.0-test12s (C) 1995-2000 Linux DECnet Project Team\n"; static int __init decnet_init(void) { @@ -2085,7 +2162,7 @@ static int __init decnet_init(void) dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address)); #endif - printk(KERN_INFO "NET4: DECnet for Linux: V.2.4.0-test10s (C) 1995-2000 Linux DECnet Project Team\n"); + printk(banner); sock_register(&dn_family_ops); dev_add_pack(&dn_dix_packet_type); diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index d8f91ac38..056eaa043 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -52,7 +52,7 @@ static unsigned char dn_eco_version[3] = {0x02,0x00,0x00}; extern struct neigh_table dn_neigh_table; -struct net_device *decnet_default_device = NULL; +struct net_device *decnet_default_device; static struct dn_dev *dn_dev_create(struct net_device *dev, int *err); static void dn_dev_delete(struct net_device *dev); @@ -1286,9 +1286,7 @@ void __exit dn_dev_cleanup(void) } #endif /* CONFIG_SYSCTL */ -#ifdef CONFIG_PROC_FS proc_net_remove("decnet_dev"); -#endif /* CONFIG_PROC_FS */ dn_dev_devices_off(); } diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index aff2dc05d..f82e26406 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c @@ -55,7 +55,7 @@ extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); #endif /* CONFIG_RTNETLINK */ -static struct dn_fib_info *dn_fib_info_list = NULL; +static struct dn_fib_info *dn_fib_info_list; static rwlock_t dn_fib_info_lock = RW_LOCK_UNLOCKED; int dn_fib_info_cnt; @@ -641,15 +641,11 @@ static int decnet_rt_get_info(char *buffer, char **start, off_t offset, int leng return 0; } - #endif /* CONFIG_PROC_FS */ - void __exit dn_fib_cleanup(void) { -#ifdef CONFIG_PROC_FS proc_net_remove("decnet_route"); -#endif dn_fib_table_cleanup(); dn_fib_rules_cleanup(); diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 00c27cdec..f25f37275 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -18,6 +18,8 @@ * forwarding now stands a good chance of * working. * Steve Whitehouse : Fixed neighbour states (for now anyway). + * Steve Whitehouse : Made error_report functions dummies. This + * is not the right place to return skbs. * */ @@ -52,81 +54,66 @@ static int dn_phase3_output(struct sk_buff *); * For talking to broadcast devices: Ethernet & PPP */ static struct neigh_ops dn_long_ops = { - AF_DECnet, - NULL, - NULL, - dn_long_error_report, - dn_long_output, - dn_long_output, - dev_queue_xmit, - dev_queue_xmit + family: AF_DECnet, + error_report: dn_long_error_report, + output: dn_long_output, + connected_output: dn_long_output, + hh_output: dev_queue_xmit, + queue_xmit: dev_queue_xmit, }; /* * For talking to pointopoint and multidrop devices: DDCMP and X.25 */ static struct neigh_ops dn_short_ops = { - AF_DECnet, - NULL, - NULL, - dn_short_error_report, - dn_short_output, - dn_short_output, - dev_queue_xmit, - dev_queue_xmit + family: AF_DECnet, + error_report: dn_short_error_report, + output: dn_short_output, + connected_output: dn_short_output, + hh_output: dev_queue_xmit, + queue_xmit: dev_queue_xmit, }; /* * For talking to DECnet phase III nodes */ static struct neigh_ops dn_phase3_ops = { - AF_DECnet, - NULL, - NULL, - dn_short_error_report, /* Can use short version here */ - dn_phase3_output, - dn_phase3_output, - dev_queue_xmit, - dev_queue_xmit + family: AF_DECnet, + error_report: dn_short_error_report, /* Can use short version here */ + output: dn_phase3_output, + connected_output: dn_phase3_output, + hh_output: dev_queue_xmit, + queue_xmit: dev_queue_xmit }; struct neigh_table dn_neigh_table = { - NULL, - PF_DECnet, - sizeof(struct dn_neigh), - sizeof(dn_address), - dn_neigh_hash, - dn_neigh_construct, - NULL, /* pconstructor */ - NULL, /* pdestructor */ - NULL, /* proxyredo */ - "dn_neigh_cache", - { - NULL, - NULL, - &dn_neigh_table, - 0, - NULL, - NULL, - 30 * HZ, /* base_reachable_time */ - 1 * HZ, /* retrans_time */ - 60 * HZ, /* gc_staletime */ - 30 * HZ, /* reachable_time */ - 5 * HZ, /* delay_probe_time */ - 3, /* queue_len */ - 0, /* ucast_probes */ - 0, /* app_probes */ - 0, /* mcast_probes */ - 0, /* anycast_delay */ - 0, /* proxy_delay */ - 0, /* proxy_qlen */ - 1 * HZ, /* locktime */ + family: PF_DECnet, + entry_size: sizeof(struct dn_neigh), + key_len: sizeof(dn_address), + hash: dn_neigh_hash, + constructor: dn_neigh_construct, + id: "dn_neigh_cache", + parms: { + tbl: &dn_neigh_table, + entries: 0, + base_reachable_time: 30 * HZ, + retrans_time: 1 * HZ, + gc_staletime: 60 * HZ, + reachable_time: 30 * HZ, + delay_probe_time: 5 * HZ, + queue_len: 3, + ucast_probes: 0, + app_probes: 0, + mcast_probes: 0, + anycast_delay: 0, + proxy_delay: 0, + proxy_qlen: 0, + locktime: 1 * HZ, }, - 30 * HZ, /* gc_interval */ - 128, /* gc_thresh1 */ - 512, /* gc_thresh2 */ - 1024, /* gc_thresh3 */ - + gc_interval: 30 * HZ, + gc_thresh1: 128, + gc_thresh2: 512, + gc_thresh3: 1024, }; static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev) @@ -180,66 +167,15 @@ static int dn_neigh_construct(struct neighbour *neigh) static void dn_long_error_report(struct neighbour *neigh, struct sk_buff *skb) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; - unsigned char *ptr; - printk(KERN_DEBUG "dn_long_error_report: called\n"); - - if (!(cb->rt_flags & DN_RT_F_RQR)) { - kfree_skb(skb); - return; - } - - skb_push(skb, skb->data - skb->nh.raw); - ptr = skb->data; - - *(unsigned short *)ptr = dn_htons(skb->len - 2); - ptr += 2; - - if (*ptr & DN_RT_F_PF) { - char padlen = (*ptr & ~DN_RT_F_PF); - ptr += padlen; - } - - *ptr++ |= (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS; - - ptr += 2; - dn_dn2eth(ptr, dn_ntohs(cb->src)); - ptr += 8; - dn_dn2eth(ptr, dn_ntohs(cb->dst)); - ptr += 6; - *ptr = 0; - - skb->dst->neighbour->ops->queue_xmit(skb); + kfree_skb(skb); } static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; - unsigned char *ptr; - printk(KERN_DEBUG "dn_short_error_report: called\n"); - - if (!(cb->rt_flags & DN_RT_F_RQR)) { - kfree_skb(skb); - return; - } - - skb_push(skb, skb->data - skb->nh.raw); - ptr = skb->data; - - *(unsigned short *)ptr = dn_htons(skb->len - 2); - ptr += 2; - *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS; - - *(dn_address *)ptr = cb->src; - ptr += 2; - *(dn_address *)ptr = cb->dst; - ptr += 2; - *ptr = 0; - - skb->dst->neighbour->ops->queue_xmit(skb); + kfree_skb(skb); } static int dn_neigh_output_packet(struct sk_buff *skb) @@ -266,7 +202,7 @@ static int dn_long_output(struct sk_buff *skb) int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3; unsigned char *data; struct dn_long_packet *lp; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); if (skb_headroom(skb) < headroom) { @@ -312,7 +248,7 @@ static int dn_short_output(struct sk_buff *skb) int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; struct dn_short_packet *sp; unsigned char *data; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); if (skb_headroom(skb) < headroom) { @@ -355,7 +291,7 @@ static int dn_phase3_output(struct sk_buff *skb) int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; struct dn_short_packet *sp; unsigned char *data; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); if (skb_headroom(skb) < headroom) { struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom); @@ -659,8 +595,6 @@ void __init dn_neigh_init(void) void __exit dn_neigh_cleanup(void) { -#ifdef CONFIG_PROC_FS proc_net_remove("decnet_neigh"); -#endif /* CONFIG_PROC_FS */ neigh_table_clear(&dn_neigh_table); } diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 361729458..11a4e8237 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -25,6 +25,9 @@ * Steve Whitehouse: * Patrick Caulfield: Checking conninits for correctness & sending of error * responses. + * Steve Whitehouse: Added backlog congestion level return codes. + * Patrick Caulfield: + * Steve Whitehouse: Added flow control support (outbound) */ /****************************************************************************** @@ -79,7 +82,7 @@ static void dn_log_martian(struct sk_buff *skb, const char *msg) { if (decnet_log_martians && net_ratelimit()) { char *devname = skb->dev ? skb->dev->name : "???"; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); printk(KERN_INFO "DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n", msg, devname, cb->src, cb->dst, cb->src_port, cb->dst_port); } } @@ -91,7 +94,7 @@ static void dn_log_martian(struct sk_buff *skb, const char *msg) */ static void dn_ack(struct sock *sk, struct sk_buff *skb, unsigned short ack) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); unsigned short type = ((ack >> 12) & 0x0003); int wakeup = 0; @@ -212,7 +215,7 @@ static struct { */ static struct sock *dn_find_listener(struct sk_buff *skb, unsigned short *reason) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); struct nsp_conn_init_msg *msg = (struct nsp_conn_init_msg *)skb->data; struct sockaddr_dn dstaddr; struct sockaddr_dn srcaddr; @@ -331,33 +334,26 @@ static void dn_nsp_conn_init(struct sock *sk, struct sk_buff *skb) static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_skb_cb *cb = DN_SKB_CB(skb); + struct dn_scp *scp = DN_SK(sk); + unsigned char *ptr; - if (skb->len < 3) + if (skb->len < 4) goto out; - cb->services = *skb->data; - cb->info = *(skb->data+1); - skb_pull(skb, 2); - cb->segsize = dn_ntohs(*(__u16 *)skb->data); - skb_pull(skb, 2); - - /* - * FIXME: Check out services and info fields to check that - * we can talk to this kind of node. - */ + ptr = skb->data; + cb->services = *ptr++; + cb->info = *ptr++; + cb->segsize = dn_ntohs(*(__u16 *)ptr); if ((scp->state == DN_CI) || (scp->state == DN_CD)) { scp->persist = 0; scp->addrrem = cb->src_port; sk->state = TCP_ESTABLISHED; scp->state = DN_RUN; - - if (scp->mss > cb->segsize) - scp->mss = cb->segsize; - if (scp->mss < 230) - scp->mss = 230; + scp->services_rem = cb->services; + scp->info_rem = cb->info; + scp->segsize_rem = cb->segsize; if (skb->len > 0) { unsigned char dlen = *skb->data; @@ -366,7 +362,7 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb) memcpy(scp->conndata_in.opt_data, skb->data + 1, dlen); } } - dn_nsp_send_lnk(sk, DN_NOCHANGE); + dn_nsp_send_link(sk, DN_NOCHANGE, 0); if (!sk->dead) sk->state_change(sk); } @@ -377,7 +373,7 @@ out: static void dn_nsp_conn_ack(struct sock *sk, struct sk_buff *skb) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); if (scp->state == DN_CI) { scp->state = DN_CD; @@ -389,8 +385,8 @@ static void dn_nsp_conn_ack(struct sock *sk, struct sk_buff *skb) static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb) { - struct dn_scp *scp = &sk->protinfo.dn; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_scp *scp = DN_SK(sk); + struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned short reason; if (skb->len < 2) @@ -448,7 +444,7 @@ out: */ static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); unsigned short reason; if (skb->len != 2) @@ -492,38 +488,65 @@ out: static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_scp *scp = DN_SK(sk); unsigned short segnum; unsigned char lsflags; char fcval; + int wake_up = 0; + char *ptr = skb->data; + unsigned char fctype = scp->services_rem & NSP_FC_MASK; if (skb->len != 4) goto out; - cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data); - skb_pull(skb, 2); - lsflags = *(unsigned char *)skb->data; - skb_pull(skb, 1); - fcval = *(char *)skb->data; + segnum = dn_ntohs(*(__u16 *)ptr); + ptr += 2; + lsflags = *(unsigned char *)ptr++; + fcval = *ptr; - if (lsflags & 0xf0) + /* + * Here we ignore erronous packets which should really + * should cause a connection abort. It is not critical + * for now though. + */ + if (lsflags & 0xf8) goto out; - if (((sk->protinfo.dn.numoth_rcv + 1) & 0x0FFF) == (segnum & 0x0FFF)) { - sk->protinfo.dn.numoth_rcv += 1; - switch(lsflags & 0x03) { - case 0x00: - break; - case 0x01: - sk->protinfo.dn.flowrem_sw = DN_DONTSEND; - break; - case 0x02: - sk->protinfo.dn.flowrem_sw = DN_SEND; + if (seq_next(scp->numoth_rcv, segnum)) { + seq_add(&scp->numoth_rcv, 1); + switch(lsflags & 0x04) { /* FCVAL INT */ + case 0x00: /* Normal Request */ + switch(lsflags & 0x03) { /* FCVAL MOD */ + case 0x00: /* Request count */ + if (fcval < 0) { + unsigned char p_fcval = -fcval; + if ((scp->flowrem_dat > p_fcval) && + (fctype == NSP_FC_SCMC)) { + scp->flowrem_dat -= p_fcval; + } + } else if (fcval > 0) { + scp->flowrem_dat += fcval; + wake_up = 1; + } + break; + case 0x01: /* Stop outgoing data */ + scp->flowrem_sw = DN_DONTSEND; + break; + case 0x02: /* Ok to start again */ + scp->flowrem_sw = DN_SEND; dn_nsp_output(sk); - if (!sk->dead) - sk->state_change(sk); + wake_up = 1; + } + break; + case 0x04: /* Interrupt Request */ + if (fcval > 0) { + scp->flowrem_oth += fcval; + wake_up = 1; + } + break; } - + if (wake_up && !sk->dead) + sk->state_change(sk); } dn_nsp_send_oth_ack(sk); @@ -582,9 +605,9 @@ static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); unsigned short segnum; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); int queued = 0; if (skb->len < 2) @@ -593,10 +616,10 @@ static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb) cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data); skb_pull(skb, 2); - if (((sk->protinfo.dn.numoth_rcv + 1) & 0x0fff) == (segnum & 0x0fff)) { + if (seq_next(scp->numoth_rcv, segnum)) { if (dn_queue_skb(sk, skb, SIGURG, &scp->other_receive_queue) == 0) { - sk->protinfo.dn.numoth_rcv++; + seq_add(&scp->numoth_rcv, 1); scp->other_report = 0; queued = 1; } @@ -612,8 +635,8 @@ static void dn_nsp_data(struct sock *sk, struct sk_buff *skb) { int queued = 0; unsigned short segnum; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_skb_cb *cb = DN_SKB_CB(skb); + struct dn_scp *scp = DN_SK(sk); if (skb->len < 2) goto out; @@ -621,17 +644,15 @@ static void dn_nsp_data(struct sock *sk, struct sk_buff *skb) cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data); skb_pull(skb, 2); - if (((sk->protinfo.dn.numdat_rcv + 1) & 0x0FFF) == - (segnum & 0x0FFF)) { - + if (seq_next(scp->numdat_rcv, segnum)) { if (dn_queue_skb(sk, skb, SIGIO, &sk->receive_queue) == 0) { - sk->protinfo.dn.numdat_rcv++; + seq_add(&scp->numdat_rcv, 1); queued = 1; } if ((scp->flowloc_sw == DN_SEND) && dn_congested(sk)) { scp->flowloc_sw = DN_DONTSEND; - dn_nsp_send_lnk(sk, DN_DONTSEND); + dn_nsp_send_link(sk, DN_DONTSEND, 0); } } @@ -648,7 +669,7 @@ out: */ static void dn_returned_conn_init(struct sock *sk, struct sk_buff *skb) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); if (scp->state == DN_CI) { scp->state = DN_NC; @@ -660,28 +681,37 @@ static void dn_returned_conn_init(struct sock *sk, struct sk_buff *skb) kfree_skb(skb); } -static void dn_nsp_no_socket(struct sk_buff *skb, unsigned short reason) +static int dn_nsp_no_socket(struct sk_buff *skb, unsigned short reason) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); + int ret = NET_RX_DROP; + + /* Must not reply to returned packets */ + if (cb->rt_flags & DN_RT_F_RTS) + goto out; if ((reason != NSP_REASON_OK) && ((cb->nsp_flags & 0x0c) == 0x08)) { switch(cb->nsp_flags & 0x70) { case 0x10: case 0x60: /* (Retransmitted) Connect Init */ dn_nsp_return_disc(skb, NSP_DISCINIT, reason); + ret = NET_RX_SUCCESS; break; case 0x20: /* Connect Confirm */ dn_nsp_return_disc(skb, NSP_DISCCONF, reason); + ret = NET_RX_SUCCESS; break; } } +out: kfree_skb(skb); + return ret; } static int dn_nsp_rx_packet(struct sk_buff *skb) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); struct sock *sk = NULL; unsigned char *ptr = (unsigned char *)skb->data; unsigned short reason = NSP_REASON_NL; @@ -754,14 +784,19 @@ static int dn_nsp_rx_packet(struct sk_buff *skb) sk = dn_find_by_skb(skb); got_it: if (sk != NULL) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); int ret; /* Reset backoff */ scp->nsp_rxtshift = 0; bh_lock_sock(sk); - ret = 0; + ret = NET_RX_SUCCESS; + if (decnet_debug_level & 8) + printk(KERN_DEBUG "NSP: 0x%02x 0x%02x 0x%04x 0x%04x %d\n", + (int)cb->rt_flags, (int)cb->nsp_flags, + (int)cb->src_port, (int)cb->dst_port, + (int)sk->lock.users); if (sk->lock.users == 0) ret = dn_nsp_backlog_rcv(sk, skb); else @@ -772,12 +807,11 @@ got_it: return ret; } - dn_nsp_no_socket(skb, reason); - return 1; + return dn_nsp_no_socket(skb, reason); free_out: kfree_skb(skb); - return 0; + return NET_RX_DROP; } int dn_nsp_rx(struct sk_buff *skb) @@ -792,12 +826,12 @@ int dn_nsp_rx(struct sk_buff *skb) */ int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb) { - struct dn_scp *scp = &sk->protinfo.dn; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_scp *scp = DN_SK(sk); + struct dn_skb_cb *cb = DN_SKB_CB(skb); if (cb->rt_flags & DN_RT_F_RTS) { dn_returned_conn_init(sk, skb); - return 0; + return NET_RX_SUCCESS; } /* @@ -875,6 +909,6 @@ free_out: } } - return 0; + return NET_RX_SUCCESS; } diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index 6965cbf42..5e8482ce0 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -20,6 +20,7 @@ * Steve Whitehouse: New output state machine * Paul Koning: Connect Confirm message fix. * Eduardo Serrat: Fix to stop dn_nsp_do_disc() sending malformed packets. + * Steve Whitehouse: dn_nsp_output() and friends needed a spring clean */ /****************************************************************************** @@ -165,7 +166,7 @@ struct sk_buff *dn_alloc_send_skb(struct sock *sk, int *size, int noblock, int * */ unsigned long dn_nsp_persist(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1; @@ -188,7 +189,7 @@ unsigned long dn_nsp_persist(struct sock *sk) */ static void dn_nsp_rtt(struct sock *sk, long rtt) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); long srtt = (long)scp->nsp_srtt; long rttvar = (long)scp->nsp_rttvar; long delta; @@ -223,65 +224,64 @@ static void dn_nsp_rtt(struct sock *sk, long rtt) /* printk(KERN_DEBUG "srtt=%lu rttvar=%lu\n", scp->nsp_srtt, scp->nsp_rttvar); */ } -/* - * Walk the queues, otherdata/linkservice first. Send as many - * frames as the window allows, increment send counts on all - * skbs which are sent. Reduce the window if we are retransmitting - * frames. +/** + * dn_nsp_clone_and_send - Send a data packet by cloning it + * @skb: The packet to clone and transmit + * @gfp: memory allocation flag + * + * Clone a queued data or other data packet and transmit it. + * + * Returns: The number of times the packet has been sent previously */ -void dn_nsp_output(struct sock *sk) +static inline unsigned dn_nsp_clone_and_send(struct sk_buff *skb, int gfp) { - struct dn_scp *scp = &sk->protinfo.dn; - unsigned long win = scp->snd_window; - struct sk_buff *skb, *skb2, *list; - struct dn_skb_cb *cb; - int reduce_win = 0; + struct dn_skb_cb *cb = DN_SKB_CB(skb); + struct sk_buff *skb2; + int ret = 0; - /* printk(KERN_DEBUG "dn_nsp_output: ping\n"); */ + if ((skb2 = skb_clone(skb, gfp)) != NULL) { + ret = cb->xmit_count; + cb->xmit_count++; + cb->stamp = jiffies; + skb2->sk = skb->sk; + dn_nsp_send(skb2); + } + + return ret; +} + +/** + * dn_nsp_output - Try and send something from socket queues + * @sk: The socket whose queues are to be investigated + * @gfp: The memory allocation flags + * + * Try and send the packet on the end of the data and other data queues. + * Other data gets priority over data, and if we retransmit a packet we + * reduce the window by dividing it in two. + * + */ +void dn_nsp_output(struct sock *sk) +{ + struct dn_scp *scp = DN_SK(sk); + struct sk_buff *skb; + unsigned reduce_win = 0; /* * First we check for otherdata/linkservice messages */ - skb = scp->other_xmit_queue.next; - list = (struct sk_buff *)&scp->other_xmit_queue; - while(win && (skb != list)) { - if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { - cb = (struct dn_skb_cb *)skb; - if (cb->xmit_count > 0) - reduce_win = 1; - else - cb->stamp = jiffies; - cb->xmit_count++; - skb2->sk = sk; - dn_nsp_send(skb2); - } - skb = skb->next; - win--; - } + if ((skb = skb_peek(&scp->other_xmit_queue)) != NULL) + reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC); /* * If we may not send any data, we don't. - * Should this apply to otherdata as well ? - SJW + * If we are still trying to get some other data down the + * channel, we don't try and send any data. */ - if (scp->flowrem_sw != DN_SEND) + if (reduce_win || (scp->flowrem_sw != DN_SEND)) goto recalc_window; - skb = scp->data_xmit_queue.next; - list = (struct sk_buff *)&scp->data_xmit_queue; - while(win && (skb != list)) { - if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { - cb = (struct dn_skb_cb *)skb; - if (cb->xmit_count > 0) - reduce_win = 1; - else - cb->stamp = jiffies; - cb->xmit_count++; - skb2->sk = sk; - dn_nsp_send(skb2); - } - skb = skb->next; - win--; - } + if ((skb = skb_peek(&scp->data_xmit_queue)) != NULL) + reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC); /* * If we've sent any frame more than once, we cut the @@ -290,7 +290,6 @@ void dn_nsp_output(struct sock *sk) */ recalc_window: if (reduce_win) { - /* printk(KERN_DEBUG "Window reduction %ld\n", scp->snd_window); */ scp->snd_window >>= 1; if (scp->snd_window < NSP_MIN_WINDOW) scp->snd_window = NSP_MIN_WINDOW; @@ -299,7 +298,7 @@ recalc_window: int dn_nsp_xmit_timeout(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); dn_nsp_output(sk); @@ -309,14 +308,60 @@ int dn_nsp_xmit_timeout(struct sock *sk) return 0; } -void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int oth) +static inline unsigned char *dn_mk_common_header(struct dn_scp *scp, struct sk_buff *skb, unsigned char msgflag, int len) +{ + unsigned char *ptr = skb_push(skb, len); + + if (len < 5) + BUG(); + + *ptr++ = msgflag; + *((unsigned short *)ptr) = scp->addrrem; + ptr += 2; + *((unsigned short *)ptr) = scp->addrloc; + ptr += 2; + return ptr; +} + +static unsigned short *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, unsigned char msgflag, int hlen, int other) +{ + struct dn_scp *scp = DN_SK(sk); + unsigned short acknum = scp->numdat_rcv & 0x0FFF; + unsigned short ackcrs = scp->numoth_rcv & 0x0FFF; + unsigned short *ptr; + + if (hlen < 9) + BUG(); + + scp->ackxmt_dat = acknum; + scp->ackxmt_oth = ackcrs; + acknum |= 0x8000; + ackcrs |= 0x8000; + + /* If this is an "other data/ack" message, swap acknum and ackcrs */ + if (other) { + unsigned short tmp = acknum; + acknum = ackcrs; + ackcrs = tmp; + } + + /* Set "cross subchannel" bit in ackcrs */ + ackcrs |= 0x2000; + + ptr = (unsigned short *)dn_mk_common_header(scp, skb, msgflag, hlen); + + *ptr++ = dn_htons(acknum); + *ptr++ = dn_htons(ackcrs); + + return ptr; +} + +void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int gfp, int oth) { - struct dn_scp *scp = &sk->protinfo.dn; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_scp *scp = DN_SK(sk); + struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1; - struct sk_buff *skb2; - if (t < HZ) t = HZ; /* * Slow start: If we have been idle for more than * one RTT, then reset window to min size. @@ -336,20 +381,17 @@ void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int oth) if (scp->flowrem_sw != DN_SEND) return; - if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { - cb->stamp = jiffies; - cb->xmit_count++; - skb2->sk = sk; - dn_nsp_send(skb2); - } + dn_nsp_clone_and_send(skb, gfp); } + int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_skb_cb *cb = DN_SKB_CB(skb); + struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb2, *list, *ack = NULL; int wakeup = 0; + int try_retrans = 0; unsigned long reftime = cb->stamp; unsigned long pkttime; unsigned short xmit_count; @@ -358,7 +400,7 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff skb2 = q->next; list = (struct sk_buff *)q; while(list != skb2) { - struct dn_skb_cb *cb2 = (struct dn_skb_cb *)skb2->cb; + struct dn_skb_cb *cb2 = DN_SKB_CB(skb2); if (before_or_equal(cb2->segnum, acknum)) ack = skb2; @@ -372,27 +414,50 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff /* printk(KERN_DEBUG "check_xmit_queue: %04x, %d\n", acknum, cb2->xmit_count); */ + /* Does _last_ packet acked have xmit_count > 1 */ + try_retrans = 0; + /* Remember to wake up the sending process */ wakeup = 1; + /* Keep various statistics */ pkttime = cb2->stamp; xmit_count = cb2->xmit_count; segnum = cb2->segnum; + /* Remove and drop ack'ed packet */ skb_unlink(ack); kfree_skb(ack); ack = NULL; + + /* + * We don't expect to see acknowledgements for packets we + * haven't sent yet. + */ + if (xmit_count == 0) + BUG(); + /* + * If the packet has only been sent once, we can use it + * to calculate the RTT and also open the window a little + * further. + */ if (xmit_count == 1) { if (equal(segnum, acknum)) dn_nsp_rtt(sk, (long)(pkttime - reftime)); - if (scp->snd_window < NSP_MAX_WINDOW) + if (scp->snd_window < scp->max_window) scp->snd_window++; } + + /* + * Packet has been sent more than once. If this is the last + * packet to be acknowledged then we want to send the next + * packet in the send queue again (assumes the remote host does + * go-back-N error control). + */ + if (xmit_count > 1) + try_retrans = 1; } -#if 0 /* Turned off due to possible interference in socket shutdown */ - if ((skb_queue_len(&scp->data_xmit_queue) == 0) && - (skb_queue_len(&scp->other_xmit_queue) == 0)) - scp->persist = 0; -#endif + if (try_retrans) + dn_nsp_output(sk); return wakeup; } @@ -400,47 +465,31 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff void dn_nsp_send_data_ack(struct sock *sk) { struct sk_buff *skb = NULL; - struct nsp_data_ack_msg *msg; - if ((skb = dn_alloc_skb(sk, 200, GFP_ATOMIC)) == NULL) + if ((skb = dn_alloc_skb(sk, 9, GFP_ATOMIC)) == NULL) return; - - msg = (struct nsp_data_ack_msg *)skb_put(skb,sizeof(*msg)); - - msg->msgflg = 0x04; /* data ack message */ - msg->dstaddr = sk->protinfo.dn.addrrem; - msg->srcaddr = sk->protinfo.dn.addrloc; - msg->acknum = dn_htons((sk->protinfo.dn.numdat_rcv & 0x0FFF) | 0x8000); - - sk->protinfo.dn.ackxmt_dat = sk->protinfo.dn.numdat_rcv; + skb_reserve(skb, 9); + dn_mk_ack_header(sk, skb, 0x04, 9, 0); dn_nsp_send(skb); } void dn_nsp_send_oth_ack(struct sock *sk) { struct sk_buff *skb = NULL; - struct nsp_data_ack_msg *msg; - if ((skb = dn_alloc_skb(sk, 200, GFP_ATOMIC)) == NULL) + if ((skb = dn_alloc_skb(sk, 9, GFP_ATOMIC)) == NULL) return; - - msg = (struct nsp_data_ack_msg *)skb_put(skb,sizeof(*msg)); - - msg->msgflg = 0x14; /* oth ack message */ - msg->dstaddr = sk->protinfo.dn.addrrem; - msg->srcaddr = sk->protinfo.dn.addrloc; - msg->acknum = dn_htons((sk->protinfo.dn.numoth_rcv & 0x0FFF) | 0x8000); - - sk->protinfo.dn.ackxmt_oth = sk->protinfo.dn.numoth_rcv; + skb_reserve(skb, 9); + dn_mk_ack_header(sk, skb, 0x14, 9, 1); dn_nsp_send(skb); } void dn_send_conn_ack (struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb = NULL; struct nsp_conn_ack_msg *msg; @@ -456,7 +505,7 @@ void dn_send_conn_ack (struct sock *sk) void dn_nsp_delayed_ack(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); if (scp->ackxmt_oth != scp->numoth_rcv) dn_nsp_send_oth_ack(sk); @@ -467,7 +516,7 @@ void dn_nsp_delayed_ack(struct sock *sk) static int dn_nsp_retrans_conn_conf(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); if (scp->state == DN_CC) dn_send_conn_conf(sk, GFP_ATOMIC); @@ -477,7 +526,7 @@ static int dn_nsp_retrans_conn_conf(struct sock *sk) void dn_send_conn_conf(struct sock *sk, int gfp) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb = NULL; struct nsp_conn_init_msg *msg; unsigned char len = scp->conndata_out.opt_optl; @@ -489,9 +538,9 @@ void dn_send_conn_conf(struct sock *sk, int gfp) msg->msgflg = 0x28; msg->dstaddr = scp->addrrem; msg->srcaddr = scp->addrloc; - msg->services = 0x01; - msg->info = 0x03; - msg->segsize = dn_htons(0x05B3); + msg->services = scp->services_loc; + msg->info = scp->info_loc; + msg->segsize = dn_htons(scp->segsize_loc); *skb_put(skb,1) = len; @@ -551,7 +600,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg, unsigned short reason, int gfp) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); int ddl = 0; if (msgflg == NSP_DISCINIT) @@ -568,7 +617,7 @@ void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg, void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg, unsigned short reason) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); int ddl = 0; int gfp = GFP_ATOMIC; @@ -577,38 +626,35 @@ void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg, } -void dn_nsp_send_lnk(struct sock *sk, unsigned short flgs) +void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval) { - struct dn_scp *scp = &sk->protinfo.dn; - struct sk_buff *skb = NULL; - struct nsp_data_seg_msg *msg; - struct nsp_data_opt_msg *msg1; - struct dn_skb_cb *cb; + struct dn_scp *scp = DN_SK(sk); + struct sk_buff *skb; + unsigned short *segnum; + unsigned char *ptr; + int gfp = GFP_ATOMIC; - if ((skb = dn_alloc_skb(sk, 80, GFP_ATOMIC)) == NULL) + if ((skb = dn_alloc_skb(sk, 13, gfp)) == NULL) return; - cb = (struct dn_skb_cb *)skb->cb; - msg = (struct nsp_data_seg_msg *)skb_put(skb, sizeof(*msg)); - msg->msgflg = 0x10; /* Link svc message */ - msg->dstaddr = scp->addrrem; - msg->srcaddr = scp->addrloc; + skb_reserve(skb, 13); + segnum = dn_mk_ack_header(sk, skb, 0x10, 13, 1); + *segnum = dn_htons(scp->numoth); + DN_SKB_CB(skb)->segnum = scp->numoth; + seq_add(&scp->numoth, 1); + ptr = (unsigned char *)(segnum + 1); + *ptr++ = lsflags; + *ptr = fcval; - msg1 = (struct nsp_data_opt_msg *)skb_put(skb, sizeof(*msg1)); - msg1->acknum = dn_htons((scp->ackxmt_oth & 0x0FFF) | 0x8000); - msg1->segnum = dn_htons(cb->segnum = (scp->numoth++ & 0x0FFF)); - msg1->lsflgs = flgs; - - dn_nsp_queue_xmit(sk, skb, 1); + dn_nsp_queue_xmit(sk, skb, gfp, 1); scp->persist = dn_nsp_persist(sk); scp->persist_fxn = dn_nsp_xmit_timeout; - } static int dn_nsp_retrans_conninit(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); if (scp->state == DN_CI) dn_nsp_send_conninit(sk, NSP_RCI); @@ -618,7 +664,7 @@ static int dn_nsp_retrans_conninit(struct sock *sk) void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb = NULL; struct nsp_conn_init_msg *msg; unsigned char aux; @@ -629,16 +675,16 @@ void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg) if ((skb = dn_alloc_skb(sk, 200, (msgflg == NSP_CI) ? sk->allocation : GFP_ATOMIC)) == NULL) return; - cb = (struct dn_skb_cb *)skb->cb; + cb = DN_SKB_CB(skb); msg = (struct nsp_conn_init_msg *)skb_put(skb,sizeof(*msg)); msg->msgflg = msgflg; msg->dstaddr = 0x0000; /* Remote Node will assign it*/ - msg->srcaddr = sk->protinfo.dn.addrloc; - msg->services = 1 | NSP_FC_NONE; /* Requested flow control */ - msg->info = 0x03; /* Version Number */ - msg->segsize = dn_htons(1459); /* Max segment size */ + msg->srcaddr = scp->addrloc; + msg->services = scp->services_loc; /* Requested flow control */ + msg->info = scp->info_loc; /* Version Number */ + msg->segsize = dn_htons(scp->segsize_loc); /* Max segment size */ if (scp->peer.sdn_objnum) type = 0; @@ -674,8 +720,8 @@ void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg) if (aux > 0) memcpy(skb_put(skb,aux), scp->conndata_out.opt_data, aux); - sk->protinfo.dn.persist = dn_nsp_persist(sk); - sk->protinfo.dn.persist_fxn = dn_nsp_retrans_conninit; + scp->persist = dn_nsp_persist(sk); + scp->persist_fxn = dn_nsp_retrans_conninit; cb->rt_flags = DN_RT_F_RQR; diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 70646fc11..b40c601b6 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -33,6 +33,9 @@ * Steve Whitehouse : Real SMP at last :-) Also new netfilter * stuff. Look out raw sockets your days * are numbered! + * Steve Whitehouse : Added return-to-sender functions. Added + * backlog congestion level return codes. + * */ /****************************************************************************** @@ -109,17 +112,16 @@ static struct timer_list dn_rt_flush_timer = { function: dn_run_flush }; int decnet_dst_gc_interval = 2; static struct dst_ops dn_dst_ops = { - PF_DECnet, - __constant_htons(ETH_P_DNA_RT), - 128, - dn_dst_gc, - dn_dst_check, - dn_dst_reroute, - NULL, - dn_dst_negative_advice, - dn_dst_link_failure, - sizeof(struct dn_route), - ATOMIC_INIT(0) + family: PF_DECnet, + protocol: __constant_htons(ETH_P_DNA_RT), + gc_thresh: 128, + gc: dn_dst_gc, + check: dn_dst_check, + reroute: dn_dst_reroute, + negative_advice: dn_dst_negative_advice, + link_failure: dn_dst_link_failure, + entry_size: sizeof(struct dn_route), + entries: ATOMIC_INIT(0), }; static __inline__ unsigned dn_hash(unsigned short src, unsigned short dst) @@ -294,21 +296,131 @@ void dn_rt_cache_flush(int delay) spin_unlock_bh(&dn_rt_flush_lock); } +/** + * dn_return_short - Return a short packet to its sender + * @skb: The packet to return + * + */ +static int dn_return_short(struct sk_buff *skb) +{ + struct dn_skb_cb *cb; + unsigned char *ptr; + dn_address *src; + dn_address *dst; + dn_address tmp; + + /* Add back headers */ + skb_push(skb, skb->data - skb->nh.raw); + + if ((skb = skb_unshare(skb, GFP_ATOMIC)) == NULL) + return NET_RX_DROP; + + cb = DN_SKB_CB(skb); + /* Skip packet length and point to flags */ + ptr = skb->data + 2; + *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS; + + dst = (dn_address *)ptr; + ptr += 2; + src = (dn_address *)ptr; + ptr += 2; + *ptr = 0; /* Zero hop count */ + + /* Swap source and destination */ + tmp = *src; + *src = *dst; + *dst = tmp; + + skb->pkt_type = PACKET_OUTGOING; + dn_rt_finish_output(skb, NULL); + return NET_RX_SUCCESS; +} + +/** + * dn_return_long - Return a long packet to its sender + * @skb: The long format packet to return + * + */ +static int dn_return_long(struct sk_buff *skb) +{ + struct dn_skb_cb *cb; + unsigned char *ptr; + unsigned char *src_addr, *dst_addr; + unsigned char tmp[ETH_ALEN]; + + /* Add back all headers */ + skb_push(skb, skb->data - skb->nh.raw); + + if ((skb = skb_unshare(skb, GFP_ATOMIC)) == NULL) + return NET_RX_DROP; + cb = DN_SKB_CB(skb); + /* Ignore packet length and point to flags */ + ptr = skb->data + 2; + + /* Skip padding */ + if (*ptr & DN_RT_F_PF) { + char padlen = (*ptr & ~DN_RT_F_PF); + ptr += padlen; + } + + *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS; + ptr += 2; + dst_addr = ptr; + ptr += 8; + src_addr = ptr; + ptr += 6; + *ptr = 0; /* Zero hop count */ + + /* Swap source and destination */ + memcpy(tmp, src_addr, ETH_ALEN); + memcpy(src_addr, dst_addr, ETH_ALEN); + memcpy(dst_addr, tmp, ETH_ALEN); + + skb->pkt_type = PACKET_OUTGOING; + dn_rt_finish_output(skb, tmp); + return NET_RX_SUCCESS; +} + +/** + * dn_route_rx_packet - Try and find a route for an incoming packet + * @skb: The packet to find a route for + * + * Returns: result of input function if route is found, error code otherwise + */ static int dn_route_rx_packet(struct sk_buff *skb) { + struct dn_skb_cb *cb = DN_SKB_CB(skb); int err; if ((err = dn_route_input(skb)) == 0) return skb->dst->input(skb); + if (decnet_debug_level & 4) { + char *devname = skb->dev ? skb->dev->name : "???"; + struct dn_skb_cb *cb = DN_SKB_CB(skb); + printk(KERN_DEBUG + "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n", + (int)cb->rt_flags, devname, skb->len, cb->src, cb->dst, + err, skb->pkt_type); + } + + if ((skb->pkt_type == PACKET_HOST) && (cb->rt_flags & DN_RT_F_RQR)) { + switch(cb->rt_flags & DN_RT_PKT_MSK) { + case DN_RT_PKT_SHORT: + return dn_return_short(skb); + case DN_RT_PKT_LONG: + return dn_return_long(skb); + } + } + kfree_skb(skb); - return err; + return NET_RX_DROP; } static int dn_route_rx_long(struct sk_buff *skb) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned char *ptr = skb->data; if (skb->len < 21) /* 20 for long header, 1 for shortest nsp */ @@ -339,14 +451,14 @@ static int dn_route_rx_long(struct sk_buff *skb) drop_it: kfree_skb(skb); - return 0; + return NET_RX_DROP; } static int dn_route_rx_short(struct sk_buff *skb) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned char *ptr = skb->data; if (skb->len < 6) /* 5 for short header + 1 for shortest nsp */ @@ -365,29 +477,33 @@ static int dn_route_rx_short(struct sk_buff *skb) drop_it: kfree_skb(skb); - return 0; + return NET_RX_DROP; } static int dn_route_discard(struct sk_buff *skb) { + /* + * I know we drop the packet here, but thats considered success in + * this case + */ kfree_skb(skb); - return 0; + return NET_RX_SUCCESS; } static int dn_route_ptp_hello(struct sk_buff *skb) { dn_dev_hello(skb); dn_neigh_pointopoint_hello(skb); - return 0; + return NET_RX_SUCCESS; } int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) { struct dn_skb_cb *cb; unsigned char flags = 0; - int padlen = 0; __u16 len = dn_ntohs(*(__u16 *)skb->data); struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr; + unsigned char padlen = 0; if (dn == NULL) goto dump_it; @@ -404,7 +520,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type flags = *skb->data; - cb = (struct dn_skb_cb *)skb->cb; + cb = DN_SKB_CB(skb); cb->stamp = jiffies; cb->iif = dev->ifindex; @@ -448,20 +564,16 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type switch(flags & DN_RT_CNTL_MSK) { case DN_RT_PKT_HELO: - NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_route_ptp_hello); - goto out; + return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_route_ptp_hello); case DN_RT_PKT_L1RT: case DN_RT_PKT_L2RT: - NF_HOOK(PF_DECnet, NF_DN_ROUTE, skb, skb->dev, NULL, dn_route_discard); - goto out; + return NF_HOOK(PF_DECnet, NF_DN_ROUTE, skb, skb->dev, NULL, dn_route_discard); case DN_RT_PKT_ERTH: - NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_router_hello); - goto out; + return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_router_hello); case DN_RT_PKT_EEDH: - NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_endnode_hello); - goto out; + return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_endnode_hello); } } else { if (dn->parms.state != DN_DEV_S_RU) @@ -480,7 +592,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type dump_it: kfree_skb(skb); out: - return 0; + return NET_RX_DROP; } static int dn_output(struct sk_buff *skb) @@ -488,7 +600,7 @@ static int dn_output(struct sk_buff *skb) struct dst_entry *dst = skb->dst; struct dn_route *rt = (struct dn_route *)dst; struct net_device *dev = dst->dev; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); struct neighbour *neigh; int err = -EINVAL; @@ -524,7 +636,7 @@ error: #ifdef CONFIG_DECNET_ROUTER static int dn_forward(struct sk_buff *skb) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); struct dst_entry *dst = skb->dst; struct net_device *dev = skb->dev; struct neighbour *neigh; @@ -536,7 +648,7 @@ static int dn_forward(struct sk_buff *skb) /* * Hop count exceeded. */ - err = 0; + err = NET_RX_DROP; if (++cb->hops > 30) goto drop; @@ -573,7 +685,7 @@ drop: static int dn_blackhole(struct sk_buff *skb) { kfree_skb(skb); - return 0; + return NET_RX_DROP; } /* @@ -583,7 +695,7 @@ static int dn_blackhole(struct sk_buff *skb) static int dn_rt_bug(struct sk_buff *skb) { if (net_ratelimit()) { - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); printk(KERN_DEBUG "dn_rt_bug: skb from:%04x to:%04x\n", cb->src, cb->dst); @@ -591,7 +703,7 @@ static int dn_rt_bug(struct sk_buff *skb) kfree_skb(skb); - return -EINVAL; + return NET_RX_BAD; } static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_address src, int flags) @@ -732,7 +844,7 @@ int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int static int dn_route_input_slow(struct sk_buff *skb) { struct dn_route *rt = NULL; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); struct net_device *dev = skb->dev; struct dn_dev *dn_db; struct neighbour *neigh = NULL; @@ -880,7 +992,7 @@ add_entry: int dn_route_input(struct sk_buff *skb) { struct dn_route *rt; - struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb; + struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned hash = dn_hash(cb->src, cb->dst); if (skb->dst) @@ -964,7 +1076,7 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg) if (skb == NULL) return -ENOBUFS; skb->mac.raw = skb->data; - cb = (struct dn_skb_cb *)skb->cb; + cb = DN_SKB_CB(skb); if (rta[RTA_SRC-1]) memcpy(&src, RTA_DATA(rta[RTA_SRC-1]), 2); @@ -1185,8 +1297,6 @@ void __exit dn_route_cleanup(void) del_timer(&dn_route_timer); dn_run_flush(0); -#ifdef CONFIG_PROC_FS proc_net_remove("decnet_cache"); -#endif /* CONFIG_PROC_FS */ } diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 133591f0b..32adfecba 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -57,7 +57,12 @@ struct dn_fib_rule int r_dead; }; -static struct dn_fib_rule default_rule = { NULL, ATOMIC_INIT(2), 0x7fff, DN_DEFAULT_TABLE, RTN_UNICAST }; +static struct dn_fib_rule default_rule = { + r_clntref: ATOMIC_INIT(2), + r_preference: 0x7fff, + r_table: DN_DEFAULT_TABLE, + r_action: RTN_UNICAST +}; static struct dn_fib_rule *dn_fib_rules = &default_rule; static rwlock_t dn_fib_rules_lock = RW_LOCK_UNLOCKED; @@ -291,9 +296,7 @@ static int dn_fib_rules_event(struct notifier_block *this, unsigned long event, static struct notifier_block dn_fib_rules_notifier = { - dn_fib_rules_event, - NULL, - 0 + notifier_call: dn_fib_rules_event, }; #ifdef CONFIG_RTNETLINK diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index ce7a3ac06..bc21acb4b 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -78,7 +78,7 @@ static rwlock_t dn_fib_tables_lock = RW_LOCK_UNLOCKED; static struct dn_fib_table *dn_fib_tables[DN_NUM_TABLES + 1]; static kmem_cache_t *dn_hash_kmem; -static int dn_fib_hash_zombies = 0; +static int dn_fib_hash_zombies; static __inline__ dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz) { diff --git a/net/decnet/dn_timer.c b/net/decnet/dn_timer.c index bbba58b02..41a4aa602 100644 --- a/net/decnet/dn_timer.c +++ b/net/decnet/dn_timer.c @@ -52,7 +52,7 @@ void dn_stop_slow_timer(struct sock *sk) static void dn_slow_timer(unsigned long arg) { struct sock *sk = (struct sock *)arg; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); sock_hold(sk); bh_lock_sock(sk); @@ -112,7 +112,7 @@ out: static void dn_fast_timer(unsigned long arg) { struct sock *sk = (struct sock *)arg; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); bh_lock_sock(sk); if (sk->lock.users != 0) { @@ -131,7 +131,7 @@ out: void dn_start_fast_timer(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); if (!scp->delack_pending) { scp->delack_pending = 1; @@ -145,7 +145,7 @@ void dn_start_fast_timer(struct sock *sk) void dn_stop_fast_timer(struct sock *sk) { - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); if (scp->delack_pending) { scp->delack_pending = 0; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 1d8002bdd..81fae9233 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -504,8 +504,8 @@ void ip_mc_inc_group(struct in_device *in_dev, u32 addr) im->timer.function=&igmp_timer_expire; im->unsolicit_count = IGMP_Unsolicited_Report_Count; im->reporter = 0; - im->loaded = 0; #endif + im->loaded = 0; write_lock_bh(&in_dev->lock); im->next=in_dev->mc_list; in_dev->mc_list=im; diff --git a/net/ipv4/netfilter/Config.in b/net/ipv4/netfilter/Config.in index 406d2ea3d..5887658fb 100644 --- a/net/ipv4/netfilter/Config.in +++ b/net/ipv4/netfilter/Config.in @@ -37,11 +37,20 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then fi if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then - dep_tristate ' Full NAT' CONFIG_IP_NF_NAT $CONFIG_IP_NF_IPTABLES + dep_tristate ' Full NAT' CONFIG_IP_NF_NAT $CONFIG_IP_NF_IPTABLES $CONFIG_IP_NF_CONNTRACK if [ "$CONFIG_IP_NF_NAT" != "n" ]; then define_bool CONFIG_IP_NF_NAT_NEEDED y dep_tristate ' MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE $CONFIG_IP_NF_NAT dep_tristate ' REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT $CONFIG_IP_NF_NAT + # If they want FTP, set to $CONFIG_IP_NF_NAT (m or y), + # or $CONFIG_IP_NF_FTP (m or y), whichever is weaker. Argh. + if [ "$CONFIG_IP_NF_FTP" = "m" ]; then + define_tristate CONFIG_IP_NF_NAT_FTP m + else + if [ "$CONFIG_IP_NF_FTP" = "y" ]; then + define_tristate CONFIG_IP_NF_NAT_FTP $CONFIG_IP_NF_NAT + fi + fi fi fi diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 995860767..c40caa75e 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -35,7 +35,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o # NAT helpers -obj-$(CONFIG_IP_NF_FTP) += ip_nat_ftp.o +obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o # generic IP tables obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 2e4dd82ee..bc7e64c8b 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -882,10 +882,15 @@ ip_ct_gather_frags(struct sk_buff *skb) #ifdef CONFIG_NETFILTER_DEBUG unsigned int olddebug = skb->nf_debug; #endif - if (sk) sock_hold(sk); + if (sk) { + sock_hold(sk); + skb_orphan(skb); + } + local_bh_disable(); skb = ip_defrag(skb); - local_bh_enable(); + local_bh_enable(); + if (!skb) { if (sk) sock_put(sk); return skb; diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 9ba62dc84..cc19e1f0b 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -438,8 +438,27 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple, conntrack)); ret = 1; goto clear_fulls; + } else if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) { + /* Try implicit source NAT; protocol + may be able to play with ports to + make it unique. */ + struct ip_nat_range r + = { IP_NAT_RANGE_MAP_IPS, + tuple->src.ip, tuple->src.ip, + { 0 }, { 0 } }; + DEBUGP("Trying implicit mapping\n"); + if (proto->unique_tuple(tuple, &r, + IP_NAT_MANIP_SRC, + conntrack)) { + /* Must be unique. */ + IP_NF_ASSERT(!ip_nat_used_tuple + (tuple, conntrack)); + ret = 1; + goto clear_fulls; + } } - DEBUGP("Protocol can't get unique tuple.\n"); + DEBUGP("Protocol can't get unique tuple %u.\n", + hooknum); } /* Eliminate that from range, and try again. */ diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 99164a7a0..f2a19702d 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -1,5 +1,6 @@ /* Masquerade. Simple mapping which alters range to a local IP address (depending on route). */ +#include <linux/config.h> #include <linux/types.h> #include <linux/ip.h> #include <linux/timer.h> @@ -68,6 +69,7 @@ masquerade_target(struct sk_buff **pskb, struct ip_nat_multi_range newrange; u_int32_t newsrc; struct rtable *rt; + struct rt_key key; IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING); @@ -82,10 +84,14 @@ masquerade_target(struct sk_buff **pskb, mr = targinfo; - if (ip_route_output(&rt, (*pskb)->nh.iph->daddr, - 0, - RT_TOS((*pskb)->nh.iph->tos)|RTO_CONN, - out->ifindex) != 0) { + key.dst = (*pskb)->nh.iph->daddr; + key.src = 0; /* Unknown: that's what we're trying to establish */ + key.tos = RT_TOS((*pskb)->nh.iph->tos)|RTO_CONN; + key.oif = out->ifindex; +#ifdef CONFIG_IP_ROUTE_FWMARK + key.fwmark = (*pskb)->nfmark; +#endif + if (ip_route_output_key(&rt, &key) != 0) { /* Shouldn't happen */ printk("MASQUERADE: No route: Rusty's brain broke!\n"); return NF_DROP; diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 9c1088e76..cc5ffbc4a 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -167,27 +167,9 @@ static unsigned int reject(struct sk_buff **pskb, case IPT_ICMP_HOST_PROHIBITED: icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0); break; - case IPT_ICMP_ECHOREPLY: { - struct icmphdr *icmph = (struct icmphdr *) - ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl); - unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4; - - /* Not non-head frags, or truncated */ - if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0) - && datalen >= 4) { - /* Usually I don't like cut & pasting code, - but dammit, my party is starting in 45 - mins! --RR */ - struct icmp_bxm icmp_param; - - icmp_param.icmph=*icmph; - icmp_param.icmph.type=ICMP_ECHOREPLY; - icmp_param.data_ptr=(icmph+1); - icmp_param.data_len=datalen; - icmp_reply(&icmp_param, *pskb); - } - } - break; + case IPT_ICMP_ECHOREPLY: + printk("REJECT: ECHOREPLY no longer supported.\n"); + break; case IPT_TCP_RESET: send_reset(*pskb, hooknum == NF_IP_LOCAL_IN); break; diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index c52ada64e..60d4698fb 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -53,7 +53,7 @@ static struct sizeof(struct ipt_entry), sizeof(struct ipt_standard), 0, { 0, 0 }, { } }, - { { { { sizeof(struct ipt_standard_target), "" } }, { } }, + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, -NF_ACCEPT - 1 } }, /* LOCAL_OUT */ { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, @@ -61,7 +61,7 @@ static struct sizeof(struct ipt_entry), sizeof(struct ipt_standard), 0, { 0, 0 }, { } }, - { { { { sizeof(struct ipt_standard_target), "" } }, { } }, + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, -NF_ACCEPT - 1 } } }, /* ERROR */ @@ -70,7 +70,7 @@ static struct sizeof(struct ipt_entry), sizeof(struct ipt_error), 0, { 0, 0 }, { } }, - { { { { sizeof(struct ipt_error_target), IPT_ERROR_TARGET } }, + { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, { } }, "ERROR" } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index b370fcdf9..6660e0f72 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -954,7 +954,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size) */ skb = sk->write_queue.prev; if (tp->send_head && - (mss_now - skb->len) > 0) { + (mss_now > skb->len)) { copy = skb->len; if (skb_tailroom(skb) > 0) { int last_byte_was_odd = (copy % 4); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 4e3eab087..a3f83272b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1705,7 +1705,7 @@ static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp) if ((__s32)when < (__s32)tp->rttvar) when = tp->rttvar; - tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, when); + tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, min(when, TCP_RTO_MAX)); } } diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index aec5db879..fcc9bc058 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o +obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o include $(TOPDIR)/Rules.make diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 57430f29f..659bb3a1e 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -11,7 +11,7 @@ #include <linux/module.h> #include <linux/tcp.h> #include <linux/udp.h> -#include <linux/icmp.h> +#include <linux/icmpv6.h> #include <net/ip.h> #include <asm/uaccess.h> #include <asm/semaphore.h> @@ -1642,7 +1642,7 @@ udp_checkentry(const char *tablename, /* Returns 1 if the type and code is matched by the range, 0 otherwise */ static inline int -icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, +icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, u_int8_t type, u_int8_t code, int invert) { @@ -1651,7 +1651,7 @@ icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, } static int -icmp_match(const struct sk_buff *skb, +icmp6_match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, @@ -1660,7 +1660,7 @@ icmp_match(const struct sk_buff *skb, u_int16_t datalen, int *hotdrop) { - const struct icmphdr *icmp = hdr; + const struct icmp6hdr *icmp = hdr; const struct ip6t_icmp *icmpinfo = matchinfo; if (offset == 0 && datalen < 2) { @@ -1673,16 +1673,16 @@ icmp_match(const struct sk_buff *skb, /* Must not be a fragment. */ return !offset - && icmp_type_code_match(icmpinfo->type, + && icmp6_type_code_match(icmpinfo->type, icmpinfo->code[0], icmpinfo->code[1], - icmp->type, icmp->code, + icmp->icmp6_type, icmp->icmp6_code, !!(icmpinfo->invflags&IP6T_ICMP_INV)); } /* Called when user tries to insert an entry of this type. */ static int -icmp_checkentry(const char *tablename, +icmp6_checkentry(const char *tablename, const struct ip6t_ip6 *ipv6, void *matchinfo, unsigned int matchsize, @@ -1691,7 +1691,7 @@ icmp_checkentry(const char *tablename, const struct ip6t_icmp *icmpinfo = matchinfo; /* Must specify proto == ICMP, and no unknown invflags */ - return ipv6->proto == IPPROTO_ICMP + return ipv6->proto == IPPROTO_ICMPV6 && !(ipv6->invflags & IP6T_INV_PROTO) && matchsize == IP6T_ALIGN(sizeof(struct ip6t_icmp)) && !(icmpinfo->invflags & ~IP6T_ICMP_INV); @@ -1711,8 +1711,8 @@ static struct ip6t_match tcp_matchstruct = { { NULL, NULL }, "tcp", &tcp_match, &tcp_checkentry, NULL }; static struct ip6t_match udp_matchstruct = { { NULL, NULL }, "udp", &udp_match, &udp_checkentry, NULL }; -static struct ip6t_match icmp_matchstruct -= { { NULL, NULL }, "icmp", &icmp_match, &icmp_checkentry, NULL }; +static struct ip6t_match icmp6_matchstruct += { { NULL, NULL }, "icmp6", &icmp6_match, &icmp6_checkentry, NULL }; #ifdef CONFIG_PROC_FS static inline int print_name(const struct ip6t_table *t, @@ -1761,7 +1761,7 @@ static int __init init(void) list_append(&ip6t_target, &ip6t_error_target); list_append(&ip6t_match, &tcp_matchstruct); list_append(&ip6t_match, &udp_matchstruct); - list_append(&ip6t_match, &icmp_matchstruct); + list_append(&ip6t_match, &icmp6_matchstruct); up(&ip6t_mutex); /* Register setsockopt */ diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c index dd8bb3226..08df336e8 100644 --- a/net/ipv6/netfilter/ip6t_MARK.c +++ b/net/ipv6/netfilter/ip6t_MARK.c @@ -4,8 +4,8 @@ #include <linux/ip.h> #include <net/checksum.h> -#include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ipt_MARK.h> +#include <linux/netfilter_ipv6/ip6_tables.h> +#include <linux/netfilter_ipv6/ip6t_MARK.h> static unsigned int target(struct sk_buff **pskb, @@ -15,26 +15,26 @@ target(struct sk_buff **pskb, const void *targinfo, void *userinfo) { - const struct ipt_mark_target_info *markinfo = targinfo; + const struct ip6t_mark_target_info *markinfo = targinfo; if((*pskb)->nfmark != markinfo->mark) { (*pskb)->nfmark = markinfo->mark; (*pskb)->nfcache |= NFC_ALTERED; } - return IPT_CONTINUE; + return IP6T_CONTINUE; } static int checkentry(const char *tablename, - const struct ipt_entry *e, + const struct ip6t_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))) { printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", targinfosize, - IPT_ALIGN(sizeof(struct ipt_mark_target_info))); + IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))); return 0; } @@ -46,12 +46,13 @@ checkentry(const char *tablename, return 1; } -static struct ipt_target ipt_mark_reg +static struct ip6t_target ip6t_mark_reg = { { NULL, NULL }, "MARK", target, checkentry, NULL, THIS_MODULE }; static int __init init(void) { - if (ipt_register_target(&ipt_mark_reg)) + printk(KERN_DEBUG "registreing ipv6 mark target\n"); + if (ip6t_register_target(&ip6t_mark_reg)) return -EINVAL; return 0; @@ -59,7 +60,7 @@ static int __init init(void) static void __exit fini(void) { - ipt_unregister_target(&ipt_mark_reg); + ip6t_unregister_target(&ip6t_mark_reg); } module_init(init); diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c index babe202a4..9a78b1ca2 100644 --- a/net/ipv6/netfilter/ip6t_mark.c +++ b/net/ipv6/netfilter/ip6t_mark.c @@ -2,7 +2,7 @@ #include <linux/module.h> #include <linux/skbuff.h> -#include <linux/netfilter_ipv4/ipt_mark.h> +#include <linux/netfilter_ipv6/ip6t_mark.h> #include <linux/netfilter_ipv6/ip6_tables.h> static int @@ -15,7 +15,7 @@ match(const struct sk_buff *skb, u_int16_t datalen, int *hotdrop) { - const struct ipt_mark_info *info = matchinfo; + const struct ip6t_mark_info *info = matchinfo; return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; } @@ -27,7 +27,7 @@ checkentry(const char *tablename, unsigned int matchsize, unsigned int hook_mask) { - if (matchsize != IP6T_ALIGN(sizeof(struct ipt_mark_info))) + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info))) return 0; return 1; diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c new file mode 100644 index 000000000..612c292c4 --- /dev/null +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -0,0 +1,189 @@ +/* + * IPv6 packet mangling table, a port of the IPv4 mangle table to IPv6 + * + * Copyright (C) 2000 by Harald Welte <laforge@gnumonks.org> + */ +#include <linux/module.h> +#include <linux/netfilter_ipv6/ip6_tables.h> + +#define MANGLE_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT)) + +#if 1 +#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args) +#else +#define DEBUGP(x, args...) +#endif + +/* Standard entry. */ +struct ip6t_standard +{ + struct ip6t_entry entry; + struct ip6t_standard_target target; +}; + +struct ip6t_error_target +{ + struct ip6t_entry_target target; + char errorname[IP6T_FUNCTION_MAXNAMELEN]; +}; + +struct ip6t_error +{ + struct ip6t_entry entry; + struct ip6t_error_target target; +}; + +static struct +{ + struct ip6t_replace repl; + struct ip6t_standard entries[2]; + struct ip6t_error term; +} initial_table __initdata += { { "mangle", MANGLE_VALID_HOOKS, 3, + sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error), + { [NF_IP6_PRE_ROUTING] 0, + [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) }, + { [NF_IP6_PRE_ROUTING] 0, + [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) }, + 0, NULL, { } }, + { + /* PRE_ROUTING */ + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, + 0, + sizeof(struct ip6t_entry), + sizeof(struct ip6t_standard), + 0, { 0, 0 }, { } }, + { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, + -NF_ACCEPT - 1 } }, + /* LOCAL_OUT */ + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, + 0, + sizeof(struct ip6t_entry), + sizeof(struct ip6t_standard), + 0, { 0, 0 }, { } }, + { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, + -NF_ACCEPT - 1 } } + }, + /* ERROR */ + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, + 0, + sizeof(struct ip6t_entry), + sizeof(struct ip6t_error), + 0, { 0, 0 }, { } }, + { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } }, + { } }, + "ERROR" + } + } +}; + +static struct ip6t_table packet_mangler += { { NULL, NULL }, "mangle", &initial_table.repl, + MANGLE_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL }; + +/* The work comes in here from netfilter.c. */ +static unsigned int +ip6t_hook(unsigned int hook, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + return ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL); +} + +static unsigned int +ip6t_local_out_hook(unsigned int hook, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + + unsigned long nfmark; + unsigned int ret; + struct in6_addr saddr, daddr; + u_int8_t hop_limit; + u_int32_t flowlabel; + +#if 0 + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) + || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { + if (net_ratelimit()) + printk("ip6t_hook: happy cracking.\n"); + return NF_ACCEPT; + } +#endif + + /* save source/dest address, nfmark, hoplimit, flowlabel, priority, */ + memcpy(&saddr, &(*pskb)->nh.ipv6h->saddr, sizeof(saddr)); + memcpy(&daddr, &(*pskb)->nh.ipv6h->daddr, sizeof(daddr)); + nfmark = (*pskb)->nfmark; + hop_limit = (*pskb)->nh.ipv6h->hop_limit; + + /* flowlabel and prio (includes version, which shouldn't change either */ + flowlabel = (u_int32_t) (*pskb)->nh.ipv6h; + + ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL); + + if (ret != NF_DROP && ret != NF_STOLEN + && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr)) + || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr)) + || (*pskb)->nfmark != nfmark + || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) { + + /* something which could affect routing has changed */ + + DEBUGP("ip6table_mangle: we'd need to re-route a packet\n"); + } + + return ret; +} + +static struct nf_hook_ops ip6t_ops[] += { { { NULL, NULL }, ip6t_hook, PF_INET6, NF_IP6_PRE_ROUTING, NF_IP6_PRI_MANGLE }, + { { NULL, NULL }, ip6t_local_out_hook, PF_INET6, NF_IP6_LOCAL_OUT, + NF_IP6_PRI_MANGLE } +}; + +static int __init init(void) +{ + int ret; + + /* Register table */ + ret = ip6t_register_table(&packet_mangler); + if (ret < 0) + return ret; + + /* Register hooks */ + ret = nf_register_hook(&ip6t_ops[0]); + if (ret < 0) + goto cleanup_table; + + ret = nf_register_hook(&ip6t_ops[1]); + if (ret < 0) + goto cleanup_hook0; + + return ret; + + cleanup_hook0: + nf_unregister_hook(&ip6t_ops[0]); + cleanup_table: + ip6t_unregister_table(&packet_mangler); + + return ret; +} + +static void __exit fini(void) +{ + unsigned int i; + + for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++) + nf_unregister_hook(&ip6t_ops[i]); + + ip6t_unregister_table(&packet_mangler); +} + +module_init(init); +module_exit(fini); diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 26cc63348..fb73651bf 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -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 @@ static ipx_interface *ipx_internal_net; 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 @@ static int ipxcfg_get_config_data(ipx_config_data *arg) 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 @@ void ipx_remove_socket(struct sock *sk) /* 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 ipx_route * ipxrtr_lookup(__u32); 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 void ipxitf_clear_primary_net(void) 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_phys(struct net_device *dev, 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 @@ static ipx_interface *ipxitf_find_using_net(__u32 net) 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 @@ static void ipxitf_insert_socket(ipx_interface *intrfc, struct sock *sk) 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 @@ static void ipxitf_insert_socket(ipx_interface *intrfc, struct sock *sk) } /* 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 @@ static struct sock *ipxitf_find_socket(ipx_interface *intrfc, unsigned short por 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 @@ static struct sock *ipxitf_find_internal_socket(ipx_interface *intrfc, 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 @@ static void __ipxitf_down(ipx_interface *intrfc) 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 @@ static void __ipxitf_down(ipx_interface *intrfc) 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 @@ static void ipxitf_down(ipx_interface *intrfc) 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 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c 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 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c * VERY fast as well. */ int connection = 0; - - 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. - */ + u8 *ncphdr = (u8 *)(ipx + 1); + + 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 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c * 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 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c /* * 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 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c * 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 @@ out: if (sock1) } #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 @@ static struct sk_buff *ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buf 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 struct sk_buff *ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buf 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 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node) * 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 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node) * 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 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node) * 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 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node) /* 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 const char * ipx_device_name(ipx_interface *); 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 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb) 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 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb) } /* 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 @@ static void ipxitf_insert(ipx_interface *intrfc) 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 @@ static int ipxitf_create_internal(ipx_interface_definition *idef) 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 @@ static int ipxitf_create_internal(ipx_interface_definition *idef) 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 ipxitf_create_internal(ipx_interface_definition *idef) 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 @@ static int ipxitf_create(ipx_interface_definition *idef) 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 @@ static int ipxitf_create(ipx_interface_definition *idef) 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 @@ static int ipxitf_create(ipx_interface_definition *idef) } 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 @@ static int ipxitf_create(ipx_interface_definition *idef) 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 @@ static int ipxitf_create(ipx_interface_definition *idef) /* 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 @@ static int ipxitf_delete(ipx_interface_definition *idef) 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 @@ static int ipxitf_delete(ipx_interface_definition *idef) } 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 @@ out: spin_unlock_bh(&ipx_interfaces_lock); } 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 @@ static ipx_interface *ipxitf_auto_create(struct net_device *dev, 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 @@ static ipx_interface *ipxitf_auto_create(struct net_device *dev, 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 @@ static int ipxitf_ioctl(unsigned int cmd, void *arg) 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 @@ static int ipxitf_ioctl(unsigned int cmd, void *arg) 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 @@ static ipx_route *ipxrtr_lookup(__u32 net) 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 @@ static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc, unsigned char /* 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 @@ static void ipxrtr_del_routes(ipx_interface *intrfc) 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 @@ static int ipxrtr_create(ipx_route_definition *rd) /* 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 @@ static int ipxrtr_delete(long net) 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 @@ out: write_unlock_bh(&ipx_routes_lock); */ /* 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 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, stru 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 @@ out: ipxitf_put(intrfc); 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 @@ static int ipxrtr_ioctl(unsigned int cmd, void *arg) 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 @@ static int ipxrtr_ioctl(unsigned int cmd, void *arg) 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 @@ static int ipx_interface_get_info(char *buffer, char **start, off_t offset, #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 @@ static int ipx_interface_get_info(char *buffer, char **start, off_t offset, /* 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 @@ static int ipx_interface_get_info(char *buffer, char **start, off_t offset, /* 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 @@ static int ipx_get_info(char *buffer, char **start, off_t offset, int length) "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 @@ static int ipx_get_info(char *buffer, char **start, off_t offset, int length) 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 @@ static int ipx_get_info(char *buffer, char **start, off_t offset, int length) 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 @@ static int ipx_get_info(char *buffer, char **start, off_t offset, int length) /* 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 @@ static int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length) 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_rt_get_info(char *buffer, char **start, off_t offset, int length) * * \**************************************************************************/ -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 @@ static int ipx_create(struct socket *sock, int protocol) * 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 @@ static int ipx_create(struct socket *sock, int protocol) 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 @@ static unsigned short ipx_first_free_socketnum(ipx_interface *intrfc) 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 == 0) - return (-EINVAL); + if (!sk->zapped) + 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 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) 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 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) 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 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, 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 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, 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 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, 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 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, 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 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, 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 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, } 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 @@ int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) /* 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 @@ static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len, 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 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, 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 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, 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 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, 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 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg) 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 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg) * 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 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg) 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 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg) 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 @@ static struct packet_type ipx_8023_packet_type = __constant_htons(ETH_P_802_3), NULL, /* All devices */ ipx_rcv, - NULL, + (void *) 1, /* yap, I understand shared skbs :-) */ NULL, }; @@ -2585,7 +2449,7 @@ static struct packet_type ipx_dix_packet_type = __constant_htons(ETH_P_IPX), NULL, /* All devices */ ipx_rcv, - NULL, + (void *) 1, /* yap, I understand shared skbs :-) */ NULL, }; @@ -2604,12 +2468,9 @@ extern void destroy_8023_client(struct datalink_proto *); 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 @@ static int __init ipx_init(void) 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 @@ static void ipx_proto_finito(void) 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 */ diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index e5504ee96..250b22ae9 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -2409,6 +2409,7 @@ int __init irda_proto_init(void) #endif return 0; } +module_init(irda_proto_init); /* * Function irda_proto_cleanup (void) @@ -2429,11 +2430,9 @@ void irda_proto_cleanup(void) return; } -module_init(irda_proto_init); module_exit(irda_proto_cleanup); MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); MODULE_PARM(irda_debug, "1l"); #endif /* MODULE */ - diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 550519e0b..43ed8e26b 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -252,7 +252,7 @@ static u32 gen_new_htid(struct tc_u_common *tp_c) do { if (++tp_c->hgenerator == 0x7FF) tp_c->hgenerator = 1; - } while (i>0 && u32_lookup_ht(tp_c, (tp_c->hgenerator|0x800)<<20)); + } while (--i>0 && u32_lookup_ht(tp_c, (tp_c->hgenerator|0x800)<<20)); return i > 0 ? (tp_c->hgenerator|0x800)<<20 : 0; } diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 76f2fc394..a66fd2b45 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -39,16 +39,22 @@ * x:y y>0 y+1 use entry [y] * ... ... ... * x:indices-1 indices use entry [indices-1] + * ... ... ... + * x:y y+1 use entry [y & (indices-1)] + * ... ... ... + * 0xffff 0x10000 use entry [indices-1] */ +#define NO_DEFAULT_INDEX (1 << 16) + struct dsmark_qdisc_data { struct Qdisc *q; struct tcf_proto *filter_list; __u8 *mask; /* "owns" the array */ __u8 *value; __u16 indices; - __u16 default_index; + __u32 default_index; /* index range is 0...0xffff */ int set_tc_index; }; @@ -217,7 +223,7 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) case TC_POLICE_UNSPEC: /* fall through */ default: - if (p->default_index) + if (p->default_index != NO_DEFAULT_INDEX) skb->tc_index = p->default_index; break; }; @@ -325,14 +331,12 @@ int dsmark_init(struct Qdisc *sch,struct rtattr *opt) if (tmp & 1) return -EINVAL; } - p->default_index = 0; + p->default_index = NO_DEFAULT_INDEX; if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) { if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX-1]) < sizeof(__u16)) return -EINVAL; p->default_index = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]); - if (!p->default_index || p->default_index >= p->indices) - return -EINVAL; } p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1]; p->mask = kmalloc(p->indices*2,GFP_KERNEL); @@ -411,9 +415,11 @@ static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb) rta = (struct rtattr *) b; RTA_PUT(skb,TCA_OPTIONS,0,NULL); RTA_PUT(skb,TCA_DSMARK_INDICES,sizeof(__u16),&p->indices); - if (p->default_index) - RTA_PUT(skb,TCA_DSMARK_DEFAULT_INDEX, sizeof(__u16), - &p->default_index); + if (p->default_index != NO_DEFAULT_INDEX) { + __u16 tmp = p->default_index; + + RTA_PUT(skb,TCA_DSMARK_DEFAULT_INDEX, sizeof(__u16), &tmp); + } if (p->set_tc_index) RTA_PUT(skb, TCA_DSMARK_SET_TC_INDEX, 0, NULL); rta->rta_len = skb->tail-b; diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 4983e898e..3a48c3ebf 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -110,12 +110,9 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) unsigned long qave=0; int i=0; - if (!t->initd) { - DPRINTK("NO GRED Queues setup yet! Enqueued anyway\n"); - if (q->backlog <= q->limit) { - __skb_queue_tail(&sch->q, skb); - return NET_XMIT_DROP; /* @@@@ */ - } + if (!t->initd && skb_queue_len(&sch->q) <= sch->dev->tx_queue_len) { + D2PRINTK("NO GRED Queues setup yet! Enqueued anyway\n"); + goto do_enqueue; } @@ -179,11 +176,12 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) q->qcount = -1; enqueue: if (q->backlog <= q->limit) { + q->backlog += skb->len; +do_enqueue: __skb_queue_tail(&sch->q, skb); sch->stats.backlog += skb->len; sch->stats.bytes += skb->len; sch->stats.packets++; - q->backlog += skb->len; return 0; } else { q->pdrop++; diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index a295ecaf7..a6af993c8 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -267,22 +267,26 @@ rpcauth_holdcred(struct rpc_task *task) dprintk("RPC: %4d holding %s cred %p\n", task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred); if (task->tk_msg.rpc_cred) { + spin_lock(&rpc_credcache_lock); task->tk_msg.rpc_cred->cr_count++; task->tk_msg.rpc_cred->cr_expire = jiffies + task->tk_auth->au_expire; + spin_unlock(&rpc_credcache_lock); } } void rpcauth_releasecred(struct rpc_auth *auth, struct rpc_cred *cred) { + spin_lock(&rpc_credcache_lock); if (cred != NULL && cred->cr_count > 0) { - cred->cr_count--; - if (cred->cr_flags & RPCAUTH_CRED_DEAD) { + if (!--cred->cr_count && (cred->cr_flags & RPCAUTH_CRED_DEAD)) { + spin_unlock(&rpc_credcache_lock); rpcauth_remove_credcache(auth, cred); - if (!cred->cr_count) - rpcauth_crdestroy(auth, cred); + rpcauth_crdestroy(auth, cred); + return; } } + spin_unlock(&rpc_credcache_lock); } void @@ -335,13 +339,19 @@ rpcauth_invalcred(struct rpc_task *task) { dprintk("RPC: %4d invalidating %s cred %p\n", task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred); + spin_lock(&rpc_credcache_lock); if (task->tk_msg.rpc_cred) task->tk_msg.rpc_cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; + spin_unlock(&rpc_credcache_lock); } int rpcauth_uptodatecred(struct rpc_task *task) { - return !(task->tk_msg.rpc_cred) || + int retval; + spin_lock(&rpc_credcache_lock); + retval = !(task->tk_msg.rpc_cred) || (task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE); + spin_unlock(&rpc_credcache_lock); + return retval; } diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index e53759e3e..1c5fd3740 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -36,6 +36,7 @@ EXPORT_SYMBOL(rpciod_down); EXPORT_SYMBOL(rpciod_up); EXPORT_SYMBOL(rpc_new_task); EXPORT_SYMBOL(rpc_wake_up_status); +EXPORT_SYMBOL(rpc_release_task); /* RPC client functions */ EXPORT_SYMBOL(rpc_create_client); diff --git a/net/sysctl_net.c b/net/sysctl_net.c index bda8d54d8..61f948390 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c @@ -26,10 +26,6 @@ extern ctl_table ipx_table[]; extern ctl_table core_table[]; -#ifdef CONFIG_UNIX -extern ctl_table unix_table[]; -#endif - #ifdef CONFIG_NET extern ctl_table ether_table[], e802_table[]; #endif @@ -48,9 +44,6 @@ extern ctl_table econet_table[]; ctl_table net_table[] = { {NET_CORE, "core", NULL, 0, 0555, core_table}, -#ifdef CONFIG_UNIX - {NET_UNIX, "unix", NULL, 0, 0555, unix_table}, -#endif #ifdef CONFIG_NET {NET_802, "802", NULL, 0, 0555, e802_table}, {NET_ETHER, "ethernet", NULL, 0, 0555, ether_table}, diff --git a/net/unix/Makefile b/net/unix/Makefile index 88a262671..9a840afde 100644 --- a/net/unix/Makefile +++ b/net/unix/Makefile @@ -16,5 +16,3 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_unix.o include $(TOPDIR)/Rules.make -tar: - tar -cvf /dev/f1 . diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index e48b8549a..121e4d9de 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1,5 +1,5 @@ /* - * NET3: Implementation of BSD Unix domain sockets. + * NET4: Implementation of BSD Unix domain sockets. * * Authors: Alan Cox, <alan.cox@linux.org> * @@ -8,7 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version: $Id: af_unix.c,v 1.108 2000/11/10 04:02:04 davem Exp $ + * Version: $Id: af_unix.c,v 1.109 2001/01/06 00:42:23 davem Exp $ * * Fixes: * Linus Torvalds : Assorted bug cures. @@ -124,13 +124,12 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0); #define UNIX_ABSTRACT(sk) ((sk)->protinfo.af_unix.addr->hash!=UNIX_HASH_SIZE) /* - SMP locking strategy. - * hash table is protceted with rwlock unix_table_lock - * each socket state is protected by separate rwlock. - + * SMP locking strategy: + * hash table is protected with rwlock unix_table_lock + * each socket state is protected by separate rwlock. */ -extern __inline__ unsigned unix_hash_fold(unsigned hash) +static inline unsigned unix_hash_fold(unsigned hash) { hash ^= hash>>16; hash ^= hash>>8; @@ -139,17 +138,17 @@ extern __inline__ unsigned unix_hash_fold(unsigned hash) #define unix_peer(sk) ((sk)->pair) -extern __inline__ int unix_our_peer(unix_socket *sk, unix_socket *osk) +static inline int unix_our_peer(unix_socket *sk, unix_socket *osk) { return unix_peer(osk) == sk; } -extern __inline__ int unix_may_send(unix_socket *sk, unix_socket *osk) +static inline int unix_may_send(unix_socket *sk, unix_socket *osk) { return (unix_peer(osk) == NULL || unix_our_peer(sk, osk)); } -static __inline__ unix_socket * unix_peer_get(unix_socket *s) +static inline unix_socket * unix_peer_get(unix_socket *s) { unix_socket *peer; @@ -161,7 +160,7 @@ static __inline__ unix_socket * unix_peer_get(unix_socket *s) return peer; } -extern __inline__ void unix_release_addr(struct unix_address *addr) +extern inline void unix_release_addr(struct unix_address *addr) { if (atomic_dec_and_test(&addr->refcnt)) kfree(addr); @@ -231,14 +230,14 @@ static void __unix_insert_socket(unix_socket **list, unix_socket *sk) sock_hold(sk); } -static __inline__ void unix_remove_socket(unix_socket *sk) +static inline void unix_remove_socket(unix_socket *sk) { write_lock(&unix_table_lock); __unix_remove_socket(sk); write_unlock(&unix_table_lock); } -static __inline__ void unix_insert_socket(unix_socket **list, unix_socket *sk) +static inline void unix_insert_socket(unix_socket **list, unix_socket *sk) { write_lock(&unix_table_lock); __unix_insert_socket(list, sk); @@ -258,7 +257,7 @@ static unix_socket *__unix_find_socket_byname(struct sockaddr_un *sunname, return NULL; } -static __inline__ unix_socket * +static inline unix_socket * unix_find_socket_byname(struct sockaddr_un *sunname, int len, int type, unsigned hash) { @@ -291,7 +290,7 @@ static unix_socket *unix_find_socket_byinode(struct inode *i) return s; } -static __inline__ int unix_writable(struct sock *sk) +static inline int unix_writable(struct sock *sk) { return ((atomic_read(&sk->wmem_alloc)<<2) <= sk->sndbuf); } @@ -1823,7 +1822,7 @@ struct proto_ops unix_stream_ops = { struct proto_ops unix_dgram_ops = { family: PF_UNIX, - + release: unix_release, bind: unix_bind, connect: unix_dgram_connect, @@ -1842,20 +1841,25 @@ struct proto_ops unix_dgram_ops = { }; struct net_proto_family unix_family_ops = { - PF_UNIX, - unix_create + family: PF_UNIX, + create: unix_create }; #ifdef CONFIG_SYSCTL extern void unix_sysctl_register(void); extern void unix_sysctl_unregister(void); +#else +static inline unix_sysctl_register() {}; +static inline unix_sysctl_unregister() {}; #endif +static const char banner[] __initdata = KERN_INFO "NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.\n"; + static int __init af_unix_init(void) { struct sk_buff *dummy_skb; - - printk(KERN_INFO "NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.\n"); + + printk(banner); if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "unix_proto_init: panic\n"); @@ -1865,23 +1869,15 @@ static int __init af_unix_init(void) #ifdef CONFIG_PROC_FS create_proc_read_entry("net/unix", 0, 0, unix_read_proc, NULL); #endif - -#ifdef CONFIG_SYSCTL unix_sysctl_register(); -#endif - return 0; } static void __exit af_unix_exit(void) { sock_unregister(PF_UNIX); -#ifdef CONFIG_SYSCTL unix_sysctl_unregister(); -#endif -#ifdef CONFIG_PROC_FS remove_proc_entry("net/unix", 0); -#endif } module_init(af_unix_init); diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c index 885119da3..eceea5c95 100644 --- a/net/unix/sysctl_net_unix.c +++ b/net/unix/sysctl_net_unix.c @@ -1,10 +1,8 @@ /* - * NET3: Sysctl interface to net af_unix subsystem. + * NET4: Sysctl interface to net af_unix subsystem. * * Authors: Mike Shaver. * - * Added /proc/sys/net/unix directory entry (empty =) ). - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version @@ -13,9 +11,6 @@ #include <linux/mm.h> #include <linux/sysctl.h> -#include <linux/config.h> - -#ifdef CONFIG_SYSCTL extern int sysctl_unix_max_dgram_qlen; @@ -26,20 +21,18 @@ ctl_table unix_table[] = { {0} }; -static struct ctl_table_header * unix_sysctl_header; -static struct ctl_table unix_root_table[]; -static struct ctl_table unix_net_table[]; - -ctl_table unix_root_table[] = { - {CTL_NET, "net", NULL, 0, 0555, unix_net_table}, +static ctl_table unix_net_table[] = { + {NET_UNIX, "unix", NULL, 0, 0555, unix_table}, {0} }; -ctl_table unix_net_table[] = { - {NET_UNIX, "unix", NULL, 0, 0555, unix_table}, +static ctl_table unix_root_table[] = { + {CTL_NET, "net", NULL, 0, 0555, unix_net_table}, {0} }; +static struct ctl_table_header * unix_sysctl_header; + void unix_sysctl_register(void) { unix_sysctl_header = register_sysctl_table(unix_root_table, 0); @@ -50,4 +43,3 @@ void unix_sysctl_unregister(void) unregister_sysctl_table(unix_sysctl_header); } -#endif /* CONFIG_SYSCTL */ diff --git a/net/x25/Makefile b/net/x25/Makefile index 0890eff84..d0082933f 100644 --- a/net/x25/Makefile +++ b/net/x25/Makefile @@ -17,5 +17,3 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_x25.o include $(TOPDIR)/Rules.make -tar: - tar -cvf /dev/f1 . diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index c8f8c3e97..a938f3bc1 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1084,6 +1084,9 @@ static int x25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int fl msg->msg_namelen = sizeof(struct sockaddr_x25); skb_free_datagram(sk, skb); + lock_sock(sk); + x25_check_rbuf(sk); + release_sock(sk); return copied; } @@ -1258,8 +1261,8 @@ static int x25_get_info(char *buffer, char **start, off_t offset, int length) } struct net_proto_family x25_family_ops = { - AF_X25, - x25_create + family: AF_X25, + create: x25_create, }; static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { @@ -1286,18 +1289,13 @@ static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { SOCKOPS_WRAP(x25_proto, AF_X25); -static struct packet_type x25_packet_type = -{ - 0, /* MUTTER ntohs(ETH_P_X25),*/ - 0, /* copy */ - x25_lapb_receive_frame, - NULL, - NULL, +static struct packet_type x25_packet_type = { + type: __constant_htons(ETH_P_X25), + func: x25_lapb_receive_frame, }; struct notifier_block x25_dev_notifier = { - x25_device_event, - 0 + notifier_call: x25_device_event, }; void x25_kill_by_neigh(struct x25_neigh *neigh) @@ -1317,7 +1315,6 @@ static int __init x25_init(void) #endif /* MODULE */ sock_register(&x25_family_ops); - x25_packet_type.type = htons(ETH_P_X25); dev_add_pack(&x25_packet_type); register_netdevice_notifier(&x25_dev_notifier); diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index fbc781dce..1abb28358 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c @@ -18,7 +18,6 @@ */ #include <linux/config.h> -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -249,8 +248,3 @@ void x25_send_frame(struct sk_buff *skb, struct x25_neigh *neigh) dev_queue_xmit(skb); } - -#endif - - - diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index ad41d1cde..adf757e56 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -18,8 +18,6 @@ * negotiation. */ -#include <linux/config.h> -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -232,7 +230,3 @@ void x25_limit_facilities(struct x25_facilities *facilities, } } } - -#endif - - diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index bcb5f1cf4..73a567e89 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c @@ -22,8 +22,6 @@ * i-frames. */ -#include <linux/config.h> -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -369,5 +367,3 @@ int x25_backlog_rcv(struct sock *sk, struct sk_buff *skb) return 0; } - -#endif diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index d6b878371..841499325 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c @@ -20,8 +20,6 @@ * 2000-09-04 Henner Eisen dev_hold() / dev_put() for x25_neigh. */ -#include <linux/config.h> -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -42,9 +40,10 @@ #include <linux/fcntl.h> #include <linux/mm.h> #include <linux/interrupt.h> +#include <linux/init.h> #include <net/x25.h> -static struct x25_neigh *x25_neigh_list = NULL; +static struct x25_neigh *x25_neigh_list /* = NULL initially */; static void x25_t20timer_expiry(unsigned long); @@ -422,12 +421,11 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg) return 0; } -#ifdef MODULE /* * Release all memory associated with X.25 neighbour structures. */ -void x25_link_free(void) +void __exit x25_link_free(void) { struct x25_neigh *neigh, *x25_neigh = x25_neigh_list; @@ -438,7 +436,3 @@ void x25_link_free(void) x25_remove_neigh(neigh); } } - -#endif - -#endif diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c index b3ce30477..2521078a6 100644 --- a/net/x25/x25_out.c +++ b/net/x25/x25_out.c @@ -21,8 +21,6 @@ * needed cleaned seq-number fields. */ -#include <linux/config.h> -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -229,5 +227,3 @@ void x25_enquiry_response(struct sock *sk) x25_stop_timer(sk); } - -#endif diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c index 4cb51300b..a4651699e 100644 --- a/net/x25/x25_route.c +++ b/net/x25/x25_route.c @@ -17,7 +17,6 @@ */ #include <linux/config.h> -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -42,9 +41,10 @@ #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/notifier.h> +#include <linux/init.h> #include <net/x25.h> -static struct x25_route *x25_route_list = NULL; +static struct x25_route *x25_route_list /* = NULL initially */; /* * Add a new route. @@ -255,12 +255,10 @@ int x25_routes_get_info(char *buffer, char **start, off_t offset, int length) return len; } -#ifdef MODULE - /* * Release all memory associated with X.25 routing structures. */ -void x25_route_free(void) +void __exit x25_route_free(void) { struct x25_route *route, *x25_route = x25_route_list; @@ -271,7 +269,3 @@ void x25_route_free(void) x25_remove_route(route); } } - -#endif - -#endif diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 25a700af9..635c872e5 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c @@ -19,8 +19,6 @@ * negotiation. */ -#include <linux/config.h> -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -351,4 +349,18 @@ void x25_disconnect(struct sock *sk, int reason, unsigned char cause, unsigned c sk->dead = 1; } -#endif +/* + * Clear an own-rx-busy condition and tell the peer about this, provided + * that there is a significant amount of free receive buffer space available. + */ +void x25_check_rbuf(struct sock *sk) +{ + if (atomic_read(&sk->rmem_alloc) < (sk->rcvbuf / 2) && + (sk->protinfo.x25->condition & X25_COND_OWN_RX_BUSY)) { + sk->protinfo.x25->condition &= ~X25_COND_OWN_RX_BUSY; + sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; + sk->protinfo.x25->vl = sk->protinfo.x25->vr; + x25_write_internal(sk, X25_RR); + x25_stop_timer(sk); + } +} diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c index 20672419e..cf9b42606 100644 --- a/net/x25/x25_timer.c +++ b/net/x25/x25_timer.c @@ -18,8 +18,6 @@ * Centralised disconnection processing. */ -#include <linux/config.h> -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -121,6 +119,11 @@ static void x25_heartbeat_expiry(unsigned long param) { struct sock *sk = (struct sock *)param; + bh_lock_sock(sk); + if (sk->lock.users) { /* can currently only occur in state 3 */ + goto restart_heartbeat; + } + switch (sk->protinfo.x25->state) { case X25_STATE_0: @@ -128,7 +131,7 @@ static void x25_heartbeat_expiry(unsigned long param) is accepted() it isn't 'dead' so doesn't get removed. */ if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) { x25_destroy_socket(sk); - return; + goto unlock; } break; @@ -136,29 +139,21 @@ static void x25_heartbeat_expiry(unsigned long param) /* * Check for the state of the receive buffer. */ - if (atomic_read(&sk->rmem_alloc) < (sk->rcvbuf / 2) && - (sk->protinfo.x25->condition & X25_COND_OWN_RX_BUSY)) { - sk->protinfo.x25->condition &= ~X25_COND_OWN_RX_BUSY; - sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; - sk->protinfo.x25->vl = sk->protinfo.x25->vr; - x25_write_internal(sk, X25_RR); - x25_stop_timer(sk); - break; - } + x25_check_rbuf(sk); break; } - + restart_heartbeat: x25_start_heartbeat(sk); + unlock: + bh_unlock_sock(sk); } /* * Timer has expired, it may have been T2, T21, T22, or T23. We can tell * by the state machine state. */ -static void x25_timer_expiry(unsigned long param) +static inline void x25_do_timer_expiry(struct sock * sk) { - struct sock *sk = (struct sock *)param; - switch (sk->protinfo.x25->state) { case X25_STATE_3: /* T2 */ @@ -181,4 +176,17 @@ static void x25_timer_expiry(unsigned long param) } } -#endif +static void x25_timer_expiry(unsigned long param) +{ + struct sock *sk = (struct sock *)param; + + bh_lock_sock(sk); + if (sk->lock.users) { /* can currently only occur in state 3 */ + if (sk->protinfo.x25->state == X25_STATE_3) { + x25_start_t2timer(sk); + } + } else { + x25_do_timer_expiry(sk); + } + bh_unlock_sock(sk); +} |