diff options
Diffstat (limited to 'net/x25/x25_facilities.c')
| -rw-r--r-- | net/x25/x25_facilities.c | 27 |
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 | ||
