root/net/lapb/lapb_iface.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lapb_free_cb
  2. lapb_hold
  3. lapb_put
  4. __lapb_remove_cb
  5. __lapb_insert_cb
  6. __lapb_devtostruct
  7. lapb_devtostruct
  8. lapb_create_cb
  9. lapb_register
  10. lapb_unregister
  11. lapb_getparms
  12. lapb_setparms
  13. lapb_connect_request
  14. lapb_disconnect_request
  15. lapb_data_request
  16. lapb_data_received
  17. lapb_connect_confirmation
  18. lapb_connect_indication
  19. lapb_disconnect_confirmation
  20. lapb_disconnect_indication
  21. lapb_data_indication
  22. lapb_data_transmit
  23. lapb_init
  24. lapb_exit

   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 
  39 static LIST_HEAD(lapb_list);
  40 static DEFINE_RWLOCK(lapb_list_lock);
  41 
  42 /*
  43  *      Free an allocated lapb control block.
  44  */
  45 static void lapb_free_cb(struct lapb_cb *lapb)
  46 {
  47         kfree(lapb);
  48 }
  49 
  50 static __inline__ void lapb_hold(struct lapb_cb *lapb)
  51 {
  52         refcount_inc(&lapb->refcnt);
  53 }
  54 
  55 static __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  */
  64 static 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  */
  75 static void __lapb_insert_cb(struct lapb_cb *lapb)
  76 {
  77         list_add(&lapb->node, &lapb_list);
  78         lapb_hold(lapb);
  79 }
  80 
  81 static struct lapb_cb *__lapb_devtostruct(struct net_device *dev)
  82 {
  83         struct list_head *entry;
  84         struct lapb_cb *lapb, *use = NULL;
  85 
  86         list_for_each(entry, &lapb_list) {
  87                 lapb = list_entry(entry, struct lapb_cb, node);
  88                 if (lapb->dev == dev) {
  89                         use = lapb;
  90                         break;
  91                 }
  92         }
  93 
  94         if (use)
  95                 lapb_hold(use);
  96 
  97         return use;
  98 }
  99 
 100 static struct lapb_cb *lapb_devtostruct(struct net_device *dev)
 101 {
 102         struct lapb_cb *rc;
 103 
 104         read_lock_bh(&lapb_list_lock);
 105         rc = __lapb_devtostruct(dev);
 106         read_unlock_bh(&lapb_list_lock);
 107 
 108         return rc;
 109 }
 110 /*
 111  *      Create an empty LAPB control block.
 112  */
 113 static struct lapb_cb *lapb_create_cb(void)
 114 {
 115         struct lapb_cb *lapb = kzalloc(sizeof(*lapb), GFP_ATOMIC);
 116 
 117         if (!lapb)
 118                 goto out;
 119 
 120         skb_queue_head_init(&lapb->write_queue);
 121         skb_queue_head_init(&lapb->ack_queue);
 122 
 123         timer_setup(&lapb->t1timer, NULL, 0);
 124         timer_setup(&lapb->t2timer, NULL, 0);
 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         refcount_set(&lapb->refcnt, 1);
 133 out:
 134         return lapb;
 135 }
 136 
 137 int lapb_register(struct net_device *dev,
 138                   const struct lapb_register_struct *callbacks)
 139 {
 140         struct lapb_cb *lapb;
 141         int rc = LAPB_BADTOKEN;
 142 
 143         write_lock_bh(&lapb_list_lock);
 144 
 145         lapb = __lapb_devtostruct(dev);
 146         if (lapb) {
 147                 lapb_put(lapb);
 148                 goto out;
 149         }
 150 
 151         lapb = lapb_create_cb();
 152         rc = LAPB_NOMEM;
 153         if (!lapb)
 154                 goto out;
 155 
 156         lapb->dev       = dev;
 157         lapb->callbacks = callbacks;
 158 
 159         __lapb_insert_cb(lapb);
 160 
 161         lapb_start_t1timer(lapb);
 162 
 163         rc = LAPB_OK;
 164 out:
 165         write_unlock_bh(&lapb_list_lock);
 166         return rc;
 167 }
 168 EXPORT_SYMBOL(lapb_register);
 169 
 170 int lapb_unregister(struct net_device *dev)
 171 {
 172         struct lapb_cb *lapb;
 173         int rc = LAPB_BADTOKEN;
 174 
 175         write_lock_bh(&lapb_list_lock);
 176         lapb = __lapb_devtostruct(dev);
 177         if (!lapb)
 178                 goto out;
 179         lapb_put(lapb);
 180 
 181         lapb_stop_t1timer(lapb);
 182         lapb_stop_t2timer(lapb);
 183 
 184         lapb_clear_queues(lapb);
 185 
 186         __lapb_remove_cb(lapb);
 187 
 188         lapb_put(lapb);
 189         rc = LAPB_OK;
 190 out:
 191         write_unlock_bh(&lapb_list_lock);
 192         return rc;
 193 }
 194 EXPORT_SYMBOL(lapb_unregister);
 195 
 196 int 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;
 224 out:
 225         return rc;
 226 }
 227 EXPORT_SYMBOL(lapb_getparms);
 228 
 229 int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms)
 230 {
 231         int rc = LAPB_BADTOKEN;
 232         struct lapb_cb *lapb = lapb_devtostruct(dev);
 233 
 234         if (!lapb)
 235                 goto out;
 236 
 237         rc = LAPB_INVALUE;
 238         if (parms->t1 < 1 || parms->t2 < 1 || parms->n2 < 1)
 239                 goto out_put;
 240 
 241         if (lapb->state == LAPB_STATE_0) {
 242                 if (parms->mode & LAPB_EXTENDED) {
 243                         if (parms->window < 1 || parms->window > 127)
 244                                 goto out_put;
 245                 } else {
 246                         if (parms->window < 1 || parms->window > 7)
 247                                 goto out_put;
 248                 }
 249                 lapb->mode    = parms->mode;
 250                 lapb->window  = parms->window;
 251         }
 252 
 253         lapb->t1    = parms->t1 * HZ;
 254         lapb->t2    = parms->t2 * HZ;
 255         lapb->n2    = parms->n2;
 256 
 257         rc = LAPB_OK;
 258 out_put:
 259         lapb_put(lapb);
 260 out:
 261         return rc;
 262 }
 263 EXPORT_SYMBOL(lapb_setparms);
 264 
 265 int lapb_connect_request(struct net_device *dev)
 266 {
 267         struct lapb_cb *lapb = lapb_devtostruct(dev);
 268         int rc = LAPB_BADTOKEN;
 269 
 270         if (!lapb)
 271                 goto out;
 272 
 273         rc = LAPB_OK;
 274         if (lapb->state == LAPB_STATE_1)
 275                 goto out_put;
 276 
 277         rc = LAPB_CONNECTED;
 278         if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4)
 279                 goto out_put;
 280 
 281         lapb_establish_data_link(lapb);
 282 
 283         lapb_dbg(0, "(%p) S0 -> S1\n", lapb->dev);
 284         lapb->state = LAPB_STATE_1;
 285 
 286         rc = LAPB_OK;
 287 out_put:
 288         lapb_put(lapb);
 289 out:
 290         return rc;
 291 }
 292 EXPORT_SYMBOL(lapb_connect_request);
 293 
 294 int lapb_disconnect_request(struct net_device *dev)
 295 {
 296         struct lapb_cb *lapb = lapb_devtostruct(dev);
 297         int rc = LAPB_BADTOKEN;
 298 
 299         if (!lapb)
 300                 goto out;
 301 
 302         switch (lapb->state) {
 303         case LAPB_STATE_0:
 304                 rc = LAPB_NOTCONNECTED;
 305                 goto out_put;
 306 
 307         case LAPB_STATE_1:
 308                 lapb_dbg(1, "(%p) S1 TX DISC(1)\n", lapb->dev);
 309                 lapb_dbg(0, "(%p) S1 -> S0\n", lapb->dev);
 310                 lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 311                 lapb->state = LAPB_STATE_0;
 312                 lapb_start_t1timer(lapb);
 313                 rc = LAPB_NOTCONNECTED;
 314                 goto out_put;
 315 
 316         case LAPB_STATE_2:
 317                 rc = LAPB_OK;
 318                 goto out_put;
 319         }
 320 
 321         lapb_clear_queues(lapb);
 322         lapb->n2count = 0;
 323         lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 324         lapb_start_t1timer(lapb);
 325         lapb_stop_t2timer(lapb);
 326         lapb->state = LAPB_STATE_2;
 327 
 328         lapb_dbg(1, "(%p) S3 DISC(1)\n", lapb->dev);
 329         lapb_dbg(0, "(%p) S3 -> S2\n", lapb->dev);
 330 
 331         rc = LAPB_OK;
 332 out_put:
 333         lapb_put(lapb);
 334 out:
 335         return rc;
 336 }
 337 EXPORT_SYMBOL(lapb_disconnect_request);
 338 
 339 int lapb_data_request(struct net_device *dev, struct sk_buff *skb)
 340 {
 341         struct lapb_cb *lapb = lapb_devtostruct(dev);
 342         int rc = LAPB_BADTOKEN;
 343 
 344         if (!lapb)
 345                 goto out;
 346 
 347         rc = LAPB_NOTCONNECTED;
 348         if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4)
 349                 goto out_put;
 350 
 351         skb_queue_tail(&lapb->write_queue, skb);
 352         lapb_kick(lapb);
 353         rc = LAPB_OK;
 354 out_put:
 355         lapb_put(lapb);
 356 out:
 357         return rc;
 358 }
 359 EXPORT_SYMBOL(lapb_data_request);
 360 
 361 int lapb_data_received(struct net_device *dev, struct sk_buff *skb)
 362 {
 363         struct lapb_cb *lapb = lapb_devtostruct(dev);
 364         int rc = LAPB_BADTOKEN;
 365 
 366         if (lapb) {
 367                 lapb_data_input(lapb, skb);
 368                 lapb_put(lapb);
 369                 rc = LAPB_OK;
 370         }
 371 
 372         return rc;
 373 }
 374 EXPORT_SYMBOL(lapb_data_received);
 375 
 376 void lapb_connect_confirmation(struct lapb_cb *lapb, int reason)
 377 {
 378         if (lapb->callbacks->connect_confirmation)
 379                 lapb->callbacks->connect_confirmation(lapb->dev, reason);
 380 }
 381 
 382 void lapb_connect_indication(struct lapb_cb *lapb, int reason)
 383 {
 384         if (lapb->callbacks->connect_indication)
 385                 lapb->callbacks->connect_indication(lapb->dev, reason);
 386 }
 387 
 388 void lapb_disconnect_confirmation(struct lapb_cb *lapb, int reason)
 389 {
 390         if (lapb->callbacks->disconnect_confirmation)
 391                 lapb->callbacks->disconnect_confirmation(lapb->dev, reason);
 392 }
 393 
 394 void lapb_disconnect_indication(struct lapb_cb *lapb, int reason)
 395 {
 396         if (lapb->callbacks->disconnect_indication)
 397                 lapb->callbacks->disconnect_indication(lapb->dev, reason);
 398 }
 399 
 400 int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *skb)
 401 {
 402         if (lapb->callbacks->data_indication)
 403                 return lapb->callbacks->data_indication(lapb->dev, skb);
 404 
 405         kfree_skb(skb);
 406         return NET_RX_SUCCESS; /* For now; must be != NET_RX_DROP */
 407 }
 408 
 409 int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb)
 410 {
 411         int used = 0;
 412 
 413         if (lapb->callbacks->data_transmit) {
 414                 lapb->callbacks->data_transmit(lapb->dev, skb);
 415                 used = 1;
 416         }
 417 
 418         return used;
 419 }
 420 
 421 static int __init lapb_init(void)
 422 {
 423         return 0;
 424 }
 425 
 426 static void __exit lapb_exit(void)
 427 {
 428         WARN_ON(!list_empty(&lapb_list));
 429 }
 430 
 431 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
 432 MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
 433 MODULE_LICENSE("GPL");
 434 
 435 module_init(lapb_init);
 436 module_exit(lapb_exit);

/* [<][>][^][v][top][bottom][index][help] */