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