Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / net / x25 / x25_facilities.c
blobad41d1cde1ce6dc7c51ea4a50c9d4f3a450d842a
1 /*
2 * X.25 Packet Layer release 002
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.
7 * This code REQUIRES 2.1.15 or higher
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.
15 * History
16 * X.25 001 Split from x25_subr.c
17 * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
18 * negotiation.
21 #include <linux/config.h>
22 #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
23 #include <linux/errno.h>
24 #include <linux/types.h>
25 #include <linux/socket.h>
26 #include <linux/in.h>
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/timer.h>
30 #include <linux/string.h>
31 #include <linux/sockios.h>
32 #include <linux/net.h>
33 #include <linux/inet.h>
34 #include <linux/netdevice.h>
35 #include <linux/skbuff.h>
36 #include <net/sock.h>
37 #include <asm/segment.h>
38 #include <asm/system.h>
39 #include <linux/fcntl.h>
40 #include <linux/mm.h>
41 #include <linux/interrupt.h>
42 #include <net/x25.h>
45 * Parse a set of facilities into the facilities structure. Unrecognised
46 * facilities are written to the debug log file.
48 int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, unsigned long *vc_fac_mask)
50 unsigned int len;
51 unsigned char *p = skb->data;
53 len = *p++;
54 *vc_fac_mask = 0;
56 while (len > 0) {
57 switch (*p & X25_FAC_CLASS_MASK) {
58 case X25_FAC_CLASS_A:
59 switch (*p) {
60 case X25_FAC_REVERSE:
61 facilities->reverse = (p[1] & 0x01);
62 *vc_fac_mask |= X25_MASK_REVERSE;
63 break;
64 case X25_FAC_THROUGHPUT:
65 facilities->throughput = p[1];
66 *vc_fac_mask |= X25_MASK_THROUGHPUT;
67 break;
68 default:
69 printk(KERN_DEBUG "X.25: unknown facility %02X, value %02X\n", p[0], p[1]);
70 break;
72 p += 2;
73 len -= 2;
74 break;
76 case X25_FAC_CLASS_B:
77 switch (*p) {
78 case X25_FAC_PACKET_SIZE:
79 facilities->pacsize_in = p[1];
80 facilities->pacsize_out = p[2];
81 *vc_fac_mask |= X25_MASK_PACKET_SIZE;
82 break;
83 case X25_FAC_WINDOW_SIZE:
84 facilities->winsize_in = p[1];
85 facilities->winsize_out = p[2];
86 *vc_fac_mask |= X25_MASK_WINDOW_SIZE;
87 break;
88 default:
89 printk(KERN_DEBUG "X.25: unknown facility %02X, values %02X, %02X\n", p[0], p[1], p[2]);
90 break;
92 p += 3;
93 len -= 3;
94 break;
96 case X25_FAC_CLASS_C:
97 printk(KERN_DEBUG "X.25: unknown facility %02X, values %02X, %02X, %02X\n", p[0], p[1], p[2], p[3]);
98 p += 4;
99 len -= 4;
100 break;
102 case X25_FAC_CLASS_D:
103 printk(KERN_DEBUG "X.25: unknown facility %02X, length %d, values %02X, %02X, %02X, %02X\n", p[0], p[1], p[2], p[3], p[4], p[5]);
104 p += p[1] + 2;
105 len -= p[1] + 2;
106 break;
110 return p - skb->data;
114 * Create a set of facilities.
116 int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities, unsigned long facil_mask)
118 unsigned char *p = buffer + 1;
119 int len;
121 if (facil_mask == 0) {
122 buffer [0] = 0; /* length of the facilities field in call_req or call_accept packets */
123 len = 1; /* 1 byte for the length field */
124 return len;
127 if ((facilities->reverse != 0) && (facil_mask & X25_MASK_REVERSE)) {
128 *p++ = X25_FAC_REVERSE;
129 *p++ = (facilities->reverse) ? 0x01 : 0x00;
132 if ((facilities->throughput != 0) && (facil_mask & X25_MASK_THROUGHPUT)) {
133 *p++ = X25_FAC_THROUGHPUT;
134 *p++ = facilities->throughput;
137 if ((facilities->pacsize_in != 0 || facilities->pacsize_out != 0) && (facil_mask & X25_MASK_PACKET_SIZE)) {
138 *p++ = X25_FAC_PACKET_SIZE;
139 *p++ = (facilities->pacsize_in == 0) ? facilities->pacsize_out : facilities->pacsize_in;
140 *p++ = (facilities->pacsize_out == 0) ? facilities->pacsize_in : facilities->pacsize_out;
143 if ((facilities->winsize_in != 0 || facilities->winsize_out != 0) && (facil_mask & X25_MASK_WINDOW_SIZE)) {
144 *p++ = X25_FAC_WINDOW_SIZE;
145 *p++ = (facilities->winsize_in == 0) ? facilities->winsize_out : facilities->winsize_in;
146 *p++ = (facilities->winsize_out == 0) ? facilities->winsize_in : facilities->winsize_out;
149 len = p - buffer;
150 buffer[0] = len - 1;
152 return len;
156 * Try to reach a compromise on a set of facilities.
158 * The only real problem is with reverse charging.
160 int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, struct x25_facilities *new)
162 struct x25_facilities *ours;
163 struct x25_facilities theirs;
164 int len;
166 memset(&theirs, 0x00, sizeof(struct x25_facilities));
168 ours = &sk->protinfo.x25->facilities;
170 *new = *ours;
172 len = x25_parse_facilities(skb, &theirs, &sk->protinfo.x25->vc_facil_mask);
175 * They want reverse charging, we won't accept it.
177 if (theirs.reverse != 0 && ours->reverse == 0) {
178 SOCK_DEBUG(sk, "X.25: rejecting reverse charging request");
179 return -1;
182 new->reverse = theirs.reverse;
184 if (theirs.throughput != 0) {
185 if (theirs.throughput < ours->throughput) {
186 SOCK_DEBUG(sk, "X.25: throughput negotiated down");
187 new->throughput = theirs.throughput;
191 if (theirs.pacsize_in != 0 && theirs.pacsize_out != 0) {
192 if (theirs.pacsize_in < ours->pacsize_in) {
193 SOCK_DEBUG(sk, "X.25: packet size inwards negotiated down");
194 new->pacsize_in = theirs.pacsize_in;
196 if (theirs.pacsize_out < ours->pacsize_out) {
197 SOCK_DEBUG(sk, "X.25: packet size outwards negotiated down");
198 new->pacsize_out = theirs.pacsize_out;
202 if (theirs.winsize_in != 0 && theirs.winsize_out != 0) {
203 if (theirs.winsize_in < ours->winsize_in) {
204 SOCK_DEBUG(sk, "X.25: window size inwards negotiated down");
205 new->winsize_in = theirs.winsize_in;
207 if (theirs.winsize_out < ours->winsize_out) {
208 SOCK_DEBUG(sk, "X.25: window size outwards negotiated down");
209 new->winsize_out = theirs.winsize_out;
213 return len;
217 * Limit values of certain facilities according to the capability of the
218 * currently attached x25 link.
220 void x25_limit_facilities(struct x25_facilities *facilities,
221 struct x25_neigh *neighbour)
224 if( ! neighbour->extended ){
225 if( facilities->winsize_in > 7 ){
226 printk(KERN_DEBUG "X.25: incoming winsize limited to 7\n");
227 facilities->winsize_in = 7;
229 if( facilities->winsize_out > 7 ){
230 facilities->winsize_out = 7;
231 printk( KERN_DEBUG "X.25: outgoing winsize limited to 7\n");
236 #endif