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