x25_link.c 9.1 KB

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