diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/bridge/netfilter/nft_reject_bridge.c | 29 | ||||
| -rw-r--r-- | net/caif/chnl_net.c | 1 | ||||
| -rw-r--r-- | net/core/dev.c | 37 | ||||
| -rw-r--r-- | net/core/rtnetlink.c | 6 | ||||
| -rw-r--r-- | net/ipv4/ip_output.c | 29 | ||||
| -rw-r--r-- | net/ipv4/route.c | 3 | ||||
| -rw-r--r-- | net/ipv4/tcp_bic.c | 2 | ||||
| -rw-r--r-- | net/ipv4/tcp_cong.c | 32 | ||||
| -rw-r--r-- | net/ipv4/tcp_cubic.c | 39 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 37 | ||||
| -rw-r--r-- | net/ipv4/tcp_scalable.c | 3 | ||||
| -rw-r--r-- | net/ipv4/tcp_veno.c | 2 | ||||
| -rw-r--r-- | net/ipv4/tcp_yeah.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6_gre.c | 4 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 14 | ||||
| -rw-r--r-- | net/ipv6/output_core.c | 41 | ||||
| -rw-r--r-- | net/ipv6/sit.c | 8 | ||||
| -rw-r--r-- | net/ipv6/udp_offload.c | 10 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 33 | ||||
| -rw-r--r-- | net/netfilter/nf_tables_api.c | 28 | ||||
| -rw-r--r-- | net/netfilter/nft_masq.c | 26 | ||||
| -rw-r--r-- | net/netfilter/nft_nat.c | 40 | ||||
| -rw-r--r-- | net/netfilter/nft_redir.c | 25 | ||||
| -rw-r--r-- | net/netlink/af_netlink.c | 4 | ||||
| -rw-r--r-- | net/rds/sysctl.c | 4 | ||||
| -rw-r--r-- | net/sched/cls_api.c | 7 | ||||
| -rw-r--r-- | net/sched/sch_fq.c | 10 | ||||
| -rw-r--r-- | net/sctp/sm_make_chunk.c | 2 |
28 files changed, 274 insertions, 204 deletions
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index b0330aecbf97..3244aead0926 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
| @@ -265,22 +265,12 @@ out: | |||
| 265 | data[NFT_REG_VERDICT].verdict = NF_DROP; | 265 | data[NFT_REG_VERDICT].verdict = NF_DROP; |
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | static int nft_reject_bridge_validate_hooks(const struct nft_chain *chain) | 268 | static int nft_reject_bridge_validate(const struct nft_ctx *ctx, |
| 269 | const struct nft_expr *expr, | ||
| 270 | const struct nft_data **data) | ||
| 269 | { | 271 | { |
| 270 | struct nft_base_chain *basechain; | 272 | return nft_chain_validate_hooks(ctx->chain, (1 << NF_BR_PRE_ROUTING) | |
| 271 | 273 | (1 << NF_BR_LOCAL_IN)); | |
| 272 | if (chain->flags & NFT_BASE_CHAIN) { | ||
| 273 | basechain = nft_base_chain(chain); | ||
| 274 | |||
| 275 | switch (basechain->ops[0].hooknum) { | ||
| 276 | case NF_BR_PRE_ROUTING: | ||
| 277 | case NF_BR_LOCAL_IN: | ||
| 278 | break; | ||
| 279 | default: | ||
| 280 | return -EOPNOTSUPP; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | return 0; | ||
| 284 | } | 274 | } |
| 285 | 275 | ||
| 286 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, | 276 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, |
| @@ -290,7 +280,7 @@ static int nft_reject_bridge_init(const struct nft_ctx *ctx, | |||
| 290 | struct nft_reject *priv = nft_expr_priv(expr); | 280 | struct nft_reject *priv = nft_expr_priv(expr); |
| 291 | int icmp_code, err; | 281 | int icmp_code, err; |
| 292 | 282 | ||
| 293 | err = nft_reject_bridge_validate_hooks(ctx->chain); | 283 | err = nft_reject_bridge_validate(ctx, expr, NULL); |
| 294 | if (err < 0) | 284 | if (err < 0) |
| 295 | return err; | 285 | return err; |
| 296 | 286 | ||
| @@ -341,13 +331,6 @@ nla_put_failure: | |||
| 341 | return -1; | 331 | return -1; |
| 342 | } | 332 | } |
| 343 | 333 | ||
| 344 | static int nft_reject_bridge_validate(const struct nft_ctx *ctx, | ||
| 345 | const struct nft_expr *expr, | ||
| 346 | const struct nft_data **data) | ||
| 347 | { | ||
| 348 | return nft_reject_bridge_validate_hooks(ctx->chain); | ||
| 349 | } | ||
| 350 | |||
| 351 | static struct nft_expr_type nft_reject_bridge_type; | 334 | static struct nft_expr_type nft_reject_bridge_type; |
| 352 | static const struct nft_expr_ops nft_reject_bridge_ops = { | 335 | static const struct nft_expr_ops nft_reject_bridge_ops = { |
| 353 | .type = &nft_reject_bridge_type, | 336 | .type = &nft_reject_bridge_type, |
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 4589ff67bfa9..67a4a36febd1 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c | |||
| @@ -470,7 +470,6 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev, | |||
| 470 | ASSERT_RTNL(); | 470 | ASSERT_RTNL(); |
| 471 | caifdev = netdev_priv(dev); | 471 | caifdev = netdev_priv(dev); |
| 472 | caif_netlink_parms(data, &caifdev->conn_req); | 472 | caif_netlink_parms(data, &caifdev->conn_req); |
| 473 | dev_net_set(caifdev->netdev, src_net); | ||
| 474 | 473 | ||
| 475 | ret = register_netdevice(dev); | 474 | ret = register_netdevice(dev); |
| 476 | if (ret) | 475 | if (ret) |
diff --git a/net/core/dev.c b/net/core/dev.c index 171420e75b03..7fe82929f509 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2352,7 +2352,6 @@ EXPORT_SYMBOL(skb_checksum_help); | |||
| 2352 | 2352 | ||
| 2353 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | 2353 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) |
| 2354 | { | 2354 | { |
| 2355 | unsigned int vlan_depth = skb->mac_len; | ||
| 2356 | __be16 type = skb->protocol; | 2355 | __be16 type = skb->protocol; |
| 2357 | 2356 | ||
| 2358 | /* Tunnel gso handlers can set protocol to ethernet. */ | 2357 | /* Tunnel gso handlers can set protocol to ethernet. */ |
| @@ -2366,35 +2365,7 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | |||
| 2366 | type = eth->h_proto; | 2365 | type = eth->h_proto; |
| 2367 | } | 2366 | } |
| 2368 | 2367 | ||
| 2369 | /* if skb->protocol is 802.1Q/AD then the header should already be | 2368 | return __vlan_get_protocol(skb, type, depth); |
| 2370 | * present at mac_len - VLAN_HLEN (if mac_len > 0), or at | ||
| 2371 | * ETH_HLEN otherwise | ||
| 2372 | */ | ||
| 2373 | if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { | ||
| 2374 | if (vlan_depth) { | ||
| 2375 | if (WARN_ON(vlan_depth < VLAN_HLEN)) | ||
| 2376 | return 0; | ||
| 2377 | vlan_depth -= VLAN_HLEN; | ||
| 2378 | } else { | ||
| 2379 | vlan_depth = ETH_HLEN; | ||
| 2380 | } | ||
| 2381 | do { | ||
| 2382 | struct vlan_hdr *vh; | ||
| 2383 | |||
| 2384 | if (unlikely(!pskb_may_pull(skb, | ||
| 2385 | vlan_depth + VLAN_HLEN))) | ||
| 2386 | return 0; | ||
| 2387 | |||
| 2388 | vh = (struct vlan_hdr *)(skb->data + vlan_depth); | ||
| 2389 | type = vh->h_vlan_encapsulated_proto; | ||
| 2390 | vlan_depth += VLAN_HLEN; | ||
| 2391 | } while (type == htons(ETH_P_8021Q) || | ||
| 2392 | type == htons(ETH_P_8021AD)); | ||
| 2393 | } | ||
| 2394 | |||
| 2395 | *depth = vlan_depth; | ||
| 2396 | |||
| 2397 | return type; | ||
| 2398 | } | 2369 | } |
| 2399 | 2370 | ||
| 2400 | /** | 2371 | /** |
| @@ -5323,7 +5294,7 @@ void netdev_upper_dev_unlink(struct net_device *dev, | |||
| 5323 | } | 5294 | } |
| 5324 | EXPORT_SYMBOL(netdev_upper_dev_unlink); | 5295 | EXPORT_SYMBOL(netdev_upper_dev_unlink); |
| 5325 | 5296 | ||
| 5326 | void netdev_adjacent_add_links(struct net_device *dev) | 5297 | static void netdev_adjacent_add_links(struct net_device *dev) |
| 5327 | { | 5298 | { |
| 5328 | struct netdev_adjacent *iter; | 5299 | struct netdev_adjacent *iter; |
| 5329 | 5300 | ||
| @@ -5348,7 +5319,7 @@ void netdev_adjacent_add_links(struct net_device *dev) | |||
| 5348 | } | 5319 | } |
| 5349 | } | 5320 | } |
| 5350 | 5321 | ||
| 5351 | void netdev_adjacent_del_links(struct net_device *dev) | 5322 | static void netdev_adjacent_del_links(struct net_device *dev) |
| 5352 | { | 5323 | { |
| 5353 | struct netdev_adjacent *iter; | 5324 | struct netdev_adjacent *iter; |
| 5354 | 5325 | ||
| @@ -6656,7 +6627,7 @@ struct netdev_queue *dev_ingress_queue_create(struct net_device *dev) | |||
| 6656 | if (!queue) | 6627 | if (!queue) |
| 6657 | return NULL; | 6628 | return NULL; |
| 6658 | netdev_init_one_queue(dev, queue, NULL); | 6629 | netdev_init_one_queue(dev, queue, NULL); |
| 6659 | queue->qdisc = &noop_qdisc; | 6630 | RCU_INIT_POINTER(queue->qdisc, &noop_qdisc); |
| 6660 | queue->qdisc_sleeping = &noop_qdisc; | 6631 | queue->qdisc_sleeping = &noop_qdisc; |
| 6661 | rcu_assign_pointer(dev->ingress_queue, queue); | 6632 | rcu_assign_pointer(dev->ingress_queue, queue); |
| 6662 | #endif | 6633 | #endif |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9cf6fe9ddc0c..446cbaf81185 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -2895,12 +2895,16 @@ static int rtnl_bridge_notify(struct net_device *dev, u16 flags) | |||
| 2895 | goto errout; | 2895 | goto errout; |
| 2896 | } | 2896 | } |
| 2897 | 2897 | ||
| 2898 | if (!skb->len) | ||
| 2899 | goto errout; | ||
| 2900 | |||
| 2898 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); | 2901 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); |
| 2899 | return 0; | 2902 | return 0; |
| 2900 | errout: | 2903 | errout: |
| 2901 | WARN_ON(err == -EMSGSIZE); | 2904 | WARN_ON(err == -EMSGSIZE); |
| 2902 | kfree_skb(skb); | 2905 | kfree_skb(skb); |
| 2903 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); | 2906 | if (err) |
| 2907 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); | ||
| 2904 | return err; | 2908 | return err; |
| 2905 | } | 2909 | } |
| 2906 | 2910 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index b50861b22b6b..c373c0708d97 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -1506,23 +1506,8 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, | |||
| 1506 | /* | 1506 | /* |
| 1507 | * Generic function to send a packet as reply to another packet. | 1507 | * Generic function to send a packet as reply to another packet. |
| 1508 | * Used to send some TCP resets/acks so far. | 1508 | * Used to send some TCP resets/acks so far. |
| 1509 | * | ||
| 1510 | * Use a fake percpu inet socket to avoid false sharing and contention. | ||
| 1511 | */ | 1509 | */ |
| 1512 | static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = { | 1510 | void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, |
| 1513 | .sk = { | ||
| 1514 | .__sk_common = { | ||
| 1515 | .skc_refcnt = ATOMIC_INIT(1), | ||
| 1516 | }, | ||
| 1517 | .sk_wmem_alloc = ATOMIC_INIT(1), | ||
| 1518 | .sk_allocation = GFP_ATOMIC, | ||
| 1519 | .sk_flags = (1UL << SOCK_USE_WRITE_QUEUE), | ||
| 1520 | }, | ||
| 1521 | .pmtudisc = IP_PMTUDISC_WANT, | ||
| 1522 | .uc_ttl = -1, | ||
| 1523 | }; | ||
| 1524 | |||
| 1525 | void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, | ||
| 1526 | const struct ip_options *sopt, | 1511 | const struct ip_options *sopt, |
| 1527 | __be32 daddr, __be32 saddr, | 1512 | __be32 daddr, __be32 saddr, |
| 1528 | const struct ip_reply_arg *arg, | 1513 | const struct ip_reply_arg *arg, |
| @@ -1532,9 +1517,8 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, | |||
| 1532 | struct ipcm_cookie ipc; | 1517 | struct ipcm_cookie ipc; |
| 1533 | struct flowi4 fl4; | 1518 | struct flowi4 fl4; |
| 1534 | struct rtable *rt = skb_rtable(skb); | 1519 | struct rtable *rt = skb_rtable(skb); |
| 1520 | struct net *net = sock_net(sk); | ||
| 1535 | struct sk_buff *nskb; | 1521 | struct sk_buff *nskb; |
| 1536 | struct sock *sk; | ||
| 1537 | struct inet_sock *inet; | ||
| 1538 | int err; | 1522 | int err; |
| 1539 | 1523 | ||
| 1540 | if (__ip_options_echo(&replyopts.opt.opt, skb, sopt)) | 1524 | if (__ip_options_echo(&replyopts.opt.opt, skb, sopt)) |
| @@ -1565,15 +1549,11 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, | |||
| 1565 | if (IS_ERR(rt)) | 1549 | if (IS_ERR(rt)) |
| 1566 | return; | 1550 | return; |
| 1567 | 1551 | ||
| 1568 | inet = &get_cpu_var(unicast_sock); | 1552 | inet_sk(sk)->tos = arg->tos; |
| 1569 | 1553 | ||
| 1570 | inet->tos = arg->tos; | ||
| 1571 | sk = &inet->sk; | ||
| 1572 | sk->sk_priority = skb->priority; | 1554 | sk->sk_priority = skb->priority; |
| 1573 | sk->sk_protocol = ip_hdr(skb)->protocol; | 1555 | sk->sk_protocol = ip_hdr(skb)->protocol; |
| 1574 | sk->sk_bound_dev_if = arg->bound_dev_if; | 1556 | sk->sk_bound_dev_if = arg->bound_dev_if; |
| 1575 | sock_net_set(sk, net); | ||
| 1576 | __skb_queue_head_init(&sk->sk_write_queue); | ||
| 1577 | sk->sk_sndbuf = sysctl_wmem_default; | 1557 | sk->sk_sndbuf = sysctl_wmem_default; |
| 1578 | err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, | 1558 | err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, |
| 1579 | len, 0, &ipc, &rt, MSG_DONTWAIT); | 1559 | len, 0, &ipc, &rt, MSG_DONTWAIT); |
| @@ -1589,13 +1569,10 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, | |||
| 1589 | arg->csumoffset) = csum_fold(csum_add(nskb->csum, | 1569 | arg->csumoffset) = csum_fold(csum_add(nskb->csum, |
| 1590 | arg->csum)); | 1570 | arg->csum)); |
| 1591 | nskb->ip_summed = CHECKSUM_NONE; | 1571 | nskb->ip_summed = CHECKSUM_NONE; |
| 1592 | skb_orphan(nskb); | ||
| 1593 | skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); | 1572 | skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); |
| 1594 | ip_push_pending_frames(sk, &fl4); | 1573 | ip_push_pending_frames(sk, &fl4); |
| 1595 | } | 1574 | } |
| 1596 | out: | 1575 | out: |
| 1597 | put_cpu_var(unicast_sock); | ||
| 1598 | |||
| 1599 | ip_rt_put(rt); | 1576 | ip_rt_put(rt); |
| 1600 | } | 1577 | } |
| 1601 | 1578 | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d58dd0ec3e53..52e1f2bf0ca2 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -966,6 +966,9 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) | |||
| 966 | if (dst->dev->mtu < mtu) | 966 | if (dst->dev->mtu < mtu) |
| 967 | return; | 967 | return; |
| 968 | 968 | ||
| 969 | if (rt->rt_pmtu && rt->rt_pmtu < mtu) | ||
| 970 | return; | ||
| 971 | |||
| 969 | if (mtu < ip_rt_min_pmtu) | 972 | if (mtu < ip_rt_min_pmtu) |
| 970 | mtu = ip_rt_min_pmtu; | 973 | mtu = ip_rt_min_pmtu; |
| 971 | 974 | ||
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c index bb395d46a389..c037644eafb7 100644 --- a/net/ipv4/tcp_bic.c +++ b/net/ipv4/tcp_bic.c | |||
| @@ -150,7 +150,7 @@ static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 150 | tcp_slow_start(tp, acked); | 150 | tcp_slow_start(tp, acked); |
| 151 | else { | 151 | else { |
| 152 | bictcp_update(ca, tp->snd_cwnd); | 152 | bictcp_update(ca, tp->snd_cwnd); |
| 153 | tcp_cong_avoid_ai(tp, ca->cnt); | 153 | tcp_cong_avoid_ai(tp, ca->cnt, 1); |
| 154 | } | 154 | } |
| 155 | } | 155 | } |
| 156 | 156 | ||
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 27ead0dd16bc..8670e68e2ce6 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
| @@ -291,26 +291,32 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
| 291 | * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and | 291 | * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and |
| 292 | * returns the leftover acks to adjust cwnd in congestion avoidance mode. | 292 | * returns the leftover acks to adjust cwnd in congestion avoidance mode. |
| 293 | */ | 293 | */ |
| 294 | void tcp_slow_start(struct tcp_sock *tp, u32 acked) | 294 | u32 tcp_slow_start(struct tcp_sock *tp, u32 acked) |
| 295 | { | 295 | { |
| 296 | u32 cwnd = tp->snd_cwnd + acked; | 296 | u32 cwnd = tp->snd_cwnd + acked; |
| 297 | 297 | ||
| 298 | if (cwnd > tp->snd_ssthresh) | 298 | if (cwnd > tp->snd_ssthresh) |
| 299 | cwnd = tp->snd_ssthresh + 1; | 299 | cwnd = tp->snd_ssthresh + 1; |
| 300 | acked -= cwnd - tp->snd_cwnd; | ||
| 300 | tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); | 301 | tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); |
| 302 | |||
| 303 | return acked; | ||
| 301 | } | 304 | } |
| 302 | EXPORT_SYMBOL_GPL(tcp_slow_start); | 305 | EXPORT_SYMBOL_GPL(tcp_slow_start); |
| 303 | 306 | ||
| 304 | /* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w) */ | 307 | /* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w), |
| 305 | void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w) | 308 | * for every packet that was ACKed. |
| 309 | */ | ||
| 310 | void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w, u32 acked) | ||
| 306 | { | 311 | { |
| 312 | tp->snd_cwnd_cnt += acked; | ||
| 307 | if (tp->snd_cwnd_cnt >= w) { | 313 | if (tp->snd_cwnd_cnt >= w) { |
| 308 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 314 | u32 delta = tp->snd_cwnd_cnt / w; |
| 309 | tp->snd_cwnd++; | 315 | |
| 310 | tp->snd_cwnd_cnt = 0; | 316 | tp->snd_cwnd_cnt -= delta * w; |
| 311 | } else { | 317 | tp->snd_cwnd += delta; |
| 312 | tp->snd_cwnd_cnt++; | ||
| 313 | } | 318 | } |
| 319 | tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_cwnd_clamp); | ||
| 314 | } | 320 | } |
| 315 | EXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); | 321 | EXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); |
| 316 | 322 | ||
| @@ -329,11 +335,13 @@ void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 329 | return; | 335 | return; |
| 330 | 336 | ||
| 331 | /* In "safe" area, increase. */ | 337 | /* In "safe" area, increase. */ |
| 332 | if (tp->snd_cwnd <= tp->snd_ssthresh) | 338 | if (tp->snd_cwnd <= tp->snd_ssthresh) { |
| 333 | tcp_slow_start(tp, acked); | 339 | acked = tcp_slow_start(tp, acked); |
| 340 | if (!acked) | ||
| 341 | return; | ||
| 342 | } | ||
| 334 | /* In dangerous area, increase slowly. */ | 343 | /* In dangerous area, increase slowly. */ |
| 335 | else | 344 | tcp_cong_avoid_ai(tp, tp->snd_cwnd, acked); |
| 336 | tcp_cong_avoid_ai(tp, tp->snd_cwnd); | ||
| 337 | } | 345 | } |
| 338 | EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); | 346 | EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); |
| 339 | 347 | ||
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 6b6002416a73..4b276d1ed980 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c | |||
| @@ -93,9 +93,7 @@ struct bictcp { | |||
| 93 | u32 epoch_start; /* beginning of an epoch */ | 93 | u32 epoch_start; /* beginning of an epoch */ |
| 94 | u32 ack_cnt; /* number of acks */ | 94 | u32 ack_cnt; /* number of acks */ |
| 95 | u32 tcp_cwnd; /* estimated tcp cwnd */ | 95 | u32 tcp_cwnd; /* estimated tcp cwnd */ |
| 96 | #define ACK_RATIO_SHIFT 4 | 96 | u16 unused; |
| 97 | #define ACK_RATIO_LIMIT (32u << ACK_RATIO_SHIFT) | ||
| 98 | u16 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */ | ||
| 99 | u8 sample_cnt; /* number of samples to decide curr_rtt */ | 97 | u8 sample_cnt; /* number of samples to decide curr_rtt */ |
| 100 | u8 found; /* the exit point is found? */ | 98 | u8 found; /* the exit point is found? */ |
| 101 | u32 round_start; /* beginning of each round */ | 99 | u32 round_start; /* beginning of each round */ |
| @@ -114,7 +112,6 @@ static inline void bictcp_reset(struct bictcp *ca) | |||
| 114 | ca->bic_K = 0; | 112 | ca->bic_K = 0; |
| 115 | ca->delay_min = 0; | 113 | ca->delay_min = 0; |
| 116 | ca->epoch_start = 0; | 114 | ca->epoch_start = 0; |
| 117 | ca->delayed_ack = 2 << ACK_RATIO_SHIFT; | ||
| 118 | ca->ack_cnt = 0; | 115 | ca->ack_cnt = 0; |
| 119 | ca->tcp_cwnd = 0; | 116 | ca->tcp_cwnd = 0; |
| 120 | ca->found = 0; | 117 | ca->found = 0; |
| @@ -205,23 +202,30 @@ static u32 cubic_root(u64 a) | |||
| 205 | /* | 202 | /* |
| 206 | * Compute congestion window to use. | 203 | * Compute congestion window to use. |
| 207 | */ | 204 | */ |
| 208 | static inline void bictcp_update(struct bictcp *ca, u32 cwnd) | 205 | static inline void bictcp_update(struct bictcp *ca, u32 cwnd, u32 acked) |
| 209 | { | 206 | { |
| 210 | u32 delta, bic_target, max_cnt; | 207 | u32 delta, bic_target, max_cnt; |
| 211 | u64 offs, t; | 208 | u64 offs, t; |
| 212 | 209 | ||
| 213 | ca->ack_cnt++; /* count the number of ACKs */ | 210 | ca->ack_cnt += acked; /* count the number of ACKed packets */ |
| 214 | 211 | ||
| 215 | if (ca->last_cwnd == cwnd && | 212 | if (ca->last_cwnd == cwnd && |
| 216 | (s32)(tcp_time_stamp - ca->last_time) <= HZ / 32) | 213 | (s32)(tcp_time_stamp - ca->last_time) <= HZ / 32) |
| 217 | return; | 214 | return; |
| 218 | 215 | ||
| 216 | /* The CUBIC function can update ca->cnt at most once per jiffy. | ||
| 217 | * On all cwnd reduction events, ca->epoch_start is set to 0, | ||
| 218 | * which will force a recalculation of ca->cnt. | ||
| 219 | */ | ||
| 220 | if (ca->epoch_start && tcp_time_stamp == ca->last_time) | ||
| 221 | goto tcp_friendliness; | ||
| 222 | |||
| 219 | ca->last_cwnd = cwnd; | 223 | ca->last_cwnd = cwnd; |
| 220 | ca->last_time = tcp_time_stamp; | 224 | ca->last_time = tcp_time_stamp; |
| 221 | 225 | ||
| 222 | if (ca->epoch_start == 0) { | 226 | if (ca->epoch_start == 0) { |
| 223 | ca->epoch_start = tcp_time_stamp; /* record beginning */ | 227 | ca->epoch_start = tcp_time_stamp; /* record beginning */ |
| 224 | ca->ack_cnt = 1; /* start counting */ | 228 | ca->ack_cnt = acked; /* start counting */ |
| 225 | ca->tcp_cwnd = cwnd; /* syn with cubic */ | 229 | ca->tcp_cwnd = cwnd; /* syn with cubic */ |
| 226 | 230 | ||
| 227 | if (ca->last_max_cwnd <= cwnd) { | 231 | if (ca->last_max_cwnd <= cwnd) { |
| @@ -283,6 +287,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) | |||
| 283 | if (ca->last_max_cwnd == 0 && ca->cnt > 20) | 287 | if (ca->last_max_cwnd == 0 && ca->cnt > 20) |
| 284 | ca->cnt = 20; /* increase cwnd 5% per RTT */ | 288 | ca->cnt = 20; /* increase cwnd 5% per RTT */ |
| 285 | 289 | ||
| 290 | tcp_friendliness: | ||
| 286 | /* TCP Friendly */ | 291 | /* TCP Friendly */ |
| 287 | if (tcp_friendliness) { | 292 | if (tcp_friendliness) { |
| 288 | u32 scale = beta_scale; | 293 | u32 scale = beta_scale; |
| @@ -301,7 +306,6 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) | |||
| 301 | } | 306 | } |
| 302 | } | 307 | } |
| 303 | 308 | ||
| 304 | ca->cnt = (ca->cnt << ACK_RATIO_SHIFT) / ca->delayed_ack; | ||
| 305 | if (ca->cnt == 0) /* cannot be zero */ | 309 | if (ca->cnt == 0) /* cannot be zero */ |
| 306 | ca->cnt = 1; | 310 | ca->cnt = 1; |
| 307 | } | 311 | } |
| @@ -317,11 +321,12 @@ static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 317 | if (tp->snd_cwnd <= tp->snd_ssthresh) { | 321 | if (tp->snd_cwnd <= tp->snd_ssthresh) { |
| 318 | if (hystart && after(ack, ca->end_seq)) | 322 | if (hystart && after(ack, ca->end_seq)) |
| 319 | bictcp_hystart_reset(sk); | 323 | bictcp_hystart_reset(sk); |
| 320 | tcp_slow_start(tp, acked); | 324 | acked = tcp_slow_start(tp, acked); |
| 321 | } else { | 325 | if (!acked) |
| 322 | bictcp_update(ca, tp->snd_cwnd); | 326 | return; |
| 323 | tcp_cong_avoid_ai(tp, ca->cnt); | ||
| 324 | } | 327 | } |
| 328 | bictcp_update(ca, tp->snd_cwnd, acked); | ||
| 329 | tcp_cong_avoid_ai(tp, ca->cnt, acked); | ||
| 325 | } | 330 | } |
| 326 | 331 | ||
| 327 | static u32 bictcp_recalc_ssthresh(struct sock *sk) | 332 | static u32 bictcp_recalc_ssthresh(struct sock *sk) |
| @@ -411,20 +416,10 @@ static void hystart_update(struct sock *sk, u32 delay) | |||
| 411 | */ | 416 | */ |
| 412 | static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) | 417 | static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) |
| 413 | { | 418 | { |
| 414 | const struct inet_connection_sock *icsk = inet_csk(sk); | ||
| 415 | const struct tcp_sock *tp = tcp_sk(sk); | 419 | const struct tcp_sock *tp = tcp_sk(sk); |
| 416 | struct bictcp *ca = inet_csk_ca(sk); | 420 | struct bictcp *ca = inet_csk_ca(sk); |
| 417 | u32 delay; | 421 | u32 delay; |
| 418 | 422 | ||
| 419 | if (icsk->icsk_ca_state == TCP_CA_Open) { | ||
| 420 | u32 ratio = ca->delayed_ack; | ||
| 421 | |||
| 422 | ratio -= ca->delayed_ack >> ACK_RATIO_SHIFT; | ||
| 423 | ratio += cnt; | ||
| 424 | |||
| 425 | ca->delayed_ack = clamp(ratio, 1U, ACK_RATIO_LIMIT); | ||
| 426 | } | ||
| 427 | |||
| 428 | /* Some calls are for duplicates without timetamps */ | 423 | /* Some calls are for duplicates without timetamps */ |
| 429 | if (rtt_us < 0) | 424 | if (rtt_us < 0) |
| 430 | return; | 425 | return; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a3f72d7fc06c..d22f54482bab 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -683,7 +683,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
| 683 | arg.bound_dev_if = sk->sk_bound_dev_if; | 683 | arg.bound_dev_if = sk->sk_bound_dev_if; |
| 684 | 684 | ||
| 685 | arg.tos = ip_hdr(skb)->tos; | 685 | arg.tos = ip_hdr(skb)->tos; |
| 686 | ip_send_unicast_reply(net, skb, &TCP_SKB_CB(skb)->header.h4.opt, | 686 | ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), |
| 687 | skb, &TCP_SKB_CB(skb)->header.h4.opt, | ||
| 687 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, | 688 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, |
| 688 | &arg, arg.iov[0].iov_len); | 689 | &arg, arg.iov[0].iov_len); |
| 689 | 690 | ||
| @@ -767,7 +768,8 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
| 767 | if (oif) | 768 | if (oif) |
| 768 | arg.bound_dev_if = oif; | 769 | arg.bound_dev_if = oif; |
| 769 | arg.tos = tos; | 770 | arg.tos = tos; |
| 770 | ip_send_unicast_reply(net, skb, &TCP_SKB_CB(skb)->header.h4.opt, | 771 | ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), |
| 772 | skb, &TCP_SKB_CB(skb)->header.h4.opt, | ||
| 771 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, | 773 | ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, |
| 772 | &arg, arg.iov[0].iov_len); | 774 | &arg, arg.iov[0].iov_len); |
| 773 | 775 | ||
| @@ -2428,14 +2430,39 @@ struct proto tcp_prot = { | |||
| 2428 | }; | 2430 | }; |
| 2429 | EXPORT_SYMBOL(tcp_prot); | 2431 | EXPORT_SYMBOL(tcp_prot); |
| 2430 | 2432 | ||
| 2433 | static void __net_exit tcp_sk_exit(struct net *net) | ||
| 2434 | { | ||
| 2435 | int cpu; | ||
| 2436 | |||
| 2437 | for_each_possible_cpu(cpu) | ||
| 2438 | inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.tcp_sk, cpu)); | ||
| 2439 | free_percpu(net->ipv4.tcp_sk); | ||
| 2440 | } | ||
| 2441 | |||
| 2431 | static int __net_init tcp_sk_init(struct net *net) | 2442 | static int __net_init tcp_sk_init(struct net *net) |
| 2432 | { | 2443 | { |
| 2444 | int res, cpu; | ||
| 2445 | |||
| 2446 | net->ipv4.tcp_sk = alloc_percpu(struct sock *); | ||
| 2447 | if (!net->ipv4.tcp_sk) | ||
| 2448 | return -ENOMEM; | ||
| 2449 | |||
| 2450 | for_each_possible_cpu(cpu) { | ||
| 2451 | struct sock *sk; | ||
| 2452 | |||
| 2453 | res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW, | ||
| 2454 | IPPROTO_TCP, net); | ||
| 2455 | if (res) | ||
| 2456 | goto fail; | ||
| 2457 | *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk; | ||
| 2458 | } | ||
| 2433 | net->ipv4.sysctl_tcp_ecn = 2; | 2459 | net->ipv4.sysctl_tcp_ecn = 2; |
| 2434 | return 0; | 2460 | return 0; |
| 2435 | } | ||
| 2436 | 2461 | ||
| 2437 | static void __net_exit tcp_sk_exit(struct net *net) | 2462 | fail: |
| 2438 | { | 2463 | tcp_sk_exit(net); |
| 2464 | |||
| 2465 | return res; | ||
| 2439 | } | 2466 | } |
| 2440 | 2467 | ||
| 2441 | static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) | 2468 | static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) |
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c index 6824afb65d93..333bcb2415ff 100644 --- a/net/ipv4/tcp_scalable.c +++ b/net/ipv4/tcp_scalable.c | |||
| @@ -25,7 +25,8 @@ static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 25 | if (tp->snd_cwnd <= tp->snd_ssthresh) | 25 | if (tp->snd_cwnd <= tp->snd_ssthresh) |
| 26 | tcp_slow_start(tp, acked); | 26 | tcp_slow_start(tp, acked); |
| 27 | else | 27 | else |
| 28 | tcp_cong_avoid_ai(tp, min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)); | 28 | tcp_cong_avoid_ai(tp, min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT), |
| 29 | 1); | ||
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | static u32 tcp_scalable_ssthresh(struct sock *sk) | 32 | static u32 tcp_scalable_ssthresh(struct sock *sk) |
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c index a4d2d2d88dca..112151eeee45 100644 --- a/net/ipv4/tcp_veno.c +++ b/net/ipv4/tcp_veno.c | |||
| @@ -159,7 +159,7 @@ static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 159 | /* In the "non-congestive state", increase cwnd | 159 | /* In the "non-congestive state", increase cwnd |
| 160 | * every rtt. | 160 | * every rtt. |
| 161 | */ | 161 | */ |
| 162 | tcp_cong_avoid_ai(tp, tp->snd_cwnd); | 162 | tcp_cong_avoid_ai(tp, tp->snd_cwnd, 1); |
| 163 | } else { | 163 | } else { |
| 164 | /* In the "congestive state", increase cwnd | 164 | /* In the "congestive state", increase cwnd |
| 165 | * every other rtt. | 165 | * every other rtt. |
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index cd7273218598..17d35662930d 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c | |||
| @@ -92,7 +92,7 @@ static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 92 | 92 | ||
| 93 | } else { | 93 | } else { |
| 94 | /* Reno */ | 94 | /* Reno */ |
| 95 | tcp_cong_avoid_ai(tp, tp->snd_cwnd); | 95 | tcp_cong_avoid_ai(tp, tp->snd_cwnd, 1); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | /* The key players are v_vegas.beg_snd_una and v_beg_snd_nxt. | 98 | /* The key players are v_vegas.beg_snd_una and v_beg_snd_nxt. |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 13cda4c6313b..01ccc28a686f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -417,7 +417,7 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 417 | if (code == ICMPV6_HDR_FIELD) | 417 | if (code == ICMPV6_HDR_FIELD) |
| 418 | teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); | 418 | teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); |
| 419 | 419 | ||
| 420 | if (teli && teli == info - 2) { | 420 | if (teli && teli == be32_to_cpu(info) - 2) { |
| 421 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; | 421 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; |
| 422 | if (tel->encap_limit == 0) { | 422 | if (tel->encap_limit == 0) { |
| 423 | net_warn_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n", | 423 | net_warn_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n", |
| @@ -429,7 +429,7 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 429 | } | 429 | } |
| 430 | break; | 430 | break; |
| 431 | case ICMPV6_PKT_TOOBIG: | 431 | case ICMPV6_PKT_TOOBIG: |
| 432 | mtu = info - offset; | 432 | mtu = be32_to_cpu(info) - offset; |
| 433 | if (mtu < IPV6_MIN_MTU) | 433 | if (mtu < IPV6_MIN_MTU) |
| 434 | mtu = IPV6_MIN_MTU; | 434 | mtu = IPV6_MIN_MTU; |
| 435 | t->dev->mtu = mtu; | 435 | t->dev->mtu = mtu; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ce69a12ae48c..d28f2a2efb32 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -537,20 +537,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
| 537 | skb_copy_secmark(to, from); | 537 | skb_copy_secmark(to, from); |
| 538 | } | 538 | } |
| 539 | 539 | ||
| 540 | static void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | ||
| 541 | { | ||
| 542 | static u32 ip6_idents_hashrnd __read_mostly; | ||
| 543 | u32 hash, id; | ||
| 544 | |||
| 545 | net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); | ||
| 546 | |||
| 547 | hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd); | ||
| 548 | hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash); | ||
| 549 | |||
| 550 | id = ip_idents_reserve(hash, 1); | ||
| 551 | fhdr->identification = htonl(id); | ||
| 552 | } | ||
| 553 | |||
| 554 | int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | 540 | int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) |
| 555 | { | 541 | { |
| 556 | struct sk_buff *frag; | 542 | struct sk_buff *frag; |
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index 97f41a3e68d9..54520a0bd5e3 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c | |||
| @@ -9,6 +9,24 @@ | |||
| 9 | #include <net/addrconf.h> | 9 | #include <net/addrconf.h> |
| 10 | #include <net/secure_seq.h> | 10 | #include <net/secure_seq.h> |
| 11 | 11 | ||
| 12 | u32 __ipv6_select_ident(u32 hashrnd, struct in6_addr *dst, struct in6_addr *src) | ||
| 13 | { | ||
| 14 | u32 hash, id; | ||
| 15 | |||
| 16 | hash = __ipv6_addr_jhash(dst, hashrnd); | ||
| 17 | hash = __ipv6_addr_jhash(src, hash); | ||
| 18 | |||
| 19 | /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve, | ||
| 20 | * set the hight order instead thus minimizing possible future | ||
| 21 | * collisions. | ||
| 22 | */ | ||
| 23 | id = ip_idents_reserve(hash, 1); | ||
| 24 | if (unlikely(!id)) | ||
| 25 | id = 1 << 31; | ||
| 26 | |||
| 27 | return id; | ||
| 28 | } | ||
| 29 | |||
| 12 | /* This function exists only for tap drivers that must support broken | 30 | /* This function exists only for tap drivers that must support broken |
| 13 | * clients requesting UFO without specifying an IPv6 fragment ID. | 31 | * clients requesting UFO without specifying an IPv6 fragment ID. |
| 14 | * | 32 | * |
| @@ -22,7 +40,7 @@ void ipv6_proxy_select_ident(struct sk_buff *skb) | |||
| 22 | static u32 ip6_proxy_idents_hashrnd __read_mostly; | 40 | static u32 ip6_proxy_idents_hashrnd __read_mostly; |
| 23 | struct in6_addr buf[2]; | 41 | struct in6_addr buf[2]; |
| 24 | struct in6_addr *addrs; | 42 | struct in6_addr *addrs; |
| 25 | u32 hash, id; | 43 | u32 id; |
| 26 | 44 | ||
| 27 | addrs = skb_header_pointer(skb, | 45 | addrs = skb_header_pointer(skb, |
| 28 | skb_network_offset(skb) + | 46 | skb_network_offset(skb) + |
| @@ -34,14 +52,25 @@ void ipv6_proxy_select_ident(struct sk_buff *skb) | |||
| 34 | net_get_random_once(&ip6_proxy_idents_hashrnd, | 52 | net_get_random_once(&ip6_proxy_idents_hashrnd, |
| 35 | sizeof(ip6_proxy_idents_hashrnd)); | 53 | sizeof(ip6_proxy_idents_hashrnd)); |
| 36 | 54 | ||
| 37 | hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd); | 55 | id = __ipv6_select_ident(ip6_proxy_idents_hashrnd, |
| 38 | hash = __ipv6_addr_jhash(&addrs[0], hash); | 56 | &addrs[1], &addrs[0]); |
| 39 | 57 | skb_shinfo(skb)->ip6_frag_id = id; | |
| 40 | id = ip_idents_reserve(hash, 1); | ||
| 41 | skb_shinfo(skb)->ip6_frag_id = htonl(id); | ||
| 42 | } | 58 | } |
| 43 | EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); | 59 | EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); |
| 44 | 60 | ||
| 61 | void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | ||
| 62 | { | ||
| 63 | static u32 ip6_idents_hashrnd __read_mostly; | ||
| 64 | u32 id; | ||
| 65 | |||
| 66 | net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); | ||
| 67 | |||
| 68 | id = __ipv6_select_ident(ip6_idents_hashrnd, &rt->rt6i_dst.addr, | ||
| 69 | &rt->rt6i_src.addr); | ||
| 70 | fhdr->identification = htonl(id); | ||
| 71 | } | ||
| 72 | EXPORT_SYMBOL(ipv6_select_ident); | ||
| 73 | |||
| 45 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | 74 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) |
| 46 | { | 75 | { |
| 47 | u16 offset = sizeof(struct ipv6hdr); | 76 | u16 offset = sizeof(struct ipv6hdr); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 213546bd6d5d..cdbfe5af6187 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -1506,12 +1506,12 @@ static bool ipip6_netlink_encap_parms(struct nlattr *data[], | |||
| 1506 | 1506 | ||
| 1507 | if (data[IFLA_IPTUN_ENCAP_SPORT]) { | 1507 | if (data[IFLA_IPTUN_ENCAP_SPORT]) { |
| 1508 | ret = true; | 1508 | ret = true; |
| 1509 | ipencap->sport = nla_get_u16(data[IFLA_IPTUN_ENCAP_SPORT]); | 1509 | ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]); |
| 1510 | } | 1510 | } |
| 1511 | 1511 | ||
| 1512 | if (data[IFLA_IPTUN_ENCAP_DPORT]) { | 1512 | if (data[IFLA_IPTUN_ENCAP_DPORT]) { |
| 1513 | ret = true; | 1513 | ret = true; |
| 1514 | ipencap->dport = nla_get_u16(data[IFLA_IPTUN_ENCAP_DPORT]); | 1514 | ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]); |
| 1515 | } | 1515 | } |
| 1516 | 1516 | ||
| 1517 | return ret; | 1517 | return ret; |
| @@ -1707,9 +1707,9 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 1707 | 1707 | ||
| 1708 | if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, | 1708 | if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, |
| 1709 | tunnel->encap.type) || | 1709 | tunnel->encap.type) || |
| 1710 | nla_put_u16(skb, IFLA_IPTUN_ENCAP_SPORT, | 1710 | nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, |
| 1711 | tunnel->encap.sport) || | 1711 | tunnel->encap.sport) || |
| 1712 | nla_put_u16(skb, IFLA_IPTUN_ENCAP_DPORT, | 1712 | nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, |
| 1713 | tunnel->encap.dport) || | 1713 | tunnel->encap.dport) || |
| 1714 | nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS, | 1714 | nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS, |
| 1715 | tunnel->encap.flags)) | 1715 | tunnel->encap.flags)) |
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index b6aa8ed18257..a56276996b72 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
| @@ -52,6 +52,10 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
| 52 | 52 | ||
| 53 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); | 53 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); |
| 54 | 54 | ||
| 55 | /* Set the IPv6 fragment id if not set yet */ | ||
| 56 | if (!skb_shinfo(skb)->ip6_frag_id) | ||
| 57 | ipv6_proxy_select_ident(skb); | ||
| 58 | |||
| 55 | segs = NULL; | 59 | segs = NULL; |
| 56 | goto out; | 60 | goto out; |
| 57 | } | 61 | } |
| @@ -108,7 +112,11 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
| 108 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); | 112 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); |
| 109 | fptr->nexthdr = nexthdr; | 113 | fptr->nexthdr = nexthdr; |
| 110 | fptr->reserved = 0; | 114 | fptr->reserved = 0; |
| 111 | fptr->identification = skb_shinfo(skb)->ip6_frag_id; | 115 | if (skb_shinfo(skb)->ip6_frag_id) |
| 116 | fptr->identification = skb_shinfo(skb)->ip6_frag_id; | ||
| 117 | else | ||
| 118 | ipv6_select_ident(fptr, | ||
| 119 | (struct rt6_info *)skb_dst(skb)); | ||
| 112 | 120 | ||
| 113 | /* Fragment the skb. ipv6 header and the remaining fields of the | 121 | /* Fragment the skb. ipv6 header and the remaining fields of the |
| 114 | * fragment header are updated in ipv6_gso_segment() | 122 | * fragment header are updated in ipv6_gso_segment() |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 990decba1fe4..b87ca32efa0b 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -659,16 +659,24 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) | |||
| 659 | return err; | 659 | return err; |
| 660 | } | 660 | } |
| 661 | 661 | ||
| 662 | static int ip_vs_route_me_harder(int af, struct sk_buff *skb) | 662 | static int ip_vs_route_me_harder(int af, struct sk_buff *skb, |
| 663 | unsigned int hooknum) | ||
| 663 | { | 664 | { |
| 665 | if (!sysctl_snat_reroute(skb)) | ||
| 666 | return 0; | ||
| 667 | /* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */ | ||
| 668 | if (NF_INET_LOCAL_IN == hooknum) | ||
| 669 | return 0; | ||
| 664 | #ifdef CONFIG_IP_VS_IPV6 | 670 | #ifdef CONFIG_IP_VS_IPV6 |
| 665 | if (af == AF_INET6) { | 671 | if (af == AF_INET6) { |
| 666 | if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0) | 672 | struct dst_entry *dst = skb_dst(skb); |
| 673 | |||
| 674 | if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) && | ||
| 675 | ip6_route_me_harder(skb) != 0) | ||
| 667 | return 1; | 676 | return 1; |
| 668 | } else | 677 | } else |
| 669 | #endif | 678 | #endif |
| 670 | if ((sysctl_snat_reroute(skb) || | 679 | if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) && |
| 671 | skb_rtable(skb)->rt_flags & RTCF_LOCAL) && | ||
| 672 | ip_route_me_harder(skb, RTN_LOCAL) != 0) | 680 | ip_route_me_harder(skb, RTN_LOCAL) != 0) |
| 673 | return 1; | 681 | return 1; |
| 674 | 682 | ||
| @@ -791,7 +799,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, | |||
| 791 | union nf_inet_addr *snet, | 799 | union nf_inet_addr *snet, |
| 792 | __u8 protocol, struct ip_vs_conn *cp, | 800 | __u8 protocol, struct ip_vs_conn *cp, |
| 793 | struct ip_vs_protocol *pp, | 801 | struct ip_vs_protocol *pp, |
| 794 | unsigned int offset, unsigned int ihl) | 802 | unsigned int offset, unsigned int ihl, |
| 803 | unsigned int hooknum) | ||
| 795 | { | 804 | { |
| 796 | unsigned int verdict = NF_DROP; | 805 | unsigned int verdict = NF_DROP; |
| 797 | 806 | ||
| @@ -821,7 +830,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb, | |||
| 821 | #endif | 830 | #endif |
| 822 | ip_vs_nat_icmp(skb, pp, cp, 1); | 831 | ip_vs_nat_icmp(skb, pp, cp, 1); |
| 823 | 832 | ||
| 824 | if (ip_vs_route_me_harder(af, skb)) | 833 | if (ip_vs_route_me_harder(af, skb, hooknum)) |
| 825 | goto out; | 834 | goto out; |
| 826 | 835 | ||
| 827 | /* do the statistics and put it back */ | 836 | /* do the statistics and put it back */ |
| @@ -916,7 +925,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related, | |||
| 916 | 925 | ||
| 917 | snet.ip = iph->saddr; | 926 | snet.ip = iph->saddr; |
| 918 | return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp, | 927 | return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp, |
| 919 | pp, ciph.len, ihl); | 928 | pp, ciph.len, ihl, hooknum); |
| 920 | } | 929 | } |
| 921 | 930 | ||
| 922 | #ifdef CONFIG_IP_VS_IPV6 | 931 | #ifdef CONFIG_IP_VS_IPV6 |
| @@ -981,7 +990,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, | |||
| 981 | snet.in6 = ciph.saddr.in6; | 990 | snet.in6 = ciph.saddr.in6; |
| 982 | writable = ciph.len; | 991 | writable = ciph.len; |
| 983 | return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, | 992 | return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, |
| 984 | pp, writable, sizeof(struct ipv6hdr)); | 993 | pp, writable, sizeof(struct ipv6hdr), |
| 994 | hooknum); | ||
| 985 | } | 995 | } |
| 986 | #endif | 996 | #endif |
| 987 | 997 | ||
| @@ -1040,7 +1050,8 @@ static inline bool is_new_conn(const struct sk_buff *skb, | |||
| 1040 | */ | 1050 | */ |
| 1041 | static unsigned int | 1051 | static unsigned int |
| 1042 | handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, | 1052 | handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, |
| 1043 | struct ip_vs_conn *cp, struct ip_vs_iphdr *iph) | 1053 | struct ip_vs_conn *cp, struct ip_vs_iphdr *iph, |
| 1054 | unsigned int hooknum) | ||
| 1044 | { | 1055 | { |
| 1045 | struct ip_vs_protocol *pp = pd->pp; | 1056 | struct ip_vs_protocol *pp = pd->pp; |
| 1046 | 1057 | ||
| @@ -1078,7 +1089,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, | |||
| 1078 | * if it came from this machine itself. So re-compute | 1089 | * if it came from this machine itself. So re-compute |
| 1079 | * the routing information. | 1090 | * the routing information. |
| 1080 | */ | 1091 | */ |
| 1081 | if (ip_vs_route_me_harder(af, skb)) | 1092 | if (ip_vs_route_me_harder(af, skb, hooknum)) |
| 1082 | goto drop; | 1093 | goto drop; |
| 1083 | 1094 | ||
| 1084 | IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); | 1095 | IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); |
| @@ -1181,7 +1192,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) | |||
| 1181 | cp = pp->conn_out_get(af, skb, &iph, 0); | 1192 | cp = pp->conn_out_get(af, skb, &iph, 0); |
| 1182 | 1193 | ||
| 1183 | if (likely(cp)) | 1194 | if (likely(cp)) |
| 1184 | return handle_response(af, skb, pd, cp, &iph); | 1195 | return handle_response(af, skb, pd, cp, &iph, hooknum); |
| 1185 | if (sysctl_nat_icmp_send(net) && | 1196 | if (sysctl_nat_icmp_send(net) && |
| 1186 | (pp->protocol == IPPROTO_TCP || | 1197 | (pp->protocol == IPPROTO_TCP || |
| 1187 | pp->protocol == IPPROTO_UDP || | 1198 | pp->protocol == IPPROTO_UDP || |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 3b3ddb4fb9ee..1ff04bcd4871 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -1134,9 +1134,11 @@ static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr) | |||
| 1134 | /* Restore old counters on this cpu, no problem. Per-cpu statistics | 1134 | /* Restore old counters on this cpu, no problem. Per-cpu statistics |
| 1135 | * are not exposed to userspace. | 1135 | * are not exposed to userspace. |
| 1136 | */ | 1136 | */ |
| 1137 | preempt_disable(); | ||
| 1137 | stats = this_cpu_ptr(newstats); | 1138 | stats = this_cpu_ptr(newstats); |
| 1138 | stats->bytes = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES])); | 1139 | stats->bytes = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES])); |
| 1139 | stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])); | 1140 | stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])); |
| 1141 | preempt_enable(); | ||
| 1140 | 1142 | ||
| 1141 | return newstats; | 1143 | return newstats; |
| 1142 | } | 1144 | } |
| @@ -1262,8 +1264,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 1262 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); | 1264 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); |
| 1263 | trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN, | 1265 | trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN, |
| 1264 | sizeof(struct nft_trans_chain)); | 1266 | sizeof(struct nft_trans_chain)); |
| 1265 | if (trans == NULL) | 1267 | if (trans == NULL) { |
| 1268 | free_percpu(stats); | ||
| 1266 | return -ENOMEM; | 1269 | return -ENOMEM; |
| 1270 | } | ||
| 1267 | 1271 | ||
| 1268 | nft_trans_chain_stats(trans) = stats; | 1272 | nft_trans_chain_stats(trans) = stats; |
| 1269 | nft_trans_chain_update(trans) = true; | 1273 | nft_trans_chain_update(trans) = true; |
| @@ -1319,8 +1323,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
| 1319 | hookfn = type->hooks[hooknum]; | 1323 | hookfn = type->hooks[hooknum]; |
| 1320 | 1324 | ||
| 1321 | basechain = kzalloc(sizeof(*basechain), GFP_KERNEL); | 1325 | basechain = kzalloc(sizeof(*basechain), GFP_KERNEL); |
| 1322 | if (basechain == NULL) | 1326 | if (basechain == NULL) { |
| 1327 | module_put(type->owner); | ||
| 1323 | return -ENOMEM; | 1328 | return -ENOMEM; |
| 1329 | } | ||
| 1324 | 1330 | ||
| 1325 | if (nla[NFTA_CHAIN_COUNTERS]) { | 1331 | if (nla[NFTA_CHAIN_COUNTERS]) { |
| 1326 | stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]); | 1332 | stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]); |
| @@ -3753,6 +3759,24 @@ int nft_chain_validate_dependency(const struct nft_chain *chain, | |||
| 3753 | } | 3759 | } |
| 3754 | EXPORT_SYMBOL_GPL(nft_chain_validate_dependency); | 3760 | EXPORT_SYMBOL_GPL(nft_chain_validate_dependency); |
| 3755 | 3761 | ||
| 3762 | int nft_chain_validate_hooks(const struct nft_chain *chain, | ||
| 3763 | unsigned int hook_flags) | ||
| 3764 | { | ||
| 3765 | struct nft_base_chain *basechain; | ||
| 3766 | |||
| 3767 | if (chain->flags & NFT_BASE_CHAIN) { | ||
| 3768 | basechain = nft_base_chain(chain); | ||
| 3769 | |||
| 3770 | if ((1 << basechain->ops[0].hooknum) & hook_flags) | ||
| 3771 | return 0; | ||
| 3772 | |||
| 3773 | return -EOPNOTSUPP; | ||
| 3774 | } | ||
| 3775 | |||
| 3776 | return 0; | ||
| 3777 | } | ||
| 3778 | EXPORT_SYMBOL_GPL(nft_chain_validate_hooks); | ||
| 3779 | |||
| 3756 | /* | 3780 | /* |
| 3757 | * Loop detection - walk through the ruleset beginning at the destination chain | 3781 | * Loop detection - walk through the ruleset beginning at the destination chain |
| 3758 | * of a new jump until either the source chain is reached (loop) or all | 3782 | * of a new jump until either the source chain is reached (loop) or all |
diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c index d1ffd5eb3a9b..9aea747b43ea 100644 --- a/net/netfilter/nft_masq.c +++ b/net/netfilter/nft_masq.c | |||
| @@ -21,6 +21,21 @@ const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = { | |||
| 21 | }; | 21 | }; |
| 22 | EXPORT_SYMBOL_GPL(nft_masq_policy); | 22 | EXPORT_SYMBOL_GPL(nft_masq_policy); |
| 23 | 23 | ||
| 24 | int nft_masq_validate(const struct nft_ctx *ctx, | ||
| 25 | const struct nft_expr *expr, | ||
| 26 | const struct nft_data **data) | ||
| 27 | { | ||
| 28 | int err; | ||
| 29 | |||
| 30 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 31 | if (err < 0) | ||
| 32 | return err; | ||
| 33 | |||
| 34 | return nft_chain_validate_hooks(ctx->chain, | ||
| 35 | (1 << NF_INET_POST_ROUTING)); | ||
| 36 | } | ||
| 37 | EXPORT_SYMBOL_GPL(nft_masq_validate); | ||
| 38 | |||
| 24 | int nft_masq_init(const struct nft_ctx *ctx, | 39 | int nft_masq_init(const struct nft_ctx *ctx, |
| 25 | const struct nft_expr *expr, | 40 | const struct nft_expr *expr, |
| 26 | const struct nlattr * const tb[]) | 41 | const struct nlattr * const tb[]) |
| @@ -28,8 +43,8 @@ int nft_masq_init(const struct nft_ctx *ctx, | |||
| 28 | struct nft_masq *priv = nft_expr_priv(expr); | 43 | struct nft_masq *priv = nft_expr_priv(expr); |
| 29 | int err; | 44 | int err; |
| 30 | 45 | ||
| 31 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | 46 | err = nft_masq_validate(ctx, expr, NULL); |
| 32 | if (err < 0) | 47 | if (err) |
| 33 | return err; | 48 | return err; |
| 34 | 49 | ||
| 35 | if (tb[NFTA_MASQ_FLAGS] == NULL) | 50 | if (tb[NFTA_MASQ_FLAGS] == NULL) |
| @@ -60,12 +75,5 @@ nla_put_failure: | |||
| 60 | } | 75 | } |
| 61 | EXPORT_SYMBOL_GPL(nft_masq_dump); | 76 | EXPORT_SYMBOL_GPL(nft_masq_dump); |
| 62 | 77 | ||
| 63 | int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, | ||
| 64 | const struct nft_data **data) | ||
| 65 | { | ||
| 66 | return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 67 | } | ||
| 68 | EXPORT_SYMBOL_GPL(nft_masq_validate); | ||
| 69 | |||
| 70 | MODULE_LICENSE("GPL"); | 78 | MODULE_LICENSE("GPL"); |
| 71 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); | 79 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); |
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c index aff54fb1c8a0..a0837c6c9283 100644 --- a/net/netfilter/nft_nat.c +++ b/net/netfilter/nft_nat.c | |||
| @@ -88,17 +88,40 @@ static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = { | |||
| 88 | [NFTA_NAT_FLAGS] = { .type = NLA_U32 }, | 88 | [NFTA_NAT_FLAGS] = { .type = NLA_U32 }, |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | 91 | static int nft_nat_validate(const struct nft_ctx *ctx, |
| 92 | const struct nlattr * const tb[]) | 92 | const struct nft_expr *expr, |
| 93 | const struct nft_data **data) | ||
| 93 | { | 94 | { |
| 94 | struct nft_nat *priv = nft_expr_priv(expr); | 95 | struct nft_nat *priv = nft_expr_priv(expr); |
| 95 | u32 family; | ||
| 96 | int err; | 96 | int err; |
| 97 | 97 | ||
| 98 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | 98 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); |
| 99 | if (err < 0) | 99 | if (err < 0) |
| 100 | return err; | 100 | return err; |
| 101 | 101 | ||
| 102 | switch (priv->type) { | ||
| 103 | case NFT_NAT_SNAT: | ||
| 104 | err = nft_chain_validate_hooks(ctx->chain, | ||
| 105 | (1 << NF_INET_POST_ROUTING) | | ||
| 106 | (1 << NF_INET_LOCAL_IN)); | ||
| 107 | break; | ||
| 108 | case NFT_NAT_DNAT: | ||
| 109 | err = nft_chain_validate_hooks(ctx->chain, | ||
| 110 | (1 << NF_INET_PRE_ROUTING) | | ||
| 111 | (1 << NF_INET_LOCAL_OUT)); | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | |||
| 115 | return err; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | ||
| 119 | const struct nlattr * const tb[]) | ||
| 120 | { | ||
| 121 | struct nft_nat *priv = nft_expr_priv(expr); | ||
| 122 | u32 family; | ||
| 123 | int err; | ||
| 124 | |||
| 102 | if (tb[NFTA_NAT_TYPE] == NULL || | 125 | if (tb[NFTA_NAT_TYPE] == NULL || |
| 103 | (tb[NFTA_NAT_REG_ADDR_MIN] == NULL && | 126 | (tb[NFTA_NAT_REG_ADDR_MIN] == NULL && |
| 104 | tb[NFTA_NAT_REG_PROTO_MIN] == NULL)) | 127 | tb[NFTA_NAT_REG_PROTO_MIN] == NULL)) |
| @@ -115,6 +138,10 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
| 115 | return -EINVAL; | 138 | return -EINVAL; |
| 116 | } | 139 | } |
| 117 | 140 | ||
| 141 | err = nft_nat_validate(ctx, expr, NULL); | ||
| 142 | if (err < 0) | ||
| 143 | return err; | ||
| 144 | |||
| 118 | if (tb[NFTA_NAT_FAMILY] == NULL) | 145 | if (tb[NFTA_NAT_FAMILY] == NULL) |
| 119 | return -EINVAL; | 146 | return -EINVAL; |
| 120 | 147 | ||
| @@ -219,13 +246,6 @@ nla_put_failure: | |||
| 219 | return -1; | 246 | return -1; |
| 220 | } | 247 | } |
| 221 | 248 | ||
| 222 | static int nft_nat_validate(const struct nft_ctx *ctx, | ||
| 223 | const struct nft_expr *expr, | ||
| 224 | const struct nft_data **data) | ||
| 225 | { | ||
| 226 | return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 227 | } | ||
| 228 | |||
| 229 | static struct nft_expr_type nft_nat_type; | 249 | static struct nft_expr_type nft_nat_type; |
| 230 | static const struct nft_expr_ops nft_nat_ops = { | 250 | static const struct nft_expr_ops nft_nat_ops = { |
| 231 | .type = &nft_nat_type, | 251 | .type = &nft_nat_type, |
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c index 9e8093f28311..d7e9e93a4e90 100644 --- a/net/netfilter/nft_redir.c +++ b/net/netfilter/nft_redir.c | |||
| @@ -23,6 +23,22 @@ const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = { | |||
| 23 | }; | 23 | }; |
| 24 | EXPORT_SYMBOL_GPL(nft_redir_policy); | 24 | EXPORT_SYMBOL_GPL(nft_redir_policy); |
| 25 | 25 | ||
| 26 | int nft_redir_validate(const struct nft_ctx *ctx, | ||
| 27 | const struct nft_expr *expr, | ||
| 28 | const struct nft_data **data) | ||
| 29 | { | ||
| 30 | int err; | ||
| 31 | |||
| 32 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 33 | if (err < 0) | ||
| 34 | return err; | ||
| 35 | |||
| 36 | return nft_chain_validate_hooks(ctx->chain, | ||
| 37 | (1 << NF_INET_PRE_ROUTING) | | ||
| 38 | (1 << NF_INET_LOCAL_OUT)); | ||
| 39 | } | ||
| 40 | EXPORT_SYMBOL_GPL(nft_redir_validate); | ||
| 41 | |||
| 26 | int nft_redir_init(const struct nft_ctx *ctx, | 42 | int nft_redir_init(const struct nft_ctx *ctx, |
| 27 | const struct nft_expr *expr, | 43 | const struct nft_expr *expr, |
| 28 | const struct nlattr * const tb[]) | 44 | const struct nlattr * const tb[]) |
| @@ -30,7 +46,7 @@ int nft_redir_init(const struct nft_ctx *ctx, | |||
| 30 | struct nft_redir *priv = nft_expr_priv(expr); | 46 | struct nft_redir *priv = nft_expr_priv(expr); |
| 31 | int err; | 47 | int err; |
| 32 | 48 | ||
| 33 | err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | 49 | err = nft_redir_validate(ctx, expr, NULL); |
| 34 | if (err < 0) | 50 | if (err < 0) |
| 35 | return err; | 51 | return err; |
| 36 | 52 | ||
| @@ -88,12 +104,5 @@ nla_put_failure: | |||
| 88 | } | 104 | } |
| 89 | EXPORT_SYMBOL_GPL(nft_redir_dump); | 105 | EXPORT_SYMBOL_GPL(nft_redir_dump); |
| 90 | 106 | ||
| 91 | int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, | ||
| 92 | const struct nft_data **data) | ||
| 93 | { | ||
| 94 | return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); | ||
| 95 | } | ||
| 96 | EXPORT_SYMBOL_GPL(nft_redir_validate); | ||
| 97 | |||
| 98 | MODULE_LICENSE("GPL"); | 107 | MODULE_LICENSE("GPL"); |
| 99 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); | 108 | MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 02fdde28dada..75532efa51cd 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1438,7 +1438,7 @@ static void netlink_undo_bind(int group, long unsigned int groups, | |||
| 1438 | 1438 | ||
| 1439 | for (undo = 0; undo < group; undo++) | 1439 | for (undo = 0; undo < group; undo++) |
| 1440 | if (test_bit(undo, &groups)) | 1440 | if (test_bit(undo, &groups)) |
| 1441 | nlk->netlink_unbind(sock_net(sk), undo); | 1441 | nlk->netlink_unbind(sock_net(sk), undo + 1); |
| 1442 | } | 1442 | } |
| 1443 | 1443 | ||
| 1444 | static int netlink_bind(struct socket *sock, struct sockaddr *addr, | 1444 | static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
| @@ -1476,7 +1476,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
| 1476 | for (group = 0; group < nlk->ngroups; group++) { | 1476 | for (group = 0; group < nlk->ngroups; group++) { |
| 1477 | if (!test_bit(group, &groups)) | 1477 | if (!test_bit(group, &groups)) |
| 1478 | continue; | 1478 | continue; |
| 1479 | err = nlk->netlink_bind(net, group); | 1479 | err = nlk->netlink_bind(net, group + 1); |
| 1480 | if (!err) | 1480 | if (!err) |
| 1481 | continue; | 1481 | continue; |
| 1482 | netlink_undo_bind(group, groups, sk); | 1482 | netlink_undo_bind(group, groups, sk); |
diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c index c3b0cd43eb56..c173f69e1479 100644 --- a/net/rds/sysctl.c +++ b/net/rds/sysctl.c | |||
| @@ -71,14 +71,14 @@ static struct ctl_table rds_sysctl_rds_table[] = { | |||
| 71 | { | 71 | { |
| 72 | .procname = "max_unacked_packets", | 72 | .procname = "max_unacked_packets", |
| 73 | .data = &rds_sysctl_max_unacked_packets, | 73 | .data = &rds_sysctl_max_unacked_packets, |
| 74 | .maxlen = sizeof(unsigned long), | 74 | .maxlen = sizeof(int), |
| 75 | .mode = 0644, | 75 | .mode = 0644, |
| 76 | .proc_handler = proc_dointvec, | 76 | .proc_handler = proc_dointvec, |
| 77 | }, | 77 | }, |
| 78 | { | 78 | { |
| 79 | .procname = "max_unacked_bytes", | 79 | .procname = "max_unacked_bytes", |
| 80 | .data = &rds_sysctl_max_unacked_bytes, | 80 | .data = &rds_sysctl_max_unacked_bytes, |
| 81 | .maxlen = sizeof(unsigned long), | 81 | .maxlen = sizeof(int), |
| 82 | .mode = 0644, | 82 | .mode = 0644, |
| 83 | .proc_handler = proc_dointvec, | 83 | .proc_handler = proc_dointvec, |
| 84 | }, | 84 | }, |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index aad6a679fb13..baef987fe2c0 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
| @@ -556,8 +556,9 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, | |||
| 556 | } | 556 | } |
| 557 | EXPORT_SYMBOL(tcf_exts_change); | 557 | EXPORT_SYMBOL(tcf_exts_change); |
| 558 | 558 | ||
| 559 | #define tcf_exts_first_act(ext) \ | 559 | #define tcf_exts_first_act(ext) \ |
| 560 | list_first_entry(&(exts)->actions, struct tc_action, list) | 560 | list_first_entry_or_null(&(exts)->actions, \ |
| 561 | struct tc_action, list) | ||
| 561 | 562 | ||
| 562 | int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts) | 563 | int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts) |
| 563 | { | 564 | { |
| @@ -603,7 +604,7 @@ int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts) | |||
| 603 | { | 604 | { |
| 604 | #ifdef CONFIG_NET_CLS_ACT | 605 | #ifdef CONFIG_NET_CLS_ACT |
| 605 | struct tc_action *a = tcf_exts_first_act(exts); | 606 | struct tc_action *a = tcf_exts_first_act(exts); |
| 606 | if (tcf_action_copy_stats(skb, a, 1) < 0) | 607 | if (a != NULL && tcf_action_copy_stats(skb, a, 1) < 0) |
| 607 | return -1; | 608 | return -1; |
| 608 | #endif | 609 | #endif |
| 609 | return 0; | 610 | return 0; |
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 9b05924cc386..333cd94ba381 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
| @@ -670,8 +670,14 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 670 | if (tb[TCA_FQ_FLOW_PLIMIT]) | 670 | if (tb[TCA_FQ_FLOW_PLIMIT]) |
| 671 | q->flow_plimit = nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]); | 671 | q->flow_plimit = nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]); |
| 672 | 672 | ||
| 673 | if (tb[TCA_FQ_QUANTUM]) | 673 | if (tb[TCA_FQ_QUANTUM]) { |
| 674 | q->quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]); | 674 | u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]); |
| 675 | |||
| 676 | if (quantum > 0) | ||
| 677 | q->quantum = quantum; | ||
| 678 | else | ||
| 679 | err = -EINVAL; | ||
| 680 | } | ||
| 675 | 681 | ||
| 676 | if (tb[TCA_FQ_INITIAL_QUANTUM]) | 682 | if (tb[TCA_FQ_INITIAL_QUANTUM]) |
| 677 | q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]); | 683 | q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]); |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index e49e231cef52..06320c8c1c86 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -2608,7 +2608,7 @@ do_addr_param: | |||
| 2608 | 2608 | ||
| 2609 | addr_param = param.v + sizeof(sctp_addip_param_t); | 2609 | addr_param = param.v + sizeof(sctp_addip_param_t); |
| 2610 | 2610 | ||
| 2611 | af = sctp_get_af_specific(param_type2af(param.p->type)); | 2611 | af = sctp_get_af_specific(param_type2af(addr_param->p.type)); |
| 2612 | if (af == NULL) | 2612 | if (af == NULL) |
| 2613 | break; | 2613 | break; |
| 2614 | 2614 | ||
