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