diff options
Diffstat (limited to 'net')
88 files changed, 848 insertions, 529 deletions
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index fc1835c6bb40..00f9e144cc97 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
| @@ -251,7 +251,7 @@ batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) | |||
| 251 | kfree(entry); | 251 | kfree(entry); |
| 252 | 252 | ||
| 253 | /* Make room for the rest of the fragments. */ | 253 | /* Make room for the rest of the fragments. */ |
| 254 | if (pskb_expand_head(skb_out, 0, size - skb->len, GFP_ATOMIC) < 0) { | 254 | if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { |
| 255 | kfree_skb(skb_out); | 255 | kfree_skb(skb_out); |
| 256 | skb_out = NULL; | 256 | skb_out = NULL; |
| 257 | goto free; | 257 | goto free; |
| @@ -434,7 +434,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb, | |||
| 434 | * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE | 434 | * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE |
| 435 | */ | 435 | */ |
| 436 | mtu = min_t(unsigned, mtu, BATADV_FRAG_MAX_FRAG_SIZE); | 436 | mtu = min_t(unsigned, mtu, BATADV_FRAG_MAX_FRAG_SIZE); |
| 437 | max_fragment_size = (mtu - header_size - ETH_HLEN); | 437 | max_fragment_size = mtu - header_size; |
| 438 | max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS; | 438 | max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS; |
| 439 | 439 | ||
| 440 | /* Don't even try to fragment, if we need more than 16 fragments */ | 440 | /* Don't even try to fragment, if we need more than 16 fragments */ |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 90cff585b37d..e0bcf9e84273 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
| @@ -810,7 +810,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
| 810 | goto out; | 810 | goto out; |
| 811 | 811 | ||
| 812 | gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); | 812 | gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); |
| 813 | if (!gw_node->bandwidth_down == 0) | 813 | if (!gw_node) |
| 814 | goto out; | 814 | goto out; |
| 815 | 815 | ||
| 816 | switch (atomic_read(&bat_priv->gw_mode)) { | 816 | switch (atomic_read(&bat_priv->gw_mode)) { |
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index ab6bb2af1d45..b24e4bb64fb5 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c | |||
| @@ -685,11 +685,13 @@ static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | |||
| 685 | if (orig_initialized) | 685 | if (orig_initialized) |
| 686 | atomic_dec(&bat_priv->mcast.num_disabled); | 686 | atomic_dec(&bat_priv->mcast.num_disabled); |
| 687 | orig->capabilities |= BATADV_ORIG_CAPA_HAS_MCAST; | 687 | orig->capabilities |= BATADV_ORIG_CAPA_HAS_MCAST; |
| 688 | /* If mcast support is being switched off increase the disabled | 688 | /* If mcast support is being switched off or if this is an initial |
| 689 | * mcast node counter. | 689 | * OGM without mcast support then increase the disabled mcast |
| 690 | * node counter. | ||
| 690 | */ | 691 | */ |
| 691 | } else if (!orig_mcast_enabled && | 692 | } else if (!orig_mcast_enabled && |
| 692 | orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST) { | 693 | (orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST || |
| 694 | !orig_initialized)) { | ||
| 693 | atomic_inc(&bat_priv->mcast.num_disabled); | 695 | atomic_inc(&bat_priv->mcast.num_disabled); |
| 694 | orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_MCAST; | 696 | orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_MCAST; |
| 695 | } | 697 | } |
| @@ -738,7 +740,8 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig) | |||
| 738 | { | 740 | { |
| 739 | struct batadv_priv *bat_priv = orig->bat_priv; | 741 | struct batadv_priv *bat_priv = orig->bat_priv; |
| 740 | 742 | ||
| 741 | if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) | 743 | if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST) && |
| 744 | orig->capa_initialized & BATADV_ORIG_CAPA_HAS_MCAST) | ||
| 742 | atomic_dec(&bat_priv->mcast.num_disabled); | 745 | atomic_dec(&bat_priv->mcast.num_disabled); |
| 743 | 746 | ||
| 744 | batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS); | 747 | batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS); |
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 8d04d174669e..fab47f1f3ef9 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
| @@ -133,7 +133,7 @@ int batadv_nc_mesh_init(struct batadv_priv *bat_priv) | |||
| 133 | if (!bat_priv->nc.decoding_hash) | 133 | if (!bat_priv->nc.decoding_hash) |
| 134 | goto err; | 134 | goto err; |
| 135 | 135 | ||
| 136 | batadv_hash_set_lock_class(bat_priv->nc.coding_hash, | 136 | batadv_hash_set_lock_class(bat_priv->nc.decoding_hash, |
| 137 | &batadv_nc_decoding_hash_lock_class_key); | 137 | &batadv_nc_decoding_hash_lock_class_key); |
| 138 | 138 | ||
| 139 | INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); | 139 | INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 6a484514cd3e..bea8198d0198 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
| @@ -570,9 +570,6 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu) | |||
| 570 | 570 | ||
| 571 | batadv_frag_purge_orig(orig_node, NULL); | 571 | batadv_frag_purge_orig(orig_node, NULL); |
| 572 | 572 | ||
| 573 | batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, -1, | ||
| 574 | "originator timed out"); | ||
| 575 | |||
| 576 | if (orig_node->bat_priv->bat_algo_ops->bat_orig_free) | 573 | if (orig_node->bat_priv->bat_algo_ops->bat_orig_free) |
| 577 | orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node); | 574 | orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node); |
| 578 | 575 | ||
| @@ -678,6 +675,7 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, | |||
| 678 | atomic_set(&orig_node->last_ttvn, 0); | 675 | atomic_set(&orig_node->last_ttvn, 0); |
| 679 | orig_node->tt_buff = NULL; | 676 | orig_node->tt_buff = NULL; |
| 680 | orig_node->tt_buff_len = 0; | 677 | orig_node->tt_buff_len = 0; |
| 678 | orig_node->last_seen = jiffies; | ||
| 681 | reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); | 679 | reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); |
| 682 | orig_node->bcast_seqno_reset = reset_time; | 680 | orig_node->bcast_seqno_reset = reset_time; |
| 683 | #ifdef CONFIG_BATMAN_ADV_MCAST | 681 | #ifdef CONFIG_BATMAN_ADV_MCAST |
| @@ -977,6 +975,9 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv) | |||
| 977 | if (batadv_purge_orig_node(bat_priv, orig_node)) { | 975 | if (batadv_purge_orig_node(bat_priv, orig_node)) { |
| 978 | batadv_gw_node_delete(bat_priv, orig_node); | 976 | batadv_gw_node_delete(bat_priv, orig_node); |
| 979 | hlist_del_rcu(&orig_node->hash_entry); | 977 | hlist_del_rcu(&orig_node->hash_entry); |
| 978 | batadv_tt_global_del_orig(orig_node->bat_priv, | ||
| 979 | orig_node, -1, | ||
| 980 | "originator timed out"); | ||
| 980 | batadv_orig_node_free_ref(orig_node); | 981 | batadv_orig_node_free_ref(orig_node); |
| 981 | continue; | 982 | continue; |
| 982 | } | 983 | } |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 35f76f2f7824..6648f321864d 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
| @@ -443,11 +443,13 @@ batadv_find_router(struct batadv_priv *bat_priv, | |||
| 443 | 443 | ||
| 444 | router = batadv_orig_router_get(orig_node, recv_if); | 444 | router = batadv_orig_router_get(orig_node, recv_if); |
| 445 | 445 | ||
| 446 | if (!router) | ||
| 447 | return router; | ||
| 448 | |||
| 446 | /* only consider bonding for recv_if == BATADV_IF_DEFAULT (first hop) | 449 | /* only consider bonding for recv_if == BATADV_IF_DEFAULT (first hop) |
| 447 | * and if activated. | 450 | * and if activated. |
| 448 | */ | 451 | */ |
| 449 | if (recv_if == BATADV_IF_DEFAULT || !atomic_read(&bat_priv->bonding) || | 452 | if (!(recv_if == BATADV_IF_DEFAULT && atomic_read(&bat_priv->bonding))) |
| 450 | !router) | ||
| 451 | return router; | 453 | return router; |
| 452 | 454 | ||
| 453 | /* bonding: loop through the list of possible routers found | 455 | /* bonding: loop through the list of possible routers found |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 76617be1e797..c989253737f0 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
| @@ -390,7 +390,6 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
| 390 | 390 | ||
| 391 | drop: | 391 | drop: |
| 392 | dev->stats.rx_dropped++; | 392 | dev->stats.rx_dropped++; |
| 393 | kfree_skb(skb); | ||
| 394 | return NET_RX_DROP; | 393 | return NET_RX_DROP; |
| 395 | } | 394 | } |
| 396 | 395 | ||
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 85bcc21e84d2..ce82722d049b 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
| @@ -533,6 +533,9 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
| 533 | 533 | ||
| 534 | BT_DBG(""); | 534 | BT_DBG(""); |
| 535 | 535 | ||
| 536 | if (!l2cap_is_socket(sock)) | ||
| 537 | return -EBADFD; | ||
| 538 | |||
| 536 | baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst); | 539 | baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst); |
| 537 | baswap((void *) src, &l2cap_pi(sock->sk)->chan->src); | 540 | baswap((void *) src, &l2cap_pi(sock->sk)->chan->src); |
| 538 | 541 | ||
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 67fe5e84e68f..278a194e6af4 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
| @@ -334,6 +334,9 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) | |||
| 334 | 334 | ||
| 335 | BT_DBG(""); | 335 | BT_DBG(""); |
| 336 | 336 | ||
| 337 | if (!l2cap_is_socket(sock)) | ||
| 338 | return -EBADFD; | ||
| 339 | |||
| 337 | session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL); | 340 | session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL); |
| 338 | if (!session) | 341 | if (!session) |
| 339 | return -ENOMEM; | 342 | return -ENOMEM; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 39a5c8a01726..3f2e8b830cbd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
| @@ -242,7 +242,8 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 242 | if (rp->status) | 242 | if (rp->status) |
| 243 | return; | 243 | return; |
| 244 | 244 | ||
| 245 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) | 245 | if (test_bit(HCI_SETUP, &hdev->dev_flags) || |
| 246 | test_bit(HCI_CONFIG, &hdev->dev_flags)) | ||
| 246 | memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); | 247 | memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); |
| 247 | } | 248 | } |
| 248 | 249 | ||
| @@ -509,7 +510,8 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 509 | if (rp->status) | 510 | if (rp->status) |
| 510 | return; | 511 | return; |
| 511 | 512 | ||
| 512 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) { | 513 | if (test_bit(HCI_SETUP, &hdev->dev_flags) || |
| 514 | test_bit(HCI_CONFIG, &hdev->dev_flags)) { | ||
| 513 | hdev->hci_ver = rp->hci_ver; | 515 | hdev->hci_ver = rp->hci_ver; |
| 514 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); | 516 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); |
| 515 | hdev->lmp_ver = rp->lmp_ver; | 517 | hdev->lmp_ver = rp->lmp_ver; |
| @@ -528,7 +530,8 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, | |||
| 528 | if (rp->status) | 530 | if (rp->status) |
| 529 | return; | 531 | return; |
| 530 | 532 | ||
| 531 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) | 533 | if (test_bit(HCI_SETUP, &hdev->dev_flags) || |
| 534 | test_bit(HCI_CONFIG, &hdev->dev_flags)) | ||
| 532 | memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); | 535 | memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); |
| 533 | } | 536 | } |
| 534 | 537 | ||
| @@ -2194,7 +2197,12 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2194 | return; | 2197 | return; |
| 2195 | } | 2198 | } |
| 2196 | 2199 | ||
| 2197 | if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && | 2200 | /* Require HCI_CONNECTABLE or a whitelist entry to accept the |
| 2201 | * connection. These features are only touched through mgmt so | ||
| 2202 | * only do the checks if HCI_MGMT is set. | ||
| 2203 | */ | ||
| 2204 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && | ||
| 2205 | !test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && | ||
| 2198 | !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, | 2206 | !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, |
| 2199 | BDADDR_BREDR)) { | 2207 | BDADDR_BREDR)) { |
| 2200 | hci_reject_conn(hdev, &ev->bdaddr); | 2208 | hci_reject_conn(hdev, &ev->bdaddr); |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index cc25d0b74b36..07348e142f16 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -1314,13 +1314,14 @@ int hidp_connection_add(struct hidp_connadd_req *req, | |||
| 1314 | { | 1314 | { |
| 1315 | struct hidp_session *session; | 1315 | struct hidp_session *session; |
| 1316 | struct l2cap_conn *conn; | 1316 | struct l2cap_conn *conn; |
| 1317 | struct l2cap_chan *chan = l2cap_pi(ctrl_sock->sk)->chan; | 1317 | struct l2cap_chan *chan; |
| 1318 | int ret; | 1318 | int ret; |
| 1319 | 1319 | ||
| 1320 | ret = hidp_verify_sockets(ctrl_sock, intr_sock); | 1320 | ret = hidp_verify_sockets(ctrl_sock, intr_sock); |
| 1321 | if (ret) | 1321 | if (ret) |
| 1322 | return ret; | 1322 | return ret; |
| 1323 | 1323 | ||
| 1324 | chan = l2cap_pi(ctrl_sock->sk)->chan; | ||
| 1324 | conn = NULL; | 1325 | conn = NULL; |
| 1325 | l2cap_chan_lock(chan); | 1326 | l2cap_chan_lock(chan); |
| 1326 | if (chan->conn) | 1327 | if (chan->conn) |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 1f1de715197c..e2aa7be3a847 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -154,7 +154,8 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
| 154 | dst = NULL; | 154 | dst = NULL; |
| 155 | 155 | ||
| 156 | if (is_broadcast_ether_addr(dest)) { | 156 | if (is_broadcast_ether_addr(dest)) { |
| 157 | if (p->flags & BR_PROXYARP && | 157 | if (IS_ENABLED(CONFIG_INET) && |
| 158 | p->flags & BR_PROXYARP && | ||
| 158 | skb->protocol == htons(ETH_P_ARP)) | 159 | skb->protocol == htons(ETH_P_ARP)) |
| 159 | br_do_proxy_arp(skb, br, vid); | 160 | br_do_proxy_arp(skb, br, vid); |
| 160 | 161 | ||
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index b0330aecbf97..3244aead0926 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
| @@ -265,22 +265,12 @@ out: | |||
| 265 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 265 | data[NFT_REG_VERDICT].verdict = NF_DROP; |
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | static int nft_reject_bridge_validate_hooks(const struct nft_chain *chain) | 268 | static int nft_reject_bridge_validate(const struct nft_ctx *ctx, |
| 269 | const struct nft_expr *expr, | ||
| 270 | const struct nft_data **data) | ||
| 269 | { | 271 | { |
| 270 | struct nft_base_chain *basechain; | 272 | return nft_chain_validate_hooks(ctx->chain, (1 << NF_BR_PRE_ROUTING) | |
| 271 | 273 | (1 << NF_BR_LOCAL_IN)); | |
| 272 | if (chain->flags & NFT_BASE_CHAIN) { | ||
| 273 | basechain = nft_base_chain(chain); | ||
| 274 | |||
| 275 | switch (basechain->ops[0].hooknum) { | ||
| 276 | case NF_BR_PRE_ROUTING: | ||
| 277 | case NF_BR_LOCAL_IN: | ||
| 278 | break; | ||
| 279 | default: | ||
| 280 | return -EOPNOTSUPP; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | return 0; | ||
| 284 | } | 274 | } |
| 285 | 275 | ||
| 286 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, | 276 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, |
| @@ -290,7 +280,7 @@ static int nft_reject_bridge_init(const struct nft_ctx *ctx, | |||
| 290 | struct nft_reject *priv = nft_expr_priv(expr); | 280 | struct nft_reject *priv = nft_expr_priv(expr); |
| 291 | int icmp_code, err; | 281 | int icmp_code, err; |
| 292 | 282 | ||
| 293 | err = nft_reject_bridge_validate_hooks(ctx->chain); | 283 | err = nft_reject_bridge_validate(ctx, expr, NULL); |
| 294 | if (err < 0) | 284 | if (err < 0) |
| 295 | return err; | 285 | return err; |
| 296 | 286 | ||
| @@ -341,13 +331,6 @@ nla_put_failure: | |||
| 341 | return -1; | 331 | return -1; |
| 342 | } | 332 | } |
| 343 | 333 | ||
| 344 | static int nft_reject_bridge_validate(const struct nft_ctx *ctx, | ||
| 345 | const struct nft_expr *expr, | ||
| 346 | const struct nft_data **data) | ||
| 347 | { | ||
| 348 | return nft_reject_bridge_validate_hooks(ctx->chain); | ||
| 349 | } | ||
| 350 | |||
| 351 | static struct nft_expr_type nft_reject_bridge_type; | 334 | static struct nft_expr_type nft_reject_bridge_type; |
| 352 | static const struct nft_expr_ops nft_reject_bridge_ops = { | 335 | static const struct nft_expr_ops nft_reject_bridge_ops = { |
| 353 | .type = &nft_reject_bridge_type, | 336 | .type = &nft_reject_bridge_type, |
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 4589ff67bfa9..67a4a36febd1 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c | |||
| @@ -470,7 +470,6 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev, | |||
| 470 | ASSERT_RTNL(); | 470 | ASSERT_RTNL(); |
| 471 | caifdev = netdev_priv(dev); | 471 | caifdev = netdev_priv(dev); |
| 472 | caif_netlink_parms(data, &caifdev->conn_req); | 472 | caif_netlink_parms(data, &caifdev->conn_req); |
| 473 | dev_net_set(caifdev->netdev, src_net); | ||
| 474 | 473 | ||
| 475 | ret = register_netdevice(dev); | 474 | ret = register_netdevice(dev); |
| 476 | if (ret) | 475 | if (ret) |
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 15845814a0f2..ba6eb17226da 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c | |||
| @@ -676,7 +676,7 @@ static int calcu_signature(struct ceph_x_authorizer *au, | |||
| 676 | int ret; | 676 | int ret; |
| 677 | char tmp_enc[40]; | 677 | char tmp_enc[40]; |
| 678 | __le32 tmp[5] = { | 678 | __le32 tmp[5] = { |
| 679 | 16u, msg->hdr.crc, msg->footer.front_crc, | 679 | cpu_to_le32(16), msg->hdr.crc, msg->footer.front_crc, |
| 680 | msg->footer.middle_crc, msg->footer.data_crc, | 680 | msg->footer.middle_crc, msg->footer.data_crc, |
| 681 | }; | 681 | }; |
| 682 | ret = ceph_x_encrypt(&au->session_key, &tmp, sizeof(tmp), | 682 | ret = ceph_x_encrypt(&au->session_key, &tmp, sizeof(tmp), |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index a83062ceeec9..f2148e22b148 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
| @@ -717,7 +717,7 @@ static int get_poolop_reply_buf(const char *src, size_t src_len, | |||
| 717 | if (src_len != sizeof(u32) + dst_len) | 717 | if (src_len != sizeof(u32) + dst_len) |
| 718 | return -EINVAL; | 718 | return -EINVAL; |
| 719 | 719 | ||
| 720 | buf_len = le32_to_cpu(*(u32 *)src); | 720 | buf_len = le32_to_cpu(*(__le32 *)src); |
| 721 | if (buf_len != dst_len) | 721 | if (buf_len != dst_len) |
| 722 | return -EINVAL; | 722 | return -EINVAL; |
| 723 | 723 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index f411c28d0a66..7fe82929f509 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1694,6 +1694,7 @@ int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb) | |||
| 1694 | 1694 | ||
| 1695 | skb_scrub_packet(skb, true); | 1695 | skb_scrub_packet(skb, true); |
| 1696 | skb->protocol = eth_type_trans(skb, dev); | 1696 | skb->protocol = eth_type_trans(skb, dev); |
| 1697 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); | ||
| 1697 | 1698 | ||
| 1698 | return 0; | 1699 | return 0; |
| 1699 | } | 1700 | } |
| @@ -2351,7 +2352,6 @@ EXPORT_SYMBOL(skb_checksum_help); | |||
| 2351 | 2352 | ||
| 2352 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | 2353 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) |
| 2353 | { | 2354 | { |
| 2354 | unsigned int vlan_depth = skb->mac_len; | ||
| 2355 | __be16 type = skb->protocol; | 2355 | __be16 type = skb->protocol; |
| 2356 | 2356 | ||
| 2357 | /* Tunnel gso handlers can set protocol to ethernet. */ | 2357 | /* Tunnel gso handlers can set protocol to ethernet. */ |
| @@ -2365,35 +2365,7 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | |||
| 2365 | type = eth->h_proto; | 2365 | type = eth->h_proto; |
| 2366 | } | 2366 | } |
| 2367 | 2367 | ||
| 2368 | /* if skb->protocol is 802.1Q/AD then the header should already be | 2368 | return __vlan_get_protocol(skb, type, depth); |
| 2369 | * present at mac_len - VLAN_HLEN (if mac_len > 0), or at | ||
| 2370 | * ETH_HLEN otherwise | ||
| 2371 | */ | ||
| 2372 | if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { | ||
| 2373 | if (vlan_depth) { | ||
| 2374 | if (WARN_ON(vlan_depth < VLAN_HLEN)) | ||
| 2375 | return 0; | ||
| 2376 | vlan_depth -= VLAN_HLEN; | ||
| 2377 | } else { | ||
| 2378 | vlan_depth = ETH_HLEN; | ||
| 2379 | } | ||
| 2380 | do { | ||
| 2381 | struct vlan_hdr *vh; | ||
| 2382 | |||
| 2383 | if (unlikely(!pskb_may_pull(skb, | ||
| 2384 | vlan_depth + VLAN_HLEN))) | ||
| 2385 | return 0; | ||
| 2386 | |||
| 2387 | vh = (struct vlan_hdr *)(skb->data + vlan_depth); | ||
| 2388 | type = vh->h_vlan_encapsulated_proto; | ||
| 2389 | vlan_depth += VLAN_HLEN; | ||
| 2390 | } while (type == htons(ETH_P_8021Q) || | ||
| 2391 | type == htons(ETH_P_8021AD)); | ||
| 2392 | } | ||
| 2393 | |||
| 2394 | *depth = vlan_depth; | ||
| 2395 | |||
| 2396 | return type; | ||
| 2397 | } | 2369 | } |
| 2398 | 2370 | ||
| 2399 | /** | 2371 | /** |
| @@ -2522,7 +2494,7 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) | |||
| 2522 | /* If MPLS offload request, verify we are testing hardware MPLS features | 2494 | /* If MPLS offload request, verify we are testing hardware MPLS features |
| 2523 | * instead of standard features for the netdev. | 2495 | * instead of standard features for the netdev. |
| 2524 | */ | 2496 | */ |
| 2525 | #ifdef CONFIG_NET_MPLS_GSO | 2497 | #if IS_ENABLED(CONFIG_NET_MPLS_GSO) |
| 2526 | static netdev_features_t net_mpls_features(struct sk_buff *skb, | 2498 | static netdev_features_t net_mpls_features(struct sk_buff *skb, |
| 2527 | netdev_features_t features, | 2499 | netdev_features_t features, |
| 2528 | __be16 type) | 2500 | __be16 type) |
| @@ -2562,7 +2534,7 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, | |||
| 2562 | 2534 | ||
| 2563 | netdev_features_t netif_skb_features(struct sk_buff *skb) | 2535 | netdev_features_t netif_skb_features(struct sk_buff *skb) |
| 2564 | { | 2536 | { |
| 2565 | const struct net_device *dev = skb->dev; | 2537 | struct net_device *dev = skb->dev; |
| 2566 | netdev_features_t features = dev->features; | 2538 | netdev_features_t features = dev->features; |
| 2567 | u16 gso_segs = skb_shinfo(skb)->gso_segs; | 2539 | u16 gso_segs = skb_shinfo(skb)->gso_segs; |
| 2568 | __be16 protocol = skb->protocol; | 2540 | __be16 protocol = skb->protocol; |
| @@ -2570,11 +2542,21 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
| 2570 | if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs) | 2542 | if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs) |
| 2571 | features &= ~NETIF_F_GSO_MASK; | 2543 | features &= ~NETIF_F_GSO_MASK; |
| 2572 | 2544 | ||
| 2573 | if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) { | 2545 | /* If encapsulation offload request, verify we are testing |
| 2574 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | 2546 | * hardware encapsulation features instead of standard |
| 2575 | protocol = veh->h_vlan_encapsulated_proto; | 2547 | * features for the netdev |
| 2576 | } else if (!vlan_tx_tag_present(skb)) { | 2548 | */ |
| 2577 | return harmonize_features(skb, features); | 2549 | if (skb->encapsulation) |
| 2550 | features &= dev->hw_enc_features; | ||
| 2551 | |||
| 2552 | if (!vlan_tx_tag_present(skb)) { | ||
| 2553 | if (unlikely(protocol == htons(ETH_P_8021Q) || | ||
| 2554 | protocol == htons(ETH_P_8021AD))) { | ||
| 2555 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | ||
| 2556 | protocol = veh->h_vlan_encapsulated_proto; | ||
| 2557 | } else { | ||
| 2558 | goto finalize; | ||
| 2559 | } | ||
| 2578 | } | 2560 | } |
| 2579 | 2561 | ||
| 2580 | features = netdev_intersect_features(features, | 2562 | features = netdev_intersect_features(features, |
| @@ -2591,6 +2573,11 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
| 2591 | NETIF_F_HW_VLAN_CTAG_TX | | 2573 | NETIF_F_HW_VLAN_CTAG_TX | |
| 2592 | NETIF_F_HW_VLAN_STAG_TX); | 2574 | NETIF_F_HW_VLAN_STAG_TX); |
| 2593 | 2575 | ||
| 2576 | finalize: | ||
| 2577 | if (dev->netdev_ops->ndo_features_check) | ||
| 2578 | features &= dev->netdev_ops->ndo_features_check(skb, dev, | ||
| 2579 | features); | ||
| 2580 | |||
| 2594 | return harmonize_features(skb, features); | 2581 | return harmonize_features(skb, features); |
| 2595 | } | 2582 | } |
| 2596 | EXPORT_SYMBOL(netif_skb_features); | 2583 | EXPORT_SYMBOL(netif_skb_features); |
| @@ -2661,19 +2648,12 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device | |||
| 2661 | if (unlikely(!skb)) | 2648 | if (unlikely(!skb)) |
| 2662 | goto out_null; | 2649 | goto out_null; |
| 2663 | 2650 | ||
| 2664 | /* If encapsulation offload request, verify we are testing | ||
| 2665 | * hardware encapsulation features instead of standard | ||
| 2666 | * features for the netdev | ||
| 2667 | */ | ||
| 2668 | if (skb->encapsulation) | ||
| 2669 | features &= dev->hw_enc_features; | ||
| 2670 | |||
| 2671 | if (netif_needs_gso(dev, skb, features)) { | 2651 | if (netif_needs_gso(dev, skb, features)) { |
| 2672 | struct sk_buff *segs; | 2652 | struct sk_buff *segs; |
| 2673 | 2653 | ||
| 2674 | segs = skb_gso_segment(skb, features); | 2654 | segs = skb_gso_segment(skb, features); |
| 2675 | if (IS_ERR(segs)) { | 2655 | if (IS_ERR(segs)) { |
| 2676 | segs = NULL; | 2656 | goto out_kfree_skb; |
| 2677 | } else if (segs) { | 2657 | } else if (segs) { |
| 2678 | consume_skb(skb); | 2658 | consume_skb(skb); |
| 2679 | skb = segs; | 2659 | skb = segs; |
| @@ -4557,6 +4537,68 @@ void netif_napi_del(struct napi_struct *napi) | |||
| 4557 | } | 4537 | } |
| 4558 | EXPORT_SYMBOL(netif_napi_del); | 4538 | EXPORT_SYMBOL(netif_napi_del); |
| 4559 | 4539 | ||
| 4540 | static int napi_poll(struct napi_struct *n, struct list_head *repoll) | ||
| 4541 | { | ||
| 4542 | void *have; | ||
| 4543 | int work, weight; | ||
| 4544 | |||
| 4545 | list_del_init(&n->poll_list); | ||
| 4546 | |||
| 4547 | have = netpoll_poll_lock(n); | ||
| 4548 | |||
| 4549 | weight = n->weight; | ||
| 4550 | |||
| 4551 | /* This NAPI_STATE_SCHED test is for avoiding a race | ||
| 4552 | * with netpoll's poll_napi(). Only the entity which | ||
| 4553 | * obtains the lock and sees NAPI_STATE_SCHED set will | ||
| 4554 | * actually make the ->poll() call. Therefore we avoid | ||
| 4555 | * accidentally calling ->poll() when NAPI is not scheduled. | ||
| 4556 | */ | ||
| 4557 | work = 0; | ||
| 4558 | if (test_bit(NAPI_STATE_SCHED, &n->state)) { | ||
| 4559 | work = n->poll(n, weight); | ||
| 4560 | trace_napi_poll(n); | ||
| 4561 | } | ||
| 4562 | |||
| 4563 | WARN_ON_ONCE(work > weight); | ||
| 4564 | |||
| 4565 | if (likely(work < weight)) | ||
| 4566 | goto out_unlock; | ||
| 4567 | |||
| 4568 | /* Drivers must not modify the NAPI state if they | ||
| 4569 | * consume the entire weight. In such cases this code | ||
| 4570 | * still "owns" the NAPI instance and therefore can | ||
| 4571 | * move the instance around on the list at-will. | ||
| 4572 | */ | ||
| 4573 | if (unlikely(napi_disable_pending(n))) { | ||
| 4574 | napi_complete(n); | ||
| 4575 | goto out_unlock; | ||
| 4576 | } | ||
| 4577 | |||
| 4578 | if (n->gro_list) { | ||
| 4579 | /* flush too old packets | ||
| 4580 | * If HZ < 1000, flush all packets. | ||
| 4581 | */ | ||
| 4582 | napi_gro_flush(n, HZ >= 1000); | ||
| 4583 | } | ||
| 4584 | |||
| 4585 | /* Some drivers may have called napi_schedule | ||
| 4586 | * prior to exhausting their budget. | ||
| 4587 | */ | ||
| 4588 | if (unlikely(!list_empty(&n->poll_list))) { | ||
| 4589 | pr_warn_once("%s: Budget exhausted after napi rescheduled\n", | ||
| 4590 | n->dev ? n->dev->name : "backlog"); | ||
| 4591 | goto out_unlock; | ||
| 4592 | } | ||
| 4593 | |||
| 4594 | list_add_tail(&n->poll_list, repoll); | ||
| 4595 | |||
| 4596 | out_unlock: | ||
| 4597 | netpoll_poll_unlock(have); | ||
| 4598 | |||
| 4599 | return work; | ||
| 4600 | } | ||
| 4601 | |||
| 4560 | static void net_rx_action(struct softirq_action *h) | 4602 | static void net_rx_action(struct softirq_action *h) |
| 4561 | { | 4603 | { |
| 4562 | struct softnet_data *sd = this_cpu_ptr(&softnet_data); | 4604 | struct softnet_data *sd = this_cpu_ptr(&softnet_data); |
| @@ -4564,74 +4606,34 @@ static void net_rx_action(struct softirq_action *h) | |||
| 4564 | int budget = netdev_budget; | 4606 | int budget = netdev_budget; |
| 4565 | LIST_HEAD(list); | 4607 | LIST_HEAD(list); |
| 4566 | LIST_HEAD(repoll); | 4608 | LIST_HEAD(repoll); |
| 4567 | void *have; | ||
| 4568 | 4609 | ||
| 4569 | local_irq_disable(); | 4610 | local_irq_disable(); |
| 4570 | list_splice_init(&sd->poll_list, &list); | 4611 | list_splice_init(&sd->poll_list, &list); |
| 4571 | local_irq_enable(); | 4612 | local_irq_enable(); |
| 4572 | 4613 | ||
| 4573 | while (!list_empty(&list)) { | 4614 | for (;;) { |
| 4574 | struct napi_struct *n; | 4615 | struct napi_struct *n; |
| 4575 | int work, weight; | ||
| 4576 | |||
| 4577 | /* If softirq window is exhausted then punt. | ||
| 4578 | * Allow this to run for 2 jiffies since which will allow | ||
| 4579 | * an average latency of 1.5/HZ. | ||
| 4580 | */ | ||
| 4581 | if (unlikely(budget <= 0 || time_after_eq(jiffies, time_limit))) | ||
| 4582 | goto softnet_break; | ||
| 4583 | |||
| 4584 | |||
| 4585 | n = list_first_entry(&list, struct napi_struct, poll_list); | ||
| 4586 | list_del_init(&n->poll_list); | ||
| 4587 | |||
| 4588 | have = netpoll_poll_lock(n); | ||
| 4589 | 4616 | ||
| 4590 | weight = n->weight; | 4617 | if (list_empty(&list)) { |
| 4591 | 4618 | if (!sd_has_rps_ipi_waiting(sd) && list_empty(&repoll)) | |
| 4592 | /* This NAPI_STATE_SCHED test is for avoiding a race | 4619 | return; |
| 4593 | * with netpoll's poll_napi(). Only the entity which | 4620 | break; |
| 4594 | * obtains the lock and sees NAPI_STATE_SCHED set will | ||
| 4595 | * actually make the ->poll() call. Therefore we avoid | ||
| 4596 | * accidentally calling ->poll() when NAPI is not scheduled. | ||
| 4597 | */ | ||
| 4598 | work = 0; | ||
| 4599 | if (test_bit(NAPI_STATE_SCHED, &n->state)) { | ||
| 4600 | work = n->poll(n, weight); | ||
| 4601 | trace_napi_poll(n); | ||
| 4602 | } | 4621 | } |
| 4603 | 4622 | ||
| 4604 | WARN_ON_ONCE(work > weight); | 4623 | n = list_first_entry(&list, struct napi_struct, poll_list); |
| 4605 | 4624 | budget -= napi_poll(n, &repoll); | |
| 4606 | budget -= work; | ||
| 4607 | 4625 | ||
| 4608 | /* Drivers must not modify the NAPI state if they | 4626 | /* If softirq window is exhausted then punt. |
| 4609 | * consume the entire weight. In such cases this code | 4627 | * Allow this to run for 2 jiffies since which will allow |
| 4610 | * still "owns" the NAPI instance and therefore can | 4628 | * an average latency of 1.5/HZ. |
| 4611 | * move the instance around on the list at-will. | ||
| 4612 | */ | 4629 | */ |
| 4613 | if (unlikely(work == weight)) { | 4630 | if (unlikely(budget <= 0 || |
| 4614 | if (unlikely(napi_disable_pending(n))) { | 4631 | time_after_eq(jiffies, time_limit))) { |
| 4615 | napi_complete(n); | 4632 | sd->time_squeeze++; |
| 4616 | } else { | 4633 | break; |
| 4617 | if (n->gro_list) { | ||
| 4618 | /* flush too old packets | ||
| 4619 | * If HZ < 1000, flush all packets. | ||
| 4620 | */ | ||
| 4621 | napi_gro_flush(n, HZ >= 1000); | ||
| 4622 | } | ||
| 4623 | list_add_tail(&n->poll_list, &repoll); | ||
| 4624 | } | ||
| 4625 | } | 4634 | } |
| 4626 | |||
| 4627 | netpoll_poll_unlock(have); | ||
| 4628 | } | 4635 | } |
| 4629 | 4636 | ||
| 4630 | if (!sd_has_rps_ipi_waiting(sd) && | ||
| 4631 | list_empty(&list) && | ||
| 4632 | list_empty(&repoll)) | ||
| 4633 | return; | ||
| 4634 | out: | ||
| 4635 | local_irq_disable(); | 4637 | local_irq_disable(); |
| 4636 | 4638 | ||
| 4637 | list_splice_tail_init(&sd->poll_list, &list); | 4639 | list_splice_tail_init(&sd->poll_list, &list); |
| @@ -4641,12 +4643,6 @@ out: | |||
| 4641 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | 4643 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); |
| 4642 | 4644 | ||
| 4643 | net_rps_action_and_irq_enable(sd); | 4645 | net_rps_action_and_irq_enable(sd); |
| 4644 | |||
| 4645 | return; | ||
| 4646 | |||
| 4647 | softnet_break: | ||
| 4648 | sd->time_squeeze++; | ||
| 4649 | goto out; | ||
| 4650 | } | 4646 | } |
| 4651 | 4647 | ||
| 4652 | struct netdev_adjacent { | 4648 | struct netdev_adjacent { |
| @@ -5298,7 +5294,7 @@ void netdev_upper_dev_unlink(struct net_device *dev, | |||
| 5298 | } | 5294 | } |
| 5299 | EXPORT_SYMBOL(netdev_upper_dev_unlink); | 5295 | EXPORT_SYMBOL(netdev_upper_dev_unlink); |
| 5300 | 5296 | ||
| 5301 | void netdev_adjacent_add_links(struct net_device *dev) | 5297 | static void netdev_adjacent_add_links(struct net_device *dev) |
| 5302 | { | 5298 | { |
| 5303 | struct netdev_adjacent *iter; | 5299 | struct netdev_adjacent *iter; |
| 5304 | 5300 | ||
| @@ -5323,7 +5319,7 @@ void netdev_adjacent_add_links(struct net_device *dev) | |||
| 5323 | } | 5319 | } |
| 5324 | } | 5320 | } |
| 5325 | 5321 | ||
| 5326 | void netdev_adjacent_del_links(struct net_device *dev) | 5322 | static void netdev_adjacent_del_links(struct net_device *dev) |
| 5327 | { | 5323 | { |
| 5328 | struct netdev_adjacent *iter; | 5324 | struct netdev_adjacent *iter; |
| 5329 | 5325 | ||
| @@ -6631,7 +6627,7 @@ struct netdev_queue *dev_ingress_queue_create(struct net_device *dev) | |||
| 6631 | if (!queue) | 6627 | if (!queue) |
| 6632 | return NULL; | 6628 | return NULL; |
| 6633 | netdev_init_one_queue(dev, queue, NULL); | 6629 | netdev_init_one_queue(dev, queue, NULL); |
| 6634 | queue->qdisc = &noop_qdisc; | 6630 | RCU_INIT_POINTER(queue->qdisc, &noop_qdisc); |
| 6635 | queue->qdisc_sleeping = &noop_qdisc; | 6631 | queue->qdisc_sleeping = &noop_qdisc; |
| 6636 | rcu_assign_pointer(dev->ingress_queue, queue); | 6632 | rcu_assign_pointer(dev->ingress_queue, queue); |
| 6637 | #endif | 6633 | #endif |
| @@ -7047,10 +7043,20 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
| 7047 | oldsd->output_queue = NULL; | 7043 | oldsd->output_queue = NULL; |
| 7048 | oldsd->output_queue_tailp = &oldsd->output_queue; | 7044 | oldsd->output_queue_tailp = &oldsd->output_queue; |
| 7049 | } | 7045 | } |
| 7050 | /* Append NAPI poll list from offline CPU. */ | 7046 | /* Append NAPI poll list from offline CPU, with one exception : |
| 7051 | if (!list_empty(&oldsd->poll_list)) { | 7047 | * process_backlog() must be called by cpu owning percpu backlog. |
| 7052 | list_splice_init(&oldsd->poll_list, &sd->poll_list); | 7048 | * We properly handle process_queue & input_pkt_queue later. |
| 7053 | raise_softirq_irqoff(NET_RX_SOFTIRQ); | 7049 | */ |
| 7050 | while (!list_empty(&oldsd->poll_list)) { | ||
| 7051 | struct napi_struct *napi = list_first_entry(&oldsd->poll_list, | ||
| 7052 | struct napi_struct, | ||
| 7053 | poll_list); | ||
| 7054 | |||
| 7055 | list_del_init(&napi->poll_list); | ||
| 7056 | if (napi->poll == process_backlog) | ||
| 7057 | napi->state = 0; | ||
| 7058 | else | ||
| 7059 | ____napi_schedule(sd, napi); | ||
| 7054 | } | 7060 | } |
| 7055 | 7061 | ||
| 7056 | raise_softirq_irqoff(NET_TX_SOFTIRQ); | 7062 | raise_softirq_irqoff(NET_TX_SOFTIRQ); |
| @@ -7061,7 +7067,7 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
| 7061 | netif_rx_internal(skb); | 7067 | netif_rx_internal(skb); |
| 7062 | input_queue_head_incr(oldsd); | 7068 | input_queue_head_incr(oldsd); |
| 7063 | } | 7069 | } |
| 7064 | while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { | 7070 | while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) { |
| 7065 | netif_rx_internal(skb); | 7071 | netif_rx_internal(skb); |
| 7066 | input_queue_head_incr(oldsd); | 7072 | input_queue_head_incr(oldsd); |
| 7067 | } | 7073 | } |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 8e38f17288d3..8d614c93f86a 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -2043,6 +2043,12 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 2043 | case NDTPA_BASE_REACHABLE_TIME: | 2043 | case NDTPA_BASE_REACHABLE_TIME: |
| 2044 | NEIGH_VAR_SET(p, BASE_REACHABLE_TIME, | 2044 | NEIGH_VAR_SET(p, BASE_REACHABLE_TIME, |
| 2045 | nla_get_msecs(tbp[i])); | 2045 | nla_get_msecs(tbp[i])); |
| 2046 | /* update reachable_time as well, otherwise, the change will | ||
| 2047 | * only be effective after the next time neigh_periodic_work | ||
| 2048 | * decides to recompute it (can be multiple minutes) | ||
| 2049 | */ | ||
| 2050 | p->reachable_time = | ||
| 2051 | neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME)); | ||
| 2046 | break; | 2052 | break; |
| 2047 | case NDTPA_GC_STALETIME: | 2053 | case NDTPA_GC_STALETIME: |
| 2048 | NEIGH_VAR_SET(p, GC_STALETIME, | 2054 | NEIGH_VAR_SET(p, GC_STALETIME, |
| @@ -2921,6 +2927,31 @@ static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write, | |||
| 2921 | return ret; | 2927 | return ret; |
| 2922 | } | 2928 | } |
| 2923 | 2929 | ||
| 2930 | static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write, | ||
| 2931 | void __user *buffer, | ||
| 2932 | size_t *lenp, loff_t *ppos) | ||
| 2933 | { | ||
| 2934 | struct neigh_parms *p = ctl->extra2; | ||
| 2935 | int ret; | ||
| 2936 | |||
| 2937 | if (strcmp(ctl->procname, "base_reachable_time") == 0) | ||
| 2938 | ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos); | ||
| 2939 | else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0) | ||
| 2940 | ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos); | ||
| 2941 | else | ||
| 2942 | ret = -1; | ||
| 2943 | |||
| 2944 | if (write && ret == 0) { | ||
| 2945 | /* update reachable_time as well, otherwise, the change will | ||
| 2946 | * only be effective after the next time neigh_periodic_work | ||
| 2947 | * decides to recompute it | ||
| 2948 | */ | ||
| 2949 | p->reachable_time = | ||
| 2950 | neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME)); | ||
| 2951 | } | ||
| 2952 | return ret; | ||
| 2953 | } | ||
| 2954 | |||
| 2924 | #define NEIGH_PARMS_DATA_OFFSET(index) \ | 2955 | #define NEIGH_PARMS_DATA_OFFSET(index) \ |
| 2925 | (&((struct neigh_parms *) 0)->data[index]) | 2956 | (&((struct neigh_parms *) 0)->data[index]) |
| 2926 | 2957 | ||
| @@ -3047,6 +3078,19 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | |||
| 3047 | t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler; | 3078 | t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler; |
| 3048 | /* ReachableTime (in milliseconds) */ | 3079 | /* ReachableTime (in milliseconds) */ |
| 3049 | t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler; | 3080 | t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler; |
| 3081 | } else { | ||
| 3082 | /* Those handlers will update p->reachable_time after | ||
| 3083 | * base_reachable_time(_ms) is set to ensure the new timer starts being | ||
| 3084 | * applied after the next neighbour update instead of waiting for | ||
| 3085 | * neigh_periodic_work to update its value (can be multiple minutes) | ||
| 3086 | * So any handler that replaces them should do this as well | ||
| 3087 | */ | ||
| 3088 | /* ReachableTime */ | ||
| 3089 | t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = | ||
| 3090 | neigh_proc_base_reachable_time; | ||
| 3091 | /* ReachableTime (in milliseconds) */ | ||
| 3092 | t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = | ||
| 3093 | neigh_proc_base_reachable_time; | ||
| 3050 | } | 3094 | } |
| 3051 | 3095 | ||
| 3052 | /* Don't export sysctls to unprivileged users */ | 3096 | /* Don't export sysctls to unprivileged users */ |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9cf6fe9ddc0c..446cbaf81185 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -2895,12 +2895,16 @@ static int rtnl_bridge_notify(struct net_device *dev, u16 flags) | |||
| 2895 | goto errout; | 2895 | goto errout; |
| 2896 | } | 2896 | } |
| 2897 | 2897 | ||
| 2898 | if (!skb->len) | ||
| 2899 | goto errout; | ||
| 2900 | |||
| 2898 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); | 2901 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); |
| 2899 | return 0; | 2902 | return 0; |
| 2900 | errout: | 2903 | errout: |
| 2901 | WARN_ON(err == -EMSGSIZE); | 2904 | WARN_ON(err == -EMSGSIZE); |
| 2902 | kfree_skb(skb); | 2905 | kfree_skb(skb); |
| 2903 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); | 2906 | if (err) |
| 2907 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); | ||
| 2904 | return err; | 2908 | return err; |
| 2905 | } | 2909 | } |
| 2906 | 2910 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ae13ef6b3ea7..395c15b82087 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -4148,6 +4148,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) | |||
| 4148 | skb->ignore_df = 0; | 4148 | skb->ignore_df = 0; |
| 4149 | skb_dst_drop(skb); | 4149 | skb_dst_drop(skb); |
| 4150 | skb->mark = 0; | 4150 | skb->mark = 0; |
| 4151 | skb_init_secmark(skb); | ||
| 4151 | secpath_reset(skb); | 4152 | secpath_reset(skb); |
| 4152 | nf_reset(skb); | 4153 | nf_reset(skb); |
| 4153 | nf_reset_trace(skb); | 4154 | nf_reset_trace(skb); |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 515569ffde8a..589aafd01fc5 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
| @@ -46,6 +46,7 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds) | |||
| 46 | snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d:%.2x", | 46 | snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d:%.2x", |
| 47 | ds->index, ds->pd->sw_addr); | 47 | ds->index, ds->pd->sw_addr); |
| 48 | ds->slave_mii_bus->parent = ds->master_dev; | 48 | ds->slave_mii_bus->parent = ds->master_dev; |
| 49 | ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask; | ||
| 49 | } | 50 | } |
| 50 | 51 | ||
| 51 | 52 | ||
diff --git a/net/ipv4/geneve.c b/net/ipv4/geneve.c index 95e47c97585e..394a200f93c1 100644 --- a/net/ipv4/geneve.c +++ b/net/ipv4/geneve.c | |||
| @@ -122,14 +122,18 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt, | |||
| 122 | int err; | 122 | int err; |
| 123 | 123 | ||
| 124 | skb = udp_tunnel_handle_offloads(skb, !gs->sock->sk->sk_no_check_tx); | 124 | skb = udp_tunnel_handle_offloads(skb, !gs->sock->sk->sk_no_check_tx); |
| 125 | if (IS_ERR(skb)) | ||
| 126 | return PTR_ERR(skb); | ||
| 125 | 127 | ||
| 126 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len | 128 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len |
| 127 | + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr) | 129 | + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr) |
| 128 | + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); | 130 | + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); |
| 129 | 131 | ||
| 130 | err = skb_cow_head(skb, min_headroom); | 132 | err = skb_cow_head(skb, min_headroom); |
| 131 | if (unlikely(err)) | 133 | if (unlikely(err)) { |
| 134 | kfree_skb(skb); | ||
| 132 | return err; | 135 | return err; |
| 136 | } | ||
| 133 | 137 | ||
| 134 | skb = vlan_hwaccel_push_inside(skb); | 138 | skb = vlan_hwaccel_push_inside(skb); |
| 135 | if (unlikely(!skb)) | 139 | if (unlikely(!skb)) |
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 3a83ce5efa80..787b3c294ce6 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
| @@ -129,7 +129,8 @@ int ip_forward(struct sk_buff *skb) | |||
| 129 | * We now generate an ICMP HOST REDIRECT giving the route | 129 | * We now generate an ICMP HOST REDIRECT giving the route |
| 130 | * we calculated. | 130 | * we calculated. |
| 131 | */ | 131 | */ |
| 132 | if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) | 132 | if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr && |
| 133 | !skb_sec_path(skb)) | ||
| 133 | ip_rt_send_redirect(skb); | 134 | ip_rt_send_redirect(skb); |
| 134 | 135 | ||
| 135 | skb->priority = rt_tos2priority(iph->tos); | 136 | skb->priority = rt_tos2priority(iph->tos); |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index b50861b22b6b..c373c0708d97 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -1506,23 +1506,8 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, | |||
| 1506 | /* | 1506 | /* |
| 1507 | * Generic function to send a packet as reply to another packet. | 1507 | * Generic function to send a packet as reply to another packet. |
| 1508 | * Used to send some TCP resets/acks so far. | 1508 | * Used to send some TCP resets/acks so far. |
| 1509 | * | ||
| 1510 | * Use a fake percpu inet socket to avoid false sharing and contention. | ||
| 1511 | */ | 1509 | */ |
| 1512 | static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = { | 1510 | void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, |
| 1513 | .sk = { | ||
| 1514 | .__sk_common = { | ||
| 1515 | .skc_refcnt = ATOMIC_INIT(1), | ||
| 1516 | }, | ||
| 1517 | .sk_wmem_alloc = ATOMIC_INIT(1), | ||
| 1518 | .sk_allocation = GFP_ATOMIC, | ||
| 1519 | .sk_flags = (1UL << SOCK_USE_WRITE_QUEUE), | ||
| 1520 | }, | ||
| 1521 | .pmtudisc = IP_PMTUDISC_WANT, | ||
| 1522 | .uc_ttl = -1, | ||
| 1523 | }; | ||
| 1524 | |||
| 1525 | void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, | ||
| 1526 | const struct ip_options *sopt, | 1511 | const struct ip_options *sopt, |
| 1527 | __be32 daddr, __be32 saddr, | 1512 | __be32 daddr, __be32 saddr, |
| 1528 | const struct ip_reply_arg *arg, | 1513 | const struct ip_reply_arg *arg, |
| @@ -1532,9 +1517,8 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, | |||
| 1532 | struct ipcm_cookie ipc; | 1517 | struct ipcm_cookie ipc; |
| 1533 | struct flowi4 fl4; | 1518 | struct flowi4 fl4; |
| 1534 | struct rtable *rt = skb_rtable(skb); | 1519 | struct rtable *rt = skb_rtable(skb); |
| 1520 | struct net *net = sock_net(sk); | ||
| 1535 | struct sk_buff *nskb; | 1521 | struct sk_buff *nskb; |
| 1536 | struct sock *sk; | ||
| 1537 | struct inet_sock *inet; | ||
| 1538 | int err; | 1522 | int err; |
| 1539 | 1523 | ||
| 1540 | if (__ip_options_echo(&replyopts.opt.opt, skb, sopt)) | 1524 | if (__ip_options_echo(&replyopts.opt.opt, skb, sopt)) |
| @@ -1565,15 +1549,11 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, | |||
| 1565 | if (IS_ERR(rt)) | 1549 | if (IS_ERR(rt)) |
| 1566 | return; | 1550 | return; |
| 1567 | 1551 | ||
| 1568 | inet = &get_cpu_var(unicast_sock); | 1552 | inet_sk(sk)->tos = arg->tos; |
| 1569 | 1553 | ||
| 1570 | inet->tos = arg->tos; | ||
| 1571 | sk = &inet->sk; | ||
| 1572 | sk->sk_priority = skb->priority; | 1554 | sk->sk_priority = skb->priority; |
| 1573 | sk->sk_protocol = ip_hdr(skb)->protocol; | 1555 | sk->sk_protocol = ip_hdr(skb)->protocol; |
| 1574 | sk->sk_bound_dev_if = arg->bound_dev_if; | 1556 | sk->sk_bound_dev_if = arg->bound_dev_if; |
| 1575 | sock_net_set(sk, net); | ||
| 1576 | __skb_queue_head_init(&sk->sk_write_queue); | ||
| 1577 | sk->sk_sndbuf = sysctl_wmem_default; | 1557 | sk->sk_sndbuf = sysctl_wmem_default; |
| 1578 | err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, | 1558 | err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, |
| 1579 | len, 0, &ipc, &rt, MSG_DONTWAIT); | 1559 | len, 0, &ipc, &rt, MSG_DONTWAIT); |
| @@ -1589,13 +1569,10 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, | |||
| 1589 | arg->csumoffset) = csum_fold(csum_add(nskb->csum, | 1569 | arg->csumoffset) = csum_fold(csum_add(nskb->csum, |
| 1590 | arg->csum)); | 1570 | arg->csum)); |
| 1591 | nskb->ip_summed = CHECKSUM_NONE; | 1571 | nskb->ip_summed = CHECKSUM_NONE; |
| 1592 | skb_orphan(nskb); | ||
| 1593 | skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); | 1572 | skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); |
| 1594 | ip_push_pending_frames(sk, &fl4); | 1573 | ip_push_pending_frames(sk, &fl4); |
| 1595 | } | 1574 | } |
| 1596 | out: | 1575 | out: |
| 1597 | put_cpu_var(unicast_sock); | ||
| 1598 | |||
| 1599 | ip_rt_put(rt); | 1576 | ip_rt_put(rt); |
| 1600 | } | 1577 | } |
| 1601 | 1578 | ||
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 8a89c738b7a3..6b85adb05003 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
| @@ -461,17 +461,13 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
| 461 | 461 | ||
| 462 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 462 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
| 463 | sin = &errhdr.offender; | 463 | sin = &errhdr.offender; |
| 464 | sin->sin_family = AF_UNSPEC; | 464 | memset(sin, 0, sizeof(*sin)); |
| 465 | 465 | ||
| 466 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || | 466 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || |
| 467 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { | 467 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { |
| 468 | struct inet_sock *inet = inet_sk(sk); | ||
| 469 | |||
| 470 | sin->sin_family = AF_INET; | 468 | sin->sin_family = AF_INET; |
| 471 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; | 469 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
| 472 | sin->sin_port = 0; | 470 | if (inet_sk(sk)->cmsg_flags) |
| 473 | memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
| 474 | if (inet->cmsg_flags) | ||
| 475 | ip_cmsg_recv(msg, skb); | 471 | ip_cmsg_recv(msg, skb); |
| 476 | } | 472 | } |
| 477 | 473 | ||
diff --git a/net/ipv4/netfilter/nft_redir_ipv4.c b/net/ipv4/netfilter/nft_redir_ipv4.c index ff2d23d8c87a..6ecfce63201a 100644 --- a/net/ipv4/netfilter/nft_redir_ipv4.c +++ b/net/ipv4/netfilter/nft_redir_ipv4.c | |||
| @@ -27,10 +27,10 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr, | |||
| 27 | 27 | ||
| 28 | memset(&mr, 0, sizeof(mr)); | 28 | memset(&mr, 0, sizeof(mr)); |
| 29 | if (priv->sreg_proto_min) { | 29 | if (priv->sreg_proto_min) { |
| 30 | mr.range[0].min.all = (__force __be16) | 30 | mr.range[0].min.all = |
| 31 | data[priv->sreg_proto_min].data[0]; | 31 | *(__be16 *)&data[priv->sreg_proto_min].data[0]; |
| 32 | mr.range[0].max.all = (__force __be16) | 32 | mr.range[0].max.all = |
| 33 | data[priv->sreg_proto_max].data[0]; | 33 | *(__be16 *)&data[priv->sreg_proto_max].data[0]; |
| 34 | mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 34 | mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
| 35 | } | 35 | } |
| 36 | 36 | ||
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index c0d82f78d364..2a3720fb5a5f 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
| @@ -966,8 +966,11 @@ bool ping_rcv(struct sk_buff *skb) | |||
| 966 | 966 | ||
| 967 | sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); | 967 | sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); |
| 968 | if (sk != NULL) { | 968 | if (sk != NULL) { |
| 969 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | ||
| 970 | |||
| 969 | pr_debug("rcv on socket %p\n", sk); | 971 | pr_debug("rcv on socket %p\n", sk); |
| 970 | ping_queue_rcv_skb(sk, skb_get(skb)); | 972 | if (skb2) |
| 973 | ping_queue_rcv_skb(sk, skb2); | ||
| 971 | sock_put(sk); | 974 | sock_put(sk); |
| 972 | return true; | 975 | return true; |
| 973 | } | 976 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6a2155b02602..52e1f2bf0ca2 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -966,6 +966,9 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) | |||
| 966 | if (dst->dev->mtu < mtu) | 966 | if (dst->dev->mtu < mtu) |
| 967 | return; | 967 | return; |
| 968 | 968 | ||
| 969 | if (rt->rt_pmtu && rt->rt_pmtu < mtu) | ||
| 970 | return; | ||
| 971 | |||
| 969 | if (mtu < ip_rt_min_pmtu) | 972 | if (mtu < ip_rt_min_pmtu) |
| 970 | mtu = ip_rt_min_pmtu; | 973 | mtu = ip_rt_min_pmtu; |
| 971 | 974 | ||
| @@ -1554,11 +1557,10 @@ static int __mkroute_input(struct sk_buff *skb, | |||
| 1554 | 1557 | ||
| 1555 | do_cache = res->fi && !itag; | 1558 | do_cache = res->fi && !itag; |
| 1556 | if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && | 1559 | if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && |
| 1560 | skb->protocol == htons(ETH_P_IP) && | ||
| 1557 | (IN_DEV_SHARED_MEDIA(out_dev) || | 1561 | (IN_DEV_SHARED_MEDIA(out_dev) || |
| 1558 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) { | 1562 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) |
| 1559 | flags |= RTCF_DOREDIRECT; | 1563 | IPCB(skb)->flags |= IPSKB_DOREDIRECT; |
| 1560 | do_cache = false; | ||
| 1561 | } | ||
| 1562 | 1564 | ||
| 1563 | if (skb->protocol != htons(ETH_P_IP)) { | 1565 | if (skb->protocol != htons(ETH_P_IP)) { |
| 1564 | /* Not IP (i.e. ARP). Do not create route, if it is | 1566 | /* Not IP (i.e. ARP). Do not create route, if it is |
| @@ -2303,6 +2305,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | |||
| 2303 | r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; | 2305 | r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; |
| 2304 | if (rt->rt_flags & RTCF_NOTIFY) | 2306 | if (rt->rt_flags & RTCF_NOTIFY) |
| 2305 | r->rtm_flags |= RTM_F_NOTIFY; | 2307 | r->rtm_flags |= RTM_F_NOTIFY; |
| 2308 | if (IPCB(skb)->flags & IPSKB_DOREDIRECT) | ||
| 2309 | r->rtm_flags |= RTCF_DOREDIRECT; | ||
| 2306 | 2310 | ||
| 2307 | if (nla_put_be32(skb, RTA_DST, dst)) | 2311 | if (nla_put_be32(skb, RTA_DST, dst)) |
| 2308 | goto nla_put_failure; | 2312 | goto nla_put_failure; |
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c index bb395d46a389..c037644eafb7 100644 --- a/net/ipv4/tcp_bic.c +++ b/net/ipv4/tcp_bic.c | |||
| @@ -150,7 +150,7 @@ static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 150 | tcp_slow_start(tp, acked); | 150 | tcp_slow_start(tp, acked); |
| 151 | else { | 151 | else { |
| 152 | bictcp_update(ca, tp->snd_cwnd); | 152 | bictcp_update(ca, tp->snd_cwnd); |
| 153 | tcp_cong_avoid_ai(tp, ca->cnt); | 153 | tcp_cong_avoid_ai(tp, ca->cnt, 1); |
| 154 | } | 154 | } |
| 155 | } | 155 | } |
| 156 | 156 | ||
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 27ead0dd16bc..8670e68e2ce6 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
| @@ -291,26 +291,32 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
| 291 | * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and | 291 | * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and |
| 292 | * returns the leftover acks to adjust cwnd in congestion avoidance mode. | 292 | * returns the leftover acks to adjust cwnd in congestion avoidance mode. |
| 293 | */ | 293 | */ |
| 294 | void tcp_slow_start(struct tcp_sock *tp, u32 acked) | 294 | u32 tcp_slow_start(struct tcp_sock *tp, u32 acked) |
| 295 | { | 295 | { |
| 296 | u32 cwnd = tp->snd_cwnd + acked; | 296 | u32 cwnd = tp->snd_cwnd + acked; |
| 297 | 297 | ||
| 298 | if (cwnd > tp->snd_ssthresh) | 298 | if (cwnd > tp->snd_ssthresh) |
| 299 | cwnd = tp->snd_ssthresh + 1; | 299 | cwnd = tp->snd_ssthresh + 1; |
| 300 | acked -= cwnd - tp->snd_cwnd; | ||
| 300 | tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); | 301 | tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); |
| 302 | |||
| 303 | return acked; | ||
| 301 | } | 304 | } |
| 302 | EXPORT_SYMBOL_GPL(tcp_slow_start); | 305 | EXPORT_SYMBOL_GPL(tcp_slow_start); |
| 303 | 306 | ||
| 304 | /* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w) */ | 307 | /* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w), |
| 305 | void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w) | 308 | * for every packet that was ACKed. |
| 309 | */ | ||
| 310 | void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w, u32 acked) | ||
| 306 | { | 311 | { |
| 312 | tp->snd_cwnd_cnt += acked; | ||
| 307 | if (tp->snd_cwnd_cnt >= w) { | 313 | if (tp->snd_cwnd_cnt >= w) { |
| 308 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 314 | u32 delta = tp->snd_cwnd_cnt / w; |
| 309 | tp->snd_cwnd++; | 315 | |
| 310 | tp->snd_cwnd_cnt = 0; | 316 | tp->snd_cwnd_cnt -= delta * w; |
| 311 | } else { | 317 | tp->snd_cwnd += delta; |
| 312 | tp->snd_cwnd_cnt++; | ||
| 313 | } | 318 | } |
| 319 | tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_cwnd_clamp); | ||
| 314 | } | 320 | } |
| 315 | EXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); | 321 | EXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); |
| 316 | 322 | ||
| @@ -329,11 +335,13 @@ void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 329 | return; | 335 | return; |
| 330 | 336 | ||
| 331 | /* In "safe" area, increase. */ | 337 | /* In "safe" area, increase. */ |
| 332 | if (tp->snd_cwnd <= tp->snd_ssthresh) | 338 | if (tp->snd_cwnd <= tp->snd_ssthresh) { |
| 333 | tcp_slow_start(tp, acked); | 339 | acked = tcp_slow_start(tp, acked); |
| 340 | if (!acked) | ||
| 341 | return; | ||
| 342 | } | ||
| 334 | /* In dangerous area, increase slowly. */ | 343 | /* In dangerous area, increase slowly. */ |
| 335 | else | 344 | tcp_cong_avoid_ai(tp, tp->snd_cwnd, acked); |
| 336 | tcp_cong_avoid_ai(tp, tp->snd_cwnd); | ||
| 337 | } | 345 | } |
| 338 | EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); | 346 | EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); |
| 339 | 347 | ||
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 6b6002416a73..4b276d1ed980 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c | |||
| @@ -93,9 +93,7 @@ struct bictcp { | |||
| 93 | u32 epoch_start; /* beginning of an epoch */ | 93 | u32 epoch_start; /* beginning of an epoch */ |
| 94 | u32 ack_cnt; /* number of acks */ | 94 | u32 ack_cnt; /* number of acks */ |
| 95 | u32 tcp_cwnd; /* estimated tcp cwnd */ | 95 | u32 tcp_cwnd; /* estimated tcp cwnd */ |
| 96 | #define ACK_RATIO_SHIFT 4 | 96 | u16 unused; |
| 97 | #define ACK_RATIO_LIMIT (32u << ACK_RATIO_SHIFT) | ||
| 98 | u16 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */ | ||
| 99 | u8 sample_cnt; /* number of samples to decide curr_rtt */ | 97 | u8 sample_cnt; /* number of samples to decide curr_rtt */ |
| 100 | u8 found; /* the exit point is found? */ | 98 | u8 found; /* the exit point is found? */ |
| 101 | u32 round_start; /* beginning of each round */ | 99 | u32 round_start; /* beginning of each round */ |
| @@ -114,7 +112,6 @@ static inline void bictcp_reset(struct bictcp *ca) | |||
| 114 | ca->bic_K = 0; | 112 | ca->bic_K = 0; |
| 115 | ca->delay_min = 0; | 113 | ca->delay_min = 0; |
| 116 | ca->epoch_start = 0; | 114 | ca->epoch_start = 0; |
| 117 | ca->delayed_ack = 2 << ACK_RATIO_SHIFT; | ||
| 118 | ca->ack_cnt = 0; | 115 | ca->ack_cnt = 0; |
| 119 | ca->tcp_cwnd = 0; | 116 | ca->tcp_cwnd = 0; |
| 120 | ca->found = 0; | 117 | ca->found = 0; |
| @@ -205,23 +202,30 @@ static u32 cubic_root(u64 a) | |||
| 205 | /* | 202 | /* |
| 206 | * Compute congestion window to use. | 203 | * Compute congestion window to use. |
| 207 | */ | 204 | */ |
| 208 | static inline void bictcp_update(struct bictcp *ca, u32 cwnd) | 205 | static inline void bictcp_update(struct bictcp *ca, u32 cwnd, u32 acked) |
| 209 | { | 206 | { |
| 210 | u32 delta, bic_target, max_cnt; | 207 | u32 delta, bic_target, max_cnt; |
| 211 | u64 offs, t; | 208 | u64 offs, t; |
| 212 | 209 | ||
| 213 | ca->ack_cnt++; /* count the number of ACKs */ | 210 | ca->ack_cnt += acked; /* count the number of ACKed packets */ |
| 214 | 211 | ||
| 215 | if (ca->last_cwnd == cwnd && | 212 | if (ca->last_cwnd == cwnd && |
| 216 | (s32)(tcp_time_stamp - ca->last_time) <= HZ / 32) | 213 | (s32)(tcp_time_stamp - ca->last_time) <= HZ / 32) |
| 217 | return; | 214 | return; |
| 218 | 215 | ||
| 216 | /* The CUBIC function can update ca->cnt at most once per jiffy. | ||
| 217 | * On all cwnd reduction events, ca->epoch_start is set to 0, | ||
| 218 | * which will force a recalculation of ca->cnt. | ||
| 219 | */ | ||
| 220 | if (ca->epoch_start && tcp_time_stamp == ca->last_time) | ||
| 221 | goto tcp_friendliness; | ||
| 222 | |||
| 219 | ca->last_cwnd = cwnd; | 223 | ca->last_cwnd = cwnd; |
| 220 | ca->last_time = tcp_time_stamp; | 224 | ca->last_time = tcp_time_stamp; |
| 221 | 225 | ||
| 222 | if (ca->epoch_start == 0) { | 226 | if (ca->epoch_start == 0) { |
| 223 | ca->epoch_start = tcp_time_stamp; /* record beginning */ | 227 | ca->epoch_start = tcp_time_stamp; /* record beginning */ |
| 224 | ca->ack_cnt = 1; /* start counting */ | 228 | ca->ack_cnt = acked; /* start counting */ |
| 225 | ca->tcp_cwnd = cwnd; /* syn with cubic */ | 229 | ca->tcp_cwnd = cwnd; /* syn with cubic */ |
| 226 | 230 | ||
| 227 | if (ca->last_max_cwnd <= cwnd) { | 231 | if (ca->last_max_cwnd <= cwnd) { |
| @@ -283,6 +287,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) | |||
| 283 | if (ca->last_max_cwnd == 0 && ca->cnt > 20) | 287 | if (ca->last_max_cwnd == 0 && ca->cnt > 20) |
| 284 | ca->cnt = 20; /* increase cwnd 5% per RTT */ | 288 | ca->cnt = 20; /* increase cwnd 5% per RTT */ |
| 285 | 289 | ||
| 290 | tcp_friendliness: | ||
| 286 | /* TCP Friendly */ | 291 | /* TCP Friendly */ |
| 287 | if (tcp_friendliness) { | 292 | if (tcp_friendliness) { |
| 288 | u32 scale = beta_scale; | 293 | u32 scale = beta_scale; |
| @@ -301,7 +306,6 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) | |||
| 301 | } | 306 | } |
| 302 | } | 307 | } |
| 303 | 308 | ||
| 304 | ca->cnt = (ca->cnt << ACK_RATIO_SHIFT) / ca->delayed_ack; | ||
| 305 | if (ca->cnt == 0) /* cannot be zero */ | 309 | if (ca->cnt == 0) /* cannot be zero */ |
| 306 | ca->cnt = 1; | 310 | ca->cnt = 1; |
| 307 | } | 311 | } |
| @@ -317,11 +321,12 @@ static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 317 | if (tp->snd_cwnd <= tp->snd_ssthresh) { | 321 | if (tp->snd_cwnd <= tp->snd_ssthresh) { |
| 318 | if (hystart && after(ack, ca->end_seq)) | 322 | if (hystart && after(ack, ca->end_seq)) |
| 319 | bictcp_hystart_reset(sk); | 323 | bictcp_hystart_reset(sk); |
| 320 | tcp_slow_start(tp, acked); | 324 | acked = tcp_slow_start(tp, acked); |
| 321 | } else { | 325 | if (!acked) |
| 322 | bictcp_update(ca, tp->snd_cwnd); | 326 | return; |
| 323 | tcp_cong_avoid_ai(tp, ca->cnt); | ||
| 324 | } | 327 | } |
| 328 | bictcp_update(ca, tp->snd_cwnd, acked); | ||
| 329 | tcp_cong_avoid_ai(tp, ca->cnt, acked); | ||
| 325 | } | 330 | } |
| 326 | 331 | ||
| 327 | static u32 bictcp_recalc_ssthresh(struct sock *sk) | 332 | static u32 bictcp_recalc_ssthresh(struct sock *sk) |
| @@ -411,20 +416,10 @@ static void hystart_update(struct sock *sk, u32 delay) | |||
| 411 | */ | 416 | */ |
| 412 | static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) | 417 | static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) |
| 413 | { | 418 | { |
| 414 | const struct inet_connection_sock *icsk = inet_csk(sk); | ||
| 415 | const struct tcp_sock *tp = tcp_sk(sk); | 419 | const struct tcp_sock *tp = tcp_sk(sk); |
| 416 | struct bictcp *ca = inet_csk_ca(sk); | 420 | struct bictcp *ca = inet_csk_ca(sk); |
| 417 | u32 delay; | 421 | u32 delay; |
| 418 | 422 | ||
| 419 | if (icsk->icsk_ca_state == TCP_CA_Open) { | ||
| 420 | u32 ratio = ca->delayed_ack; | ||
| 421 | |||
| 422 | ratio -= ca->delayed_ack >> ACK_RATIO_SHIFT; | ||
| 423 | ratio += cnt; | ||
| 424 | |||
| 425 | ca->delayed_ack = clamp(ratio, 1U, ACK_RATIO_LIMIT); | ||
| 426 | } | ||
| 427 | |||
| 428 | /* Some calls are for duplicates without timetamps */ | 423 | /* Some calls are for duplicates without timetamps */ |
| 429 | if (rtt_us < 0) | 424 | if (rtt_us < 0) |
| 430 | return; | 425 | return; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a3f72d7fc06c..d22f54482bab 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -683,7 +683,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
| 683 | arg.bound_dev_if = sk->sk_bound_dev_if; | 683 | arg.bound_dev_if = sk->sk_bound_dev_if; |
| 684 | 684 | ||
| 685 | arg.tos = ip_hdr(skb)->tos; | 685 | arg.tos = ip_hdr(skb)->tos; |
| 686 | ip_send_unicast_reply(net, skb, &TCP_SKB_CB(skb)->header.h4.opt, | 686 | ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), |
| 687 | skb, &TCP_SKB_CB(skb)->header.h4.opt, | ||
| 687 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, | 688 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, |
| 688 | &arg, arg.iov[0].iov_len); | 689 | &arg, arg.iov[0].iov_len); |
| 689 | 690 | ||
| @@ -767,7 +768,8 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
| 767 | if (oif) | 768 | if (oif) |
| 768 | arg.bound_dev_if = oif; | 769 | arg.bound_dev_if = oif; |
| 769 | arg.tos = tos; | 770 | arg.tos = tos; |
| 770 | ip_send_unicast_reply(net, skb, &TCP_SKB_CB(skb)->header.h4.opt, | 771 | ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), |
| 772 | skb, &TCP_SKB_CB(skb)->header.h4.opt, | ||
| 771 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, | 773 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, |
| 772 | &arg, arg.iov[0].iov_len); | 774 | &arg, arg.iov[0].iov_len); |
| 773 | 775 | ||
| @@ -2428,14 +2430,39 @@ struct proto tcp_prot = { | |||
| 2428 | }; | 2430 | }; |
| 2429 | EXPORT_SYMBOL(tcp_prot); | 2431 | EXPORT_SYMBOL(tcp_prot); |
| 2430 | 2432 | ||
| 2433 | static void __net_exit tcp_sk_exit(struct net *net) | ||
| 2434 | { | ||
| 2435 | int cpu; | ||
| 2436 | |||
| 2437 | for_each_possible_cpu(cpu) | ||
| 2438 | inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.tcp_sk, cpu)); | ||
| 2439 | free_percpu(net->ipv4.tcp_sk); | ||
| 2440 | } | ||
| 2441 | |||
| 2431 | static int __net_init tcp_sk_init(struct net *net) | 2442 | static int __net_init tcp_sk_init(struct net *net) |
| 2432 | { | 2443 | { |
| 2444 | int res, cpu; | ||
| 2445 | |||
| 2446 | net->ipv4.tcp_sk = alloc_percpu(struct sock *); | ||
| 2447 | if (!net->ipv4.tcp_sk) | ||
| 2448 | return -ENOMEM; | ||
| 2449 | |||
| 2450 | for_each_possible_cpu(cpu) { | ||
| 2451 | struct sock *sk; | ||
| 2452 | |||
| 2453 | res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW, | ||
| 2454 | IPPROTO_TCP, net); | ||
| 2455 | if (res) | ||
| 2456 | goto fail; | ||
| 2457 | *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk; | ||
| 2458 | } | ||
| 2433 | net->ipv4.sysctl_tcp_ecn = 2; | 2459 | net->ipv4.sysctl_tcp_ecn = 2; |
| 2434 | return 0; | 2460 | return 0; |
| 2435 | } | ||
| 2436 | 2461 | ||
| 2437 | static void __net_exit tcp_sk_exit(struct net *net) | 2462 | fail: |
| 2438 | { | 2463 | tcp_sk_exit(net); |
| 2464 | |||
| 2465 | return res; | ||
| 2439 | } | 2466 | } |
| 2440 | 2467 | ||
| 2441 | static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) | 2468 | static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7f18262e2326..65caf8b95e17 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -2019,7 +2019,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
| 2019 | if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now))) | 2019 | if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now))) |
| 2020 | break; | 2020 | break; |
| 2021 | 2021 | ||
| 2022 | if (tso_segs == 1) { | 2022 | if (tso_segs == 1 || !max_segs) { |
| 2023 | if (unlikely(!tcp_nagle_test(tp, skb, mss_now, | 2023 | if (unlikely(!tcp_nagle_test(tp, skb, mss_now, |
| 2024 | (tcp_skb_is_last(sk, skb) ? | 2024 | (tcp_skb_is_last(sk, skb) ? |
| 2025 | nonagle : TCP_NAGLE_PUSH)))) | 2025 | nonagle : TCP_NAGLE_PUSH)))) |
| @@ -2032,7 +2032,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
| 2032 | } | 2032 | } |
| 2033 | 2033 | ||
| 2034 | limit = mss_now; | 2034 | limit = mss_now; |
| 2035 | if (tso_segs > 1 && !tcp_urg_mode(tp)) | 2035 | if (tso_segs > 1 && max_segs && !tcp_urg_mode(tp)) |
| 2036 | limit = tcp_mss_split_point(sk, skb, mss_now, | 2036 | limit = tcp_mss_split_point(sk, skb, mss_now, |
| 2037 | min_t(unsigned int, | 2037 | min_t(unsigned int, |
| 2038 | cwnd_quota, | 2038 | cwnd_quota, |
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c index 6824afb65d93..333bcb2415ff 100644 --- a/net/ipv4/tcp_scalable.c +++ b/net/ipv4/tcp_scalable.c | |||
| @@ -25,7 +25,8 @@ static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 25 | if (tp->snd_cwnd <= tp->snd_ssthresh) | 25 | if (tp->snd_cwnd <= tp->snd_ssthresh) |
| 26 | tcp_slow_start(tp, acked); | 26 | tcp_slow_start(tp, acked); |
| 27 | else | 27 | else |
| 28 | tcp_cong_avoid_ai(tp, min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)); | 28 | tcp_cong_avoid_ai(tp, min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT), |
| 29 | 1); | ||
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | static u32 tcp_scalable_ssthresh(struct sock *sk) | 32 | static u32 tcp_scalable_ssthresh(struct sock *sk) |
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c index a4d2d2d88dca..112151eeee45 100644 --- a/net/ipv4/tcp_veno.c +++ b/net/ipv4/tcp_veno.c | |||
| @@ -159,7 +159,7 @@ static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 159 | /* In the "non-congestive state", increase cwnd | 159 | /* In the "non-congestive state", increase cwnd |
| 160 | * every rtt. | 160 | * every rtt. |
| 161 | */ | 161 | */ |
| 162 | tcp_cong_avoid_ai(tp, tp->snd_cwnd); | 162 | tcp_cong_avoid_ai(tp, tp->snd_cwnd, 1); |
| 163 | } else { | 163 | } else { |
| 164 | /* In the "congestive state", increase cwnd | 164 | /* In the "congestive state", increase cwnd |
| 165 | * every other rtt. | 165 | * every other rtt. |
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index cd7273218598..17d35662930d 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c | |||
| @@ -92,7 +92,7 @@ static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 92 | 92 | ||
| 93 | } else { | 93 | } else { |
| 94 | /* Reno */ | 94 | /* Reno */ |
| 95 | tcp_cong_avoid_ai(tp, tp->snd_cwnd); | 95 | tcp_cong_avoid_ai(tp, tp->snd_cwnd, 1); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | /* The key players are v_vegas.beg_snd_una and v_beg_snd_nxt. | 98 | /* The key players are v_vegas.beg_snd_una and v_beg_snd_nxt. |
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 7927db0a9279..4a000f1dd757 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
| @@ -99,11 +99,13 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin | |||
| 99 | s_slot = cb->args[0]; | 99 | s_slot = cb->args[0]; |
| 100 | num = s_num = cb->args[1]; | 100 | num = s_num = cb->args[1]; |
| 101 | 101 | ||
| 102 | for (slot = s_slot; slot <= table->mask; num = s_num = 0, slot++) { | 102 | for (slot = s_slot; slot <= table->mask; s_num = 0, slot++) { |
| 103 | struct sock *sk; | 103 | struct sock *sk; |
| 104 | struct hlist_nulls_node *node; | 104 | struct hlist_nulls_node *node; |
| 105 | struct udp_hslot *hslot = &table->hash[slot]; | 105 | struct udp_hslot *hslot = &table->hash[slot]; |
| 106 | 106 | ||
| 107 | num = 0; | ||
| 108 | |||
| 107 | if (hlist_nulls_empty(&hslot->head)) | 109 | if (hlist_nulls_empty(&hslot->head)) |
| 108 | continue; | 110 | continue; |
| 109 | 111 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 100c589a2a6c..49f5e73db122 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -393,11 +393,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
| 393 | 393 | ||
| 394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
| 395 | sin = &errhdr.offender; | 395 | sin = &errhdr.offender; |
| 396 | sin->sin6_family = AF_UNSPEC; | 396 | memset(sin, 0, sizeof(*sin)); |
| 397 | |||
| 397 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { | 398 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { |
| 398 | sin->sin6_family = AF_INET6; | 399 | sin->sin6_family = AF_INET6; |
| 399 | sin->sin6_flowinfo = 0; | ||
| 400 | sin->sin6_port = 0; | ||
| 401 | if (np->rxopt.all) { | 400 | if (np->rxopt.all) { |
| 402 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && | 401 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && |
| 403 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) | 402 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) |
| @@ -412,12 +411,9 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
| 412 | ipv6_iface_scope_id(&sin->sin6_addr, | 411 | ipv6_iface_scope_id(&sin->sin6_addr, |
| 413 | IP6CB(skb)->iif); | 412 | IP6CB(skb)->iif); |
| 414 | } else { | 413 | } else { |
| 415 | struct inet_sock *inet = inet_sk(sk); | ||
| 416 | |||
| 417 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, | 414 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
| 418 | &sin->sin6_addr); | 415 | &sin->sin6_addr); |
| 419 | sin->sin6_scope_id = 0; | 416 | if (inet_sk(sk)->cmsg_flags) |
| 420 | if (inet->cmsg_flags) | ||
| 421 | ip_cmsg_recv(msg, skb); | 417 | ip_cmsg_recv(msg, skb); |
| 422 | } | 418 | } |
| 423 | } | 419 | } |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index b2d1838897c9..f1c6d5e98322 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -659,6 +659,29 @@ static int fib6_commit_metrics(struct dst_entry *dst, | |||
| 659 | return 0; | 659 | return 0; |
| 660 | } | 660 | } |
| 661 | 661 | ||
| 662 | static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn, | ||
| 663 | struct net *net) | ||
| 664 | { | ||
| 665 | if (atomic_read(&rt->rt6i_ref) != 1) { | ||
| 666 | /* This route is used as dummy address holder in some split | ||
| 667 | * nodes. It is not leaked, but it still holds other resources, | ||
| 668 | * which must be released in time. So, scan ascendant nodes | ||
| 669 | * and replace dummy references to this route with references | ||
| 670 | * to still alive ones. | ||
| 671 | */ | ||
| 672 | while (fn) { | ||
| 673 | if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { | ||
| 674 | fn->leaf = fib6_find_prefix(net, fn); | ||
| 675 | atomic_inc(&fn->leaf->rt6i_ref); | ||
| 676 | rt6_release(rt); | ||
| 677 | } | ||
| 678 | fn = fn->parent; | ||
| 679 | } | ||
| 680 | /* No more references are possible at this point. */ | ||
| 681 | BUG_ON(atomic_read(&rt->rt6i_ref) != 1); | ||
| 682 | } | ||
| 683 | } | ||
| 684 | |||
| 662 | /* | 685 | /* |
| 663 | * Insert routing information in a node. | 686 | * Insert routing information in a node. |
| 664 | */ | 687 | */ |
| @@ -807,11 +830,12 @@ add: | |||
| 807 | rt->dst.rt6_next = iter->dst.rt6_next; | 830 | rt->dst.rt6_next = iter->dst.rt6_next; |
| 808 | atomic_inc(&rt->rt6i_ref); | 831 | atomic_inc(&rt->rt6i_ref); |
| 809 | inet6_rt_notify(RTM_NEWROUTE, rt, info); | 832 | inet6_rt_notify(RTM_NEWROUTE, rt, info); |
| 810 | rt6_release(iter); | ||
| 811 | if (!(fn->fn_flags & RTN_RTINFO)) { | 833 | if (!(fn->fn_flags & RTN_RTINFO)) { |
| 812 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; | 834 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; |
| 813 | fn->fn_flags |= RTN_RTINFO; | 835 | fn->fn_flags |= RTN_RTINFO; |
| 814 | } | 836 | } |
| 837 | fib6_purge_rt(iter, fn, info->nl_net); | ||
| 838 | rt6_release(iter); | ||
| 815 | } | 839 | } |
| 816 | 840 | ||
| 817 | return 0; | 841 | return 0; |
| @@ -1322,24 +1346,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
| 1322 | fn = fib6_repair_tree(net, fn); | 1346 | fn = fib6_repair_tree(net, fn); |
| 1323 | } | 1347 | } |
| 1324 | 1348 | ||
| 1325 | if (atomic_read(&rt->rt6i_ref) != 1) { | 1349 | fib6_purge_rt(rt, fn, net); |
| 1326 | /* This route is used as dummy address holder in some split | ||
| 1327 | * nodes. It is not leaked, but it still holds other resources, | ||
| 1328 | * which must be released in time. So, scan ascendant nodes | ||
| 1329 | * and replace dummy references to this route with references | ||
| 1330 | * to still alive ones. | ||
| 1331 | */ | ||
| 1332 | while (fn) { | ||
| 1333 | if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { | ||
| 1334 | fn->leaf = fib6_find_prefix(net, fn); | ||
| 1335 | atomic_inc(&fn->leaf->rt6i_ref); | ||
| 1336 | rt6_release(rt); | ||
| 1337 | } | ||
| 1338 | fn = fn->parent; | ||
| 1339 | } | ||
| 1340 | /* No more references are possible at this point. */ | ||
| 1341 | BUG_ON(atomic_read(&rt->rt6i_ref) != 1); | ||
| 1342 | } | ||
| 1343 | 1350 | ||
| 1344 | inet6_rt_notify(RTM_DELROUTE, rt, info); | 1351 | inet6_rt_notify(RTM_DELROUTE, rt, info); |
| 1345 | rt6_release(rt); | 1352 | rt6_release(rt); |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 13cda4c6313b..01ccc28a686f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -417,7 +417,7 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 417 | if (code == ICMPV6_HDR_FIELD) | 417 | if (code == ICMPV6_HDR_FIELD) |
| 418 | teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); | 418 | teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); |
| 419 | 419 | ||
| 420 | if (teli && teli == info - 2) { | 420 | if (teli && teli == be32_to_cpu(info) - 2) { |
| 421 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; | 421 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; |
| 422 | if (tel->encap_limit == 0) { | 422 | if (tel->encap_limit == 0) { |
| 423 | net_warn_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n", | 423 | net_warn_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n", |
| @@ -429,7 +429,7 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 429 | } | 429 | } |
| 430 | break; | 430 | break; |
| 431 | case ICMPV6_PKT_TOOBIG: | 431 | case ICMPV6_PKT_TOOBIG: |
| 432 | mtu = info - offset; | 432 | mtu = be32_to_cpu(info) - offset; |
| 433 | if (mtu < IPV6_MIN_MTU) | 433 | if (mtu < IPV6_MIN_MTU) |
| 434 | mtu = IPV6_MIN_MTU; | 434 | mtu = IPV6_MIN_MTU; |
| 435 | t->dev->mtu = mtu; | 435 | t->dev->mtu = mtu; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ce69a12ae48c..d28f2a2efb32 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -537,20 +537,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
| 537 | skb_copy_secmark(to, from); | 537 | skb_copy_secmark(to, from); |
| 538 | } | 538 | } |
| 539 | 539 | ||
| 540 | static void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | ||
| 541 | { | ||
| 542 | static u32 ip6_idents_hashrnd __read_mostly; | ||
| 543 | u32 hash, id; | ||
| 544 | |||
| 545 | net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); | ||
| 546 | |||
| 547 | hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd); | ||
| 548 | hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash); | ||
| 549 | |||
| 550 | id = ip_idents_reserve(hash, 1); | ||
| 551 | fhdr->identification = htonl(id); | ||
| 552 | } | ||
| 553 | |||
| 554 | int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | 540 | int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) |
| 555 | { | 541 | { |
| 556 | struct sk_buff *frag; | 542 | struct sk_buff *frag; |
diff --git a/net/ipv6/netfilter/nft_redir_ipv6.c b/net/ipv6/netfilter/nft_redir_ipv6.c index 2433a6bfb191..11820b6b3613 100644 --- a/net/ipv6/netfilter/nft_redir_ipv6.c +++ b/net/ipv6/netfilter/nft_redir_ipv6.c | |||
| @@ -27,10 +27,10 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr, | |||
| 27 | 27 | ||
| 28 | memset(&range, 0, sizeof(range)); | 28 | memset(&range, 0, sizeof(range)); |
| 29 | if (priv->sreg_proto_min) { | 29 | if (priv->sreg_proto_min) { |
| 30 | range.min_proto.all = (__force __be16) | 30 | range.min_proto.all = |
| 31 | data[priv->sreg_proto_min].data[0]; | 31 | *(__be16 *)&data[priv->sreg_proto_min].data[0]; |
| 32 | range.max_proto.all = (__force __be16) | 32 | range.max_proto.all = |
| 33 | data[priv->sreg_proto_max].data[0]; | 33 | *(__be16 *)&data[priv->sreg_proto_max].data[0]; |
| 34 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 34 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
| 35 | } | 35 | } |
| 36 | 36 | ||
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index 97f41a3e68d9..54520a0bd5e3 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c | |||
| @@ -9,6 +9,24 @@ | |||
| 9 | #include <net/addrconf.h> | 9 | #include <net/addrconf.h> |
| 10 | #include <net/secure_seq.h> | 10 | #include <net/secure_seq.h> |
| 11 | 11 | ||
| 12 | u32 __ipv6_select_ident(u32 hashrnd, struct in6_addr *dst, struct in6_addr *src) | ||
| 13 | { | ||
| 14 | u32 hash, id; | ||
| 15 | |||
| 16 | hash = __ipv6_addr_jhash(dst, hashrnd); | ||
| 17 | hash = __ipv6_addr_jhash(src, hash); | ||
| 18 | |||
| 19 | /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve, | ||
| 20 | * set the hight order instead thus minimizing possible future | ||
| 21 | * collisions. | ||
| 22 | */ | ||
| 23 | id = ip_idents_reserve(hash, 1); | ||
| 24 | if (unlikely(!id)) | ||
| 25 | id = 1 << 31; | ||
| 26 | |||
| 27 | return id; | ||
| 28 | } | ||
| 29 | |||
| 12 | /* This function exists only for tap drivers that must support broken | 30 | /* This function exists only for tap drivers that must support broken |
| 13 | * clients requesting UFO without specifying an IPv6 fragment ID. | 31 | * clients requesting UFO without specifying an IPv6 fragment ID. |
| 14 | * | 32 | * |
| @@ -22,7 +40,7 @@ void ipv6_proxy_select_ident(struct sk_buff *skb) | |||
| 22 | static u32 ip6_proxy_idents_hashrnd __read_mostly; | 40 | static u32 ip6_proxy_idents_hashrnd __read_mostly; |
| 23 | struct in6_addr buf[2]; | 41 | struct in6_addr buf[2]; |
| 24 | struct in6_addr *addrs; | 42 | struct in6_addr *addrs; |
| 25 | u32 hash, id; | 43 | u32 id; |
| 26 | 44 | ||
| 27 | addrs = skb_header_pointer(skb, | 45 | addrs = skb_header_pointer(skb, |
| 28 | skb_network_offset(skb) + | 46 | skb_network_offset(skb) + |
| @@ -34,14 +52,25 @@ void ipv6_proxy_select_ident(struct sk_buff *skb) | |||
| 34 | net_get_random_once(&ip6_proxy_idents_hashrnd, | 52 | net_get_random_once(&ip6_proxy_idents_hashrnd, |
| 35 | sizeof(ip6_proxy_idents_hashrnd)); | 53 | sizeof(ip6_proxy_idents_hashrnd)); |
| 36 | 54 | ||
| 37 | hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd); | 55 | id = __ipv6_select_ident(ip6_proxy_idents_hashrnd, |
| 38 | hash = __ipv6_addr_jhash(&addrs[0], hash); | 56 | &addrs[1], &addrs[0]); |
| 39 | 57 | skb_shinfo(skb)->ip6_frag_id = id; | |
| 40 | id = ip_idents_reserve(hash, 1); | ||
| 41 | skb_shinfo(skb)->ip6_frag_id = htonl(id); | ||
| 42 | } | 58 | } |
| 43 | EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); | 59 | EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); |
| 44 | 60 | ||
| 61 | void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | ||
| 62 | { | ||
| 63 | static u32 ip6_idents_hashrnd __read_mostly; | ||
| 64 | u32 id; | ||
| 65 | |||
| 66 | net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); | ||
| 67 | |||
| 68 | id = __ipv6_select_ident(ip6_idents_hashrnd, &rt->rt6i_dst.addr, | ||
| 69 | &rt->rt6i_src.addr); | ||
| 70 | fhdr->identification = htonl(id); | ||
| 71 | } | ||
| 72 | EXPORT_SYMBOL(ipv6_select_ident); | ||
| 73 | |||
| 45 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | 74 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) |
| 46 | { | 75 | { |
| 47 | u16 offset = sizeof(struct ipv6hdr); | 76 | u16 offset = sizeof(struct ipv6hdr); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c91083156edb..495965358d22 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -1160,12 +1160,9 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | |||
| 1160 | struct net *net = dev_net(dst->dev); | 1160 | struct net *net = dev_net(dst->dev); |
| 1161 | 1161 | ||
| 1162 | rt6->rt6i_flags |= RTF_MODIFIED; | 1162 | rt6->rt6i_flags |= RTF_MODIFIED; |
| 1163 | if (mtu < IPV6_MIN_MTU) { | 1163 | if (mtu < IPV6_MIN_MTU) |
| 1164 | u32 features = dst_metric(dst, RTAX_FEATURES); | ||
| 1165 | mtu = IPV6_MIN_MTU; | 1164 | mtu = IPV6_MIN_MTU; |
| 1166 | features |= RTAX_FEATURE_ALLFRAG; | 1165 | |
| 1167 | dst_metric_set(dst, RTAX_FEATURES, features); | ||
| 1168 | } | ||
| 1169 | dst_metric_set(dst, RTAX_MTU, mtu); | 1166 | dst_metric_set(dst, RTAX_MTU, mtu); |
| 1170 | rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1167 | rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); |
| 1171 | } | 1168 | } |
| @@ -1245,12 +1242,16 @@ restart: | |||
| 1245 | rt = net->ipv6.ip6_null_entry; | 1242 | rt = net->ipv6.ip6_null_entry; |
| 1246 | else if (rt->dst.error) { | 1243 | else if (rt->dst.error) { |
| 1247 | rt = net->ipv6.ip6_null_entry; | 1244 | rt = net->ipv6.ip6_null_entry; |
| 1248 | } else if (rt == net->ipv6.ip6_null_entry) { | 1245 | goto out; |
| 1246 | } | ||
| 1247 | |||
| 1248 | if (rt == net->ipv6.ip6_null_entry) { | ||
| 1249 | fn = fib6_backtrack(fn, &fl6->saddr); | 1249 | fn = fib6_backtrack(fn, &fl6->saddr); |
| 1250 | if (fn) | 1250 | if (fn) |
| 1251 | goto restart; | 1251 | goto restart; |
| 1252 | } | 1252 | } |
| 1253 | 1253 | ||
| 1254 | out: | ||
| 1254 | dst_hold(&rt->dst); | 1255 | dst_hold(&rt->dst); |
| 1255 | 1256 | ||
| 1256 | read_unlock_bh(&table->tb6_lock); | 1257 | read_unlock_bh(&table->tb6_lock); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 213546bd6d5d..cdbfe5af6187 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -1506,12 +1506,12 @@ static bool ipip6_netlink_encap_parms(struct nlattr *data[], | |||
| 1506 | 1506 | ||
| 1507 | if (data[IFLA_IPTUN_ENCAP_SPORT]) { | 1507 | if (data[IFLA_IPTUN_ENCAP_SPORT]) { |
| 1508 | ret = true; | 1508 | ret = true; |
| 1509 | ipencap->sport = nla_get_u16(data[IFLA_IPTUN_ENCAP_SPORT]); | 1509 | ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]); |
| 1510 | } | 1510 | } |
| 1511 | 1511 | ||
| 1512 | if (data[IFLA_IPTUN_ENCAP_DPORT]) { | 1512 | if (data[IFLA_IPTUN_ENCAP_DPORT]) { |
| 1513 | ret = true; | 1513 | ret = true; |
| 1514 | ipencap->dport = nla_get_u16(data[IFLA_IPTUN_ENCAP_DPORT]); | 1514 | ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]); |
| 1515 | } | 1515 | } |
| 1516 | 1516 | ||
| 1517 | return ret; | 1517 | return ret; |
| @@ -1707,9 +1707,9 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 1707 | 1707 | ||
| 1708 | if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, | 1708 | if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, |
| 1709 | tunnel->encap.type) || | 1709 | tunnel->encap.type) || |
| 1710 | nla_put_u16(skb, IFLA_IPTUN_ENCAP_SPORT, | 1710 | nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, |
| 1711 | tunnel->encap.sport) || | 1711 | tunnel->encap.sport) || |
| 1712 | nla_put_u16(skb, IFLA_IPTUN_ENCAP_DPORT, | 1712 | nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, |
| 1713 | tunnel->encap.dport) || | 1713 | tunnel->encap.dport) || |
| 1714 | nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS, | 1714 | nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS, |
| 1715 | tunnel->encap.flags)) | 1715 | tunnel->encap.flags)) |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5ff87805258e..9c0b54e87b47 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -1387,6 +1387,28 @@ ipv6_pktoptions: | |||
| 1387 | return 0; | 1387 | return 0; |
| 1388 | } | 1388 | } |
| 1389 | 1389 | ||
| 1390 | static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, | ||
| 1391 | const struct tcphdr *th) | ||
| 1392 | { | ||
| 1393 | /* This is tricky: we move IP6CB at its correct location into | ||
| 1394 | * TCP_SKB_CB(). It must be done after xfrm6_policy_check(), because | ||
| 1395 | * _decode_session6() uses IP6CB(). | ||
| 1396 | * barrier() makes sure compiler won't play aliasing games. | ||
| 1397 | */ | ||
| 1398 | memmove(&TCP_SKB_CB(skb)->header.h6, IP6CB(skb), | ||
| 1399 | sizeof(struct inet6_skb_parm)); | ||
| 1400 | barrier(); | ||
| 1401 | |||
| 1402 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | ||
| 1403 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | ||
| 1404 | skb->len - th->doff*4); | ||
| 1405 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | ||
| 1406 | TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); | ||
| 1407 | TCP_SKB_CB(skb)->tcp_tw_isn = 0; | ||
| 1408 | TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr); | ||
| 1409 | TCP_SKB_CB(skb)->sacked = 0; | ||
| 1410 | } | ||
| 1411 | |||
| 1390 | static int tcp_v6_rcv(struct sk_buff *skb) | 1412 | static int tcp_v6_rcv(struct sk_buff *skb) |
| 1391 | { | 1413 | { |
| 1392 | const struct tcphdr *th; | 1414 | const struct tcphdr *th; |
| @@ -1418,24 +1440,9 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
| 1418 | 1440 | ||
| 1419 | th = tcp_hdr(skb); | 1441 | th = tcp_hdr(skb); |
| 1420 | hdr = ipv6_hdr(skb); | 1442 | hdr = ipv6_hdr(skb); |
| 1421 | /* This is tricky : We move IPCB at its correct location into TCP_SKB_CB() | ||
| 1422 | * barrier() makes sure compiler wont play fool^Waliasing games. | ||
| 1423 | */ | ||
| 1424 | memmove(&TCP_SKB_CB(skb)->header.h6, IP6CB(skb), | ||
| 1425 | sizeof(struct inet6_skb_parm)); | ||
| 1426 | barrier(); | ||
| 1427 | |||
| 1428 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | ||
| 1429 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | ||
| 1430 | skb->len - th->doff*4); | ||
| 1431 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | ||
| 1432 | TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); | ||
| 1433 | TCP_SKB_CB(skb)->tcp_tw_isn = 0; | ||
| 1434 | TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr); | ||
| 1435 | TCP_SKB_CB(skb)->sacked = 0; | ||
| 1436 | 1443 | ||
| 1437 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest, | 1444 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest, |
| 1438 | tcp_v6_iif(skb)); | 1445 | inet6_iif(skb)); |
| 1439 | if (!sk) | 1446 | if (!sk) |
| 1440 | goto no_tcp_socket; | 1447 | goto no_tcp_socket; |
| 1441 | 1448 | ||
| @@ -1451,6 +1458,8 @@ process: | |||
| 1451 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 1458 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
| 1452 | goto discard_and_relse; | 1459 | goto discard_and_relse; |
| 1453 | 1460 | ||
| 1461 | tcp_v6_fill_cb(skb, hdr, th); | ||
| 1462 | |||
| 1454 | #ifdef CONFIG_TCP_MD5SIG | 1463 | #ifdef CONFIG_TCP_MD5SIG |
| 1455 | if (tcp_v6_inbound_md5_hash(sk, skb)) | 1464 | if (tcp_v6_inbound_md5_hash(sk, skb)) |
| 1456 | goto discard_and_relse; | 1465 | goto discard_and_relse; |
| @@ -1482,6 +1491,8 @@ no_tcp_socket: | |||
| 1482 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 1491 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
| 1483 | goto discard_it; | 1492 | goto discard_it; |
| 1484 | 1493 | ||
| 1494 | tcp_v6_fill_cb(skb, hdr, th); | ||
| 1495 | |||
| 1485 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { | 1496 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { |
| 1486 | csum_error: | 1497 | csum_error: |
| 1487 | TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); | 1498 | TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); |
| @@ -1505,6 +1516,8 @@ do_time_wait: | |||
| 1505 | goto discard_it; | 1516 | goto discard_it; |
| 1506 | } | 1517 | } |
| 1507 | 1518 | ||
| 1519 | tcp_v6_fill_cb(skb, hdr, th); | ||
| 1520 | |||
| 1508 | if (skb->len < (th->doff<<2)) { | 1521 | if (skb->len < (th->doff<<2)) { |
| 1509 | inet_twsk_put(inet_twsk(sk)); | 1522 | inet_twsk_put(inet_twsk(sk)); |
| 1510 | goto bad_packet; | 1523 | goto bad_packet; |
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index b6aa8ed18257..a56276996b72 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
| @@ -52,6 +52,10 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
| 52 | 52 | ||
| 53 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); | 53 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); |
| 54 | 54 | ||
| 55 | /* Set the IPv6 fragment id if not set yet */ | ||
| 56 | if (!skb_shinfo(skb)->ip6_frag_id) | ||
| 57 | ipv6_proxy_select_ident(skb); | ||
| 58 | |||
| 55 | segs = NULL; | 59 | segs = NULL; |
| 56 | goto out; | 60 | goto out; |
| 57 | } | 61 | } |
| @@ -108,7 +112,11 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
| 108 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); | 112 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); |
| 109 | fptr->nexthdr = nexthdr; | 113 | fptr->nexthdr = nexthdr; |
| 110 | fptr->reserved = 0; | 114 | fptr->reserved = 0; |
| 111 | fptr->identification = skb_shinfo(skb)->ip6_frag_id; | 115 | if (skb_shinfo(skb)->ip6_frag_id) |
| 116 | fptr->identification = skb_shinfo(skb)->ip6_frag_id; | ||
| 117 | else | ||
| 118 | ipv6_select_ident(fptr, | ||
| 119 | (struct rt6_info *)skb_dst(skb)); | ||
| 112 | 120 | ||
| 113 | /* Fragment the skb. ipv6 header and the remaining fields of the | 121 | /* Fragment the skb. ipv6 header and the remaining fields of the |
| 114 | * fragment header are updated in ipv6_gso_segment() | 122 | * fragment header are updated in ipv6_gso_segment() |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 5f983644373a..48bf5a06847b 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
| @@ -130,12 +130,18 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
| 130 | { | 130 | { |
| 131 | struct flowi6 *fl6 = &fl->u.ip6; | 131 | struct flowi6 *fl6 = &fl->u.ip6; |
| 132 | int onlyproto = 0; | 132 | int onlyproto = 0; |
| 133 | u16 offset = skb_network_header_len(skb); | ||
| 134 | const struct ipv6hdr *hdr = ipv6_hdr(skb); | 133 | const struct ipv6hdr *hdr = ipv6_hdr(skb); |
| 134 | u16 offset = sizeof(*hdr); | ||
| 135 | struct ipv6_opt_hdr *exthdr; | 135 | struct ipv6_opt_hdr *exthdr; |
| 136 | const unsigned char *nh = skb_network_header(skb); | 136 | const unsigned char *nh = skb_network_header(skb); |
| 137 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; | 137 | u16 nhoff = IP6CB(skb)->nhoff; |
| 138 | int oif = 0; | 138 | int oif = 0; |
| 139 | u8 nexthdr; | ||
| 140 | |||
| 141 | if (!nhoff) | ||
| 142 | nhoff = offsetof(struct ipv6hdr, nexthdr); | ||
| 143 | |||
| 144 | nexthdr = nh[nhoff]; | ||
| 139 | 145 | ||
| 140 | if (skb_dst(skb)) | 146 | if (skb_dst(skb)) |
| 141 | oif = skb_dst(skb)->dev->ifindex; | 147 | oif = skb_dst(skb)->dev->ifindex; |
diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c index 612a5ddaf93b..799bafc2af39 100644 --- a/net/llc/sysctl_net_llc.c +++ b/net/llc/sysctl_net_llc.c | |||
| @@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = { | |||
| 18 | { | 18 | { |
| 19 | .procname = "ack", | 19 | .procname = "ack", |
| 20 | .data = &sysctl_llc2_ack_timeout, | 20 | .data = &sysctl_llc2_ack_timeout, |
| 21 | .maxlen = sizeof(long), | 21 | .maxlen = sizeof(sysctl_llc2_ack_timeout), |
| 22 | .mode = 0644, | 22 | .mode = 0644, |
| 23 | .proc_handler = proc_dointvec_jiffies, | 23 | .proc_handler = proc_dointvec_jiffies, |
| 24 | }, | 24 | }, |
| 25 | { | 25 | { |
| 26 | .procname = "busy", | 26 | .procname = "busy", |
| 27 | .data = &sysctl_llc2_busy_timeout, | 27 | .data = &sysctl_llc2_busy_timeout, |
| 28 | .maxlen = sizeof(long), | 28 | .maxlen = sizeof(sysctl_llc2_busy_timeout), |
| 29 | .mode = 0644, | 29 | .mode = 0644, |
| 30 | .proc_handler = proc_dointvec_jiffies, | 30 | .proc_handler = proc_dointvec_jiffies, |
| 31 | }, | 31 | }, |
| 32 | { | 32 | { |
| 33 | .procname = "p", | 33 | .procname = "p", |
| 34 | .data = &sysctl_llc2_p_timeout, | 34 | .data = &sysctl_llc2_p_timeout, |
| 35 | .maxlen = sizeof(long), | 35 | .maxlen = sizeof(sysctl_llc2_p_timeout), |
| 36 | .mode = 0644, | 36 | .mode = 0644, |
| 37 | .proc_handler = proc_dointvec_jiffies, | 37 | .proc_handler = proc_dointvec_jiffies, |
| 38 | }, | 38 | }, |
| 39 | { | 39 | { |
| 40 | .procname = "rej", | 40 | .procname = "rej", |
| 41 | .data = &sysctl_llc2_rej_timeout, | 41 | .data = &sysctl_llc2_rej_timeout, |
| 42 | .maxlen = sizeof(long), | 42 | .maxlen = sizeof(sysctl_llc2_rej_timeout), |
| 43 | .mode = 0644, | 43 | .mode = 0644, |
| 44 | .proc_handler = proc_dointvec_jiffies, | 44 | .proc_handler = proc_dointvec_jiffies, |
| 45 | }, | 45 | }, |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 0bb7038121ac..bd4e46ec32bd 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
| @@ -140,7 +140,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
| 140 | if (!ret) { | 140 | if (!ret) { |
| 141 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 141 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
| 142 | 142 | ||
| 143 | if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) | 143 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
| 144 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) || | ||
| 145 | (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) | ||
| 144 | sdata->crypto_tx_tailroom_needed_cnt--; | 146 | sdata->crypto_tx_tailroom_needed_cnt--; |
| 145 | 147 | ||
| 146 | WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && | 148 | WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && |
| @@ -188,7 +190,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
| 188 | sta = key->sta; | 190 | sta = key->sta; |
| 189 | sdata = key->sdata; | 191 | sdata = key->sdata; |
| 190 | 192 | ||
| 191 | if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) | 193 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
| 194 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) || | ||
| 195 | (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) | ||
| 192 | increment_tailroom_need_count(sdata); | 196 | increment_tailroom_need_count(sdata); |
| 193 | 197 | ||
| 194 | ret = drv_set_key(key->local, DISABLE_KEY, sdata, | 198 | ret = drv_set_key(key->local, DISABLE_KEY, sdata, |
| @@ -884,7 +888,9 @@ void ieee80211_remove_key(struct ieee80211_key_conf *keyconf) | |||
| 884 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 888 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
| 885 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 889 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
| 886 | 890 | ||
| 887 | if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) | 891 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
| 892 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) || | ||
| 893 | (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) | ||
| 888 | increment_tailroom_need_count(key->sdata); | 894 | increment_tailroom_need_count(key->sdata); |
| 889 | } | 895 | } |
| 890 | 896 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2c36c4765f47..837a406a9dd6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -1643,7 +1643,7 @@ __ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata) | |||
| 1643 | { | 1643 | { |
| 1644 | struct ieee80211_local *local = sdata->local; | 1644 | struct ieee80211_local *local = sdata->local; |
| 1645 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1645 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 1646 | bool ret; | 1646 | bool ret = false; |
| 1647 | int ac; | 1647 | int ac; |
| 1648 | 1648 | ||
| 1649 | if (local->hw.queues < IEEE80211_NUM_ACS) | 1649 | if (local->hw.queues < IEEE80211_NUM_ACS) |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 4c5192e0d66c..4a95fe3cffbc 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
| @@ -86,20 +86,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 86 | } | 86 | } |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | /* tear down aggregation sessions and remove STAs */ | ||
| 90 | mutex_lock(&local->sta_mtx); | ||
| 91 | list_for_each_entry(sta, &local->sta_list, list) { | ||
| 92 | if (sta->uploaded) { | ||
| 93 | enum ieee80211_sta_state state; | ||
| 94 | |||
| 95 | state = sta->sta_state; | ||
| 96 | for (; state > IEEE80211_STA_NOTEXIST; state--) | ||
| 97 | WARN_ON(drv_sta_state(local, sta->sdata, sta, | ||
| 98 | state, state - 1)); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | mutex_unlock(&local->sta_mtx); | ||
| 102 | |||
| 103 | /* remove all interfaces that were created in the driver */ | 89 | /* remove all interfaces that were created in the driver */ |
| 104 | list_for_each_entry(sdata, &local->interfaces, list) { | 90 | list_for_each_entry(sdata, &local->interfaces, list) { |
| 105 | if (!ieee80211_sdata_running(sdata)) | 91 | if (!ieee80211_sdata_running(sdata)) |
| @@ -111,6 +97,21 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 111 | case NL80211_IFTYPE_STATION: | 97 | case NL80211_IFTYPE_STATION: |
| 112 | ieee80211_mgd_quiesce(sdata); | 98 | ieee80211_mgd_quiesce(sdata); |
| 113 | break; | 99 | break; |
| 100 | case NL80211_IFTYPE_WDS: | ||
| 101 | /* tear down aggregation sessions and remove STAs */ | ||
| 102 | mutex_lock(&local->sta_mtx); | ||
| 103 | sta = sdata->u.wds.sta; | ||
| 104 | if (sta && sta->uploaded) { | ||
| 105 | enum ieee80211_sta_state state; | ||
| 106 | |||
| 107 | state = sta->sta_state; | ||
| 108 | for (; state > IEEE80211_STA_NOTEXIST; state--) | ||
| 109 | WARN_ON(drv_sta_state(local, sta->sdata, | ||
| 110 | sta, state, | ||
| 111 | state - 1)); | ||
| 112 | } | ||
| 113 | mutex_unlock(&local->sta_mtx); | ||
| 114 | break; | ||
| 114 | default: | 115 | default: |
| 115 | break; | 116 | break; |
| 116 | } | 117 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 683b10f46505..d69ca513848e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -272,7 +272,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 272 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) | 272 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
| 273 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; | 273 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; |
| 274 | else if (rate) | 274 | else if (rate) |
| 275 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; | 275 | channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ; |
| 276 | else | 276 | else |
| 277 | channel_flags |= IEEE80211_CHAN_2GHZ; | 277 | channel_flags |= IEEE80211_CHAN_2GHZ; |
| 278 | put_unaligned_le16(channel_flags, pos); | 278 | put_unaligned_le16(channel_flags, pos); |
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c index ca27837974fe..349295d21946 100644 --- a/net/mpls/mpls_gso.c +++ b/net/mpls/mpls_gso.c | |||
| @@ -31,10 +31,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, | |||
| 31 | SKB_GSO_TCPV6 | | 31 | SKB_GSO_TCPV6 | |
| 32 | SKB_GSO_UDP | | 32 | SKB_GSO_UDP | |
| 33 | SKB_GSO_DODGY | | 33 | SKB_GSO_DODGY | |
| 34 | SKB_GSO_TCP_ECN | | 34 | SKB_GSO_TCP_ECN))) |
| 35 | SKB_GSO_GRE | | ||
| 36 | SKB_GSO_GRE_CSUM | | ||
| 37 | SKB_GSO_IPIP))) | ||
| 38 | goto out; | 35 | goto out; |
| 39 | 36 | ||
| 40 | /* Setup inner SKB. */ | 37 | /* Setup inner SKB. */ |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 990decba1fe4..b87ca32efa0b 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -659,16 +659,24 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) | |||
| 659 | return err; | 659 | return err; |
| 660 | } | 660 | } |
| 661 | 661 | ||
| 662 | static int ip_vs_route_me_harder(int af, struct sk_buff *skb) | 662 | static int ip_vs_route_me_harder(int af, struct sk_buff *skb, |
| 663 | unsigned int hooknum) | ||
| 663 | { | 664 | { |
| 665 | if (!sysctl_snat_reroute(skb)) | ||
| 666 | return 0; | ||
| 667 | /* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */ | ||
| 668 | if (NF_INET_LOCAL_IN == hooknum) | ||
| 669 | return 0; | ||
| 664 | #ifdef CONFIG_IP_VS_IPV6 | 670 | #ifdef CONFIG_IP_VS_IPV6 |
| 665 | if (af == AF_INET6) { | 671 | if (af == AF_INET6) { |
| 666 | if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0) | 672 | struct dst_entry *dst = skb_dst(skb); |
| 673 | |||
| 674 | if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) && | ||
| 675 | ip6_route_me_harder(skb) != 0) | ||
| 667 | return 1; | 676 | return 1; |
| 668 | } else | 677 | } else |
| 669 | #endif | 678 | #endif |
| 670 | if ((sysctl_snat_reroute(skb) || | 679 | if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) && |
| 671 | skb_rtable(skb)->rt_flags & RTCF_LOCAL) && | ||
| 672 | ip_route_me_harder(skb, RTN_LOCAL) != 0) | 680 | ip_route_me_harder(skb, RTN_LOCAL) != 0) |
| 673 | return 1; | 681 | return 1; |
| 674 | 682 | ||
| @@ -791,7 +799,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, | |||
| 791 | union nf_inet_addr *snet, | 799 | union nf_inet_addr *snet, |
| 792 | __u8 protocol, struct ip_vs_conn *cp, | 800 | __u8 protocol, struct ip_vs_conn *cp, |
| 793 | struct ip_vs_protocol *pp, | 801 | struct ip_vs_protocol *pp, |
| 794 | unsigned int offset, unsigned int ihl) | 802 | unsigned int offset, unsigned int ihl, |
| 803 | unsigned int hooknum) | ||
| 795 | { | 804 | { |
| 796 | unsigned int verdict = NF_DROP; | 805 | unsigned int verdict = NF_DROP; |
| 797 | 806 | ||
| @@ -821,7 +830,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb, | |||
| 821 | #endif | 830 | #endif |
| 822 | ip_vs_nat_icmp(skb, pp, cp, 1); | 831 | ip_vs_nat_icmp(skb, pp, cp, 1); |
| 823 | 832 | ||
| 824 | if (ip_vs_route_me_harder(af, skb)) | 833 | if (ip_vs_route_me_harder(af, skb, hooknum)) |
| 825 | goto out; | 834 | goto out; |
| 826 | 835 | ||
| 827 | /* do the statistics and put it back */ | 836 | /* do the statistics and put it back */ |
| @@ -916,7 +925,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related, | |||
| 916 | 925 | ||
| 917 | snet.ip = iph->saddr; | 926 | snet.ip = iph->saddr; |
| 918 | return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp, | 927 | return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp, |
| 919 | pp, ciph.len, ihl); | 928 | pp, ciph.len, ihl, hooknum); |
| 920 | } | 929 | } |
| 921 | 930 | ||
| 922 | #ifdef CONFIG_IP_VS_IPV6 | 931 | #ifdef CONFIG_IP_VS_IPV6 |
| @@ -981,7 +990,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, | |||
| 981 | snet.in6 = ciph.saddr.in6; | 990 | snet.in6 = ciph.saddr.in6; |
| 982 | writable = ciph.len; | 991 | writable = ciph.len; |
| 983 | return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, | 992 | return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, |
| 984 | pp, writable, sizeof(struct ipv6hdr)); | 993 | pp, writable, sizeof(struct ipv6hdr), |
| 994 | hooknum); | ||
| 985 | } | 995 | } |
| 986 | #endif | 996 | #endif |
| 987 | 997 | ||
| @@ -1040,7 +1050,8 @@ static inline bool is_new_conn(const struct sk_buff *skb, | |||
| 1040 | */ | 1050 | */ |
| 1041 | static unsigned int | 1051 | static unsigned int |
| 1042 | handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, | 1052 | handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, |
| 1043 | struct ip_vs_conn *cp, struct ip_vs_iphdr *iph) | 1053 | struct ip_vs_conn *cp, struct ip_vs_iphdr *iph, |
| 1054 | unsigned int hooknum) | ||
| 1044 | { | 1055 | { |
| 1045 | struct ip_vs_protocol *pp = pd->pp; | 1056 | struct ip_vs_protocol *pp = pd->pp; |
| 1046 | 1057 | ||
| @@ -1078,7 +1089,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, | |||
| 1078 | * if it came from this machine itself. So re-compute | 1089 | * if it came from this machine itself. So re-compute |
| 1079 | * the routing information. | 1090 | * the routing information. |
| 1080 | */ | 1091 | */ |
| 1081 | if (ip_vs_route_me_harder(af, skb)) | 1092 | if (ip_vs_route_me_harder(af, skb, hooknum)) |
| 1082 | goto drop; | 1093 | goto drop; |
| 1083 | 1094 | ||
| 1084 | IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); | 1095 | IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); |
| @@ -1181,7 +1192,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) | |||
| 1181 | cp = pp->conn_out_get(af, skb, &iph, 0); | 1192 | cp = pp->conn_out_get(af, skb, &iph, 0); |
| 1182 | 1193 | ||
| 1183 | if (likely(cp)) | 1194 | if (likely(cp)) |
| 1184 | return handle_response(af, skb, pd, cp, &iph); | 1195 | return handle_response(af, skb, pd, cp, &iph, hooknum); |
| 1185 | if (sysctl_nat_icmp_send(net) && | 1196 | if (sysctl_nat_icmp_send(net) && |
| 1186 | (pp->protocol == IPPROTO_TCP || | 1197 | (pp->protocol == IPPROTO_TCP || |
| 1187 | pp->protocol == IPPROTO_UDP || | 1198 | pp->protocol == IPPROTO_UDP || |
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index 1d5341f3761d..5d3daae98bf0 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c | |||
| @@ -183,6 +183,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 183 | struct nf_conn *ct; | 183 | struct nf_conn *ct; |
| 184 | struct net *net; | 184 | struct net *net; |
| 185 | 185 | ||
| 186 | *diff = 0; | ||
| 187 | |||
| 186 | #ifdef CONFIG_IP_VS_IPV6 | 188 | #ifdef CONFIG_IP_VS_IPV6 |
| 187 | /* This application helper doesn't work with IPv6 yet, | 189 | /* This application helper doesn't work with IPv6 yet, |
| 188 | * so turn this into a no-op for IPv6 packets | 190 | * so turn this into a no-op for IPv6 packets |
| @@ -191,8 +193,6 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 191 | return 1; | 193 | return 1; |
| 192 | #endif | 194 | #endif |
| 193 | 195 | ||
| 194 | *diff = 0; | ||
| 195 | |||
| 196 | /* Only useful for established sessions */ | 196 | /* Only useful for established sessions */ |
| 197 | if (cp->state != IP_VS_TCP_S_ESTABLISHED) | 197 | if (cp->state != IP_VS_TCP_S_ESTABLISHED) |
| 198 | return 1; | 198 | return 1; |
| @@ -322,6 +322,9 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 322 | struct ip_vs_conn *n_cp; | 322 | struct ip_vs_conn *n_cp; |
| 323 | struct net *net; | 323 | struct net *net; |
| 324 | 324 | ||
| 325 | /* no diff required for incoming packets */ | ||
| 326 | *diff = 0; | ||
| 327 | |||
| 325 | #ifdef CONFIG_IP_VS_IPV6 | 328 | #ifdef CONFIG_IP_VS_IPV6 |
| 326 | /* This application helper doesn't work with IPv6 yet, | 329 | /* This application helper doesn't work with IPv6 yet, |
| 327 | * so turn this into a no-op for IPv6 packets | 330 | * so turn this into a no-op for IPv6 packets |
| @@ -330,9 +333,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 330 | return 1; | 333 | return 1; |
| 331 | #endif | 334 | #endif |
| 332 | 335 | ||
| 333 | /* no diff required for incoming packets */ | ||
| 334 | *diff = 0; | ||
| 335 | |||
| 336 | /* Only useful for established sessions */ | 336 | /* Only useful for established sessions */ |
| 337 | if (cp->state != IP_VS_TCP_S_ESTABLISHED) | 337 | if (cp->state != IP_VS_TCP_S_ESTABLISHED) |
| 338 | return 1; | 338 | return 1; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index a11674806707..46d1b26a468e 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -611,16 +611,15 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 611 | */ | 611 | */ |
| 612 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); | 612 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); |
| 613 | pr_debug("Confirming conntrack %p\n", ct); | 613 | pr_debug("Confirming conntrack %p\n", ct); |
| 614 | /* We have to check the DYING flag inside the lock to prevent | 614 | /* We have to check the DYING flag after unlink to prevent |
| 615 | a race against nf_ct_get_next_corpse() possibly called from | 615 | * a race against nf_ct_get_next_corpse() possibly called from |
| 616 | user context, else we insert an already 'dead' hash, blocking | 616 | * user context, else we insert an already 'dead' hash, blocking |
| 617 | further use of that particular connection -JM */ | 617 | * further use of that particular connection -JM. |
| 618 | */ | ||
| 619 | nf_ct_del_from_dying_or_unconfirmed_list(ct); | ||
| 618 | 620 | ||
| 619 | if (unlikely(nf_ct_is_dying(ct))) { | 621 | if (unlikely(nf_ct_is_dying(ct))) |
| 620 | nf_conntrack_double_unlock(hash, reply_hash); | 622 | goto out; |
| 621 | local_bh_enable(); | ||
| 622 | return NF_ACCEPT; | ||
| 623 | } | ||
| 624 | 623 | ||
| 625 | /* See if there's one in the list already, including reverse: | 624 | /* See if there's one in the list already, including reverse: |
| 626 | NAT could have grabbed it without realizing, since we're | 625 | NAT could have grabbed it without realizing, since we're |
| @@ -636,8 +635,6 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 636 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) | 635 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) |
| 637 | goto out; | 636 | goto out; |
| 638 | 637 | ||
| 639 | nf_ct_del_from_dying_or_unconfirmed_list(ct); | ||
| 640 | |||
| 641 | /* Timer relative to confirmation time, not original | 638 | /* Timer relative to confirmation time, not original |
| 642 | setting time, otherwise we'd get timer wrap in | 639 | setting time, otherwise we'd get timer wrap in |
| 643 | weird delay cases. */ | 640 | weird delay cases. */ |
| @@ -673,6 +670,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 673 | return NF_ACCEPT; | 670 | return NF_ACCEPT; |
| 674 | 671 | ||
| 675 | out: | 672 | out: |
| 673 | nf_ct_add_to_dying_list(ct); | ||
| 676 | nf_conntrack_double_unlock(hash, reply_hash); | 674 | nf_conntrack_double_unlock(hash, reply_hash); |
| 677 | NF_CT_STAT_INC(net, insert_failed); | 675 | NF_CT_STAT_INC(net, insert_failed); |
| 678 | local_bh_enable(); | 676 | local_bh_enable(); |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 129a8daa4abf..1ff04bcd4871 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -713,16 +713,12 @@ static int nft_flush_table(struct nft_ctx *ctx) | |||
| 713 | struct nft_chain *chain, *nc; | 713 | struct nft_chain *chain, *nc; |
| 714 | struct nft_set *set, *ns; | 714 | struct nft_set *set, *ns; |
| 715 | 715 | ||
| 716 | list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) { | 716 | list_for_each_entry(chain, &ctx->table->chains, list) { |
| 717 | ctx->chain = chain; | 717 | ctx->chain = chain; |
| 718 | 718 | ||
| 719 | err = nft_delrule_by_chain(ctx); | 719 | err = nft_delrule_by_chain(ctx); |
| 720 | if (err < 0) | 720 | if (err < 0) |
| 721 | goto out; | 721 | goto out; |
| 722 | |||
| 723 | err = nft_delchain(ctx); | ||
| 724 | if (err < 0) | ||
| 725 | goto out; | ||
| 726 | } | 722 | } |
| 727 | 723 | ||
| 728 | list_for_each_entry_safe(set, ns, &ctx->table->sets, list) { | 724 | list_for_each_entry_safe(set, ns, &ctx->table->sets, list) { |
| @@ -735,6 +731,14 @@ static int nft_flush_table(struct nft_ctx *ctx) | |||
| 735 | goto out; | 731 | goto out; |
| 736 | } | 732 | } |
| 737 | 733 | ||
| 734 | list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) { | ||
| 735 | ctx->chain = chain; | ||
| 736 | |||
| 737 | err = nft_delchain(ctx); | ||
| 738 | if (err < 0) | ||
| 739 | goto out; | ||
| 740 | } | ||
| 741 | |||
| 738 | err = nft_deltable(ctx); | 742 | err = nft_deltable(ctx); |
| 739 | out: | 743 | out: |
| 740 | return err; | 744 | return err; |
| @@ -1130,9 +1134,11 @@ static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr) | |||
| 1130 | /* Restore old counters on this cpu, no problem. Per-cpu statistics | 1134 | /* Restore old counters on this cpu, no problem. Per-cpu statistics |
| 1131 | * are not exposed to userspace. | 1135 | * are not exposed to userspace. |
| 1132 | */ | 1136 | */ |
| 1137 | preempt_disable(); | ||
| 1133 | stats = this_cpu_ptr(newstats); | 1138 | stats = this_cpu_ptr(newstats); |
| 1134 | stats->bytes = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES])); | 1139 | stats->bytes = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES])); |
| 1135 | stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])); | 1140 | stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])); |
| 1141 | preempt_enable(); | ||
| 1136 | 1142 | ||
| 1137 | return newstats; | 1143 | return newstats; |
| 1138 | } | 1144 | } |
| @@ -1258,8 +1264,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 1258 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); | 1264 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); |
| 1259 | trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN, | 1265 | trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN, |
| 1260 | sizeof(struct nft_trans_chain)); | 1266 | sizeof(struct nft_trans_chain)); |
| 1261 | if (trans == NULL) | 1267 | if (trans == NULL) { |
| 1268 | free_percpu(stats); | ||
| 1262 | return -ENOMEM; | 1269 | return -ENOMEM; |
| 1270 | } | ||
| 1263 | 1271 | ||
| 1264 | nft_trans_chain_stats(trans) = stats; | 1272 | nft_trans_chain_stats(trans) = stats; |
| 1265 | nft_trans_chain_update(trans) = true; | 1273 | nft_trans_chain_update(trans) = true; |
| @@ -1315,8 +1323,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 1315 | hookfn = type->hooks[hooknum]; | 1323 | hookfn = type->hooks[hooknum]; |
| 1316 | 1324 | ||
| 1317 | basechain = kzalloc(sizeof(*basechain), GFP_KERNEL); | 1325 | basechain = kzalloc(sizeof(*basechain), GFP_KERNEL); |
| 1318 | if (basechain == NULL) | 1326 | if (basechain == NULL) { |
| 1327 | module_put(type->owner); | ||
| 1319 | return -ENOMEM; | 1328 | return -ENOMEM; |
| 1329 | } | ||
| 1320 | 1330 | ||
| 1321 | if (nla[NFTA_CHAIN_COUNTERS]) { | 1331 | if (nla[NFTA_CHAIN_COUNTERS]) { |
| 1322 | stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]); | 1332 | stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]); |
| @@ -3749,6 +3759,24 @@ int nft_chain_validate_dependency(const struct nft_chain *chain, | |||
| 3749 | } | 3759 | } |
| 3750 | EXPORT_SYMBOL_GPL(nft_chain_validate_dependency); | 3760 | EXPORT_SYMBOL_GPL(nft_chain_validate_dependency); |
| 3751 | 3761 | ||
| 3762 | int nft_chain_validate_hooks(const struct nft_chain *chain, | ||
| 3763 | unsigned int hook_flags) | ||
| 3764 | { | ||
| 3765 | struct nft_base_chain *basechain; | ||
| 3766 | |||
| 3767 | if (chain->flags & NFT_BASE_CHAIN) { | ||
| 3768 | basechain = nft_base_chain(chain); | ||
| 3769 | |||
| 3770 | if ((1 << basechain->ops[0].hooknum) & hook_flags) | ||
| 3771 | return 0; | ||
| 3772 | |||
| 3773 | return -EOPNOTSUPP; | ||
| 3774 | } | ||
| 3775 | |||
| 3776 | return 0; | ||
| 3777 | } | ||
| 3778 | EXPORT_SYMBOL_GPL(nft_chain_validate_hooks); | ||
| 3779 | |||
| 3752 | /* | 3780 | /* |
| 3753 | * Loop detection - walk through the ruleset beginning at the destination chain | 3781 | * Loop detection - walk through the ruleset beginning at the destination chain |
| 3754 | * of a new jump until either the source chain is reached (loop) or all | 3782 | * of a new jump until either the source chain is reached (loop) or all |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 13c2e17bbe27..c421d94c4652 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
| @@ -321,7 +321,8 @@ replay: | |||
| 321 | nlh = nlmsg_hdr(skb); | 321 | nlh = nlmsg_hdr(skb); |
| 322 | err = 0; | 322 | err = 0; |
| 323 | 323 | ||
| 324 | if (nlh->nlmsg_len < NLMSG_HDRLEN) { | 324 | if (nlmsg_len(nlh) < sizeof(struct nfgenmsg) || |
| 325 | skb->len < nlh->nlmsg_len) { | ||
| 325 | err = -EINVAL; | 326 | err = -EINVAL; |
| 326 | goto ack; | 327 | goto ack; |
| 327 | } | 328 | } |
| @@ -463,13 +464,13 @@ static void nfnetlink_rcv(struct sk_buff *skb) | |||
| 463 | } | 464 | } |
| 464 | 465 | ||
| 465 | #ifdef CONFIG_MODULES | 466 | #ifdef CONFIG_MODULES |
| 466 | static int nfnetlink_bind(int group) | 467 | static int nfnetlink_bind(struct net *net, int group) |
| 467 | { | 468 | { |
| 468 | const struct nfnetlink_subsystem *ss; | 469 | const struct nfnetlink_subsystem *ss; |
| 469 | int type; | 470 | int type; |
| 470 | 471 | ||
| 471 | if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX) | 472 | if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX) |
| 472 | return -EINVAL; | 473 | return 0; |
| 473 | 474 | ||
| 474 | type = nfnl_group2type[group]; | 475 | type = nfnl_group2type[group]; |
| 475 | 476 | ||
diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c index d1ffd5eb3a9b..9aea747b43ea 100644 --- a/net/netfilter/nft_masq.c +++ b/net/netfilter/nft_masq.c | |||
| @@ -21,6 +21,21 @@ const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = { | |||
| 21 | }; | 21 | }; |
| 22 | EXPORT_SYMBOL_GPL(nft_masq_policy); | 22 | EXPORT_SYMBOL_GPL(nft_masq_policy); |
| 23 | 23 | ||
| 24 | int nft_masq_validate(const struct nft_ctx *ctx, | ||
| 25 | const struct nft_expr *expr, | ||
| 26 | const struct nft_data **data) | ||
| 27 | { | ||
| 28 | int err; | ||
| 29 | |||
| 30 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 31 | if (err < 0) | ||
| 32 | return err; | ||
| 33 | |||
| 34 | return nft_chain_validate_hooks(ctx->chain, | ||
| 35 | (1 << NF_INET_POST_ROUTING)); | ||
| 36 | } | ||
| 37 | EXPORT_SYMBOL_GPL(nft_masq_validate); | ||
| 38 | |||
| 24 | int nft_masq_init(const struct nft_ctx *ctx, | 39 | int nft_masq_init(const struct nft_ctx *ctx, |
| 25 | const struct nft_expr *expr, | 40 | const struct nft_expr *expr, |
| 26 | const struct nlattr * const tb[]) | 41 | const struct nlattr * const tb[]) |
| @@ -28,8 +43,8 @@ int nft_masq_init(const struct nft_ctx *ctx, | |||
| 28 | struct nft_masq *priv = nft_expr_priv(expr); | 43 | struct nft_masq *priv = nft_expr_priv(expr); |
| 29 | int err; | 44 | int err; |
| 30 | 45 | ||
| 31 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | 46 | err = nft_masq_validate(ctx, expr, NULL); |
| 32 | if (err < 0) | 47 | if (err) |
| 33 | return err; | 48 | return err; |
| 34 | 49 | ||
| 35 | if (tb[NFTA_MASQ_FLAGS] == NULL) | 50 | if (tb[NFTA_MASQ_FLAGS] == NULL) |
| @@ -60,12 +75,5 @@ nla_put_failure: | |||
| 60 | } | 75 | } |
| 61 | EXPORT_SYMBOL_GPL(nft_masq_dump); | 76 | EXPORT_SYMBOL_GPL(nft_masq_dump); |
| 62 | 77 | ||
| 63 | int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, | ||
| 64 | const struct nft_data **data) | ||
| 65 | { | ||
| 66 | return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 67 | } | ||
| 68 | EXPORT_SYMBOL_GPL(nft_masq_validate); | ||
| 69 | |||
| 70 | MODULE_LICENSE("GPL"); | 78 | MODULE_LICENSE("GPL"); |
| 71 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); | 79 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); |
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c index afe2b0b45ec4..a0837c6c9283 100644 --- a/net/netfilter/nft_nat.c +++ b/net/netfilter/nft_nat.c | |||
| @@ -65,10 +65,10 @@ static void nft_nat_eval(const struct nft_expr *expr, | |||
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | if (priv->sreg_proto_min) { | 67 | if (priv->sreg_proto_min) { |
| 68 | range.min_proto.all = (__force __be16) | 68 | range.min_proto.all = |
| 69 | data[priv->sreg_proto_min].data[0]; | 69 | *(__be16 *)&data[priv->sreg_proto_min].data[0]; |
| 70 | range.max_proto.all = (__force __be16) | 70 | range.max_proto.all = |
| 71 | data[priv->sreg_proto_max].data[0]; | 71 | *(__be16 *)&data[priv->sreg_proto_max].data[0]; |
| 72 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 72 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| @@ -88,17 +88,40 @@ static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = { | |||
| 88 | [NFTA_NAT_FLAGS] = { .type = NLA_U32 }, | 88 | [NFTA_NAT_FLAGS] = { .type = NLA_U32 }, |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | 91 | static int nft_nat_validate(const struct nft_ctx *ctx, |
| 92 | const struct nlattr * const tb[]) | 92 | const struct nft_expr *expr, |
| 93 | const struct nft_data **data) | ||
| 93 | { | 94 | { |
| 94 | struct nft_nat *priv = nft_expr_priv(expr); | 95 | struct nft_nat *priv = nft_expr_priv(expr); |
| 95 | u32 family; | ||
| 96 | int err; | 96 | int err; |
| 97 | 97 | ||
| 98 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | 98 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); |
| 99 | if (err < 0) | 99 | if (err < 0) |
| 100 | return err; | 100 | return err; |
| 101 | 101 | ||
| 102 | switch (priv->type) { | ||
| 103 | case NFT_NAT_SNAT: | ||
| 104 | err = nft_chain_validate_hooks(ctx->chain, | ||
| 105 | (1 << NF_INET_POST_ROUTING) | | ||
| 106 | (1 << NF_INET_LOCAL_IN)); | ||
| 107 | break; | ||
| 108 | case NFT_NAT_DNAT: | ||
| 109 | err = nft_chain_validate_hooks(ctx->chain, | ||
| 110 | (1 << NF_INET_PRE_ROUTING) | | ||
| 111 | (1 << NF_INET_LOCAL_OUT)); | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | |||
| 115 | return err; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | ||
| 119 | const struct nlattr * const tb[]) | ||
| 120 | { | ||
| 121 | struct nft_nat *priv = nft_expr_priv(expr); | ||
| 122 | u32 family; | ||
| 123 | int err; | ||
| 124 | |||
| 102 | if (tb[NFTA_NAT_TYPE] == NULL || | 125 | if (tb[NFTA_NAT_TYPE] == NULL || |
| 103 | (tb[NFTA_NAT_REG_ADDR_MIN] == NULL && | 126 | (tb[NFTA_NAT_REG_ADDR_MIN] == NULL && |
| 104 | tb[NFTA_NAT_REG_PROTO_MIN] == NULL)) | 127 | tb[NFTA_NAT_REG_PROTO_MIN] == NULL)) |
| @@ -115,6 +138,10 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
| 115 | return -EINVAL; | 138 | return -EINVAL; |
| 116 | } | 139 | } |
| 117 | 140 | ||
| 141 | err = nft_nat_validate(ctx, expr, NULL); | ||
| 142 | if (err < 0) | ||
| 143 | return err; | ||
| 144 | |||
| 118 | if (tb[NFTA_NAT_FAMILY] == NULL) | 145 | if (tb[NFTA_NAT_FAMILY] == NULL) |
| 119 | return -EINVAL; | 146 | return -EINVAL; |
| 120 | 147 | ||
| @@ -219,13 +246,6 @@ nla_put_failure: | |||
| 219 | return -1; | 246 | return -1; |
| 220 | } | 247 | } |
| 221 | 248 | ||
| 222 | static int nft_nat_validate(const struct nft_ctx *ctx, | ||
| 223 | const struct nft_expr *expr, | ||
| 224 | const struct nft_data **data) | ||
| 225 | { | ||
| 226 | return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 227 | } | ||
| 228 | |||
| 229 | static struct nft_expr_type nft_nat_type; | 249 | static struct nft_expr_type nft_nat_type; |
| 230 | static const struct nft_expr_ops nft_nat_ops = { | 250 | static const struct nft_expr_ops nft_nat_ops = { |
| 231 | .type = &nft_nat_type, | 251 | .type = &nft_nat_type, |
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c index 9e8093f28311..d7e9e93a4e90 100644 --- a/net/netfilter/nft_redir.c +++ b/net/netfilter/nft_redir.c | |||
| @@ -23,6 +23,22 @@ const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = { | |||
| 23 | }; | 23 | }; |
| 24 | EXPORT_SYMBOL_GPL(nft_redir_policy); | 24 | EXPORT_SYMBOL_GPL(nft_redir_policy); |
| 25 | 25 | ||
| 26 | int nft_redir_validate(const struct nft_ctx *ctx, | ||
| 27 | const struct nft_expr *expr, | ||
| 28 | const struct nft_data **data) | ||
| 29 | { | ||
| 30 | int err; | ||
| 31 | |||
| 32 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 33 | if (err < 0) | ||
| 34 | return err; | ||
| 35 | |||
| 36 | return nft_chain_validate_hooks(ctx->chain, | ||
| 37 | (1 << NF_INET_PRE_ROUTING) | | ||
| 38 | (1 << NF_INET_LOCAL_OUT)); | ||
| 39 | } | ||
| 40 | EXPORT_SYMBOL_GPL(nft_redir_validate); | ||
| 41 | |||
| 26 | int nft_redir_init(const struct nft_ctx *ctx, | 42 | int nft_redir_init(const struct nft_ctx *ctx, |
| 27 | const struct nft_expr *expr, | 43 | const struct nft_expr *expr, |
| 28 | const struct nlattr * const tb[]) | 44 | const struct nlattr * const tb[]) |
| @@ -30,7 +46,7 @@ int nft_redir_init(const struct nft_ctx *ctx, | |||
| 30 | struct nft_redir *priv = nft_expr_priv(expr); | 46 | struct nft_redir *priv = nft_expr_priv(expr); |
| 31 | int err; | 47 | int err; |
| 32 | 48 | ||
| 33 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | 49 | err = nft_redir_validate(ctx, expr, NULL); |
| 34 | if (err < 0) | 50 | if (err < 0) |
| 35 | return err; | 51 | return err; |
| 36 | 52 | ||
| @@ -88,12 +104,5 @@ nla_put_failure: | |||
| 88 | } | 104 | } |
| 89 | EXPORT_SYMBOL_GPL(nft_redir_dump); | 105 | EXPORT_SYMBOL_GPL(nft_redir_dump); |
| 90 | 106 | ||
| 91 | int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, | ||
| 92 | const struct nft_data **data) | ||
| 93 | { | ||
| 94 | return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 95 | } | ||
| 96 | EXPORT_SYMBOL_GPL(nft_redir_validate); | ||
| 97 | |||
| 98 | MODULE_LICENSE("GPL"); | 107 | MODULE_LICENSE("GPL"); |
| 99 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); | 108 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 074cf3e91c6f..75532efa51cd 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -61,6 +61,7 @@ | |||
| 61 | #include <linux/rhashtable.h> | 61 | #include <linux/rhashtable.h> |
| 62 | #include <asm/cacheflush.h> | 62 | #include <asm/cacheflush.h> |
| 63 | #include <linux/hash.h> | 63 | #include <linux/hash.h> |
| 64 | #include <linux/genetlink.h> | ||
| 64 | 65 | ||
| 65 | #include <net/net_namespace.h> | 66 | #include <net/net_namespace.h> |
| 66 | #include <net/sock.h> | 67 | #include <net/sock.h> |
| @@ -1091,8 +1092,12 @@ static void netlink_remove(struct sock *sk) | |||
| 1091 | mutex_unlock(&nl_sk_hash_lock); | 1092 | mutex_unlock(&nl_sk_hash_lock); |
| 1092 | 1093 | ||
| 1093 | netlink_table_grab(); | 1094 | netlink_table_grab(); |
| 1094 | if (nlk_sk(sk)->subscriptions) | 1095 | if (nlk_sk(sk)->subscriptions) { |
| 1095 | __sk_del_bind_node(sk); | 1096 | __sk_del_bind_node(sk); |
| 1097 | netlink_update_listeners(sk); | ||
| 1098 | } | ||
| 1099 | if (sk->sk_protocol == NETLINK_GENERIC) | ||
| 1100 | atomic_inc(&genl_sk_destructing_cnt); | ||
| 1096 | netlink_table_ungrab(); | 1101 | netlink_table_ungrab(); |
| 1097 | } | 1102 | } |
| 1098 | 1103 | ||
| @@ -1139,8 +1144,8 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol, | |||
| 1139 | struct module *module = NULL; | 1144 | struct module *module = NULL; |
| 1140 | struct mutex *cb_mutex; | 1145 | struct mutex *cb_mutex; |
| 1141 | struct netlink_sock *nlk; | 1146 | struct netlink_sock *nlk; |
| 1142 | int (*bind)(int group); | 1147 | int (*bind)(struct net *net, int group); |
| 1143 | void (*unbind)(int group); | 1148 | void (*unbind)(struct net *net, int group); |
| 1144 | int err = 0; | 1149 | int err = 0; |
| 1145 | 1150 | ||
| 1146 | sock->state = SS_UNCONNECTED; | 1151 | sock->state = SS_UNCONNECTED; |
| @@ -1209,6 +1214,20 @@ static int netlink_release(struct socket *sock) | |||
| 1209 | * will be purged. | 1214 | * will be purged. |
| 1210 | */ | 1215 | */ |
| 1211 | 1216 | ||
| 1217 | /* must not acquire netlink_table_lock in any way again before unbind | ||
| 1218 | * and notifying genetlink is done as otherwise it might deadlock | ||
| 1219 | */ | ||
| 1220 | if (nlk->netlink_unbind) { | ||
| 1221 | int i; | ||
| 1222 | |||
| 1223 | for (i = 0; i < nlk->ngroups; i++) | ||
| 1224 | if (test_bit(i, nlk->groups)) | ||
| 1225 | nlk->netlink_unbind(sock_net(sk), i + 1); | ||
| 1226 | } | ||
| 1227 | if (sk->sk_protocol == NETLINK_GENERIC && | ||
| 1228 | atomic_dec_return(&genl_sk_destructing_cnt) == 0) | ||
| 1229 | wake_up(&genl_sk_destructing_waitq); | ||
| 1230 | |||
| 1212 | sock->sk = NULL; | 1231 | sock->sk = NULL; |
| 1213 | wake_up_interruptible_all(&nlk->wait); | 1232 | wake_up_interruptible_all(&nlk->wait); |
| 1214 | 1233 | ||
| @@ -1226,8 +1245,8 @@ static int netlink_release(struct socket *sock) | |||
| 1226 | 1245 | ||
| 1227 | module_put(nlk->module); | 1246 | module_put(nlk->module); |
| 1228 | 1247 | ||
| 1229 | netlink_table_grab(); | ||
| 1230 | if (netlink_is_kernel(sk)) { | 1248 | if (netlink_is_kernel(sk)) { |
| 1249 | netlink_table_grab(); | ||
| 1231 | BUG_ON(nl_table[sk->sk_protocol].registered == 0); | 1250 | BUG_ON(nl_table[sk->sk_protocol].registered == 0); |
| 1232 | if (--nl_table[sk->sk_protocol].registered == 0) { | 1251 | if (--nl_table[sk->sk_protocol].registered == 0) { |
| 1233 | struct listeners *old; | 1252 | struct listeners *old; |
| @@ -1241,10 +1260,8 @@ static int netlink_release(struct socket *sock) | |||
| 1241 | nl_table[sk->sk_protocol].flags = 0; | 1260 | nl_table[sk->sk_protocol].flags = 0; |
| 1242 | nl_table[sk->sk_protocol].registered = 0; | 1261 | nl_table[sk->sk_protocol].registered = 0; |
| 1243 | } | 1262 | } |
| 1244 | } else if (nlk->subscriptions) { | 1263 | netlink_table_ungrab(); |
| 1245 | netlink_update_listeners(sk); | ||
| 1246 | } | 1264 | } |
| 1247 | netlink_table_ungrab(); | ||
| 1248 | 1265 | ||
| 1249 | kfree(nlk->groups); | 1266 | kfree(nlk->groups); |
| 1250 | nlk->groups = NULL; | 1267 | nlk->groups = NULL; |
| @@ -1410,9 +1427,10 @@ static int netlink_realloc_groups(struct sock *sk) | |||
| 1410 | return err; | 1427 | return err; |
| 1411 | } | 1428 | } |
| 1412 | 1429 | ||
| 1413 | static void netlink_unbind(int group, long unsigned int groups, | 1430 | static void netlink_undo_bind(int group, long unsigned int groups, |
| 1414 | struct netlink_sock *nlk) | 1431 | struct sock *sk) |
| 1415 | { | 1432 | { |
| 1433 | struct netlink_sock *nlk = nlk_sk(sk); | ||
| 1416 | int undo; | 1434 | int undo; |
| 1417 | 1435 | ||
| 1418 | if (!nlk->netlink_unbind) | 1436 | if (!nlk->netlink_unbind) |
| @@ -1420,7 +1438,7 @@ static void netlink_unbind(int group, long unsigned int groups, | |||
| 1420 | 1438 | ||
| 1421 | for (undo = 0; undo < group; undo++) | 1439 | for (undo = 0; undo < group; undo++) |
| 1422 | if (test_bit(undo, &groups)) | 1440 | if (test_bit(undo, &groups)) |
| 1423 | nlk->netlink_unbind(undo); | 1441 | nlk->netlink_unbind(sock_net(sk), undo + 1); |
| 1424 | } | 1442 | } |
| 1425 | 1443 | ||
| 1426 | static int netlink_bind(struct socket *sock, struct sockaddr *addr, | 1444 | static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
| @@ -1458,10 +1476,10 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
| 1458 | for (group = 0; group < nlk->ngroups; group++) { | 1476 | for (group = 0; group < nlk->ngroups; group++) { |
| 1459 | if (!test_bit(group, &groups)) | 1477 | if (!test_bit(group, &groups)) |
| 1460 | continue; | 1478 | continue; |
| 1461 | err = nlk->netlink_bind(group); | 1479 | err = nlk->netlink_bind(net, group + 1); |
| 1462 | if (!err) | 1480 | if (!err) |
| 1463 | continue; | 1481 | continue; |
| 1464 | netlink_unbind(group, groups, nlk); | 1482 | netlink_undo_bind(group, groups, sk); |
| 1465 | return err; | 1483 | return err; |
| 1466 | } | 1484 | } |
| 1467 | } | 1485 | } |
| @@ -1471,7 +1489,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
| 1471 | netlink_insert(sk, net, nladdr->nl_pid) : | 1489 | netlink_insert(sk, net, nladdr->nl_pid) : |
| 1472 | netlink_autobind(sock); | 1490 | netlink_autobind(sock); |
| 1473 | if (err) { | 1491 | if (err) { |
| 1474 | netlink_unbind(nlk->ngroups, groups, nlk); | 1492 | netlink_undo_bind(nlk->ngroups, groups, sk); |
| 1475 | return err; | 1493 | return err; |
| 1476 | } | 1494 | } |
| 1477 | } | 1495 | } |
| @@ -2122,7 +2140,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, | |||
| 2122 | if (!val || val - 1 >= nlk->ngroups) | 2140 | if (!val || val - 1 >= nlk->ngroups) |
| 2123 | return -EINVAL; | 2141 | return -EINVAL; |
| 2124 | if (optname == NETLINK_ADD_MEMBERSHIP && nlk->netlink_bind) { | 2142 | if (optname == NETLINK_ADD_MEMBERSHIP && nlk->netlink_bind) { |
| 2125 | err = nlk->netlink_bind(val); | 2143 | err = nlk->netlink_bind(sock_net(sk), val); |
| 2126 | if (err) | 2144 | if (err) |
| 2127 | return err; | 2145 | return err; |
| 2128 | } | 2146 | } |
| @@ -2131,7 +2149,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, | |||
| 2131 | optname == NETLINK_ADD_MEMBERSHIP); | 2149 | optname == NETLINK_ADD_MEMBERSHIP); |
| 2132 | netlink_table_ungrab(); | 2150 | netlink_table_ungrab(); |
| 2133 | if (optname == NETLINK_DROP_MEMBERSHIP && nlk->netlink_unbind) | 2151 | if (optname == NETLINK_DROP_MEMBERSHIP && nlk->netlink_unbind) |
| 2134 | nlk->netlink_unbind(val); | 2152 | nlk->netlink_unbind(sock_net(sk), val); |
| 2135 | 2153 | ||
| 2136 | err = 0; | 2154 | err = 0; |
| 2137 | break; | 2155 | break; |
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index b20a1731759b..f1c31b39aa3e 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define _AF_NETLINK_H | 2 | #define _AF_NETLINK_H |
| 3 | 3 | ||
| 4 | #include <linux/rhashtable.h> | 4 | #include <linux/rhashtable.h> |
| 5 | #include <linux/atomic.h> | ||
| 5 | #include <net/sock.h> | 6 | #include <net/sock.h> |
| 6 | 7 | ||
| 7 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) | 8 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) |
| @@ -39,8 +40,8 @@ struct netlink_sock { | |||
| 39 | struct mutex *cb_mutex; | 40 | struct mutex *cb_mutex; |
| 40 | struct mutex cb_def_mutex; | 41 | struct mutex cb_def_mutex; |
| 41 | void (*netlink_rcv)(struct sk_buff *skb); | 42 | void (*netlink_rcv)(struct sk_buff *skb); |
| 42 | int (*netlink_bind)(int group); | 43 | int (*netlink_bind)(struct net *net, int group); |
| 43 | void (*netlink_unbind)(int group); | 44 | void (*netlink_unbind)(struct net *net, int group); |
| 44 | struct module *module; | 45 | struct module *module; |
| 45 | #ifdef CONFIG_NETLINK_MMAP | 46 | #ifdef CONFIG_NETLINK_MMAP |
| 46 | struct mutex pg_vec_lock; | 47 | struct mutex pg_vec_lock; |
| @@ -65,8 +66,8 @@ struct netlink_table { | |||
| 65 | unsigned int groups; | 66 | unsigned int groups; |
| 66 | struct mutex *cb_mutex; | 67 | struct mutex *cb_mutex; |
| 67 | struct module *module; | 68 | struct module *module; |
| 68 | int (*bind)(int group); | 69 | int (*bind)(struct net *net, int group); |
| 69 | void (*unbind)(int group); | 70 | void (*unbind)(struct net *net, int group); |
| 70 | bool (*compare)(struct net *net, struct sock *sock); | 71 | bool (*compare)(struct net *net, struct sock *sock); |
| 71 | int registered; | 72 | int registered; |
| 72 | }; | 73 | }; |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 76393f2f4b22..ee57459fc258 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
| @@ -23,6 +23,9 @@ | |||
| 23 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ | 23 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ |
| 24 | static DECLARE_RWSEM(cb_lock); | 24 | static DECLARE_RWSEM(cb_lock); |
| 25 | 25 | ||
| 26 | atomic_t genl_sk_destructing_cnt = ATOMIC_INIT(0); | ||
| 27 | DECLARE_WAIT_QUEUE_HEAD(genl_sk_destructing_waitq); | ||
| 28 | |||
| 26 | void genl_lock(void) | 29 | void genl_lock(void) |
| 27 | { | 30 | { |
| 28 | mutex_lock(&genl_mutex); | 31 | mutex_lock(&genl_mutex); |
| @@ -435,15 +438,18 @@ int genl_unregister_family(struct genl_family *family) | |||
| 435 | 438 | ||
| 436 | genl_lock_all(); | 439 | genl_lock_all(); |
| 437 | 440 | ||
| 438 | genl_unregister_mc_groups(family); | ||
| 439 | |||
| 440 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { | 441 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { |
| 441 | if (family->id != rc->id || strcmp(rc->name, family->name)) | 442 | if (family->id != rc->id || strcmp(rc->name, family->name)) |
| 442 | continue; | 443 | continue; |
| 443 | 444 | ||
| 445 | genl_unregister_mc_groups(family); | ||
| 446 | |||
| 444 | list_del(&rc->family_list); | 447 | list_del(&rc->family_list); |
| 445 | family->n_ops = 0; | 448 | family->n_ops = 0; |
| 446 | genl_unlock_all(); | 449 | up_write(&cb_lock); |
| 450 | wait_event(genl_sk_destructing_waitq, | ||
| 451 | atomic_read(&genl_sk_destructing_cnt) == 0); | ||
| 452 | genl_unlock(); | ||
| 447 | 453 | ||
| 448 | kfree(family->attrbuf); | 454 | kfree(family->attrbuf); |
| 449 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0); | 455 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0); |
| @@ -983,11 +989,63 @@ static struct genl_multicast_group genl_ctrl_groups[] = { | |||
| 983 | { .name = "notify", }, | 989 | { .name = "notify", }, |
| 984 | }; | 990 | }; |
| 985 | 991 | ||
| 992 | static int genl_bind(struct net *net, int group) | ||
| 993 | { | ||
| 994 | int i, err = -ENOENT; | ||
| 995 | |||
| 996 | down_read(&cb_lock); | ||
| 997 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | ||
| 998 | struct genl_family *f; | ||
| 999 | |||
| 1000 | list_for_each_entry(f, genl_family_chain(i), family_list) { | ||
| 1001 | if (group >= f->mcgrp_offset && | ||
| 1002 | group < f->mcgrp_offset + f->n_mcgrps) { | ||
| 1003 | int fam_grp = group - f->mcgrp_offset; | ||
| 1004 | |||
| 1005 | if (!f->netnsok && net != &init_net) | ||
| 1006 | err = -ENOENT; | ||
| 1007 | else if (f->mcast_bind) | ||
| 1008 | err = f->mcast_bind(net, fam_grp); | ||
| 1009 | else | ||
| 1010 | err = 0; | ||
| 1011 | break; | ||
| 1012 | } | ||
| 1013 | } | ||
| 1014 | } | ||
| 1015 | up_read(&cb_lock); | ||
| 1016 | |||
| 1017 | return err; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | static void genl_unbind(struct net *net, int group) | ||
| 1021 | { | ||
| 1022 | int i; | ||
| 1023 | |||
| 1024 | down_read(&cb_lock); | ||
| 1025 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | ||
| 1026 | struct genl_family *f; | ||
| 1027 | |||
| 1028 | list_for_each_entry(f, genl_family_chain(i), family_list) { | ||
| 1029 | if (group >= f->mcgrp_offset && | ||
| 1030 | group < f->mcgrp_offset + f->n_mcgrps) { | ||
| 1031 | int fam_grp = group - f->mcgrp_offset; | ||
| 1032 | |||
| 1033 | if (f->mcast_unbind) | ||
| 1034 | f->mcast_unbind(net, fam_grp); | ||
| 1035 | break; | ||
| 1036 | } | ||
| 1037 | } | ||
| 1038 | } | ||
| 1039 | up_read(&cb_lock); | ||
| 1040 | } | ||
| 1041 | |||
| 986 | static int __net_init genl_pernet_init(struct net *net) | 1042 | static int __net_init genl_pernet_init(struct net *net) |
| 987 | { | 1043 | { |
| 988 | struct netlink_kernel_cfg cfg = { | 1044 | struct netlink_kernel_cfg cfg = { |
| 989 | .input = genl_rcv, | 1045 | .input = genl_rcv, |
| 990 | .flags = NL_CFG_F_NONROOT_RECV, | 1046 | .flags = NL_CFG_F_NONROOT_RECV, |
| 1047 | .bind = genl_bind, | ||
| 1048 | .unbind = genl_unbind, | ||
| 991 | }; | 1049 | }; |
| 992 | 1050 | ||
| 993 | /* we'll bump the group number right afterwards */ | 1051 | /* we'll bump the group number right afterwards */ |
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 764fdc39c63b..770064c83711 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
| @@ -147,7 +147,8 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, | |||
| 147 | hdr = eth_hdr(skb); | 147 | hdr = eth_hdr(skb); |
| 148 | hdr->h_proto = mpls->mpls_ethertype; | 148 | hdr->h_proto = mpls->mpls_ethertype; |
| 149 | 149 | ||
| 150 | skb_set_inner_protocol(skb, skb->protocol); | 150 | if (!skb->inner_protocol) |
| 151 | skb_set_inner_protocol(skb, skb->protocol); | ||
| 151 | skb->protocol = mpls->mpls_ethertype; | 152 | skb->protocol = mpls->mpls_ethertype; |
| 152 | 153 | ||
| 153 | invalidate_flow_key(key); | 154 | invalidate_flow_key(key); |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 332b5a031739..b07349e82d78 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -83,8 +83,7 @@ static bool ovs_must_notify(struct genl_family *family, struct genl_info *info, | |||
| 83 | unsigned int group) | 83 | unsigned int group) |
| 84 | { | 84 | { |
| 85 | return info->nlhdr->nlmsg_flags & NLM_F_ECHO || | 85 | return info->nlhdr->nlmsg_flags & NLM_F_ECHO || |
| 86 | genl_has_listeners(family, genl_info_net(info)->genl_sock, | 86 | genl_has_listeners(family, genl_info_net(info), group); |
| 87 | group); | ||
| 88 | } | 87 | } |
| 89 | 88 | ||
| 90 | static void ovs_notify(struct genl_family *family, | 89 | static void ovs_notify(struct genl_family *family, |
| @@ -525,7 +524,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) | |||
| 525 | struct vport *input_vport; | 524 | struct vport *input_vport; |
| 526 | int len; | 525 | int len; |
| 527 | int err; | 526 | int err; |
| 528 | bool log = !a[OVS_FLOW_ATTR_PROBE]; | 527 | bool log = !a[OVS_PACKET_ATTR_PROBE]; |
| 529 | 528 | ||
| 530 | err = -EINVAL; | 529 | err = -EINVAL; |
| 531 | if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] || | 530 | if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] || |
| @@ -611,6 +610,7 @@ static const struct nla_policy packet_policy[OVS_PACKET_ATTR_MAX + 1] = { | |||
| 611 | [OVS_PACKET_ATTR_PACKET] = { .len = ETH_HLEN }, | 610 | [OVS_PACKET_ATTR_PACKET] = { .len = ETH_HLEN }, |
| 612 | [OVS_PACKET_ATTR_KEY] = { .type = NLA_NESTED }, | 611 | [OVS_PACKET_ATTR_KEY] = { .type = NLA_NESTED }, |
| 613 | [OVS_PACKET_ATTR_ACTIONS] = { .type = NLA_NESTED }, | 612 | [OVS_PACKET_ATTR_ACTIONS] = { .type = NLA_NESTED }, |
| 613 | [OVS_PACKET_ATTR_PROBE] = { .type = NLA_FLAG }, | ||
| 614 | }; | 614 | }; |
| 615 | 615 | ||
| 616 | static const struct genl_ops dp_packet_genl_ops[] = { | 616 | static const struct genl_ops dp_packet_genl_ops[] = { |
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 70bef2ab7f2b..da2fae0873a5 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
| @@ -70,6 +70,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags, | |||
| 70 | { | 70 | { |
| 71 | struct flow_stats *stats; | 71 | struct flow_stats *stats; |
| 72 | int node = numa_node_id(); | 72 | int node = numa_node_id(); |
| 73 | int len = skb->len + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); | ||
| 73 | 74 | ||
| 74 | stats = rcu_dereference(flow->stats[node]); | 75 | stats = rcu_dereference(flow->stats[node]); |
| 75 | 76 | ||
| @@ -105,7 +106,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags, | |||
| 105 | if (likely(new_stats)) { | 106 | if (likely(new_stats)) { |
| 106 | new_stats->used = jiffies; | 107 | new_stats->used = jiffies; |
| 107 | new_stats->packet_count = 1; | 108 | new_stats->packet_count = 1; |
| 108 | new_stats->byte_count = skb->len; | 109 | new_stats->byte_count = len; |
| 109 | new_stats->tcp_flags = tcp_flags; | 110 | new_stats->tcp_flags = tcp_flags; |
| 110 | spin_lock_init(&new_stats->lock); | 111 | spin_lock_init(&new_stats->lock); |
| 111 | 112 | ||
| @@ -120,7 +121,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags, | |||
| 120 | 121 | ||
| 121 | stats->used = jiffies; | 122 | stats->used = jiffies; |
| 122 | stats->packet_count++; | 123 | stats->packet_count++; |
| 123 | stats->byte_count += skb->len; | 124 | stats->byte_count += len; |
| 124 | stats->tcp_flags |= tcp_flags; | 125 | stats->tcp_flags |= tcp_flags; |
| 125 | unlock: | 126 | unlock: |
| 126 | spin_unlock(&stats->lock); | 127 | spin_unlock(&stats->lock); |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 9645a21d9eaa..d1eecf707613 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
| @@ -1753,7 +1753,6 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr, | |||
| 1753 | __be16 eth_type, __be16 vlan_tci, bool log) | 1753 | __be16 eth_type, __be16 vlan_tci, bool log) |
| 1754 | { | 1754 | { |
| 1755 | const struct nlattr *a; | 1755 | const struct nlattr *a; |
| 1756 | bool out_tnl_port = false; | ||
| 1757 | int rem, err; | 1756 | int rem, err; |
| 1758 | 1757 | ||
| 1759 | if (depth >= SAMPLE_ACTION_DEPTH) | 1758 | if (depth >= SAMPLE_ACTION_DEPTH) |
| @@ -1796,8 +1795,6 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr, | |||
| 1796 | case OVS_ACTION_ATTR_OUTPUT: | 1795 | case OVS_ACTION_ATTR_OUTPUT: |
| 1797 | if (nla_get_u32(a) >= DP_MAX_PORTS) | 1796 | if (nla_get_u32(a) >= DP_MAX_PORTS) |
| 1798 | return -EINVAL; | 1797 | return -EINVAL; |
| 1799 | out_tnl_port = false; | ||
| 1800 | |||
| 1801 | break; | 1798 | break; |
| 1802 | 1799 | ||
| 1803 | case OVS_ACTION_ATTR_HASH: { | 1800 | case OVS_ACTION_ATTR_HASH: { |
| @@ -1832,12 +1829,6 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr, | |||
| 1832 | case OVS_ACTION_ATTR_PUSH_MPLS: { | 1829 | case OVS_ACTION_ATTR_PUSH_MPLS: { |
| 1833 | const struct ovs_action_push_mpls *mpls = nla_data(a); | 1830 | const struct ovs_action_push_mpls *mpls = nla_data(a); |
| 1834 | 1831 | ||
| 1835 | /* Networking stack do not allow simultaneous Tunnel | ||
| 1836 | * and MPLS GSO. | ||
| 1837 | */ | ||
| 1838 | if (out_tnl_port) | ||
| 1839 | return -EINVAL; | ||
| 1840 | |||
| 1841 | if (!eth_p_mpls(mpls->mpls_ethertype)) | 1832 | if (!eth_p_mpls(mpls->mpls_ethertype)) |
| 1842 | return -EINVAL; | 1833 | return -EINVAL; |
| 1843 | /* Prohibit push MPLS other than to a white list | 1834 | /* Prohibit push MPLS other than to a white list |
| @@ -1873,11 +1864,9 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr, | |||
| 1873 | 1864 | ||
| 1874 | case OVS_ACTION_ATTR_SET: | 1865 | case OVS_ACTION_ATTR_SET: |
| 1875 | err = validate_set(a, key, sfa, | 1866 | err = validate_set(a, key, sfa, |
| 1876 | &out_tnl_port, eth_type, log); | 1867 | &skip_copy, eth_type, log); |
| 1877 | if (err) | 1868 | if (err) |
| 1878 | return err; | 1869 | return err; |
| 1879 | |||
| 1880 | skip_copy = out_tnl_port; | ||
| 1881 | break; | 1870 | break; |
| 1882 | 1871 | ||
| 1883 | case OVS_ACTION_ATTR_SAMPLE: | 1872 | case OVS_ACTION_ATTR_SAMPLE: |
diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c index 347fa2325b22..484864dd0e68 100644 --- a/net/openvswitch/vport-geneve.c +++ b/net/openvswitch/vport-geneve.c | |||
| @@ -219,7 +219,10 @@ static int geneve_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 219 | false); | 219 | false); |
| 220 | if (err < 0) | 220 | if (err < 0) |
| 221 | ip_rt_put(rt); | 221 | ip_rt_put(rt); |
| 222 | return err; | ||
| 223 | |||
| 222 | error: | 224 | error: |
| 225 | kfree_skb(skb); | ||
| 223 | return err; | 226 | return err; |
| 224 | } | 227 | } |
| 225 | 228 | ||
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index 6b69df545b1d..d4168c442db5 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c | |||
| @@ -73,7 +73,7 @@ static struct sk_buff *__build_header(struct sk_buff *skb, | |||
| 73 | 73 | ||
| 74 | skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM)); | 74 | skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM)); |
| 75 | if (IS_ERR(skb)) | 75 | if (IS_ERR(skb)) |
| 76 | return NULL; | 76 | return skb; |
| 77 | 77 | ||
| 78 | tpi.flags = filter_tnl_flags(tun_key->tun_flags); | 78 | tpi.flags = filter_tnl_flags(tun_key->tun_flags); |
| 79 | tpi.proto = htons(ETH_P_TEB); | 79 | tpi.proto = htons(ETH_P_TEB); |
| @@ -144,7 +144,7 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 144 | 144 | ||
| 145 | if (unlikely(!OVS_CB(skb)->egress_tun_info)) { | 145 | if (unlikely(!OVS_CB(skb)->egress_tun_info)) { |
| 146 | err = -EINVAL; | 146 | err = -EINVAL; |
| 147 | goto error; | 147 | goto err_free_skb; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | tun_key = &OVS_CB(skb)->egress_tun_info->tunnel; | 150 | tun_key = &OVS_CB(skb)->egress_tun_info->tunnel; |
| @@ -157,8 +157,10 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 157 | fl.flowi4_proto = IPPROTO_GRE; | 157 | fl.flowi4_proto = IPPROTO_GRE; |
| 158 | 158 | ||
| 159 | rt = ip_route_output_key(net, &fl); | 159 | rt = ip_route_output_key(net, &fl); |
| 160 | if (IS_ERR(rt)) | 160 | if (IS_ERR(rt)) { |
| 161 | return PTR_ERR(rt); | 161 | err = PTR_ERR(rt); |
| 162 | goto err_free_skb; | ||
| 163 | } | ||
| 162 | 164 | ||
| 163 | tunnel_hlen = ip_gre_calc_hlen(tun_key->tun_flags); | 165 | tunnel_hlen = ip_gre_calc_hlen(tun_key->tun_flags); |
| 164 | 166 | ||
| @@ -183,8 +185,9 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 183 | 185 | ||
| 184 | /* Push Tunnel header. */ | 186 | /* Push Tunnel header. */ |
| 185 | skb = __build_header(skb, tunnel_hlen); | 187 | skb = __build_header(skb, tunnel_hlen); |
| 186 | if (unlikely(!skb)) { | 188 | if (IS_ERR(skb)) { |
| 187 | err = 0; | 189 | err = PTR_ERR(skb); |
| 190 | skb = NULL; | ||
| 188 | goto err_free_rt; | 191 | goto err_free_rt; |
| 189 | } | 192 | } |
| 190 | 193 | ||
| @@ -198,7 +201,8 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 198 | tun_key->ipv4_tos, tun_key->ipv4_ttl, df, false); | 201 | tun_key->ipv4_tos, tun_key->ipv4_ttl, df, false); |
| 199 | err_free_rt: | 202 | err_free_rt: |
| 200 | ip_rt_put(rt); | 203 | ip_rt_put(rt); |
| 201 | error: | 204 | err_free_skb: |
| 205 | kfree_skb(skb); | ||
| 202 | return err; | 206 | return err; |
| 203 | } | 207 | } |
| 204 | 208 | ||
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index 38f95a52241b..d7c46b301024 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c | |||
| @@ -187,7 +187,9 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 187 | false); | 187 | false); |
| 188 | if (err < 0) | 188 | if (err < 0) |
| 189 | ip_rt_put(rt); | 189 | ip_rt_put(rt); |
| 190 | return err; | ||
| 190 | error: | 191 | error: |
| 192 | kfree_skb(skb); | ||
| 191 | return err; | 193 | return err; |
| 192 | } | 194 | } |
| 193 | 195 | ||
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 9584526c0778..2034c6d9cb5a 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c | |||
| @@ -480,7 +480,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb, | |||
| 480 | stats = this_cpu_ptr(vport->percpu_stats); | 480 | stats = this_cpu_ptr(vport->percpu_stats); |
| 481 | u64_stats_update_begin(&stats->syncp); | 481 | u64_stats_update_begin(&stats->syncp); |
| 482 | stats->rx_packets++; | 482 | stats->rx_packets++; |
| 483 | stats->rx_bytes += skb->len; | 483 | stats->rx_bytes += skb->len + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); |
| 484 | u64_stats_update_end(&stats->syncp); | 484 | u64_stats_update_end(&stats->syncp); |
| 485 | 485 | ||
| 486 | OVS_CB(skb)->input_vport = vport; | 486 | OVS_CB(skb)->input_vport = vport; |
| @@ -519,10 +519,9 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb) | |||
| 519 | u64_stats_update_end(&stats->syncp); | 519 | u64_stats_update_end(&stats->syncp); |
| 520 | } else if (sent < 0) { | 520 | } else if (sent < 0) { |
| 521 | ovs_vport_record_error(vport, VPORT_E_TX_ERROR); | 521 | ovs_vport_record_error(vport, VPORT_E_TX_ERROR); |
| 522 | kfree_skb(skb); | 522 | } else { |
| 523 | } else | ||
| 524 | ovs_vport_record_error(vport, VPORT_E_TX_DROPPED); | 523 | ovs_vport_record_error(vport, VPORT_E_TX_DROPPED); |
| 525 | 524 | } | |
| 526 | return sent; | 525 | return sent; |
| 527 | } | 526 | } |
| 528 | 527 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e52a44785681..9cfe2e1dd8b5 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -785,6 +785,7 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1, | |||
| 785 | 785 | ||
| 786 | struct tpacket3_hdr *last_pkt; | 786 | struct tpacket3_hdr *last_pkt; |
| 787 | struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1; | 787 | struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1; |
| 788 | struct sock *sk = &po->sk; | ||
| 788 | 789 | ||
| 789 | if (po->stats.stats3.tp_drops) | 790 | if (po->stats.stats3.tp_drops) |
| 790 | status |= TP_STATUS_LOSING; | 791 | status |= TP_STATUS_LOSING; |
| @@ -809,6 +810,8 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1, | |||
| 809 | /* Flush the block */ | 810 | /* Flush the block */ |
| 810 | prb_flush_block(pkc1, pbd1, status); | 811 | prb_flush_block(pkc1, pbd1, status); |
| 811 | 812 | ||
| 813 | sk->sk_data_ready(sk); | ||
| 814 | |||
| 812 | pkc1->kactive_blk_num = GET_NEXT_PRB_BLK_NUM(pkc1); | 815 | pkc1->kactive_blk_num = GET_NEXT_PRB_BLK_NUM(pkc1); |
| 813 | } | 816 | } |
| 814 | 817 | ||
| @@ -2052,12 +2055,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 2052 | smp_wmb(); | 2055 | smp_wmb(); |
| 2053 | #endif | 2056 | #endif |
| 2054 | 2057 | ||
| 2055 | if (po->tp_version <= TPACKET_V2) | 2058 | if (po->tp_version <= TPACKET_V2) { |
| 2056 | __packet_set_status(po, h.raw, status); | 2059 | __packet_set_status(po, h.raw, status); |
| 2057 | else | 2060 | sk->sk_data_ready(sk); |
| 2061 | } else { | ||
| 2058 | prb_clear_blk_fill_status(&po->rx_ring); | 2062 | prb_clear_blk_fill_status(&po->rx_ring); |
| 2059 | 2063 | } | |
| 2060 | sk->sk_data_ready(sk); | ||
| 2061 | 2064 | ||
| 2062 | drop_n_restore: | 2065 | drop_n_restore: |
| 2063 | if (skb_head != skb->data && skb_shared(skb)) { | 2066 | if (skb_head != skb->data && skb_shared(skb)) { |
| @@ -2514,7 +2517,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
| 2514 | err = -EINVAL; | 2517 | err = -EINVAL; |
| 2515 | if (sock->type == SOCK_DGRAM) { | 2518 | if (sock->type == SOCK_DGRAM) { |
| 2516 | offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len); | 2519 | offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len); |
| 2517 | if (unlikely(offset) < 0) | 2520 | if (unlikely(offset < 0)) |
| 2518 | goto out_free; | 2521 | goto out_free; |
| 2519 | } else { | 2522 | } else { |
| 2520 | if (ll_header_truncated(dev, len)) | 2523 | if (ll_header_truncated(dev, len)) |
diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c index c3b0cd43eb56..c173f69e1479 100644 --- a/net/rds/sysctl.c +++ b/net/rds/sysctl.c | |||
| @@ -71,14 +71,14 @@ static struct ctl_table rds_sysctl_rds_table[] = { | |||
| 71 | { | 71 | { |
| 72 | .procname = "max_unacked_packets", | 72 | .procname = "max_unacked_packets", |
| 73 | .data = &rds_sysctl_max_unacked_packets, | 73 | .data = &rds_sysctl_max_unacked_packets, |
| 74 | .maxlen = sizeof(unsigned long), | 74 | .maxlen = sizeof(int), |
| 75 | .mode = 0644, | 75 | .mode = 0644, |
| 76 | .proc_handler = proc_dointvec, | 76 | .proc_handler = proc_dointvec, |
| 77 | }, | 77 | }, |
| 78 | { | 78 | { |
| 79 | .procname = "max_unacked_bytes", | 79 | .procname = "max_unacked_bytes", |
| 80 | .data = &rds_sysctl_max_unacked_bytes, | 80 | .data = &rds_sysctl_max_unacked_bytes, |
| 81 | .maxlen = sizeof(unsigned long), | 81 | .maxlen = sizeof(int), |
| 82 | .mode = 0644, | 82 | .mode = 0644, |
| 83 | .proc_handler = proc_dointvec, | 83 | .proc_handler = proc_dointvec, |
| 84 | }, | 84 | }, |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index aad6a679fb13..baef987fe2c0 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
| @@ -556,8 +556,9 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, | |||
| 556 | } | 556 | } |
| 557 | EXPORT_SYMBOL(tcf_exts_change); | 557 | EXPORT_SYMBOL(tcf_exts_change); |
| 558 | 558 | ||
| 559 | #define tcf_exts_first_act(ext) \ | 559 | #define tcf_exts_first_act(ext) \ |
| 560 | list_first_entry(&(exts)->actions, struct tc_action, list) | 560 | list_first_entry_or_null(&(exts)->actions, \ |
| 561 | struct tc_action, list) | ||
| 561 | 562 | ||
| 562 | int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts) | 563 | int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts) |
| 563 | { | 564 | { |
| @@ -603,7 +604,7 @@ int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts) | |||
| 603 | { | 604 | { |
| 604 | #ifdef CONFIG_NET_CLS_ACT | 605 | #ifdef CONFIG_NET_CLS_ACT |
| 605 | struct tc_action *a = tcf_exts_first_act(exts); | 606 | struct tc_action *a = tcf_exts_first_act(exts); |
| 606 | if (tcf_action_copy_stats(skb, a, 1) < 0) | 607 | if (a != NULL && tcf_action_copy_stats(skb, a, 1) < 0) |
| 607 | return -1; | 608 | return -1; |
| 608 | #endif | 609 | #endif |
| 609 | return 0; | 610 | return 0; |
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 84c8219c3e1c..f59adf8a4cd7 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
| @@ -180,6 +180,11 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, | |||
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | bpf_size = bpf_len * sizeof(*bpf_ops); | 182 | bpf_size = bpf_len * sizeof(*bpf_ops); |
| 183 | if (bpf_size != nla_len(tb[TCA_BPF_OPS])) { | ||
| 184 | ret = -EINVAL; | ||
| 185 | goto errout; | ||
| 186 | } | ||
| 187 | |||
| 183 | bpf_ops = kzalloc(bpf_size, GFP_KERNEL); | 188 | bpf_ops = kzalloc(bpf_size, GFP_KERNEL); |
| 184 | if (bpf_ops == NULL) { | 189 | if (bpf_ops == NULL) { |
| 185 | ret = -ENOMEM; | 190 | ret = -ENOMEM; |
| @@ -215,15 +220,21 @@ static u32 cls_bpf_grab_new_handle(struct tcf_proto *tp, | |||
| 215 | struct cls_bpf_head *head) | 220 | struct cls_bpf_head *head) |
| 216 | { | 221 | { |
| 217 | unsigned int i = 0x80000000; | 222 | unsigned int i = 0x80000000; |
| 223 | u32 handle; | ||
| 218 | 224 | ||
| 219 | do { | 225 | do { |
| 220 | if (++head->hgen == 0x7FFFFFFF) | 226 | if (++head->hgen == 0x7FFFFFFF) |
| 221 | head->hgen = 1; | 227 | head->hgen = 1; |
| 222 | } while (--i > 0 && cls_bpf_get(tp, head->hgen)); | 228 | } while (--i > 0 && cls_bpf_get(tp, head->hgen)); |
| 223 | if (i == 0) | 229 | |
| 230 | if (unlikely(i == 0)) { | ||
| 224 | pr_err("Insufficient number of handles\n"); | 231 | pr_err("Insufficient number of handles\n"); |
| 232 | handle = 0; | ||
| 233 | } else { | ||
| 234 | handle = head->hgen; | ||
| 235 | } | ||
| 225 | 236 | ||
| 226 | return i; | 237 | return handle; |
| 227 | } | 238 | } |
| 228 | 239 | ||
| 229 | static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, | 240 | static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, |
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 9b05924cc386..333cd94ba381 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
| @@ -670,8 +670,14 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 670 | if (tb[TCA_FQ_FLOW_PLIMIT]) | 670 | if (tb[TCA_FQ_FLOW_PLIMIT]) |
| 671 | q->flow_plimit = nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]); | 671 | q->flow_plimit = nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]); |
| 672 | 672 | ||
| 673 | if (tb[TCA_FQ_QUANTUM]) | 673 | if (tb[TCA_FQ_QUANTUM]) { |
| 674 | q->quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]); | 674 | u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]); |
| 675 | |||
| 676 | if (quantum > 0) | ||
| 677 | q->quantum = quantum; | ||
| 678 | else | ||
| 679 | err = -EINVAL; | ||
| 680 | } | ||
| 675 | 681 | ||
| 676 | if (tb[TCA_FQ_INITIAL_QUANTUM]) | 682 | if (tb[TCA_FQ_INITIAL_QUANTUM]) |
| 677 | q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]); | 683 | q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]); |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index f791edd64d6c..26d06dbcc1c8 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -1182,7 +1182,6 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
| 1182 | asoc->peer.peer_hmacs = new->peer.peer_hmacs; | 1182 | asoc->peer.peer_hmacs = new->peer.peer_hmacs; |
| 1183 | new->peer.peer_hmacs = NULL; | 1183 | new->peer.peer_hmacs = NULL; |
| 1184 | 1184 | ||
| 1185 | sctp_auth_key_put(asoc->asoc_shared_key); | ||
| 1186 | sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); | 1185 | sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); |
| 1187 | } | 1186 | } |
| 1188 | 1187 | ||
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index e49e231cef52..06320c8c1c86 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -2608,7 +2608,7 @@ do_addr_param: | |||
| 2608 | 2608 | ||
| 2609 | addr_param = param.v + sizeof(sctp_addip_param_t); | 2609 | addr_param = param.v + sizeof(sctp_addip_param_t); |
| 2610 | 2610 | ||
| 2611 | af = sctp_get_af_specific(param_type2af(param.p->type)); | 2611 | af = sctp_get_af_specific(param_type2af(addr_param->p.type)); |
| 2612 | if (af == NULL) | 2612 | if (af == NULL) |
| 2613 | break; | 2613 | break; |
| 2614 | 2614 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 2625eccb77d5..aafe94bf292e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -1603,7 +1603,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1603 | sctp_assoc_t associd = 0; | 1603 | sctp_assoc_t associd = 0; |
| 1604 | sctp_cmsgs_t cmsgs = { NULL }; | 1604 | sctp_cmsgs_t cmsgs = { NULL }; |
| 1605 | sctp_scope_t scope; | 1605 | sctp_scope_t scope; |
| 1606 | bool fill_sinfo_ttl = false; | 1606 | bool fill_sinfo_ttl = false, wait_connect = false; |
| 1607 | struct sctp_datamsg *datamsg; | 1607 | struct sctp_datamsg *datamsg; |
| 1608 | int msg_flags = msg->msg_flags; | 1608 | int msg_flags = msg->msg_flags; |
| 1609 | __u16 sinfo_flags = 0; | 1609 | __u16 sinfo_flags = 0; |
| @@ -1943,6 +1943,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1943 | if (err < 0) | 1943 | if (err < 0) |
| 1944 | goto out_free; | 1944 | goto out_free; |
| 1945 | 1945 | ||
| 1946 | wait_connect = true; | ||
| 1946 | pr_debug("%s: we associated primitively\n", __func__); | 1947 | pr_debug("%s: we associated primitively\n", __func__); |
| 1947 | } | 1948 | } |
| 1948 | 1949 | ||
| @@ -1980,6 +1981,11 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1980 | sctp_datamsg_put(datamsg); | 1981 | sctp_datamsg_put(datamsg); |
| 1981 | err = msg_len; | 1982 | err = msg_len; |
| 1982 | 1983 | ||
| 1984 | if (unlikely(wait_connect)) { | ||
| 1985 | timeo = sock_sndtimeo(sk, msg_flags & MSG_DONTWAIT); | ||
| 1986 | sctp_wait_for_connect(asoc, &timeo); | ||
| 1987 | } | ||
| 1988 | |||
| 1983 | /* If we are already past ASSOCIATE, the lower | 1989 | /* If we are already past ASSOCIATE, the lower |
| 1984 | * layers are responsible for association cleanup. | 1990 | * layers are responsible for association cleanup. |
| 1985 | */ | 1991 | */ |
diff --git a/net/socket.c b/net/socket.c index a2c33a4dc7ba..418795caa897 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -869,9 +869,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, | |||
| 869 | static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, | 869 | static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, |
| 870 | struct sock_iocb *siocb) | 870 | struct sock_iocb *siocb) |
| 871 | { | 871 | { |
| 872 | if (!is_sync_kiocb(iocb)) | ||
| 873 | BUG(); | ||
| 874 | |||
| 875 | siocb->kiocb = iocb; | 872 | siocb->kiocb = iocb; |
| 876 | iocb->private = siocb; | 873 | iocb->private = siocb; |
| 877 | return siocb; | 874 | return siocb; |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 1cb61242e55e..4439ac4c1b53 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
| @@ -606,7 +606,7 @@ void xdr_truncate_encode(struct xdr_stream *xdr, size_t len) | |||
| 606 | struct kvec *head = buf->head; | 606 | struct kvec *head = buf->head; |
| 607 | struct kvec *tail = buf->tail; | 607 | struct kvec *tail = buf->tail; |
| 608 | int fraglen; | 608 | int fraglen; |
| 609 | int new, old; | 609 | int new; |
| 610 | 610 | ||
| 611 | if (len > buf->len) { | 611 | if (len > buf->len) { |
| 612 | WARN_ON_ONCE(1); | 612 | WARN_ON_ONCE(1); |
| @@ -629,8 +629,8 @@ void xdr_truncate_encode(struct xdr_stream *xdr, size_t len) | |||
| 629 | buf->len -= fraglen; | 629 | buf->len -= fraglen; |
| 630 | 630 | ||
| 631 | new = buf->page_base + buf->page_len; | 631 | new = buf->page_base + buf->page_len; |
| 632 | old = new + fraglen; | 632 | |
| 633 | xdr->page_ptr -= (old >> PAGE_SHIFT) - (new >> PAGE_SHIFT); | 633 | xdr->page_ptr = buf->pages + (new >> PAGE_SHIFT); |
| 634 | 634 | ||
| 635 | if (buf->page_len) { | 635 | if (buf->page_len) { |
| 636 | xdr->p = page_address(*xdr->page_ptr); | 636 | xdr->p = page_address(*xdr->page_ptr); |
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 96ceefeb9daf..a9e174fc0f91 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
| @@ -220,10 +220,11 @@ static void bclink_retransmit_pkt(u32 after, u32 to) | |||
| 220 | struct sk_buff *skb; | 220 | struct sk_buff *skb; |
| 221 | 221 | ||
| 222 | skb_queue_walk(&bcl->outqueue, skb) { | 222 | skb_queue_walk(&bcl->outqueue, skb) { |
| 223 | if (more(buf_seqno(skb), after)) | 223 | if (more(buf_seqno(skb), after)) { |
| 224 | tipc_link_retransmit(bcl, skb, mod(to - after)); | ||
| 224 | break; | 225 | break; |
| 226 | } | ||
| 225 | } | 227 | } |
| 226 | tipc_link_retransmit(bcl, skb, mod(to - after)); | ||
| 227 | } | 228 | } |
| 228 | 229 | ||
| 229 | /** | 230 | /** |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 22ba971741e5..29c8675f9a11 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
| @@ -175,7 +175,7 @@ config CFG80211_INTERNAL_REGDB | |||
| 175 | Most distributions have a CRDA package. So if unsure, say N. | 175 | Most distributions have a CRDA package. So if unsure, say N. |
| 176 | 176 | ||
| 177 | config CFG80211_WEXT | 177 | config CFG80211_WEXT |
| 178 | bool | 178 | bool "cfg80211 wireless extensions compatibility" |
| 179 | depends on CFG80211 | 179 | depends on CFG80211 |
| 180 | select WEXT_CORE | 180 | select WEXT_CORE |
| 181 | help | 181 | help |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7ca4b5133123..8887c6e5fca8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -2854,6 +2854,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
| 2854 | if (!rdev->ops->get_key) | 2854 | if (!rdev->ops->get_key) |
| 2855 | return -EOPNOTSUPP; | 2855 | return -EOPNOTSUPP; |
| 2856 | 2856 | ||
| 2857 | if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
| 2858 | return -ENOENT; | ||
| 2859 | |||
| 2857 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 2860 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
| 2858 | if (!msg) | 2861 | if (!msg) |
| 2859 | return -ENOMEM; | 2862 | return -ENOMEM; |
| @@ -2873,10 +2876,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
| 2873 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) | 2876 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) |
| 2874 | goto nla_put_failure; | 2877 | goto nla_put_failure; |
| 2875 | 2878 | ||
| 2876 | if (pairwise && mac_addr && | ||
| 2877 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
| 2878 | return -ENOENT; | ||
| 2879 | |||
| 2880 | err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, | 2879 | err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, |
| 2881 | get_key_callback); | 2880 | get_key_callback); |
| 2882 | 2881 | ||
| @@ -3047,7 +3046,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
| 3047 | wdev_lock(dev->ieee80211_ptr); | 3046 | wdev_lock(dev->ieee80211_ptr); |
| 3048 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 3047 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
| 3049 | 3048 | ||
| 3050 | if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr && | 3049 | if (key.type == NL80211_KEYTYPE_GROUP && mac_addr && |
| 3051 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | 3050 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) |
| 3052 | err = -ENOENT; | 3051 | err = -ENOENT; |
| 3053 | 3052 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7b8309840d4e..d39d1cbc86b1 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -1530,45 +1530,40 @@ static void reg_call_notifier(struct wiphy *wiphy, | |||
| 1530 | 1530 | ||
| 1531 | static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) | 1531 | static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) |
| 1532 | { | 1532 | { |
| 1533 | struct ieee80211_channel *ch; | ||
| 1534 | struct cfg80211_chan_def chandef; | 1533 | struct cfg80211_chan_def chandef; |
| 1535 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | 1534 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
| 1536 | bool ret = true; | 1535 | enum nl80211_iftype iftype; |
| 1537 | 1536 | ||
| 1538 | wdev_lock(wdev); | 1537 | wdev_lock(wdev); |
| 1538 | iftype = wdev->iftype; | ||
| 1539 | 1539 | ||
| 1540 | /* make sure the interface is active */ | ||
| 1540 | if (!wdev->netdev || !netif_running(wdev->netdev)) | 1541 | if (!wdev->netdev || !netif_running(wdev->netdev)) |
| 1541 | goto out; | 1542 | goto wdev_inactive_unlock; |
| 1542 | 1543 | ||
| 1543 | switch (wdev->iftype) { | 1544 | switch (iftype) { |
| 1544 | case NL80211_IFTYPE_AP: | 1545 | case NL80211_IFTYPE_AP: |
| 1545 | case NL80211_IFTYPE_P2P_GO: | 1546 | case NL80211_IFTYPE_P2P_GO: |
| 1546 | if (!wdev->beacon_interval) | 1547 | if (!wdev->beacon_interval) |
| 1547 | goto out; | 1548 | goto wdev_inactive_unlock; |
| 1548 | 1549 | chandef = wdev->chandef; | |
| 1549 | ret = cfg80211_reg_can_beacon(wiphy, | ||
| 1550 | &wdev->chandef, wdev->iftype); | ||
| 1551 | break; | 1550 | break; |
| 1552 | case NL80211_IFTYPE_ADHOC: | 1551 | case NL80211_IFTYPE_ADHOC: |
| 1553 | if (!wdev->ssid_len) | 1552 | if (!wdev->ssid_len) |
| 1554 | goto out; | 1553 | goto wdev_inactive_unlock; |
| 1555 | 1554 | chandef = wdev->chandef; | |
| 1556 | ret = cfg80211_reg_can_beacon(wiphy, | ||
| 1557 | &wdev->chandef, wdev->iftype); | ||
| 1558 | break; | 1555 | break; |
| 1559 | case NL80211_IFTYPE_STATION: | 1556 | case NL80211_IFTYPE_STATION: |
| 1560 | case NL80211_IFTYPE_P2P_CLIENT: | 1557 | case NL80211_IFTYPE_P2P_CLIENT: |
| 1561 | if (!wdev->current_bss || | 1558 | if (!wdev->current_bss || |
| 1562 | !wdev->current_bss->pub.channel) | 1559 | !wdev->current_bss->pub.channel) |
| 1563 | goto out; | 1560 | goto wdev_inactive_unlock; |
| 1564 | 1561 | ||
| 1565 | ch = wdev->current_bss->pub.channel; | 1562 | if (!rdev->ops->get_channel || |
| 1566 | if (rdev->ops->get_channel && | 1563 | rdev_get_channel(rdev, wdev, &chandef)) |
| 1567 | !rdev_get_channel(rdev, wdev, &chandef)) | 1564 | cfg80211_chandef_create(&chandef, |
| 1568 | ret = cfg80211_chandef_usable(wiphy, &chandef, | 1565 | wdev->current_bss->pub.channel, |
| 1569 | IEEE80211_CHAN_DISABLED); | 1566 | NL80211_CHAN_NO_HT); |
| 1570 | else | ||
| 1571 | ret = !(ch->flags & IEEE80211_CHAN_DISABLED); | ||
| 1572 | break; | 1567 | break; |
| 1573 | case NL80211_IFTYPE_MONITOR: | 1568 | case NL80211_IFTYPE_MONITOR: |
| 1574 | case NL80211_IFTYPE_AP_VLAN: | 1569 | case NL80211_IFTYPE_AP_VLAN: |
| @@ -1581,9 +1576,26 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
| 1581 | break; | 1576 | break; |
| 1582 | } | 1577 | } |
| 1583 | 1578 | ||
| 1584 | out: | ||
| 1585 | wdev_unlock(wdev); | 1579 | wdev_unlock(wdev); |
| 1586 | return ret; | 1580 | |
| 1581 | switch (iftype) { | ||
| 1582 | case NL80211_IFTYPE_AP: | ||
| 1583 | case NL80211_IFTYPE_P2P_GO: | ||
| 1584 | case NL80211_IFTYPE_ADHOC: | ||
| 1585 | return cfg80211_reg_can_beacon(wiphy, &chandef, iftype); | ||
| 1586 | case NL80211_IFTYPE_STATION: | ||
| 1587 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 1588 | return cfg80211_chandef_usable(wiphy, &chandef, | ||
| 1589 | IEEE80211_CHAN_DISABLED); | ||
| 1590 | default: | ||
| 1591 | break; | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | return true; | ||
| 1595 | |||
| 1596 | wdev_inactive_unlock: | ||
| 1597 | wdev_unlock(wdev); | ||
| 1598 | return true; | ||
| 1587 | } | 1599 | } |
| 1588 | 1600 | ||
| 1589 | static void reg_leave_invalid_chans(struct wiphy *wiphy) | 1601 | static void reg_leave_invalid_chans(struct wiphy *wiphy) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index d0ac795445b7..5488c3662f7d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
| @@ -308,6 +308,12 @@ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc) | |||
| 308 | goto out; | 308 | goto out; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | if (ieee80211_is_mgmt(fc)) { | ||
| 312 | if (ieee80211_has_order(fc)) | ||
| 313 | hdrlen += IEEE80211_HT_CTL_LEN; | ||
| 314 | goto out; | ||
| 315 | } | ||
| 316 | |||
| 311 | if (ieee80211_is_ctl(fc)) { | 317 | if (ieee80211_is_ctl(fc)) { |
| 312 | /* | 318 | /* |
| 313 | * ACK and CTS are 10 bytes, all others 16. To see how | 319 | * ACK and CTS are 10 bytes, all others 16. To see how |
