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