diff options
Diffstat (limited to 'net/appletalk/aarp.c')
| -rw-r--r-- | net/appletalk/aarp.c | 164 |
1 files changed, 68 insertions, 96 deletions
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 690356fa52b9..4744e3fd4544 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * AARP: An implementation of the AppleTalk AARP protocol for * Ethernet 'ELAP'. @@ -13,12 +14,6 @@ * Use neighbour discovery code. * Token Ring Support. * - * 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 - * 2 of the License, or (at your option) any later version. - * - * * References: * Inside AppleTalk (2nd Ed). * Fixes: @@ -26,7 +21,6 @@ * Rob Newberry - Added proxy AARP and AARP proc fs, * moved probing from DDP module. * Arnaldo C. Melo - don't mangle rx packets - * */ #include <linux/if_arp.h> @@ -40,6 +34,8 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/export.h> +#include <linux/etherdevice.h> +#include <linux/refcount.h> int sysctl_aarp_expiry_time = AARP_EXPIRY_TIME; int sysctl_aarp_tick_time = AARP_TICK_TIME; @@ -49,17 +45,19 @@ int sysctl_aarp_resolve_time = AARP_RESOLVE_TIME; /* Lists of aarp entries */ /** * struct aarp_entry - AARP entry - * @last_sent - Last time we xmitted the aarp request - * @packet_queue - Queue of frames wait for resolution - * @status - Used for proxy AARP - * expires_at - Entry expiry time - * target_addr - DDP Address - * dev - Device to use - * hwaddr - Physical i/f address of target/router - * xmit_count - When this hits 10 we give up - * next - Next entry in chain + * @refcnt: Reference count + * @last_sent: Last time we xmitted the aarp request + * @packet_queue: Queue of frames wait for resolution + * @status: Used for proxy AARP + * @expires_at: Entry expiry time + * @target_addr: DDP Address + * @dev: Device to use + * @hwaddr: Physical i/f address of target/router + * @xmit_count: When this hits 10 we give up + * @next: Next entry in chain */ struct aarp_entry { + refcount_t refcnt; /* These first two are only used for unresolved entries */ unsigned long last_sent; struct sk_buff_head packet_queue; @@ -67,7 +65,7 @@ struct aarp_entry { unsigned long expires_at; struct atalk_addr target_addr; struct net_device *dev; - char hwaddr[6]; + char hwaddr[ETH_ALEN]; unsigned short xmit_count; struct aarp_entry *next; }; @@ -84,6 +82,17 @@ static DEFINE_RWLOCK(aarp_lock); /* Used to walk the list and purge/kick entries. */ static struct timer_list aarp_timer; +static inline void aarp_entry_get(struct aarp_entry *a) +{ + refcount_inc(&a->refcnt); +} + +static inline void aarp_entry_put(struct aarp_entry *a) +{ + if (refcount_dec_and_test(&a->refcnt)) + kfree(a); +} + /* * Delete an aarp queue * @@ -92,7 +101,7 @@ static struct timer_list aarp_timer; static void __aarp_expire(struct aarp_entry *a) { skb_queue_purge(&a->packet_queue); - kfree(a); + aarp_entry_put(a); } /* @@ -134,13 +143,13 @@ static void __aarp_send_query(struct aarp_entry *a) eah->pa_len = AARP_PA_ALEN; eah->function = htons(AARP_REQUEST); - memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); + ether_addr_copy(eah->hw_src, dev->dev_addr); eah->pa_src_zero = 0; eah->pa_src_net = sat->s_net; eah->pa_src_node = sat->s_node; - memset(eah->hw_dst, '\0', ETH_ALEN); + eth_zero_addr(eah->hw_dst); eah->pa_dst_zero = 0; eah->pa_dst_net = a->target_addr.s_net; @@ -181,16 +190,16 @@ static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us, eah->pa_len = AARP_PA_ALEN; eah->function = htons(AARP_REPLY); - memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); + ether_addr_copy(eah->hw_src, dev->dev_addr); eah->pa_src_zero = 0; eah->pa_src_net = us->s_net; eah->pa_src_node = us->s_node; if (!sha) - memset(eah->hw_dst, '\0', ETH_ALEN); + eth_zero_addr(eah->hw_dst); else - memcpy(eah->hw_dst, sha, ETH_ALEN); + ether_addr_copy(eah->hw_dst, sha); eah->pa_dst_zero = 0; eah->pa_dst_net = them->s_net; @@ -232,13 +241,13 @@ static void aarp_send_probe(struct net_device *dev, struct atalk_addr *us) eah->pa_len = AARP_PA_ALEN; eah->function = htons(AARP_PROBE); - memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); + ether_addr_copy(eah->hw_src, dev->dev_addr); eah->pa_src_zero = 0; eah->pa_src_net = us->s_net; eah->pa_src_node = us->s_node; - memset(eah->hw_dst, '\0', ETH_ALEN); + eth_zero_addr(eah->hw_dst); eah->pa_dst_zero = 0; eah->pa_dst_net = us->s_net; @@ -309,7 +318,7 @@ static void __aarp_expire_device(struct aarp_entry **n, struct net_device *dev) } /* Handle the timer event */ -static void aarp_expire_timeout(unsigned long unused) +static void aarp_expire_timeout(struct timer_list *unused) { int ct; @@ -385,9 +394,11 @@ static void aarp_purge(void) static struct aarp_entry *aarp_alloc(void) { struct aarp_entry *a = kmalloc(sizeof(*a), GFP_ATOMIC); + if (!a) + return NULL; - if (a) - skb_queue_head_init(&a->packet_queue); + refcount_set(&a->refcnt, 1); + skb_queue_head_init(&a->packet_queue); return a; } @@ -437,49 +448,18 @@ static struct atalk_addr *__aarp_proxy_find(struct net_device *dev, return a ? sa : NULL; } -/* - * Probe a Phase 1 device or a device that requires its Net:Node to - * be set via an ioctl. - */ -static void aarp_send_probe_phase1(struct atalk_iface *iface) -{ - struct ifreq atreq; - struct sockaddr_at *sa = (struct sockaddr_at *)&atreq.ifr_addr; - const struct net_device_ops *ops = iface->dev->netdev_ops; - - sa->sat_addr.s_node = iface->address.s_node; - sa->sat_addr.s_net = ntohs(iface->address.s_net); - - /* We pass the Net:Node to the drivers/cards by a Device ioctl. */ - if (!(ops->ndo_do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) { - ops->ndo_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) - iface->status |= ATIF_PROBE_FAIL; - - iface->address.s_net = htons(sa->sat_addr.s_net); - iface->address.s_node = sa->sat_addr.s_node; - } -} - - void aarp_probe_network(struct atalk_iface *atif) { - if (atif->dev->type == ARPHRD_LOCALTLK || - atif->dev->type == ARPHRD_PPP) - aarp_send_probe_phase1(atif); - else { - unsigned int count; + unsigned int count; - for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) { - aarp_send_probe(atif->dev, &atif->address); + for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) { + aarp_send_probe(atif->dev, &atif->address); - /* Defer 1/10th */ - msleep(100); + /* Defer 1/10th */ + msleep(100); - if (atif->status & ATIF_PROBE_FAIL) - break; - } + if (atif->status & ATIF_PROBE_FAIL) + break; } } @@ -513,6 +493,7 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa) entry->dev = atif->dev; write_lock_bh(&aarp_lock); + aarp_entry_get(entry); hash = sa->s_node % (AARP_HASH_SIZE - 1); entry->next = proxies[hash]; @@ -538,6 +519,7 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa) retval = 1; } + aarp_entry_put(entry); write_unlock_bh(&aarp_lock); out: return retval; @@ -669,7 +651,7 @@ out_unlock: sendit: if (skb->sk) - skb->priority = skb->sk->sk_priority; + skb->priority = READ_ONCE(skb->sk->sk_priority); if (dev_queue_xmit(skb)) goto drop; sent: @@ -773,7 +755,7 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, if (a && a->status & ATIF_PROBE) { a->status |= ATIF_PROBE_FAIL; /* - * we do not respond to probe or request packets for + * we do not respond to probe or request packets of * this address while we are probing this address */ goto unlock; @@ -790,7 +772,7 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, break; /* We can fill one in - this is good. */ - memcpy(a->hwaddr, ea->hw_src, ETH_ALEN); + ether_addr_copy(a->hwaddr, ea->hw_src); __aarp_resolved(&unresolved[hash], a, hash); if (!unresolved_count) mod_timer(&aarp_timer, @@ -878,15 +860,24 @@ static struct notifier_block aarp_notifier = { static unsigned char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; -void __init aarp_proto_init(void) +int __init aarp_proto_init(void) { + int rc; + aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv); - if (!aarp_dl) + if (!aarp_dl) { printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); - setup_timer(&aarp_timer, aarp_expire_timeout, 0); + return -ENOMEM; + } + timer_setup(&aarp_timer, aarp_expire_timeout, 0); aarp_timer.expires = jiffies + sysctl_aarp_expiry_time; add_timer(&aarp_timer); - register_netdevice_notifier(&aarp_notifier); + rc = register_netdevice_notifier(&aarp_notifier); + if (rc) { + timer_delete_sync(&aarp_timer); + unregister_snap_client(aarp_dl); + } + return rc; } /* Remove the AARP entries associated with a device. */ @@ -906,11 +897,6 @@ void aarp_device_down(struct net_device *dev) } #ifdef CONFIG_PROC_FS -struct aarp_iter_state { - int bucket; - struct aarp_entry **table; -}; - /* * Get the aarp entry that is in the chain described * by the iterator. @@ -925,7 +911,7 @@ static struct aarp_entry *iter_next(struct aarp_iter_state *iter, loff_t *pos) struct aarp_entry *entry; rescan: - while(ct < AARP_HASH_SIZE) { + while (ct < AARP_HASH_SIZE) { for (entry = table[ct]; entry; entry = entry->next) { if (!pos || ++off == *pos) { iter->table = table; @@ -994,7 +980,7 @@ static const char *dt2str(unsigned long ticks) { static char buf[32]; - sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100 ) / HZ); + sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100) / HZ); return buf; } @@ -1032,32 +1018,18 @@ static int aarp_seq_show(struct seq_file *seq, void *v) return 0; } -static const struct seq_operations aarp_seq_ops = { +const struct seq_operations aarp_seq_ops = { .start = aarp_seq_start, .next = aarp_seq_next, .stop = aarp_seq_stop, .show = aarp_seq_show, }; - -static int aarp_seq_open(struct inode *inode, struct file *file) -{ - return seq_open_private(file, &aarp_seq_ops, - sizeof(struct aarp_iter_state)); -} - -const struct file_operations atalk_seq_arp_fops = { - .owner = THIS_MODULE, - .open = aarp_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, -}; #endif /* General module cleanup. Called from cleanup_module() in ddp.c. */ void aarp_cleanup_module(void) { - del_timer_sync(&aarp_timer); + timer_delete_sync(&aarp_timer); unregister_netdevice_notifier(&aarp_notifier); unregister_snap_client(aarp_dl); aarp_purge(); |
