Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.37-rc7 612 lines 16 kB view raw
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 * Steve Whitehouse : Convert to seq_file 24 * 25 */ 26 27#include <linux/net.h> 28#include <linux/module.h> 29#include <linux/socket.h> 30#include <linux/if_arp.h> 31#include <linux/slab.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/rcupdate.h> 40#include <linux/jhash.h> 41#include <asm/atomic.h> 42#include <net/net_namespace.h> 43#include <net/neighbour.h> 44#include <net/dst.h> 45#include <net/flow.h> 46#include <net/dn.h> 47#include <net/dn_dev.h> 48#include <net/dn_neigh.h> 49#include <net/dn_route.h> 50 51static int dn_neigh_construct(struct neighbour *); 52static void dn_long_error_report(struct neighbour *, struct sk_buff *); 53static void dn_short_error_report(struct neighbour *, struct sk_buff *); 54static int dn_long_output(struct sk_buff *); 55static int dn_short_output(struct sk_buff *); 56static int dn_phase3_output(struct sk_buff *); 57 58 59/* 60 * For talking to broadcast devices: Ethernet & PPP 61 */ 62static const struct neigh_ops dn_long_ops = { 63 .family = AF_DECnet, 64 .error_report = dn_long_error_report, 65 .output = dn_long_output, 66 .connected_output = dn_long_output, 67 .hh_output = dev_queue_xmit, 68 .queue_xmit = dev_queue_xmit, 69}; 70 71/* 72 * For talking to pointopoint and multidrop devices: DDCMP and X.25 73 */ 74static const struct neigh_ops dn_short_ops = { 75 .family = AF_DECnet, 76 .error_report = dn_short_error_report, 77 .output = dn_short_output, 78 .connected_output = dn_short_output, 79 .hh_output = dev_queue_xmit, 80 .queue_xmit = dev_queue_xmit, 81}; 82 83/* 84 * For talking to DECnet phase III nodes 85 */ 86static const struct neigh_ops dn_phase3_ops = { 87 .family = AF_DECnet, 88 .error_report = dn_short_error_report, /* Can use short version here */ 89 .output = dn_phase3_output, 90 .connected_output = dn_phase3_output, 91 .hh_output = dev_queue_xmit, 92 .queue_xmit = dev_queue_xmit 93}; 94 95static u32 dn_neigh_hash(const void *pkey, 96 const struct net_device *dev, 97 __u32 hash_rnd) 98{ 99 return jhash_2words(*(__u16 *)pkey, 0, hash_rnd); 100} 101 102struct neigh_table dn_neigh_table = { 103 .family = PF_DECnet, 104 .entry_size = sizeof(struct dn_neigh), 105 .key_len = sizeof(__le16), 106 .hash = dn_neigh_hash, 107 .constructor = dn_neigh_construct, 108 .id = "dn_neigh_cache", 109 .parms ={ 110 .tbl = &dn_neigh_table, 111 .base_reachable_time = 30 * HZ, 112 .retrans_time = 1 * HZ, 113 .gc_staletime = 60 * HZ, 114 .reachable_time = 30 * HZ, 115 .delay_probe_time = 5 * HZ, 116 .queue_len = 3, 117 .ucast_probes = 0, 118 .app_probes = 0, 119 .mcast_probes = 0, 120 .anycast_delay = 0, 121 .proxy_delay = 0, 122 .proxy_qlen = 0, 123 .locktime = 1 * HZ, 124 }, 125 .gc_interval = 30 * HZ, 126 .gc_thresh1 = 128, 127 .gc_thresh2 = 512, 128 .gc_thresh3 = 1024, 129}; 130 131static int dn_neigh_construct(struct neighbour *neigh) 132{ 133 struct net_device *dev = neigh->dev; 134 struct dn_neigh *dn = (struct dn_neigh *)neigh; 135 struct dn_dev *dn_db; 136 struct neigh_parms *parms; 137 138 rcu_read_lock(); 139 dn_db = rcu_dereference(dev->dn_ptr); 140 if (dn_db == NULL) { 141 rcu_read_unlock(); 142 return -EINVAL; 143 } 144 145 parms = dn_db->neigh_parms; 146 if (!parms) { 147 rcu_read_unlock(); 148 return -EINVAL; 149 } 150 151 __neigh_parms_put(neigh->parms); 152 neigh->parms = neigh_parms_clone(parms); 153 154 if (dn_db->use_long) 155 neigh->ops = &dn_long_ops; 156 else 157 neigh->ops = &dn_short_ops; 158 rcu_read_unlock(); 159 160 if (dn->flags & DN_NDFLAG_P3) 161 neigh->ops = &dn_phase3_ops; 162 163 neigh->nud_state = NUD_NOARP; 164 neigh->output = neigh->ops->connected_output; 165 166 if ((dev->type == ARPHRD_IPGRE) || (dev->flags & IFF_POINTOPOINT)) 167 memcpy(neigh->ha, dev->broadcast, dev->addr_len); 168 else if ((dev->type == ARPHRD_ETHER) || (dev->type == ARPHRD_LOOPBACK)) 169 dn_dn2eth(neigh->ha, dn->addr); 170 else { 171 if (net_ratelimit()) 172 printk(KERN_DEBUG "Trying to create neigh for hw %d\n", dev->type); 173 return -EINVAL; 174 } 175 176 /* 177 * Make an estimate of the remote block size by assuming that its 178 * two less then the device mtu, which it true for ethernet (and 179 * other things which support long format headers) since there is 180 * an extra length field (of 16 bits) which isn't part of the 181 * ethernet headers and which the DECnet specs won't admit is part 182 * of the DECnet routing headers either. 183 * 184 * If we over estimate here its no big deal, the NSP negotiations 185 * will prevent us from sending packets which are too large for the 186 * remote node to handle. In any case this figure is normally updated 187 * by a hello message in most cases. 188 */ 189 dn->blksize = dev->mtu - 2; 190 191 return 0; 192} 193 194static void dn_long_error_report(struct neighbour *neigh, struct sk_buff *skb) 195{ 196 printk(KERN_DEBUG "dn_long_error_report: called\n"); 197 kfree_skb(skb); 198} 199 200 201static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb) 202{ 203 printk(KERN_DEBUG "dn_short_error_report: called\n"); 204 kfree_skb(skb); 205} 206 207static int dn_neigh_output_packet(struct sk_buff *skb) 208{ 209 struct dst_entry *dst = skb_dst(skb); 210 struct dn_route *rt = (struct dn_route *)dst; 211 struct neighbour *neigh = dst->neighbour; 212 struct net_device *dev = neigh->dev; 213 char mac_addr[ETH_ALEN]; 214 215 dn_dn2eth(mac_addr, rt->rt_local_src); 216 if (dev_hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, 217 mac_addr, skb->len) >= 0) 218 return neigh->ops->queue_xmit(skb); 219 220 if (net_ratelimit()) 221 printk(KERN_DEBUG "dn_neigh_output_packet: oops, can't send packet\n"); 222 223 kfree_skb(skb); 224 return -EINVAL; 225} 226 227static int dn_long_output(struct sk_buff *skb) 228{ 229 struct dst_entry *dst = skb_dst(skb); 230 struct neighbour *neigh = dst->neighbour; 231 struct net_device *dev = neigh->dev; 232 int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3; 233 unsigned char *data; 234 struct dn_long_packet *lp; 235 struct dn_skb_cb *cb = DN_SKB_CB(skb); 236 237 238 if (skb_headroom(skb) < headroom) { 239 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom); 240 if (skb2 == NULL) { 241 if (net_ratelimit()) 242 printk(KERN_CRIT "dn_long_output: no memory\n"); 243 kfree_skb(skb); 244 return -ENOBUFS; 245 } 246 kfree_skb(skb); 247 skb = skb2; 248 if (net_ratelimit()) 249 printk(KERN_INFO "dn_long_output: Increasing headroom\n"); 250 } 251 252 data = skb_push(skb, sizeof(struct dn_long_packet) + 3); 253 lp = (struct dn_long_packet *)(data+3); 254 255 *((__le16 *)data) = cpu_to_le16(skb->len - 2); 256 *(data + 2) = 1 | DN_RT_F_PF; /* Padding */ 257 258 lp->msgflg = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS)); 259 lp->d_area = lp->d_subarea = 0; 260 dn_dn2eth(lp->d_id, cb->dst); 261 lp->s_area = lp->s_subarea = 0; 262 dn_dn2eth(lp->s_id, cb->src); 263 lp->nl2 = 0; 264 lp->visit_ct = cb->hops & 0x3f; 265 lp->s_class = 0; 266 lp->pt = 0; 267 268 skb_reset_network_header(skb); 269 270 return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, skb, NULL, 271 neigh->dev, dn_neigh_output_packet); 272} 273 274static int dn_short_output(struct sk_buff *skb) 275{ 276 struct dst_entry *dst = skb_dst(skb); 277 struct neighbour *neigh = dst->neighbour; 278 struct net_device *dev = neigh->dev; 279 int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; 280 struct dn_short_packet *sp; 281 unsigned char *data; 282 struct dn_skb_cb *cb = DN_SKB_CB(skb); 283 284 285 if (skb_headroom(skb) < headroom) { 286 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom); 287 if (skb2 == NULL) { 288 if (net_ratelimit()) 289 printk(KERN_CRIT "dn_short_output: no memory\n"); 290 kfree_skb(skb); 291 return -ENOBUFS; 292 } 293 kfree_skb(skb); 294 skb = skb2; 295 if (net_ratelimit()) 296 printk(KERN_INFO "dn_short_output: Increasing headroom\n"); 297 } 298 299 data = skb_push(skb, sizeof(struct dn_short_packet) + 2); 300 *((__le16 *)data) = cpu_to_le16(skb->len - 2); 301 sp = (struct dn_short_packet *)(data+2); 302 303 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS)); 304 sp->dstnode = cb->dst; 305 sp->srcnode = cb->src; 306 sp->forward = cb->hops & 0x3f; 307 308 skb_reset_network_header(skb); 309 310 return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, skb, NULL, 311 neigh->dev, dn_neigh_output_packet); 312} 313 314/* 315 * Phase 3 output is the same is short output, execpt that 316 * it clears the area bits before transmission. 317 */ 318static int dn_phase3_output(struct sk_buff *skb) 319{ 320 struct dst_entry *dst = skb_dst(skb); 321 struct neighbour *neigh = dst->neighbour; 322 struct net_device *dev = neigh->dev; 323 int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; 324 struct dn_short_packet *sp; 325 unsigned char *data; 326 struct dn_skb_cb *cb = DN_SKB_CB(skb); 327 328 if (skb_headroom(skb) < headroom) { 329 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom); 330 if (skb2 == NULL) { 331 if (net_ratelimit()) 332 printk(KERN_CRIT "dn_phase3_output: no memory\n"); 333 kfree_skb(skb); 334 return -ENOBUFS; 335 } 336 kfree_skb(skb); 337 skb = skb2; 338 if (net_ratelimit()) 339 printk(KERN_INFO "dn_phase3_output: Increasing headroom\n"); 340 } 341 342 data = skb_push(skb, sizeof(struct dn_short_packet) + 2); 343 *((__le16 *)data) = cpu_to_le16(skb->len - 2); 344 sp = (struct dn_short_packet *)(data + 2); 345 346 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS)); 347 sp->dstnode = cb->dst & cpu_to_le16(0x03ff); 348 sp->srcnode = cb->src & cpu_to_le16(0x03ff); 349 sp->forward = cb->hops & 0x3f; 350 351 skb_reset_network_header(skb); 352 353 return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, skb, NULL, 354 neigh->dev, dn_neigh_output_packet); 355} 356 357/* 358 * Unfortunately, the neighbour code uses the device in its hash 359 * function, so we don't get any advantage from it. This function 360 * basically does a neigh_lookup(), but without comparing the device 361 * field. This is required for the On-Ethernet cache 362 */ 363 364/* 365 * Pointopoint link receives a hello message 366 */ 367void dn_neigh_pointopoint_hello(struct sk_buff *skb) 368{ 369 kfree_skb(skb); 370} 371 372/* 373 * Ethernet router hello message received 374 */ 375int dn_neigh_router_hello(struct sk_buff *skb) 376{ 377 struct rtnode_hello_message *msg = (struct rtnode_hello_message *)skb->data; 378 379 struct neighbour *neigh; 380 struct dn_neigh *dn; 381 struct dn_dev *dn_db; 382 __le16 src; 383 384 src = dn_eth2dn(msg->id); 385 386 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); 387 388 dn = (struct dn_neigh *)neigh; 389 390 if (neigh) { 391 write_lock(&neigh->lock); 392 393 neigh->used = jiffies; 394 dn_db = (struct dn_dev *)neigh->dev->dn_ptr; 395 396 if (!(neigh->nud_state & NUD_PERMANENT)) { 397 neigh->updated = jiffies; 398 399 if (neigh->dev->type == ARPHRD_ETHER) 400 memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN); 401 402 dn->blksize = le16_to_cpu(msg->blksize); 403 dn->priority = msg->priority; 404 405 dn->flags &= ~DN_NDFLAG_P3; 406 407 switch(msg->iinfo & DN_RT_INFO_TYPE) { 408 case DN_RT_INFO_L1RT: 409 dn->flags &=~DN_NDFLAG_R2; 410 dn->flags |= DN_NDFLAG_R1; 411 break; 412 case DN_RT_INFO_L2RT: 413 dn->flags |= DN_NDFLAG_R2; 414 } 415 } 416 417 /* Only use routers in our area */ 418 if ((le16_to_cpu(src)>>10) == (le16_to_cpu((decnet_address))>>10)) { 419 if (!dn_db->router) { 420 dn_db->router = neigh_clone(neigh); 421 } else { 422 if (msg->priority > ((struct dn_neigh *)dn_db->router)->priority) 423 neigh_release(xchg(&dn_db->router, neigh_clone(neigh))); 424 } 425 } 426 write_unlock(&neigh->lock); 427 neigh_release(neigh); 428 } 429 430 kfree_skb(skb); 431 return 0; 432} 433 434/* 435 * Endnode hello message received 436 */ 437int dn_neigh_endnode_hello(struct sk_buff *skb) 438{ 439 struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data; 440 struct neighbour *neigh; 441 struct dn_neigh *dn; 442 __le16 src; 443 444 src = dn_eth2dn(msg->id); 445 446 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); 447 448 dn = (struct dn_neigh *)neigh; 449 450 if (neigh) { 451 write_lock(&neigh->lock); 452 453 neigh->used = jiffies; 454 455 if (!(neigh->nud_state & NUD_PERMANENT)) { 456 neigh->updated = jiffies; 457 458 if (neigh->dev->type == ARPHRD_ETHER) 459 memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN); 460 dn->flags &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2); 461 dn->blksize = le16_to_cpu(msg->blksize); 462 dn->priority = 0; 463 } 464 465 write_unlock(&neigh->lock); 466 neigh_release(neigh); 467 } 468 469 kfree_skb(skb); 470 return 0; 471} 472 473static char *dn_find_slot(char *base, int max, int priority) 474{ 475 int i; 476 unsigned char *min = NULL; 477 478 base += 6; /* skip first id */ 479 480 for(i = 0; i < max; i++) { 481 if (!min || (*base < *min)) 482 min = base; 483 base += 7; /* find next priority */ 484 } 485 486 if (!min) 487 return NULL; 488 489 return (*min < priority) ? (min - 6) : NULL; 490} 491 492struct elist_cb_state { 493 struct net_device *dev; 494 unsigned char *ptr; 495 unsigned char *rs; 496 int t, n; 497}; 498 499static void neigh_elist_cb(struct neighbour *neigh, void *_info) 500{ 501 struct elist_cb_state *s = _info; 502 struct dn_neigh *dn; 503 504 if (neigh->dev != s->dev) 505 return; 506 507 dn = (struct dn_neigh *) neigh; 508 if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2))) 509 return; 510 511 if (s->t == s->n) 512 s->rs = dn_find_slot(s->ptr, s->n, dn->priority); 513 else 514 s->t++; 515 if (s->rs == NULL) 516 return; 517 518 dn_dn2eth(s->rs, dn->addr); 519 s->rs += 6; 520 *(s->rs) = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0; 521 *(s->rs) |= dn->priority; 522 s->rs++; 523} 524 525int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n) 526{ 527 struct elist_cb_state state; 528 529 state.dev = dev; 530 state.t = 0; 531 state.n = n; 532 state.ptr = ptr; 533 state.rs = ptr; 534 535 neigh_for_each(&dn_neigh_table, neigh_elist_cb, &state); 536 537 return state.t; 538} 539 540 541#ifdef CONFIG_PROC_FS 542 543static inline void dn_neigh_format_entry(struct seq_file *seq, 544 struct neighbour *n) 545{ 546 struct dn_neigh *dn = (struct dn_neigh *) n; 547 char buf[DN_ASCBUF_LEN]; 548 549 read_lock(&n->lock); 550 seq_printf(seq, "%-7s %s%s%s %02x %02d %07ld %-8s\n", 551 dn_addr2asc(le16_to_cpu(dn->addr), buf), 552 (dn->flags&DN_NDFLAG_R1) ? "1" : "-", 553 (dn->flags&DN_NDFLAG_R2) ? "2" : "-", 554 (dn->flags&DN_NDFLAG_P3) ? "3" : "-", 555 dn->n.nud_state, 556 atomic_read(&dn->n.refcnt), 557 dn->blksize, 558 (dn->n.dev) ? dn->n.dev->name : "?"); 559 read_unlock(&n->lock); 560} 561 562static int dn_neigh_seq_show(struct seq_file *seq, void *v) 563{ 564 if (v == SEQ_START_TOKEN) { 565 seq_puts(seq, "Addr Flags State Use Blksize Dev\n"); 566 } else { 567 dn_neigh_format_entry(seq, v); 568 } 569 570 return 0; 571} 572 573static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos) 574{ 575 return neigh_seq_start(seq, pos, &dn_neigh_table, 576 NEIGH_SEQ_NEIGH_ONLY); 577} 578 579static const struct seq_operations dn_neigh_seq_ops = { 580 .start = dn_neigh_seq_start, 581 .next = neigh_seq_next, 582 .stop = neigh_seq_stop, 583 .show = dn_neigh_seq_show, 584}; 585 586static int dn_neigh_seq_open(struct inode *inode, struct file *file) 587{ 588 return seq_open_net(inode, file, &dn_neigh_seq_ops, 589 sizeof(struct neigh_seq_state)); 590} 591 592static const struct file_operations dn_neigh_seq_fops = { 593 .owner = THIS_MODULE, 594 .open = dn_neigh_seq_open, 595 .read = seq_read, 596 .llseek = seq_lseek, 597 .release = seq_release_net, 598}; 599 600#endif 601 602void __init dn_neigh_init(void) 603{ 604 neigh_table_init(&dn_neigh_table); 605 proc_net_fops_create(&init_net, "decnet_neigh", S_IRUGO, &dn_neigh_seq_fops); 606} 607 608void __exit dn_neigh_cleanup(void) 609{ 610 proc_net_remove(&init_net, "decnet_neigh"); 611 neigh_table_clear(&dn_neigh_table); 612}