diff options
Diffstat (limited to 'net')
159 files changed, 1962 insertions, 1178 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index de51c48c4393..4b65aa492fb6 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -538,6 +538,9 @@ static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev | |||
| 538 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); | 538 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); |
| 539 | struct net_device *real_dev = vlan->real_dev; | 539 | struct net_device *real_dev = vlan->real_dev; |
| 540 | 540 | ||
| 541 | if (saddr == NULL) | ||
| 542 | saddr = dev->dev_addr; | ||
| 543 | |||
| 541 | return dev_hard_header(skb, real_dev, type, daddr, saddr, len); | 544 | return dev_hard_header(skb, real_dev, type, daddr, saddr, len); |
| 542 | } | 545 | } |
| 543 | 546 | ||
diff --git a/net/9p/client.c b/net/9p/client.c index a5e4d2dcb03e..9186550d77a6 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -204,7 +204,7 @@ free_and_return: | |||
| 204 | return ret; | 204 | return ret; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | struct p9_fcall *p9_fcall_alloc(int alloc_msize) | 207 | static struct p9_fcall *p9_fcall_alloc(int alloc_msize) |
| 208 | { | 208 | { |
| 209 | struct p9_fcall *fc; | 209 | struct p9_fcall *fc; |
| 210 | fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS); | 210 | fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS); |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index cd1e1ede73a4..ac2666c1d011 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
| @@ -340,7 +340,10 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, | |||
| 340 | int count = nr_pages; | 340 | int count = nr_pages; |
| 341 | while (nr_pages) { | 341 | while (nr_pages) { |
| 342 | s = rest_of_page(data); | 342 | s = rest_of_page(data); |
| 343 | pages[index++] = kmap_to_page(data); | 343 | if (is_vmalloc_addr(data)) |
| 344 | pages[index++] = vmalloc_to_page(data); | ||
| 345 | else | ||
| 346 | pages[index++] = kmap_to_page(data); | ||
| 344 | data += s; | 347 | data += s; |
| 345 | nr_pages--; | 348 | nr_pages--; |
| 346 | } | 349 | } |
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 512159bf607f..8323bced8e5b 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
| @@ -241,19 +241,19 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const uint8_t *addr) | |||
| 241 | size = bat_priv->num_ifaces * sizeof(uint8_t); | 241 | size = bat_priv->num_ifaces * sizeof(uint8_t); |
| 242 | orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC); | 242 | orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC); |
| 243 | if (!orig_node->bat_iv.bcast_own_sum) | 243 | if (!orig_node->bat_iv.bcast_own_sum) |
| 244 | goto free_bcast_own; | 244 | goto free_orig_node; |
| 245 | 245 | ||
| 246 | hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig, | 246 | hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig, |
| 247 | batadv_choose_orig, orig_node, | 247 | batadv_choose_orig, orig_node, |
| 248 | &orig_node->hash_entry); | 248 | &orig_node->hash_entry); |
| 249 | if (hash_added != 0) | 249 | if (hash_added != 0) |
| 250 | goto free_bcast_own; | 250 | goto free_orig_node; |
| 251 | 251 | ||
| 252 | return orig_node; | 252 | return orig_node; |
| 253 | 253 | ||
| 254 | free_bcast_own: | ||
| 255 | kfree(orig_node->bat_iv.bcast_own); | ||
| 256 | free_orig_node: | 254 | free_orig_node: |
| 255 | /* free twice, as batadv_orig_node_new sets refcount to 2 */ | ||
| 256 | batadv_orig_node_free_ref(orig_node); | ||
| 257 | batadv_orig_node_free_ref(orig_node); | 257 | batadv_orig_node_free_ref(orig_node); |
| 258 | 258 | ||
| 259 | return NULL; | 259 | return NULL; |
| @@ -266,7 +266,7 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, | |||
| 266 | struct batadv_orig_node *orig_neigh) | 266 | struct batadv_orig_node *orig_neigh) |
| 267 | { | 267 | { |
| 268 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 268 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
| 269 | struct batadv_neigh_node *neigh_node; | 269 | struct batadv_neigh_node *neigh_node, *tmp_neigh_node; |
| 270 | 270 | ||
| 271 | neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, orig_node); | 271 | neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, orig_node); |
| 272 | if (!neigh_node) | 272 | if (!neigh_node) |
| @@ -281,14 +281,24 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, | |||
| 281 | neigh_node->orig_node = orig_neigh; | 281 | neigh_node->orig_node = orig_neigh; |
| 282 | neigh_node->if_incoming = hard_iface; | 282 | neigh_node->if_incoming = hard_iface; |
| 283 | 283 | ||
| 284 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 285 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", | ||
| 286 | neigh_addr, orig_node->orig, hard_iface->net_dev->name); | ||
| 287 | |||
| 288 | spin_lock_bh(&orig_node->neigh_list_lock); | 284 | spin_lock_bh(&orig_node->neigh_list_lock); |
| 289 | hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); | 285 | tmp_neigh_node = batadv_neigh_node_get(orig_node, hard_iface, |
| 286 | neigh_addr); | ||
| 287 | if (!tmp_neigh_node) { | ||
| 288 | hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); | ||
| 289 | } else { | ||
| 290 | kfree(neigh_node); | ||
| 291 | batadv_hardif_free_ref(hard_iface); | ||
| 292 | neigh_node = tmp_neigh_node; | ||
| 293 | } | ||
| 290 | spin_unlock_bh(&orig_node->neigh_list_lock); | 294 | spin_unlock_bh(&orig_node->neigh_list_lock); |
| 291 | 295 | ||
| 296 | if (!tmp_neigh_node) | ||
| 297 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 298 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", | ||
| 299 | neigh_addr, orig_node->orig, | ||
| 300 | hard_iface->net_dev->name); | ||
| 301 | |||
| 292 | out: | 302 | out: |
| 293 | return neigh_node; | 303 | return neigh_node; |
| 294 | } | 304 | } |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 3d417d3641c6..b851cc580853 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
| @@ -241,7 +241,7 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface) | |||
| 241 | { | 241 | { |
| 242 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 242 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
| 243 | const struct batadv_hard_iface *hard_iface; | 243 | const struct batadv_hard_iface *hard_iface; |
| 244 | int min_mtu = ETH_DATA_LEN; | 244 | int min_mtu = INT_MAX; |
| 245 | 245 | ||
| 246 | rcu_read_lock(); | 246 | rcu_read_lock(); |
| 247 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | 247 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { |
| @@ -256,8 +256,6 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface) | |||
| 256 | } | 256 | } |
| 257 | rcu_read_unlock(); | 257 | rcu_read_unlock(); |
| 258 | 258 | ||
| 259 | atomic_set(&bat_priv->packet_size_max, min_mtu); | ||
| 260 | |||
| 261 | if (atomic_read(&bat_priv->fragmentation) == 0) | 259 | if (atomic_read(&bat_priv->fragmentation) == 0) |
| 262 | goto out; | 260 | goto out; |
| 263 | 261 | ||
| @@ -268,13 +266,21 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface) | |||
| 268 | min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE); | 266 | min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE); |
| 269 | min_mtu -= sizeof(struct batadv_frag_packet); | 267 | min_mtu -= sizeof(struct batadv_frag_packet); |
| 270 | min_mtu *= BATADV_FRAG_MAX_FRAGMENTS; | 268 | min_mtu *= BATADV_FRAG_MAX_FRAGMENTS; |
| 271 | atomic_set(&bat_priv->packet_size_max, min_mtu); | ||
| 272 | |||
| 273 | /* with fragmentation enabled we can fragment external packets easily */ | ||
| 274 | min_mtu = min_t(int, min_mtu, ETH_DATA_LEN); | ||
| 275 | 269 | ||
| 276 | out: | 270 | out: |
| 277 | return min_mtu - batadv_max_header_len(); | 271 | /* report to the other components the maximum amount of bytes that |
| 272 | * batman-adv can send over the wire (without considering the payload | ||
| 273 | * overhead). For example, this value is used by TT to compute the | ||
| 274 | * maximum local table table size | ||
| 275 | */ | ||
| 276 | atomic_set(&bat_priv->packet_size_max, min_mtu); | ||
| 277 | |||
| 278 | /* the real soft-interface MTU is computed by removing the payload | ||
| 279 | * overhead from the maximum amount of bytes that was just computed. | ||
| 280 | * | ||
| 281 | * However batman-adv does not support MTUs bigger than ETH_DATA_LEN | ||
| 282 | */ | ||
| 283 | return min_t(int, min_mtu - batadv_max_header_len(), ETH_DATA_LEN); | ||
| 278 | } | 284 | } |
| 279 | 285 | ||
| 280 | /* adjusts the MTU if a new interface with a smaller MTU appeared. */ | 286 | /* adjusts the MTU if a new interface with a smaller MTU appeared. */ |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 6df12a2e3605..853941629dc1 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
| @@ -458,6 +458,42 @@ out: | |||
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | /** | 460 | /** |
| 461 | * batadv_neigh_node_get - retrieve a neighbour from the list | ||
| 462 | * @orig_node: originator which the neighbour belongs to | ||
| 463 | * @hard_iface: the interface where this neighbour is connected to | ||
| 464 | * @addr: the address of the neighbour | ||
| 465 | * | ||
| 466 | * Looks for and possibly returns a neighbour belonging to this originator list | ||
| 467 | * which is connected through the provided hard interface. | ||
| 468 | * Returns NULL if the neighbour is not found. | ||
| 469 | */ | ||
| 470 | struct batadv_neigh_node * | ||
| 471 | batadv_neigh_node_get(const struct batadv_orig_node *orig_node, | ||
| 472 | const struct batadv_hard_iface *hard_iface, | ||
| 473 | const uint8_t *addr) | ||
| 474 | { | ||
| 475 | struct batadv_neigh_node *tmp_neigh_node, *res = NULL; | ||
| 476 | |||
| 477 | rcu_read_lock(); | ||
| 478 | hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) { | ||
| 479 | if (!batadv_compare_eth(tmp_neigh_node->addr, addr)) | ||
| 480 | continue; | ||
| 481 | |||
| 482 | if (tmp_neigh_node->if_incoming != hard_iface) | ||
| 483 | continue; | ||
| 484 | |||
| 485 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
| 486 | continue; | ||
| 487 | |||
| 488 | res = tmp_neigh_node; | ||
| 489 | break; | ||
| 490 | } | ||
| 491 | rcu_read_unlock(); | ||
| 492 | |||
| 493 | return res; | ||
| 494 | } | ||
| 495 | |||
| 496 | /** | ||
| 461 | * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object | 497 | * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object |
| 462 | * @rcu: rcu pointer of the orig_ifinfo object | 498 | * @rcu: rcu pointer of the orig_ifinfo object |
| 463 | */ | 499 | */ |
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 37be290f63f6..db3a9ed734cb 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
| @@ -29,6 +29,10 @@ void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); | |||
| 29 | struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, | 29 | struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, |
| 30 | const uint8_t *addr); | 30 | const uint8_t *addr); |
| 31 | struct batadv_neigh_node * | 31 | struct batadv_neigh_node * |
| 32 | batadv_neigh_node_get(const struct batadv_orig_node *orig_node, | ||
| 33 | const struct batadv_hard_iface *hard_iface, | ||
| 34 | const uint8_t *addr); | ||
| 35 | struct batadv_neigh_node * | ||
| 32 | batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, | 36 | batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, |
| 33 | const uint8_t *neigh_addr, | 37 | const uint8_t *neigh_addr, |
| 34 | struct batadv_orig_node *orig_node); | 38 | struct batadv_orig_node *orig_node); |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 1ed9f7c9ecea..a953d5b196a3 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
| @@ -688,7 +688,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | |||
| 688 | int is_old_ttvn; | 688 | int is_old_ttvn; |
| 689 | 689 | ||
| 690 | /* check if there is enough data before accessing it */ | 690 | /* check if there is enough data before accessing it */ |
| 691 | if (pskb_may_pull(skb, hdr_len + ETH_HLEN) < 0) | 691 | if (!pskb_may_pull(skb, hdr_len + ETH_HLEN)) |
| 692 | return 0; | 692 | return 0; |
| 693 | 693 | ||
| 694 | /* create a copy of the skb (in case of for re-routing) to modify it. */ | 694 | /* create a copy of the skb (in case of for re-routing) to modify it. */ |
| @@ -918,6 +918,8 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb, | |||
| 918 | 918 | ||
| 919 | if (ret != NET_RX_SUCCESS) | 919 | if (ret != NET_RX_SUCCESS) |
| 920 | ret = batadv_route_unicast_packet(skb, recv_if); | 920 | ret = batadv_route_unicast_packet(skb, recv_if); |
| 921 | else | ||
| 922 | consume_skb(skb); | ||
| 921 | 923 | ||
| 922 | return ret; | 924 | return ret; |
| 923 | } | 925 | } |
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 579f5f00a385..843febd1e519 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
| @@ -254,9 +254,9 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, | |||
| 254 | struct batadv_orig_node *orig_node, | 254 | struct batadv_orig_node *orig_node, |
| 255 | unsigned short vid) | 255 | unsigned short vid) |
| 256 | { | 256 | { |
| 257 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 257 | struct ethhdr *ethhdr; |
| 258 | struct batadv_unicast_packet *unicast_packet; | 258 | struct batadv_unicast_packet *unicast_packet; |
| 259 | int ret = NET_XMIT_DROP; | 259 | int ret = NET_XMIT_DROP, hdr_size; |
| 260 | 260 | ||
| 261 | if (!orig_node) | 261 | if (!orig_node) |
| 262 | goto out; | 262 | goto out; |
| @@ -265,12 +265,16 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, | |||
| 265 | case BATADV_UNICAST: | 265 | case BATADV_UNICAST: |
| 266 | if (!batadv_send_skb_prepare_unicast(skb, orig_node)) | 266 | if (!batadv_send_skb_prepare_unicast(skb, orig_node)) |
| 267 | goto out; | 267 | goto out; |
| 268 | |||
| 269 | hdr_size = sizeof(*unicast_packet); | ||
| 268 | break; | 270 | break; |
| 269 | case BATADV_UNICAST_4ADDR: | 271 | case BATADV_UNICAST_4ADDR: |
| 270 | if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, | 272 | if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, |
| 271 | orig_node, | 273 | orig_node, |
| 272 | packet_subtype)) | 274 | packet_subtype)) |
| 273 | goto out; | 275 | goto out; |
| 276 | |||
| 277 | hdr_size = sizeof(struct batadv_unicast_4addr_packet); | ||
| 274 | break; | 278 | break; |
| 275 | default: | 279 | default: |
| 276 | /* this function supports UNICAST and UNICAST_4ADDR only. It | 280 | /* this function supports UNICAST and UNICAST_4ADDR only. It |
| @@ -279,6 +283,7 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, | |||
| 279 | goto out; | 283 | goto out; |
| 280 | } | 284 | } |
| 281 | 285 | ||
| 286 | ethhdr = (struct ethhdr *)(skb->data + hdr_size); | ||
| 282 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 287 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
| 283 | 288 | ||
| 284 | /* inform the destination node that we are still missing a correct route | 289 | /* inform the destination node that we are still missing a correct route |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index b6071f675a3e..959dde721c46 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
| @@ -1975,6 +1975,7 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
| 1975 | struct hlist_head *head; | 1975 | struct hlist_head *head; |
| 1976 | uint32_t i, crc_tmp, crc = 0; | 1976 | uint32_t i, crc_tmp, crc = 0; |
| 1977 | uint8_t flags; | 1977 | uint8_t flags; |
| 1978 | __be16 tmp_vid; | ||
| 1978 | 1979 | ||
| 1979 | for (i = 0; i < hash->size; i++) { | 1980 | for (i = 0; i < hash->size; i++) { |
| 1980 | head = &hash->table[i]; | 1981 | head = &hash->table[i]; |
| @@ -2011,8 +2012,11 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
| 2011 | orig_node)) | 2012 | orig_node)) |
| 2012 | continue; | 2013 | continue; |
| 2013 | 2014 | ||
| 2014 | crc_tmp = crc32c(0, &tt_common->vid, | 2015 | /* use network order to read the VID: this ensures that |
| 2015 | sizeof(tt_common->vid)); | 2016 | * every node reads the bytes in the same order. |
| 2017 | */ | ||
| 2018 | tmp_vid = htons(tt_common->vid); | ||
| 2019 | crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid)); | ||
| 2016 | 2020 | ||
| 2017 | /* compute the CRC on flags that have to be kept in sync | 2021 | /* compute the CRC on flags that have to be kept in sync |
| 2018 | * among nodes | 2022 | * among nodes |
| @@ -2046,6 +2050,7 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv, | |||
| 2046 | struct hlist_head *head; | 2050 | struct hlist_head *head; |
| 2047 | uint32_t i, crc_tmp, crc = 0; | 2051 | uint32_t i, crc_tmp, crc = 0; |
| 2048 | uint8_t flags; | 2052 | uint8_t flags; |
| 2053 | __be16 tmp_vid; | ||
| 2049 | 2054 | ||
| 2050 | for (i = 0; i < hash->size; i++) { | 2055 | for (i = 0; i < hash->size; i++) { |
| 2051 | head = &hash->table[i]; | 2056 | head = &hash->table[i]; |
| @@ -2064,8 +2069,11 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv, | |||
| 2064 | if (tt_common->flags & BATADV_TT_CLIENT_NEW) | 2069 | if (tt_common->flags & BATADV_TT_CLIENT_NEW) |
| 2065 | continue; | 2070 | continue; |
| 2066 | 2071 | ||
| 2067 | crc_tmp = crc32c(0, &tt_common->vid, | 2072 | /* use network order to read the VID: this ensures that |
| 2068 | sizeof(tt_common->vid)); | 2073 | * every node reads the bytes in the same order. |
| 2074 | */ | ||
| 2075 | tmp_vid = htons(tt_common->vid); | ||
| 2076 | crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid)); | ||
| 2069 | 2077 | ||
| 2070 | /* compute the CRC on flags that have to be kept in sync | 2078 | /* compute the CRC on flags that have to be kept in sync |
| 2071 | * among nodes | 2079 | * among nodes |
| @@ -2262,6 +2270,7 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node, | |||
| 2262 | { | 2270 | { |
| 2263 | struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp; | 2271 | struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp; |
| 2264 | struct batadv_orig_node_vlan *vlan; | 2272 | struct batadv_orig_node_vlan *vlan; |
| 2273 | uint32_t crc; | ||
| 2265 | int i; | 2274 | int i; |
| 2266 | 2275 | ||
| 2267 | /* check if each received CRC matches the locally stored one */ | 2276 | /* check if each received CRC matches the locally stored one */ |
| @@ -2281,7 +2290,10 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node, | |||
| 2281 | if (!vlan) | 2290 | if (!vlan) |
| 2282 | return false; | 2291 | return false; |
| 2283 | 2292 | ||
| 2284 | if (vlan->tt.crc != ntohl(tt_vlan_tmp->crc)) | 2293 | crc = vlan->tt.crc; |
| 2294 | batadv_orig_node_vlan_free_ref(vlan); | ||
| 2295 | |||
| 2296 | if (crc != ntohl(tt_vlan_tmp->crc)) | ||
| 2285 | return false; | 2297 | return false; |
| 2286 | } | 2298 | } |
| 2287 | 2299 | ||
| @@ -3218,7 +3230,6 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv, | |||
| 3218 | 3230 | ||
| 3219 | spin_lock_bh(&orig_node->tt_lock); | 3231 | spin_lock_bh(&orig_node->tt_lock); |
| 3220 | 3232 | ||
| 3221 | tt_change = (struct batadv_tvlv_tt_change *)tt_buff; | ||
| 3222 | batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, | 3233 | batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, |
| 3223 | ttvn, tt_change); | 3234 | ttvn, tt_change); |
| 3224 | 3235 | ||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 292e619db896..d9fb93451442 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -430,6 +430,16 @@ static void hidp_del_timer(struct hidp_session *session) | |||
| 430 | del_timer(&session->timer); | 430 | del_timer(&session->timer); |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | static void hidp_process_report(struct hidp_session *session, | ||
| 434 | int type, const u8 *data, int len, int intr) | ||
| 435 | { | ||
| 436 | if (len > HID_MAX_BUFFER_SIZE) | ||
| 437 | len = HID_MAX_BUFFER_SIZE; | ||
| 438 | |||
| 439 | memcpy(session->input_buf, data, len); | ||
| 440 | hid_input_report(session->hid, type, session->input_buf, len, intr); | ||
| 441 | } | ||
| 442 | |||
| 433 | static void hidp_process_handshake(struct hidp_session *session, | 443 | static void hidp_process_handshake(struct hidp_session *session, |
| 434 | unsigned char param) | 444 | unsigned char param) |
| 435 | { | 445 | { |
| @@ -502,7 +512,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb, | |||
| 502 | hidp_input_report(session, skb); | 512 | hidp_input_report(session, skb); |
| 503 | 513 | ||
| 504 | if (session->hid) | 514 | if (session->hid) |
| 505 | hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0); | 515 | hidp_process_report(session, HID_INPUT_REPORT, |
| 516 | skb->data, skb->len, 0); | ||
| 506 | break; | 517 | break; |
| 507 | 518 | ||
| 508 | case HIDP_DATA_RTYPE_OTHER: | 519 | case HIDP_DATA_RTYPE_OTHER: |
| @@ -584,7 +595,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session, | |||
| 584 | hidp_input_report(session, skb); | 595 | hidp_input_report(session, skb); |
| 585 | 596 | ||
| 586 | if (session->hid) { | 597 | if (session->hid) { |
| 587 | hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1); | 598 | hidp_process_report(session, HID_INPUT_REPORT, |
| 599 | skb->data, skb->len, 1); | ||
| 588 | BT_DBG("report len %d", skb->len); | 600 | BT_DBG("report len %d", skb->len); |
| 589 | } | 601 | } |
| 590 | } else { | 602 | } else { |
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index ab5241400cf7..8798492a6e99 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #define __HIDP_H | 24 | #define __HIDP_H |
| 25 | 25 | ||
| 26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
| 27 | #include <linux/hid.h> | ||
| 27 | #include <linux/kref.h> | 28 | #include <linux/kref.h> |
| 28 | #include <net/bluetooth/bluetooth.h> | 29 | #include <net/bluetooth/bluetooth.h> |
| 29 | #include <net/bluetooth/l2cap.h> | 30 | #include <net/bluetooth/l2cap.h> |
| @@ -179,6 +180,9 @@ struct hidp_session { | |||
| 179 | 180 | ||
| 180 | /* Used in hidp_output_raw_report() */ | 181 | /* Used in hidp_output_raw_report() */ |
| 181 | int output_report_success; /* boolean */ | 182 | int output_report_success; /* boolean */ |
| 183 | |||
| 184 | /* temporary input buffer */ | ||
| 185 | u8 input_buf[HID_MAX_BUFFER_SIZE]; | ||
| 182 | }; | 186 | }; |
| 183 | 187 | ||
| 184 | /* HIDP init defines */ | 188 | /* HIDP init defines */ |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index e4401a531afb..63f0455c0bc3 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
| @@ -187,8 +187,7 @@ static int br_set_mac_address(struct net_device *dev, void *p) | |||
| 187 | 187 | ||
| 188 | spin_lock_bh(&br->lock); | 188 | spin_lock_bh(&br->lock); |
| 189 | if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) { | 189 | if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) { |
| 190 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 190 | /* Mac address will be changed in br_stp_change_bridge_id(). */ |
| 191 | br_fdb_change_mac_address(br, addr->sa_data); | ||
| 192 | br_stp_change_bridge_id(br, addr->sa_data); | 191 | br_stp_change_bridge_id(br, addr->sa_data); |
| 193 | } | 192 | } |
| 194 | spin_unlock_bh(&br->lock); | 193 | spin_unlock_bh(&br->lock); |
| @@ -226,6 +225,33 @@ static void br_netpoll_cleanup(struct net_device *dev) | |||
| 226 | br_netpoll_disable(p); | 225 | br_netpoll_disable(p); |
| 227 | } | 226 | } |
| 228 | 227 | ||
| 228 | static int __br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) | ||
| 229 | { | ||
| 230 | struct netpoll *np; | ||
| 231 | int err; | ||
| 232 | |||
| 233 | np = kzalloc(sizeof(*p->np), gfp); | ||
| 234 | if (!np) | ||
| 235 | return -ENOMEM; | ||
| 236 | |||
| 237 | err = __netpoll_setup(np, p->dev, gfp); | ||
| 238 | if (err) { | ||
| 239 | kfree(np); | ||
| 240 | return err; | ||
| 241 | } | ||
| 242 | |||
| 243 | p->np = np; | ||
| 244 | return err; | ||
| 245 | } | ||
| 246 | |||
| 247 | int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) | ||
| 248 | { | ||
| 249 | if (!p->br->dev->npinfo) | ||
| 250 | return 0; | ||
| 251 | |||
| 252 | return __br_netpoll_enable(p, gfp); | ||
| 253 | } | ||
| 254 | |||
| 229 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, | 255 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, |
| 230 | gfp_t gfp) | 256 | gfp_t gfp) |
| 231 | { | 257 | { |
| @@ -236,7 +262,7 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, | |||
| 236 | list_for_each_entry(p, &br->port_list, list) { | 262 | list_for_each_entry(p, &br->port_list, list) { |
| 237 | if (!p->dev) | 263 | if (!p->dev) |
| 238 | continue; | 264 | continue; |
| 239 | err = br_netpoll_enable(p, gfp); | 265 | err = __br_netpoll_enable(p, gfp); |
| 240 | if (err) | 266 | if (err) |
| 241 | goto fail; | 267 | goto fail; |
| 242 | } | 268 | } |
| @@ -249,28 +275,6 @@ fail: | |||
| 249 | goto out; | 275 | goto out; |
| 250 | } | 276 | } |
| 251 | 277 | ||
| 252 | int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) | ||
| 253 | { | ||
| 254 | struct netpoll *np; | ||
| 255 | int err; | ||
| 256 | |||
| 257 | if (!p->br->dev->npinfo) | ||
| 258 | return 0; | ||
| 259 | |||
| 260 | np = kzalloc(sizeof(*p->np), gfp); | ||
| 261 | if (!np) | ||
| 262 | return -ENOMEM; | ||
| 263 | |||
| 264 | err = __netpoll_setup(np, p->dev, gfp); | ||
| 265 | if (err) { | ||
| 266 | kfree(np); | ||
| 267 | return err; | ||
| 268 | } | ||
| 269 | |||
| 270 | p->np = np; | ||
| 271 | return err; | ||
| 272 | } | ||
| 273 | |||
| 274 | void br_netpoll_disable(struct net_bridge_port *p) | 278 | void br_netpoll_disable(struct net_bridge_port *p) |
| 275 | { | 279 | { |
| 276 | struct netpoll *np = p->np; | 280 | struct netpoll *np = p->np; |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index c5f5a4a933f4..9203d5a1943f 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
| @@ -27,6 +27,9 @@ | |||
| 27 | #include "br_private.h" | 27 | #include "br_private.h" |
| 28 | 28 | ||
| 29 | static struct kmem_cache *br_fdb_cache __read_mostly; | 29 | static struct kmem_cache *br_fdb_cache __read_mostly; |
| 30 | static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, | ||
| 31 | const unsigned char *addr, | ||
| 32 | __u16 vid); | ||
| 30 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | 33 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, |
| 31 | const unsigned char *addr, u16 vid); | 34 | const unsigned char *addr, u16 vid); |
| 32 | static void fdb_notify(struct net_bridge *br, | 35 | static void fdb_notify(struct net_bridge *br, |
| @@ -89,11 +92,57 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f) | |||
| 89 | call_rcu(&f->rcu, fdb_rcu_free); | 92 | call_rcu(&f->rcu, fdb_rcu_free); |
| 90 | } | 93 | } |
| 91 | 94 | ||
| 95 | /* Delete a local entry if no other port had the same address. */ | ||
| 96 | static void fdb_delete_local(struct net_bridge *br, | ||
| 97 | const struct net_bridge_port *p, | ||
| 98 | struct net_bridge_fdb_entry *f) | ||
| 99 | { | ||
| 100 | const unsigned char *addr = f->addr.addr; | ||
| 101 | u16 vid = f->vlan_id; | ||
| 102 | struct net_bridge_port *op; | ||
| 103 | |||
| 104 | /* Maybe another port has same hw addr? */ | ||
| 105 | list_for_each_entry(op, &br->port_list, list) { | ||
| 106 | if (op != p && ether_addr_equal(op->dev->dev_addr, addr) && | ||
| 107 | (!vid || nbp_vlan_find(op, vid))) { | ||
| 108 | f->dst = op; | ||
| 109 | f->added_by_user = 0; | ||
| 110 | return; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | /* Maybe bridge device has same hw addr? */ | ||
| 115 | if (p && ether_addr_equal(br->dev->dev_addr, addr) && | ||
| 116 | (!vid || br_vlan_find(br, vid))) { | ||
| 117 | f->dst = NULL; | ||
| 118 | f->added_by_user = 0; | ||
| 119 | return; | ||
| 120 | } | ||
| 121 | |||
| 122 | fdb_delete(br, f); | ||
| 123 | } | ||
| 124 | |||
| 125 | void br_fdb_find_delete_local(struct net_bridge *br, | ||
| 126 | const struct net_bridge_port *p, | ||
| 127 | const unsigned char *addr, u16 vid) | ||
| 128 | { | ||
| 129 | struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; | ||
| 130 | struct net_bridge_fdb_entry *f; | ||
| 131 | |||
| 132 | spin_lock_bh(&br->hash_lock); | ||
| 133 | f = fdb_find(head, addr, vid); | ||
| 134 | if (f && f->is_local && !f->added_by_user && f->dst == p) | ||
| 135 | fdb_delete_local(br, p, f); | ||
| 136 | spin_unlock_bh(&br->hash_lock); | ||
| 137 | } | ||
| 138 | |||
| 92 | void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) | 139 | void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) |
| 93 | { | 140 | { |
| 94 | struct net_bridge *br = p->br; | 141 | struct net_bridge *br = p->br; |
| 95 | bool no_vlan = (nbp_get_vlan_info(p) == NULL) ? true : false; | 142 | struct net_port_vlans *pv = nbp_get_vlan_info(p); |
| 143 | bool no_vlan = !pv; | ||
| 96 | int i; | 144 | int i; |
| 145 | u16 vid; | ||
| 97 | 146 | ||
| 98 | spin_lock_bh(&br->hash_lock); | 147 | spin_lock_bh(&br->hash_lock); |
| 99 | 148 | ||
| @@ -104,38 +153,34 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) | |||
| 104 | struct net_bridge_fdb_entry *f; | 153 | struct net_bridge_fdb_entry *f; |
| 105 | 154 | ||
| 106 | f = hlist_entry(h, struct net_bridge_fdb_entry, hlist); | 155 | f = hlist_entry(h, struct net_bridge_fdb_entry, hlist); |
| 107 | if (f->dst == p && f->is_local) { | 156 | if (f->dst == p && f->is_local && !f->added_by_user) { |
| 108 | /* maybe another port has same hw addr? */ | ||
| 109 | struct net_bridge_port *op; | ||
| 110 | u16 vid = f->vlan_id; | ||
| 111 | list_for_each_entry(op, &br->port_list, list) { | ||
| 112 | if (op != p && | ||
| 113 | ether_addr_equal(op->dev->dev_addr, | ||
| 114 | f->addr.addr) && | ||
| 115 | nbp_vlan_find(op, vid)) { | ||
| 116 | f->dst = op; | ||
| 117 | goto insert; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | /* delete old one */ | 157 | /* delete old one */ |
| 122 | fdb_delete(br, f); | 158 | fdb_delete_local(br, p, f); |
| 123 | insert: | ||
| 124 | /* insert new address, may fail if invalid | ||
| 125 | * address or dup. | ||
| 126 | */ | ||
| 127 | fdb_insert(br, p, newaddr, vid); | ||
| 128 | 159 | ||
| 129 | /* if this port has no vlan information | 160 | /* if this port has no vlan information |
| 130 | * configured, we can safely be done at | 161 | * configured, we can safely be done at |
| 131 | * this point. | 162 | * this point. |
| 132 | */ | 163 | */ |
| 133 | if (no_vlan) | 164 | if (no_vlan) |
| 134 | goto done; | 165 | goto insert; |
| 135 | } | 166 | } |
| 136 | } | 167 | } |
| 137 | } | 168 | } |
| 138 | 169 | ||
| 170 | insert: | ||
| 171 | /* insert new address, may fail if invalid address or dup. */ | ||
| 172 | fdb_insert(br, p, newaddr, 0); | ||
| 173 | |||
| 174 | if (no_vlan) | ||
| 175 | goto done; | ||
| 176 | |||
| 177 | /* Now add entries for every VLAN configured on the port. | ||
| 178 | * This function runs under RTNL so the bitmap will not change | ||
| 179 | * from under us. | ||
| 180 | */ | ||
| 181 | for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) | ||
| 182 | fdb_insert(br, p, newaddr, vid); | ||
| 183 | |||
| 139 | done: | 184 | done: |
| 140 | spin_unlock_bh(&br->hash_lock); | 185 | spin_unlock_bh(&br->hash_lock); |
| 141 | } | 186 | } |
| @@ -146,10 +191,12 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) | |||
| 146 | struct net_port_vlans *pv; | 191 | struct net_port_vlans *pv; |
| 147 | u16 vid = 0; | 192 | u16 vid = 0; |
| 148 | 193 | ||
| 194 | spin_lock_bh(&br->hash_lock); | ||
| 195 | |||
| 149 | /* If old entry was unassociated with any port, then delete it. */ | 196 | /* If old entry was unassociated with any port, then delete it. */ |
| 150 | f = __br_fdb_get(br, br->dev->dev_addr, 0); | 197 | f = __br_fdb_get(br, br->dev->dev_addr, 0); |
| 151 | if (f && f->is_local && !f->dst) | 198 | if (f && f->is_local && !f->dst) |
| 152 | fdb_delete(br, f); | 199 | fdb_delete_local(br, NULL, f); |
| 153 | 200 | ||
| 154 | fdb_insert(br, NULL, newaddr, 0); | 201 | fdb_insert(br, NULL, newaddr, 0); |
| 155 | 202 | ||
| @@ -159,14 +206,16 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) | |||
| 159 | */ | 206 | */ |
| 160 | pv = br_get_vlan_info(br); | 207 | pv = br_get_vlan_info(br); |
| 161 | if (!pv) | 208 | if (!pv) |
| 162 | return; | 209 | goto out; |
| 163 | 210 | ||
| 164 | for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) { | 211 | for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) { |
| 165 | f = __br_fdb_get(br, br->dev->dev_addr, vid); | 212 | f = __br_fdb_get(br, br->dev->dev_addr, vid); |
| 166 | if (f && f->is_local && !f->dst) | 213 | if (f && f->is_local && !f->dst) |
| 167 | fdb_delete(br, f); | 214 | fdb_delete_local(br, NULL, f); |
| 168 | fdb_insert(br, NULL, newaddr, vid); | 215 | fdb_insert(br, NULL, newaddr, vid); |
| 169 | } | 216 | } |
| 217 | out: | ||
| 218 | spin_unlock_bh(&br->hash_lock); | ||
| 170 | } | 219 | } |
| 171 | 220 | ||
| 172 | void br_fdb_cleanup(unsigned long _data) | 221 | void br_fdb_cleanup(unsigned long _data) |
| @@ -235,25 +284,11 @@ void br_fdb_delete_by_port(struct net_bridge *br, | |||
| 235 | 284 | ||
| 236 | if (f->is_static && !do_all) | 285 | if (f->is_static && !do_all) |
| 237 | continue; | 286 | continue; |
| 238 | /* | ||
| 239 | * if multiple ports all have the same device address | ||
| 240 | * then when one port is deleted, assign | ||
| 241 | * the local entry to other port | ||
| 242 | */ | ||
| 243 | if (f->is_local) { | ||
| 244 | struct net_bridge_port *op; | ||
| 245 | list_for_each_entry(op, &br->port_list, list) { | ||
| 246 | if (op != p && | ||
| 247 | ether_addr_equal(op->dev->dev_addr, | ||
| 248 | f->addr.addr)) { | ||
| 249 | f->dst = op; | ||
| 250 | goto skip_delete; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | } | ||
| 254 | 287 | ||
| 255 | fdb_delete(br, f); | 288 | if (f->is_local) |
| 256 | skip_delete: ; | 289 | fdb_delete_local(br, p, f); |
| 290 | else | ||
| 291 | fdb_delete(br, f); | ||
| 257 | } | 292 | } |
| 258 | } | 293 | } |
| 259 | spin_unlock_bh(&br->hash_lock); | 294 | spin_unlock_bh(&br->hash_lock); |
| @@ -397,6 +432,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, | |||
| 397 | fdb->vlan_id = vid; | 432 | fdb->vlan_id = vid; |
| 398 | fdb->is_local = 0; | 433 | fdb->is_local = 0; |
| 399 | fdb->is_static = 0; | 434 | fdb->is_static = 0; |
| 435 | fdb->added_by_user = 0; | ||
| 400 | fdb->updated = fdb->used = jiffies; | 436 | fdb->updated = fdb->used = jiffies; |
| 401 | hlist_add_head_rcu(&fdb->hlist, head); | 437 | hlist_add_head_rcu(&fdb->hlist, head); |
| 402 | } | 438 | } |
| @@ -447,7 +483,7 @@ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | |||
| 447 | } | 483 | } |
| 448 | 484 | ||
| 449 | void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | 485 | void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, |
| 450 | const unsigned char *addr, u16 vid) | 486 | const unsigned char *addr, u16 vid, bool added_by_user) |
| 451 | { | 487 | { |
| 452 | struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; | 488 | struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; |
| 453 | struct net_bridge_fdb_entry *fdb; | 489 | struct net_bridge_fdb_entry *fdb; |
| @@ -473,13 +509,18 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
| 473 | /* fastpath: update of existing entry */ | 509 | /* fastpath: update of existing entry */ |
| 474 | fdb->dst = source; | 510 | fdb->dst = source; |
| 475 | fdb->updated = jiffies; | 511 | fdb->updated = jiffies; |
| 512 | if (unlikely(added_by_user)) | ||
| 513 | fdb->added_by_user = 1; | ||
| 476 | } | 514 | } |
| 477 | } else { | 515 | } else { |
| 478 | spin_lock(&br->hash_lock); | 516 | spin_lock(&br->hash_lock); |
| 479 | if (likely(!fdb_find(head, addr, vid))) { | 517 | if (likely(!fdb_find(head, addr, vid))) { |
| 480 | fdb = fdb_create(head, source, addr, vid); | 518 | fdb = fdb_create(head, source, addr, vid); |
| 481 | if (fdb) | 519 | if (fdb) { |
| 520 | if (unlikely(added_by_user)) | ||
| 521 | fdb->added_by_user = 1; | ||
| 482 | fdb_notify(br, fdb, RTM_NEWNEIGH); | 522 | fdb_notify(br, fdb, RTM_NEWNEIGH); |
| 523 | } | ||
| 483 | } | 524 | } |
| 484 | /* else we lose race and someone else inserts | 525 | /* else we lose race and someone else inserts |
| 485 | * it first, don't bother updating | 526 | * it first, don't bother updating |
| @@ -647,6 +688,7 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, | |||
| 647 | 688 | ||
| 648 | modified = true; | 689 | modified = true; |
| 649 | } | 690 | } |
| 691 | fdb->added_by_user = 1; | ||
| 650 | 692 | ||
| 651 | fdb->used = jiffies; | 693 | fdb->used = jiffies; |
| 652 | if (modified) { | 694 | if (modified) { |
| @@ -664,7 +706,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p, | |||
| 664 | 706 | ||
| 665 | if (ndm->ndm_flags & NTF_USE) { | 707 | if (ndm->ndm_flags & NTF_USE) { |
| 666 | rcu_read_lock(); | 708 | rcu_read_lock(); |
| 667 | br_fdb_update(p->br, p, addr, vid); | 709 | br_fdb_update(p->br, p, addr, vid, true); |
| 668 | rcu_read_unlock(); | 710 | rcu_read_unlock(); |
| 669 | } else { | 711 | } else { |
| 670 | spin_lock_bh(&p->br->hash_lock); | 712 | spin_lock_bh(&p->br->hash_lock); |
| @@ -749,8 +791,7 @@ out: | |||
| 749 | return err; | 791 | return err; |
| 750 | } | 792 | } |
| 751 | 793 | ||
| 752 | int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, | 794 | static int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vlan) |
| 753 | u16 vlan) | ||
| 754 | { | 795 | { |
| 755 | struct hlist_head *head = &br->hash[br_mac_hash(addr, vlan)]; | 796 | struct hlist_head *head = &br->hash[br_mac_hash(addr, vlan)]; |
| 756 | struct net_bridge_fdb_entry *fdb; | 797 | struct net_bridge_fdb_entry *fdb; |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index cffe1d666ba1..54d207d3a31c 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -389,6 +389,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 389 | if (br->dev->needed_headroom < dev->needed_headroom) | 389 | if (br->dev->needed_headroom < dev->needed_headroom) |
| 390 | br->dev->needed_headroom = dev->needed_headroom; | 390 | br->dev->needed_headroom = dev->needed_headroom; |
| 391 | 391 | ||
| 392 | if (br_fdb_insert(br, p, dev->dev_addr, 0)) | ||
| 393 | netdev_err(dev, "failed insert local address bridge forwarding table\n"); | ||
| 394 | |||
| 392 | spin_lock_bh(&br->lock); | 395 | spin_lock_bh(&br->lock); |
| 393 | changed_addr = br_stp_recalculate_bridge_id(br); | 396 | changed_addr = br_stp_recalculate_bridge_id(br); |
| 394 | 397 | ||
| @@ -404,9 +407,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 404 | 407 | ||
| 405 | dev_set_mtu(br->dev, br_min_mtu(br)); | 408 | dev_set_mtu(br->dev, br_min_mtu(br)); |
| 406 | 409 | ||
| 407 | if (br_fdb_insert(br, p, dev->dev_addr, 0)) | ||
| 408 | netdev_err(dev, "failed insert local address bridge forwarding table\n"); | ||
| 409 | |||
| 410 | kobject_uevent(&p->kobj, KOBJ_ADD); | 410 | kobject_uevent(&p->kobj, KOBJ_ADD); |
| 411 | 411 | ||
| 412 | return 0; | 412 | return 0; |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index bf8dc7d308d6..28d544627422 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -77,7 +77,7 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
| 77 | /* insert into forwarding database after filtering to avoid spoofing */ | 77 | /* insert into forwarding database after filtering to avoid spoofing */ |
| 78 | br = p->br; | 78 | br = p->br; |
| 79 | if (p->flags & BR_LEARNING) | 79 | if (p->flags & BR_LEARNING) |
| 80 | br_fdb_update(br, p, eth_hdr(skb)->h_source, vid); | 80 | br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false); |
| 81 | 81 | ||
| 82 | if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && | 82 | if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && |
| 83 | br_multicast_rcv(br, p, skb, vid)) | 83 | br_multicast_rcv(br, p, skb, vid)) |
| @@ -148,7 +148,7 @@ static int br_handle_local_finish(struct sk_buff *skb) | |||
| 148 | 148 | ||
| 149 | br_vlan_get_tag(skb, &vid); | 149 | br_vlan_get_tag(skb, &vid); |
| 150 | if (p->flags & BR_LEARNING) | 150 | if (p->flags & BR_LEARNING) |
| 151 | br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid); | 151 | br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); |
| 152 | return 0; /* process further */ | 152 | return 0; /* process further */ |
| 153 | } | 153 | } |
| 154 | 154 | ||
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index ef66365b7354..93067ecdb9a2 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -1127,9 +1127,10 @@ static void br_multicast_query_received(struct net_bridge *br, | |||
| 1127 | struct net_bridge_port *port, | 1127 | struct net_bridge_port *port, |
| 1128 | struct bridge_mcast_querier *querier, | 1128 | struct bridge_mcast_querier *querier, |
| 1129 | int saddr, | 1129 | int saddr, |
| 1130 | bool is_general_query, | ||
| 1130 | unsigned long max_delay) | 1131 | unsigned long max_delay) |
| 1131 | { | 1132 | { |
| 1132 | if (saddr) | 1133 | if (saddr && is_general_query) |
| 1133 | br_multicast_update_querier_timer(br, querier, max_delay); | 1134 | br_multicast_update_querier_timer(br, querier, max_delay); |
| 1134 | else if (timer_pending(&querier->timer)) | 1135 | else if (timer_pending(&querier->timer)) |
| 1135 | return; | 1136 | return; |
| @@ -1181,8 +1182,16 @@ static int br_ip4_multicast_query(struct net_bridge *br, | |||
| 1181 | IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; | 1182 | IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; |
| 1182 | } | 1183 | } |
| 1183 | 1184 | ||
| 1185 | /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer | ||
| 1186 | * all-systems destination addresses (224.0.0.1) for general queries | ||
| 1187 | */ | ||
| 1188 | if (!group && iph->daddr != htonl(INADDR_ALLHOSTS_GROUP)) { | ||
| 1189 | err = -EINVAL; | ||
| 1190 | goto out; | ||
| 1191 | } | ||
| 1192 | |||
| 1184 | br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr, | 1193 | br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr, |
| 1185 | max_delay); | 1194 | !group, max_delay); |
| 1186 | 1195 | ||
| 1187 | if (!group) | 1196 | if (!group) |
| 1188 | goto out; | 1197 | goto out; |
| @@ -1228,6 +1237,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1228 | unsigned long max_delay; | 1237 | unsigned long max_delay; |
| 1229 | unsigned long now = jiffies; | 1238 | unsigned long now = jiffies; |
| 1230 | const struct in6_addr *group = NULL; | 1239 | const struct in6_addr *group = NULL; |
| 1240 | bool is_general_query; | ||
| 1231 | int err = 0; | 1241 | int err = 0; |
| 1232 | 1242 | ||
| 1233 | spin_lock(&br->multicast_lock); | 1243 | spin_lock(&br->multicast_lock); |
| @@ -1235,6 +1245,12 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1235 | (port && port->state == BR_STATE_DISABLED)) | 1245 | (port && port->state == BR_STATE_DISABLED)) |
| 1236 | goto out; | 1246 | goto out; |
| 1237 | 1247 | ||
| 1248 | /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */ | ||
| 1249 | if (!(ipv6_addr_type(&ip6h->saddr) & IPV6_ADDR_LINKLOCAL)) { | ||
| 1250 | err = -EINVAL; | ||
| 1251 | goto out; | ||
| 1252 | } | ||
| 1253 | |||
| 1238 | if (skb->len == sizeof(*mld)) { | 1254 | if (skb->len == sizeof(*mld)) { |
| 1239 | if (!pskb_may_pull(skb, sizeof(*mld))) { | 1255 | if (!pskb_may_pull(skb, sizeof(*mld))) { |
| 1240 | err = -EINVAL; | 1256 | err = -EINVAL; |
| @@ -1256,8 +1272,19 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1256 | max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL); | 1272 | max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL); |
| 1257 | } | 1273 | } |
| 1258 | 1274 | ||
| 1275 | is_general_query = group && ipv6_addr_any(group); | ||
| 1276 | |||
| 1277 | /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer | ||
| 1278 | * all-nodes destination address (ff02::1) for general queries | ||
| 1279 | */ | ||
| 1280 | if (is_general_query && !ipv6_addr_is_ll_all_nodes(&ip6h->daddr)) { | ||
| 1281 | err = -EINVAL; | ||
| 1282 | goto out; | ||
| 1283 | } | ||
| 1284 | |||
| 1259 | br_multicast_query_received(br, port, &br->ip6_querier, | 1285 | br_multicast_query_received(br, port, &br->ip6_querier, |
| 1260 | !ipv6_addr_any(&ip6h->saddr), max_delay); | 1286 | !ipv6_addr_any(&ip6h->saddr), |
| 1287 | is_general_query, max_delay); | ||
| 1261 | 1288 | ||
| 1262 | if (!group) | 1289 | if (!group) |
| 1263 | goto out; | 1290 | goto out; |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index fcd12333c59b..3ba11bc99b65 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -104,6 +104,7 @@ struct net_bridge_fdb_entry | |||
| 104 | mac_addr addr; | 104 | mac_addr addr; |
| 105 | unsigned char is_local; | 105 | unsigned char is_local; |
| 106 | unsigned char is_static; | 106 | unsigned char is_static; |
| 107 | unsigned char added_by_user; | ||
| 107 | __u16 vlan_id; | 108 | __u16 vlan_id; |
| 108 | }; | 109 | }; |
| 109 | 110 | ||
| @@ -370,6 +371,9 @@ static inline void br_netpoll_disable(struct net_bridge_port *p) | |||
| 370 | int br_fdb_init(void); | 371 | int br_fdb_init(void); |
| 371 | void br_fdb_fini(void); | 372 | void br_fdb_fini(void); |
| 372 | void br_fdb_flush(struct net_bridge *br); | 373 | void br_fdb_flush(struct net_bridge *br); |
| 374 | void br_fdb_find_delete_local(struct net_bridge *br, | ||
| 375 | const struct net_bridge_port *p, | ||
| 376 | const unsigned char *addr, u16 vid); | ||
| 373 | void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr); | 377 | void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr); |
| 374 | void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr); | 378 | void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr); |
| 375 | void br_fdb_cleanup(unsigned long arg); | 379 | void br_fdb_cleanup(unsigned long arg); |
| @@ -383,8 +387,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, unsigned long count, | |||
| 383 | int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | 387 | int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, |
| 384 | const unsigned char *addr, u16 vid); | 388 | const unsigned char *addr, u16 vid); |
| 385 | void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | 389 | void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, |
| 386 | const unsigned char *addr, u16 vid); | 390 | const unsigned char *addr, u16 vid, bool added_by_user); |
| 387 | int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vid); | ||
| 388 | 391 | ||
| 389 | int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], | 392 | int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], |
| 390 | struct net_device *dev, const unsigned char *addr); | 393 | struct net_device *dev, const unsigned char *addr); |
| @@ -584,6 +587,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, | |||
| 584 | int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags); | 587 | int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags); |
| 585 | int br_vlan_delete(struct net_bridge *br, u16 vid); | 588 | int br_vlan_delete(struct net_bridge *br, u16 vid); |
| 586 | void br_vlan_flush(struct net_bridge *br); | 589 | void br_vlan_flush(struct net_bridge *br); |
| 590 | bool br_vlan_find(struct net_bridge *br, u16 vid); | ||
| 587 | int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); | 591 | int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); |
| 588 | int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags); | 592 | int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags); |
| 589 | int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); | 593 | int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); |
| @@ -665,6 +669,11 @@ static inline void br_vlan_flush(struct net_bridge *br) | |||
| 665 | { | 669 | { |
| 666 | } | 670 | } |
| 667 | 671 | ||
| 672 | static inline bool br_vlan_find(struct net_bridge *br, u16 vid) | ||
| 673 | { | ||
| 674 | return false; | ||
| 675 | } | ||
| 676 | |||
| 668 | static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) | 677 | static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) |
| 669 | { | 678 | { |
| 670 | return -EOPNOTSUPP; | 679 | return -EOPNOTSUPP; |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 656a6f3e40de..189ba1e7d851 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
| @@ -194,6 +194,8 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | |||
| 194 | 194 | ||
| 195 | wasroot = br_is_root_bridge(br); | 195 | wasroot = br_is_root_bridge(br); |
| 196 | 196 | ||
| 197 | br_fdb_change_mac_address(br, addr); | ||
| 198 | |||
| 197 | memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN); | 199 | memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN); |
| 198 | memcpy(br->bridge_id.addr, addr, ETH_ALEN); | 200 | memcpy(br->bridge_id.addr, addr, ETH_ALEN); |
| 199 | memcpy(br->dev->dev_addr, addr, ETH_ALEN); | 201 | memcpy(br->dev->dev_addr, addr, ETH_ALEN); |
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 4ca4d0a0151c..8249ca764c79 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
| @@ -275,9 +275,7 @@ int br_vlan_delete(struct net_bridge *br, u16 vid) | |||
| 275 | if (!pv) | 275 | if (!pv) |
| 276 | return -EINVAL; | 276 | return -EINVAL; |
| 277 | 277 | ||
| 278 | spin_lock_bh(&br->hash_lock); | 278 | br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid); |
| 279 | fdb_delete_by_addr(br, br->dev->dev_addr, vid); | ||
| 280 | spin_unlock_bh(&br->hash_lock); | ||
| 281 | 279 | ||
| 282 | __vlan_del(pv, vid); | 280 | __vlan_del(pv, vid); |
| 283 | return 0; | 281 | return 0; |
| @@ -295,6 +293,25 @@ void br_vlan_flush(struct net_bridge *br) | |||
| 295 | __vlan_flush(pv); | 293 | __vlan_flush(pv); |
| 296 | } | 294 | } |
| 297 | 295 | ||
| 296 | bool br_vlan_find(struct net_bridge *br, u16 vid) | ||
| 297 | { | ||
| 298 | struct net_port_vlans *pv; | ||
| 299 | bool found = false; | ||
| 300 | |||
| 301 | rcu_read_lock(); | ||
| 302 | pv = rcu_dereference(br->vlan_info); | ||
| 303 | |||
| 304 | if (!pv) | ||
| 305 | goto out; | ||
| 306 | |||
| 307 | if (test_bit(vid, pv->vlan_bitmap)) | ||
| 308 | found = true; | ||
| 309 | |||
| 310 | out: | ||
| 311 | rcu_read_unlock(); | ||
| 312 | return found; | ||
| 313 | } | ||
| 314 | |||
| 298 | int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) | 315 | int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) |
| 299 | { | 316 | { |
| 300 | if (!rtnl_trylock()) | 317 | if (!rtnl_trylock()) |
| @@ -359,9 +376,7 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) | |||
| 359 | if (!pv) | 376 | if (!pv) |
| 360 | return -EINVAL; | 377 | return -EINVAL; |
| 361 | 378 | ||
| 362 | spin_lock_bh(&port->br->hash_lock); | 379 | br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid); |
| 363 | fdb_delete_by_addr(port->br, port->dev->dev_addr, vid); | ||
| 364 | spin_unlock_bh(&port->br->hash_lock); | ||
| 365 | 380 | ||
| 366 | return __vlan_del(pv, vid); | 381 | return __vlan_del(pv, vid); |
| 367 | } | 382 | } |
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 4dca159435cf..edbca468fa73 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <net/pkt_sched.h> | 22 | #include <net/pkt_sched.h> |
| 23 | #include <net/caif/caif_device.h> | 23 | #include <net/caif/caif_device.h> |
| 24 | #include <net/caif/caif_layer.h> | 24 | #include <net/caif/caif_layer.h> |
| 25 | #include <net/caif/caif_dev.h> | ||
| 25 | #include <net/caif/cfpkt.h> | 26 | #include <net/caif/cfpkt.h> |
| 26 | #include <net/caif/cfcnfg.h> | 27 | #include <net/caif/cfcnfg.h> |
| 27 | #include <net/caif/cfserl.h> | 28 | #include <net/caif/cfserl.h> |
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index 353f793d1b3b..a6e115463052 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <net/caif/caif_layer.h> | 15 | #include <net/caif/caif_layer.h> |
| 16 | #include <net/caif/cfsrvl.h> | 16 | #include <net/caif/cfsrvl.h> |
| 17 | #include <net/caif/cfpkt.h> | 17 | #include <net/caif/cfpkt.h> |
| 18 | #include <net/caif/caif_dev.h> | ||
| 18 | 19 | ||
| 19 | #define SRVL_CTRL_PKT_SIZE 1 | 20 | #define SRVL_CTRL_PKT_SIZE 1 |
| 20 | #define SRVL_FLOW_OFF 0x81 | 21 | #define SRVL_FLOW_OFF 0x81 |
diff --git a/net/can/af_can.c b/net/can/af_can.c index d249874a366d..a27f8aad9e99 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | #include <linux/skbuff.h> | 57 | #include <linux/skbuff.h> |
| 58 | #include <linux/can.h> | 58 | #include <linux/can.h> |
| 59 | #include <linux/can/core.h> | 59 | #include <linux/can/core.h> |
| 60 | #include <linux/can/skb.h> | ||
| 60 | #include <linux/ratelimit.h> | 61 | #include <linux/ratelimit.h> |
| 61 | #include <net/net_namespace.h> | 62 | #include <net/net_namespace.h> |
| 62 | #include <net/sock.h> | 63 | #include <net/sock.h> |
| @@ -290,7 +291,7 @@ int can_send(struct sk_buff *skb, int loop) | |||
| 290 | return -ENOMEM; | 291 | return -ENOMEM; |
| 291 | } | 292 | } |
| 292 | 293 | ||
| 293 | newskb->sk = skb->sk; | 294 | can_skb_set_owner(newskb, skb->sk); |
| 294 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | 295 | newskb->ip_summed = CHECKSUM_UNNECESSARY; |
| 295 | newskb->pkt_type = PACKET_BROADCAST; | 296 | newskb->pkt_type = PACKET_BROADCAST; |
| 296 | } | 297 | } |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 3fc737b214c7..dcb75c0e66c1 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
| @@ -268,7 +268,7 @@ static void bcm_can_tx(struct bcm_op *op) | |||
| 268 | 268 | ||
| 269 | /* send with loopback */ | 269 | /* send with loopback */ |
| 270 | skb->dev = dev; | 270 | skb->dev = dev; |
| 271 | skb->sk = op->sk; | 271 | can_skb_set_owner(skb, op->sk); |
| 272 | can_send(skb, 1); | 272 | can_send(skb, 1); |
| 273 | 273 | ||
| 274 | /* update statistics */ | 274 | /* update statistics */ |
| @@ -1223,7 +1223,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk) | |||
| 1223 | 1223 | ||
| 1224 | can_skb_prv(skb)->ifindex = dev->ifindex; | 1224 | can_skb_prv(skb)->ifindex = dev->ifindex; |
| 1225 | skb->dev = dev; | 1225 | skb->dev = dev; |
| 1226 | skb->sk = sk; | 1226 | can_skb_set_owner(skb, sk); |
| 1227 | err = can_send(skb, 1); /* send with loopback */ | 1227 | err = can_send(skb, 1); /* send with loopback */ |
| 1228 | dev_put(dev); | 1228 | dev_put(dev); |
| 1229 | 1229 | ||
diff --git a/net/can/raw.c b/net/can/raw.c index 07d72d852324..081e81fd017f 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
| @@ -121,13 +121,9 @@ static void raw_rcv(struct sk_buff *oskb, void *data) | |||
| 121 | if (!ro->recv_own_msgs && oskb->sk == sk) | 121 | if (!ro->recv_own_msgs && oskb->sk == sk) |
| 122 | return; | 122 | return; |
| 123 | 123 | ||
| 124 | /* do not pass frames with DLC > 8 to a legacy socket */ | 124 | /* do not pass non-CAN2.0 frames to a legacy socket */ |
| 125 | if (!ro->fd_frames) { | 125 | if (!ro->fd_frames && oskb->len != CAN_MTU) |
| 126 | struct canfd_frame *cfd = (struct canfd_frame *)oskb->data; | 126 | return; |
| 127 | |||
| 128 | if (unlikely(cfd->len > CAN_MAX_DLEN)) | ||
| 129 | return; | ||
| 130 | } | ||
| 131 | 127 | ||
| 132 | /* clone the given skb to be able to enqueue it into the rcv queue */ | 128 | /* clone the given skb to be able to enqueue it into the rcv queue */ |
| 133 | skb = skb_clone(oskb, GFP_ATOMIC); | 129 | skb = skb_clone(oskb, GFP_ATOMIC); |
| @@ -715,6 +711,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 715 | 711 | ||
| 716 | skb->dev = dev; | 712 | skb->dev = dev; |
| 717 | skb->sk = sk; | 713 | skb->sk = sk; |
| 714 | skb->priority = sk->sk_priority; | ||
| 718 | 715 | ||
| 719 | err = can_send(skb, ro->loopback); | 716 | err = can_send(skb, ro->loopback); |
| 720 | 717 | ||
| @@ -737,9 +734,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 737 | struct msghdr *msg, size_t size, int flags) | 734 | struct msghdr *msg, size_t size, int flags) |
| 738 | { | 735 | { |
| 739 | struct sock *sk = sock->sk; | 736 | struct sock *sk = sock->sk; |
| 740 | struct raw_sock *ro = raw_sk(sk); | ||
| 741 | struct sk_buff *skb; | 737 | struct sk_buff *skb; |
| 742 | int rxmtu; | ||
| 743 | int err = 0; | 738 | int err = 0; |
| 744 | int noblock; | 739 | int noblock; |
| 745 | 740 | ||
| @@ -750,20 +745,10 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 750 | if (!skb) | 745 | if (!skb) |
| 751 | return err; | 746 | return err; |
| 752 | 747 | ||
| 753 | /* | 748 | if (size < skb->len) |
| 754 | * when serving a legacy socket the DLC <= 8 is already checked inside | ||
| 755 | * raw_rcv(). Now check if we need to pass a canfd_frame to a legacy | ||
| 756 | * socket and cut the possible CANFD_MTU/CAN_MTU length to CAN_MTU | ||
| 757 | */ | ||
| 758 | if (!ro->fd_frames) | ||
| 759 | rxmtu = CAN_MTU; | ||
| 760 | else | ||
| 761 | rxmtu = skb->len; | ||
| 762 | |||
| 763 | if (size < rxmtu) | ||
| 764 | msg->msg_flags |= MSG_TRUNC; | 749 | msg->msg_flags |= MSG_TRUNC; |
| 765 | else | 750 | else |
| 766 | size = rxmtu; | 751 | size = skb->len; |
| 767 | 752 | ||
| 768 | err = memcpy_toiovec(msg->msg_iov, skb->data, size); | 753 | err = memcpy_toiovec(msg->msg_iov, skb->data, size); |
| 769 | if (err < 0) { | 754 | if (err < 0) { |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 0e478a0f4204..30efc5c18622 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
| @@ -840,9 +840,13 @@ static bool ceph_msg_data_bio_advance(struct ceph_msg_data_cursor *cursor, | |||
| 840 | 840 | ||
| 841 | if (!cursor->bvec_iter.bi_size) { | 841 | if (!cursor->bvec_iter.bi_size) { |
| 842 | bio = bio->bi_next; | 842 | bio = bio->bi_next; |
| 843 | cursor->bvec_iter = bio->bi_iter; | 843 | cursor->bio = bio; |
| 844 | if (bio) | ||
| 845 | cursor->bvec_iter = bio->bi_iter; | ||
| 846 | else | ||
| 847 | memset(&cursor->bvec_iter, 0, | ||
| 848 | sizeof(cursor->bvec_iter)); | ||
| 844 | } | 849 | } |
| 845 | cursor->bio = bio; | ||
| 846 | 850 | ||
| 847 | if (!cursor->last_piece) { | 851 | if (!cursor->last_piece) { |
| 848 | BUG_ON(!cursor->resid); | 852 | BUG_ON(!cursor->resid); |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 010ff3bd58ad..0676f2b199d6 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
| @@ -1427,6 +1427,40 @@ static void __send_queued(struct ceph_osd_client *osdc) | |||
| 1427 | } | 1427 | } |
| 1428 | 1428 | ||
| 1429 | /* | 1429 | /* |
| 1430 | * Caller should hold map_sem for read and request_mutex. | ||
| 1431 | */ | ||
| 1432 | static int __ceph_osdc_start_request(struct ceph_osd_client *osdc, | ||
| 1433 | struct ceph_osd_request *req, | ||
| 1434 | bool nofail) | ||
| 1435 | { | ||
| 1436 | int rc; | ||
| 1437 | |||
| 1438 | __register_request(osdc, req); | ||
| 1439 | req->r_sent = 0; | ||
| 1440 | req->r_got_reply = 0; | ||
| 1441 | rc = __map_request(osdc, req, 0); | ||
| 1442 | if (rc < 0) { | ||
| 1443 | if (nofail) { | ||
| 1444 | dout("osdc_start_request failed map, " | ||
| 1445 | " will retry %lld\n", req->r_tid); | ||
| 1446 | rc = 0; | ||
| 1447 | } else { | ||
| 1448 | __unregister_request(osdc, req); | ||
| 1449 | } | ||
| 1450 | return rc; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | if (req->r_osd == NULL) { | ||
| 1454 | dout("send_request %p no up osds in pg\n", req); | ||
| 1455 | ceph_monc_request_next_osdmap(&osdc->client->monc); | ||
| 1456 | } else { | ||
| 1457 | __send_queued(osdc); | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | return 0; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | /* | ||
| 1430 | * Timeout callback, called every N seconds when 1 or more osd | 1464 | * Timeout callback, called every N seconds when 1 or more osd |
| 1431 | * requests has been active for more than N seconds. When this | 1465 | * requests has been active for more than N seconds. When this |
| 1432 | * happens, we ping all OSDs with requests who have timed out to | 1466 | * happens, we ping all OSDs with requests who have timed out to |
| @@ -1653,6 +1687,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
| 1653 | osdmap_epoch = ceph_decode_32(&p); | 1687 | osdmap_epoch = ceph_decode_32(&p); |
| 1654 | 1688 | ||
| 1655 | /* lookup */ | 1689 | /* lookup */ |
| 1690 | down_read(&osdc->map_sem); | ||
| 1656 | mutex_lock(&osdc->request_mutex); | 1691 | mutex_lock(&osdc->request_mutex); |
| 1657 | req = __lookup_request(osdc, tid); | 1692 | req = __lookup_request(osdc, tid); |
| 1658 | if (req == NULL) { | 1693 | if (req == NULL) { |
| @@ -1709,7 +1744,6 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
| 1709 | dout("redirect pool %lld\n", redir.oloc.pool); | 1744 | dout("redirect pool %lld\n", redir.oloc.pool); |
| 1710 | 1745 | ||
| 1711 | __unregister_request(osdc, req); | 1746 | __unregister_request(osdc, req); |
| 1712 | mutex_unlock(&osdc->request_mutex); | ||
| 1713 | 1747 | ||
| 1714 | req->r_target_oloc = redir.oloc; /* struct */ | 1748 | req->r_target_oloc = redir.oloc; /* struct */ |
| 1715 | 1749 | ||
| @@ -1721,10 +1755,10 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
| 1721 | * successfully. In the future we might want to follow | 1755 | * successfully. In the future we might want to follow |
| 1722 | * original request's nofail setting here. | 1756 | * original request's nofail setting here. |
| 1723 | */ | 1757 | */ |
| 1724 | err = ceph_osdc_start_request(osdc, req, true); | 1758 | err = __ceph_osdc_start_request(osdc, req, true); |
| 1725 | BUG_ON(err); | 1759 | BUG_ON(err); |
| 1726 | 1760 | ||
| 1727 | goto done; | 1761 | goto out_unlock; |
| 1728 | } | 1762 | } |
| 1729 | 1763 | ||
| 1730 | already_completed = req->r_got_reply; | 1764 | already_completed = req->r_got_reply; |
| @@ -1742,8 +1776,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
| 1742 | req->r_got_reply = 1; | 1776 | req->r_got_reply = 1; |
| 1743 | } else if ((flags & CEPH_OSD_FLAG_ONDISK) == 0) { | 1777 | } else if ((flags & CEPH_OSD_FLAG_ONDISK) == 0) { |
| 1744 | dout("handle_reply tid %llu dup ack\n", tid); | 1778 | dout("handle_reply tid %llu dup ack\n", tid); |
| 1745 | mutex_unlock(&osdc->request_mutex); | 1779 | goto out_unlock; |
| 1746 | goto done; | ||
| 1747 | } | 1780 | } |
| 1748 | 1781 | ||
| 1749 | dout("handle_reply tid %llu flags %d\n", tid, flags); | 1782 | dout("handle_reply tid %llu flags %d\n", tid, flags); |
| @@ -1758,6 +1791,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
| 1758 | __unregister_request(osdc, req); | 1791 | __unregister_request(osdc, req); |
| 1759 | 1792 | ||
| 1760 | mutex_unlock(&osdc->request_mutex); | 1793 | mutex_unlock(&osdc->request_mutex); |
| 1794 | up_read(&osdc->map_sem); | ||
| 1761 | 1795 | ||
| 1762 | if (!already_completed) { | 1796 | if (!already_completed) { |
| 1763 | if (req->r_unsafe_callback && | 1797 | if (req->r_unsafe_callback && |
| @@ -1775,10 +1809,14 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
| 1775 | complete_request(req); | 1809 | complete_request(req); |
| 1776 | } | 1810 | } |
| 1777 | 1811 | ||
| 1778 | done: | 1812 | out: |
| 1779 | dout("req=%p req->r_linger=%d\n", req, req->r_linger); | 1813 | dout("req=%p req->r_linger=%d\n", req, req->r_linger); |
| 1780 | ceph_osdc_put_request(req); | 1814 | ceph_osdc_put_request(req); |
| 1781 | return; | 1815 | return; |
| 1816 | out_unlock: | ||
| 1817 | mutex_unlock(&osdc->request_mutex); | ||
| 1818 | up_read(&osdc->map_sem); | ||
| 1819 | goto out; | ||
| 1782 | 1820 | ||
| 1783 | bad_put: | 1821 | bad_put: |
| 1784 | req->r_result = -EIO; | 1822 | req->r_result = -EIO; |
| @@ -1791,6 +1829,7 @@ bad_put: | |||
| 1791 | ceph_osdc_put_request(req); | 1829 | ceph_osdc_put_request(req); |
| 1792 | bad_mutex: | 1830 | bad_mutex: |
| 1793 | mutex_unlock(&osdc->request_mutex); | 1831 | mutex_unlock(&osdc->request_mutex); |
| 1832 | up_read(&osdc->map_sem); | ||
| 1794 | bad: | 1833 | bad: |
| 1795 | pr_err("corrupt osd_op_reply got %d %d\n", | 1834 | pr_err("corrupt osd_op_reply got %d %d\n", |
| 1796 | (int)msg->front.iov_len, le32_to_cpu(msg->hdr.front_len)); | 1835 | (int)msg->front.iov_len, le32_to_cpu(msg->hdr.front_len)); |
| @@ -2351,34 +2390,16 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
| 2351 | struct ceph_osd_request *req, | 2390 | struct ceph_osd_request *req, |
| 2352 | bool nofail) | 2391 | bool nofail) |
| 2353 | { | 2392 | { |
| 2354 | int rc = 0; | 2393 | int rc; |
| 2355 | 2394 | ||
| 2356 | down_read(&osdc->map_sem); | 2395 | down_read(&osdc->map_sem); |
| 2357 | mutex_lock(&osdc->request_mutex); | 2396 | mutex_lock(&osdc->request_mutex); |
| 2358 | __register_request(osdc, req); | 2397 | |
| 2359 | req->r_sent = 0; | 2398 | rc = __ceph_osdc_start_request(osdc, req, nofail); |
| 2360 | req->r_got_reply = 0; | 2399 | |
| 2361 | rc = __map_request(osdc, req, 0); | ||
| 2362 | if (rc < 0) { | ||
| 2363 | if (nofail) { | ||
| 2364 | dout("osdc_start_request failed map, " | ||
| 2365 | " will retry %lld\n", req->r_tid); | ||
| 2366 | rc = 0; | ||
| 2367 | } else { | ||
| 2368 | __unregister_request(osdc, req); | ||
| 2369 | } | ||
| 2370 | goto out_unlock; | ||
| 2371 | } | ||
| 2372 | if (req->r_osd == NULL) { | ||
| 2373 | dout("send_request %p no up osds in pg\n", req); | ||
| 2374 | ceph_monc_request_next_osdmap(&osdc->client->monc); | ||
| 2375 | } else { | ||
| 2376 | __send_queued(osdc); | ||
| 2377 | } | ||
| 2378 | rc = 0; | ||
| 2379 | out_unlock: | ||
| 2380 | mutex_unlock(&osdc->request_mutex); | 2400 | mutex_unlock(&osdc->request_mutex); |
| 2381 | up_read(&osdc->map_sem); | 2401 | up_read(&osdc->map_sem); |
| 2402 | |||
| 2382 | return rc; | 2403 | return rc; |
| 2383 | } | 2404 | } |
| 2384 | EXPORT_SYMBOL(ceph_osdc_start_request); | 2405 | EXPORT_SYMBOL(ceph_osdc_start_request); |
| @@ -2504,9 +2525,12 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client) | |||
| 2504 | err = -ENOMEM; | 2525 | err = -ENOMEM; |
| 2505 | osdc->notify_wq = create_singlethread_workqueue("ceph-watch-notify"); | 2526 | osdc->notify_wq = create_singlethread_workqueue("ceph-watch-notify"); |
| 2506 | if (!osdc->notify_wq) | 2527 | if (!osdc->notify_wq) |
| 2507 | goto out_msgpool; | 2528 | goto out_msgpool_reply; |
| 2529 | |||
| 2508 | return 0; | 2530 | return 0; |
| 2509 | 2531 | ||
| 2532 | out_msgpool_reply: | ||
| 2533 | ceph_msgpool_destroy(&osdc->msgpool_op_reply); | ||
| 2510 | out_msgpool: | 2534 | out_msgpool: |
| 2511 | ceph_msgpool_destroy(&osdc->msgpool_op); | 2535 | ceph_msgpool_destroy(&osdc->msgpool_op); |
| 2512 | out_mempool: | 2536 | out_mempool: |
diff --git a/net/core/dev.c b/net/core/dev.c index 3721db716350..b1b0c8d4d7df 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2420,7 +2420,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault); | |||
| 2420 | * 2. No high memory really exists on this machine. | 2420 | * 2. No high memory really exists on this machine. |
| 2421 | */ | 2421 | */ |
| 2422 | 2422 | ||
| 2423 | static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) | 2423 | static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb) |
| 2424 | { | 2424 | { |
| 2425 | #ifdef CONFIG_HIGHMEM | 2425 | #ifdef CONFIG_HIGHMEM |
| 2426 | int i; | 2426 | int i; |
| @@ -2495,34 +2495,36 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features) | |||
| 2495 | } | 2495 | } |
| 2496 | 2496 | ||
| 2497 | static netdev_features_t harmonize_features(struct sk_buff *skb, | 2497 | static netdev_features_t harmonize_features(struct sk_buff *skb, |
| 2498 | netdev_features_t features) | 2498 | const struct net_device *dev, |
| 2499 | netdev_features_t features) | ||
| 2499 | { | 2500 | { |
| 2500 | if (skb->ip_summed != CHECKSUM_NONE && | 2501 | if (skb->ip_summed != CHECKSUM_NONE && |
| 2501 | !can_checksum_protocol(features, skb_network_protocol(skb))) { | 2502 | !can_checksum_protocol(features, skb_network_protocol(skb))) { |
| 2502 | features &= ~NETIF_F_ALL_CSUM; | 2503 | features &= ~NETIF_F_ALL_CSUM; |
| 2503 | } else if (illegal_highdma(skb->dev, skb)) { | 2504 | } else if (illegal_highdma(dev, skb)) { |
| 2504 | features &= ~NETIF_F_SG; | 2505 | features &= ~NETIF_F_SG; |
| 2505 | } | 2506 | } |
| 2506 | 2507 | ||
| 2507 | return features; | 2508 | return features; |
| 2508 | } | 2509 | } |
| 2509 | 2510 | ||
| 2510 | netdev_features_t netif_skb_features(struct sk_buff *skb) | 2511 | netdev_features_t netif_skb_dev_features(struct sk_buff *skb, |
| 2512 | const struct net_device *dev) | ||
| 2511 | { | 2513 | { |
| 2512 | __be16 protocol = skb->protocol; | 2514 | __be16 protocol = skb->protocol; |
| 2513 | netdev_features_t features = skb->dev->features; | 2515 | netdev_features_t features = dev->features; |
| 2514 | 2516 | ||
| 2515 | if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) | 2517 | if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs) |
| 2516 | features &= ~NETIF_F_GSO_MASK; | 2518 | features &= ~NETIF_F_GSO_MASK; |
| 2517 | 2519 | ||
| 2518 | if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) { | 2520 | if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) { |
| 2519 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | 2521 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; |
| 2520 | protocol = veh->h_vlan_encapsulated_proto; | 2522 | protocol = veh->h_vlan_encapsulated_proto; |
| 2521 | } else if (!vlan_tx_tag_present(skb)) { | 2523 | } else if (!vlan_tx_tag_present(skb)) { |
| 2522 | return harmonize_features(skb, features); | 2524 | return harmonize_features(skb, dev, features); |
| 2523 | } | 2525 | } |
| 2524 | 2526 | ||
| 2525 | features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | | 2527 | features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | |
| 2526 | NETIF_F_HW_VLAN_STAG_TX); | 2528 | NETIF_F_HW_VLAN_STAG_TX); |
| 2527 | 2529 | ||
| 2528 | if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) | 2530 | if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) |
| @@ -2530,9 +2532,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
| 2530 | NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX | | 2532 | NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX | |
| 2531 | NETIF_F_HW_VLAN_STAG_TX; | 2533 | NETIF_F_HW_VLAN_STAG_TX; |
| 2532 | 2534 | ||
| 2533 | return harmonize_features(skb, features); | 2535 | return harmonize_features(skb, dev, features); |
| 2534 | } | 2536 | } |
| 2535 | EXPORT_SYMBOL(netif_skb_features); | 2537 | EXPORT_SYMBOL(netif_skb_dev_features); |
| 2536 | 2538 | ||
| 2537 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | 2539 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, |
| 2538 | struct netdev_queue *txq) | 2540 | struct netdev_queue *txq) |
| @@ -2803,7 +2805,7 @@ EXPORT_SYMBOL(dev_loopback_xmit); | |||
| 2803 | * the BH enable code must have IRQs enabled so that it will not deadlock. | 2805 | * the BH enable code must have IRQs enabled so that it will not deadlock. |
| 2804 | * --BLG | 2806 | * --BLG |
| 2805 | */ | 2807 | */ |
| 2806 | int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) | 2808 | static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) |
| 2807 | { | 2809 | { |
| 2808 | struct net_device *dev = skb->dev; | 2810 | struct net_device *dev = skb->dev; |
| 2809 | struct netdev_queue *txq; | 2811 | struct netdev_queue *txq; |
| @@ -4637,7 +4639,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev) | |||
| 4637 | } | 4639 | } |
| 4638 | EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu); | 4640 | EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu); |
| 4639 | 4641 | ||
| 4640 | int netdev_adjacent_sysfs_add(struct net_device *dev, | 4642 | static int netdev_adjacent_sysfs_add(struct net_device *dev, |
| 4641 | struct net_device *adj_dev, | 4643 | struct net_device *adj_dev, |
| 4642 | struct list_head *dev_list) | 4644 | struct list_head *dev_list) |
| 4643 | { | 4645 | { |
| @@ -4647,7 +4649,7 @@ int netdev_adjacent_sysfs_add(struct net_device *dev, | |||
| 4647 | return sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj), | 4649 | return sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj), |
| 4648 | linkname); | 4650 | linkname); |
| 4649 | } | 4651 | } |
| 4650 | void netdev_adjacent_sysfs_del(struct net_device *dev, | 4652 | static void netdev_adjacent_sysfs_del(struct net_device *dev, |
| 4651 | char *name, | 4653 | char *name, |
| 4652 | struct list_head *dev_list) | 4654 | struct list_head *dev_list) |
| 4653 | { | 4655 | { |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index f409e0bd35c0..185c341fafbd 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
| @@ -745,6 +745,13 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event, | |||
| 745 | attach_rules(&ops->rules_list, dev); | 745 | attach_rules(&ops->rules_list, dev); |
| 746 | break; | 746 | break; |
| 747 | 747 | ||
| 748 | case NETDEV_CHANGENAME: | ||
| 749 | list_for_each_entry(ops, &net->rules_ops, list) { | ||
| 750 | detach_rules(&ops->rules_list, dev); | ||
| 751 | attach_rules(&ops->rules_list, dev); | ||
| 752 | } | ||
| 753 | break; | ||
| 754 | |||
| 748 | case NETDEV_UNREGISTER: | 755 | case NETDEV_UNREGISTER: |
| 749 | list_for_each_entry(ops, &net->rules_ops, list) | 756 | list_for_each_entry(ops, &net->rules_ops, list) |
| 750 | detach_rules(&ops->rules_list, dev); | 757 | detach_rules(&ops->rules_list, dev); |
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 87577d447554..e29e810663d7 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
| @@ -323,17 +323,6 @@ u32 __skb_get_poff(const struct sk_buff *skb) | |||
| 323 | return poff; | 323 | return poff; |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index) | ||
| 327 | { | ||
| 328 | if (unlikely(queue_index >= dev->real_num_tx_queues)) { | ||
| 329 | net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n", | ||
| 330 | dev->name, queue_index, | ||
| 331 | dev->real_num_tx_queues); | ||
| 332 | return 0; | ||
| 333 | } | ||
| 334 | return queue_index; | ||
| 335 | } | ||
| 336 | |||
| 337 | static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) | 326 | static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) |
| 338 | { | 327 | { |
| 339 | #ifdef CONFIG_XPS | 328 | #ifdef CONFIG_XPS |
| @@ -372,7 +361,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) | |||
| 372 | #endif | 361 | #endif |
| 373 | } | 362 | } |
| 374 | 363 | ||
| 375 | u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) | 364 | static u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) |
| 376 | { | 365 | { |
| 377 | struct sock *sk = skb->sk; | 366 | struct sock *sk = skb->sk; |
| 378 | int queue_index = sk_tx_queue_get(sk); | 367 | int queue_index = sk_tx_queue_get(sk); |
| @@ -392,7 +381,6 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) | |||
| 392 | 381 | ||
| 393 | return queue_index; | 382 | return queue_index; |
| 394 | } | 383 | } |
| 395 | EXPORT_SYMBOL(__netdev_pick_tx); | ||
| 396 | 384 | ||
| 397 | struct netdev_queue *netdev_pick_tx(struct net_device *dev, | 385 | struct netdev_queue *netdev_pick_tx(struct net_device *dev, |
| 398 | struct sk_buff *skb, | 386 | struct sk_buff *skb, |
| @@ -403,13 +391,13 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev, | |||
| 403 | if (dev->real_num_tx_queues != 1) { | 391 | if (dev->real_num_tx_queues != 1) { |
| 404 | const struct net_device_ops *ops = dev->netdev_ops; | 392 | const struct net_device_ops *ops = dev->netdev_ops; |
| 405 | if (ops->ndo_select_queue) | 393 | if (ops->ndo_select_queue) |
| 406 | queue_index = ops->ndo_select_queue(dev, skb, | 394 | queue_index = ops->ndo_select_queue(dev, skb, accel_priv, |
| 407 | accel_priv); | 395 | __netdev_pick_tx); |
| 408 | else | 396 | else |
| 409 | queue_index = __netdev_pick_tx(dev, skb); | 397 | queue_index = __netdev_pick_tx(dev, skb); |
| 410 | 398 | ||
| 411 | if (!accel_priv) | 399 | if (!accel_priv) |
| 412 | queue_index = dev_cap_txqueue(dev, queue_index); | 400 | queue_index = netdev_cap_txqueue(dev, queue_index); |
| 413 | } | 401 | } |
| 414 | 402 | ||
| 415 | skb_set_queue_mapping(skb, queue_index); | 403 | skb_set_queue_mapping(skb, queue_index); |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b9e9e0d38672..e16129019c66 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -766,9 +766,6 @@ static void neigh_periodic_work(struct work_struct *work) | |||
| 766 | nht = rcu_dereference_protected(tbl->nht, | 766 | nht = rcu_dereference_protected(tbl->nht, |
| 767 | lockdep_is_held(&tbl->lock)); | 767 | lockdep_is_held(&tbl->lock)); |
| 768 | 768 | ||
| 769 | if (atomic_read(&tbl->entries) < tbl->gc_thresh1) | ||
| 770 | goto out; | ||
| 771 | |||
| 772 | /* | 769 | /* |
| 773 | * periodically recompute ReachableTime from random function | 770 | * periodically recompute ReachableTime from random function |
| 774 | */ | 771 | */ |
| @@ -781,6 +778,9 @@ static void neigh_periodic_work(struct work_struct *work) | |||
| 781 | neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME)); | 778 | neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME)); |
| 782 | } | 779 | } |
| 783 | 780 | ||
| 781 | if (atomic_read(&tbl->entries) < tbl->gc_thresh1) | ||
| 782 | goto out; | ||
| 783 | |||
| 784 | for (i = 0 ; i < (1 << nht->hash_shift); i++) { | 784 | for (i = 0 ; i < (1 << nht->hash_shift); i++) { |
| 785 | np = &nht->hash_buckets[i]; | 785 | np = &nht->hash_buckets[i]; |
| 786 | 786 | ||
| @@ -3046,7 +3046,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | |||
| 3046 | if (!t) | 3046 | if (!t) |
| 3047 | goto err; | 3047 | goto err; |
| 3048 | 3048 | ||
| 3049 | for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) { | 3049 | for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) { |
| 3050 | t->neigh_vars[i].data += (long) p; | 3050 | t->neigh_vars[i].data += (long) p; |
| 3051 | t->neigh_vars[i].extra1 = dev; | 3051 | t->neigh_vars[i].extra1 = dev; |
| 3052 | t->neigh_vars[i].extra2 = p; | 3052 | t->neigh_vars[i].extra2 = p; |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index c03f3dec4763..a664f7829a6d 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -948,6 +948,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) | |||
| 948 | { | 948 | { |
| 949 | char *cur=opt, *delim; | 949 | char *cur=opt, *delim; |
| 950 | int ipv6; | 950 | int ipv6; |
| 951 | bool ipversion_set = false; | ||
| 951 | 952 | ||
| 952 | if (*cur != '@') { | 953 | if (*cur != '@') { |
| 953 | if ((delim = strchr(cur, '@')) == NULL) | 954 | if ((delim = strchr(cur, '@')) == NULL) |
| @@ -960,6 +961,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) | |||
| 960 | cur++; | 961 | cur++; |
| 961 | 962 | ||
| 962 | if (*cur != '/') { | 963 | if (*cur != '/') { |
| 964 | ipversion_set = true; | ||
| 963 | if ((delim = strchr(cur, '/')) == NULL) | 965 | if ((delim = strchr(cur, '/')) == NULL) |
| 964 | goto parse_failed; | 966 | goto parse_failed; |
| 965 | *delim = 0; | 967 | *delim = 0; |
| @@ -1002,7 +1004,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) | |||
| 1002 | ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip); | 1004 | ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip); |
| 1003 | if (ipv6 < 0) | 1005 | if (ipv6 < 0) |
| 1004 | goto parse_failed; | 1006 | goto parse_failed; |
| 1005 | else if (np->ipv6 != (bool)ipv6) | 1007 | else if (ipversion_set && np->ipv6 != (bool)ipv6) |
| 1006 | goto parse_failed; | 1008 | goto parse_failed; |
| 1007 | else | 1009 | else |
| 1008 | np->ipv6 = (bool)ipv6; | 1010 | np->ipv6 = (bool)ipv6; |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 393b1bc9a618..1a0dac2ef9ad 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -374,7 +374,7 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) | |||
| 374 | if (!master_dev) | 374 | if (!master_dev) |
| 375 | return 0; | 375 | return 0; |
| 376 | ops = master_dev->rtnl_link_ops; | 376 | ops = master_dev->rtnl_link_ops; |
| 377 | if (!ops->get_slave_size) | 377 | if (!ops || !ops->get_slave_size) |
| 378 | return 0; | 378 | return 0; |
| 379 | /* IFLA_INFO_SLAVE_DATA + nested data */ | 379 | /* IFLA_INFO_SLAVE_DATA + nested data */ |
| 380 | return nla_total_size(sizeof(struct nlattr)) + | 380 | return nla_total_size(sizeof(struct nlattr)) + |
| @@ -1963,16 +1963,21 @@ replay: | |||
| 1963 | 1963 | ||
| 1964 | dev->ifindex = ifm->ifi_index; | 1964 | dev->ifindex = ifm->ifi_index; |
| 1965 | 1965 | ||
| 1966 | if (ops->newlink) | 1966 | if (ops->newlink) { |
| 1967 | err = ops->newlink(net, dev, tb, data); | 1967 | err = ops->newlink(net, dev, tb, data); |
| 1968 | else | 1968 | /* Drivers should call free_netdev() in ->destructor |
| 1969 | * and unregister it on failure so that device could be | ||
| 1970 | * finally freed in rtnl_unlock. | ||
| 1971 | */ | ||
| 1972 | if (err < 0) | ||
| 1973 | goto out; | ||
| 1974 | } else { | ||
| 1969 | err = register_netdevice(dev); | 1975 | err = register_netdevice(dev); |
| 1970 | 1976 | if (err < 0) { | |
| 1971 | if (err < 0) { | 1977 | free_netdev(dev); |
| 1972 | free_netdev(dev); | 1978 | goto out; |
| 1973 | goto out; | 1979 | } |
| 1974 | } | 1980 | } |
| 1975 | |||
| 1976 | err = rtnl_configure_link(dev, ifm); | 1981 | err = rtnl_configure_link(dev, ifm); |
| 1977 | if (err < 0) | 1982 | if (err < 0) |
| 1978 | unregister_netdevice(dev); | 1983 | unregister_netdevice(dev); |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5976ef0846bd..869c7afe3b07 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -707,9 +707,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
| 707 | new->mark = old->mark; | 707 | new->mark = old->mark; |
| 708 | new->skb_iif = old->skb_iif; | 708 | new->skb_iif = old->skb_iif; |
| 709 | __nf_copy(new, old); | 709 | __nf_copy(new, old); |
| 710 | #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) | ||
| 711 | new->nf_trace = old->nf_trace; | ||
| 712 | #endif | ||
| 713 | #ifdef CONFIG_NET_SCHED | 710 | #ifdef CONFIG_NET_SCHED |
| 714 | new->tc_index = old->tc_index; | 711 | new->tc_index = old->tc_index; |
| 715 | #ifdef CONFIG_NET_CLS_ACT | 712 | #ifdef CONFIG_NET_CLS_ACT |
| @@ -2841,81 +2838,84 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum); | |||
| 2841 | 2838 | ||
| 2842 | /** | 2839 | /** |
| 2843 | * skb_segment - Perform protocol segmentation on skb. | 2840 | * skb_segment - Perform protocol segmentation on skb. |
| 2844 | * @skb: buffer to segment | 2841 | * @head_skb: buffer to segment |
| 2845 | * @features: features for the output path (see dev->features) | 2842 | * @features: features for the output path (see dev->features) |
| 2846 | * | 2843 | * |
| 2847 | * This function performs segmentation on the given skb. It returns | 2844 | * This function performs segmentation on the given skb. It returns |
| 2848 | * a pointer to the first in a list of new skbs for the segments. | 2845 | * a pointer to the first in a list of new skbs for the segments. |
| 2849 | * In case of error it returns ERR_PTR(err). | 2846 | * In case of error it returns ERR_PTR(err). |
| 2850 | */ | 2847 | */ |
| 2851 | struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | 2848 | struct sk_buff *skb_segment(struct sk_buff *head_skb, |
| 2849 | netdev_features_t features) | ||
| 2852 | { | 2850 | { |
| 2853 | struct sk_buff *segs = NULL; | 2851 | struct sk_buff *segs = NULL; |
| 2854 | struct sk_buff *tail = NULL; | 2852 | struct sk_buff *tail = NULL; |
| 2855 | struct sk_buff *fskb = skb_shinfo(skb)->frag_list; | 2853 | struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list; |
| 2856 | skb_frag_t *skb_frag = skb_shinfo(skb)->frags; | 2854 | skb_frag_t *frag = skb_shinfo(head_skb)->frags; |
| 2857 | unsigned int mss = skb_shinfo(skb)->gso_size; | 2855 | unsigned int mss = skb_shinfo(head_skb)->gso_size; |
| 2858 | unsigned int doffset = skb->data - skb_mac_header(skb); | 2856 | unsigned int doffset = head_skb->data - skb_mac_header(head_skb); |
| 2857 | struct sk_buff *frag_skb = head_skb; | ||
| 2859 | unsigned int offset = doffset; | 2858 | unsigned int offset = doffset; |
| 2860 | unsigned int tnl_hlen = skb_tnl_header_len(skb); | 2859 | unsigned int tnl_hlen = skb_tnl_header_len(head_skb); |
| 2861 | unsigned int headroom; | 2860 | unsigned int headroom; |
| 2862 | unsigned int len; | 2861 | unsigned int len; |
| 2863 | __be16 proto; | 2862 | __be16 proto; |
| 2864 | bool csum; | 2863 | bool csum; |
| 2865 | int sg = !!(features & NETIF_F_SG); | 2864 | int sg = !!(features & NETIF_F_SG); |
| 2866 | int nfrags = skb_shinfo(skb)->nr_frags; | 2865 | int nfrags = skb_shinfo(head_skb)->nr_frags; |
| 2867 | int err = -ENOMEM; | 2866 | int err = -ENOMEM; |
| 2868 | int i = 0; | 2867 | int i = 0; |
| 2869 | int pos; | 2868 | int pos; |
| 2870 | 2869 | ||
| 2871 | proto = skb_network_protocol(skb); | 2870 | proto = skb_network_protocol(head_skb); |
| 2872 | if (unlikely(!proto)) | 2871 | if (unlikely(!proto)) |
| 2873 | return ERR_PTR(-EINVAL); | 2872 | return ERR_PTR(-EINVAL); |
| 2874 | 2873 | ||
| 2875 | csum = !!can_checksum_protocol(features, proto); | 2874 | csum = !!can_checksum_protocol(features, proto); |
| 2876 | __skb_push(skb, doffset); | 2875 | __skb_push(head_skb, doffset); |
| 2877 | headroom = skb_headroom(skb); | 2876 | headroom = skb_headroom(head_skb); |
| 2878 | pos = skb_headlen(skb); | 2877 | pos = skb_headlen(head_skb); |
| 2879 | 2878 | ||
| 2880 | do { | 2879 | do { |
| 2881 | struct sk_buff *nskb; | 2880 | struct sk_buff *nskb; |
| 2882 | skb_frag_t *frag; | 2881 | skb_frag_t *nskb_frag; |
| 2883 | int hsize; | 2882 | int hsize; |
| 2884 | int size; | 2883 | int size; |
| 2885 | 2884 | ||
| 2886 | len = skb->len - offset; | 2885 | len = head_skb->len - offset; |
| 2887 | if (len > mss) | 2886 | if (len > mss) |
| 2888 | len = mss; | 2887 | len = mss; |
| 2889 | 2888 | ||
| 2890 | hsize = skb_headlen(skb) - offset; | 2889 | hsize = skb_headlen(head_skb) - offset; |
| 2891 | if (hsize < 0) | 2890 | if (hsize < 0) |
| 2892 | hsize = 0; | 2891 | hsize = 0; |
| 2893 | if (hsize > len || !sg) | 2892 | if (hsize > len || !sg) |
| 2894 | hsize = len; | 2893 | hsize = len; |
| 2895 | 2894 | ||
| 2896 | if (!hsize && i >= nfrags && skb_headlen(fskb) && | 2895 | if (!hsize && i >= nfrags && skb_headlen(list_skb) && |
| 2897 | (skb_headlen(fskb) == len || sg)) { | 2896 | (skb_headlen(list_skb) == len || sg)) { |
| 2898 | BUG_ON(skb_headlen(fskb) > len); | 2897 | BUG_ON(skb_headlen(list_skb) > len); |
| 2899 | 2898 | ||
| 2900 | i = 0; | 2899 | i = 0; |
| 2901 | nfrags = skb_shinfo(fskb)->nr_frags; | 2900 | nfrags = skb_shinfo(list_skb)->nr_frags; |
| 2902 | skb_frag = skb_shinfo(fskb)->frags; | 2901 | frag = skb_shinfo(list_skb)->frags; |
| 2903 | pos += skb_headlen(fskb); | 2902 | frag_skb = list_skb; |
| 2903 | pos += skb_headlen(list_skb); | ||
| 2904 | 2904 | ||
| 2905 | while (pos < offset + len) { | 2905 | while (pos < offset + len) { |
| 2906 | BUG_ON(i >= nfrags); | 2906 | BUG_ON(i >= nfrags); |
| 2907 | 2907 | ||
| 2908 | size = skb_frag_size(skb_frag); | 2908 | size = skb_frag_size(frag); |
| 2909 | if (pos + size > offset + len) | 2909 | if (pos + size > offset + len) |
| 2910 | break; | 2910 | break; |
| 2911 | 2911 | ||
| 2912 | i++; | 2912 | i++; |
| 2913 | pos += size; | 2913 | pos += size; |
| 2914 | skb_frag++; | 2914 | frag++; |
| 2915 | } | 2915 | } |
| 2916 | 2916 | ||
| 2917 | nskb = skb_clone(fskb, GFP_ATOMIC); | 2917 | nskb = skb_clone(list_skb, GFP_ATOMIC); |
| 2918 | fskb = fskb->next; | 2918 | list_skb = list_skb->next; |
| 2919 | 2919 | ||
| 2920 | if (unlikely(!nskb)) | 2920 | if (unlikely(!nskb)) |
| 2921 | goto err; | 2921 | goto err; |
| @@ -2936,7 +2936,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
| 2936 | __skb_push(nskb, doffset); | 2936 | __skb_push(nskb, doffset); |
| 2937 | } else { | 2937 | } else { |
| 2938 | nskb = __alloc_skb(hsize + doffset + headroom, | 2938 | nskb = __alloc_skb(hsize + doffset + headroom, |
| 2939 | GFP_ATOMIC, skb_alloc_rx_flag(skb), | 2939 | GFP_ATOMIC, skb_alloc_rx_flag(head_skb), |
| 2940 | NUMA_NO_NODE); | 2940 | NUMA_NO_NODE); |
| 2941 | 2941 | ||
| 2942 | if (unlikely(!nskb)) | 2942 | if (unlikely(!nskb)) |
| @@ -2952,12 +2952,12 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
| 2952 | segs = nskb; | 2952 | segs = nskb; |
| 2953 | tail = nskb; | 2953 | tail = nskb; |
| 2954 | 2954 | ||
| 2955 | __copy_skb_header(nskb, skb); | 2955 | __copy_skb_header(nskb, head_skb); |
| 2956 | nskb->mac_len = skb->mac_len; | 2956 | nskb->mac_len = head_skb->mac_len; |
| 2957 | 2957 | ||
| 2958 | skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); | 2958 | skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); |
| 2959 | 2959 | ||
| 2960 | skb_copy_from_linear_data_offset(skb, -tnl_hlen, | 2960 | skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, |
| 2961 | nskb->data - tnl_hlen, | 2961 | nskb->data - tnl_hlen, |
| 2962 | doffset + tnl_hlen); | 2962 | doffset + tnl_hlen); |
| 2963 | 2963 | ||
| @@ -2966,30 +2966,32 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
| 2966 | 2966 | ||
| 2967 | if (!sg) { | 2967 | if (!sg) { |
| 2968 | nskb->ip_summed = CHECKSUM_NONE; | 2968 | nskb->ip_summed = CHECKSUM_NONE; |
| 2969 | nskb->csum = skb_copy_and_csum_bits(skb, offset, | 2969 | nskb->csum = skb_copy_and_csum_bits(head_skb, offset, |
| 2970 | skb_put(nskb, len), | 2970 | skb_put(nskb, len), |
| 2971 | len, 0); | 2971 | len, 0); |
| 2972 | continue; | 2972 | continue; |
| 2973 | } | 2973 | } |
| 2974 | 2974 | ||
| 2975 | frag = skb_shinfo(nskb)->frags; | 2975 | nskb_frag = skb_shinfo(nskb)->frags; |
| 2976 | 2976 | ||
| 2977 | skb_copy_from_linear_data_offset(skb, offset, | 2977 | skb_copy_from_linear_data_offset(head_skb, offset, |
| 2978 | skb_put(nskb, hsize), hsize); | 2978 | skb_put(nskb, hsize), hsize); |
| 2979 | 2979 | ||
| 2980 | skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG; | 2980 | skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags & |
| 2981 | SKBTX_SHARED_FRAG; | ||
| 2981 | 2982 | ||
| 2982 | while (pos < offset + len) { | 2983 | while (pos < offset + len) { |
| 2983 | if (i >= nfrags) { | 2984 | if (i >= nfrags) { |
| 2984 | BUG_ON(skb_headlen(fskb)); | 2985 | BUG_ON(skb_headlen(list_skb)); |
| 2985 | 2986 | ||
| 2986 | i = 0; | 2987 | i = 0; |
| 2987 | nfrags = skb_shinfo(fskb)->nr_frags; | 2988 | nfrags = skb_shinfo(list_skb)->nr_frags; |
| 2988 | skb_frag = skb_shinfo(fskb)->frags; | 2989 | frag = skb_shinfo(list_skb)->frags; |
| 2990 | frag_skb = list_skb; | ||
| 2989 | 2991 | ||
| 2990 | BUG_ON(!nfrags); | 2992 | BUG_ON(!nfrags); |
| 2991 | 2993 | ||
| 2992 | fskb = fskb->next; | 2994 | list_skb = list_skb->next; |
| 2993 | } | 2995 | } |
| 2994 | 2996 | ||
| 2995 | if (unlikely(skb_shinfo(nskb)->nr_frags >= | 2997 | if (unlikely(skb_shinfo(nskb)->nr_frags >= |
| @@ -3000,27 +3002,30 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
| 3000 | goto err; | 3002 | goto err; |
| 3001 | } | 3003 | } |
| 3002 | 3004 | ||
| 3003 | *frag = *skb_frag; | 3005 | if (unlikely(skb_orphan_frags(frag_skb, GFP_ATOMIC))) |
| 3004 | __skb_frag_ref(frag); | 3006 | goto err; |
| 3005 | size = skb_frag_size(frag); | 3007 | |
| 3008 | *nskb_frag = *frag; | ||
| 3009 | __skb_frag_ref(nskb_frag); | ||
| 3010 | size = skb_frag_size(nskb_frag); | ||
| 3006 | 3011 | ||
| 3007 | if (pos < offset) { | 3012 | if (pos < offset) { |
| 3008 | frag->page_offset += offset - pos; | 3013 | nskb_frag->page_offset += offset - pos; |
| 3009 | skb_frag_size_sub(frag, offset - pos); | 3014 | skb_frag_size_sub(nskb_frag, offset - pos); |
| 3010 | } | 3015 | } |
| 3011 | 3016 | ||
| 3012 | skb_shinfo(nskb)->nr_frags++; | 3017 | skb_shinfo(nskb)->nr_frags++; |
| 3013 | 3018 | ||
| 3014 | if (pos + size <= offset + len) { | 3019 | if (pos + size <= offset + len) { |
| 3015 | i++; | 3020 | i++; |
| 3016 | skb_frag++; | 3021 | frag++; |
| 3017 | pos += size; | 3022 | pos += size; |
| 3018 | } else { | 3023 | } else { |
| 3019 | skb_frag_size_sub(frag, pos + size - (offset + len)); | 3024 | skb_frag_size_sub(nskb_frag, pos + size - (offset + len)); |
| 3020 | goto skip_fraglist; | 3025 | goto skip_fraglist; |
| 3021 | } | 3026 | } |
| 3022 | 3027 | ||
| 3023 | frag++; | 3028 | nskb_frag++; |
| 3024 | } | 3029 | } |
| 3025 | 3030 | ||
| 3026 | skip_fraglist: | 3031 | skip_fraglist: |
| @@ -3034,7 +3039,7 @@ perform_csum_check: | |||
| 3034 | nskb->len - doffset, 0); | 3039 | nskb->len - doffset, 0); |
| 3035 | nskb->ip_summed = CHECKSUM_NONE; | 3040 | nskb->ip_summed = CHECKSUM_NONE; |
| 3036 | } | 3041 | } |
| 3037 | } while ((offset += len) < skb->len); | 3042 | } while ((offset += len) < head_skb->len); |
| 3038 | 3043 | ||
| 3039 | return segs; | 3044 | return segs; |
| 3040 | 3045 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 0c127dcdf6a8..c0fc6bdad1e3 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -1775,7 +1775,9 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | |||
| 1775 | while (order) { | 1775 | while (order) { |
| 1776 | if (npages >= 1 << order) { | 1776 | if (npages >= 1 << order) { |
| 1777 | page = alloc_pages(sk->sk_allocation | | 1777 | page = alloc_pages(sk->sk_allocation | |
| 1778 | __GFP_COMP | __GFP_NOWARN, | 1778 | __GFP_COMP | |
| 1779 | __GFP_NOWARN | | ||
| 1780 | __GFP_NORETRY, | ||
| 1779 | order); | 1781 | order); |
| 1780 | if (page) | 1782 | if (page) |
| 1781 | goto fill_page; | 1783 | goto fill_page; |
| @@ -1845,7 +1847,7 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio) | |||
| 1845 | gfp_t gfp = prio; | 1847 | gfp_t gfp = prio; |
| 1846 | 1848 | ||
| 1847 | if (order) | 1849 | if (order) |
| 1848 | gfp |= __GFP_COMP | __GFP_NOWARN; | 1850 | gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY; |
| 1849 | pfrag->page = alloc_pages(gfp, order); | 1851 | pfrag->page = alloc_pages(gfp, order); |
| 1850 | if (likely(pfrag->page)) { | 1852 | if (likely(pfrag->page)) { |
| 1851 | pfrag->offset = 0; | 1853 | pfrag->offset = 0; |
| @@ -2355,10 +2357,13 @@ void release_sock(struct sock *sk) | |||
| 2355 | if (sk->sk_backlog.tail) | 2357 | if (sk->sk_backlog.tail) |
| 2356 | __release_sock(sk); | 2358 | __release_sock(sk); |
| 2357 | 2359 | ||
| 2360 | /* Warning : release_cb() might need to release sk ownership, | ||
| 2361 | * ie call sock_release_ownership(sk) before us. | ||
| 2362 | */ | ||
| 2358 | if (sk->sk_prot->release_cb) | 2363 | if (sk->sk_prot->release_cb) |
| 2359 | sk->sk_prot->release_cb(sk); | 2364 | sk->sk_prot->release_cb(sk); |
| 2360 | 2365 | ||
| 2361 | sk->sk_lock.owned = 0; | 2366 | sock_release_ownership(sk); |
| 2362 | if (waitqueue_active(&sk->sk_lock.wq)) | 2367 | if (waitqueue_active(&sk->sk_lock.wq)) |
| 2363 | wake_up(&sk->sk_lock.wq); | 2368 | wake_up(&sk->sk_lock.wq); |
| 2364 | spin_unlock_bh(&sk->sk_lock.slock); | 2369 | spin_unlock_bh(&sk->sk_lock.slock); |
diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c index c073b81a1f3e..62b5828acde0 100644 --- a/net/dccp/ccids/lib/tfrc.c +++ b/net/dccp/ccids/lib/tfrc.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "tfrc.h" | 8 | #include "tfrc.h" |
| 9 | 9 | ||
| 10 | #ifdef CONFIG_IP_DCCP_TFRC_DEBUG | 10 | #ifdef CONFIG_IP_DCCP_TFRC_DEBUG |
| 11 | static bool tfrc_debug; | 11 | bool tfrc_debug; |
| 12 | module_param(tfrc_debug, bool, 0644); | 12 | module_param(tfrc_debug, bool, 0644); |
| 13 | MODULE_PARM_DESC(tfrc_debug, "Enable TFRC debug messages"); | 13 | MODULE_PARM_DESC(tfrc_debug, "Enable TFRC debug messages"); |
| 14 | #endif | 14 | #endif |
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h index a3d8f7c76ae0..40ee7d62b652 100644 --- a/net/dccp/ccids/lib/tfrc.h +++ b/net/dccp/ccids/lib/tfrc.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include "packet_history.h" | 21 | #include "packet_history.h" |
| 22 | 22 | ||
| 23 | #ifdef CONFIG_IP_DCCP_TFRC_DEBUG | 23 | #ifdef CONFIG_IP_DCCP_TFRC_DEBUG |
| 24 | extern bool tfrc_debug; | ||
| 24 | #define tfrc_pr_debug(format, a...) DCCP_PR_DEBUG(tfrc_debug, format, ##a) | 25 | #define tfrc_pr_debug(format, a...) DCCP_PR_DEBUG(tfrc_debug, format, ##a) |
| 25 | #else | 26 | #else |
| 26 | #define tfrc_pr_debug(format, a...) | 27 | #define tfrc_pr_debug(format, a...) |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 2954dcbca832..4c04848953bd 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
| @@ -2104,8 +2104,6 @@ static struct notifier_block dn_dev_notifier = { | |||
| 2104 | .notifier_call = dn_device_event, | 2104 | .notifier_call = dn_device_event, |
| 2105 | }; | 2105 | }; |
| 2106 | 2106 | ||
| 2107 | extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); | ||
| 2108 | |||
| 2109 | static struct packet_type dn_dix_packet_type __read_mostly = { | 2107 | static struct packet_type dn_dix_packet_type __read_mostly = { |
| 2110 | .type = cpu_to_be16(ETH_P_DNA_RT), | 2108 | .type = cpu_to_be16(ETH_P_DNA_RT), |
| 2111 | .func = dn_route_rcv, | 2109 | .func = dn_route_rcv, |
| @@ -2353,9 +2351,6 @@ static const struct proto_ops dn_proto_ops = { | |||
| 2353 | .sendpage = sock_no_sendpage, | 2351 | .sendpage = sock_no_sendpage, |
| 2354 | }; | 2352 | }; |
| 2355 | 2353 | ||
| 2356 | void dn_register_sysctl(void); | ||
| 2357 | void dn_unregister_sysctl(void); | ||
| 2358 | |||
| 2359 | MODULE_DESCRIPTION("The Linux DECnet Network Protocol"); | 2354 | MODULE_DESCRIPTION("The Linux DECnet Network Protocol"); |
| 2360 | MODULE_AUTHOR("Linux DECnet Project Team"); | 2355 | MODULE_AUTHOR("Linux DECnet Project Team"); |
| 2361 | MODULE_LICENSE("GPL"); | 2356 | MODULE_LICENSE("GPL"); |
diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 327060c6c874..7ae0d7f6dbd0 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c | |||
| @@ -297,7 +297,7 @@ static bool seq_nr_after(u16 a, u16 b) | |||
| 297 | 297 | ||
| 298 | void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx) | 298 | void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx) |
| 299 | { | 299 | { |
| 300 | if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) { | 300 | if ((dev_idx < 0) || (dev_idx >= HSR_MAX_SLAVE)) { |
| 301 | WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx); | 301 | WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx); |
| 302 | return; | 302 | return; |
| 303 | } | 303 | } |
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 48b25c0af4d0..8edfea5da572 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c | |||
| @@ -106,7 +106,6 @@ static int lowpan_header_create(struct sk_buff *skb, | |||
| 106 | unsigned short type, const void *_daddr, | 106 | unsigned short type, const void *_daddr, |
| 107 | const void *_saddr, unsigned int len) | 107 | const void *_saddr, unsigned int len) |
| 108 | { | 108 | { |
| 109 | struct ipv6hdr *hdr; | ||
| 110 | const u8 *saddr = _saddr; | 109 | const u8 *saddr = _saddr; |
| 111 | const u8 *daddr = _daddr; | 110 | const u8 *daddr = _daddr; |
| 112 | struct ieee802154_addr sa, da; | 111 | struct ieee802154_addr sa, da; |
| @@ -117,8 +116,6 @@ static int lowpan_header_create(struct sk_buff *skb, | |||
| 117 | if (type != ETH_P_IPV6) | 116 | if (type != ETH_P_IPV6) |
| 118 | return 0; | 117 | return 0; |
| 119 | 118 | ||
| 120 | hdr = ipv6_hdr(skb); | ||
| 121 | |||
| 122 | if (!saddr) | 119 | if (!saddr) |
| 123 | saddr = dev->dev_addr; | 120 | saddr = dev->dev_addr; |
| 124 | 121 | ||
| @@ -533,7 +530,27 @@ static struct header_ops lowpan_header_ops = { | |||
| 533 | .create = lowpan_header_create, | 530 | .create = lowpan_header_create, |
| 534 | }; | 531 | }; |
| 535 | 532 | ||
| 533 | static struct lock_class_key lowpan_tx_busylock; | ||
| 534 | static struct lock_class_key lowpan_netdev_xmit_lock_key; | ||
| 535 | |||
| 536 | static void lowpan_set_lockdep_class_one(struct net_device *dev, | ||
| 537 | struct netdev_queue *txq, | ||
| 538 | void *_unused) | ||
| 539 | { | ||
| 540 | lockdep_set_class(&txq->_xmit_lock, | ||
| 541 | &lowpan_netdev_xmit_lock_key); | ||
| 542 | } | ||
| 543 | |||
| 544 | |||
| 545 | static int lowpan_dev_init(struct net_device *dev) | ||
| 546 | { | ||
| 547 | netdev_for_each_tx_queue(dev, lowpan_set_lockdep_class_one, NULL); | ||
| 548 | dev->qdisc_tx_busylock = &lowpan_tx_busylock; | ||
| 549 | return 0; | ||
| 550 | } | ||
| 551 | |||
| 536 | static const struct net_device_ops lowpan_netdev_ops = { | 552 | static const struct net_device_ops lowpan_netdev_ops = { |
| 553 | .ndo_init = lowpan_dev_init, | ||
| 537 | .ndo_start_xmit = lowpan_xmit, | 554 | .ndo_start_xmit = lowpan_xmit, |
| 538 | .ndo_set_mac_address = lowpan_set_address, | 555 | .ndo_set_mac_address = lowpan_set_address, |
| 539 | }; | 556 | }; |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index ecd2c3f245ce..19ab78aca547 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -1296,8 +1296,11 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, | |||
| 1296 | 1296 | ||
| 1297 | segs = ERR_PTR(-EPROTONOSUPPORT); | 1297 | segs = ERR_PTR(-EPROTONOSUPPORT); |
| 1298 | 1298 | ||
| 1299 | /* Note : following gso_segment() might change skb->encapsulation */ | 1299 | if (skb->encapsulation && |
| 1300 | udpfrag = !skb->encapsulation && proto == IPPROTO_UDP; | 1300 | skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP)) |
| 1301 | udpfrag = proto == IPPROTO_UDP && encap; | ||
| 1302 | else | ||
| 1303 | udpfrag = proto == IPPROTO_UDP && !skb->encapsulation; | ||
| 1301 | 1304 | ||
| 1302 | ops = rcu_dereference(inet_offloads[proto]); | 1305 | ops = rcu_dereference(inet_offloads[proto]); |
| 1303 | if (likely(ops && ops->callbacks.gso_segment)) | 1306 | if (likely(ops && ops->callbacks.gso_segment)) |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index ac2dff3c2c1c..bdbf68bb2e2d 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
| @@ -1443,7 +1443,8 @@ static size_t inet_nlmsg_size(void) | |||
| 1443 | + nla_total_size(4) /* IFA_LOCAL */ | 1443 | + nla_total_size(4) /* IFA_LOCAL */ |
| 1444 | + nla_total_size(4) /* IFA_BROADCAST */ | 1444 | + nla_total_size(4) /* IFA_BROADCAST */ |
| 1445 | + nla_total_size(IFNAMSIZ) /* IFA_LABEL */ | 1445 | + nla_total_size(IFNAMSIZ) /* IFA_LABEL */ |
| 1446 | + nla_total_size(4); /* IFA_FLAGS */ | 1446 | + nla_total_size(4) /* IFA_FLAGS */ |
| 1447 | + nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */ | ||
| 1447 | } | 1448 | } |
| 1448 | 1449 | ||
| 1449 | static inline u32 cstamp_delta(unsigned long cstamp) | 1450 | static inline u32 cstamp_delta(unsigned long cstamp) |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index bb075fc9a14f..3b01959bf4bb 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
| @@ -208,7 +208,7 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force) | |||
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | work = frag_mem_limit(nf) - nf->low_thresh; | 210 | work = frag_mem_limit(nf) - nf->low_thresh; |
| 211 | while (work > 0) { | 211 | while (work > 0 || force) { |
| 212 | spin_lock(&nf->lru_lock); | 212 | spin_lock(&nf->lru_lock); |
| 213 | 213 | ||
| 214 | if (list_empty(&nf->lru_list)) { | 214 | if (list_empty(&nf->lru_list)) { |
| @@ -278,9 +278,10 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, | |||
| 278 | 278 | ||
| 279 | atomic_inc(&qp->refcnt); | 279 | atomic_inc(&qp->refcnt); |
| 280 | hlist_add_head(&qp->list, &hb->chain); | 280 | hlist_add_head(&qp->list, &hb->chain); |
| 281 | inet_frag_lru_add(nf, qp); | ||
| 281 | spin_unlock(&hb->chain_lock); | 282 | spin_unlock(&hb->chain_lock); |
| 282 | read_unlock(&f->lock); | 283 | read_unlock(&f->lock); |
| 283 | inet_frag_lru_add(nf, qp); | 284 | |
| 284 | return qp; | 285 | return qp; |
| 285 | } | 286 | } |
| 286 | 287 | ||
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index e9f1217a8afd..f3869c186d97 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
| @@ -39,6 +39,71 @@ | |||
| 39 | #include <net/route.h> | 39 | #include <net/route.h> |
| 40 | #include <net/xfrm.h> | 40 | #include <net/xfrm.h> |
| 41 | 41 | ||
| 42 | static bool ip_may_fragment(const struct sk_buff *skb) | ||
| 43 | { | ||
| 44 | return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) || | ||
| 45 | !skb->local_df; | ||
| 46 | } | ||
| 47 | |||
| 48 | static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) | ||
| 49 | { | ||
| 50 | if (skb->len <= mtu || skb->local_df) | ||
| 51 | return false; | ||
| 52 | |||
| 53 | if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) | ||
| 54 | return false; | ||
| 55 | |||
| 56 | return true; | ||
| 57 | } | ||
| 58 | |||
| 59 | static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb) | ||
| 60 | { | ||
| 61 | unsigned int mtu; | ||
| 62 | |||
| 63 | if (skb->local_df || !skb_is_gso(skb)) | ||
| 64 | return false; | ||
| 65 | |||
| 66 | mtu = ip_dst_mtu_maybe_forward(skb_dst(skb), true); | ||
| 67 | |||
| 68 | /* if seglen > mtu, do software segmentation for IP fragmentation on | ||
| 69 | * output. DF bit cannot be set since ip_forward would have sent | ||
| 70 | * icmp error. | ||
| 71 | */ | ||
| 72 | return skb_gso_network_seglen(skb) > mtu; | ||
| 73 | } | ||
| 74 | |||
| 75 | /* called if GSO skb needs to be fragmented on forward */ | ||
| 76 | static int ip_forward_finish_gso(struct sk_buff *skb) | ||
| 77 | { | ||
| 78 | struct dst_entry *dst = skb_dst(skb); | ||
| 79 | netdev_features_t features; | ||
| 80 | struct sk_buff *segs; | ||
| 81 | int ret = 0; | ||
| 82 | |||
| 83 | features = netif_skb_dev_features(skb, dst->dev); | ||
| 84 | segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); | ||
| 85 | if (IS_ERR(segs)) { | ||
| 86 | kfree_skb(skb); | ||
| 87 | return -ENOMEM; | ||
| 88 | } | ||
| 89 | |||
| 90 | consume_skb(skb); | ||
| 91 | |||
| 92 | do { | ||
| 93 | struct sk_buff *nskb = segs->next; | ||
| 94 | int err; | ||
| 95 | |||
| 96 | segs->next = NULL; | ||
| 97 | err = dst_output(segs); | ||
| 98 | |||
| 99 | if (err && ret == 0) | ||
| 100 | ret = err; | ||
| 101 | segs = nskb; | ||
| 102 | } while (segs); | ||
| 103 | |||
| 104 | return ret; | ||
| 105 | } | ||
| 106 | |||
| 42 | static int ip_forward_finish(struct sk_buff *skb) | 107 | static int ip_forward_finish(struct sk_buff *skb) |
| 43 | { | 108 | { |
| 44 | struct ip_options *opt = &(IPCB(skb)->opt); | 109 | struct ip_options *opt = &(IPCB(skb)->opt); |
| @@ -49,6 +114,9 @@ static int ip_forward_finish(struct sk_buff *skb) | |||
| 49 | if (unlikely(opt->optlen)) | 114 | if (unlikely(opt->optlen)) |
| 50 | ip_forward_options(skb); | 115 | ip_forward_options(skb); |
| 51 | 116 | ||
| 117 | if (ip_gso_exceeds_dst_mtu(skb)) | ||
| 118 | return ip_forward_finish_gso(skb); | ||
| 119 | |||
| 52 | return dst_output(skb); | 120 | return dst_output(skb); |
| 53 | } | 121 | } |
| 54 | 122 | ||
| @@ -91,8 +159,7 @@ int ip_forward(struct sk_buff *skb) | |||
| 91 | 159 | ||
| 92 | IPCB(skb)->flags |= IPSKB_FORWARDED; | 160 | IPCB(skb)->flags |= IPSKB_FORWARDED; |
| 93 | mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); | 161 | mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); |
| 94 | if (unlikely(skb->len > mtu && !skb_is_gso(skb) && | 162 | if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, mtu)) { |
| 95 | (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) { | ||
| 96 | IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS); | 163 | IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS); |
| 97 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, | 164 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
| 98 | htonl(mtu)); | 165 | htonl(mtu)); |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8971780aec7c..73c6b63bba74 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -422,9 +422,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
| 422 | to->tc_index = from->tc_index; | 422 | to->tc_index = from->tc_index; |
| 423 | #endif | 423 | #endif |
| 424 | nf_copy(to, from); | 424 | nf_copy(to, from); |
| 425 | #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) | ||
| 426 | to->nf_trace = from->nf_trace; | ||
| 427 | #endif | ||
| 428 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 425 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
| 429 | to->ipvs_property = from->ipvs_property; | 426 | to->ipvs_property = from->ipvs_property; |
| 430 | #endif | 427 | #endif |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index bd28f386bd02..78a89e61925d 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
| @@ -93,83 +93,32 @@ static void tunnel_dst_reset(struct ip_tunnel *t) | |||
| 93 | tunnel_dst_set(t, NULL); | 93 | tunnel_dst_set(t, NULL); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | static void tunnel_dst_reset_all(struct ip_tunnel *t) | 96 | void ip_tunnel_dst_reset_all(struct ip_tunnel *t) |
| 97 | { | 97 | { |
| 98 | int i; | 98 | int i; |
| 99 | 99 | ||
| 100 | for_each_possible_cpu(i) | 100 | for_each_possible_cpu(i) |
| 101 | __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); | 101 | __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); |
| 102 | } | 102 | } |
| 103 | EXPORT_SYMBOL(ip_tunnel_dst_reset_all); | ||
| 103 | 104 | ||
| 104 | static struct dst_entry *tunnel_dst_get(struct ip_tunnel *t) | 105 | static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) |
| 105 | { | 106 | { |
| 106 | struct dst_entry *dst; | 107 | struct dst_entry *dst; |
| 107 | 108 | ||
| 108 | rcu_read_lock(); | 109 | rcu_read_lock(); |
| 109 | dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst); | 110 | dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst); |
| 110 | if (dst) | 111 | if (dst) { |
| 112 | if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) { | ||
| 113 | rcu_read_unlock(); | ||
| 114 | tunnel_dst_reset(t); | ||
| 115 | return NULL; | ||
| 116 | } | ||
| 111 | dst_hold(dst); | 117 | dst_hold(dst); |
| 112 | rcu_read_unlock(); | ||
| 113 | return dst; | ||
| 114 | } | ||
| 115 | |||
| 116 | static struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie) | ||
| 117 | { | ||
| 118 | struct dst_entry *dst = tunnel_dst_get(t); | ||
| 119 | |||
| 120 | if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) { | ||
| 121 | tunnel_dst_reset(t); | ||
| 122 | return NULL; | ||
| 123 | } | ||
| 124 | |||
| 125 | return dst; | ||
| 126 | } | ||
| 127 | |||
| 128 | /* Often modified stats are per cpu, other are shared (netdev->stats) */ | ||
| 129 | struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, | ||
| 130 | struct rtnl_link_stats64 *tot) | ||
| 131 | { | ||
| 132 | int i; | ||
| 133 | |||
| 134 | for_each_possible_cpu(i) { | ||
| 135 | const struct pcpu_sw_netstats *tstats = | ||
| 136 | per_cpu_ptr(dev->tstats, i); | ||
| 137 | u64 rx_packets, rx_bytes, tx_packets, tx_bytes; | ||
| 138 | unsigned int start; | ||
| 139 | |||
| 140 | do { | ||
| 141 | start = u64_stats_fetch_begin_bh(&tstats->syncp); | ||
| 142 | rx_packets = tstats->rx_packets; | ||
| 143 | tx_packets = tstats->tx_packets; | ||
| 144 | rx_bytes = tstats->rx_bytes; | ||
| 145 | tx_bytes = tstats->tx_bytes; | ||
| 146 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | ||
| 147 | |||
| 148 | tot->rx_packets += rx_packets; | ||
| 149 | tot->tx_packets += tx_packets; | ||
| 150 | tot->rx_bytes += rx_bytes; | ||
| 151 | tot->tx_bytes += tx_bytes; | ||
| 152 | } | 118 | } |
| 153 | 119 | rcu_read_unlock(); | |
| 154 | tot->multicast = dev->stats.multicast; | 120 | return (struct rtable *)dst; |
| 155 | |||
| 156 | tot->rx_crc_errors = dev->stats.rx_crc_errors; | ||
| 157 | tot->rx_fifo_errors = dev->stats.rx_fifo_errors; | ||
| 158 | tot->rx_length_errors = dev->stats.rx_length_errors; | ||
| 159 | tot->rx_frame_errors = dev->stats.rx_frame_errors; | ||
| 160 | tot->rx_errors = dev->stats.rx_errors; | ||
| 161 | |||
| 162 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; | ||
| 163 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; | ||
| 164 | tot->tx_dropped = dev->stats.tx_dropped; | ||
| 165 | tot->tx_aborted_errors = dev->stats.tx_aborted_errors; | ||
| 166 | tot->tx_errors = dev->stats.tx_errors; | ||
| 167 | |||
| 168 | tot->collisions = dev->stats.collisions; | ||
| 169 | |||
| 170 | return tot; | ||
| 171 | } | 121 | } |
| 172 | EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64); | ||
| 173 | 122 | ||
| 174 | static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p, | 123 | static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p, |
| 175 | __be16 flags, __be32 key) | 124 | __be16 flags, __be32 key) |
| @@ -584,7 +533,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
| 584 | struct flowi4 fl4; | 533 | struct flowi4 fl4; |
| 585 | u8 tos, ttl; | 534 | u8 tos, ttl; |
| 586 | __be16 df; | 535 | __be16 df; |
| 587 | struct rtable *rt = NULL; /* Route to the other host */ | 536 | struct rtable *rt; /* Route to the other host */ |
| 588 | unsigned int max_headroom; /* The extra header space needed */ | 537 | unsigned int max_headroom; /* The extra header space needed */ |
| 589 | __be32 dst; | 538 | __be32 dst; |
| 590 | int err; | 539 | int err; |
| @@ -657,8 +606,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
| 657 | init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, | 606 | init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, |
| 658 | tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); | 607 | tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); |
| 659 | 608 | ||
| 660 | if (connected) | 609 | rt = connected ? tunnel_rtable_get(tunnel, 0) : NULL; |
| 661 | rt = (struct rtable *)tunnel_dst_check(tunnel, 0); | ||
| 662 | 610 | ||
| 663 | if (!rt) { | 611 | if (!rt) { |
| 664 | rt = ip_route_output_key(tunnel->net, &fl4); | 612 | rt = ip_route_output_key(tunnel->net, &fl4); |
| @@ -766,7 +714,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn, | |||
| 766 | if (set_mtu) | 714 | if (set_mtu) |
| 767 | dev->mtu = mtu; | 715 | dev->mtu = mtu; |
| 768 | } | 716 | } |
| 769 | tunnel_dst_reset_all(t); | 717 | ip_tunnel_dst_reset_all(t); |
| 770 | netdev_state_change(dev); | 718 | netdev_state_change(dev); |
| 771 | } | 719 | } |
| 772 | 720 | ||
| @@ -1095,7 +1043,7 @@ void ip_tunnel_uninit(struct net_device *dev) | |||
| 1095 | if (itn->fb_tunnel_dev != dev) | 1043 | if (itn->fb_tunnel_dev != dev) |
| 1096 | ip_tunnel_del(netdev_priv(dev)); | 1044 | ip_tunnel_del(netdev_priv(dev)); |
| 1097 | 1045 | ||
| 1098 | tunnel_dst_reset_all(tunnel); | 1046 | ip_tunnel_dst_reset_all(tunnel); |
| 1099 | } | 1047 | } |
| 1100 | EXPORT_SYMBOL_GPL(ip_tunnel_uninit); | 1048 | EXPORT_SYMBOL_GPL(ip_tunnel_uninit); |
| 1101 | 1049 | ||
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 6156f4ef5e91..6f847dd56dbc 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c | |||
| @@ -108,7 +108,6 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto) | |||
| 108 | nf_reset(skb); | 108 | nf_reset(skb); |
| 109 | secpath_reset(skb); | 109 | secpath_reset(skb); |
| 110 | skb_clear_hash_if_not_l4(skb); | 110 | skb_clear_hash_if_not_l4(skb); |
| 111 | skb_dst_drop(skb); | ||
| 112 | skb->vlan_tci = 0; | 111 | skb->vlan_tci = 0; |
| 113 | skb_set_queue_mapping(skb, 0); | 112 | skb_set_queue_mapping(skb, 0); |
| 114 | skb->pkt_type = PACKET_HOST; | 113 | skb->pkt_type = PACKET_HOST; |
| @@ -148,3 +147,49 @@ error: | |||
| 148 | return ERR_PTR(err); | 147 | return ERR_PTR(err); |
| 149 | } | 148 | } |
| 150 | EXPORT_SYMBOL_GPL(iptunnel_handle_offloads); | 149 | EXPORT_SYMBOL_GPL(iptunnel_handle_offloads); |
| 150 | |||
| 151 | /* Often modified stats are per cpu, other are shared (netdev->stats) */ | ||
| 152 | struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, | ||
| 153 | struct rtnl_link_stats64 *tot) | ||
| 154 | { | ||
| 155 | int i; | ||
| 156 | |||
| 157 | for_each_possible_cpu(i) { | ||
| 158 | const struct pcpu_sw_netstats *tstats = | ||
| 159 | per_cpu_ptr(dev->tstats, i); | ||
| 160 | u64 rx_packets, rx_bytes, tx_packets, tx_bytes; | ||
| 161 | unsigned int start; | ||
| 162 | |||
| 163 | do { | ||
| 164 | start = u64_stats_fetch_begin_bh(&tstats->syncp); | ||
| 165 | rx_packets = tstats->rx_packets; | ||
| 166 | tx_packets = tstats->tx_packets; | ||
| 167 | rx_bytes = tstats->rx_bytes; | ||
| 168 | tx_bytes = tstats->tx_bytes; | ||
| 169 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | ||
| 170 | |||
| 171 | tot->rx_packets += rx_packets; | ||
| 172 | tot->tx_packets += tx_packets; | ||
| 173 | tot->rx_bytes += rx_bytes; | ||
| 174 | tot->tx_bytes += tx_bytes; | ||
| 175 | } | ||
| 176 | |||
| 177 | tot->multicast = dev->stats.multicast; | ||
| 178 | |||
| 179 | tot->rx_crc_errors = dev->stats.rx_crc_errors; | ||
| 180 | tot->rx_fifo_errors = dev->stats.rx_fifo_errors; | ||
| 181 | tot->rx_length_errors = dev->stats.rx_length_errors; | ||
| 182 | tot->rx_frame_errors = dev->stats.rx_frame_errors; | ||
| 183 | tot->rx_errors = dev->stats.rx_errors; | ||
| 184 | |||
| 185 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; | ||
| 186 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; | ||
| 187 | tot->tx_dropped = dev->stats.tx_dropped; | ||
| 188 | tot->tx_aborted_errors = dev->stats.tx_aborted_errors; | ||
| 189 | tot->tx_errors = dev->stats.tx_errors; | ||
| 190 | |||
| 191 | tot->collisions = dev->stats.collisions; | ||
| 192 | |||
| 193 | return tot; | ||
| 194 | } | ||
| 195 | EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64); | ||
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index efa1138fa523..b3e86ea7b71b 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
| @@ -273,7 +273,7 @@ static int __init ic_open_devs(void) | |||
| 273 | 273 | ||
| 274 | msleep(1); | 274 | msleep(1); |
| 275 | 275 | ||
| 276 | if time_before(jiffies, next_msg) | 276 | if (time_before(jiffies, next_msg)) |
| 277 | continue; | 277 | continue; |
| 278 | 278 | ||
| 279 | elapsed = jiffies_to_msecs(jiffies - start); | 279 | elapsed = jiffies_to_msecs(jiffies - start); |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 81c6910cfa92..a26ce035e3fa 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
| @@ -61,6 +61,11 @@ config NFT_CHAIN_NAT_IPV4 | |||
| 61 | packet transformations such as the source, destination address and | 61 | packet transformations such as the source, destination address and |
| 62 | source and destination ports. | 62 | source and destination ports. |
| 63 | 63 | ||
| 64 | config NFT_REJECT_IPV4 | ||
| 65 | depends on NF_TABLES_IPV4 | ||
| 66 | default NFT_REJECT | ||
| 67 | tristate | ||
| 68 | |||
| 64 | config NF_TABLES_ARP | 69 | config NF_TABLES_ARP |
| 65 | depends on NF_TABLES | 70 | depends on NF_TABLES |
| 66 | tristate "ARP nf_tables support" | 71 | tristate "ARP nf_tables support" |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index c16be9d58420..90b82405331e 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
| @@ -30,6 +30,7 @@ obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o | |||
| 30 | obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o | 30 | obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o |
| 31 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o | 31 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o |
| 32 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o | 32 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o |
| 33 | obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o | ||
| 33 | obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o | 34 | obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o |
| 34 | 35 | ||
| 35 | # generic IP tables | 36 | # generic IP tables |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index 9eea059dd621..574f7ebba0b6 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
| @@ -229,7 +229,10 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | |||
| 229 | ret = nf_ct_expect_related(rtcp_exp); | 229 | ret = nf_ct_expect_related(rtcp_exp); |
| 230 | if (ret == 0) | 230 | if (ret == 0) |
| 231 | break; | 231 | break; |
| 232 | else if (ret != -EBUSY) { | 232 | else if (ret == -EBUSY) { |
| 233 | nf_ct_unexpect_related(rtp_exp); | ||
| 234 | continue; | ||
| 235 | } else if (ret < 0) { | ||
| 233 | nf_ct_unexpect_related(rtp_exp); | 236 | nf_ct_unexpect_related(rtp_exp); |
| 234 | nated_port = 0; | 237 | nated_port = 0; |
| 235 | break; | 238 | break; |
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index d551e31b416e..7c676671329d 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c | |||
| @@ -1198,8 +1198,8 @@ static int snmp_translate(struct nf_conn *ct, | |||
| 1198 | map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); | 1198 | map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); |
| 1199 | } else { | 1199 | } else { |
| 1200 | /* DNAT replies */ | 1200 | /* DNAT replies */ |
| 1201 | map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip); | 1201 | map.from = NOCT1(&ct->tuplehash[!dir].tuple.src.u3.ip); |
| 1202 | map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); | 1202 | map.to = NOCT1(&ct->tuplehash[dir].tuple.dst.u3.ip); |
| 1203 | } | 1203 | } |
| 1204 | 1204 | ||
| 1205 | if (map.from == map.to) | 1205 | if (map.from == map.to) |
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c new file mode 100644 index 000000000000..e79718a382f2 --- /dev/null +++ b/net/ipv4/netfilter/nft_reject_ipv4.c | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> | ||
| 3 | * Copyright (c) 2013 Eric Leblond <eric@regit.org> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/netlink.h> | ||
| 16 | #include <linux/netfilter.h> | ||
| 17 | #include <linux/netfilter/nf_tables.h> | ||
| 18 | #include <net/netfilter/nf_tables.h> | ||
| 19 | #include <net/icmp.h> | ||
| 20 | #include <net/netfilter/ipv4/nf_reject.h> | ||
| 21 | #include <net/netfilter/nft_reject.h> | ||
| 22 | |||
| 23 | void nft_reject_ipv4_eval(const struct nft_expr *expr, | ||
| 24 | struct nft_data data[NFT_REG_MAX + 1], | ||
| 25 | const struct nft_pktinfo *pkt) | ||
| 26 | { | ||
| 27 | struct nft_reject *priv = nft_expr_priv(expr); | ||
| 28 | |||
| 29 | switch (priv->type) { | ||
| 30 | case NFT_REJECT_ICMP_UNREACH: | ||
| 31 | nf_send_unreach(pkt->skb, priv->icmp_code); | ||
| 32 | break; | ||
| 33 | case NFT_REJECT_TCP_RST: | ||
| 34 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | ||
| 35 | break; | ||
| 36 | } | ||
| 37 | |||
| 38 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
| 39 | } | ||
| 40 | EXPORT_SYMBOL_GPL(nft_reject_ipv4_eval); | ||
| 41 | |||
| 42 | static struct nft_expr_type nft_reject_ipv4_type; | ||
| 43 | static const struct nft_expr_ops nft_reject_ipv4_ops = { | ||
| 44 | .type = &nft_reject_ipv4_type, | ||
| 45 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
| 46 | .eval = nft_reject_ipv4_eval, | ||
| 47 | .init = nft_reject_init, | ||
| 48 | .dump = nft_reject_dump, | ||
| 49 | }; | ||
| 50 | |||
| 51 | static struct nft_expr_type nft_reject_ipv4_type __read_mostly = { | ||
| 52 | .family = NFPROTO_IPV4, | ||
| 53 | .name = "reject", | ||
| 54 | .ops = &nft_reject_ipv4_ops, | ||
| 55 | .policy = nft_reject_policy, | ||
| 56 | .maxattr = NFTA_REJECT_MAX, | ||
| 57 | .owner = THIS_MODULE, | ||
| 58 | }; | ||
| 59 | |||
| 60 | static int __init nft_reject_ipv4_module_init(void) | ||
| 61 | { | ||
| 62 | return nft_register_expr(&nft_reject_ipv4_type); | ||
| 63 | } | ||
| 64 | |||
| 65 | static void __exit nft_reject_ipv4_module_exit(void) | ||
| 66 | { | ||
| 67 | nft_unregister_expr(&nft_reject_ipv4_type); | ||
| 68 | } | ||
| 69 | |||
| 70 | module_init(nft_reject_ipv4_module_init); | ||
| 71 | module_exit(nft_reject_ipv4_module_exit); | ||
| 72 | |||
| 73 | MODULE_LICENSE("GPL"); | ||
| 74 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 75 | MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "reject"); | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 25071b48921c..4c011ec69ed4 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -1597,6 +1597,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
| 1597 | rth->rt_gateway = 0; | 1597 | rth->rt_gateway = 0; |
| 1598 | rth->rt_uses_gateway = 0; | 1598 | rth->rt_uses_gateway = 0; |
| 1599 | INIT_LIST_HEAD(&rth->rt_uncached); | 1599 | INIT_LIST_HEAD(&rth->rt_uncached); |
| 1600 | RT_CACHE_STAT_INC(in_slow_tot); | ||
| 1600 | 1601 | ||
| 1601 | rth->dst.input = ip_forward; | 1602 | rth->dst.input = ip_forward; |
| 1602 | rth->dst.output = ip_output; | 1603 | rth->dst.output = ip_output; |
| @@ -1695,10 +1696,11 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
| 1695 | fl4.daddr = daddr; | 1696 | fl4.daddr = daddr; |
| 1696 | fl4.saddr = saddr; | 1697 | fl4.saddr = saddr; |
| 1697 | err = fib_lookup(net, &fl4, &res); | 1698 | err = fib_lookup(net, &fl4, &res); |
| 1698 | if (err != 0) | 1699 | if (err != 0) { |
| 1700 | if (!IN_DEV_FORWARD(in_dev)) | ||
| 1701 | err = -EHOSTUNREACH; | ||
| 1699 | goto no_route; | 1702 | goto no_route; |
| 1700 | 1703 | } | |
| 1701 | RT_CACHE_STAT_INC(in_slow_tot); | ||
| 1702 | 1704 | ||
| 1703 | if (res.type == RTN_BROADCAST) | 1705 | if (res.type == RTN_BROADCAST) |
| 1704 | goto brd_input; | 1706 | goto brd_input; |
| @@ -1712,8 +1714,10 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
| 1712 | goto local_input; | 1714 | goto local_input; |
| 1713 | } | 1715 | } |
| 1714 | 1716 | ||
| 1715 | if (!IN_DEV_FORWARD(in_dev)) | 1717 | if (!IN_DEV_FORWARD(in_dev)) { |
| 1718 | err = -EHOSTUNREACH; | ||
| 1716 | goto no_route; | 1719 | goto no_route; |
| 1720 | } | ||
| 1717 | if (res.type != RTN_UNICAST) | 1721 | if (res.type != RTN_UNICAST) |
| 1718 | goto martian_destination; | 1722 | goto martian_destination; |
| 1719 | 1723 | ||
| @@ -1768,6 +1772,7 @@ local_input: | |||
| 1768 | rth->rt_gateway = 0; | 1772 | rth->rt_gateway = 0; |
| 1769 | rth->rt_uses_gateway = 0; | 1773 | rth->rt_uses_gateway = 0; |
| 1770 | INIT_LIST_HEAD(&rth->rt_uncached); | 1774 | INIT_LIST_HEAD(&rth->rt_uncached); |
| 1775 | RT_CACHE_STAT_INC(in_slow_tot); | ||
| 1771 | if (res.type == RTN_UNREACHABLE) { | 1776 | if (res.type == RTN_UNREACHABLE) { |
| 1772 | rth->dst.input= ip_error; | 1777 | rth->dst.input= ip_error; |
| 1773 | rth->dst.error= -err; | 1778 | rth->dst.error= -err; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 4475b3bb494d..97c8f5620c43 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -1044,7 +1044,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp) | |||
| 1044 | } | 1044 | } |
| 1045 | } | 1045 | } |
| 1046 | 1046 | ||
| 1047 | static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size) | 1047 | static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, |
| 1048 | int *copied, size_t size) | ||
| 1048 | { | 1049 | { |
| 1049 | struct tcp_sock *tp = tcp_sk(sk); | 1050 | struct tcp_sock *tp = tcp_sk(sk); |
| 1050 | int err, flags; | 1051 | int err, flags; |
| @@ -1059,11 +1060,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size) | |||
| 1059 | if (unlikely(tp->fastopen_req == NULL)) | 1060 | if (unlikely(tp->fastopen_req == NULL)) |
| 1060 | return -ENOBUFS; | 1061 | return -ENOBUFS; |
| 1061 | tp->fastopen_req->data = msg; | 1062 | tp->fastopen_req->data = msg; |
| 1063 | tp->fastopen_req->size = size; | ||
| 1062 | 1064 | ||
| 1063 | flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; | 1065 | flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; |
| 1064 | err = __inet_stream_connect(sk->sk_socket, msg->msg_name, | 1066 | err = __inet_stream_connect(sk->sk_socket, msg->msg_name, |
| 1065 | msg->msg_namelen, flags); | 1067 | msg->msg_namelen, flags); |
| 1066 | *size = tp->fastopen_req->copied; | 1068 | *copied = tp->fastopen_req->copied; |
| 1067 | tcp_free_fastopen_req(tp); | 1069 | tcp_free_fastopen_req(tp); |
| 1068 | return err; | 1070 | return err; |
| 1069 | } | 1071 | } |
| @@ -1083,7 +1085,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 1083 | 1085 | ||
| 1084 | flags = msg->msg_flags; | 1086 | flags = msg->msg_flags; |
| 1085 | if (flags & MSG_FASTOPEN) { | 1087 | if (flags & MSG_FASTOPEN) { |
| 1086 | err = tcp_sendmsg_fastopen(sk, msg, &copied_syn); | 1088 | err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size); |
| 1087 | if (err == -EINPROGRESS && copied_syn > 0) | 1089 | if (err == -EINPROGRESS && copied_syn > 0) |
| 1088 | goto out; | 1090 | goto out; |
| 1089 | else if (err) | 1091 | else if (err) |
| @@ -2229,7 +2231,7 @@ adjudge_to_death: | |||
| 2229 | /* This is a (useful) BSD violating of the RFC. There is a | 2231 | /* This is a (useful) BSD violating of the RFC. There is a |
| 2230 | * problem with TCP as specified in that the other end could | 2232 | * problem with TCP as specified in that the other end could |
| 2231 | * keep a socket open forever with no application left this end. | 2233 | * keep a socket open forever with no application left this end. |
| 2232 | * We use a 3 minute timeout (about the same as BSD) then kill | 2234 | * We use a 1 minute timeout (about the same as BSD) then kill |
| 2233 | * our end. If they send after that then tough - BUT: long enough | 2235 | * our end. If they send after that then tough - BUT: long enough |
| 2234 | * that we won't make the old 4*rto = almost no time - whoops | 2236 | * that we won't make the old 4*rto = almost no time - whoops |
| 2235 | * reset mistake. | 2237 | * reset mistake. |
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index ad37bf18ae4b..2388275adb9b 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
| @@ -290,8 +290,7 @@ bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) | |||
| 290 | left = tp->snd_cwnd - in_flight; | 290 | left = tp->snd_cwnd - in_flight; |
| 291 | if (sk_can_gso(sk) && | 291 | if (sk_can_gso(sk) && |
| 292 | left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && | 292 | left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && |
| 293 | left * tp->mss_cache < sk->sk_gso_max_size && | 293 | left < tp->xmit_size_goal_segs) |
| 294 | left < sk->sk_gso_max_segs) | ||
| 295 | return true; | 294 | return true; |
| 296 | return left <= tcp_max_tso_deferred_mss(tp); | 295 | return left <= tcp_max_tso_deferred_mss(tp); |
| 297 | } | 296 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 65cf90e063d5..eeaac399420d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -671,6 +671,7 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) | |||
| 671 | { | 671 | { |
| 672 | struct tcp_sock *tp = tcp_sk(sk); | 672 | struct tcp_sock *tp = tcp_sk(sk); |
| 673 | long m = mrtt; /* RTT */ | 673 | long m = mrtt; /* RTT */ |
| 674 | u32 srtt = tp->srtt; | ||
| 674 | 675 | ||
| 675 | /* The following amusing code comes from Jacobson's | 676 | /* The following amusing code comes from Jacobson's |
| 676 | * article in SIGCOMM '88. Note that rtt and mdev | 677 | * article in SIGCOMM '88. Note that rtt and mdev |
| @@ -688,11 +689,9 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) | |||
| 688 | * does not matter how to _calculate_ it. Seems, it was trap | 689 | * does not matter how to _calculate_ it. Seems, it was trap |
| 689 | * that VJ failed to avoid. 8) | 690 | * that VJ failed to avoid. 8) |
| 690 | */ | 691 | */ |
| 691 | if (m == 0) | 692 | if (srtt != 0) { |
| 692 | m = 1; | 693 | m -= (srtt >> 3); /* m is now error in rtt est */ |
| 693 | if (tp->srtt != 0) { | 694 | srtt += m; /* rtt = 7/8 rtt + 1/8 new */ |
| 694 | m -= (tp->srtt >> 3); /* m is now error in rtt est */ | ||
| 695 | tp->srtt += m; /* rtt = 7/8 rtt + 1/8 new */ | ||
| 696 | if (m < 0) { | 695 | if (m < 0) { |
| 697 | m = -m; /* m is now abs(error) */ | 696 | m = -m; /* m is now abs(error) */ |
| 698 | m -= (tp->mdev >> 2); /* similar update on mdev */ | 697 | m -= (tp->mdev >> 2); /* similar update on mdev */ |
| @@ -723,11 +722,12 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) | |||
| 723 | } | 722 | } |
| 724 | } else { | 723 | } else { |
| 725 | /* no previous measure. */ | 724 | /* no previous measure. */ |
| 726 | tp->srtt = m << 3; /* take the measured time to be rtt */ | 725 | srtt = m << 3; /* take the measured time to be rtt */ |
| 727 | tp->mdev = m << 1; /* make sure rto = 3*rtt */ | 726 | tp->mdev = m << 1; /* make sure rto = 3*rtt */ |
| 728 | tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk)); | 727 | tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk)); |
| 729 | tp->rtt_seq = tp->snd_nxt; | 728 | tp->rtt_seq = tp->snd_nxt; |
| 730 | } | 729 | } |
| 730 | tp->srtt = max(1U, srtt); | ||
| 731 | } | 731 | } |
| 732 | 732 | ||
| 733 | /* Set the sk_pacing_rate to allow proper sizing of TSO packets. | 733 | /* Set the sk_pacing_rate to allow proper sizing of TSO packets. |
| @@ -746,8 +746,10 @@ static void tcp_update_pacing_rate(struct sock *sk) | |||
| 746 | 746 | ||
| 747 | rate *= max(tp->snd_cwnd, tp->packets_out); | 747 | rate *= max(tp->snd_cwnd, tp->packets_out); |
| 748 | 748 | ||
| 749 | /* Correction for small srtt : minimum srtt being 8 (1 jiffy << 3), | 749 | /* Correction for small srtt and scheduling constraints. |
| 750 | * be conservative and assume srtt = 1 (125 us instead of 1.25 ms) | 750 | * For small rtt, consider noise is too high, and use |
| 751 | * the minimal value (srtt = 1 -> 125 us for HZ=1000) | ||
| 752 | * | ||
| 751 | * We probably need usec resolution in the future. | 753 | * We probably need usec resolution in the future. |
| 752 | * Note: This also takes care of possible srtt=0 case, | 754 | * Note: This also takes care of possible srtt=0 case, |
| 753 | * when tcp_rtt_estimator() was not yet called. | 755 | * when tcp_rtt_estimator() was not yet called. |
| @@ -1943,8 +1945,9 @@ void tcp_enter_loss(struct sock *sk, int how) | |||
| 1943 | if (skb == tcp_send_head(sk)) | 1945 | if (skb == tcp_send_head(sk)) |
| 1944 | break; | 1946 | break; |
| 1945 | 1947 | ||
| 1946 | if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS) | 1948 | if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) |
| 1947 | tp->undo_marker = 0; | 1949 | tp->undo_marker = 0; |
| 1950 | |||
| 1948 | TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED; | 1951 | TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED; |
| 1949 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) { | 1952 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) { |
| 1950 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; | 1953 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 03d26b85eab8..17a11e65e57f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -698,7 +698,8 @@ static void tcp_tsq_handler(struct sock *sk) | |||
| 698 | if ((1 << sk->sk_state) & | 698 | if ((1 << sk->sk_state) & |
| 699 | (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_CLOSING | | 699 | (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_CLOSING | |
| 700 | TCPF_CLOSE_WAIT | TCPF_LAST_ACK)) | 700 | TCPF_CLOSE_WAIT | TCPF_LAST_ACK)) |
| 701 | tcp_write_xmit(sk, tcp_current_mss(sk), 0, 0, GFP_ATOMIC); | 701 | tcp_write_xmit(sk, tcp_current_mss(sk), tcp_sk(sk)->nonagle, |
| 702 | 0, GFP_ATOMIC); | ||
| 702 | } | 703 | } |
| 703 | /* | 704 | /* |
| 704 | * One tasklet per cpu tries to send more skbs. | 705 | * One tasklet per cpu tries to send more skbs. |
| @@ -766,6 +767,17 @@ void tcp_release_cb(struct sock *sk) | |||
| 766 | if (flags & (1UL << TCP_TSQ_DEFERRED)) | 767 | if (flags & (1UL << TCP_TSQ_DEFERRED)) |
| 767 | tcp_tsq_handler(sk); | 768 | tcp_tsq_handler(sk); |
| 768 | 769 | ||
| 770 | /* Here begins the tricky part : | ||
| 771 | * We are called from release_sock() with : | ||
| 772 | * 1) BH disabled | ||
| 773 | * 2) sk_lock.slock spinlock held | ||
| 774 | * 3) socket owned by us (sk->sk_lock.owned == 1) | ||
| 775 | * | ||
| 776 | * But following code is meant to be called from BH handlers, | ||
| 777 | * so we should keep BH disabled, but early release socket ownership | ||
| 778 | */ | ||
| 779 | sock_release_ownership(sk); | ||
| 780 | |||
| 769 | if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) { | 781 | if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) { |
| 770 | tcp_write_timer_handler(sk); | 782 | tcp_write_timer_handler(sk); |
| 771 | __sock_put(sk); | 783 | __sock_put(sk); |
| @@ -863,8 +875,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 863 | 875 | ||
| 864 | if (unlikely(skb->fclone == SKB_FCLONE_ORIG && | 876 | if (unlikely(skb->fclone == SKB_FCLONE_ORIG && |
| 865 | fclone->fclone == SKB_FCLONE_CLONE)) | 877 | fclone->fclone == SKB_FCLONE_CLONE)) |
| 866 | NET_INC_STATS_BH(sock_net(sk), | 878 | NET_INC_STATS(sock_net(sk), |
| 867 | LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); | 879 | LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); |
| 868 | 880 | ||
| 869 | if (unlikely(skb_cloned(skb))) | 881 | if (unlikely(skb_cloned(skb))) |
| 870 | skb = pskb_copy(skb, gfp_mask); | 882 | skb = pskb_copy(skb, gfp_mask); |
| @@ -1904,7 +1916,15 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
| 1904 | 1916 | ||
| 1905 | if (atomic_read(&sk->sk_wmem_alloc) > limit) { | 1917 | if (atomic_read(&sk->sk_wmem_alloc) > limit) { |
| 1906 | set_bit(TSQ_THROTTLED, &tp->tsq_flags); | 1918 | set_bit(TSQ_THROTTLED, &tp->tsq_flags); |
| 1907 | break; | 1919 | /* It is possible TX completion already happened |
| 1920 | * before we set TSQ_THROTTLED, so we must | ||
| 1921 | * test again the condition. | ||
| 1922 | * We abuse smp_mb__after_clear_bit() because | ||
| 1923 | * there is no smp_mb__after_set_bit() yet | ||
| 1924 | */ | ||
| 1925 | smp_mb__after_clear_bit(); | ||
| 1926 | if (atomic_read(&sk->sk_wmem_alloc) > limit) | ||
| 1927 | break; | ||
| 1908 | } | 1928 | } |
| 1909 | 1929 | ||
| 1910 | limit = mss_now; | 1930 | limit = mss_now; |
| @@ -1977,7 +1997,7 @@ bool tcp_schedule_loss_probe(struct sock *sk) | |||
| 1977 | /* Schedule a loss probe in 2*RTT for SACK capable connections | 1997 | /* Schedule a loss probe in 2*RTT for SACK capable connections |
| 1978 | * in Open state, that are either limited by cwnd or application. | 1998 | * in Open state, that are either limited by cwnd or application. |
| 1979 | */ | 1999 | */ |
| 1980 | if (sysctl_tcp_early_retrans < 3 || !rtt || !tp->packets_out || | 2000 | if (sysctl_tcp_early_retrans < 3 || !tp->srtt || !tp->packets_out || |
| 1981 | !tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open) | 2001 | !tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open) |
| 1982 | return false; | 2002 | return false; |
| 1983 | 2003 | ||
| @@ -2328,6 +2348,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
| 2328 | struct tcp_sock *tp = tcp_sk(sk); | 2348 | struct tcp_sock *tp = tcp_sk(sk); |
| 2329 | struct inet_connection_sock *icsk = inet_csk(sk); | 2349 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 2330 | unsigned int cur_mss; | 2350 | unsigned int cur_mss; |
| 2351 | int err; | ||
| 2331 | 2352 | ||
| 2332 | /* Inconslusive MTU probe */ | 2353 | /* Inconslusive MTU probe */ |
| 2333 | if (icsk->icsk_mtup.probe_size) { | 2354 | if (icsk->icsk_mtup.probe_size) { |
| @@ -2391,11 +2412,15 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
| 2391 | skb_headroom(skb) >= 0xFFFF)) { | 2412 | skb_headroom(skb) >= 0xFFFF)) { |
| 2392 | struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, | 2413 | struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, |
| 2393 | GFP_ATOMIC); | 2414 | GFP_ATOMIC); |
| 2394 | return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : | 2415 | err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : |
| 2395 | -ENOBUFS; | 2416 | -ENOBUFS; |
| 2396 | } else { | 2417 | } else { |
| 2397 | return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC); | 2418 | err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC); |
| 2398 | } | 2419 | } |
| 2420 | |||
| 2421 | if (likely(!err)) | ||
| 2422 | TCP_SKB_CB(skb)->sacked |= TCPCB_EVER_RETRANS; | ||
| 2423 | return err; | ||
| 2399 | } | 2424 | } |
| 2400 | 2425 | ||
| 2401 | int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | 2426 | int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) |
| @@ -2899,7 +2924,12 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) | |||
| 2899 | space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) - | 2924 | space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) - |
| 2900 | MAX_TCP_OPTION_SPACE; | 2925 | MAX_TCP_OPTION_SPACE; |
| 2901 | 2926 | ||
| 2902 | syn_data = skb_copy_expand(syn, skb_headroom(syn), space, | 2927 | space = min_t(size_t, space, fo->size); |
| 2928 | |||
| 2929 | /* limit to order-0 allocations */ | ||
| 2930 | space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER)); | ||
| 2931 | |||
| 2932 | syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space, | ||
| 2903 | sk->sk_allocation); | 2933 | sk->sk_allocation); |
| 2904 | if (syn_data == NULL) | 2934 | if (syn_data == NULL) |
| 2905 | goto fallback; | 2935 | goto fallback; |
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 25f5cee3a08a..88b4023ecfcf 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | static DEFINE_SPINLOCK(udp_offload_lock); | 17 | static DEFINE_SPINLOCK(udp_offload_lock); |
| 18 | static struct udp_offload_priv __rcu *udp_offload_base __read_mostly; | 18 | static struct udp_offload_priv __rcu *udp_offload_base __read_mostly; |
| 19 | 19 | ||
| 20 | #define udp_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&udp_offload_lock)) | ||
| 21 | |||
| 20 | struct udp_offload_priv { | 22 | struct udp_offload_priv { |
| 21 | struct udp_offload *offload; | 23 | struct udp_offload *offload; |
| 22 | struct rcu_head rcu; | 24 | struct rcu_head rcu; |
| @@ -100,8 +102,7 @@ out: | |||
| 100 | 102 | ||
| 101 | int udp_add_offload(struct udp_offload *uo) | 103 | int udp_add_offload(struct udp_offload *uo) |
| 102 | { | 104 | { |
| 103 | struct udp_offload_priv __rcu **head = &udp_offload_base; | 105 | struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_ATOMIC); |
| 104 | struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_KERNEL); | ||
| 105 | 106 | ||
| 106 | if (!new_offload) | 107 | if (!new_offload) |
| 107 | return -ENOMEM; | 108 | return -ENOMEM; |
| @@ -109,8 +110,8 @@ int udp_add_offload(struct udp_offload *uo) | |||
| 109 | new_offload->offload = uo; | 110 | new_offload->offload = uo; |
| 110 | 111 | ||
| 111 | spin_lock(&udp_offload_lock); | 112 | spin_lock(&udp_offload_lock); |
| 112 | rcu_assign_pointer(new_offload->next, rcu_dereference(*head)); | 113 | new_offload->next = udp_offload_base; |
| 113 | rcu_assign_pointer(*head, new_offload); | 114 | rcu_assign_pointer(udp_offload_base, new_offload); |
| 114 | spin_unlock(&udp_offload_lock); | 115 | spin_unlock(&udp_offload_lock); |
| 115 | 116 | ||
| 116 | return 0; | 117 | return 0; |
| @@ -130,12 +131,12 @@ void udp_del_offload(struct udp_offload *uo) | |||
| 130 | 131 | ||
| 131 | spin_lock(&udp_offload_lock); | 132 | spin_lock(&udp_offload_lock); |
| 132 | 133 | ||
| 133 | uo_priv = rcu_dereference(*head); | 134 | uo_priv = udp_deref_protected(*head); |
| 134 | for (; uo_priv != NULL; | 135 | for (; uo_priv != NULL; |
| 135 | uo_priv = rcu_dereference(*head)) { | 136 | uo_priv = udp_deref_protected(*head)) { |
| 136 | |||
| 137 | if (uo_priv->offload == uo) { | 137 | if (uo_priv->offload == uo) { |
| 138 | rcu_assign_pointer(*head, rcu_dereference(uo_priv->next)); | 138 | rcu_assign_pointer(*head, |
| 139 | udp_deref_protected(uo_priv->next)); | ||
| 139 | goto unlock; | 140 | goto unlock; |
| 140 | } | 141 | } |
| 141 | head = &uo_priv->next; | 142 | head = &uo_priv->next; |
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index d92e5586783e..438a73aa777c 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
| @@ -138,6 +138,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION | |||
| 138 | config IPV6_VTI | 138 | config IPV6_VTI |
| 139 | tristate "Virtual (secure) IPv6: tunneling" | 139 | tristate "Virtual (secure) IPv6: tunneling" |
| 140 | select IPV6_TUNNEL | 140 | select IPV6_TUNNEL |
| 141 | select NET_IP_TUNNEL | ||
| 141 | depends on INET6_XFRM_MODE_TUNNEL | 142 | depends on INET6_XFRM_MODE_TUNNEL |
| 142 | ---help--- | 143 | ---help--- |
| 143 | Tunneling means encapsulating data of one protocol type within | 144 | Tunneling means encapsulating data of one protocol type within |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ad235690684c..344e972426df 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -1103,8 +1103,11 @@ retry: | |||
| 1103 | * Lifetime is greater than REGEN_ADVANCE time units. In particular, | 1103 | * Lifetime is greater than REGEN_ADVANCE time units. In particular, |
| 1104 | * an implementation must not create a temporary address with a zero | 1104 | * an implementation must not create a temporary address with a zero |
| 1105 | * Preferred Lifetime. | 1105 | * Preferred Lifetime. |
| 1106 | * Use age calculation as in addrconf_verify to avoid unnecessary | ||
| 1107 | * temporary addresses being generated. | ||
| 1106 | */ | 1108 | */ |
| 1107 | if (tmp_prefered_lft <= regen_advance) { | 1109 | age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; |
| 1110 | if (tmp_prefered_lft <= regen_advance + age) { | ||
| 1108 | in6_ifa_put(ifp); | 1111 | in6_ifa_put(ifp); |
| 1109 | in6_dev_put(idev); | 1112 | in6_dev_put(idev); |
| 1110 | ret = -1; | 1113 | ret = -1; |
| @@ -2783,6 +2786,8 @@ static void addrconf_gre_config(struct net_device *dev) | |||
| 2783 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | 2786 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); |
| 2784 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | 2787 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) |
| 2785 | addrconf_add_linklocal(idev, &addr); | 2788 | addrconf_add_linklocal(idev, &addr); |
| 2789 | else | ||
| 2790 | addrconf_prefix_route(&addr, 64, dev, 0, 0); | ||
| 2786 | } | 2791 | } |
| 2787 | #endif | 2792 | #endif |
| 2788 | 2793 | ||
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 140748debc4a..8af3eb57f438 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c | |||
| @@ -212,7 +212,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | |||
| 212 | found = (nexthdr == target); | 212 | found = (nexthdr == target); |
| 213 | 213 | ||
| 214 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { | 214 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { |
| 215 | if (target < 0) | 215 | if (target < 0 || found) |
| 216 | break; | 216 | break; |
| 217 | return -ENOENT; | 217 | return -ENOENT; |
| 218 | } | 218 | } |
diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c index cf77f3abfd06..447a7fbd1bb6 100644 --- a/net/ipv6/exthdrs_offload.c +++ b/net/ipv6/exthdrs_offload.c | |||
| @@ -25,11 +25,11 @@ int __init ipv6_exthdrs_offload_init(void) | |||
| 25 | int ret; | 25 | int ret; |
| 26 | 26 | ||
| 27 | ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING); | 27 | ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING); |
| 28 | if (!ret) | 28 | if (ret) |
| 29 | goto out; | 29 | goto out; |
| 30 | 30 | ||
| 31 | ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS); | 31 | ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS); |
| 32 | if (!ret) | 32 | if (ret) |
| 33 | goto out_rt; | 33 | goto out_rt; |
| 34 | 34 | ||
| 35 | out: | 35 | out: |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f81f59686f21..f2610e157660 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -414,7 +414,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
| 414 | addr_type = ipv6_addr_type(&hdr->daddr); | 414 | addr_type = ipv6_addr_type(&hdr->daddr); |
| 415 | 415 | ||
| 416 | if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0) || | 416 | if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0) || |
| 417 | ipv6_anycast_destination(skb)) | 417 | ipv6_chk_acast_addr_src(net, skb->dev, &hdr->daddr)) |
| 418 | saddr = &hdr->daddr; | 418 | saddr = &hdr->daddr; |
| 419 | 419 | ||
| 420 | /* | 420 | /* |
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 1e8683b135bb..59f95affceb0 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
| @@ -89,7 +89,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 89 | unsigned int unfrag_ip6hlen; | 89 | unsigned int unfrag_ip6hlen; |
| 90 | u8 *prevhdr; | 90 | u8 *prevhdr; |
| 91 | int offset = 0; | 91 | int offset = 0; |
| 92 | bool tunnel; | 92 | bool encap, udpfrag; |
| 93 | int nhoff; | 93 | int nhoff; |
| 94 | 94 | ||
| 95 | if (unlikely(skb_shinfo(skb)->gso_type & | 95 | if (unlikely(skb_shinfo(skb)->gso_type & |
| @@ -110,8 +110,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 110 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | 110 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) |
| 111 | goto out; | 111 | goto out; |
| 112 | 112 | ||
| 113 | tunnel = SKB_GSO_CB(skb)->encap_level > 0; | 113 | encap = SKB_GSO_CB(skb)->encap_level > 0; |
| 114 | if (tunnel) | 114 | if (encap) |
| 115 | features = skb->dev->hw_enc_features & netif_skb_features(skb); | 115 | features = skb->dev->hw_enc_features & netif_skb_features(skb); |
| 116 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); | 116 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); |
| 117 | 117 | ||
| @@ -121,6 +121,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 121 | 121 | ||
| 122 | proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | 122 | proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); |
| 123 | 123 | ||
| 124 | if (skb->encapsulation && | ||
| 125 | skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP)) | ||
| 126 | udpfrag = proto == IPPROTO_UDP && encap; | ||
| 127 | else | ||
| 128 | udpfrag = proto == IPPROTO_UDP && !skb->encapsulation; | ||
| 129 | |||
| 124 | ops = rcu_dereference(inet6_offloads[proto]); | 130 | ops = rcu_dereference(inet6_offloads[proto]); |
| 125 | if (likely(ops && ops->callbacks.gso_segment)) { | 131 | if (likely(ops && ops->callbacks.gso_segment)) { |
| 126 | skb_reset_transport_header(skb); | 132 | skb_reset_transport_header(skb); |
| @@ -133,13 +139,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 133 | for (skb = segs; skb; skb = skb->next) { | 139 | for (skb = segs; skb; skb = skb->next) { |
| 134 | ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff); | 140 | ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff); |
| 135 | ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h)); | 141 | ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h)); |
| 136 | if (tunnel) { | ||
| 137 | skb_reset_inner_headers(skb); | ||
| 138 | skb->encapsulation = 1; | ||
| 139 | } | ||
| 140 | skb->network_header = (u8 *)ipv6h - skb->head; | 142 | skb->network_header = (u8 *)ipv6h - skb->head; |
| 141 | 143 | ||
| 142 | if (!tunnel && proto == IPPROTO_UDP) { | 144 | if (udpfrag) { |
| 143 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); | 145 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); |
| 144 | fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); | 146 | fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); |
| 145 | fptr->frag_off = htons(offset); | 147 | fptr->frag_off = htons(offset); |
| @@ -148,6 +150,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 148 | offset += (ntohs(ipv6h->payload_len) - | 150 | offset += (ntohs(ipv6h->payload_len) - |
| 149 | sizeof(struct frag_hdr)); | 151 | sizeof(struct frag_hdr)); |
| 150 | } | 152 | } |
| 153 | if (encap) | ||
| 154 | skb_reset_inner_headers(skb); | ||
| 151 | } | 155 | } |
| 152 | 156 | ||
| 153 | out: | 157 | out: |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ef02b26ccf81..16f91a2e7888 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -342,6 +342,20 @@ static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) | |||
| 342 | return mtu; | 342 | return mtu; |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) | ||
| 346 | { | ||
| 347 | if (skb->len <= mtu || skb->local_df) | ||
| 348 | return false; | ||
| 349 | |||
| 350 | if (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu) | ||
| 351 | return true; | ||
| 352 | |||
| 353 | if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) | ||
| 354 | return false; | ||
| 355 | |||
| 356 | return true; | ||
| 357 | } | ||
| 358 | |||
| 345 | int ip6_forward(struct sk_buff *skb) | 359 | int ip6_forward(struct sk_buff *skb) |
| 346 | { | 360 | { |
| 347 | struct dst_entry *dst = skb_dst(skb); | 361 | struct dst_entry *dst = skb_dst(skb); |
| @@ -466,8 +480,7 @@ int ip6_forward(struct sk_buff *skb) | |||
| 466 | if (mtu < IPV6_MIN_MTU) | 480 | if (mtu < IPV6_MIN_MTU) |
| 467 | mtu = IPV6_MIN_MTU; | 481 | mtu = IPV6_MIN_MTU; |
| 468 | 482 | ||
| 469 | if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) || | 483 | if (ip6_pkt_too_big(skb, mtu)) { |
| 470 | (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) { | ||
| 471 | /* Again, force OUTPUT device used as source address */ | 484 | /* Again, force OUTPUT device used as source address */ |
| 472 | skb->dev = dst->dev; | 485 | skb->dev = dst->dev; |
| 473 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 486 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
| @@ -517,9 +530,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
| 517 | to->tc_index = from->tc_index; | 530 | to->tc_index = from->tc_index; |
| 518 | #endif | 531 | #endif |
| 519 | nf_copy(to, from); | 532 | nf_copy(to, from); |
| 520 | #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) | ||
| 521 | to->nf_trace = from->nf_trace; | ||
| 522 | #endif | ||
| 523 | skb_copy_secmark(to, from); | 533 | skb_copy_secmark(to, from); |
| 524 | } | 534 | } |
| 525 | 535 | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 35750df744dc..4bff1f297e39 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
| @@ -50,6 +50,11 @@ config NFT_CHAIN_NAT_IPV6 | |||
| 50 | packet transformations such as the source, destination address and | 50 | packet transformations such as the source, destination address and |
| 51 | source and destination ports. | 51 | source and destination ports. |
| 52 | 52 | ||
| 53 | config NFT_REJECT_IPV6 | ||
| 54 | depends on NF_TABLES_IPV6 | ||
| 55 | default NFT_REJECT | ||
| 56 | tristate | ||
| 57 | |||
| 53 | config IP6_NF_IPTABLES | 58 | config IP6_NF_IPTABLES |
| 54 | tristate "IP6 tables support (required for filtering)" | 59 | tristate "IP6 tables support (required for filtering)" |
| 55 | depends on INET && IPV6 | 60 | depends on INET && IPV6 |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index d1b4928f34f7..70d3dd66f2cd 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
| @@ -27,6 +27,7 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | |||
| 27 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o | 27 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o |
| 28 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o | 28 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o |
| 29 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o | 29 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o |
| 30 | obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o | ||
| 30 | 31 | ||
| 31 | # matches | 32 | # matches |
| 32 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o | 33 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o |
diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c new file mode 100644 index 000000000000..0bc19fa87821 --- /dev/null +++ b/net/ipv6/netfilter/nft_reject_ipv6.c | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> | ||
| 3 | * Copyright (c) 2013 Eric Leblond <eric@regit.org> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/netlink.h> | ||
| 16 | #include <linux/netfilter.h> | ||
| 17 | #include <linux/netfilter/nf_tables.h> | ||
| 18 | #include <net/netfilter/nf_tables.h> | ||
| 19 | #include <net/netfilter/nft_reject.h> | ||
| 20 | #include <net/netfilter/ipv6/nf_reject.h> | ||
| 21 | |||
| 22 | void nft_reject_ipv6_eval(const struct nft_expr *expr, | ||
| 23 | struct nft_data data[NFT_REG_MAX + 1], | ||
| 24 | const struct nft_pktinfo *pkt) | ||
| 25 | { | ||
| 26 | struct nft_reject *priv = nft_expr_priv(expr); | ||
| 27 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | ||
| 28 | |||
| 29 | switch (priv->type) { | ||
| 30 | case NFT_REJECT_ICMP_UNREACH: | ||
| 31 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | ||
| 32 | pkt->ops->hooknum); | ||
| 33 | break; | ||
| 34 | case NFT_REJECT_TCP_RST: | ||
| 35 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | ||
| 36 | break; | ||
| 37 | } | ||
| 38 | |||
| 39 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
| 40 | } | ||
| 41 | EXPORT_SYMBOL_GPL(nft_reject_ipv6_eval); | ||
| 42 | |||
| 43 | static struct nft_expr_type nft_reject_ipv6_type; | ||
| 44 | static const struct nft_expr_ops nft_reject_ipv6_ops = { | ||
| 45 | .type = &nft_reject_ipv6_type, | ||
| 46 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
| 47 | .eval = nft_reject_ipv6_eval, | ||
| 48 | .init = nft_reject_init, | ||
| 49 | .dump = nft_reject_dump, | ||
| 50 | }; | ||
| 51 | |||
| 52 | static struct nft_expr_type nft_reject_ipv6_type __read_mostly = { | ||
| 53 | .family = NFPROTO_IPV6, | ||
| 54 | .name = "reject", | ||
| 55 | .ops = &nft_reject_ipv6_ops, | ||
| 56 | .policy = nft_reject_policy, | ||
| 57 | .maxattr = NFTA_REJECT_MAX, | ||
| 58 | .owner = THIS_MODULE, | ||
| 59 | }; | ||
| 60 | |||
| 61 | static int __init nft_reject_ipv6_module_init(void) | ||
| 62 | { | ||
| 63 | return nft_register_expr(&nft_reject_ipv6_type); | ||
| 64 | } | ||
| 65 | |||
| 66 | static void __exit nft_reject_ipv6_module_exit(void) | ||
| 67 | { | ||
| 68 | nft_unregister_expr(&nft_reject_ipv6_type); | ||
| 69 | } | ||
| 70 | |||
| 71 | module_init(nft_reject_ipv6_module_init); | ||
| 72 | module_exit(nft_reject_ipv6_module_exit); | ||
| 73 | |||
| 74 | MODULE_LICENSE("GPL"); | ||
| 75 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 76 | MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "reject"); | ||
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index fb9beb78f00b..587bbdcb22b4 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c | |||
| @@ -135,6 +135,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 135 | fl6.flowi6_proto = IPPROTO_ICMPV6; | 135 | fl6.flowi6_proto = IPPROTO_ICMPV6; |
| 136 | fl6.saddr = np->saddr; | 136 | fl6.saddr = np->saddr; |
| 137 | fl6.daddr = *daddr; | 137 | fl6.daddr = *daddr; |
| 138 | fl6.flowi6_mark = sk->sk_mark; | ||
| 138 | fl6.fl6_icmp_type = user_icmph.icmp6_type; | 139 | fl6.fl6_icmp_type = user_icmph.icmp6_type; |
| 139 | fl6.fl6_icmp_code = user_icmph.icmp6_code; | 140 | fl6.fl6_icmp_code = user_icmph.icmp6_code; |
| 140 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 141 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 11dac21e6586..fba54a407bb2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -1513,7 +1513,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1513 | if (!table) | 1513 | if (!table) |
| 1514 | goto out; | 1514 | goto out; |
| 1515 | 1515 | ||
| 1516 | rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT, table); | 1516 | rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table); |
| 1517 | 1517 | ||
| 1518 | if (!rt) { | 1518 | if (!rt) { |
| 1519 | err = -ENOMEM; | 1519 | err = -ENOMEM; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3dfbcf1dcb1c..b4d74c86586c 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -475,6 +475,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
| 475 | ipip6_tunnel_unlink(sitn, tunnel); | 475 | ipip6_tunnel_unlink(sitn, tunnel); |
| 476 | ipip6_tunnel_del_prl(tunnel, NULL); | 476 | ipip6_tunnel_del_prl(tunnel, NULL); |
| 477 | } | 477 | } |
| 478 | ip_tunnel_dst_reset_all(tunnel); | ||
| 478 | dev_put(dev); | 479 | dev_put(dev); |
| 479 | } | 480 | } |
| 480 | 481 | ||
| @@ -1082,6 +1083,7 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) | |||
| 1082 | t->parms.link = p->link; | 1083 | t->parms.link = p->link; |
| 1083 | ipip6_tunnel_bind_dev(t->dev); | 1084 | ipip6_tunnel_bind_dev(t->dev); |
| 1084 | } | 1085 | } |
| 1086 | ip_tunnel_dst_reset_all(t); | ||
| 1085 | netdev_state_change(t->dev); | 1087 | netdev_state_change(t->dev); |
| 1086 | } | 1088 | } |
| 1087 | 1089 | ||
| @@ -1112,6 +1114,7 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t, | |||
| 1112 | t->ip6rd.relay_prefix = relay_prefix; | 1114 | t->ip6rd.relay_prefix = relay_prefix; |
| 1113 | t->ip6rd.prefixlen = ip6rd->prefixlen; | 1115 | t->ip6rd.prefixlen = ip6rd->prefixlen; |
| 1114 | t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; | 1116 | t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; |
| 1117 | ip_tunnel_dst_reset_all(t); | ||
| 1115 | netdev_state_change(t->dev); | 1118 | netdev_state_change(t->dev); |
| 1116 | return 0; | 1119 | return 0; |
| 1117 | } | 1120 | } |
| @@ -1271,6 +1274,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1271 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); | 1274 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); |
| 1272 | break; | 1275 | break; |
| 1273 | } | 1276 | } |
| 1277 | ip_tunnel_dst_reset_all(t); | ||
| 1274 | netdev_state_change(dev); | 1278 | netdev_state_change(dev); |
| 1275 | break; | 1279 | break; |
| 1276 | 1280 | ||
| @@ -1326,6 +1330,9 @@ static const struct net_device_ops ipip6_netdev_ops = { | |||
| 1326 | 1330 | ||
| 1327 | static void ipip6_dev_free(struct net_device *dev) | 1331 | static void ipip6_dev_free(struct net_device *dev) |
| 1328 | { | 1332 | { |
| 1333 | struct ip_tunnel *tunnel = netdev_priv(dev); | ||
| 1334 | |||
| 1335 | free_percpu(tunnel->dst_cache); | ||
| 1329 | free_percpu(dev->tstats); | 1336 | free_percpu(dev->tstats); |
| 1330 | free_netdev(dev); | 1337 | free_netdev(dev); |
| 1331 | } | 1338 | } |
| @@ -1375,6 +1382,12 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
| 1375 | u64_stats_init(&ipip6_tunnel_stats->syncp); | 1382 | u64_stats_init(&ipip6_tunnel_stats->syncp); |
| 1376 | } | 1383 | } |
| 1377 | 1384 | ||
| 1385 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | ||
| 1386 | if (!tunnel->dst_cache) { | ||
| 1387 | free_percpu(dev->tstats); | ||
| 1388 | return -ENOMEM; | ||
| 1389 | } | ||
| 1390 | |||
| 1378 | return 0; | 1391 | return 0; |
| 1379 | } | 1392 | } |
| 1380 | 1393 | ||
| @@ -1405,6 +1418,12 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
| 1405 | u64_stats_init(&ipip6_fb_stats->syncp); | 1418 | u64_stats_init(&ipip6_fb_stats->syncp); |
| 1406 | } | 1419 | } |
| 1407 | 1420 | ||
| 1421 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | ||
| 1422 | if (!tunnel->dst_cache) { | ||
| 1423 | free_percpu(dev->tstats); | ||
| 1424 | return -ENOMEM; | ||
| 1425 | } | ||
| 1426 | |||
| 1408 | dev_hold(dev); | 1427 | dev_hold(dev); |
| 1409 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); | 1428 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); |
| 1410 | return 0; | 1429 | return 0; |
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index e7359f9eaa8d..b261ee8b83fc 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
| @@ -113,7 +113,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
| 113 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); | 113 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); |
| 114 | fptr->nexthdr = nexthdr; | 114 | fptr->nexthdr = nexthdr; |
| 115 | fptr->reserved = 0; | 115 | fptr->reserved = 0; |
| 116 | ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb)); | 116 | fptr->identification = skb_shinfo(skb)->ip6_frag_id; |
| 117 | 117 | ||
| 118 | /* Fragment the skb. ipv6 header and the remaining fields of the | 118 | /* Fragment the skb. ipv6 header and the remaining fields of the |
| 119 | * fragment header are updated in ipv6_gso_segment() | 119 | * fragment header are updated in ipv6_gso_segment() |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 994e28bfb32e..00b2a6d1c009 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
| @@ -52,18 +52,12 @@ | |||
| 52 | #include <net/p8022.h> | 52 | #include <net/p8022.h> |
| 53 | #include <net/psnap.h> | 53 | #include <net/psnap.h> |
| 54 | #include <net/sock.h> | 54 | #include <net/sock.h> |
| 55 | #include <net/datalink.h> | ||
| 55 | #include <net/tcp_states.h> | 56 | #include <net/tcp_states.h> |
| 57 | #include <net/net_namespace.h> | ||
| 56 | 58 | ||
| 57 | #include <asm/uaccess.h> | 59 | #include <asm/uaccess.h> |
| 58 | 60 | ||
| 59 | #ifdef CONFIG_SYSCTL | ||
| 60 | extern void ipx_register_sysctl(void); | ||
| 61 | extern void ipx_unregister_sysctl(void); | ||
| 62 | #else | ||
| 63 | #define ipx_register_sysctl() | ||
| 64 | #define ipx_unregister_sysctl() | ||
| 65 | #endif | ||
| 66 | |||
| 67 | /* Configuration Variables */ | 61 | /* Configuration Variables */ |
| 68 | static unsigned char ipxcfg_max_hops = 16; | 62 | static unsigned char ipxcfg_max_hops = 16; |
| 69 | static char ipxcfg_auto_select_primary; | 63 | static char ipxcfg_auto_select_primary; |
| @@ -84,15 +78,6 @@ DEFINE_SPINLOCK(ipx_interfaces_lock); | |||
| 84 | struct ipx_interface *ipx_primary_net; | 78 | struct ipx_interface *ipx_primary_net; |
| 85 | struct ipx_interface *ipx_internal_net; | 79 | struct ipx_interface *ipx_internal_net; |
| 86 | 80 | ||
| 87 | extern int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, | ||
| 88 | unsigned char *node); | ||
| 89 | extern void ipxrtr_del_routes(struct ipx_interface *intrfc); | ||
| 90 | extern int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, | ||
| 91 | struct iovec *iov, size_t len, int noblock); | ||
| 92 | extern int ipxrtr_route_skb(struct sk_buff *skb); | ||
| 93 | extern struct ipx_route *ipxrtr_lookup(__be32 net); | ||
| 94 | extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg); | ||
| 95 | |||
| 96 | struct ipx_interface *ipx_interfaces_head(void) | 81 | struct ipx_interface *ipx_interfaces_head(void) |
| 97 | { | 82 | { |
| 98 | struct ipx_interface *rc = NULL; | 83 | struct ipx_interface *rc = NULL; |
| @@ -1986,9 +1971,6 @@ static struct notifier_block ipx_dev_notifier = { | |||
| 1986 | .notifier_call = ipxitf_device_event, | 1971 | .notifier_call = ipxitf_device_event, |
| 1987 | }; | 1972 | }; |
| 1988 | 1973 | ||
| 1989 | extern struct datalink_proto *make_EII_client(void); | ||
| 1990 | extern void destroy_EII_client(struct datalink_proto *); | ||
| 1991 | |||
| 1992 | static const unsigned char ipx_8022_type = 0xE0; | 1974 | static const unsigned char ipx_8022_type = 0xE0; |
| 1993 | static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; | 1975 | static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; |
| 1994 | static const char ipx_EII_err_msg[] __initconst = | 1976 | static const char ipx_EII_err_msg[] __initconst = |
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c index 30f4519b092f..c1f03185c5e1 100644 --- a/net/ipx/ipx_route.c +++ b/net/ipx/ipx_route.c | |||
| @@ -20,15 +20,11 @@ DEFINE_RWLOCK(ipx_routes_lock); | |||
| 20 | 20 | ||
| 21 | extern struct ipx_interface *ipx_internal_net; | 21 | extern struct ipx_interface *ipx_internal_net; |
| 22 | 22 | ||
| 23 | extern __be16 ipx_cksum(struct ipxhdr *packet, int length); | ||
| 24 | extern struct ipx_interface *ipxitf_find_using_net(__be32 net); | 23 | extern struct ipx_interface *ipxitf_find_using_net(__be32 net); |
| 25 | extern int ipxitf_demux_socket(struct ipx_interface *intrfc, | 24 | extern int ipxitf_demux_socket(struct ipx_interface *intrfc, |
| 26 | struct sk_buff *skb, int copy); | 25 | struct sk_buff *skb, int copy); |
| 27 | extern int ipxitf_demux_socket(struct ipx_interface *intrfc, | 26 | extern int ipxitf_demux_socket(struct ipx_interface *intrfc, |
| 28 | struct sk_buff *skb, int copy); | 27 | struct sk_buff *skb, int copy); |
| 29 | extern int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, | ||
| 30 | char *node); | ||
| 31 | extern struct ipx_interface *ipxitf_find_using_net(__be32 net); | ||
| 32 | 28 | ||
| 33 | struct ipx_route *ipxrtr_lookup(__be32 net) | 29 | struct ipx_route *ipxrtr_lookup(__be32 net) |
| 34 | { | 30 | { |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 735d0f60c83a..85d9d94c0a3c 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -112,7 +112,6 @@ struct l2tp_net { | |||
| 112 | spinlock_t l2tp_session_hlist_lock; | 112 | spinlock_t l2tp_session_hlist_lock; |
| 113 | }; | 113 | }; |
| 114 | 114 | ||
| 115 | static void l2tp_session_set_header_len(struct l2tp_session *session, int version); | ||
| 116 | static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); | 115 | static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); |
| 117 | 116 | ||
| 118 | static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) | 117 | static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) |
| @@ -1863,7 +1862,7 @@ EXPORT_SYMBOL_GPL(l2tp_session_delete); | |||
| 1863 | /* We come here whenever a session's send_seq, cookie_len or | 1862 | /* We come here whenever a session's send_seq, cookie_len or |
| 1864 | * l2specific_len parameters are set. | 1863 | * l2specific_len parameters are set. |
| 1865 | */ | 1864 | */ |
| 1866 | static void l2tp_session_set_header_len(struct l2tp_session *session, int version) | 1865 | void l2tp_session_set_header_len(struct l2tp_session *session, int version) |
| 1867 | { | 1866 | { |
| 1868 | if (version == L2TP_HDR_VER_2) { | 1867 | if (version == L2TP_HDR_VER_2) { |
| 1869 | session->hdr_len = 6; | 1868 | session->hdr_len = 6; |
| @@ -1876,6 +1875,7 @@ static void l2tp_session_set_header_len(struct l2tp_session *session, int versio | |||
| 1876 | } | 1875 | } |
| 1877 | 1876 | ||
| 1878 | } | 1877 | } |
| 1878 | EXPORT_SYMBOL_GPL(l2tp_session_set_header_len); | ||
| 1879 | 1879 | ||
| 1880 | struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) | 1880 | struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) |
| 1881 | { | 1881 | { |
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 1f01ba3435bc..3f93ccd6ba97 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h | |||
| @@ -263,6 +263,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, | |||
| 263 | int length, int (*payload_hook)(struct sk_buff *skb)); | 263 | int length, int (*payload_hook)(struct sk_buff *skb)); |
| 264 | int l2tp_session_queue_purge(struct l2tp_session *session); | 264 | int l2tp_session_queue_purge(struct l2tp_session *session); |
| 265 | int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); | 265 | int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); |
| 266 | void l2tp_session_set_header_len(struct l2tp_session *session, int version); | ||
| 266 | 267 | ||
| 267 | int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, | 268 | int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, |
| 268 | int hdr_len); | 269 | int hdr_len); |
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 4cfd722e9153..bd7387adea9e 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c | |||
| @@ -578,8 +578,10 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf | |||
| 578 | if (info->attrs[L2TP_ATTR_RECV_SEQ]) | 578 | if (info->attrs[L2TP_ATTR_RECV_SEQ]) |
| 579 | session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]); | 579 | session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]); |
| 580 | 580 | ||
| 581 | if (info->attrs[L2TP_ATTR_SEND_SEQ]) | 581 | if (info->attrs[L2TP_ATTR_SEND_SEQ]) { |
| 582 | session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]); | 582 | session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]); |
| 583 | l2tp_session_set_header_len(session, session->tunnel->version); | ||
| 584 | } | ||
| 583 | 585 | ||
| 584 | if (info->attrs[L2TP_ATTR_LNS_MODE]) | 586 | if (info->attrs[L2TP_ATTR_LNS_MODE]) |
| 585 | session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]); | 587 | session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]); |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index be5fadf34739..5990919356a5 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
| @@ -254,12 +254,14 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int | |||
| 254 | po = pppox_sk(sk); | 254 | po = pppox_sk(sk); |
| 255 | ppp_input(&po->chan, skb); | 255 | ppp_input(&po->chan, skb); |
| 256 | } else { | 256 | } else { |
| 257 | l2tp_info(session, PPPOL2TP_MSG_DATA, "%s: socket not bound\n", | 257 | l2tp_dbg(session, PPPOL2TP_MSG_DATA, |
| 258 | session->name); | 258 | "%s: recv %d byte data frame, passing to L2TP socket\n", |
| 259 | session->name, data_len); | ||
| 259 | 260 | ||
| 260 | /* Not bound. Nothing we can do, so discard. */ | 261 | if (sock_queue_rcv_skb(sk, skb) < 0) { |
| 261 | atomic_long_inc(&session->stats.rx_errors); | 262 | atomic_long_inc(&session->stats.rx_errors); |
| 262 | kfree_skb(skb); | 263 | kfree_skb(skb); |
| 264 | } | ||
| 263 | } | 265 | } |
| 264 | 266 | ||
| 265 | return; | 267 | return; |
| @@ -1312,6 +1314,7 @@ static int pppol2tp_session_setsockopt(struct sock *sk, | |||
| 1312 | po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ : | 1314 | po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ : |
| 1313 | PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; | 1315 | PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; |
| 1314 | } | 1316 | } |
| 1317 | l2tp_session_set_header_len(session, session->tunnel->version); | ||
| 1315 | l2tp_info(session, PPPOL2TP_MSG_CONTROL, | 1318 | l2tp_info(session, PPPOL2TP_MSG_CONTROL, |
| 1316 | "%s: set send_seq=%d\n", | 1319 | "%s: set send_seq=%d\n", |
| 1317 | session->name, session->send_seq); | 1320 | session->name, session->send_seq); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f9ae9b85d4c1..453e974287d1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
| 1021 | IEEE80211_P2P_OPPPS_ENABLE_BIT; | 1021 | IEEE80211_P2P_OPPPS_ENABLE_BIT; |
| 1022 | 1022 | ||
| 1023 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon); | 1023 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon); |
| 1024 | if (err < 0) | 1024 | if (err < 0) { |
| 1025 | ieee80211_vif_release_channel(sdata); | ||
| 1025 | return err; | 1026 | return err; |
| 1027 | } | ||
| 1026 | changed |= err; | 1028 | changed |= err; |
| 1027 | 1029 | ||
| 1028 | err = drv_start_ap(sdata->local, sdata); | 1030 | err = drv_start_ap(sdata->local, sdata); |
| @@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
| 1032 | if (old) | 1034 | if (old) |
| 1033 | kfree_rcu(old, rcu_head); | 1035 | kfree_rcu(old, rcu_head); |
| 1034 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | 1036 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
| 1037 | ieee80211_vif_release_channel(sdata); | ||
| 1035 | return err; | 1038 | return err; |
| 1036 | } | 1039 | } |
| 1037 | 1040 | ||
| @@ -1090,8 +1093,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 1090 | kfree(sdata->u.ap.next_beacon); | 1093 | kfree(sdata->u.ap.next_beacon); |
| 1091 | sdata->u.ap.next_beacon = NULL; | 1094 | sdata->u.ap.next_beacon = NULL; |
| 1092 | 1095 | ||
| 1093 | cancel_work_sync(&sdata->u.ap.request_smps_work); | ||
| 1094 | |||
| 1095 | /* turn off carrier for this interface and dependent VLANs */ | 1096 | /* turn off carrier for this interface and dependent VLANs */ |
| 1096 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1097 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
| 1097 | netif_carrier_off(vlan->dev); | 1098 | netif_carrier_off(vlan->dev); |
| @@ -1103,6 +1104,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 1103 | kfree_rcu(old_beacon, rcu_head); | 1104 | kfree_rcu(old_beacon, rcu_head); |
| 1104 | if (old_probe_resp) | 1105 | if (old_probe_resp) |
| 1105 | kfree_rcu(old_probe_resp, rcu_head); | 1106 | kfree_rcu(old_probe_resp, rcu_head); |
| 1107 | sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; | ||
| 1106 | 1108 | ||
| 1107 | __sta_info_flush(sdata, true); | 1109 | __sta_info_flush(sdata, true); |
| 1108 | ieee80211_free_keys(sdata, true); | 1110 | ieee80211_free_keys(sdata, true); |
| @@ -2638,6 +2640,24 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
| 2638 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); | 2640 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); |
| 2639 | INIT_LIST_HEAD(&roc->dependents); | 2641 | INIT_LIST_HEAD(&roc->dependents); |
| 2640 | 2642 | ||
| 2643 | /* | ||
| 2644 | * cookie is either the roc cookie (for normal roc) | ||
| 2645 | * or the SKB (for mgmt TX) | ||
| 2646 | */ | ||
| 2647 | if (!txskb) { | ||
| 2648 | /* local->mtx protects this */ | ||
| 2649 | local->roc_cookie_counter++; | ||
| 2650 | roc->cookie = local->roc_cookie_counter; | ||
| 2651 | /* wow, you wrapped 64 bits ... more likely a bug */ | ||
| 2652 | if (WARN_ON(roc->cookie == 0)) { | ||
| 2653 | roc->cookie = 1; | ||
| 2654 | local->roc_cookie_counter++; | ||
| 2655 | } | ||
| 2656 | *cookie = roc->cookie; | ||
| 2657 | } else { | ||
| 2658 | *cookie = (unsigned long)txskb; | ||
| 2659 | } | ||
| 2660 | |||
| 2641 | /* if there's one pending or we're scanning, queue this one */ | 2661 | /* if there's one pending or we're scanning, queue this one */ |
| 2642 | if (!list_empty(&local->roc_list) || | 2662 | if (!list_empty(&local->roc_list) || |
| 2643 | local->scanning || local->radar_detect_enabled) | 2663 | local->scanning || local->radar_detect_enabled) |
| @@ -2772,24 +2792,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
| 2772 | if (!queued) | 2792 | if (!queued) |
| 2773 | list_add_tail(&roc->list, &local->roc_list); | 2793 | list_add_tail(&roc->list, &local->roc_list); |
| 2774 | 2794 | ||
| 2775 | /* | ||
| 2776 | * cookie is either the roc cookie (for normal roc) | ||
| 2777 | * or the SKB (for mgmt TX) | ||
| 2778 | */ | ||
| 2779 | if (!txskb) { | ||
| 2780 | /* local->mtx protects this */ | ||
| 2781 | local->roc_cookie_counter++; | ||
| 2782 | roc->cookie = local->roc_cookie_counter; | ||
| 2783 | /* wow, you wrapped 64 bits ... more likely a bug */ | ||
| 2784 | if (WARN_ON(roc->cookie == 0)) { | ||
| 2785 | roc->cookie = 1; | ||
| 2786 | local->roc_cookie_counter++; | ||
| 2787 | } | ||
| 2788 | *cookie = roc->cookie; | ||
| 2789 | } else { | ||
| 2790 | *cookie = (unsigned long)txskb; | ||
| 2791 | } | ||
| 2792 | |||
| 2793 | return 0; | 2795 | return 0; |
| 2794 | } | 2796 | } |
| 2795 | 2797 | ||
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f43613a97dd6..0c1ecfdf9a12 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
| @@ -100,6 +100,12 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, | |||
| 100 | } | 100 | } |
| 101 | max_bw = max(max_bw, width); | 101 | max_bw = max(max_bw, width); |
| 102 | } | 102 | } |
| 103 | |||
| 104 | /* use the configured bandwidth in case of monitor interface */ | ||
| 105 | sdata = rcu_dereference(local->monitor_sdata); | ||
| 106 | if (sdata && rcu_access_pointer(sdata->vif.chanctx_conf) == conf) | ||
| 107 | max_bw = max(max_bw, conf->def.width); | ||
| 108 | |||
| 103 | rcu_read_unlock(); | 109 | rcu_read_unlock(); |
| 104 | 110 | ||
| 105 | return max_bw; | 111 | return max_bw; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index fab7b91923e0..70dd013de836 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
| @@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(struct work_struct *work) | |||
| 466 | u.ap.request_smps_work); | 466 | u.ap.request_smps_work); |
| 467 | 467 | ||
| 468 | sdata_lock(sdata); | 468 | sdata_lock(sdata); |
| 469 | __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode); | 469 | if (sdata_dereference(sdata->u.ap.beacon, sdata)) |
| 470 | __ieee80211_request_smps_ap(sdata, | ||
| 471 | sdata->u.ap.driver_smps_mode); | ||
| 470 | sdata_unlock(sdata); | 472 | sdata_unlock(sdata); |
| 471 | } | 473 | } |
| 472 | 474 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 771080ec7212..2796a198728f 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
| @@ -695,12 +695,9 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) | |||
| 695 | struct cfg80211_bss *cbss; | 695 | struct cfg80211_bss *cbss; |
| 696 | struct beacon_data *presp; | 696 | struct beacon_data *presp; |
| 697 | struct sta_info *sta; | 697 | struct sta_info *sta; |
| 698 | int active_ibss; | ||
| 699 | u16 capability; | 698 | u16 capability; |
| 700 | 699 | ||
| 701 | active_ibss = ieee80211_sta_active_ibss(sdata); | 700 | if (!is_zero_ether_addr(ifibss->bssid)) { |
| 702 | |||
| 703 | if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { | ||
| 704 | capability = WLAN_CAPABILITY_IBSS; | 701 | capability = WLAN_CAPABILITY_IBSS; |
| 705 | 702 | ||
| 706 | if (ifibss->privacy) | 703 | if (ifibss->privacy) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3701930c6649..5e44e3179e02 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -1692,14 +1692,8 @@ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | |||
| 1692 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); | 1692 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); |
| 1693 | void ieee80211_add_pending_skb(struct ieee80211_local *local, | 1693 | void ieee80211_add_pending_skb(struct ieee80211_local *local, |
| 1694 | struct sk_buff *skb); | 1694 | struct sk_buff *skb); |
| 1695 | void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | 1695 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, |
| 1696 | struct sk_buff_head *skbs, | 1696 | struct sk_buff_head *skbs); |
| 1697 | void (*fn)(void *data), void *data); | ||
| 1698 | static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, | ||
| 1699 | struct sk_buff_head *skbs) | ||
| 1700 | { | ||
| 1701 | ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); | ||
| 1702 | } | ||
| 1703 | void ieee80211_flush_queues(struct ieee80211_local *local, | 1697 | void ieee80211_flush_queues(struct ieee80211_local *local, |
| 1704 | struct ieee80211_sub_if_data *sdata); | 1698 | struct ieee80211_sub_if_data *sdata); |
| 1705 | 1699 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3dfd20a453ab..ce1c44370610 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -418,20 +418,24 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
| 418 | return ret; | 418 | return ret; |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | mutex_lock(&local->iflist_mtx); | ||
| 422 | rcu_assign_pointer(local->monitor_sdata, sdata); | ||
| 423 | mutex_unlock(&local->iflist_mtx); | ||
| 424 | |||
| 421 | mutex_lock(&local->mtx); | 425 | mutex_lock(&local->mtx); |
| 422 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, | 426 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
| 423 | IEEE80211_CHANCTX_EXCLUSIVE); | 427 | IEEE80211_CHANCTX_EXCLUSIVE); |
| 424 | mutex_unlock(&local->mtx); | 428 | mutex_unlock(&local->mtx); |
| 425 | if (ret) { | 429 | if (ret) { |
| 430 | mutex_lock(&local->iflist_mtx); | ||
| 431 | rcu_assign_pointer(local->monitor_sdata, NULL); | ||
| 432 | mutex_unlock(&local->iflist_mtx); | ||
| 433 | synchronize_net(); | ||
| 426 | drv_remove_interface(local, sdata); | 434 | drv_remove_interface(local, sdata); |
| 427 | kfree(sdata); | 435 | kfree(sdata); |
| 428 | return ret; | 436 | return ret; |
| 429 | } | 437 | } |
| 430 | 438 | ||
| 431 | mutex_lock(&local->iflist_mtx); | ||
| 432 | rcu_assign_pointer(local->monitor_sdata, sdata); | ||
| 433 | mutex_unlock(&local->iflist_mtx); | ||
| 434 | |||
| 435 | return 0; | 439 | return 0; |
| 436 | } | 440 | } |
| 437 | 441 | ||
| @@ -770,12 +774,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
| 770 | 774 | ||
| 771 | ieee80211_roc_purge(local, sdata); | 775 | ieee80211_roc_purge(local, sdata); |
| 772 | 776 | ||
| 773 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 777 | switch (sdata->vif.type) { |
| 778 | case NL80211_IFTYPE_STATION: | ||
| 774 | ieee80211_mgd_stop(sdata); | 779 | ieee80211_mgd_stop(sdata); |
| 775 | 780 | break; | |
| 776 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 781 | case NL80211_IFTYPE_ADHOC: |
| 777 | ieee80211_ibss_stop(sdata); | 782 | ieee80211_ibss_stop(sdata); |
| 778 | 783 | break; | |
| 784 | case NL80211_IFTYPE_AP: | ||
| 785 | cancel_work_sync(&sdata->u.ap.request_smps_work); | ||
| 786 | break; | ||
| 787 | default: | ||
| 788 | break; | ||
| 789 | } | ||
| 779 | 790 | ||
| 780 | /* | 791 | /* |
| 781 | * Remove all stations associated with this interface. | 792 | * Remove all stations associated with this interface. |
| @@ -1046,7 +1057,8 @@ static void ieee80211_uninit(struct net_device *dev) | |||
| 1046 | 1057 | ||
| 1047 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, | 1058 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, |
| 1048 | struct sk_buff *skb, | 1059 | struct sk_buff *skb, |
| 1049 | void *accel_priv) | 1060 | void *accel_priv, |
| 1061 | select_queue_fallback_t fallback) | ||
| 1050 | { | 1062 | { |
| 1051 | return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); | 1063 | return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); |
| 1052 | } | 1064 | } |
| @@ -1064,7 +1076,8 @@ static const struct net_device_ops ieee80211_dataif_ops = { | |||
| 1064 | 1076 | ||
| 1065 | static u16 ieee80211_monitor_select_queue(struct net_device *dev, | 1077 | static u16 ieee80211_monitor_select_queue(struct net_device *dev, |
| 1066 | struct sk_buff *skb, | 1078 | struct sk_buff *skb, |
| 1067 | void *accel_priv) | 1079 | void *accel_priv, |
| 1080 | select_queue_fallback_t fallback) | ||
| 1068 | { | 1081 | { |
| 1069 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1082 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1070 | struct ieee80211_local *local = sdata->local; | 1083 | struct ieee80211_local *local = sdata->local; |
diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c index 2802f9d9279d..ad8b377b4b9f 100644 --- a/net/mac80211/mesh_ps.c +++ b/net/mac80211/mesh_ps.c | |||
| @@ -36,6 +36,7 @@ static struct sk_buff *mps_qos_null_get(struct sta_info *sta) | |||
| 36 | sdata->vif.addr); | 36 | sdata->vif.addr); |
| 37 | nullfunc->frame_control = fc; | 37 | nullfunc->frame_control = fc; |
| 38 | nullfunc->duration_id = 0; | 38 | nullfunc->duration_id = 0; |
| 39 | nullfunc->seq_ctrl = 0; | ||
| 39 | /* no address resolution for this frame -> set addr 1 immediately */ | 40 | /* no address resolution for this frame -> set addr 1 immediately */ |
| 40 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); | 41 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); |
| 41 | memset(skb_put(skb, 2), 0, 2); /* append QoS control field */ | 42 | memset(skb_put(skb, 2), 0, 2); /* append QoS control field */ |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fc1d82465b3c..245dce969b31 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -222,6 +222,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 222 | switch (vht_oper->chan_width) { | 222 | switch (vht_oper->chan_width) { |
| 223 | case IEEE80211_VHT_CHANWIDTH_USE_HT: | 223 | case IEEE80211_VHT_CHANWIDTH_USE_HT: |
| 224 | vht_chandef.width = chandef->width; | 224 | vht_chandef.width = chandef->width; |
| 225 | vht_chandef.center_freq1 = chandef->center_freq1; | ||
| 225 | break; | 226 | break; |
| 226 | case IEEE80211_VHT_CHANWIDTH_80MHZ: | 227 | case IEEE80211_VHT_CHANWIDTH_80MHZ: |
| 227 | vht_chandef.width = NL80211_CHAN_WIDTH_80; | 228 | vht_chandef.width = NL80211_CHAN_WIDTH_80; |
| @@ -271,6 +272,28 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 271 | ret = 0; | 272 | ret = 0; |
| 272 | 273 | ||
| 273 | out: | 274 | out: |
| 275 | /* | ||
| 276 | * When tracking the current AP, don't do any further checks if the | ||
| 277 | * new chandef is identical to the one we're currently using for the | ||
| 278 | * connection. This keeps us from playing ping-pong with regulatory, | ||
| 279 | * without it the following can happen (for example): | ||
| 280 | * - connect to an AP with 80 MHz, world regdom allows 80 MHz | ||
| 281 | * - AP advertises regdom US | ||
| 282 | * - CRDA loads regdom US with 80 MHz prohibited (old database) | ||
| 283 | * - the code below detects an unsupported channel, downgrades, and | ||
| 284 | * we disconnect from the AP in the caller | ||
| 285 | * - disconnect causes CRDA to reload world regdomain and the game | ||
| 286 | * starts anew. | ||
| 287 | * (see https://bugzilla.kernel.org/show_bug.cgi?id=70881) | ||
| 288 | * | ||
| 289 | * It seems possible that there are still scenarios with CSA or real | ||
| 290 | * bandwidth changes where a this could happen, but those cases are | ||
| 291 | * less common and wouldn't completely prevent using the AP. | ||
| 292 | */ | ||
| 293 | if (tracking && | ||
| 294 | cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) | ||
| 295 | return ret; | ||
| 296 | |||
| 274 | /* don't print the message below for VHT mismatch if VHT is disabled */ | 297 | /* don't print the message below for VHT mismatch if VHT is disabled */ |
| 275 | if (ret & IEEE80211_STA_DISABLE_VHT) | 298 | if (ret & IEEE80211_STA_DISABLE_VHT) |
| 276 | vht_chandef = *chandef; | 299 | vht_chandef = *chandef; |
| @@ -3753,6 +3776,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
| 3753 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 3776 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
| 3754 | if (WARN_ON(!chanctx_conf)) { | 3777 | if (WARN_ON(!chanctx_conf)) { |
| 3755 | rcu_read_unlock(); | 3778 | rcu_read_unlock(); |
| 3779 | sta_info_free(local, new_sta); | ||
| 3756 | return -EINVAL; | 3780 | return -EINVAL; |
| 3757 | } | 3781 | } |
| 3758 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | 3782 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c24ca0d0f469..3e57f96c9666 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info *sta) | |||
| 1128 | sta->sta.addr, sta->sta.aid); | 1128 | sta->sta.addr, sta->sta.aid); |
| 1129 | 1129 | ||
| 1130 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | 1130 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { |
| 1131 | /* | ||
| 1132 | * Clear the flag only if the other one is still set | ||
| 1133 | * so that the TX path won't start TX'ing new frames | ||
| 1134 | * directly ... In the case that the driver flag isn't | ||
| 1135 | * set ieee80211_sta_ps_deliver_wakeup() will clear it. | ||
| 1136 | */ | ||
| 1137 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
| 1131 | ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n", | 1138 | ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n", |
| 1132 | sta->sta.addr, sta->sta.aid); | 1139 | sta->sta.addr, sta->sta.aid); |
| 1133 | return; | 1140 | return; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index decd30c1e290..137a192e64bc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
| @@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
| 91 | return -ENOENT; | 91 | return -ENOENT; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static void cleanup_single_sta(struct sta_info *sta) | 94 | static void __cleanup_single_sta(struct sta_info *sta) |
| 95 | { | 95 | { |
| 96 | int ac, i; | 96 | int ac, i; |
| 97 | struct tid_ampdu_tx *tid_tx; | 97 | struct tid_ampdu_tx *tid_tx; |
| @@ -99,7 +99,8 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
| 99 | struct ieee80211_local *local = sdata->local; | 99 | struct ieee80211_local *local = sdata->local; |
| 100 | struct ps_data *ps; | 100 | struct ps_data *ps; |
| 101 | 101 | ||
| 102 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | 102 | if (test_sta_flag(sta, WLAN_STA_PS_STA) || |
| 103 | test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | ||
| 103 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || | 104 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || |
| 104 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 105 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| 105 | ps = &sdata->bss->ps; | 106 | ps = &sdata->bss->ps; |
| @@ -109,6 +110,7 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
| 109 | return; | 110 | return; |
| 110 | 111 | ||
| 111 | clear_sta_flag(sta, WLAN_STA_PS_STA); | 112 | clear_sta_flag(sta, WLAN_STA_PS_STA); |
| 113 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
| 112 | 114 | ||
| 113 | atomic_dec(&ps->num_sta_ps); | 115 | atomic_dec(&ps->num_sta_ps); |
| 114 | sta_info_recalc_tim(sta); | 116 | sta_info_recalc_tim(sta); |
| @@ -139,7 +141,14 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
| 139 | ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); | 141 | ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); |
| 140 | kfree(tid_tx); | 142 | kfree(tid_tx); |
| 141 | } | 143 | } |
| 144 | } | ||
| 142 | 145 | ||
| 146 | static void cleanup_single_sta(struct sta_info *sta) | ||
| 147 | { | ||
| 148 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
| 149 | struct ieee80211_local *local = sdata->local; | ||
| 150 | |||
| 151 | __cleanup_single_sta(sta); | ||
| 143 | sta_info_free(local, sta); | 152 | sta_info_free(local, sta); |
| 144 | } | 153 | } |
| 145 | 154 | ||
| @@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
| 330 | rcu_read_unlock(); | 339 | rcu_read_unlock(); |
| 331 | 340 | ||
| 332 | spin_lock_init(&sta->lock); | 341 | spin_lock_init(&sta->lock); |
| 342 | spin_lock_init(&sta->ps_lock); | ||
| 333 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | 343 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); |
| 334 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | 344 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); |
| 335 | mutex_init(&sta->ampdu_mlme.mtx); | 345 | mutex_init(&sta->ampdu_mlme.mtx); |
| @@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
| 487 | goto out_err; | 497 | goto out_err; |
| 488 | } | 498 | } |
| 489 | 499 | ||
| 490 | /* notify driver */ | ||
| 491 | err = sta_info_insert_drv_state(local, sdata, sta); | ||
| 492 | if (err) | ||
| 493 | goto out_err; | ||
| 494 | |||
| 495 | local->num_sta++; | 500 | local->num_sta++; |
| 496 | local->sta_generation++; | 501 | local->sta_generation++; |
| 497 | smp_mb(); | 502 | smp_mb(); |
| 498 | 503 | ||
| 504 | /* simplify things and don't accept BA sessions yet */ | ||
| 505 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | ||
| 506 | |||
| 499 | /* make the station visible */ | 507 | /* make the station visible */ |
| 500 | sta_info_hash_add(local, sta); | 508 | sta_info_hash_add(local, sta); |
| 501 | 509 | ||
| 502 | list_add_rcu(&sta->list, &local->sta_list); | 510 | list_add_rcu(&sta->list, &local->sta_list); |
| 503 | 511 | ||
| 512 | /* notify driver */ | ||
| 513 | err = sta_info_insert_drv_state(local, sdata, sta); | ||
| 514 | if (err) | ||
| 515 | goto out_remove; | ||
| 516 | |||
| 504 | set_sta_flag(sta, WLAN_STA_INSERTED); | 517 | set_sta_flag(sta, WLAN_STA_INSERTED); |
| 518 | /* accept BA sessions now */ | ||
| 519 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); | ||
| 505 | 520 | ||
| 506 | ieee80211_recalc_min_chandef(sdata); | 521 | ieee80211_recalc_min_chandef(sdata); |
| 507 | ieee80211_sta_debugfs_add(sta); | 522 | ieee80211_sta_debugfs_add(sta); |
| @@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
| 522 | mesh_accept_plinks_update(sdata); | 537 | mesh_accept_plinks_update(sdata); |
| 523 | 538 | ||
| 524 | return 0; | 539 | return 0; |
| 540 | out_remove: | ||
| 541 | sta_info_hash_del(local, sta); | ||
| 542 | list_del_rcu(&sta->list); | ||
| 543 | local->num_sta--; | ||
| 544 | synchronize_net(); | ||
| 545 | __cleanup_single_sta(sta); | ||
| 525 | out_err: | 546 | out_err: |
| 526 | mutex_unlock(&local->sta_mtx); | 547 | mutex_unlock(&local->sta_mtx); |
| 527 | rcu_read_lock(); | 548 | rcu_read_lock(); |
| @@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, | |||
| 1071 | } | 1092 | } |
| 1072 | EXPORT_SYMBOL(ieee80211_find_sta); | 1093 | EXPORT_SYMBOL(ieee80211_find_sta); |
| 1073 | 1094 | ||
| 1074 | static void clear_sta_ps_flags(void *_sta) | 1095 | /* powersave support code */ |
| 1096 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | ||
| 1075 | { | 1097 | { |
| 1076 | struct sta_info *sta = _sta; | ||
| 1077 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1098 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
| 1099 | struct ieee80211_local *local = sdata->local; | ||
| 1100 | struct sk_buff_head pending; | ||
| 1101 | int filtered = 0, buffered = 0, ac; | ||
| 1102 | unsigned long flags; | ||
| 1078 | struct ps_data *ps; | 1103 | struct ps_data *ps; |
| 1079 | 1104 | ||
| 1080 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 1105 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
| @@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_sta) | |||
| 1085 | else | 1110 | else |
| 1086 | return; | 1111 | return; |
| 1087 | 1112 | ||
| 1088 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
| 1089 | if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA)) | ||
| 1090 | atomic_dec(&ps->num_sta_ps); | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | /* powersave support code */ | ||
| 1094 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | ||
| 1095 | { | ||
| 1096 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
| 1097 | struct ieee80211_local *local = sdata->local; | ||
| 1098 | struct sk_buff_head pending; | ||
| 1099 | int filtered = 0, buffered = 0, ac; | ||
| 1100 | unsigned long flags; | ||
| 1101 | |||
| 1102 | clear_sta_flag(sta, WLAN_STA_SP); | 1113 | clear_sta_flag(sta, WLAN_STA_SP); |
| 1103 | 1114 | ||
| 1104 | BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); | 1115 | BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); |
| @@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
| 1109 | 1120 | ||
| 1110 | skb_queue_head_init(&pending); | 1121 | skb_queue_head_init(&pending); |
| 1111 | 1122 | ||
| 1123 | /* sync with ieee80211_tx_h_unicast_ps_buf */ | ||
| 1124 | spin_lock(&sta->ps_lock); | ||
| 1112 | /* Send all buffered frames to the station */ | 1125 | /* Send all buffered frames to the station */ |
| 1113 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 1126 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
| 1114 | int count = skb_queue_len(&pending), tmp; | 1127 | int count = skb_queue_len(&pending), tmp; |
| @@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
| 1127 | buffered += tmp - count; | 1140 | buffered += tmp - count; |
| 1128 | } | 1141 | } |
| 1129 | 1142 | ||
| 1130 | ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); | 1143 | ieee80211_add_pending_skbs(local, &pending); |
| 1144 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
| 1145 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
| 1146 | spin_unlock(&sta->ps_lock); | ||
| 1147 | |||
| 1148 | atomic_dec(&ps->num_sta_ps); | ||
| 1131 | 1149 | ||
| 1132 | /* This station just woke up and isn't aware of our SMPS state */ | 1150 | /* This station just woke up and isn't aware of our SMPS state */ |
| 1133 | if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, | 1151 | if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, |
| @@ -1188,6 +1206,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | |||
| 1188 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); | 1206 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); |
| 1189 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); | 1207 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); |
| 1190 | memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); | 1208 | memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); |
| 1209 | nullfunc->seq_ctrl = 0; | ||
| 1191 | 1210 | ||
| 1192 | skb->priority = tid; | 1211 | skb->priority = tid; |
| 1193 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); | 1212 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d77ff7090630..d3a6d8208f2f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
| @@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat { | |||
| 267 | * @drv_unblock_wk: used for driver PS unblocking | 267 | * @drv_unblock_wk: used for driver PS unblocking |
| 268 | * @listen_interval: listen interval of this station, when we're acting as AP | 268 | * @listen_interval: listen interval of this station, when we're acting as AP |
| 269 | * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly | 269 | * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly |
| 270 | * @ps_lock: used for powersave (when mac80211 is the AP) related locking | ||
| 270 | * @ps_tx_buf: buffers (per AC) of frames to transmit to this station | 271 | * @ps_tx_buf: buffers (per AC) of frames to transmit to this station |
| 271 | * when it leaves power saving state or polls | 272 | * when it leaves power saving state or polls |
| 272 | * @tx_filtered: buffers (per AC) of frames we already tried to | 273 | * @tx_filtered: buffers (per AC) of frames we already tried to |
| @@ -356,10 +357,8 @@ struct sta_info { | |||
| 356 | /* use the accessors defined below */ | 357 | /* use the accessors defined below */ |
| 357 | unsigned long _flags; | 358 | unsigned long _flags; |
| 358 | 359 | ||
| 359 | /* | 360 | /* STA powersave lock and frame queues */ |
| 360 | * STA powersave frame queues, no more than the internal | 361 | spinlock_t ps_lock; |
| 361 | * locking required. | ||
| 362 | */ | ||
| 363 | struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; | 362 | struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; |
| 364 | struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; | 363 | struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; |
| 365 | unsigned long driver_buffered_tids; | 364 | unsigned long driver_buffered_tids; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 27c990bf2320..4080c615636f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -478,6 +478,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
| 478 | sta->sta.addr, sta->sta.aid, ac); | 478 | sta->sta.addr, sta->sta.aid, ac); |
| 479 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 479 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
| 480 | purge_old_ps_buffers(tx->local); | 480 | purge_old_ps_buffers(tx->local); |
| 481 | |||
| 482 | /* sync with ieee80211_sta_ps_deliver_wakeup */ | ||
| 483 | spin_lock(&sta->ps_lock); | ||
| 484 | /* | ||
| 485 | * STA woke up the meantime and all the frames on ps_tx_buf have | ||
| 486 | * been queued to pending queue. No reordering can happen, go | ||
| 487 | * ahead and Tx the packet. | ||
| 488 | */ | ||
| 489 | if (!test_sta_flag(sta, WLAN_STA_PS_STA) && | ||
| 490 | !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | ||
| 491 | spin_unlock(&sta->ps_lock); | ||
| 492 | return TX_CONTINUE; | ||
| 493 | } | ||
| 494 | |||
| 481 | if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { | 495 | if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { |
| 482 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); | 496 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); |
| 483 | ps_dbg(tx->sdata, | 497 | ps_dbg(tx->sdata, |
| @@ -492,6 +506,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
| 492 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 506 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
| 493 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; | 507 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; |
| 494 | skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); | 508 | skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); |
| 509 | spin_unlock(&sta->ps_lock); | ||
| 495 | 510 | ||
| 496 | if (!timer_pending(&local->sta_cleanup)) | 511 | if (!timer_pending(&local->sta_cleanup)) |
| 497 | mod_timer(&local->sta_cleanup, | 512 | mod_timer(&local->sta_cleanup, |
| @@ -878,7 +893,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx, | |||
| 878 | } | 893 | } |
| 879 | 894 | ||
| 880 | /* adjust first fragment's length */ | 895 | /* adjust first fragment's length */ |
| 881 | skb->len = hdrlen + per_fragm; | 896 | skb_trim(skb, hdrlen + per_fragm); |
| 882 | return 0; | 897 | return 0; |
| 883 | } | 898 | } |
| 884 | 899 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 676dc0967f37..b8700d417a9c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
| 435 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 435 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | 438 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, |
| 439 | struct sk_buff_head *skbs, | 439 | struct sk_buff_head *skbs) |
| 440 | void (*fn)(void *data), void *data) | ||
| 441 | { | 440 | { |
| 442 | struct ieee80211_hw *hw = &local->hw; | 441 | struct ieee80211_hw *hw = &local->hw; |
| 443 | struct sk_buff *skb; | 442 | struct sk_buff *skb; |
| @@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
| 461 | __skb_queue_tail(&local->pending[queue], skb); | 460 | __skb_queue_tail(&local->pending[queue], skb); |
| 462 | } | 461 | } |
| 463 | 462 | ||
| 464 | if (fn) | ||
| 465 | fn(data); | ||
| 466 | |||
| 467 | for (i = 0; i < hw->queues; i++) | 463 | for (i = 0; i < hw->queues; i++) |
| 468 | __ieee80211_wake_queue(hw, i, | 464 | __ieee80211_wake_queue(hw, i, |
| 469 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 465 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
| @@ -1741,6 +1737,26 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1741 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 1737 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
| 1742 | 1738 | ||
| 1743 | /* | 1739 | /* |
| 1740 | * Reconfigure sched scan if it was interrupted by FW restart or | ||
| 1741 | * suspend. | ||
| 1742 | */ | ||
| 1743 | mutex_lock(&local->mtx); | ||
| 1744 | sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata, | ||
| 1745 | lockdep_is_held(&local->mtx)); | ||
| 1746 | if (sched_scan_sdata && local->sched_scan_req) | ||
| 1747 | /* | ||
| 1748 | * Sched scan stopped, but we don't want to report it. Instead, | ||
| 1749 | * we're trying to reschedule. | ||
| 1750 | */ | ||
| 1751 | if (__ieee80211_request_sched_scan_start(sched_scan_sdata, | ||
| 1752 | local->sched_scan_req)) | ||
| 1753 | sched_scan_stopped = true; | ||
| 1754 | mutex_unlock(&local->mtx); | ||
| 1755 | |||
| 1756 | if (sched_scan_stopped) | ||
| 1757 | cfg80211_sched_scan_stopped(local->hw.wiphy); | ||
| 1758 | |||
| 1759 | /* | ||
| 1744 | * If this is for hw restart things are still running. | 1760 | * If this is for hw restart things are still running. |
| 1745 | * We may want to change that later, however. | 1761 | * We may want to change that later, however. |
| 1746 | */ | 1762 | */ |
| @@ -1768,26 +1784,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1768 | WARN_ON(1); | 1784 | WARN_ON(1); |
| 1769 | #endif | 1785 | #endif |
| 1770 | 1786 | ||
| 1771 | /* | ||
| 1772 | * Reconfigure sched scan if it was interrupted by FW restart or | ||
| 1773 | * suspend. | ||
| 1774 | */ | ||
| 1775 | mutex_lock(&local->mtx); | ||
| 1776 | sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata, | ||
| 1777 | lockdep_is_held(&local->mtx)); | ||
| 1778 | if (sched_scan_sdata && local->sched_scan_req) | ||
| 1779 | /* | ||
| 1780 | * Sched scan stopped, but we don't want to report it. Instead, | ||
| 1781 | * we're trying to reschedule. | ||
| 1782 | */ | ||
| 1783 | if (__ieee80211_request_sched_scan_start(sched_scan_sdata, | ||
| 1784 | local->sched_scan_req)) | ||
| 1785 | sched_scan_stopped = true; | ||
| 1786 | mutex_unlock(&local->mtx); | ||
| 1787 | |||
| 1788 | if (sched_scan_stopped) | ||
| 1789 | cfg80211_sched_scan_stopped(local->hw.wiphy); | ||
| 1790 | |||
| 1791 | return 0; | 1787 | return 0; |
| 1792 | } | 1788 | } |
| 1793 | 1789 | ||
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 21211c60ca98..d51422c778de 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
| @@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
| 154 | return IEEE80211_AC_BE; | 154 | return IEEE80211_AC_BE; |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | if (skb->protocol == sdata->control_port_protocol) { | ||
| 158 | skb->priority = 7; | ||
| 159 | return ieee80211_downgrade_queue(sdata, skb); | ||
| 160 | } | ||
| 161 | |||
| 157 | /* use the data classifier to determine what 802.1d tag the | 162 | /* use the data classifier to determine what 802.1d tag the |
| 158 | * data frame has */ | 163 | * data frame has */ |
| 159 | rcu_read_lock(); | 164 | rcu_read_lock(); |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c37467562fd0..e9410d17619d 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -513,7 +513,6 @@ config NFT_QUEUE | |||
| 513 | 513 | ||
| 514 | config NFT_REJECT | 514 | config NFT_REJECT |
| 515 | depends on NF_TABLES | 515 | depends on NF_TABLES |
| 516 | depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6 | ||
| 517 | default m if NETFILTER_ADVANCED=n | 516 | default m if NETFILTER_ADVANCED=n |
| 518 | tristate "Netfilter nf_tables reject support" | 517 | tristate "Netfilter nf_tables reject support" |
| 519 | help | 518 | help |
| @@ -521,6 +520,11 @@ config NFT_REJECT | |||
| 521 | explicitly deny and notify via TCP reset/ICMP informational errors | 520 | explicitly deny and notify via TCP reset/ICMP informational errors |
| 522 | unallowed traffic. | 521 | unallowed traffic. |
| 523 | 522 | ||
| 523 | config NFT_REJECT_INET | ||
| 524 | depends on NF_TABLES_INET | ||
| 525 | default NFT_REJECT | ||
| 526 | tristate | ||
| 527 | |||
| 524 | config NFT_COMPAT | 528 | config NFT_COMPAT |
| 525 | depends on NF_TABLES | 529 | depends on NF_TABLES |
| 526 | depends on NETFILTER_XTABLES | 530 | depends on NETFILTER_XTABLES |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index ee9c4de5f8ed..bffdad774da7 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
| @@ -79,6 +79,7 @@ obj-$(CONFIG_NFT_LIMIT) += nft_limit.o | |||
| 79 | obj-$(CONFIG_NFT_NAT) += nft_nat.o | 79 | obj-$(CONFIG_NFT_NAT) += nft_nat.o |
| 80 | obj-$(CONFIG_NFT_QUEUE) += nft_queue.o | 80 | obj-$(CONFIG_NFT_QUEUE) += nft_queue.o |
| 81 | obj-$(CONFIG_NFT_REJECT) += nft_reject.o | 81 | obj-$(CONFIG_NFT_REJECT) += nft_reject.o |
| 82 | obj-$(CONFIG_NFT_REJECT_INET) += nft_reject_inet.o | ||
| 82 | obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o | 83 | obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o |
| 83 | obj-$(CONFIG_NFT_HASH) += nft_hash.o | 84 | obj-$(CONFIG_NFT_HASH) += nft_hash.o |
| 84 | obj-$(CONFIG_NFT_COUNTER) += nft_counter.o | 85 | obj-$(CONFIG_NFT_COUNTER) += nft_counter.o |
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 59a1a85bcb3e..a8eb0a89326a 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c | |||
| @@ -871,11 +871,11 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, | |||
| 871 | cp->protocol = p->protocol; | 871 | cp->protocol = p->protocol; |
| 872 | ip_vs_addr_set(p->af, &cp->caddr, p->caddr); | 872 | ip_vs_addr_set(p->af, &cp->caddr, p->caddr); |
| 873 | cp->cport = p->cport; | 873 | cp->cport = p->cport; |
| 874 | ip_vs_addr_set(p->af, &cp->vaddr, p->vaddr); | 874 | /* proto should only be IPPROTO_IP if p->vaddr is a fwmark */ |
| 875 | cp->vport = p->vport; | ||
| 876 | /* proto should only be IPPROTO_IP if d_addr is a fwmark */ | ||
| 877 | ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af, | 875 | ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af, |
| 878 | &cp->daddr, daddr); | 876 | &cp->vaddr, p->vaddr); |
| 877 | cp->vport = p->vport; | ||
| 878 | ip_vs_addr_set(p->af, &cp->daddr, daddr); | ||
| 879 | cp->dport = dport; | 879 | cp->dport = dport; |
| 880 | cp->flags = flags; | 880 | cp->flags = flags; |
| 881 | cp->fwmark = fwmark; | 881 | cp->fwmark = fwmark; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 8824ed0ccc9c..356bef519fe5 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -312,6 +312,21 @@ static void death_by_timeout(unsigned long ul_conntrack) | |||
| 312 | nf_ct_delete((struct nf_conn *)ul_conntrack, 0, 0); | 312 | nf_ct_delete((struct nf_conn *)ul_conntrack, 0, 0); |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | static inline bool | ||
| 316 | nf_ct_key_equal(struct nf_conntrack_tuple_hash *h, | ||
| 317 | const struct nf_conntrack_tuple *tuple, | ||
| 318 | u16 zone) | ||
| 319 | { | ||
| 320 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); | ||
| 321 | |||
| 322 | /* A conntrack can be recreated with the equal tuple, | ||
| 323 | * so we need to check that the conntrack is confirmed | ||
| 324 | */ | ||
| 325 | return nf_ct_tuple_equal(tuple, &h->tuple) && | ||
| 326 | nf_ct_zone(ct) == zone && | ||
| 327 | nf_ct_is_confirmed(ct); | ||
| 328 | } | ||
| 329 | |||
| 315 | /* | 330 | /* |
| 316 | * Warning : | 331 | * Warning : |
| 317 | * - Caller must take a reference on returned object | 332 | * - Caller must take a reference on returned object |
| @@ -333,8 +348,7 @@ ____nf_conntrack_find(struct net *net, u16 zone, | |||
| 333 | local_bh_disable(); | 348 | local_bh_disable(); |
| 334 | begin: | 349 | begin: |
| 335 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) { | 350 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) { |
| 336 | if (nf_ct_tuple_equal(tuple, &h->tuple) && | 351 | if (nf_ct_key_equal(h, tuple, zone)) { |
| 337 | nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) { | ||
| 338 | NF_CT_STAT_INC(net, found); | 352 | NF_CT_STAT_INC(net, found); |
| 339 | local_bh_enable(); | 353 | local_bh_enable(); |
| 340 | return h; | 354 | return h; |
| @@ -372,8 +386,7 @@ begin: | |||
| 372 | !atomic_inc_not_zero(&ct->ct_general.use))) | 386 | !atomic_inc_not_zero(&ct->ct_general.use))) |
| 373 | h = NULL; | 387 | h = NULL; |
| 374 | else { | 388 | else { |
| 375 | if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) || | 389 | if (unlikely(!nf_ct_key_equal(h, tuple, zone))) { |
| 376 | nf_ct_zone(ct) != zone)) { | ||
| 377 | nf_ct_put(ct); | 390 | nf_ct_put(ct); |
| 378 | goto begin; | 391 | goto begin; |
| 379 | } | 392 | } |
| @@ -435,7 +448,9 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) | |||
| 435 | goto out; | 448 | goto out; |
| 436 | 449 | ||
| 437 | add_timer(&ct->timeout); | 450 | add_timer(&ct->timeout); |
| 438 | nf_conntrack_get(&ct->ct_general); | 451 | smp_wmb(); |
| 452 | /* The caller holds a reference to this object */ | ||
| 453 | atomic_set(&ct->ct_general.use, 2); | ||
| 439 | __nf_conntrack_hash_insert(ct, hash, repl_hash); | 454 | __nf_conntrack_hash_insert(ct, hash, repl_hash); |
| 440 | NF_CT_STAT_INC(net, insert); | 455 | NF_CT_STAT_INC(net, insert); |
| 441 | spin_unlock_bh(&nf_conntrack_lock); | 456 | spin_unlock_bh(&nf_conntrack_lock); |
| @@ -449,6 +464,21 @@ out: | |||
| 449 | } | 464 | } |
| 450 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); | 465 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); |
| 451 | 466 | ||
| 467 | /* deletion from this larval template list happens via nf_ct_put() */ | ||
| 468 | void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl) | ||
| 469 | { | ||
| 470 | __set_bit(IPS_TEMPLATE_BIT, &tmpl->status); | ||
| 471 | __set_bit(IPS_CONFIRMED_BIT, &tmpl->status); | ||
| 472 | nf_conntrack_get(&tmpl->ct_general); | ||
| 473 | |||
| 474 | spin_lock_bh(&nf_conntrack_lock); | ||
| 475 | /* Overload tuple linked list to put us in template list. */ | ||
| 476 | hlist_nulls_add_head_rcu(&tmpl->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | ||
| 477 | &net->ct.tmpl); | ||
| 478 | spin_unlock_bh(&nf_conntrack_lock); | ||
| 479 | } | ||
| 480 | EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert); | ||
| 481 | |||
| 452 | /* Confirm a connection given skb; places it in hash table */ | 482 | /* Confirm a connection given skb; places it in hash table */ |
| 453 | int | 483 | int |
| 454 | __nf_conntrack_confirm(struct sk_buff *skb) | 484 | __nf_conntrack_confirm(struct sk_buff *skb) |
| @@ -720,11 +750,10 @@ __nf_conntrack_alloc(struct net *net, u16 zone, | |||
| 720 | nf_ct_zone->id = zone; | 750 | nf_ct_zone->id = zone; |
| 721 | } | 751 | } |
| 722 | #endif | 752 | #endif |
| 723 | /* | 753 | /* Because we use RCU lookups, we set ct_general.use to zero before |
| 724 | * changes to lookup keys must be done before setting refcnt to 1 | 754 | * this is inserted in any list. |
| 725 | */ | 755 | */ |
| 726 | smp_wmb(); | 756 | atomic_set(&ct->ct_general.use, 0); |
| 727 | atomic_set(&ct->ct_general.use, 1); | ||
| 728 | return ct; | 757 | return ct; |
| 729 | 758 | ||
| 730 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 759 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
| @@ -748,6 +777,11 @@ void nf_conntrack_free(struct nf_conn *ct) | |||
| 748 | { | 777 | { |
| 749 | struct net *net = nf_ct_net(ct); | 778 | struct net *net = nf_ct_net(ct); |
| 750 | 779 | ||
| 780 | /* A freed object has refcnt == 0, that's | ||
| 781 | * the golden rule for SLAB_DESTROY_BY_RCU | ||
| 782 | */ | ||
| 783 | NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 0); | ||
| 784 | |||
| 751 | nf_ct_ext_destroy(ct); | 785 | nf_ct_ext_destroy(ct); |
| 752 | nf_ct_ext_free(ct); | 786 | nf_ct_ext_free(ct); |
| 753 | kmem_cache_free(net->ct.nf_conntrack_cachep, ct); | 787 | kmem_cache_free(net->ct.nf_conntrack_cachep, ct); |
| @@ -843,6 +877,9 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
| 843 | NF_CT_STAT_INC(net, new); | 877 | NF_CT_STAT_INC(net, new); |
| 844 | } | 878 | } |
| 845 | 879 | ||
| 880 | /* Now it is inserted into the unconfirmed list, bump refcount */ | ||
| 881 | nf_conntrack_get(&ct->ct_general); | ||
| 882 | |||
| 846 | /* Overload tuple linked list to put us in unconfirmed list. */ | 883 | /* Overload tuple linked list to put us in unconfirmed list. */ |
| 847 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | 884 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, |
| 848 | &net->ct.unconfirmed); | 885 | &net->ct.unconfirmed); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index bb322d0beb48..b9f0e0374322 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -1310,27 +1310,22 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[]) | |||
| 1310 | } | 1310 | } |
| 1311 | 1311 | ||
| 1312 | static int | 1312 | static int |
| 1313 | ctnetlink_change_nat(struct nf_conn *ct, const struct nlattr * const cda[]) | 1313 | ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[]) |
| 1314 | { | 1314 | { |
| 1315 | #ifdef CONFIG_NF_NAT_NEEDED | 1315 | #ifdef CONFIG_NF_NAT_NEEDED |
| 1316 | int ret; | 1316 | int ret; |
| 1317 | 1317 | ||
| 1318 | if (cda[CTA_NAT_DST]) { | 1318 | ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST, |
| 1319 | ret = ctnetlink_parse_nat_setup(ct, | 1319 | cda[CTA_NAT_DST]); |
| 1320 | NF_NAT_MANIP_DST, | 1320 | if (ret < 0) |
| 1321 | cda[CTA_NAT_DST]); | 1321 | return ret; |
| 1322 | if (ret < 0) | 1322 | |
| 1323 | return ret; | 1323 | ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_SRC, |
| 1324 | } | 1324 | cda[CTA_NAT_SRC]); |
| 1325 | if (cda[CTA_NAT_SRC]) { | 1325 | return ret; |
| 1326 | ret = ctnetlink_parse_nat_setup(ct, | ||
| 1327 | NF_NAT_MANIP_SRC, | ||
| 1328 | cda[CTA_NAT_SRC]); | ||
| 1329 | if (ret < 0) | ||
| 1330 | return ret; | ||
| 1331 | } | ||
| 1332 | return 0; | ||
| 1333 | #else | 1326 | #else |
| 1327 | if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC]) | ||
| 1328 | return 0; | ||
| 1334 | return -EOPNOTSUPP; | 1329 | return -EOPNOTSUPP; |
| 1335 | #endif | 1330 | #endif |
| 1336 | } | 1331 | } |
| @@ -1659,11 +1654,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
| 1659 | goto err2; | 1654 | goto err2; |
| 1660 | } | 1655 | } |
| 1661 | 1656 | ||
| 1662 | if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { | 1657 | err = ctnetlink_setup_nat(ct, cda); |
| 1663 | err = ctnetlink_change_nat(ct, cda); | 1658 | if (err < 0) |
| 1664 | if (err < 0) | 1659 | goto err2; |
| 1665 | goto err2; | ||
| 1666 | } | ||
| 1667 | 1660 | ||
| 1668 | nf_ct_acct_ext_add(ct, GFP_ATOMIC); | 1661 | nf_ct_acct_ext_add(ct, GFP_ATOMIC); |
| 1669 | nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); | 1662 | nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); |
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index d3f5cd6dd962..52ca952b802c 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c | |||
| @@ -432,15 +432,15 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
| 432 | } | 432 | } |
| 433 | EXPORT_SYMBOL(nf_nat_setup_info); | 433 | EXPORT_SYMBOL(nf_nat_setup_info); |
| 434 | 434 | ||
| 435 | unsigned int | 435 | static unsigned int |
| 436 | nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | 436 | __nf_nat_alloc_null_binding(struct nf_conn *ct, enum nf_nat_manip_type manip) |
| 437 | { | 437 | { |
| 438 | /* Force range to this IP; let proto decide mapping for | 438 | /* Force range to this IP; let proto decide mapping for |
| 439 | * per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). | 439 | * per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). |
| 440 | * Use reply in case it's already been mangled (eg local packet). | 440 | * Use reply in case it's already been mangled (eg local packet). |
| 441 | */ | 441 | */ |
| 442 | union nf_inet_addr ip = | 442 | union nf_inet_addr ip = |
| 443 | (HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ? | 443 | (manip == NF_NAT_MANIP_SRC ? |
| 444 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3 : | 444 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3 : |
| 445 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3); | 445 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3); |
| 446 | struct nf_nat_range range = { | 446 | struct nf_nat_range range = { |
| @@ -448,7 +448,13 @@ nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | |||
| 448 | .min_addr = ip, | 448 | .min_addr = ip, |
| 449 | .max_addr = ip, | 449 | .max_addr = ip, |
| 450 | }; | 450 | }; |
| 451 | return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum)); | 451 | return nf_nat_setup_info(ct, &range, manip); |
| 452 | } | ||
| 453 | |||
| 454 | unsigned int | ||
| 455 | nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | ||
| 456 | { | ||
| 457 | return __nf_nat_alloc_null_binding(ct, HOOK2MANIP(hooknum)); | ||
| 452 | } | 458 | } |
| 453 | EXPORT_SYMBOL_GPL(nf_nat_alloc_null_binding); | 459 | EXPORT_SYMBOL_GPL(nf_nat_alloc_null_binding); |
| 454 | 460 | ||
| @@ -702,9 +708,9 @@ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { | |||
| 702 | 708 | ||
| 703 | static int | 709 | static int |
| 704 | nfnetlink_parse_nat(const struct nlattr *nat, | 710 | nfnetlink_parse_nat(const struct nlattr *nat, |
| 705 | const struct nf_conn *ct, struct nf_nat_range *range) | 711 | const struct nf_conn *ct, struct nf_nat_range *range, |
| 712 | const struct nf_nat_l3proto *l3proto) | ||
| 706 | { | 713 | { |
| 707 | const struct nf_nat_l3proto *l3proto; | ||
| 708 | struct nlattr *tb[CTA_NAT_MAX+1]; | 714 | struct nlattr *tb[CTA_NAT_MAX+1]; |
| 709 | int err; | 715 | int err; |
| 710 | 716 | ||
| @@ -714,38 +720,46 @@ nfnetlink_parse_nat(const struct nlattr *nat, | |||
| 714 | if (err < 0) | 720 | if (err < 0) |
| 715 | return err; | 721 | return err; |
| 716 | 722 | ||
| 717 | rcu_read_lock(); | ||
| 718 | l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); | ||
| 719 | if (l3proto == NULL) { | ||
| 720 | err = -EAGAIN; | ||
| 721 | goto out; | ||
| 722 | } | ||
| 723 | err = l3proto->nlattr_to_range(tb, range); | 723 | err = l3proto->nlattr_to_range(tb, range); |
| 724 | if (err < 0) | 724 | if (err < 0) |
| 725 | goto out; | 725 | return err; |
| 726 | 726 | ||
| 727 | if (!tb[CTA_NAT_PROTO]) | 727 | if (!tb[CTA_NAT_PROTO]) |
| 728 | goto out; | 728 | return 0; |
| 729 | 729 | ||
| 730 | err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); | 730 | return nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); |
| 731 | out: | ||
| 732 | rcu_read_unlock(); | ||
| 733 | return err; | ||
| 734 | } | 731 | } |
| 735 | 732 | ||
| 733 | /* This function is called under rcu_read_lock() */ | ||
| 736 | static int | 734 | static int |
| 737 | nfnetlink_parse_nat_setup(struct nf_conn *ct, | 735 | nfnetlink_parse_nat_setup(struct nf_conn *ct, |
| 738 | enum nf_nat_manip_type manip, | 736 | enum nf_nat_manip_type manip, |
| 739 | const struct nlattr *attr) | 737 | const struct nlattr *attr) |
| 740 | { | 738 | { |
| 741 | struct nf_nat_range range; | 739 | struct nf_nat_range range; |
| 740 | const struct nf_nat_l3proto *l3proto; | ||
| 742 | int err; | 741 | int err; |
| 743 | 742 | ||
| 744 | err = nfnetlink_parse_nat(attr, ct, &range); | 743 | /* Should not happen, restricted to creating new conntracks |
| 744 | * via ctnetlink. | ||
| 745 | */ | ||
| 746 | if (WARN_ON_ONCE(nf_nat_initialized(ct, manip))) | ||
| 747 | return -EEXIST; | ||
| 748 | |||
| 749 | /* Make sure that L3 NAT is there by when we call nf_nat_setup_info to | ||
| 750 | * attach the null binding, otherwise this may oops. | ||
| 751 | */ | ||
| 752 | l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); | ||
| 753 | if (l3proto == NULL) | ||
| 754 | return -EAGAIN; | ||
| 755 | |||
| 756 | /* No NAT information has been passed, allocate the null-binding */ | ||
| 757 | if (attr == NULL) | ||
| 758 | return __nf_nat_alloc_null_binding(ct, manip); | ||
| 759 | |||
| 760 | err = nfnetlink_parse_nat(attr, ct, &range, l3proto); | ||
| 745 | if (err < 0) | 761 | if (err < 0) |
| 746 | return err; | 762 | return err; |
| 747 | if (nf_nat_initialized(ct, manip)) | ||
| 748 | return -EEXIST; | ||
| 749 | 763 | ||
| 750 | return nf_nat_setup_info(ct, &range, manip); | 764 | return nf_nat_setup_info(ct, &range, manip); |
| 751 | } | 765 | } |
diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c index 9858e3e51a3a..52e20c9a46a5 100644 --- a/net/netfilter/nf_synproxy_core.c +++ b/net/netfilter/nf_synproxy_core.c | |||
| @@ -363,9 +363,8 @@ static int __net_init synproxy_net_init(struct net *net) | |||
| 363 | goto err2; | 363 | goto err2; |
| 364 | if (!nfct_synproxy_ext_add(ct)) | 364 | if (!nfct_synproxy_ext_add(ct)) |
| 365 | goto err2; | 365 | goto err2; |
| 366 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); | ||
| 367 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | ||
| 368 | 366 | ||
| 367 | nf_conntrack_tmpl_insert(net, ct); | ||
| 369 | snet->tmpl = ct; | 368 | snet->tmpl = ct; |
| 370 | 369 | ||
| 371 | snet->stats = alloc_percpu(struct synproxy_stats); | 370 | snet->stats = alloc_percpu(struct synproxy_stats); |
| @@ -390,7 +389,7 @@ static void __net_exit synproxy_net_exit(struct net *net) | |||
| 390 | { | 389 | { |
| 391 | struct synproxy_net *snet = synproxy_pernet(net); | 390 | struct synproxy_net *snet = synproxy_pernet(net); |
| 392 | 391 | ||
| 393 | nf_conntrack_free(snet->tmpl); | 392 | nf_ct_put(snet->tmpl); |
| 394 | synproxy_proc_exit(net); | 393 | synproxy_proc_exit(net); |
| 395 | free_percpu(snet->stats); | 394 | free_percpu(snet->stats); |
| 396 | } | 395 | } |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 117bbaaddde6..adce01e8bb57 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -1008,10 +1008,8 @@ notify: | |||
| 1008 | return 0; | 1008 | return 0; |
| 1009 | } | 1009 | } |
| 1010 | 1010 | ||
| 1011 | static void nf_tables_rcu_chain_destroy(struct rcu_head *head) | 1011 | static void nf_tables_chain_destroy(struct nft_chain *chain) |
| 1012 | { | 1012 | { |
| 1013 | struct nft_chain *chain = container_of(head, struct nft_chain, rcu_head); | ||
| 1014 | |||
| 1015 | BUG_ON(chain->use > 0); | 1013 | BUG_ON(chain->use > 0); |
| 1016 | 1014 | ||
| 1017 | if (chain->flags & NFT_BASE_CHAIN) { | 1015 | if (chain->flags & NFT_BASE_CHAIN) { |
| @@ -1045,7 +1043,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 1045 | if (IS_ERR(chain)) | 1043 | if (IS_ERR(chain)) |
| 1046 | return PTR_ERR(chain); | 1044 | return PTR_ERR(chain); |
| 1047 | 1045 | ||
| 1048 | if (!list_empty(&chain->rules)) | 1046 | if (!list_empty(&chain->rules) || chain->use > 0) |
| 1049 | return -EBUSY; | 1047 | return -EBUSY; |
| 1050 | 1048 | ||
| 1051 | list_del(&chain->list); | 1049 | list_del(&chain->list); |
| @@ -1059,7 +1057,9 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 1059 | family); | 1057 | family); |
| 1060 | 1058 | ||
| 1061 | /* Make sure all rule references are gone before this is released */ | 1059 | /* Make sure all rule references are gone before this is released */ |
| 1062 | call_rcu(&chain->rcu_head, nf_tables_rcu_chain_destroy); | 1060 | synchronize_rcu(); |
| 1061 | |||
| 1062 | nf_tables_chain_destroy(chain); | ||
| 1063 | return 0; | 1063 | return 0; |
| 1064 | } | 1064 | } |
| 1065 | 1065 | ||
| @@ -1114,35 +1114,45 @@ void nft_unregister_expr(struct nft_expr_type *type) | |||
| 1114 | } | 1114 | } |
| 1115 | EXPORT_SYMBOL_GPL(nft_unregister_expr); | 1115 | EXPORT_SYMBOL_GPL(nft_unregister_expr); |
| 1116 | 1116 | ||
| 1117 | static const struct nft_expr_type *__nft_expr_type_get(struct nlattr *nla) | 1117 | static const struct nft_expr_type *__nft_expr_type_get(u8 family, |
| 1118 | struct nlattr *nla) | ||
| 1118 | { | 1119 | { |
| 1119 | const struct nft_expr_type *type; | 1120 | const struct nft_expr_type *type; |
| 1120 | 1121 | ||
| 1121 | list_for_each_entry(type, &nf_tables_expressions, list) { | 1122 | list_for_each_entry(type, &nf_tables_expressions, list) { |
| 1122 | if (!nla_strcmp(nla, type->name)) | 1123 | if (!nla_strcmp(nla, type->name) && |
| 1124 | (!type->family || type->family == family)) | ||
| 1123 | return type; | 1125 | return type; |
| 1124 | } | 1126 | } |
| 1125 | return NULL; | 1127 | return NULL; |
| 1126 | } | 1128 | } |
| 1127 | 1129 | ||
| 1128 | static const struct nft_expr_type *nft_expr_type_get(struct nlattr *nla) | 1130 | static const struct nft_expr_type *nft_expr_type_get(u8 family, |
| 1131 | struct nlattr *nla) | ||
| 1129 | { | 1132 | { |
| 1130 | const struct nft_expr_type *type; | 1133 | const struct nft_expr_type *type; |
| 1131 | 1134 | ||
| 1132 | if (nla == NULL) | 1135 | if (nla == NULL) |
| 1133 | return ERR_PTR(-EINVAL); | 1136 | return ERR_PTR(-EINVAL); |
| 1134 | 1137 | ||
| 1135 | type = __nft_expr_type_get(nla); | 1138 | type = __nft_expr_type_get(family, nla); |
| 1136 | if (type != NULL && try_module_get(type->owner)) | 1139 | if (type != NULL && try_module_get(type->owner)) |
| 1137 | return type; | 1140 | return type; |
| 1138 | 1141 | ||
| 1139 | #ifdef CONFIG_MODULES | 1142 | #ifdef CONFIG_MODULES |
| 1140 | if (type == NULL) { | 1143 | if (type == NULL) { |
| 1141 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | 1144 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
| 1145 | request_module("nft-expr-%u-%.*s", family, | ||
| 1146 | nla_len(nla), (char *)nla_data(nla)); | ||
| 1147 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | ||
| 1148 | if (__nft_expr_type_get(family, nla)) | ||
| 1149 | return ERR_PTR(-EAGAIN); | ||
| 1150 | |||
| 1151 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | ||
| 1142 | request_module("nft-expr-%.*s", | 1152 | request_module("nft-expr-%.*s", |
| 1143 | nla_len(nla), (char *)nla_data(nla)); | 1153 | nla_len(nla), (char *)nla_data(nla)); |
| 1144 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | 1154 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
| 1145 | if (__nft_expr_type_get(nla)) | 1155 | if (__nft_expr_type_get(family, nla)) |
| 1146 | return ERR_PTR(-EAGAIN); | 1156 | return ERR_PTR(-EAGAIN); |
| 1147 | } | 1157 | } |
| 1148 | #endif | 1158 | #endif |
| @@ -1193,7 +1203,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx, | |||
| 1193 | if (err < 0) | 1203 | if (err < 0) |
| 1194 | return err; | 1204 | return err; |
| 1195 | 1205 | ||
| 1196 | type = nft_expr_type_get(tb[NFTA_EXPR_NAME]); | 1206 | type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]); |
| 1197 | if (IS_ERR(type)) | 1207 | if (IS_ERR(type)) |
| 1198 | return PTR_ERR(type); | 1208 | return PTR_ERR(type); |
| 1199 | 1209 | ||
| @@ -1521,9 +1531,8 @@ err: | |||
| 1521 | return err; | 1531 | return err; |
| 1522 | } | 1532 | } |
| 1523 | 1533 | ||
| 1524 | static void nf_tables_rcu_rule_destroy(struct rcu_head *head) | 1534 | static void nf_tables_rule_destroy(struct nft_rule *rule) |
| 1525 | { | 1535 | { |
| 1526 | struct nft_rule *rule = container_of(head, struct nft_rule, rcu_head); | ||
| 1527 | struct nft_expr *expr; | 1536 | struct nft_expr *expr; |
| 1528 | 1537 | ||
| 1529 | /* | 1538 | /* |
| @@ -1538,11 +1547,6 @@ static void nf_tables_rcu_rule_destroy(struct rcu_head *head) | |||
| 1538 | kfree(rule); | 1547 | kfree(rule); |
| 1539 | } | 1548 | } |
| 1540 | 1549 | ||
| 1541 | static void nf_tables_rule_destroy(struct nft_rule *rule) | ||
| 1542 | { | ||
| 1543 | call_rcu(&rule->rcu_head, nf_tables_rcu_rule_destroy); | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | #define NFT_RULE_MAXEXPRS 128 | 1550 | #define NFT_RULE_MAXEXPRS 128 |
| 1547 | 1551 | ||
| 1548 | static struct nft_expr_info *info; | 1552 | static struct nft_expr_info *info; |
| @@ -1809,9 +1813,6 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
| 1809 | synchronize_rcu(); | 1813 | synchronize_rcu(); |
| 1810 | 1814 | ||
| 1811 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | 1815 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { |
| 1812 | /* Delete this rule from the dirty list */ | ||
| 1813 | list_del(&rupd->list); | ||
| 1814 | |||
| 1815 | /* This rule was inactive in the past and just became active. | 1816 | /* This rule was inactive in the past and just became active. |
| 1816 | * Clear the next bit of the genmask since its meaning has | 1817 | * Clear the next bit of the genmask since its meaning has |
| 1817 | * changed, now it is the future. | 1818 | * changed, now it is the future. |
| @@ -1822,6 +1823,7 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
| 1822 | rupd->chain, rupd->rule, | 1823 | rupd->chain, rupd->rule, |
| 1823 | NFT_MSG_NEWRULE, 0, | 1824 | NFT_MSG_NEWRULE, 0, |
| 1824 | rupd->family); | 1825 | rupd->family); |
| 1826 | list_del(&rupd->list); | ||
| 1825 | kfree(rupd); | 1827 | kfree(rupd); |
| 1826 | continue; | 1828 | continue; |
| 1827 | } | 1829 | } |
| @@ -1831,7 +1833,15 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
| 1831 | nf_tables_rule_notify(skb, rupd->nlh, rupd->table, rupd->chain, | 1833 | nf_tables_rule_notify(skb, rupd->nlh, rupd->table, rupd->chain, |
| 1832 | rupd->rule, NFT_MSG_DELRULE, 0, | 1834 | rupd->rule, NFT_MSG_DELRULE, 0, |
| 1833 | rupd->family); | 1835 | rupd->family); |
| 1836 | } | ||
| 1837 | |||
| 1838 | /* Make sure we don't see any packet traversing old rules */ | ||
| 1839 | synchronize_rcu(); | ||
| 1840 | |||
| 1841 | /* Now we can safely release unused old rules */ | ||
| 1842 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | ||
| 1834 | nf_tables_rule_destroy(rupd->rule); | 1843 | nf_tables_rule_destroy(rupd->rule); |
| 1844 | list_del(&rupd->list); | ||
| 1835 | kfree(rupd); | 1845 | kfree(rupd); |
| 1836 | } | 1846 | } |
| 1837 | 1847 | ||
| @@ -1844,20 +1854,26 @@ static int nf_tables_abort(struct sk_buff *skb) | |||
| 1844 | struct nft_rule_trans *rupd, *tmp; | 1854 | struct nft_rule_trans *rupd, *tmp; |
| 1845 | 1855 | ||
| 1846 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | 1856 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { |
| 1847 | /* Delete all rules from the dirty list */ | ||
| 1848 | list_del(&rupd->list); | ||
| 1849 | |||
| 1850 | if (!nft_rule_is_active_next(net, rupd->rule)) { | 1857 | if (!nft_rule_is_active_next(net, rupd->rule)) { |
| 1851 | nft_rule_clear(net, rupd->rule); | 1858 | nft_rule_clear(net, rupd->rule); |
| 1859 | list_del(&rupd->list); | ||
| 1852 | kfree(rupd); | 1860 | kfree(rupd); |
| 1853 | continue; | 1861 | continue; |
| 1854 | } | 1862 | } |
| 1855 | 1863 | ||
| 1856 | /* This rule is inactive, get rid of it */ | 1864 | /* This rule is inactive, get rid of it */ |
| 1857 | list_del_rcu(&rupd->rule->list); | 1865 | list_del_rcu(&rupd->rule->list); |
| 1866 | } | ||
| 1867 | |||
| 1868 | /* Make sure we don't see any packet accessing aborted rules */ | ||
| 1869 | synchronize_rcu(); | ||
| 1870 | |||
| 1871 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | ||
| 1858 | nf_tables_rule_destroy(rupd->rule); | 1872 | nf_tables_rule_destroy(rupd->rule); |
| 1873 | list_del(&rupd->list); | ||
| 1859 | kfree(rupd); | 1874 | kfree(rupd); |
| 1860 | } | 1875 | } |
| 1876 | |||
| 1861 | return 0; | 1877 | return 0; |
| 1862 | } | 1878 | } |
| 1863 | 1879 | ||
| @@ -1943,6 +1959,9 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, | |||
| 1943 | } | 1959 | } |
| 1944 | 1960 | ||
| 1945 | if (nla[NFTA_SET_TABLE] != NULL) { | 1961 | if (nla[NFTA_SET_TABLE] != NULL) { |
| 1962 | if (afi == NULL) | ||
| 1963 | return -EAFNOSUPPORT; | ||
| 1964 | |||
| 1946 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); | 1965 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); |
| 1947 | if (IS_ERR(table)) | 1966 | if (IS_ERR(table)) |
| 1948 | return PTR_ERR(table); | 1967 | return PTR_ERR(table); |
| @@ -1989,13 +2008,13 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set, | |||
| 1989 | 2008 | ||
| 1990 | if (!sscanf(i->name, name, &tmp)) | 2009 | if (!sscanf(i->name, name, &tmp)) |
| 1991 | continue; | 2010 | continue; |
| 1992 | if (tmp < 0 || tmp > BITS_PER_LONG * PAGE_SIZE) | 2011 | if (tmp < 0 || tmp >= BITS_PER_BYTE * PAGE_SIZE) |
| 1993 | continue; | 2012 | continue; |
| 1994 | 2013 | ||
| 1995 | set_bit(tmp, inuse); | 2014 | set_bit(tmp, inuse); |
| 1996 | } | 2015 | } |
| 1997 | 2016 | ||
| 1998 | n = find_first_zero_bit(inuse, BITS_PER_LONG * PAGE_SIZE); | 2017 | n = find_first_zero_bit(inuse, BITS_PER_BYTE * PAGE_SIZE); |
| 1999 | free_page((unsigned long)inuse); | 2018 | free_page((unsigned long)inuse); |
| 2000 | } | 2019 | } |
| 2001 | 2020 | ||
| @@ -2428,6 +2447,8 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, | |||
| 2428 | struct nft_ctx ctx; | 2447 | struct nft_ctx ctx; |
| 2429 | int err; | 2448 | int err; |
| 2430 | 2449 | ||
| 2450 | if (nfmsg->nfgen_family == NFPROTO_UNSPEC) | ||
| 2451 | return -EAFNOSUPPORT; | ||
| 2431 | if (nla[NFTA_SET_TABLE] == NULL) | 2452 | if (nla[NFTA_SET_TABLE] == NULL) |
| 2432 | return -EINVAL; | 2453 | return -EINVAL; |
| 2433 | 2454 | ||
| @@ -2435,9 +2456,6 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, | |||
| 2435 | if (err < 0) | 2456 | if (err < 0) |
| 2436 | return err; | 2457 | return err; |
| 2437 | 2458 | ||
| 2438 | if (nfmsg->nfgen_family == NFPROTO_UNSPEC) | ||
| 2439 | return -EAFNOSUPPORT; | ||
| 2440 | |||
| 2441 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); | 2459 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); |
| 2442 | if (IS_ERR(set)) | 2460 | if (IS_ERR(set)) |
| 2443 | return PTR_ERR(set); | 2461 | return PTR_ERR(set); |
| @@ -2723,6 +2741,9 @@ static int nft_add_set_elem(const struct nft_ctx *ctx, struct nft_set *set, | |||
| 2723 | if (nla[NFTA_SET_ELEM_DATA] == NULL && | 2741 | if (nla[NFTA_SET_ELEM_DATA] == NULL && |
| 2724 | !(elem.flags & NFT_SET_ELEM_INTERVAL_END)) | 2742 | !(elem.flags & NFT_SET_ELEM_INTERVAL_END)) |
| 2725 | return -EINVAL; | 2743 | return -EINVAL; |
| 2744 | if (nla[NFTA_SET_ELEM_DATA] != NULL && | ||
| 2745 | elem.flags & NFT_SET_ELEM_INTERVAL_END) | ||
| 2746 | return -EINVAL; | ||
| 2726 | } else { | 2747 | } else { |
| 2727 | if (nla[NFTA_SET_ELEM_DATA] != NULL) | 2748 | if (nla[NFTA_SET_ELEM_DATA] != NULL) |
| 2728 | return -EINVAL; | 2749 | return -EINVAL; |
| @@ -2977,6 +2998,9 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx, | |||
| 2977 | const struct nft_set_iter *iter, | 2998 | const struct nft_set_iter *iter, |
| 2978 | const struct nft_set_elem *elem) | 2999 | const struct nft_set_elem *elem) |
| 2979 | { | 3000 | { |
| 3001 | if (elem->flags & NFT_SET_ELEM_INTERVAL_END) | ||
| 3002 | return 0; | ||
| 3003 | |||
| 2980 | switch (elem->data.verdict) { | 3004 | switch (elem->data.verdict) { |
| 2981 | case NFT_JUMP: | 3005 | case NFT_JUMP: |
| 2982 | case NFT_GOTO: | 3006 | case NFT_GOTO: |
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 0d879fcb8763..90998a6ff8b9 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
| @@ -103,9 +103,9 @@ static struct nf_loginfo trace_loginfo = { | |||
| 103 | }, | 103 | }, |
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | static inline void nft_trace_packet(const struct nft_pktinfo *pkt, | 106 | static void nft_trace_packet(const struct nft_pktinfo *pkt, |
| 107 | const struct nft_chain *chain, | 107 | const struct nft_chain *chain, |
| 108 | int rulenum, enum nft_trace type) | 108 | int rulenum, enum nft_trace type) |
| 109 | { | 109 | { |
| 110 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); | 110 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); |
| 111 | 111 | ||
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 917052e20602..46e275403838 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c | |||
| @@ -226,6 +226,7 @@ static int nft_ct_init_validate_get(const struct nft_expr *expr, | |||
| 226 | if (tb[NFTA_CT_DIRECTION] != NULL) | 226 | if (tb[NFTA_CT_DIRECTION] != NULL) |
| 227 | return -EINVAL; | 227 | return -EINVAL; |
| 228 | break; | 228 | break; |
| 229 | case NFT_CT_L3PROTOCOL: | ||
| 229 | case NFT_CT_PROTOCOL: | 230 | case NFT_CT_PROTOCOL: |
| 230 | case NFT_CT_SRC: | 231 | case NFT_CT_SRC: |
| 231 | case NFT_CT_DST: | 232 | case NFT_CT_DST: |
| @@ -311,8 +312,19 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
| 311 | goto nla_put_failure; | 312 | goto nla_put_failure; |
| 312 | if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) | 313 | if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) |
| 313 | goto nla_put_failure; | 314 | goto nla_put_failure; |
| 314 | if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir)) | 315 | |
| 315 | goto nla_put_failure; | 316 | switch (priv->key) { |
| 317 | case NFT_CT_PROTOCOL: | ||
| 318 | case NFT_CT_SRC: | ||
| 319 | case NFT_CT_DST: | ||
| 320 | case NFT_CT_PROTO_SRC: | ||
| 321 | case NFT_CT_PROTO_DST: | ||
| 322 | if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir)) | ||
| 323 | goto nla_put_failure; | ||
| 324 | default: | ||
| 325 | break; | ||
| 326 | } | ||
| 327 | |||
| 316 | return 0; | 328 | return 0; |
| 317 | 329 | ||
| 318 | nla_put_failure: | 330 | nla_put_failure: |
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index 5af790123ad8..26c5154e05f3 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c | |||
| @@ -23,7 +23,6 @@ static const char *nft_log_null_prefix = ""; | |||
| 23 | struct nft_log { | 23 | struct nft_log { |
| 24 | struct nf_loginfo loginfo; | 24 | struct nf_loginfo loginfo; |
| 25 | char *prefix; | 25 | char *prefix; |
| 26 | int family; | ||
| 27 | }; | 26 | }; |
| 28 | 27 | ||
| 29 | static void nft_log_eval(const struct nft_expr *expr, | 28 | static void nft_log_eval(const struct nft_expr *expr, |
| @@ -33,7 +32,7 @@ static void nft_log_eval(const struct nft_expr *expr, | |||
| 33 | const struct nft_log *priv = nft_expr_priv(expr); | 32 | const struct nft_log *priv = nft_expr_priv(expr); |
| 34 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); | 33 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); |
| 35 | 34 | ||
| 36 | nf_log_packet(net, priv->family, pkt->ops->hooknum, pkt->skb, pkt->in, | 35 | nf_log_packet(net, pkt->ops->pf, pkt->ops->hooknum, pkt->skb, pkt->in, |
| 37 | pkt->out, &priv->loginfo, "%s", priv->prefix); | 36 | pkt->out, &priv->loginfo, "%s", priv->prefix); |
| 38 | } | 37 | } |
| 39 | 38 | ||
| @@ -52,8 +51,6 @@ static int nft_log_init(const struct nft_ctx *ctx, | |||
| 52 | struct nf_loginfo *li = &priv->loginfo; | 51 | struct nf_loginfo *li = &priv->loginfo; |
| 53 | const struct nlattr *nla; | 52 | const struct nlattr *nla; |
| 54 | 53 | ||
| 55 | priv->family = ctx->afi->family; | ||
| 56 | |||
| 57 | nla = tb[NFTA_LOG_PREFIX]; | 54 | nla = tb[NFTA_LOG_PREFIX]; |
| 58 | if (nla != NULL) { | 55 | if (nla != NULL) { |
| 59 | priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL); | 56 | priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL); |
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index 8a6116b75b5a..bb4ef4cccb6e 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/netfilter.h> | 16 | #include <linux/netfilter.h> |
| 17 | #include <linux/netfilter/nf_tables.h> | 17 | #include <linux/netfilter/nf_tables.h> |
| 18 | #include <net/netfilter/nf_tables.h> | 18 | #include <net/netfilter/nf_tables.h> |
| 19 | #include <net/netfilter/nf_tables_core.h> | ||
| 19 | 20 | ||
| 20 | struct nft_lookup { | 21 | struct nft_lookup { |
| 21 | struct nft_set *set; | 22 | struct nft_set *set; |
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index e8254ad2e5a9..425cf39af890 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c | |||
| @@ -116,7 +116,7 @@ static void nft_meta_get_eval(const struct nft_expr *expr, | |||
| 116 | skb->sk->sk_socket->file->f_cred->fsgid); | 116 | skb->sk->sk_socket->file->f_cred->fsgid); |
| 117 | read_unlock_bh(&skb->sk->sk_callback_lock); | 117 | read_unlock_bh(&skb->sk->sk_callback_lock); |
| 118 | break; | 118 | break; |
| 119 | #ifdef CONFIG_NET_CLS_ROUTE | 119 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 120 | case NFT_META_RTCLASSID: { | 120 | case NFT_META_RTCLASSID: { |
| 121 | const struct dst_entry *dst = skb_dst(skb); | 121 | const struct dst_entry *dst = skb_dst(skb); |
| 122 | 122 | ||
| @@ -199,7 +199,7 @@ static int nft_meta_init_validate_get(uint32_t key) | |||
| 199 | case NFT_META_OIFTYPE: | 199 | case NFT_META_OIFTYPE: |
| 200 | case NFT_META_SKUID: | 200 | case NFT_META_SKUID: |
| 201 | case NFT_META_SKGID: | 201 | case NFT_META_SKGID: |
| 202 | #ifdef CONFIG_NET_CLS_ROUTE | 202 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 203 | case NFT_META_RTCLASSID: | 203 | case NFT_META_RTCLASSID: |
| 204 | #endif | 204 | #endif |
| 205 | #ifdef CONFIG_NETWORK_SECMARK | 205 | #ifdef CONFIG_NETWORK_SECMARK |
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index a2aeb318678f..85daa84bfdfe 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c | |||
| @@ -135,7 +135,8 @@ nft_payload_select_ops(const struct nft_ctx *ctx, | |||
| 135 | if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data)) | 135 | if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data)) |
| 136 | return ERR_PTR(-EINVAL); | 136 | return ERR_PTR(-EINVAL); |
| 137 | 137 | ||
| 138 | if (len <= 4 && IS_ALIGNED(offset, len) && base != NFT_PAYLOAD_LL_HEADER) | 138 | if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) && |
| 139 | base != NFT_PAYLOAD_LL_HEADER) | ||
| 139 | return &nft_payload_fast_ops; | 140 | return &nft_payload_fast_ops; |
| 140 | else | 141 | else |
| 141 | return &nft_payload_ops; | 142 | return &nft_payload_ops; |
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c index cbea473d69e9..e8ae2f6bf232 100644 --- a/net/netfilter/nft_queue.c +++ b/net/netfilter/nft_queue.c | |||
| @@ -25,7 +25,6 @@ struct nft_queue { | |||
| 25 | u16 queuenum; | 25 | u16 queuenum; |
| 26 | u16 queues_total; | 26 | u16 queues_total; |
| 27 | u16 flags; | 27 | u16 flags; |
| 28 | u8 family; | ||
| 29 | }; | 28 | }; |
| 30 | 29 | ||
| 31 | static void nft_queue_eval(const struct nft_expr *expr, | 30 | static void nft_queue_eval(const struct nft_expr *expr, |
| @@ -43,7 +42,7 @@ static void nft_queue_eval(const struct nft_expr *expr, | |||
| 43 | queue = priv->queuenum + cpu % priv->queues_total; | 42 | queue = priv->queuenum + cpu % priv->queues_total; |
| 44 | } else { | 43 | } else { |
| 45 | queue = nfqueue_hash(pkt->skb, queue, | 44 | queue = nfqueue_hash(pkt->skb, queue, |
| 46 | priv->queues_total, priv->family, | 45 | priv->queues_total, pkt->ops->pf, |
| 47 | jhash_initval); | 46 | jhash_initval); |
| 48 | } | 47 | } |
| 49 | } | 48 | } |
| @@ -71,7 +70,6 @@ static int nft_queue_init(const struct nft_ctx *ctx, | |||
| 71 | return -EINVAL; | 70 | return -EINVAL; |
| 72 | 71 | ||
| 73 | init_hashrandom(&jhash_initval); | 72 | init_hashrandom(&jhash_initval); |
| 74 | priv->family = ctx->afi->family; | ||
| 75 | priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM])); | 73 | priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM])); |
| 76 | 74 | ||
| 77 | if (tb[NFTA_QUEUE_TOTAL] != NULL) | 75 | if (tb[NFTA_QUEUE_TOTAL] != NULL) |
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c index ca0c1b231bfe..e21d69d13506 100644 --- a/net/netfilter/nft_rbtree.c +++ b/net/netfilter/nft_rbtree.c | |||
| @@ -69,8 +69,10 @@ static void nft_rbtree_elem_destroy(const struct nft_set *set, | |||
| 69 | struct nft_rbtree_elem *rbe) | 69 | struct nft_rbtree_elem *rbe) |
| 70 | { | 70 | { |
| 71 | nft_data_uninit(&rbe->key, NFT_DATA_VALUE); | 71 | nft_data_uninit(&rbe->key, NFT_DATA_VALUE); |
| 72 | if (set->flags & NFT_SET_MAP) | 72 | if (set->flags & NFT_SET_MAP && |
| 73 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
| 73 | nft_data_uninit(rbe->data, set->dtype); | 74 | nft_data_uninit(rbe->data, set->dtype); |
| 75 | |||
| 74 | kfree(rbe); | 76 | kfree(rbe); |
| 75 | } | 77 | } |
| 76 | 78 | ||
| @@ -108,7 +110,8 @@ static int nft_rbtree_insert(const struct nft_set *set, | |||
| 108 | int err; | 110 | int err; |
| 109 | 111 | ||
| 110 | size = sizeof(*rbe); | 112 | size = sizeof(*rbe); |
| 111 | if (set->flags & NFT_SET_MAP) | 113 | if (set->flags & NFT_SET_MAP && |
| 114 | !(elem->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
| 112 | size += sizeof(rbe->data[0]); | 115 | size += sizeof(rbe->data[0]); |
| 113 | 116 | ||
| 114 | rbe = kzalloc(size, GFP_KERNEL); | 117 | rbe = kzalloc(size, GFP_KERNEL); |
| @@ -117,7 +120,8 @@ static int nft_rbtree_insert(const struct nft_set *set, | |||
| 117 | 120 | ||
| 118 | rbe->flags = elem->flags; | 121 | rbe->flags = elem->flags; |
| 119 | nft_data_copy(&rbe->key, &elem->key); | 122 | nft_data_copy(&rbe->key, &elem->key); |
| 120 | if (set->flags & NFT_SET_MAP) | 123 | if (set->flags & NFT_SET_MAP && |
| 124 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
| 121 | nft_data_copy(rbe->data, &elem->data); | 125 | nft_data_copy(rbe->data, &elem->data); |
| 122 | 126 | ||
| 123 | err = __nft_rbtree_insert(set, rbe); | 127 | err = __nft_rbtree_insert(set, rbe); |
| @@ -153,7 +157,8 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem) | |||
| 153 | parent = parent->rb_right; | 157 | parent = parent->rb_right; |
| 154 | else { | 158 | else { |
| 155 | elem->cookie = rbe; | 159 | elem->cookie = rbe; |
| 156 | if (set->flags & NFT_SET_MAP) | 160 | if (set->flags & NFT_SET_MAP && |
| 161 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
| 157 | nft_data_copy(&elem->data, rbe->data); | 162 | nft_data_copy(&elem->data, rbe->data); |
| 158 | elem->flags = rbe->flags; | 163 | elem->flags = rbe->flags; |
| 159 | return 0; | 164 | return 0; |
| @@ -177,7 +182,8 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx, | |||
| 177 | 182 | ||
| 178 | rbe = rb_entry(node, struct nft_rbtree_elem, node); | 183 | rbe = rb_entry(node, struct nft_rbtree_elem, node); |
| 179 | nft_data_copy(&elem.key, &rbe->key); | 184 | nft_data_copy(&elem.key, &rbe->key); |
| 180 | if (set->flags & NFT_SET_MAP) | 185 | if (set->flags & NFT_SET_MAP && |
| 186 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
| 181 | nft_data_copy(&elem.data, rbe->data); | 187 | nft_data_copy(&elem.data, rbe->data); |
| 182 | elem.flags = rbe->flags; | 188 | elem.flags = rbe->flags; |
| 183 | 189 | ||
diff --git a/net/netfilter/nft_reject.c b/net/netfilter/nft_reject.c index 5e204711d704..f3448c296446 100644 --- a/net/netfilter/nft_reject.c +++ b/net/netfilter/nft_reject.c | |||
| @@ -16,65 +16,23 @@ | |||
| 16 | #include <linux/netfilter.h> | 16 | #include <linux/netfilter.h> |
| 17 | #include <linux/netfilter/nf_tables.h> | 17 | #include <linux/netfilter/nf_tables.h> |
| 18 | #include <net/netfilter/nf_tables.h> | 18 | #include <net/netfilter/nf_tables.h> |
| 19 | #include <net/icmp.h> | 19 | #include <net/netfilter/nft_reject.h> |
| 20 | #include <net/netfilter/ipv4/nf_reject.h> | ||
| 21 | 20 | ||
| 22 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | 21 | const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { |
| 23 | #include <net/netfilter/ipv6/nf_reject.h> | ||
| 24 | #endif | ||
| 25 | |||
| 26 | struct nft_reject { | ||
| 27 | enum nft_reject_types type:8; | ||
| 28 | u8 icmp_code; | ||
| 29 | u8 family; | ||
| 30 | }; | ||
| 31 | |||
| 32 | static void nft_reject_eval(const struct nft_expr *expr, | ||
| 33 | struct nft_data data[NFT_REG_MAX + 1], | ||
| 34 | const struct nft_pktinfo *pkt) | ||
| 35 | { | ||
| 36 | struct nft_reject *priv = nft_expr_priv(expr); | ||
| 37 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | ||
| 38 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | ||
| 39 | #endif | ||
| 40 | switch (priv->type) { | ||
| 41 | case NFT_REJECT_ICMP_UNREACH: | ||
| 42 | if (priv->family == NFPROTO_IPV4) | ||
| 43 | nf_send_unreach(pkt->skb, priv->icmp_code); | ||
| 44 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | ||
| 45 | else if (priv->family == NFPROTO_IPV6) | ||
| 46 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | ||
| 47 | pkt->ops->hooknum); | ||
| 48 | #endif | ||
| 49 | break; | ||
| 50 | case NFT_REJECT_TCP_RST: | ||
| 51 | if (priv->family == NFPROTO_IPV4) | ||
| 52 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | ||
| 53 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | ||
| 54 | else if (priv->family == NFPROTO_IPV6) | ||
| 55 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | ||
| 56 | #endif | ||
| 57 | break; | ||
| 58 | } | ||
| 59 | |||
| 60 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
| 61 | } | ||
| 62 | |||
| 63 | static const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { | ||
| 64 | [NFTA_REJECT_TYPE] = { .type = NLA_U32 }, | 22 | [NFTA_REJECT_TYPE] = { .type = NLA_U32 }, |
| 65 | [NFTA_REJECT_ICMP_CODE] = { .type = NLA_U8 }, | 23 | [NFTA_REJECT_ICMP_CODE] = { .type = NLA_U8 }, |
| 66 | }; | 24 | }; |
| 25 | EXPORT_SYMBOL_GPL(nft_reject_policy); | ||
| 67 | 26 | ||
| 68 | static int nft_reject_init(const struct nft_ctx *ctx, | 27 | int nft_reject_init(const struct nft_ctx *ctx, |
| 69 | const struct nft_expr *expr, | 28 | const struct nft_expr *expr, |
| 70 | const struct nlattr * const tb[]) | 29 | const struct nlattr * const tb[]) |
| 71 | { | 30 | { |
| 72 | struct nft_reject *priv = nft_expr_priv(expr); | 31 | struct nft_reject *priv = nft_expr_priv(expr); |
| 73 | 32 | ||
| 74 | if (tb[NFTA_REJECT_TYPE] == NULL) | 33 | if (tb[NFTA_REJECT_TYPE] == NULL) |
| 75 | return -EINVAL; | 34 | return -EINVAL; |
| 76 | 35 | ||
| 77 | priv->family = ctx->afi->family; | ||
| 78 | priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); | 36 | priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); |
| 79 | switch (priv->type) { | 37 | switch (priv->type) { |
| 80 | case NFT_REJECT_ICMP_UNREACH: | 38 | case NFT_REJECT_ICMP_UNREACH: |
| @@ -89,8 +47,9 @@ static int nft_reject_init(const struct nft_ctx *ctx, | |||
| 89 | 47 | ||
| 90 | return 0; | 48 | return 0; |
| 91 | } | 49 | } |
| 50 | EXPORT_SYMBOL_GPL(nft_reject_init); | ||
| 92 | 51 | ||
| 93 | static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) | 52 | int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) |
| 94 | { | 53 | { |
| 95 | const struct nft_reject *priv = nft_expr_priv(expr); | 54 | const struct nft_reject *priv = nft_expr_priv(expr); |
| 96 | 55 | ||
| @@ -109,37 +68,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
| 109 | nla_put_failure: | 68 | nla_put_failure: |
| 110 | return -1; | 69 | return -1; |
| 111 | } | 70 | } |
| 112 | 71 | EXPORT_SYMBOL_GPL(nft_reject_dump); | |
| 113 | static struct nft_expr_type nft_reject_type; | ||
| 114 | static const struct nft_expr_ops nft_reject_ops = { | ||
| 115 | .type = &nft_reject_type, | ||
| 116 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
| 117 | .eval = nft_reject_eval, | ||
| 118 | .init = nft_reject_init, | ||
| 119 | .dump = nft_reject_dump, | ||
| 120 | }; | ||
| 121 | |||
| 122 | static struct nft_expr_type nft_reject_type __read_mostly = { | ||
| 123 | .name = "reject", | ||
| 124 | .ops = &nft_reject_ops, | ||
| 125 | .policy = nft_reject_policy, | ||
| 126 | .maxattr = NFTA_REJECT_MAX, | ||
| 127 | .owner = THIS_MODULE, | ||
| 128 | }; | ||
| 129 | |||
| 130 | static int __init nft_reject_module_init(void) | ||
| 131 | { | ||
| 132 | return nft_register_expr(&nft_reject_type); | ||
| 133 | } | ||
| 134 | |||
| 135 | static void __exit nft_reject_module_exit(void) | ||
| 136 | { | ||
| 137 | nft_unregister_expr(&nft_reject_type); | ||
| 138 | } | ||
| 139 | |||
| 140 | module_init(nft_reject_module_init); | ||
| 141 | module_exit(nft_reject_module_exit); | ||
| 142 | 72 | ||
| 143 | MODULE_LICENSE("GPL"); | 73 | MODULE_LICENSE("GPL"); |
| 144 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 74 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
| 145 | MODULE_ALIAS_NFT_EXPR("reject"); | ||
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c new file mode 100644 index 000000000000..b718a52a4654 --- /dev/null +++ b/net/netfilter/nft_reject_inet.c | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014 Patrick McHardy <kaber@trash.net> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/netlink.h> | ||
| 13 | #include <linux/netfilter.h> | ||
| 14 | #include <linux/netfilter/nf_tables.h> | ||
| 15 | #include <net/netfilter/nf_tables.h> | ||
| 16 | #include <net/netfilter/nft_reject.h> | ||
| 17 | |||
| 18 | static void nft_reject_inet_eval(const struct nft_expr *expr, | ||
| 19 | struct nft_data data[NFT_REG_MAX + 1], | ||
| 20 | const struct nft_pktinfo *pkt) | ||
| 21 | { | ||
| 22 | switch (pkt->ops->pf) { | ||
| 23 | case NFPROTO_IPV4: | ||
| 24 | return nft_reject_ipv4_eval(expr, data, pkt); | ||
| 25 | case NFPROTO_IPV6: | ||
| 26 | return nft_reject_ipv6_eval(expr, data, pkt); | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | static struct nft_expr_type nft_reject_inet_type; | ||
| 31 | static const struct nft_expr_ops nft_reject_inet_ops = { | ||
| 32 | .type = &nft_reject_inet_type, | ||
| 33 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
| 34 | .eval = nft_reject_inet_eval, | ||
| 35 | .init = nft_reject_init, | ||
| 36 | .dump = nft_reject_dump, | ||
| 37 | }; | ||
| 38 | |||
| 39 | static struct nft_expr_type nft_reject_inet_type __read_mostly = { | ||
| 40 | .family = NFPROTO_INET, | ||
| 41 | .name = "reject", | ||
| 42 | .ops = &nft_reject_inet_ops, | ||
| 43 | .policy = nft_reject_policy, | ||
| 44 | .maxattr = NFTA_REJECT_MAX, | ||
| 45 | .owner = THIS_MODULE, | ||
| 46 | }; | ||
| 47 | |||
| 48 | static int __init nft_reject_inet_module_init(void) | ||
| 49 | { | ||
| 50 | return nft_register_expr(&nft_reject_inet_type); | ||
| 51 | } | ||
| 52 | |||
| 53 | static void __exit nft_reject_inet_module_exit(void) | ||
| 54 | { | ||
| 55 | nft_unregister_expr(&nft_reject_inet_type); | ||
| 56 | } | ||
| 57 | |||
| 58 | module_init(nft_reject_inet_module_init); | ||
| 59 | module_exit(nft_reject_inet_module_exit); | ||
| 60 | |||
| 61 | MODULE_LICENSE("GPL"); | ||
| 62 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 63 | MODULE_ALIAS_NFT_AF_EXPR(1, "reject"); | ||
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 5929be622c5c..75747aecdebe 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
| @@ -228,12 +228,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, | |||
| 228 | goto err3; | 228 | goto err3; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); | 231 | nf_conntrack_tmpl_insert(par->net, ct); |
| 232 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | ||
| 233 | |||
| 234 | /* Overload tuple linked list to put us in template list. */ | ||
| 235 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | ||
| 236 | &par->net->ct.tmpl); | ||
| 237 | out: | 232 | out: |
| 238 | info->ct = ct; | 233 | info->ct = ct; |
| 239 | return 0; | 234 | return 0; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index fdf51353cf78..04748ab649c2 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1489,8 +1489,8 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, | |||
| 1489 | if (addr->sa_family != AF_NETLINK) | 1489 | if (addr->sa_family != AF_NETLINK) |
| 1490 | return -EINVAL; | 1490 | return -EINVAL; |
| 1491 | 1491 | ||
| 1492 | /* Only superuser is allowed to send multicasts */ | 1492 | if ((nladdr->nl_groups || nladdr->nl_pid) && |
| 1493 | if (nladdr->nl_groups && !netlink_capable(sock, NL_CFG_F_NONROOT_SEND)) | 1493 | !netlink_capable(sock, NL_CFG_F_NONROOT_SEND)) |
| 1494 | return -EPERM; | 1494 | return -EPERM; |
| 1495 | 1495 | ||
| 1496 | if (!nlk->portid) | 1496 | if (!nlk->portid) |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 46bda010bf11..56db888b1cd5 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
| @@ -301,7 +301,7 @@ static int nci_open_device(struct nci_dev *ndev) | |||
| 301 | rc = __nci_request(ndev, nci_reset_req, 0, | 301 | rc = __nci_request(ndev, nci_reset_req, 0, |
| 302 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); | 302 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); |
| 303 | 303 | ||
| 304 | if (ndev->ops->setup(ndev)) | 304 | if (ndev->ops->setup) |
| 305 | ndev->ops->setup(ndev); | 305 | ndev->ops->setup(ndev); |
| 306 | 306 | ||
| 307 | if (!rc) { | 307 | if (!rc) { |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index df4692826ead..e9a48baf8551 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -55,6 +55,7 @@ | |||
| 55 | 55 | ||
| 56 | #include "datapath.h" | 56 | #include "datapath.h" |
| 57 | #include "flow.h" | 57 | #include "flow.h" |
| 58 | #include "flow_table.h" | ||
| 58 | #include "flow_netlink.h" | 59 | #include "flow_netlink.h" |
| 59 | #include "vport-internal_dev.h" | 60 | #include "vport-internal_dev.h" |
| 60 | #include "vport-netdev.h" | 61 | #include "vport-netdev.h" |
| @@ -160,7 +161,6 @@ static void destroy_dp_rcu(struct rcu_head *rcu) | |||
| 160 | { | 161 | { |
| 161 | struct datapath *dp = container_of(rcu, struct datapath, rcu); | 162 | struct datapath *dp = container_of(rcu, struct datapath, rcu); |
| 162 | 163 | ||
| 163 | ovs_flow_tbl_destroy(&dp->table); | ||
| 164 | free_percpu(dp->stats_percpu); | 164 | free_percpu(dp->stats_percpu); |
| 165 | release_net(ovs_dp_get_net(dp)); | 165 | release_net(ovs_dp_get_net(dp)); |
| 166 | kfree(dp->ports); | 166 | kfree(dp->ports); |
| @@ -466,6 +466,14 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
| 466 | 466 | ||
| 467 | skb_zerocopy(user_skb, skb, skb->len, hlen); | 467 | skb_zerocopy(user_skb, skb, skb->len, hlen); |
| 468 | 468 | ||
| 469 | /* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */ | ||
| 470 | if (!(dp->user_features & OVS_DP_F_UNALIGNED)) { | ||
| 471 | size_t plen = NLA_ALIGN(user_skb->len) - user_skb->len; | ||
| 472 | |||
| 473 | if (plen > 0) | ||
| 474 | memset(skb_put(user_skb, plen), 0, plen); | ||
| 475 | } | ||
| 476 | |||
| 469 | ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; | 477 | ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; |
| 470 | 478 | ||
| 471 | err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); | 479 | err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); |
| @@ -852,11 +860,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
| 852 | goto err_unlock_ovs; | 860 | goto err_unlock_ovs; |
| 853 | 861 | ||
| 854 | /* The unmasked key has to be the same for flow updates. */ | 862 | /* The unmasked key has to be the same for flow updates. */ |
| 855 | error = -EINVAL; | 863 | if (!ovs_flow_cmp_unmasked_key(flow, &match)) |
| 856 | if (!ovs_flow_cmp_unmasked_key(flow, &match)) { | ||
| 857 | OVS_NLERR("Flow modification message rejected, unmasked key does not match.\n"); | ||
| 858 | goto err_unlock_ovs; | 864 | goto err_unlock_ovs; |
| 859 | } | ||
| 860 | 865 | ||
| 861 | /* Update actions. */ | 866 | /* Update actions. */ |
| 862 | old_acts = ovsl_dereference(flow->sf_acts); | 867 | old_acts = ovsl_dereference(flow->sf_acts); |
| @@ -1079,6 +1084,7 @@ static size_t ovs_dp_cmd_msg_size(void) | |||
| 1079 | msgsize += nla_total_size(IFNAMSIZ); | 1084 | msgsize += nla_total_size(IFNAMSIZ); |
| 1080 | msgsize += nla_total_size(sizeof(struct ovs_dp_stats)); | 1085 | msgsize += nla_total_size(sizeof(struct ovs_dp_stats)); |
| 1081 | msgsize += nla_total_size(sizeof(struct ovs_dp_megaflow_stats)); | 1086 | msgsize += nla_total_size(sizeof(struct ovs_dp_megaflow_stats)); |
| 1087 | msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */ | ||
| 1082 | 1088 | ||
| 1083 | return msgsize; | 1089 | return msgsize; |
| 1084 | } | 1090 | } |
| @@ -1279,7 +1285,7 @@ err_destroy_ports_array: | |||
| 1279 | err_destroy_percpu: | 1285 | err_destroy_percpu: |
| 1280 | free_percpu(dp->stats_percpu); | 1286 | free_percpu(dp->stats_percpu); |
| 1281 | err_destroy_table: | 1287 | err_destroy_table: |
| 1282 | ovs_flow_tbl_destroy(&dp->table); | 1288 | ovs_flow_tbl_destroy(&dp->table, false); |
| 1283 | err_free_dp: | 1289 | err_free_dp: |
| 1284 | release_net(ovs_dp_get_net(dp)); | 1290 | release_net(ovs_dp_get_net(dp)); |
| 1285 | kfree(dp); | 1291 | kfree(dp); |
| @@ -1306,10 +1312,13 @@ static void __dp_destroy(struct datapath *dp) | |||
| 1306 | list_del_rcu(&dp->list_node); | 1312 | list_del_rcu(&dp->list_node); |
| 1307 | 1313 | ||
| 1308 | /* OVSP_LOCAL is datapath internal port. We need to make sure that | 1314 | /* OVSP_LOCAL is datapath internal port. We need to make sure that |
| 1309 | * all port in datapath are destroyed first before freeing datapath. | 1315 | * all ports in datapath are destroyed first before freeing datapath. |
| 1310 | */ | 1316 | */ |
| 1311 | ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL)); | 1317 | ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL)); |
| 1312 | 1318 | ||
| 1319 | /* RCU destroy the flow table */ | ||
| 1320 | ovs_flow_tbl_destroy(&dp->table, true); | ||
| 1321 | |||
| 1313 | call_rcu(&dp->rcu, destroy_dp_rcu); | 1322 | call_rcu(&dp->rcu, destroy_dp_rcu); |
| 1314 | } | 1323 | } |
| 1315 | 1324 | ||
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index c58a0fe3c889..3c268b3d71c3 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c | |||
| @@ -153,29 +153,29 @@ static void rcu_free_flow_callback(struct rcu_head *rcu) | |||
| 153 | flow_free(flow); | 153 | flow_free(flow); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | static void flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred) | ||
| 157 | { | ||
| 158 | if (!mask) | ||
| 159 | return; | ||
| 160 | |||
| 161 | BUG_ON(!mask->ref_count); | ||
| 162 | mask->ref_count--; | ||
| 163 | |||
| 164 | if (!mask->ref_count) { | ||
| 165 | list_del_rcu(&mask->list); | ||
| 166 | if (deferred) | ||
| 167 | kfree_rcu(mask, rcu); | ||
| 168 | else | ||
| 169 | kfree(mask); | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | void ovs_flow_free(struct sw_flow *flow, bool deferred) | 156 | void ovs_flow_free(struct sw_flow *flow, bool deferred) |
| 174 | { | 157 | { |
| 175 | if (!flow) | 158 | if (!flow) |
| 176 | return; | 159 | return; |
| 177 | 160 | ||
| 178 | flow_mask_del_ref(flow->mask, deferred); | 161 | if (flow->mask) { |
| 162 | struct sw_flow_mask *mask = flow->mask; | ||
| 163 | |||
| 164 | /* ovs-lock is required to protect mask-refcount and | ||
| 165 | * mask list. | ||
| 166 | */ | ||
| 167 | ASSERT_OVSL(); | ||
| 168 | BUG_ON(!mask->ref_count); | ||
| 169 | mask->ref_count--; | ||
| 170 | |||
| 171 | if (!mask->ref_count) { | ||
| 172 | list_del_rcu(&mask->list); | ||
| 173 | if (deferred) | ||
| 174 | kfree_rcu(mask, rcu); | ||
| 175 | else | ||
| 176 | kfree(mask); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | 179 | ||
| 180 | if (deferred) | 180 | if (deferred) |
| 181 | call_rcu(&flow->rcu, rcu_free_flow_callback); | 181 | call_rcu(&flow->rcu, rcu_free_flow_callback); |
| @@ -188,26 +188,9 @@ static void free_buckets(struct flex_array *buckets) | |||
| 188 | flex_array_free(buckets); | 188 | flex_array_free(buckets); |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | |||
| 191 | static void __table_instance_destroy(struct table_instance *ti) | 192 | static void __table_instance_destroy(struct table_instance *ti) |
| 192 | { | 193 | { |
| 193 | int i; | ||
| 194 | |||
| 195 | if (ti->keep_flows) | ||
| 196 | goto skip_flows; | ||
| 197 | |||
| 198 | for (i = 0; i < ti->n_buckets; i++) { | ||
| 199 | struct sw_flow *flow; | ||
| 200 | struct hlist_head *head = flex_array_get(ti->buckets, i); | ||
| 201 | struct hlist_node *n; | ||
| 202 | int ver = ti->node_ver; | ||
| 203 | |||
| 204 | hlist_for_each_entry_safe(flow, n, head, hash_node[ver]) { | ||
| 205 | hlist_del(&flow->hash_node[ver]); | ||
| 206 | ovs_flow_free(flow, false); | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | skip_flows: | ||
| 211 | free_buckets(ti->buckets); | 194 | free_buckets(ti->buckets); |
| 212 | kfree(ti); | 195 | kfree(ti); |
| 213 | } | 196 | } |
| @@ -258,20 +241,38 @@ static void flow_tbl_destroy_rcu_cb(struct rcu_head *rcu) | |||
| 258 | 241 | ||
| 259 | static void table_instance_destroy(struct table_instance *ti, bool deferred) | 242 | static void table_instance_destroy(struct table_instance *ti, bool deferred) |
| 260 | { | 243 | { |
| 244 | int i; | ||
| 245 | |||
| 261 | if (!ti) | 246 | if (!ti) |
| 262 | return; | 247 | return; |
| 263 | 248 | ||
| 249 | if (ti->keep_flows) | ||
| 250 | goto skip_flows; | ||
| 251 | |||
| 252 | for (i = 0; i < ti->n_buckets; i++) { | ||
| 253 | struct sw_flow *flow; | ||
| 254 | struct hlist_head *head = flex_array_get(ti->buckets, i); | ||
| 255 | struct hlist_node *n; | ||
| 256 | int ver = ti->node_ver; | ||
| 257 | |||
| 258 | hlist_for_each_entry_safe(flow, n, head, hash_node[ver]) { | ||
| 259 | hlist_del_rcu(&flow->hash_node[ver]); | ||
| 260 | ovs_flow_free(flow, deferred); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | skip_flows: | ||
| 264 | if (deferred) | 265 | if (deferred) |
| 265 | call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb); | 266 | call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb); |
| 266 | else | 267 | else |
| 267 | __table_instance_destroy(ti); | 268 | __table_instance_destroy(ti); |
| 268 | } | 269 | } |
| 269 | 270 | ||
| 270 | void ovs_flow_tbl_destroy(struct flow_table *table) | 271 | void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred) |
| 271 | { | 272 | { |
| 272 | struct table_instance *ti = ovsl_dereference(table->ti); | 273 | struct table_instance *ti = ovsl_dereference(table->ti); |
| 273 | 274 | ||
| 274 | table_instance_destroy(ti, false); | 275 | table_instance_destroy(ti, deferred); |
| 275 | } | 276 | } |
| 276 | 277 | ||
| 277 | struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti, | 278 | struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti, |
| @@ -504,16 +505,11 @@ static struct sw_flow_mask *mask_alloc(void) | |||
| 504 | 505 | ||
| 505 | mask = kmalloc(sizeof(*mask), GFP_KERNEL); | 506 | mask = kmalloc(sizeof(*mask), GFP_KERNEL); |
| 506 | if (mask) | 507 | if (mask) |
| 507 | mask->ref_count = 0; | 508 | mask->ref_count = 1; |
| 508 | 509 | ||
| 509 | return mask; | 510 | return mask; |
| 510 | } | 511 | } |
| 511 | 512 | ||
| 512 | static void mask_add_ref(struct sw_flow_mask *mask) | ||
| 513 | { | ||
| 514 | mask->ref_count++; | ||
| 515 | } | ||
| 516 | |||
| 517 | static bool mask_equal(const struct sw_flow_mask *a, | 513 | static bool mask_equal(const struct sw_flow_mask *a, |
| 518 | const struct sw_flow_mask *b) | 514 | const struct sw_flow_mask *b) |
| 519 | { | 515 | { |
| @@ -554,9 +550,11 @@ static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow, | |||
| 554 | mask->key = new->key; | 550 | mask->key = new->key; |
| 555 | mask->range = new->range; | 551 | mask->range = new->range; |
| 556 | list_add_rcu(&mask->list, &tbl->mask_list); | 552 | list_add_rcu(&mask->list, &tbl->mask_list); |
| 553 | } else { | ||
| 554 | BUG_ON(!mask->ref_count); | ||
| 555 | mask->ref_count++; | ||
| 557 | } | 556 | } |
| 558 | 557 | ||
| 559 | mask_add_ref(mask); | ||
| 560 | flow->mask = mask; | 558 | flow->mask = mask; |
| 561 | return 0; | 559 | return 0; |
| 562 | } | 560 | } |
diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h index 1996e34c0fd8..baaeb101924d 100644 --- a/net/openvswitch/flow_table.h +++ b/net/openvswitch/flow_table.h | |||
| @@ -60,7 +60,7 @@ void ovs_flow_free(struct sw_flow *, bool deferred); | |||
| 60 | 60 | ||
| 61 | int ovs_flow_tbl_init(struct flow_table *); | 61 | int ovs_flow_tbl_init(struct flow_table *); |
| 62 | int ovs_flow_tbl_count(struct flow_table *table); | 62 | int ovs_flow_tbl_count(struct flow_table *table); |
| 63 | void ovs_flow_tbl_destroy(struct flow_table *table); | 63 | void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred); |
| 64 | int ovs_flow_tbl_flush(struct flow_table *flow_table); | 64 | int ovs_flow_tbl_flush(struct flow_table *flow_table); |
| 65 | 65 | ||
| 66 | int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow, | 66 | int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow, |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 6a2bb37506c5..48a6a93db296 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -308,11 +308,27 @@ static bool packet_use_direct_xmit(const struct packet_sock *po) | |||
| 308 | return po->xmit == packet_direct_xmit; | 308 | return po->xmit == packet_direct_xmit; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | static u16 packet_pick_tx_queue(struct net_device *dev) | 311 | static u16 __packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb) |
| 312 | { | 312 | { |
| 313 | return (u16) raw_smp_processor_id() % dev->real_num_tx_queues; | 313 | return (u16) raw_smp_processor_id() % dev->real_num_tx_queues; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb) | ||
| 317 | { | ||
| 318 | const struct net_device_ops *ops = dev->netdev_ops; | ||
| 319 | u16 queue_index; | ||
| 320 | |||
| 321 | if (ops->ndo_select_queue) { | ||
| 322 | queue_index = ops->ndo_select_queue(dev, skb, NULL, | ||
| 323 | __packet_pick_tx_queue); | ||
| 324 | queue_index = netdev_cap_txqueue(dev, queue_index); | ||
| 325 | } else { | ||
| 326 | queue_index = __packet_pick_tx_queue(dev, skb); | ||
| 327 | } | ||
| 328 | |||
| 329 | skb_set_queue_mapping(skb, queue_index); | ||
| 330 | } | ||
| 331 | |||
| 316 | /* register_prot_hook must be invoked with the po->bind_lock held, | 332 | /* register_prot_hook must be invoked with the po->bind_lock held, |
| 317 | * or from a context in which asynchronous accesses to the packet | 333 | * or from a context in which asynchronous accesses to the packet |
| 318 | * socket is not possible (packet_create()). | 334 | * socket is not possible (packet_create()). |
| @@ -2285,7 +2301,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 2285 | } | 2301 | } |
| 2286 | } | 2302 | } |
| 2287 | 2303 | ||
| 2288 | skb_set_queue_mapping(skb, packet_pick_tx_queue(dev)); | 2304 | packet_pick_tx_queue(dev, skb); |
| 2305 | |||
| 2289 | skb->destructor = tpacket_destruct_skb; | 2306 | skb->destructor = tpacket_destruct_skb; |
| 2290 | __packet_set_status(po, ph, TP_STATUS_SENDING); | 2307 | __packet_set_status(po, ph, TP_STATUS_SENDING); |
| 2291 | packet_inc_pending(&po->tx_ring); | 2308 | packet_inc_pending(&po->tx_ring); |
| @@ -2499,7 +2516,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
| 2499 | skb->dev = dev; | 2516 | skb->dev = dev; |
| 2500 | skb->priority = sk->sk_priority; | 2517 | skb->priority = sk->sk_priority; |
| 2501 | skb->mark = sk->sk_mark; | 2518 | skb->mark = sk->sk_mark; |
| 2502 | skb_set_queue_mapping(skb, packet_pick_tx_queue(dev)); | 2519 | |
| 2520 | packet_pick_tx_queue(dev, skb); | ||
| 2503 | 2521 | ||
| 2504 | if (po->has_vnet_hdr) { | 2522 | if (po->has_vnet_hdr) { |
| 2505 | if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { | 2523 | if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { |
| @@ -3786,7 +3804,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
| 3786 | */ | 3804 | */ |
| 3787 | if (!tx_ring) | 3805 | if (!tx_ring) |
| 3788 | init_prb_bdqc(po, rb, pg_vec, req_u, tx_ring); | 3806 | init_prb_bdqc(po, rb, pg_vec, req_u, tx_ring); |
| 3789 | break; | 3807 | break; |
| 3790 | default: | 3808 | default: |
| 3791 | break; | 3809 | break; |
| 3792 | } | 3810 | } |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 1313145e3b86..a07d55e75698 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
| @@ -273,11 +273,12 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle) | |||
| 273 | 273 | ||
| 274 | void qdisc_list_add(struct Qdisc *q) | 274 | void qdisc_list_add(struct Qdisc *q) |
| 275 | { | 275 | { |
| 276 | struct Qdisc *root = qdisc_dev(q)->qdisc; | 276 | if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) { |
| 277 | struct Qdisc *root = qdisc_dev(q)->qdisc; | ||
| 277 | 278 | ||
| 278 | WARN_ON_ONCE(root == &noop_qdisc); | 279 | WARN_ON_ONCE(root == &noop_qdisc); |
| 279 | if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) | ||
| 280 | list_add_tail(&q->list, &root->list); | 280 | list_add_tail(&q->list, &root->list); |
| 281 | } | ||
| 281 | } | 282 | } |
| 282 | EXPORT_SYMBOL(qdisc_list_add); | 283 | EXPORT_SYMBOL(qdisc_list_add); |
| 283 | 284 | ||
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 08ef7a42c0e4..21e251766eb1 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
| @@ -601,6 +601,7 @@ static int fq_resize(struct Qdisc *sch, u32 log) | |||
| 601 | { | 601 | { |
| 602 | struct fq_sched_data *q = qdisc_priv(sch); | 602 | struct fq_sched_data *q = qdisc_priv(sch); |
| 603 | struct rb_root *array; | 603 | struct rb_root *array; |
| 604 | void *old_fq_root; | ||
| 604 | u32 idx; | 605 | u32 idx; |
| 605 | 606 | ||
| 606 | if (q->fq_root && log == q->fq_trees_log) | 607 | if (q->fq_root && log == q->fq_trees_log) |
| @@ -615,13 +616,19 @@ static int fq_resize(struct Qdisc *sch, u32 log) | |||
| 615 | for (idx = 0; idx < (1U << log); idx++) | 616 | for (idx = 0; idx < (1U << log); idx++) |
| 616 | array[idx] = RB_ROOT; | 617 | array[idx] = RB_ROOT; |
| 617 | 618 | ||
| 618 | if (q->fq_root) { | 619 | sch_tree_lock(sch); |
| 619 | fq_rehash(q, q->fq_root, q->fq_trees_log, array, log); | 620 | |
| 620 | fq_free(q->fq_root); | 621 | old_fq_root = q->fq_root; |
| 621 | } | 622 | if (old_fq_root) |
| 623 | fq_rehash(q, old_fq_root, q->fq_trees_log, array, log); | ||
| 624 | |||
| 622 | q->fq_root = array; | 625 | q->fq_root = array; |
| 623 | q->fq_trees_log = log; | 626 | q->fq_trees_log = log; |
| 624 | 627 | ||
| 628 | sch_tree_unlock(sch); | ||
| 629 | |||
| 630 | fq_free(old_fq_root); | ||
| 631 | |||
| 625 | return 0; | 632 | return 0; |
| 626 | } | 633 | } |
| 627 | 634 | ||
| @@ -697,9 +704,11 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 697 | q->flow_refill_delay = usecs_to_jiffies(usecs_delay); | 704 | q->flow_refill_delay = usecs_to_jiffies(usecs_delay); |
| 698 | } | 705 | } |
| 699 | 706 | ||
| 700 | if (!err) | 707 | if (!err) { |
| 708 | sch_tree_unlock(sch); | ||
| 701 | err = fq_resize(sch, fq_log); | 709 | err = fq_resize(sch, fq_log); |
| 702 | 710 | sch_tree_lock(sch); | |
| 711 | } | ||
| 703 | while (sch->q.qlen > sch->limit) { | 712 | while (sch->q.qlen > sch->limit) { |
| 704 | struct sk_buff *skb = fq_dequeue(sch); | 713 | struct sk_buff *skb = fq_dequeue(sch); |
| 705 | 714 | ||
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c index a255d0200a59..fefeeb73f15f 100644 --- a/net/sched/sch_pie.c +++ b/net/sched/sch_pie.c | |||
| @@ -15,6 +15,11 @@ | |||
| 15 | * | 15 | * |
| 16 | * ECN support is added by Naeem Khademi <naeemk@ifi.uio.no> | 16 | * ECN support is added by Naeem Khademi <naeemk@ifi.uio.no> |
| 17 | * University of Oslo, Norway. | 17 | * University of Oslo, Norway. |
| 18 | * | ||
| 19 | * References: | ||
| 20 | * IETF draft submission: http://tools.ietf.org/html/draft-pan-aqm-pie-00 | ||
| 21 | * IEEE Conference on High Performance Switching and Routing 2013 : | ||
| 22 | * "PIE: A * Lightweight Control Scheme to Address the Bufferbloat Problem" | ||
| 18 | */ | 23 | */ |
| 19 | 24 | ||
| 20 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| @@ -36,7 +41,7 @@ struct pie_params { | |||
| 36 | psched_time_t target; /* user specified target delay in pschedtime */ | 41 | psched_time_t target; /* user specified target delay in pschedtime */ |
| 37 | u32 tupdate; /* timer frequency (in jiffies) */ | 42 | u32 tupdate; /* timer frequency (in jiffies) */ |
| 38 | u32 limit; /* number of packets that can be enqueued */ | 43 | u32 limit; /* number of packets that can be enqueued */ |
| 39 | u32 alpha; /* alpha and beta are between -4 and 4 */ | 44 | u32 alpha; /* alpha and beta are between 0 and 32 */ |
| 40 | u32 beta; /* and are used for shift relative to 1 */ | 45 | u32 beta; /* and are used for shift relative to 1 */ |
| 41 | bool ecn; /* true if ecn is enabled */ | 46 | bool ecn; /* true if ecn is enabled */ |
| 42 | bool bytemode; /* to scale drop early prob based on pkt size */ | 47 | bool bytemode; /* to scale drop early prob based on pkt size */ |
| @@ -326,10 +331,16 @@ static void calculate_probability(struct Qdisc *sch) | |||
| 326 | if (qdelay == 0 && qlen != 0) | 331 | if (qdelay == 0 && qlen != 0) |
| 327 | update_prob = false; | 332 | update_prob = false; |
| 328 | 333 | ||
| 329 | /* Add ranges for alpha and beta, more aggressive for high dropping | 334 | /* In the algorithm, alpha and beta are between 0 and 2 with typical |
| 330 | * mode and gentle steps for light dropping mode | 335 | * value for alpha as 0.125. In this implementation, we use values 0-32 |
| 331 | * In light dropping mode, take gentle steps; in medium dropping mode, | 336 | * passed from user space to represent this. Also, alpha and beta have |
| 332 | * take medium steps; in high dropping mode, take big steps. | 337 | * unit of HZ and need to be scaled before they can used to update |
| 338 | * probability. alpha/beta are updated locally below by 1) scaling them | ||
| 339 | * appropriately 2) scaling down by 16 to come to 0-2 range. | ||
| 340 | * Please see paper for details. | ||
| 341 | * | ||
| 342 | * We scale alpha and beta differently depending on whether we are in | ||
| 343 | * light, medium or high dropping mode. | ||
| 333 | */ | 344 | */ |
| 334 | if (q->vars.prob < MAX_PROB / 100) { | 345 | if (q->vars.prob < MAX_PROB / 100) { |
| 335 | alpha = | 346 | alpha = |
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 1cb413fead89..4f505a006896 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
| @@ -334,18 +334,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 334 | qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate, | 334 | qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate, |
| 335 | tb[TCA_TBF_PTAB])); | 335 | tb[TCA_TBF_PTAB])); |
| 336 | 336 | ||
| 337 | if (q->qdisc != &noop_qdisc) { | ||
| 338 | err = fifo_set_limit(q->qdisc, qopt->limit); | ||
| 339 | if (err) | ||
| 340 | goto done; | ||
| 341 | } else if (qopt->limit > 0) { | ||
| 342 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); | ||
| 343 | if (IS_ERR(child)) { | ||
| 344 | err = PTR_ERR(child); | ||
| 345 | goto done; | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U); | 337 | buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U); |
| 350 | mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U); | 338 | mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U); |
| 351 | 339 | ||
| @@ -390,6 +378,18 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 390 | goto done; | 378 | goto done; |
| 391 | } | 379 | } |
| 392 | 380 | ||
| 381 | if (q->qdisc != &noop_qdisc) { | ||
| 382 | err = fifo_set_limit(q->qdisc, qopt->limit); | ||
| 383 | if (err) | ||
| 384 | goto done; | ||
| 385 | } else if (qopt->limit > 0) { | ||
| 386 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); | ||
| 387 | if (IS_ERR(child)) { | ||
| 388 | err = PTR_ERR(child); | ||
| 389 | goto done; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | sch_tree_lock(sch); | 393 | sch_tree_lock(sch); |
| 394 | if (child) { | 394 | if (child) { |
| 395 | qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); | 395 | qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 5ae609200674..ee13d28d39d1 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -1239,78 +1239,107 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
| 1239 | } | 1239 | } |
| 1240 | 1240 | ||
| 1241 | /* Update the retran path for sending a retransmitted packet. | 1241 | /* Update the retran path for sending a retransmitted packet. |
| 1242 | * Round-robin through the active transports, else round-robin | 1242 | * See also RFC4960, 6.4. Multi-Homed SCTP Endpoints: |
| 1243 | * through the inactive transports as this is the next best thing | 1243 | * |
| 1244 | * we can try. | 1244 | * When there is outbound data to send and the primary path |
| 1245 | * becomes inactive (e.g., due to failures), or where the | ||
| 1246 | * SCTP user explicitly requests to send data to an | ||
| 1247 | * inactive destination transport address, before reporting | ||
| 1248 | * an error to its ULP, the SCTP endpoint should try to send | ||
| 1249 | * the data to an alternate active destination transport | ||
| 1250 | * address if one exists. | ||
| 1251 | * | ||
| 1252 | * When retransmitting data that timed out, if the endpoint | ||
| 1253 | * is multihomed, it should consider each source-destination | ||
| 1254 | * address pair in its retransmission selection policy. | ||
| 1255 | * When retransmitting timed-out data, the endpoint should | ||
| 1256 | * attempt to pick the most divergent source-destination | ||
| 1257 | * pair from the original source-destination pair to which | ||
| 1258 | * the packet was transmitted. | ||
| 1259 | * | ||
| 1260 | * Note: Rules for picking the most divergent source-destination | ||
| 1261 | * pair are an implementation decision and are not specified | ||
| 1262 | * within this document. | ||
| 1263 | * | ||
| 1264 | * Our basic strategy is to round-robin transports in priorities | ||
| 1265 | * according to sctp_state_prio_map[] e.g., if no such | ||
| 1266 | * transport with state SCTP_ACTIVE exists, round-robin through | ||
| 1267 | * SCTP_UNKNOWN, etc. You get the picture. | ||
| 1245 | */ | 1268 | */ |
| 1246 | void sctp_assoc_update_retran_path(struct sctp_association *asoc) | 1269 | static const u8 sctp_trans_state_to_prio_map[] = { |
| 1270 | [SCTP_ACTIVE] = 3, /* best case */ | ||
| 1271 | [SCTP_UNKNOWN] = 2, | ||
| 1272 | [SCTP_PF] = 1, | ||
| 1273 | [SCTP_INACTIVE] = 0, /* worst case */ | ||
| 1274 | }; | ||
| 1275 | |||
| 1276 | static u8 sctp_trans_score(const struct sctp_transport *trans) | ||
| 1247 | { | 1277 | { |
| 1248 | struct sctp_transport *t, *next; | 1278 | return sctp_trans_state_to_prio_map[trans->state]; |
| 1249 | struct list_head *head = &asoc->peer.transport_addr_list; | 1279 | } |
| 1250 | struct list_head *pos; | ||
| 1251 | 1280 | ||
| 1252 | if (asoc->peer.transport_count == 1) | 1281 | static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr, |
| 1253 | return; | 1282 | struct sctp_transport *best) |
| 1283 | { | ||
| 1284 | if (best == NULL) | ||
| 1285 | return curr; | ||
| 1254 | 1286 | ||
| 1255 | /* Find the next transport in a round-robin fashion. */ | 1287 | return sctp_trans_score(curr) > sctp_trans_score(best) ? curr : best; |
| 1256 | t = asoc->peer.retran_path; | 1288 | } |
| 1257 | pos = &t->transports; | ||
| 1258 | next = NULL; | ||
| 1259 | 1289 | ||
| 1260 | while (1) { | 1290 | void sctp_assoc_update_retran_path(struct sctp_association *asoc) |
| 1261 | /* Skip the head. */ | 1291 | { |
| 1262 | if (pos->next == head) | 1292 | struct sctp_transport *trans = asoc->peer.retran_path; |
| 1263 | pos = head->next; | 1293 | struct sctp_transport *trans_next = NULL; |
| 1264 | else | ||
| 1265 | pos = pos->next; | ||
| 1266 | 1294 | ||
| 1267 | t = list_entry(pos, struct sctp_transport, transports); | 1295 | /* We're done as we only have the one and only path. */ |
| 1296 | if (asoc->peer.transport_count == 1) | ||
| 1297 | return; | ||
| 1298 | /* If active_path and retran_path are the same and active, | ||
| 1299 | * then this is the only active path. Use it. | ||
| 1300 | */ | ||
| 1301 | if (asoc->peer.active_path == asoc->peer.retran_path && | ||
| 1302 | asoc->peer.active_path->state == SCTP_ACTIVE) | ||
| 1303 | return; | ||
| 1268 | 1304 | ||
| 1269 | /* We have exhausted the list, but didn't find any | 1305 | /* Iterate from retran_path's successor back to retran_path. */ |
| 1270 | * other active transports. If so, use the next | 1306 | for (trans = list_next_entry(trans, transports); 1; |
| 1271 | * transport. | 1307 | trans = list_next_entry(trans, transports)) { |
| 1272 | */ | 1308 | /* Manually skip the head element. */ |
| 1273 | if (t == asoc->peer.retran_path) { | 1309 | if (&trans->transports == &asoc->peer.transport_addr_list) |
| 1274 | t = next; | 1310 | continue; |
| 1311 | if (trans->state == SCTP_UNCONFIRMED) | ||
| 1312 | continue; | ||
| 1313 | trans_next = sctp_trans_elect_best(trans, trans_next); | ||
| 1314 | /* Active is good enough for immediate return. */ | ||
| 1315 | if (trans_next->state == SCTP_ACTIVE) | ||
| 1275 | break; | 1316 | break; |
| 1276 | } | 1317 | /* We've reached the end, time to update path. */ |
| 1277 | 1318 | if (trans == asoc->peer.retran_path) | |
| 1278 | /* Try to find an active transport. */ | ||
| 1279 | |||
| 1280 | if ((t->state == SCTP_ACTIVE) || | ||
| 1281 | (t->state == SCTP_UNKNOWN)) { | ||
| 1282 | break; | 1319 | break; |
| 1283 | } else { | ||
| 1284 | /* Keep track of the next transport in case | ||
| 1285 | * we don't find any active transport. | ||
| 1286 | */ | ||
| 1287 | if (t->state != SCTP_UNCONFIRMED && !next) | ||
| 1288 | next = t; | ||
| 1289 | } | ||
| 1290 | } | 1320 | } |
| 1291 | 1321 | ||
| 1292 | if (t) | 1322 | if (trans_next != NULL) |
| 1293 | asoc->peer.retran_path = t; | 1323 | asoc->peer.retran_path = trans_next; |
| 1294 | else | ||
| 1295 | t = asoc->peer.retran_path; | ||
| 1296 | 1324 | ||
| 1297 | pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc, | 1325 | pr_debug("%s: association:%p updated new path to addr:%pISpc\n", |
| 1298 | &t->ipaddr.sa); | 1326 | __func__, asoc, &asoc->peer.retran_path->ipaddr.sa); |
| 1299 | } | 1327 | } |
| 1300 | 1328 | ||
| 1301 | /* Choose the transport for sending retransmit packet. */ | 1329 | struct sctp_transport * |
| 1302 | struct sctp_transport *sctp_assoc_choose_alter_transport( | 1330 | sctp_assoc_choose_alter_transport(struct sctp_association *asoc, |
| 1303 | struct sctp_association *asoc, struct sctp_transport *last_sent_to) | 1331 | struct sctp_transport *last_sent_to) |
| 1304 | { | 1332 | { |
| 1305 | /* If this is the first time packet is sent, use the active path, | 1333 | /* If this is the first time packet is sent, use the active path, |
| 1306 | * else use the retran path. If the last packet was sent over the | 1334 | * else use the retran path. If the last packet was sent over the |
| 1307 | * retran path, update the retran path and use it. | 1335 | * retran path, update the retran path and use it. |
| 1308 | */ | 1336 | */ |
| 1309 | if (!last_sent_to) | 1337 | if (last_sent_to == NULL) { |
| 1310 | return asoc->peer.active_path; | 1338 | return asoc->peer.active_path; |
| 1311 | else { | 1339 | } else { |
| 1312 | if (last_sent_to == asoc->peer.retran_path) | 1340 | if (last_sent_to == asoc->peer.retran_path) |
| 1313 | sctp_assoc_update_retran_path(asoc); | 1341 | sctp_assoc_update_retran_path(asoc); |
| 1342 | |||
| 1314 | return asoc->peer.retran_path; | 1343 | return asoc->peer.retran_path; |
| 1315 | } | 1344 | } |
| 1316 | } | 1345 | } |
| @@ -1367,44 +1396,35 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc) | |||
| 1367 | return false; | 1396 | return false; |
| 1368 | } | 1397 | } |
| 1369 | 1398 | ||
| 1370 | /* Increase asoc's rwnd by len and send any window update SACK if needed. */ | 1399 | /* Update asoc's rwnd for the approximated state in the buffer, |
| 1371 | void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) | 1400 | * and check whether SACK needs to be sent. |
| 1401 | */ | ||
| 1402 | void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer) | ||
| 1372 | { | 1403 | { |
| 1404 | int rx_count; | ||
| 1373 | struct sctp_chunk *sack; | 1405 | struct sctp_chunk *sack; |
| 1374 | struct timer_list *timer; | 1406 | struct timer_list *timer; |
| 1375 | 1407 | ||
| 1376 | if (asoc->rwnd_over) { | 1408 | if (asoc->ep->rcvbuf_policy) |
| 1377 | if (asoc->rwnd_over >= len) { | 1409 | rx_count = atomic_read(&asoc->rmem_alloc); |
| 1378 | asoc->rwnd_over -= len; | 1410 | else |
| 1379 | } else { | 1411 | rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); |
| 1380 | asoc->rwnd += (len - asoc->rwnd_over); | ||
| 1381 | asoc->rwnd_over = 0; | ||
| 1382 | } | ||
| 1383 | } else { | ||
| 1384 | asoc->rwnd += len; | ||
| 1385 | } | ||
| 1386 | 1412 | ||
| 1387 | /* If we had window pressure, start recovering it | 1413 | if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0) |
| 1388 | * once our rwnd had reached the accumulated pressure | 1414 | asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1; |
| 1389 | * threshold. The idea is to recover slowly, but up | 1415 | else |
| 1390 | * to the initial advertised window. | 1416 | asoc->rwnd = 0; |
| 1391 | */ | ||
| 1392 | if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) { | ||
| 1393 | int change = min(asoc->pathmtu, asoc->rwnd_press); | ||
| 1394 | asoc->rwnd += change; | ||
| 1395 | asoc->rwnd_press -= change; | ||
| 1396 | } | ||
| 1397 | 1417 | ||
| 1398 | pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n", | 1418 | pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n", |
| 1399 | __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, | 1419 | __func__, asoc, asoc->rwnd, rx_count, |
| 1400 | asoc->a_rwnd); | 1420 | asoc->base.sk->sk_rcvbuf); |
| 1401 | 1421 | ||
| 1402 | /* Send a window update SACK if the rwnd has increased by at least the | 1422 | /* Send a window update SACK if the rwnd has increased by at least the |
| 1403 | * minimum of the association's PMTU and half of the receive buffer. | 1423 | * minimum of the association's PMTU and half of the receive buffer. |
| 1404 | * The algorithm used is similar to the one described in | 1424 | * The algorithm used is similar to the one described in |
| 1405 | * Section 4.2.3.3 of RFC 1122. | 1425 | * Section 4.2.3.3 of RFC 1122. |
| 1406 | */ | 1426 | */ |
| 1407 | if (sctp_peer_needs_update(asoc)) { | 1427 | if (update_peer && sctp_peer_needs_update(asoc)) { |
| 1408 | asoc->a_rwnd = asoc->rwnd; | 1428 | asoc->a_rwnd = asoc->rwnd; |
| 1409 | 1429 | ||
| 1410 | pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " | 1430 | pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " |
| @@ -1426,45 +1446,6 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) | |||
| 1426 | } | 1446 | } |
| 1427 | } | 1447 | } |
| 1428 | 1448 | ||
| 1429 | /* Decrease asoc's rwnd by len. */ | ||
| 1430 | void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) | ||
| 1431 | { | ||
| 1432 | int rx_count; | ||
| 1433 | int over = 0; | ||
| 1434 | |||
| 1435 | if (unlikely(!asoc->rwnd || asoc->rwnd_over)) | ||
| 1436 | pr_debug("%s: association:%p has asoc->rwnd:%u, " | ||
| 1437 | "asoc->rwnd_over:%u!\n", __func__, asoc, | ||
| 1438 | asoc->rwnd, asoc->rwnd_over); | ||
| 1439 | |||
| 1440 | if (asoc->ep->rcvbuf_policy) | ||
| 1441 | rx_count = atomic_read(&asoc->rmem_alloc); | ||
| 1442 | else | ||
| 1443 | rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); | ||
| 1444 | |||
| 1445 | /* If we've reached or overflowed our receive buffer, announce | ||
| 1446 | * a 0 rwnd if rwnd would still be positive. Store the | ||
| 1447 | * the potential pressure overflow so that the window can be restored | ||
| 1448 | * back to original value. | ||
| 1449 | */ | ||
| 1450 | if (rx_count >= asoc->base.sk->sk_rcvbuf) | ||
| 1451 | over = 1; | ||
| 1452 | |||
| 1453 | if (asoc->rwnd >= len) { | ||
| 1454 | asoc->rwnd -= len; | ||
| 1455 | if (over) { | ||
| 1456 | asoc->rwnd_press += asoc->rwnd; | ||
| 1457 | asoc->rwnd = 0; | ||
| 1458 | } | ||
| 1459 | } else { | ||
| 1460 | asoc->rwnd_over = len - asoc->rwnd; | ||
| 1461 | asoc->rwnd = 0; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n", | ||
| 1465 | __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, | ||
| 1466 | asoc->rwnd_press); | ||
| 1467 | } | ||
| 1468 | 1449 | ||
| 1469 | /* Build the bind address list for the association based on info from the | 1450 | /* Build the bind address list for the association based on info from the |
| 1470 | * local endpoint and the remote peer. | 1451 | * local endpoint and the remote peer. |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 0f6259a6a932..2b1738ef9394 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
| @@ -662,6 +662,8 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
| 662 | */ | 662 | */ |
| 663 | sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk); | 663 | sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk); |
| 664 | 664 | ||
| 665 | newsk->sk_v6_rcv_saddr = sk->sk_v6_rcv_saddr; | ||
| 666 | |||
| 665 | sk_refcnt_debug_inc(newsk); | 667 | sk_refcnt_debug_inc(newsk); |
| 666 | 668 | ||
| 667 | if (newsk->sk_prot->init(newsk)) { | 669 | if (newsk->sk_prot->init(newsk)) { |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 632090b961c3..3a1767ef3201 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -1421,8 +1421,8 @@ static void sctp_chunk_destroy(struct sctp_chunk *chunk) | |||
| 1421 | BUG_ON(!list_empty(&chunk->list)); | 1421 | BUG_ON(!list_empty(&chunk->list)); |
| 1422 | list_del_init(&chunk->transmitted_list); | 1422 | list_del_init(&chunk->transmitted_list); |
| 1423 | 1423 | ||
| 1424 | /* Free the chunk skb data and the SCTP_chunk stub itself. */ | 1424 | consume_skb(chunk->skb); |
| 1425 | dev_kfree_skb(chunk->skb); | 1425 | consume_skb(chunk->auth_chunk); |
| 1426 | 1426 | ||
| 1427 | SCTP_DBG_OBJCNT_DEC(chunk); | 1427 | SCTP_DBG_OBJCNT_DEC(chunk); |
| 1428 | kmem_cache_free(sctp_chunk_cachep, chunk); | 1428 | kmem_cache_free(sctp_chunk_cachep, chunk); |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index bd859154000e..5d6883ff00c3 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
| @@ -495,11 +495,12 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands, | |||
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | /* If the transport error count is greater than the pf_retrans | 497 | /* If the transport error count is greater than the pf_retrans |
| 498 | * threshold, and less than pathmaxrtx, then mark this transport | 498 | * threshold, and less than pathmaxrtx, and if the current state |
| 499 | * as Partially Failed, ee SCTP Quick Failover Draft, secon 5.1, | 499 | * is not SCTP_UNCONFIRMED, then mark this transport as Partially |
| 500 | * point 1 | 500 | * Failed, see SCTP Quick Failover Draft, section 5.1 |
| 501 | */ | 501 | */ |
| 502 | if ((transport->state != SCTP_PF) && | 502 | if ((transport->state != SCTP_PF) && |
| 503 | (transport->state != SCTP_UNCONFIRMED) && | ||
| 503 | (asoc->pf_retrans < transport->pathmaxrxt) && | 504 | (asoc->pf_retrans < transport->pathmaxrxt) && |
| 504 | (transport->error_count > asoc->pf_retrans)) { | 505 | (transport->error_count > asoc->pf_retrans)) { |
| 505 | 506 | ||
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 483dcd71b3c5..01e002430c85 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -758,6 +758,12 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, | |||
| 758 | struct sctp_chunk auth; | 758 | struct sctp_chunk auth; |
| 759 | sctp_ierror_t ret; | 759 | sctp_ierror_t ret; |
| 760 | 760 | ||
| 761 | /* Make sure that we and the peer are AUTH capable */ | ||
| 762 | if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) { | ||
| 763 | sctp_association_free(new_asoc); | ||
| 764 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | ||
| 765 | } | ||
| 766 | |||
| 761 | /* set-up our fake chunk so that we can process it */ | 767 | /* set-up our fake chunk so that we can process it */ |
| 762 | auth.skb = chunk->auth_chunk; | 768 | auth.skb = chunk->auth_chunk; |
| 763 | auth.asoc = chunk->asoc; | 769 | auth.asoc = chunk->asoc; |
| @@ -768,10 +774,6 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, | |||
| 768 | auth.transport = chunk->transport; | 774 | auth.transport = chunk->transport; |
| 769 | 775 | ||
| 770 | ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth); | 776 | ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth); |
| 771 | |||
| 772 | /* We can now safely free the auth_chunk clone */ | ||
| 773 | kfree_skb(chunk->auth_chunk); | ||
| 774 | |||
| 775 | if (ret != SCTP_IERROR_NO_ERROR) { | 777 | if (ret != SCTP_IERROR_NO_ERROR) { |
| 776 | sctp_association_free(new_asoc); | 778 | sctp_association_free(new_asoc); |
| 777 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | 779 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
| @@ -6176,7 +6178,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
| 6176 | * PMTU. In cases, such as loopback, this might be a rather | 6178 | * PMTU. In cases, such as loopback, this might be a rather |
| 6177 | * large spill over. | 6179 | * large spill over. |
| 6178 | */ | 6180 | */ |
| 6179 | if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over || | 6181 | if ((!chunk->data_accepted) && (!asoc->rwnd || |
| 6180 | (datalen > asoc->rwnd + asoc->frag_point))) { | 6182 | (datalen > asoc->rwnd + asoc->frag_point))) { |
| 6181 | 6183 | ||
| 6182 | /* If this is the next TSN, consider reneging to make | 6184 | /* If this is the next TSN, consider reneging to make |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9e91d6e5df63..981aaf8b6ace 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -64,6 +64,7 @@ | |||
| 64 | #include <linux/crypto.h> | 64 | #include <linux/crypto.h> |
| 65 | #include <linux/slab.h> | 65 | #include <linux/slab.h> |
| 66 | #include <linux/file.h> | 66 | #include <linux/file.h> |
| 67 | #include <linux/compat.h> | ||
| 67 | 68 | ||
| 68 | #include <net/ip.h> | 69 | #include <net/ip.h> |
| 69 | #include <net/icmp.h> | 70 | #include <net/icmp.h> |
| @@ -1368,11 +1369,19 @@ static int sctp_setsockopt_connectx(struct sock *sk, | |||
| 1368 | /* | 1369 | /* |
| 1369 | * New (hopefully final) interface for the API. | 1370 | * New (hopefully final) interface for the API. |
| 1370 | * We use the sctp_getaddrs_old structure so that use-space library | 1371 | * We use the sctp_getaddrs_old structure so that use-space library |
| 1371 | * can avoid any unnecessary allocations. The only defferent part | 1372 | * can avoid any unnecessary allocations. The only different part |
| 1372 | * is that we store the actual length of the address buffer into the | 1373 | * is that we store the actual length of the address buffer into the |
| 1373 | * addrs_num structure member. That way we can re-use the existing | 1374 | * addrs_num structure member. That way we can re-use the existing |
| 1374 | * code. | 1375 | * code. |
| 1375 | */ | 1376 | */ |
| 1377 | #ifdef CONFIG_COMPAT | ||
| 1378 | struct compat_sctp_getaddrs_old { | ||
| 1379 | sctp_assoc_t assoc_id; | ||
| 1380 | s32 addr_num; | ||
| 1381 | compat_uptr_t addrs; /* struct sockaddr * */ | ||
| 1382 | }; | ||
| 1383 | #endif | ||
| 1384 | |||
| 1376 | static int sctp_getsockopt_connectx3(struct sock *sk, int len, | 1385 | static int sctp_getsockopt_connectx3(struct sock *sk, int len, |
| 1377 | char __user *optval, | 1386 | char __user *optval, |
| 1378 | int __user *optlen) | 1387 | int __user *optlen) |
| @@ -1381,16 +1390,30 @@ static int sctp_getsockopt_connectx3(struct sock *sk, int len, | |||
| 1381 | sctp_assoc_t assoc_id = 0; | 1390 | sctp_assoc_t assoc_id = 0; |
| 1382 | int err = 0; | 1391 | int err = 0; |
| 1383 | 1392 | ||
| 1384 | if (len < sizeof(param)) | 1393 | #ifdef CONFIG_COMPAT |
| 1385 | return -EINVAL; | 1394 | if (is_compat_task()) { |
| 1395 | struct compat_sctp_getaddrs_old param32; | ||
| 1386 | 1396 | ||
| 1387 | if (copy_from_user(¶m, optval, sizeof(param))) | 1397 | if (len < sizeof(param32)) |
| 1388 | return -EFAULT; | 1398 | return -EINVAL; |
| 1399 | if (copy_from_user(¶m32, optval, sizeof(param32))) | ||
| 1400 | return -EFAULT; | ||
| 1389 | 1401 | ||
| 1390 | err = __sctp_setsockopt_connectx(sk, | 1402 | param.assoc_id = param32.assoc_id; |
| 1391 | (struct sockaddr __user *)param.addrs, | 1403 | param.addr_num = param32.addr_num; |
| 1392 | param.addr_num, &assoc_id); | 1404 | param.addrs = compat_ptr(param32.addrs); |
| 1405 | } else | ||
| 1406 | #endif | ||
| 1407 | { | ||
| 1408 | if (len < sizeof(param)) | ||
| 1409 | return -EINVAL; | ||
| 1410 | if (copy_from_user(¶m, optval, sizeof(param))) | ||
| 1411 | return -EFAULT; | ||
| 1412 | } | ||
| 1393 | 1413 | ||
| 1414 | err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *) | ||
| 1415 | param.addrs, param.addr_num, | ||
| 1416 | &assoc_id); | ||
| 1394 | if (err == 0 || err == -EINPROGRESS) { | 1417 | if (err == 0 || err == -EINPROGRESS) { |
| 1395 | if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) | 1418 | if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) |
| 1396 | return -EFAULT; | 1419 | return -EFAULT; |
| @@ -2092,12 +2115,6 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
| 2092 | sctp_skb_pull(skb, copied); | 2115 | sctp_skb_pull(skb, copied); |
| 2093 | skb_queue_head(&sk->sk_receive_queue, skb); | 2116 | skb_queue_head(&sk->sk_receive_queue, skb); |
| 2094 | 2117 | ||
| 2095 | /* When only partial message is copied to the user, increase | ||
| 2096 | * rwnd by that amount. If all the data in the skb is read, | ||
| 2097 | * rwnd is updated when the event is freed. | ||
| 2098 | */ | ||
| 2099 | if (!sctp_ulpevent_is_notification(event)) | ||
| 2100 | sctp_assoc_rwnd_increase(event->asoc, copied); | ||
| 2101 | goto out; | 2118 | goto out; |
| 2102 | } else if ((event->msg_flags & MSG_NOTIFICATION) || | 2119 | } else if ((event->msg_flags & MSG_NOTIFICATION) || |
| 2103 | (event->msg_flags & MSG_EOR)) | 2120 | (event->msg_flags & MSG_EOR)) |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 7135e617ab0f..35c8923b5554 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
| @@ -151,6 +151,7 @@ static struct ctl_table sctp_net_table[] = { | |||
| 151 | }, | 151 | }, |
| 152 | { | 152 | { |
| 153 | .procname = "cookie_hmac_alg", | 153 | .procname = "cookie_hmac_alg", |
| 154 | .data = &init_net.sctp.sctp_hmac_alg, | ||
| 154 | .maxlen = 8, | 155 | .maxlen = 8, |
| 155 | .mode = 0644, | 156 | .mode = 0644, |
| 156 | .proc_handler = proc_sctp_do_hmac_alg, | 157 | .proc_handler = proc_sctp_do_hmac_alg, |
| @@ -401,15 +402,18 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | |||
| 401 | 402 | ||
| 402 | int sctp_sysctl_net_register(struct net *net) | 403 | int sctp_sysctl_net_register(struct net *net) |
| 403 | { | 404 | { |
| 404 | struct ctl_table *table; | 405 | struct ctl_table *table = sctp_net_table; |
| 405 | int i; | 406 | |
| 407 | if (!net_eq(net, &init_net)) { | ||
| 408 | int i; | ||
| 406 | 409 | ||
| 407 | table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); | 410 | table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); |
| 408 | if (!table) | 411 | if (!table) |
| 409 | return -ENOMEM; | 412 | return -ENOMEM; |
| 410 | 413 | ||
| 411 | for (i = 0; table[i].data; i++) | 414 | for (i = 0; table[i].data; i++) |
| 412 | table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; | 415 | table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; |
| 416 | } | ||
| 413 | 417 | ||
| 414 | net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); | 418 | net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); |
| 415 | return 0; | 419 | return 0; |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 85c64658bd0b..8d198ae03606 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
| @@ -989,7 +989,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, | |||
| 989 | skb = sctp_event2skb(event); | 989 | skb = sctp_event2skb(event); |
| 990 | /* Set the owner and charge rwnd for bytes received. */ | 990 | /* Set the owner and charge rwnd for bytes received. */ |
| 991 | sctp_ulpevent_set_owner(event, asoc); | 991 | sctp_ulpevent_set_owner(event, asoc); |
| 992 | sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb)); | 992 | sctp_assoc_rwnd_update(asoc, false); |
| 993 | 993 | ||
| 994 | if (!skb->data_len) | 994 | if (!skb->data_len) |
| 995 | return; | 995 | return; |
| @@ -1011,6 +1011,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | |||
| 1011 | { | 1011 | { |
| 1012 | struct sk_buff *skb, *frag; | 1012 | struct sk_buff *skb, *frag; |
| 1013 | unsigned int len; | 1013 | unsigned int len; |
| 1014 | struct sctp_association *asoc; | ||
| 1014 | 1015 | ||
| 1015 | /* Current stack structures assume that the rcv buffer is | 1016 | /* Current stack structures assume that the rcv buffer is |
| 1016 | * per socket. For UDP style sockets this is not true as | 1017 | * per socket. For UDP style sockets this is not true as |
| @@ -1035,8 +1036,11 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | |||
| 1035 | } | 1036 | } |
| 1036 | 1037 | ||
| 1037 | done: | 1038 | done: |
| 1038 | sctp_assoc_rwnd_increase(event->asoc, len); | 1039 | asoc = event->asoc; |
| 1040 | sctp_association_hold(asoc); | ||
| 1039 | sctp_ulpevent_release_owner(event); | 1041 | sctp_ulpevent_release_owner(event); |
| 1042 | sctp_assoc_rwnd_update(asoc, true); | ||
| 1043 | sctp_association_put(asoc); | ||
| 1040 | } | 1044 | } |
| 1041 | 1045 | ||
| 1042 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) | 1046 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) |
diff --git a/net/socket.c b/net/socket.c index 879933aaed4c..a19ae1968d37 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -450,16 +450,17 @@ EXPORT_SYMBOL(sockfd_lookup); | |||
| 450 | 450 | ||
| 451 | static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) | 451 | static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) |
| 452 | { | 452 | { |
| 453 | struct file *file; | 453 | struct fd f = fdget(fd); |
| 454 | struct socket *sock; | 454 | struct socket *sock; |
| 455 | 455 | ||
| 456 | *err = -EBADF; | 456 | *err = -EBADF; |
| 457 | file = fget_light(fd, fput_needed); | 457 | if (f.file) { |
| 458 | if (file) { | 458 | sock = sock_from_file(f.file, err); |
| 459 | sock = sock_from_file(file, err); | 459 | if (likely(sock)) { |
| 460 | if (sock) | 460 | *fput_needed = f.flags; |
| 461 | return sock; | 461 | return sock; |
| 462 | fput_light(file, *fput_needed); | 462 | } |
| 463 | fdput(f); | ||
| 463 | } | 464 | } |
| 464 | return NULL; | 465 | return NULL; |
| 465 | } | 466 | } |
| @@ -1985,6 +1986,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, | |||
| 1985 | { | 1986 | { |
| 1986 | if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) | 1987 | if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) |
| 1987 | return -EFAULT; | 1988 | return -EFAULT; |
| 1989 | |||
| 1990 | if (kmsg->msg_namelen < 0) | ||
| 1991 | return -EINVAL; | ||
| 1992 | |||
| 1988 | if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) | 1993 | if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) |
| 1989 | kmsg->msg_namelen = sizeof(struct sockaddr_storage); | 1994 | kmsg->msg_namelen = sizeof(struct sockaddr_storage); |
| 1990 | return 0; | 1995 | return 0; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 6c0513a7f992..36e431ee1c90 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
| @@ -108,6 +108,7 @@ struct gss_auth { | |||
| 108 | static DEFINE_SPINLOCK(pipe_version_lock); | 108 | static DEFINE_SPINLOCK(pipe_version_lock); |
| 109 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; | 109 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; |
| 110 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); | 110 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); |
| 111 | static void gss_put_auth(struct gss_auth *gss_auth); | ||
| 111 | 112 | ||
| 112 | static void gss_free_ctx(struct gss_cl_ctx *); | 113 | static void gss_free_ctx(struct gss_cl_ctx *); |
| 113 | static const struct rpc_pipe_ops gss_upcall_ops_v0; | 114 | static const struct rpc_pipe_ops gss_upcall_ops_v0; |
| @@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) | |||
| 320 | if (gss_msg->ctx != NULL) | 321 | if (gss_msg->ctx != NULL) |
| 321 | gss_put_ctx(gss_msg->ctx); | 322 | gss_put_ctx(gss_msg->ctx); |
| 322 | rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue); | 323 | rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue); |
| 324 | gss_put_auth(gss_msg->auth); | ||
| 323 | kfree(gss_msg); | 325 | kfree(gss_msg); |
| 324 | } | 326 | } |
| 325 | 327 | ||
| @@ -498,9 +500,12 @@ gss_alloc_msg(struct gss_auth *gss_auth, | |||
| 498 | default: | 500 | default: |
| 499 | err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); | 501 | err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); |
| 500 | if (err) | 502 | if (err) |
| 501 | goto err_free_msg; | 503 | goto err_put_pipe_version; |
| 502 | }; | 504 | }; |
| 505 | kref_get(&gss_auth->kref); | ||
| 503 | return gss_msg; | 506 | return gss_msg; |
| 507 | err_put_pipe_version: | ||
| 508 | put_pipe_version(gss_auth->net); | ||
| 504 | err_free_msg: | 509 | err_free_msg: |
| 505 | kfree(gss_msg); | 510 | kfree(gss_msg); |
| 506 | err: | 511 | err: |
| @@ -991,6 +996,8 @@ gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | |||
| 991 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); | 996 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); |
| 992 | if (gss_auth->service == 0) | 997 | if (gss_auth->service == 0) |
| 993 | goto err_put_mech; | 998 | goto err_put_mech; |
| 999 | if (!gssd_running(gss_auth->net)) | ||
| 1000 | goto err_put_mech; | ||
| 994 | auth = &gss_auth->rpc_auth; | 1001 | auth = &gss_auth->rpc_auth; |
| 995 | auth->au_cslack = GSS_CRED_SLACK >> 2; | 1002 | auth->au_cslack = GSS_CRED_SLACK >> 2; |
| 996 | auth->au_rslack = GSS_VERF_SLACK >> 2; | 1003 | auth->au_rslack = GSS_VERF_SLACK >> 2; |
| @@ -1062,6 +1069,12 @@ gss_free_callback(struct kref *kref) | |||
| 1062 | } | 1069 | } |
| 1063 | 1070 | ||
| 1064 | static void | 1071 | static void |
| 1072 | gss_put_auth(struct gss_auth *gss_auth) | ||
| 1073 | { | ||
| 1074 | kref_put(&gss_auth->kref, gss_free_callback); | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | static void | ||
| 1065 | gss_destroy(struct rpc_auth *auth) | 1078 | gss_destroy(struct rpc_auth *auth) |
| 1066 | { | 1079 | { |
| 1067 | struct gss_auth *gss_auth = container_of(auth, | 1080 | struct gss_auth *gss_auth = container_of(auth, |
| @@ -1082,7 +1095,7 @@ gss_destroy(struct rpc_auth *auth) | |||
| 1082 | gss_auth->gss_pipe[1] = NULL; | 1095 | gss_auth->gss_pipe[1] = NULL; |
| 1083 | rpcauth_destroy_credcache(auth); | 1096 | rpcauth_destroy_credcache(auth); |
| 1084 | 1097 | ||
| 1085 | kref_put(&gss_auth->kref, gss_free_callback); | 1098 | gss_put_auth(gss_auth); |
| 1086 | } | 1099 | } |
| 1087 | 1100 | ||
| 1088 | /* | 1101 | /* |
| @@ -1253,7 +1266,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) | |||
| 1253 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); | 1266 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); |
| 1254 | if (ctx) | 1267 | if (ctx) |
| 1255 | gss_put_ctx(ctx); | 1268 | gss_put_ctx(ctx); |
| 1256 | kref_put(&gss_auth->kref, gss_free_callback); | 1269 | gss_put_auth(gss_auth); |
| 1257 | } | 1270 | } |
| 1258 | 1271 | ||
| 1259 | static void | 1272 | static void |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 890a29912d5a..e860d4f7ed2a 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
| @@ -64,7 +64,6 @@ static void xprt_free_allocation(struct rpc_rqst *req) | |||
| 64 | free_page((unsigned long)xbufp->head[0].iov_base); | 64 | free_page((unsigned long)xbufp->head[0].iov_base); |
| 65 | xbufp = &req->rq_snd_buf; | 65 | xbufp = &req->rq_snd_buf; |
| 66 | free_page((unsigned long)xbufp->head[0].iov_base); | 66 | free_page((unsigned long)xbufp->head[0].iov_base); |
| 67 | list_del(&req->rq_bc_pa_list); | ||
| 68 | kfree(req); | 67 | kfree(req); |
| 69 | } | 68 | } |
| 70 | 69 | ||
| @@ -168,8 +167,10 @@ out_free: | |||
| 168 | /* | 167 | /* |
| 169 | * Memory allocation failed, free the temporary list | 168 | * Memory allocation failed, free the temporary list |
| 170 | */ | 169 | */ |
| 171 | list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) | 170 | list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) { |
| 171 | list_del(&req->rq_bc_pa_list); | ||
| 172 | xprt_free_allocation(req); | 172 | xprt_free_allocation(req); |
| 173 | } | ||
| 173 | 174 | ||
| 174 | dprintk("RPC: setup backchannel transport failed\n"); | 175 | dprintk("RPC: setup backchannel transport failed\n"); |
| 175 | return -ENOMEM; | 176 | return -ENOMEM; |
| @@ -198,6 +199,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) | |||
| 198 | xprt_dec_alloc_count(xprt, max_reqs); | 199 | xprt_dec_alloc_count(xprt, max_reqs); |
| 199 | list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { | 200 | list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { |
| 200 | dprintk("RPC: req=%p\n", req); | 201 | dprintk("RPC: req=%p\n", req); |
| 202 | list_del(&req->rq_bc_pa_list); | ||
| 201 | xprt_free_allocation(req); | 203 | xprt_free_allocation(req); |
| 202 | if (--max_reqs == 0) | 204 | if (--max_reqs == 0) |
| 203 | break; | 205 | break; |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 80a6640f329b..06c6ff0cb911 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
| @@ -571,7 +571,7 @@ static void svc_check_conn_limits(struct svc_serv *serv) | |||
| 571 | } | 571 | } |
| 572 | } | 572 | } |
| 573 | 573 | ||
| 574 | int svc_alloc_arg(struct svc_rqst *rqstp) | 574 | static int svc_alloc_arg(struct svc_rqst *rqstp) |
| 575 | { | 575 | { |
| 576 | struct svc_serv *serv = rqstp->rq_server; | 576 | struct svc_serv *serv = rqstp->rq_server; |
| 577 | struct xdr_buf *arg; | 577 | struct xdr_buf *arg; |
| @@ -612,7 +612,7 @@ int svc_alloc_arg(struct svc_rqst *rqstp) | |||
| 612 | return 0; | 612 | return 0; |
| 613 | } | 613 | } |
| 614 | 614 | ||
| 615 | struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) | 615 | static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) |
| 616 | { | 616 | { |
| 617 | struct svc_xprt *xprt; | 617 | struct svc_xprt *xprt; |
| 618 | struct svc_pool *pool = rqstp->rq_pool; | 618 | struct svc_pool *pool = rqstp->rq_pool; |
| @@ -691,7 +691,7 @@ struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) | |||
| 691 | return xprt; | 691 | return xprt; |
| 692 | } | 692 | } |
| 693 | 693 | ||
| 694 | void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) | 694 | static void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) |
| 695 | { | 695 | { |
| 696 | spin_lock_bh(&serv->sv_lock); | 696 | spin_lock_bh(&serv->sv_lock); |
| 697 | set_bit(XPT_TEMP, &newxpt->xpt_flags); | 697 | set_bit(XPT_TEMP, &newxpt->xpt_flags); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 817a1e523969..0addefca8e77 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -510,6 +510,7 @@ static int xs_nospace(struct rpc_task *task) | |||
| 510 | struct rpc_rqst *req = task->tk_rqstp; | 510 | struct rpc_rqst *req = task->tk_rqstp; |
| 511 | struct rpc_xprt *xprt = req->rq_xprt; | 511 | struct rpc_xprt *xprt = req->rq_xprt; |
| 512 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 512 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
| 513 | struct sock *sk = transport->inet; | ||
| 513 | int ret = -EAGAIN; | 514 | int ret = -EAGAIN; |
| 514 | 515 | ||
| 515 | dprintk("RPC: %5u xmit incomplete (%u left of %u)\n", | 516 | dprintk("RPC: %5u xmit incomplete (%u left of %u)\n", |
| @@ -527,7 +528,7 @@ static int xs_nospace(struct rpc_task *task) | |||
| 527 | * window size | 528 | * window size |
| 528 | */ | 529 | */ |
| 529 | set_bit(SOCK_NOSPACE, &transport->sock->flags); | 530 | set_bit(SOCK_NOSPACE, &transport->sock->flags); |
| 530 | transport->inet->sk_write_pending++; | 531 | sk->sk_write_pending++; |
| 531 | /* ...and wait for more buffer space */ | 532 | /* ...and wait for more buffer space */ |
| 532 | xprt_wait_for_buffer_space(task, xs_nospace_callback); | 533 | xprt_wait_for_buffer_space(task, xs_nospace_callback); |
| 533 | } | 534 | } |
| @@ -537,6 +538,9 @@ static int xs_nospace(struct rpc_task *task) | |||
| 537 | } | 538 | } |
| 538 | 539 | ||
| 539 | spin_unlock_bh(&xprt->transport_lock); | 540 | spin_unlock_bh(&xprt->transport_lock); |
| 541 | |||
| 542 | /* Race breaker in case memory is freed before above code is called */ | ||
| 543 | sk->sk_write_space(sk); | ||
| 540 | return ret; | 544 | return ret; |
| 541 | } | 545 | } |
| 542 | 546 | ||
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index a38c89969c68..574b86193b15 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -610,8 +610,13 @@ static struct notifier_block notifier = { | |||
| 610 | 610 | ||
| 611 | int tipc_bearer_setup(void) | 611 | int tipc_bearer_setup(void) |
| 612 | { | 612 | { |
| 613 | int err; | ||
| 614 | |||
| 615 | err = register_netdevice_notifier(¬ifier); | ||
| 616 | if (err) | ||
| 617 | return err; | ||
| 613 | dev_add_pack(&tipc_packet_type); | 618 | dev_add_pack(&tipc_packet_type); |
| 614 | return register_netdevice_notifier(¬ifier); | 619 | return 0; |
| 615 | } | 620 | } |
| 616 | 621 | ||
| 617 | void tipc_bearer_cleanup(void) | 622 | void tipc_bearer_cleanup(void) |
diff --git a/net/tipc/config.c b/net/tipc/config.c index c301a9a592d8..e6d721692ae0 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
| @@ -181,7 +181,7 @@ static struct sk_buff *cfg_set_own_addr(void) | |||
| 181 | if (tipc_own_addr) | 181 | if (tipc_own_addr) |
| 182 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 182 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 183 | " (cannot change node address once assigned)"); | 183 | " (cannot change node address once assigned)"); |
| 184 | tipc_core_start_net(addr); | 184 | tipc_net_start(addr); |
| 185 | return tipc_cfg_reply_none(); | 185 | return tipc_cfg_reply_none(); |
| 186 | } | 186 | } |
| 187 | 187 | ||
| @@ -376,7 +376,6 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr, | |||
| 376 | struct tipc_cfg_msg_hdr *req_hdr; | 376 | struct tipc_cfg_msg_hdr *req_hdr; |
| 377 | struct tipc_cfg_msg_hdr *rep_hdr; | 377 | struct tipc_cfg_msg_hdr *rep_hdr; |
| 378 | struct sk_buff *rep_buf; | 378 | struct sk_buff *rep_buf; |
| 379 | int ret; | ||
| 380 | 379 | ||
| 381 | /* Validate configuration message header (ignore invalid message) */ | 380 | /* Validate configuration message header (ignore invalid message) */ |
| 382 | req_hdr = (struct tipc_cfg_msg_hdr *)buf; | 381 | req_hdr = (struct tipc_cfg_msg_hdr *)buf; |
| @@ -398,12 +397,8 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr, | |||
| 398 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); | 397 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); |
| 399 | rep_hdr->tcm_len = htonl(rep_buf->len); | 398 | rep_hdr->tcm_len = htonl(rep_buf->len); |
| 400 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); | 399 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); |
| 401 | 400 | tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, | |
| 402 | ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, | 401 | rep_buf->len); |
| 403 | rep_buf->len); | ||
| 404 | if (ret < 0) | ||
| 405 | pr_err("Sending cfg reply message failed, no memory\n"); | ||
| 406 | |||
| 407 | kfree_skb(rep_buf); | 402 | kfree_skb(rep_buf); |
| 408 | } | 403 | } |
| 409 | } | 404 | } |
diff --git a/net/tipc/core.c b/net/tipc/core.c index f9e88d8b04ca..80c20647b3d2 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
| @@ -77,37 +77,13 @@ struct sk_buff *tipc_buf_acquire(u32 size) | |||
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | /** | 79 | /** |
| 80 | * tipc_core_stop_net - shut down TIPC networking sub-systems | ||
| 81 | */ | ||
| 82 | static void tipc_core_stop_net(void) | ||
| 83 | { | ||
| 84 | tipc_net_stop(); | ||
| 85 | tipc_bearer_cleanup(); | ||
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * start_net - start TIPC networking sub-systems | ||
| 90 | */ | ||
| 91 | int tipc_core_start_net(unsigned long addr) | ||
| 92 | { | ||
| 93 | int res; | ||
| 94 | |||
| 95 | tipc_net_start(addr); | ||
| 96 | res = tipc_bearer_setup(); | ||
| 97 | if (res < 0) | ||
| 98 | goto err; | ||
| 99 | return res; | ||
| 100 | |||
| 101 | err: | ||
| 102 | tipc_core_stop_net(); | ||
| 103 | return res; | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode | 80 | * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode |
| 108 | */ | 81 | */ |
| 109 | static void tipc_core_stop(void) | 82 | static void tipc_core_stop(void) |
| 110 | { | 83 | { |
| 84 | tipc_handler_stop(); | ||
| 85 | tipc_net_stop(); | ||
| 86 | tipc_bearer_cleanup(); | ||
| 111 | tipc_netlink_stop(); | 87 | tipc_netlink_stop(); |
| 112 | tipc_cfg_stop(); | 88 | tipc_cfg_stop(); |
| 113 | tipc_subscr_stop(); | 89 | tipc_subscr_stop(); |
| @@ -122,30 +98,65 @@ static void tipc_core_stop(void) | |||
| 122 | */ | 98 | */ |
| 123 | static int tipc_core_start(void) | 99 | static int tipc_core_start(void) |
| 124 | { | 100 | { |
| 125 | int res; | 101 | int err; |
| 126 | 102 | ||
| 127 | get_random_bytes(&tipc_random, sizeof(tipc_random)); | 103 | get_random_bytes(&tipc_random, sizeof(tipc_random)); |
| 128 | 104 | ||
| 129 | res = tipc_handler_start(); | 105 | err = tipc_handler_start(); |
| 130 | if (!res) | 106 | if (err) |
| 131 | res = tipc_ref_table_init(tipc_max_ports, tipc_random); | 107 | goto out_handler; |
| 132 | if (!res) | 108 | |
| 133 | res = tipc_nametbl_init(); | 109 | err = tipc_ref_table_init(tipc_max_ports, tipc_random); |
| 134 | if (!res) | 110 | if (err) |
| 135 | res = tipc_netlink_start(); | 111 | goto out_reftbl; |
| 136 | if (!res) | 112 | |
| 137 | res = tipc_socket_init(); | 113 | err = tipc_nametbl_init(); |
| 138 | if (!res) | 114 | if (err) |
| 139 | res = tipc_register_sysctl(); | 115 | goto out_nametbl; |
| 140 | if (!res) | 116 | |
| 141 | res = tipc_subscr_start(); | 117 | err = tipc_netlink_start(); |
| 142 | if (!res) | 118 | if (err) |
| 143 | res = tipc_cfg_init(); | 119 | goto out_netlink; |
| 144 | if (res) { | 120 | |
| 145 | tipc_handler_stop(); | 121 | err = tipc_socket_init(); |
| 146 | tipc_core_stop(); | 122 | if (err) |
| 147 | } | 123 | goto out_socket; |
| 148 | return res; | 124 | |
| 125 | err = tipc_register_sysctl(); | ||
| 126 | if (err) | ||
| 127 | goto out_sysctl; | ||
| 128 | |||
| 129 | err = tipc_subscr_start(); | ||
| 130 | if (err) | ||
| 131 | goto out_subscr; | ||
| 132 | |||
| 133 | err = tipc_cfg_init(); | ||
| 134 | if (err) | ||
| 135 | goto out_cfg; | ||
| 136 | |||
| 137 | err = tipc_bearer_setup(); | ||
| 138 | if (err) | ||
| 139 | goto out_bearer; | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | out_bearer: | ||
| 143 | tipc_cfg_stop(); | ||
| 144 | out_cfg: | ||
| 145 | tipc_subscr_stop(); | ||
| 146 | out_subscr: | ||
| 147 | tipc_unregister_sysctl(); | ||
| 148 | out_sysctl: | ||
| 149 | tipc_socket_stop(); | ||
| 150 | out_socket: | ||
| 151 | tipc_netlink_stop(); | ||
| 152 | out_netlink: | ||
| 153 | tipc_nametbl_stop(); | ||
| 154 | out_nametbl: | ||
| 155 | tipc_ref_table_stop(); | ||
| 156 | out_reftbl: | ||
| 157 | tipc_handler_stop(); | ||
| 158 | out_handler: | ||
| 159 | return err; | ||
| 149 | } | 160 | } |
| 150 | 161 | ||
| 151 | static int __init tipc_init(void) | 162 | static int __init tipc_init(void) |
| @@ -174,8 +185,6 @@ static int __init tipc_init(void) | |||
| 174 | 185 | ||
| 175 | static void __exit tipc_exit(void) | 186 | static void __exit tipc_exit(void) |
| 176 | { | 187 | { |
| 177 | tipc_handler_stop(); | ||
| 178 | tipc_core_stop_net(); | ||
| 179 | tipc_core_stop(); | 188 | tipc_core_stop(); |
| 180 | pr_info("Deactivated\n"); | 189 | pr_info("Deactivated\n"); |
| 181 | } | 190 | } |
diff --git a/net/tipc/core.h b/net/tipc/core.h index 1ff477b0450d..4dfe137587bb 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
| @@ -90,7 +90,6 @@ extern int tipc_random __read_mostly; | |||
| 90 | /* | 90 | /* |
| 91 | * Routines available to privileged subsystems | 91 | * Routines available to privileged subsystems |
| 92 | */ | 92 | */ |
| 93 | int tipc_core_start_net(unsigned long); | ||
| 94 | int tipc_handler_start(void); | 93 | int tipc_handler_start(void); |
| 95 | void tipc_handler_stop(void); | 94 | void tipc_handler_stop(void); |
| 96 | int tipc_netlink_start(void); | 95 | int tipc_netlink_start(void); |
| @@ -192,6 +191,7 @@ static inline void k_term_timer(struct timer_list *timer) | |||
| 192 | 191 | ||
| 193 | struct tipc_skb_cb { | 192 | struct tipc_skb_cb { |
| 194 | void *handle; | 193 | void *handle; |
| 194 | bool deferred; | ||
| 195 | }; | 195 | }; |
| 196 | 196 | ||
| 197 | #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) | 197 | #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) |
diff --git a/net/tipc/handler.c b/net/tipc/handler.c index e4bc8a296744..1fabf160501f 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c | |||
| @@ -58,7 +58,6 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument) | |||
| 58 | 58 | ||
| 59 | spin_lock_bh(&qitem_lock); | 59 | spin_lock_bh(&qitem_lock); |
| 60 | if (!handler_enabled) { | 60 | if (!handler_enabled) { |
| 61 | pr_err("Signal request ignored by handler\n"); | ||
| 62 | spin_unlock_bh(&qitem_lock); | 61 | spin_unlock_bh(&qitem_lock); |
| 63 | return -ENOPROTOOPT; | 62 | return -ENOPROTOOPT; |
| 64 | } | 63 | } |
diff --git a/net/tipc/link.c b/net/tipc/link.c index d4b5de41b682..da6018beb6eb 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -1391,6 +1391,12 @@ static int link_recv_buf_validate(struct sk_buff *buf) | |||
| 1391 | u32 hdr_size; | 1391 | u32 hdr_size; |
| 1392 | u32 min_hdr_size; | 1392 | u32 min_hdr_size; |
| 1393 | 1393 | ||
| 1394 | /* If this packet comes from the defer queue, the skb has already | ||
| 1395 | * been validated | ||
| 1396 | */ | ||
| 1397 | if (unlikely(TIPC_SKB_CB(buf)->deferred)) | ||
| 1398 | return 1; | ||
| 1399 | |||
| 1394 | if (unlikely(buf->len < MIN_H_SIZE)) | 1400 | if (unlikely(buf->len < MIN_H_SIZE)) |
| 1395 | return 0; | 1401 | return 0; |
| 1396 | 1402 | ||
| @@ -1703,6 +1709,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, | |||
| 1703 | &l_ptr->newest_deferred_in, buf)) { | 1709 | &l_ptr->newest_deferred_in, buf)) { |
| 1704 | l_ptr->deferred_inqueue_sz++; | 1710 | l_ptr->deferred_inqueue_sz++; |
| 1705 | l_ptr->stats.deferred_recv++; | 1711 | l_ptr->stats.deferred_recv++; |
| 1712 | TIPC_SKB_CB(buf)->deferred = true; | ||
| 1706 | if ((l_ptr->deferred_inqueue_sz % 16) == 1) | 1713 | if ((l_ptr->deferred_inqueue_sz % 16) == 1) |
| 1707 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | 1714 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); |
| 1708 | } else | 1715 | } else |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 92a1533af4e0..042e8e3cabc0 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
| @@ -941,20 +941,48 @@ int tipc_nametbl_init(void) | |||
| 941 | return 0; | 941 | return 0; |
| 942 | } | 942 | } |
| 943 | 943 | ||
| 944 | void tipc_nametbl_stop(void) | 944 | /** |
| 945 | * tipc_purge_publications - remove all publications for a given type | ||
| 946 | * | ||
| 947 | * tipc_nametbl_lock must be held when calling this function | ||
| 948 | */ | ||
| 949 | static void tipc_purge_publications(struct name_seq *seq) | ||
| 945 | { | 950 | { |
| 946 | u32 i; | 951 | struct publication *publ, *safe; |
| 952 | struct sub_seq *sseq; | ||
| 953 | struct name_info *info; | ||
| 947 | 954 | ||
| 948 | if (!table.types) | 955 | if (!seq->sseqs) { |
| 956 | nameseq_delete_empty(seq); | ||
| 949 | return; | 957 | return; |
| 958 | } | ||
| 959 | sseq = seq->sseqs; | ||
| 960 | info = sseq->info; | ||
| 961 | list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) { | ||
| 962 | tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, | ||
| 963 | publ->ref, publ->key); | ||
| 964 | } | ||
| 965 | } | ||
| 966 | |||
| 967 | void tipc_nametbl_stop(void) | ||
| 968 | { | ||
| 969 | u32 i; | ||
| 970 | struct name_seq *seq; | ||
| 971 | struct hlist_head *seq_head; | ||
| 972 | struct hlist_node *safe; | ||
| 950 | 973 | ||
| 951 | /* Verify name table is empty, then release it */ | 974 | /* Verify name table is empty and purge any lingering |
| 975 | * publications, then release the name table | ||
| 976 | */ | ||
| 952 | write_lock_bh(&tipc_nametbl_lock); | 977 | write_lock_bh(&tipc_nametbl_lock); |
| 953 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { | 978 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { |
| 954 | if (hlist_empty(&table.types[i])) | 979 | if (hlist_empty(&table.types[i])) |
| 955 | continue; | 980 | continue; |
| 956 | pr_err("nametbl_stop(): orphaned hash chain detected\n"); | 981 | seq_head = &table.types[i]; |
| 957 | break; | 982 | hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) { |
| 983 | tipc_purge_publications(seq); | ||
| 984 | } | ||
| 985 | continue; | ||
| 958 | } | 986 | } |
| 959 | kfree(table.types); | 987 | kfree(table.types); |
| 960 | table.types = NULL; | 988 | table.types = NULL; |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 9f72a6376362..3aaf73de9e2d 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
| @@ -83,8 +83,6 @@ static struct genl_ops tipc_genl_ops[] = { | |||
| 83 | }, | 83 | }, |
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | static int tipc_genl_family_registered; | ||
| 87 | |||
| 88 | int tipc_netlink_start(void) | 86 | int tipc_netlink_start(void) |
| 89 | { | 87 | { |
| 90 | int res; | 88 | int res; |
| @@ -94,16 +92,10 @@ int tipc_netlink_start(void) | |||
| 94 | pr_err("Failed to register netlink interface\n"); | 92 | pr_err("Failed to register netlink interface\n"); |
| 95 | return res; | 93 | return res; |
| 96 | } | 94 | } |
| 97 | |||
| 98 | tipc_genl_family_registered = 1; | ||
| 99 | return 0; | 95 | return 0; |
| 100 | } | 96 | } |
| 101 | 97 | ||
| 102 | void tipc_netlink_stop(void) | 98 | void tipc_netlink_stop(void) |
| 103 | { | 99 | { |
| 104 | if (!tipc_genl_family_registered) | ||
| 105 | return; | ||
| 106 | |||
| 107 | genl_unregister_family(&tipc_genl_family); | 100 | genl_unregister_family(&tipc_genl_family); |
| 108 | tipc_genl_family_registered = 0; | ||
| 109 | } | 101 | } |
diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 2a2a938dc22c..de3d593e2fee 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c | |||
| @@ -126,9 +126,6 @@ int tipc_ref_table_init(u32 requested_size, u32 start) | |||
| 126 | */ | 126 | */ |
| 127 | void tipc_ref_table_stop(void) | 127 | void tipc_ref_table_stop(void) |
| 128 | { | 128 | { |
| 129 | if (!tipc_ref_table.entries) | ||
| 130 | return; | ||
| 131 | |||
| 132 | vfree(tipc_ref_table.entries); | 129 | vfree(tipc_ref_table.entries); |
| 133 | tipc_ref_table.entries = NULL; | 130 | tipc_ref_table.entries = NULL; |
| 134 | } | 131 | } |
diff --git a/net/tipc/server.c b/net/tipc/server.c index b635ca347a87..646a930eefbf 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c | |||
| @@ -87,7 +87,6 @@ static void tipc_clean_outqueues(struct tipc_conn *con); | |||
| 87 | static void tipc_conn_kref_release(struct kref *kref) | 87 | static void tipc_conn_kref_release(struct kref *kref) |
| 88 | { | 88 | { |
| 89 | struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); | 89 | struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); |
| 90 | struct tipc_server *s = con->server; | ||
| 91 | 90 | ||
| 92 | if (con->sock) { | 91 | if (con->sock) { |
| 93 | tipc_sock_release_local(con->sock); | 92 | tipc_sock_release_local(con->sock); |
| @@ -95,10 +94,6 @@ static void tipc_conn_kref_release(struct kref *kref) | |||
| 95 | } | 94 | } |
| 96 | 95 | ||
| 97 | tipc_clean_outqueues(con); | 96 | tipc_clean_outqueues(con); |
| 98 | |||
| 99 | if (con->conid) | ||
| 100 | s->tipc_conn_shutdown(con->conid, con->usr_data); | ||
| 101 | |||
| 102 | kfree(con); | 97 | kfree(con); |
| 103 | } | 98 | } |
| 104 | 99 | ||
| @@ -181,6 +176,9 @@ static void tipc_close_conn(struct tipc_conn *con) | |||
| 181 | struct tipc_server *s = con->server; | 176 | struct tipc_server *s = con->server; |
| 182 | 177 | ||
| 183 | if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { | 178 | if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { |
| 179 | if (con->conid) | ||
| 180 | s->tipc_conn_shutdown(con->conid, con->usr_data); | ||
| 181 | |||
| 184 | spin_lock_bh(&s->idr_lock); | 182 | spin_lock_bh(&s->idr_lock); |
| 185 | idr_remove(&s->conn_idr, con->conid); | 183 | idr_remove(&s->conn_idr, con->conid); |
| 186 | s->idr_in_use--; | 184 | s->idr_in_use--; |
| @@ -429,10 +427,12 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid, | |||
| 429 | list_add_tail(&e->list, &con->outqueue); | 427 | list_add_tail(&e->list, &con->outqueue); |
| 430 | spin_unlock_bh(&con->outqueue_lock); | 428 | spin_unlock_bh(&con->outqueue_lock); |
| 431 | 429 | ||
| 432 | if (test_bit(CF_CONNECTED, &con->flags)) | 430 | if (test_bit(CF_CONNECTED, &con->flags)) { |
| 433 | if (!queue_work(s->send_wq, &con->swork)) | 431 | if (!queue_work(s->send_wq, &con->swork)) |
| 434 | conn_put(con); | 432 | conn_put(con); |
| 435 | 433 | } else { | |
| 434 | conn_put(con); | ||
| 435 | } | ||
| 436 | return 0; | 436 | return 0; |
| 437 | } | 437 | } |
| 438 | 438 | ||
| @@ -573,7 +573,6 @@ int tipc_server_start(struct tipc_server *s) | |||
| 573 | kmem_cache_destroy(s->rcvbuf_cache); | 573 | kmem_cache_destroy(s->rcvbuf_cache); |
| 574 | return ret; | 574 | return ret; |
| 575 | } | 575 | } |
| 576 | s->enabled = 1; | ||
| 577 | return ret; | 576 | return ret; |
| 578 | } | 577 | } |
| 579 | 578 | ||
| @@ -583,10 +582,6 @@ void tipc_server_stop(struct tipc_server *s) | |||
| 583 | int total = 0; | 582 | int total = 0; |
| 584 | int id; | 583 | int id; |
| 585 | 584 | ||
| 586 | if (!s->enabled) | ||
| 587 | return; | ||
| 588 | |||
| 589 | s->enabled = 0; | ||
| 590 | spin_lock_bh(&s->idr_lock); | 585 | spin_lock_bh(&s->idr_lock); |
| 591 | for (id = 0; total < s->idr_in_use; id++) { | 586 | for (id = 0; total < s->idr_in_use; id++) { |
| 592 | con = idr_find(&s->conn_idr, id); | 587 | con = idr_find(&s->conn_idr, id); |
diff --git a/net/tipc/server.h b/net/tipc/server.h index 98b23f20bc0f..be817b0b547e 100644 --- a/net/tipc/server.h +++ b/net/tipc/server.h | |||
| @@ -56,7 +56,6 @@ | |||
| 56 | * @name: server name | 56 | * @name: server name |
| 57 | * @imp: message importance | 57 | * @imp: message importance |
| 58 | * @type: socket type | 58 | * @type: socket type |
| 59 | * @enabled: identify whether server is launched or not | ||
| 60 | */ | 59 | */ |
| 61 | struct tipc_server { | 60 | struct tipc_server { |
| 62 | struct idr conn_idr; | 61 | struct idr conn_idr; |
| @@ -74,7 +73,6 @@ struct tipc_server { | |||
| 74 | const char name[TIPC_SERVER_NAME_LEN]; | 73 | const char name[TIPC_SERVER_NAME_LEN]; |
| 75 | int imp; | 74 | int imp; |
| 76 | int type; | 75 | int type; |
| 77 | int enabled; | ||
| 78 | }; | 76 | }; |
| 79 | 77 | ||
| 80 | int tipc_conn_sendmsg(struct tipc_server *s, int conid, | 78 | int tipc_conn_sendmsg(struct tipc_server *s, int conid, |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index aab4948f0aff..0ed0eaa62f29 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -70,8 +70,6 @@ static const struct proto_ops msg_ops; | |||
| 70 | static struct proto tipc_proto; | 70 | static struct proto tipc_proto; |
| 71 | static struct proto tipc_proto_kern; | 71 | static struct proto tipc_proto_kern; |
| 72 | 72 | ||
| 73 | static int sockets_enabled; | ||
| 74 | |||
| 75 | /* | 73 | /* |
| 76 | * Revised TIPC socket locking policy: | 74 | * Revised TIPC socket locking policy: |
| 77 | * | 75 | * |
| @@ -999,7 +997,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo) | |||
| 999 | 997 | ||
| 1000 | for (;;) { | 998 | for (;;) { |
| 1001 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 999 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1002 | if (skb_queue_empty(&sk->sk_receive_queue)) { | 1000 | if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { |
| 1003 | if (sock->state == SS_DISCONNECTING) { | 1001 | if (sock->state == SS_DISCONNECTING) { |
| 1004 | err = -ENOTCONN; | 1002 | err = -ENOTCONN; |
| 1005 | break; | 1003 | break; |
| @@ -1625,7 +1623,7 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo) | |||
| 1625 | for (;;) { | 1623 | for (;;) { |
| 1626 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, | 1624 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
| 1627 | TASK_INTERRUPTIBLE); | 1625 | TASK_INTERRUPTIBLE); |
| 1628 | if (skb_queue_empty(&sk->sk_receive_queue)) { | 1626 | if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { |
| 1629 | release_sock(sk); | 1627 | release_sock(sk); |
| 1630 | timeo = schedule_timeout(timeo); | 1628 | timeo = schedule_timeout(timeo); |
| 1631 | lock_sock(sk); | 1629 | lock_sock(sk); |
| @@ -2027,8 +2025,6 @@ int tipc_socket_init(void) | |||
| 2027 | proto_unregister(&tipc_proto); | 2025 | proto_unregister(&tipc_proto); |
| 2028 | goto out; | 2026 | goto out; |
| 2029 | } | 2027 | } |
| 2030 | |||
| 2031 | sockets_enabled = 1; | ||
| 2032 | out: | 2028 | out: |
| 2033 | return res; | 2029 | return res; |
| 2034 | } | 2030 | } |
| @@ -2038,10 +2034,6 @@ int tipc_socket_init(void) | |||
| 2038 | */ | 2034 | */ |
| 2039 | void tipc_socket_stop(void) | 2035 | void tipc_socket_stop(void) |
| 2040 | { | 2036 | { |
| 2041 | if (!sockets_enabled) | ||
| 2042 | return; | ||
| 2043 | |||
| 2044 | sockets_enabled = 0; | ||
| 2045 | sock_unregister(tipc_family_ops.family); | 2037 | sock_unregister(tipc_family_ops.family); |
| 2046 | proto_unregister(&tipc_proto); | 2038 | proto_unregister(&tipc_proto); |
| 2047 | } | 2039 | } |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 7cb0bd5b1176..11c9ae00837d 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
| @@ -96,20 +96,16 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, | |||
| 96 | { | 96 | { |
| 97 | struct tipc_subscriber *subscriber = sub->subscriber; | 97 | struct tipc_subscriber *subscriber = sub->subscriber; |
| 98 | struct kvec msg_sect; | 98 | struct kvec msg_sect; |
| 99 | int ret; | ||
| 100 | 99 | ||
| 101 | msg_sect.iov_base = (void *)&sub->evt; | 100 | msg_sect.iov_base = (void *)&sub->evt; |
| 102 | msg_sect.iov_len = sizeof(struct tipc_event); | 101 | msg_sect.iov_len = sizeof(struct tipc_event); |
| 103 | |||
| 104 | sub->evt.event = htohl(event, sub->swap); | 102 | sub->evt.event = htohl(event, sub->swap); |
| 105 | sub->evt.found_lower = htohl(found_lower, sub->swap); | 103 | sub->evt.found_lower = htohl(found_lower, sub->swap); |
| 106 | sub->evt.found_upper = htohl(found_upper, sub->swap); | 104 | sub->evt.found_upper = htohl(found_upper, sub->swap); |
| 107 | sub->evt.port.ref = htohl(port_ref, sub->swap); | 105 | sub->evt.port.ref = htohl(port_ref, sub->swap); |
| 108 | sub->evt.port.node = htohl(node, sub->swap); | 106 | sub->evt.port.node = htohl(node, sub->swap); |
| 109 | ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, | 107 | tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base, |
| 110 | msg_sect.iov_base, msg_sect.iov_len); | 108 | msg_sect.iov_len); |
| 111 | if (ret < 0) | ||
| 112 | pr_err("Sending subscription event failed, no memory\n"); | ||
| 113 | } | 109 | } |
| 114 | 110 | ||
| 115 | /** | 111 | /** |
| @@ -153,14 +149,6 @@ static void subscr_timeout(struct tipc_subscription *sub) | |||
| 153 | /* The spin lock per subscriber is used to protect its members */ | 149 | /* The spin lock per subscriber is used to protect its members */ |
| 154 | spin_lock_bh(&subscriber->lock); | 150 | spin_lock_bh(&subscriber->lock); |
| 155 | 151 | ||
| 156 | /* Validate if the connection related to the subscriber is | ||
| 157 | * closed (in case subscriber is terminating) | ||
| 158 | */ | ||
| 159 | if (subscriber->conid == 0) { | ||
| 160 | spin_unlock_bh(&subscriber->lock); | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | |||
| 164 | /* Validate timeout (in case subscription is being cancelled) */ | 152 | /* Validate timeout (in case subscription is being cancelled) */ |
| 165 | if (sub->timeout == TIPC_WAIT_FOREVER) { | 153 | if (sub->timeout == TIPC_WAIT_FOREVER) { |
| 166 | spin_unlock_bh(&subscriber->lock); | 154 | spin_unlock_bh(&subscriber->lock); |
| @@ -215,9 +203,6 @@ static void subscr_release(struct tipc_subscriber *subscriber) | |||
| 215 | 203 | ||
| 216 | spin_lock_bh(&subscriber->lock); | 204 | spin_lock_bh(&subscriber->lock); |
| 217 | 205 | ||
| 218 | /* Invalidate subscriber reference */ | ||
| 219 | subscriber->conid = 0; | ||
| 220 | |||
| 221 | /* Destroy any existing subscriptions for subscriber */ | 206 | /* Destroy any existing subscriptions for subscriber */ |
| 222 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 207 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, |
| 223 | subscription_list) { | 208 | subscription_list) { |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 29fc8bee9702..ce6ec6c2f4de 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -163,9 +163,8 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) | |||
| 163 | 163 | ||
| 164 | static inline unsigned int unix_hash_fold(__wsum n) | 164 | static inline unsigned int unix_hash_fold(__wsum n) |
| 165 | { | 165 | { |
| 166 | unsigned int hash = (__force unsigned int)n; | 166 | unsigned int hash = (__force unsigned int)csum_fold(n); |
| 167 | 167 | ||
| 168 | hash ^= hash>>16; | ||
| 169 | hash ^= hash>>8; | 168 | hash ^= hash>>8; |
| 170 | return hash&(UNIX_HASH_SIZE-1); | 169 | return hash&(UNIX_HASH_SIZE-1); |
| 171 | } | 170 | } |
diff --git a/net/wireless/core.c b/net/wireless/core.c index d89dee2259b5..a3bf18d11609 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | |||
| 203 | 203 | ||
| 204 | rdev->opencount--; | 204 | rdev->opencount--; |
| 205 | 205 | ||
| 206 | WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && | 206 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { |
| 207 | !rdev->scan_req->notified); | 207 | if (WARN_ON(!rdev->scan_req->notified)) |
| 208 | rdev->scan_req->aborted = true; | ||
| 209 | ___cfg80211_scan_done(rdev, false); | ||
| 210 | } | ||
| 208 | } | 211 | } |
| 209 | 212 | ||
| 210 | static int cfg80211_rfkill_set_block(void *data, bool blocked) | 213 | static int cfg80211_rfkill_set_block(void *data, bool blocked) |
| @@ -440,9 +443,6 @@ int wiphy_register(struct wiphy *wiphy) | |||
| 440 | int i; | 443 | int i; |
| 441 | u16 ifmodes = wiphy->interface_modes; | 444 | u16 ifmodes = wiphy->interface_modes; |
| 442 | 445 | ||
| 443 | /* support for 5/10 MHz is broken due to nl80211 API mess - disable */ | ||
| 444 | wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ; | ||
| 445 | |||
| 446 | /* | 446 | /* |
| 447 | * There are major locking problems in nl80211/mac80211 for CSA, | 447 | * There are major locking problems in nl80211/mac80211 for CSA, |
| 448 | * disable for all drivers until this has been reworked. | 448 | * disable for all drivers until this has been reworked. |
| @@ -788,8 +788,6 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
| 788 | default: | 788 | default: |
| 789 | break; | 789 | break; |
| 790 | } | 790 | } |
| 791 | |||
| 792 | wdev->beacon_interval = 0; | ||
| 793 | } | 791 | } |
| 794 | 792 | ||
| 795 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | 793 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, |
| @@ -859,8 +857,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
| 859 | break; | 857 | break; |
| 860 | case NETDEV_DOWN: | 858 | case NETDEV_DOWN: |
| 861 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); | 859 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); |
| 862 | WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && | 860 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { |
| 863 | !rdev->scan_req->notified); | 861 | if (WARN_ON(!rdev->scan_req->notified)) |
| 862 | rdev->scan_req->aborted = true; | ||
| 863 | ___cfg80211_scan_done(rdev, false); | ||
| 864 | } | ||
| 864 | 865 | ||
| 865 | if (WARN_ON(rdev->sched_scan_req && | 866 | if (WARN_ON(rdev->sched_scan_req && |
| 866 | rdev->sched_scan_req->dev == wdev->netdev)) { | 867 | rdev->sched_scan_req->dev == wdev->netdev)) { |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 37ec16d7bb1a..f1d193b557b6 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
| @@ -62,6 +62,7 @@ struct cfg80211_registered_device { | |||
| 62 | struct rb_root bss_tree; | 62 | struct rb_root bss_tree; |
| 63 | u32 bss_generation; | 63 | u32 bss_generation; |
| 64 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ | 64 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ |
| 65 | struct sk_buff *scan_msg; | ||
| 65 | struct cfg80211_sched_scan_request *sched_scan_req; | 66 | struct cfg80211_sched_scan_request *sched_scan_req; |
| 66 | unsigned long suspend_at; | 67 | unsigned long suspend_at; |
| 67 | struct work_struct scan_done_wk; | 68 | struct work_struct scan_done_wk; |
| @@ -361,7 +362,8 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | |||
| 361 | struct key_params *params, int key_idx, | 362 | struct key_params *params, int key_idx, |
| 362 | bool pairwise, const u8 *mac_addr); | 363 | bool pairwise, const u8 *mac_addr); |
| 363 | void __cfg80211_scan_done(struct work_struct *wk); | 364 | void __cfg80211_scan_done(struct work_struct *wk); |
| 364 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev); | 365 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, |
| 366 | bool send_message); | ||
| 365 | void __cfg80211_sched_scan_results(struct work_struct *wk); | 367 | void __cfg80211_sched_scan_results(struct work_struct *wk); |
| 366 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | 368 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, |
| 367 | bool driver_initiated); | 369 | bool driver_initiated); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7a742594916e..4fe2e6e2bc76 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -1719,9 +1719,10 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1719 | * We can then retry with the larger buffer. | 1719 | * We can then retry with the larger buffer. |
| 1720 | */ | 1720 | */ |
| 1721 | if ((ret == -ENOBUFS || ret == -EMSGSIZE) && | 1721 | if ((ret == -ENOBUFS || ret == -EMSGSIZE) && |
| 1722 | !skb->len && | 1722 | !skb->len && !state->split && |
| 1723 | cb->min_dump_alloc < 4096) { | 1723 | cb->min_dump_alloc < 4096) { |
| 1724 | cb->min_dump_alloc = 4096; | 1724 | cb->min_dump_alloc = 4096; |
| 1725 | state->split_start = 0; | ||
| 1725 | rtnl_unlock(); | 1726 | rtnl_unlock(); |
| 1726 | return 1; | 1727 | return 1; |
| 1727 | } | 1728 | } |
| @@ -5244,7 +5245,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
| 5244 | if (!rdev->ops->scan) | 5245 | if (!rdev->ops->scan) |
| 5245 | return -EOPNOTSUPP; | 5246 | return -EOPNOTSUPP; |
| 5246 | 5247 | ||
| 5247 | if (rdev->scan_req) { | 5248 | if (rdev->scan_req || rdev->scan_msg) { |
| 5248 | err = -EBUSY; | 5249 | err = -EBUSY; |
| 5249 | goto unlock; | 5250 | goto unlock; |
| 5250 | } | 5251 | } |
| @@ -10011,40 +10012,31 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | |||
| 10011 | NL80211_MCGRP_SCAN, GFP_KERNEL); | 10012 | NL80211_MCGRP_SCAN, GFP_KERNEL); |
| 10012 | } | 10013 | } |
| 10013 | 10014 | ||
| 10014 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | 10015 | struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, |
| 10015 | struct wireless_dev *wdev) | 10016 | struct wireless_dev *wdev, bool aborted) |
| 10016 | { | 10017 | { |
| 10017 | struct sk_buff *msg; | 10018 | struct sk_buff *msg; |
| 10018 | 10019 | ||
| 10019 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 10020 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
| 10020 | if (!msg) | 10021 | if (!msg) |
| 10021 | return; | 10022 | return NULL; |
| 10022 | 10023 | ||
| 10023 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, | 10024 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, |
| 10024 | NL80211_CMD_NEW_SCAN_RESULTS) < 0) { | 10025 | aborted ? NL80211_CMD_SCAN_ABORTED : |
| 10026 | NL80211_CMD_NEW_SCAN_RESULTS) < 0) { | ||
| 10025 | nlmsg_free(msg); | 10027 | nlmsg_free(msg); |
| 10026 | return; | 10028 | return NULL; |
| 10027 | } | 10029 | } |
| 10028 | 10030 | ||
| 10029 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | 10031 | return msg; |
| 10030 | NL80211_MCGRP_SCAN, GFP_KERNEL); | ||
| 10031 | } | 10032 | } |
| 10032 | 10033 | ||
| 10033 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 10034 | void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, |
| 10034 | struct wireless_dev *wdev) | 10035 | struct sk_buff *msg) |
| 10035 | { | 10036 | { |
| 10036 | struct sk_buff *msg; | ||
| 10037 | |||
| 10038 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 10039 | if (!msg) | 10037 | if (!msg) |
| 10040 | return; | 10038 | return; |
| 10041 | 10039 | ||
| 10042 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, | ||
| 10043 | NL80211_CMD_SCAN_ABORTED) < 0) { | ||
| 10044 | nlmsg_free(msg); | ||
| 10045 | return; | ||
| 10046 | } | ||
| 10047 | |||
| 10048 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | 10040 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, |
| 10049 | NL80211_MCGRP_SCAN, GFP_KERNEL); | 10041 | NL80211_MCGRP_SCAN, GFP_KERNEL); |
| 10050 | } | 10042 | } |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index b1b231324e10..75799746d845 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
| @@ -8,10 +8,10 @@ void nl80211_exit(void); | |||
| 8 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); | 8 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); |
| 9 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | 9 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, |
| 10 | struct wireless_dev *wdev); | 10 | struct wireless_dev *wdev); |
| 11 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | 11 | struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, |
| 12 | struct wireless_dev *wdev); | 12 | struct wireless_dev *wdev, bool aborted); |
| 13 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 13 | void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, |
| 14 | struct wireless_dev *wdev); | 14 | struct sk_buff *msg); |
| 15 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | 15 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, |
| 16 | struct net_device *netdev, u32 cmd); | 16 | struct net_device *netdev, u32 cmd); |
| 17 | void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, | 17 | void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 9b897fca7487..f0541370e68e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
| 1700 | return; | 1700 | return; |
| 1701 | case NL80211_REGDOM_SET_BY_USER: | 1701 | case NL80211_REGDOM_SET_BY_USER: |
| 1702 | treatment = reg_process_hint_user(reg_request); | 1702 | treatment = reg_process_hint_user(reg_request); |
| 1703 | if (treatment == REG_REQ_OK || | 1703 | if (treatment == REG_REQ_IGNORE || |
| 1704 | treatment == REG_REQ_ALREADY_SET) | 1704 | treatment == REG_REQ_ALREADY_SET) |
| 1705 | return; | 1705 | return; |
| 1706 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | 1706 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); |
| @@ -2373,6 +2373,7 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, | |||
| 2373 | int set_regdom(const struct ieee80211_regdomain *rd) | 2373 | int set_regdom(const struct ieee80211_regdomain *rd) |
| 2374 | { | 2374 | { |
| 2375 | struct regulatory_request *lr; | 2375 | struct regulatory_request *lr; |
| 2376 | bool user_reset = false; | ||
| 2376 | int r; | 2377 | int r; |
| 2377 | 2378 | ||
| 2378 | if (!reg_is_valid_request(rd->alpha2)) { | 2379 | if (!reg_is_valid_request(rd->alpha2)) { |
| @@ -2389,6 +2390,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2389 | break; | 2390 | break; |
| 2390 | case NL80211_REGDOM_SET_BY_USER: | 2391 | case NL80211_REGDOM_SET_BY_USER: |
| 2391 | r = reg_set_rd_user(rd, lr); | 2392 | r = reg_set_rd_user(rd, lr); |
| 2393 | user_reset = true; | ||
| 2392 | break; | 2394 | break; |
| 2393 | case NL80211_REGDOM_SET_BY_DRIVER: | 2395 | case NL80211_REGDOM_SET_BY_DRIVER: |
| 2394 | r = reg_set_rd_driver(rd, lr); | 2396 | r = reg_set_rd_driver(rd, lr); |
| @@ -2402,8 +2404,14 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2402 | } | 2404 | } |
| 2403 | 2405 | ||
| 2404 | if (r) { | 2406 | if (r) { |
| 2405 | if (r == -EALREADY) | 2407 | switch (r) { |
| 2408 | case -EALREADY: | ||
| 2406 | reg_set_request_processed(); | 2409 | reg_set_request_processed(); |
| 2410 | break; | ||
| 2411 | default: | ||
| 2412 | /* Back to world regulatory in case of errors */ | ||
| 2413 | restore_regulatory_settings(user_reset); | ||
| 2414 | } | ||
| 2407 | 2415 | ||
| 2408 | kfree(rd); | 2416 | kfree(rd); |
| 2409 | return r; | 2417 | return r; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index b528e31da2cf..d1ed4aebbbb7 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
| @@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, | |||
| 161 | dev->bss_generation++; | 161 | dev->bss_generation++; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) | 164 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, |
| 165 | bool send_message) | ||
| 165 | { | 166 | { |
| 166 | struct cfg80211_scan_request *request; | 167 | struct cfg80211_scan_request *request; |
| 167 | struct wireless_dev *wdev; | 168 | struct wireless_dev *wdev; |
| 169 | struct sk_buff *msg; | ||
| 168 | #ifdef CONFIG_CFG80211_WEXT | 170 | #ifdef CONFIG_CFG80211_WEXT |
| 169 | union iwreq_data wrqu; | 171 | union iwreq_data wrqu; |
| 170 | #endif | 172 | #endif |
| 171 | 173 | ||
| 172 | ASSERT_RTNL(); | 174 | ASSERT_RTNL(); |
| 173 | 175 | ||
| 174 | request = rdev->scan_req; | 176 | if (rdev->scan_msg) { |
| 177 | nl80211_send_scan_result(rdev, rdev->scan_msg); | ||
| 178 | rdev->scan_msg = NULL; | ||
| 179 | return; | ||
| 180 | } | ||
| 175 | 181 | ||
| 182 | request = rdev->scan_req; | ||
| 176 | if (!request) | 183 | if (!request) |
| 177 | return; | 184 | return; |
| 178 | 185 | ||
| @@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) | |||
| 186 | if (wdev->netdev) | 193 | if (wdev->netdev) |
| 187 | cfg80211_sme_scan_done(wdev->netdev); | 194 | cfg80211_sme_scan_done(wdev->netdev); |
| 188 | 195 | ||
| 189 | if (request->aborted) { | 196 | if (!request->aborted && |
| 190 | nl80211_send_scan_aborted(rdev, wdev); | 197 | request->flags & NL80211_SCAN_FLAG_FLUSH) { |
| 191 | } else { | 198 | /* flush entries from previous scans */ |
| 192 | if (request->flags & NL80211_SCAN_FLAG_FLUSH) { | 199 | spin_lock_bh(&rdev->bss_lock); |
| 193 | /* flush entries from previous scans */ | 200 | __cfg80211_bss_expire(rdev, request->scan_start); |
| 194 | spin_lock_bh(&rdev->bss_lock); | 201 | spin_unlock_bh(&rdev->bss_lock); |
| 195 | __cfg80211_bss_expire(rdev, request->scan_start); | ||
| 196 | spin_unlock_bh(&rdev->bss_lock); | ||
| 197 | } | ||
| 198 | nl80211_send_scan_done(rdev, wdev); | ||
| 199 | } | 202 | } |
| 200 | 203 | ||
| 204 | msg = nl80211_build_scan_msg(rdev, wdev, request->aborted); | ||
| 205 | |||
| 201 | #ifdef CONFIG_CFG80211_WEXT | 206 | #ifdef CONFIG_CFG80211_WEXT |
| 202 | if (wdev->netdev && !request->aborted) { | 207 | if (wdev->netdev && !request->aborted) { |
| 203 | memset(&wrqu, 0, sizeof(wrqu)); | 208 | memset(&wrqu, 0, sizeof(wrqu)); |
| @@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) | |||
| 211 | 216 | ||
| 212 | rdev->scan_req = NULL; | 217 | rdev->scan_req = NULL; |
| 213 | kfree(request); | 218 | kfree(request); |
| 219 | |||
| 220 | if (!send_message) | ||
| 221 | rdev->scan_msg = msg; | ||
| 222 | else | ||
| 223 | nl80211_send_scan_result(rdev, msg); | ||
| 214 | } | 224 | } |
| 215 | 225 | ||
| 216 | void __cfg80211_scan_done(struct work_struct *wk) | 226 | void __cfg80211_scan_done(struct work_struct *wk) |
| @@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_struct *wk) | |||
| 221 | scan_done_wk); | 231 | scan_done_wk); |
| 222 | 232 | ||
| 223 | rtnl_lock(); | 233 | rtnl_lock(); |
| 224 | ___cfg80211_scan_done(rdev); | 234 | ___cfg80211_scan_done(rdev, true); |
| 225 | rtnl_unlock(); | 235 | rtnl_unlock(); |
| 226 | } | 236 | } |
| 227 | 237 | ||
| @@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
| 1079 | if (IS_ERR(rdev)) | 1089 | if (IS_ERR(rdev)) |
| 1080 | return PTR_ERR(rdev); | 1090 | return PTR_ERR(rdev); |
| 1081 | 1091 | ||
| 1082 | if (rdev->scan_req) { | 1092 | if (rdev->scan_req || rdev->scan_msg) { |
| 1083 | err = -EBUSY; | 1093 | err = -EBUSY; |
| 1084 | goto out; | 1094 | goto out; |
| 1085 | } | 1095 | } |
| @@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_device *dev, | |||
| 1481 | if (IS_ERR(rdev)) | 1491 | if (IS_ERR(rdev)) |
| 1482 | return PTR_ERR(rdev); | 1492 | return PTR_ERR(rdev); |
| 1483 | 1493 | ||
| 1484 | if (rdev->scan_req) | 1494 | if (rdev->scan_req || rdev->scan_msg) |
| 1485 | return -EAGAIN; | 1495 | return -EAGAIN; |
| 1486 | 1496 | ||
| 1487 | res = ieee80211_scan_results(rdev, info, extra, data->length); | 1497 | res = ieee80211_scan_results(rdev, info, extra, data->length); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index a63509118508..f04d4c32e96e 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
| @@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
| 67 | ASSERT_RDEV_LOCK(rdev); | 67 | ASSERT_RDEV_LOCK(rdev); |
| 68 | ASSERT_WDEV_LOCK(wdev); | 68 | ASSERT_WDEV_LOCK(wdev); |
| 69 | 69 | ||
| 70 | if (rdev->scan_req) | 70 | if (rdev->scan_req || rdev->scan_msg) |
| 71 | return -EBUSY; | 71 | return -EBUSY; |
| 72 | 72 | ||
| 73 | if (wdev->conn->params.channel) | 73 | if (wdev->conn->params.channel) |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 4b98b25793c5..1d5c7bf29938 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -1158,7 +1158,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | |||
| 1158 | if (hlist_unhashed(&pol->bydst)) | 1158 | if (hlist_unhashed(&pol->bydst)) |
| 1159 | return NULL; | 1159 | return NULL; |
| 1160 | 1160 | ||
| 1161 | hlist_del(&pol->bydst); | 1161 | hlist_del_init(&pol->bydst); |
| 1162 | hlist_del(&pol->byidx); | 1162 | hlist_del(&pol->byidx); |
| 1163 | list_del(&pol->walk.all); | 1163 | list_del(&pol->walk.all); |
| 1164 | net->xfrm.policy_count[dir]--; | 1164 | net->xfrm.policy_count[dir]--; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a26b7aa79475..40f1b3e92e78 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -1159,6 +1159,11 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
| 1159 | } | 1159 | } |
| 1160 | x->props.aalgo = orig->props.aalgo; | 1160 | x->props.aalgo = orig->props.aalgo; |
| 1161 | 1161 | ||
| 1162 | if (orig->aead) { | ||
| 1163 | x->aead = xfrm_algo_aead_clone(orig->aead); | ||
| 1164 | if (!x->aead) | ||
| 1165 | goto error; | ||
| 1166 | } | ||
| 1162 | if (orig->ealg) { | 1167 | if (orig->ealg) { |
| 1163 | x->ealg = xfrm_algo_clone(orig->ealg); | 1168 | x->ealg = xfrm_algo_clone(orig->ealg); |
| 1164 | if (!x->ealg) | 1169 | if (!x->ealg) |
| @@ -1201,6 +1206,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
| 1201 | x->props.flags = orig->props.flags; | 1206 | x->props.flags = orig->props.flags; |
| 1202 | x->props.extra_flags = orig->props.extra_flags; | 1207 | x->props.extra_flags = orig->props.extra_flags; |
| 1203 | 1208 | ||
| 1209 | x->tfcpad = orig->tfcpad; | ||
| 1210 | x->replay_maxdiff = orig->replay_maxdiff; | ||
| 1211 | x->replay_maxage = orig->replay_maxage; | ||
| 1204 | x->curlft.add_time = orig->curlft.add_time; | 1212 | x->curlft.add_time = orig->curlft.add_time; |
| 1205 | x->km.state = orig->km.state; | 1213 | x->km.state = orig->km.state; |
| 1206 | x->km.seq = orig->km.seq; | 1214 | x->km.seq = orig->km.seq; |
| @@ -1215,11 +1223,12 @@ out: | |||
| 1215 | return NULL; | 1223 | return NULL; |
| 1216 | } | 1224 | } |
| 1217 | 1225 | ||
| 1218 | /* net->xfrm.xfrm_state_lock is held */ | ||
| 1219 | struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net) | 1226 | struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net) |
| 1220 | { | 1227 | { |
| 1221 | unsigned int h; | 1228 | unsigned int h; |
| 1222 | struct xfrm_state *x; | 1229 | struct xfrm_state *x = NULL; |
| 1230 | |||
| 1231 | spin_lock_bh(&net->xfrm.xfrm_state_lock); | ||
| 1223 | 1232 | ||
| 1224 | if (m->reqid) { | 1233 | if (m->reqid) { |
| 1225 | h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr, | 1234 | h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr, |
| @@ -1236,7 +1245,7 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n | |||
| 1236 | m->old_family)) | 1245 | m->old_family)) |
| 1237 | continue; | 1246 | continue; |
| 1238 | xfrm_state_hold(x); | 1247 | xfrm_state_hold(x); |
| 1239 | return x; | 1248 | break; |
| 1240 | } | 1249 | } |
| 1241 | } else { | 1250 | } else { |
| 1242 | h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr, | 1251 | h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr, |
| @@ -1251,11 +1260,13 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n | |||
| 1251 | m->old_family)) | 1260 | m->old_family)) |
| 1252 | continue; | 1261 | continue; |
| 1253 | xfrm_state_hold(x); | 1262 | xfrm_state_hold(x); |
| 1254 | return x; | 1263 | break; |
| 1255 | } | 1264 | } |
| 1256 | } | 1265 | } |
| 1257 | 1266 | ||
| 1258 | return NULL; | 1267 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); |
| 1268 | |||
| 1269 | return x; | ||
| 1259 | } | 1270 | } |
| 1260 | EXPORT_SYMBOL(xfrm_migrate_state_find); | 1271 | EXPORT_SYMBOL(xfrm_migrate_state_find); |
| 1261 | 1272 | ||
| @@ -1451,7 +1462,7 @@ xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, | |||
| 1451 | { | 1462 | { |
| 1452 | int err = 0; | 1463 | int err = 0; |
| 1453 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | 1464 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); |
| 1454 | struct net *net = xs_net(*dst); | 1465 | struct net *net = xs_net(*src); |
| 1455 | 1466 | ||
| 1456 | if (!afinfo) | 1467 | if (!afinfo) |
| 1457 | return -EAFNOSUPPORT; | 1468 | return -EAFNOSUPPORT; |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 1ae3ec7c18b0..c274179d60a2 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -32,11 +32,6 @@ | |||
| 32 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | static inline int aead_len(struct xfrm_algo_aead *alg) | ||
| 36 | { | ||
| 37 | return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); | ||
| 38 | } | ||
| 39 | |||
| 40 | static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) | 35 | static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) |
| 41 | { | 36 | { |
| 42 | struct nlattr *rt = attrs[type]; | 37 | struct nlattr *rt = attrs[type]; |
