aboutsummaryrefslogtreecommitdiffstats
path: root/net/x25/x25_facilities.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/x25/x25_facilities.c')
-rw-r--r--net/x25/x25_facilities.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index a21f6646eb3a..771bab00754b 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -35,7 +35,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
35 struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) 35 struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)
36{ 36{
37 unsigned char *p = skb->data; 37 unsigned char *p = skb->data;
38 unsigned int len = *p++; 38 unsigned int len;
39 39
40 *vc_fac_mask = 0; 40 *vc_fac_mask = 0;
41 41
@@ -50,6 +50,14 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
50 memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); 50 memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));
51 memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); 51 memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae));
52 52
53 if (skb->len < 1)
54 return 0;
55
56 len = *p++;
57
58 if (len >= skb->len)
59 return -1;
60
53 while (len > 0) { 61 while (len > 0) {
54 switch (*p & X25_FAC_CLASS_MASK) { 62 switch (*p & X25_FAC_CLASS_MASK) {
55 case X25_FAC_CLASS_A: 63 case X25_FAC_CLASS_A:
@@ -247,6 +255,8 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
247 memcpy(new, ours, sizeof(*new)); 255 memcpy(new, ours, sizeof(*new));
248 256
249 len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); 257 len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask);
258 if (len < 0)
259 return len;
250 260
251 /* 261 /*
252 * They want reverse charging, we won't accept it. 262 * They want reverse charging, we won't accept it.
@@ -259,9 +269,18 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
259 new->reverse = theirs.reverse; 269 new->reverse = theirs.reverse;
260 270
261 if (theirs.throughput) { 271 if (theirs.throughput) {
262 if (theirs.throughput < ours->throughput) { 272 int theirs_in = theirs.throughput & 0x0f;
263 SOCK_DEBUG(sk, "X.25: throughput negotiated down\n"); 273 int theirs_out = theirs.throughput & 0xf0;
264 new->throughput = theirs.throughput; 274 int ours_in = ours->throughput & 0x0f;
275 int ours_out = ours->throughput & 0xf0;
276 if (!ours_in || theirs_in < ours_in) {
277 SOCK_DEBUG(sk, "X.25: inbound throughput negotiated\n");
278 new->throughput = (new->throughput & 0xf0) | theirs_in;
279 }
280 if (!ours_out || theirs_out < ours_out) {
281 SOCK_DEBUG(sk,
282 "X.25: outbound throughput negotiated\n");
283 new->throughput = (new->throughput & 0x0f) | theirs_out;
265 } 284 }
266 } 285 }
267 286