linux/net/lapb/lapb_iface.c
<<
>>
Prefs
   1/*
   2 *      LAPB release 002
   3 *
   4 *      This code REQUIRES 2.1.15 or higher/ NET3.038
   5 *
   6 *      This module:
   7 *              This module is free software; you can redistribute it and/or
   8 *              modify it under the terms of the GNU General Public License
   9 *              as published by the Free Software Foundation; either version
  10 *              2 of the License, or (at your option) any later version.
  11 *
  12 *      History
  13 *      LAPB 001        Jonathan Naylor Started Coding
  14 *      LAPB 002        Jonathan Naylor New timer architecture.
  15 *      2000-10-29      Henner Eisen    lapb_data_indication() return status.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/errno.h>
  20#include <linux/types.h>
  21#include <linux/socket.h>
  22#include <linux/in.h>
  23#include <linux/kernel.h>
  24#include <linux/jiffies.h>
  25#include <linux/timer.h>
  26#include <linux/string.h>
  27#include <linux/sockios.h>
  28#include <linux/net.h>
  29#include <linux/inet.h>
  30#include <linux/if_arp.h>
  31#include <linux/skbuff.h>
  32#include <net/sock.h>
  33#include <asm/uaccess.h>
  34#include <asm/system.h>
  35#include <linux/fcntl.h>
  36#include <linux/mm.h>
  37#include <linux/interrupt.h>
  38#include <linux/stat.h>
  39#include <linux/init.h>
  40#include <net/lapb.h>
  41
  42static LIST_HEAD(lapb_list);
  43static DEFINE_RWLOCK(lapb_list_lock);
  44
  45/*
  46 *      Free an allocated lapb control block.
  47 */
  48static void lapb_free_cb(struct lapb_cb *lapb)
  49{
  50        kfree(lapb);
  51}
  52
  53static __inline__ void lapb_hold(struct lapb_cb *lapb)
  54{
  55        atomic_inc(&lapb->refcnt);
  56}
  57
  58static __inline__ void lapb_put(struct lapb_cb *lapb)
  59{
  60        if (atomic_dec_and_test(&lapb->refcnt))
  61                lapb_free_cb(lapb);
  62}
  63
  64/*
  65 *      Socket removal during an interrupt is now safe.
  66 */
  67static void __lapb_remove_cb(struct lapb_cb *lapb)
  68{
  69        if (lapb->node.next) {
  70                list_del(&lapb->node);
  71                lapb_put(lapb);
  72        }
  73}
  74
  75/*
  76 *      Add a socket to the bound sockets list.
  77 */
  78static void __lapb_insert_cb(struct lapb_cb *lapb)
  79{
  80        list_add(&lapb->node, &lapb_list);
  81        lapb_hold(lapb);
  82}
  83
  84static struct lapb_cb *__lapb_devtostruct(struct net_device *dev)
  85{
  86        struct list_head *entry;
  87        struct lapb_cb *lapb, *use = NULL;
  88
  89        list_for_each(entry, &lapb_list) {
  90                lapb = list_entry(entry, struct lapb_cb, node);
  91                if (lapb->dev == dev) {
  92                        use = lapb;
  93                        break;
  94                }
  95        }
  96
  97        if (use)
  98                lapb_hold(use);
  99
 100        return use;
 101}
 102
 103static struct lapb_cb *lapb_devtostruct(struct net_device *dev)
 104{
 105        struct lapb_cb *rc;
 106
 107        read_lock_bh(&lapb_list_lock);
 108        rc = __lapb_devtostruct(dev);
 109        read_unlock_bh(&lapb_list_lock);
 110
 111        return rc;
 112}
 113/*
 114 *      Create an empty LAPB control block.
 115 */
 116static struct lapb_cb *lapb_create_cb(void)
 117{
 118        struct lapb_cb *lapb = kzalloc(sizeof(*lapb), GFP_ATOMIC);
 119
 120
 121        if (!lapb)
 122                goto out;
 123
 124        skb_queue_head_init(&lapb->write_queue);
 125        skb_queue_head_init(&lapb->ack_queue);
 126
 127        init_timer(&lapb->t1timer);
 128        init_timer(&lapb->t2timer);
 129
 130        lapb->t1      = LAPB_DEFAULT_T1;
 131        lapb->t2      = LAPB_DEFAULT_T2;
 132        lapb->n2      = LAPB_DEFAULT_N2;
 133        lapb->mode    = LAPB_DEFAULT_MODE;
 134        lapb->window  = LAPB_DEFAULT_WINDOW;
 135        lapb->state   = LAPB_STATE_0;
 136        atomic_set(&lapb->refcnt, 1);
 137out:
 138        return lapb;
 139}
 140
 141int lapb_register(struct net_device *dev, struct lapb_register_struct *callbacks)
 142{
 143        struct lapb_cb *lapb;
 144        int rc = LAPB_BADTOKEN;
 145
 146        write_lock_bh(&lapb_list_lock);
 147
 148        lapb = __lapb_devtostruct(dev);
 149        if (lapb) {
 150                lapb_put(lapb);
 151                goto out;
 152        }
 153
 154        lapb = lapb_create_cb();
 155        rc = LAPB_NOMEM;
 156        if (!lapb)
 157                goto out;
 158
 159        lapb->dev       = dev;
 160        lapb->callbacks = *callbacks;
 161
 162        __lapb_insert_cb(lapb);
 163
 164        lapb_start_t1timer(lapb);
 165
 166        rc = LAPB_OK;
 167out:
 168        write_unlock_bh(&lapb_list_lock);
 169        return rc;
 170}
 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
 182        lapb_stop_t1timer(lapb);
 183        lapb_stop_t2timer(lapb);
 184
 185        lapb_clear_queues(lapb);
 186
 187        __lapb_remove_cb(lapb);
 188
 189        lapb_put(lapb);
 190        rc = LAPB_OK;
 191out:
 192        write_unlock_bh(&lapb_list_lock);
 193        return rc;
 194}
 195
 196int lapb_getparms(struct net_device *dev, struct lapb_parms_struct *parms)
 197{
 198        int rc = LAPB_BADTOKEN;
 199        struct lapb_cb *lapb = lapb_devtostruct(dev);
 200
 201        if (!lapb)
 202                goto out;
 203
 204        parms->t1      = lapb->t1 / HZ;
 205        parms->t2      = lapb->t2 / HZ;
 206        parms->n2      = lapb->n2;
 207        parms->n2count = lapb->n2count;
 208        parms->state   = lapb->state;
 209        parms->window  = lapb->window;
 210        parms->mode    = lapb->mode;
 211
 212        if (!timer_pending(&lapb->t1timer))
 213                parms->t1timer = 0;
 214        else
 215                parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ;
 216
 217        if (!timer_pending(&lapb->t2timer))
 218                parms->t2timer = 0;
 219        else
 220                parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ;
 221
 222        lapb_put(lapb);
 223        rc = LAPB_OK;
 224out:
 225        return rc;
 226}
 227
 228int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms)
 229{
 230        int rc = LAPB_BADTOKEN;
 231        struct lapb_cb *lapb = lapb_devtostruct(dev);
 232
 233        if (!lapb)
 234                goto out;
 235
 236        rc = LAPB_INVALUE;
 237        if (parms->t1 < 1 || parms->t2 < 1 || parms->n2 < 1)
 238                goto out_put;
 239
 240        if (lapb->state == LAPB_STATE_0) {
 241                if (parms->mode & LAPB_EXTENDED) {
 242                        if (parms->window < 1 || parms->window > 127)
 243                                goto out_put;
 244                } else {
 245                        if (parms->window < 1 || parms->window > 7)
 246                                goto out_put;
 247                }
 248                lapb->mode    = parms->mode;
 249                lapb->window  = parms->window;
 250        }
 251
 252        lapb->t1    = parms->t1 * HZ;
 253        lapb->t2    = parms->t2 * HZ;
 254        lapb->n2    = parms->n2;
 255
 256        rc = LAPB_OK;
 257out_put:
 258        lapb_put(lapb);
 259out:
 260        return rc;
 261}
 262
 263int lapb_connect_request(struct net_device *dev)
 264{
 265        struct lapb_cb *lapb = lapb_devtostruct(dev);
 266        int rc = LAPB_BADTOKEN;
 267
 268        if (!lapb)
 269                goto out;
 270
 271        rc = LAPB_OK;
 272        if (lapb->state == LAPB_STATE_1)
 273                goto out_put;
 274
 275        rc = LAPB_CONNECTED;
 276        if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4)
 277                goto out_put;
 278
 279        lapb_establish_data_link(lapb);
 280
 281#if LAPB_DEBUG > 0
 282        printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->dev);
 283#endif
 284        lapb->state = LAPB_STATE_1;
 285
 286        rc = LAPB_OK;
 287out_put:
 288        lapb_put(lapb);
 289out:
 290        return rc;
 291}
 292
 293int lapb_disconnect_request(struct net_device *dev)
 294{
 295        struct lapb_cb *lapb = lapb_devtostruct(dev);
 296        int rc = LAPB_BADTOKEN;
 297
 298        if (!lapb)
 299                goto out;
 300
 301        switch (lapb->state) {
 302                case LAPB_STATE_0:
 303                        rc = LAPB_NOTCONNECTED;
 304                        goto out_put;
 305
 306                case LAPB_STATE_1:
 307#if LAPB_DEBUG > 1
 308                        printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev);
 309#endif
 310#if LAPB_DEBUG > 0
 311                        printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
 312#endif
 313                        lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 314                        lapb->state = LAPB_STATE_0;
 315                        lapb_start_t1timer(lapb);
 316                        rc = LAPB_NOTCONNECTED;
 317                        goto out_put;
 319                case LAPB_STATE_2:
 320                        rc = LAPB_OK;
 321                        goto out_put;
 322        }
 323
 324        lapb_clear_queues(lapb);
 325        lapb->n2count = 0;
 326        lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 327        lapb_start_t1timer(lapb);
 328        lapb_stop_t2timer(lapb);
 329        lapb->state = LAPB_STATE_2;
 330
 331#if LAPB_DEBUG > 1
 332        printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->dev);
 333#endif
 334#if LAPB_DEBUG > 0
 335        LAPB_DEBUG > 1
 332        LAPB_OK;
 321    U class="line" name="L321"> 321   ace.class="line" na3ref="+t/lapb/lapb_iface.c#L334" id="L334" class="line" name="L237"> 237     3  if 33/lapb/lapb_iface.c#L298" id="L298" cla3s="line" 3ame="L238"> 238     3     33ef="+code=lapb_stop_t2timer"c = LAPB_OK;
 239
out>out_put:
 240     3  if 34ef="+code=lapb" class="sref">lap>lapb_put(lapb);
 241     3     34e=out" class="sref">out:
 242     3     3            ifode=rc" class="sref">rc;
 243     3     3      b/lapb_iface.c#L323" id="L323" class="line" 3ame="L244"> 244     3     34/lapb/lapb_iface.c#L275" id="L275" cla3s="line" 3ame="L245"> 245     3     3      =lapb_disconnect_request"ef="ef">lapb_disconnect_requestlape=lapode=net_device" class="sref">net_device *dev, struct  = skpb);
 246     3     3      b/lapb_iface.c#L302" id="L302" class="line" 3ame="L247"> 247     3     3    }
lapb_cb *lapb = lapb_devtostruct(dev);
 248     3     34a href="+code=rc" class="sref">rc = LAPB_BADTOKEN;
 249     3     34/lapb/lapb_iface.c#L240" id="L240" cla3s="line" 3ame="L250"> 250     3  }
<35a href="+code=lappb" class="sref">lapb)
 251
out;
 252     3   253     3   = LAPB_NOTCONNECTED;
 254     3  lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4)
 255
out_put;
 256     3   257lapb->->(&="+code=LAPB_COMMAND" classkpb);
 258     3  kiapb_list_lock);
lapb);
 259 = LAPB_OK;
 260     3  ret3rn out>out_put:
 261}
r>lap>lapb_put(lapb);
 262
out:
 263int <3 href36n rc;
 264{
 265     3  str36/lapb/lapb_iface.c#L306" id="L306" class="line" 3ame="L266"> 266     3  int36+code=lapb_getparms" class="snet_device *dev, struct  = skpb);
 267
 268     3  if 3!lapb_cb *lapb = lapb_devtostruct(dev);
 269     3     3    goto rc = LAPB_BADTOKEN;
 270
 271     3  lapb);
 272     3  if 3r>lap>(lapb,  273     3     3    goto r>lap>lapb_put(lapb);
 274
 = LAPB_OK;
 275     3   276     3  if 37/lapb/lapb_iface.c#L217" id="L217" cla3s="line" 3ame="L277"> 277     3     3    goto rc;
 278
 279     3   280
lapb_cb *lapb = rceasonb_cb * 281#if <3 href3"+codeb/lapb_iface.c#L302" id="L302" class="line" 3ame="L282"> 282     3  lapb-> * 283#endi3
r>lapb-> *lapb->rceasonb_cb * 284     3   285
 286     3  lapb_cb *lapb = rceasonb_cb * 287 288     3  r>lapb-> * 289lapb-> *lapb->rceasonb_cb * 290     3  ret3rn  291}
 292
(structlasfirmationb_cb *lapb_cb *lapb = rceasonb_cb * 293int <3 href3"+codeb/lapb_iface.c#L198" id="L198" cla3s="line" 3ame="L294"> 294{
lapb-> 295     3  str39           lapb->lapb->rceasonb_cb * 296     3  int39t/lapb/lapb_iface.c#L227" id="L227" cla3s="line" 3ame="L297"> 297
 298     3  if 3!(structindicationb_cb *lapb_cb *lapb = rceasonb_cb * 299     3     39t/lapb/lapb_iface.c#L230" id="L230" cla4s="line" 4ame="L300"> 300
lapb-> 291}
lapb->lapb->rceasonb_cb * 302     4     4    cab/lapb_iface.c#L227" id="L227" cla4s="line" 4ame="L303"> 303     4     40/lapb/lapb_iface.c#L324" id="L324" cla4s="line" 4ame="L304"> 304     4     4      =lapb_getparms" class="s *lapb_cb *lapb =  = skpb);
 305
 296     4     40a href="+code=lapb" class="sref">lapb-> * 297
r>lapb-> *lapb->rskpb);
 308     4     40/lapb/lapb_iface.c#L319" id="L319" cla4s="line" 4ame="L309"> 309#endi4
);
);
 310#if <4 href41n rNET_RX_CN_HIGHb);
        /* For now; must be=!APNET_RX_DROP */_OK" cl/lapb_iface.c#L322" id="L322" cla4s1"line" 4ame="L311"> 311     4     41t/lapb/lapb_iface.c#L292" id="L292" cla4s="line" 4ame="L312"> 312#endi4
 313     4     41+code=lapb_disconnect_request"ef="transmipb_put(lapb_cb *lapb =  = skpb);
 314     4     41t/lapb/lapb_iface.c#L295" id="L295" cla4s="line" 4ame="L315"> 315     4     4             316     4     41/lapb/lapb_iface.c#L217" id="L217" cla4s="line" 4ame="L317"> 317     4     4            go=lapb" class="sref">lapb->(lapb->(lapb->rskpb);
 319     4     4    case  320     4     42href="net/lapb/lapb_iface.c#L251" id="L251" cla4s="line" 4ame="L321"> 321     4     42/lapb/lapb_iface.c#L252" id="L252" cla4s="line" 4ame="L322"> 322     4  }
<4 href="net/lapode=rc" class="sref">rusedb_disconnect_reusedode=b/lapb_iface.c#L322" id="L322" cla4s="line" 4ame="L323"> 323
 324     4   325     4  rEXPORT_SYMBOLb_disconnect_reEXPORT_SYMBOLe=lapb" class="sref">lap_registapb_stop_t2timer( 326     4  rEXPORT_SYMBOLb_disconnect_reEXPORT_SYMBOLe=lapb" class="sref">lap_unregistapb_stop_t2timer( 327     4  lap_get">parms->lap_get">par/lapbb/lapb_iface.c#L322" id="L322" cla4s="line" 4ame="L328"> 328     4  lap_set">parms->lap_set">par/lapbb/lapb_iface.c#L322" id="L322" cla4s="line" 4ame="L329"> 329     4  EXPORT_SYMBOLb_disconnect_reEXPORT_SYMBOLe=lapb" class="sref">lap_lass="sref">lapb_connect_request(struct  330
EXPORT_SYMBOLb_disconnect_reEXPORT_SYMBOLe=lapb" class="sref">lap_" class="sref">lapb_disconnect_request(struct  331#if <4 href43e=out" class="sref">EXPORT_SYMBOLb_disconnect_reEXPORT_SYMBOLe=lapb" class="sref">lap_"ef="ef">lapb_disconnect_requestlape=labb/lapb_iface.c#L322" id="L322" cla4s="line" 4ame="L332"> 332     4  EXPORT_SYMBOLb_disconnect_reEXPORT_SYMBOLe=lapb" class="sref">lap_"ef="efceivedb_disconnect_request 333#endi4
 334#if <4 href4"+codeef="ica=lapb_disconnect_re__inipb_put(lap_inipb_put(lap_inipe=lapvoidb/lapb_iface.c#L299" id="L299" cla4s="line" 4ame="L335"> 335     4     ace.class="li4e" na43a href="+codeode=rc"pb/lapb_iface.c#L326" id="L326" cla4s="line" 4ame="L237"> 237     4  if 43/lapbb/lapb_iface.c#L323" id="L323" cla4s="line" 4ame="L238"> 238     4     43/lapb/lapb_iface.c#L319" id="L319" cla4s="line" 4ame="L239"> 239
(lap_exipb_put(lap_exipe=lapvoidb/lapb_iface.c#L299" id="L299" cla4s="line" 4ame="L240"> 240     4  if 44ef="+b/lapb_iface.c#L230" id="L230" cla4s="line" 4ame="L241"> 241     4     44ef="+code=rc" class="sref">rWARN_APB_POLLON, ist_emptyb_put(ist_emptye=lape=lapb" class="sref">lap_>istb_put(lap_>iste=labbb/lapb_iface.c#L322" id="L322" cla4s="line" 4ame="L242"> 242     4     44   cab/lapb_iface.c#L227" id="L227" cla4s="line" 4ame="L243"> 243     4     44/lapb/lapb_iface.c#L324" id="L324" cla4s="line" 4ame="L244"> 244     4     44/lapbb" class="sref"MODULE_AUTHORb_put( 245     4     44ef="+ class="sref">rMODULE_DESCRIPTIAPB_POLLON,  246     4     44ef="+ class="sref">rMODULE_LICENSEB_POLLON,  247     4     44/lapb/lapb_iface.c#L298" id="L298" cla4s="line" 4ame="L248"> 248     4     44ef="+_put" class="srmodule_inipb_put(lap_inipb_put(lap_inipe=labb/lapb_iface.c#L322" id="L322" cla4s="line" 4ame="L249"> 249     4     44e=out" class="sref">module_exipb_put(lap_exipb_put(lap_exipe=labb/lapb_iface.c#L322" id="L322" cla4s="line" 4ame="L250"> 250     4  }
<45a hre


footapb> The original LXR software by thAPB_STATE_2http://sourceforge.e.c#projrucs/lxpb>LXR communipyef="+cthis experimental version by B_STATE_2mailto:lxp@ 25ux.nohr>xp@ 25ux.no+codp
subfootapb> >xp. 25ux.no kindly hostad by B_STATE_2http://www.redpill- 25pro.nohrRedpill Linpro ASef="+cprovider of Linux consult"+c and operations ser"+cos since 1995.