diff options
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r-- | net/x25/af_x25.c | 69 |
1 files changed, 64 insertions, 5 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 9796f3ed1edb..36e84e13c6aa 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/netdevice.h> | 47 | #include <linux/netdevice.h> |
48 | #include <linux/if_arp.h> | 48 | #include <linux/if_arp.h> |
49 | #include <linux/skbuff.h> | 49 | #include <linux/skbuff.h> |
50 | #include <linux/slab.h> | ||
50 | #include <net/sock.h> | 51 | #include <net/sock.h> |
51 | #include <net/tcp_states.h> | 52 | #include <net/tcp_states.h> |
52 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
@@ -82,6 +83,41 @@ struct compat_x25_subscrip_struct { | |||
82 | }; | 83 | }; |
83 | #endif | 84 | #endif |
84 | 85 | ||
86 | |||
87 | int x25_parse_address_block(struct sk_buff *skb, | ||
88 | struct x25_address *called_addr, | ||
89 | struct x25_address *calling_addr) | ||
90 | { | ||
91 | unsigned char len; | ||
92 | int needed; | ||
93 | int rc; | ||
94 | |||
95 | if (skb->len < 1) { | ||
96 | /* packet has no address block */ | ||
97 | rc = 0; | ||
98 | goto empty; | ||
99 | } | ||
100 | |||
101 | len = *skb->data; | ||
102 | needed = 1 + (len >> 4) + (len & 0x0f); | ||
103 | |||
104 | if (skb->len < needed) { | ||
105 | /* packet is too short to hold the addresses it claims | ||
106 | to hold */ | ||
107 | rc = -1; | ||
108 | goto empty; | ||
109 | } | ||
110 | |||
111 | return x25_addr_ntoa(skb->data, called_addr, calling_addr); | ||
112 | |||
113 | empty: | ||
114 | *called_addr->x25_addr = 0; | ||
115 | *calling_addr->x25_addr = 0; | ||
116 | |||
117 | return rc; | ||
118 | } | ||
119 | |||
120 | |||
85 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, | 121 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, |
86 | struct x25_address *calling_addr) | 122 | struct x25_address *calling_addr) |
87 | { | 123 | { |
@@ -366,6 +402,7 @@ static void __x25_destroy_socket(struct sock *sk) | |||
366 | /* | 402 | /* |
367 | * Queue the unaccepted socket for death | 403 | * Queue the unaccepted socket for death |
368 | */ | 404 | */ |
405 | skb->sk->sk_state = TCP_LISTEN; | ||
369 | sock_set_flag(skb->sk, SOCK_DEAD); | 406 | sock_set_flag(skb->sk, SOCK_DEAD); |
370 | x25_start_heartbeat(skb->sk); | 407 | x25_start_heartbeat(skb->sk); |
371 | x25_sk(skb->sk)->state = X25_STATE_0; | 408 | x25_sk(skb->sk)->state = X25_STATE_0; |
@@ -553,7 +590,8 @@ static int x25_create(struct net *net, struct socket *sock, int protocol, | |||
553 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; | 590 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; |
554 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; | 591 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; |
555 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; | 592 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; |
556 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; | 593 | x25->facilities.throughput = 0; /* by default don't negotiate |
594 | throughput */ | ||
557 | x25->facilities.reverse = X25_DEFAULT_REVERSE; | 595 | x25->facilities.reverse = X25_DEFAULT_REVERSE; |
558 | x25->dte_facilities.calling_len = 0; | 596 | x25->dte_facilities.calling_len = 0; |
559 | x25->dte_facilities.called_len = 0; | 597 | x25->dte_facilities.called_len = 0; |
@@ -921,16 +959,26 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
921 | /* | 959 | /* |
922 | * Extract the X.25 addresses and convert them to ASCII strings, | 960 | * Extract the X.25 addresses and convert them to ASCII strings, |
923 | * and remove them. | 961 | * and remove them. |
962 | * | ||
963 | * Address block is mandatory in call request packets | ||
924 | */ | 964 | */ |
925 | addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); | 965 | addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr); |
966 | if (addr_len <= 0) | ||
967 | goto out_clear_request; | ||
926 | skb_pull(skb, addr_len); | 968 | skb_pull(skb, addr_len); |
927 | 969 | ||
928 | /* | 970 | /* |
929 | * Get the length of the facilities, skip past them for the moment | 971 | * Get the length of the facilities, skip past them for the moment |
930 | * get the call user data because this is needed to determine | 972 | * get the call user data because this is needed to determine |
931 | * the correct listener | 973 | * the correct listener |
974 | * | ||
975 | * Facilities length is mandatory in call request packets | ||
932 | */ | 976 | */ |
977 | if (skb->len < 1) | ||
978 | goto out_clear_request; | ||
933 | len = skb->data[0] + 1; | 979 | len = skb->data[0] + 1; |
980 | if (skb->len < len) | ||
981 | goto out_clear_request; | ||
934 | skb_pull(skb,len); | 982 | skb_pull(skb,len); |
935 | 983 | ||
936 | /* | 984 | /* |
@@ -1414,9 +1462,20 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1414 | if (facilities.winsize_in < 1 || | 1462 | if (facilities.winsize_in < 1 || |
1415 | facilities.winsize_in > 127) | 1463 | facilities.winsize_in > 127) |
1416 | break; | 1464 | break; |
1417 | if (facilities.throughput < 0x03 || | 1465 | if (facilities.throughput) { |
1418 | facilities.throughput > 0xDD) | 1466 | int out = facilities.throughput & 0xf0; |
1419 | break; | 1467 | int in = facilities.throughput & 0x0f; |
1468 | if (!out) | ||
1469 | facilities.throughput |= | ||
1470 | X25_DEFAULT_THROUGHPUT << 4; | ||
1471 | else if (out < 0x30 || out > 0xD0) | ||
1472 | break; | ||
1473 | if (!in) | ||
1474 | facilities.throughput |= | ||
1475 | X25_DEFAULT_THROUGHPUT; | ||
1476 | else if (in < 0x03 || in > 0x0D) | ||
1477 | break; | ||
1478 | } | ||
1420 | if (facilities.reverse && | 1479 | if (facilities.reverse && |
1421 | (facilities.reverse & 0x81) != 0x81) | 1480 | (facilities.reverse & 0x81) != 0x81) |
1422 | break; | 1481 | break; |