x25_subr.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * X.25 Packet Layer release 002
  3.  *
  4.  * This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  5.  * releases, misbehave and/or generally screw up. It might even work. 
  6.  *
  7.  * This code REQUIRES 2.1.15 or higher
  8.  *
  9.  * This module:
  10.  * This module is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License
  12.  * as published by the Free Software Foundation; either version
  13.  * 2 of the License, or (at your option) any later version.
  14.  *
  15.  * History
  16.  * X.25 001 Jonathan Naylor   Started coding.
  17.  * X.25 002 Jonathan Naylor   Centralised disconnection processing.
  18.  * mar/20/00 Daniela Squassoni Disabling/enabling of facilities 
  19.  *   negotiation.
  20.  * jun/24/01 Arnaldo C. Melo   use skb_queue_purge, cleanups
  21.  */
  22. #include <linux/errno.h>
  23. #include <linux/types.h>
  24. #include <linux/socket.h>
  25. #include <linux/in.h>
  26. #include <linux/kernel.h>
  27. #include <linux/sched.h>
  28. #include <linux/timer.h>
  29. #include <linux/string.h>
  30. #include <linux/sockios.h>
  31. #include <linux/net.h>
  32. #include <linux/inet.h>
  33. #include <linux/netdevice.h>
  34. #include <linux/skbuff.h>
  35. #include <net/sock.h>
  36. #include <asm/segment.h>
  37. #include <asm/system.h>
  38. #include <linux/fcntl.h>
  39. #include <linux/mm.h>
  40. #include <linux/interrupt.h>
  41. #include <net/x25.h>
  42. /*
  43.  * This routine purges all of the queues of frames.
  44.  */
  45. void x25_clear_queues(struct sock *sk)
  46. {
  47. skb_queue_purge(&sk->write_queue);
  48. skb_queue_purge(&sk->protinfo.x25->ack_queue);
  49. skb_queue_purge(&sk->protinfo.x25->interrupt_in_queue);
  50. skb_queue_purge(&sk->protinfo.x25->interrupt_out_queue);
  51. skb_queue_purge(&sk->protinfo.x25->fragment_queue);
  52. }
  53. /*
  54.  * This routine purges the input queue of those frames that have been
  55.  * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
  56.  * SDL diagram.
  57. */
  58. void x25_frames_acked(struct sock *sk, unsigned short nr)
  59. {
  60. struct sk_buff *skb;
  61. int modulus = sk->protinfo.x25->neighbour->extended ? X25_EMODULUS :
  62.       X25_SMODULUS;
  63. /*
  64.  * Remove all the ack-ed frames from the ack queue.
  65.  */
  66. if (sk->protinfo.x25->va != nr)
  67. while (skb_peek(&sk->protinfo.x25->ack_queue) != NULL &&
  68.        sk->protinfo.x25->va != nr) {
  69. skb = skb_dequeue(&sk->protinfo.x25->ack_queue);
  70. kfree_skb(skb);
  71. sk->protinfo.x25->va = (sk->protinfo.x25->va + 1) %
  72. modulus;
  73. }
  74. }
  75. void x25_requeue_frames(struct sock *sk)
  76. {
  77. struct sk_buff *skb, *skb_prev = NULL;
  78. /*
  79.  * Requeue all the un-ack-ed frames on the output queue to be picked
  80.  * up by x25_kick. This arrangement handles the possibility of an empty
  81.  * output queue.
  82.  */
  83. while ((skb = skb_dequeue(&sk->protinfo.x25->ack_queue)) != NULL) {
  84. if (skb_prev == NULL)
  85. skb_queue_head(&sk->write_queue, skb);
  86. else
  87. skb_append(skb_prev, skb);
  88. skb_prev = skb;
  89. }
  90. }
  91. /*
  92.  * Validate that the value of nr is between va and vs. Return true or
  93.  * false for testing.
  94.  */
  95. int x25_validate_nr(struct sock *sk, unsigned short nr)
  96. {
  97. unsigned short vc = sk->protinfo.x25->va;
  98. int modulus = sk->protinfo.x25->neighbour->extended ? X25_EMODULUS :
  99.       X25_SMODULUS;
  100. while (vc != sk->protinfo.x25->vs) {
  101. if (nr == vc) return 1;
  102. vc = (vc + 1) % modulus;
  103. }
  104. return nr == sk->protinfo.x25->vs ? 1 : 0;
  105. }
  106. /* 
  107.  *  This routine is called when the packet layer internally generates a
  108.  *  control frame.
  109.  */
  110. void x25_write_internal(struct sock *sk, int frametype)
  111. {
  112. struct sk_buff *skb;
  113. unsigned char  *dptr;
  114. unsigned char  facilities[X25_MAX_FAC_LEN];
  115. unsigned char  addresses[1 + X25_ADDR_LEN];
  116. unsigned char  lci1, lci2;
  117. int len;
  118. /*
  119.  * Default safe frame size.
  120.  */
  121. len = X25_MAX_L2_LEN + X25_EXT_MIN_LEN;
  122. /*
  123.  * Adjust frame size.
  124.  */
  125. switch (frametype) {
  126. case X25_CALL_REQUEST:
  127. len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN +
  128.        X25_MAX_CUD_LEN;
  129. break;
  130. case X25_CALL_ACCEPTED:
  131. len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
  132. break;
  133. case X25_CLEAR_REQUEST:
  134. case X25_RESET_REQUEST:
  135. len += 2;
  136. break;
  137. case X25_RR:
  138. case X25_RNR:
  139. case X25_REJ:
  140. case X25_CLEAR_CONFIRMATION:
  141. case X25_INTERRUPT_CONFIRMATION:
  142. case X25_RESET_CONFIRMATION:
  143. break;
  144. default:
  145. printk(KERN_ERR "X.25: invalid frame type %02Xn",
  146.        frametype);
  147. return;
  148. }
  149. if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
  150. return;
  151. /*
  152.  * Space for Ethernet and 802.2 LLC headers.
  153.  */
  154. skb_reserve(skb, X25_MAX_L2_LEN);
  155. /*
  156.  * Make space for the GFI and LCI, and fill them in.
  157.  */
  158. dptr = skb_put(skb, 2);
  159. lci1 = (sk->protinfo.x25->lci >> 8) & 0x0F;
  160. lci2 = (sk->protinfo.x25->lci >> 0) & 0xFF;
  161. if (sk->protinfo.x25->neighbour->extended) {
  162. *dptr++ = lci1 | X25_GFI_EXTSEQ;
  163. *dptr++ = lci2;
  164. } else {
  165. *dptr++ = lci1 | X25_GFI_STDSEQ;
  166. *dptr++ = lci2;
  167. }
  168. /*
  169.  * Now fill in the frame type specific information.
  170.  */
  171. switch (frametype) {
  172. case X25_CALL_REQUEST:
  173. dptr    = skb_put(skb, 1);
  174. *dptr++ = X25_CALL_REQUEST;
  175. len     = x25_addr_aton(addresses, &sk->protinfo.x25->dest_addr, &sk->protinfo.x25->source_addr);
  176. dptr    = skb_put(skb, len);
  177. memcpy(dptr, addresses, len);
  178. len     = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->neighbour->global_facil_mask);
  179. dptr    = skb_put(skb, len);
  180. memcpy(dptr, facilities, len);
  181. dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength);
  182. memcpy(dptr, sk->protinfo.x25->calluserdata.cuddata, sk->protinfo.x25->calluserdata.cudlength);
  183. sk->protinfo.x25->calluserdata.cudlength = 0;
  184. break;
  185. case X25_CALL_ACCEPTED:
  186. dptr    = skb_put(skb, 2);
  187. *dptr++ = X25_CALL_ACCEPTED;
  188. *dptr++ = 0x00; /* Address lengths */
  189. len     = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->vc_facil_mask);
  190. dptr    = skb_put(skb, len);
  191. memcpy(dptr, facilities, len);
  192. dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength);
  193. memcpy(dptr, sk->protinfo.x25->calluserdata.cuddata, sk->protinfo.x25->calluserdata.cudlength);
  194. sk->protinfo.x25->calluserdata.cudlength = 0;
  195. break;
  196. case X25_CLEAR_REQUEST:
  197. case X25_RESET_REQUEST:
  198. dptr    = skb_put(skb, 3);
  199. *dptr++ = frametype;
  200. *dptr++ = 0x00; /* XXX */
  201. *dptr++ = 0x00; /* XXX */
  202. break;
  203. case X25_RR:
  204. case X25_RNR:
  205. case X25_REJ:
  206. if (sk->protinfo.x25->neighbour->extended) {
  207. dptr     = skb_put(skb, 2);
  208. *dptr++  = frametype;
  209. *dptr++  = (sk->protinfo.x25->vr << 1) & 0xFE;
  210. } else {
  211. dptr     = skb_put(skb, 1);
  212. *dptr    = frametype;
  213. *dptr++ |= (sk->protinfo.x25->vr << 5) & 0xE0;
  214. }
  215. break;
  216. case X25_CLEAR_CONFIRMATION:
  217. case X25_INTERRUPT_CONFIRMATION:
  218. case X25_RESET_CONFIRMATION:
  219. dptr  = skb_put(skb, 1);
  220. *dptr = frametype;
  221. break;
  222. }
  223. x25_transmit_link(skb, sk->protinfo.x25->neighbour);
  224. }
  225. /*
  226.  * Unpick the contents of the passed X.25 Packet Layer frame.
  227.  */
  228. int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q,
  229.        int *d, int *m)
  230. {
  231. unsigned char *frame = skb->data;
  232. *ns = *nr = *q = *d = *m = 0;
  233. switch (frame[2]) {
  234. case X25_CALL_REQUEST:
  235. case X25_CALL_ACCEPTED:
  236. case X25_CLEAR_REQUEST:
  237. case X25_CLEAR_CONFIRMATION:
  238. case X25_INTERRUPT:
  239. case X25_INTERRUPT_CONFIRMATION:
  240. case X25_RESET_REQUEST:
  241. case X25_RESET_CONFIRMATION:
  242. case X25_RESTART_REQUEST:
  243. case X25_RESTART_CONFIRMATION:
  244. case X25_REGISTRATION_REQUEST:
  245. case X25_REGISTRATION_CONFIRMATION:
  246. case X25_DIAGNOSTIC:
  247. return frame[2];
  248. }
  249. if (sk->protinfo.x25->neighbour->extended) {
  250. if (frame[2] == X25_RR  ||
  251.     frame[2] == X25_RNR ||
  252.     frame[2] == X25_REJ) {
  253. *nr = (frame[3] >> 1) & 0x7F;
  254. return frame[2];
  255. }
  256. } else {
  257. if ((frame[2] & 0x1F) == X25_RR  ||
  258.     (frame[2] & 0x1F) == X25_RNR ||
  259.     (frame[2] & 0x1F) == X25_REJ) {
  260. *nr = (frame[2] >> 5) & 0x07;
  261. return frame[2] & 0x1F;
  262. }
  263. }
  264. if (sk->protinfo.x25->neighbour->extended) {
  265. if ((frame[2] & 0x01) == X25_DATA) {
  266. *q  = (frame[0] & X25_Q_BIT) == X25_Q_BIT;
  267. *d  = (frame[0] & X25_D_BIT) == X25_D_BIT;
  268. *m  = (frame[3] & X25_EXT_M_BIT) == X25_EXT_M_BIT;
  269. *nr = (frame[3] >> 1) & 0x7F;
  270. *ns = (frame[2] >> 1) & 0x7F;
  271. return X25_DATA;
  272. }
  273. } else {
  274. if ((frame[2] & 0x01) == X25_DATA) {
  275. *q  = (frame[0] & X25_Q_BIT) == X25_Q_BIT;
  276. *d  = (frame[0] & X25_D_BIT) == X25_D_BIT;
  277. *m  = (frame[2] & X25_STD_M_BIT) == X25_STD_M_BIT;
  278. *nr = (frame[2] >> 5) & 0x07;
  279. *ns = (frame[2] >> 1) & 0x07;
  280. return X25_DATA;
  281. }
  282. }
  283. printk(KERN_DEBUG "X.25: invalid PLP frame %02X %02X %02Xn",
  284.        frame[0], frame[1], frame[2]);
  285. return X25_ILLEGAL;
  286. }
  287. void x25_disconnect(struct sock *sk, int reason, unsigned char cause,
  288.     unsigned char diagnostic)
  289. {
  290. x25_clear_queues(sk);
  291. x25_stop_timer(sk);
  292. sk->protinfo.x25->lci   = 0;
  293. sk->protinfo.x25->state = X25_STATE_0;
  294. sk->protinfo.x25->causediag.cause      = cause;
  295. sk->protinfo.x25->causediag.diagnostic = diagnostic;
  296. sk->state     = TCP_CLOSE;
  297. sk->err       = reason;
  298. sk->shutdown |= SEND_SHUTDOWN;
  299. if (!sk->dead)
  300. sk->state_change(sk);
  301. sk->dead = 1;
  302. }
  303. /*
  304.  * Clear an own-rx-busy condition and tell the peer about this, provided
  305.  * that there is a significant amount of free receive buffer space available.
  306.  */
  307. void x25_check_rbuf(struct sock *sk)
  308. {
  309. if (atomic_read(&sk->rmem_alloc) < (sk->rcvbuf / 2) &&
  310.     (sk->protinfo.x25->condition & X25_COND_OWN_RX_BUSY)) {
  311. sk->protinfo.x25->condition &= ~X25_COND_OWN_RX_BUSY;
  312. sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING;
  313. sk->protinfo.x25->vl         = sk->protinfo.x25->vr;
  314. x25_write_internal(sk, X25_RR);
  315. x25_stop_timer(sk);
  316. }
  317. }