x25_facilities.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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 Split from x25_subr.c
  18. * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
  19. * negotiation.
  20. * apr/14/05 Shaun Pereira - Allow fast select with no restriction
  21. * on response.
  22. */
  23. #include <linux/kernel.h>
  24. #include <linux/string.h>
  25. #include <linux/skbuff.h>
  26. #include <net/sock.h>
  27. #include <net/x25.h>
  28. /*
  29. * Parse a set of facilities into the facilities structure. Unrecognised
  30. * facilities are written to the debug log file.
  31. */
  32. int x25_parse_facilities(struct sk_buff *skb,
  33. struct x25_facilities *facilities,
  34. unsigned long *vc_fac_mask)
  35. {
  36. unsigned char *p = skb->data;
  37. unsigned int len = *p++;
  38. *vc_fac_mask = 0;
  39. while (len > 0) {
  40. switch (*p & X25_FAC_CLASS_MASK) {
  41. case X25_FAC_CLASS_A:
  42. switch (*p) {
  43. case X25_FAC_REVERSE:
  44. if((p[1] & 0x81) == 0x81) {
  45. facilities->reverse = p[1] & 0x81;
  46. *vc_fac_mask |= X25_MASK_REVERSE;
  47. break;
  48. }
  49. if((p[1] & 0x01) == 0x01) {
  50. facilities->reverse = p[1] & 0x01;
  51. *vc_fac_mask |= X25_MASK_REVERSE;
  52. break;
  53. }
  54. if((p[1] & 0x80) == 0x80) {
  55. facilities->reverse = p[1] & 0x80;
  56. *vc_fac_mask |= X25_MASK_REVERSE;
  57. break;
  58. }
  59. if(p[1] == 0x00) {
  60. facilities->reverse
  61. = X25_DEFAULT_REVERSE;
  62. *vc_fac_mask |= X25_MASK_REVERSE;
  63. break;
  64. }
  65. case X25_FAC_THROUGHPUT:
  66. facilities->throughput = p[1];
  67. *vc_fac_mask |= X25_MASK_THROUGHPUT;
  68. break;
  69. default:
  70. printk(KERN_DEBUG "X.25: unknown facility "
  71. "%02X, value %02X\n",
  72. p[0], p[1]);
  73. break;
  74. }
  75. p += 2;
  76. len -= 2;
  77. break;
  78. case X25_FAC_CLASS_B:
  79. switch (*p) {
  80. case X25_FAC_PACKET_SIZE:
  81. facilities->pacsize_in = p[1];
  82. facilities->pacsize_out = p[2];
  83. *vc_fac_mask |= X25_MASK_PACKET_SIZE;
  84. break;
  85. case X25_FAC_WINDOW_SIZE:
  86. facilities->winsize_in = p[1];
  87. facilities->winsize_out = p[2];
  88. *vc_fac_mask |= X25_MASK_WINDOW_SIZE;
  89. break;
  90. default:
  91. printk(KERN_DEBUG "X.25: unknown facility "
  92. "%02X, values %02X, %02X\n",
  93. p[0], p[1], p[2]);
  94. break;
  95. }
  96. p += 3;
  97. len -= 3;
  98. break;
  99. case X25_FAC_CLASS_C:
  100. printk(KERN_DEBUG "X.25: unknown facility %02X, "
  101. "values %02X, %02X, %02X\n",
  102. p[0], p[1], p[2], p[3]);
  103. p += 4;
  104. len -= 4;
  105. break;
  106. case X25_FAC_CLASS_D:
  107. printk(KERN_DEBUG "X.25: unknown facility %02X, "
  108. "length %d, values %02X, %02X, %02X, %02X\n",
  109. p[0], p[1], p[2], p[3], p[4], p[5]);
  110. len -= p[1] + 2;
  111. p += p[1] + 2;
  112. break;
  113. }
  114. }
  115. return p - skb->data;
  116. }
  117. /*
  118. * Create a set of facilities.
  119. */
  120. int x25_create_facilities(unsigned char *buffer,
  121. struct x25_facilities *facilities,
  122. unsigned long facil_mask)
  123. {
  124. unsigned char *p = buffer + 1;
  125. int len;
  126. if (!facil_mask) {
  127. /*
  128. * Length of the facilities field in call_req or
  129. * call_accept packets
  130. */
  131. buffer[0] = 0;
  132. len = 1; /* 1 byte for the length field */
  133. return len;
  134. }
  135. if (facilities->reverse && (facil_mask & X25_MASK_REVERSE)) {
  136. *p++ = X25_FAC_REVERSE;
  137. *p++ = facilities->reverse;
  138. }
  139. if (facilities->throughput && (facil_mask & X25_MASK_THROUGHPUT)) {
  140. *p++ = X25_FAC_THROUGHPUT;
  141. *p++ = facilities->throughput;
  142. }
  143. if ((facilities->pacsize_in || facilities->pacsize_out) &&
  144. (facil_mask & X25_MASK_PACKET_SIZE)) {
  145. *p++ = X25_FAC_PACKET_SIZE;
  146. *p++ = facilities->pacsize_in ? : facilities->pacsize_out;
  147. *p++ = facilities->pacsize_out ? : facilities->pacsize_in;
  148. }
  149. if ((facilities->winsize_in || facilities->winsize_out) &&
  150. (facil_mask & X25_MASK_WINDOW_SIZE)) {
  151. *p++ = X25_FAC_WINDOW_SIZE;
  152. *p++ = facilities->winsize_in ? : facilities->winsize_out;
  153. *p++ = facilities->winsize_out ? : facilities->winsize_in;
  154. }
  155. len = p - buffer;
  156. buffer[0] = len - 1;
  157. return len;
  158. }
  159. /*
  160. * Try to reach a compromise on a set of facilities.
  161. *
  162. * The only real problem is with reverse charging.
  163. */
  164. int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
  165. struct x25_facilities *new)
  166. {
  167. struct x25_sock *x25 = x25_sk(sk);
  168. struct x25_facilities *ours = &x25->facilities;
  169. struct x25_facilities theirs;
  170. int len;
  171. memset(&theirs, 0, sizeof(theirs));
  172. memcpy(new, ours, sizeof(*new));
  173. len = x25_parse_facilities(skb, &theirs, &x25->vc_facil_mask);
  174. /*
  175. * They want reverse charging, we won't accept it.
  176. */
  177. if ((theirs.reverse & 0x01 ) && (ours->reverse & 0x01)) {
  178. SOCK_DEBUG(sk, "X.25: rejecting reverse charging request");
  179. return -1;
  180. }
  181. new->reverse = theirs.reverse;
  182. if (theirs.throughput) {
  183. if (theirs.throughput < ours->throughput) {
  184. SOCK_DEBUG(sk, "X.25: throughput negotiated down");
  185. new->throughput = theirs.throughput;
  186. }
  187. }
  188. if (theirs.pacsize_in && theirs.pacsize_out) {
  189. if (theirs.pacsize_in < ours->pacsize_in) {
  190. SOCK_DEBUG(sk, "X.25: packet size inwards negotiated down");
  191. new->pacsize_in = theirs.pacsize_in;
  192. }
  193. if (theirs.pacsize_out < ours->pacsize_out) {
  194. SOCK_DEBUG(sk, "X.25: packet size outwards negotiated down");
  195. new->pacsize_out = theirs.pacsize_out;
  196. }
  197. }
  198. if (theirs.winsize_in && theirs.winsize_out) {
  199. if (theirs.winsize_in < ours->winsize_in) {
  200. SOCK_DEBUG(sk, "X.25: window size inwards negotiated down");
  201. new->winsize_in = theirs.winsize_in;
  202. }
  203. if (theirs.winsize_out < ours->winsize_out) {
  204. SOCK_DEBUG(sk, "X.25: window size outwards negotiated down");
  205. new->winsize_out = theirs.winsize_out;
  206. }
  207. }
  208. return len;
  209. }
  210. /*
  211. * Limit values of certain facilities according to the capability of the
  212. * currently attached x25 link.
  213. */
  214. void x25_limit_facilities(struct x25_facilities *facilities,
  215. struct x25_neigh *nb)
  216. {
  217. if (!nb->extended) {
  218. if (facilities->winsize_in > 7) {
  219. printk(KERN_DEBUG "X.25: incoming winsize limited to 7\n");
  220. facilities->winsize_in = 7;
  221. }
  222. if (facilities->winsize_out > 7) {
  223. facilities->winsize_out = 7;
  224. printk( KERN_DEBUG "X.25: outgoing winsize limited to 7\n");
  225. }
  226. }
  227. }