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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * AX.25 release 037
  3.  *
  4.  * This code REQUIRES 2.1.15 or higher/ NET3.038
  5.  *
  6.  * This module:
  7.  * This module is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License
  9.  * as published by the Free Software Foundation; either version
  10.  * 2 of the License, or (at your option) any later version.
  11.  *
  12.  * Most of this code is based on the SDL diagrams published in the 7th
  13.  * ARRL Computer Networking Conference papers. The diagrams have mistakes
  14.  * in them, but are mostly correct. Before you modify the code could you
  15.  * read the SDL diagrams as the code is not obvious and probably very
  16.  * easy to break;
  17.  *
  18.  * History
  19.  * AX.25 028a Jonathan(G4KLX) New state machine based on SDL diagrams.
  20.  * AX.25 029 Alan(GW4PTS) Switched to KA9Q constant names.
  21.  * Jonathan(G4KLX) Only poll when window is full.
  22.  * AX.25 030 Jonathan(G4KLX) Added fragmentation to ax25_output.
  23.  * Added support for extended AX.25.
  24.  * AX.25 031 Joerg(DL1BKE) Added DAMA support
  25.  * Joerg(DL1BKE) Modified fragmenter to fragment vanilla 
  26.  * AX.25 I-Frames. Added PACLEN parameter.
  27.  * Joerg(DL1BKE) Fixed a problem with buffer allocation
  28.  * for fragments.
  29.  * AX.25 037 Jonathan(G4KLX) New timer architecture.
  30.  * Joerg(DL1BKE) Fixed DAMA Slave mode: will work
  31.  * on non-DAMA interfaces like AX25L2V2
  32.  * again (this behaviour is _required_).
  33.  * Joerg(DL1BKE) ax25_check_iframes_acked() returns a 
  34.  * value now (for DAMA n2count handling)
  35.  */
  36. #include <linux/config.h>
  37. #include <linux/errno.h>
  38. #include <linux/types.h>
  39. #include <linux/socket.h>
  40. #include <linux/in.h>
  41. #include <linux/kernel.h>
  42. #include <linux/sched.h>
  43. #include <linux/timer.h>
  44. #include <linux/string.h>
  45. #include <linux/sockios.h>
  46. #include <linux/net.h>
  47. #include <net/ax25.h>
  48. #include <linux/inet.h>
  49. #include <linux/netdevice.h>
  50. #include <linux/skbuff.h>
  51. #include <linux/netfilter.h>
  52. #include <net/sock.h>
  53. #include <asm/uaccess.h>
  54. #include <asm/system.h>
  55. #include <linux/fcntl.h>
  56. #include <linux/mm.h>
  57. #include <linux/interrupt.h>
  58. ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax25_address *dest, ax25_digi *digi, struct net_device *dev)
  59. {
  60. ax25_dev *ax25_dev;
  61. ax25_cb *ax25;
  62. /*
  63.  * Take the default packet length for the device if zero is
  64.  * specified.
  65.  */
  66. if (paclen == 0) {
  67. if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
  68. return NULL;
  69. paclen = ax25_dev->values[AX25_VALUES_PACLEN];
  70. }
  71. /*
  72.  * Look for an existing connection.
  73.  */
  74. if ((ax25 = ax25_find_cb(src, dest, digi, dev)) != NULL) {
  75. ax25_output(ax25, paclen, skb);
  76. return ax25; /* It already existed */
  77. }
  78. if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
  79. return NULL;
  80. if ((ax25 = ax25_create_cb()) == NULL)
  81. return NULL;
  82. ax25_fillin_cb(ax25, ax25_dev);
  83. ax25->source_addr = *src;
  84. ax25->dest_addr   = *dest;
  85. if (digi != NULL) {
  86. if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
  87. ax25_free_cb(ax25);
  88. return NULL;
  89. }
  90. memcpy(ax25->digipeat, digi, sizeof(ax25_digi));
  91. }
  92. switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
  93. case AX25_PROTO_STD_SIMPLEX:
  94. case AX25_PROTO_STD_DUPLEX:
  95. ax25_std_establish_data_link(ax25);
  96. break;
  97. #ifdef CONFIG_AX25_DAMA_SLAVE
  98. case AX25_PROTO_DAMA_SLAVE:
  99. if (ax25_dev->dama.slave)
  100. ax25_ds_establish_data_link(ax25);
  101. else
  102. ax25_std_establish_data_link(ax25);
  103. break;
  104. #endif
  105. }
  106. ax25_insert_socket(ax25);
  107. ax25->state = AX25_STATE_1;
  108. ax25_start_heartbeat(ax25);
  109. ax25_output(ax25, paclen, skb);
  110. return ax25; /* We had to create it */
  111. }
  112. /*
  113.  * All outgoing AX.25 I frames pass via this routine. Therefore this is
  114.  * where the fragmentation of frames takes place. If fragment is set to
  115.  * zero then we are not allowed to do fragmentation, even if the frame
  116.  * is too large.
  117.  */
  118. void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
  119. {
  120. struct sk_buff *skbn;
  121. unsigned char *p;
  122. int frontlen, len, fragno, ka9qfrag, first = 1;
  123. long flags;
  124. if ((skb->len - 1) > paclen) {
  125. if (*skb->data == AX25_P_TEXT) {
  126. skb_pull(skb, 1); /* skip PID */
  127. ka9qfrag = 0;
  128. } else {
  129. paclen -= 2; /* Allow for fragment control info */
  130. ka9qfrag = 1;
  131. }
  132. fragno = skb->len / paclen;
  133. if (skb->len % paclen == 0) fragno--;
  134. frontlen = skb_headroom(skb); /* Address space + CTRL */
  135. while (skb->len > 0) {
  136. save_flags(flags); 
  137. cli();
  138. if ((skbn = alloc_skb(paclen + 2 + frontlen, GFP_ATOMIC)) == NULL) {
  139. restore_flags(flags);
  140. printk(KERN_CRIT "AX.25: ax25_output - out of memoryn");
  141. return;
  142. }
  143. if (skb->sk != NULL)
  144. skb_set_owner_w(skbn, skb->sk);
  145. restore_flags(flags);
  146. len = (paclen > skb->len) ? skb->len : paclen;
  147. if (ka9qfrag == 1) {
  148. skb_reserve(skbn, frontlen + 2);
  149. skbn->nh.raw = skbn->data + (skb->nh.raw - skb->data);
  150. memcpy(skb_put(skbn, len), skb->data, len);
  151. p = skb_push(skbn, 2);
  152. *p++ = AX25_P_SEGMENT;
  153. *p = fragno--;
  154. if (first) {
  155. *p |= AX25_SEG_FIRST;
  156. first = 0;
  157. }
  158. } else {
  159. skb_reserve(skbn, frontlen + 1);
  160. skbn->nh.raw = skbn->data + (skb->nh.raw - skb->data);
  161. memcpy(skb_put(skbn, len), skb->data, len);
  162. p = skb_push(skbn, 1);
  163. *p = AX25_P_TEXT;
  164. }
  165. skb_pull(skb, len);
  166. skb_queue_tail(&ax25->write_queue, skbn); /* Throw it on the queue */
  167. }
  168. kfree_skb(skb);
  169. } else {
  170. skb_queue_tail(&ax25->write_queue, skb);   /* Throw it on the queue */
  171. }
  172. switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
  173. case AX25_PROTO_STD_SIMPLEX:
  174. case AX25_PROTO_STD_DUPLEX:
  175. ax25_kick(ax25);
  176. break;
  177. #ifdef CONFIG_AX25_DAMA_SLAVE
  178. /* 
  179.  * A DAMA slave is _required_ to work as normal AX.25L2V2
  180.  * if no DAMA master is available.
  181.  */
  182. case AX25_PROTO_DAMA_SLAVE:
  183. if (!ax25->ax25_dev->dama.slave) ax25_kick(ax25);
  184. break;
  185. #endif
  186. }
  187. }
  188. /* 
  189.  *  This procedure is passed a buffer descriptor for an iframe. It builds
  190.  *  the rest of the control part of the frame and then writes it out.
  191.  */
  192. static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit)
  193. {
  194. unsigned char *frame;
  195. if (skb == NULL)
  196. return;
  197. skb->nh.raw = skb->data;
  198. if (ax25->modulus == AX25_MODULUS) {
  199. frame = skb_push(skb, 1);
  200. *frame = AX25_I;
  201. *frame |= (poll_bit) ? AX25_PF : 0;
  202. *frame |= (ax25->vr << 5);
  203. *frame |= (ax25->vs << 1);
  204. } else {
  205. frame = skb_push(skb, 2);
  206. frame[0] = AX25_I;
  207. frame[0] |= (ax25->vs << 1);
  208. frame[1] = (poll_bit) ? AX25_EPF : 0;
  209. frame[1] |= (ax25->vr << 1);
  210. }
  211. ax25_start_idletimer(ax25);
  212. ax25_transmit_buffer(ax25, skb, AX25_COMMAND);
  213. }
  214. void ax25_kick(ax25_cb *ax25)
  215. {
  216. struct sk_buff *skb, *skbn;
  217. int last = 1;
  218. unsigned short start, end, next;
  219. if (ax25->state != AX25_STATE_3 && ax25->state != AX25_STATE_4)
  220. return;
  221. if (ax25->condition & AX25_COND_PEER_RX_BUSY)
  222. return;
  223. if (skb_peek(&ax25->write_queue) == NULL)
  224. return;
  225. start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs;
  226. end   = (ax25->va + ax25->window) % ax25->modulus;
  227. if (start == end)
  228. return;
  229. ax25->vs = start;
  230. /*
  231.  * Transmit data until either we're out of data to send or
  232.  * the window is full. Send a poll on the final I frame if
  233.  * the window is filled.
  234.  */
  235. /*
  236.  * Dequeue the frame and copy it.
  237.  */
  238. skb  = skb_dequeue(&ax25->write_queue);
  239. do {
  240. if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
  241. skb_queue_head(&ax25->write_queue, skb);
  242. break;
  243. }
  244. if (skb->sk != NULL)
  245. skb_set_owner_w(skbn, skb->sk);
  246. next = (ax25->vs + 1) % ax25->modulus;
  247. last = (next == end);
  248. /*
  249.  * Transmit the frame copy.
  250.  * bke 960114: do not set the Poll bit on the last frame
  251.  * in DAMA mode.
  252.  */
  253. switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
  254. case AX25_PROTO_STD_SIMPLEX:
  255. case AX25_PROTO_STD_DUPLEX:
  256. ax25_send_iframe(ax25, skbn, (last) ? AX25_POLLON : AX25_POLLOFF);
  257. break;
  258. #ifdef CONFIG_AX25_DAMA_SLAVE
  259. case AX25_PROTO_DAMA_SLAVE:
  260. ax25_send_iframe(ax25, skbn, AX25_POLLOFF);
  261. break;
  262. #endif
  263. }
  264. ax25->vs = next;
  265. /*
  266.  * Requeue the original data frame.
  267.  */
  268. skb_queue_tail(&ax25->ack_queue, skb);
  269. } while (!last && (skb = skb_dequeue(&ax25->write_queue)) != NULL);
  270. ax25->condition &= ~AX25_COND_ACK_PENDING;
  271. if (!ax25_t1timer_running(ax25)) {
  272. ax25_stop_t3timer(ax25);
  273. ax25_calculate_t1(ax25);
  274. ax25_start_t1timer(ax25);
  275. }
  276. }
  277. void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
  278. {
  279. struct sk_buff *skbn;
  280. unsigned char *ptr;
  281. int headroom;
  282. if (ax25->ax25_dev == NULL) {
  283. ax25_disconnect(ax25, ENETUNREACH);
  284. return;
  285. }
  286. headroom = ax25_addr_size(ax25->digipeat);
  287. if (skb_headroom(skb) < headroom) {
  288. if ((skbn = skb_realloc_headroom(skb, headroom)) == NULL) {
  289. printk(KERN_CRIT "AX.25: ax25_transmit_buffer - out of memoryn");
  290. kfree_skb(skb);
  291. return;
  292. }
  293. if (skb->sk != NULL)
  294. skb_set_owner_w(skbn, skb->sk);
  295. kfree_skb(skb);
  296. skb = skbn;
  297. }
  298. ptr = skb_push(skb, headroom);
  299. ax25_addr_build(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type, ax25->modulus);
  300. skb->dev = ax25->ax25_dev->dev;
  301. ax25_queue_xmit(skb);
  302. }
  303. /*
  304.  * A small shim to dev_queue_xmit to add the KISS control byte, and do
  305.  * any packet forwarding in operation.
  306.  */
  307. void ax25_queue_xmit(struct sk_buff *skb)
  308. {
  309. unsigned char *ptr;
  310. skb->protocol = htons(ETH_P_AX25);
  311. skb->dev      = ax25_fwd_dev(skb->dev);
  312. ptr  = skb_push(skb, 1);
  313. *ptr = 0x00; /* KISS */
  314. dev_queue_xmit(skb);
  315. }
  316. int ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
  317. {
  318. if (ax25->vs == nr) {
  319. ax25_frames_acked(ax25, nr);
  320. ax25_calculate_rtt(ax25);
  321. ax25_stop_t1timer(ax25);
  322. ax25_start_t3timer(ax25);
  323. return 1;
  324. } else {
  325. if (ax25->va != nr) {
  326. ax25_frames_acked(ax25, nr);
  327. ax25_calculate_t1(ax25);
  328. ax25_start_t1timer(ax25);
  329. return 1;
  330. }
  331. }
  332. return 0;
  333. }