1 /*
2 * AX.25 release 029
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 1.2.1 or higher/ NET3.029
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 * AX.25 028a Jonathan(G4KLX) New state machine based on SDL diagrams.
17 * AX.25 028b Jonathan(G4KLX) Extracted AX25 control block from the
18 * sock structure.
19 * AX.25 029 Alan(GW4PTS) Switched to KA9Q constant names.
20 */
21
22 #include <linux/config.h>
23 #ifdef CONFIG_AX25
24 #include <linux/errno.h>
25 #include <linux/types.h>
26 #include <linux/socket.h>
27 #include <linux/in.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/timer.h>
31 #include <linux/string.h>
32 #include <linux/sockios.h>
33 #include <linux/net.h>
34 #include <net/ax25.h>
35 #include <linux/inet.h>
36 #include <linux/netdevice.h>
37 #include <linux/skbuff.h>
38 #include <net/sock.h>
39 #include <asm/segment.h>
40 #include <asm/system.h>
41 #include <linux/fcntl.h>
42 #include <linux/mm.h>
43 #include <linux/interrupt.h>
44 #ifdef CONFIG_NETROM
45 #include <net/netrom.h>
46 #endif
47
48 static void ax25_timer(unsigned long);
49
50 /*
51 * Linux set/reset timer routines
52 */
53 void ax25_set_timer(ax25_cb *ax25)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
54 {
55 unsigned long flags;
56
57 save_flags(flags);
58 cli();
59 del_timer(&ax25->timer);
60 restore_flags(flags);
61
62 ax25->timer.next = ax25->timer.prev = NULL;
63 ax25->timer.data = (unsigned long)ax25;
64 ax25->timer.function = &ax25_timer;
65
66 ax25->timer.expires = 10;
67 add_timer(&ax25->timer);
68 }
69
70 static void ax25_reset_timer(ax25_cb *ax25)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
71 {
72 unsigned long flags;
73
74 save_flags(flags);
75 cli();
76 del_timer(&ax25->timer);
77 restore_flags(flags);
78
79 ax25->timer.data = (unsigned long)ax25;
80 ax25->timer.function = &ax25_timer;
81 ax25->timer.expires = 10;
82 add_timer(&ax25->timer);
83 }
84
85 /*
86 * AX.25 TIMER
87 *
88 * This routine is called every 500ms. Decrement timer by this
89 * amount - if expired then process the event.
90 */
91 static void ax25_timer(unsigned long param)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
92 {
93 ax25_cb *ax25 = (ax25_cb *)param;
94
95 switch (ax25->state) {
96 case AX25_STATE_0:
97 /* Magic here: If we listen() and a new link dies before it
98 is accepted() it isnt 'dead' so doesnt get removed. */
99 if ((ax25->sk != NULL && ax25->sk->dead) || ax25->sk == NULL) {
100 del_timer(&ax25->timer);
101 ax25_destroy_socket(ax25);
102 return;
103 }
104 break;
105
106 case AX25_STATE_3:
107 case AX25_STATE_4:
108 /*
109 * Check the state of the receive buffer.
110 */
111 if (ax25->sk != NULL) {
112 if (ax25->sk->rmem_alloc < (ax25->sk->rcvbuf / 2) && (ax25->condition & OWN_RX_BUSY_CONDITION)) {
113 ax25->condition &= ~OWN_RX_BUSY_CONDITION;
114 ax25_send_control(ax25, RR, C_RESPONSE);
115 ax25->condition &= ~ACK_PENDING_CONDITION;
116 break;
117 }
118 }
119 /*
120 * Check for frames to transmit.
121 */
122 ax25_kick(ax25);
123 break;
124
125 default:
126 break;
127 }
128
129 if (ax25->t2timer > 0 && --ax25->t2timer == 0) {
130 if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) {
131 if (ax25->condition & ACK_PENDING_CONDITION) {
132 ax25->condition &= ~ACK_PENDING_CONDITION;
133 ax25_enquiry_response(ax25);
134 }
135 }
136 }
137
138 if (ax25->t3timer > 0 && --ax25->t3timer == 0) {
139 if (ax25->state == AX25_STATE_3) {
140 ax25->n2count = 0;
141 ax25_transmit_enquiry(ax25);
142 ax25->state = AX25_STATE_4;
143 }
144 ax25->t3timer = ax25->t3;
145 }
146
147 if (ax25->t1timer == 0 || --ax25->t1timer > 0) {
148 ax25_reset_timer(ax25);
149 return;
150 }
151
152 switch (ax25->state) {
153 case AX25_STATE_1:
154 if (ax25->n2count == ax25->n2) {
155 #ifdef CONFIG_NETROM
156 nr_link_failed(&ax25->dest_addr, ax25->device);
157 #endif
158 ax25_clear_tx_queue(ax25);
159 ax25->state = AX25_STATE_0;
160 if (ax25->sk != NULL) {
161 ax25->sk->state = TCP_CLOSE;
162 ax25->sk->err = ETIMEDOUT;
163 if (!ax25->sk->dead)
164 ax25->sk->state_change(ax25->sk);
165 ax25->sk->dead = 1;
166 }
167 } else {
168 ax25->n2count++;
169 ax25_send_control(ax25, SABM | PF, C_COMMAND);
170 }
171 break;
172
173 case AX25_STATE_2:
174 if (ax25->n2count == ax25->n2) {
175 #ifdef CONFIG_NETROM
176 nr_link_failed(&ax25->dest_addr, ax25->device);
177 #endif
178 ax25_clear_tx_queue(ax25);
179 ax25->state = AX25_STATE_0;
180 if (ax25->sk != NULL) {
181 ax25->sk->state = TCP_CLOSE;
182 ax25->sk->err = ETIMEDOUT;
183 if (!ax25->sk->dead)
184 ax25->sk->state_change(ax25->sk);
185 ax25->sk->dead = 1;
186 }
187 } else {
188 ax25->n2count++;
189 ax25_send_control(ax25, DISC | PF, C_COMMAND);
190 }
191 break;
192
193 case AX25_STATE_3:
194 ax25->n2count = 1;
195 ax25_transmit_enquiry(ax25);
196 ax25->state = AX25_STATE_4;
197 break;
198
199 case AX25_STATE_4:
200 if (ax25->n2count == ax25->n2) {
201 #ifdef CONFIG_NETROM
202 nr_link_failed(&ax25->dest_addr, ax25->device);
203 #endif
204 ax25_clear_tx_queue(ax25);
205 ax25_send_control(ax25, DM | PF, C_RESPONSE);
206 ax25->state = AX25_STATE_0;
207 if (ax25->sk != NULL) {
208 ax25->sk->state = TCP_CLOSE;
209 ax25->sk->err = ETIMEDOUT;
210 if (!ax25->sk->dead)
211 ax25->sk->state_change(ax25->sk);
212 ax25->sk->dead = 1;
213 }
214 } else {
215 ax25->n2count++;
216 ax25_transmit_enquiry(ax25);
217 }
218 break;
219 }
220
221 ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
222
223 ax25_set_timer(ax25);
224 }
225
226 #endif