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 EXPORT_SYMBOL(lapb_register); 72 73 /* 74 * Add a socket to the bound sockets list. 75 */ 76 static void __lapb_insert_cb(struct lapb_cb *lapb) 77 { 78 list_add(&lapb->node, &lapb_list); 79 lapb_hold(lapb); 80 } 81 82 static struct lapb_cb *__lapb_devtostruct(struct net_device *dev) 83 { 84 struct list_head *entry; 85 struct lapb_cb *lapb, *use = NULL; 86 87 list_for_each(entry, &lapb_list) { 88 lapb = list_entry(entry, struct lapb_cb, node); 89 if (lapb->dev == dev) { 90 use = lapb; 91 break; 92 } 93 } 94 95 if (use) 96 lapb_hold(use); 97 98 return use; 99 } 100 101 static struct lapb_cb *lapb_devtostruct(struct net_device *dev) 102 { 103 struct lapb_cb *rc; 104 105 read_lock_bh(&lapb_list_lock); 106 rc = __lapb_devtostruct(dev); 107 read_unlock_bh(&lapb_list_lock); 108 109 return rc; 110 } 111 /* 112 * Create an empty LAPB control block. 113 */ 114 static struct lapb_cb *lapb_create_cb(void) 115 { 116 struct lapb_cb *lapb = kzalloc(sizeof(*lapb), GFP_ATOMIC); 117 118 119 if (!lapb) 120 goto out; 121 122 skb_queue_head_init(&lapb->write_queue); 123 skb_queue_head_init(&lapb->ack_queue); 124 125 timer_setup(&lapb->t1timer, NULL, 0); 126 timer_setup(&lapb->t2timer, NULL, 0); 127 128 lapb->t1 = LAPB_DEFAULT_T1; 129 lapb->t2 = LAPB_DEFAULT_T2; 130 lapb->n2 = LAPB_DEFAULT_N2; 131 lapb->mode = LAPB_DEFAULT_MODE; 132 lapb->window = LAPB_DEFAULT_WINDOW; 133 lapb->state = LAPB_STATE_0; 134 refcount_set(&lapb->refcnt, 1); 135 out: 136 return lapb; 137 } 138 139 int 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; 166 out: 167 write_unlock_bh(&lapb_list_lock); 168 return rc; 169 } 170 171 int lapb_unregister(struct net_device *dev) 172 { 173 struct lapb_cb *lapb; 174 int rc = LAPB_BADTOKEN; 175 176 write_lock_bh(&lapb_list_lock); 177 lapb = __lapb_devtostruct(dev); 178 if (!lapb) 179 goto out; 180 lapb_put(lapb); 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; 191 out: 192 write_unlock_bh(&lapb_list_lock); 193 return rc; 194 } 195 EXPORT_SYMBOL(lapb_unregister); 196 197 int lapb_getparms(struct net_device *dev, struct lapb_parms_struct *parms) 198 { 199 int rc = LAPB_BADTOKEN; 200 struct lapb_cb *lapb = lapb_devtostruct(dev); 201 202 if (!lapb) 203 goto out; 204 205 parms->t1 = lapb->t1 / HZ; 206 parms->t2 = lapb->t2 / HZ; 207 parms->n2 = lapb->n2; 208 parms->n2count = lapb->n2count; 209 parms->state = lapb->state; 210 parms->window = lapb->window; 211 parms->mode = lapb->mode; 212 213 if (!timer_pending(&lapb->t1timer)) 214 parms->t1timer = 0; 215 else 216 parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ; 217 218 if (!timer_pending(&lapb->t2timer)) 219 parms->t2timer = 0; 220 else 221 parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ; 222 223 lapb_put(lapb); 224 rc = LAPB_OK; 225 out: 226 return rc; 227 } 228 EXPORT_SYMBOL(lapb_getparms); 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 EXPORT_SYMBOL(lapb_setparms); 265 266 int lapb_connect_request(struct net_device *dev) 267 { 268 struct lapb_cb *lapb = lapb_devtostruct(dev); 269 int rc = LAPB_BADTOKEN; 270 271 if (!lapb) 272 goto out; 273 274 rc = LAPB_OK; 275 if (lapb->state == LAPB_STATE_1) 276 goto out_put; 277 278 rc = LAPB_CONNECTED; 279 if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4) 280 goto out_put; 281 282 lapb_establish_data_link(lapb); 283 284 lapb_dbg(0, "(%p) S0 -> S1\n", lapb->dev); 285 lapb->state = LAPB_STATE_1; 286 287 rc = LAPB_OK; 288 out_put: 289 lapb_put(lapb); 290 out: 291 return rc; 292 } 293 EXPORT_SYMBOL(lapb_connect_request); 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 lapb_dbg(1, "(%p) S1 TX DISC(1)\n", lapb->dev); 310 lapb_dbg(0, "(%p) S1 -> S0\n", lapb->dev); 311 lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); 312 lapb->state = LAPB_STATE_0; 313 lapb_start_t1timer(lapb); 314 rc = LAPB_NOTCONNECTED; 315 goto out_put; 316 317 case LAPB_STATE_2: 318 rc = LAPB_OK; 319 goto out_put; 320 } 321 322 lapb_clear_queues(lapb); 323 lapb->n2count = 0; 324 lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); 325 lapb_start_t1timer(lapb); 326 lapb_stop_t2timer(lapb); 327 lapb->state = LAPB_STATE_2; 328 329 lapb_dbg(1, "(%p) S3 DISC(1)\n", lapb->dev); 330 lapb_dbg(0, "(%p) S3 -> S2\n", lapb->dev); 331 332 rc = LAPB_OK; 333 out_put: 334 lapb_put(lapb); 335 out: 336 return rc; 337 } 338 EXPORT_SYMBOL(lapb_disconnect_request); 339 340 int lapb_data_request(struct net_device *dev, struct sk_buff *skb) 341 { 342 struct lapb_cb *lapb = lapb_devtostruct(dev); 343 int rc = LAPB_BADTOKEN; 344 345 if (!lapb) 346 goto out; 347 348 rc = LAPB_NOTCONNECTED; 349 if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4) 350 goto out_put; 351 352 skb_queue_tail(&lapb->write_queue, skb); 353 lapb_kick(lapb); 354 rc = LAPB_OK; 355 out_put: 356 lapb_put(lapb); 357 out: 358 return rc; 359 } 360 EXPORT_SYMBOL(lapb_data_request); 361 362 int lapb_data_received(struct net_device *dev, struct sk_buff *skb) 363 { 364 struct lapb_cb *lapb = lapb_devtostruct(dev); 365 int rc = LAPB_BADTOKEN; 366 367 if (lapb) { 368 lapb_data_input(lapb, skb); 369 lapb_put(lapb); 370 rc = LAPB_OK; 371 } 372 373 return rc; 374 } 375 EXPORT_SYMBOL(lapb_data_received); 376 377 void lapb_connect_confirmation(struct lapb_cb *lapb, int reason) 378 { 379 if (lapb->callbacks->connect_confirmation) 380 lapb->callbacks->connect_confirmation(lapb->dev, reason); 381 } 382 383 void lapb_connect_indication(struct lapb_cb *lapb, int reason) 384 { 385 if (lapb->callbacks->connect_indication) 386 lapb->callbacks->connect_indication(lapb->dev, reason); 387 } 388 389 void lapb_disconnect_confirmation(struct lapb_cb *lapb, int reason) 390 { 391 if (lapb->callbacks->disconnect_confirmation) 392 lapb->callbacks->disconnect_confirmation(lapb->dev, reason); 393 } 394 395 void lapb_disconnect_indication(struct lapb_cb *lapb, int reason) 396 { 397 if (lapb->callbacks->disconnect_indication) 398 lapb->callbacks->disconnect_indication(lapb->dev, reason); 399 } 400 401 int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *skb) 402 { 403 if (lapb->callbacks->data_indication) 404 return lapb->callbacks->data_indication(lapb->dev, skb); 405 406 kfree_skb(skb); 407 return NET_RX_SUCCESS; /* For now; must be != NET_RX_DROP */ 408 } 409 410 int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb) 411 { 412 int used = 0; 413 414 if (lapb->callbacks->data_transmit) { 415 lapb->callbacks->data_transmit(lapb->dev, skb); 416 used = 1; 417 } 418 419 return used; 420 } 421 422 static int __init lapb_init(void) 423 { 424 return 0; 425 } 426 427 static void __exit lapb_exit(void) 428 { 429 WARN_ON(!list_empty(&lapb_list)); 430 } 431 432 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>"); 433 MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol"); 434 MODULE_LICENSE("GPL"); 435 436 module_init(lapb_init); 437 module_exit(lapb_exit); 438