Contents of /alx-src/tags/kernel26-2.6.12-alx-r9/net/appletalk/aarp.c
Parent Directory | Revision Log
Revision 630 -
(show annotations)
(download)
Wed Mar 4 11:03:09 2009 UTC (15 years, 3 months ago) by niro
File MIME type: text/plain
File size: 25622 byte(s)
Wed Mar 4 11:03:09 2009 UTC (15 years, 3 months ago) by niro
File MIME type: text/plain
File size: 25622 byte(s)
Tag kernel26-2.6.12-alx-r9
1 | /* |
2 | * AARP: An implementation of the AppleTalk AARP protocol for |
3 | * Ethernet 'ELAP'. |
4 | * |
5 | * Alan Cox <Alan.Cox@linux.org> |
6 | * |
7 | * This doesn't fit cleanly with the IP arp. Potentially we can use |
8 | * the generic neighbour discovery code to clean this up. |
9 | * |
10 | * FIXME: |
11 | * We ought to handle the retransmits with a single list and a |
12 | * separate fast timer for when it is needed. |
13 | * Use neighbour discovery code. |
14 | * Token Ring Support. |
15 | * |
16 | * This program is free software; you can redistribute it and/or |
17 | * modify it under the terms of the GNU General Public License |
18 | * as published by the Free Software Foundation; either version |
19 | * 2 of the License, or (at your option) any later version. |
20 | * |
21 | * |
22 | * References: |
23 | * Inside AppleTalk (2nd Ed). |
24 | * Fixes: |
25 | * Jaume Grau - flush caches on AARP_PROBE |
26 | * Rob Newberry - Added proxy AARP and AARP proc fs, |
27 | * moved probing from DDP module. |
28 | * Arnaldo C. Melo - don't mangle rx packets |
29 | * |
30 | */ |
31 | |
32 | #include <linux/config.h> |
33 | #include <linux/if_arp.h> |
34 | #include <net/sock.h> |
35 | #include <net/datalink.h> |
36 | #include <net/psnap.h> |
37 | #include <linux/atalk.h> |
38 | #include <linux/init.h> |
39 | #include <linux/proc_fs.h> |
40 | #include <linux/seq_file.h> |
41 | |
42 | int sysctl_aarp_expiry_time = AARP_EXPIRY_TIME; |
43 | int sysctl_aarp_tick_time = AARP_TICK_TIME; |
44 | int sysctl_aarp_retransmit_limit = AARP_RETRANSMIT_LIMIT; |
45 | int sysctl_aarp_resolve_time = AARP_RESOLVE_TIME; |
46 | |
47 | /* Lists of aarp entries */ |
48 | /** |
49 | * struct aarp_entry - AARP entry |
50 | * @last_sent - Last time we xmitted the aarp request |
51 | * @packet_queue - Queue of frames wait for resolution |
52 | * @status - Used for proxy AARP |
53 | * expires_at - Entry expiry time |
54 | * target_addr - DDP Address |
55 | * dev - Device to use |
56 | * hwaddr - Physical i/f address of target/router |
57 | * xmit_count - When this hits 10 we give up |
58 | * next - Next entry in chain |
59 | */ |
60 | struct aarp_entry { |
61 | /* These first two are only used for unresolved entries */ |
62 | unsigned long last_sent; |
63 | struct sk_buff_head packet_queue; |
64 | int status; |
65 | unsigned long expires_at; |
66 | struct atalk_addr target_addr; |
67 | struct net_device *dev; |
68 | char hwaddr[6]; |
69 | unsigned short xmit_count; |
70 | struct aarp_entry *next; |
71 | }; |
72 | |
73 | /* Hashed list of resolved, unresolved and proxy entries */ |
74 | static struct aarp_entry *resolved[AARP_HASH_SIZE]; |
75 | static struct aarp_entry *unresolved[AARP_HASH_SIZE]; |
76 | static struct aarp_entry *proxies[AARP_HASH_SIZE]; |
77 | static int unresolved_count; |
78 | |
79 | /* One lock protects it all. */ |
80 | static DEFINE_RWLOCK(aarp_lock); |
81 | |
82 | /* Used to walk the list and purge/kick entries. */ |
83 | static struct timer_list aarp_timer; |
84 | |
85 | /* |
86 | * Delete an aarp queue |
87 | * |
88 | * Must run under aarp_lock. |
89 | */ |
90 | static void __aarp_expire(struct aarp_entry *a) |
91 | { |
92 | skb_queue_purge(&a->packet_queue); |
93 | kfree(a); |
94 | } |
95 | |
96 | /* |
97 | * Send an aarp queue entry request |
98 | * |
99 | * Must run under aarp_lock. |
100 | */ |
101 | static void __aarp_send_query(struct aarp_entry *a) |
102 | { |
103 | static unsigned char aarp_eth_multicast[ETH_ALEN] = |
104 | { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; |
105 | struct net_device *dev = a->dev; |
106 | struct elapaarp *eah; |
107 | int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length; |
108 | struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); |
109 | struct atalk_addr *sat = atalk_find_dev_addr(dev); |
110 | |
111 | if (!skb) |
112 | return; |
113 | |
114 | if (!sat) { |
115 | kfree_skb(skb); |
116 | return; |
117 | } |
118 | |
119 | /* Set up the buffer */ |
120 | skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); |
121 | skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah)); |
122 | skb->protocol = htons(ETH_P_ATALK); |
123 | skb->dev = dev; |
124 | eah = aarp_hdr(skb); |
125 | |
126 | /* Set up the ARP */ |
127 | eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); |
128 | eah->pa_type = htons(ETH_P_ATALK); |
129 | eah->hw_len = ETH_ALEN; |
130 | eah->pa_len = AARP_PA_ALEN; |
131 | eah->function = htons(AARP_REQUEST); |
132 | |
133 | memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); |
134 | |
135 | eah->pa_src_zero = 0; |
136 | eah->pa_src_net = sat->s_net; |
137 | eah->pa_src_node = sat->s_node; |
138 | |
139 | memset(eah->hw_dst, '\0', ETH_ALEN); |
140 | |
141 | eah->pa_dst_zero = 0; |
142 | eah->pa_dst_net = a->target_addr.s_net; |
143 | eah->pa_dst_node = a->target_addr.s_node; |
144 | |
145 | /* Send it */ |
146 | aarp_dl->request(aarp_dl, skb, aarp_eth_multicast); |
147 | /* Update the sending count */ |
148 | a->xmit_count++; |
149 | a->last_sent = jiffies; |
150 | } |
151 | |
152 | /* This runs under aarp_lock and in softint context, so only atomic memory |
153 | * allocations can be used. */ |
154 | static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us, |
155 | struct atalk_addr *them, unsigned char *sha) |
156 | { |
157 | struct elapaarp *eah; |
158 | int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length; |
159 | struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); |
160 | |
161 | if (!skb) |
162 | return; |
163 | |
164 | /* Set up the buffer */ |
165 | skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); |
166 | skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah)); |
167 | skb->protocol = htons(ETH_P_ATALK); |
168 | skb->dev = dev; |
169 | eah = aarp_hdr(skb); |
170 | |
171 | /* Set up the ARP */ |
172 | eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); |
173 | eah->pa_type = htons(ETH_P_ATALK); |
174 | eah->hw_len = ETH_ALEN; |
175 | eah->pa_len = AARP_PA_ALEN; |
176 | eah->function = htons(AARP_REPLY); |
177 | |
178 | memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); |
179 | |
180 | eah->pa_src_zero = 0; |
181 | eah->pa_src_net = us->s_net; |
182 | eah->pa_src_node = us->s_node; |
183 | |
184 | if (!sha) |
185 | memset(eah->hw_dst, '\0', ETH_ALEN); |
186 | else |
187 | memcpy(eah->hw_dst, sha, ETH_ALEN); |
188 | |
189 | eah->pa_dst_zero = 0; |
190 | eah->pa_dst_net = them->s_net; |
191 | eah->pa_dst_node = them->s_node; |
192 | |
193 | /* Send it */ |
194 | aarp_dl->request(aarp_dl, skb, sha); |
195 | } |
196 | |
197 | /* |
198 | * Send probe frames. Called from aarp_probe_network and |
199 | * aarp_proxy_probe_network. |
200 | */ |
201 | |
202 | static void aarp_send_probe(struct net_device *dev, struct atalk_addr *us) |
203 | { |
204 | struct elapaarp *eah; |
205 | int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length; |
206 | struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); |
207 | static unsigned char aarp_eth_multicast[ETH_ALEN] = |
208 | { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; |
209 | |
210 | if (!skb) |
211 | return; |
212 | |
213 | /* Set up the buffer */ |
214 | skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); |
215 | skb->nh.raw = skb->h.raw = skb_put(skb, sizeof(*eah)); |
216 | skb->protocol = htons(ETH_P_ATALK); |
217 | skb->dev = dev; |
218 | eah = aarp_hdr(skb); |
219 | |
220 | /* Set up the ARP */ |
221 | eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); |
222 | eah->pa_type = htons(ETH_P_ATALK); |
223 | eah->hw_len = ETH_ALEN; |
224 | eah->pa_len = AARP_PA_ALEN; |
225 | eah->function = htons(AARP_PROBE); |
226 | |
227 | memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); |
228 | |
229 | eah->pa_src_zero = 0; |
230 | eah->pa_src_net = us->s_net; |
231 | eah->pa_src_node = us->s_node; |
232 | |
233 | memset(eah->hw_dst, '\0', ETH_ALEN); |
234 | |
235 | eah->pa_dst_zero = 0; |
236 | eah->pa_dst_net = us->s_net; |
237 | eah->pa_dst_node = us->s_node; |
238 | |
239 | /* Send it */ |
240 | aarp_dl->request(aarp_dl, skb, aarp_eth_multicast); |
241 | } |
242 | |
243 | /* |
244 | * Handle an aarp timer expire |
245 | * |
246 | * Must run under the aarp_lock. |
247 | */ |
248 | |
249 | static void __aarp_expire_timer(struct aarp_entry **n) |
250 | { |
251 | struct aarp_entry *t; |
252 | |
253 | while (*n) |
254 | /* Expired ? */ |
255 | if (time_after(jiffies, (*n)->expires_at)) { |
256 | t = *n; |
257 | *n = (*n)->next; |
258 | __aarp_expire(t); |
259 | } else |
260 | n = &((*n)->next); |
261 | } |
262 | |
263 | /* |
264 | * Kick all pending requests 5 times a second. |
265 | * |
266 | * Must run under the aarp_lock. |
267 | */ |
268 | static void __aarp_kick(struct aarp_entry **n) |
269 | { |
270 | struct aarp_entry *t; |
271 | |
272 | while (*n) |
273 | /* Expired: if this will be the 11th tx, we delete instead. */ |
274 | if ((*n)->xmit_count >= sysctl_aarp_retransmit_limit) { |
275 | t = *n; |
276 | *n = (*n)->next; |
277 | __aarp_expire(t); |
278 | } else { |
279 | __aarp_send_query(*n); |
280 | n = &((*n)->next); |
281 | } |
282 | } |
283 | |
284 | /* |
285 | * A device has gone down. Take all entries referring to the device |
286 | * and remove them. |
287 | * |
288 | * Must run under the aarp_lock. |
289 | */ |
290 | static void __aarp_expire_device(struct aarp_entry **n, struct net_device *dev) |
291 | { |
292 | struct aarp_entry *t; |
293 | |
294 | while (*n) |
295 | if ((*n)->dev == dev) { |
296 | t = *n; |
297 | *n = (*n)->next; |
298 | __aarp_expire(t); |
299 | } else |
300 | n = &((*n)->next); |
301 | } |
302 | |
303 | /* Handle the timer event */ |
304 | static void aarp_expire_timeout(unsigned long unused) |
305 | { |
306 | int ct; |
307 | |
308 | write_lock_bh(&aarp_lock); |
309 | |
310 | for (ct = 0; ct < AARP_HASH_SIZE; ct++) { |
311 | __aarp_expire_timer(&resolved[ct]); |
312 | __aarp_kick(&unresolved[ct]); |
313 | __aarp_expire_timer(&unresolved[ct]); |
314 | __aarp_expire_timer(&proxies[ct]); |
315 | } |
316 | |
317 | write_unlock_bh(&aarp_lock); |
318 | mod_timer(&aarp_timer, jiffies + |
319 | (unresolved_count ? sysctl_aarp_tick_time : |
320 | sysctl_aarp_expiry_time)); |
321 | } |
322 | |
323 | /* Network device notifier chain handler. */ |
324 | static int aarp_device_event(struct notifier_block *this, unsigned long event, |
325 | void *ptr) |
326 | { |
327 | int ct; |
328 | |
329 | if (event == NETDEV_DOWN) { |
330 | write_lock_bh(&aarp_lock); |
331 | |
332 | for (ct = 0; ct < AARP_HASH_SIZE; ct++) { |
333 | __aarp_expire_device(&resolved[ct], ptr); |
334 | __aarp_expire_device(&unresolved[ct], ptr); |
335 | __aarp_expire_device(&proxies[ct], ptr); |
336 | } |
337 | |
338 | write_unlock_bh(&aarp_lock); |
339 | } |
340 | return NOTIFY_DONE; |
341 | } |
342 | |
343 | /* Expire all entries in a hash chain */ |
344 | static void __aarp_expire_all(struct aarp_entry **n) |
345 | { |
346 | struct aarp_entry *t; |
347 | |
348 | while (*n) { |
349 | t = *n; |
350 | *n = (*n)->next; |
351 | __aarp_expire(t); |
352 | } |
353 | } |
354 | |
355 | /* Cleanup all hash chains -- module unloading */ |
356 | static void aarp_purge(void) |
357 | { |
358 | int ct; |
359 | |
360 | write_lock_bh(&aarp_lock); |
361 | for (ct = 0; ct < AARP_HASH_SIZE; ct++) { |
362 | __aarp_expire_all(&resolved[ct]); |
363 | __aarp_expire_all(&unresolved[ct]); |
364 | __aarp_expire_all(&proxies[ct]); |
365 | } |
366 | write_unlock_bh(&aarp_lock); |
367 | } |
368 | |
369 | /* |
370 | * Create a new aarp entry. This must use GFP_ATOMIC because it |
371 | * runs while holding spinlocks. |
372 | */ |
373 | static struct aarp_entry *aarp_alloc(void) |
374 | { |
375 | struct aarp_entry *a = kmalloc(sizeof(*a), GFP_ATOMIC); |
376 | |
377 | if (a) |
378 | skb_queue_head_init(&a->packet_queue); |
379 | return a; |
380 | } |
381 | |
382 | /* |
383 | * Find an entry. We might return an expired but not yet purged entry. We |
384 | * don't care as it will do no harm. |
385 | * |
386 | * This must run under the aarp_lock. |
387 | */ |
388 | static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list, |
389 | struct net_device *dev, |
390 | struct atalk_addr *sat) |
391 | { |
392 | while (list) { |
393 | if (list->target_addr.s_net == sat->s_net && |
394 | list->target_addr.s_node == sat->s_node && |
395 | list->dev == dev) |
396 | break; |
397 | list = list->next; |
398 | } |
399 | |
400 | return list; |
401 | } |
402 | |
403 | /* Called from the DDP code, and thus must be exported. */ |
404 | void aarp_proxy_remove(struct net_device *dev, struct atalk_addr *sa) |
405 | { |
406 | int hash = sa->s_node % (AARP_HASH_SIZE - 1); |
407 | struct aarp_entry *a; |
408 | |
409 | write_lock_bh(&aarp_lock); |
410 | |
411 | a = __aarp_find_entry(proxies[hash], dev, sa); |
412 | if (a) |
413 | a->expires_at = jiffies - 1; |
414 | |
415 | write_unlock_bh(&aarp_lock); |
416 | } |
417 | |
418 | /* This must run under aarp_lock. */ |
419 | static struct atalk_addr *__aarp_proxy_find(struct net_device *dev, |
420 | struct atalk_addr *sa) |
421 | { |
422 | int hash = sa->s_node % (AARP_HASH_SIZE - 1); |
423 | struct aarp_entry *a = __aarp_find_entry(proxies[hash], dev, sa); |
424 | |
425 | return a ? sa : NULL; |
426 | } |
427 | |
428 | /* |
429 | * Probe a Phase 1 device or a device that requires its Net:Node to |
430 | * be set via an ioctl. |
431 | */ |
432 | static void aarp_send_probe_phase1(struct atalk_iface *iface) |
433 | { |
434 | struct ifreq atreq; |
435 | struct sockaddr_at *sa = (struct sockaddr_at *)&atreq.ifr_addr; |
436 | |
437 | sa->sat_addr.s_node = iface->address.s_node; |
438 | sa->sat_addr.s_net = ntohs(iface->address.s_net); |
439 | |
440 | /* We pass the Net:Node to the drivers/cards by a Device ioctl. */ |
441 | if (!(iface->dev->do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) { |
442 | (void)iface->dev->do_ioctl(iface->dev, &atreq, SIOCGIFADDR); |
443 | if (iface->address.s_net != htons(sa->sat_addr.s_net) || |
444 | iface->address.s_node != sa->sat_addr.s_node) |
445 | iface->status |= ATIF_PROBE_FAIL; |
446 | |
447 | iface->address.s_net = htons(sa->sat_addr.s_net); |
448 | iface->address.s_node = sa->sat_addr.s_node; |
449 | } |
450 | } |
451 | |
452 | |
453 | void aarp_probe_network(struct atalk_iface *atif) |
454 | { |
455 | if (atif->dev->type == ARPHRD_LOCALTLK || |
456 | atif->dev->type == ARPHRD_PPP) |
457 | aarp_send_probe_phase1(atif); |
458 | else { |
459 | unsigned int count; |
460 | |
461 | for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) { |
462 | aarp_send_probe(atif->dev, &atif->address); |
463 | |
464 | /* Defer 1/10th */ |
465 | current->state = TASK_INTERRUPTIBLE; |
466 | schedule_timeout(HZ / 10); |
467 | |
468 | if (atif->status & ATIF_PROBE_FAIL) |
469 | break; |
470 | } |
471 | } |
472 | } |
473 | |
474 | int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa) |
475 | { |
476 | int hash, retval = -EPROTONOSUPPORT; |
477 | struct aarp_entry *entry; |
478 | unsigned int count; |
479 | |
480 | /* |
481 | * we don't currently support LocalTalk or PPP for proxy AARP; |
482 | * if someone wants to try and add it, have fun |
483 | */ |
484 | if (atif->dev->type == ARPHRD_LOCALTLK || |
485 | atif->dev->type == ARPHRD_PPP) |
486 | goto out; |
487 | |
488 | /* |
489 | * create a new AARP entry with the flags set to be published -- |
490 | * we need this one to hang around even if it's in use |
491 | */ |
492 | entry = aarp_alloc(); |
493 | retval = -ENOMEM; |
494 | if (!entry) |
495 | goto out; |
496 | |
497 | entry->expires_at = -1; |
498 | entry->status = ATIF_PROBE; |
499 | entry->target_addr.s_node = sa->s_node; |
500 | entry->target_addr.s_net = sa->s_net; |
501 | entry->dev = atif->dev; |
502 | |
503 | write_lock_bh(&aarp_lock); |
504 | |
505 | hash = sa->s_node % (AARP_HASH_SIZE - 1); |
506 | entry->next = proxies[hash]; |
507 | proxies[hash] = entry; |
508 | |
509 | for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) { |
510 | aarp_send_probe(atif->dev, sa); |
511 | |
512 | /* Defer 1/10th */ |
513 | current->state = TASK_INTERRUPTIBLE; |
514 | write_unlock_bh(&aarp_lock); |
515 | schedule_timeout(HZ / 10); |
516 | write_lock_bh(&aarp_lock); |
517 | |
518 | if (entry->status & ATIF_PROBE_FAIL) |
519 | break; |
520 | } |
521 | |
522 | if (entry->status & ATIF_PROBE_FAIL) { |
523 | entry->expires_at = jiffies - 1; /* free the entry */ |
524 | retval = -EADDRINUSE; /* return network full */ |
525 | } else { /* clear the probing flag */ |
526 | entry->status &= ~ATIF_PROBE; |
527 | retval = 1; |
528 | } |
529 | |
530 | write_unlock_bh(&aarp_lock); |
531 | out: |
532 | return retval; |
533 | } |
534 | |
535 | /* Send a DDP frame */ |
536 | int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb, |
537 | struct atalk_addr *sa, void *hwaddr) |
538 | { |
539 | static char ddp_eth_multicast[ETH_ALEN] = |
540 | { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; |
541 | int hash; |
542 | struct aarp_entry *a; |
543 | |
544 | skb->nh.raw = skb->data; |
545 | |
546 | /* Check for LocalTalk first */ |
547 | if (dev->type == ARPHRD_LOCALTLK) { |
548 | struct atalk_addr *at = atalk_find_dev_addr(dev); |
549 | struct ddpehdr *ddp = (struct ddpehdr *)skb->data; |
550 | int ft = 2; |
551 | |
552 | /* |
553 | * Compressible ? |
554 | * |
555 | * IFF: src_net == dest_net == device_net |
556 | * (zero matches anything) |
557 | */ |
558 | |
559 | if ((!ddp->deh_snet || at->s_net == ddp->deh_snet) && |
560 | (!ddp->deh_dnet || at->s_net == ddp->deh_dnet)) { |
561 | skb_pull(skb, sizeof(*ddp) - 4); |
562 | |
563 | /* |
564 | * The upper two remaining bytes are the port |
565 | * numbers we just happen to need. Now put the |
566 | * length in the lower two. |
567 | */ |
568 | *((__u16 *)skb->data) = htons(skb->len); |
569 | ft = 1; |
570 | } |
571 | /* |
572 | * Nice and easy. No AARP type protocols occur here so we can |
573 | * just shovel it out with a 3 byte LLAP header |
574 | */ |
575 | |
576 | skb_push(skb, 3); |
577 | skb->data[0] = sa->s_node; |
578 | skb->data[1] = at->s_node; |
579 | skb->data[2] = ft; |
580 | skb->dev = dev; |
581 | goto sendit; |
582 | } |
583 | |
584 | /* On a PPP link we neither compress nor aarp. */ |
585 | if (dev->type == ARPHRD_PPP) { |
586 | skb->protocol = htons(ETH_P_PPPTALK); |
587 | skb->dev = dev; |
588 | goto sendit; |
589 | } |
590 | |
591 | /* Non ELAP we cannot do. */ |
592 | if (dev->type != ARPHRD_ETHER) |
593 | return -1; |
594 | |
595 | skb->dev = dev; |
596 | skb->protocol = htons(ETH_P_ATALK); |
597 | hash = sa->s_node % (AARP_HASH_SIZE - 1); |
598 | |
599 | /* Do we have a resolved entry? */ |
600 | if (sa->s_node == ATADDR_BCAST) { |
601 | /* Send it */ |
602 | ddp_dl->request(ddp_dl, skb, ddp_eth_multicast); |
603 | goto sent; |
604 | } |
605 | |
606 | write_lock_bh(&aarp_lock); |
607 | a = __aarp_find_entry(resolved[hash], dev, sa); |
608 | |
609 | if (a) { /* Return 1 and fill in the address */ |
610 | a->expires_at = jiffies + (sysctl_aarp_expiry_time * 10); |
611 | ddp_dl->request(ddp_dl, skb, a->hwaddr); |
612 | write_unlock_bh(&aarp_lock); |
613 | goto sent; |
614 | } |
615 | |
616 | /* Do we have an unresolved entry: This is the less common path */ |
617 | a = __aarp_find_entry(unresolved[hash], dev, sa); |
618 | if (a) { /* Queue onto the unresolved queue */ |
619 | skb_queue_tail(&a->packet_queue, skb); |
620 | goto out_unlock; |
621 | } |
622 | |
623 | /* Allocate a new entry */ |
624 | a = aarp_alloc(); |
625 | if (!a) { |
626 | /* Whoops slipped... good job it's an unreliable protocol 8) */ |
627 | write_unlock_bh(&aarp_lock); |
628 | return -1; |
629 | } |
630 | |
631 | /* Set up the queue */ |
632 | skb_queue_tail(&a->packet_queue, skb); |
633 | a->expires_at = jiffies + sysctl_aarp_resolve_time; |
634 | a->dev = dev; |
635 | a->next = unresolved[hash]; |
636 | a->target_addr = *sa; |
637 | a->xmit_count = 0; |
638 | unresolved[hash] = a; |
639 | unresolved_count++; |
640 | |
641 | /* Send an initial request for the address */ |
642 | __aarp_send_query(a); |
643 | |
644 | /* |
645 | * Switch to fast timer if needed (That is if this is the first |
646 | * unresolved entry to get added) |
647 | */ |
648 | |
649 | if (unresolved_count == 1) |
650 | mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time); |
651 | |
652 | /* Now finally, it is safe to drop the lock. */ |
653 | out_unlock: |
654 | write_unlock_bh(&aarp_lock); |
655 | |
656 | /* Tell the ddp layer we have taken over for this frame. */ |
657 | return 0; |
658 | |
659 | sendit: |
660 | if (skb->sk) |
661 | skb->priority = skb->sk->sk_priority; |
662 | dev_queue_xmit(skb); |
663 | sent: |
664 | return 1; |
665 | } |
666 | |
667 | /* |
668 | * An entry in the aarp unresolved queue has become resolved. Send |
669 | * all the frames queued under it. |
670 | * |
671 | * Must run under aarp_lock. |
672 | */ |
673 | static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a, |
674 | int hash) |
675 | { |
676 | struct sk_buff *skb; |
677 | |
678 | while (*list) |
679 | if (*list == a) { |
680 | unresolved_count--; |
681 | *list = a->next; |
682 | |
683 | /* Move into the resolved list */ |
684 | a->next = resolved[hash]; |
685 | resolved[hash] = a; |
686 | |
687 | /* Kick frames off */ |
688 | while ((skb = skb_dequeue(&a->packet_queue)) != NULL) { |
689 | a->expires_at = jiffies + |
690 | sysctl_aarp_expiry_time * 10; |
691 | ddp_dl->request(ddp_dl, skb, a->hwaddr); |
692 | } |
693 | } else |
694 | list = &((*list)->next); |
695 | } |
696 | |
697 | /* |
698 | * This is called by the SNAP driver whenever we see an AARP SNAP |
699 | * frame. We currently only support Ethernet. |
700 | */ |
701 | static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, |
702 | struct packet_type *pt) |
703 | { |
704 | struct elapaarp *ea = aarp_hdr(skb); |
705 | int hash, ret = 0; |
706 | __u16 function; |
707 | struct aarp_entry *a; |
708 | struct atalk_addr sa, *ma, da; |
709 | struct atalk_iface *ifa; |
710 | |
711 | /* We only do Ethernet SNAP AARP. */ |
712 | if (dev->type != ARPHRD_ETHER) |
713 | goto out0; |
714 | |
715 | /* Frame size ok? */ |
716 | if (!skb_pull(skb, sizeof(*ea))) |
717 | goto out0; |
718 | |
719 | function = ntohs(ea->function); |
720 | |
721 | /* Sanity check fields. */ |
722 | if (function < AARP_REQUEST || function > AARP_PROBE || |
723 | ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN || |
724 | ea->pa_src_zero || ea->pa_dst_zero) |
725 | goto out0; |
726 | |
727 | /* Looks good. */ |
728 | hash = ea->pa_src_node % (AARP_HASH_SIZE - 1); |
729 | |
730 | /* Build an address. */ |
731 | sa.s_node = ea->pa_src_node; |
732 | sa.s_net = ea->pa_src_net; |
733 | |
734 | /* Process the packet. Check for replies of me. */ |
735 | ifa = atalk_find_dev(dev); |
736 | if (!ifa) |
737 | goto out1; |
738 | |
739 | if (ifa->status & ATIF_PROBE && |
740 | ifa->address.s_node == ea->pa_dst_node && |
741 | ifa->address.s_net == ea->pa_dst_net) { |
742 | ifa->status |= ATIF_PROBE_FAIL; /* Fail the probe (in use) */ |
743 | goto out1; |
744 | } |
745 | |
746 | /* Check for replies of proxy AARP entries */ |
747 | da.s_node = ea->pa_dst_node; |
748 | da.s_net = ea->pa_dst_net; |
749 | |
750 | write_lock_bh(&aarp_lock); |
751 | a = __aarp_find_entry(proxies[hash], dev, &da); |
752 | |
753 | if (a && a->status & ATIF_PROBE) { |
754 | a->status |= ATIF_PROBE_FAIL; |
755 | /* |
756 | * we do not respond to probe or request packets for |
757 | * this address while we are probing this address |
758 | */ |
759 | goto unlock; |
760 | } |
761 | |
762 | switch (function) { |
763 | case AARP_REPLY: |
764 | if (!unresolved_count) /* Speed up */ |
765 | break; |
766 | |
767 | /* Find the entry. */ |
768 | a = __aarp_find_entry(unresolved[hash], dev, &sa); |
769 | if (!a || dev != a->dev) |
770 | break; |
771 | |
772 | /* We can fill one in - this is good. */ |
773 | memcpy(a->hwaddr, ea->hw_src, ETH_ALEN); |
774 | __aarp_resolved(&unresolved[hash], a, hash); |
775 | if (!unresolved_count) |
776 | mod_timer(&aarp_timer, |
777 | jiffies + sysctl_aarp_expiry_time); |
778 | break; |
779 | |
780 | case AARP_REQUEST: |
781 | case AARP_PROBE: |
782 | |
783 | /* |
784 | * If it is my address set ma to my address and reply. |
785 | * We can treat probe and request the same. Probe |
786 | * simply means we shouldn't cache the querying host, |
787 | * as in a probe they are proposing an address not |
788 | * using one. |
789 | * |
790 | * Support for proxy-AARP added. We check if the |
791 | * address is one of our proxies before we toss the |
792 | * packet out. |
793 | */ |
794 | |
795 | sa.s_node = ea->pa_dst_node; |
796 | sa.s_net = ea->pa_dst_net; |
797 | |
798 | /* See if we have a matching proxy. */ |
799 | ma = __aarp_proxy_find(dev, &sa); |
800 | if (!ma) |
801 | ma = &ifa->address; |
802 | else { /* We need to make a copy of the entry. */ |
803 | da.s_node = sa.s_node; |
804 | da.s_net = da.s_net; |
805 | ma = &da; |
806 | } |
807 | |
808 | if (function == AARP_PROBE) { |
809 | /* |
810 | * A probe implies someone trying to get an |
811 | * address. So as a precaution flush any |
812 | * entries we have for this address. |
813 | */ |
814 | struct aarp_entry *a; |
815 | |
816 | a = __aarp_find_entry(resolved[sa.s_node % |
817 | (AARP_HASH_SIZE - 1)], |
818 | skb->dev, &sa); |
819 | |
820 | /* |
821 | * Make it expire next tick - that avoids us |
822 | * getting into a probe/flush/learn/probe/ |
823 | * flush/learn cycle during probing of a slow |
824 | * to respond host addr. |
825 | */ |
826 | if (a) { |
827 | a->expires_at = jiffies - 1; |
828 | mod_timer(&aarp_timer, jiffies + |
829 | sysctl_aarp_tick_time); |
830 | } |
831 | } |
832 | |
833 | if (sa.s_node != ma->s_node) |
834 | break; |
835 | |
836 | if (sa.s_net && ma->s_net && sa.s_net != ma->s_net) |
837 | break; |
838 | |
839 | sa.s_node = ea->pa_src_node; |
840 | sa.s_net = ea->pa_src_net; |
841 | |
842 | /* aarp_my_address has found the address to use for us. |
843 | */ |
844 | aarp_send_reply(dev, ma, &sa, ea->hw_src); |
845 | break; |
846 | } |
847 | |
848 | unlock: |
849 | write_unlock_bh(&aarp_lock); |
850 | out1: |
851 | ret = 1; |
852 | out0: |
853 | kfree_skb(skb); |
854 | return ret; |
855 | } |
856 | |
857 | static struct notifier_block aarp_notifier = { |
858 | .notifier_call = aarp_device_event, |
859 | }; |
860 | |
861 | static unsigned char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; |
862 | |
863 | void __init aarp_proto_init(void) |
864 | { |
865 | aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv); |
866 | if (!aarp_dl) |
867 | printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); |
868 | init_timer(&aarp_timer); |
869 | aarp_timer.function = aarp_expire_timeout; |
870 | aarp_timer.data = 0; |
871 | aarp_timer.expires = jiffies + sysctl_aarp_expiry_time; |
872 | add_timer(&aarp_timer); |
873 | register_netdevice_notifier(&aarp_notifier); |
874 | } |
875 | |
876 | /* Remove the AARP entries associated with a device. */ |
877 | void aarp_device_down(struct net_device *dev) |
878 | { |
879 | int ct; |
880 | |
881 | write_lock_bh(&aarp_lock); |
882 | |
883 | for (ct = 0; ct < AARP_HASH_SIZE; ct++) { |
884 | __aarp_expire_device(&resolved[ct], dev); |
885 | __aarp_expire_device(&unresolved[ct], dev); |
886 | __aarp_expire_device(&proxies[ct], dev); |
887 | } |
888 | |
889 | write_unlock_bh(&aarp_lock); |
890 | } |
891 | |
892 | #ifdef CONFIG_PROC_FS |
893 | struct aarp_iter_state { |
894 | int bucket; |
895 | struct aarp_entry **table; |
896 | }; |
897 | |
898 | /* |
899 | * Get the aarp entry that is in the chain described |
900 | * by the iterator. |
901 | * If pos is set then skip till that index. |
902 | * pos = 1 is the first entry |
903 | */ |
904 | static struct aarp_entry *iter_next(struct aarp_iter_state *iter, loff_t *pos) |
905 | { |
906 | int ct = iter->bucket; |
907 | struct aarp_entry **table = iter->table; |
908 | loff_t off = 0; |
909 | struct aarp_entry *entry; |
910 | |
911 | rescan: |
912 | while(ct < AARP_HASH_SIZE) { |
913 | for (entry = table[ct]; entry; entry = entry->next) { |
914 | if (!pos || ++off == *pos) { |
915 | iter->table = table; |
916 | iter->bucket = ct; |
917 | return entry; |
918 | } |
919 | } |
920 | ++ct; |
921 | } |
922 | |
923 | if (table == resolved) { |
924 | ct = 0; |
925 | table = unresolved; |
926 | goto rescan; |
927 | } |
928 | if (table == unresolved) { |
929 | ct = 0; |
930 | table = proxies; |
931 | goto rescan; |
932 | } |
933 | return NULL; |
934 | } |
935 | |
936 | static void *aarp_seq_start(struct seq_file *seq, loff_t *pos) |
937 | { |
938 | struct aarp_iter_state *iter = seq->private; |
939 | |
940 | read_lock_bh(&aarp_lock); |
941 | iter->table = resolved; |
942 | iter->bucket = 0; |
943 | |
944 | return *pos ? iter_next(iter, pos) : SEQ_START_TOKEN; |
945 | } |
946 | |
947 | static void *aarp_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
948 | { |
949 | struct aarp_entry *entry = v; |
950 | struct aarp_iter_state *iter = seq->private; |
951 | |
952 | ++*pos; |
953 | |
954 | /* first line after header */ |
955 | if (v == SEQ_START_TOKEN) |
956 | entry = iter_next(iter, NULL); |
957 | |
958 | /* next entry in current bucket */ |
959 | else if (entry->next) |
960 | entry = entry->next; |
961 | |
962 | /* next bucket or table */ |
963 | else { |
964 | ++iter->bucket; |
965 | entry = iter_next(iter, NULL); |
966 | } |
967 | return entry; |
968 | } |
969 | |
970 | static void aarp_seq_stop(struct seq_file *seq, void *v) |
971 | { |
972 | read_unlock_bh(&aarp_lock); |
973 | } |
974 | |
975 | static const char *dt2str(unsigned long ticks) |
976 | { |
977 | static char buf[32]; |
978 | |
979 | sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100 ) / HZ); |
980 | |
981 | return buf; |
982 | } |
983 | |
984 | static int aarp_seq_show(struct seq_file *seq, void *v) |
985 | { |
986 | struct aarp_iter_state *iter = seq->private; |
987 | struct aarp_entry *entry = v; |
988 | unsigned long now = jiffies; |
989 | |
990 | if (v == SEQ_START_TOKEN) |
991 | seq_puts(seq, |
992 | "Address Interface Hardware Address" |
993 | " Expires LastSend Retry Status\n"); |
994 | else { |
995 | seq_printf(seq, "%04X:%02X %-12s", |
996 | ntohs(entry->target_addr.s_net), |
997 | (unsigned int) entry->target_addr.s_node, |
998 | entry->dev ? entry->dev->name : "????"); |
999 | seq_printf(seq, "%02X:%02X:%02X:%02X:%02X:%02X", |
1000 | entry->hwaddr[0] & 0xFF, |
1001 | entry->hwaddr[1] & 0xFF, |
1002 | entry->hwaddr[2] & 0xFF, |
1003 | entry->hwaddr[3] & 0xFF, |
1004 | entry->hwaddr[4] & 0xFF, |
1005 | entry->hwaddr[5] & 0xFF); |
1006 | seq_printf(seq, " %8s", |
1007 | dt2str((long)entry->expires_at - (long)now)); |
1008 | if (iter->table == unresolved) |
1009 | seq_printf(seq, " %8s %6hu", |
1010 | dt2str(now - entry->last_sent), |
1011 | entry->xmit_count); |
1012 | else |
1013 | seq_puts(seq, " "); |
1014 | seq_printf(seq, " %s\n", |
1015 | (iter->table == resolved) ? "resolved" |
1016 | : (iter->table == unresolved) ? "unresolved" |
1017 | : (iter->table == proxies) ? "proxies" |
1018 | : "unknown"); |
1019 | } |
1020 | return 0; |
1021 | } |
1022 | |
1023 | static struct seq_operations aarp_seq_ops = { |
1024 | .start = aarp_seq_start, |
1025 | .next = aarp_seq_next, |
1026 | .stop = aarp_seq_stop, |
1027 | .show = aarp_seq_show, |
1028 | }; |
1029 | |
1030 | static int aarp_seq_open(struct inode *inode, struct file *file) |
1031 | { |
1032 | struct seq_file *seq; |
1033 | int rc = -ENOMEM; |
1034 | struct aarp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); |
1035 | |
1036 | if (!s) |
1037 | goto out; |
1038 | |
1039 | rc = seq_open(file, &aarp_seq_ops); |
1040 | if (rc) |
1041 | goto out_kfree; |
1042 | |
1043 | seq = file->private_data; |
1044 | seq->private = s; |
1045 | memset(s, 0, sizeof(*s)); |
1046 | out: |
1047 | return rc; |
1048 | out_kfree: |
1049 | kfree(s); |
1050 | goto out; |
1051 | } |
1052 | |
1053 | struct file_operations atalk_seq_arp_fops = { |
1054 | .owner = THIS_MODULE, |
1055 | .open = aarp_seq_open, |
1056 | .read = seq_read, |
1057 | .llseek = seq_lseek, |
1058 | .release = seq_release_private, |
1059 | }; |
1060 | #endif |
1061 | |
1062 | /* General module cleanup. Called from cleanup_module() in ddp.c. */ |
1063 | void aarp_cleanup_module(void) |
1064 | { |
1065 | del_timer_sync(&aarp_timer); |
1066 | unregister_netdevice_notifier(&aarp_notifier); |
1067 | unregister_snap_client(aarp_dl); |
1068 | aarp_purge(); |
1069 | } |