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 - its a user space issue now
22  *         Patrick Caulfield : Fixed router hello message format
23  */
24 
25 #include <linux/config.h>
26 #include <linux/net.h>
27 #include <linux/netdevice.h>
28 #include <linux/proc_fs.h>
29 #include <linux/timer.h>
30 #include <linux/string.h>
31 #include <linux/if_arp.h>
32 #include <linux/if_ether.h>
33 #include <linux/init.h>
34 #include <linux/skbuff.h>
35 #include <linux/rtnetlink.h>
36 #include <linux/sysctl.h>
37 #include <asm/uaccess.h>
38 #include <net/neighbour.h>
39 #include <net/dst.h>
40 #include <net/dn.h>
41 #include <net/dn_dev.h>
42 #include <net/dn_route.h>
43 #include <net/dn_neigh.h>
44 #include <net/dn_fib.h>
45 
46 #define DN_IFREQ_SIZE (sizeof(struct ifreq) - sizeof(struct sockaddr) + sizeof(struct sockaddr_dn))
47 
48 static char dn_rt_all_end_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x04,0x00,0x00};
49 static char dn_rt_all_rt_mcast[ETH_ALEN]  = {0xAB,0x00,0x00,0x03,0x00,0x00};
50 static char dn_hiord[ETH_ALEN]            = {0xAA,0x00,0x04,0x00,0x00,0x00};
51 static unsigned char dn_eco_version[3]    = {0x02,0x00,0x00};
52 
53 extern struct neigh_table dn_neigh_table;
54 
55 struct net_device *decnet_default_device;
56 
57 static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
58 static void dn_dev_delete(struct net_device *dev);
59 static void rtmsg_ifa(int event, struct dn_ifaddr *ifa);
60 
61 static int dn_eth_up(struct net_device *);
62 static void dn_send_brd_hello(struct net_device *dev);
63 #if 0
64 static void dn_send_ptp_hello(struct net_device *dev);
65 #endif
66 
67 static struct dn_dev_parms dn_dev_list[] =  {
68 {
69 	type:		ARPHRD_ETHER, /* Ethernet */
70 	mode:		DN_DEV_BCAST,
71 	state:		DN_DEV_S_RU,
72 	blksize:	1498,
73 	t2:		1,
74 	t3:		10,
75 	name:		"ethernet",
76 	ctl_name:	NET_DECNET_CONF_ETHER,
77 	up:		dn_eth_up,
78 	timer3:		dn_send_brd_hello,
79 },
80 {
81 	type:		ARPHRD_IPGRE, /* DECnet tunneled over GRE in IP */
82 	mode:		DN_DEV_BCAST,
83 	state:		DN_DEV_S_RU,
84 	blksize:	1400,
85 	t2:		1,
86 	t3:		10,
87 	name:		"ipgre",
88 	ctl_name:	NET_DECNET_CONF_GRE,
89 	timer3:		dn_send_brd_hello,
90 },
91 #if 0
92 {
93 	type:		ARPHRD_X25, /* Bog standard X.25 */
94 	mode:		DN_DEV_UCAST,
95 	state:		DN_DEV_S_DS,
96 	blksize:	230,
97 	t2:		1,
98 	t3:		120,
99 	name:		"x25",
100 	ctl_name:	NET_DECNET_CONF_X25,
101 	timer3:		dn_send_ptp_hello,
102 },
103 #endif
104 #if 0
105 {
106 	type:		ARPHRD_PPP, /* DECnet over PPP */
107 	mode:		DN_DEV_BCAST,
108 	state:		DN_DEV_S_RU,
109 	blksize:	230,
110 	t2:		1,
111 	t3:		10,
112 	name:		"ppp",
113 	ctl_name:	NET_DECNET_CONF_PPP,
114 	timer3:		dn_send_brd_hello,
115 },
116 #endif
117 #if 0
118 {
119 	type:		ARPHRD_DDCMP, /* DECnet over DDCMP */
120 	mode:		DN_DEV_UCAST,
121 	state:		DN_DEV_S_DS,
122 	blksize:	230,
123 	t2:		1,
124 	t3:		120,
125 	name:		"ddcmp",
126 	ctl_name:	NET_DECNET_CONF_DDCMP,
127 	timer3:		dn_send_ptp_hello,
128 },
129 #endif
130 {
131 	type:		ARPHRD_LOOPBACK, /* Loopback interface - always last */
132 	mode:		DN_DEV_BCAST,
133 	state:		DN_DEV_S_RU,
134 	blksize:	1498,
135 	t2:		1,
136 	t3:		10,
137 	name:		"loopback",
138 	ctl_name:	NET_DECNET_CONF_LOOPBACK,
139 	timer3:		dn_send_brd_hello,
140 }
141 };
142 
143 #define DN_DEV_LIST_SIZE (sizeof(dn_dev_list)/sizeof(struct dn_dev_parms))
144 
145 #define DN_DEV_PARMS_OFFSET(x) ((int) ((char *) &((struct dn_dev_parms *)0)->x))
146 
147 #ifdef CONFIG_SYSCTL
148 
149 static int min_t2[] = { 1 };
150 static int max_t2[] = { 60 }; /* No max specified, but this seems sensible */
151 static int min_t3[] = { 1 };
152 static int max_t3[] = { 8191 }; /* Must fit in 16 bits when multiplied by BCT3MULT or T3MULT */
153 
154 static int min_priority[1];
155 static int max_priority[] = { 127 }; /* From DECnet spec */
156 
157 static int dn_forwarding_proc(ctl_table *, int, struct file *,
158 			void *, size_t *);
159 static int dn_forwarding_sysctl(ctl_table *table, int *name, int nlen,
160 			void *oldval, size_t *oldlenp,
161 			void *newval, size_t newlen,
162 			void **context);
163 
164 static struct dn_dev_sysctl_table {
165 	struct ctl_table_header *sysctl_header;
166 	ctl_table dn_dev_vars[5];
167 	ctl_table dn_dev_dev[2];
168 	ctl_table dn_dev_conf_dir[2];
169 	ctl_table dn_dev_proto_dir[2];
170 	ctl_table dn_dev_root_dir[2];
171 } dn_dev_sysctl = {
172 	NULL,
173 	{
174 	{NET_DECNET_CONF_DEV_FORWARDING, "forwarding",
175 	(void *)DN_DEV_PARMS_OFFSET(forwarding),
176 	sizeof(int), 0644, NULL,
177 	dn_forwarding_proc, dn_forwarding_sysctl,
178 	NULL, NULL, NULL},
179 	{NET_DECNET_CONF_DEV_PRIORITY, "priority",
180 	(void *)DN_DEV_PARMS_OFFSET(priority),
181 	sizeof(int), 0644, NULL,
182 	proc_dointvec_minmax, sysctl_intvec,
183 	NULL, &min_priority, &max_priority},
184 	{NET_DECNET_CONF_DEV_T2, "t2", (void *)DN_DEV_PARMS_OFFSET(t2),
185 	sizeof(int), 0644, NULL,
186 	proc_dointvec_minmax, sysctl_intvec,
187 	NULL, &min_t2, &max_t2},
188 	{NET_DECNET_CONF_DEV_T3, "t3", (void *)DN_DEV_PARMS_OFFSET(t3),
189 	sizeof(int), 0644, NULL,
190 	proc_dointvec_minmax, sysctl_intvec,
191 	NULL, &min_t3, &max_t3},
192 	{0}
193 	},
194 	{{0, "", NULL, 0, 0555, dn_dev_sysctl.dn_dev_vars}, {0}},
195 	{{NET_DECNET_CONF, "conf", NULL, 0, 0555, dn_dev_sysctl.dn_dev_dev}, {0}},
196 	{{NET_DECNET, "decnet", NULL, 0, 0555, dn_dev_sysctl.dn_dev_conf_dir}, {0}},
197 	{{CTL_NET, "net", NULL, 0, 0555, dn_dev_sysctl.dn_dev_proto_dir}, {0}}
198 };
199 
dn_dev_sysctl_register(struct net_device * dev,struct dn_dev_parms * parms)200 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
201 {
202 	struct dn_dev_sysctl_table *t;
203 	int i;
204 
205 	t = kmalloc(sizeof(*t), GFP_KERNEL);
206 	if (t == NULL)
207 		return;
208 
209 	memcpy(t, &dn_dev_sysctl, sizeof(*t));
210 
211 	for(i = 0; i < (sizeof(t->dn_dev_vars)/sizeof(t->dn_dev_vars[0]) - 1); i++) {
212 		long offset = (long)t->dn_dev_vars[i].data;
213 		t->dn_dev_vars[i].data = ((char *)parms) + offset;
214 		t->dn_dev_vars[i].de = NULL;
215 	}
216 
217 	if (dev) {
218 		t->dn_dev_dev[0].procname = dev->name;
219 		t->dn_dev_dev[0].ctl_name = dev->ifindex;
220 	} else {
221 		t->dn_dev_dev[0].procname = parms->name;
222 		t->dn_dev_dev[0].ctl_name = parms->ctl_name;
223 	}
224 
225 	t->dn_dev_dev[0].child = t->dn_dev_vars;
226 	t->dn_dev_dev[0].de = NULL;
227 	t->dn_dev_conf_dir[0].child = t->dn_dev_dev;
228 	t->dn_dev_conf_dir[0].de = NULL;
229 	t->dn_dev_proto_dir[0].child = t->dn_dev_conf_dir;
230 	t->dn_dev_proto_dir[0].de = NULL;
231 	t->dn_dev_root_dir[0].child = t->dn_dev_proto_dir;
232 	t->dn_dev_root_dir[0].de = NULL;
233 	t->dn_dev_vars[0].extra1 = (void *)dev;
234 
235 	t->sysctl_header = register_sysctl_table(t->dn_dev_root_dir, 0);
236 	if (t->sysctl_header == NULL)
237 		kfree(t);
238 	else
239 		parms->sysctl = t;
240 }
241 
dn_dev_sysctl_unregister(struct dn_dev_parms * parms)242 static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
243 {
244 	if (parms->sysctl) {
245 		struct dn_dev_sysctl_table *t = parms->sysctl;
246 		parms->sysctl = NULL;
247 		unregister_sysctl_table(t->sysctl_header);
248 		kfree(t);
249 	}
250 }
251 
252 
dn_forwarding_proc(ctl_table * table,int write,struct file * filep,void * buffer,size_t * lenp)253 static int dn_forwarding_proc(ctl_table *table, int write,
254 				struct file *filep,
255 				void *buffer, size_t *lenp)
256 {
257 #ifdef CONFIG_DECNET_ROUTER
258 	struct net_device *dev = table->extra1;
259 	struct dn_dev *dn_db;
260 	int err;
261 	int tmp, old;
262 
263 	if (table->extra1 == NULL)
264 		return -EINVAL;
265 
266 	dn_db = dev->dn_ptr;
267 	old = dn_db->parms.forwarding;
268 
269 	err = proc_dointvec(table, write, filep, buffer, lenp);
270 
271 	if ((err >= 0) && write) {
272 		if (dn_db->parms.forwarding < 0)
273 			dn_db->parms.forwarding = 0;
274 		if (dn_db->parms.forwarding > 2)
275 			dn_db->parms.forwarding = 2;
276 		/*
277 		 * What an ugly hack this is... its works, just. It
278 		 * would be nice if sysctl/proc were just that little
279 		 * bit more flexible so I don't have to write a special
280 		 * routine, or suffer hacks like this - SJW
281 		 */
282 		tmp = dn_db->parms.forwarding;
283 		dn_db->parms.forwarding = old;
284 		if (dn_db->parms.down)
285 			dn_db->parms.down(dev);
286 		dn_db->parms.forwarding = tmp;
287 		if (dn_db->parms.up)
288 			dn_db->parms.up(dev);
289 	}
290 
291 	return err;
292 #else
293 	return -EINVAL;
294 #endif
295 }
296 
dn_forwarding_sysctl(ctl_table * table,int * name,int nlen,void * oldval,size_t * oldlenp,void * newval,size_t newlen,void ** context)297 static int dn_forwarding_sysctl(ctl_table *table, int *name, int nlen,
298 			void *oldval, size_t *oldlenp,
299 			void *newval, size_t newlen,
300 			void **context)
301 {
302 #ifdef CONFIG_DECNET_ROUTER
303 	struct net_device *dev = table->extra1;
304 	struct dn_dev *dn_db;
305 	int value;
306 
307 	if (table->extra1 == NULL)
308 		return -EINVAL;
309 
310 	dn_db = dev->dn_ptr;
311 
312 	if (newval && newlen) {
313 		if (newlen != sizeof(int))
314 			return -EINVAL;
315 
316 		if (get_user(value, (int *)newval))
317 			return -EFAULT;
318 		if (value < 0)
319 			return -EINVAL;
320 		if (value > 2)
321 			return -EINVAL;
322 
323 		if (dn_db->parms.down)
324 			dn_db->parms.down(dev);
325 		dn_db->parms.forwarding = value;
326 		if (dn_db->parms.up)
327 			dn_db->parms.up(dev);
328 	}
329 
330 	return 0;
331 #else
332 	return -EINVAL;
333 #endif
334 }
335 
336 #else /* CONFIG_SYSCTL */
dn_dev_sysctl_unregister(struct dn_dev_parms * parms)337 static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
338 {
339 }
dn_dev_sysctl_register(struct net_device * dev,struct dn_dev_parms * parms)340 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
341 {
342 }
343 
344 #endif /* CONFIG_SYSCTL */
345 
dn_dev_alloc_ifa(void)346 static struct dn_ifaddr *dn_dev_alloc_ifa(void)
347 {
348 	struct dn_ifaddr *ifa;
349 
350 	ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
351 
352 	if (ifa) {
353 		memset(ifa, 0, sizeof(*ifa));
354 	}
355 
356 	return ifa;
357 }
358 
dn_dev_free_ifa(struct dn_ifaddr * ifa)359 static __inline__ void dn_dev_free_ifa(struct dn_ifaddr *ifa)
360 {
361 	kfree(ifa);
362 }
363 
dn_dev_del_ifa(struct dn_dev * dn_db,struct dn_ifaddr ** ifap,int destroy)364 static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int destroy)
365 {
366 	struct dn_ifaddr *ifa1 = *ifap;
367 
368 	*ifap = ifa1->ifa_next;
369 
370 	rtmsg_ifa(RTM_DELADDR, ifa1);
371 
372 	if (destroy) {
373 		dn_dev_free_ifa(ifa1);
374 
375 		if (dn_db->ifa_list == NULL)
376 			dn_dev_delete(dn_db->dev);
377 	}
378 }
379 
dn_dev_insert_ifa(struct dn_dev * dn_db,struct dn_ifaddr * ifa)380 static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
381 {
382 	/*
383 	 * FIXME: Duplicate check here.
384 	 */
385 
386 	ifa->ifa_next = dn_db->ifa_list;
387 	dn_db->ifa_list = ifa;
388 
389 	rtmsg_ifa(RTM_NEWADDR, ifa);
390 
391 	return 0;
392 }
393 
dn_dev_set_ifa(struct net_device * dev,struct dn_ifaddr * ifa)394 static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa)
395 {
396 	struct dn_dev *dn_db = dev->dn_ptr;
397 
398 	if (dn_db == NULL) {
399 		int err;
400 		dn_db = dn_dev_create(dev, &err);
401 		if (dn_db == NULL)
402 			return err;
403 	}
404 
405 	ifa->ifa_dev = dn_db;
406 
407 	if (dev->flags & IFF_LOOPBACK)
408 		ifa->ifa_scope = RT_SCOPE_HOST;
409 
410 	return dn_dev_insert_ifa(dn_db, ifa);
411 }
412 
413 
dn_dev_ioctl(unsigned int cmd,void * arg)414 int dn_dev_ioctl(unsigned int cmd, void *arg)
415 {
416 	char buffer[DN_IFREQ_SIZE];
417 	struct ifreq *ifr = (struct ifreq *)buffer;
418 	struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr;
419 	struct dn_dev *dn_db;
420 	struct net_device *dev;
421 	struct dn_ifaddr *ifa = NULL, **ifap = NULL;
422 	int exclusive = 0;
423 	int ret = 0;
424 
425 	if (copy_from_user(ifr, arg, DN_IFREQ_SIZE))
426 		return -EFAULT;
427 	ifr->ifr_name[IFNAMSIZ-1] = 0;
428 
429 #ifdef CONFIG_KMOD
430 	dev_load(ifr->ifr_name);
431 #endif
432 
433 	switch(cmd) {
434 		case SIOCGIFADDR:
435 			break;
436 		case SIOCSIFADDR:
437 			if (!capable(CAP_NET_ADMIN))
438 				return -EACCES;
439 			if (sdn->sdn_family != AF_DECnet)
440 				return -EINVAL;
441 			rtnl_lock();
442 			exclusive = 1;
443 			break;
444 		default:
445 			return -EINVAL;
446 	}
447 
448 	if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL) {
449 		ret = -ENODEV;
450 		goto done;
451 	}
452 
453 	if ((dn_db = dev->dn_ptr) != NULL) {
454 		for (ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next)
455 			if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0)
456 				break;
457 	}
458 
459 	if (ifa == NULL && cmd != SIOCSIFADDR) {
460 		ret = -EADDRNOTAVAIL;
461 		goto done;
462 	}
463 
464 	switch(cmd) {
465 		case SIOCGIFADDR:
466 			*((dn_address *)sdn->sdn_nodeaddr) = ifa->ifa_local;
467 			goto rarok;
468 
469 		case SIOCSIFADDR:
470 			if (!ifa) {
471 				if ((ifa = dn_dev_alloc_ifa()) == NULL) {
472 					ret = -ENOBUFS;
473 					break;
474 				}
475 				memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
476 			} else {
477 				if (ifa->ifa_local == dn_saddr2dn(sdn))
478 					break;
479 				dn_dev_del_ifa(dn_db, ifap, 0);
480 			}
481 
482 			ifa->ifa_local = dn_saddr2dn(sdn);
483 
484 			ret = dn_dev_set_ifa(dev, ifa);
485 	}
486 done:
487 	if (exclusive)
488 		rtnl_unlock();
489 
490 	return ret;
491 rarok:
492 	if (copy_to_user(arg, ifr, DN_IFREQ_SIZE))
493 		return -EFAULT;
494 
495 	return 0;
496 }
497 
dn_dev_by_index(int ifindex)498 static struct dn_dev *dn_dev_by_index(int ifindex)
499 {
500 	struct net_device *dev;
501 	struct dn_dev *dn_dev = NULL;
502 	dev = dev_get_by_index(ifindex);
503 	if (dev) {
504 		dn_dev = dev->dn_ptr;
505 		dev_put(dev);
506 	}
507 
508 	return dn_dev;
509 }
510 
dn_dev_rtm_deladdr(struct sk_buff * skb,struct nlmsghdr * nlh,void * arg)511 static int dn_dev_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
512 {
513 	struct rtattr **rta = arg;
514 	struct dn_dev *dn_db;
515 	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
516 	struct dn_ifaddr *ifa, **ifap;
517 
518 	if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL)
519 		return -EADDRNOTAVAIL;
520 
521 	for(ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next) {
522 		void *tmp = rta[IFA_LOCAL-1];
523 		if ((tmp && memcmp(RTA_DATA(tmp), &ifa->ifa_local, 2)) ||
524 				(rta[IFA_LABEL-1] && strcmp(RTA_DATA(rta[IFA_LABEL-1]), ifa->ifa_label)))
525 			continue;
526 
527 		dn_dev_del_ifa(dn_db, ifap, 1);
528 		return 0;
529 	}
530 
531 	return -EADDRNOTAVAIL;
532 }
533 
dn_dev_rtm_newaddr(struct sk_buff * skb,struct nlmsghdr * nlh,void * arg)534 static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
535 {
536 	struct rtattr **rta = arg;
537 	struct net_device *dev;
538 	struct dn_dev *dn_db;
539 	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
540 	struct dn_ifaddr *ifa;
541 
542 	if (rta[IFA_LOCAL-1] == NULL)
543 		return -EINVAL;
544 
545 	if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
546 		return -ENODEV;
547 
548 	if ((dn_db = dev->dn_ptr) == NULL) {
549 		int err;
550 		dn_db = dn_dev_create(dev, &err);
551 		if (!dn_db)
552 			return err;
553 	}
554 
555 	if ((ifa = dn_dev_alloc_ifa()) == NULL)
556 		return -ENOBUFS;
557 
558 	memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 2);
559 	ifa->ifa_flags = ifm->ifa_flags;
560 	ifa->ifa_scope = ifm->ifa_scope;
561 	ifa->ifa_dev = dn_db;
562 	if (rta[IFA_LABEL-1])
563 		memcpy(ifa->ifa_label, RTA_DATA(rta[IFA_LABEL-1]), IFNAMSIZ);
564 	else
565 		memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
566 
567 	return dn_dev_insert_ifa(dn_db, ifa);
568 }
569 
dn_dev_fill_ifaddr(struct sk_buff * skb,struct dn_ifaddr * ifa,u32 pid,u32 seq,int event)570 static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
571 				u32 pid, u32 seq, int event)
572 {
573 	struct ifaddrmsg *ifm;
574 	struct nlmsghdr *nlh;
575 	unsigned char *b = skb->tail;
576 
577 	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
578 	ifm = NLMSG_DATA(nlh);
579 
580 	ifm->ifa_family = AF_DECnet;
581 	ifm->ifa_prefixlen = 16;
582 	ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
583 	ifm->ifa_scope = ifa->ifa_scope;
584 	ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
585 	RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local);
586 	if (ifa->ifa_label[0])
587 		RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
588 	nlh->nlmsg_len = skb->tail - b;
589 	return skb->len;
590 
591 nlmsg_failure:
592 rtattr_failure:
593         skb_trim(skb, b - skb->data);
594         return -1;
595 }
596 
rtmsg_ifa(int event,struct dn_ifaddr * ifa)597 static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
598 {
599 	struct sk_buff *skb;
600 	int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
601 
602 	skb = alloc_skb(size, GFP_KERNEL);
603 	if (!skb) {
604 		netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, ENOBUFS);
605 		return;
606 	}
607 	if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
608 		kfree_skb(skb);
609 		netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, EINVAL);
610 		return;
611 	}
612 	NETLINK_CB(skb).dst_groups = RTMGRP_DECnet_IFADDR;
613 	netlink_broadcast(rtnl, skb, 0, RTMGRP_DECnet_IFADDR, GFP_KERNEL);
614 }
615 
dn_dev_dump_ifaddr(struct sk_buff * skb,struct netlink_callback * cb)616 static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
617 {
618 	int idx, dn_idx;
619 	int s_idx, s_dn_idx;
620 	struct net_device *dev;
621 	struct dn_dev *dn_db;
622 	struct dn_ifaddr *ifa;
623 
624 	s_idx = cb->args[0];
625 	s_dn_idx = dn_idx = cb->args[1];
626 	read_lock(&dev_base_lock);
627 	for(dev = dev_base, idx = 0; dev; dev = dev->next) {
628 		if ((dn_db = dev->dn_ptr) == NULL)
629 			continue;
630 		idx++;
631 		if (idx < s_idx)
632 			continue;
633 		if (idx > s_idx)
634 			s_dn_idx = 0;
635 		if ((dn_db = dev->dn_ptr) == NULL)
636 			continue;
637 
638 		for(ifa = dn_db->ifa_list, dn_idx = 0; ifa; ifa = ifa->ifa_next, dn_idx++) {
639 			if (dn_idx < s_dn_idx)
640 				continue;
641 
642 			if (dn_dev_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0)
643 				goto done;
644 		}
645 	}
646 done:
647 	read_unlock(&dev_base_lock);
648 	cb->args[0] = idx;
649 	cb->args[1] = dn_idx;
650 
651 	return skb->len;
652 }
653 
dn_send_endnode_hello(struct net_device * dev)654 static void dn_send_endnode_hello(struct net_device *dev)
655 {
656         struct endnode_hello_message *msg;
657         struct sk_buff *skb = NULL;
658         unsigned short int *pktlen;
659 	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
660 
661         if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
662 		return;
663 
664         skb->dev = dev;
665 
666         msg = (struct endnode_hello_message *)skb_put(skb,sizeof(*msg));
667 
668         msg->msgflg  = 0x0D;
669         memcpy(msg->tiver, dn_eco_version, 3);
670         memcpy(msg->id, decnet_ether_address, 6);
671         msg->iinfo   = DN_RT_INFO_ENDN;
672         msg->blksize = dn_htons(dn_db->parms.blksize);
673         msg->area    = 0x00;
674         memset(msg->seed, 0, 8);
675         memcpy(msg->neighbor, dn_hiord, ETH_ALEN);
676 
677 	if (dn_db->router) {
678 		struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
679 		dn_dn2eth(msg->neighbor, dn->addr);
680 	}
681 
682         msg->timer   = dn_htons((unsigned short)dn_db->parms.t3);
683         msg->mpd     = 0x00;
684         msg->datalen = 0x02;
685         memset(msg->data, 0xAA, 2);
686 
687         pktlen = (unsigned short *)skb_push(skb,2);
688         *pktlen = dn_htons(skb->len - 2);
689 
690 	skb->nh.raw = skb->data;
691 
692 	dn_rt_finish_output(skb, dn_rt_all_rt_mcast);
693 }
694 
695 
696 #ifdef CONFIG_DECNET_ROUTER
697 
698 #define DRDELAY (5 * HZ)
699 
dn_am_i_a_router(struct dn_neigh * dn,struct dn_dev * dn_db)700 static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db)
701 {
702 	/* First check time since device went up */
703 	if ((jiffies - dn_db->uptime) < DRDELAY)
704 		return 0;
705 
706 	/* If there is no router, then yes... */
707 	if (!dn_db->router)
708 		return 1;
709 
710 	/* otherwise only if we have a higher priority or.. */
711 	if (dn->priority < dn_db->parms.priority)
712 		return 1;
713 
714 	/* if we have equal priority and a higher node number */
715 	if (dn->priority != dn_db->parms.priority)
716 		return 0;
717 
718 	if (dn_ntohs(dn->addr) < dn_ntohs(decnet_address))
719 		return 1;
720 
721 	return 0;
722 }
723 
dn_send_router_hello(struct net_device * dev)724 static void dn_send_router_hello(struct net_device *dev)
725 {
726 	int n;
727 	struct dn_dev *dn_db = dev->dn_ptr;
728 	struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
729 	struct sk_buff *skb;
730 	size_t size;
731 	unsigned char *ptr;
732 	unsigned char *i1, *i2;
733 	unsigned short *pktlen;
734 
735 	if (dn_db->parms.blksize < (26 + 7))
736 		return;
737 
738 	n = dn_db->parms.blksize - 26;
739 	n /= 7;
740 
741 	if (n > 32)
742 		n = 32;
743 
744 	size = 2 + 26 + 7 * n;
745 
746 	if ((skb = dn_alloc_skb(NULL, size, GFP_ATOMIC)) == NULL)
747 		return;
748 
749 	skb->dev = dev;
750 	ptr = skb_put(skb, size);
751 
752 	*ptr++ = DN_RT_PKT_CNTL | DN_RT_PKT_ERTH;
753 	*ptr++ = 2; /* ECO */
754 	*ptr++ = 0;
755 	*ptr++ = 0;
756 	memcpy(ptr, decnet_ether_address, ETH_ALEN);
757 	ptr += ETH_ALEN;
758 	*ptr++ = dn_db->parms.forwarding == 1 ?
759 			DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
760 	*((unsigned short *)ptr) = dn_htons(dn_db->parms.blksize);
761 	ptr += 2;
762 	*ptr++ = dn_db->parms.priority; /* Priority */
763 	*ptr++ = 0; /* Area: Reserved */
764 	*((unsigned short *)ptr) = dn_htons((unsigned short)dn_db->parms.t3);
765 	ptr += 2;
766 	*ptr++ = 0; /* MPD: Reserved */
767 	i1 = ptr++;
768 	memset(ptr, 0, 7); /* Name: Reserved */
769 	ptr += 7;
770 	i2 = ptr++;
771 
772 	n = dn_neigh_elist(dev, ptr, n);
773 
774 	*i2 = 7 * n;
775 	*i1 = 8 + *i2;
776 
777 	skb_trim(skb, (27 + *i2));
778 
779 	pktlen = (unsigned short *)skb_push(skb, 2);
780 	*pktlen = dn_htons(skb->len - 2);
781 
782 	skb->nh.raw = skb->data;
783 
784 	if (dn_am_i_a_router(dn, dn_db)) {
785 		struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
786 		if (skb2) {
787 			dn_rt_finish_output(skb2, dn_rt_all_end_mcast);
788 		}
789 	}
790 
791 	dn_rt_finish_output(skb, dn_rt_all_rt_mcast);
792 }
793 
dn_send_brd_hello(struct net_device * dev)794 static void dn_send_brd_hello(struct net_device *dev)
795 {
796 	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
797 
798 	if (dn_db->parms.forwarding == 0)
799 		dn_send_endnode_hello(dev);
800 	else
801 		dn_send_router_hello(dev);
802 }
803 #else
dn_send_brd_hello(struct net_device * dev)804 static void dn_send_brd_hello(struct net_device *dev)
805 {
806 	dn_send_endnode_hello(dev);
807 }
808 #endif
809 
810 #if 0
811 static void dn_send_ptp_hello(struct net_device *dev)
812 {
813 	int tdlen = 16;
814 	int size = dev->hard_header_len + 2 + 4 + tdlen;
815 	struct sk_buff *skb = dn_alloc_skb(NULL, size, GFP_ATOMIC);
816 	struct dn_dev *dn_db = dev->dn_ptr;
817 	int i;
818 	unsigned char *ptr;
819 	struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
820 
821 	if (skb == NULL)
822 		return ;
823 
824 	skb->dev = dev;
825 	skb_push(skb, dev->hard_header_len);
826 	ptr = skb_put(skb, 2 + 4 + tdlen);
827 
828 	*ptr++ = DN_RT_PKT_HELO;
829 	*((dn_address *)ptr) = decnet_address;
830 	ptr += 2;
831 	*ptr++ = tdlen;
832 
833 	for(i = 0; i < tdlen; i++)
834 		*ptr++ = 0252;
835 
836 	if (dn_am_i_a_router(dn, dn_db)) {
837 		struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
838 		if (skb2) {
839 			dn_rt_finish_output(skb2, dn_rt_all_end_mcast);
840 		}
841 	}
842 
843 	dn_rt_finish_output(skb, dn_rt_all_rt_mcast);
844 }
845 #endif
846 
dn_eth_up(struct net_device * dev)847 static int dn_eth_up(struct net_device *dev)
848 {
849 	struct dn_dev *dn_db = dev->dn_ptr;
850 
851 	if (dn_db->parms.forwarding == 0)
852 		dev_mc_add(dev, dn_rt_all_end_mcast, ETH_ALEN, 0);
853 	else
854 		dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0);
855 
856 	dev_mc_upload(dev);
857 
858 	dn_db->use_long = 1;
859 
860 	return 0;
861 }
862 
863 static void dn_dev_set_timer(struct net_device *dev);
864 
dn_dev_timer_func(unsigned long arg)865 static void dn_dev_timer_func(unsigned long arg)
866 {
867 	struct net_device *dev = (struct net_device *)arg;
868 	struct dn_dev *dn_db = dev->dn_ptr;
869 
870 	if (dn_db->t3 <= dn_db->parms.t2) {
871 		if (dn_db->parms.timer3)
872 			dn_db->parms.timer3(dev);
873 		dn_db->t3 = dn_db->parms.t3;
874 	} else {
875 		dn_db->t3 -= dn_db->parms.t2;
876 	}
877 
878 	dn_dev_set_timer(dev);
879 }
880 
dn_dev_set_timer(struct net_device * dev)881 static void dn_dev_set_timer(struct net_device *dev)
882 {
883 	struct dn_dev *dn_db = dev->dn_ptr;
884 
885 	if (dn_db->parms.t2 > dn_db->parms.t3)
886 		dn_db->parms.t2 = dn_db->parms.t3;
887 
888 	dn_db->timer.data = (unsigned long)dev;
889 	dn_db->timer.function = dn_dev_timer_func;
890 	dn_db->timer.expires = jiffies + (dn_db->parms.t2 * HZ);
891 
892 	add_timer(&dn_db->timer);
893 }
894 
dn_dev_create(struct net_device * dev,int * err)895 struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
896 {
897 	int i;
898 	struct dn_dev_parms *p = dn_dev_list;
899 	struct dn_dev *dn_db;
900 
901 	for(i = 0; i < DN_DEV_LIST_SIZE; i++, p++) {
902 		if (p->type == dev->type)
903 			break;
904 	}
905 
906 	*err = -ENODEV;
907 	if (i == DN_DEV_LIST_SIZE)
908 		return NULL;
909 
910 	*err = -ENOBUFS;
911 	if ((dn_db = kmalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)
912 		return NULL;
913 
914 	memset(dn_db, 0, sizeof(struct dn_dev));
915 	memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
916 	dev->dn_ptr = dn_db;
917 	dn_db->dev = dev;
918 	init_timer(&dn_db->timer);
919 
920 	memcpy(dn_db->addr, decnet_ether_address, ETH_ALEN); /* To go... */
921 
922 	dn_db->uptime = jiffies;
923 	if (dn_db->parms.up) {
924 		if (dn_db->parms.up(dev) < 0) {
925 			dev->dn_ptr = NULL;
926 			kfree(dn_db);
927 			return NULL;
928 		}
929 	}
930 
931 	dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
932 	/* dn_db->neigh_parms->neigh_setup = dn_db->parms.neigh_setup; */
933 
934 	dn_dev_sysctl_register(dev, &dn_db->parms);
935 
936 	dn_dev_set_timer(dev);
937 
938 	*err = 0;
939 	return dn_db;
940 }
941 
942 
943 /*
944  * This processes a device up event. We only start up
945  * the loopback device & ethernet devices with correct
946  * MAC addreses automatically. Others must be started
947  * specifically.
948  */
dn_dev_up(struct net_device * dev)949 void dn_dev_up(struct net_device *dev)
950 {
951 	struct dn_ifaddr *ifa;
952 
953 	if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
954 		return;
955 
956 	if (dev->type == ARPHRD_ETHER)
957 		if (memcmp(dev->dev_addr, decnet_ether_address, ETH_ALEN) != 0)
958 			return;
959 
960 	if ((ifa = dn_dev_alloc_ifa()) == NULL)
961 		return;
962 
963 	ifa->ifa_local = decnet_address;
964 	ifa->ifa_flags = 0;
965 	ifa->ifa_scope = RT_SCOPE_UNIVERSE;
966 	strcpy(ifa->ifa_label, dev->name);
967 
968 	dn_dev_set_ifa(dev, ifa);
969 }
970 
dn_dev_delete(struct net_device * dev)971 static void dn_dev_delete(struct net_device *dev)
972 {
973 	struct dn_dev *dn_db = dev->dn_ptr;
974 
975 	if (dn_db == NULL)
976 		return;
977 
978 	del_timer_sync(&dn_db->timer);
979 
980 	dn_dev_sysctl_unregister(&dn_db->parms);
981 
982 	neigh_ifdown(&dn_neigh_table, dev);
983 
984 	if (dev == decnet_default_device)
985 		decnet_default_device = NULL;
986 
987 	if (dn_db->parms.down)
988 		dn_db->parms.down(dev);
989 
990 	dev->dn_ptr = NULL;
991 
992 	neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
993 
994 	if (dn_db->router)
995 		neigh_release(dn_db->router);
996 	if (dn_db->peer)
997 		neigh_release(dn_db->peer);
998 
999 	kfree(dn_db);
1000 }
1001 
dn_dev_down(struct net_device * dev)1002 void dn_dev_down(struct net_device *dev)
1003 {
1004 	struct dn_dev *dn_db = dev->dn_ptr;
1005 	struct dn_ifaddr *ifa;
1006 
1007 	if (dn_db == NULL)
1008 		return;
1009 
1010 	while((ifa = dn_db->ifa_list) != NULL) {
1011 		dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0);
1012 		dn_dev_free_ifa(ifa);
1013 	}
1014 
1015 	dn_dev_delete(dev);
1016 }
1017 
dn_dev_init_pkt(struct sk_buff * skb)1018 void dn_dev_init_pkt(struct sk_buff *skb)
1019 {
1020 	return;
1021 }
1022 
dn_dev_veri_pkt(struct sk_buff * skb)1023 void dn_dev_veri_pkt(struct sk_buff *skb)
1024 {
1025 	return;
1026 }
1027 
dn_dev_hello(struct sk_buff * skb)1028 void dn_dev_hello(struct sk_buff *skb)
1029 {
1030 	return;
1031 }
1032 
dn_dev_devices_off(void)1033 void dn_dev_devices_off(void)
1034 {
1035 	struct net_device *dev;
1036 
1037 	for(dev = dev_base; dev; dev = dev->next)
1038 		dn_dev_down(dev);
1039 
1040 }
1041 
dn_dev_devices_on(void)1042 void dn_dev_devices_on(void)
1043 {
1044 	struct net_device *dev;
1045 
1046 	for(dev = dev_base; dev; dev = dev->next) {
1047 		if (dev->flags & IFF_UP)
1048 			dn_dev_up(dev);
1049 	}
1050 }
1051 
1052 
1053 #ifdef CONFIG_DECNET_SIOCGIFCONF
1054 /*
1055  * Now we support multiple addresses per interface.
1056  * Since we don't want to break existing code, you have to enable
1057  * it as a compile time option. Probably you should use the
1058  * rtnetlink interface instead.
1059  */
dnet_gifconf(struct net_device * dev,char * buf,int len)1060 int dnet_gifconf(struct net_device *dev, char *buf, int len)
1061 {
1062 	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
1063 	struct dn_ifaddr *ifa;
1064 	char buffer[DN_IFREQ_SIZE];
1065 	struct ifreq *ifr = (struct ifreq *)buffer;
1066 	struct sockaddr_dn *addr = (struct sockaddr_dn *)&ifr->ifr_addr;
1067 	int done = 0;
1068 
1069 	if ((dn_db == NULL) || ((ifa = dn_db->ifa_list) == NULL))
1070 		return 0;
1071 
1072 	for(; ifa; ifa = ifa->ifa_next) {
1073 		if (!buf) {
1074 			done += sizeof(DN_IFREQ_SIZE);
1075 			continue;
1076 		}
1077 		if (len < DN_IFREQ_SIZE)
1078 			return done;
1079 		memset(buffer, 0, DN_IFREQ_SIZE);
1080 
1081 		if (ifa->ifa_label)
1082 			strcpy(ifr->ifr_name, ifa->ifa_label);
1083 		else
1084 			strcpy(ifr->ifr_name, dev->name);
1085 
1086 		addr->sdn_family = AF_DECnet;
1087 		addr->sdn_add.a_len = 2;
1088 		memcpy(addr->sdn_add.a_addr, &ifa->ifa_local,
1089 			sizeof(dn_address));
1090 
1091 		if (copy_to_user(buf, buffer, DN_IFREQ_SIZE)) {
1092 			done = -EFAULT;
1093 			break;
1094 		}
1095 
1096 		buf  += DN_IFREQ_SIZE;
1097 		len  -= DN_IFREQ_SIZE;
1098 		done += DN_IFREQ_SIZE;
1099 	}
1100 
1101 	return done;
1102 }
1103 #endif /* CONFIG_DECNET_SIOCGIFCONF */
1104 
1105 
1106 #ifdef CONFIG_PROC_FS
1107 
dn_type2asc(char type)1108 static char *dn_type2asc(char type)
1109 {
1110 	switch(type) {
1111 		case DN_DEV_BCAST:
1112 			return "B";
1113 		case DN_DEV_UCAST:
1114 			return "U";
1115 		case DN_DEV_MPOINT:
1116 			return "M";
1117 	}
1118 
1119 	return "?";
1120 }
1121 
decnet_dev_get_info(char * buffer,char ** start,off_t offset,int length)1122 static int decnet_dev_get_info(char *buffer, char **start, off_t offset, int length)
1123 {
1124         struct dn_dev *dn_db;
1125 	struct net_device *dev;
1126         int len = 0;
1127         off_t pos = 0;
1128         off_t begin = 0;
1129 	char peer_buf[DN_ASCBUF_LEN];
1130 	char router_buf[DN_ASCBUF_LEN];
1131 
1132 
1133         len += sprintf(buffer, "Name     Flags T1   Timer1 T3   Timer3 BlkSize Pri State DevType    Router Peer\n");
1134 
1135 	read_lock(&dev_base_lock);
1136         for (dev = dev_base; dev; dev = dev->next) {
1137 		if ((dn_db = (struct dn_dev *)dev->dn_ptr) == NULL)
1138 			continue;
1139 
1140                 len += sprintf(buffer + len, "%-8s %1s     %04u %04u   %04lu %04lu   %04hu    %03d %02x    %-10s %-7s %-7s\n",
1141                              	dev->name ? dev->name : "???",
1142                              	dn_type2asc(dn_db->parms.mode),
1143                              	0, 0,
1144 				dn_db->t3, dn_db->parms.t3,
1145 				dn_db->parms.blksize,
1146 				dn_db->parms.priority,
1147 				dn_db->parms.state, dn_db->parms.name,
1148 				dn_db->router ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->router->primary_key), router_buf) : "",
1149 				dn_db->peer ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->peer->primary_key), peer_buf) : "");
1150 
1151 
1152                 pos = begin + len;
1153 
1154                 if (pos < offset) {
1155                         len   = 0;
1156                         begin = pos;
1157                 }
1158                 if (pos > offset + length)
1159                         break;
1160         }
1161 
1162 	read_unlock(&dev_base_lock);
1163 
1164         *start = buffer + (offset - begin);
1165         len   -= (offset - begin);
1166 
1167         if (len > length) len = length;
1168 
1169         return(len);
1170 }
1171 
1172 #endif /* CONFIG_PROC_FS */
1173 
1174 static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
1175 {
1176 	{ NULL,			NULL,			},
1177 	{ NULL,			NULL,			},
1178 	{ NULL,			NULL,			},
1179 	{ NULL,			NULL,			},
1180 
1181 	{ dn_dev_rtm_newaddr,	NULL,			},
1182 	{ dn_dev_rtm_deladdr,	NULL,			},
1183 	{ NULL,			dn_dev_dump_ifaddr,	},
1184 	{ NULL,			NULL,			},
1185 
1186 #ifdef CONFIG_DECNET_ROUTER
1187 	{ dn_fib_rtm_newroute,	NULL,			},
1188 	{ dn_fib_rtm_delroute,	NULL,			},
1189 	{ dn_cache_getroute,	dn_fib_dump,		},
1190 	{ NULL,			NULL,			},
1191 #else
1192 	{ NULL,			NULL,			},
1193 	{ NULL,			NULL,			},
1194 	{ dn_cache_getroute,	dn_cache_dump,		},
1195 	{ NULL,			NULL,			},
1196 #endif
1197 	{ NULL,			NULL,			},
1198 	{ NULL,			NULL,			},
1199 	{ NULL,			NULL,			},
1200 	{ NULL,			NULL,			},
1201 
1202 #ifdef CONFIG_DECNET_ROUTER
1203 	{ dn_fib_rtm_newrule,	NULL,			},
1204 	{ dn_fib_rtm_delrule,	NULL,			},
1205 	{ NULL,			dn_fib_dump_rules,	},
1206 	{ NULL,			NULL,			}
1207 #else
1208 	{ NULL,			NULL,			},
1209 	{ NULL,			NULL,			},
1210 	{ NULL,			NULL,			},
1211 	{ NULL,			NULL,			}
1212 #endif
1213 };
1214 
dn_dev_init(void)1215 void __init dn_dev_init(void)
1216 {
1217 
1218 	dn_dev_devices_on();
1219 #ifdef CONFIG_DECNET_SIOCGIFCONF
1220 	register_gifconf(PF_DECnet, dnet_gifconf);
1221 #endif /* CONFIG_DECNET_SIOCGIFCONF */
1222 
1223 	rtnetlink_links[PF_DECnet] = dnet_rtnetlink_table;
1224 
1225 #ifdef CONFIG_PROC_FS
1226 	proc_net_create("decnet_dev", 0, decnet_dev_get_info);
1227 #endif /* CONFIG_PROC_FS */
1228 
1229 #ifdef CONFIG_SYSCTL
1230 	{
1231 		int i;
1232 		for(i = 0; i < DN_DEV_LIST_SIZE; i++)
1233 			dn_dev_sysctl_register(NULL, &dn_dev_list[i]);
1234 	}
1235 #endif /* CONFIG_SYSCTL */
1236 }
1237 
dn_dev_cleanup(void)1238 void __exit dn_dev_cleanup(void)
1239 {
1240 	rtnetlink_links[PF_DECnet] = NULL;
1241 
1242 #ifdef CONFIG_DECNET_SIOCGIFCONF
1243 	unregister_gifconf(PF_DECnet);
1244 #endif /* CONFIG_DECNET_SIOCGIFCONF */
1245 
1246 #ifdef CONFIG_SYSCTL
1247 	{
1248 		int i;
1249 		for(i = 0; i < DN_DEV_LIST_SIZE; i++)
1250 			dn_dev_sysctl_unregister(&dn_dev_list[i]);
1251 	}
1252 #endif /* CONFIG_SYSCTL */
1253 
1254 	proc_net_remove("decnet_dev");
1255 
1256 	dn_dev_devices_off();
1257 }
1258