linux/net/netrom/nr_route.c
<<
>>
Prefs
   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 Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
   8 * Copyright Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
   9 * Copyright Tomi Manninen OH2BNS (oh2bns@sral.fi)
  10 */
  11#include <linux/errno.h>
  12#include <linux/types.h>
  13#include <linux/socket.h>
  14#include <linux/in.h>
  15#include <linux/kernel.h>
  16#include <linux/timer.h>
  17#include <linux/string.h>
  18#include <linux/sockios.h>
  19#include <linux/net.h>
  20#include <linux/slab.h>
  21#include <net/ax25.h>
  22#include <linux/inet.h>
  23#include <linux/netdevice.h>
  24#include <net/arp.h>
  25#include <linux/if_arp.h>
  26#include <linux/skbuff.h>
  27#include <net/sock.h>
  28#include <asm/uaccess.h>
  29#include <asm/system.h>
  30#include <linux/fcntl.h>
  31#include <linux/termios.h>      /* For TIOCINQ/OUTQ */
  32#include <linux/mm.h>
  33#include <linux/interrupt.h>
  34#include <linux/notifier.h>
  35#include <linux/netfilter.h>
  36#include <linux/init.h>
  37#include <linux/spinlock.h>
  38#include <net/netrom.h>
  39#include <linux/seq_file.h>
  40#include <linux/export.h>
  41
  42static unsigned int nr_neigh_no = 1;
  43
  44static HLIST_HEAD(nr_node_list);
  45static DEFINE_SPINLOCK(nr_node_list_lock);
  46static HLIST_HEAD(nr_neigh_list);
  47static DEFINE_SPINLOCK(nr_neigh_list_lock);
  48
  49static struct nr_node *nr_node_get(ax25_address *callsign)
  50{
  51        struct nr_node *found = NULL;
  52        struct nr_node *nr_node;
  53        struct hlist_node *node;
  54
  55        spin_lock_bh(&nr_node_list_lock);
  56        nr_node_for_each(nr_node, node, &nr_node_list)
  57                if (ax25cmp(callsign, &nr_node->callsign) == 0) {
  58                        nr_node_hold(nr_node);
  59                        found = nr_node;
  60                        break;
  61                }
  62        spin_unlock_bh(&nr_node_list_lock);
  63        return found;
  64}
  65
  66static struct nr_neigh *nr_neigh_get_dev(ax25_address *callsign,
  67                                         struct net_device *dev)
  68{
  69        struct nr_neigh *found = NULL;
  70        struct nr_neigh *nr_neigh;
  71        struct hlist_node *node;
  72
  73        spin_lock_bh(&nr_neigh_list_lock);
  74        nr_neigh_for_each(nr_neigh, node, &nr_neigh_list)
  75                if (ax25cmp(callsign, &nr_neigh->callsign) == 0 &&
  76                    nr_neigh->dev == dev) {
  77                        nr_neigh_hold(nr_neigh);
  78                        found = nr_neigh;
  79                        break;
  80                }
  81        spin_unlock_bh(&nr_neigh_list_lock);
  82        return found;
  83}
  84
  85static void nr_remove_neigh(struct nr_neigh *);
  86
  87/*
  88 *      Add a new route to a node, and in the process add the node and the
  89 *      neighbour if it is new.
  90 */
  91static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
  92        ax25_address *ax25, ax25_digi *ax25_digi, struct net_device *dev,
  93        int quality, int obs_count)
  94{
  95        struct nr_node  *nr_node;
  96        struct nr_neigh *nr_neigh;
  97        struct nr_route nr_route;
  98        int i, found;
  99        struct net_device *odev;
 100
 101        if ((odev=nr_dev_get(nr)) != NULL) {    /* Can't add routes to ourself */
 102                dev_put(odev);
 103                return -EINVAL;
 104        }
 105
 106        nr_node = nr_node_get(nr);
 107
 108        nr_neigh = nr_neigh_get_dev(ax25, dev);
 109
 110        /*
 111         * The L2 link to a neighbour has failed in the past
 112         * and now a frame comes from this neighbour. We assume
 113         * it was a temporary trouble with the link and reset the
 114         * routes now (and not wait for a node broadcast).
 115         */
 116        if (nr_neigh != NULL && nr_neigh->failed != 0 && quality == 0) {
 117                struct nr_node *nr_nodet;
 118                struct hlist_node *node;
 119
 120                spin_lock_bh(&nr_node_list_lock);
 121                nr_node_for_each(nr_nodet, node, &nr_node_list) {
 122                        nr_node_lock(nr_nodet);
 123                        for (i = 0; i < nr_nodet->count; i++)
 124                                if (nr_nodet->routes[i].neighbour == nr_neigh)
 125                                        if (i < nr_nodet->which)
 126                                                nr_nodet->which = i;
 127                        nr_node_unlock(nr_nodet);
 128                }
 129                spin_unlock_bh(&nr_node_list_lock);
 130        }
 131
 132        if (nr_neigh != NULL)
 133                nr_neigh->failed = 0;
 134
 135        if (quality == 0 && nr_neigh != NULL && nr_node != NULL) {
 136                nr_neigh_put(nr_neigh);
 137                nr_node_put(nr_node);
 138                return 0;
 139        }
 140
 141        if (nr_neigh == NULL) {
 142                if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL) {
 143                        if (nr_node)
 144                                nr_node_put(nr_node);
 145                        return -ENOMEM;
 146                }
 147
 148                nr_neigh->callsign = *ax25;
 149                nr_neigh->digipeat = NULL;
 150                nr_neigh->ax25     = NULL;
 151                nr_neigh->dev      = dev;
 152                nr_neigh->quality  = sysctl_netrom_default_path_quality;
 153                nr_neigh->locked   = 0;
 154                nr_neigh->count    = 0;
 155                nr_neigh->number   = nr_neigh_no++;
 156                nr_neigh->failed   = 0;
 157                atomic_set(&nr_neigh->refcount, 1);
 158
 159                if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
 160                        nr_neigh->digipeat = kmemdup(ax25_digi,
 161                                                     sizeof(*ax25_digi),
 162                                                     GFP_KERNEL);
 163                        if (nr_neigh->digipeat == NULL) {
 164                                kfree(nr_neigh);
 165                                if (nr_node)
 166                                        nr_node_put(nr_node);
 167                                return -ENOMEM;
 168                        }
 169                }
 170
 171                spin_lock_bh(&nr_neigh_list_lock);
 172                hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
 173                nr_neigh_hold(nr_neigh);
 174                spin_unlock_bh(&nr_neigh_list_lock);
 175        }
 176
 177        if (quality != 0 && ax25cmp(nr, ax25) == 0 && !nr_neigh->locked)
 178                nr_neigh->quality = quality;
 179
 180        if (nr_node == NULL) {
 181                if ((nr_node = kmalloc(sizeof(*nr_node), GFP_ATOMIC)) == NULL) {
 182                        if (nr_neigh)
 183                                nr_neigh_put(nr_neigh);
 184                        return -ENOMEM;
 185                }
 186
 187                nr_node->callsign = *nr;
 188                strcpy(nr_node->mnemonic, mnemonic);
 189
 190                nr_node->which = 0;
 191                nr_node->count = 1;
 192                atomic_set(&nr_node->refcount, 1);
 193                spin_lock_init(&nr_node->node_lock);
 194
 195                nr_node->routes[0].quality   = quality;
 196                nr_node->routes[0].obs_count = obs_count;
 197                nr_node->routes[0].neighbour = nr_neigh;
 198
 199                nr_neigh_hold(nr_neigh);
 200                nr_neigh->count++;
 201
 202                spin_lock_bh(&nr_node_list_lock);
 203                hlist_add_head(&nr_node->node_node, &nr_node_list);
 204                /* refcount initialized at 1 */
 205                spin_unlock_bh(&nr_node_list_lock);
 206
 207                return 0;
 208        }
 209        nr_node_lock(nr_node);
 210
 211        if (quality != 0)
 212                strcpy(nr_node->mnemonic, mnemonic);
 213
 214        for (found = 0, i = 0; i < nr_node->count; i++) {
 215                if (nr_node->routes[i].neighbour == nr_neigh) {
 216                        nr_node->routes[i].quality   = quality;
 217                        nr_node->routes[i].obs_count = obs_count;
 218                        found = 1;
 219                        break;
 220                }
 221        }
 222
 223        if (!found) {
 224                /* We have space at the bottom, slot it in */
 225                if (nr_node->count < 3) {
 226                        nr_node->routes[2] = nr_node->routes[1];
 227                        nr_node->routes[1] = nr_node->routes[0];
 228
 229                        nr_node->routes[0].quality   = quality;
 230                        nr_node->routes[0].obs_count = obs_count;
 231                        nr_node->routes[0].neighbour = nr_neigh;
 232
 233                        nr_node->which++;
 234                        nr_node->count++;
 235                        nr_neigh_hold(nr_neigh);
 236                        nr_neigh->count++;
 237                } else {
 238                        /* It must be better than the worst */
 239                        if (quality > nr_node->routes[2].quality) {
 240                                nr_node->routes[2].neighbour->count--;
 241                                nr_neigh_put(nr_node->routes[2].neighbour);
 242
 243                                if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked)
 244                                        nr_remove_neigh(nr_node->routes[2].neighbour);
 245
 246                                nr_node->routes[2].quality   = quality;
 247                                nr_node->routes[2].obs_count = obs_count;
 248                                nr_node->routes[2].neighbour = nr_neigh;
 249
 250                                nr_neigh_hold(nr_neigh);
 251                                nr_neigh->count++;
 252                        }
 253                }
 254        }
 255
 256        /* Now re-sort the routes in quality order */
 257        switch (nr_node->count) {
 258        case 3:
 259                if (nr_node->routes[1].quality > nr_node->routes[0].quality) {
 260                        switch (nr_node->which) {
 261                        case 0:
 262                                nr_node->which = 1;
 263                                break;
 264                        case 1:
 265                                nr_node->which = 0;
 266                                break;
 267                        }
 268                        nr_route           = nr_node->routes[0];
 269                        nr_node->routes[0] = nr_node->routes[1];
 270                        nr_node->routes[1] = nr_route;
 271                }
 272                if (nr_node->routes[2].quality > nr_node->routes[1].quality) {
 273                        switch (nr_node->which) {
 274                        case 1:  nr_node->which = 2;
 275                                break;
 276
 277                        case 2:  nr_node->which = 1;
 278                                break;
 279
 280                        default:
 281                                break;
 282                        }
 283                        nr_route           = nr_node->routes[1];
 284                        nr_node->routes[1] = nr_node->routes[2];
 285                        nr_node->routes[2] = nr_route;
 286                }
 287        case 2:
 288                if (nr_node->routes[1].quality > nr_node->routes[0].quality) {
 289                        switch (nr_node->which) {
 290                        case 0:  nr_node->which = 1;
 291                                break;
 292
 293                        case 1:  nr_node->which = 0;
 294                                break;
 295
 296                        default: break;
 297                        }
 298                        nr_route           = nr_node->routes[0];
 299                        nr_node->routes[0] = nr_node->routes[1];
 300                        nr_node->routes[1] = nr_route;
 301                        }
 302        case 1:
 303                break;
 304        }
 305
 306        for (i = 0; i < nr_node->count; i++) {
 307                if (nr_node->routes[i].neighbour == nr_neigh) {
 308                        if (i < nr_node->which)
 309                                nr_node->which = i;
 310                        break;
 311                }
 312        }
 313
 314        nr_neigh_put(nr_neigh);
 315        nr_node_unlock(nr_node);
 316        nr_node_put(nr_node);
 317        return 0;
 318}
 319
 320static inline void __nr_remove_node(struct nr_node *nr_node)
 321{
 322        hlist_del_init(&nr_node->node_node);
 323        nr_node_put(nr_node);
 324}
 325
 326#define nr_remove_node_locked(__node) \
 327        __nr_remove_node(__node)
 328
 329static void nr_remove_node(struct nr_node *nr_node)
 330{
 331        spin_lock_bh(&nr_node_list_lock);
 332        __nr_remove_node(nr_node);
 333        spin_unlock_bh(&nr_node_list_lock);
 334}
 335
 336static inline void __nr_remove_neigh(struct nr_neigh *nr_neigh)
 337{
 338        hlist_del_init(&nr_neigh->neigh_node);
 339        nr_neigh_put(nr_neigh);
 340}
 341
 342#define nr_remove_neigh_locked(__neigh) \
 343        __nr_remove_neigh(__neigh)
 344
 345static void nr_remove_neigh(struct nr_neigh *nr_neigh)
 346{
 347        spin_lock_bh(&nr_neigh_list_lock);
 348        __nr_remove_neigh(nr_neigh);
 349        spin_unlock_bh(&nr_neigh_list_lock);
 350}
 351
 352/*
 353 *      "Delete" a node. Strictly speaking remove a route to a node. The node
 354 *      is only deleted if no routes are left to it.
 355 */
 356static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct net_device *dev)
 357{
 358        struct nr_node  *nr_node;
 359        struct nr_neigh *nr_neigh;
 360        int i;
 361
 362        nr_node = nr_node_get(callsign);
 363
 364        if (nr_node == NULL)
 365                return -EINVAL;
 366
 367        nr_neigh = nr_neigh_get_dev(neighbour, dev);
 368
 369        if (nr_neigh == NULL) {
 370                nr_node_put(nr_node);
 371                return -EINVAL;
 372        }
 373
 374        nr_node_lock(nr_node);
 375        for (i = 0; i < nr_node->count; i++) {
 376                if (nr_node->routes[i].neighbour == nr_neigh) {
 377                        nr_neigh->count--;
 378                        nr_neigh_put(nr_neigh);
 379
 380                        if (nr_neigh->count == 0 && !nr_neigh->locked)
 381                                nr_remove_neigh(nr_neigh);
 382                        nr_neigh_put(nr_neigh);
 383
 384                        nr_node->count--;
 385
 386                        if (nr_node->count == 0) {
 387                                nr_remove_node(nr_node);
 388                        } else {
 389                                switch (i) {
 390                                case 0:
 391                                        nr_node->routes[0] = nr_node->routes[1];
 392                                case 1:
 393                                        nr_node->routes[1] = nr_node->routes[2];
 394                                case 2:
 395                                        break;
 396                                }
 397                                nr_node_put(nr_node);
 398                        }
 399                        nr_node_unlock(nr_node);
 400
 401                        return 0;
 402                }
 403        }
 404        nr_neigh_put(nr_neigh);
 405        nr_node_unlock(nr_node);
 406        nr_node_put(nr_node);
 407
 408        return -EINVAL;
 409}
 410
 411/*
 412 *      Lock a neighbour with a quality.
 413 */
 414static int __must_check nr_add_neigh(ax25_address *callsign,
 415        ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)
 416{
 417        struct nr_neigh *nr_neigh;
 418
 419        nr_neigh = nr_neigh_get_dev(callsign, dev);
 420        if (nr_neigh) {
 421                nr_neigh->quality = quality;
 422                nr_neigh->locked  = 1;
 423                nr_neigh_put(nr_neigh);
 424                return 0;
 425        }
 426
 427        if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
 428                return -ENOMEM;
 429
 430        nr_neigh->callsign = *callsign;
 431        nr_neigh->digipeat = NULL;
 432        nr_neigh->ax25     = NULL;
 433        nr_neigh->dev      = dev;
 434        nr_neigh->quality  = quality;
 435        nr_neigh->locked   = 1;
 436        nr_neigh->count    = 0;
 437        nr_neigh->number   = nr_neigh_no++;
 438        nr_neigh->failed   = 0;
 439        atomic_set(&nr_neigh->refcount, 1);
 440
 441        if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
 442                nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),
 443                                             GFP_KERNEL);
 444                if (nr_neigh->digipeat == NULL) {
 445                        kfree(nr_neigh);
 446                        return -ENOMEM;
 447                }
 448        }
 449
 450        spin_lock_bh(&nr_neigh_list_lock);
 451        hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
 452        /* refcount is initialized at 1 */
 453        spin_unlock_bh(&nr_neigh_list_lock);
 454
 455        return 0;
 456}
 457
 458/*
 459 *      "Delete" a neighbour. The neighbour is only removed if the number
 460 *      of nodes that may use it is zero.
 461 */
 462static int nr_del_neigh(ax25_address *callsign, struct net_device *dev, unsigned int quality)
 463{
 464        struct nr_neigh *nr_neigh;
 465
 466        nr_neigh = nr_neigh_get_dev(callsign, dev);
 467
 468        if (nr_neigh == NULL) return -EINVAL;
 469
 470        nr_neigh->quality = quality;
 471        nr_neigh->locked  = 0;
 472
 473        if (nr_neigh->count == 0)
 474                nr_remove_neigh(nr_neigh);
 475        nr_neigh_put(nr_neigh);
 476
 477        return 0;
 478}
 479
 480/*
 481 *      Decrement the obsolescence count by one. If a route is reduced to a
 482 *      count of zero, remove it. Also remove any unlocked neighbours with
 483 *      zero nodes routing via it.
 484 */
 485static int nr_dec_obs(void)
 486{
 487        struct nr_neigh *nr_neigh;
 488        struct nr_node  *s;
 489        struct hlist_node *node, *nodet;
 490        int i;
 491
 492        spin_lock_bh(&nr_node_list_lock);
 493        nr_node_for_each_safe(s, node, nodet, &nr_node_list) {
 494                nr_node_lock(s);
 495                for (i = 0; i < s->count; i++) {
 496                        switch (s->routes[i].obs_count) {
 497                        case 0:         /* A locked entry */
 498                                break;
 499
 500                        case 1:         /* From 1 -> 0 */
 501                                nr_neigh = s->routes[i].neighbour;
 502
 503                                nr_neigh->count--;
 504                                nr_neigh_put(nr_neigh);
 505
 506                                if (nr_neigh->count == 0 && !nr_neigh->locked)
 507                                        nr_remove_neigh(nr_neigh);
 508
 509                                s->count--;
 510
 511                                switch (i) {
 512                                case 0:
 513                                        s->routes[0] = s->routes[1];
 514                                        /* Fallthrough */
 515                                case 1:
 516                                        s->routes[1] = s->routes[2];
 517                                case 2:
 518                                        break;
 519                                }
 520                                break;
 521
 522                        default:
 523                                s->routes[i].obs_count--;
 524                                break;
 525
 526                        }
 527                }
 528
 529                if (s->count <= 0)
 530                        nr_remove_node_locked(s);
 531                nr_node_unlock(s);
 532        }
 533        spin_unlock_bh(&nr_node_list_lock);
 534
 535        return 0;
 536}
 537
 538/*
 539 *      A device has been removed. Remove its routes and neighbours.
 540 */
 541void nr_rt_device_down(struct net_device *dev)
 542{
 543        struct nr_neigh *s;
 544        struct hlist_node *node, *nodet, *node2, *node2t;
 545        struct nr_node  *t;
 546        int i;
 547
 548        spin_lock_bh(&nr_neigh_list_lock);
 549        nr_neigh_for_each_safe(s, node, nodet, &nr_neigh_list) {
 550                if (s->dev == dev) {
 551                        spin_lock_bh(&nr_node_list_lock);
 552                        nr_node_for_each_safe(t, node2, node2t, &nr_node_list) {
 553                                nr_node_lock(t);
 554                                for (i = 0; i < t->count; i++) {
 555                                        if (t->routes[i].neighbour == s) {
 556                                                t->count--;
 557
 558                                                switch (i) {
 559                                                case 0:
 560                                                        t->routes[0] = t->routes[1];
 561                                                case 1:
 562                                                        t->routes[1] = t->routes[2];
 563                                                case 2:
 564                                                        break;
 565                                                }
 566                                        }
 567                                }
 568
 569                                if (t->count <= 0)
 570                                        nr_remove_node_locked(t);
 571                                nr_node_unlock(t);
 572                        }
 573                        spin_unlock_bh(&nr_node_list_lock);
 574
 575                        nr_remove_neigh_locked(s);
 576                }
 577        }
 578        spin_unlock_bh(&nr_neigh_list_lock);
 579}
 580
 581/*
 582 *      Check that the device given is a valid AX.25 interface that is "up".
 583 *      Or a valid ethernet interface with an AX.25 callsign binding.
 584 */
 585static struct net_device *nr_ax25_dev_get(char *devname)
 586{
 587        struct net_device *dev;
 588
 589        if ((dev = dev_get_by_name(&init_net, devname)) == NULL)
 590                return NULL;
 591
 592        if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
 593                return dev;
 594
 595        dev_put(dev);
 596        return NULL;
 597}
 598
 599/*
 600 *      Find the first active NET/ROM device, usually "nr0".
 601 */
 602struct net_device *nr_dev_first(void)
 603{
 604        struct net_device *dev, *first = NULL;
 605
 606        rcu_read_lock();
 607        for_each_netdev_rcu(&init_net, dev) {
 608                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
 609                        if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
 610                                first = dev;
 611        }
 612        if (first)
 613                dev_hold(first);
 614        rcu_read_unlock();
 615
 616        return first;
 617}
 618
 619/*
 620 *      Find the NET/ROM device for the given callsign.
 621 */
 622struct net_device *nr_dev_get(ax25_address *addr)
 623{
 624        struct net_device *dev;
 625
 626        rcu_read_lock();
 627        for_each_netdev_rcu(&init_net, dev) {
 628                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM &&
 629                    ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
 630                        dev_hold(dev);
 631                        goto out;
 632                }
 633        }
 634        dev = NULL;
 635out:
 636        rcu_read_unlock();
 637        return dev;
 638}
 639
 640static ax25_digi *nr_call_to_digi(ax25_digi *digi, int ndigis,
 641        ax25_address *digipeaters)
 642{
 643        int i;
 644
 645        if (ndigis == 0)
 646                return NULL;
 647
 648        for (i = 0; i < ndigis; i++) {
 649                digi->calls[i]    = digipeaters[i];
 650                digi->repeated[i] = 0;
 651        }
 652
 653        digi->ndigi      = ndigis;
 654        digi->lastrepeat = -1;
 655
 656        return digi;
 657}
 658
 659/*
 660 *      Handle the ioctls that control the routing functions.
 661 */
 662int nr_rt_ioctl(unsigned int cmd, void __user *arg)
 663{
 664        struct nr_route_struct nr_route;
 665        struct net_device *dev;
 666        ax25_digi digi;
 667        int ret;
 668
 669        switch (cmd) {
 670        case SIOCADDRT:
 671                if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
 672                        return -EFAULT;
 673                if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
 674                        return -EINVAL;
 675                if (nr_route.ndigis < 0 || nr_route.ndigis > AX25_MAX_DIGIS) {
 676                        dev_put(dev);
 677                        return -EINVAL;
 678                }
 679                switch (nr_route.type) {
 680                case NETROM_NODE:
 681                        ret = nr_add_node(&nr_route.callsign,
 682                                nr_route.mnemonic,
 683                                &nr_route.neighbour,
 684                                nr_call_to_digi(&digi, nr_route.ndigis,
 685                                                nr_route.digipeaters),
 686                                dev, nr_route.quality,
 687                                nr_route.obs_count);
 688                        break;
 689                case NETROM_NEIGH:
 690                        ret = nr_add_neigh(&nr_route.callsign,
 691                                nr_call_to_digi(&digi, nr_route.ndigis,
 692                                                nr_route.digipeaters),
 693                                dev, nr_route.quality);
 694                        break;
 695                default:
 696                        ret = -EINVAL;
 697                }
 698                dev_put(dev);
 699                return ret;
 700
 701        case SIOCDELRT:
 702                if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
 703                        return -EFAULT;
 704                if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
 705                        return -EINVAL;
 706                switch (nr_route.type) {
 707                case NETROM_NODE:
 708                        ret = nr_del_node(&nr_route.callsign,
 709                                &nr_route.neighbour, dev);
 710                        break;
 711                case NETROM_NEIGH:
 712                        ret = nr_del_neigh(&nr_route.callsign,
 713                                dev, nr_route.quality);
 714                        break;
 715                default:
 716                        ret = -EINVAL;
 717                }
 718                dev_put(dev);
 719                return ret;
 720
 721        case SIOCNRDECOBS:
 722                return nr_dec_obs();
 723
 724        default:
 725                return -EINVAL;
 726        }
 727
 728        return 0;
 729}
 730
 731/*
 732 *      A level 2 link has timed out, therefore it appears to be a poor link,
 733 *      then don't use that neighbour until it is reset.
 734 */
 735void nr_link_failed(ax25_cb *ax25, int reason)
 736{
 737        struct nr_neigh *s, *nr_neigh = NULL;
 738        struct hlist_node *node;
 739        struct nr_node  *nr_node = NULL;
 740
 741        spin_lock_bh(&nr_neigh_list_lock);
 742        nr_neigh_for_each(s, node, &nr_neigh_list) {
 743                if (s->ax25 == ax25) {
 744                        nr_neigh_hold(s);
 745                        nr_neigh = s;
 746                        break;
 747                }
 748        }
 749        spin_unlock_bh(&nr_neigh_list_lock);
 750
 751        if (nr_neigh == NULL)
 752                return;
 753
 754        nr_neigh->ax25 = NULL;
 755        ax25_cb_put(ax25);
 756
 757        if (++nr_neigh->failed < sysctl_netrom_link_fails_count) {
 758                nr_neigh_put(nr_neigh);
 759                return;
 760        }
 761        spin_lock_bh(&nr_node_list_lock);
 762        nr_node_for_each(nr_node, node, &nr_node_list) {
 763                nr_node_lock(nr_node);
 764                if (nr_node->which < nr_node->count &&
 765                    nr_node->routes[nr_node->which].neighbour == nr_neigh)
 766                        nr_node->which++;
 767                nr_node_unlock(nr_node);
 768        }
 769        spin_unlock_bh(&nr_node_list_lock);
 770        nr_neigh_put(nr_neigh);
 771}
 772
 773/*
 774 *      Route a frame to an appropriate AX.25 connection. A NULL ax25_cb
 775 *      indicates an internally generated frame.
 776 */
 777int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 778{
 779        ax25_address *nr_src, *nr_dest;
 780        struct nr_neigh *nr_neigh;
 781        struct nr_node  *nr_node;
 782        struct net_device *dev;
 783        unsigned char *dptr;
 784        ax25_cb *ax25s;
 785        int ret;
 786        struct sk_buff *skbn;
 787
 788
 789        nr_src  = (ax25_address *)(skb->data + 0);
 790        nr_dest = (ax25_address *)(skb->data + 7);
 791
 792        if (ax25 != NULL) {
 793                ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
 794                                  ax25->ax25_dev->dev, 0,
 795                                  sysctl_netrom_obsolescence_count_initialiser);
 796                if (ret)
 797                        return ret;
 798        }
 799
 800        if ((dev = nr_dev_get(nr_dest)) != NULL) {      /* Its for me */
 801                if (ax25 == NULL)                       /* Its from me */
 802                        ret = nr_loopback_queue(skb);
 803                else
 804                        ret = nr_rx_frame(skb, dev);
 805                dev_put(dev);
 806                return ret;
 807        }
 808
 809        if (!sysctl_netrom_routing_control && ax25 != NULL)
 810                return 0;
 811
 812        /* Its Time-To-Live has expired */
 813        if (skb->data[14] == 1) {
 814                return 0;
 815        }
 816
 817        nr_node = nr_node_get(nr_dest);
 818        if (nr_node == NULL)
 819                return 0;
 820        nr_node_lock(nr_node);
 821
 822        if (nr_node->which >= nr_node->count) {
 823                nr_node_unlock(nr_node);
 824                nr_node_put(nr_node);
 825                return 0;
 826        }
 827
 828        nr_neigh = nr_node->routes[nr_node->which].neighbour;
 829
 830        if ((dev = nr_dev_first()) == NULL) {
 831                nr_node_unlock(nr_node);
 832                nr_node_put(nr_node);
 833                return 0;
 834        }
 835
 836        /* We are going to change the netrom headers so we should get our
 837           own skb, we also did not know until now how much header space
 838           we had to reserve... - RXQ */
 839        if ((skbn=skb_copy_expand(skb, dev->hard_header_len, 0, GFP_ATOMIC)) == NULL) {
 840                nr_node_unlock(nr_node);
 841                nr_node_put(nr_node);
 842                dev_put(dev);
 843                return 0;
 844        }
 845        kfree_skb(skb);
 846        skb=skbn;
 847        skb->data[14]--;
 848
 849        dptr  = skb_push(skb, 1);
 850        *dptr = AX25_P_NETROM;
 851
 852        ax25s = nr_neigh->ax25;
 853        nr_neigh->ax25 = ax25_send_frame(skb, 256,
 854                                         (ax25_address *)dev->dev_addr,
 855                                         &nr_neigh->callsign,
 856                                         nr_neigh->digipeat, nr_neigh->dev);
 857        if (ax25s)
 858                ax25_cb_put(ax25s);
 859
 860        dev_put(dev);
 861        ret = (nr_neigh->ax25 != NULL);
 862        nr_node_unlock(nr_node);
 863        nr_node_put(nr_node);
 864
 865        return ret;
 866}
 867
 868#ifdef CONFIG_PROC_FS
 869
 870static void *nr_node_start(struct seq_file *seq, loff_t *pos)
 871{
 872        spin_lock_bh(&nr_node_list_lock);
 873        return seq_hlist_start_head(&nr_node_list, *pos);
 874}
 875
 876static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos)
 877{
 878        return seq_hlist_next(v, &nr_node_list, pos);
 879}
 880
 881static void nr_node_stop(struct seq_file *seq, void *v)
 882{
 883        spin_unlock_bh(&nr_node_list_lock);
 884}
 885
 886static int nr_node_show(struct seq_file *seq, void *v)
 887{
 888        char buf[11];
 889        int i;
 890
 891        if (v == SEQ_START_TOKEN)
 892                seq_puts(seq,
 893                         "callsign  mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");
 894        else {
 895                struct nr_node *nr_node = hlist_entry(v, struct nr_node,
 896                                                      node_node);
 897
 898                nr_node_lock(nr_node);
 899                seq_printf(seq, "%-9s %-7s  %d %d",
 900                        ax2asc(buf, &nr_node->callsign),
 901                        (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
 902                        nr_node->which + 1,
 903                        nr_node->count);
 904
 905                for (i = 0; i < nr_node->count; i++) {
 906                        seq_printf(seq, "  %3d   %d %05d",
 907                                nr_node->routes[i].quality,
 908                                nr_node->routes[i].obs_count,
 909                                nr_node->routes[i].neighbour->number);
 910                }
 911                nr_node_unlock(nr_node);
 912
 913                seq_puts(seq, "\n");
 914        }
 915        return 0;
 916}
 917
 918static const struct seq_operations nr_node_seqops = {
 919        .start = nr_node_start,
 920        .next = nr_node_next,
 921        .stop = nr_node_stop,
 922        .show = nr_node_show,
 923};
 924
 925static int nr_node_info_open(struct inode *inode, struct file *file)
 926{
 927        return seq_open(file, &nr_node_seqops);
 928}
 929
 930const struct file_operations nr_nodes_fops = {
 931        .owner = THIS_MODULE,
 932        .open = nr_node_info_open,
 933        .read = seq_read,
 934        .llseek = seq_lseek,
 935        .release = seq_release,
 936};
 937
 938static void *nr_neigh_start(struct seq_file *seq, loff_t *pos)
 939{
 940        spin_lock_bh(&nr_neigh_list_lock);
 941        return seq_hlist_start_head(&nr_neigh_list, *pos);
 942}
 943
 944static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos)
 945{
 946        return seq_hlist_next(v, &nr_neigh_list, pos);
 947}
 948
 949static void nr_neigh_stop(struct seq_file *seq, void *v)
 950{
 951        spin_unlock_bh(&nr_neigh_list_lock);
 952}
 953
 954static int nr_neigh_show(struct seq_file *seq, void *v)
 955{
 956        char buf[11];
 957        int i;
 958
 959        if (v == SEQ_START_TOKEN)
 960                seq_puts(seq, "addr  callsign  dev  qual lock count failed digipeaters\n");
 961        else {
 962                struct nr_neigh *nr_neigh;
 963
 964                nr_neigh = hlist_entry(v, struct nr_neigh, neigh_node);
 965                seq_printf(seq, "%05d %-9s %-4s  %3d    %d   %3d    %3d",
 966                        nr_neigh->number,
 967                        ax2asc(buf, &nr_neigh->callsign),
 968                        nr_neigh->dev ? nr_neigh->dev->name : "???",
 969                        nr_neigh->quality,
 970                        nr_neigh->locked,
 971                        nr_neigh->count,
 972                        nr_neigh->failed);
 973
 974                if (nr_neigh->digipeat != NULL) {
 975                        for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
 976                                seq_printf(seq, " %s",
 977                                           ax2asc(buf, &nr_neigh->digipeat->calls[i]));
 978                }
 979
 980                seq_puts(seq, "\n");
 981        }
 982        return 0;
 983}
 984
 985static const struct seq_operations nr_neigh_seqops = {
 986        .start = nr_neigh_start,
 987        .next = nr_neigh_next,
 988        .stop = nr_neigh_stop,
 989        .show = nr_neigh_show,
 990};
 991
 992static int nr_neigh_info_open(struct inode *inode, struct file *file)
 993{
 994        return seq_open(file, &nr_neigh_seqops);
 995}
 996
 997const struct file_operations nr_neigh_fops = {
 998        .owner = THIS_MODULE,
 999        .open = nr_neigh_info_open,
1000        .read = seq_read,
1001        .llseek = seq_lseek,
1002        .release = seq_release,
1003};
1004
1005#endif
1006
1007/*
1008 *      Free all memory associated with the nodes and routes lists.
1009 */
1010void __exit nr_rt_free(void)
1011{
1012        struct nr_neigh *s = NULL;
1013        struct nr_node  *t = NULL;
1014        struct hlist_node *node, *nodet;
1015
1016        spin_lock_bh(&nr_neigh_list_lock);
1017        spin_lock_bh(&nr_node_list_lock);
1018        nr_node_for_each_safe(t, node, nodet, &nr_node_list) {
1019                nr_node_lock(t);
1020                nr_remove_node_locked(t);
1021                nr_node_unlock(t);
1022        }
1023        nr_neigh_for_each_safe(s, node, nodet, &nr_neigh_list) {
1024                while(s->count) {
1025                        s->count--;
1026                        nr_neigh_put(s);
1027                }
1028                nr_remove_neigh_locked(s);
1029        }
1030        spin_unlock_bh(&nr_node_list_lock);
1031        spin_unlock_bh(&nr_neigh_list_lock);
1032}
1033
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.