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_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 #include <linux/config.h>
28 #ifdef CONFIG_AX25
29 #include <linux/errno.h>
30 #include <linux/types.h>
31 #include <linux/socket.h>
32 #include <linux/in.h>
33 #include <linux/kernel.h>
34 #include <linux/sched.h>
35 #include <linux/timer.h>
36 #include <linux/string.h>
37 #include <linux/sockios.h>
38 #include <linux/net.h>
39 #include <net/ax25.h>
40 #include <linux/inet.h>
41 #include <linux/netdevice.h>
42 #include <linux/skbuff.h>
43 #include <net/sock.h>
44 #include <asm/segment.h>
45 #include <asm/system.h>
46 #include <linux/fcntl.h>
47 #include <linux/mm.h>
48 #include <linux/interrupt.h>
49
50 int ax25_output(ax25_cb *ax25, struct sk_buff *skb)
51 {
52 skb_queue_tail(&ax25->write_queue, skb);
53
54 if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4)
55 ax25_kick(ax25);
56
57 return 0;
58 }
59
60
61
62
63
64 static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit)
65 {
66 unsigned char *frame;
67
68 if (skb == NULL)
69 return;
70
71 frame = skb_push(skb, 1);
72
73 *frame = I;
74 *frame |= poll_bit;
75 *frame |= (ax25->vr << 5);
76 *frame |= (ax25->vs << 1);
77
78 ax25_transmit_buffer(ax25, skb, C_COMMAND);
79 }
80
81 void ax25_kick(ax25_cb *ax25)
82 {
83 struct sk_buff *skb, *skbn;
84 int last = 1;
85 unsigned short start, end, next;
86
87 del_timer(&ax25->timer);
88
89 start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs;
90 end = (ax25->va + ax25->window) % MODULUS;
91
92 if (!(ax25->condition & PEER_RX_BUSY_CONDITION) &&
93 start != end &&
94 skb_peek(&ax25->write_queue) != NULL) {
95
96 ax25->vs = start;
97
98
99
100
101
102
103 do {
104
105
106
107 skb = skb_dequeue(&ax25->write_queue);
108
109 if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
110 skb_queue_head(&ax25->write_queue, skb);
111 return;
112 }
113
114 next = (ax25->vs + 1) % MODULUS;
115 #ifdef notdef
116 last = (next == end) || skb_peek(&ax25->write_queue) == NULL;
117 #else
118 last = (next == end);
119 #endif
120
121
122
123 ax25_send_iframe(ax25, skbn, (last) ? PF : 0);
124
125 ax25->vs = next;
126
127
128
129
130 skb_queue_tail(&ax25->ack_queue, skb);
131 #ifdef notdef
132 } while (!last);
133 #else
134 } while (!last && skb_peek(&ax25->write_queue) != NULL);
135 #endif
136 ax25->condition &= ~ACK_PENDING_CONDITION;
137
138 if (ax25->t1timer == 0) {
139 ax25->t3timer = 0;
140 ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
141 }
142 }
143
144 ax25_set_timer(ax25);
145 }
146
147 void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
148 {
149 unsigned char *ptr;
150
151 if (ax25->device == NULL) {
152 if (ax25->sk != NULL) {
153 ax25->sk->state = TCP_CLOSE;
154 ax25->sk->err = ENETUNREACH;
155 if (!ax25->sk->dead)
156 ax25->sk->state_change(ax25->sk);
157 ax25->sk->dead = 1;
158 }
159 return;
160 }
161
162 if (skb_headroom(skb) < size_ax25_addr(ax25->digipeat)) {
163 printk("ax25_transmit_buffer: not enough room for digi-peaters\n");
164 skb->free = 1;
165 kfree_skb(skb, FREE_WRITE);
166 return;
167 }
168
169 ptr = skb_push(skb, size_ax25_addr(ax25->digipeat));
170 build_ax25_addr(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type);
171
172 skb->arp = 1;
173
174 ax25_queue_xmit(skb, ax25->device, SOPRI_NORMAL);
175 }
176
177
178
179
180
181
182 void ax25_nr_error_recovery(ax25_cb *ax25)
183 {
184 ax25_establish_data_link(ax25);
185 }
186
187 void ax25_establish_data_link(ax25_cb *ax25)
188 {
189 ax25->condition = 0x00;
190 ax25->n2count = 0;
191
192 ax25_send_control(ax25, SABM | PF, C_COMMAND);
193
194 ax25->t3timer = 0;
195 ax25->t2timer = 0;
196 ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
197 }
198
199 void ax25_transmit_enquiry(ax25_cb *ax25)
200 {
201 if (ax25->condition & OWN_RX_BUSY_CONDITION)
202 ax25_send_control(ax25, RNR | PF, C_COMMAND);
203 else
204 ax25_send_control(ax25, RR | PF, C_COMMAND);
205
206 ax25->condition &= ~ACK_PENDING_CONDITION;
207
208 ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
209 }
210
211 void ax25_enquiry_response(ax25_cb *ax25)
212 {
213 if (ax25->condition & OWN_RX_BUSY_CONDITION)
214 ax25_send_control(ax25, RNR | PF, C_RESPONSE);
215 else
216 ax25_send_control(ax25, RR | PF, C_RESPONSE);
217
218 ax25->condition &= ~ACK_PENDING_CONDITION;
219 }
220
221 void ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
222 {
223 if (ax25->vs == nr) {
224 ax25_frames_acked(ax25, nr);
225 ax25_calculate_rtt(ax25);
226 ax25->t1timer = 0;
227 ax25->t3timer = ax25->t3;
228 } else {
229 if (ax25->va != nr) {
230 ax25_frames_acked(ax25, nr);
231 ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
232 }
233 }
234 }
235
236 void ax25_check_need_response(ax25_cb *ax25, int type, int pf)
237 {
238 if (type == C_COMMAND && pf)
239 ax25_enquiry_response(ax25);
240 }
241
242 #endif