This source file includes following definitions.
- ax25_output
- ax25_send_iframe
- ax25_kick
- ax25_transmit_buffer
- ax25_nr_error_recovery
- ax25_establish_data_link
- ax25_transmit_enquiry
- ax25_enquiry_response
- ax25_timeout_response
- ax25_check_iframes_acked
- ax25_check_need_response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <linux/config.h>
30 #ifdef CONFIG_AX25
31 #include <linux/errno.h>
32 #include <linux/types.h>
33 #include <linux/socket.h>
34 #include <linux/in.h>
35 #include <linux/kernel.h>
36 #include <linux/sched.h>
37 #include <linux/timer.h>
38 #include <linux/string.h>
39 #include <linux/sockios.h>
40 #include <linux/net.h>
41 #include <net/ax25.h>
42 #include <linux/inet.h>
43 #include <linux/netdevice.h>
44 #include <linux/skbuff.h>
45 #include <net/sock.h>
46 #include <asm/segment.h>
47 #include <asm/system.h>
48 #include <linux/fcntl.h>
49 #include <linux/mm.h>
50 #include <linux/interrupt.h>
51
52
53
54
55
56 void ax25_output(ax25_cb *ax25, struct sk_buff *skb)
57 {
58 struct sk_buff *skbn;
59 unsigned char *p;
60 int err, frontlen, mtu, len, fragno, first = 1;
61
62 mtu = ax25->device->mtu;
63
64 if ((skb->len - 1) > mtu) {
65 mtu -= 2;
66
67 fragno = skb->len / mtu;
68 if (skb->len % mtu == 0) fragno--;
69
70 frontlen = skb_headroom(skb);
71
72 while (skb->len > 0) {
73 if (skb->sk != NULL) {
74 if ((skbn = sock_alloc_send_skb(skb->sk, mtu + 2 + frontlen, 0, 0, &err)) == NULL)
75 return;
76 } else {
77 if ((skbn = alloc_skb(mtu + 2 + frontlen, GFP_ATOMIC)) == NULL)
78 return;
79 }
80
81 skbn->sk = skb->sk;
82 skbn->free = 1;
83 skbn->arp = 1;
84
85 skb_reserve(skbn, frontlen + 2);
86
87 len = (mtu > skb->len) ? skb->len : mtu;
88
89 memcpy(skb_put(skbn, len), skb->data, len);
90 skb_pull(skb, len);
91
92 p = skb_push(skbn, 2);
93
94 *p++ = AX25_P_SEGMENT;
95
96 *p = fragno--;
97 if (first) {
98 *p |= SEG_FIRST;
99 first = 0;
100 }
101
102 skb_queue_tail(&ax25->write_queue, skbn);
103 }
104
105 skb->free = 1;
106 kfree_skb(skb, FREE_WRITE);
107 } else {
108 skb_queue_tail(&ax25->write_queue, skb);
109 }
110
111 if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4)
112 ax25_kick(ax25);
113 }
114
115
116
117
118
119 static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit)
120 {
121 unsigned char *frame;
122
123 if (skb == NULL)
124 return;
125
126 if (ax25->modulus == MODULUS) {
127 frame = skb_push(skb, 1);
128
129 *frame = I;
130 *frame |= (poll_bit) ? PF : 0;
131 *frame |= (ax25->vr << 5);
132 *frame |= (ax25->vs << 1);
133 } else {
134 frame = skb_push(skb, 2);
135
136 frame[0] = I;
137 frame[0] |= (ax25->vs << 1);
138 frame[1] = (poll_bit) ? EPF : 0;
139 frame[1] |= (ax25->vr << 1);
140 }
141
142 ax25_transmit_buffer(ax25, skb, C_COMMAND);
143 }
144
145 void ax25_kick(ax25_cb *ax25)
146 {
147 struct sk_buff *skb, *skbn;
148 int last = 1;
149 unsigned short start, end, next;
150
151 del_timer(&ax25->timer);
152
153 start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs;
154 end = (ax25->va + ax25->window) % ax25->modulus;
155
156 if (!(ax25->condition & PEER_RX_BUSY_CONDITION) &&
157 start != end &&
158 skb_peek(&ax25->write_queue) != NULL) {
159
160 ax25->vs = start;
161
162
163
164
165
166
167
168
169
170
171 skb = skb_dequeue(&ax25->write_queue);
172
173 do {
174 if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
175 skb_queue_head(&ax25->write_queue, skb);
176 return;
177 }
178
179 next = (ax25->vs + 1) % ax25->modulus;
180 #ifdef notdef
181 last = (next == end) || skb_peek(&ax25->write_queue) == NULL;
182 #else
183 last = (next == end);
184 #endif
185
186
187
188 ax25_send_iframe(ax25, skbn, (last) ? POLLON : POLLOFF);
189
190 ax25->vs = next;
191
192
193
194
195 skb_queue_tail(&ax25->ack_queue, skb);
196 #ifdef notdef
197 } while (!last);
198 #else
199 } while (!last && (skb = skb_dequeue(&ax25->write_queue)) != NULL);
200 #endif
201 ax25->condition &= ~ACK_PENDING_CONDITION;
202
203 if (ax25->t1timer == 0) {
204 ax25->t3timer = 0;
205 ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
206 }
207 }
208
209 ax25_set_timer(ax25);
210 }
211
212 void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
213 {
214 unsigned char *ptr;
215
216 if (ax25->device == NULL) {
217 if (ax25->sk != NULL) {
218 ax25->sk->state = TCP_CLOSE;
219 ax25->sk->err = ENETUNREACH;
220 if (!ax25->sk->dead)
221 ax25->sk->state_change(ax25->sk);
222 ax25->sk->dead = 1;
223 }
224 return;
225 }
226
227 if (skb_headroom(skb) < size_ax25_addr(ax25->digipeat)) {
228 printk("ax25_transmit_buffer: not enough room for digi-peaters\n");
229 skb->free = 1;
230 kfree_skb(skb, FREE_WRITE);
231 return;
232 }
233
234 ptr = skb_push(skb, size_ax25_addr(ax25->digipeat));
235 build_ax25_addr(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type, ax25->modulus);
236
237 skb->arp = 1;
238
239 ax25_queue_xmit(skb, ax25->device, SOPRI_NORMAL);
240 }
241
242
243
244
245
246
247 void ax25_nr_error_recovery(ax25_cb *ax25)
248 {
249 ax25_establish_data_link(ax25);
250 }
251
252 void ax25_establish_data_link(ax25_cb *ax25)
253 {
254 ax25->condition = 0x00;
255 ax25->n2count = 0;
256
257 if (ax25->modulus == MODULUS) {
258 ax25_send_control(ax25, SABM, POLLON, C_COMMAND);
259 } else {
260 ax25_send_control(ax25, SABME, POLLON, C_COMMAND);
261 }
262
263 ax25->t3timer = 0;
264 ax25->t2timer = 0;
265 ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
266 }
267
268 void ax25_transmit_enquiry(ax25_cb *ax25)
269 {
270 if (ax25->condition & OWN_RX_BUSY_CONDITION)
271 ax25_send_control(ax25, RNR, POLLON, C_COMMAND);
272 else
273 ax25_send_control(ax25, RR, POLLON, C_COMMAND);
274
275 ax25->condition &= ~ACK_PENDING_CONDITION;
276
277 ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
278 }
279
280 void ax25_enquiry_response(ax25_cb *ax25)
281 {
282 if (ax25->condition & OWN_RX_BUSY_CONDITION)
283 ax25_send_control(ax25, RNR, POLLON, C_RESPONSE);
284 else
285 ax25_send_control(ax25, RR, POLLON, C_RESPONSE);
286
287 ax25->condition &= ~ACK_PENDING_CONDITION;
288 }
289
290 void ax25_timeout_response(ax25_cb *ax25)
291 {
292 if (ax25->condition & OWN_RX_BUSY_CONDITION)
293 ax25_send_control(ax25, RNR, POLLOFF, C_RESPONSE);
294 else
295 ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE);
296
297 ax25->condition &= ~ACK_PENDING_CONDITION;
298 }
299
300 void ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
301 {
302 if (ax25->vs == nr) {
303 ax25_frames_acked(ax25, nr);
304 ax25_calculate_rtt(ax25);
305 ax25->t1timer = 0;
306 ax25->t3timer = ax25->t3;
307 } else {
308 if (ax25->va != nr) {
309 ax25_frames_acked(ax25, nr);
310 ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
311 }
312 }
313 }
314
315 void ax25_check_need_response(ax25_cb *ax25, int type, int pf)
316 {
317 if (type == C_COMMAND && pf)
318 ax25_enquiry_response(ax25);
319 }
320
321 #endif