x25_link.c (9234B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * X.25 Packet Layer release 002 4 * 5 * This is ALPHA test software. This code may break your machine, 6 * randomly fail to work with new releases, misbehave and/or generally 7 * screw up. It might even work. 8 * 9 * This code REQUIRES 2.1.15 or higher 10 * 11 * History 12 * X.25 001 Jonathan Naylor Started coding. 13 * X.25 002 Jonathan Naylor New timer architecture. 14 * mar/20/00 Daniela Squassoni Disabling/enabling of facilities 15 * negotiation. 16 * 2000-09-04 Henner Eisen dev_hold() / dev_put() for x25_neigh. 17 */ 18 19#define pr_fmt(fmt) "X25: " fmt 20 21#include <linux/kernel.h> 22#include <linux/jiffies.h> 23#include <linux/timer.h> 24#include <linux/slab.h> 25#include <linux/netdevice.h> 26#include <linux/skbuff.h> 27#include <linux/uaccess.h> 28#include <linux/init.h> 29#include <net/x25.h> 30 31LIST_HEAD(x25_neigh_list); 32DEFINE_RWLOCK(x25_neigh_list_lock); 33 34static void x25_t20timer_expiry(struct timer_list *); 35 36static void x25_transmit_restart_confirmation(struct x25_neigh *nb); 37static void x25_transmit_restart_request(struct x25_neigh *nb); 38 39/* 40 * Linux set/reset timer routines 41 */ 42static inline void x25_start_t20timer(struct x25_neigh *nb) 43{ 44 mod_timer(&nb->t20timer, jiffies + nb->t20); 45} 46 47static void x25_t20timer_expiry(struct timer_list *t) 48{ 49 struct x25_neigh *nb = from_timer(nb, t, t20timer); 50 51 x25_transmit_restart_request(nb); 52 53 x25_start_t20timer(nb); 54} 55 56static inline void x25_stop_t20timer(struct x25_neigh *nb) 57{ 58 del_timer(&nb->t20timer); 59} 60 61/* 62 * This handles all restart and diagnostic frames. 63 */ 64void x25_link_control(struct sk_buff *skb, struct x25_neigh *nb, 65 unsigned short frametype) 66{ 67 struct sk_buff *skbn; 68 69 switch (frametype) { 70 case X25_RESTART_REQUEST: 71 switch (nb->state) { 72 case X25_LINK_STATE_0: 73 /* This can happen when the x25 module just gets loaded 74 * and doesn't know layer 2 has already connected 75 */ 76 nb->state = X25_LINK_STATE_3; 77 x25_transmit_restart_confirmation(nb); 78 break; 79 case X25_LINK_STATE_2: 80 x25_stop_t20timer(nb); 81 nb->state = X25_LINK_STATE_3; 82 break; 83 case X25_LINK_STATE_3: 84 /* clear existing virtual calls */ 85 x25_kill_by_neigh(nb); 86 87 x25_transmit_restart_confirmation(nb); 88 break; 89 } 90 break; 91 92 case X25_RESTART_CONFIRMATION: 93 switch (nb->state) { 94 case X25_LINK_STATE_2: 95 x25_stop_t20timer(nb); 96 nb->state = X25_LINK_STATE_3; 97 break; 98 case X25_LINK_STATE_3: 99 /* clear existing virtual calls */ 100 x25_kill_by_neigh(nb); 101 102 x25_transmit_restart_request(nb); 103 nb->state = X25_LINK_STATE_2; 104 x25_start_t20timer(nb); 105 break; 106 } 107 break; 108 109 case X25_DIAGNOSTIC: 110 if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 4)) 111 break; 112 113 pr_warn("diagnostic #%d - %02X %02X %02X\n", 114 skb->data[3], skb->data[4], 115 skb->data[5], skb->data[6]); 116 break; 117 118 default: 119 pr_warn("received unknown %02X with LCI 000\n", 120 frametype); 121 break; 122 } 123 124 if (nb->state == X25_LINK_STATE_3) 125 while ((skbn = skb_dequeue(&nb->queue)) != NULL) 126 x25_send_frame(skbn, nb); 127} 128 129/* 130 * This routine is called when a Restart Request is needed 131 */ 132static void x25_transmit_restart_request(struct x25_neigh *nb) 133{ 134 unsigned char *dptr; 135 int len = X25_MAX_L2_LEN + X25_STD_MIN_LEN + 2; 136 struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); 137 138 if (!skb) 139 return; 140 141 skb_reserve(skb, X25_MAX_L2_LEN); 142 143 dptr = skb_put(skb, X25_STD_MIN_LEN + 2); 144 145 *dptr++ = nb->extended ? X25_GFI_EXTSEQ : X25_GFI_STDSEQ; 146 *dptr++ = 0x00; 147 *dptr++ = X25_RESTART_REQUEST; 148 *dptr++ = 0x00; 149 *dptr++ = 0; 150 151 skb->sk = NULL; 152 153 x25_send_frame(skb, nb); 154} 155 156/* 157 * This routine is called when a Restart Confirmation is needed 158 */ 159static void x25_transmit_restart_confirmation(struct x25_neigh *nb) 160{ 161 unsigned char *dptr; 162 int len = X25_MAX_L2_LEN + X25_STD_MIN_LEN; 163 struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); 164 165 if (!skb) 166 return; 167 168 skb_reserve(skb, X25_MAX_L2_LEN); 169 170 dptr = skb_put(skb, X25_STD_MIN_LEN); 171 172 *dptr++ = nb->extended ? X25_GFI_EXTSEQ : X25_GFI_STDSEQ; 173 *dptr++ = 0x00; 174 *dptr++ = X25_RESTART_CONFIRMATION; 175 176 skb->sk = NULL; 177 178 x25_send_frame(skb, nb); 179} 180 181/* 182 * This routine is called when a Clear Request is needed outside of the context 183 * of a connected socket. 184 */ 185void x25_transmit_clear_request(struct x25_neigh *nb, unsigned int lci, 186 unsigned char cause) 187{ 188 unsigned char *dptr; 189 int len = X25_MAX_L2_LEN + X25_STD_MIN_LEN + 2; 190 struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); 191 192 if (!skb) 193 return; 194 195 skb_reserve(skb, X25_MAX_L2_LEN); 196 197 dptr = skb_put(skb, X25_STD_MIN_LEN + 2); 198 199 *dptr++ = ((lci >> 8) & 0x0F) | (nb->extended ? 200 X25_GFI_EXTSEQ : 201 X25_GFI_STDSEQ); 202 *dptr++ = (lci >> 0) & 0xFF; 203 *dptr++ = X25_CLEAR_REQUEST; 204 *dptr++ = cause; 205 *dptr++ = 0x00; 206 207 skb->sk = NULL; 208 209 x25_send_frame(skb, nb); 210} 211 212void x25_transmit_link(struct sk_buff *skb, struct x25_neigh *nb) 213{ 214 switch (nb->state) { 215 case X25_LINK_STATE_0: 216 skb_queue_tail(&nb->queue, skb); 217 nb->state = X25_LINK_STATE_1; 218 x25_establish_link(nb); 219 break; 220 case X25_LINK_STATE_1: 221 case X25_LINK_STATE_2: 222 skb_queue_tail(&nb->queue, skb); 223 break; 224 case X25_LINK_STATE_3: 225 x25_send_frame(skb, nb); 226 break; 227 } 228} 229 230/* 231 * Called when the link layer has become established. 232 */ 233void x25_link_established(struct x25_neigh *nb) 234{ 235 switch (nb->state) { 236 case X25_LINK_STATE_0: 237 case X25_LINK_STATE_1: 238 x25_transmit_restart_request(nb); 239 nb->state = X25_LINK_STATE_2; 240 x25_start_t20timer(nb); 241 break; 242 } 243} 244 245/* 246 * Called when the link layer has terminated, or an establishment 247 * request has failed. 248 */ 249 250void x25_link_terminated(struct x25_neigh *nb) 251{ 252 nb->state = X25_LINK_STATE_0; 253 skb_queue_purge(&nb->queue); 254 x25_stop_t20timer(nb); 255 256 /* Out of order: clear existing virtual calls (X.25 03/93 4.6.3) */ 257 x25_kill_by_neigh(nb); 258} 259 260/* 261 * Add a new device. 262 */ 263void x25_link_device_up(struct net_device *dev) 264{ 265 struct x25_neigh *nb = kmalloc(sizeof(*nb), GFP_ATOMIC); 266 267 if (!nb) 268 return; 269 270 skb_queue_head_init(&nb->queue); 271 timer_setup(&nb->t20timer, x25_t20timer_expiry, 0); 272 273 dev_hold(dev); 274 nb->dev = dev; 275 nb->state = X25_LINK_STATE_0; 276 nb->extended = 0; 277 /* 278 * Enables negotiation 279 */ 280 nb->global_facil_mask = X25_MASK_REVERSE | 281 X25_MASK_THROUGHPUT | 282 X25_MASK_PACKET_SIZE | 283 X25_MASK_WINDOW_SIZE; 284 nb->t20 = sysctl_x25_restart_request_timeout; 285 refcount_set(&nb->refcnt, 1); 286 287 write_lock_bh(&x25_neigh_list_lock); 288 list_add(&nb->node, &x25_neigh_list); 289 write_unlock_bh(&x25_neigh_list_lock); 290} 291 292/** 293 * __x25_remove_neigh - remove neighbour from x25_neigh_list 294 * @nb: - neigh to remove 295 * 296 * Remove neighbour from x25_neigh_list. If it was there. 297 * Caller must hold x25_neigh_list_lock. 298 */ 299static void __x25_remove_neigh(struct x25_neigh *nb) 300{ 301 if (nb->node.next) { 302 list_del(&nb->node); 303 x25_neigh_put(nb); 304 } 305} 306 307/* 308 * A device has been removed, remove its links. 309 */ 310void x25_link_device_down(struct net_device *dev) 311{ 312 struct x25_neigh *nb; 313 struct list_head *entry, *tmp; 314 315 write_lock_bh(&x25_neigh_list_lock); 316 317 list_for_each_safe(entry, tmp, &x25_neigh_list) { 318 nb = list_entry(entry, struct x25_neigh, node); 319 320 if (nb->dev == dev) { 321 __x25_remove_neigh(nb); 322 dev_put(dev); 323 } 324 } 325 326 write_unlock_bh(&x25_neigh_list_lock); 327} 328 329/* 330 * Given a device, return the neighbour address. 331 */ 332struct x25_neigh *x25_get_neigh(struct net_device *dev) 333{ 334 struct x25_neigh *nb, *use = NULL; 335 336 read_lock_bh(&x25_neigh_list_lock); 337 list_for_each_entry(nb, &x25_neigh_list, node) { 338 if (nb->dev == dev) { 339 use = nb; 340 break; 341 } 342 } 343 344 if (use) 345 x25_neigh_hold(use); 346 read_unlock_bh(&x25_neigh_list_lock); 347 return use; 348} 349 350/* 351 * Handle the ioctls that control the subscription functions. 352 */ 353int x25_subscr_ioctl(unsigned int cmd, void __user *arg) 354{ 355 struct x25_subscrip_struct x25_subscr; 356 struct x25_neigh *nb; 357 struct net_device *dev; 358 int rc = -EINVAL; 359 360 if (cmd != SIOCX25GSUBSCRIP && cmd != SIOCX25SSUBSCRIP) 361 goto out; 362 363 rc = -EFAULT; 364 if (copy_from_user(&x25_subscr, arg, sizeof(x25_subscr))) 365 goto out; 366 367 rc = -EINVAL; 368 if ((dev = x25_dev_get(x25_subscr.device)) == NULL) 369 goto out; 370 371 if ((nb = x25_get_neigh(dev)) == NULL) 372 goto out_dev_put; 373 374 dev_put(dev); 375 376 if (cmd == SIOCX25GSUBSCRIP) { 377 read_lock_bh(&x25_neigh_list_lock); 378 x25_subscr.extended = nb->extended; 379 x25_subscr.global_facil_mask = nb->global_facil_mask; 380 read_unlock_bh(&x25_neigh_list_lock); 381 rc = copy_to_user(arg, &x25_subscr, 382 sizeof(x25_subscr)) ? -EFAULT : 0; 383 } else { 384 rc = -EINVAL; 385 if (!(x25_subscr.extended && x25_subscr.extended != 1)) { 386 rc = 0; 387 write_lock_bh(&x25_neigh_list_lock); 388 nb->extended = x25_subscr.extended; 389 nb->global_facil_mask = x25_subscr.global_facil_mask; 390 write_unlock_bh(&x25_neigh_list_lock); 391 } 392 } 393 x25_neigh_put(nb); 394out: 395 return rc; 396out_dev_put: 397 dev_put(dev); 398 goto out; 399} 400 401 402/* 403 * Release all memory associated with X.25 neighbour structures. 404 */ 405void __exit x25_link_free(void) 406{ 407 struct x25_neigh *nb; 408 struct list_head *entry, *tmp; 409 410 write_lock_bh(&x25_neigh_list_lock); 411 412 list_for_each_safe(entry, tmp, &x25_neigh_list) { 413 struct net_device *dev; 414 415 nb = list_entry(entry, struct x25_neigh, node); 416 dev = nb->dev; 417 __x25_remove_neigh(nb); 418 dev_put(dev); 419 } 420 write_unlock_bh(&x25_neigh_list_lock); 421}