diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_multicast.c | 2 | ||||
-rw-r--r-- | net/can/raw.c | 2 | ||||
-rw-r--r-- | net/core/dev.c | 8 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 4 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 2 | ||||
-rw-r--r-- | net/ipv4/udp.c | 4 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 2 | ||||
-rw-r--r-- | net/ipv6/udp.c | 4 | ||||
-rw-r--r-- | net/mac80211/main.c | 4 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 3 | ||||
-rw-r--r-- | net/mac80211/rx.c | 5 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 20 | ||||
-rw-r--r-- | net/packet/af_packet.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_transport.c | 5 | ||||
-rw-r--r-- | net/x25/af_x25.c | 67 | ||||
-rw-r--r-- | net/x25/x25_facilities.c | 27 | ||||
-rw-r--r-- | net/x25/x25_in.c | 15 |
17 files changed, 140 insertions, 36 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 6980625537ca..f29ada827a6a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -723,7 +723,7 @@ static int br_multicast_igmp3_report(struct net_bridge *br, | |||
723 | if (!pskb_may_pull(skb, len)) | 723 | if (!pskb_may_pull(skb, len)) |
724 | return -EINVAL; | 724 | return -EINVAL; |
725 | 725 | ||
726 | grec = (void *)(skb->data + len); | 726 | grec = (void *)(skb->data + len - sizeof(*grec)); |
727 | group = grec->grec_mca; | 727 | group = grec->grec_mca; |
728 | type = grec->grec_type; | 728 | type = grec->grec_type; |
729 | 729 | ||
diff --git a/net/can/raw.c b/net/can/raw.c index 3a7dffb6519c..da99cf153b33 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -445,7 +445,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||
445 | return -EFAULT; | 445 | return -EFAULT; |
446 | } | 446 | } |
447 | } else if (count == 1) { | 447 | } else if (count == 1) { |
448 | if (copy_from_user(&sfilter, optval, optlen)) | 448 | if (copy_from_user(&sfilter, optval, sizeof(sfilter))) |
449 | return -EFAULT; | 449 | return -EFAULT; |
450 | } | 450 | } |
451 | 451 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index 1c8a0ce473a8..92584bfef09b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1989,8 +1989,12 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, | |||
1989 | if (dev->real_num_tx_queues > 1) | 1989 | if (dev->real_num_tx_queues > 1) |
1990 | queue_index = skb_tx_hash(dev, skb); | 1990 | queue_index = skb_tx_hash(dev, skb); |
1991 | 1991 | ||
1992 | if (sk && sk->sk_dst_cache) | 1992 | if (sk) { |
1993 | sk_tx_queue_set(sk, queue_index); | 1993 | struct dst_entry *dst = rcu_dereference(sk->sk_dst_cache); |
1994 | |||
1995 | if (dst && skb_dst(skb) == dst) | ||
1996 | sk_tx_queue_set(sk, queue_index); | ||
1997 | } | ||
1994 | } | 1998 | } |
1995 | } | 1999 | } |
1996 | 2000 | ||
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 59a838795e3e..c98f115fb0fd 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -209,7 +209,9 @@ static inline struct node *tnode_get_child_rcu(struct tnode *tn, unsigned int i) | |||
209 | { | 209 | { |
210 | struct node *ret = tnode_get_child(tn, i); | 210 | struct node *ret = tnode_get_child(tn, i); |
211 | 211 | ||
212 | return rcu_dereference(ret); | 212 | return rcu_dereference_check(ret, |
213 | rcu_read_lock_held() || | ||
214 | lockdep_rtnl_is_held()); | ||
213 | } | 215 | } |
214 | 216 | ||
215 | static inline int tnode_child_length(const struct tnode *tn) | 217 | static inline int tnode_child_length(const struct tnode *tn) |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index c65f18e0936e..d1bcc9f21d4f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -120,7 +120,7 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb) | |||
120 | newskb->pkt_type = PACKET_LOOPBACK; | 120 | newskb->pkt_type = PACKET_LOOPBACK; |
121 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | 121 | newskb->ip_summed = CHECKSUM_UNNECESSARY; |
122 | WARN_ON(!skb_dst(newskb)); | 122 | WARN_ON(!skb_dst(newskb)); |
123 | netif_rx(newskb); | 123 | netif_rx_ni(newskb); |
124 | return 0; | 124 | return 0; |
125 | } | 125 | } |
126 | 126 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 954bbfb39dff..8fef859db35d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -472,8 +472,8 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
472 | if (hslot->count < hslot2->count) | 472 | if (hslot->count < hslot2->count) |
473 | goto begin; | 473 | goto begin; |
474 | 474 | ||
475 | result = udp4_lib_lookup2(net, INADDR_ANY, sport, | 475 | result = udp4_lib_lookup2(net, saddr, sport, |
476 | daddr, hnum, dif, | 476 | INADDR_ANY, hnum, dif, |
477 | hslot2, slot2); | 477 | hslot2, slot2); |
478 | } | 478 | } |
479 | rcu_read_unlock(); | 479 | rcu_read_unlock(); |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 16c4391f952b..65f9c379df38 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -108,7 +108,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | |||
108 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | 108 | newskb->ip_summed = CHECKSUM_UNNECESSARY; |
109 | WARN_ON(!skb_dst(newskb)); | 109 | WARN_ON(!skb_dst(newskb)); |
110 | 110 | ||
111 | netif_rx(newskb); | 111 | netif_rx_ni(newskb); |
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
114 | 114 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index c177aea88c0b..90824852f598 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -259,8 +259,8 @@ static struct sock *__udp6_lib_lookup(struct net *net, | |||
259 | if (hslot->count < hslot2->count) | 259 | if (hslot->count < hslot2->count) |
260 | goto begin; | 260 | goto begin; |
261 | 261 | ||
262 | result = udp6_lib_lookup2(net, &in6addr_any, sport, | 262 | result = udp6_lib_lookup2(net, saddr, sport, |
263 | daddr, hnum, dif, | 263 | &in6addr_any, hnum, dif, |
264 | hslot2, slot2); | 264 | hslot2, slot2); |
265 | } | 265 | } |
266 | rcu_read_unlock(); | 266 | rcu_read_unlock(); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 06c33b68d8e5..b887e484ae04 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -225,11 +225,11 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
225 | switch (sdata->vif.type) { | 225 | switch (sdata->vif.type) { |
226 | case NL80211_IFTYPE_AP: | 226 | case NL80211_IFTYPE_AP: |
227 | sdata->vif.bss_conf.enable_beacon = | 227 | sdata->vif.bss_conf.enable_beacon = |
228 | !!rcu_dereference(sdata->u.ap.beacon); | 228 | !!sdata->u.ap.beacon; |
229 | break; | 229 | break; |
230 | case NL80211_IFTYPE_ADHOC: | 230 | case NL80211_IFTYPE_ADHOC: |
231 | sdata->vif.bss_conf.enable_beacon = | 231 | sdata->vif.bss_conf.enable_beacon = |
232 | !!rcu_dereference(sdata->u.ibss.presp); | 232 | !!sdata->u.ibss.presp; |
233 | break; | 233 | break; |
234 | case NL80211_IFTYPE_MESH_POINT: | 234 | case NL80211_IFTYPE_MESH_POINT: |
235 | sdata->vif.bss_conf.enable_beacon = true; | 235 | sdata->vif.bss_conf.enable_beacon = true; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 58e3e3a61d99..859ee5f3d941 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -750,9 +750,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
750 | 750 | ||
751 | switch (fc & IEEE80211_FCTL_STYPE) { | 751 | switch (fc & IEEE80211_FCTL_STYPE) { |
752 | case IEEE80211_STYPE_ACTION: | 752 | case IEEE80211_STYPE_ACTION: |
753 | if (skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
754 | return RX_DROP_MONITOR; | ||
755 | /* fall through */ | ||
756 | case IEEE80211_STYPE_PROBE_RESP: | 753 | case IEEE80211_STYPE_PROBE_RESP: |
757 | case IEEE80211_STYPE_BEACON: | 754 | case IEEE80211_STYPE_BEACON: |
758 | skb_queue_tail(&ifmsh->skb_queue, skb); | 755 | skb_queue_tail(&ifmsh->skb_queue, skb); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f0accf622cd7..04ea07f0e78a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1974,6 +1974,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1974 | goto handled; | 1974 | goto handled; |
1975 | } | 1975 | } |
1976 | break; | 1976 | break; |
1977 | case MESH_PLINK_CATEGORY: | ||
1978 | case MESH_PATH_SEL_CATEGORY: | ||
1979 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1980 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | ||
1981 | break; | ||
1977 | } | 1982 | } |
1978 | 1983 | ||
1979 | /* | 1984 | /* |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 56422d894351..fb12cec4d333 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -93,12 +93,18 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
93 | struct ieee80211_local *local = sdata->local; | 93 | struct ieee80211_local *local = sdata->local; |
94 | struct sta_info *sta; | 94 | struct sta_info *sta; |
95 | 95 | ||
96 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 96 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
97 | rcu_read_lock_held() || | ||
98 | lockdep_is_held(&local->sta_lock) || | ||
99 | lockdep_is_held(&local->sta_mtx)); | ||
97 | while (sta) { | 100 | while (sta) { |
98 | if (sta->sdata == sdata && | 101 | if (sta->sdata == sdata && |
99 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 102 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
100 | break; | 103 | break; |
101 | sta = rcu_dereference(sta->hnext); | 104 | sta = rcu_dereference_check(sta->hnext, |
105 | rcu_read_lock_held() || | ||
106 | lockdep_is_held(&local->sta_lock) || | ||
107 | lockdep_is_held(&local->sta_mtx)); | ||
102 | } | 108 | } |
103 | return sta; | 109 | return sta; |
104 | } | 110 | } |
@@ -113,13 +119,19 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
113 | struct ieee80211_local *local = sdata->local; | 119 | struct ieee80211_local *local = sdata->local; |
114 | struct sta_info *sta; | 120 | struct sta_info *sta; |
115 | 121 | ||
116 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 122 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
123 | rcu_read_lock_held() || | ||
124 | lockdep_is_held(&local->sta_lock) || | ||
125 | lockdep_is_held(&local->sta_mtx)); | ||
117 | while (sta) { | 126 | while (sta) { |
118 | if ((sta->sdata == sdata || | 127 | if ((sta->sdata == sdata || |
119 | sta->sdata->bss == sdata->bss) && | 128 | sta->sdata->bss == sdata->bss) && |
120 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
121 | break; | 130 | break; |
122 | sta = rcu_dereference(sta->hnext); | 131 | sta = rcu_dereference_check(sta->hnext, |
132 | rcu_read_lock_held() || | ||
133 | lockdep_is_held(&local->sta_lock) || | ||
134 | lockdep_is_held(&local->sta_mtx)); | ||
123 | } | 135 | } |
124 | return sta; | 136 | return sta; |
125 | } | 137 | } |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index cc90363d7e7a..243946d4809d 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -2169,8 +2169,6 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, | |||
2169 | case SIOCGIFDSTADDR: | 2169 | case SIOCGIFDSTADDR: |
2170 | case SIOCSIFDSTADDR: | 2170 | case SIOCSIFDSTADDR: |
2171 | case SIOCSIFFLAGS: | 2171 | case SIOCSIFFLAGS: |
2172 | if (!net_eq(sock_net(sk), &init_net)) | ||
2173 | return -ENOIOCTLCMD; | ||
2174 | return inet_dgram_ops.ioctl(sock, cmd, arg); | 2172 | return inet_dgram_ops.ioctl(sock, cmd, arg); |
2175 | #endif | 2173 | #endif |
2176 | 2174 | ||
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index fd90eb89842b..edea15a54e51 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -679,7 +679,10 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, | |||
679 | int ret; | 679 | int ret; |
680 | 680 | ||
681 | dprintk("svcrdma: Creating RDMA socket\n"); | 681 | dprintk("svcrdma: Creating RDMA socket\n"); |
682 | 682 | if (sa->sa_family != AF_INET) { | |
683 | dprintk("svcrdma: Address family %d is not supported.\n", sa->sa_family); | ||
684 | return ERR_PTR(-EAFNOSUPPORT); | ||
685 | } | ||
683 | cma_xprt = rdma_create_xprt(serv, 1); | 686 | cma_xprt = rdma_create_xprt(serv, 1); |
684 | if (!cma_xprt) | 687 | if (!cma_xprt) |
685 | return ERR_PTR(-ENOMEM); | 688 | return ERR_PTR(-ENOMEM); |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e56f711baccc..cbddd0cb83f1 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -83,6 +83,41 @@ struct compat_x25_subscrip_struct { | |||
83 | }; | 83 | }; |
84 | #endif | 84 | #endif |
85 | 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 | |||
86 | 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, |
87 | struct x25_address *calling_addr) | 122 | struct x25_address *calling_addr) |
88 | { | 123 | { |
@@ -554,7 +589,8 @@ static int x25_create(struct net *net, struct socket *sock, int protocol, | |||
554 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; | 589 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; |
555 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; | 590 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; |
556 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; | 591 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; |
557 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; | 592 | x25->facilities.throughput = 0; /* by default don't negotiate |
593 | throughput */ | ||
558 | x25->facilities.reverse = X25_DEFAULT_REVERSE; | 594 | x25->facilities.reverse = X25_DEFAULT_REVERSE; |
559 | x25->dte_facilities.calling_len = 0; | 595 | x25->dte_facilities.calling_len = 0; |
560 | x25->dte_facilities.called_len = 0; | 596 | x25->dte_facilities.called_len = 0; |
@@ -922,16 +958,26 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
922 | /* | 958 | /* |
923 | * Extract the X.25 addresses and convert them to ASCII strings, | 959 | * Extract the X.25 addresses and convert them to ASCII strings, |
924 | * and remove them. | 960 | * and remove them. |
961 | * | ||
962 | * Address block is mandatory in call request packets | ||
925 | */ | 963 | */ |
926 | addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); | 964 | addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr); |
965 | if (addr_len <= 0) | ||
966 | goto out_clear_request; | ||
927 | skb_pull(skb, addr_len); | 967 | skb_pull(skb, addr_len); |
928 | 968 | ||
929 | /* | 969 | /* |
930 | * Get the length of the facilities, skip past them for the moment | 970 | * Get the length of the facilities, skip past them for the moment |
931 | * get the call user data because this is needed to determine | 971 | * get the call user data because this is needed to determine |
932 | * the correct listener | 972 | * the correct listener |
973 | * | ||
974 | * Facilities length is mandatory in call request packets | ||
933 | */ | 975 | */ |
976 | if (skb->len < 1) | ||
977 | goto out_clear_request; | ||
934 | len = skb->data[0] + 1; | 978 | len = skb->data[0] + 1; |
979 | if (skb->len < len) | ||
980 | goto out_clear_request; | ||
935 | skb_pull(skb,len); | 981 | skb_pull(skb,len); |
936 | 982 | ||
937 | /* | 983 | /* |
@@ -1415,9 +1461,20 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1415 | if (facilities.winsize_in < 1 || | 1461 | if (facilities.winsize_in < 1 || |
1416 | facilities.winsize_in > 127) | 1462 | facilities.winsize_in > 127) |
1417 | break; | 1463 | break; |
1418 | if (facilities.throughput < 0x03 || | 1464 | if (facilities.throughput) { |
1419 | facilities.throughput > 0xDD) | 1465 | int out = facilities.throughput & 0xf0; |
1420 | break; | 1466 | int in = facilities.throughput & 0x0f; |
1467 | if (!out) | ||
1468 | facilities.throughput |= | ||
1469 | X25_DEFAULT_THROUGHPUT << 4; | ||
1470 | else if (out < 0x30 || out > 0xD0) | ||
1471 | break; | ||
1472 | if (!in) | ||
1473 | facilities.throughput |= | ||
1474 | X25_DEFAULT_THROUGHPUT; | ||
1475 | else if (in < 0x03 || in > 0x0D) | ||
1476 | break; | ||
1477 | } | ||
1421 | if (facilities.reverse && | 1478 | if (facilities.reverse && |
1422 | (facilities.reverse & 0x81) != 0x81) | 1479 | (facilities.reverse & 0x81) != 0x81) |
1423 | break; | 1480 | break; |
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 | ||
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index a31b3b9e5966..372ac226e648 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
@@ -90,6 +90,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) | |||
90 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) | 90 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) |
91 | { | 91 | { |
92 | struct x25_address source_addr, dest_addr; | 92 | struct x25_address source_addr, dest_addr; |
93 | int len; | ||
93 | 94 | ||
94 | switch (frametype) { | 95 | switch (frametype) { |
95 | case X25_CALL_ACCEPTED: { | 96 | case X25_CALL_ACCEPTED: { |
@@ -107,11 +108,17 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
107 | * Parse the data in the frame. | 108 | * Parse the data in the frame. |
108 | */ | 109 | */ |
109 | skb_pull(skb, X25_STD_MIN_LEN); | 110 | skb_pull(skb, X25_STD_MIN_LEN); |
110 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); | 111 | |
111 | skb_pull(skb, | 112 | len = x25_parse_address_block(skb, &source_addr, |
112 | x25_parse_facilities(skb, &x25->facilities, | 113 | &dest_addr); |
114 | if (len > 0) | ||
115 | skb_pull(skb, len); | ||
116 | |||
117 | len = x25_parse_facilities(skb, &x25->facilities, | ||
113 | &x25->dte_facilities, | 118 | &x25->dte_facilities, |
114 | &x25->vc_facil_mask)); | 119 | &x25->vc_facil_mask); |
120 | if (len > 0) | ||
121 | skb_pull(skb, len); | ||
115 | /* | 122 | /* |
116 | * Copy any Call User Data. | 123 | * Copy any Call User Data. |
117 | */ | 124 | */ |