linux/net/lapb/lapb_iface.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *      LAPB release 002
   4 *
   5 *      This code REQUIRES 2.1.15 or higher/ NET3.038
   6 *
   7 *      History
   8 *      LAPB 001        Jonathan Naylor Started Coding
   9 *      LAPB 002        Jonathan Naylor New timer architecture.
  10 *      2000-10-29      Henner Eisen    lapb_data_indication() return status.
  11 */
  12
  13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  14
  15#include <linux/module.h>
  16#include <linux/errno.h>
  17#include <linux/types.h>
  18#include <linux/socket.h>
  19#include <linux/in.h>
  20#include <linux/kernel.h>
  21#include <linux/jiffies.h>
  22#include <linux/timer.h>
  23#include <linux/string.h>
  24#include <linux/sockios.h>
  25#include <linux/net.h>
  26#include <linux/inet.h>
  27#include <linux/if_arp.h>
  28#include <linux/skbuff.h>
  29#include <linux/slab.h>
  30#include <net/sock.h>
  31#include <linux/uaccess.h>
  32#include <linux/fcntl.h>
  33#include <linux/mm.h>
  34#include <linux/interrupt.h>
  35#include <linux/stat.h>
  36#include <linux/init.h>
  37#include <net/lapb.h>
  38
  39static LIST_HEAD(lapb_list);
  40static DEFINE_RWLOCK(lapb_list_lock);
  41
  42/*
  43 *      Free an allocated lapb control block.
  44 */
  45static void lapb_free_cb(struct lapb_cb *lapb)
  46{
  47        kfree(lapb);
  48}
  49
  50static __inline__ void lapb_hold(struct lapb_cb *lapb)
  51{
  52        refcount_inc(&lapb->refcnt);
  53}
  54
  55static __inline__ void lapb_put(struct lapb_cb *lapb)
  56{
  57        if (refcount_dec_and_test(&lapb->refcnt))
  58                lapb_free_cb(lapb);
  59}
  60
  61/*
  62 *      Socket removal during an interrupt is now safe.
  63 */
  64static void __lapb_remove_cb(struct lapb_cb *lapb)
  65{
  66        if (lapb->node.next) {
  67                list_del(&lapb->node);
  68                lapb_put(lapb);
  69        }
  70}
  71
  72/*
  73 *      Add a socket to the bound sockets list.
  74 */
  75static void __lapb_insert_cb(struct lapb_cb *lapb)
  76{
  77        list_add(&lapb->node, &lapb_list);
  78        lapb_hold(lapb);
  79}
  80
  81static struct lapb_cb *__lapb_devtostruct(struct net_device *dev)
  82{
  83        struct lapb_cb *lapb, *use = NULL;
  84
  85        list_for_each_entry(lapb, &lapb_list, node) {
  86                if (lapb->dev == dev) {
  87                        use = lapb;
  88                        break;
  89                }
  90        }
  91
  92        if (use)
  93                lapb_hold(use);
  94
  95        return use;
  96}
  97
  98static struct lapb_cb *lapb_devtostruct(struct net_device *dev)
  99{
 100        struct lapb_cb *rc;
 101
 102        read_lock_bh(&lapb_list_lock);
 103        rc = __lapb_devtostruct(dev);
 104        read_unlock_bh(&lapb_list_lock);
 105
 106        return rc;
 107}
 108/*
 109 *      Create an empty LAPB control block.
 110 */
 111static struct lapb_cb *lapb_create_cb(void)
 112{
 113        struct lapb_cb *lapb = kzalloc(sizeof(*lapb), GFP_ATOMIC);
 114
 115        if (!lapb)
 116                goto out;
 117
 118        skb_queue_head_init(&lapb->write_queue);
 119        skb_queue_head_init(&lapb->ack_queue);
 120
 121        timer_setup(&lapb->t1timer, NULL, 0);
 122        timer_setup(&lapb->t2timer, NULL, 0);
 123        lapb->t1timer_running = false;
 124        lapb->t2timer_running = false;
 125
 126        lapb->t1      = LAPB_DEFAULT_T1;
 127        lapb->t2      = LAPB_DEFAULT_T2;
 128        lapb->n2      = LAPB_DEFAULT_N2;
 129        lapb->mode    = LAPB_DEFAULT_MODE;
 130        lapb->window  = LAPB_DEFAULT_WINDOW;
 131        lapb->state   = LAPB_STATE_0;
 132
 133        spin_lock_init(&lapb->lock);
 134        refcount_set(&lapb->refcnt, 1);
 135out:
 136        return lapb;
 137}
 138
 139int lapb_register(struct net_device *dev,
 140                  const struct lapb_register_struct *callbacks)
 141{
 142        struct lapb_cb *lapb;
 143        int rc = LAPB_BADTOKEN;
 144
 145        write_lock_bh(&lapb_list_lock);
 146
 147        lapb = __lapb_devtostruct(dev);
 148        if (lapb) {
 149                lapb_put(lapb);
 150                goto out;
 151        }
 152
 153        lapb = lapb_create_cb();
 154        rc = LAPB_NOMEM;
 155        if (!lapb)
 156                goto out;
 157
 158        lapb->dev       = dev;
 159        lapb->callbacks = callbacks;
 160
 161        __lapb_insert_cb(lapb);
 162
 163        lapb_start_t1timer(lapb);
 164
 165        rc = LAPB_OK;
 166out:
 167        write_unlock_bh(&lapb_list_lock);
 168        return rc;
 169}
 170EXPORT_SYMBOL(lapb_register);
 171
 172int lapb_unregister(struct net_device *dev)
 173{
 174        struct lapb_cb *lapb;
 175        int rc = LAPB_BADTOKEN;
 176
 177        write_lock_bh(&lapb_list_lock);
 178        lapb = __lapb_devtostruct(dev);
 179        if (!lapb)
 180                goto out;
 181        lapb_put(lapb);
 182
 183        /* Wait for other refs to "lapb" to drop */
 184        while (refcount_read(&lapb->refcnt) > 2)
 185                usleep_range(1, 10);
 186
 187        spin_lock_bh(&lapb->lock);
 188
 189        lapb_stop_t1timer(lapb);
 190        lapb_stop_t2timer(lapb);
 191
 192        lapb_clear_queues(lapb);
 193
 194        spin_unlock_bh(&lapb->lock);
 195
 196        /* Wait for running timers to stop */
 197        del_timer_sync(&lapb->t1timer);
 198        del_timer_sync(&lapb->t2timer);
 199
 200        __lapb_remove_cb(lapb);
 201
 202        lapb_put(lapb);
 203        rc = LAPB_OK;
 204out:
 205        write_unlock_bh(&lapb_list_lock);
 206        return rc;
 207}
 208EXPORT_SYMBOL(lapb_unregister);
 209
 210int lapb_getparms(struct net_device *dev, struct lapb_parms_struct *parms)
 211{
 212        int rc = LAPB_BADTOKEN;
 213        struct lapb_cb *lapb = lapb_devtostruct(dev);
 214
 215        if (!lapb)
 216                goto out;
 217
 218        spin_lock_bh(&lapb->lock);
 219
 220        parms->t1      = lapb->t1 / HZ;
 221        parms->t2      = lapb->t2 / HZ;
 222        parms->n2      = lapb->n2;
 223        parms->n2count = lapb->n2count;
 224        parms->state   = lapb->state;
 225        parms->window  = lapb->window;
 226        parms->mode    = lapb->mode;
 227
 228        if (!timer_pending(&lapb->t1timer))
 229                parms->t1timer = 0;
 230        else
 231                parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ;
 232
 233        if (!timer_pending(&lapb->t2timer))
 234                parms->t2timer = 0;
 235        else
 236                parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ;
 237
 238        spin_unlock_bh(&lapb->lock);
 239        lapb_put(lapb);
 240        rc = LAPB_OK;
 241out:
 242        return rc;
 243}
 244EXPORT_SYMBOL(lapb_getparms);
 245
 246int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms)
 247{
 248        int rc = LAPB_BADTOKEN;
 249        struct lapb_cb *lapb = lapb_devtostruct(dev);
 250
 251        if (!lapb)
 252                goto out;
 253
 254        spin_lock_bh(&lapb->lock);
 255
 256        rc = LAPB_INVALUE;
 257        if (parms->t1 < 1 || parms->t2 < 1 || parms->n2 < 1)
 258                goto out_put;
 259
 260        if (lapb->state == LAPB_STATE_0) {
 261                if (parms->mode & LAPB_EXTENDED) {
 262                        if (parms->window < 1 || parms->window > 127)
 263                                goto out_put;
 264                } else {
 265                        if (parms->window < 1 || parms->window > 7)
 266                                goto out_put;
 267                }
 268                lapb->mode    = parms->mode;
 269                lapb->window  = parms->window;
 270        }
 271
 272        lapb->t1    = parms->t1 * HZ;
 273        lapb->t2    = parms->t2 * HZ;
 274        lapb->n2    = parms->n2;
 275
 276        rc = LAPB_OK;
 277out_put:
 278        spin_unlock_bh(&lapb->lock);
 279        lapb_put(lapb);
 280out:
 281        return rc;
 282}
 283EXPORT_SYMBOL(lapb_setparms);
 284
 285int lapb_connect_request(struct net_device *dev)
 286{
 287        struct lapb_cb *lapb = lapb_devtostruct(dev);
 288        int rc = LAPB_BADTOKEN;
 289
 290        if (!lapb)
 291                goto out;
 292
 293        spin_lock_bh(&lapb->lock);
 294
 295        rc = LAPB_OK;
 296        if (lapb->state == LAPB_STATE_1)
 297                goto out_put;
 298
 299        rc = LAPB_CONNECTED;
 300        if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4)
 301                goto out_put;
 302
 303        lapb_establish_data_link(lapb);
 304
 305        lapb_dbg(0, "(%p) S0 -> S1\n", lapb->dev);
 306        lapb->state = LAPB_STATE_1;
 307
 308        rc = LAPB_OK;
 309out_put:
 310        spin_unlock_bh(&lapb->lock);
 311        lapb_put(lapb);
 312out:
 313        return rc;
 314}
 315EXPORT_SYMBOL(lapb_connect_request);
 316
 317static int __lapb_disconnect_request(struct lapb_cb *lapb)
 318{
 319        switch (lapb->state) {
 320        case LAPB_STATE_0:
 321                return LAPB_NOTCONNECTED;
 322
 323        case LAPB_STATE_1:
 324                lapb_dbg(1, "(%p) S1 TX DISC(1)\n", lapb->dev);
 325                lapb_dbg(0, "(%p) S1 -> S0\n", lapb->dev);
 326                lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 327                lapb->state = LAPB_STATE_0;
 328                lapb_start_t1timer(lapb);
 329                return LAPB_NOTCONNECTED;
 330
 331        case LAPB_STATE_2:
 332                return LAPB_OK;
 333        }
 334
 335        lapb_clear_queues(lapb);
 336        lapb->n2count = 0;
 337        lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 338        lapb_start_t1timer(lapb);
 339        lapb_stop_t2timer(lapb);
 340        lapb->state = LAPB_STATE_2;
 341
 342        lapb_dbg(1, "(%p) S3 DISC(1)\n", lapb->dev);
 343        lapb_dbg(0, "(%p) S3 -> S2\n", lapb->dev);
 344
 345        return LAPB_OK;
 346}
 347
 348int lapb_disconnect_request(struct net_device *dev)
 349{
 350        struct lapb_cb *lapb = lapb_devtostruct(dev);
 351        int rc = LAPB_BADTOKEN;
 352
 353        if (!lapb)
 354                goto out;
 355
 356        spin_lock_bh(&lapb->lock);
 357
 358        rc = __lapb_disconnect_request(lapb);
 359
 360        spin_unlock_bh(&lapb->lock);
 361        lapb_put(lapb);
 362out:
 363        return rc;
 364}
 365EXPORT_SYMBOL(lapb_disconnect_request);
 366
 367int lapb_data_request(struct net_device *dev, struct sk_buff *skb)
 368{
 369        struct lapb_cb *lapb = lapb_devtostruct(dev);
 370        int rc = LAPB_BADTOKEN;
 371
 372        if (!lapb)
 373                goto out;
 374
 375        spin_lock_bh(&lapb->lock);
 376
 377        rc = LAPB_NOTCONNECTED;
 378        if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4)
 379                goto out_put;
 380
 381        skb_queue_tail(&lapb->write_queue, skb);
 382        lapb_kick(lapb);
 383        rc = LAPB_OK;
 384out_put:
 385        spin_unlock_bh(&lapb->lock);
 386        lapb_put(lapb);
 387out:
 388        return rc;
 389}
 390EXPORT_SYMBOL(lapb_data_request);
 391
 392int lapb_data_received(struct net_device *dev, struct sk_buff *skb)
 393{
 394        struct lapb_cb *lapb = lapb_devtostruct(dev);
 395        int rc = LAPB_BADTOKEN;
 396
 397        if (lapb) {
 398                spin_lock_bh(&lapb->lock);
 399                lapb_data_input(lapb, skb);
 400                spin_unlock_bh(&lapb->lock);
 401                lapb_put(lapb);
 402                rc = LAPB_OK;
 403        }
 404
 405        return rc;
 406}
 407EXPORT_SYMBOL(lapb_data_received);
 408
 409void lapb_connect_confirmation(struct lapb_cb *lapb, int reason)
 410{
 411        if (lapb->callbacks->connect_confirmation)
 412                lapb->callbacks->connect_confirmation(lapb->dev, reason);
 413}
 414
 415void lapb_connect_indication(struct lapb_cb *lapb, int reason)
 416{
 417        if (lapb->callbacks->connect_indication)
 418                lapb->callbacks->connect_indication(lapb->dev, reason);
 419}
 420
 421void lapb_disconnect_confirmation(struct lapb_cb *lapb, int reason)
 422{
 423        if (lapb->callbacks->disconnect_confirmation)
 424                lapb->callbacks->disconnect_confirmation(lapb->dev, reason);
 425}
 426
 427void lapb_disconnect_indication(struct lapb_cb *lapb, int reason)
 428{
 429        if (lapb->callbacks->disconnect_indication)
 430                lapb->callbacks->disconnect_indication(lapb->dev, reason);
 431}
 432
 433int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *skb)
 434{
 435        if (lapb->callbacks->data_indication)
 436                return lapb->callbacks->data_indication(lapb->dev, skb);
 437
 438        kfree_skb(skb);
 439        return NET_RX_SUCCESS; /* For now; must be != NET_RX_DROP */
 440}
 441
 442int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb)
 443{
 444        int used = 0;
 445
 446        if (lapb->callbacks->data_transmit) {
 447                lapb->callbacks->data_transmit(lapb->dev, skb);
 448                used = 1;
 449        }
 450
 451        return used;
 452}
 453
 454/* Handle device status changes. */
 455static int lapb_device_event(struct notifier_block *this, unsigned long event,
 456                             void *ptr)
 457{
 458        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 459        struct lapb_cb *lapb;
 460
 461        if (!net_eq(dev_net(dev), &init_net))
 462                return NOTIFY_DONE;
 463
 464        if (dev->type != ARPHRD_X25)
 465                return NOTIFY_DONE;
 466
 467        lapb = lapb_devtostruct(dev);
 468        if (!lapb)
 469                return NOTIFY_DONE;
 470
 471        spin_lock_bh(&lapb->lock);
 472
 473        switch (event) {
 474        case NETDEV_UP:
 475                lapb_dbg(0, "(%p) Interface up: %s\n", dev, dev->name);
 476
 477                if (netif_carrier_ok(dev)) {
 478                        lapb_dbg(0, "(%p): Carrier is already up: %s\n", dev,
 479                                 dev->name);
 480                        if (lapb->mode & LAPB_DCE) {
 481                                lapb_start_t1timer(lapb);
 482                        } else {
 483                                if (lapb->state == LAPB_STATE_0) {
 484                                        lapb->state = LAPB_STATE_1;
 485                                        lapb_establish_data_link(lapb);
 486                                }
 487                        }
 488                }
 489                break;
 490        case NETDEV_GOING_DOWN:
 491                if (netif_carrier_ok(dev))
 492                        __lapb_disconnect_request(lapb);
 493                break;
 494        case NETDEV_DOWN:
 495                lapb_dbg(0, "(%p) Interface down: %s\n", dev, dev->name);
 496                lapb_dbg(0, "(%p) S%d -> S0\n", dev, lapb->state);
 497                lapb_clear_queues(lapb);
 498                lapb->state = LAPB_STATE_0;
 499                lapb->n2count   = 0;
 500                lapb_stop_t1timer(lapb);
 501                lapb_stop_t2timer(lapb);
 502                break;
 503        case NETDEV_CHANGE:
 504                if (netif_carrier_ok(dev)) {
 505                        lapb_dbg(0, "(%p): Carrier detected: %s\n", dev,
 506                                 dev->name);
 507                        if (lapb->mode & LAPB_DCE) {
 508                                lapb_start_t1timer(lapb);
 509                        } else {
 510                                if (lapb->state == LAPB_STATE_0) {
 511                                        lapb->state = LAPB_STATE_1;
 512                                        lapb_establish_data_link(lapb);
 513                                }
 514                        }
 515                } else {
 516                        lapb_dbg(0, "(%p) Carrier lost: %s\n", dev, dev->name);
 517                        lapb_dbg(0, "(%p) S%d -> S0\n", dev, lapb->state);
 518                        lapb_clear_queues(lapb);
 519                        lapb->state = LAPB_STATE_0;
 520                        lapb->n2count   = 0;
 521                        lapb_stop_t1timer(lapb);
 522                        lapb_stop_t2timer(lapb);
 523                }
 524                break;
 525        }
 526
 527        spin_unlock_bh(&lapb->lock);
 528        lapb_put(lapb);
 529        return NOTIFY_DONE;
 530}
 531
 532static struct notifier_block lapb_dev_notifier = {
 533        .notifier_call = lapb_device_event,
 534};
 535
 536static int __init lapb_init(void)
 537{
 538        return register_netdevice_notifier(&lapb_dev_notifier);
 539}
 540
 541static void __exit lapb_exit(void)
 542{
 543        WARN_ON(!list_empty(&lapb_list));
 544
 545        unregister_netdevice_notifier(&lapb_dev_notifier);
 546}
 547
 548MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
 549MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
 550MODULE_LICENSE("GPL");
 551
 552module_init(lapb_init);
 553module_exit(lapb_exit);
 554