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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [x25/] [x25_facilities.c] - Blame information for rev 79

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *      X.25 Packet Layer release 002
3
 *
4
 *      This is ALPHA test software. This code may break your machine,
5
 *      randomly fail to work with new releases, misbehave and/or generally
6
 *      screw up. It might even work.
7
 *
8
 *      This code REQUIRES 2.1.15 or higher
9
 *
10
 *      This module:
11
 *              This module is free software; you can redistribute it and/or
12
 *              modify it under the terms of the GNU General Public License
13
 *              as published by the Free Software Foundation; either version
14
 *              2 of the License, or (at your option) any later version.
15
 *
16
 *      History
17
 *      X.25 001        Split from x25_subr.c
18
 *      mar/20/00       Daniela Squassoni Disabling/enabling of facilities
19
 *                                        negotiation.
20
 *      apr/14/05       Shaun Pereira - Allow fast select with no restriction
21
 *                                      on response.
22
 */
23
 
24
#include <linux/kernel.h>
25
#include <linux/string.h>
26
#include <linux/skbuff.h>
27
#include <net/sock.h>
28
#include <net/x25.h>
29
 
30
/*
31
 * Parse a set of facilities into the facilities structures. Unrecognised
32
 *      facilities are written to the debug log file.
33
 */
34
int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
35
                struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)
36
{
37
        unsigned char *p = skb->data;
38
        unsigned int len = *p++;
39
 
40
        *vc_fac_mask = 0;
41
 
42
        /*
43
         * The kernel knows which facilities were set on an incoming call but
44
         * currently this information is not available to userspace.  Here we
45
         * give userspace who read incoming call facilities 0 length to indicate
46
         * it wasn't set.
47
         */
48
        dte_facs->calling_len = 0;
49
        dte_facs->called_len = 0;
50
        memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));
51
        memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae));
52
 
53
        while (len > 0) {
54
                switch (*p & X25_FAC_CLASS_MASK) {
55
                case X25_FAC_CLASS_A:
56
                        switch (*p) {
57
                        case X25_FAC_REVERSE:
58
                                if((p[1] & 0x81) == 0x81) {
59
                                        facilities->reverse = p[1] & 0x81;
60
                                        *vc_fac_mask |= X25_MASK_REVERSE;
61
                                        break;
62
                                }
63
 
64
                                if((p[1] & 0x01) == 0x01) {
65
                                        facilities->reverse = p[1] & 0x01;
66
                                        *vc_fac_mask |= X25_MASK_REVERSE;
67
                                        break;
68
                                }
69
 
70
                                if((p[1] & 0x80) == 0x80) {
71
                                        facilities->reverse = p[1] & 0x80;
72
                                        *vc_fac_mask |= X25_MASK_REVERSE;
73
                                        break;
74
                                }
75
 
76
                                if(p[1] == 0x00) {
77
                                        facilities->reverse
78
                                                = X25_DEFAULT_REVERSE;
79
                                        *vc_fac_mask |= X25_MASK_REVERSE;
80
                                        break;
81
                                }
82
 
83
                        case X25_FAC_THROUGHPUT:
84
                                facilities->throughput = p[1];
85
                                *vc_fac_mask |= X25_MASK_THROUGHPUT;
86
                                break;
87
                        case X25_MARKER:
88
                                break;
89
                        default:
90
                                printk(KERN_DEBUG "X.25: unknown facility "
91
                                       "%02X, value %02X\n",
92
                                       p[0], p[1]);
93
                                break;
94
                        }
95
                        p   += 2;
96
                        len -= 2;
97
                        break;
98
                case X25_FAC_CLASS_B:
99
                        switch (*p) {
100
                        case X25_FAC_PACKET_SIZE:
101
                                facilities->pacsize_in  = p[1];
102
                                facilities->pacsize_out = p[2];
103
                                *vc_fac_mask |= X25_MASK_PACKET_SIZE;
104
                                break;
105
                        case X25_FAC_WINDOW_SIZE:
106
                                facilities->winsize_in  = p[1];
107
                                facilities->winsize_out = p[2];
108
                                *vc_fac_mask |= X25_MASK_WINDOW_SIZE;
109
                                break;
110
                        default:
111
                                printk(KERN_DEBUG "X.25: unknown facility "
112
                                       "%02X, values %02X, %02X\n",
113
                                       p[0], p[1], p[2]);
114
                                break;
115
                        }
116
                        p   += 3;
117
                        len -= 3;
118
                        break;
119
                case X25_FAC_CLASS_C:
120
                        printk(KERN_DEBUG "X.25: unknown facility %02X, "
121
                               "values %02X, %02X, %02X\n",
122
                               p[0], p[1], p[2], p[3]);
123
                        p   += 4;
124
                        len -= 4;
125
                        break;
126
                case X25_FAC_CLASS_D:
127
                        switch (*p) {
128
                        case X25_FAC_CALLING_AE:
129
                                if (p[1] > X25_MAX_DTE_FACIL_LEN)
130
                                        break;
131
                                dte_facs->calling_len = p[2];
132
                                memcpy(dte_facs->calling_ae, &p[3], p[1] - 1);
133
                                *vc_fac_mask |= X25_MASK_CALLING_AE;
134
                                break;
135
                        case X25_FAC_CALLED_AE:
136
                                if (p[1] > X25_MAX_DTE_FACIL_LEN)
137
                                        break;
138
                                dte_facs->called_len = p[2];
139
                                memcpy(dte_facs->called_ae, &p[3], p[1] - 1);
140
                                *vc_fac_mask |= X25_MASK_CALLED_AE;
141
                                break;
142
                        default:
143
                                printk(KERN_DEBUG "X.25: unknown facility %02X,"
144
                                        "length %d, values %02X, %02X, "
145
                                        "%02X, %02X\n",
146
                                        p[0], p[1], p[2], p[3], p[4], p[5]);
147
                                break;
148
                        }
149
                        len -= p[1] + 2;
150
                        p += p[1] + 2;
151
                        break;
152
                }
153
        }
154
 
155
        return p - skb->data;
156
}
157
 
158
/*
159
 *      Create a set of facilities.
160
 */
161
int x25_create_facilities(unsigned char *buffer,
162
                struct x25_facilities *facilities,
163
                struct x25_dte_facilities *dte_facs, unsigned long facil_mask)
164
{
165
        unsigned char *p = buffer + 1;
166
        int len;
167
 
168
        if (!facil_mask) {
169
                /*
170
                 * Length of the facilities field in call_req or
171
                 * call_accept packets
172
                 */
173
                buffer[0] = 0;
174
                len = 1; /* 1 byte for the length field */
175
                return len;
176
        }
177
 
178
        if (facilities->reverse && (facil_mask & X25_MASK_REVERSE)) {
179
                *p++ = X25_FAC_REVERSE;
180
                *p++ = facilities->reverse;
181
        }
182
 
183
        if (facilities->throughput && (facil_mask & X25_MASK_THROUGHPUT)) {
184
                *p++ = X25_FAC_THROUGHPUT;
185
                *p++ = facilities->throughput;
186
        }
187
 
188
        if ((facilities->pacsize_in || facilities->pacsize_out) &&
189
            (facil_mask & X25_MASK_PACKET_SIZE)) {
190
                *p++ = X25_FAC_PACKET_SIZE;
191
                *p++ = facilities->pacsize_in ? : facilities->pacsize_out;
192
                *p++ = facilities->pacsize_out ? : facilities->pacsize_in;
193
        }
194
 
195
        if ((facilities->winsize_in || facilities->winsize_out) &&
196
            (facil_mask & X25_MASK_WINDOW_SIZE)) {
197
                *p++ = X25_FAC_WINDOW_SIZE;
198
                *p++ = facilities->winsize_in ? : facilities->winsize_out;
199
                *p++ = facilities->winsize_out ? : facilities->winsize_in;
200
        }
201
 
202
        if (facil_mask & (X25_MASK_CALLING_AE|X25_MASK_CALLED_AE)) {
203
                *p++ = X25_MARKER;
204
                *p++ = X25_DTE_SERVICES;
205
        }
206
 
207
        if (dte_facs->calling_len && (facil_mask & X25_MASK_CALLING_AE)) {
208
                unsigned bytecount = (dte_facs->calling_len % 2) ?
209
                                        dte_facs->calling_len / 2 + 1 :
210
                                        dte_facs->calling_len / 2;
211
                *p++ = X25_FAC_CALLING_AE;
212
                *p++ = 1 + bytecount;
213
                *p++ = dte_facs->calling_len;
214
                memcpy(p, dte_facs->calling_ae, bytecount);
215
                p += bytecount;
216
        }
217
 
218
        if (dte_facs->called_len && (facil_mask & X25_MASK_CALLED_AE)) {
219
                unsigned bytecount = (dte_facs->called_len % 2) ?
220
                dte_facs->called_len / 2 + 1 :
221
                dte_facs->called_len / 2;
222
                *p++ = X25_FAC_CALLED_AE;
223
                *p++ = 1 + bytecount;
224
                *p++ = dte_facs->called_len;
225
                memcpy(p, dte_facs->called_ae, bytecount);
226
                p+=bytecount;
227
        }
228
 
229
        len       = p - buffer;
230
        buffer[0] = len - 1;
231
 
232
        return len;
233
}
234
 
235
/*
236
 *      Try to reach a compromise on a set of facilities.
237
 *
238
 *      The only real problem is with reverse charging.
239
 */
240
int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
241
                struct x25_facilities *new, struct x25_dte_facilities *dte)
242
{
243
        struct x25_sock *x25 = x25_sk(sk);
244
        struct x25_facilities *ours = &x25->facilities;
245
        struct x25_facilities theirs;
246
        int len;
247
 
248
        memset(&theirs, 0, sizeof(theirs));
249
        memcpy(new, ours, sizeof(*new));
250
 
251
        len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask);
252
 
253
        /*
254
         *      They want reverse charging, we won't accept it.
255
         */
256
        if ((theirs.reverse & 0x01 ) && (ours->reverse & 0x01)) {
257
                SOCK_DEBUG(sk, "X.25: rejecting reverse charging request\n");
258
                return -1;
259
        }
260
 
261
        new->reverse = theirs.reverse;
262
 
263
        if (theirs.throughput) {
264
                if (theirs.throughput < ours->throughput) {
265
                        SOCK_DEBUG(sk, "X.25: throughput negotiated down\n");
266
                        new->throughput = theirs.throughput;
267
                }
268
        }
269
 
270
        if (theirs.pacsize_in && theirs.pacsize_out) {
271
                if (theirs.pacsize_in < ours->pacsize_in) {
272
                        SOCK_DEBUG(sk, "X.25: packet size inwards negotiated down\n");
273
                        new->pacsize_in = theirs.pacsize_in;
274
                }
275
                if (theirs.pacsize_out < ours->pacsize_out) {
276
                        SOCK_DEBUG(sk, "X.25: packet size outwards negotiated down\n");
277
                        new->pacsize_out = theirs.pacsize_out;
278
                }
279
        }
280
 
281
        if (theirs.winsize_in && theirs.winsize_out) {
282
                if (theirs.winsize_in < ours->winsize_in) {
283
                        SOCK_DEBUG(sk, "X.25: window size inwards negotiated down\n");
284
                        new->winsize_in = theirs.winsize_in;
285
                }
286
                if (theirs.winsize_out < ours->winsize_out) {
287
                        SOCK_DEBUG(sk, "X.25: window size outwards negotiated down\n");
288
                        new->winsize_out = theirs.winsize_out;
289
                }
290
        }
291
 
292
        return len;
293
}
294
 
295
/*
296
 *      Limit values of certain facilities according to the capability of the
297
 *      currently attached x25 link.
298
 */
299
void x25_limit_facilities(struct x25_facilities *facilities,
300
                          struct x25_neigh *nb)
301
{
302
 
303
        if (!nb->extended) {
304
                if (facilities->winsize_in  > 7) {
305
                        printk(KERN_DEBUG "X.25: incoming winsize limited to 7\n");
306
                        facilities->winsize_in = 7;
307
                }
308
                if (facilities->winsize_out > 7) {
309
                        facilities->winsize_out = 7;
310
                        printk( KERN_DEBUG "X.25: outgoing winsize limited to 7\n");
311
                }
312
        }
313
}

powered by: WebSVN 2.1.0

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