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