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