This source file includes following definitions.
- ax25_route_invert
- ax25_rt_rx_frame
- ax25_rt_device_down
- ax25_rt_ioctl
- ax25_rt_get_info
- ax25_cs_get_info
- ax25_find_route
- ax25_adjust_path
- ax25_rt_autobind
- ax25_rt_build_path
- ax25_dg_build_path
- ax25_ip_mode_set
- ax25_ip_mode_get
- ax25_dev_get_dev
- ax25_dev_get_value
- ax25_dev_device_up
- ax25_dev_device_down
- ax25_dev_ioctl
- ax25_bpq_get_info
- ax25_bpq_get_addr
- ax25_bpq_ioctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 #include <linux/config.h>
43 #ifdef CONFIG_AX25
44 #include <linux/errno.h>
45 #include <linux/types.h>
46 #include <linux/socket.h>
47 #include <linux/in.h>
48 #include <linux/kernel.h>
49 #include <linux/sched.h>
50 #include <linux/timer.h>
51 #include <linux/string.h>
52 #include <linux/sockios.h>
53 #include <linux/net.h>
54 #include <net/ax25.h>
55 #include <linux/inet.h>
56 #include <linux/netdevice.h>
57 #include <linux/if_arp.h>
58 #include <linux/skbuff.h>
59 #include <net/sock.h>
60 #include <asm/segment.h>
61 #include <asm/system.h>
62 #include <linux/fcntl.h>
63 #include <linux/mm.h>
64 #include <linux/interrupt.h>
65
66 #define AX25_ROUTE_MAX 128
67
68 static struct ax25_route {
69 struct ax25_route *next;
70 ax25_address callsign;
71 struct device *dev;
72 ax25_digi *digipeat;
73 struct timeval stamp;
74 int n;
75 char ip_mode;
76 char perm;
77 } *ax25_route = NULL;
78
79 static struct ax25_dev {
80 struct ax25_dev *next;
81 struct device *dev;
82 unsigned short values[AX25_MAX_VALUES];
83 } *ax25_device = NULL;
84
85 static struct ax25_route * ax25_find_route(ax25_address *addr);
86
87
88
89
90
91 static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out)
92 {
93 int k;
94 for (k = 0; k < in->ndigi; k++)
95 if (!in->repeated[k])
96 break;
97 in->ndigi = k;
98 ax25_digi_invert(in, out);
99
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 void ax25_rt_rx_frame(ax25_address *src, struct device *dev, ax25_digi *digi)
118 {
119 unsigned long flags;
120 extern struct timeval xtime;
121 struct ax25_route *ax25_rt;
122 struct ax25_route *oldest;
123 int count;
124
125 count = 0;
126 oldest = NULL;
127
128 for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
129 if (count == 0 || oldest->stamp.tv_sec == 0 || (ax25_rt->stamp.tv_sec != 0 && ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec))
130 oldest = ax25_rt;
131
132 if (ax25cmp(&ax25_rt->callsign, src) == 0) {
133 if (ax25_rt->stamp.tv_sec != 0)
134 ax25_rt->stamp = xtime;
135
136 if (ax25_rt->perm == AX25_RT_PERMANENT) {
137 ax25_rt->n++;
138 return;
139 }
140
141 ax25_rt->dev = dev;
142 if (digi == NULL) {
143
144 if (ax25_rt->digipeat != NULL) {
145 kfree_s(ax25_rt->digipeat, sizeof(ax25_digi));
146 ax25_rt->digipeat = NULL;
147 }
148 return;
149 }
150
151 if (ax25_rt->digipeat == NULL && (ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
152 return;
153
154 ax25_route_invert(digi, ax25_rt->digipeat);
155 return;
156 }
157
158 count++;
159 }
160
161 if (count > AX25_ROUTE_MAX) {
162 if (oldest->stamp.tv_sec == 0)
163 return;
164 if (oldest->digipeat != NULL)
165 kfree_s(oldest->digipeat, sizeof(ax25_digi));
166 ax25_rt = oldest;
167 } else {
168 if ((ax25_rt = (struct ax25_route *)kmalloc(sizeof(struct ax25_route), GFP_ATOMIC)) == NULL)
169 return;
170 }
171
172 ax25_rt->callsign = *src;
173 ax25_rt->dev = dev;
174 ax25_rt->digipeat = NULL;
175 ax25_rt->stamp = xtime;
176 ax25_rt->n = 1;
177 ax25_rt->ip_mode = ' ';
178 ax25_rt->perm = AX25_RT_DYNAMIC;
179
180 if (digi != NULL) {
181 if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
182 kfree_s(ax25_rt, sizeof(struct ax25_route));
183 return;
184 }
185
186 ax25_route_invert(digi, ax25_rt->digipeat);
187
188 }
189
190 if (ax25_rt != oldest) {
191 save_flags(flags);
192 cli();
193
194 ax25_rt->next = ax25_route;
195 ax25_route = ax25_rt;
196
197 restore_flags(flags);
198 }
199 }
200
201 void ax25_rt_device_down(struct device *dev)
202 {
203 struct ax25_route *s, *t, *ax25_rt = ax25_route;
204
205 while (ax25_rt != NULL) {
206 s = ax25_rt;
207 ax25_rt = ax25_rt->next;
208
209 if (s->dev == dev) {
210 if (ax25_route == s) {
211 ax25_route = s->next;
212 if (s->digipeat != NULL)
213 kfree_s((void *)s->digipeat, sizeof(ax25_digi));
214 kfree_s((void *)s, (sizeof *s));
215 } else {
216 for (t = ax25_route; t != NULL; t = t->next) {
217 if (t->next == s) {
218 t->next = s->next;
219 if (s->digipeat != NULL)
220 kfree_s((void *)s->digipeat, sizeof(ax25_digi));
221 kfree_s((void *)s, sizeof(*s));
222 break;
223 }
224 }
225 }
226 }
227 }
228 }
229
230 int ax25_rt_ioctl(unsigned int cmd, void *arg)
231 {
232 unsigned long flags;
233 struct ax25_route *s, *t, *ax25_rt;
234 struct ax25_routes_struct route;
235 struct ax25_route_opt_struct rt_option;
236 struct device *dev;
237 int i, err;
238
239 switch (cmd) {
240 case SIOCADDRT:
241 if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
242 return err;
243 memcpy_fromfs(&route, arg, sizeof(route));
244 if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL)
245 return -EINVAL;
246 if (route.digi_count > AX25_MAX_DIGIS)
247 return -EINVAL;
248 for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
249 if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == dev) {
250 if (ax25_rt->digipeat != NULL) {
251 kfree_s(ax25_rt->digipeat, sizeof(ax25_digi));
252 ax25_rt->digipeat = NULL;
253 }
254 if (route.digi_count != 0) {
255 if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
256 return -ENOMEM;
257 ax25_rt->digipeat->lastrepeat = 0;
258 ax25_rt->digipeat->ndigi = route.digi_count;
259 for (i = 0; i < route.digi_count; i++) {
260 ax25_rt->digipeat->repeated[i] = 0;
261 ax25_rt->digipeat->calls[i] = route.digi_addr[i];
262 }
263 }
264 ax25_rt->stamp.tv_sec = 0;
265 return 0;
266 }
267 }
268 if ((ax25_rt = (struct ax25_route *)kmalloc(sizeof(struct ax25_route), GFP_ATOMIC)) == NULL)
269 return -ENOMEM;
270 ax25_rt->callsign = route.dest_addr;
271 ax25_rt->dev = dev;
272 ax25_rt->digipeat = NULL;
273 ax25_rt->stamp.tv_sec = 0;
274 ax25_rt->n = 0;
275 ax25_rt->ip_mode = ' ';
276 ax25_rt->perm = AX25_RT_DYNAMIC;
277 if (route.digi_count != 0) {
278 if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
279 kfree_s(ax25_rt, sizeof(struct ax25_route));
280 return -ENOMEM;
281 }
282 ax25_rt->digipeat->lastrepeat = 0;
283 ax25_rt->digipeat->ndigi = route.digi_count;
284 for (i = 0; i < route.digi_count; i++) {
285 ax25_rt->digipeat->repeated[i] = 0;
286 ax25_rt->digipeat->calls[i] = route.digi_addr[i];
287 }
288 }
289 save_flags(flags);
290 cli();
291 ax25_rt->next = ax25_route;
292 ax25_route = ax25_rt;
293 restore_flags(flags);
294 break;
295
296 case SIOCDELRT:
297 if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
298 return err;
299 memcpy_fromfs(&route, arg, sizeof(route));
300 if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL)
301 return -EINVAL;
302 ax25_rt = ax25_route;
303 while (ax25_rt != NULL) {
304 s = ax25_rt;
305 ax25_rt = ax25_rt->next;
306 if (s->dev == dev && ax25cmp(&route.dest_addr, &s->callsign) == 0) {
307 if (ax25_route == s) {
308 ax25_route = s->next;
309 if (s->digipeat != NULL)
310 kfree_s((void *)s->digipeat, sizeof(ax25_digi));
311 kfree_s((void *)s, (sizeof *s));
312 } else {
313 for (t = ax25_route; t != NULL; t = t->next) {
314 if (t->next == s) {
315 t->next = s->next;
316 if (s->digipeat != NULL)
317 kfree_s((void *)s->digipeat, sizeof(ax25_digi));
318 kfree_s((void *)s, sizeof(*s));
319 break;
320 }
321 }
322 }
323 }
324 }
325 break;
326 case SIOCAX25OPTRT:
327 if ((err = verify_area(VERIFY_READ, arg, sizeof(rt_option))) != 0)
328 return err;
329 memcpy_fromfs(&rt_option, arg, sizeof(rt_option));
330 if ((dev = ax25rtr_get_dev(&rt_option.port_addr)) == NULL)
331 return -EINVAL;
332 ax25_rt = ax25_route;
333 while (ax25_rt != NULL) {
334 if (ax25_rt->dev == dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) {
335 switch(rt_option.cmd) {
336 case AX25_SET_RT_PERMANENT:
337 ax25_rt->perm = (char) rt_option.arg;
338 ax25_rt->stamp.tv_sec = 0;
339 break;
340 case AX25_SET_RT_IPMODE:
341 switch (rt_option.arg) {
342 case AX25_RT_IPMODE_DEFAULT:
343 ax25_rt->ip_mode = ' ';
344 break;
345 case AX25_RT_IPMODE_DATAGRAM:
346 ax25_rt->ip_mode = 'D';
347 break;
348 case AX25_RT_IPMODE_VC:
349 ax25_rt->ip_mode = 'V';
350 break;
351 default:
352 return -EINVAL;
353 }
354 break;
355 }
356 }
357 ax25_rt = ax25_rt->next;
358 }
359 break;
360 }
361
362 return 0;
363 }
364
365 int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
366 {
367 struct ax25_route *ax25_rt;
368 int len = 0;
369 off_t pos = 0;
370 off_t begin = 0;
371 char *callsign;
372 int i;
373
374 cli();
375
376 len += sprintf(buffer, "callsign dev count time mode F digipeaters\n");
377
378 for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
379 if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
380 callsign = "default";
381 else
382 callsign = ax2asc(&ax25_rt->callsign);
383 len += sprintf(buffer + len, "%-9s %-4s %5d %9d",
384 callsign,
385 ax25_rt->dev ? ax25_rt->dev->name : "???",
386 ax25_rt->n,
387 ax25_rt->stamp.tv_sec);
388
389 switch (ax25_rt->ip_mode) {
390 case 'V':
391 case 'v':
392 len += sprintf(buffer + len, " vc");
393 break;
394 case 'D':
395 case 'd':
396 len += sprintf(buffer + len, " dg");
397 break;
398 default:
399 len += sprintf(buffer + len, " *");
400 break;
401 }
402
403 switch (ax25_rt->perm) {
404 case AX25_RT_DYNAMIC:
405 if (ax25_rt->stamp.tv_sec == 0)
406 len += sprintf(buffer + len, " M");
407 else
408 len += sprintf(buffer + len, " ");
409 break;
410 case AX25_RT_PERMANENT:
411 len += sprintf(buffer + len, " P");
412 break;
413 default:
414 len += sprintf(buffer + len, " ?");
415 }
416
417 if (ax25_rt->digipeat != NULL)
418 for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
419 len += sprintf(buffer + len, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
420
421 len += sprintf(buffer + len, "\n");
422
423 pos = begin + len;
424
425 if (pos < offset) {
426 len = 0;
427 begin = pos;
428 }
429
430 if (pos > offset + length)
431 break;
432 }
433
434 sti();
435
436 *start = buffer + (offset - begin);
437 len -= (offset - begin);
438
439 if (len > length) len = length;
440
441 return len;
442 }
443
444 int ax25_cs_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
445 {
446 ax25_uid_assoc *pt;
447 int len = 0;
448 off_t pos = 0;
449 off_t begin = 0;
450
451 cli();
452
453 len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy);
454
455 for (pt = ax25_uid_list; pt != NULL; pt = pt->next) {
456 len += sprintf(buffer + len, "%6d %s\n", pt->uid, ax2asc(&pt->call));
457
458 pos = begin + len;
459
460 if (pos < offset) {
461 len = 0;
462 begin = pos;
463 }
464
465 if (pos > offset + length)
466 break;
467 }
468
469 sti();
470
471 *start = buffer + (offset - begin);
472 len -= offset - begin;
473
474 if (len > length) len = length;
475
476 return len;
477 }
478
479
480
481
482
483 static struct ax25_route * ax25_find_route(ax25_address *addr)
484 {
485 struct ax25_route *ax25_spe_rt = NULL;
486 struct ax25_route *ax25_def_rt = NULL;
487 struct ax25_route *ax25_rt;
488
489
490
491
492
493 for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
494 if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
495 ax25_spe_rt = ax25_rt;
496 if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
497 ax25_def_rt = ax25_rt;
498 }
499
500 if (ax25_spe_rt != NULL)
501 return ax25_spe_rt;
502
503 return ax25_def_rt;
504 }
505
506
507
508
509
510
511
512 static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat)
513 {
514 int k;
515
516 for (k = 0; k < digipeat->ndigi; k++) {
517 if (ax25cmp(addr, &digipeat->calls[k]) == 0)
518 break;
519 }
520
521 digipeat->ndigi = k;
522 }
523
524
525
526
527
528 int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
529 {
530 struct ax25_route *ax25_rt;
531 ax25_address *call;
532
533 if ((ax25_rt = ax25_find_route(addr)) == NULL)
534 return -EHOSTUNREACH;
535
536 if ((call = ax25_findbyuid(current->euid)) == NULL) {
537 if (ax25_uid_policy && !suser())
538 return -EPERM;
539 if (ax25->device == NULL)
540 return -ENODEV;
541 call = (ax25_address *)ax25->device->dev_addr;
542 }
543
544 ax25->source_addr = *call;
545
546 if (ax25_rt->digipeat != NULL) {
547 if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
548 return -ENOMEM;
549 *ax25->digipeat = *ax25_rt->digipeat;
550 ax25_adjust_path(addr, ax25->digipeat);
551 }
552
553 if (ax25->sk != NULL)
554 ax25->sk->zapped = 0;
555
556 return 0;
557 }
558
559
560
561
562
563 void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr)
564 {
565 struct ax25_route *ax25_rt;
566
567 ax25_rt = ax25_find_route(addr);
568
569 if (ax25_rt == NULL || ax25_rt->digipeat == NULL)
570 return;
571
572 if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
573 return;
574
575 ax25->device = ax25_rt->dev;
576 *ax25->digipeat = *ax25_rt->digipeat;
577 ax25_adjust_path(addr, ax25->digipeat);
578 }
579
580 void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *dev)
581 {
582 struct ax25_route *ax25_rt;
583 ax25_digi digipeat;
584 ax25_address src, dest;
585 unsigned char *bp;
586 int len;
587
588 skb_pull(skb, 1);
589
590 ax25_rt = ax25_find_route(addr);
591 if (ax25_rt == NULL || ax25_rt->digipeat == NULL)
592 return;
593
594 digipeat = *ax25_rt->digipeat;
595
596 ax25_adjust_path(addr, &digipeat);
597
598 len = ax25_rt->digipeat->ndigi * AX25_ADDR_LEN;
599
600 if (skb_headroom(skb) < len) {
601 printk("ax25_dg_build_path: not enough headroom for digis in skb\n");
602 return;
603 }
604
605 memcpy(&dest, skb->data , AX25_ADDR_LEN);
606 memcpy(&src, skb->data + 7, AX25_ADDR_LEN);
607
608 bp = skb_push(skb, len);
609
610 build_ax25_addr(bp, &src, &dest, ax25_rt->digipeat, C_COMMAND, MODULUS);
611 }
612
613
614
615
616
617 void ax25_ip_mode_set(ax25_address *callsign, struct device *dev, char ip_mode)
618 {
619 struct ax25_route *ax25_rt;
620
621 for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
622 if (ax25cmp(&ax25_rt->callsign, callsign) == 0 && ax25_rt->dev == dev) {
623 ax25_rt->ip_mode = ip_mode;
624 return;
625 }
626 }
627 }
628
629
630
631
632 char ax25_ip_mode_get(ax25_address *callsign, struct device *dev)
633 {
634 struct ax25_route *ax25_rt;
635
636 for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next)
637 if (ax25cmp(&ax25_rt->callsign, callsign) == 0 && ax25_rt->dev == dev)
638 return ax25_rt->ip_mode;
639
640 return ' ';
641 }
642
643 static struct ax25_dev *ax25_dev_get_dev(struct device *dev)
644 {
645 struct ax25_dev *s;
646
647 for (s = ax25_device; s != NULL; s = s->next)
648 if (s->dev == dev)
649 return s;
650
651 return NULL;
652 }
653
654
655
656
657 unsigned short ax25_dev_get_value(struct device *dev, int valueno)
658 {
659 struct ax25_dev *ax25_dev;
660
661 if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL) {
662 printk("ax25_dev_get_flag called with invalid device\n");
663 return 1;
664 }
665
666 return ax25_dev->values[valueno];
667 }
668
669
670
671
672
673 void ax25_dev_device_up(struct device *dev)
674 {
675 unsigned long flags;
676 struct ax25_dev *ax25_dev;
677
678 if ((ax25_dev = (struct ax25_dev *)kmalloc(sizeof(struct ax25_dev), GFP_ATOMIC)) == NULL)
679 return;
680
681 ax25_dev->dev = dev;
682
683 ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE;
684 ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE;
685 ax25_dev->values[AX25_VALUES_NETROM] = AX25_DEF_NETROM;
686 ax25_dev->values[AX25_VALUES_TEXT] = AX25_DEF_TEXT;
687 ax25_dev->values[AX25_VALUES_BACKOFF] = AX25_DEF_BACKOFF;
688 ax25_dev->values[AX25_VALUES_CONMODE] = AX25_DEF_CONMODE;
689 ax25_dev->values[AX25_VALUES_WINDOW] = AX25_DEF_WINDOW;
690 ax25_dev->values[AX25_VALUES_EWINDOW] = AX25_DEF_EWINDOW;
691 ax25_dev->values[AX25_VALUES_T1] = AX25_DEF_T1 * PR_SLOWHZ;
692 ax25_dev->values[AX25_VALUES_T2] = AX25_DEF_T2 * PR_SLOWHZ;
693 ax25_dev->values[AX25_VALUES_T3] = AX25_DEF_T3 * PR_SLOWHZ;
694 ax25_dev->values[AX25_VALUES_IDLE] = AX25_DEF_IDLE * PR_SLOWHZ * 60;
695 ax25_dev->values[AX25_VALUES_N2] = AX25_DEF_N2;
696 ax25_dev->values[AX25_VALUES_DIGI] = AX25_DEF_DIGI;
697 ax25_dev->values[AX25_VALUES_PACLEN] = AX25_DEF_PACLEN;
698 ax25_dev->values[AX25_VALUES_IPMAXQUEUE]= AX25_DEF_IPMAXQUEUE;
699
700 save_flags(flags);
701 cli();
702
703 ax25_dev->next = ax25_device;
704 ax25_device = ax25_dev;
705
706 restore_flags(flags);
707 }
708
709 void ax25_dev_device_down(struct device *dev)
710 {
711 struct ax25_dev *s, *t, *ax25_dev = ax25_device;
712
713 while (ax25_dev != NULL) {
714 s = ax25_dev;
715 ax25_dev = ax25_dev->next;
716
717 if (s->dev == dev) {
718 if (ax25_device == s) {
719 ax25_device = s->next;
720 kfree_s((void *)s, (sizeof *s));
721 } else {
722 for (t = ax25_device; t != NULL; t = t->next) {
723 if (t->next == s) {
724 t->next = s->next;
725 kfree_s((void *)s, sizeof(*s));
726 break;
727 }
728 }
729 }
730 }
731 }
732 }
733
734 int ax25_dev_ioctl(unsigned int cmd, void *arg)
735 {
736 struct ax25_parms_struct ax25_parms;
737 struct device *dev;
738 struct ax25_dev *ax25_dev;
739 int err;
740
741 switch (cmd) {
742 case SIOCAX25SETPARMS:
743 if (!suser())
744 return -EPERM;
745 if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_parms))) != 0)
746 return err;
747 memcpy_fromfs(&ax25_parms, arg, sizeof(ax25_parms));
748 if ((dev = ax25rtr_get_dev(&ax25_parms.port_addr)) == NULL)
749 return -EINVAL;
750 if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL)
751 return -EINVAL;
752 if (ax25_parms.values[AX25_VALUES_IPDEFMODE] != 'D' &&
753 ax25_parms.values[AX25_VALUES_IPDEFMODE] != 'V')
754 return -EINVAL;
755 if (ax25_parms.values[AX25_VALUES_AXDEFMODE] != MODULUS &&
756 ax25_parms.values[AX25_VALUES_AXDEFMODE] != EMODULUS)
757 return -EINVAL;
758 if (ax25_parms.values[AX25_VALUES_NETROM] != 0 &&
759 ax25_parms.values[AX25_VALUES_NETROM] != 1)
760 return -EINVAL;
761 if (ax25_parms.values[AX25_VALUES_TEXT] != 0 &&
762 ax25_parms.values[AX25_VALUES_TEXT] != 1)
763 return -EINVAL;
764 if (ax25_parms.values[AX25_VALUES_BACKOFF] != 'E' &&
765 ax25_parms.values[AX25_VALUES_BACKOFF] != 'L')
766 return -EINVAL;
767 if (ax25_parms.values[AX25_VALUES_CONMODE] != 0 &&
768 ax25_parms.values[AX25_VALUES_CONMODE] != 1)
769 return -EINVAL;
770 if (ax25_parms.values[AX25_VALUES_WINDOW] < 1 ||
771 ax25_parms.values[AX25_VALUES_WINDOW] > 7)
772 return -EINVAL;
773 if (ax25_parms.values[AX25_VALUES_EWINDOW] < 1 ||
774 ax25_parms.values[AX25_VALUES_EWINDOW] > 63)
775 return -EINVAL;
776 if (ax25_parms.values[AX25_VALUES_T1] < 1)
777 return -EINVAL;
778 if (ax25_parms.values[AX25_VALUES_T2] < 1)
779 return -EINVAL;
780 if (ax25_parms.values[AX25_VALUES_T3] < 1)
781 return -EINVAL;
782 if (ax25_parms.values[AX25_VALUES_IDLE] > 100)
783 return -EINVAL;
784 if (ax25_parms.values[AX25_VALUES_N2] < 1 ||
785 ax25_parms.values[AX25_VALUES_N2] > 31)
786 return -EINVAL;
787 if (ax25_parms.values[AX25_VALUES_PACLEN] < 22)
788 return -EINVAL;
789 if ((ax25_parms.values[AX25_VALUES_DIGI] &
790 ~(AX25_DIGI_INBAND | AX25_DIGI_XBAND)) != 0)
791 return -EINVAL;
792 if (ax25_parms.values[AX25_VALUES_IPMAXQUEUE] < 1)
793 return -EINVAL;
794 memcpy(ax25_dev->values, ax25_parms.values, AX25_MAX_VALUES * sizeof(short));
795 ax25_dev->values[AX25_VALUES_T1] *= PR_SLOWHZ;
796 ax25_dev->values[AX25_VALUES_T1] /= 2;
797 ax25_dev->values[AX25_VALUES_T2] *= PR_SLOWHZ;
798 ax25_dev->values[AX25_VALUES_T3] *= PR_SLOWHZ;
799 ax25_dev->values[AX25_VALUES_IDLE] *= PR_SLOWHZ * 60;
800 break;
801
802 case SIOCAX25GETPARMS:
803 if ((err = verify_area(VERIFY_WRITE, arg, sizeof(struct ax25_parms_struct))) != 0)
804 return err;
805 memcpy_fromfs(&ax25_parms, arg, sizeof(ax25_parms));
806 if ((dev = ax25rtr_get_dev(&ax25_parms.port_addr)) == NULL)
807 return -EINVAL;
808 if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL)
809 return -EINVAL;
810 memcpy(ax25_parms.values, ax25_dev->values, AX25_MAX_VALUES * sizeof(short));
811 ax25_parms.values[AX25_VALUES_T1] *= 2;
812 ax25_parms.values[AX25_VALUES_T1] /= PR_SLOWHZ;
813 ax25_parms.values[AX25_VALUES_T2] /= PR_SLOWHZ;
814 ax25_parms.values[AX25_VALUES_T3] /= PR_SLOWHZ;
815 ax25_parms.values[AX25_VALUES_IDLE] /= PR_SLOWHZ * 60;
816 memcpy_tofs(arg, &ax25_parms, sizeof(ax25_parms));
817 break;
818 }
819
820 return 0;
821 }
822
823 #ifdef CONFIG_BPQETHER
824 static struct ax25_bpqdev {
825 struct ax25_bpqdev *next;
826 struct device *dev;
827 ax25_address callsign;
828 } *ax25_bpqdev = NULL;
829
830 int ax25_bpq_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
831 {
832 struct ax25_bpqdev *bpqdev;
833 int len = 0;
834 off_t pos = 0;
835 off_t begin = 0;
836
837 cli();
838
839 len += sprintf(buffer, "dev callsign\n");
840
841 for (bpqdev = ax25_bpqdev; bpqdev != NULL; bpqdev = bpqdev->next) {
842 len += sprintf(buffer + len, "%-4s %-9s\n",
843 bpqdev->dev ? bpqdev->dev->name : "???",
844 ax2asc(&bpqdev->callsign));
845
846 pos = begin + len;
847
848 if (pos < offset) {
849 len = 0;
850 begin = pos;
851 }
852
853 if (pos > offset + length)
854 break;
855 }
856
857 sti();
858
859 *start = buffer + (offset - begin);
860 len -= (offset - begin);
861
862 if (len > length) len = length;
863
864 return len;
865 }
866
867 ax25_address *ax25_bpq_get_addr(struct device *dev)
868 {
869 struct ax25_bpqdev *bpqdev;
870
871 for (bpqdev = ax25_bpqdev; bpqdev != NULL; bpqdev = bpqdev->next)
872 if (bpqdev->dev == dev)
873 return &bpqdev->callsign;
874
875 return NULL;
876 }
877
878 int ax25_bpq_ioctl(unsigned int cmd, void *arg)
879 {
880 unsigned long flags;
881 struct ax25_bpqdev *bpqdev;
882 struct ax25_bpqaddr_struct bpqaddr;
883 struct device *dev;
884 int err;
885
886 switch (cmd) {
887 case SIOCAX25BPQADDR:
888 if ((err = verify_area(VERIFY_READ, arg, sizeof(bpqaddr))) != 0)
889 return err;
890 memcpy_fromfs(&bpqaddr, arg, sizeof(bpqaddr));
891 if ((dev = dev_get(bpqaddr.dev)) == NULL)
892 return -EINVAL;
893 if (dev->type != ARPHRD_ETHER)
894 return -EINVAL;
895 for (bpqdev = ax25_bpqdev; bpqdev != NULL; bpqdev = bpqdev->next) {
896 if (bpqdev->dev == dev) {
897 bpqdev->callsign = bpqaddr.addr;
898 return 0;
899 }
900 }
901 if ((bpqdev = (struct ax25_bpqdev *)kmalloc(sizeof(struct ax25_bpqdev), GFP_ATOMIC)) == NULL)
902 return -ENOMEM;
903 bpqdev->dev = dev;
904 bpqdev->callsign = bpqaddr.addr;
905 save_flags(flags);
906 cli();
907 bpqdev->next = ax25_bpqdev;
908 ax25_bpqdev = bpqdev;
909 restore_flags(flags);
910 break;
911 }
912
913 return 0;
914 }
915
916 #endif
917
918 #endif