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