~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/decnet/dn_dev.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 Device Layer
  7  *
  8  * Authors:     Steve Whitehouse <SteveW@ACM.org>
  9  *              Eduardo Marcelo Serrat <emserrat@geocities.com>
 10  *
 11  * Changes:
 12  *          Steve Whitehouse : Devices now see incoming frames so they
 13  *                             can mark on who it came from.
 14  *          Steve Whitehouse : Fixed bug in creating neighbours. Each neighbour
 15  *                             can now have a device specific setup func.
 16  *          Steve Whitehouse : Added /proc/sys/net/decnet/conf/<dev>/
 17  *          Steve Whitehouse : Fixed bug which sometimes killed timer
 18  *          Steve Whitehouse : Multiple ifaddr support
 19  *          Steve Whitehouse : SIOCGIFCONF is now a compile time option
 20  *          Steve Whitehouse : /proc/sys/net/decnet/conf/<sys>/forwarding
 21  *          Steve Whitehouse : Removed timer1 - it's a user space issue now
 22  *         Patrick Caulfield : Fixed router hello message format
 23  *          Steve Whitehouse : Got rid of constant sizes for blksize for
 24  *                             devices. All mtu based now.
 25  */
 26 
 27 #include <linux/config.h>
 28 #include <linux/module.h>
 29 #include <linux/init.h>
 30 #include <linux/net.h>
 31 #include <linux/netdevice.h>
 32 #include <linux/proc_fs.h>
 33 #include <linux/seq_file.h>
 34 #include <linux/timer.h>
 35 #include <linux/string.h>
 36 #include <linux/if_arp.h>
 37 #include <linux/if_ether.h>
 38 #include <linux/skbuff.h>
 39 #include <linux/rtnetlink.h>
 40 #include <linux/sysctl.h>
 41 #include <linux/notifier.h>
 42 #include <asm/uaccess.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_route.h>
 49 #include <net/dn_neigh.h>
 50 #include <net/dn_fib.h>
 51 
 52 #define DN_IFREQ_SIZE (sizeof(struct ifreq) - sizeof(struct sockaddr) + sizeof(struct sockaddr_dn))
 53 
 54 static char dn_rt_all_end_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x04,0x00,0x00};
 55 static char dn_rt_all_rt_mcast[ETH_ALEN]  = {0xAB,0x00,0x00,0x03,0x00,0x00};
 56 static char dn_hiord[ETH_ALEN]            = {0xAA,0x00,0x04,0x00,0x00,0x00};
 57 static unsigned char dn_eco_version[3]    = {0x02,0x00,0x00};
 58 
 59 extern struct neigh_table dn_neigh_table;
 60 
 61 /*
 62  * decnet_address is kept in network order.
 63  */
 64 dn_address decnet_address = 0;
 65 
 66 static rwlock_t dndev_lock = RW_LOCK_UNLOCKED;
 67 static struct net_device *decnet_default_device;
 68 static struct notifier_block *dnaddr_chain;
 69 
 70 static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
 71 static void dn_dev_delete(struct net_device *dev);
 72 static void rtmsg_ifa(int event, struct dn_ifaddr *ifa);
 73 
 74 static int dn_eth_up(struct net_device *);
 75 static void dn_eth_down(struct net_device *);
 76 static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa);
 77 static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa);
 78 
 79 static struct dn_dev_parms dn_dev_list[] =  {
 80 {
 81         .type =         ARPHRD_ETHER, /* Ethernet */
 82         .mode =         DN_DEV_BCAST,
 83         .state =        DN_DEV_S_RU,
 84         .t2 =           1,
 85         .t3 =           10,
 86         .name =         "ethernet",
 87         .ctl_name =     NET_DECNET_CONF_ETHER,
 88         .up =           dn_eth_up,
 89         .down =         dn_eth_down,
 90         .timer3 =       dn_send_brd_hello,
 91 },
 92 {
 93         .type =         ARPHRD_IPGRE, /* DECnet tunneled over GRE in IP */
 94         .mode =         DN_DEV_BCAST,
 95         .state =        DN_DEV_S_RU,
 96         .t2 =           1,
 97         .t3 =           10,
 98         .name =         "ipgre",
 99         .ctl_name =     NET_DECNET_CONF_GRE,
100         .timer3 =       dn_send_brd_hello,
101 },
102 #if 0
103 {
104         .type =         ARPHRD_X25, /* Bog standard X.25 */
105         .mode =         DN_DEV_UCAST,
106         .state =        DN_DEV_S_DS,
107         .t2 =           1,
108         .t3 =           120,
109         .name =         "x25",
110         .ctl_name =     NET_DECNET_CONF_X25,
111         .timer3 =       dn_send_ptp_hello,
112 },
113 #endif
114 #if 0
115 {
116         .type =         ARPHRD_PPP, /* DECnet over PPP */
117         .mode =         DN_DEV_BCAST,
118         .state =        DN_DEV_S_RU,
119         .t2 =           1,
120         .t3 =           10,
121         .name =         "ppp",
122         .ctl_name =     NET_DECNET_CONF_PPP,
123         .timer3 =       dn_send_brd_hello,
124 },
125 #endif
126 {
127         .type =         ARPHRD_DDCMP, /* DECnet over DDCMP */
128         .mode =         DN_DEV_UCAST,
129         .state =        DN_DEV_S_DS,
130         .t2 =           1,
131         .t3 =           120,
132         .name =         "ddcmp",
133         .ctl_name =     NET_DECNET_CONF_DDCMP,
134         .timer3 =       dn_send_ptp_hello,
135 },
136 {
137         .type =         ARPHRD_LOOPBACK, /* Loopback interface - always last */
138         .mode =         DN_DEV_BCAST,
139         .state =        DN_DEV_S_RU,
140         .t2 =           1,
141         .t3 =           10,
142         .name =         "loopback",
143         .ctl_name =     NET_DECNET_CONF_LOOPBACK,
144         .timer3 =       dn_send_brd_hello,
145 }
146 };
147 
148 #define DN_DEV_LIST_SIZE (sizeof(dn_dev_list)/sizeof(struct dn_dev_parms))
149 
150 #define DN_DEV_PARMS_OFFSET(x) ((int) ((char *) &((struct dn_dev_parms *)0)->x))
151 
152 #ifdef CONFIG_SYSCTL
153 
154 static int min_t2[] = { 1 };
155 static int max_t2[] = { 60 }; /* No max specified, but this seems sensible */
156 static int min_t3[] = { 1 };
157 static int max_t3[] = { 8191 }; /* Must fit in 16 bits when multiplied by BCT3MULT or T3MULT */
158 
159 static int min_priority[1];
160 static int max_priority[] = { 127 }; /* From DECnet spec */
161 
162 static int dn_forwarding_proc(ctl_table *, int, struct file *,
163                         void *, size_t *);
164 static int dn_forwarding_sysctl(ctl_table *table, int *name, int nlen,
165                         void *oldval, size_t *oldlenp,
166                         void *newval, size_t newlen,
167                         void **context);
168 
169 static struct dn_dev_sysctl_table {
170         struct ctl_table_header *sysctl_header;
171         ctl_table dn_dev_vars[5];
172         ctl_table dn_dev_dev[2];
173         ctl_table dn_dev_conf_dir[2];
174         ctl_table dn_dev_proto_dir[2];
175         ctl_table dn_dev_root_dir[2];
176 } dn_dev_sysctl = {
177         NULL,
178         {
179         {
180                 .ctl_name = NET_DECNET_CONF_DEV_FORWARDING,
181                 .procname = "forwarding",
182                 .data = (void *)DN_DEV_PARMS_OFFSET(forwarding),
183                 .maxlen = sizeof(int),
184                 .mode = 0644,
185                 .proc_handler = dn_forwarding_proc,
186                 .strategy = dn_forwarding_sysctl,
187         },
188         {
189                 .ctl_name = NET_DECNET_CONF_DEV_PRIORITY,
190                 .procname = "priority",
191                 .data = (void *)DN_DEV_PARMS_OFFSET(priority),
192                 .maxlen = sizeof(int),
193                 .mode = 0644,
194                 .proc_handler = proc_dointvec_minmax,
195                 .strategy = sysctl_intvec,
196                 .extra1 = &min_priority,
197                 .extra2 = &max_priority
198         },
199         {
200                 .ctl_name = NET_DECNET_CONF_DEV_T2,
201                 .procname = "t2",
202                 .data = (void *)DN_DEV_PARMS_OFFSET(t2),
203                 .maxlen = sizeof(int),
204                 .mode = 0644,
205                 .proc_handler = proc_dointvec_minmax,
206                 .strategy = sysctl_intvec,
207                 .extra1 = &min_t2,
208                 .extra2 = &max_t2
209         },
210         {
211                 .ctl_name = NET_DECNET_CONF_DEV_T3,
212                 .procname = "t3",
213                 .data = (void *)DN_DEV_PARMS_OFFSET(t3),
214                 .maxlen = sizeof(int),
215                 .mode = 0644,
216                 .proc_handler = proc_dointvec_minmax,
217                 .strategy = sysctl_intvec,
218                 .extra1 = &min_t3,
219                 .extra2 = &max_t3
220         },
221         {0}
222         },
223         {{
224                 .ctl_name = 0, 
225                 .procname = "", 
226                 .mode = 0555, 
227                 .child = dn_dev_sysctl.dn_dev_vars
228         }, {0}},
229         {{
230                 .ctl_name = NET_DECNET_CONF,
231                 .procname = "conf", 
232                 .mode = 0555, 
233                 .child = dn_dev_sysctl.dn_dev_dev
234         }, {0}},
235         {{
236                 .ctl_name = NET_DECNET, 
237                 .procname = "decnet", 
238                 .mode = 0555, 
239                 .child = dn_dev_sysctl.dn_dev_conf_dir
240         }, {0}},
241         {{
242                 .ctl_name = CTL_NET, 
243                 .procname = "net", 
244                 .mode = 0555, 
245                 .child = dn_dev_sysctl.dn_dev_proto_dir
246         }, {0}}
247 };
248 
249 static inline __u16 mtu2blksize(struct net_device *dev)
250 {
251         u32 blksize = dev->mtu;
252         if (blksize > 0xffff)
253                 blksize = 0xffff;
254 
255         if (dev->type == ARPHRD_ETHER ||
256             dev->type == ARPHRD_PPP ||
257             dev->type == ARPHRD_IPGRE ||
258             dev->type == ARPHRD_LOOPBACK)
259                 blksize -= 2;
260 
261         return (__u16)blksize;
262 }
263 
264 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
265 {
266         struct dn_dev_sysctl_table *t;
267         int i;
268 
269         t = kmalloc(sizeof(*t), GFP_KERNEL);
270         if (t == NULL)
271                 return;
272 
273         memcpy(t, &dn_dev_sysctl, sizeof(*t));
274 
275         for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) {
276                 long offset = (long)t->dn_dev_vars[i].data;
277                 t->dn_dev_vars[i].data = ((char *)parms) + offset;
278                 t->dn_dev_vars[i].de = NULL;
279         }
280 
281         if (dev) {
282                 t->dn_dev_dev[0].procname = dev->name;
283                 t->dn_dev_dev[0].ctl_name = dev->ifindex;
284         } else {
285                 t->dn_dev_dev[0].procname = parms->name;
286                 t->dn_dev_dev[0].ctl_name = parms->ctl_name;
287         }
288 
289         t->dn_dev_dev[0].child = t->dn_dev_vars;
290         t->dn_dev_dev[0].de = NULL;
291         t->dn_dev_conf_dir[0].child = t->dn_dev_dev;
292         t->dn_dev_conf_dir[0].de = NULL;
293         t->dn_dev_proto_dir[0].child = t->dn_dev_conf_dir;
294         t->dn_dev_proto_dir[0].de = NULL;
295         t->dn_dev_root_dir[0].child = t->dn_dev_proto_dir;
296         t->dn_dev_root_dir[0].de = NULL;
297         t->dn_dev_vars[0].extra1 = (void *)dev;
298 
299         t->sysctl_header = register_sysctl_table(t->dn_dev_root_dir, 0);
300         if (t->sysctl_header == NULL)
301                 kfree(t);
302         else
303                 parms->sysctl = t;
304 }
305 
306 static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
307 {
308         if (parms->sysctl) {
309                 struct dn_dev_sysctl_table *t = parms->sysctl;
310                 parms->sysctl = NULL;
311                 unregister_sysctl_table(t->sysctl_header);
312                 kfree(t);
313         }
314 }
315 
316 struct net_device *dn_dev_get_default(void)
317 {
318         struct net_device *dev;
319         read_lock(&dndev_lock);
320         dev = decnet_default_device;
321         if (dev) {
322                 if (dev->dn_ptr)
323                         dev_hold(dev);
324                 else
325                         dev = NULL;
326         }
327         read_unlock(&dndev_lock);
328         return dev;
329 }
330 
331 int dn_dev_set_default(struct net_device *dev, int force)
332 {
333         struct net_device *old = NULL;
334         int rv = -EBUSY;
335         if (!dev->dn_ptr)
336                 return -ENODEV;
337         write_lock(&dndev_lock);
338         if (force || decnet_default_device == NULL) {
339                 old = decnet_default_device;
340                 decnet_default_device = dev;
341                 rv = 0;
342         }
343         write_unlock(&dndev_lock);
344         if (old)
345                 dev_put(dev);
346         return rv;
347 }
348 
349 static void dn_dev_check_default(struct net_device *dev)
350 {
351         write_lock(&dndev_lock);
352         if (dev == decnet_default_device) {
353                 decnet_default_device = NULL;
354         } else {
355                 dev = NULL;
356         }
357         write_unlock(&dndev_lock);
358         if (dev)
359                 dev_put(dev);
360 }
361 
362 static int dn_forwarding_proc(ctl_table *table, int write, 
363                                 struct file *filep,
364                                 void *buffer, size_t *lenp)
365 {
366 #ifdef CONFIG_DECNET_ROUTER
367         struct net_device *dev = table->extra1;
368         struct dn_dev *dn_db;
369         int err;
370         int tmp, old;
371 
372         if (table->extra1 == NULL)
373                 return -EINVAL;
374 
375         dn_db = dev->dn_ptr;
376         old = dn_db->parms.forwarding;
377 
378         err = proc_dointvec(table, write, filep, buffer, lenp);
379 
380         if ((err >= 0) && write) {
381                 if (dn_db->parms.forwarding < 0)
382                         dn_db->parms.forwarding = 0;
383                 if (dn_db->parms.forwarding > 2)
384                         dn_db->parms.forwarding = 2;
385                 /*
386                  * What an ugly hack this is... its works, just. It
387                  * would be nice if sysctl/proc were just that little
388                  * bit more flexible so I don't have to write a special
389                  * routine, or suffer hacks like this - SJW
390                  */
391                 tmp = dn_db->parms.forwarding;
392                 dn_db->parms.forwarding = old;
393                 if (dn_db->parms.down)
394                         dn_db->parms.down(dev);
395                 dn_db->parms.forwarding = tmp;
396                 if (dn_db->parms.up)
397                         dn_db->parms.up(dev);
398         }
399 
400         return err;
401 #else
402         return -EINVAL;
403 #endif
404 }
405 
406 static int dn_forwarding_sysctl(ctl_table *table, int *name, int nlen,
407                         void *oldval, size_t *oldlenp,
408                         void *newval, size_t newlen,
409                         void **context)
410 {
411 #ifdef CONFIG_DECNET_ROUTER
412         struct net_device *dev = table->extra1;
413         struct dn_dev *dn_db;
414         int value;
415 
416         if (table->extra1 == NULL)
417                 return -EINVAL;
418 
419         dn_db = dev->dn_ptr;
420 
421         if (newval && newlen) {
422                 if (newlen != sizeof(int))
423                         return -EINVAL;
424 
425                 if (get_user(value, (int *)newval))
426                         return -EFAULT;
427                 if (value < 0)
428                         return -EINVAL;
429                 if (value > 2)
430                         return -EINVAL;
431 
432                 if (dn_db->parms.down)
433                         dn_db->parms.down(dev);
434                 dn_db->parms.forwarding = value;
435                 if (dn_db->parms.up)
436                         dn_db->parms.up(dev);
437         }
438 
439         return 0;
440 #else
441         return -EINVAL;
442 #endif
443 }
444 
445 #else /* CONFIG_SYSCTL */
446 static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
447 {
448 }
449 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
450 {
451 }
452 
453 #endif /* CONFIG_SYSCTL */
454 
455 static struct dn_ifaddr *dn_dev_alloc_ifa(void)
456 {
457         struct dn_ifaddr *ifa;
458 
459         ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
460 
461         if (ifa) {
462                 memset(ifa, 0, sizeof(*ifa));
463         }
464 
465         return ifa;
466 }
467 
468 static __inline__ void dn_dev_free_ifa(struct dn_ifaddr *ifa)
469 {
470         kfree(ifa);
471 }
472 
473 static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int destroy)
474 {
475         struct dn_ifaddr *ifa1 = *ifap;
476         unsigned char mac_addr[6];
477         struct net_device *dev = dn_db->dev;
478 
479         ASSERT_RTNL();
480 
481         *ifap = ifa1->ifa_next;
482 
483         if (dn_db->dev->type == ARPHRD_ETHER) {
484                 if (ifa1->ifa_local != dn_htons(dn_eth2dn(dev->dev_addr))) {
485                         dn_dn2eth(mac_addr, ifa1->ifa_local);
486                         dev_mc_delete(dev, mac_addr, ETH_ALEN, 0);
487                 }
488         }
489 
490         rtmsg_ifa(RTM_DELADDR, ifa1);
491         notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
492         if (destroy) {
493                 dn_dev_free_ifa(ifa1);
494 
495                 if (dn_db->ifa_list == NULL)
496                         dn_dev_delete(dn_db->dev);
497         }
498 }
499 
500 static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
501 {
502         struct net_device *dev = dn_db->dev;
503         struct dn_ifaddr *ifa1;
504         unsigned char mac_addr[6];
505 
506         ASSERT_RTNL();
507 
508         /* Check for duplicates */      
509         for(ifa1 = dn_db->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
510                 if (ifa1->ifa_local == ifa->ifa_local)
511                         return -EEXIST;
512         }
513 
514         if (dev->type == ARPHRD_ETHER) {
515                 if (ifa->ifa_local != dn_htons(dn_eth2dn(dev->dev_addr))) {
516                         dn_dn2eth(mac_addr, ifa->ifa_local);
517                         dev_mc_add(dev, mac_addr, ETH_ALEN, 0);
518                         dev_mc_upload(dev);
519                 }
520         }
521 
522         ifa->ifa_next = dn_db->ifa_list;
523         dn_db->ifa_list = ifa;
524 
525         rtmsg_ifa(RTM_NEWADDR, ifa);
526         notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
527 
528         return 0;
529 }
530 
531 static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa)
532 {
533         struct dn_dev *dn_db = dev->dn_ptr;
534         int rv;
535 
536         if (dn_db == NULL) {
537                 int err;
538                 dn_db = dn_dev_create(dev, &err);
539                 if (dn_db == NULL)
540                         return err;
541         }
542 
543         ifa->ifa_dev = dn_db;
544 
545         if (dev->flags & IFF_LOOPBACK)
546                 ifa->ifa_scope = RT_SCOPE_HOST;
547 
548         rv = dn_dev_insert_ifa(dn_db, ifa);
549         if (rv)
550                 dn_dev_free_ifa(ifa);
551         return rv;
552 }
553 
554 
555 int dn_dev_ioctl(unsigned int cmd, void *arg)
556 {
557         char buffer[DN_IFREQ_SIZE];
558         struct ifreq *ifr = (struct ifreq *)buffer;
559         struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr;
560         struct dn_dev *dn_db;
561         struct net_device *dev;
562         struct dn_ifaddr *ifa = NULL, **ifap = NULL;
563         int ret = 0;
564 
565         if (copy_from_user(ifr, arg, DN_IFREQ_SIZE))
566                 return -EFAULT;
567         ifr->ifr_name[IFNAMSIZ-1] = 0;
568 
569 #ifdef CONFIG_KMOD
570         dev_load(ifr->ifr_name);
571 #endif
572 
573         switch(cmd) {
574                 case SIOCGIFADDR:
575                         break;
576                 case SIOCSIFADDR:
577                         if (!capable(CAP_NET_ADMIN))
578                                 return -EACCES;
579                         if (sdn->sdn_family != AF_DECnet)
580                                 return -EINVAL;
581                         break;
582                 default:
583                         return -EINVAL;
584         }
585 
586         rtnl_lock();
587 
588         if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL) {
589                 ret = -ENODEV;
590                 goto done;
591         }
592 
593         if ((dn_db = dev->dn_ptr) != NULL) {
594                 for (ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next)
595                         if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0)
596                                 break;
597         }
598 
599         if (ifa == NULL && cmd != SIOCSIFADDR) {
600                 ret = -EADDRNOTAVAIL;
601                 goto done;
602         }
603 
604         switch(cmd) {
605                 case SIOCGIFADDR:
606                         *((dn_address *)sdn->sdn_nodeaddr) = ifa->ifa_local;
607                         goto rarok;
608 
609                 case SIOCSIFADDR:
610                         if (!ifa) {
611                                 if ((ifa = dn_dev_alloc_ifa()) == NULL) {
612                                         ret = -ENOBUFS;
613                                         break;
614                                 }
615                                 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
616                         } else {
617                                 if (ifa->ifa_local == dn_saddr2dn(sdn))
618                                         break;
619                                 dn_dev_del_ifa(dn_db, ifap, 0);
620                         }
621 
622                         ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn);
623 
624                         ret = dn_dev_set_ifa(dev, ifa);
625         }
626 done:
627         rtnl_unlock();
628 
629         return ret;
630 rarok:
631         if (copy_to_user(arg, ifr, DN_IFREQ_SIZE))
632                 ret = -EFAULT;
633         goto done;
634 }
635 
636 static struct dn_dev *dn_dev_by_index(int ifindex)
637 {
638         struct net_device *dev;
639         struct dn_dev *dn_dev = NULL;
640         dev = dev_get_by_index(ifindex);
641         if (dev) {
642                 dn_dev = dev->dn_ptr;
643                 dev_put(dev);
644         }
645 
646         return dn_dev;
647 }
648 
649 static int dn_dev_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
650 {
651         struct rtattr **rta = arg;
652         struct dn_dev *dn_db;
653         struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
654         struct dn_ifaddr *ifa, **ifap;
655 
656         if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL)
657                 return -EADDRNOTAVAIL;
658 
659         for(ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next) {
660                 void *tmp = rta[IFA_LOCAL-1];
661                 if ((tmp && memcmp(RTA_DATA(tmp), &ifa->ifa_local, 2)) ||
662                                 (rta[IFA_LABEL-1] && strcmp(RTA_DATA(rta[IFA_LABEL-1]), ifa->ifa_label)))
663                         continue;
664 
665                 dn_dev_del_ifa(dn_db, ifap, 1);
666                 return 0;
667         }
668 
669         return -EADDRNOTAVAIL;
670 }
671 
672 static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
673 {
674         struct rtattr **rta = arg;
675         struct net_device *dev;
676         struct dn_dev *dn_db;
677         struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
678         struct dn_ifaddr *ifa;
679         int rv;
680 
681         if (rta[IFA_LOCAL-1] == NULL)
682                 return -EINVAL;
683 
684         if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
685                 return -ENODEV;
686 
687         if ((dn_db = dev->dn_ptr) == NULL) {
688                 int err;
689                 dn_db = dn_dev_create(dev, &err);
690                 if (!dn_db)
691                         return err;
692         }
693         
694         if ((ifa = dn_dev_alloc_ifa()) == NULL)
695                 return -ENOBUFS;
696 
697         if (!rta[IFA_ADDRESS - 1])
698                 rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1];
699         memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 2);
700         memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 2);
701         ifa->ifa_flags = ifm->ifa_flags;
702         ifa->ifa_scope = ifm->ifa_scope;
703         ifa->ifa_dev = dn_db;
704         if (rta[IFA_LABEL-1])
705                 memcpy(ifa->ifa_label, RTA_DATA(rta[IFA_LABEL-1]), IFNAMSIZ);
706         else
707                 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
708 
709         rv = dn_dev_insert_ifa(dn_db, ifa);
710         if (rv)
711                 dn_dev_free_ifa(ifa);
712         return rv;
713 }
714 
715 static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
716                                 u32 pid, u32 seq, int event)
717 {
718         struct ifaddrmsg *ifm;
719         struct nlmsghdr *nlh;
720         unsigned char *b = skb->tail;
721 
722         nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
723         ifm = NLMSG_DATA(nlh);
724 
725         ifm->ifa_family = AF_DECnet;
726         ifm->ifa_prefixlen = 16;
727         ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
728         ifm->ifa_scope = ifa->ifa_scope;
729         ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
730         if (ifa->ifa_address)
731                 RTA_PUT(skb, IFA_ADDRESS, 2, &ifa->ifa_address);
732         if (ifa->ifa_local)
733                 RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local);
734         if (ifa->ifa_label[0])
735                 RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
736         nlh->nlmsg_len = skb->tail - b;
737         return skb->len;
738 
739 nlmsg_failure:
740 rtattr_failure:
741         skb_trim(skb, b - skb->data);
742         return -1;
743 }
744 
745 static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
746 {
747         struct sk_buff *skb;
748         int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
749 
750         skb = alloc_skb(size, GFP_KERNEL);
751         if (!skb) {
752                 netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, ENOBUFS);
753                 return;
754         }
755         if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
756                 kfree_skb(skb);
757                 netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, EINVAL);
758                 return;
759         }
760         NETLINK_CB(skb).dst_groups = RTMGRP_DECnet_IFADDR;
761         netlink_broadcast(rtnl, skb, 0, RTMGRP_DECnet_IFADDR, GFP_KERNEL);
762 }
763 
764 static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
765 {
766         int idx, dn_idx;
767         int s_idx, s_dn_idx;
768         struct net_device *dev;
769         struct dn_dev *dn_db;
770         struct dn_ifaddr *ifa;
771 
772         s_idx = cb->args[0];
773         s_dn_idx = dn_idx = cb->args[1];
774         read_lock(&dev_base_lock);
775         for(dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
776                 if (idx < s_idx)
777                         continue;
778                 if (idx > s_idx)
779                         s_dn_idx = 0;
780                 if ((dn_db = dev->dn_ptr) == NULL)
781                         continue;
782 
783                 for(ifa = dn_db->ifa_list, dn_idx = 0; ifa; ifa = ifa->ifa_next, dn_idx++) {
784                         if (dn_idx < s_dn_idx)
785                                 continue;
786 
787                         if (dn_dev_fill_ifaddr(skb, ifa,
788                                                NETLINK_CB(cb->skb).pid,
789                                                cb->nlh->nlmsg_seq,
790                                                RTM_NEWADDR) <= 0)
791                                 goto done;
792                 }
793         }
794 done:
795         read_unlock(&dev_base_lock);
796         cb->args[0] = idx;
797         cb->args[1] = dn_idx;
798 
799         return skb->len;
800 }
801 
802 static int dn_dev_get_first(struct net_device *dev, dn_address *addr)
803 {
804         struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
805         struct dn_ifaddr *ifa;
806         int rv = -ENODEV;
807         if (dn_db == NULL)
808                 goto out;
809         ifa = dn_db->ifa_list;
810         if (ifa != NULL) {
811                 *addr = ifa->ifa_local;
812                 rv = 0;
813         }
814 out:
815         return rv;
816 }
817 
818 /* 
819  * Find a default address to bind to.
820  *
821  * This is one of those areas where the initial VMS concepts don't really
822  * map onto the Linux concepts, and since we introduced multiple addresses
823  * per interface we have to cope with slightly odd ways of finding out what
824  * "our address" really is. Mostly it's not a problem; for this we just guess
825  * a sensible default. Eventually the routing code will take care of all the
826  * nasties for us I hope.
827  */
828 int dn_dev_bind_default(dn_address *addr)
829 {
830         struct net_device *dev;
831         int rv;
832         dev = dn_dev_get_default();
833 last_chance:
834         if (dev) {
835                 read_lock(&dev_base_lock);
836                 rv = dn_dev_get_first(dev, addr);
837                 read_unlock(&dev_base_lock);
838                 dev_put(dev);
839                 if (rv == 0 || dev == &loopback_dev)
840                         return rv;
841         }
842         dev = &loopback_dev;
843         dev_hold(dev);
844         goto last_chance;
845 }
846 
847 static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa)
848 {
849         struct endnode_hello_message *msg;
850         struct sk_buff *skb = NULL;
851         unsigned short int *pktlen;
852         struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
853 
854         if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
855                 return;
856 
857         skb->dev = dev;
858 
859         msg = (struct endnode_hello_message *)skb_put(skb,sizeof(*msg));
860 
861         msg->msgflg  = 0x0D;
862         memcpy(msg->tiver, dn_eco_version, 3);
863         dn_dn2eth(msg->id, ifa->ifa_local);
864         msg->iinfo   = DN_RT_INFO_ENDN;
865         msg->blksize = dn_htons(mtu2blksize(dev));
866         msg->area    = 0x00;
867         memset(msg->seed, 0, 8);
868         memcpy(msg->neighbor, dn_hiord, ETH_ALEN);
869 
870         if (dn_db->router) {
871                 struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
872                 dn_dn2eth(msg->neighbor, dn->addr);
873         }
874 
875         msg->timer   = dn_htons((unsigned short)dn_db->parms.t3);
876         msg->mpd     = 0x00;
877         msg->datalen = 0x02;
878         memset(msg->data, 0xAA, 2);
879         
880         pktlen = (unsigned short *)skb_push(skb,2);
881         *pktlen = dn_htons(skb->len - 2);
882 
883         skb->nh.raw = skb->data;
884 
885         dn_rt_finish_output(skb, dn_rt_all_rt_mcast, msg->id);
886 }
887 
888 
889 #define DRDELAY (5 * HZ)
890 
891 static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn_ifaddr *ifa)
892 {
893         /* First check time since device went up */
894         if ((jiffies - dn_db->uptime) < DRDELAY)
895                 return 0;
896 
897         /* If there is no router, then yes... */
898         if (!dn_db->router)
899                 return 1;
900 
901         /* otherwise only if we have a higher priority or.. */
902         if (dn->priority < dn_db->parms.priority)
903                 return 1;
904 
905         /* if we have equal priority and a higher node number */
906         if (dn->priority != dn_db->parms.priority)
907                 return 0;
908 
909         if (dn_ntohs(dn->addr) < dn_ntohs(ifa->ifa_local))
910                 return 1;
911 
912         return 0;
913 }
914 
915 static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
916 {
917         int n;
918         struct dn_dev *dn_db = dev->dn_ptr;
919         struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
920         struct sk_buff *skb;
921         size_t size;
922         unsigned char *ptr;
923         unsigned char *i1, *i2;
924         unsigned short *pktlen;
925         char *src;
926 
927         if (mtu2blksize(dev) < (26 + 7))
928                 return;
929 
930         n = mtu2blksize(dev) - 26;
931         n /= 7;
932 
933         if (n > 32)
934                 n = 32;
935 
936         size = 2 + 26 + 7 * n;
937 
938         if ((skb = dn_alloc_skb(NULL, size, GFP_ATOMIC)) == NULL)
939                 return;
940 
941         skb->dev = dev;
942         ptr = skb_put(skb, size);
943 
944         *ptr++ = DN_RT_PKT_CNTL | DN_RT_PKT_ERTH;
945         *ptr++ = 2; /* ECO */
946         *ptr++ = 0;
947         *ptr++ = 0;
948         dn_dn2eth(ptr, ifa->ifa_local);
949         src = ptr;
950         ptr += ETH_ALEN;
951         *ptr++ = dn_db->parms.forwarding == 1 ? 
952                         DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
953         *((unsigned short *)ptr) = dn_htons(mtu2blksize(dev));
954         ptr += 2;
955         *ptr++ = dn_db->parms.priority; /* Priority */ 
956         *ptr++ = 0; /* Area: Reserved */
957         *((unsigned short *)ptr) = dn_htons((unsigned short)dn_db->parms.t3);
958         ptr += 2;
959         *ptr++ = 0; /* MPD: Reserved */
960         i1 = ptr++;
961         memset(ptr, 0, 7); /* Name: Reserved */
962         ptr += 7;
963         i2 = ptr++;
964 
965         n = dn_neigh_elist(dev, ptr, n);
966 
967         *i2 = 7 * n;
968         *i1 = 8 + *i2;
969 
970         skb_trim(skb, (27 + *i2));
971 
972         pktlen = (unsigned short *)skb_push(skb, 2);
973         *pktlen = dn_htons(skb->len - 2);
974 
975         skb->nh.raw = skb->data;
976 
977         if (dn_am_i_a_router(dn, dn_db, ifa)) {
978                 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
979                 if (skb2) {
980                         dn_rt_finish_output(skb2, dn_rt_all_end_mcast, src);
981                 }
982         }
983 
984         dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);
985 }
986 
987 static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa)
988 {
989         struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
990 
991         if (dn_db->parms.forwarding == 0)
992                 dn_send_endnode_hello(dev, ifa);
993         else
994                 dn_send_router_hello(dev, ifa);
995 }
996 
997 static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa)
998 {
999         int tdlen = 16;
1000         int size = dev->hard_header_len + 2 + 4 + tdlen;
1001         struct sk_buff *skb = dn_alloc_skb(NULL, size, GFP_ATOMIC);
1002         int i;
1003         unsigned char *ptr;
1004         char src[ETH_ALEN];
1005 
1006         if (skb == NULL)
1007                 return ;
1008 
1009         skb->dev = dev;
1010         skb_push(skb, dev->hard_header_len);
1011         ptr = skb_put(skb, 2 + 4 + tdlen);
1012 
1013         *ptr++ = DN_RT_PKT_HELO;
1014         *((dn_address *)ptr) = ifa->ifa_local;
1015         ptr += 2;
1016         *ptr++ = tdlen;
1017 
1018         for(i = 0; i < tdlen; i++)
1019                 *ptr++ = 0252;
1020 
1021         dn_dn2eth(src, ifa->ifa_local);
1022         dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);
1023 }
1024 
1025 static int dn_eth_up(struct net_device *dev)
1026 {
1027         struct dn_dev *dn_db = dev->dn_ptr;
1028 
1029         if (dn_db->parms.forwarding == 0)
1030                 dev_mc_add(dev, dn_rt_all_end_mcast, ETH_ALEN, 0);
1031         else
1032                 dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0);
1033 
1034         dev_mc_upload(dev);
1035 
1036         dn_db->use_long = 1;
1037 
1038         return 0;
1039 }
1040 
1041 static void dn_eth_down(struct net_device *dev)
1042 {
1043         struct dn_dev *dn_db = dev->dn_ptr;
1044 
1045         if (dn_db->parms.forwarding == 0)
1046                 dev_mc_delete(dev, dn_rt_all_end_mcast, ETH_ALEN, 0);
1047         else
1048                 dev_mc_delete(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0);
1049 }
1050 
1051 static void dn_dev_set_timer(struct net_device *dev);
1052 
1053 static void dn_dev_timer_func(unsigned long arg)
1054 {
1055         struct net_device *dev = (struct net_device *)arg;
1056         struct dn_dev *dn_db = dev->dn_ptr;
1057         struct dn_ifaddr *ifa;
1058 
1059         if (dn_db->t3 <= dn_db->parms.t2) {
1060                 if (dn_db->parms.timer3) {
1061                         for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) {
1062                                 if (!(ifa->ifa_flags & IFA_F_SECONDARY))
1063                                         dn_db->parms.timer3(dev, ifa);
1064                         }
1065                 }
1066                 dn_db->t3 = dn_db->parms.t3;
1067         } else {
1068                 dn_db->t3 -= dn_db->parms.t2;
1069         }
1070 
1071         dn_dev_set_timer(dev);
1072 }
1073 
1074 static void dn_dev_set_timer(struct net_device *dev)
1075 {
1076         struct dn_dev *dn_db = dev->dn_ptr;
1077 
1078         if (dn_db->parms.t2 > dn_db->parms.t3)
1079                 dn_db->parms.t2 = dn_db->parms.t3;
1080 
1081         dn_db->timer.data = (unsigned long)dev;
1082         dn_db->timer.function = dn_dev_timer_func;
1083         dn_db->timer.expires = jiffies + (dn_db->parms.t2 * HZ);
1084 
1085         add_timer(&dn_db->timer);
1086 }
1087 
1088 struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
1089 {
1090         int i;
1091         struct dn_dev_parms *p = dn_dev_list;
1092         struct dn_dev *dn_db;
1093 
1094         for(i = 0; i < DN_DEV_LIST_SIZE; i++, p++) {
1095                 if (p->type == dev->type)
1096                         break;
1097         }
1098 
1099         *err = -ENODEV;
1100         if (i == DN_DEV_LIST_SIZE)
1101                 return NULL;
1102 
1103         *err = -ENOBUFS;
1104         if ((dn_db = kmalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)
1105                 return NULL;
1106 
1107         memset(dn_db, 0, sizeof(struct dn_dev));
1108         memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
1109         dev->dn_ptr = dn_db;
1110         dn_db->dev = dev;
1111         init_timer(&dn_db->timer);
1112 
1113         dn_db->uptime = jiffies;
1114         if (dn_db->parms.up) {
1115                 if (dn_db->parms.up(dev) < 0) {
1116                         dev->dn_ptr = NULL;
1117                         kfree(dn_db);
1118                         return NULL;
1119                 }
1120         }
1121 
1122         dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
1123 
1124         dn_dev_sysctl_register(dev, &dn_db->parms);
1125 
1126         dn_dev_set_timer(dev);
1127 
1128         *err = 0;
1129         return dn_db;
1130 }
1131 
1132 
1133 /*
1134  * This processes a device up event. We only start up
1135  * the loopback device & ethernet devices with correct
1136  * MAC addreses automatically. Others must be started
1137  * specifically.
1138  *
1139  * FIXME: How should we configure the loopback address ? If we could dispense
1140  * with using decnet_address here and for autobind, it will be one less thing
1141  * for users to worry about setting up.
1142  */
1143 
1144 void dn_dev_up(struct net_device *dev)
1145 {
1146         struct dn_ifaddr *ifa;
1147         dn_address addr = decnet_address;
1148         int maybe_default = 0;
1149         struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
1150 
1151         if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
1152                 return;
1153 
1154         /*
1155          * Need to ensure that loopback device has a dn_db attached to it
1156          * to allow creation of neighbours against it, even though it might
1157          * not have a local address of its own. Might as well do the same for
1158          * all autoconfigured interfaces.
1159          */
1160         if (dn_db == NULL) {
1161                 int err;
1162                 dn_db = dn_dev_create(dev, &err);
1163                 if (dn_db == NULL)
1164                         return;
1165         }
1166 
1167         if (dev->type == ARPHRD_ETHER) {
1168                 if (memcmp(dev->dev_addr, dn_hiord, 4) != 0)
1169                         return;
1170                 addr = dn_htons(dn_eth2dn(dev->dev_addr));
1171                 maybe_default = 1;
1172         }
1173 
1174         if (addr == 0)
1175                 return;
1176 
1177         if ((ifa = dn_dev_alloc_ifa()) == NULL)
1178                 return;
1179 
1180         ifa->ifa_local = ifa->ifa_address = addr;
1181         ifa->ifa_flags = 0;
1182         ifa->ifa_scope = RT_SCOPE_UNIVERSE;
1183         strcpy(ifa->ifa_label, dev->name);
1184 
1185         dn_dev_set_ifa(dev, ifa);
1186 
1187         /*
1188          * Automagically set the default device to the first automatically
1189          * configured ethernet card in the system.
1190          */
1191         if (maybe_default) {
1192                 dev_hold(dev);
1193                 if (dn_dev_set_default(dev, 0))
1194                         dev_put(dev);
1195         }
1196 }
1197 
1198 static void dn_dev_delete(struct net_device *dev)
1199 {
1200         struct dn_dev *dn_db = dev->dn_ptr;
1201 
1202         if (dn_db == NULL)
1203                 return;
1204 
1205         del_timer_sync(&dn_db->timer);
1206         dn_dev_sysctl_unregister(&dn_db->parms);
1207         dn_dev_check_default(dev);
1208         neigh_ifdown(&dn_neigh_table, dev);
1209 
1210         if (dn_db->parms.down)
1211                 dn_db->parms.down(dev);
1212 
1213         dev->dn_ptr = NULL;
1214 
1215         neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
1216 
1217         if (dn_db->router)
1218                 neigh_release(dn_db->router);
1219         if (dn_db->peer)
1220                 neigh_release(dn_db->peer);
1221 
1222         kfree(dn_db);
1223 }
1224 
1225 void dn_dev_down(struct net_device *dev)
1226 {
1227         struct dn_dev *dn_db = dev->dn_ptr;
1228         struct dn_ifaddr *ifa;
1229 
1230         if (dn_db == NULL)
1231                 return;
1232 
1233         while((ifa = dn_db->ifa_list) != NULL) {
1234                 dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0);
1235                 dn_dev_free_ifa(ifa);
1236         }
1237 
1238         dn_dev_delete(dev);
1239 }
1240 
1241 void dn_dev_init_pkt(struct sk_buff *skb)
1242 {
1243         return;
1244 }
1245 
1246 void dn_dev_veri_pkt(struct sk_buff *skb)
1247 {
1248         return;
1249 }
1250 
1251 void dn_dev_hello(struct sk_buff *skb)
1252 {
1253         return;
1254 }
1255 
1256 void dn_dev_devices_off(void)
1257 {
1258         struct net_device *dev;
1259 
1260         rtnl_lock();
1261         for(dev = dev_base; dev; dev = dev->next)
1262                 dn_dev_down(dev);
1263         rtnl_unlock();
1264 
1265 }
1266 
1267 void dn_dev_devices_on(void)
1268 {
1269         struct net_device *dev;
1270 
1271         rtnl_lock();
1272         for(dev = dev_base; dev; dev = dev->next) {
1273                 if (dev->flags & IFF_UP)
1274                         dn_dev_up(dev);
1275         }
1276         rtnl_unlock();
1277 }
1278 
1279 int register_dnaddr_notifier(struct notifier_block *nb)
1280 {
1281         return notifier_chain_register(&dnaddr_chain, nb);
1282 }
1283 
1284 int unregister_dnaddr_notifier(struct notifier_block *nb)
1285 {
1286         return notifier_chain_unregister(&dnaddr_chain, nb);
1287 }
1288 
1289 #ifdef CONFIG_DECNET_SIOCGIFCONF
1290 /*
1291  * Now we support multiple addresses per interface.
1292  * Since we don't want to break existing code, you have to enable
1293  * it as a compile time option. Probably you should use the
1294  * rtnetlink interface instead.
1295  */
1296 int dnet_gifconf(struct net_device *dev, char *buf, int len)
1297 {
1298         struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
1299         struct dn_ifaddr *ifa;
1300         struct ifreq *ifr = (struct ifreq *)buf;
1301         int done = 0;
1302 
1303         if ((dn_db == NULL) || ((ifa = dn_db->ifa_list) == NULL))
1304                 return 0;
1305 
1306         for(; ifa; ifa = ifa->ifa_next) {
1307                 if (!ifr) {
1308                         done += sizeof(DN_IFREQ_SIZE);
1309                         continue;
1310                 }
1311                 if (len < DN_IFREQ_SIZE)
1312                         return done;
1313                 memset(ifr, 0, DN_IFREQ_SIZE);
1314 
1315                 if (ifa->ifa_label)
1316                         strcpy(ifr->ifr_name, ifa->ifa_label);
1317                 else
1318                         strcpy(ifr->ifr_name, dev->name);
1319 
1320                 (*(struct sockaddr_dn *) &ifr->ifr_addr).sdn_family = AF_DECnet;
1321                 (*(struct sockaddr_dn *) &ifr->ifr_addr).sdn_add.a_len = 2;
1322                 (*(dn_address *)(*(struct sockaddr_dn *) &ifr->ifr_addr).sdn_add.a_addr) = ifa->ifa_local;
1323 
1324                 ifr = (struct ifreq *)((char *)ifr + DN_IFREQ_SIZE);
1325                 len  -= DN_IFREQ_SIZE;
1326                 done += DN_IFREQ_SIZE;
1327         }
1328 
1329         return done;
1330 }
1331 #endif /* CONFIG_DECNET_SIOCGIFCONF */
1332 
1333 
1334 #ifdef CONFIG_PROC_FS
1335 static inline struct net_device *dn_dev_get_next(struct seq_file *seq, struct net_device *dev)
1336 {
1337         do {
1338                 dev = dev->next;
1339         } while(dev && !dev->dn_ptr);
1340 
1341         return dev;
1342 }
1343 
1344 static struct net_device *dn_dev_get_idx(struct seq_file *seq, loff_t pos)
1345 {
1346         struct net_device *dev;
1347 
1348         dev = dev_base;
1349         if (dev && !dev->dn_ptr)
1350                 dev = dn_dev_get_next(seq, dev);
1351         if (pos) {
1352                 while(dev && (dev = dn_dev_get_next(seq, dev)))
1353                         --pos;
1354         }
1355         return dev;
1356 }
1357 
1358 static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
1359 {
1360         if (*pos) {
1361                 struct net_device *dev;
1362                 read_lock(&dev_base_lock);
1363                 dev = dn_dev_get_idx(seq, *pos - 1);
1364                 if (dev == NULL)
1365                         read_unlock(&dev_base_lock);
1366                 return dev;
1367         }
1368         return SEQ_START_TOKEN;
1369 }
1370 
1371 static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1372 {
1373         struct net_device *dev = v;
1374         loff_t one = 1;
1375 
1376         if (v == SEQ_START_TOKEN) {
1377                 dev = dn_dev_seq_start(seq, &one);
1378         } else {
1379                 dev = dn_dev_get_next(seq, dev);
1380                 if (dev == NULL)
1381                         read_unlock(&dev_base_lock);
1382         }
1383         ++*pos;
1384         return dev;
1385 }
1386 
1387 static void dn_dev_seq_stop(struct seq_file *seq, void *v)
1388 {
1389         if (v && v != SEQ_START_TOKEN)
1390                 read_unlock(&dev_base_lock);
1391 }
1392 
1393 static char *dn_type2asc(char type)
1394 {
1395         switch(type) {
1396                 case DN_DEV_BCAST:
1397                         return "B";
1398                 case DN_DEV_UCAST:
1399                         return "U";
1400                 case DN_DEV_MPOINT:
1401                         return "M";
1402         }
1403 
1404         return "?";
1405 }
1406 
1407 static int dn_dev_seq_show(struct seq_file *seq, void *v)
1408 {
1409         if (v == SEQ_START_TOKEN)
1410                 seq_puts(seq, "Name     Flags T1   Timer1 T3   Timer3 BlkSize Pri State DevType    Router Peer\n");
1411         else {
1412                 struct net_device *dev = v;
1413                 char peer_buf[DN_ASCBUF_LEN];
1414                 char router_buf[DN_ASCBUF_LEN];
1415                 struct dn_dev *dn_db = dev->dn_ptr;
1416 
1417                 seq_printf(seq, "%-8s %1s     %04u %04u   %04lu %04lu"
1418                                 "   %04hu    %03d %02x    %-10s %-7s %-7s\n",
1419                                 dev->name ? dev->name : "???",
1420                                 dn_type2asc(dn_db->parms.mode),
1421                                 0, 0,
1422                                 dn_db->t3, dn_db->parms.t3,
1423                                 mtu2blksize(dev),
1424                                 dn_db->parms.priority,
1425                                 dn_db->parms.state, dn_db->parms.name,
1426                                 dn_db->router ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->router->primary_key), router_buf) : "",
1427                                 dn_db->peer ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->peer->primary_key), peer_buf) : "");
1428         }
1429         return 0;
1430 }
1431 
1432 static struct seq_operations dn_dev_seq_ops = {
1433         .start  = dn_dev_seq_start,
1434         .next   = dn_dev_seq_next,
1435         .stop   = dn_dev_seq_stop,
1436         .show   = dn_dev_seq_show,
1437 };
1438 
1439 static int dn_dev_seq_open(struct inode *inode, struct file *file)
1440 {
1441         return seq_open(file, &dn_dev_seq_ops);
1442 }
1443 
1444 static struct file_operations dn_dev_seq_fops = {
1445         .owner   = THIS_MODULE,
1446         .open    = dn_dev_seq_open,
1447         .read    = seq_read,
1448         .llseek  = seq_lseek,
1449         .release = seq_release,
1450 };
1451 
1452 #endif /* CONFIG_PROC_FS */
1453 
1454 static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] = 
1455 {
1456          [4] = { .doit   = dn_dev_rtm_newaddr,  },
1457          [5] = { .doit   = dn_dev_rtm_deladdr,  },
1458          [6] = { .dumpit = dn_dev_dump_ifaddr,  },
1459 
1460 #ifdef CONFIG_DECNET_ROUTER
1461          [8] = { .doit   = dn_fib_rtm_newroute, },
1462          [9] = { .doit   = dn_fib_rtm_delroute, },
1463         [10] = { .doit   = dn_cache_getroute, .dumpit = dn_fib_dump, },
1464         [16] = { .doit   = dn_fib_rtm_newrule, },
1465         [17] = { .doit   = dn_fib_rtm_delrule, },
1466         [18] = { .dumpit = dn_fib_dump_rules,  },
1467 #else
1468         [10] = { .doit   = dn_cache_getroute, .dumpit = dn_cache_dump, },
1469 #endif
1470 
1471 };
1472 
1473 #ifdef MODULE
1474 static int addr[2];
1475 
1476 MODULE_PARM(addr, "2i");
1477 MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
1478 #endif
1479 
1480 void __init dn_dev_init(void)
1481 {
1482 #ifdef MODULE
1483         if (addr[0] > 63 || addr[0] < 0) {
1484                 printk(KERN_ERR "DECnet: Area must be between 0 and 63");
1485                 return;
1486         }
1487 
1488         if (addr[1] > 1023 || addr[1] < 0) {
1489                 printk(KERN_ERR "DECnet: Node must be between 0 and 1023");
1490                 return;
1491         }
1492 
1493         decnet_address = dn_htons((addr[0] << 10) | addr[1]);
1494 #endif
1495 
1496         dn_dev_devices_on();
1497 #ifdef CONFIG_DECNET_SIOCGIFCONF
1498         register_gifconf(PF_DECnet, dnet_gifconf);
1499 #endif /* CONFIG_DECNET_SIOCGIFCONF */
1500 
1501         rtnetlink_links[PF_DECnet] = dnet_rtnetlink_table;
1502 
1503         proc_net_fops_create("decnet_dev", S_IRUGO, &dn_dev_seq_fops);
1504 
1505 #ifdef CONFIG_SYSCTL
1506         {
1507                 int i;
1508                 for(i = 0; i < DN_DEV_LIST_SIZE; i++)
1509                         dn_dev_sysctl_register(NULL, &dn_dev_list[i]);
1510         }
1511 #endif /* CONFIG_SYSCTL */
1512 }
1513 
1514 void __exit dn_dev_cleanup(void)
1515 {
1516         rtnetlink_links[PF_DECnet] = NULL;
1517 
1518 #ifdef CONFIG_DECNET_SIOCGIFCONF
1519         unregister_gifconf(PF_DECnet);
1520 #endif /* CONFIG_DECNET_SIOCGIFCONF */
1521 
1522 #ifdef CONFIG_SYSCTL
1523         {
1524                 int i;
1525                 for(i = 0; i < DN_DEV_LIST_SIZE; i++)
1526                         dn_dev_sysctl_unregister(&dn_dev_list[i]);
1527         }
1528 #endif /* CONFIG_SYSCTL */
1529 
1530         proc_net_remove("decnet_dev");
1531 
1532         dn_dev_devices_off();
1533 }
1534 
1535 #ifndef MODULE
1536 static int __init decnet_setup(char *str)
1537 {
1538         unsigned short area = simple_strtoul(str, &str, 0);
1539         unsigned short node = simple_strtoul(*str > 0 ? ++str : str, &str, 0);
1540 
1541         decnet_address = dn_htons(area << 10 | node);
1542 
1543         return 1;
1544 }
1545 
1546 __setup("decnet=", decnet_setup);  
1547 #endif
1548 
1549 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp