diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/x25/af_x25.c | 45 | ||||
-rw-r--r-- | net/x25/x25_facilities.c | 82 | ||||
-rw-r--r-- | net/x25/x25_in.c | 3 | ||||
-rw-r--r-- | net/x25/x25_subr.c | 6 |
4 files changed, 120 insertions, 16 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 03725c051752..7bf93df7248b 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -525,6 +525,13 @@ static int x25_create(struct socket *sock, int protocol) | |||
525 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; | 525 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; |
526 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; | 526 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; |
527 | x25->facilities.reverse = X25_DEFAULT_REVERSE; | 527 | x25->facilities.reverse = X25_DEFAULT_REVERSE; |
528 | x25->dte_facilities.calling_len = 0; | ||
529 | x25->dte_facilities.called_len = 0; | ||
530 | memset(x25->dte_facilities.called_ae, '\0', | ||
531 | sizeof(x25->dte_facilities.called_ae)); | ||
532 | memset(x25->dte_facilities.calling_ae, '\0', | ||
533 | sizeof(x25->dte_facilities.calling_ae)); | ||
534 | |||
528 | rc = 0; | 535 | rc = 0; |
529 | out: | 536 | out: |
530 | return rc; | 537 | return rc; |
@@ -561,6 +568,7 @@ static struct sock *x25_make_new(struct sock *osk) | |||
561 | x25->t2 = ox25->t2; | 568 | x25->t2 = ox25->t2; |
562 | x25->facilities = ox25->facilities; | 569 | x25->facilities = ox25->facilities; |
563 | x25->qbitincl = ox25->qbitincl; | 570 | x25->qbitincl = ox25->qbitincl; |
571 | x25->dte_facilities = ox25->dte_facilities; | ||
564 | x25->cudmatchlength = ox25->cudmatchlength; | 572 | x25->cudmatchlength = ox25->cudmatchlength; |
565 | x25->accptapprv = ox25->accptapprv; | 573 | x25->accptapprv = ox25->accptapprv; |
566 | 574 | ||
@@ -840,6 +848,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
840 | struct x25_sock *makex25; | 848 | struct x25_sock *makex25; |
841 | struct x25_address source_addr, dest_addr; | 849 | struct x25_address source_addr, dest_addr; |
842 | struct x25_facilities facilities; | 850 | struct x25_facilities facilities; |
851 | struct x25_dte_facilities dte_facilities; | ||
843 | int len, rc; | 852 | int len, rc; |
844 | 853 | ||
845 | /* | 854 | /* |
@@ -876,7 +885,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
876 | /* | 885 | /* |
877 | * Try to reach a compromise on the requested facilities. | 886 | * Try to reach a compromise on the requested facilities. |
878 | */ | 887 | */ |
879 | if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1) | 888 | len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities); |
889 | if (len == -1) | ||
880 | goto out_sock_put; | 890 | goto out_sock_put; |
881 | 891 | ||
882 | /* | 892 | /* |
@@ -907,9 +917,12 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
907 | makex25->source_addr = source_addr; | 917 | makex25->source_addr = source_addr; |
908 | makex25->neighbour = nb; | 918 | makex25->neighbour = nb; |
909 | makex25->facilities = facilities; | 919 | makex25->facilities = facilities; |
920 | makex25->dte_facilities= dte_facilities; | ||
910 | makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; | 921 | makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; |
911 | /* ensure no reverse facil on accept */ | 922 | /* ensure no reverse facil on accept */ |
912 | makex25->vc_facil_mask &= ~X25_MASK_REVERSE; | 923 | makex25->vc_facil_mask &= ~X25_MASK_REVERSE; |
924 | /* ensure no calling address extension on accept */ | ||
925 | makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE; | ||
913 | makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; | 926 | makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; |
914 | 927 | ||
915 | /* Normally all calls are accepted immediatly */ | 928 | /* Normally all calls are accepted immediatly */ |
@@ -1316,6 +1329,36 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1316 | break; | 1329 | break; |
1317 | } | 1330 | } |
1318 | 1331 | ||
1332 | case SIOCX25GDTEFACILITIES: { | ||
1333 | rc = copy_to_user(argp, &x25->dte_facilities, | ||
1334 | sizeof(x25->dte_facilities)); | ||
1335 | if (rc) | ||
1336 | rc = -EFAULT; | ||
1337 | break; | ||
1338 | } | ||
1339 | |||
1340 | case SIOCX25SDTEFACILITIES: { | ||
1341 | struct x25_dte_facilities dtefacs; | ||
1342 | rc = -EFAULT; | ||
1343 | if (copy_from_user(&dtefacs, argp, sizeof(dtefacs))) | ||
1344 | break; | ||
1345 | rc = -EINVAL; | ||
1346 | if (sk->sk_state != TCP_LISTEN && | ||
1347 | sk->sk_state != TCP_CLOSE) | ||
1348 | break; | ||
1349 | if (dtefacs.calling_len > X25_MAX_AE_LEN) | ||
1350 | break; | ||
1351 | if (dtefacs.calling_ae == NULL) | ||
1352 | break; | ||
1353 | if (dtefacs.called_len > X25_MAX_AE_LEN) | ||
1354 | break; | ||
1355 | if (dtefacs.called_ae == NULL) | ||
1356 | break; | ||
1357 | x25->dte_facilities = dtefacs; | ||
1358 | rc = 0; | ||
1359 | break; | ||
1360 | } | ||
1361 | |||
1319 | case SIOCX25GCALLUSERDATA: { | 1362 | case SIOCX25GCALLUSERDATA: { |
1320 | struct x25_calluserdata cud = x25->calluserdata; | 1363 | struct x25_calluserdata cud = x25->calluserdata; |
1321 | rc = copy_to_user(argp, &cud, | 1364 | rc = copy_to_user(argp, &cud, |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 54278b962f4c..9f42b9c9de37 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
@@ -28,18 +28,28 @@ | |||
28 | #include <net/x25.h> | 28 | #include <net/x25.h> |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Parse a set of facilities into the facilities structure. Unrecognised | 31 | * Parse a set of facilities into the facilities structures. Unrecognised |
32 | * facilities are written to the debug log file. | 32 | * facilities are written to the debug log file. |
33 | */ | 33 | */ |
34 | int x25_parse_facilities(struct sk_buff *skb, | 34 | int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, |
35 | struct x25_facilities *facilities, | 35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) |
36 | unsigned long *vc_fac_mask) | ||
37 | { | 36 | { |
38 | unsigned char *p = skb->data; | 37 | unsigned char *p = skb->data; |
39 | unsigned int len = *p++; | 38 | unsigned int len = *p++; |
40 | 39 | ||
41 | *vc_fac_mask = 0; | 40 | *vc_fac_mask = 0; |
42 | 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 | |||
43 | while (len > 0) { | 53 | while (len > 0) { |
44 | switch (*p & X25_FAC_CLASS_MASK) { | 54 | switch (*p & X25_FAC_CLASS_MASK) { |
45 | case X25_FAC_CLASS_A: | 55 | case X25_FAC_CLASS_A: |
@@ -74,6 +84,8 @@ int x25_parse_facilities(struct sk_buff *skb, | |||
74 | facilities->throughput = p[1]; | 84 | facilities->throughput = p[1]; |
75 | *vc_fac_mask |= X25_MASK_THROUGHPUT; | 85 | *vc_fac_mask |= X25_MASK_THROUGHPUT; |
76 | break; | 86 | break; |
87 | case X25_MARKER: | ||
88 | break; | ||
77 | default: | 89 | default: |
78 | printk(KERN_DEBUG "X.25: unknown facility " | 90 | printk(KERN_DEBUG "X.25: unknown facility " |
79 | "%02X, value %02X\n", | 91 | "%02X, value %02X\n", |
@@ -112,11 +124,30 @@ int x25_parse_facilities(struct sk_buff *skb, | |||
112 | len -= 4; | 124 | len -= 4; |
113 | break; | 125 | break; |
114 | case X25_FAC_CLASS_D: | 126 | case X25_FAC_CLASS_D: |
115 | printk(KERN_DEBUG "X.25: unknown facility %02X, " | 127 | switch (*p) { |
116 | "length %d, values %02X, %02X, %02X, %02X\n", | 128 | case X25_FAC_CALLING_AE: |
117 | p[0], p[1], p[2], p[3], p[4], p[5]); | 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 | } | ||
118 | len -= p[1] + 2; | 149 | len -= p[1] + 2; |
119 | p += p[1] + 2; | 150 | p += p[1] + 2; |
120 | break; | 151 | break; |
121 | } | 152 | } |
122 | } | 153 | } |
@@ -128,8 +159,8 @@ int x25_parse_facilities(struct sk_buff *skb, | |||
128 | * Create a set of facilities. | 159 | * Create a set of facilities. |
129 | */ | 160 | */ |
130 | int x25_create_facilities(unsigned char *buffer, | 161 | int x25_create_facilities(unsigned char *buffer, |
131 | struct x25_facilities *facilities, | 162 | struct x25_facilities *facilities, |
132 | unsigned long facil_mask) | 163 | struct x25_dte_facilities *dte_facs, unsigned long facil_mask) |
133 | { | 164 | { |
134 | unsigned char *p = buffer + 1; | 165 | unsigned char *p = buffer + 1; |
135 | int len; | 166 | int len; |
@@ -168,6 +199,33 @@ int x25_create_facilities(unsigned char *buffer, | |||
168 | *p++ = facilities->winsize_out ? : facilities->winsize_in; | 199 | *p++ = facilities->winsize_out ? : facilities->winsize_in; |
169 | } | 200 | } |
170 | 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 | |||
171 | len = p - buffer; | 229 | len = p - buffer; |
172 | buffer[0] = len - 1; | 230 | buffer[0] = len - 1; |
173 | 231 | ||
@@ -180,7 +238,7 @@ int x25_create_facilities(unsigned char *buffer, | |||
180 | * The only real problem is with reverse charging. | 238 | * The only real problem is with reverse charging. |
181 | */ | 239 | */ |
182 | int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | 240 | int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, |
183 | struct x25_facilities *new) | 241 | struct x25_facilities *new, struct x25_dte_facilities *dte) |
184 | { | 242 | { |
185 | struct x25_sock *x25 = x25_sk(sk); | 243 | struct x25_sock *x25 = x25_sk(sk); |
186 | struct x25_facilities *ours = &x25->facilities; | 244 | struct x25_facilities *ours = &x25->facilities; |
@@ -190,7 +248,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
190 | memset(&theirs, 0, sizeof(theirs)); | 248 | memset(&theirs, 0, sizeof(theirs)); |
191 | memcpy(new, ours, sizeof(*new)); | 249 | memcpy(new, ours, sizeof(*new)); |
192 | 250 | ||
193 | len = x25_parse_facilities(skb, &theirs, &x25->vc_facil_mask); | 251 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); |
194 | 252 | ||
195 | /* | 253 | /* |
196 | * They want reverse charging, we won't accept it. | 254 | * They want reverse charging, we won't accept it. |
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 26146874b839..eed50e10f09b 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
@@ -106,7 +106,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
106 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); | 106 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); |
107 | skb_pull(skb, | 107 | skb_pull(skb, |
108 | x25_parse_facilities(skb, &x25->facilities, | 108 | x25_parse_facilities(skb, &x25->facilities, |
109 | &x25->vc_facil_mask)); | 109 | &x25->dte_facilities, |
110 | &x25->vc_facil_mask)); | ||
110 | /* | 111 | /* |
111 | * Copy any Call User Data. | 112 | * Copy any Call User Data. |
112 | */ | 113 | */ |
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 8be9b8fbc24d..8d6220aa5d0f 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c | |||
@@ -190,8 +190,9 @@ void x25_write_internal(struct sock *sk, int frametype) | |||
190 | dptr = skb_put(skb, len); | 190 | dptr = skb_put(skb, len); |
191 | memcpy(dptr, addresses, len); | 191 | memcpy(dptr, addresses, len); |
192 | len = x25_create_facilities(facilities, | 192 | len = x25_create_facilities(facilities, |
193 | &x25->facilities, | 193 | &x25->facilities, |
194 | x25->neighbour->global_facil_mask); | 194 | &x25->dte_facilities, |
195 | x25->neighbour->global_facil_mask); | ||
195 | dptr = skb_put(skb, len); | 196 | dptr = skb_put(skb, len); |
196 | memcpy(dptr, facilities, len); | 197 | memcpy(dptr, facilities, len); |
197 | dptr = skb_put(skb, x25->calluserdata.cudlength); | 198 | dptr = skb_put(skb, x25->calluserdata.cudlength); |
@@ -206,6 +207,7 @@ void x25_write_internal(struct sock *sk, int frametype) | |||
206 | *dptr++ = 0x00; /* Address lengths */ | 207 | *dptr++ = 0x00; /* Address lengths */ |
207 | len = x25_create_facilities(facilities, | 208 | len = x25_create_facilities(facilities, |
208 | &x25->facilities, | 209 | &x25->facilities, |
210 | &x25->dte_facilities, | ||
209 | x25->vc_facil_mask); | 211 | x25->vc_facil_mask); |
210 | dptr = skb_put(skb, len); | 212 | dptr = skb_put(skb, len); |
211 | memcpy(dptr, facilities, len); | 213 | memcpy(dptr, facilities, len); |