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/capability.h>
0029 #include <linux/module.h>
0030 #include <linux/moduleparam.h>
0031 #include <linux/init.h>
0032 #include <linux/net.h>
0033 #include <linux/netdevice.h>
0034 #include <linux/proc_fs.h>
0035 #include <linux/seq_file.h>
0036 #include <linux/timer.h>
0037 #include <linux/string.h>
0038 #include <linux/if_addr.h>
0039 #include <linux/if_arp.h>
0040 #include <linux/if_ether.h>
0041 #include <linux/skbuff.h>
0042 #include <linux/sysctl.h>
0043 #include <linux/notifier.h>
0044 #include <linux/slab.h>
0045 #include <linux/jiffies.h>
0046 #include <linux/uaccess.h>
0047 #include <net/net_namespace.h>
0048 #include <net/neighbour.h>
0049 #include <net/dst.h>
0050 #include <net/flow.h>
0051 #include <net/fib_rules.h>
0052 #include <net/netlink.h>
0053 #include <net/dn.h>
0054 #include <net/dn_dev.h>
0055 #include <net/dn_route.h>
0056 #include <net/dn_neigh.h>
0057 #include <net/dn_fib.h>
0058
0059 #define DN_IFREQ_SIZE (offsetof(struct ifreq, ifr_ifru) + sizeof(struct sockaddr_dn))
0060
0061 static char dn_rt_all_end_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x04,0x00,0x00};
0062 static char dn_rt_all_rt_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x03,0x00,0x00};
0063 static char dn_hiord[ETH_ALEN] = {0xAA,0x00,0x04,0x00,0x00,0x00};
0064 static unsigned char dn_eco_version[3] = {0x02,0x00,0x00};
0065
0066 extern struct neigh_table dn_neigh_table;
0067
0068
0069
0070
0071 __le16 decnet_address = 0;
0072
0073 static DEFINE_SPINLOCK(dndev_lock);
0074 static struct net_device *decnet_default_device;
0075 static BLOCKING_NOTIFIER_HEAD(dnaddr_chain);
0076
0077 static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
0078 static void dn_dev_delete(struct net_device *dev);
0079 static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa);
0080
0081 static int dn_eth_up(struct net_device *);
0082 static void dn_eth_down(struct net_device *);
0083 static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa);
0084 static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa);
0085
0086 static struct dn_dev_parms dn_dev_list[] = {
0087 {
0088 .type = ARPHRD_ETHER,
0089 .mode = DN_DEV_BCAST,
0090 .state = DN_DEV_S_RU,
0091 .t2 = 1,
0092 .t3 = 10,
0093 .name = "ethernet",
0094 .up = dn_eth_up,
0095 .down = dn_eth_down,
0096 .timer3 = dn_send_brd_hello,
0097 },
0098 {
0099 .type = ARPHRD_IPGRE,
0100 .mode = DN_DEV_BCAST,
0101 .state = DN_DEV_S_RU,
0102 .t2 = 1,
0103 .t3 = 10,
0104 .name = "ipgre",
0105 .timer3 = dn_send_brd_hello,
0106 },
0107 #if 0
0108 {
0109 .type = ARPHRD_X25,
0110 .mode = DN_DEV_UCAST,
0111 .state = DN_DEV_S_DS,
0112 .t2 = 1,
0113 .t3 = 120,
0114 .name = "x25",
0115 .timer3 = dn_send_ptp_hello,
0116 },
0117 #endif
0118 #if 0
0119 {
0120 .type = ARPHRD_PPP,
0121 .mode = DN_DEV_BCAST,
0122 .state = DN_DEV_S_RU,
0123 .t2 = 1,
0124 .t3 = 10,
0125 .name = "ppp",
0126 .timer3 = dn_send_brd_hello,
0127 },
0128 #endif
0129 {
0130 .type = ARPHRD_DDCMP,
0131 .mode = DN_DEV_UCAST,
0132 .state = DN_DEV_S_DS,
0133 .t2 = 1,
0134 .t3 = 120,
0135 .name = "ddcmp",
0136 .timer3 = dn_send_ptp_hello,
0137 },
0138 {
0139 .type = ARPHRD_LOOPBACK,
0140 .mode = DN_DEV_BCAST,
0141 .state = DN_DEV_S_RU,
0142 .t2 = 1,
0143 .t3 = 10,
0144 .name = "loopback",
0145 .timer3 = dn_send_brd_hello,
0146 }
0147 };
0148
0149 #define DN_DEV_LIST_SIZE ARRAY_SIZE(dn_dev_list)
0150
0151 #define DN_DEV_PARMS_OFFSET(x) offsetof(struct dn_dev_parms, x)
0152
0153 #ifdef CONFIG_SYSCTL
0154
0155 static int min_t2[] = { 1 };
0156 static int max_t2[] = { 60 };
0157 static int min_t3[] = { 1 };
0158 static int max_t3[] = { 8191 };
0159
0160 static int min_priority[1];
0161 static int max_priority[] = { 127 };
0162
0163 static int dn_forwarding_proc(struct ctl_table *, int, void *, size_t *,
0164 loff_t *);
0165 static struct dn_dev_sysctl_table {
0166 struct ctl_table_header *sysctl_header;
0167 struct ctl_table dn_dev_vars[5];
0168 } dn_dev_sysctl = {
0169 NULL,
0170 {
0171 {
0172 .procname = "forwarding",
0173 .data = (void *)DN_DEV_PARMS_OFFSET(forwarding),
0174 .maxlen = sizeof(int),
0175 .mode = 0644,
0176 .proc_handler = dn_forwarding_proc,
0177 },
0178 {
0179 .procname = "priority",
0180 .data = (void *)DN_DEV_PARMS_OFFSET(priority),
0181 .maxlen = sizeof(int),
0182 .mode = 0644,
0183 .proc_handler = proc_dointvec_minmax,
0184 .extra1 = &min_priority,
0185 .extra2 = &max_priority
0186 },
0187 {
0188 .procname = "t2",
0189 .data = (void *)DN_DEV_PARMS_OFFSET(t2),
0190 .maxlen = sizeof(int),
0191 .mode = 0644,
0192 .proc_handler = proc_dointvec_minmax,
0193 .extra1 = &min_t2,
0194 .extra2 = &max_t2
0195 },
0196 {
0197 .procname = "t3",
0198 .data = (void *)DN_DEV_PARMS_OFFSET(t3),
0199 .maxlen = sizeof(int),
0200 .mode = 0644,
0201 .proc_handler = proc_dointvec_minmax,
0202 .extra1 = &min_t3,
0203 .extra2 = &max_t3
0204 },
0205 { }
0206 },
0207 };
0208
0209 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
0210 {
0211 struct dn_dev_sysctl_table *t;
0212 int i;
0213
0214 char path[sizeof("net/decnet/conf/") + IFNAMSIZ];
0215
0216 t = kmemdup(&dn_dev_sysctl, sizeof(*t), GFP_KERNEL);
0217 if (t == NULL)
0218 return;
0219
0220 for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) {
0221 long offset = (long)t->dn_dev_vars[i].data;
0222 t->dn_dev_vars[i].data = ((char *)parms) + offset;
0223 }
0224
0225 snprintf(path, sizeof(path), "net/decnet/conf/%s",
0226 dev? dev->name : parms->name);
0227
0228 t->dn_dev_vars[0].extra1 = (void *)dev;
0229
0230 t->sysctl_header = register_net_sysctl(&init_net, path, t->dn_dev_vars);
0231 if (t->sysctl_header == NULL)
0232 kfree(t);
0233 else
0234 parms->sysctl = t;
0235 }
0236
0237 static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
0238 {
0239 if (parms->sysctl) {
0240 struct dn_dev_sysctl_table *t = parms->sysctl;
0241 parms->sysctl = NULL;
0242 unregister_net_sysctl_table(t->sysctl_header);
0243 kfree(t);
0244 }
0245 }
0246
0247 static int dn_forwarding_proc(struct ctl_table *table, int write,
0248 void *buffer, size_t *lenp, loff_t *ppos)
0249 {
0250 #ifdef CONFIG_DECNET_ROUTER
0251 struct net_device *dev = table->extra1;
0252 struct dn_dev *dn_db;
0253 int err;
0254 int tmp, old;
0255
0256 if (table->extra1 == NULL)
0257 return -EINVAL;
0258
0259 dn_db = rcu_dereference_raw(dev->dn_ptr);
0260 old = dn_db->parms.forwarding;
0261
0262 err = proc_dointvec(table, write, buffer, lenp, ppos);
0263
0264 if ((err >= 0) && write) {
0265 if (dn_db->parms.forwarding < 0)
0266 dn_db->parms.forwarding = 0;
0267 if (dn_db->parms.forwarding > 2)
0268 dn_db->parms.forwarding = 2;
0269
0270
0271
0272
0273
0274
0275 tmp = dn_db->parms.forwarding;
0276 dn_db->parms.forwarding = old;
0277 if (dn_db->parms.down)
0278 dn_db->parms.down(dev);
0279 dn_db->parms.forwarding = tmp;
0280 if (dn_db->parms.up)
0281 dn_db->parms.up(dev);
0282 }
0283
0284 return err;
0285 #else
0286 return -EINVAL;
0287 #endif
0288 }
0289
0290 #else
0291 static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
0292 {
0293 }
0294 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
0295 {
0296 }
0297
0298 #endif
0299
0300 static inline __u16 mtu2blksize(struct net_device *dev)
0301 {
0302 u32 blksize = dev->mtu;
0303 if (blksize > 0xffff)
0304 blksize = 0xffff;
0305
0306 if (dev->type == ARPHRD_ETHER ||
0307 dev->type == ARPHRD_PPP ||
0308 dev->type == ARPHRD_IPGRE ||
0309 dev->type == ARPHRD_LOOPBACK)
0310 blksize -= 2;
0311
0312 return (__u16)blksize;
0313 }
0314
0315 static struct dn_ifaddr *dn_dev_alloc_ifa(void)
0316 {
0317 struct dn_ifaddr *ifa;
0318
0319 ifa = kzalloc(sizeof(*ifa), GFP_KERNEL);
0320
0321 return ifa;
0322 }
0323
0324 static void dn_dev_free_ifa(struct dn_ifaddr *ifa)
0325 {
0326 kfree_rcu(ifa, rcu);
0327 }
0328
0329 static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr __rcu **ifap, int destroy)
0330 {
0331 struct dn_ifaddr *ifa1 = rtnl_dereference(*ifap);
0332 unsigned char mac_addr[6];
0333 struct net_device *dev = dn_db->dev;
0334
0335 ASSERT_RTNL();
0336
0337 *ifap = ifa1->ifa_next;
0338
0339 if (dn_db->dev->type == ARPHRD_ETHER) {
0340 if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) {
0341 dn_dn2eth(mac_addr, ifa1->ifa_local);
0342 dev_mc_del(dev, mac_addr);
0343 }
0344 }
0345
0346 dn_ifaddr_notify(RTM_DELADDR, ifa1);
0347 blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
0348 if (destroy) {
0349 dn_dev_free_ifa(ifa1);
0350
0351 if (dn_db->ifa_list == NULL)
0352 dn_dev_delete(dn_db->dev);
0353 }
0354 }
0355
0356 static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
0357 {
0358 struct net_device *dev = dn_db->dev;
0359 struct dn_ifaddr *ifa1;
0360 unsigned char mac_addr[6];
0361
0362 ASSERT_RTNL();
0363
0364
0365 for (ifa1 = rtnl_dereference(dn_db->ifa_list);
0366 ifa1 != NULL;
0367 ifa1 = rtnl_dereference(ifa1->ifa_next)) {
0368 if (ifa1->ifa_local == ifa->ifa_local)
0369 return -EEXIST;
0370 }
0371
0372 if (dev->type == ARPHRD_ETHER) {
0373 if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) {
0374 dn_dn2eth(mac_addr, ifa->ifa_local);
0375 dev_mc_add(dev, mac_addr);
0376 }
0377 }
0378
0379 ifa->ifa_next = dn_db->ifa_list;
0380 rcu_assign_pointer(dn_db->ifa_list, ifa);
0381
0382 dn_ifaddr_notify(RTM_NEWADDR, ifa);
0383 blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
0384
0385 return 0;
0386 }
0387
0388 static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa)
0389 {
0390 struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
0391 int rv;
0392
0393 if (dn_db == NULL) {
0394 int err;
0395 dn_db = dn_dev_create(dev, &err);
0396 if (dn_db == NULL)
0397 return err;
0398 }
0399
0400 ifa->ifa_dev = dn_db;
0401
0402 if (dev->flags & IFF_LOOPBACK)
0403 ifa->ifa_scope = RT_SCOPE_HOST;
0404
0405 rv = dn_dev_insert_ifa(dn_db, ifa);
0406 if (rv)
0407 dn_dev_free_ifa(ifa);
0408 return rv;
0409 }
0410
0411
0412 int dn_dev_ioctl(unsigned int cmd, void __user *arg)
0413 {
0414 char buffer[DN_IFREQ_SIZE];
0415 struct ifreq *ifr = (struct ifreq *)buffer;
0416 struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr;
0417 struct dn_dev *dn_db;
0418 struct net_device *dev;
0419 struct dn_ifaddr *ifa = NULL;
0420 struct dn_ifaddr __rcu **ifap = NULL;
0421 int ret = 0;
0422
0423 if (copy_from_user(ifr, arg, DN_IFREQ_SIZE))
0424 return -EFAULT;
0425 ifr->ifr_name[IFNAMSIZ-1] = 0;
0426
0427 dev_load(&init_net, ifr->ifr_name);
0428
0429 switch (cmd) {
0430 case SIOCGIFADDR:
0431 break;
0432 case SIOCSIFADDR:
0433 if (!capable(CAP_NET_ADMIN))
0434 return -EACCES;
0435 if (sdn->sdn_family != AF_DECnet)
0436 return -EINVAL;
0437 break;
0438 default:
0439 return -EINVAL;
0440 }
0441
0442 rtnl_lock();
0443
0444 if ((dev = __dev_get_by_name(&init_net, ifr->ifr_name)) == NULL) {
0445 ret = -ENODEV;
0446 goto done;
0447 }
0448
0449 if ((dn_db = rtnl_dereference(dev->dn_ptr)) != NULL) {
0450 for (ifap = &dn_db->ifa_list;
0451 (ifa = rtnl_dereference(*ifap)) != NULL;
0452 ifap = &ifa->ifa_next)
0453 if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0)
0454 break;
0455 }
0456
0457 if (ifa == NULL && cmd != SIOCSIFADDR) {
0458 ret = -EADDRNOTAVAIL;
0459 goto done;
0460 }
0461
0462 switch (cmd) {
0463 case SIOCGIFADDR:
0464 *((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local;
0465 if (copy_to_user(arg, ifr, DN_IFREQ_SIZE))
0466 ret = -EFAULT;
0467 break;
0468
0469 case SIOCSIFADDR:
0470 if (!ifa) {
0471 if ((ifa = dn_dev_alloc_ifa()) == NULL) {
0472 ret = -ENOBUFS;
0473 break;
0474 }
0475 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
0476 } else {
0477 if (ifa->ifa_local == dn_saddr2dn(sdn))
0478 break;
0479 dn_dev_del_ifa(dn_db, ifap, 0);
0480 }
0481
0482 ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn);
0483
0484 ret = dn_dev_set_ifa(dev, ifa);
0485 }
0486 done:
0487 rtnl_unlock();
0488
0489 return ret;
0490 }
0491
0492 struct net_device *dn_dev_get_default(void)
0493 {
0494 struct net_device *dev;
0495
0496 spin_lock(&dndev_lock);
0497 dev = decnet_default_device;
0498 if (dev) {
0499 if (dev->dn_ptr)
0500 dev_hold(dev);
0501 else
0502 dev = NULL;
0503 }
0504 spin_unlock(&dndev_lock);
0505
0506 return dev;
0507 }
0508
0509 int dn_dev_set_default(struct net_device *dev, int force)
0510 {
0511 struct net_device *old = NULL;
0512 int rv = -EBUSY;
0513 if (!dev->dn_ptr)
0514 return -ENODEV;
0515
0516 spin_lock(&dndev_lock);
0517 if (force || decnet_default_device == NULL) {
0518 old = decnet_default_device;
0519 decnet_default_device = dev;
0520 rv = 0;
0521 }
0522 spin_unlock(&dndev_lock);
0523
0524 dev_put(old);
0525 return rv;
0526 }
0527
0528 static void dn_dev_check_default(struct net_device *dev)
0529 {
0530 spin_lock(&dndev_lock);
0531 if (dev == decnet_default_device) {
0532 decnet_default_device = NULL;
0533 } else {
0534 dev = NULL;
0535 }
0536 spin_unlock(&dndev_lock);
0537
0538 dev_put(dev);
0539 }
0540
0541
0542
0543
0544 static struct dn_dev *dn_dev_by_index(int ifindex)
0545 {
0546 struct net_device *dev;
0547 struct dn_dev *dn_dev = NULL;
0548
0549 dev = __dev_get_by_index(&init_net, ifindex);
0550 if (dev)
0551 dn_dev = rtnl_dereference(dev->dn_ptr);
0552
0553 return dn_dev;
0554 }
0555
0556 static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
0557 [IFA_ADDRESS] = { .type = NLA_U16 },
0558 [IFA_LOCAL] = { .type = NLA_U16 },
0559 [IFA_LABEL] = { .type = NLA_STRING,
0560 .len = IFNAMSIZ - 1 },
0561 [IFA_FLAGS] = { .type = NLA_U32 },
0562 };
0563
0564 static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
0565 struct netlink_ext_ack *extack)
0566 {
0567 struct net *net = sock_net(skb->sk);
0568 struct nlattr *tb[IFA_MAX+1];
0569 struct dn_dev *dn_db;
0570 struct ifaddrmsg *ifm;
0571 struct dn_ifaddr *ifa;
0572 struct dn_ifaddr __rcu **ifap;
0573 int err = -EINVAL;
0574
0575 if (!netlink_capable(skb, CAP_NET_ADMIN))
0576 return -EPERM;
0577
0578 if (!net_eq(net, &init_net))
0579 goto errout;
0580
0581 err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
0582 dn_ifa_policy, extack);
0583 if (err < 0)
0584 goto errout;
0585
0586 err = -ENODEV;
0587 ifm = nlmsg_data(nlh);
0588 if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL)
0589 goto errout;
0590
0591 err = -EADDRNOTAVAIL;
0592 for (ifap = &dn_db->ifa_list;
0593 (ifa = rtnl_dereference(*ifap)) != NULL;
0594 ifap = &ifa->ifa_next) {
0595 if (tb[IFA_LOCAL] &&
0596 nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2))
0597 continue;
0598
0599 if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
0600 continue;
0601
0602 dn_dev_del_ifa(dn_db, ifap, 1);
0603 return 0;
0604 }
0605
0606 errout:
0607 return err;
0608 }
0609
0610 static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
0611 struct netlink_ext_ack *extack)
0612 {
0613 struct net *net = sock_net(skb->sk);
0614 struct nlattr *tb[IFA_MAX+1];
0615 struct net_device *dev;
0616 struct dn_dev *dn_db;
0617 struct ifaddrmsg *ifm;
0618 struct dn_ifaddr *ifa;
0619 int err;
0620
0621 if (!netlink_capable(skb, CAP_NET_ADMIN))
0622 return -EPERM;
0623
0624 if (!net_eq(net, &init_net))
0625 return -EINVAL;
0626
0627 err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
0628 dn_ifa_policy, extack);
0629 if (err < 0)
0630 return err;
0631
0632 if (tb[IFA_LOCAL] == NULL)
0633 return -EINVAL;
0634
0635 ifm = nlmsg_data(nlh);
0636 if ((dev = __dev_get_by_index(&init_net, ifm->ifa_index)) == NULL)
0637 return -ENODEV;
0638
0639 if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) {
0640 dn_db = dn_dev_create(dev, &err);
0641 if (!dn_db)
0642 return err;
0643 }
0644
0645 if ((ifa = dn_dev_alloc_ifa()) == NULL)
0646 return -ENOBUFS;
0647
0648 if (tb[IFA_ADDRESS] == NULL)
0649 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
0650
0651 ifa->ifa_local = nla_get_le16(tb[IFA_LOCAL]);
0652 ifa->ifa_address = nla_get_le16(tb[IFA_ADDRESS]);
0653 ifa->ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) :
0654 ifm->ifa_flags;
0655 ifa->ifa_scope = ifm->ifa_scope;
0656 ifa->ifa_dev = dn_db;
0657
0658 if (tb[IFA_LABEL])
0659 nla_strscpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
0660 else
0661 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
0662
0663 err = dn_dev_insert_ifa(dn_db, ifa);
0664 if (err)
0665 dn_dev_free_ifa(ifa);
0666
0667 return err;
0668 }
0669
0670 static inline size_t dn_ifaddr_nlmsg_size(void)
0671 {
0672 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
0673 + nla_total_size(IFNAMSIZ)
0674 + nla_total_size(2)
0675 + nla_total_size(2)
0676 + nla_total_size(4);
0677 }
0678
0679 static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
0680 u32 portid, u32 seq, int event, unsigned int flags)
0681 {
0682 struct ifaddrmsg *ifm;
0683 struct nlmsghdr *nlh;
0684 u32 ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
0685
0686 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*ifm), flags);
0687 if (nlh == NULL)
0688 return -EMSGSIZE;
0689
0690 ifm = nlmsg_data(nlh);
0691 ifm->ifa_family = AF_DECnet;
0692 ifm->ifa_prefixlen = 16;
0693 ifm->ifa_flags = ifa_flags;
0694 ifm->ifa_scope = ifa->ifa_scope;
0695 ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
0696
0697 if ((ifa->ifa_address &&
0698 nla_put_le16(skb, IFA_ADDRESS, ifa->ifa_address)) ||
0699 (ifa->ifa_local &&
0700 nla_put_le16(skb, IFA_LOCAL, ifa->ifa_local)) ||
0701 (ifa->ifa_label[0] &&
0702 nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) ||
0703 nla_put_u32(skb, IFA_FLAGS, ifa_flags))
0704 goto nla_put_failure;
0705 nlmsg_end(skb, nlh);
0706 return 0;
0707
0708 nla_put_failure:
0709 nlmsg_cancel(skb, nlh);
0710 return -EMSGSIZE;
0711 }
0712
0713 static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
0714 {
0715 struct sk_buff *skb;
0716 int err = -ENOBUFS;
0717
0718 skb = alloc_skb(dn_ifaddr_nlmsg_size(), GFP_KERNEL);
0719 if (skb == NULL)
0720 goto errout;
0721
0722 err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
0723 if (err < 0) {
0724
0725 WARN_ON(err == -EMSGSIZE);
0726 kfree_skb(skb);
0727 goto errout;
0728 }
0729 rtnl_notify(skb, &init_net, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
0730 return;
0731 errout:
0732 if (err < 0)
0733 rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_IFADDR, err);
0734 }
0735
0736 static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
0737 {
0738 struct net *net = sock_net(skb->sk);
0739 int idx, dn_idx = 0, skip_ndevs, skip_naddr;
0740 struct net_device *dev;
0741 struct dn_dev *dn_db;
0742 struct dn_ifaddr *ifa;
0743
0744 if (!net_eq(net, &init_net))
0745 return 0;
0746
0747 skip_ndevs = cb->args[0];
0748 skip_naddr = cb->args[1];
0749
0750 idx = 0;
0751 rcu_read_lock();
0752 for_each_netdev_rcu(&init_net, dev) {
0753 if (idx < skip_ndevs)
0754 goto cont;
0755 else if (idx > skip_ndevs) {
0756
0757
0758 skip_naddr = 0;
0759 }
0760
0761 if ((dn_db = rcu_dereference(dev->dn_ptr)) == NULL)
0762 goto cont;
0763
0764 for (ifa = rcu_dereference(dn_db->ifa_list), dn_idx = 0; ifa;
0765 ifa = rcu_dereference(ifa->ifa_next), dn_idx++) {
0766 if (dn_idx < skip_naddr)
0767 continue;
0768
0769 if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).portid,
0770 cb->nlh->nlmsg_seq, RTM_NEWADDR,
0771 NLM_F_MULTI) < 0)
0772 goto done;
0773 }
0774 cont:
0775 idx++;
0776 }
0777 done:
0778 rcu_read_unlock();
0779 cb->args[0] = idx;
0780 cb->args[1] = dn_idx;
0781
0782 return skb->len;
0783 }
0784
0785 static int dn_dev_get_first(struct net_device *dev, __le16 *addr)
0786 {
0787 struct dn_dev *dn_db;
0788 struct dn_ifaddr *ifa;
0789 int rv = -ENODEV;
0790
0791 rcu_read_lock();
0792 dn_db = rcu_dereference(dev->dn_ptr);
0793 if (dn_db == NULL)
0794 goto out;
0795
0796 ifa = rcu_dereference(dn_db->ifa_list);
0797 if (ifa != NULL) {
0798 *addr = ifa->ifa_local;
0799 rv = 0;
0800 }
0801 out:
0802 rcu_read_unlock();
0803 return rv;
0804 }
0805
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815
0816 int dn_dev_bind_default(__le16 *addr)
0817 {
0818 struct net_device *dev;
0819 int rv;
0820 dev = dn_dev_get_default();
0821 last_chance:
0822 if (dev) {
0823 rv = dn_dev_get_first(dev, addr);
0824 dev_put(dev);
0825 if (rv == 0 || dev == init_net.loopback_dev)
0826 return rv;
0827 }
0828 dev = init_net.loopback_dev;
0829 dev_hold(dev);
0830 goto last_chance;
0831 }
0832
0833 static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa)
0834 {
0835 struct endnode_hello_message *msg;
0836 struct sk_buff *skb = NULL;
0837 __le16 *pktlen;
0838 struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
0839
0840 if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
0841 return;
0842
0843 skb->dev = dev;
0844
0845 msg = skb_put(skb, sizeof(*msg));
0846
0847 msg->msgflg = 0x0D;
0848 memcpy(msg->tiver, dn_eco_version, 3);
0849 dn_dn2eth(msg->id, ifa->ifa_local);
0850 msg->iinfo = DN_RT_INFO_ENDN;
0851 msg->blksize = cpu_to_le16(mtu2blksize(dev));
0852 msg->area = 0x00;
0853 memset(msg->seed, 0, 8);
0854 memcpy(msg->neighbor, dn_hiord, ETH_ALEN);
0855
0856 if (dn_db->router) {
0857 struct dn_neigh *dn = container_of(dn_db->router, struct dn_neigh, n);
0858 dn_dn2eth(msg->neighbor, dn->addr);
0859 }
0860
0861 msg->timer = cpu_to_le16((unsigned short)dn_db->parms.t3);
0862 msg->mpd = 0x00;
0863 msg->datalen = 0x02;
0864 memset(msg->data, 0xAA, 2);
0865
0866 pktlen = skb_push(skb, 2);
0867 *pktlen = cpu_to_le16(skb->len - 2);
0868
0869 skb_reset_network_header(skb);
0870
0871 dn_rt_finish_output(skb, dn_rt_all_rt_mcast, msg->id);
0872 }
0873
0874
0875 #define DRDELAY (5 * HZ)
0876
0877 static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn_ifaddr *ifa)
0878 {
0879
0880 if (time_before(jiffies, dn_db->uptime + DRDELAY))
0881 return 0;
0882
0883
0884 if (!dn_db->router)
0885 return 1;
0886
0887
0888 if (dn->priority < dn_db->parms.priority)
0889 return 1;
0890
0891
0892 if (dn->priority != dn_db->parms.priority)
0893 return 0;
0894
0895 if (le16_to_cpu(dn->addr) < le16_to_cpu(ifa->ifa_local))
0896 return 1;
0897
0898 return 0;
0899 }
0900
0901 static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
0902 {
0903 int n;
0904 struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
0905 struct dn_neigh *dn = container_of(dn_db->router, struct dn_neigh, n);
0906 struct sk_buff *skb;
0907 size_t size;
0908 unsigned char *ptr;
0909 unsigned char *i1, *i2;
0910 __le16 *pktlen;
0911 char *src;
0912
0913 if (mtu2blksize(dev) < (26 + 7))
0914 return;
0915
0916 n = mtu2blksize(dev) - 26;
0917 n /= 7;
0918
0919 if (n > 32)
0920 n = 32;
0921
0922 size = 2 + 26 + 7 * n;
0923
0924 if ((skb = dn_alloc_skb(NULL, size, GFP_ATOMIC)) == NULL)
0925 return;
0926
0927 skb->dev = dev;
0928 ptr = skb_put(skb, size);
0929
0930 *ptr++ = DN_RT_PKT_CNTL | DN_RT_PKT_ERTH;
0931 *ptr++ = 2;
0932 *ptr++ = 0;
0933 *ptr++ = 0;
0934 dn_dn2eth(ptr, ifa->ifa_local);
0935 src = ptr;
0936 ptr += ETH_ALEN;
0937 *ptr++ = dn_db->parms.forwarding == 1 ?
0938 DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
0939 *((__le16 *)ptr) = cpu_to_le16(mtu2blksize(dev));
0940 ptr += 2;
0941 *ptr++ = dn_db->parms.priority;
0942 *ptr++ = 0;
0943 *((__le16 *)ptr) = cpu_to_le16((unsigned short)dn_db->parms.t3);
0944 ptr += 2;
0945 *ptr++ = 0;
0946 i1 = ptr++;
0947 memset(ptr, 0, 7);
0948 ptr += 7;
0949 i2 = ptr++;
0950
0951 n = dn_neigh_elist(dev, ptr, n);
0952
0953 *i2 = 7 * n;
0954 *i1 = 8 + *i2;
0955
0956 skb_trim(skb, (27 + *i2));
0957
0958 pktlen = skb_push(skb, 2);
0959 *pktlen = cpu_to_le16(skb->len - 2);
0960
0961 skb_reset_network_header(skb);
0962
0963 if (dn_am_i_a_router(dn, dn_db, ifa)) {
0964 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
0965 if (skb2) {
0966 dn_rt_finish_output(skb2, dn_rt_all_end_mcast, src);
0967 }
0968 }
0969
0970 dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);
0971 }
0972
0973 static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa)
0974 {
0975 struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
0976
0977 if (dn_db->parms.forwarding == 0)
0978 dn_send_endnode_hello(dev, ifa);
0979 else
0980 dn_send_router_hello(dev, ifa);
0981 }
0982
0983 static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa)
0984 {
0985 int tdlen = 16;
0986 int size = dev->hard_header_len + 2 + 4 + tdlen;
0987 struct sk_buff *skb = dn_alloc_skb(NULL, size, GFP_ATOMIC);
0988 int i;
0989 unsigned char *ptr;
0990 char src[ETH_ALEN];
0991
0992 if (skb == NULL)
0993 return ;
0994
0995 skb->dev = dev;
0996 skb_push(skb, dev->hard_header_len);
0997 ptr = skb_put(skb, 2 + 4 + tdlen);
0998
0999 *ptr++ = DN_RT_PKT_HELO;
1000 *((__le16 *)ptr) = ifa->ifa_local;
1001 ptr += 2;
1002 *ptr++ = tdlen;
1003
1004 for(i = 0; i < tdlen; i++)
1005 *ptr++ = 0252;
1006
1007 dn_dn2eth(src, ifa->ifa_local);
1008 dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);
1009 }
1010
1011 static int dn_eth_up(struct net_device *dev)
1012 {
1013 struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
1014
1015 if (dn_db->parms.forwarding == 0)
1016 dev_mc_add(dev, dn_rt_all_end_mcast);
1017 else
1018 dev_mc_add(dev, dn_rt_all_rt_mcast);
1019
1020 dn_db->use_long = 1;
1021
1022 return 0;
1023 }
1024
1025 static void dn_eth_down(struct net_device *dev)
1026 {
1027 struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
1028
1029 if (dn_db->parms.forwarding == 0)
1030 dev_mc_del(dev, dn_rt_all_end_mcast);
1031 else
1032 dev_mc_del(dev, dn_rt_all_rt_mcast);
1033 }
1034
1035 static void dn_dev_set_timer(struct net_device *dev);
1036
1037 static void dn_dev_timer_func(struct timer_list *t)
1038 {
1039 struct dn_dev *dn_db = from_timer(dn_db, t, timer);
1040 struct net_device *dev;
1041 struct dn_ifaddr *ifa;
1042
1043 rcu_read_lock();
1044 dev = dn_db->dev;
1045 if (dn_db->t3 <= dn_db->parms.t2) {
1046 if (dn_db->parms.timer3) {
1047 for (ifa = rcu_dereference(dn_db->ifa_list);
1048 ifa;
1049 ifa = rcu_dereference(ifa->ifa_next)) {
1050 if (!(ifa->ifa_flags & IFA_F_SECONDARY))
1051 dn_db->parms.timer3(dev, ifa);
1052 }
1053 }
1054 dn_db->t3 = dn_db->parms.t3;
1055 } else {
1056 dn_db->t3 -= dn_db->parms.t2;
1057 }
1058 rcu_read_unlock();
1059 dn_dev_set_timer(dev);
1060 }
1061
1062 static void dn_dev_set_timer(struct net_device *dev)
1063 {
1064 struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
1065
1066 if (dn_db->parms.t2 > dn_db->parms.t3)
1067 dn_db->parms.t2 = dn_db->parms.t3;
1068
1069 dn_db->timer.expires = jiffies + (dn_db->parms.t2 * HZ);
1070
1071 add_timer(&dn_db->timer);
1072 }
1073
1074 static struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
1075 {
1076 int i;
1077 struct dn_dev_parms *p = dn_dev_list;
1078 struct dn_dev *dn_db;
1079
1080 for(i = 0; i < DN_DEV_LIST_SIZE; i++, p++) {
1081 if (p->type == dev->type)
1082 break;
1083 }
1084
1085 *err = -ENODEV;
1086 if (i == DN_DEV_LIST_SIZE)
1087 return NULL;
1088
1089 *err = -ENOBUFS;
1090 if ((dn_db = kzalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)
1091 return NULL;
1092
1093 memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
1094
1095 rcu_assign_pointer(dev->dn_ptr, dn_db);
1096 dn_db->dev = dev;
1097 timer_setup(&dn_db->timer, dn_dev_timer_func, 0);
1098
1099 dn_db->uptime = jiffies;
1100
1101 dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
1102 if (!dn_db->neigh_parms) {
1103 RCU_INIT_POINTER(dev->dn_ptr, NULL);
1104 kfree(dn_db);
1105 return NULL;
1106 }
1107
1108 if (dn_db->parms.up) {
1109 if (dn_db->parms.up(dev) < 0) {
1110 neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
1111 dev->dn_ptr = NULL;
1112 kfree(dn_db);
1113 return NULL;
1114 }
1115 }
1116
1117 dn_dev_sysctl_register(dev, &dn_db->parms);
1118
1119 dn_dev_set_timer(dev);
1120
1121 *err = 0;
1122 return dn_db;
1123 }
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137 void dn_dev_up(struct net_device *dev)
1138 {
1139 struct dn_ifaddr *ifa;
1140 __le16 addr = decnet_address;
1141 int maybe_default = 0;
1142 struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
1143
1144 if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
1145 return;
1146
1147
1148
1149
1150
1151
1152
1153 if (dn_db == NULL) {
1154 int err;
1155 dn_db = dn_dev_create(dev, &err);
1156 if (dn_db == NULL)
1157 return;
1158 }
1159
1160 if (dev->type == ARPHRD_ETHER) {
1161 if (memcmp(dev->dev_addr, dn_hiord, 4) != 0)
1162 return;
1163 addr = dn_eth2dn(dev->dev_addr);
1164 maybe_default = 1;
1165 }
1166
1167 if (addr == 0)
1168 return;
1169
1170 if ((ifa = dn_dev_alloc_ifa()) == NULL)
1171 return;
1172
1173 ifa->ifa_local = ifa->ifa_address = addr;
1174 ifa->ifa_flags = 0;
1175 ifa->ifa_scope = RT_SCOPE_UNIVERSE;
1176 strcpy(ifa->ifa_label, dev->name);
1177
1178 dn_dev_set_ifa(dev, ifa);
1179
1180
1181
1182
1183
1184 if (maybe_default) {
1185 dev_hold(dev);
1186 if (dn_dev_set_default(dev, 0))
1187 dev_put(dev);
1188 }
1189 }
1190
1191 static void dn_dev_delete(struct net_device *dev)
1192 {
1193 struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
1194
1195 if (dn_db == NULL)
1196 return;
1197
1198 del_timer_sync(&dn_db->timer);
1199 dn_dev_sysctl_unregister(&dn_db->parms);
1200 dn_dev_check_default(dev);
1201 neigh_ifdown(&dn_neigh_table, dev);
1202
1203 if (dn_db->parms.down)
1204 dn_db->parms.down(dev);
1205
1206 dev->dn_ptr = NULL;
1207
1208 neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
1209 neigh_ifdown(&dn_neigh_table, dev);
1210
1211 if (dn_db->router)
1212 neigh_release(dn_db->router);
1213 if (dn_db->peer)
1214 neigh_release(dn_db->peer);
1215
1216 kfree(dn_db);
1217 }
1218
1219 void dn_dev_down(struct net_device *dev)
1220 {
1221 struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
1222 struct dn_ifaddr *ifa;
1223
1224 if (dn_db == NULL)
1225 return;
1226
1227 while ((ifa = rtnl_dereference(dn_db->ifa_list)) != NULL) {
1228 dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0);
1229 dn_dev_free_ifa(ifa);
1230 }
1231
1232 dn_dev_delete(dev);
1233 }
1234
1235 void dn_dev_init_pkt(struct sk_buff *skb)
1236 {
1237 }
1238
1239 void dn_dev_veri_pkt(struct sk_buff *skb)
1240 {
1241 }
1242
1243 void dn_dev_hello(struct sk_buff *skb)
1244 {
1245 }
1246
1247 void dn_dev_devices_off(void)
1248 {
1249 struct net_device *dev;
1250
1251 rtnl_lock();
1252 for_each_netdev(&init_net, dev)
1253 dn_dev_down(dev);
1254 rtnl_unlock();
1255
1256 }
1257
1258 void dn_dev_devices_on(void)
1259 {
1260 struct net_device *dev;
1261
1262 rtnl_lock();
1263 for_each_netdev(&init_net, dev) {
1264 if (dev->flags & IFF_UP)
1265 dn_dev_up(dev);
1266 }
1267 rtnl_unlock();
1268 }
1269
1270 int register_dnaddr_notifier(struct notifier_block *nb)
1271 {
1272 return blocking_notifier_chain_register(&dnaddr_chain, nb);
1273 }
1274
1275 int unregister_dnaddr_notifier(struct notifier_block *nb)
1276 {
1277 return blocking_notifier_chain_unregister(&dnaddr_chain, nb);
1278 }
1279
1280 #ifdef CONFIG_PROC_FS
1281 static inline int is_dn_dev(struct net_device *dev)
1282 {
1283 return dev->dn_ptr != NULL;
1284 }
1285
1286 static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
1287 __acquires(RCU)
1288 {
1289 int i;
1290 struct net_device *dev;
1291
1292 rcu_read_lock();
1293
1294 if (*pos == 0)
1295 return SEQ_START_TOKEN;
1296
1297 i = 1;
1298 for_each_netdev_rcu(&init_net, dev) {
1299 if (!is_dn_dev(dev))
1300 continue;
1301
1302 if (i++ == *pos)
1303 return dev;
1304 }
1305
1306 return NULL;
1307 }
1308
1309 static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1310 {
1311 struct net_device *dev;
1312
1313 ++*pos;
1314
1315 dev = v;
1316 if (v == SEQ_START_TOKEN)
1317 dev = net_device_entry(&init_net.dev_base_head);
1318
1319 for_each_netdev_continue_rcu(&init_net, dev) {
1320 if (!is_dn_dev(dev))
1321 continue;
1322
1323 return dev;
1324 }
1325
1326 return NULL;
1327 }
1328
1329 static void dn_dev_seq_stop(struct seq_file *seq, void *v)
1330 __releases(RCU)
1331 {
1332 rcu_read_unlock();
1333 }
1334
1335 static char *dn_type2asc(char type)
1336 {
1337 switch (type) {
1338 case DN_DEV_BCAST:
1339 return "B";
1340 case DN_DEV_UCAST:
1341 return "U";
1342 case DN_DEV_MPOINT:
1343 return "M";
1344 }
1345
1346 return "?";
1347 }
1348
1349 static int dn_dev_seq_show(struct seq_file *seq, void *v)
1350 {
1351 if (v == SEQ_START_TOKEN)
1352 seq_puts(seq, "Name Flags T1 Timer1 T3 Timer3 BlkSize Pri State DevType Router Peer\n");
1353 else {
1354 struct net_device *dev = v;
1355 char peer_buf[DN_ASCBUF_LEN];
1356 char router_buf[DN_ASCBUF_LEN];
1357 struct dn_dev *dn_db = rcu_dereference(dev->dn_ptr);
1358
1359 seq_printf(seq, "%-8s %1s %04u %04u %04lu %04lu"
1360 " %04hu %03d %02x %-10s %-7s %-7s\n",
1361 dev->name,
1362 dn_type2asc(dn_db->parms.mode),
1363 0, 0,
1364 dn_db->t3, dn_db->parms.t3,
1365 mtu2blksize(dev),
1366 dn_db->parms.priority,
1367 dn_db->parms.state, dn_db->parms.name,
1368 dn_db->router ? dn_addr2asc(le16_to_cpu(*(__le16 *)dn_db->router->primary_key), router_buf) : "",
1369 dn_db->peer ? dn_addr2asc(le16_to_cpu(*(__le16 *)dn_db->peer->primary_key), peer_buf) : "");
1370 }
1371 return 0;
1372 }
1373
1374 static const struct seq_operations dn_dev_seq_ops = {
1375 .start = dn_dev_seq_start,
1376 .next = dn_dev_seq_next,
1377 .stop = dn_dev_seq_stop,
1378 .show = dn_dev_seq_show,
1379 };
1380 #endif
1381
1382 static int addr[2];
1383 module_param_array(addr, int, NULL, 0444);
1384 MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
1385
1386 void __init dn_dev_init(void)
1387 {
1388 if (addr[0] > 63 || addr[0] < 0) {
1389 printk(KERN_ERR "DECnet: Area must be between 0 and 63");
1390 return;
1391 }
1392
1393 if (addr[1] > 1023 || addr[1] < 0) {
1394 printk(KERN_ERR "DECnet: Node must be between 0 and 1023");
1395 return;
1396 }
1397
1398 decnet_address = cpu_to_le16((addr[0] << 10) | addr[1]);
1399
1400 dn_dev_devices_on();
1401
1402 rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_NEWADDR,
1403 dn_nl_newaddr, NULL, 0);
1404 rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_DELADDR,
1405 dn_nl_deladdr, NULL, 0);
1406 rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_GETADDR,
1407 NULL, dn_nl_dump_ifaddr, 0);
1408
1409 proc_create_seq("decnet_dev", 0444, init_net.proc_net, &dn_dev_seq_ops);
1410
1411 #ifdef CONFIG_SYSCTL
1412 {
1413 int i;
1414 for(i = 0; i < DN_DEV_LIST_SIZE; i++)
1415 dn_dev_sysctl_register(NULL, &dn_dev_list[i]);
1416 }
1417 #endif
1418 }
1419
1420 void __exit dn_dev_cleanup(void)
1421 {
1422 #ifdef CONFIG_SYSCTL
1423 {
1424 int i;
1425 for(i = 0; i < DN_DEV_LIST_SIZE; i++)
1426 dn_dev_sysctl_unregister(&dn_dev_list[i]);
1427 }
1428 #endif
1429
1430 remove_proc_entry("decnet_dev", init_net.proc_net);
1431
1432 dn_dev_devices_off();
1433 }