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