0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <linux/net.h>
0029 #include <linux/module.h>
0030 #include <linux/socket.h>
0031 #include <linux/if_arp.h>
0032 #include <linux/slab.h>
0033 #include <linux/if_ether.h>
0034 #include <linux/init.h>
0035 #include <linux/proc_fs.h>
0036 #include <linux/string.h>
0037 #include <linux/netfilter_decnet.h>
0038 #include <linux/spinlock.h>
0039 #include <linux/seq_file.h>
0040 #include <linux/rcupdate.h>
0041 #include <linux/jhash.h>
0042 #include <linux/atomic.h>
0043 #include <net/net_namespace.h>
0044 #include <net/neighbour.h>
0045 #include <net/dst.h>
0046 #include <net/flow.h>
0047 #include <net/dn.h>
0048 #include <net/dn_dev.h>
0049 #include <net/dn_neigh.h>
0050 #include <net/dn_route.h>
0051
0052 static int dn_neigh_construct(struct neighbour *);
0053 static void dn_neigh_error_report(struct neighbour *, struct sk_buff *);
0054 static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb);
0055
0056
0057
0058
0059 static const struct neigh_ops dn_neigh_ops = {
0060 .family = AF_DECnet,
0061 .error_report = dn_neigh_error_report,
0062 .output = dn_neigh_output,
0063 .connected_output = dn_neigh_output,
0064 };
0065
0066 static u32 dn_neigh_hash(const void *pkey,
0067 const struct net_device *dev,
0068 __u32 *hash_rnd)
0069 {
0070 return jhash_2words(*(__u16 *)pkey, 0, hash_rnd[0]);
0071 }
0072
0073 static bool dn_key_eq(const struct neighbour *neigh, const void *pkey)
0074 {
0075 return neigh_key_eq16(neigh, pkey);
0076 }
0077
0078 struct neigh_table dn_neigh_table = {
0079 .family = PF_DECnet,
0080 .entry_size = NEIGH_ENTRY_SIZE(sizeof(struct dn_neigh)),
0081 .key_len = sizeof(__le16),
0082 .protocol = cpu_to_be16(ETH_P_DNA_RT),
0083 .hash = dn_neigh_hash,
0084 .key_eq = dn_key_eq,
0085 .constructor = dn_neigh_construct,
0086 .id = "dn_neigh_cache",
0087 .parms ={
0088 .tbl = &dn_neigh_table,
0089 .reachable_time = 30 * HZ,
0090 .data = {
0091 [NEIGH_VAR_MCAST_PROBES] = 0,
0092 [NEIGH_VAR_UCAST_PROBES] = 0,
0093 [NEIGH_VAR_APP_PROBES] = 0,
0094 [NEIGH_VAR_RETRANS_TIME] = 1 * HZ,
0095 [NEIGH_VAR_BASE_REACHABLE_TIME] = 30 * HZ,
0096 [NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
0097 [NEIGH_VAR_INTERVAL_PROBE_TIME_MS] = 5 * HZ,
0098 [NEIGH_VAR_GC_STALETIME] = 60 * HZ,
0099 [NEIGH_VAR_QUEUE_LEN_BYTES] = SK_WMEM_MAX,
0100 [NEIGH_VAR_PROXY_QLEN] = 0,
0101 [NEIGH_VAR_ANYCAST_DELAY] = 0,
0102 [NEIGH_VAR_PROXY_DELAY] = 0,
0103 [NEIGH_VAR_LOCKTIME] = 1 * HZ,
0104 },
0105 },
0106 .gc_interval = 30 * HZ,
0107 .gc_thresh1 = 128,
0108 .gc_thresh2 = 512,
0109 .gc_thresh3 = 1024,
0110 };
0111
0112 static int dn_neigh_construct(struct neighbour *neigh)
0113 {
0114 struct net_device *dev = neigh->dev;
0115 struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n);
0116 struct dn_dev *dn_db;
0117 struct neigh_parms *parms;
0118
0119 rcu_read_lock();
0120 dn_db = rcu_dereference(dev->dn_ptr);
0121 if (dn_db == NULL) {
0122 rcu_read_unlock();
0123 return -EINVAL;
0124 }
0125
0126 parms = dn_db->neigh_parms;
0127 if (!parms) {
0128 rcu_read_unlock();
0129 return -EINVAL;
0130 }
0131
0132 __neigh_parms_put(neigh->parms);
0133 neigh->parms = neigh_parms_clone(parms);
0134 rcu_read_unlock();
0135
0136 neigh->ops = &dn_neigh_ops;
0137 neigh->nud_state = NUD_NOARP;
0138 neigh->output = neigh->ops->connected_output;
0139
0140 if ((dev->type == ARPHRD_IPGRE) || (dev->flags & IFF_POINTOPOINT))
0141 memcpy(neigh->ha, dev->broadcast, dev->addr_len);
0142 else if ((dev->type == ARPHRD_ETHER) || (dev->type == ARPHRD_LOOPBACK))
0143 dn_dn2eth(neigh->ha, dn->addr);
0144 else {
0145 net_dbg_ratelimited("Trying to create neigh for hw %d\n",
0146 dev->type);
0147 return -EINVAL;
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163 dn->blksize = dev->mtu - 2;
0164
0165 return 0;
0166 }
0167
0168 static void dn_neigh_error_report(struct neighbour *neigh, struct sk_buff *skb)
0169 {
0170 printk(KERN_DEBUG "dn_neigh_error_report: called\n");
0171 kfree_skb(skb);
0172 }
0173
0174 static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb)
0175 {
0176 struct dst_entry *dst = skb_dst(skb);
0177 struct dn_route *rt = (struct dn_route *)dst;
0178 struct net_device *dev = neigh->dev;
0179 char mac_addr[ETH_ALEN];
0180 unsigned int seq;
0181 int err;
0182
0183 dn_dn2eth(mac_addr, rt->rt_local_src);
0184 do {
0185 seq = read_seqbegin(&neigh->ha_lock);
0186 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
0187 neigh->ha, mac_addr, skb->len);
0188 } while (read_seqretry(&neigh->ha_lock, seq));
0189
0190 if (err >= 0)
0191 err = dev_queue_xmit(skb);
0192 else {
0193 kfree_skb(skb);
0194 err = -EINVAL;
0195 }
0196 return err;
0197 }
0198
0199 static int dn_neigh_output_packet(struct net *net, struct sock *sk, struct sk_buff *skb)
0200 {
0201 struct dst_entry *dst = skb_dst(skb);
0202 struct dn_route *rt = (struct dn_route *)dst;
0203 struct neighbour *neigh = rt->n;
0204
0205 return neigh->output(neigh, skb);
0206 }
0207
0208
0209
0210
0211 static int dn_long_output(struct neighbour *neigh, struct sock *sk,
0212 struct sk_buff *skb)
0213 {
0214 struct net_device *dev = neigh->dev;
0215 int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
0216 unsigned char *data;
0217 struct dn_long_packet *lp;
0218 struct dn_skb_cb *cb = DN_SKB_CB(skb);
0219
0220
0221 if (skb_headroom(skb) < headroom) {
0222 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
0223 if (skb2 == NULL) {
0224 net_crit_ratelimited("dn_long_output: no memory\n");
0225 kfree_skb(skb);
0226 return -ENOBUFS;
0227 }
0228 consume_skb(skb);
0229 skb = skb2;
0230 net_info_ratelimited("dn_long_output: Increasing headroom\n");
0231 }
0232
0233 data = skb_push(skb, sizeof(struct dn_long_packet) + 3);
0234 lp = (struct dn_long_packet *)(data+3);
0235
0236 *((__le16 *)data) = cpu_to_le16(skb->len - 2);
0237 *(data + 2) = 1 | DN_RT_F_PF;
0238
0239 lp->msgflg = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS));
0240 lp->d_area = lp->d_subarea = 0;
0241 dn_dn2eth(lp->d_id, cb->dst);
0242 lp->s_area = lp->s_subarea = 0;
0243 dn_dn2eth(lp->s_id, cb->src);
0244 lp->nl2 = 0;
0245 lp->visit_ct = cb->hops & 0x3f;
0246 lp->s_class = 0;
0247 lp->pt = 0;
0248
0249 skb_reset_network_header(skb);
0250
0251 return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING,
0252 &init_net, sk, skb, NULL, neigh->dev,
0253 dn_neigh_output_packet);
0254 }
0255
0256
0257
0258
0259 static int dn_short_output(struct neighbour *neigh, struct sock *sk,
0260 struct sk_buff *skb)
0261 {
0262 struct net_device *dev = neigh->dev;
0263 int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
0264 struct dn_short_packet *sp;
0265 unsigned char *data;
0266 struct dn_skb_cb *cb = DN_SKB_CB(skb);
0267
0268
0269 if (skb_headroom(skb) < headroom) {
0270 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
0271 if (skb2 == NULL) {
0272 net_crit_ratelimited("dn_short_output: no memory\n");
0273 kfree_skb(skb);
0274 return -ENOBUFS;
0275 }
0276 consume_skb(skb);
0277 skb = skb2;
0278 net_info_ratelimited("dn_short_output: Increasing headroom\n");
0279 }
0280
0281 data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
0282 *((__le16 *)data) = cpu_to_le16(skb->len - 2);
0283 sp = (struct dn_short_packet *)(data+2);
0284
0285 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
0286 sp->dstnode = cb->dst;
0287 sp->srcnode = cb->src;
0288 sp->forward = cb->hops & 0x3f;
0289
0290 skb_reset_network_header(skb);
0291
0292 return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING,
0293 &init_net, sk, skb, NULL, neigh->dev,
0294 dn_neigh_output_packet);
0295 }
0296
0297
0298
0299
0300
0301
0302 static int dn_phase3_output(struct neighbour *neigh, struct sock *sk,
0303 struct sk_buff *skb)
0304 {
0305 struct net_device *dev = neigh->dev;
0306 int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
0307 struct dn_short_packet *sp;
0308 unsigned char *data;
0309 struct dn_skb_cb *cb = DN_SKB_CB(skb);
0310
0311 if (skb_headroom(skb) < headroom) {
0312 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
0313 if (skb2 == NULL) {
0314 net_crit_ratelimited("dn_phase3_output: no memory\n");
0315 kfree_skb(skb);
0316 return -ENOBUFS;
0317 }
0318 consume_skb(skb);
0319 skb = skb2;
0320 net_info_ratelimited("dn_phase3_output: Increasing headroom\n");
0321 }
0322
0323 data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
0324 *((__le16 *)data) = cpu_to_le16(skb->len - 2);
0325 sp = (struct dn_short_packet *)(data + 2);
0326
0327 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
0328 sp->dstnode = cb->dst & cpu_to_le16(0x03ff);
0329 sp->srcnode = cb->src & cpu_to_le16(0x03ff);
0330 sp->forward = cb->hops & 0x3f;
0331
0332 skb_reset_network_header(skb);
0333
0334 return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING,
0335 &init_net, sk, skb, NULL, neigh->dev,
0336 dn_neigh_output_packet);
0337 }
0338
0339 int dn_to_neigh_output(struct net *net, struct sock *sk, struct sk_buff *skb)
0340 {
0341 struct dst_entry *dst = skb_dst(skb);
0342 struct dn_route *rt = (struct dn_route *) dst;
0343 struct neighbour *neigh = rt->n;
0344 struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n);
0345 struct dn_dev *dn_db;
0346 bool use_long;
0347
0348 rcu_read_lock();
0349 dn_db = rcu_dereference(neigh->dev->dn_ptr);
0350 if (dn_db == NULL) {
0351 rcu_read_unlock();
0352 return -EINVAL;
0353 }
0354 use_long = dn_db->use_long;
0355 rcu_read_unlock();
0356
0357 if (dn->flags & DN_NDFLAG_P3)
0358 return dn_phase3_output(neigh, sk, skb);
0359 if (use_long)
0360 return dn_long_output(neigh, sk, skb);
0361 else
0362 return dn_short_output(neigh, sk, skb);
0363 }
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375 void dn_neigh_pointopoint_hello(struct sk_buff *skb)
0376 {
0377 kfree_skb(skb);
0378 }
0379
0380
0381
0382
0383 int dn_neigh_router_hello(struct net *net, struct sock *sk, struct sk_buff *skb)
0384 {
0385 struct rtnode_hello_message *msg = (struct rtnode_hello_message *)skb->data;
0386
0387 struct neighbour *neigh;
0388 struct dn_neigh *dn;
0389 struct dn_dev *dn_db;
0390 __le16 src;
0391
0392 src = dn_eth2dn(msg->id);
0393
0394 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
0395
0396 dn = container_of(neigh, struct dn_neigh, n);
0397
0398 if (neigh) {
0399 write_lock(&neigh->lock);
0400
0401 neigh->used = jiffies;
0402 dn_db = rcu_dereference(neigh->dev->dn_ptr);
0403
0404 if (!(neigh->nud_state & NUD_PERMANENT)) {
0405 neigh->updated = jiffies;
0406
0407 if (neigh->dev->type == ARPHRD_ETHER)
0408 memcpy(neigh->ha, ð_hdr(skb)->h_source, ETH_ALEN);
0409
0410 dn->blksize = le16_to_cpu(msg->blksize);
0411 dn->priority = msg->priority;
0412
0413 dn->flags &= ~DN_NDFLAG_P3;
0414
0415 switch (msg->iinfo & DN_RT_INFO_TYPE) {
0416 case DN_RT_INFO_L1RT:
0417 dn->flags &=~DN_NDFLAG_R2;
0418 dn->flags |= DN_NDFLAG_R1;
0419 break;
0420 case DN_RT_INFO_L2RT:
0421 dn->flags |= DN_NDFLAG_R2;
0422 }
0423 }
0424
0425
0426 if ((le16_to_cpu(src)>>10) == (le16_to_cpu((decnet_address))>>10)) {
0427 if (!dn_db->router) {
0428 dn_db->router = neigh_clone(neigh);
0429 } else {
0430 if (msg->priority > container_of(dn_db->router,
0431 struct dn_neigh, n)->priority)
0432 neigh_release(xchg(&dn_db->router, neigh_clone(neigh)));
0433 }
0434 }
0435 write_unlock(&neigh->lock);
0436 neigh_release(neigh);
0437 }
0438
0439 kfree_skb(skb);
0440 return 0;
0441 }
0442
0443
0444
0445
0446 int dn_neigh_endnode_hello(struct net *net, struct sock *sk, struct sk_buff *skb)
0447 {
0448 struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data;
0449 struct neighbour *neigh;
0450 struct dn_neigh *dn;
0451 __le16 src;
0452
0453 src = dn_eth2dn(msg->id);
0454
0455 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
0456
0457 dn = container_of(neigh, struct dn_neigh, n);
0458
0459 if (neigh) {
0460 write_lock(&neigh->lock);
0461
0462 neigh->used = jiffies;
0463
0464 if (!(neigh->nud_state & NUD_PERMANENT)) {
0465 neigh->updated = jiffies;
0466
0467 if (neigh->dev->type == ARPHRD_ETHER)
0468 memcpy(neigh->ha, ð_hdr(skb)->h_source, ETH_ALEN);
0469 dn->flags &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
0470 dn->blksize = le16_to_cpu(msg->blksize);
0471 dn->priority = 0;
0472 }
0473
0474 write_unlock(&neigh->lock);
0475 neigh_release(neigh);
0476 }
0477
0478 kfree_skb(skb);
0479 return 0;
0480 }
0481
0482 static char *dn_find_slot(char *base, int max, int priority)
0483 {
0484 int i;
0485 unsigned char *min = NULL;
0486
0487 base += 6;
0488
0489 for(i = 0; i < max; i++) {
0490 if (!min || (*base < *min))
0491 min = base;
0492 base += 7;
0493 }
0494
0495 if (!min)
0496 return NULL;
0497
0498 return (*min < priority) ? (min - 6) : NULL;
0499 }
0500
0501 struct elist_cb_state {
0502 struct net_device *dev;
0503 unsigned char *ptr;
0504 unsigned char *rs;
0505 int t, n;
0506 };
0507
0508 static void neigh_elist_cb(struct neighbour *neigh, void *_info)
0509 {
0510 struct elist_cb_state *s = _info;
0511 struct dn_neigh *dn;
0512
0513 if (neigh->dev != s->dev)
0514 return;
0515
0516 dn = container_of(neigh, struct dn_neigh, n);
0517 if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
0518 return;
0519
0520 if (s->t == s->n)
0521 s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
0522 else
0523 s->t++;
0524 if (s->rs == NULL)
0525 return;
0526
0527 dn_dn2eth(s->rs, dn->addr);
0528 s->rs += 6;
0529 *(s->rs) = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
0530 *(s->rs) |= dn->priority;
0531 s->rs++;
0532 }
0533
0534 int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
0535 {
0536 struct elist_cb_state state;
0537
0538 state.dev = dev;
0539 state.t = 0;
0540 state.n = n;
0541 state.ptr = ptr;
0542 state.rs = ptr;
0543
0544 neigh_for_each(&dn_neigh_table, neigh_elist_cb, &state);
0545
0546 return state.t;
0547 }
0548
0549
0550 #ifdef CONFIG_PROC_FS
0551
0552 static inline void dn_neigh_format_entry(struct seq_file *seq,
0553 struct neighbour *n)
0554 {
0555 struct dn_neigh *dn = container_of(n, struct dn_neigh, n);
0556 char buf[DN_ASCBUF_LEN];
0557
0558 read_lock(&n->lock);
0559 seq_printf(seq, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
0560 dn_addr2asc(le16_to_cpu(dn->addr), buf),
0561 (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
0562 (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
0563 (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
0564 dn->n.nud_state,
0565 refcount_read(&dn->n.refcnt),
0566 dn->blksize,
0567 (dn->n.dev) ? dn->n.dev->name : "?");
0568 read_unlock(&n->lock);
0569 }
0570
0571 static int dn_neigh_seq_show(struct seq_file *seq, void *v)
0572 {
0573 if (v == SEQ_START_TOKEN) {
0574 seq_puts(seq, "Addr Flags State Use Blksize Dev\n");
0575 } else {
0576 dn_neigh_format_entry(seq, v);
0577 }
0578
0579 return 0;
0580 }
0581
0582 static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
0583 {
0584 return neigh_seq_start(seq, pos, &dn_neigh_table,
0585 NEIGH_SEQ_NEIGH_ONLY);
0586 }
0587
0588 static const struct seq_operations dn_neigh_seq_ops = {
0589 .start = dn_neigh_seq_start,
0590 .next = neigh_seq_next,
0591 .stop = neigh_seq_stop,
0592 .show = dn_neigh_seq_show,
0593 };
0594 #endif
0595
0596 void __init dn_neigh_init(void)
0597 {
0598 neigh_table_init(NEIGH_DN_TABLE, &dn_neigh_table);
0599 proc_create_net("decnet_neigh", 0444, init_net.proc_net,
0600 &dn_neigh_seq_ops, sizeof(struct neigh_seq_state));
0601 }
0602
0603 void __exit dn_neigh_cleanup(void)
0604 {
0605 remove_proc_entry("decnet_neigh", init_net.proc_net);
0606 neigh_table_clear(NEIGH_DN_TABLE, &dn_neigh_table);
0607 }