diff options
Diffstat (limited to 'net')
40 files changed, 275 insertions, 152 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 9096bcb08132..ee070722a3a3 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -463,7 +463,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
463 | 463 | ||
464 | case NETDEV_PRE_TYPE_CHANGE: | 464 | case NETDEV_PRE_TYPE_CHANGE: |
465 | /* Forbid underlaying device to change its type. */ | 465 | /* Forbid underlaying device to change its type. */ |
466 | return NOTIFY_BAD; | 466 | if (vlan_uses_dev(dev)) |
467 | return NOTIFY_BAD; | ||
468 | break; | ||
467 | 469 | ||
468 | case NETDEV_NOTIFY_PEERS: | 470 | case NETDEV_NOTIFY_PEERS: |
469 | case NETDEV_BONDING_FAILOVER: | 471 | case NETDEV_BONDING_FAILOVER: |
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 0a9084ad19a6..fd8d5afec0dd 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
@@ -1167,6 +1167,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) | |||
1167 | uint16_t crc; | 1167 | uint16_t crc; |
1168 | unsigned long entrytime; | 1168 | unsigned long entrytime; |
1169 | 1169 | ||
1170 | spin_lock_init(&bat_priv->bla.bcast_duplist_lock); | ||
1171 | |||
1170 | batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n"); | 1172 | batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n"); |
1171 | 1173 | ||
1172 | /* setting claim destination address */ | 1174 | /* setting claim destination address */ |
@@ -1210,8 +1212,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) | |||
1210 | /** | 1212 | /** |
1211 | * batadv_bla_check_bcast_duplist | 1213 | * batadv_bla_check_bcast_duplist |
1212 | * @bat_priv: the bat priv with all the soft interface information | 1214 | * @bat_priv: the bat priv with all the soft interface information |
1213 | * @bcast_packet: originator mac address | 1215 | * @bcast_packet: encapsulated broadcast frame plus batman header |
1214 | * @hdr_size: maximum length of the frame | 1216 | * @bcast_packet_len: length of encapsulated broadcast frame plus batman header |
1215 | * | 1217 | * |
1216 | * check if it is on our broadcast list. Another gateway might | 1218 | * check if it is on our broadcast list. Another gateway might |
1217 | * have sent the same packet because it is connected to the same backbone, | 1219 | * have sent the same packet because it is connected to the same backbone, |
@@ -1224,20 +1226,22 @@ int batadv_bla_init(struct batadv_priv *bat_priv) | |||
1224 | */ | 1226 | */ |
1225 | int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, | 1227 | int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, |
1226 | struct batadv_bcast_packet *bcast_packet, | 1228 | struct batadv_bcast_packet *bcast_packet, |
1227 | int hdr_size) | 1229 | int bcast_packet_len) |
1228 | { | 1230 | { |
1229 | int i, length, curr; | 1231 | int i, length, curr, ret = 0; |
1230 | uint8_t *content; | 1232 | uint8_t *content; |
1231 | uint16_t crc; | 1233 | uint16_t crc; |
1232 | struct batadv_bcast_duplist_entry *entry; | 1234 | struct batadv_bcast_duplist_entry *entry; |
1233 | 1235 | ||
1234 | length = hdr_size - sizeof(*bcast_packet); | 1236 | length = bcast_packet_len - sizeof(*bcast_packet); |
1235 | content = (uint8_t *)bcast_packet; | 1237 | content = (uint8_t *)bcast_packet; |
1236 | content += sizeof(*bcast_packet); | 1238 | content += sizeof(*bcast_packet); |
1237 | 1239 | ||
1238 | /* calculate the crc ... */ | 1240 | /* calculate the crc ... */ |
1239 | crc = crc16(0, content, length); | 1241 | crc = crc16(0, content, length); |
1240 | 1242 | ||
1243 | spin_lock_bh(&bat_priv->bla.bcast_duplist_lock); | ||
1244 | |||
1241 | for (i = 0; i < BATADV_DUPLIST_SIZE; i++) { | 1245 | for (i = 0; i < BATADV_DUPLIST_SIZE; i++) { |
1242 | curr = (bat_priv->bla.bcast_duplist_curr + i); | 1246 | curr = (bat_priv->bla.bcast_duplist_curr + i); |
1243 | curr %= BATADV_DUPLIST_SIZE; | 1247 | curr %= BATADV_DUPLIST_SIZE; |
@@ -1259,9 +1263,12 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, | |||
1259 | /* this entry seems to match: same crc, not too old, | 1263 | /* this entry seems to match: same crc, not too old, |
1260 | * and from another gw. therefore return 1 to forbid it. | 1264 | * and from another gw. therefore return 1 to forbid it. |
1261 | */ | 1265 | */ |
1262 | return 1; | 1266 | ret = 1; |
1267 | goto out; | ||
1263 | } | 1268 | } |
1264 | /* not found, add a new entry (overwrite the oldest entry) */ | 1269 | /* not found, add a new entry (overwrite the oldest entry) |
1270 | * and allow it, its the first occurence. | ||
1271 | */ | ||
1265 | curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1); | 1272 | curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1); |
1266 | curr %= BATADV_DUPLIST_SIZE; | 1273 | curr %= BATADV_DUPLIST_SIZE; |
1267 | entry = &bat_priv->bla.bcast_duplist[curr]; | 1274 | entry = &bat_priv->bla.bcast_duplist[curr]; |
@@ -1270,8 +1277,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, | |||
1270 | memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); | 1277 | memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); |
1271 | bat_priv->bla.bcast_duplist_curr = curr; | 1278 | bat_priv->bla.bcast_duplist_curr = curr; |
1272 | 1279 | ||
1273 | /* allow it, its the first occurence. */ | 1280 | out: |
1274 | return 0; | 1281 | spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock); |
1282 | |||
1283 | return ret; | ||
1275 | } | 1284 | } |
1276 | 1285 | ||
1277 | 1286 | ||
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 939fc01371df..376b4cc6ca82 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -1124,8 +1124,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, | |||
1124 | 1124 | ||
1125 | spin_unlock_bh(&orig_node->bcast_seqno_lock); | 1125 | spin_unlock_bh(&orig_node->bcast_seqno_lock); |
1126 | 1126 | ||
1127 | /* keep skb linear for crc calculation */ | ||
1128 | if (skb_linearize(skb) < 0) | ||
1129 | goto out; | ||
1130 | |||
1131 | bcast_packet = (struct batadv_bcast_packet *)skb->data; | ||
1132 | |||
1127 | /* check whether this has been sent by another originator before */ | 1133 | /* check whether this has been sent by another originator before */ |
1128 | if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) | 1134 | if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len)) |
1129 | goto out; | 1135 | goto out; |
1130 | 1136 | ||
1131 | /* rebroadcast packet */ | 1137 | /* rebroadcast packet */ |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 2ed82caacdca..ac1e07a80454 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -205,6 +205,8 @@ struct batadv_priv_bla { | |||
205 | struct batadv_hashtable *backbone_hash; | 205 | struct batadv_hashtable *backbone_hash; |
206 | struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; | 206 | struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; |
207 | int bcast_duplist_curr; | 207 | int bcast_duplist_curr; |
208 | /* protects bcast_duplist and bcast_duplist_curr */ | ||
209 | spinlock_t bcast_duplist_lock; | ||
208 | struct batadv_bla_claim_dst claim_dest; | 210 | struct batadv_bla_claim_dst claim_dest; |
209 | struct delayed_work work; | 211 | struct delayed_work work; |
210 | }; | 212 | }; |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8c225ef349cd..2ac8d50861e0 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -32,6 +32,8 @@ | |||
32 | 32 | ||
33 | #define SMP_TIMEOUT msecs_to_jiffies(30000) | 33 | #define SMP_TIMEOUT msecs_to_jiffies(30000) |
34 | 34 | ||
35 | #define AUTH_REQ_MASK 0x07 | ||
36 | |||
35 | static inline void swap128(u8 src[16], u8 dst[16]) | 37 | static inline void swap128(u8 src[16], u8 dst[16]) |
36 | { | 38 | { |
37 | int i; | 39 | int i; |
@@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
230 | req->max_key_size = SMP_MAX_ENC_KEY_SIZE; | 232 | req->max_key_size = SMP_MAX_ENC_KEY_SIZE; |
231 | req->init_key_dist = 0; | 233 | req->init_key_dist = 0; |
232 | req->resp_key_dist = dist_keys; | 234 | req->resp_key_dist = dist_keys; |
233 | req->auth_req = authreq; | 235 | req->auth_req = (authreq & AUTH_REQ_MASK); |
234 | return; | 236 | return; |
235 | } | 237 | } |
236 | 238 | ||
@@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
239 | rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; | 241 | rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; |
240 | rsp->init_key_dist = 0; | 242 | rsp->init_key_dist = 0; |
241 | rsp->resp_key_dist = req->resp_key_dist & dist_keys; | 243 | rsp->resp_key_dist = req->resp_key_dist & dist_keys; |
242 | rsp->auth_req = authreq; | 244 | rsp->auth_req = (authreq & AUTH_REQ_MASK); |
243 | } | 245 | } |
244 | 246 | ||
245 | static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) | 247 | static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 159aa8bef9e7..3ef1759403b4 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -2300,10 +2300,11 @@ restart: | |||
2300 | mutex_unlock(&con->mutex); | 2300 | mutex_unlock(&con->mutex); |
2301 | return; | 2301 | return; |
2302 | } else { | 2302 | } else { |
2303 | con->ops->put(con); | ||
2304 | dout("con_work %p FAILED to back off %lu\n", con, | 2303 | dout("con_work %p FAILED to back off %lu\n", con, |
2305 | con->delay); | 2304 | con->delay); |
2305 | set_bit(CON_FLAG_BACKOFF, &con->flags); | ||
2306 | } | 2306 | } |
2307 | goto done; | ||
2307 | } | 2308 | } |
2308 | 2309 | ||
2309 | if (con->state == CON_STATE_STANDBY) { | 2310 | if (con->state == CON_STATE_STANDBY) { |
@@ -2749,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) | |||
2749 | msg = con->ops->alloc_msg(con, hdr, skip); | 2750 | msg = con->ops->alloc_msg(con, hdr, skip); |
2750 | mutex_lock(&con->mutex); | 2751 | mutex_lock(&con->mutex); |
2751 | if (con->state != CON_STATE_OPEN) { | 2752 | if (con->state != CON_STATE_OPEN) { |
2752 | ceph_msg_put(msg); | 2753 | if (msg) |
2754 | ceph_msg_put(msg); | ||
2753 | return -EAGAIN; | 2755 | return -EAGAIN; |
2754 | } | 2756 | } |
2755 | con->in_msg = msg; | 2757 | con->in_msg = msg; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6e04b1fa11f2..4007c1437fda 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -3379,10 +3379,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding); | |||
3379 | 3379 | ||
3380 | void kfree_skb_partial(struct sk_buff *skb, bool head_stolen) | 3380 | void kfree_skb_partial(struct sk_buff *skb, bool head_stolen) |
3381 | { | 3381 | { |
3382 | if (head_stolen) | 3382 | if (head_stolen) { |
3383 | skb_release_head_state(skb); | ||
3383 | kmem_cache_free(skbuff_head_cache, skb); | 3384 | kmem_cache_free(skbuff_head_cache, skb); |
3384 | else | 3385 | } else { |
3385 | __kfree_skb(skb); | 3386 | __kfree_skb(skb); |
3387 | } | ||
3386 | } | 3388 | } |
3387 | EXPORT_SYMBOL(kfree_skb_partial); | 3389 | EXPORT_SYMBOL(kfree_skb_partial); |
3388 | 3390 | ||
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index 9e0ffaf1d942..a82047282dbb 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c | |||
@@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum, | |||
184 | 184 | ||
185 | if ((ct->tuplehash[dir].tuple.src.u3.ip != | 185 | if ((ct->tuplehash[dir].tuple.src.u3.ip != |
186 | ct->tuplehash[!dir].tuple.dst.u3.ip) || | 186 | ct->tuplehash[!dir].tuple.dst.u3.ip) || |
187 | (ct->tuplehash[dir].tuple.src.u.all != | 187 | (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && |
188 | ct->tuplehash[dir].tuple.src.u.all != | ||
188 | ct->tuplehash[!dir].tuple.dst.u.all)) | 189 | ct->tuplehash[!dir].tuple.dst.u.all)) |
189 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) | 190 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) |
190 | ret = NF_DROP; | 191 | ret = NF_DROP; |
@@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum, | |||
221 | } | 222 | } |
222 | #ifdef CONFIG_XFRM | 223 | #ifdef CONFIG_XFRM |
223 | else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && | 224 | else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && |
225 | ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && | ||
224 | ct->tuplehash[dir].tuple.dst.u.all != | 226 | ct->tuplehash[dir].tuple.dst.u.all != |
225 | ct->tuplehash[!dir].tuple.src.u.all) | 227 | ct->tuplehash[!dir].tuple.src.u.all) |
226 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) | 228 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 432f4bb77238..a8c651216fa6 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1163,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, | |||
1163 | spin_lock_bh(&fnhe_lock); | 1163 | spin_lock_bh(&fnhe_lock); |
1164 | 1164 | ||
1165 | if (daddr == fnhe->fnhe_daddr) { | 1165 | if (daddr == fnhe->fnhe_daddr) { |
1166 | struct rtable *orig; | 1166 | struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); |
1167 | 1167 | if (orig && rt_is_expired(orig)) { | |
1168 | fnhe->fnhe_gw = 0; | ||
1169 | fnhe->fnhe_pmtu = 0; | ||
1170 | fnhe->fnhe_expires = 0; | ||
1171 | } | ||
1168 | if (fnhe->fnhe_pmtu) { | 1172 | if (fnhe->fnhe_pmtu) { |
1169 | unsigned long expires = fnhe->fnhe_expires; | 1173 | unsigned long expires = fnhe->fnhe_expires; |
1170 | unsigned long diff = expires - jiffies; | 1174 | unsigned long diff = expires - jiffies; |
@@ -1181,7 +1185,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, | |||
1181 | } else if (!rt->rt_gateway) | 1185 | } else if (!rt->rt_gateway) |
1182 | rt->rt_gateway = daddr; | 1186 | rt->rt_gateway = daddr; |
1183 | 1187 | ||
1184 | orig = rcu_dereference(fnhe->fnhe_rth); | ||
1185 | rcu_assign_pointer(fnhe->fnhe_rth, rt); | 1188 | rcu_assign_pointer(fnhe->fnhe_rth, rt); |
1186 | if (orig) | 1189 | if (orig) |
1187 | rt_free(orig); | 1190 | rt_free(orig); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f32c02e2a543..197c0008503c 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -549,14 +549,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
549 | !tp->urg_data || | 549 | !tp->urg_data || |
550 | before(tp->urg_seq, tp->copied_seq) || | 550 | before(tp->urg_seq, tp->copied_seq) || |
551 | !before(tp->urg_seq, tp->rcv_nxt)) { | 551 | !before(tp->urg_seq, tp->rcv_nxt)) { |
552 | struct sk_buff *skb; | ||
553 | 552 | ||
554 | answ = tp->rcv_nxt - tp->copied_seq; | 553 | answ = tp->rcv_nxt - tp->copied_seq; |
555 | 554 | ||
556 | /* Subtract 1, if FIN is in queue. */ | 555 | /* Subtract 1, if FIN was received */ |
557 | skb = skb_peek_tail(&sk->sk_receive_queue); | 556 | if (answ && sock_flag(sk, SOCK_DONE)) |
558 | if (answ && skb) | 557 | answ--; |
559 | answ -= tcp_hdr(skb)->fin; | ||
560 | } else | 558 | } else |
561 | answ = tp->urg_seq - tp->copied_seq; | 559 | answ = tp->urg_seq - tp->copied_seq; |
562 | release_sock(sk); | 560 | release_sock(sk); |
@@ -2766,6 +2764,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) | |||
2766 | info->tcpi_options |= TCPI_OPT_ECN; | 2764 | info->tcpi_options |= TCPI_OPT_ECN; |
2767 | if (tp->ecn_flags & TCP_ECN_SEEN) | 2765 | if (tp->ecn_flags & TCP_ECN_SEEN) |
2768 | info->tcpi_options |= TCPI_OPT_ECN_SEEN; | 2766 | info->tcpi_options |= TCPI_OPT_ECN_SEEN; |
2767 | if (tp->syn_data_acked) | ||
2768 | info->tcpi_options |= TCPI_OPT_SYN_DATA; | ||
2769 | 2769 | ||
2770 | info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto); | 2770 | info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto); |
2771 | info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato); | 2771 | info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato); |
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 813b43a76fec..834857f3c871 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c | |||
@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, | |||
313 | .tcpv_rttcnt = ca->cnt_rtt, | 313 | .tcpv_rttcnt = ca->cnt_rtt, |
314 | .tcpv_minrtt = ca->base_rtt, | 314 | .tcpv_minrtt = ca->base_rtt, |
315 | }; | 315 | }; |
316 | u64 t = ca->sum_rtt; | ||
317 | 316 | ||
318 | do_div(t, ca->cnt_rtt); | 317 | if (info.tcpv_rttcnt > 0) { |
319 | info.tcpv_rtt = t; | 318 | u64 t = ca->sum_rtt; |
320 | 319 | ||
320 | do_div(t, info.tcpv_rttcnt); | ||
321 | info.tcpv_rtt = t; | ||
322 | } | ||
321 | nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); | 323 | nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); |
322 | } | 324 | } |
323 | } | 325 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 432c36649db3..2c2b13a999ea 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) | |||
4529 | struct tcphdr *th; | 4529 | struct tcphdr *th; |
4530 | bool fragstolen; | 4530 | bool fragstolen; |
4531 | 4531 | ||
4532 | if (size == 0) | ||
4533 | return 0; | ||
4534 | |||
4532 | skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); | 4535 | skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); |
4533 | if (!skb) | 4536 | if (!skb) |
4534 | goto err; | 4537 | goto err; |
@@ -5646,6 +5649,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, | |||
5646 | tcp_rearm_rto(sk); | 5649 | tcp_rearm_rto(sk); |
5647 | return true; | 5650 | return true; |
5648 | } | 5651 | } |
5652 | tp->syn_data_acked = tp->syn_data; | ||
5649 | return false; | 5653 | return false; |
5650 | } | 5654 | } |
5651 | 5655 | ||
@@ -5963,7 +5967,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5963 | 5967 | ||
5964 | req = tp->fastopen_rsk; | 5968 | req = tp->fastopen_rsk; |
5965 | if (req != NULL) { | 5969 | if (req != NULL) { |
5966 | BUG_ON(sk->sk_state != TCP_SYN_RECV && | 5970 | WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && |
5967 | sk->sk_state != TCP_FIN_WAIT1); | 5971 | sk->sk_state != TCP_FIN_WAIT1); |
5968 | 5972 | ||
5969 | if (tcp_check_req(sk, skb, req, NULL, true) == NULL) | 5973 | if (tcp_check_req(sk, skb, req, NULL, true) == NULL) |
@@ -6052,7 +6056,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
6052 | * ACK we have received, this would have acknowledged | 6056 | * ACK we have received, this would have acknowledged |
6053 | * our SYNACK so stop the SYNACK timer. | 6057 | * our SYNACK so stop the SYNACK timer. |
6054 | */ | 6058 | */ |
6055 | if (acceptable && req != NULL) { | 6059 | if (req != NULL) { |
6060 | /* Return RST if ack_seq is invalid. | ||
6061 | * Note that RFC793 only says to generate a | ||
6062 | * DUPACK for it but for TCP Fast Open it seems | ||
6063 | * better to treat this case like TCP_SYN_RECV | ||
6064 | * above. | ||
6065 | */ | ||
6066 | if (!acceptable) | ||
6067 | return 1; | ||
6056 | /* We no longer need the request sock. */ | 6068 | /* We no longer need the request sock. */ |
6057 | reqsk_fastopen_remove(sk, req, false); | 6069 | reqsk_fastopen_remove(sk, req, false); |
6058 | tcp_rearm_rto(sk); | 6070 | tcp_rearm_rto(sk); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ef998b008a57..0c4a64355603 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1461,6 +1461,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, | |||
1461 | skb_set_owner_r(skb, child); | 1461 | skb_set_owner_r(skb, child); |
1462 | __skb_queue_tail(&child->sk_receive_queue, skb); | 1462 | __skb_queue_tail(&child->sk_receive_queue, skb); |
1463 | tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | 1463 | tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; |
1464 | tp->syn_data_acked = 1; | ||
1464 | } | 1465 | } |
1465 | sk->sk_data_ready(sk, 0); | 1466 | sk->sk_data_ready(sk, 0); |
1466 | bh_unlock_sock(child); | 1467 | bh_unlock_sock(child); |
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 4c752a6e0bcd..53bc5847bfa8 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
@@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr, | |||
864 | } | 864 | } |
865 | a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6]; | 865 | a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6]; |
866 | if (a) { | 866 | if (a) { |
867 | if (nla_len(a) != sizeof(sizeof(struct in6_addr))) | 867 | if (nla_len(a) != sizeof(struct in6_addr)) |
868 | return -EINVAL; | 868 | return -EINVAL; |
869 | addr->family = AF_INET6; | 869 | addr->family = AF_INET6; |
870 | memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6)); | 870 | memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6)); |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 27536ba16c9d..a7302d974f32 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -510,6 +510,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
510 | newtp->rx_opt.mss_clamp = req->mss; | 510 | newtp->rx_opt.mss_clamp = req->mss; |
511 | TCP_ECN_openreq_child(newtp, req); | 511 | TCP_ECN_openreq_child(newtp, req); |
512 | newtp->fastopen_rsk = NULL; | 512 | newtp->fastopen_rsk = NULL; |
513 | newtp->syn_data_acked = 0; | ||
513 | 514 | ||
514 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS); | 515 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS); |
515 | } | 516 | } |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index fc04711e80c8..d47c1b4421a3 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk) | |||
347 | return; | 347 | return; |
348 | } | 348 | } |
349 | if (tp->fastopen_rsk) { | 349 | if (tp->fastopen_rsk) { |
350 | BUG_ON(sk->sk_state != TCP_SYN_RECV && | 350 | WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && |
351 | sk->sk_state != TCP_FIN_WAIT1); | 351 | sk->sk_state != TCP_FIN_WAIT1); |
352 | tcp_fastopen_synack_timer(sk); | 352 | tcp_fastopen_synack_timer(sk); |
353 | /* Before we receive ACK to our SYN-ACK don't retransmit | 353 | /* Before we receive ACK to our SYN-ACK don't retransmit |
354 | * anything else (e.g., data or FIN segments). | 354 | * anything else (e.g., data or FIN segments). |
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index e418bd6350a4..d57dab17a182 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c | |||
@@ -186,7 +186,8 @@ nf_nat_ipv6_out(unsigned int hooknum, | |||
186 | 186 | ||
187 | if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, | 187 | if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, |
188 | &ct->tuplehash[!dir].tuple.dst.u3) || | 188 | &ct->tuplehash[!dir].tuple.dst.u3) || |
189 | (ct->tuplehash[dir].tuple.src.u.all != | 189 | (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && |
190 | ct->tuplehash[dir].tuple.src.u.all != | ||
190 | ct->tuplehash[!dir].tuple.dst.u.all)) | 191 | ct->tuplehash[!dir].tuple.dst.u.all)) |
191 | if (nf_xfrm_me_harder(skb, AF_INET6) < 0) | 192 | if (nf_xfrm_me_harder(skb, AF_INET6) < 0) |
192 | ret = NF_DROP; | 193 | ret = NF_DROP; |
@@ -222,6 +223,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum, | |||
222 | } | 223 | } |
223 | #ifdef CONFIG_XFRM | 224 | #ifdef CONFIG_XFRM |
224 | else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | 225 | else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && |
226 | ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && | ||
225 | ct->tuplehash[dir].tuple.dst.u.all != | 227 | ct->tuplehash[dir].tuple.dst.u.all != |
226 | ct->tuplehash[!dir].tuple.src.u.all) | 228 | ct->tuplehash[!dir].tuple.src.u.all) |
227 | if (nf_xfrm_me_harder(skb, AF_INET6)) | 229 | if (nf_xfrm_me_harder(skb, AF_INET6)) |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 18bd9bbbd1c6..22c8ea951185 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = { | |||
85 | { } | 85 | { } |
86 | }; | 86 | }; |
87 | 87 | ||
88 | static int __net_init nf_ct_frag6_sysctl_register(struct net *net) | 88 | static int nf_ct_frag6_sysctl_register(struct net *net) |
89 | { | 89 | { |
90 | struct ctl_table *table; | 90 | struct ctl_table *table; |
91 | struct ctl_table_header *hdr; | 91 | struct ctl_table_header *hdr; |
@@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) | |||
127 | } | 127 | } |
128 | 128 | ||
129 | #else | 129 | #else |
130 | static int __net_init nf_ct_frag6_sysctl_register(struct net *net) | 130 | static int nf_ct_frag6_sysctl_register(struct net *net) |
131 | { | 131 | { |
132 | return 0; | 132 | return 0; |
133 | } | 133 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7c7e963260e1..b1e6cf0b95fd 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
219 | }; | 219 | }; |
220 | 220 | ||
221 | static const u32 ip6_template_metrics[RTAX_MAX] = { | 221 | static const u32 ip6_template_metrics[RTAX_MAX] = { |
222 | [RTAX_HOPLIMIT - 1] = 255, | 222 | [RTAX_HOPLIMIT - 1] = 0, |
223 | }; | 223 | }; |
224 | 224 | ||
225 | static const struct rt6_info ip6_null_entry_template = { | 225 | static const struct rt6_info ip6_null_entry_template = { |
@@ -1232,7 +1232,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1232 | rt->rt6i_dst.addr = fl6->daddr; | 1232 | rt->rt6i_dst.addr = fl6->daddr; |
1233 | rt->rt6i_dst.plen = 128; | 1233 | rt->rt6i_dst.plen = 128; |
1234 | rt->rt6i_idev = idev; | 1234 | rt->rt6i_idev = idev; |
1235 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); | 1235 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); |
1236 | 1236 | ||
1237 | spin_lock_bh(&icmp6_dst_lock); | 1237 | spin_lock_bh(&icmp6_dst_lock); |
1238 | rt->dst.next = icmp6_dst_gc_list; | 1238 | rt->dst.next = icmp6_dst_gc_list; |
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 37b8b8ba31f7..76125c57ee6d 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c | |||
@@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p | |||
291 | 291 | ||
292 | out_del_dev: | 292 | out_del_dev: |
293 | free_netdev(dev); | 293 | free_netdev(dev); |
294 | spriv->dev = NULL; | ||
294 | out_del_session: | 295 | out_del_session: |
295 | l2tp_session_delete(session); | 296 | l2tp_session_delete(session); |
296 | out: | 297 | out: |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5f3620f0bc0a..bf87c70ac6c5 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1108 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; | 1108 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; |
1109 | sdata->u.ibss.ibss_join_req = jiffies; | 1109 | sdata->u.ibss.ibss_join_req = jiffies; |
1110 | 1110 | ||
1111 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | 1111 | memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); |
1112 | sdata->u.ibss.ssid_len = params->ssid_len; | 1112 | sdata->u.ibss.ssid_len = params->ssid_len; |
1113 | 1113 | ||
1114 | mutex_unlock(&sdata->u.ibss.mtx); | 1114 | mutex_unlock(&sdata->u.ibss.mtx); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6f8a73c64fb3..7de7717ad67d 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -853,7 +853,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
853 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 853 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
854 | if (info->control.vif == &sdata->vif) { | 854 | if (info->control.vif == &sdata->vif) { |
855 | __skb_unlink(skb, &local->pending[i]); | 855 | __skb_unlink(skb, &local->pending[i]); |
856 | dev_kfree_skb_irq(skb); | 856 | ieee80211_free_txskb(&local->hw, skb); |
857 | } | 857 | } |
858 | } | 858 | } |
859 | } | 859 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e714ed8bb198..1b7eed252fe9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3099 | ht_cfreq, ht_oper->primary_chan, | 3099 | ht_cfreq, ht_oper->primary_chan, |
3100 | cbss->channel->band); | 3100 | cbss->channel->band); |
3101 | ht_oper = NULL; | 3101 | ht_oper = NULL; |
3102 | } else { | ||
3103 | channel_type = NL80211_CHAN_HT20; | ||
3102 | } | 3104 | } |
3103 | } | 3105 | } |
3104 | 3106 | ||
3105 | if (ht_oper) { | 3107 | if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { |
3106 | channel_type = NL80211_CHAN_HT20; | 3108 | /* |
3109 | * cfg80211 already verified that the channel itself can | ||
3110 | * be used, but it didn't check that we can do the right | ||
3111 | * HT type, so do that here as well. If HT40 isn't allowed | ||
3112 | * on this channel, disable 40 MHz operation. | ||
3113 | */ | ||
3107 | 3114 | ||
3108 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | 3115 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
3109 | switch (ht_oper->ht_param & | 3116 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
3110 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 3117 | if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) |
3111 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 3118 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; |
3119 | else | ||
3112 | channel_type = NL80211_CHAN_HT40PLUS; | 3120 | channel_type = NL80211_CHAN_HT40PLUS; |
3113 | break; | 3121 | break; |
3114 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | 3122 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: |
3123 | if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) | ||
3124 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | ||
3125 | else | ||
3115 | channel_type = NL80211_CHAN_HT40MINUS; | 3126 | channel_type = NL80211_CHAN_HT40MINUS; |
3116 | break; | 3127 | break; |
3117 | } | ||
3118 | } | 3128 | } |
3119 | } | 3129 | } |
3120 | 3130 | ||
@@ -3549,6 +3559,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3549 | { | 3559 | { |
3550 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3560 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3551 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 3561 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
3562 | bool tx = !req->local_state_change; | ||
3552 | 3563 | ||
3553 | mutex_lock(&ifmgd->mtx); | 3564 | mutex_lock(&ifmgd->mtx); |
3554 | 3565 | ||
@@ -3565,12 +3576,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3565 | if (ifmgd->associated && | 3576 | if (ifmgd->associated && |
3566 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { | 3577 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { |
3567 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 3578 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
3568 | req->reason_code, true, frame_buf); | 3579 | req->reason_code, tx, frame_buf); |
3569 | } else { | 3580 | } else { |
3570 | drv_mgd_prepare_tx(sdata->local, sdata); | 3581 | drv_mgd_prepare_tx(sdata->local, sdata); |
3571 | ieee80211_send_deauth_disassoc(sdata, req->bssid, | 3582 | ieee80211_send_deauth_disassoc(sdata, req->bssid, |
3572 | IEEE80211_STYPE_DEAUTH, | 3583 | IEEE80211_STYPE_DEAUTH, |
3573 | req->reason_code, true, | 3584 | req->reason_code, tx, |
3574 | frame_buf); | 3585 | frame_buf); |
3575 | } | 3586 | } |
3576 | 3587 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 61c621e9273f..00ade7feb2e3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
531 | 531 | ||
532 | if (ieee80211_is_action(hdr->frame_control)) { | 532 | if (ieee80211_is_action(hdr->frame_control)) { |
533 | u8 category; | 533 | u8 category; |
534 | |||
535 | /* make sure category field is present */ | ||
536 | if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
537 | return RX_DROP_MONITOR; | ||
538 | |||
534 | mgmt = (struct ieee80211_mgmt *)hdr; | 539 | mgmt = (struct ieee80211_mgmt *)hdr; |
535 | category = mgmt->u.action.category; | 540 | category = mgmt->u.action.category; |
536 | if (category != WLAN_CATEGORY_MESH_ACTION && | 541 | if (category != WLAN_CATEGORY_MESH_ACTION && |
@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
883 | */ | 888 | */ |
884 | if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && | 889 | if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && |
885 | ieee80211_is_data_present(hdr->frame_control)) { | 890 | ieee80211_is_data_present(hdr->frame_control)) { |
886 | u16 ethertype; | 891 | unsigned int hdrlen; |
887 | u8 *payload; | 892 | __be16 ethertype; |
888 | 893 | ||
889 | payload = rx->skb->data + | 894 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
890 | ieee80211_hdrlen(hdr->frame_control); | 895 | |
891 | ethertype = (payload[6] << 8) | payload[7]; | 896 | if (rx->skb->len < hdrlen + 8) |
892 | if (cpu_to_be16(ethertype) == | 897 | return RX_DROP_MONITOR; |
893 | rx->sdata->control_port_protocol) | 898 | |
899 | skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); | ||
900 | if (ethertype == rx->sdata->control_port_protocol) | ||
894 | return RX_CONTINUE; | 901 | return RX_CONTINUE; |
895 | } | 902 | } |
896 | 903 | ||
@@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1462 | 1469 | ||
1463 | hdr = (struct ieee80211_hdr *)rx->skb->data; | 1470 | hdr = (struct ieee80211_hdr *)rx->skb->data; |
1464 | fc = hdr->frame_control; | 1471 | fc = hdr->frame_control; |
1472 | |||
1473 | if (ieee80211_is_ctl(fc)) | ||
1474 | return RX_CONTINUE; | ||
1475 | |||
1465 | sc = le16_to_cpu(hdr->seq_ctrl); | 1476 | sc = le16_to_cpu(hdr->seq_ctrl); |
1466 | frag = sc & IEEE80211_SCTL_FRAG; | 1477 | frag = sc & IEEE80211_SCTL_FRAG; |
1467 | 1478 | ||
1468 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || | 1479 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || |
1469 | (rx->skb)->len < 24 || | ||
1470 | is_multicast_ether_addr(hdr->addr1))) { | 1480 | is_multicast_ether_addr(hdr->addr1))) { |
1471 | /* not fragmented */ | 1481 | /* not fragmented */ |
1472 | goto out; | 1482 | goto out; |
@@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1889 | 1899 | ||
1890 | hdr = (struct ieee80211_hdr *) skb->data; | 1900 | hdr = (struct ieee80211_hdr *) skb->data; |
1891 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1901 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1902 | |||
1903 | /* make sure fixed part of mesh header is there, also checks skb len */ | ||
1904 | if (!pskb_may_pull(rx->skb, hdrlen + 6)) | ||
1905 | return RX_DROP_MONITOR; | ||
1906 | |||
1907 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | ||
1908 | |||
1909 | /* make sure full mesh header is there, also checks skb len */ | ||
1910 | if (!pskb_may_pull(rx->skb, | ||
1911 | hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) | ||
1912 | return RX_DROP_MONITOR; | ||
1913 | |||
1914 | /* reload pointers */ | ||
1915 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1892 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | 1916 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1893 | 1917 | ||
1894 | /* frame is in RMC, don't forward */ | 1918 | /* frame is in RMC, don't forward */ |
@@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1897 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) | 1921 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) |
1898 | return RX_DROP_MONITOR; | 1922 | return RX_DROP_MONITOR; |
1899 | 1923 | ||
1900 | if (!ieee80211_is_data(hdr->frame_control)) | 1924 | if (!ieee80211_is_data(hdr->frame_control) || |
1925 | !(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1901 | return RX_CONTINUE; | 1926 | return RX_CONTINUE; |
1902 | 1927 | ||
1903 | if (!mesh_hdr->ttl) | 1928 | if (!mesh_hdr->ttl) |
@@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1911 | if (is_multicast_ether_addr(hdr->addr1)) { | 1936 | if (is_multicast_ether_addr(hdr->addr1)) { |
1912 | mpp_addr = hdr->addr3; | 1937 | mpp_addr = hdr->addr3; |
1913 | proxied_addr = mesh_hdr->eaddr1; | 1938 | proxied_addr = mesh_hdr->eaddr1; |
1914 | } else { | 1939 | } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { |
1940 | /* has_a4 already checked in ieee80211_rx_mesh_check */ | ||
1915 | mpp_addr = hdr->addr4; | 1941 | mpp_addr = hdr->addr4; |
1916 | proxied_addr = mesh_hdr->eaddr2; | 1942 | proxied_addr = mesh_hdr->eaddr2; |
1943 | } else { | ||
1944 | return RX_DROP_MONITOR; | ||
1917 | } | 1945 | } |
1918 | 1946 | ||
1919 | rcu_read_lock(); | 1947 | rcu_read_lock(); |
@@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1941 | } | 1969 | } |
1942 | skb_set_queue_mapping(skb, q); | 1970 | skb_set_queue_mapping(skb, q); |
1943 | 1971 | ||
1944 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1945 | goto out; | ||
1946 | |||
1947 | if (!--mesh_hdr->ttl) { | 1972 | if (!--mesh_hdr->ttl) { |
1948 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); | 1973 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); |
1949 | return RX_DROP_MONITOR; | 1974 | goto out; |
1950 | } | 1975 | } |
1951 | 1976 | ||
1952 | if (!ifmsh->mshcfg.dot11MeshForwarding) | 1977 | if (!ifmsh->mshcfg.dot11MeshForwarding) |
@@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2353 | } | 2378 | } |
2354 | break; | 2379 | break; |
2355 | case WLAN_CATEGORY_SELF_PROTECTED: | 2380 | case WLAN_CATEGORY_SELF_PROTECTED: |
2381 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
2382 | sizeof(mgmt->u.action.u.self_prot.action_code))) | ||
2383 | break; | ||
2384 | |||
2356 | switch (mgmt->u.action.u.self_prot.action_code) { | 2385 | switch (mgmt->u.action.u.self_prot.action_code) { |
2357 | case WLAN_SP_MESH_PEERING_OPEN: | 2386 | case WLAN_SP_MESH_PEERING_OPEN: |
2358 | case WLAN_SP_MESH_PEERING_CLOSE: | 2387 | case WLAN_SP_MESH_PEERING_CLOSE: |
@@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2371 | } | 2400 | } |
2372 | break; | 2401 | break; |
2373 | case WLAN_CATEGORY_MESH_ACTION: | 2402 | case WLAN_CATEGORY_MESH_ACTION: |
2403 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
2404 | sizeof(mgmt->u.action.u.mesh_action.action_code))) | ||
2405 | break; | ||
2406 | |||
2374 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2407 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2375 | break; | 2408 | break; |
2376 | if (mesh_action_is_path_sel(mgmt) && | 2409 | if (mesh_action_is_path_sel(mgmt) && |
@@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2913 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) | 2946 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
2914 | local->dot11ReceivedFragmentCount++; | 2947 | local->dot11ReceivedFragmentCount++; |
2915 | 2948 | ||
2916 | if (ieee80211_is_mgmt(fc)) | 2949 | if (ieee80211_is_mgmt(fc)) { |
2917 | err = skb_linearize(skb); | 2950 | /* drop frame if too short for header */ |
2918 | else | 2951 | if (skb->len < ieee80211_hdrlen(fc)) |
2952 | err = -ENOBUFS; | ||
2953 | else | ||
2954 | err = skb_linearize(skb); | ||
2955 | } else { | ||
2919 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); | 2956 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); |
2957 | } | ||
2920 | 2958 | ||
2921 | if (err) { | 2959 | if (err) { |
2922 | dev_kfree_skb(skb); | 2960 | dev_kfree_skb(skb); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 797dd36a220d..0a4e4c04db89 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -650,7 +650,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, | |||
650 | */ | 650 | */ |
651 | if (!skb) | 651 | if (!skb) |
652 | break; | 652 | break; |
653 | dev_kfree_skb(skb); | 653 | ieee80211_free_txskb(&local->hw, skb); |
654 | } | 654 | } |
655 | 655 | ||
656 | /* | 656 | /* |
@@ -679,7 +679,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, | |||
679 | local->total_ps_buffered--; | 679 | local->total_ps_buffered--; |
680 | ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n", | 680 | ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n", |
681 | sta->sta.addr); | 681 | sta->sta.addr); |
682 | dev_kfree_skb(skb); | 682 | ieee80211_free_txskb(&local->hw, skb); |
683 | } | 683 | } |
684 | 684 | ||
685 | /* | 685 | /* |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 22ca35054dd0..239391807ca9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
406 | int queue = info->hw_queue; | 406 | int queue = info->hw_queue; |
407 | 407 | ||
408 | if (WARN_ON(!info->control.vif)) { | 408 | if (WARN_ON(!info->control.vif)) { |
409 | kfree_skb(skb); | 409 | ieee80211_free_txskb(&local->hw, skb); |
410 | return; | 410 | return; |
411 | } | 411 | } |
412 | 412 | ||
@@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
431 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 431 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
432 | 432 | ||
433 | if (WARN_ON(!info->control.vif)) { | 433 | if (WARN_ON(!info->control.vif)) { |
434 | kfree_skb(skb); | 434 | ieee80211_free_txskb(&local->hw, skb); |
435 | continue; | 435 | continue; |
436 | } | 436 | } |
437 | 437 | ||
@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
643 | break; | 643 | break; |
644 | } | 644 | } |
645 | 645 | ||
646 | if (id != WLAN_EID_VENDOR_SPECIFIC && | 646 | switch (id) { |
647 | id != WLAN_EID_QUIET && | 647 | case WLAN_EID_SSID: |
648 | test_bit(id, seen_elems)) { | 648 | case WLAN_EID_SUPP_RATES: |
649 | elems->parse_error = true; | 649 | case WLAN_EID_FH_PARAMS: |
650 | left -= elen; | 650 | case WLAN_EID_DS_PARAMS: |
651 | pos += elen; | 651 | case WLAN_EID_CF_PARAMS: |
652 | continue; | 652 | case WLAN_EID_TIM: |
653 | case WLAN_EID_IBSS_PARAMS: | ||
654 | case WLAN_EID_CHALLENGE: | ||
655 | case WLAN_EID_RSN: | ||
656 | case WLAN_EID_ERP_INFO: | ||
657 | case WLAN_EID_EXT_SUPP_RATES: | ||
658 | case WLAN_EID_HT_CAPABILITY: | ||
659 | case WLAN_EID_HT_OPERATION: | ||
660 | case WLAN_EID_VHT_CAPABILITY: | ||
661 | case WLAN_EID_VHT_OPERATION: | ||
662 | case WLAN_EID_MESH_ID: | ||
663 | case WLAN_EID_MESH_CONFIG: | ||
664 | case WLAN_EID_PEER_MGMT: | ||
665 | case WLAN_EID_PREQ: | ||
666 | case WLAN_EID_PREP: | ||
667 | case WLAN_EID_PERR: | ||
668 | case WLAN_EID_RANN: | ||
669 | case WLAN_EID_CHANNEL_SWITCH: | ||
670 | case WLAN_EID_EXT_CHANSWITCH_ANN: | ||
671 | case WLAN_EID_COUNTRY: | ||
672 | case WLAN_EID_PWR_CONSTRAINT: | ||
673 | case WLAN_EID_TIMEOUT_INTERVAL: | ||
674 | if (test_bit(id, seen_elems)) { | ||
675 | elems->parse_error = true; | ||
676 | left -= elen; | ||
677 | pos += elen; | ||
678 | continue; | ||
679 | } | ||
680 | break; | ||
653 | } | 681 | } |
654 | 682 | ||
655 | if (calc_crc && id < 64 && (filter & (1ULL << id))) | 683 | if (calc_crc && id < 64 && (filter & (1ULL << id))) |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index bdb53aba888e..8bd2f5c6a56e 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
106 | if (status->flag & RX_FLAG_MMIC_ERROR) | 106 | if (status->flag & RX_FLAG_MMIC_ERROR) |
107 | goto mic_fail; | 107 | goto mic_fail; |
108 | 108 | ||
109 | if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) | 109 | if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key && |
110 | rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) | ||
110 | goto update_iv; | 111 | goto update_iv; |
111 | 112 | ||
112 | return RX_CONTINUE; | 113 | return RX_CONTINUE; |
@@ -545,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
545 | 546 | ||
546 | static void bip_aad(struct sk_buff *skb, u8 *aad) | 547 | static void bip_aad(struct sk_buff *skb, u8 *aad) |
547 | { | 548 | { |
549 | __le16 mask_fc; | ||
550 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
551 | |||
548 | /* BIP AAD: FC(masked) || A1 || A2 || A3 */ | 552 | /* BIP AAD: FC(masked) || A1 || A2 || A3 */ |
549 | 553 | ||
550 | /* FC type/subtype */ | 554 | /* FC type/subtype */ |
551 | aad[0] = skb->data[0]; | ||
552 | /* Mask FC Retry, PwrMgt, MoreData flags to zero */ | 555 | /* Mask FC Retry, PwrMgt, MoreData flags to zero */ |
553 | aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); | 556 | mask_fc = hdr->frame_control; |
557 | mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM | | ||
558 | IEEE80211_FCTL_MOREDATA); | ||
559 | put_unaligned(mask_fc, (__le16 *) &aad[0]); | ||
554 | /* A1 || A2 || A3 */ | 560 | /* A1 || A2 || A3 */ |
555 | memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); | 561 | memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN); |
556 | } | 562 | } |
557 | 563 | ||
558 | 564 | ||
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 7e7198b51c06..c4ee43710aab 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -2589,6 +2589,8 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u) | |||
2589 | struct ip_vs_proto_data *pd; | 2589 | struct ip_vs_proto_data *pd; |
2590 | #endif | 2590 | #endif |
2591 | 2591 | ||
2592 | memset(u, 0, sizeof (*u)); | ||
2593 | |||
2592 | #ifdef CONFIG_IP_VS_PROTO_TCP | 2594 | #ifdef CONFIG_IP_VS_PROTO_TCP |
2593 | pd = ip_vs_proto_data_get(net, IPPROTO_TCP); | 2595 | pd = ip_vs_proto_data_get(net, IPPROTO_TCP); |
2594 | u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ; | 2596 | u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ; |
@@ -2766,7 +2768,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2766 | { | 2768 | { |
2767 | struct ip_vs_timeout_user t; | 2769 | struct ip_vs_timeout_user t; |
2768 | 2770 | ||
2769 | memset(&t, 0, sizeof(t)); | ||
2770 | __ip_vs_get_timeouts(net, &t); | 2771 | __ip_vs_get_timeouts(net, &t); |
2771 | if (copy_to_user(user, &t, sizeof(t)) != 0) | 2772 | if (copy_to_user(user, &t, sizeof(t)) != 0) |
2772 | ret = -EFAULT; | 2773 | ret = -EFAULT; |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 1b30b0dee708..962795e839ab 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -753,7 +753,8 @@ static int callforward_do_filter(const union nf_inet_addr *src, | |||
753 | flowi4_to_flowi(&fl1), false)) { | 753 | flowi4_to_flowi(&fl1), false)) { |
754 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, | 754 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, |
755 | flowi4_to_flowi(&fl2), false)) { | 755 | flowi4_to_flowi(&fl2), false)) { |
756 | if (rt1->rt_gateway == rt2->rt_gateway && | 756 | if (rt_nexthop(rt1, fl1.daddr) == |
757 | rt_nexthop(rt2, fl2.daddr) && | ||
757 | rt1->dst.dev == rt2->dst.dev) | 758 | rt1->dst.dev == rt2->dst.dev) |
758 | ret = 1; | 759 | ret = 1; |
759 | dst_release(&rt2->dst); | 760 | dst_release(&rt2->dst); |
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 16c712563860..ae7f5daeee43 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | |||
180 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; | 180 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; |
181 | struct ctnl_timeout *timeout; | 181 | struct ctnl_timeout *timeout; |
182 | struct nf_conn_timeout *timeout_ext; | 182 | struct nf_conn_timeout *timeout_ext; |
183 | const struct ipt_entry *e = par->entryinfo; | ||
184 | struct nf_conntrack_l4proto *l4proto; | 183 | struct nf_conntrack_l4proto *l4proto; |
185 | int ret = 0; | 184 | int ret = 0; |
185 | u8 proto; | ||
186 | 186 | ||
187 | rcu_read_lock(); | 187 | rcu_read_lock(); |
188 | timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); | 188 | timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); |
@@ -192,9 +192,11 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | |||
192 | goto out; | 192 | goto out; |
193 | } | 193 | } |
194 | 194 | ||
195 | if (e->ip.invflags & IPT_INV_PROTO) { | 195 | proto = xt_ct_find_proto(par); |
196 | if (!proto) { | ||
196 | ret = -EINVAL; | 197 | ret = -EINVAL; |
197 | pr_info("You cannot use inversion on L4 protocol\n"); | 198 | pr_info("You must specify a L4 protocol, and not use " |
199 | "inversions on it.\n"); | ||
198 | goto out; | 200 | goto out; |
199 | } | 201 | } |
200 | 202 | ||
@@ -214,7 +216,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | |||
214 | /* Make sure the timeout policy matches any existing protocol tracker, | 216 | /* Make sure the timeout policy matches any existing protocol tracker, |
215 | * otherwise default to generic. | 217 | * otherwise default to generic. |
216 | */ | 218 | */ |
217 | l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto); | 219 | l4proto = __nf_ct_l4proto_find(par->family, proto); |
218 | if (timeout->l4proto->l4proto != l4proto->l4proto) { | 220 | if (timeout->l4proto->l4proto != l4proto->l4proto) { |
219 | ret = -EINVAL; | 221 | ret = -EINVAL; |
220 | pr_info("Timeout policy `%s' can only be used by L4 protocol " | 222 | pr_info("Timeout policy `%s' can only be used by L4 protocol " |
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index ee2e5bc5a8c7..bd93e51d30ac 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c | |||
@@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info) | |||
70 | fl4.daddr = info->gw.ip; | 70 | fl4.daddr = info->gw.ip; |
71 | fl4.flowi4_tos = RT_TOS(iph->tos); | 71 | fl4.flowi4_tos = RT_TOS(iph->tos); |
72 | fl4.flowi4_scope = RT_SCOPE_UNIVERSE; | 72 | fl4.flowi4_scope = RT_SCOPE_UNIVERSE; |
73 | fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH; | ||
73 | rt = ip_route_output_key(net, &fl4); | 74 | rt = ip_route_output_key(net, &fl4); |
74 | if (IS_ERR(rt)) | 75 | if (IS_ERR(rt)) |
75 | return false; | 76 | return false; |
diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c index 81aafa8e4fef..bea7464cc43f 100644 --- a/net/netfilter/xt_nat.c +++ b/net/netfilter/xt_nat.c | |||
@@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { | |||
111 | .family = NFPROTO_IPV4, | 111 | .family = NFPROTO_IPV4, |
112 | .table = "nat", | 112 | .table = "nat", |
113 | .hooks = (1 << NF_INET_POST_ROUTING) | | 113 | .hooks = (1 << NF_INET_POST_ROUTING) | |
114 | (1 << NF_INET_LOCAL_OUT), | 114 | (1 << NF_INET_LOCAL_IN), |
115 | .me = THIS_MODULE, | 115 | .me = THIS_MODULE, |
116 | }, | 116 | }, |
117 | { | 117 | { |
@@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { | |||
123 | .family = NFPROTO_IPV4, | 123 | .family = NFPROTO_IPV4, |
124 | .table = "nat", | 124 | .table = "nat", |
125 | .hooks = (1 << NF_INET_PRE_ROUTING) | | 125 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
126 | (1 << NF_INET_LOCAL_IN), | 126 | (1 << NF_INET_LOCAL_OUT), |
127 | .me = THIS_MODULE, | 127 | .me = THIS_MODULE, |
128 | }, | 128 | }, |
129 | { | 129 | { |
@@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { | |||
133 | .targetsize = sizeof(struct nf_nat_range), | 133 | .targetsize = sizeof(struct nf_nat_range), |
134 | .table = "nat", | 134 | .table = "nat", |
135 | .hooks = (1 << NF_INET_POST_ROUTING) | | 135 | .hooks = (1 << NF_INET_POST_ROUTING) | |
136 | (1 << NF_INET_LOCAL_OUT), | 136 | (1 << NF_INET_LOCAL_IN), |
137 | .me = THIS_MODULE, | 137 | .me = THIS_MODULE, |
138 | }, | 138 | }, |
139 | { | 139 | { |
@@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { | |||
143 | .targetsize = sizeof(struct nf_nat_range), | 143 | .targetsize = sizeof(struct nf_nat_range), |
144 | .table = "nat", | 144 | .table = "nat", |
145 | .hooks = (1 << NF_INET_PRE_ROUTING) | | 145 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
146 | (1 << NF_INET_LOCAL_IN), | 146 | (1 << NF_INET_LOCAL_OUT), |
147 | .me = THIS_MODULE, | 147 | .me = THIS_MODULE, |
148 | }, | 148 | }, |
149 | }; | 149 | }; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 01e944a017a4..4da797fa5ec5 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk); | |||
138 | static DEFINE_RWLOCK(nl_table_lock); | 138 | static DEFINE_RWLOCK(nl_table_lock); |
139 | static atomic_t nl_table_users = ATOMIC_INIT(0); | 139 | static atomic_t nl_table_users = ATOMIC_INIT(0); |
140 | 140 | ||
141 | #define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); | ||
142 | |||
141 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); | 143 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); |
142 | 144 | ||
143 | static inline u32 netlink_group_mask(u32 group) | 145 | static inline u32 netlink_group_mask(u32 group) |
@@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk) | |||
345 | struct hlist_node *node; | 347 | struct hlist_node *node; |
346 | unsigned long mask; | 348 | unsigned long mask; |
347 | unsigned int i; | 349 | unsigned int i; |
350 | struct listeners *listeners; | ||
351 | |||
352 | listeners = nl_deref_protected(tbl->listeners); | ||
353 | if (!listeners) | ||
354 | return; | ||
348 | 355 | ||
349 | for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { | 356 | for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { |
350 | mask = 0; | 357 | mask = 0; |
@@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk) | |||
352 | if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) | 359 | if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) |
353 | mask |= nlk_sk(sk)->groups[i]; | 360 | mask |= nlk_sk(sk)->groups[i]; |
354 | } | 361 | } |
355 | tbl->listeners->masks[i] = mask; | 362 | listeners->masks[i] = mask; |
356 | } | 363 | } |
357 | /* this function is only called with the netlink table "grabbed", which | 364 | /* this function is only called with the netlink table "grabbed", which |
358 | * makes sure updates are visible before bind or setsockopt return. */ | 365 | * makes sure updates are visible before bind or setsockopt return. */ |
@@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock) | |||
536 | if (netlink_is_kernel(sk)) { | 543 | if (netlink_is_kernel(sk)) { |
537 | BUG_ON(nl_table[sk->sk_protocol].registered == 0); | 544 | BUG_ON(nl_table[sk->sk_protocol].registered == 0); |
538 | if (--nl_table[sk->sk_protocol].registered == 0) { | 545 | if (--nl_table[sk->sk_protocol].registered == 0) { |
539 | kfree(nl_table[sk->sk_protocol].listeners); | 546 | struct listeners *old; |
547 | |||
548 | old = nl_deref_protected(nl_table[sk->sk_protocol].listeners); | ||
549 | RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL); | ||
550 | kfree_rcu(old, rcu); | ||
540 | nl_table[sk->sk_protocol].module = NULL; | 551 | nl_table[sk->sk_protocol].module = NULL; |
541 | nl_table[sk->sk_protocol].bind = NULL; | 552 | nl_table[sk->sk_protocol].bind = NULL; |
542 | nl_table[sk->sk_protocol].flags = 0; | 553 | nl_table[sk->sk_protocol].flags = 0; |
@@ -982,7 +993,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) | |||
982 | rcu_read_lock(); | 993 | rcu_read_lock(); |
983 | listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); | 994 | listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); |
984 | 995 | ||
985 | if (group - 1 < nl_table[sk->sk_protocol].groups) | 996 | if (listeners && group - 1 < nl_table[sk->sk_protocol].groups) |
986 | res = test_bit(group - 1, listeners->masks); | 997 | res = test_bit(group - 1, listeners->masks); |
987 | 998 | ||
988 | rcu_read_unlock(); | 999 | rcu_read_unlock(); |
@@ -1625,7 +1636,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups) | |||
1625 | new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); | 1636 | new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); |
1626 | if (!new) | 1637 | if (!new) |
1627 | return -ENOMEM; | 1638 | return -ENOMEM; |
1628 | old = rcu_dereference_protected(tbl->listeners, 1); | 1639 | old = nl_deref_protected(tbl->listeners); |
1629 | memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); | 1640 | memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); |
1630 | rcu_assign_pointer(tbl->listeners, new); | 1641 | rcu_assign_pointer(tbl->listeners, new); |
1631 | 1642 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 59d16ea927f0..a60d1f8b41c5 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -974,7 +974,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, | |||
974 | void *addr_buf; | 974 | void *addr_buf; |
975 | struct sctp_af *af; | 975 | struct sctp_af *af; |
976 | 976 | ||
977 | SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p" | 977 | SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p" |
978 | " addrs_size %d opt %d\n", sk, addrs, addrs_size, op); | 978 | " addrs_size %d opt %d\n", sk, addrs, addrs_size, op); |
979 | 979 | ||
980 | if (unlikely(addrs_size <= 0)) | 980 | if (unlikely(addrs_size <= 0)) |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 5a3d675d2f2f..a9c0bbccad6b 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
@@ -172,7 +172,7 @@ out_free: | |||
172 | xprt_free_allocation(req); | 172 | xprt_free_allocation(req); |
173 | 173 | ||
174 | dprintk("RPC: setup backchannel transport failed\n"); | 174 | dprintk("RPC: setup backchannel transport failed\n"); |
175 | return -1; | 175 | return -ENOMEM; |
176 | } | 176 | } |
177 | EXPORT_SYMBOL_GPL(xprt_setup_backchannel); | 177 | EXPORT_SYMBOL_GPL(xprt_setup_backchannel); |
178 | 178 | ||
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index aaaadfbe36e9..75853cabf4c9 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -254,7 +254,6 @@ struct sock_xprt { | |||
254 | void (*old_data_ready)(struct sock *, int); | 254 | void (*old_data_ready)(struct sock *, int); |
255 | void (*old_state_change)(struct sock *); | 255 | void (*old_state_change)(struct sock *); |
256 | void (*old_write_space)(struct sock *); | 256 | void (*old_write_space)(struct sock *); |
257 | void (*old_error_report)(struct sock *); | ||
258 | }; | 257 | }; |
259 | 258 | ||
260 | /* | 259 | /* |
@@ -737,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
737 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | 736 | dprintk("RPC: sendmsg returned unrecognized error %d\n", |
738 | -status); | 737 | -status); |
739 | case -ECONNRESET: | 738 | case -ECONNRESET: |
740 | case -EPIPE: | ||
741 | xs_tcp_shutdown(xprt); | 739 | xs_tcp_shutdown(xprt); |
742 | case -ECONNREFUSED: | 740 | case -ECONNREFUSED: |
743 | case -ENOTCONN: | 741 | case -ENOTCONN: |
742 | case -EPIPE: | ||
744 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 743 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); |
745 | } | 744 | } |
746 | 745 | ||
@@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) | |||
781 | transport->old_data_ready = sk->sk_data_ready; | 780 | transport->old_data_ready = sk->sk_data_ready; |
782 | transport->old_state_change = sk->sk_state_change; | 781 | transport->old_state_change = sk->sk_state_change; |
783 | transport->old_write_space = sk->sk_write_space; | 782 | transport->old_write_space = sk->sk_write_space; |
784 | transport->old_error_report = sk->sk_error_report; | ||
785 | } | 783 | } |
786 | 784 | ||
787 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) | 785 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) |
@@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s | |||
789 | sk->sk_data_ready = transport->old_data_ready; | 787 | sk->sk_data_ready = transport->old_data_ready; |
790 | sk->sk_state_change = transport->old_state_change; | 788 | sk->sk_state_change = transport->old_state_change; |
791 | sk->sk_write_space = transport->old_write_space; | 789 | sk->sk_write_space = transport->old_write_space; |
792 | sk->sk_error_report = transport->old_error_report; | ||
793 | } | 790 | } |
794 | 791 | ||
795 | static void xs_reset_transport(struct sock_xprt *transport) | 792 | static void xs_reset_transport(struct sock_xprt *transport) |
@@ -1453,7 +1450,7 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) | |||
1453 | xprt_clear_connecting(xprt); | 1450 | xprt_clear_connecting(xprt); |
1454 | } | 1451 | } |
1455 | 1452 | ||
1456 | static void xs_sock_mark_closed(struct rpc_xprt *xprt) | 1453 | static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt) |
1457 | { | 1454 | { |
1458 | smp_mb__before_clear_bit(); | 1455 | smp_mb__before_clear_bit(); |
1459 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | 1456 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); |
@@ -1461,6 +1458,11 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt) | |||
1461 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | 1458 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); |
1462 | clear_bit(XPRT_CLOSING, &xprt->state); | 1459 | clear_bit(XPRT_CLOSING, &xprt->state); |
1463 | smp_mb__after_clear_bit(); | 1460 | smp_mb__after_clear_bit(); |
1461 | } | ||
1462 | |||
1463 | static void xs_sock_mark_closed(struct rpc_xprt *xprt) | ||
1464 | { | ||
1465 | xs_sock_reset_connection_flags(xprt); | ||
1464 | /* Mark transport as closed and wake up all pending tasks */ | 1466 | /* Mark transport as closed and wake up all pending tasks */ |
1465 | xprt_disconnect_done(xprt); | 1467 | xprt_disconnect_done(xprt); |
1466 | } | 1468 | } |
@@ -1516,6 +1518,7 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1516 | case TCP_CLOSE_WAIT: | 1518 | case TCP_CLOSE_WAIT: |
1517 | /* The server initiated a shutdown of the socket */ | 1519 | /* The server initiated a shutdown of the socket */ |
1518 | xprt->connect_cookie++; | 1520 | xprt->connect_cookie++; |
1521 | clear_bit(XPRT_CONNECTED, &xprt->state); | ||
1519 | xs_tcp_force_close(xprt); | 1522 | xs_tcp_force_close(xprt); |
1520 | case TCP_CLOSING: | 1523 | case TCP_CLOSING: |
1521 | /* | 1524 | /* |
@@ -1540,25 +1543,6 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1540 | read_unlock_bh(&sk->sk_callback_lock); | 1543 | read_unlock_bh(&sk->sk_callback_lock); |
1541 | } | 1544 | } |
1542 | 1545 | ||
1543 | /** | ||
1544 | * xs_error_report - callback mainly for catching socket errors | ||
1545 | * @sk: socket | ||
1546 | */ | ||
1547 | static void xs_error_report(struct sock *sk) | ||
1548 | { | ||
1549 | struct rpc_xprt *xprt; | ||
1550 | |||
1551 | read_lock_bh(&sk->sk_callback_lock); | ||
1552 | if (!(xprt = xprt_from_sock(sk))) | ||
1553 | goto out; | ||
1554 | dprintk("RPC: %s client %p...\n" | ||
1555 | "RPC: error %d\n", | ||
1556 | __func__, xprt, sk->sk_err); | ||
1557 | xprt_wake_pending_tasks(xprt, -EAGAIN); | ||
1558 | out: | ||
1559 | read_unlock_bh(&sk->sk_callback_lock); | ||
1560 | } | ||
1561 | |||
1562 | static void xs_write_space(struct sock *sk) | 1546 | static void xs_write_space(struct sock *sk) |
1563 | { | 1547 | { |
1564 | struct socket *sock; | 1548 | struct socket *sock; |
@@ -1858,7 +1842,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt, | |||
1858 | sk->sk_user_data = xprt; | 1842 | sk->sk_user_data = xprt; |
1859 | sk->sk_data_ready = xs_local_data_ready; | 1843 | sk->sk_data_ready = xs_local_data_ready; |
1860 | sk->sk_write_space = xs_udp_write_space; | 1844 | sk->sk_write_space = xs_udp_write_space; |
1861 | sk->sk_error_report = xs_error_report; | ||
1862 | sk->sk_allocation = GFP_ATOMIC; | 1845 | sk->sk_allocation = GFP_ATOMIC; |
1863 | 1846 | ||
1864 | xprt_clear_connected(xprt); | 1847 | xprt_clear_connected(xprt); |
@@ -1983,7 +1966,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1983 | sk->sk_user_data = xprt; | 1966 | sk->sk_user_data = xprt; |
1984 | sk->sk_data_ready = xs_udp_data_ready; | 1967 | sk->sk_data_ready = xs_udp_data_ready; |
1985 | sk->sk_write_space = xs_udp_write_space; | 1968 | sk->sk_write_space = xs_udp_write_space; |
1986 | sk->sk_error_report = xs_error_report; | ||
1987 | sk->sk_no_check = UDP_CSUM_NORCV; | 1969 | sk->sk_no_check = UDP_CSUM_NORCV; |
1988 | sk->sk_allocation = GFP_ATOMIC; | 1970 | sk->sk_allocation = GFP_ATOMIC; |
1989 | 1971 | ||
@@ -2050,10 +2032,8 @@ static void xs_abort_connection(struct sock_xprt *transport) | |||
2050 | any.sa_family = AF_UNSPEC; | 2032 | any.sa_family = AF_UNSPEC; |
2051 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); | 2033 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); |
2052 | if (!result) | 2034 | if (!result) |
2053 | xs_sock_mark_closed(&transport->xprt); | 2035 | xs_sock_reset_connection_flags(&transport->xprt); |
2054 | else | 2036 | dprintk("RPC: AF_UNSPEC connect return code %d\n", result); |
2055 | dprintk("RPC: AF_UNSPEC connect return code %d\n", | ||
2056 | result); | ||
2057 | } | 2037 | } |
2058 | 2038 | ||
2059 | static void xs_tcp_reuse_connection(struct sock_xprt *transport) | 2039 | static void xs_tcp_reuse_connection(struct sock_xprt *transport) |
@@ -2098,7 +2078,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
2098 | sk->sk_data_ready = xs_tcp_data_ready; | 2078 | sk->sk_data_ready = xs_tcp_data_ready; |
2099 | sk->sk_state_change = xs_tcp_state_change; | 2079 | sk->sk_state_change = xs_tcp_state_change; |
2100 | sk->sk_write_space = xs_tcp_write_space; | 2080 | sk->sk_write_space = xs_tcp_write_space; |
2101 | sk->sk_error_report = xs_error_report; | ||
2102 | sk->sk_allocation = GFP_ATOMIC; | 2081 | sk->sk_allocation = GFP_ATOMIC; |
2103 | 2082 | ||
2104 | /* socket options */ | 2083 | /* socket options */ |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 443d4d7deea2..3f7253052088 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -526,8 +526,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
526 | for (i = 0; i < sband->n_channels; i++) { | 526 | for (i = 0; i < sband->n_channels; i++) { |
527 | sband->channels[i].orig_flags = | 527 | sband->channels[i].orig_flags = |
528 | sband->channels[i].flags; | 528 | sband->channels[i].flags; |
529 | sband->channels[i].orig_mag = | 529 | sband->channels[i].orig_mag = INT_MAX; |
530 | sband->channels[i].max_antenna_gain; | ||
531 | sband->channels[i].orig_mpwr = | 530 | sband->channels[i].orig_mpwr = |
532 | sband->channels[i].max_power; | 531 | sband->channels[i].max_power; |
533 | sband->channels[i].band = band; | 532 | sband->channels[i].band = band; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 8016fee0752b..904a7f368325 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
457 | .reason_code = reason, | 457 | .reason_code = reason, |
458 | .ie = ie, | 458 | .ie = ie, |
459 | .ie_len = ie_len, | 459 | .ie_len = ie_len, |
460 | .local_state_change = local_state_change, | ||
460 | }; | 461 | }; |
461 | 462 | ||
462 | ASSERT_WDEV_LOCK(wdev); | 463 | ASSERT_WDEV_LOCK(wdev); |
463 | 464 | ||
464 | if (local_state_change) { | 465 | if (local_state_change && (!wdev->current_bss || |
465 | if (wdev->current_bss && | 466 | !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) |
466 | ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { | ||
467 | cfg80211_unhold_bss(wdev->current_bss); | ||
468 | cfg80211_put_bss(&wdev->current_bss->pub); | ||
469 | wdev->current_bss = NULL; | ||
470 | } | ||
471 | |||
472 | return 0; | 467 | return 0; |
473 | } | ||
474 | 468 | ||
475 | return rdev->ops->deauth(&rdev->wiphy, dev, &req); | 469 | return rdev->ops->deauth(&rdev->wiphy, dev, &req); |
476 | } | 470 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3b8cbbc214db..bcc7d7ee5a51 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
908 | map_regdom_flags(reg_rule->flags) | bw_flags; | 908 | map_regdom_flags(reg_rule->flags) | bw_flags; |
909 | chan->max_antenna_gain = chan->orig_mag = | 909 | chan->max_antenna_gain = chan->orig_mag = |
910 | (int) MBI_TO_DBI(power_rule->max_antenna_gain); | 910 | (int) MBI_TO_DBI(power_rule->max_antenna_gain); |
911 | chan->max_power = chan->orig_mpwr = | 911 | chan->max_reg_power = chan->max_power = chan->orig_mpwr = |
912 | (int) MBM_TO_DBM(power_rule->max_eirp); | 912 | (int) MBM_TO_DBM(power_rule->max_eirp); |
913 | return; | 913 | return; |
914 | } | 914 | } |
@@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1331 | 1331 | ||
1332 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; | 1332 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; |
1333 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); | 1333 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); |
1334 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 1334 | chan->max_reg_power = chan->max_power = |
1335 | (int) MBM_TO_DBM(power_rule->max_eirp); | ||
1335 | } | 1336 | } |
1336 | 1337 | ||
1337 | static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, | 1338 | static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index ef35f4ef2aa6..2762e8329986 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) | |||
309 | } | 309 | } |
310 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); | 310 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); |
311 | 311 | ||
312 | static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) | 312 | unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) |
313 | { | 313 | { |
314 | int ae = meshhdr->flags & MESH_FLAGS_AE; | 314 | int ae = meshhdr->flags & MESH_FLAGS_AE; |
315 | /* 7.1.3.5a.2 */ | 315 | /* 802.11-2012, 8.2.4.7.3 */ |
316 | switch (ae) { | 316 | switch (ae) { |
317 | default: | ||
317 | case 0: | 318 | case 0: |
318 | return 6; | 319 | return 6; |
319 | case MESH_FLAGS_AE_A4: | 320 | case MESH_FLAGS_AE_A4: |
320 | return 12; | 321 | return 12; |
321 | case MESH_FLAGS_AE_A5_A6: | 322 | case MESH_FLAGS_AE_A5_A6: |
322 | return 18; | 323 | return 18; |
323 | case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): | ||
324 | return 24; | ||
325 | default: | ||
326 | return 6; | ||
327 | } | 324 | } |
328 | } | 325 | } |
326 | EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); | ||
329 | 327 | ||
330 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | 328 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, |
331 | enum nl80211_iftype iftype) | 329 | enum nl80211_iftype iftype) |
@@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
373 | /* make sure meshdr->flags is on the linear part */ | 371 | /* make sure meshdr->flags is on the linear part */ |
374 | if (!pskb_may_pull(skb, hdrlen + 1)) | 372 | if (!pskb_may_pull(skb, hdrlen + 1)) |
375 | return -1; | 373 | return -1; |
374 | if (meshdr->flags & MESH_FLAGS_AE_A4) | ||
375 | return -1; | ||
376 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | 376 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { |
377 | skb_copy_bits(skb, hdrlen + | 377 | skb_copy_bits(skb, hdrlen + |
378 | offsetof(struct ieee80211s_hdr, eaddr1), | 378 | offsetof(struct ieee80211s_hdr, eaddr1), |
@@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
397 | /* make sure meshdr->flags is on the linear part */ | 397 | /* make sure meshdr->flags is on the linear part */ |
398 | if (!pskb_may_pull(skb, hdrlen + 1)) | 398 | if (!pskb_may_pull(skb, hdrlen + 1)) |
399 | return -1; | 399 | return -1; |
400 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) | ||
401 | return -1; | ||
400 | if (meshdr->flags & MESH_FLAGS_AE_A4) | 402 | if (meshdr->flags & MESH_FLAGS_AE_A4) |
401 | skb_copy_bits(skb, hdrlen + | 403 | skb_copy_bits(skb, hdrlen + |
402 | offsetof(struct ieee80211s_hdr, eaddr1), | 404 | offsetof(struct ieee80211s_hdr, eaddr1), |