1/* 2 * NET/ROM release 007 3 * 4 * This code REQUIRES 2.1.15 or higher/ NET3.038 5 * 6 * This module: 7 * This module is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 10 * 2 of the License, or (at your option) any later version. 11 * 12 * History 13 * NET/ROM 001 Jonathan(G4KLX) First attempt. 14 * NET/ROM 003 Jonathan(G4KLX) Use SIOCADDRT/SIOCDELRT ioctl values 15 * for NET/ROM routes. 16 * Use '*' for a blank mnemonic in /proc/net/nr_nodes. 17 * Change default quality for new neighbour when same 18 * as node callsign. 19 * Alan Cox(GW4PTS) Added the firewall hooks. 20 * NET/ROM 006 Jonathan(G4KLX) Added the setting of digipeated neighbours. 21 * Tomi(OH2BNS) Routing quality and link failure changes. 22 * Device refcnt fixes. 23 */ 24 25#include <linux/errno.h> 26#include <linux/types.h> 27#include <linux/socket.h> 28#include <linux/in.h> 29#include <linux/kernel.h> 30#include <linux/sched.h> 31#include <linux/timer.h> 32#include <linux/string.h> 33#include <linux/sockios.h> 34#include <linux/net.h> 35#include <net/ax25.h> 36#include <linux/inet.h> 37#include <linux/netdevice.h> 38#include <net/arp.h> 39#include <linux/if_arp.h> 40#include <linux/skbuff.h> 41#include <net/sock.h> 42#include <asm/uaccess.h> 43#include <asm/system.h> 44#include <linux/fcntl.h> 45#include <linux/termios.h> /* For TIOCINQ/OUTQ */ 46#include <linux/mm.h> 47#include <linux/interrupt.h> 48#include <linux/notifier.h> 49#include <linux/netfilter.h> 50#include <linux/init.h> 51#include <net/netrom.h> 52 53static unsigned int nr_neigh_no = 1; 54 55static struct nr_node *nr_node_list; 56static struct nr_neigh *nr_neigh_list; 57 58static void nr_remove_neigh(struct nr_neigh *); 59 60/* 61 * Add a new route to a node, and in the process add the node and the 62 * neighbour if it is new. 63 */ 64static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax25, 65 ax25_digi *ax25_digi, struct net_device *dev, int quality, int obs_count) 66{ 67 struct nr_node *nr_node; 68 struct nr_neigh *nr_neigh; 69 struct nr_route nr_route; 70 struct net_device *tdev; 71 unsigned long flags; 72 int i, found; 73 74 /* Can't add routes to ourself */ 75 if ((tdev = nr_dev_get(nr)) != NULL) { 76 dev_put(tdev); 77 return -EINVAL; 78 } 79 80 for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) 81 if (ax25cmp(nr, &nr_node->callsign) == 0) 82 break; 83 84 for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) 85 if (ax25cmp(ax25, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev) 86 break; 87 88 /* 89 * The L2 link to a neighbour has failed in the past 90 * and now a frame comes from this neighbour. We assume 91 * it was a temporary trouble with the link and reset the 92 * routes now (and not wait for a node broadcast). 93 */ 94 if (nr_neigh != NULL && nr_neigh->failed != 0 && quality == 0) { 95 struct nr_node *node; 96 97 for (node = nr_node_list; node != NULL; node = node->next) 98 for (i = 0; i < node->count; i++) 99 if (node->routes[i].neighbour == nr_neigh) 100 if (i < node->which) 101 node->which = i; 102 } 103 104 if (nr_neigh != NULL) 105 nr_neigh->failed = 0; 106 107 if (quality == 0 && nr_neigh != NULL && nr_node != NULL) 108 return 0; 109 110 if (nr_neigh == NULL) { 111 if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL) 112 return -ENOMEM; 113 114 nr_neigh->callsign = *ax25; 115 nr_neigh->digipeat = NULL; 116 nr_neigh->ax25 = NULL; 117 nr_neigh->dev = dev; 118 nr_neigh->quality = sysctl_netrom_default_path_quality; 119 nr_neigh->locked = 0; 120 nr_neigh->count = 0; 121 nr_neigh->number = nr_neigh_no++; 122 nr_neigh->failed = 0; 123 124 if (ax25_digi != NULL && ax25_digi->ndigi > 0) { 125 if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) { 126 kfree(nr_neigh); 127 return -ENOMEM; 128 } 129 memcpy(nr_neigh->digipeat, ax25_digi, sizeof(ax25_digi)); 130 } 131 132 dev_hold(nr_neigh->dev); 133 134 save_flags(flags); 135 cli(); 136 137 nr_neigh->next = nr_neigh_list; 138 nr_neigh_list = nr_neigh; 139 140 restore_flags(flags); 141 } 142 143 if (quality != 0 && ax25cmp(nr, ax25) == 0 && !nr_neigh->locked) 144 nr_neigh->quality = quality; 145 146 if (nr_node == NULL) { 147 if ((nr_node = kmalloc(sizeof(*nr_node), GFP_ATOMIC)) == NULL) 148 return -ENOMEM; 149 150 nr_node->callsign = *nr; 151 strcpy(nr_node->mnemonic, mnemonic); 152 153 nr_node->which = 0; 154 nr_node->count = 1; 155 156 nr_node->routes[0].quality = quality; 157 nr_node->routes[0].obs_count = obs_count; 158 nr_node->routes[0].neighbour = nr_neigh; 159 160 save_flags(flags); 161 cli(); 162 163 nr_node->next = nr_node_list; 164 nr_node_list = nr_node; 165 166 restore_flags(flags); 167 168 nr_neigh->count++; 169 170 return 0; 171 } 172 173 if (quality != 0) 174 strcpy(nr_node->mnemonic, mnemonic); 175 176 for (found = 0, i = 0; i < nr_node->count; i++) { 177 if (nr_node->routes[i].neighbour == nr_neigh) { 178 nr_node->routes[i].quality = quality; 179 nr_node->routes[i].obs_count = obs_count; 180 found = 1; 181 break; 182 } 183 } 184 185 if (!found) { 186 /* We have space at the bottom, slot it in */ 187 if (nr_node->count < 3) { 188 nr_node->routes[2] = nr_node->routes[1]; 189 nr_node->routes[1] = nr_node->routes[0]; 190 191 nr_node->routes[0].quality = quality; 192 nr_node->routes[0].obs_count = obs_count; 193 nr_node->routes[0].neighbour = nr_neigh; 194 195 nr_node->which++; 196 nr_node->count++; 197 nr_neigh->count++; 198 } else { 199 /* It must be better than the worst */ 200 if (quality > nr_node->routes[2].quality) { 201 nr_node->routes[2].neighbour->count--; 202 203 if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked) 204 nr_remove_neigh(nr_node->routes[2].neighbour); 205 206 nr_node->routes[2].quality = quality; 207 nr_node->routes[2].obs_count = obs_count; 208 nr_node->routes[2].neighbour = nr_neigh; 209 210 nr_neigh->count++; 211 } 212 } 213 } 214 215 /* Now re-sort the routes in quality order */ 216 switch (nr_node->count) { 217 case 3: 218 if (nr_node->routes[1].quality > nr_node->routes[0].quality) { 219 switch (nr_node->which) { 220 case 0: nr_node->which = 1; break; 221 case 1: nr_node->which = 0; break; 222 default: break; 223 } 224 nr_route = nr_node->routes[0]; 225 nr_node->routes[0] = nr_node->routes[1]; 226 nr_node->routes[1] = nr_route; 227 } 228 if (nr_node->routes[2].quality > nr_node->routes[1].quality) { 229 switch (nr_node->which) { 230 case 1: nr_node->which = 2; break; 231 case 2: nr_node->which = 1; break; 232 default: break; 233 } 234 nr_route = nr_node->routes[1]; 235 nr_node->routes[1] = nr_node->routes[2]; 236 nr_node->routes[2] = nr_route; 237 } 238 case 2: 239 if (nr_node->routes[1].quality > nr_node->routes[0].quality) { 240 switch (nr_node->which) { 241 case 0: nr_node->which = 1; break; 242 case 1: nr_node->which = 0; break; 243 default: break; 244 } 245 nr_route = nr_node->routes[0]; 246 nr_node->routes[0] = nr_node->routes[1]; 247 nr_node->routes[1] = nr_route; 248 } 249 case 1: 250 break; 251 } 252 253 for (i = 0; i < nr_node->count; i++) { 254 if (nr_node->routes[i].neighbour == nr_neigh) { 255 if (i < nr_node->which) 256 nr_node->which = i; 257 break; 258 } 259 } 260 261 return 0; 262} 263 264static void nr_remove_node(struct nr_node *nr_node) 265{ 266 struct nr_node *s; 267 unsigned long flags; 268 269 save_flags(flags); 270 cli(); 271 272 if ((s = nr_node_list) == nr_node) { 273 nr_node_list = nr_node->next; 274 restore_flags(flags); 275 kfree(nr_node); 276 return; 277 } 278 279 while (s != NULL && s->next != NULL) { 280 if (s->next == nr_node) { 281 s->next = nr_node->next; 282 restore_flags(flags); 283 kfree(nr_node); 284 return; 285 } 286 287 s = s->next; 288 } 289 290 restore_flags(flags); 291} 292 293static void nr_remove_neigh(struct nr_neigh *nr_neigh) 294{ 295 struct nr_neigh *s; 296 unsigned long flags; 297 298 save_flags(flags); 299 cli(); 300 301 if ((s = nr_neigh_list) == nr_neigh) { 302 nr_neigh_list = nr_neigh->next; 303 restore_flags(flags); 304 dev_put(nr_neigh->dev); 305 if (nr_neigh->digipeat != NULL) 306 kfree(nr_neigh->digipeat); 307 kfree(nr_neigh); 308 return; 309 } 310 311 while (s != NULL && s->next != NULL) { 312 if (s->next == nr_neigh) { 313 s->next = nr_neigh->next; 314 restore_flags(flags); 315 dev_put(nr_neigh->dev); 316 if (nr_neigh->digipeat != NULL) 317 kfree(nr_neigh->digipeat); 318 kfree(nr_neigh); 319 return; 320 } 321 322 s = s->next; 323 } 324 325 restore_flags(flags); 326} 327 328/* 329 * "Delete" a node. Strictly speaking remove a route to a node. The node 330 * is only deleted if no routes are left to it. 331 */ 332static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct net_device *dev) 333{ 334 struct nr_node *nr_node; 335 struct nr_neigh *nr_neigh; 336 int i; 337 338 for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) 339 if (ax25cmp(callsign, &nr_node->callsign) == 0) 340 break; 341 342 if (nr_node == NULL) return -EINVAL; 343 344 for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) 345 if (ax25cmp(neighbour, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev) 346 break; 347 348 if (nr_neigh == NULL) return -EINVAL; 349 350 for (i = 0; i < nr_node->count; i++) { 351 if (nr_node->routes[i].neighbour == nr_neigh) { 352 nr_neigh->count--; 353 354 if (nr_neigh->count == 0 && !nr_neigh->locked) 355 nr_remove_neigh(nr_neigh); 356 357 nr_node->count--; 358 359 if (nr_node->count == 0) { 360 nr_remove_node(nr_node); 361 } else { 362 switch (i) { 363 case 0: 364 nr_node->routes[0] = nr_node->routes[1]; 365 case 1: 366 nr_node->routes[1] = nr_node->routes[2]; 367 case 2: 368 break; 369 } 370 } 371 372 return 0; 373 } 374 } 375 376 return -EINVAL; 377} 378 379/* 380 * Lock a neighbour with a quality. 381 */ 382static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality) 383{ 384 struct nr_neigh *nr_neigh; 385 unsigned long flags; 386 387 for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) { 388 if (ax25cmp(callsign, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev) { 389 nr_neigh->quality = quality; 390 nr_neigh->locked = 1; 391 return 0; 392 } 393 } 394 395 if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL) 396 return -ENOMEM; 397 398 nr_neigh->callsign = *callsign; 399 nr_neigh->digipeat = NULL; 400 nr_neigh->ax25 = NULL; 401 nr_neigh->dev = dev; 402 nr_neigh->quality = quality; 403 nr_neigh->locked = 1; 404 nr_neigh->count = 0; 405 nr_neigh->number = nr_neigh_no++; 406 nr_neigh->failed = 0; 407 408 if (ax25_digi != NULL && ax25_digi->ndigi > 0) { 409 if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) { 410 kfree(nr_neigh); 411 return -ENOMEM; 412 } 413 memcpy(nr_neigh->digipeat, ax25_digi, sizeof(ax25_digi)); 414 } 415 416 dev_hold(nr_neigh->dev); 417 418 save_flags(flags); 419 cli(); 420 421 nr_neigh->next = nr_neigh_list; 422 nr_neigh_list = nr_neigh; 423 424 restore_flags(flags); 425 426 return 0; 427} 428 429/* 430 * "Delete" a neighbour. The neighbour is only removed if the number 431 * of nodes that may use it is zero. 432 */ 433static int nr_del_neigh(ax25_address *callsign, struct net_device *dev, unsigned int quality) 434{ 435 struct nr_neigh *nr_neigh; 436 437 for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) 438 if (ax25cmp(callsign, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev) 439 break; 440 441 if (nr_neigh == NULL) return -EINVAL; 442 443 nr_neigh->quality = quality; 444 nr_neigh->locked = 0; 445 446 if (nr_neigh->count == 0) 447 nr_remove_neigh(nr_neigh); 448 449 return 0; 450} 451 452/* 453 * Decrement the obsolescence count by one. If a route is reduced to a 454 * count of zero, remove it. Also remove any unlocked neighbours with 455 * zero nodes routing via it. 456 */ 457static int nr_dec_obs(void) 458{ 459 struct nr_neigh *nr_neigh; 460 struct nr_node *s, *nr_node; 461 int i; 462 463 nr_node = nr_node_list; 464 465 while (nr_node != NULL) { 466 s = nr_node; 467 nr_node = nr_node->next; 468 469 for (i = 0; i < s->count; i++) { 470 switch (s->routes[i].obs_count) { 471 472 case 0: /* A locked entry */ 473 break; 474 475 case 1: /* From 1 -> 0 */ 476 nr_neigh = s->routes[i].neighbour; 477 478 nr_neigh->count--; 479 480 if (nr_neigh->count == 0 && !nr_neigh->locked) 481 nr_remove_neigh(nr_neigh); 482 483 s->count--; 484 485 switch (i) { 486 case 0: 487 s->routes[0] = s->routes[1]; 488 case 1: 489 s->routes[1] = s->routes[2]; 490 case 2: 491 break; 492 } 493 break; 494 495 default: 496 s->routes[i].obs_count--; 497 break; 498 499 } 500 } 501 502 if (s->count <= 0) 503 nr_remove_node(s); 504 } 505 506 return 0; 507} 508 509/* 510 * A device has been removed. Remove its routes and neighbours. 511 */ 512void nr_rt_device_down(struct net_device *dev) 513{ 514 struct nr_neigh *s, *nr_neigh = nr_neigh_list; 515 struct nr_node *t, *nr_node; 516 int i; 517 518 while (nr_neigh != NULL) { 519 s = nr_neigh; 520 nr_neigh = nr_neigh->next; 521 522 if (s->dev == dev) { 523 nr_node = nr_node_list; 524 525 while (nr_node != NULL) { 526 t = nr_node; 527 nr_node = nr_node->next; 528 529 for (i = 0; i < t->count; i++) { 530 if (t->routes[i].neighbour == s) { 531 t->count--; 532 533 switch (i) { 534 case 0: 535 t->routes[0] = t->routes[1]; 536 case 1: 537 t->routes[1] = t->routes[2]; 538 case 2: 539 break; 540 } 541 } 542 } 543 544 if (t->count <= 0) 545 nr_remove_node(t); 546 } 547 548 nr_remove_neigh(s); 549 } 550 } 551} 552 553/* 554 * Check that the device given is a valid AX.25 interface that is "up". 555 * Or a valid ethernet interface with an AX.25 callsign binding. 556 */ 557static struct net_device *nr_ax25_dev_get(char *devname) 558{ 559 struct net_device *dev; 560 561 if ((dev = dev_get_by_name(devname)) == NULL) 562 return NULL; 563 564 if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25) 565 return dev; 566 567 dev_put(dev); 568 return NULL; 569} 570 571/* 572 * Find the first active NET/ROM device, usually "nr0". 573 */ 574struct net_device *nr_dev_first(void) 575{ 576 struct net_device *dev, *first = NULL; 577 578 read_lock(&dev_base_lock); 579 for (dev = dev_base; dev != NULL; dev = dev->next) { 580 if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM) 581 if (first == NULL || strncmp(dev->name, first->name, 3) < 0) 582 first = dev; 583 } 584 585 if (first != NULL) 586 dev_hold(first); 587 588 read_unlock(&dev_base_lock); 589 590 return first; 591} 592 593/* 594 * Find the NET/ROM device for the given callsign. 595 */ 596struct net_device *nr_dev_get(ax25_address *addr) 597{ 598 struct net_device *dev; 599 600 read_lock(&dev_base_lock); 601 for (dev = dev_base; dev != NULL; dev = dev->next) { 602 if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) { 603 dev_hold(dev); 604 goto out; 605 } 606 } 607out: 608 read_unlock(&dev_base_lock); 609 return dev; 610} 611 612static ax25_digi *nr_call_to_digi(int ndigis, ax25_address *digipeaters) 613{ 614 static ax25_digi ax25_digi; 615 int i; 616 617 if (ndigis == 0) 618 return NULL; 619 620 for (i = 0; i < ndigis; i++) { 621 ax25_digi.calls[i] = digipeaters[i]; 622 ax25_digi.repeated[i] = 0; 623 } 624 625 ax25_digi.ndigi = ndigis; 626 ax25_digi.lastrepeat = -1; 627 628 return &ax25_digi; 629} 630 631/* 632 * Handle the ioctls that control the routing functions. 633 */ 634int nr_rt_ioctl(unsigned int cmd, void *arg) 635{ 636 struct nr_route_struct nr_route; 637 struct net_device *dev; 638 int ret; 639 640 switch (cmd) { 641 642 case SIOCADDRT: 643 if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct))) 644 return -EFAULT; 645 if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL) 646 return -EINVAL; 647 if (nr_route.ndigis < 0 || nr_route.ndigis > AX25_MAX_DIGIS) { 648 dev_put(dev); 649 return -EINVAL; 650 } 651 switch (nr_route.type) { 652 case NETROM_NODE: 653 ret = nr_add_node(&nr_route.callsign, 654 nr_route.mnemonic, 655 &nr_route.neighbour, 656 nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters), 657 dev, nr_route.quality, 658 nr_route.obs_count); 659 break; 660 case NETROM_NEIGH: 661 ret = nr_add_neigh(&nr_route.callsign, 662 nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters), 663 dev, nr_route.quality); 664 break; 665 default: 666 ret = -EINVAL; 667 break; 668 } 669 dev_put(dev); 670 return ret; 671 672 case SIOCDELRT: 673 if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct))) 674 return -EFAULT; 675 if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL) 676 return -EINVAL; 677 switch (nr_route.type) { 678 case NETROM_NODE: 679 ret = nr_del_node(&nr_route.callsign, 680 &nr_route.neighbour, dev); 681 break; 682 case NETROM_NEIGH: 683 ret = nr_del_neigh(&nr_route.callsign, 684 dev, nr_route.quality); 685 break; 686 default: 687 ret = -EINVAL; 688 break; 689 } 690 dev_put(dev); 691 return ret; 692 693 case SIOCNRDECOBS: 694 return nr_dec_obs(); 695 696 default: 697 return -EINVAL; 698 } 699 700 return 0; 701} 702 703/* 704 * A level 2 link has timed out, therefore it appears to be a poor link, 705 * then don't use that neighbour until it is reset. 706 */ 707void nr_link_failed(ax25_cb *ax25, int reason) 708{ 709 struct nr_neigh *nr_neigh; 710 struct nr_node *nr_node; 711 712 for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) 713 if (nr_neigh->ax25 == ax25) 714 break; 715 716 if (nr_neigh == NULL) return; 717 718 nr_neigh->ax25 = NULL; 719 720 if (++nr_neigh->failed < sysctl_netrom_link_fails_count) return; 721 722 for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) 723 if (nr_node->which < nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh) 724 nr_node->which++; 725} 726 727/* 728 * Route a frame to an appropriate AX.25 connection. A NULL ax25_cb 729 * indicates an internally generated frame. 730 */ 731int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) 732{ 733 ax25_address *nr_src, *nr_dest; 734 struct nr_neigh *nr_neigh; 735 struct nr_node *nr_node; 736 struct net_device *dev; 737 unsigned char *dptr; 738 739 740 nr_src = (ax25_address *)(skb->data + 0); 741 nr_dest = (ax25_address *)(skb->data + 7); 742 743 if (ax25 != NULL) 744 nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat, 745 ax25->ax25_dev->dev, 0, sysctl_netrom_obsolescence_count_initialiser); 746 747 if ((dev = nr_dev_get(nr_dest)) != NULL) { /* Its for me */ 748 int ret; 749 750 if (ax25 == NULL) /* Its from me */ 751 ret = nr_loopback_queue(skb); 752 else 753 ret = nr_rx_frame(skb, dev); 754 755 dev_put(dev); 756 return ret; 757 } 758 759 if (!sysctl_netrom_routing_control && ax25 != NULL) 760 return 0; 761 762 /* Its Time-To-Live has expired */ 763 if (--skb->data[14] == 0) 764 return 0; 765 766 for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) 767 if (ax25cmp(nr_dest, &nr_node->callsign) == 0) 768 break; 769 770 if (nr_node == NULL || nr_node->which >= nr_node->count) 771 return 0; 772 773 nr_neigh = nr_node->routes[nr_node->which].neighbour; 774 775 if ((dev = nr_dev_first()) == NULL) 776 return 0; 777 778 dptr = skb_push(skb, 1); 779 *dptr = AX25_P_NETROM; 780 781 nr_neigh->ax25 = ax25_send_frame(skb, 256, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev); 782 783 dev_put(dev); 784 785 return (nr_neigh->ax25 != NULL); 786} 787 788int nr_nodes_get_info(char *buffer, char **start, off_t offset, int length) 789{ 790 struct nr_node *nr_node; 791 int len = 0; 792 off_t pos = 0; 793 off_t begin = 0; 794 int i; 795 796 cli(); 797 798 len += sprintf(buffer, "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n"); 799 800 for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) { 801 len += sprintf(buffer + len, "%-9s %-7s %d %d", 802 ax2asc(&nr_node->callsign), 803 (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic, 804 nr_node->which + 1, 805 nr_node->count); 806 807 for (i = 0; i < nr_node->count; i++) { 808 len += sprintf(buffer + len, " %3d %d %05d", 809 nr_node->routes[i].quality, 810 nr_node->routes[i].obs_count, 811 nr_node->routes[i].neighbour->number); 812 } 813 814 len += sprintf(buffer + len, "\n"); 815 816 pos = begin + len; 817 818 if (pos < offset) { 819 len = 0; 820 begin = pos; 821 } 822 823 if (pos > offset + length) 824 break; 825 } 826 827 sti(); 828 829 *start = buffer + (offset - begin); 830 len -= (offset - begin); 831 832 if (len > length) len = length; 833 834 return len; 835} 836 837int nr_neigh_get_info(char *buffer, char **start, off_t offset, int length) 838{ 839 struct nr_neigh *nr_neigh; 840 int len = 0; 841 off_t pos = 0; 842 off_t begin = 0; 843 int i; 844 845 cli(); 846 847 len += sprintf(buffer, "addr callsign dev qual lock count failed digipeaters\n"); 848 849 for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) { 850 len += sprintf(buffer + len, "%05d %-9s %-4s %3d %d %3d %3d", 851 nr_neigh->number, 852 ax2asc(&nr_neigh->callsign), 853 nr_neigh->dev ? nr_neigh->dev->name : "???", 854 nr_neigh->quality, 855 nr_neigh->locked, 856 nr_neigh->count, 857 nr_neigh->failed); 858 859 if (nr_neigh->digipeat != NULL) { 860 for (i = 0; i < nr_neigh->digipeat->ndigi; i++) 861 len += sprintf(buffer + len, " %s", ax2asc(&nr_neigh->digipeat->calls[i])); 862 } 863 864 len += sprintf(buffer + len, "\n"); 865 866 pos = begin + len; 867 868 if (pos < offset) { 869 len = 0; 870 begin = pos; 871 } 872 873 if (pos > offset + length) 874 break; 875 } 876 877 sti(); 878 879 *start = buffer + (offset - begin); 880 len -= (offset - begin); 881 882 if (len > length) len = length; 883 884 return len; 885} 886 887/* 888 * Free all memory associated with the nodes and routes lists. 889 */ 890void __exit nr_rt_free(void) 891{ 892 struct nr_neigh *s, *nr_neigh = nr_neigh_list; 893 struct nr_node *t, *nr_node = nr_node_list; 894 895 while (nr_node != NULL) { 896 t = nr_node; 897 nr_node = nr_node->next; 898 899 nr_remove_node(t); 900 } 901 902 while (nr_neigh != NULL) { 903 s = nr_neigh; 904 nr_neigh = nr_neigh->next; 905 906 nr_remove_neigh(s); 907 } 908} 909