OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [netrom/] [nr_subr.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      NET/ROM release 007
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
 *      History
13
 *      NET/ROM 001     Jonathan(G4KLX) Cloned from ax25_subr.c
14
 *      NET/ROM 003     Jonathan(G4KLX) Added G8BPQ NET/ROM extensions.
15
 *      NET/ROM 007     Jonathan(G4KLX) New timer architecture.
16
 */
17
 
18
#include <linux/errno.h>
19
#include <linux/types.h>
20
#include <linux/socket.h>
21
#include <linux/in.h>
22
#include <linux/kernel.h>
23
#include <linux/sched.h>
24
#include <linux/timer.h>
25
#include <linux/string.h>
26
#include <linux/sockios.h>
27
#include <linux/net.h>
28
#include <net/ax25.h>
29
#include <linux/inet.h>
30
#include <linux/netdevice.h>
31
#include <linux/skbuff.h>
32
#include <net/sock.h>
33
#include <asm/uaccess.h>
34
#include <asm/system.h>
35
#include <linux/fcntl.h>
36
#include <linux/mm.h>
37
#include <linux/interrupt.h>
38
#include <net/netrom.h>
39
 
40
/*
41
 *      This routine purges all of the queues of frames.
42
 */
43
void nr_clear_queues(struct sock *sk)
44
{
45
        skb_queue_purge(&sk->write_queue);
46
        skb_queue_purge(&sk->protinfo.nr->ack_queue);
47
        skb_queue_purge(&sk->protinfo.nr->reseq_queue);
48
        skb_queue_purge(&sk->protinfo.nr->frag_queue);
49
}
50
 
51
/*
52
 * This routine purges the input queue of those frames that have been
53
 * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
54
 * SDL diagram.
55
 */
56
void nr_frames_acked(struct sock *sk, unsigned short nr)
57
{
58
        struct sk_buff *skb;
59
 
60
        /*
61
         * Remove all the ack-ed frames from the ack queue.
62
         */
63
        if (sk->protinfo.nr->va != nr) {
64
                while (skb_peek(&sk->protinfo.nr->ack_queue) != NULL && sk->protinfo.nr->va != nr) {
65
                        skb = skb_dequeue(&sk->protinfo.nr->ack_queue);
66
                        kfree_skb(skb);
67
                        sk->protinfo.nr->va = (sk->protinfo.nr->va + 1) % NR_MODULUS;
68
                }
69
        }
70
}
71
 
72
/*
73
 * Requeue all the un-ack-ed frames on the output queue to be picked
74
 * up by nr_kick called from the timer. This arrangement handles the
75
 * possibility of an empty output queue.
76
 */
77
void nr_requeue_frames(struct sock *sk)
78
{
79
        struct sk_buff *skb, *skb_prev = NULL;
80
 
81
        while ((skb = skb_dequeue(&sk->protinfo.nr->ack_queue)) != NULL) {
82
                if (skb_prev == NULL)
83
                        skb_queue_head(&sk->write_queue, skb);
84
                else
85
                        skb_append(skb_prev, skb);
86
                skb_prev = skb;
87
        }
88
}
89
 
90
/*
91
 *      Validate that the value of nr is between va and vs. Return true or
92
 *      false for testing.
93
 */
94
int nr_validate_nr(struct sock *sk, unsigned short nr)
95
{
96
        unsigned short vc = sk->protinfo.nr->va;
97
 
98
        while (vc != sk->protinfo.nr->vs) {
99
                if (nr == vc) return 1;
100
                vc = (vc + 1) % NR_MODULUS;
101
        }
102
 
103
        if (nr == sk->protinfo.nr->vs) return 1;
104
 
105
        return 0;
106
}
107
 
108
/*
109
 *      Check that ns is within the receive window.
110
 */
111
int nr_in_rx_window(struct sock *sk, unsigned short ns)
112
{
113
        unsigned short vc = sk->protinfo.nr->vr;
114
        unsigned short vt = (sk->protinfo.nr->vl + sk->protinfo.nr->window) % NR_MODULUS;
115
 
116
        while (vc != vt) {
117
                if (ns == vc) return 1;
118
                vc = (vc + 1) % NR_MODULUS;
119
        }
120
 
121
        return 0;
122
}
123
 
124
/*
125
 *  This routine is called when the HDLC layer internally generates a
126
 *  control frame.
127
 */
128
void nr_write_internal(struct sock *sk, int frametype)
129
{
130
        struct sk_buff *skb;
131
        unsigned char  *dptr;
132
        int len, timeout;
133
 
134
        len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN + NR_TRANSPORT_LEN;
135
 
136
        switch (frametype & 0x0F) {
137
                case NR_CONNREQ:
138
                        len += 17;
139
                        break;
140
                case NR_CONNACK:
141
                        len += (sk->protinfo.nr->bpqext) ? 2 : 1;
142
                        break;
143
                case NR_DISCREQ:
144
                case NR_DISCACK:
145
                case NR_INFOACK:
146
                        break;
147
                default:
148
                        printk(KERN_ERR "NET/ROM: nr_write_internal - invalid frame type %d\n", frametype);
149
                        return;
150
        }
151
 
152
        if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
153
                return;
154
 
155
        /*
156
         *      Space for AX.25 and NET/ROM network header
157
         */
158
        skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN);
159
 
160
        dptr = skb_put(skb, skb_tailroom(skb));
161
 
162
        switch (frametype & 0x0F) {
163
 
164
                case NR_CONNREQ:
165
                        timeout  = sk->protinfo.nr->t1 / HZ;
166
                        *dptr++  = sk->protinfo.nr->my_index;
167
                        *dptr++  = sk->protinfo.nr->my_id;
168
                        *dptr++  = 0;
169
                        *dptr++  = 0;
170
                        *dptr++  = frametype;
171
                        *dptr++  = sk->protinfo.nr->window;
172
                        memcpy(dptr, &sk->protinfo.nr->user_addr, AX25_ADDR_LEN);
173
                        dptr[6] &= ~AX25_CBIT;
174
                        dptr[6] &= ~AX25_EBIT;
175
                        dptr[6] |= AX25_SSSID_SPARE;
176
                        dptr    += AX25_ADDR_LEN;
177
                        memcpy(dptr, &sk->protinfo.nr->source_addr, AX25_ADDR_LEN);
178
                        dptr[6] &= ~AX25_CBIT;
179
                        dptr[6] &= ~AX25_EBIT;
180
                        dptr[6] |= AX25_SSSID_SPARE;
181
                        dptr    += AX25_ADDR_LEN;
182
                        *dptr++  = timeout % 256;
183
                        *dptr++  = timeout / 256;
184
                        break;
185
 
186
                case NR_CONNACK:
187
                        *dptr++ = sk->protinfo.nr->your_index;
188
                        *dptr++ = sk->protinfo.nr->your_id;
189
                        *dptr++ = sk->protinfo.nr->my_index;
190
                        *dptr++ = sk->protinfo.nr->my_id;
191
                        *dptr++ = frametype;
192
                        *dptr++ = sk->protinfo.nr->window;
193
                        if (sk->protinfo.nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser;
194
                        break;
195
 
196
                case NR_DISCREQ:
197
                case NR_DISCACK:
198
                        *dptr++ = sk->protinfo.nr->your_index;
199
                        *dptr++ = sk->protinfo.nr->your_id;
200
                        *dptr++ = 0;
201
                        *dptr++ = 0;
202
                        *dptr++ = frametype;
203
                        break;
204
 
205
                case NR_INFOACK:
206
                        *dptr++ = sk->protinfo.nr->your_index;
207
                        *dptr++ = sk->protinfo.nr->your_id;
208
                        *dptr++ = 0;
209
                        *dptr++ = sk->protinfo.nr->vr;
210
                        *dptr++ = frametype;
211
                        break;
212
        }
213
 
214
        nr_transmit_buffer(sk, skb);
215
}
216
 
217
/*
218
 * This routine is called when a Connect Acknowledge with the Choke Flag
219
 * set is needed to refuse a connection.
220
 */
221
void nr_transmit_refusal(struct sk_buff *skb, int mine)
222
{
223
        struct sk_buff *skbn;
224
        unsigned char *dptr;
225
        int len;
226
 
227
        len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN + NR_TRANSPORT_LEN + 1;
228
 
229
        if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL)
230
                return;
231
 
232
        skb_reserve(skbn, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);
233
 
234
        dptr = skb_put(skbn, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
235
 
236
        memcpy(dptr, skb->data + 7, AX25_ADDR_LEN);
237
        dptr[6] &= ~AX25_CBIT;
238
        dptr[6] &= ~AX25_EBIT;
239
        dptr[6] |= AX25_SSSID_SPARE;
240
        dptr += AX25_ADDR_LEN;
241
 
242
        memcpy(dptr, skb->data + 0, AX25_ADDR_LEN);
243
        dptr[6] &= ~AX25_CBIT;
244
        dptr[6] |= AX25_EBIT;
245
        dptr[6] |= AX25_SSSID_SPARE;
246
        dptr += AX25_ADDR_LEN;
247
 
248
        *dptr++ = sysctl_netrom_network_ttl_initialiser;
249
 
250
        if (mine) {
251
                *dptr++ = 0;
252
                *dptr++ = 0;
253
                *dptr++ = skb->data[15];
254
                *dptr++ = skb->data[16];
255
        } else {
256
                *dptr++ = skb->data[15];
257
                *dptr++ = skb->data[16];
258
                *dptr++ = 0;
259
                *dptr++ = 0;
260
        }
261
 
262
        *dptr++ = NR_CONNACK | NR_CHOKE_FLAG;
263
        *dptr++ = 0;
264
 
265
        if (!nr_route_frame(skbn, NULL))
266
                kfree_skb(skbn);
267
}
268
 
269
void nr_disconnect(struct sock *sk, int reason)
270
{
271
        nr_stop_t1timer(sk);
272
        nr_stop_t2timer(sk);
273
        nr_stop_t4timer(sk);
274
        nr_stop_idletimer(sk);
275
 
276
        nr_clear_queues(sk);
277
 
278
        sk->protinfo.nr->state = NR_STATE_0;
279
 
280
        sk->state     = TCP_CLOSE;
281
        sk->err       = reason;
282
        sk->shutdown |= SEND_SHUTDOWN;
283
 
284
        if (!sk->dead)
285
                sk->state_change(sk);
286
 
287
        sk->dead = 1;
288
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.