1 /*
2 * DECnet An implementation of the DECnet protocol suite for the LINUX
3 * operating system. DECnet is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * DECnet Neighbour Functions (Adjacency Database and
7 * On-Ethernet Cache)
8 *
9 * Author: Steve Whitehouse <SteveW@ACM.org>
10 *
11 *
12 * Changes:
13 * Steve Whitehouse : Fixed router listing routine
14 * Steve Whitehouse : Added error_report functions
15 * Steve Whitehouse : Added default router detection
16 * Steve Whitehouse : Hop counts in outgoing messages
17 * Steve Whitehouse : Fixed src/dst in outgoing messages so
18 * forwarding now stands a good chance of
19 * working.
20 * Steve Whitehouse : Fixed neighbour states (for now anyway).
21 * Steve Whitehouse : Made error_report functions dummies. This
22 * is not the right place to return skbs.
23 * Harald Welte : Port to DaveM's generalized ncache from 2.6.x
24 *
25 */
26
27 #include <linux/config.h>
28 #include <linux/net.h>
29 #include <linux/module.h>
30 #include <linux/socket.h>
31 #include <linux/if_arp.h>
32 #include <linux/if_ether.h>
33 #include <linux/init.h>
34 #include <linux/proc_fs.h>
35 #include <linux/string.h>
36 #include <linux/netfilter_decnet.h>
37 #include <linux/spinlock.h>
38 #include <linux/seq_file.h>
39 #include <linux/jhash.h>
40 #include <asm/atomic.h>
41 #include <net/neighbour.h>
42 #include <net/dst.h>
43 #include <net/dn.h>
44 #include <net/dn_dev.h>
45 #include <net/dn_neigh.h>
46 #include <net/dn_route.h>
47
48 static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev);
49 static int dn_neigh_construct(struct neighbour *);
50 static void dn_long_error_report(struct neighbour *, struct sk_buff *);
51 static void dn_short_error_report(struct neighbour *, struct sk_buff *);
52 static int dn_long_output(struct sk_buff *);
53 static int dn_short_output(struct sk_buff *);
54 static int dn_phase3_output(struct sk_buff *);
55
56
57 /*
58 * For talking to broadcast devices: Ethernet & PPP
59 */
60 static struct neigh_ops dn_long_ops = {
61 family: AF_DECnet,
62 error_report: dn_long_error_report,
63 output: dn_long_output,
64 connected_output: dn_long_output,
65 hh_output: dev_queue_xmit,
66 queue_xmit: dev_queue_xmit,
67 };
68
69 /*
70 * For talking to pointopoint and multidrop devices: DDCMP and X.25
71 */
72 static struct neigh_ops dn_short_ops = {
73 family: AF_DECnet,
74 error_report: dn_short_error_report,
75 output: dn_short_output,
76 connected_output: dn_short_output,
77 hh_output: dev_queue_xmit,
78 queue_xmit: dev_queue_xmit,
79 };
80
81 /*
82 * For talking to DECnet phase III nodes
83 */
84 static struct neigh_ops dn_phase3_ops = {
85 family: AF_DECnet,
86 error_report: dn_short_error_report, /* Can use short version here */
87 output: dn_phase3_output,
88 connected_output: dn_phase3_output,
89 hh_output: dev_queue_xmit,
90 queue_xmit: dev_queue_xmit
91 };
92
93 struct neigh_table dn_neigh_table = {
94 family: PF_DECnet,
95 entry_size: sizeof(struct dn_neigh),
96 key_len: sizeof(dn_address),
97 hash: dn_neigh_hash,
98 constructor: dn_neigh_construct,
99 id: "dn_neigh_cache",
100 parms: {
101 tbl: &dn_neigh_table,
102 entries: 0,
103 base_reachable_time: 30 * HZ,
104 retrans_time: 1 * HZ,
105 gc_staletime: 60 * HZ,
106 reachable_time: 30 * HZ,
107 delay_probe_time: 5 * HZ,
108 queue_len: 3,
109 ucast_probes: 0,
110 app_probes: 0,
111 mcast_probes: 0,
112 anycast_delay: 0,
113 proxy_delay: 0,
114 proxy_qlen: 0,
115 locktime: 1 * HZ,
116 },
117 gc_interval: 30 * HZ,
118 gc_thresh1: 128,
119 gc_thresh2: 512,
120 gc_thresh3: 1024,
121 };
122
dn_neigh_hash(const void * pkey,const struct net_device * dev)123 static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev)
124 {
125 return jhash_2words(*(dn_address *)pkey, 0, dn_neigh_table.hash_rnd);
126 }
127
dn_neigh_construct(struct neighbour * neigh)128 static int dn_neigh_construct(struct neighbour *neigh)
129 {
130 struct net_device *dev = neigh->dev;
131 struct dn_neigh *dn = (struct dn_neigh *)neigh;
132 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
133
134 if (dn_db == NULL)
135 return -EINVAL;
136
137 if (dn_db->neigh_parms)
138 neigh->parms = dn_db->neigh_parms;
139
140 if (dn_db->use_long)
141 neigh->ops = &dn_long_ops;
142 else
143 neigh->ops = &dn_short_ops;
144
145 if (dn->flags & DN_NDFLAG_P3)
146 neigh->ops = &dn_phase3_ops;
147
148 neigh->nud_state = NUD_NOARP;
149 neigh->output = neigh->ops->connected_output;
150
151 if ((dev->type == ARPHRD_IPGRE) || (dev->flags & IFF_POINTOPOINT))
152 memcpy(neigh->ha, dev->broadcast, dev->addr_len);
153 else if ((dev->type == ARPHRD_ETHER) || (dev->type == ARPHRD_LOOPBACK))
154 dn_dn2eth(neigh->ha, dn->addr);
155 else {
156 if (net_ratelimit())
157 printk(KERN_DEBUG "Trying to create neigh for hw %d\n", dev->type);
158 return -EINVAL;
159 }
160
161 dn->blksize = 230;
162
163 return 0;
164 }
165
dn_long_error_report(struct neighbour * neigh,struct sk_buff * skb)166 static void dn_long_error_report(struct neighbour *neigh, struct sk_buff *skb)
167 {
168 printk(KERN_DEBUG "dn_long_error_report: called\n");
169 kfree_skb(skb);
170 }
171
172
dn_short_error_report(struct neighbour * neigh,struct sk_buff * skb)173 static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb)
174 {
175 printk(KERN_DEBUG "dn_short_error_report: called\n");
176 kfree_skb(skb);
177 }
178
dn_neigh_output_packet(struct sk_buff * skb)179 static int dn_neigh_output_packet(struct sk_buff *skb)
180 {
181 struct dst_entry *dst = skb->dst;
182 struct neighbour *neigh = dst->neighbour;
183 struct net_device *dev = neigh->dev;
184
185 if (!dev->hard_header || dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len) >= 0)
186 return neigh->ops->queue_xmit(skb);
187
188 if (net_ratelimit())
189 printk(KERN_DEBUG "dn_neigh_output_packet: oops, can't send packet\n");
190
191 kfree_skb(skb);
192 return -EINVAL;
193 }
194
dn_long_output(struct sk_buff * skb)195 static int dn_long_output(struct sk_buff *skb)
196 {
197 struct dst_entry *dst = skb->dst;
198 struct neighbour *neigh = dst->neighbour;
199 struct net_device *dev = neigh->dev;
200 int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
201 unsigned char *data;
202 struct dn_long_packet *lp;
203 struct dn_skb_cb *cb = DN_SKB_CB(skb);
204
205
206 if (skb_headroom(skb) < headroom) {
207 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
208 if (skb2 == NULL) {
209 if (net_ratelimit())
210 printk(KERN_CRIT "dn_long_output: no memory\n");
211 kfree_skb(skb);
212 return -ENOBUFS;
213 }
214 kfree_skb(skb);
215 skb = skb2;
216 if (net_ratelimit())
217 printk(KERN_INFO "dn_long_output: Increasing headroom\n");
218 }
219
220 data = skb_push(skb, sizeof(struct dn_long_packet) + 3);
221 lp = (struct dn_long_packet *)(data+3);
222
223 *((unsigned short *)data) = dn_htons(skb->len - 2);
224 *(data + 2) = 1 | DN_RT_F_PF; /* Padding */
225
226 lp->msgflg = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS));
227 lp->d_area = lp->d_subarea = 0;
228 dn_dn2eth(lp->d_id, dn_ntohs(cb->dst));
229 lp->s_area = lp->s_subarea = 0;
230 dn_dn2eth(lp->s_id, dn_ntohs(cb->src));
231 lp->nl2 = 0;
232 lp->visit_ct = cb->hops & 0x3f;
233 lp->s_class = 0;
234 lp->pt = 0;
235
236 skb->nh.raw = skb->data;
237
238 return NF_HOOK(PF_DECnet, NF_DN_POST_ROUTING, skb, NULL, neigh->dev, dn_neigh_output_packet);
239 }
240
dn_short_output(struct sk_buff * skb)241 static int dn_short_output(struct sk_buff *skb)
242 {
243 struct dst_entry *dst = skb->dst;
244 struct neighbour *neigh = dst->neighbour;
245 struct net_device *dev = neigh->dev;
246 int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
247 struct dn_short_packet *sp;
248 unsigned char *data;
249 struct dn_skb_cb *cb = DN_SKB_CB(skb);
250
251
252 if (skb_headroom(skb) < headroom) {
253 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
254 if (skb2 == NULL) {
255 if (net_ratelimit())
256 printk(KERN_CRIT "dn_short_output: no memory\n");
257 kfree_skb(skb);
258 return -ENOBUFS;
259 }
260 kfree_skb(skb);
261 skb = skb2;
262 if (net_ratelimit())
263 printk(KERN_INFO "dn_short_output: Increasing headroom\n");
264 }
265
266 data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
267 *((unsigned short *)data) = dn_htons(skb->len - 2);
268 sp = (struct dn_short_packet *)(data+2);
269
270 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
271 sp->dstnode = cb->dst;
272 sp->srcnode = cb->src;
273 sp->forward = cb->hops & 0x3f;
274
275 skb->nh.raw = skb->data;
276
277 return NF_HOOK(PF_DECnet, NF_DN_POST_ROUTING, skb, NULL, neigh->dev, dn_neigh_output_packet);
278 }
279
280 /*
281 * Phase 3 output is the same is short output, execpt that
282 * it clears the area bits before transmission.
283 */
dn_phase3_output(struct sk_buff * skb)284 static int dn_phase3_output(struct sk_buff *skb)
285 {
286 struct dst_entry *dst = skb->dst;
287 struct neighbour *neigh = dst->neighbour;
288 struct net_device *dev = neigh->dev;
289 int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
290 struct dn_short_packet *sp;
291 unsigned char *data;
292 struct dn_skb_cb *cb = DN_SKB_CB(skb);
293
294 if (skb_headroom(skb) < headroom) {
295 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
296 if (skb2 == NULL) {
297 if (net_ratelimit())
298 printk(KERN_CRIT "dn_phase3_output: no memory\n");
299 kfree_skb(skb);
300 return -ENOBUFS;
301 }
302 kfree_skb(skb);
303 skb = skb2;
304 if (net_ratelimit())
305 printk(KERN_INFO "dn_phase3_output: Increasing headroom\n");
306 }
307
308 data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
309 *((unsigned short *)data) = dn_htons(skb->len - 2);
310 sp = (struct dn_short_packet *)(data + 2);
311
312 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
313 sp->dstnode = cb->dst & dn_htons(0x03ff);
314 sp->srcnode = cb->src & dn_htons(0x03ff);
315 sp->forward = cb->hops & 0x3f;
316
317 skb->nh.raw = skb->data;
318
319 return NF_HOOK(PF_DECnet, NF_DN_POST_ROUTING, skb, NULL, neigh->dev, dn_neigh_output_packet);
320 }
321
322 /*
323 * Any traffic on a pointopoint link causes the timer to be reset
324 * for the entry in the neighbour table.
325 */
dn_neigh_pointopoint_notify(struct sk_buff * skb)326 void dn_neigh_pointopoint_notify(struct sk_buff *skb)
327 {
328 return;
329 }
330
331 /*
332 * Pointopoint link receives a hello message
333 */
dn_neigh_pointopoint_hello(struct sk_buff * skb)334 void dn_neigh_pointopoint_hello(struct sk_buff *skb)
335 {
336 kfree_skb(skb);
337 }
338
339 /*
340 * Ethernet router hello message received
341 */
dn_neigh_router_hello(struct sk_buff * skb)342 int dn_neigh_router_hello(struct sk_buff *skb)
343 {
344 struct rtnode_hello_message *msg = (struct rtnode_hello_message *)skb->data;
345
346 struct neighbour *neigh;
347 struct dn_neigh *dn;
348 struct dn_dev *dn_db;
349 dn_address src;
350
351 src = dn_htons(dn_eth2dn(msg->id));
352
353 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
354
355 dn = (struct dn_neigh *)neigh;
356
357 if (neigh) {
358 write_lock(&neigh->lock);
359
360 neigh->used = jiffies;
361 dn_db = (struct dn_dev *)neigh->dev->dn_ptr;
362
363 if (!(neigh->nud_state & NUD_PERMANENT)) {
364 neigh->updated = jiffies;
365
366 if (neigh->dev->type == ARPHRD_ETHER)
367 memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
368
369 dn->blksize = dn_ntohs(msg->blksize);
370 dn->priority = msg->priority;
371
372 dn->flags &= ~DN_NDFLAG_P3;
373
374 switch(msg->iinfo & DN_RT_INFO_TYPE) {
375 case DN_RT_INFO_L1RT:
376 dn->flags &=~DN_NDFLAG_R2;
377 dn->flags |= DN_NDFLAG_R1;
378 break;
379 case DN_RT_INFO_L2RT:
380 dn->flags |= DN_NDFLAG_R2;
381 }
382 }
383
384 if (!dn_db->router) {
385 dn_db->router = neigh_clone(neigh);
386 } else {
387 if (msg->priority > ((struct dn_neigh *)dn_db->router)->priority)
388 neigh_release(xchg(&dn_db->router, neigh_clone(neigh)));
389 }
390 write_unlock(&neigh->lock);
391 neigh_release(neigh);
392 }
393
394 kfree_skb(skb);
395 return 0;
396 }
397
398 /*
399 * Endnode hello message received
400 */
dn_neigh_endnode_hello(struct sk_buff * skb)401 int dn_neigh_endnode_hello(struct sk_buff *skb)
402 {
403 struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data;
404 struct neighbour *neigh;
405 struct dn_neigh *dn;
406 dn_address src;
407
408 src = dn_htons(dn_eth2dn(msg->id));
409
410 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
411
412 dn = (struct dn_neigh *)neigh;
413
414 if (neigh) {
415 write_lock(&neigh->lock);
416
417 neigh->used = jiffies;
418
419 if (!(neigh->nud_state & NUD_PERMANENT)) {
420 neigh->updated = jiffies;
421
422 if (neigh->dev->type == ARPHRD_ETHER)
423 memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
424 dn->flags &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
425 dn->blksize = dn_ntohs(msg->blksize);
426 dn->priority = 0;
427 }
428
429 write_unlock(&neigh->lock);
430 neigh_release(neigh);
431 }
432
433 kfree_skb(skb);
434 return 0;
435 }
436
437
438 #ifdef CONFIG_DECNET_ROUTER
dn_find_slot(char * base,int max,int priority)439 static char *dn_find_slot(char *base, int max, int priority)
440 {
441 int i;
442 unsigned char *min = NULL;
443
444 base += 6; /* skip first id */
445
446 for(i = 0; i < max; i++) {
447 if (!min || (*base < *min))
448 min = base;
449 base += 7; /* find next priority */
450 }
451
452 if (!min)
453 return NULL;
454
455 return (*min < priority) ? (min - 6) : NULL;
456 }
457
458 struct elist_cb_state {
459 struct net_device *dev;
460 unsigned char *ptr;
461 unsigned char *rs;
462 int t, n;
463 };
464
neigh_elist_cb(struct neighbour * neigh,void * _info)465 static void neigh_elist_cb(struct neighbour *neigh, void *_info)
466 {
467 struct elist_cb_state *s = _info;
468 struct dn_dev *dn_db;
469 struct dn_neigh *dn;
470
471 if (neigh->dev != s->dev)
472 return;
473
474 dn = (struct dn_neigh *) neigh;
475 if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
476 return;
477
478 dn_db = (struct dn_dev *) s->dev->dn_ptr;
479 if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
480 return;
481
482 if (s->t == s->n)
483 s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
484 else
485 s->t++;
486 if (s->rs == NULL)
487 return;
488
489 dn_dn2eth(s->rs, dn->addr);
490 s->rs += 6;
491 *(s->rs) = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
492 *(s->rs) |= dn->priority;
493 s->rs++;
494 }
495
dn_neigh_elist(struct net_device * dev,unsigned char * ptr,int n)496 int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
497 {
498 struct elist_cb_state state;
499
500 state.dev = dev;
501 state.t = 0;
502 state.n = n;
503 state.ptr = ptr;
504 state.rs = ptr;
505
506 neigh_for_each(&dn_neigh_table, neigh_elist_cb, &state);
507
508 return state.t;
509 }
510
511 #endif /* CONFIG_DECNET_ROUTER */
512
513
514
515 #ifdef CONFIG_PROC_FS
516
dn_neigh_format_entry(struct seq_file * seq,struct neighbour * n)517 static inline void dn_neigh_format_entry(struct seq_file *seq,
518 struct neighbour *n)
519 {
520 struct dn_neigh *dn = (struct dn_neigh *) n;
521 char buf[DN_ASCBUF_LEN];
522
523 read_lock(&n->lock);
524 seq_printf(seq, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
525 dn_addr2asc(dn_ntohs(dn->addr), buf),
526 (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
527 (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
528 (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
529 dn->n.nud_state,
530 atomic_read(&dn->n.refcnt),
531 dn->blksize,
532 (dn->n.dev) ? dn->n.dev->name : "?");
533 read_unlock(&n->lock);
534 }
535
dn_neigh_seq_show(struct seq_file * seq,void * v)536 static int dn_neigh_seq_show(struct seq_file *seq, void *v)
537 {
538 if (v == SEQ_START_TOKEN) {
539 seq_puts(seq, "Addr Flags State Use Blksize Dev\n");
540 } else {
541 dn_neigh_format_entry(seq, v);
542 }
543
544 return 0;
545 }
546
dn_neigh_seq_start(struct seq_file * seq,loff_t * pos)547 static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
548 {
549 return neigh_seq_start(seq, pos, &dn_neigh_table,
550 NEIGH_SEQ_NEIGH_ONLY);
551 }
552
553 static struct seq_operations dn_neigh_seq_ops = {
554 .start = dn_neigh_seq_start,
555 .next = neigh_seq_next,
556 .stop = neigh_seq_stop,
557 .show = dn_neigh_seq_show,
558 };
559
dn_neigh_seq_open(struct inode * inode,struct file * file)560 static int dn_neigh_seq_open(struct inode *inode, struct file *file)
561 {
562 struct seq_file *seq;
563 int rc = -ENOMEM;
564 struct neigh_seq_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
565
566 if (!s)
567 goto out;
568
569 memset(s, 0, sizeof(*s));
570 rc = seq_open(file, &dn_neigh_seq_ops);
571 if (rc)
572 goto out_kfree;
573
574 seq = file->private_data;
575 seq->private = s;
576 memset(s, 0, sizeof(*s));
577 out:
578 return rc;
579 out_kfree:
580 kfree(s);
581 goto out;
582 }
583
584 static struct file_operations dn_neigh_seq_fops = {
585 .owner = THIS_MODULE,
586 .open = dn_neigh_seq_open,
587 .read = seq_read,
588 .llseek = seq_lseek,
589 .release = seq_release_private,
590 };
591
592 #endif
593
dn_neigh_init(void)594 void __init dn_neigh_init(void)
595 {
596 neigh_table_init(&dn_neigh_table);
597 proc_net_fops_create("decnet_neigh", S_IRUGO, &dn_neigh_seq_fops);
598 }
599
dn_neigh_cleanup(void)600 void __exit dn_neigh_cleanup(void)
601 {
602 proc_net_remove("decnet_neigh");
603 neigh_table_clear(&dn_neigh_table);
604 }
605