xref: /linux/net/ax25/ax25_route.c (revision 9ce7677cfd7cd871adb457c80bea3b581b839641)
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
8  * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9  * Copyright (C) Steven Whitehouse GW7RRM (stevew@acm.org)
10  * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
11  * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
12  * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
13  */
14 #include <linux/errno.h>
15 #include <linux/types.h>
16 #include <linux/socket.h>
17 #include <linux/timer.h>
18 #include <linux/in.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/string.h>
22 #include <linux/sockios.h>
23 #include <linux/net.h>
24 #include <net/ax25.h>
25 #include <linux/inet.h>
26 #include <linux/netdevice.h>
27 #include <linux/if_arp.h>
28 #include <linux/skbuff.h>
29 #include <linux/spinlock.h>
30 #include <net/sock.h>
31 #include <asm/uaccess.h>
32 #include <asm/system.h>
33 #include <linux/fcntl.h>
34 #include <linux/mm.h>
35 #include <linux/interrupt.h>
36 #include <linux/init.h>
37 #include <linux/seq_file.h>
38 
39 static ax25_route *ax25_route_list;
40 static DEFINE_RWLOCK(ax25_route_lock);
41 
42 static ax25_route *ax25_get_route(ax25_address *, struct net_device *);
43 
44 void ax25_rt_device_down(struct net_device *dev)
45 {
46 	ax25_route *s, *t, *ax25_rt;
47 
48 	write_lock(&ax25_route_lock);
49 	ax25_rt = ax25_route_list;
50 	while (ax25_rt != NULL) {
51 		s       = ax25_rt;
52 		ax25_rt = ax25_rt->next;
53 
54 		if (s->dev == dev) {
55 			if (ax25_route_list == s) {
56 				ax25_route_list = s->next;
57 				kfree(s->digipeat);
58 				kfree(s);
59 			} else {
60 				for (t = ax25_route_list; t != NULL; t = t->next) {
61 					if (t->next == s) {
62 						t->next = s->next;
63 						kfree(s->digipeat);
64 						kfree(s);
65 						break;
66 					}
67 				}
68 			}
69 		}
70 	}
71 	write_unlock(&ax25_route_lock);
72 }
73 
74 static int ax25_rt_add(struct ax25_routes_struct *route)
75 {
76 	ax25_route *ax25_rt;
77 	ax25_dev *ax25_dev;
78 	int i;
79 
80 	if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
81 		return -EINVAL;
82 	if (route->digi_count > AX25_MAX_DIGIS)
83 		return -EINVAL;
84 
85 	write_lock(&ax25_route_lock);
86 
87 	ax25_rt = ax25_route_list;
88 	while (ax25_rt != NULL) {
89 		if (ax25cmp(&ax25_rt->callsign, &route->dest_addr) == 0 &&
90 		            ax25_rt->dev == ax25_dev->dev) {
91 			kfree(ax25_rt->digipeat);
92 			ax25_rt->digipeat = NULL;
93 			if (route->digi_count != 0) {
94 				if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
95 					write_unlock(&ax25_route_lock);
96 					return -ENOMEM;
97 				}
98 				ax25_rt->digipeat->lastrepeat = -1;
99 				ax25_rt->digipeat->ndigi      = route->digi_count;
100 				for (i = 0; i < route->digi_count; i++) {
101 					ax25_rt->digipeat->repeated[i] = 0;
102 					ax25_rt->digipeat->calls[i]    = route->digi_addr[i];
103 				}
104 			}
105 			write_unlock(&ax25_route_lock);
106 			return 0;
107 		}
108 		ax25_rt = ax25_rt->next;
109 	}
110 
111 	if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
112 		write_unlock(&ax25_route_lock);
113 		return -ENOMEM;
114 	}
115 
116 	atomic_set(&ax25_rt->ref, 0);
117 	ax25_rt->callsign     = route->dest_addr;
118 	ax25_rt->dev          = ax25_dev->dev;
119 	ax25_rt->digipeat     = NULL;
120 	ax25_rt->ip_mode      = ' ';
121 	if (route->digi_count != 0) {
122 		if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
123 			write_unlock(&ax25_route_lock);
124 			kfree(ax25_rt);
125 			return -ENOMEM;
126 		}
127 		ax25_rt->digipeat->lastrepeat = -1;
128 		ax25_rt->digipeat->ndigi      = route->digi_count;
129 		for (i = 0; i < route->digi_count; i++) {
130 			ax25_rt->digipeat->repeated[i] = 0;
131 			ax25_rt->digipeat->calls[i]    = route->digi_addr[i];
132 		}
133 	}
134 	ax25_rt->next   = ax25_route_list;
135 	ax25_route_list = ax25_rt;
136 	write_unlock(&ax25_route_lock);
137 
138 	return 0;
139 }
140 
141 static void ax25_rt_destroy(ax25_route *ax25_rt)
142 {
143 	if (atomic_read(&ax25_rt->ref) == 0) {
144 		kfree(ax25_rt->digipeat);
145 		kfree(ax25_rt);
146 		return;
147 	}
148 
149 	/*
150 	 * Uh...  Route is still in use; we can't yet destroy it.  Retry later.
151 	 */
152 	init_timer(&ax25_rt->timer);
153 	ax25_rt->timer.data	= (unsigned long) ax25_rt;
154 	ax25_rt->timer.function	= (void *) ax25_rt_destroy;
155 	ax25_rt->timer.expires	= jiffies + 5 * HZ;
156 
157 	add_timer(&ax25_rt->timer);
158 }
159 
160 static int ax25_rt_del(struct ax25_routes_struct *route)
161 {
162 	ax25_route *s, *t, *ax25_rt;
163 	ax25_dev *ax25_dev;
164 
165 	if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
166 		return -EINVAL;
167 
168 	write_lock(&ax25_route_lock);
169 
170 	ax25_rt = ax25_route_list;
171 	while (ax25_rt != NULL) {
172 		s       = ax25_rt;
173 		ax25_rt = ax25_rt->next;
174 		if (s->dev == ax25_dev->dev &&
175 		    ax25cmp(&route->dest_addr, &s->callsign) == 0) {
176 			if (ax25_route_list == s) {
177 				ax25_route_list = s->next;
178 				ax25_rt_destroy(s);
179 			} else {
180 				for (t = ax25_route_list; t != NULL; t = t->next) {
181 					if (t->next == s) {
182 						t->next = s->next;
183 						ax25_rt_destroy(s);
184 						break;
185 					}
186 				}
187 			}
188 		}
189 	}
190 	write_unlock(&ax25_route_lock);
191 
192 	return 0;
193 }
194 
195 static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)
196 {
197 	ax25_route *ax25_rt;
198 	ax25_dev *ax25_dev;
199 	int err = 0;
200 
201 	if ((ax25_dev = ax25_addr_ax25dev(&rt_option->port_addr)) == NULL)
202 		return -EINVAL;
203 
204 	write_lock(&ax25_route_lock);
205 
206 	ax25_rt = ax25_route_list;
207 	while (ax25_rt != NULL) {
208 		if (ax25_rt->dev == ax25_dev->dev &&
209 		    ax25cmp(&rt_option->dest_addr, &ax25_rt->callsign) == 0) {
210 			switch (rt_option->cmd) {
211 			case AX25_SET_RT_IPMODE:
212 				switch (rt_option->arg) {
213 				case ' ':
214 				case 'D':
215 				case 'V':
216 					ax25_rt->ip_mode = rt_option->arg;
217 					break;
218 				default:
219 					err = -EINVAL;
220 					goto out;
221 				}
222 				break;
223 			default:
224 				err = -EINVAL;
225 				goto out;
226 			}
227 		}
228 		ax25_rt = ax25_rt->next;
229 	}
230 
231 out:
232 	write_unlock(&ax25_route_lock);
233 	return err;
234 }
235 
236 int ax25_rt_ioctl(unsigned int cmd, void __user *arg)
237 {
238 	struct ax25_route_opt_struct rt_option;
239 	struct ax25_routes_struct route;
240 
241 	switch (cmd) {
242 	case SIOCADDRT:
243 		if (copy_from_user(&route, arg, sizeof(route)))
244 			return -EFAULT;
245 		return ax25_rt_add(&route);
246 
247 	case SIOCDELRT:
248 		if (copy_from_user(&route, arg, sizeof(route)))
249 			return -EFAULT;
250 		return ax25_rt_del(&route);
251 
252 	case SIOCAX25OPTRT:
253 		if (copy_from_user(&rt_option, arg, sizeof(rt_option)))
254 			return -EFAULT;
255 		return ax25_rt_opt(&rt_option);
256 
257 	default:
258 		return -EINVAL;
259 	}
260 }
261 
262 #ifdef CONFIG_PROC_FS
263 
264 static void *ax25_rt_seq_start(struct seq_file *seq, loff_t *pos)
265 {
266 	struct ax25_route *ax25_rt;
267 	int i = 1;
268 
269  	read_lock(&ax25_route_lock);
270 	if (*pos == 0)
271 		return SEQ_START_TOKEN;
272 
273 	for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
274 		if (i == *pos)
275 			return ax25_rt;
276 		++i;
277 	}
278 
279 	return NULL;
280 }
281 
282 static void *ax25_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
283 {
284 	++*pos;
285 	return (v == SEQ_START_TOKEN) ? ax25_route_list :
286 		((struct ax25_route *) v)->next;
287 }
288 
289 static void ax25_rt_seq_stop(struct seq_file *seq, void *v)
290 {
291 	read_unlock(&ax25_route_lock);
292 }
293 
294 static int ax25_rt_seq_show(struct seq_file *seq, void *v)
295 {
296 	char buf[11];
297 
298 	if (v == SEQ_START_TOKEN)
299 		seq_puts(seq, "callsign  dev  mode digipeaters\n");
300 	else {
301 		struct ax25_route *ax25_rt = v;
302 		const char *callsign;
303 		int i;
304 
305 		if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
306 			callsign = "default";
307 		else
308 			callsign = ax2asc(buf, &ax25_rt->callsign);
309 
310 		seq_printf(seq, "%-9s %-4s",
311 			callsign,
312 			ax25_rt->dev ? ax25_rt->dev->name : "???");
313 
314 		switch (ax25_rt->ip_mode) {
315 		case 'V':
316 			seq_puts(seq, "   vc");
317 			break;
318 		case 'D':
319 			seq_puts(seq, "   dg");
320 			break;
321 		default:
322 			seq_puts(seq, "    *");
323 			break;
324 		}
325 
326 		if (ax25_rt->digipeat != NULL)
327 			for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
328 				seq_printf(seq, " %s",
329 				     ax2asc(buf, &ax25_rt->digipeat->calls[i]));
330 
331 		seq_puts(seq, "\n");
332 	}
333 	return 0;
334 }
335 
336 static struct seq_operations ax25_rt_seqops = {
337 	.start = ax25_rt_seq_start,
338 	.next = ax25_rt_seq_next,
339 	.stop = ax25_rt_seq_stop,
340 	.show = ax25_rt_seq_show,
341 };
342 
343 static int ax25_rt_info_open(struct inode *inode, struct file *file)
344 {
345 	return seq_open(file, &ax25_rt_seqops);
346 }
347 
348 struct file_operations ax25_route_fops = {
349 	.owner = THIS_MODULE,
350 	.open = ax25_rt_info_open,
351 	.read = seq_read,
352 	.llseek = seq_lseek,
353 	.release = seq_release,
354 };
355 
356 #endif
357 
358 /*
359  *	Find AX.25 route
360  *
361  *	Only routes with a refernce rout of zero can be destroyed.
362  */
363 static ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
364 {
365 	ax25_route *ax25_spe_rt = NULL;
366 	ax25_route *ax25_def_rt = NULL;
367 	ax25_route *ax25_rt;
368 
369 	read_lock(&ax25_route_lock);
370 	/*
371 	 *	Bind to the physical interface we heard them on, or the default
372 	 *	route if none is found;
373 	 */
374 	for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
375 		if (dev == NULL) {
376 			if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
377 				ax25_spe_rt = ax25_rt;
378 			if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
379 				ax25_def_rt = ax25_rt;
380 		} else {
381 			if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev == dev)
382 				ax25_spe_rt = ax25_rt;
383 			if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev == dev)
384 				ax25_def_rt = ax25_rt;
385 		}
386 	}
387 
388 	ax25_rt = ax25_def_rt;
389 	if (ax25_spe_rt != NULL)
390 		ax25_rt = ax25_spe_rt;
391 
392 	if (ax25_rt != NULL)
393 		atomic_inc(&ax25_rt->ref);
394 
395 	read_unlock(&ax25_route_lock);
396 
397 	return ax25_rt;
398 }
399 
400 /*
401  *	Adjust path: If you specify a default route and want to connect
402  *      a target on the digipeater path but w/o having a special route
403  *	set before, the path has to be truncated from your target on.
404  */
405 static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat)
406 {
407 	int k;
408 
409 	for (k = 0; k < digipeat->ndigi; k++) {
410 		if (ax25cmp(addr, &digipeat->calls[k]) == 0)
411 			break;
412 	}
413 
414 	digipeat->ndigi = k;
415 }
416 
417 
418 /*
419  *	Find which interface to use.
420  */
421 int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
422 {
423 	ax25_uid_assoc *user;
424 	ax25_route *ax25_rt;
425 	int err;
426 
427 	if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL)
428 		return -EHOSTUNREACH;
429 
430 	if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) {
431 		err = -EHOSTUNREACH;
432 		goto put;
433 	}
434 
435 	user = ax25_findbyuid(current->euid);
436 	if (user) {
437 		ax25->source_addr = user->call;
438 		ax25_uid_put(user);
439 	} else {
440 		if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) {
441 			err = -EPERM;
442 			goto put;
443 		}
444 		ax25->source_addr = *(ax25_address *)ax25->ax25_dev->dev->dev_addr;
445 	}
446 
447 	if (ax25_rt->digipeat != NULL) {
448 		if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
449 			err = -ENOMEM;
450 			goto put;
451 		}
452 		memcpy(ax25->digipeat, ax25_rt->digipeat, sizeof(ax25_digi));
453 		ax25_adjust_path(addr, ax25->digipeat);
454 	}
455 
456 	if (ax25->sk != NULL) {
457 		bh_lock_sock(ax25->sk);
458 		sock_reset_flag(ax25->sk, SOCK_ZAPPED);
459 		bh_unlock_sock(ax25->sk);
460 	}
461 
462 put:
463 	ax25_put_route(ax25_rt);
464 
465 	return 0;
466 }
467 
468 ax25_route *ax25_rt_find_route(ax25_route * route, ax25_address *addr,
469 	struct net_device *dev)
470 {
471 	ax25_route *ax25_rt;
472 
473 	if ((ax25_rt = ax25_get_route(addr, dev)))
474 		return ax25_rt;
475 
476 	route->next     = NULL;
477 	atomic_set(&route->ref, 1);
478 	route->callsign = *addr;
479 	route->dev      = dev;
480 	route->digipeat = NULL;
481 	route->ip_mode  = ' ';
482 
483 	return route;
484 }
485 
486 struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src,
487 	ax25_address *dest, ax25_digi *digi)
488 {
489 	struct sk_buff *skbn;
490 	unsigned char *bp;
491 	int len;
492 
493 	len = digi->ndigi * AX25_ADDR_LEN;
494 
495 	if (skb_headroom(skb) < len) {
496 		if ((skbn = skb_realloc_headroom(skb, len)) == NULL) {
497 			printk(KERN_CRIT "AX.25: ax25_dg_build_path - out of memory\n");
498 			return NULL;
499 		}
500 
501 		if (skb->sk != NULL)
502 			skb_set_owner_w(skbn, skb->sk);
503 
504 		kfree_skb(skb);
505 
506 		skb = skbn;
507 	}
508 
509 	bp = skb_push(skb, len);
510 
511 	ax25_addr_build(bp, src, dest, digi, AX25_COMMAND, AX25_MODULUS);
512 
513 	return skb;
514 }
515 
516 /*
517  *	Free all memory associated with routing structures.
518  */
519 void __exit ax25_rt_free(void)
520 {
521 	ax25_route *s, *ax25_rt = ax25_route_list;
522 
523 	write_lock(&ax25_route_lock);
524 	while (ax25_rt != NULL) {
525 		s       = ax25_rt;
526 		ax25_rt = ax25_rt->next;
527 
528 		kfree(s->digipeat);
529 		kfree(s);
530 	}
531 	write_unlock(&ax25_route_lock);
532 }
533