diff options
Diffstat (limited to 'net')
41 files changed, 387 insertions, 329 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 77d43ae2a7bb..0ffcbdd55fa9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3272,7 +3272,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *first, struct net_device *de | |||
3272 | } | 3272 | } |
3273 | 3273 | ||
3274 | skb = next; | 3274 | skb = next; |
3275 | if (netif_xmit_stopped(txq) && skb) { | 3275 | if (netif_tx_queue_stopped(txq) && skb) { |
3276 | rc = NETDEV_TX_BUSY; | 3276 | rc = NETDEV_TX_BUSY; |
3277 | break; | 3277 | break; |
3278 | } | 3278 | } |
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 676f3ad629f9..588f475019d4 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
@@ -1166,8 +1166,8 @@ ip_proto_again: | |||
1166 | break; | 1166 | break; |
1167 | } | 1167 | } |
1168 | 1168 | ||
1169 | if (dissector_uses_key(flow_dissector, | 1169 | if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS) && |
1170 | FLOW_DISSECTOR_KEY_PORTS)) { | 1170 | !(key_control->flags & FLOW_DIS_IS_FRAGMENT)) { |
1171 | key_ports = skb_flow_dissector_target(flow_dissector, | 1171 | key_ports = skb_flow_dissector_target(flow_dissector, |
1172 | FLOW_DISSECTOR_KEY_PORTS, | 1172 | FLOW_DISSECTOR_KEY_PORTS, |
1173 | target_container); | 1173 | target_container); |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 5da9552b186b..2b9fdbc43205 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -717,7 +717,8 @@ int netpoll_setup(struct netpoll *np) | |||
717 | 717 | ||
718 | read_lock_bh(&idev->lock); | 718 | read_lock_bh(&idev->lock); |
719 | list_for_each_entry(ifp, &idev->addr_list, if_list) { | 719 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
720 | if (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL) | 720 | if (!!(ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL) != |
721 | !!(ipv6_addr_type(&np->remote_ip.in6) & IPV6_ADDR_LINKLOCAL)) | ||
721 | continue; | 722 | continue; |
722 | np->local_ip.in6 = ifp->addr; | 723 | np->local_ip.in6 = ifp->addr; |
723 | err = 0; | 724 | err = 0; |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index e01274bd5e3e..33d9227a8b80 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -3367,7 +3367,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | |||
3367 | cb->seq = 0; | 3367 | cb->seq = 0; |
3368 | } | 3368 | } |
3369 | ret = dumpit(skb, cb); | 3369 | ret = dumpit(skb, cb); |
3370 | if (ret < 0) | 3370 | if (ret) |
3371 | break; | 3371 | break; |
3372 | } | 3372 | } |
3373 | cb->family = idx; | 3373 | cb->family = idx; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 946de0e24c87..b4ee5c8b928f 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -4944,6 +4944,8 @@ static unsigned int skb_gso_mac_seglen(const struct sk_buff *skb) | |||
4944 | * | 4944 | * |
4945 | * This is a helper to do that correctly considering GSO_BY_FRAGS. | 4945 | * This is a helper to do that correctly considering GSO_BY_FRAGS. |
4946 | * | 4946 | * |
4947 | * @skb: GSO skb | ||
4948 | * | ||
4947 | * @seg_len: The segmented length (from skb_gso_*_seglen). In the | 4949 | * @seg_len: The segmented length (from skb_gso_*_seglen). In the |
4948 | * GSO_BY_FRAGS case this will be [header sizes + GSO_BY_FRAGS]. | 4950 | * GSO_BY_FRAGS case this will be [header sizes + GSO_BY_FRAGS]. |
4949 | * | 4951 | * |
diff --git a/net/core/sock.c b/net/core/sock.c index 6fcc4bc07d19..080a880a1761 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -3279,6 +3279,7 @@ int sock_load_diag_module(int family, int protocol) | |||
3279 | 3279 | ||
3280 | #ifdef CONFIG_INET | 3280 | #ifdef CONFIG_INET |
3281 | if (family == AF_INET && | 3281 | if (family == AF_INET && |
3282 | protocol != IPPROTO_RAW && | ||
3282 | !rcu_access_pointer(inet_protos[protocol])) | 3283 | !rcu_access_pointer(inet_protos[protocol])) |
3283 | return -ENOENT; | 3284 | return -ENOENT; |
3284 | #endif | 3285 | #endif |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index bcb11f3a27c0..760a9e52e02b 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -178,21 +178,22 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, | |||
178 | } | 178 | } |
179 | 179 | ||
180 | static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, | 180 | static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, |
181 | void *arg) | 181 | void *arg, |
182 | struct inet_frag_queue **prev) | ||
182 | { | 183 | { |
183 | struct inet_frags *f = nf->f; | 184 | struct inet_frags *f = nf->f; |
184 | struct inet_frag_queue *q; | 185 | struct inet_frag_queue *q; |
185 | int err; | ||
186 | 186 | ||
187 | q = inet_frag_alloc(nf, f, arg); | 187 | q = inet_frag_alloc(nf, f, arg); |
188 | if (!q) | 188 | if (!q) { |
189 | *prev = ERR_PTR(-ENOMEM); | ||
189 | return NULL; | 190 | return NULL; |
190 | 191 | } | |
191 | mod_timer(&q->timer, jiffies + nf->timeout); | 192 | mod_timer(&q->timer, jiffies + nf->timeout); |
192 | 193 | ||
193 | err = rhashtable_insert_fast(&nf->rhashtable, &q->node, | 194 | *prev = rhashtable_lookup_get_insert_key(&nf->rhashtable, &q->key, |
194 | f->rhash_params); | 195 | &q->node, f->rhash_params); |
195 | if (err < 0) { | 196 | if (*prev) { |
196 | q->flags |= INET_FRAG_COMPLETE; | 197 | q->flags |= INET_FRAG_COMPLETE; |
197 | inet_frag_kill(q); | 198 | inet_frag_kill(q); |
198 | inet_frag_destroy(q); | 199 | inet_frag_destroy(q); |
@@ -204,22 +205,22 @@ static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, | |||
204 | /* TODO : call from rcu_read_lock() and no longer use refcount_inc_not_zero() */ | 205 | /* TODO : call from rcu_read_lock() and no longer use refcount_inc_not_zero() */ |
205 | struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key) | 206 | struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key) |
206 | { | 207 | { |
207 | struct inet_frag_queue *fq; | 208 | struct inet_frag_queue *fq = NULL, *prev; |
208 | 209 | ||
209 | if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh) | 210 | if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh) |
210 | return NULL; | 211 | return NULL; |
211 | 212 | ||
212 | rcu_read_lock(); | 213 | rcu_read_lock(); |
213 | 214 | ||
214 | fq = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params); | 215 | prev = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params); |
215 | if (fq) { | 216 | if (!prev) |
217 | fq = inet_frag_create(nf, key, &prev); | ||
218 | if (prev && !IS_ERR(prev)) { | ||
219 | fq = prev; | ||
216 | if (!refcount_inc_not_zero(&fq->refcnt)) | 220 | if (!refcount_inc_not_zero(&fq->refcnt)) |
217 | fq = NULL; | 221 | fq = NULL; |
218 | rcu_read_unlock(); | ||
219 | return fq; | ||
220 | } | 222 | } |
221 | rcu_read_unlock(); | 223 | rcu_read_unlock(); |
222 | 224 | return fq; | |
223 | return inet_frag_create(nf, key); | ||
224 | } | 225 | } |
225 | EXPORT_SYMBOL(inet_frag_find); | 226 | EXPORT_SYMBOL(inet_frag_find); |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 9b0158fa431f..d6ee343fdb86 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -722,10 +722,14 @@ struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user) | |||
722 | if (ip_is_fragment(&iph)) { | 722 | if (ip_is_fragment(&iph)) { |
723 | skb = skb_share_check(skb, GFP_ATOMIC); | 723 | skb = skb_share_check(skb, GFP_ATOMIC); |
724 | if (skb) { | 724 | if (skb) { |
725 | if (!pskb_may_pull(skb, netoff + iph.ihl * 4)) | 725 | if (!pskb_may_pull(skb, netoff + iph.ihl * 4)) { |
726 | return skb; | 726 | kfree_skb(skb); |
727 | if (pskb_trim_rcsum(skb, netoff + len)) | 727 | return NULL; |
728 | return skb; | 728 | } |
729 | if (pskb_trim_rcsum(skb, netoff + len)) { | ||
730 | kfree_skb(skb); | ||
731 | return NULL; | ||
732 | } | ||
729 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | 733 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); |
730 | if (ip_defrag(net, skb, user)) | 734 | if (ip_defrag(net, skb, user)) |
731 | return NULL; | 735 | return NULL; |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 26c36cccabdc..fffcc130900e 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -1246,7 +1246,7 @@ int ip_setsockopt(struct sock *sk, int level, | |||
1246 | return -ENOPROTOOPT; | 1246 | return -ENOPROTOOPT; |
1247 | 1247 | ||
1248 | err = do_ip_setsockopt(sk, level, optname, optval, optlen); | 1248 | err = do_ip_setsockopt(sk, level, optname, optval, optlen); |
1249 | #ifdef CONFIG_BPFILTER | 1249 | #if IS_ENABLED(CONFIG_BPFILTER_UMH) |
1250 | if (optname >= BPFILTER_IPT_SO_SET_REPLACE && | 1250 | if (optname >= BPFILTER_IPT_SO_SET_REPLACE && |
1251 | optname < BPFILTER_IPT_SET_MAX) | 1251 | optname < BPFILTER_IPT_SET_MAX) |
1252 | err = bpfilter_ip_set_sockopt(sk, optname, optval, optlen); | 1252 | err = bpfilter_ip_set_sockopt(sk, optname, optval, optlen); |
@@ -1559,7 +1559,7 @@ int ip_getsockopt(struct sock *sk, int level, | |||
1559 | int err; | 1559 | int err; |
1560 | 1560 | ||
1561 | err = do_ip_getsockopt(sk, level, optname, optval, optlen, 0); | 1561 | err = do_ip_getsockopt(sk, level, optname, optval, optlen, 0); |
1562 | #ifdef CONFIG_BPFILTER | 1562 | #if IS_ENABLED(CONFIG_BPFILTER_UMH) |
1563 | if (optname >= BPFILTER_IPT_SO_GET_INFO && | 1563 | if (optname >= BPFILTER_IPT_SO_GET_INFO && |
1564 | optname < BPFILTER_IPT_GET_MAX) | 1564 | optname < BPFILTER_IPT_GET_MAX) |
1565 | err = bpfilter_ip_get_sockopt(sk, optname, optval, optlen); | 1565 | err = bpfilter_ip_get_sockopt(sk, optname, optval, optlen); |
@@ -1596,7 +1596,7 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname, | |||
1596 | err = do_ip_getsockopt(sk, level, optname, optval, optlen, | 1596 | err = do_ip_getsockopt(sk, level, optname, optval, optlen, |
1597 | MSG_CMSG_COMPAT); | 1597 | MSG_CMSG_COMPAT); |
1598 | 1598 | ||
1599 | #ifdef CONFIG_BPFILTER | 1599 | #if IS_ENABLED(CONFIG_BPFILTER_UMH) |
1600 | if (optname >= BPFILTER_IPT_SO_GET_INFO && | 1600 | if (optname >= BPFILTER_IPT_SO_GET_INFO && |
1601 | optname < BPFILTER_IPT_GET_MAX) | 1601 | optname < BPFILTER_IPT_GET_MAX) |
1602 | err = bpfilter_ip_get_sockopt(sk, optname, optval, optlen); | 1602 | err = bpfilter_ip_get_sockopt(sk, optname, optval, optlen); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3f4d61017a69..f0cd291034f0 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -1001,6 +1001,9 @@ static int __init inet6_init(void) | |||
1001 | err = ip6_flowlabel_init(); | 1001 | err = ip6_flowlabel_init(); |
1002 | if (err) | 1002 | if (err) |
1003 | goto ip6_flowlabel_fail; | 1003 | goto ip6_flowlabel_fail; |
1004 | err = ipv6_anycast_init(); | ||
1005 | if (err) | ||
1006 | goto ipv6_anycast_fail; | ||
1004 | err = addrconf_init(); | 1007 | err = addrconf_init(); |
1005 | if (err) | 1008 | if (err) |
1006 | goto addrconf_fail; | 1009 | goto addrconf_fail; |
@@ -1091,6 +1094,8 @@ ipv6_frag_fail: | |||
1091 | ipv6_exthdrs_fail: | 1094 | ipv6_exthdrs_fail: |
1092 | addrconf_cleanup(); | 1095 | addrconf_cleanup(); |
1093 | addrconf_fail: | 1096 | addrconf_fail: |
1097 | ipv6_anycast_cleanup(); | ||
1098 | ipv6_anycast_fail: | ||
1094 | ip6_flowlabel_cleanup(); | 1099 | ip6_flowlabel_cleanup(); |
1095 | ip6_flowlabel_fail: | 1100 | ip6_flowlabel_fail: |
1096 | ndisc_late_cleanup(); | 1101 | ndisc_late_cleanup(); |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 4e0ff7031edd..94999058e110 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -44,8 +44,22 @@ | |||
44 | 44 | ||
45 | #include <net/checksum.h> | 45 | #include <net/checksum.h> |
46 | 46 | ||
47 | #define IN6_ADDR_HSIZE_SHIFT 8 | ||
48 | #define IN6_ADDR_HSIZE BIT(IN6_ADDR_HSIZE_SHIFT) | ||
49 | /* anycast address hash table | ||
50 | */ | ||
51 | static struct hlist_head inet6_acaddr_lst[IN6_ADDR_HSIZE]; | ||
52 | static DEFINE_SPINLOCK(acaddr_hash_lock); | ||
53 | |||
47 | static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr); | 54 | static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr); |
48 | 55 | ||
56 | static u32 inet6_acaddr_hash(struct net *net, const struct in6_addr *addr) | ||
57 | { | ||
58 | u32 val = ipv6_addr_hash(addr) ^ net_hash_mix(net); | ||
59 | |||
60 | return hash_32(val, IN6_ADDR_HSIZE_SHIFT); | ||
61 | } | ||
62 | |||
49 | /* | 63 | /* |
50 | * socket join an anycast group | 64 | * socket join an anycast group |
51 | */ | 65 | */ |
@@ -204,16 +218,39 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
204 | rtnl_unlock(); | 218 | rtnl_unlock(); |
205 | } | 219 | } |
206 | 220 | ||
221 | static void ipv6_add_acaddr_hash(struct net *net, struct ifacaddr6 *aca) | ||
222 | { | ||
223 | unsigned int hash = inet6_acaddr_hash(net, &aca->aca_addr); | ||
224 | |||
225 | spin_lock(&acaddr_hash_lock); | ||
226 | hlist_add_head_rcu(&aca->aca_addr_lst, &inet6_acaddr_lst[hash]); | ||
227 | spin_unlock(&acaddr_hash_lock); | ||
228 | } | ||
229 | |||
230 | static void ipv6_del_acaddr_hash(struct ifacaddr6 *aca) | ||
231 | { | ||
232 | spin_lock(&acaddr_hash_lock); | ||
233 | hlist_del_init_rcu(&aca->aca_addr_lst); | ||
234 | spin_unlock(&acaddr_hash_lock); | ||
235 | } | ||
236 | |||
207 | static void aca_get(struct ifacaddr6 *aca) | 237 | static void aca_get(struct ifacaddr6 *aca) |
208 | { | 238 | { |
209 | refcount_inc(&aca->aca_refcnt); | 239 | refcount_inc(&aca->aca_refcnt); |
210 | } | 240 | } |
211 | 241 | ||
242 | static void aca_free_rcu(struct rcu_head *h) | ||
243 | { | ||
244 | struct ifacaddr6 *aca = container_of(h, struct ifacaddr6, rcu); | ||
245 | |||
246 | fib6_info_release(aca->aca_rt); | ||
247 | kfree(aca); | ||
248 | } | ||
249 | |||
212 | static void aca_put(struct ifacaddr6 *ac) | 250 | static void aca_put(struct ifacaddr6 *ac) |
213 | { | 251 | { |
214 | if (refcount_dec_and_test(&ac->aca_refcnt)) { | 252 | if (refcount_dec_and_test(&ac->aca_refcnt)) { |
215 | fib6_info_release(ac->aca_rt); | 253 | call_rcu(&ac->rcu, aca_free_rcu); |
216 | kfree(ac); | ||
217 | } | 254 | } |
218 | } | 255 | } |
219 | 256 | ||
@@ -229,6 +266,7 @@ static struct ifacaddr6 *aca_alloc(struct fib6_info *f6i, | |||
229 | aca->aca_addr = *addr; | 266 | aca->aca_addr = *addr; |
230 | fib6_info_hold(f6i); | 267 | fib6_info_hold(f6i); |
231 | aca->aca_rt = f6i; | 268 | aca->aca_rt = f6i; |
269 | INIT_HLIST_NODE(&aca->aca_addr_lst); | ||
232 | aca->aca_users = 1; | 270 | aca->aca_users = 1; |
233 | /* aca_tstamp should be updated upon changes */ | 271 | /* aca_tstamp should be updated upon changes */ |
234 | aca->aca_cstamp = aca->aca_tstamp = jiffies; | 272 | aca->aca_cstamp = aca->aca_tstamp = jiffies; |
@@ -285,6 +323,8 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr) | |||
285 | aca_get(aca); | 323 | aca_get(aca); |
286 | write_unlock_bh(&idev->lock); | 324 | write_unlock_bh(&idev->lock); |
287 | 325 | ||
326 | ipv6_add_acaddr_hash(net, aca); | ||
327 | |||
288 | ip6_ins_rt(net, f6i); | 328 | ip6_ins_rt(net, f6i); |
289 | 329 | ||
290 | addrconf_join_solict(idev->dev, &aca->aca_addr); | 330 | addrconf_join_solict(idev->dev, &aca->aca_addr); |
@@ -325,6 +365,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr) | |||
325 | else | 365 | else |
326 | idev->ac_list = aca->aca_next; | 366 | idev->ac_list = aca->aca_next; |
327 | write_unlock_bh(&idev->lock); | 367 | write_unlock_bh(&idev->lock); |
368 | ipv6_del_acaddr_hash(aca); | ||
328 | addrconf_leave_solict(idev, &aca->aca_addr); | 369 | addrconf_leave_solict(idev, &aca->aca_addr); |
329 | 370 | ||
330 | ip6_del_rt(dev_net(idev->dev), aca->aca_rt); | 371 | ip6_del_rt(dev_net(idev->dev), aca->aca_rt); |
@@ -352,6 +393,8 @@ void ipv6_ac_destroy_dev(struct inet6_dev *idev) | |||
352 | idev->ac_list = aca->aca_next; | 393 | idev->ac_list = aca->aca_next; |
353 | write_unlock_bh(&idev->lock); | 394 | write_unlock_bh(&idev->lock); |
354 | 395 | ||
396 | ipv6_del_acaddr_hash(aca); | ||
397 | |||
355 | addrconf_leave_solict(idev, &aca->aca_addr); | 398 | addrconf_leave_solict(idev, &aca->aca_addr); |
356 | 399 | ||
357 | ip6_del_rt(dev_net(idev->dev), aca->aca_rt); | 400 | ip6_del_rt(dev_net(idev->dev), aca->aca_rt); |
@@ -390,17 +433,25 @@ static bool ipv6_chk_acast_dev(struct net_device *dev, const struct in6_addr *ad | |||
390 | bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, | 433 | bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, |
391 | const struct in6_addr *addr) | 434 | const struct in6_addr *addr) |
392 | { | 435 | { |
436 | unsigned int hash = inet6_acaddr_hash(net, addr); | ||
437 | struct net_device *nh_dev; | ||
438 | struct ifacaddr6 *aca; | ||
393 | bool found = false; | 439 | bool found = false; |
394 | 440 | ||
395 | rcu_read_lock(); | 441 | rcu_read_lock(); |
396 | if (dev) | 442 | if (dev) |
397 | found = ipv6_chk_acast_dev(dev, addr); | 443 | found = ipv6_chk_acast_dev(dev, addr); |
398 | else | 444 | else |
399 | for_each_netdev_rcu(net, dev) | 445 | hlist_for_each_entry_rcu(aca, &inet6_acaddr_lst[hash], |
400 | if (ipv6_chk_acast_dev(dev, addr)) { | 446 | aca_addr_lst) { |
447 | nh_dev = fib6_info_nh_dev(aca->aca_rt); | ||
448 | if (!nh_dev || !net_eq(dev_net(nh_dev), net)) | ||
449 | continue; | ||
450 | if (ipv6_addr_equal(&aca->aca_addr, addr)) { | ||
401 | found = true; | 451 | found = true; |
402 | break; | 452 | break; |
403 | } | 453 | } |
454 | } | ||
404 | rcu_read_unlock(); | 455 | rcu_read_unlock(); |
405 | return found; | 456 | return found; |
406 | } | 457 | } |
@@ -540,3 +591,24 @@ void ac6_proc_exit(struct net *net) | |||
540 | remove_proc_entry("anycast6", net->proc_net); | 591 | remove_proc_entry("anycast6", net->proc_net); |
541 | } | 592 | } |
542 | #endif | 593 | #endif |
594 | |||
595 | /* Init / cleanup code | ||
596 | */ | ||
597 | int __init ipv6_anycast_init(void) | ||
598 | { | ||
599 | int i; | ||
600 | |||
601 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | ||
602 | INIT_HLIST_HEAD(&inet6_acaddr_lst[i]); | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | void ipv6_anycast_cleanup(void) | ||
607 | { | ||
608 | int i; | ||
609 | |||
610 | spin_lock(&acaddr_hash_lock); | ||
611 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | ||
612 | WARN_ON(!hlist_empty(&inet6_acaddr_lst[i])); | ||
613 | spin_unlock(&acaddr_hash_lock); | ||
614 | } | ||
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 1b8bc008b53b..ae3786132c23 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -591,7 +591,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
591 | 591 | ||
592 | /* fib entries are never clones */ | 592 | /* fib entries are never clones */ |
593 | if (arg.filter.flags & RTM_F_CLONED) | 593 | if (arg.filter.flags & RTM_F_CLONED) |
594 | return skb->len; | 594 | goto out; |
595 | 595 | ||
596 | w = (void *)cb->args[2]; | 596 | w = (void *)cb->args[2]; |
597 | if (!w) { | 597 | if (!w) { |
@@ -621,7 +621,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
621 | tb = fib6_get_table(net, arg.filter.table_id); | 621 | tb = fib6_get_table(net, arg.filter.table_id); |
622 | if (!tb) { | 622 | if (!tb) { |
623 | if (arg.filter.dump_all_families) | 623 | if (arg.filter.dump_all_families) |
624 | return skb->len; | 624 | goto out; |
625 | 625 | ||
626 | NL_SET_ERR_MSG_MOD(cb->extack, "FIB table does not exist"); | 626 | NL_SET_ERR_MSG_MOD(cb->extack, "FIB table does not exist"); |
627 | return -ENOENT; | 627 | return -ENOENT; |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index b8ac369f98ad..d219979c3e52 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -587,11 +587,16 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) | |||
587 | */ | 587 | */ |
588 | ret = -EINPROGRESS; | 588 | ret = -EINPROGRESS; |
589 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 589 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
590 | fq->q.meat == fq->q.len && | 590 | fq->q.meat == fq->q.len) { |
591 | nf_ct_frag6_reasm(fq, skb, dev)) | 591 | unsigned long orefdst = skb->_skb_refdst; |
592 | ret = 0; | 592 | |
593 | else | 593 | skb->_skb_refdst = 0UL; |
594 | if (nf_ct_frag6_reasm(fq, skb, dev)) | ||
595 | ret = 0; | ||
596 | skb->_skb_refdst = orefdst; | ||
597 | } else { | ||
594 | skb_dst_drop(skb); | 598 | skb_dst_drop(skb); |
599 | } | ||
595 | 600 | ||
596 | out_unlock: | 601 | out_unlock: |
597 | spin_unlock_bh(&fq->q.lock); | 602 | spin_unlock_bh(&fq->q.lock); |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index bc4bd247bb7d..1577f2f76060 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -55,11 +55,15 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | |||
55 | MODULE_DESCRIPTION("core IP set support"); | 55 | MODULE_DESCRIPTION("core IP set support"); |
56 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET); | 56 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET); |
57 | 57 | ||
58 | /* When the nfnl mutex is held: */ | 58 | /* When the nfnl mutex or ip_set_ref_lock is held: */ |
59 | #define ip_set_dereference(p) \ | 59 | #define ip_set_dereference(p) \ |
60 | rcu_dereference_protected(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET)) | 60 | rcu_dereference_protected(p, \ |
61 | lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \ | ||
62 | lockdep_is_held(&ip_set_ref_lock)) | ||
61 | #define ip_set(inst, id) \ | 63 | #define ip_set(inst, id) \ |
62 | ip_set_dereference((inst)->ip_set_list)[id] | 64 | ip_set_dereference((inst)->ip_set_list)[id] |
65 | #define ip_set_ref_netlink(inst,id) \ | ||
66 | rcu_dereference_raw((inst)->ip_set_list)[id] | ||
63 | 67 | ||
64 | /* The set types are implemented in modules and registered set types | 68 | /* The set types are implemented in modules and registered set types |
65 | * can be found in ip_set_type_list. Adding/deleting types is | 69 | * can be found in ip_set_type_list. Adding/deleting types is |
@@ -693,21 +697,20 @@ ip_set_put_byindex(struct net *net, ip_set_id_t index) | |||
693 | EXPORT_SYMBOL_GPL(ip_set_put_byindex); | 697 | EXPORT_SYMBOL_GPL(ip_set_put_byindex); |
694 | 698 | ||
695 | /* Get the name of a set behind a set index. | 699 | /* Get the name of a set behind a set index. |
696 | * We assume the set is referenced, so it does exist and | 700 | * Set itself is protected by RCU, but its name isn't: to protect against |
697 | * can't be destroyed. The set cannot be renamed due to | 701 | * renaming, grab ip_set_ref_lock as reader (see ip_set_rename()) and copy the |
698 | * the referencing either. | 702 | * name. |
699 | * | ||
700 | */ | 703 | */ |
701 | const char * | 704 | void |
702 | ip_set_name_byindex(struct net *net, ip_set_id_t index) | 705 | ip_set_name_byindex(struct net *net, ip_set_id_t index, char *name) |
703 | { | 706 | { |
704 | const struct ip_set *set = ip_set_rcu_get(net, index); | 707 | struct ip_set *set = ip_set_rcu_get(net, index); |
705 | 708 | ||
706 | BUG_ON(!set); | 709 | BUG_ON(!set); |
707 | BUG_ON(set->ref == 0); | ||
708 | 710 | ||
709 | /* Referenced, so it's safe */ | 711 | read_lock_bh(&ip_set_ref_lock); |
710 | return set->name; | 712 | strncpy(name, set->name, IPSET_MAXNAMELEN); |
713 | read_unlock_bh(&ip_set_ref_lock); | ||
711 | } | 714 | } |
712 | EXPORT_SYMBOL_GPL(ip_set_name_byindex); | 715 | EXPORT_SYMBOL_GPL(ip_set_name_byindex); |
713 | 716 | ||
@@ -961,7 +964,7 @@ static int ip_set_create(struct net *net, struct sock *ctnl, | |||
961 | /* Wraparound */ | 964 | /* Wraparound */ |
962 | goto cleanup; | 965 | goto cleanup; |
963 | 966 | ||
964 | list = kcalloc(i, sizeof(struct ip_set *), GFP_KERNEL); | 967 | list = kvcalloc(i, sizeof(struct ip_set *), GFP_KERNEL); |
965 | if (!list) | 968 | if (!list) |
966 | goto cleanup; | 969 | goto cleanup; |
967 | /* nfnl mutex is held, both lists are valid */ | 970 | /* nfnl mutex is held, both lists are valid */ |
@@ -973,7 +976,7 @@ static int ip_set_create(struct net *net, struct sock *ctnl, | |||
973 | /* Use new list */ | 976 | /* Use new list */ |
974 | index = inst->ip_set_max; | 977 | index = inst->ip_set_max; |
975 | inst->ip_set_max = i; | 978 | inst->ip_set_max = i; |
976 | kfree(tmp); | 979 | kvfree(tmp); |
977 | ret = 0; | 980 | ret = 0; |
978 | } else if (ret) { | 981 | } else if (ret) { |
979 | goto cleanup; | 982 | goto cleanup; |
@@ -1153,7 +1156,7 @@ static int ip_set_rename(struct net *net, struct sock *ctnl, | |||
1153 | if (!set) | 1156 | if (!set) |
1154 | return -ENOENT; | 1157 | return -ENOENT; |
1155 | 1158 | ||
1156 | read_lock_bh(&ip_set_ref_lock); | 1159 | write_lock_bh(&ip_set_ref_lock); |
1157 | if (set->ref != 0) { | 1160 | if (set->ref != 0) { |
1158 | ret = -IPSET_ERR_REFERENCED; | 1161 | ret = -IPSET_ERR_REFERENCED; |
1159 | goto out; | 1162 | goto out; |
@@ -1170,7 +1173,7 @@ static int ip_set_rename(struct net *net, struct sock *ctnl, | |||
1170 | strncpy(set->name, name2, IPSET_MAXNAMELEN); | 1173 | strncpy(set->name, name2, IPSET_MAXNAMELEN); |
1171 | 1174 | ||
1172 | out: | 1175 | out: |
1173 | read_unlock_bh(&ip_set_ref_lock); | 1176 | write_unlock_bh(&ip_set_ref_lock); |
1174 | return ret; | 1177 | return ret; |
1175 | } | 1178 | } |
1176 | 1179 | ||
@@ -1252,7 +1255,7 @@ ip_set_dump_done(struct netlink_callback *cb) | |||
1252 | struct ip_set_net *inst = | 1255 | struct ip_set_net *inst = |
1253 | (struct ip_set_net *)cb->args[IPSET_CB_NET]; | 1256 | (struct ip_set_net *)cb->args[IPSET_CB_NET]; |
1254 | ip_set_id_t index = (ip_set_id_t)cb->args[IPSET_CB_INDEX]; | 1257 | ip_set_id_t index = (ip_set_id_t)cb->args[IPSET_CB_INDEX]; |
1255 | struct ip_set *set = ip_set(inst, index); | 1258 | struct ip_set *set = ip_set_ref_netlink(inst, index); |
1256 | 1259 | ||
1257 | if (set->variant->uref) | 1260 | if (set->variant->uref) |
1258 | set->variant->uref(set, cb, false); | 1261 | set->variant->uref(set, cb, false); |
@@ -1441,7 +1444,7 @@ next_set: | |||
1441 | release_refcount: | 1444 | release_refcount: |
1442 | /* If there was an error or set is done, release set */ | 1445 | /* If there was an error or set is done, release set */ |
1443 | if (ret || !cb->args[IPSET_CB_ARG0]) { | 1446 | if (ret || !cb->args[IPSET_CB_ARG0]) { |
1444 | set = ip_set(inst, index); | 1447 | set = ip_set_ref_netlink(inst, index); |
1445 | if (set->variant->uref) | 1448 | if (set->variant->uref) |
1446 | set->variant->uref(set, cb, false); | 1449 | set->variant->uref(set, cb, false); |
1447 | pr_debug("release set %s\n", set->name); | 1450 | pr_debug("release set %s\n", set->name); |
@@ -2059,7 +2062,7 @@ ip_set_net_init(struct net *net) | |||
2059 | if (inst->ip_set_max >= IPSET_INVALID_ID) | 2062 | if (inst->ip_set_max >= IPSET_INVALID_ID) |
2060 | inst->ip_set_max = IPSET_INVALID_ID - 1; | 2063 | inst->ip_set_max = IPSET_INVALID_ID - 1; |
2061 | 2064 | ||
2062 | list = kcalloc(inst->ip_set_max, sizeof(struct ip_set *), GFP_KERNEL); | 2065 | list = kvcalloc(inst->ip_set_max, sizeof(struct ip_set *), GFP_KERNEL); |
2063 | if (!list) | 2066 | if (!list) |
2064 | return -ENOMEM; | 2067 | return -ENOMEM; |
2065 | inst->is_deleted = false; | 2068 | inst->is_deleted = false; |
@@ -2087,7 +2090,7 @@ ip_set_net_exit(struct net *net) | |||
2087 | } | 2090 | } |
2088 | } | 2091 | } |
2089 | nfnl_unlock(NFNL_SUBSYS_IPSET); | 2092 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
2090 | kfree(rcu_dereference_protected(inst->ip_set_list, 1)); | 2093 | kvfree(rcu_dereference_protected(inst->ip_set_list, 1)); |
2091 | } | 2094 | } |
2092 | 2095 | ||
2093 | static struct pernet_operations ip_set_net_ops = { | 2096 | static struct pernet_operations ip_set_net_ops = { |
diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c index d391485a6acd..613e18e720a4 100644 --- a/net/netfilter/ipset/ip_set_hash_netportnet.c +++ b/net/netfilter/ipset/ip_set_hash_netportnet.c | |||
@@ -213,13 +213,13 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
213 | 213 | ||
214 | if (tb[IPSET_ATTR_CIDR]) { | 214 | if (tb[IPSET_ATTR_CIDR]) { |
215 | e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]); | 215 | e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]); |
216 | if (!e.cidr[0] || e.cidr[0] > HOST_MASK) | 216 | if (e.cidr[0] > HOST_MASK) |
217 | return -IPSET_ERR_INVALID_CIDR; | 217 | return -IPSET_ERR_INVALID_CIDR; |
218 | } | 218 | } |
219 | 219 | ||
220 | if (tb[IPSET_ATTR_CIDR2]) { | 220 | if (tb[IPSET_ATTR_CIDR2]) { |
221 | e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]); | 221 | e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]); |
222 | if (!e.cidr[1] || e.cidr[1] > HOST_MASK) | 222 | if (e.cidr[1] > HOST_MASK) |
223 | return -IPSET_ERR_INVALID_CIDR; | 223 | return -IPSET_ERR_INVALID_CIDR; |
224 | } | 224 | } |
225 | 225 | ||
@@ -493,13 +493,13 @@ hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
493 | 493 | ||
494 | if (tb[IPSET_ATTR_CIDR]) { | 494 | if (tb[IPSET_ATTR_CIDR]) { |
495 | e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]); | 495 | e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]); |
496 | if (!e.cidr[0] || e.cidr[0] > HOST_MASK) | 496 | if (e.cidr[0] > HOST_MASK) |
497 | return -IPSET_ERR_INVALID_CIDR; | 497 | return -IPSET_ERR_INVALID_CIDR; |
498 | } | 498 | } |
499 | 499 | ||
500 | if (tb[IPSET_ATTR_CIDR2]) { | 500 | if (tb[IPSET_ATTR_CIDR2]) { |
501 | e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]); | 501 | e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]); |
502 | if (!e.cidr[1] || e.cidr[1] > HOST_MASK) | 502 | if (e.cidr[1] > HOST_MASK) |
503 | return -IPSET_ERR_INVALID_CIDR; | 503 | return -IPSET_ERR_INVALID_CIDR; |
504 | } | 504 | } |
505 | 505 | ||
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index 072a658fde04..4eef55da0878 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c | |||
@@ -148,9 +148,7 @@ __list_set_del_rcu(struct rcu_head * rcu) | |||
148 | { | 148 | { |
149 | struct set_elem *e = container_of(rcu, struct set_elem, rcu); | 149 | struct set_elem *e = container_of(rcu, struct set_elem, rcu); |
150 | struct ip_set *set = e->set; | 150 | struct ip_set *set = e->set; |
151 | struct list_set *map = set->data; | ||
152 | 151 | ||
153 | ip_set_put_byindex(map->net, e->id); | ||
154 | ip_set_ext_destroy(set, e); | 152 | ip_set_ext_destroy(set, e); |
155 | kfree(e); | 153 | kfree(e); |
156 | } | 154 | } |
@@ -158,15 +156,21 @@ __list_set_del_rcu(struct rcu_head * rcu) | |||
158 | static inline void | 156 | static inline void |
159 | list_set_del(struct ip_set *set, struct set_elem *e) | 157 | list_set_del(struct ip_set *set, struct set_elem *e) |
160 | { | 158 | { |
159 | struct list_set *map = set->data; | ||
160 | |||
161 | set->elements--; | 161 | set->elements--; |
162 | list_del_rcu(&e->list); | 162 | list_del_rcu(&e->list); |
163 | ip_set_put_byindex(map->net, e->id); | ||
163 | call_rcu(&e->rcu, __list_set_del_rcu); | 164 | call_rcu(&e->rcu, __list_set_del_rcu); |
164 | } | 165 | } |
165 | 166 | ||
166 | static inline void | 167 | static inline void |
167 | list_set_replace(struct set_elem *e, struct set_elem *old) | 168 | list_set_replace(struct ip_set *set, struct set_elem *e, struct set_elem *old) |
168 | { | 169 | { |
170 | struct list_set *map = set->data; | ||
171 | |||
169 | list_replace_rcu(&old->list, &e->list); | 172 | list_replace_rcu(&old->list, &e->list); |
173 | ip_set_put_byindex(map->net, old->id); | ||
170 | call_rcu(&old->rcu, __list_set_del_rcu); | 174 | call_rcu(&old->rcu, __list_set_del_rcu); |
171 | } | 175 | } |
172 | 176 | ||
@@ -298,7 +302,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
298 | INIT_LIST_HEAD(&e->list); | 302 | INIT_LIST_HEAD(&e->list); |
299 | list_set_init_extensions(set, ext, e); | 303 | list_set_init_extensions(set, ext, e); |
300 | if (n) | 304 | if (n) |
301 | list_set_replace(e, n); | 305 | list_set_replace(set, e, n); |
302 | else if (next) | 306 | else if (next) |
303 | list_add_tail_rcu(&e->list, &next->list); | 307 | list_add_tail_rcu(&e->list, &next->list); |
304 | else if (prev) | 308 | else if (prev) |
@@ -486,6 +490,7 @@ list_set_list(const struct ip_set *set, | |||
486 | const struct list_set *map = set->data; | 490 | const struct list_set *map = set->data; |
487 | struct nlattr *atd, *nested; | 491 | struct nlattr *atd, *nested; |
488 | u32 i = 0, first = cb->args[IPSET_CB_ARG0]; | 492 | u32 i = 0, first = cb->args[IPSET_CB_ARG0]; |
493 | char name[IPSET_MAXNAMELEN]; | ||
489 | struct set_elem *e; | 494 | struct set_elem *e; |
490 | int ret = 0; | 495 | int ret = 0; |
491 | 496 | ||
@@ -504,8 +509,8 @@ list_set_list(const struct ip_set *set, | |||
504 | nested = ipset_nest_start(skb, IPSET_ATTR_DATA); | 509 | nested = ipset_nest_start(skb, IPSET_ATTR_DATA); |
505 | if (!nested) | 510 | if (!nested) |
506 | goto nla_put_failure; | 511 | goto nla_put_failure; |
507 | if (nla_put_string(skb, IPSET_ATTR_NAME, | 512 | ip_set_name_byindex(map->net, e->id, name); |
508 | ip_set_name_byindex(map->net, e->id))) | 513 | if (nla_put_string(skb, IPSET_ATTR_NAME, name)) |
509 | goto nla_put_failure; | 514 | goto nla_put_failure; |
510 | if (ip_set_put_extensions(skb, set, e, true)) | 515 | if (ip_set_put_extensions(skb, set, e, true)) |
511 | goto nla_put_failure; | 516 | goto nla_put_failure; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ca1168d67fac..e92e749aff53 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -1073,19 +1073,22 @@ static unsigned int early_drop_list(struct net *net, | |||
1073 | return drops; | 1073 | return drops; |
1074 | } | 1074 | } |
1075 | 1075 | ||
1076 | static noinline int early_drop(struct net *net, unsigned int _hash) | 1076 | static noinline int early_drop(struct net *net, unsigned int hash) |
1077 | { | 1077 | { |
1078 | unsigned int i; | 1078 | unsigned int i, bucket; |
1079 | 1079 | ||
1080 | for (i = 0; i < NF_CT_EVICTION_RANGE; i++) { | 1080 | for (i = 0; i < NF_CT_EVICTION_RANGE; i++) { |
1081 | struct hlist_nulls_head *ct_hash; | 1081 | struct hlist_nulls_head *ct_hash; |
1082 | unsigned int hash, hsize, drops; | 1082 | unsigned int hsize, drops; |
1083 | 1083 | ||
1084 | rcu_read_lock(); | 1084 | rcu_read_lock(); |
1085 | nf_conntrack_get_ht(&ct_hash, &hsize); | 1085 | nf_conntrack_get_ht(&ct_hash, &hsize); |
1086 | hash = reciprocal_scale(_hash++, hsize); | 1086 | if (!i) |
1087 | bucket = reciprocal_scale(hash, hsize); | ||
1088 | else | ||
1089 | bucket = (bucket + 1) % hsize; | ||
1087 | 1090 | ||
1088 | drops = early_drop_list(net, &ct_hash[hash]); | 1091 | drops = early_drop_list(net, &ct_hash[bucket]); |
1089 | rcu_read_unlock(); | 1092 | rcu_read_unlock(); |
1090 | 1093 | ||
1091 | if (drops) { | 1094 | if (drops) { |
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 171e9e122e5f..023c1445bc39 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c | |||
@@ -384,11 +384,6 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = | |||
384 | }, | 384 | }, |
385 | }; | 385 | }; |
386 | 386 | ||
387 | static inline struct nf_dccp_net *dccp_pernet(struct net *net) | ||
388 | { | ||
389 | return &net->ct.nf_ct_proto.dccp; | ||
390 | } | ||
391 | |||
392 | static noinline bool | 387 | static noinline bool |
393 | dccp_new(struct nf_conn *ct, const struct sk_buff *skb, | 388 | dccp_new(struct nf_conn *ct, const struct sk_buff *skb, |
394 | const struct dccp_hdr *dh) | 389 | const struct dccp_hdr *dh) |
@@ -401,7 +396,7 @@ dccp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
401 | state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; | 396 | state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; |
402 | switch (state) { | 397 | switch (state) { |
403 | default: | 398 | default: |
404 | dn = dccp_pernet(net); | 399 | dn = nf_dccp_pernet(net); |
405 | if (dn->dccp_loose == 0) { | 400 | if (dn->dccp_loose == 0) { |
406 | msg = "not picking up existing connection "; | 401 | msg = "not picking up existing connection "; |
407 | goto out_invalid; | 402 | goto out_invalid; |
@@ -568,7 +563,7 @@ static int dccp_packet(struct nf_conn *ct, struct sk_buff *skb, | |||
568 | 563 | ||
569 | timeouts = nf_ct_timeout_lookup(ct); | 564 | timeouts = nf_ct_timeout_lookup(ct); |
570 | if (!timeouts) | 565 | if (!timeouts) |
571 | timeouts = dccp_pernet(nf_ct_net(ct))->dccp_timeout; | 566 | timeouts = nf_dccp_pernet(nf_ct_net(ct))->dccp_timeout; |
572 | nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]); | 567 | nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]); |
573 | 568 | ||
574 | return NF_ACCEPT; | 569 | return NF_ACCEPT; |
@@ -681,7 +676,7 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) | |||
681 | static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[], | 676 | static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[], |
682 | struct net *net, void *data) | 677 | struct net *net, void *data) |
683 | { | 678 | { |
684 | struct nf_dccp_net *dn = dccp_pernet(net); | 679 | struct nf_dccp_net *dn = nf_dccp_pernet(net); |
685 | unsigned int *timeouts = data; | 680 | unsigned int *timeouts = data; |
686 | int i; | 681 | int i; |
687 | 682 | ||
@@ -814,7 +809,7 @@ static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn, | |||
814 | 809 | ||
815 | static int dccp_init_net(struct net *net) | 810 | static int dccp_init_net(struct net *net) |
816 | { | 811 | { |
817 | struct nf_dccp_net *dn = dccp_pernet(net); | 812 | struct nf_dccp_net *dn = nf_dccp_pernet(net); |
818 | struct nf_proto_net *pn = &dn->pn; | 813 | struct nf_proto_net *pn = &dn->pn; |
819 | 814 | ||
820 | if (!pn->users) { | 815 | if (!pn->users) { |
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index e10e867e0b55..5da19d5fbc76 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c | |||
@@ -27,11 +27,6 @@ static bool nf_generic_should_process(u8 proto) | |||
27 | } | 27 | } |
28 | } | 28 | } |
29 | 29 | ||
30 | static inline struct nf_generic_net *generic_pernet(struct net *net) | ||
31 | { | ||
32 | return &net->ct.nf_ct_proto.generic; | ||
33 | } | ||
34 | |||
35 | static bool generic_pkt_to_tuple(const struct sk_buff *skb, | 30 | static bool generic_pkt_to_tuple(const struct sk_buff *skb, |
36 | unsigned int dataoff, | 31 | unsigned int dataoff, |
37 | struct net *net, struct nf_conntrack_tuple *tuple) | 32 | struct net *net, struct nf_conntrack_tuple *tuple) |
@@ -58,7 +53,7 @@ static int generic_packet(struct nf_conn *ct, | |||
58 | } | 53 | } |
59 | 54 | ||
60 | if (!timeout) | 55 | if (!timeout) |
61 | timeout = &generic_pernet(nf_ct_net(ct))->timeout; | 56 | timeout = &nf_generic_pernet(nf_ct_net(ct))->timeout; |
62 | 57 | ||
63 | nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); | 58 | nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); |
64 | return NF_ACCEPT; | 59 | return NF_ACCEPT; |
@@ -72,7 +67,7 @@ static int generic_packet(struct nf_conn *ct, | |||
72 | static int generic_timeout_nlattr_to_obj(struct nlattr *tb[], | 67 | static int generic_timeout_nlattr_to_obj(struct nlattr *tb[], |
73 | struct net *net, void *data) | 68 | struct net *net, void *data) |
74 | { | 69 | { |
75 | struct nf_generic_net *gn = generic_pernet(net); | 70 | struct nf_generic_net *gn = nf_generic_pernet(net); |
76 | unsigned int *timeout = data; | 71 | unsigned int *timeout = data; |
77 | 72 | ||
78 | if (!timeout) | 73 | if (!timeout) |
@@ -138,7 +133,7 @@ static int generic_kmemdup_sysctl_table(struct nf_proto_net *pn, | |||
138 | 133 | ||
139 | static int generic_init_net(struct net *net) | 134 | static int generic_init_net(struct net *net) |
140 | { | 135 | { |
141 | struct nf_generic_net *gn = generic_pernet(net); | 136 | struct nf_generic_net *gn = nf_generic_pernet(net); |
142 | struct nf_proto_net *pn = &gn->pn; | 137 | struct nf_proto_net *pn = &gn->pn; |
143 | 138 | ||
144 | gn->timeout = nf_ct_generic_timeout; | 139 | gn->timeout = nf_ct_generic_timeout; |
diff --git a/net/netfilter/nf_conntrack_proto_icmp.c b/net/netfilter/nf_conntrack_proto_icmp.c index 3598520bd19b..de64d8a5fdfd 100644 --- a/net/netfilter/nf_conntrack_proto_icmp.c +++ b/net/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -25,11 +25,6 @@ | |||
25 | 25 | ||
26 | static const unsigned int nf_ct_icmp_timeout = 30*HZ; | 26 | static const unsigned int nf_ct_icmp_timeout = 30*HZ; |
27 | 27 | ||
28 | static inline struct nf_icmp_net *icmp_pernet(struct net *net) | ||
29 | { | ||
30 | return &net->ct.nf_ct_proto.icmp; | ||
31 | } | ||
32 | |||
33 | static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, | 28 | static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, |
34 | struct net *net, struct nf_conntrack_tuple *tuple) | 29 | struct net *net, struct nf_conntrack_tuple *tuple) |
35 | { | 30 | { |
@@ -103,7 +98,7 @@ static int icmp_packet(struct nf_conn *ct, | |||
103 | } | 98 | } |
104 | 99 | ||
105 | if (!timeout) | 100 | if (!timeout) |
106 | timeout = &icmp_pernet(nf_ct_net(ct))->timeout; | 101 | timeout = &nf_icmp_pernet(nf_ct_net(ct))->timeout; |
107 | 102 | ||
108 | nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); | 103 | nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); |
109 | return NF_ACCEPT; | 104 | return NF_ACCEPT; |
@@ -275,7 +270,7 @@ static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[], | |||
275 | struct net *net, void *data) | 270 | struct net *net, void *data) |
276 | { | 271 | { |
277 | unsigned int *timeout = data; | 272 | unsigned int *timeout = data; |
278 | struct nf_icmp_net *in = icmp_pernet(net); | 273 | struct nf_icmp_net *in = nf_icmp_pernet(net); |
279 | 274 | ||
280 | if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) { | 275 | if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) { |
281 | if (!timeout) | 276 | if (!timeout) |
@@ -337,7 +332,7 @@ static int icmp_kmemdup_sysctl_table(struct nf_proto_net *pn, | |||
337 | 332 | ||
338 | static int icmp_init_net(struct net *net) | 333 | static int icmp_init_net(struct net *net) |
339 | { | 334 | { |
340 | struct nf_icmp_net *in = icmp_pernet(net); | 335 | struct nf_icmp_net *in = nf_icmp_pernet(net); |
341 | struct nf_proto_net *pn = &in->pn; | 336 | struct nf_proto_net *pn = &in->pn; |
342 | 337 | ||
343 | in->timeout = nf_ct_icmp_timeout; | 338 | in->timeout = nf_ct_icmp_timeout; |
diff --git a/net/netfilter/nf_conntrack_proto_icmpv6.c b/net/netfilter/nf_conntrack_proto_icmpv6.c index 378618feed5d..a15eefb8e317 100644 --- a/net/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -30,11 +30,6 @@ | |||
30 | 30 | ||
31 | static const unsigned int nf_ct_icmpv6_timeout = 30*HZ; | 31 | static const unsigned int nf_ct_icmpv6_timeout = 30*HZ; |
32 | 32 | ||
33 | static inline struct nf_icmp_net *icmpv6_pernet(struct net *net) | ||
34 | { | ||
35 | return &net->ct.nf_ct_proto.icmpv6; | ||
36 | } | ||
37 | |||
38 | static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb, | 33 | static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb, |
39 | unsigned int dataoff, | 34 | unsigned int dataoff, |
40 | struct net *net, | 35 | struct net *net, |
@@ -87,7 +82,7 @@ static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple, | |||
87 | 82 | ||
88 | static unsigned int *icmpv6_get_timeouts(struct net *net) | 83 | static unsigned int *icmpv6_get_timeouts(struct net *net) |
89 | { | 84 | { |
90 | return &icmpv6_pernet(net)->timeout; | 85 | return &nf_icmpv6_pernet(net)->timeout; |
91 | } | 86 | } |
92 | 87 | ||
93 | /* Returns verdict for packet, or -1 for invalid. */ | 88 | /* Returns verdict for packet, or -1 for invalid. */ |
@@ -286,7 +281,7 @@ static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[], | |||
286 | struct net *net, void *data) | 281 | struct net *net, void *data) |
287 | { | 282 | { |
288 | unsigned int *timeout = data; | 283 | unsigned int *timeout = data; |
289 | struct nf_icmp_net *in = icmpv6_pernet(net); | 284 | struct nf_icmp_net *in = nf_icmpv6_pernet(net); |
290 | 285 | ||
291 | if (!timeout) | 286 | if (!timeout) |
292 | timeout = icmpv6_get_timeouts(net); | 287 | timeout = icmpv6_get_timeouts(net); |
@@ -348,7 +343,7 @@ static int icmpv6_kmemdup_sysctl_table(struct nf_proto_net *pn, | |||
348 | 343 | ||
349 | static int icmpv6_init_net(struct net *net) | 344 | static int icmpv6_init_net(struct net *net) |
350 | { | 345 | { |
351 | struct nf_icmp_net *in = icmpv6_pernet(net); | 346 | struct nf_icmp_net *in = nf_icmpv6_pernet(net); |
352 | struct nf_proto_net *pn = &in->pn; | 347 | struct nf_proto_net *pn = &in->pn; |
353 | 348 | ||
354 | in->timeout = nf_ct_icmpv6_timeout; | 349 | in->timeout = nf_ct_icmpv6_timeout; |
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 3d719d3eb9a3..d53e3e78f605 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -146,11 +146,6 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { | |||
146 | } | 146 | } |
147 | }; | 147 | }; |
148 | 148 | ||
149 | static inline struct nf_sctp_net *sctp_pernet(struct net *net) | ||
150 | { | ||
151 | return &net->ct.nf_ct_proto.sctp; | ||
152 | } | ||
153 | |||
154 | #ifdef CONFIG_NF_CONNTRACK_PROCFS | 149 | #ifdef CONFIG_NF_CONNTRACK_PROCFS |
155 | /* Print out the private part of the conntrack. */ | 150 | /* Print out the private part of the conntrack. */ |
156 | static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct) | 151 | static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct) |
@@ -480,7 +475,7 @@ static int sctp_packet(struct nf_conn *ct, | |||
480 | 475 | ||
481 | timeouts = nf_ct_timeout_lookup(ct); | 476 | timeouts = nf_ct_timeout_lookup(ct); |
482 | if (!timeouts) | 477 | if (!timeouts) |
483 | timeouts = sctp_pernet(nf_ct_net(ct))->timeouts; | 478 | timeouts = nf_sctp_pernet(nf_ct_net(ct))->timeouts; |
484 | 479 | ||
485 | nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]); | 480 | nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]); |
486 | 481 | ||
@@ -599,7 +594,7 @@ static int sctp_timeout_nlattr_to_obj(struct nlattr *tb[], | |||
599 | struct net *net, void *data) | 594 | struct net *net, void *data) |
600 | { | 595 | { |
601 | unsigned int *timeouts = data; | 596 | unsigned int *timeouts = data; |
602 | struct nf_sctp_net *sn = sctp_pernet(net); | 597 | struct nf_sctp_net *sn = nf_sctp_pernet(net); |
603 | int i; | 598 | int i; |
604 | 599 | ||
605 | /* set default SCTP timeouts. */ | 600 | /* set default SCTP timeouts. */ |
@@ -736,7 +731,7 @@ static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn, | |||
736 | 731 | ||
737 | static int sctp_init_net(struct net *net) | 732 | static int sctp_init_net(struct net *net) |
738 | { | 733 | { |
739 | struct nf_sctp_net *sn = sctp_pernet(net); | 734 | struct nf_sctp_net *sn = nf_sctp_pernet(net); |
740 | struct nf_proto_net *pn = &sn->pn; | 735 | struct nf_proto_net *pn = &sn->pn; |
741 | 736 | ||
742 | if (!pn->users) { | 737 | if (!pn->users) { |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 1bcf9984d45e..4dcbd51a8e97 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -272,11 +272,6 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { | |||
272 | } | 272 | } |
273 | }; | 273 | }; |
274 | 274 | ||
275 | static inline struct nf_tcp_net *tcp_pernet(struct net *net) | ||
276 | { | ||
277 | return &net->ct.nf_ct_proto.tcp; | ||
278 | } | ||
279 | |||
280 | #ifdef CONFIG_NF_CONNTRACK_PROCFS | 275 | #ifdef CONFIG_NF_CONNTRACK_PROCFS |
281 | /* Print out the private part of the conntrack. */ | 276 | /* Print out the private part of the conntrack. */ |
282 | static void tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct) | 277 | static void tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct) |
@@ -475,7 +470,7 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
475 | const struct tcphdr *tcph) | 470 | const struct tcphdr *tcph) |
476 | { | 471 | { |
477 | struct net *net = nf_ct_net(ct); | 472 | struct net *net = nf_ct_net(ct); |
478 | struct nf_tcp_net *tn = tcp_pernet(net); | 473 | struct nf_tcp_net *tn = nf_tcp_pernet(net); |
479 | struct ip_ct_tcp_state *sender = &state->seen[dir]; | 474 | struct ip_ct_tcp_state *sender = &state->seen[dir]; |
480 | struct ip_ct_tcp_state *receiver = &state->seen[!dir]; | 475 | struct ip_ct_tcp_state *receiver = &state->seen[!dir]; |
481 | const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; | 476 | const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; |
@@ -767,7 +762,7 @@ static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
767 | { | 762 | { |
768 | enum tcp_conntrack new_state; | 763 | enum tcp_conntrack new_state; |
769 | struct net *net = nf_ct_net(ct); | 764 | struct net *net = nf_ct_net(ct); |
770 | const struct nf_tcp_net *tn = tcp_pernet(net); | 765 | const struct nf_tcp_net *tn = nf_tcp_pernet(net); |
771 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0]; | 766 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0]; |
772 | const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1]; | 767 | const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1]; |
773 | 768 | ||
@@ -841,7 +836,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
841 | const struct nf_hook_state *state) | 836 | const struct nf_hook_state *state) |
842 | { | 837 | { |
843 | struct net *net = nf_ct_net(ct); | 838 | struct net *net = nf_ct_net(ct); |
844 | struct nf_tcp_net *tn = tcp_pernet(net); | 839 | struct nf_tcp_net *tn = nf_tcp_pernet(net); |
845 | struct nf_conntrack_tuple *tuple; | 840 | struct nf_conntrack_tuple *tuple; |
846 | enum tcp_conntrack new_state, old_state; | 841 | enum tcp_conntrack new_state, old_state; |
847 | unsigned int index, *timeouts; | 842 | unsigned int index, *timeouts; |
@@ -1283,7 +1278,7 @@ static unsigned int tcp_nlattr_tuple_size(void) | |||
1283 | static int tcp_timeout_nlattr_to_obj(struct nlattr *tb[], | 1278 | static int tcp_timeout_nlattr_to_obj(struct nlattr *tb[], |
1284 | struct net *net, void *data) | 1279 | struct net *net, void *data) |
1285 | { | 1280 | { |
1286 | struct nf_tcp_net *tn = tcp_pernet(net); | 1281 | struct nf_tcp_net *tn = nf_tcp_pernet(net); |
1287 | unsigned int *timeouts = data; | 1282 | unsigned int *timeouts = data; |
1288 | int i; | 1283 | int i; |
1289 | 1284 | ||
@@ -1508,7 +1503,7 @@ static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn, | |||
1508 | 1503 | ||
1509 | static int tcp_init_net(struct net *net) | 1504 | static int tcp_init_net(struct net *net) |
1510 | { | 1505 | { |
1511 | struct nf_tcp_net *tn = tcp_pernet(net); | 1506 | struct nf_tcp_net *tn = nf_tcp_pernet(net); |
1512 | struct nf_proto_net *pn = &tn->pn; | 1507 | struct nf_proto_net *pn = &tn->pn; |
1513 | 1508 | ||
1514 | if (!pn->users) { | 1509 | if (!pn->users) { |
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index a7aa70370913..c879d8d78cfd 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c | |||
@@ -32,14 +32,9 @@ static const unsigned int udp_timeouts[UDP_CT_MAX] = { | |||
32 | [UDP_CT_REPLIED] = 180*HZ, | 32 | [UDP_CT_REPLIED] = 180*HZ, |
33 | }; | 33 | }; |
34 | 34 | ||
35 | static inline struct nf_udp_net *udp_pernet(struct net *net) | ||
36 | { | ||
37 | return &net->ct.nf_ct_proto.udp; | ||
38 | } | ||
39 | |||
40 | static unsigned int *udp_get_timeouts(struct net *net) | 35 | static unsigned int *udp_get_timeouts(struct net *net) |
41 | { | 36 | { |
42 | return udp_pernet(net)->timeouts; | 37 | return nf_udp_pernet(net)->timeouts; |
43 | } | 38 | } |
44 | 39 | ||
45 | static void udp_error_log(const struct sk_buff *skb, | 40 | static void udp_error_log(const struct sk_buff *skb, |
@@ -212,7 +207,7 @@ static int udp_timeout_nlattr_to_obj(struct nlattr *tb[], | |||
212 | struct net *net, void *data) | 207 | struct net *net, void *data) |
213 | { | 208 | { |
214 | unsigned int *timeouts = data; | 209 | unsigned int *timeouts = data; |
215 | struct nf_udp_net *un = udp_pernet(net); | 210 | struct nf_udp_net *un = nf_udp_pernet(net); |
216 | 211 | ||
217 | if (!timeouts) | 212 | if (!timeouts) |
218 | timeouts = un->timeouts; | 213 | timeouts = un->timeouts; |
@@ -292,7 +287,7 @@ static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn, | |||
292 | 287 | ||
293 | static int udp_init_net(struct net *net) | 288 | static int udp_init_net(struct net *net) |
294 | { | 289 | { |
295 | struct nf_udp_net *un = udp_pernet(net); | 290 | struct nf_udp_net *un = nf_udp_pernet(net); |
296 | struct nf_proto_net *pn = &un->pn; | 291 | struct nf_proto_net *pn = &un->pn; |
297 | 292 | ||
298 | if (!pn->users) { | 293 | if (!pn->users) { |
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index e7a50af1b3d6..a518eb162344 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c | |||
@@ -382,7 +382,8 @@ err: | |||
382 | static int | 382 | static int |
383 | cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, | 383 | cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, |
384 | u32 seq, u32 type, int event, u16 l3num, | 384 | u32 seq, u32 type, int event, u16 l3num, |
385 | const struct nf_conntrack_l4proto *l4proto) | 385 | const struct nf_conntrack_l4proto *l4proto, |
386 | const unsigned int *timeouts) | ||
386 | { | 387 | { |
387 | struct nlmsghdr *nlh; | 388 | struct nlmsghdr *nlh; |
388 | struct nfgenmsg *nfmsg; | 389 | struct nfgenmsg *nfmsg; |
@@ -408,7 +409,7 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, | |||
408 | if (!nest_parms) | 409 | if (!nest_parms) |
409 | goto nla_put_failure; | 410 | goto nla_put_failure; |
410 | 411 | ||
411 | ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, NULL); | 412 | ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts); |
412 | if (ret < 0) | 413 | if (ret < 0) |
413 | goto nla_put_failure; | 414 | goto nla_put_failure; |
414 | 415 | ||
@@ -430,6 +431,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, | |||
430 | struct netlink_ext_ack *extack) | 431 | struct netlink_ext_ack *extack) |
431 | { | 432 | { |
432 | const struct nf_conntrack_l4proto *l4proto; | 433 | const struct nf_conntrack_l4proto *l4proto; |
434 | unsigned int *timeouts = NULL; | ||
433 | struct sk_buff *skb2; | 435 | struct sk_buff *skb2; |
434 | int ret, err; | 436 | int ret, err; |
435 | __u16 l3num; | 437 | __u16 l3num; |
@@ -442,12 +444,44 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, | |||
442 | l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); | 444 | l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); |
443 | l4proto = nf_ct_l4proto_find_get(l4num); | 445 | l4proto = nf_ct_l4proto_find_get(l4num); |
444 | 446 | ||
445 | /* This protocol is not supported, skip. */ | 447 | err = -EOPNOTSUPP; |
446 | if (l4proto->l4proto != l4num) { | 448 | if (l4proto->l4proto != l4num) |
447 | err = -EOPNOTSUPP; | ||
448 | goto err; | 449 | goto err; |
450 | |||
451 | switch (l4proto->l4proto) { | ||
452 | case IPPROTO_ICMP: | ||
453 | timeouts = &nf_icmp_pernet(net)->timeout; | ||
454 | break; | ||
455 | case IPPROTO_TCP: | ||
456 | timeouts = nf_tcp_pernet(net)->timeouts; | ||
457 | break; | ||
458 | case IPPROTO_UDP: | ||
459 | timeouts = nf_udp_pernet(net)->timeouts; | ||
460 | break; | ||
461 | case IPPROTO_DCCP: | ||
462 | #ifdef CONFIG_NF_CT_PROTO_DCCP | ||
463 | timeouts = nf_dccp_pernet(net)->dccp_timeout; | ||
464 | #endif | ||
465 | break; | ||
466 | case IPPROTO_ICMPV6: | ||
467 | timeouts = &nf_icmpv6_pernet(net)->timeout; | ||
468 | break; | ||
469 | case IPPROTO_SCTP: | ||
470 | #ifdef CONFIG_NF_CT_PROTO_SCTP | ||
471 | timeouts = nf_sctp_pernet(net)->timeouts; | ||
472 | #endif | ||
473 | break; | ||
474 | case 255: | ||
475 | timeouts = &nf_generic_pernet(net)->timeout; | ||
476 | break; | ||
477 | default: | ||
478 | WARN_ON_ONCE(1); | ||
479 | break; | ||
449 | } | 480 | } |
450 | 481 | ||
482 | if (!timeouts) | ||
483 | goto err; | ||
484 | |||
451 | skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 485 | skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
452 | if (skb2 == NULL) { | 486 | if (skb2 == NULL) { |
453 | err = -ENOMEM; | 487 | err = -ENOMEM; |
@@ -458,8 +492,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, | |||
458 | nlh->nlmsg_seq, | 492 | nlh->nlmsg_seq, |
459 | NFNL_MSG_TYPE(nlh->nlmsg_type), | 493 | NFNL_MSG_TYPE(nlh->nlmsg_type), |
460 | IPCTNL_MSG_TIMEOUT_DEFAULT_SET, | 494 | IPCTNL_MSG_TIMEOUT_DEFAULT_SET, |
461 | l3num, | 495 | l3num, l4proto, timeouts); |
462 | l4proto); | ||
463 | if (ret <= 0) { | 496 | if (ret <= 0) { |
464 | kfree_skb(skb2); | 497 | kfree_skb(skb2); |
465 | err = -ENOMEM; | 498 | err = -ENOMEM; |
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 768292eac2a4..9d0ede474224 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
@@ -54,9 +54,11 @@ static bool nft_xt_put(struct nft_xt *xt) | |||
54 | return false; | 54 | return false; |
55 | } | 55 | } |
56 | 56 | ||
57 | static int nft_compat_chain_validate_dependency(const char *tablename, | 57 | static int nft_compat_chain_validate_dependency(const struct nft_ctx *ctx, |
58 | const struct nft_chain *chain) | 58 | const char *tablename) |
59 | { | 59 | { |
60 | enum nft_chain_types type = NFT_CHAIN_T_DEFAULT; | ||
61 | const struct nft_chain *chain = ctx->chain; | ||
60 | const struct nft_base_chain *basechain; | 62 | const struct nft_base_chain *basechain; |
61 | 63 | ||
62 | if (!tablename || | 64 | if (!tablename || |
@@ -64,9 +66,12 @@ static int nft_compat_chain_validate_dependency(const char *tablename, | |||
64 | return 0; | 66 | return 0; |
65 | 67 | ||
66 | basechain = nft_base_chain(chain); | 68 | basechain = nft_base_chain(chain); |
67 | if (strcmp(tablename, "nat") == 0 && | 69 | if (strcmp(tablename, "nat") == 0) { |
68 | basechain->type->type != NFT_CHAIN_T_NAT) | 70 | if (ctx->family != NFPROTO_BRIDGE) |
69 | return -EINVAL; | 71 | type = NFT_CHAIN_T_NAT; |
72 | if (basechain->type->type != type) | ||
73 | return -EINVAL; | ||
74 | } | ||
70 | 75 | ||
71 | return 0; | 76 | return 0; |
72 | } | 77 | } |
@@ -342,8 +347,7 @@ static int nft_target_validate(const struct nft_ctx *ctx, | |||
342 | if (target->hooks && !(hook_mask & target->hooks)) | 347 | if (target->hooks && !(hook_mask & target->hooks)) |
343 | return -EINVAL; | 348 | return -EINVAL; |
344 | 349 | ||
345 | ret = nft_compat_chain_validate_dependency(target->table, | 350 | ret = nft_compat_chain_validate_dependency(ctx, target->table); |
346 | ctx->chain); | ||
347 | if (ret < 0) | 351 | if (ret < 0) |
348 | return ret; | 352 | return ret; |
349 | } | 353 | } |
@@ -590,8 +594,7 @@ static int nft_match_validate(const struct nft_ctx *ctx, | |||
590 | if (match->hooks && !(hook_mask & match->hooks)) | 594 | if (match->hooks && !(hook_mask & match->hooks)) |
591 | return -EINVAL; | 595 | return -EINVAL; |
592 | 596 | ||
593 | ret = nft_compat_chain_validate_dependency(match->table, | 597 | ret = nft_compat_chain_validate_dependency(ctx, match->table); |
594 | ctx->chain); | ||
595 | if (ret < 0) | 598 | if (ret < 0) |
596 | return ret; | 599 | return ret; |
597 | } | 600 | } |
diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c index 649d1700ec5b..3cc1b3dc3c3c 100644 --- a/net/netfilter/nft_numgen.c +++ b/net/netfilter/nft_numgen.c | |||
@@ -24,7 +24,6 @@ struct nft_ng_inc { | |||
24 | u32 modulus; | 24 | u32 modulus; |
25 | atomic_t counter; | 25 | atomic_t counter; |
26 | u32 offset; | 26 | u32 offset; |
27 | struct nft_set *map; | ||
28 | }; | 27 | }; |
29 | 28 | ||
30 | static u32 nft_ng_inc_gen(struct nft_ng_inc *priv) | 29 | static u32 nft_ng_inc_gen(struct nft_ng_inc *priv) |
@@ -48,34 +47,11 @@ static void nft_ng_inc_eval(const struct nft_expr *expr, | |||
48 | regs->data[priv->dreg] = nft_ng_inc_gen(priv); | 47 | regs->data[priv->dreg] = nft_ng_inc_gen(priv); |
49 | } | 48 | } |
50 | 49 | ||
51 | static void nft_ng_inc_map_eval(const struct nft_expr *expr, | ||
52 | struct nft_regs *regs, | ||
53 | const struct nft_pktinfo *pkt) | ||
54 | { | ||
55 | struct nft_ng_inc *priv = nft_expr_priv(expr); | ||
56 | const struct nft_set *map = priv->map; | ||
57 | const struct nft_set_ext *ext; | ||
58 | u32 result; | ||
59 | bool found; | ||
60 | |||
61 | result = nft_ng_inc_gen(priv); | ||
62 | found = map->ops->lookup(nft_net(pkt), map, &result, &ext); | ||
63 | |||
64 | if (!found) | ||
65 | return; | ||
66 | |||
67 | nft_data_copy(®s->data[priv->dreg], | ||
68 | nft_set_ext_data(ext), map->dlen); | ||
69 | } | ||
70 | |||
71 | static const struct nla_policy nft_ng_policy[NFTA_NG_MAX + 1] = { | 50 | static const struct nla_policy nft_ng_policy[NFTA_NG_MAX + 1] = { |
72 | [NFTA_NG_DREG] = { .type = NLA_U32 }, | 51 | [NFTA_NG_DREG] = { .type = NLA_U32 }, |
73 | [NFTA_NG_MODULUS] = { .type = NLA_U32 }, | 52 | [NFTA_NG_MODULUS] = { .type = NLA_U32 }, |
74 | [NFTA_NG_TYPE] = { .type = NLA_U32 }, | 53 | [NFTA_NG_TYPE] = { .type = NLA_U32 }, |
75 | [NFTA_NG_OFFSET] = { .type = NLA_U32 }, | 54 | [NFTA_NG_OFFSET] = { .type = NLA_U32 }, |
76 | [NFTA_NG_SET_NAME] = { .type = NLA_STRING, | ||
77 | .len = NFT_SET_MAXNAMELEN - 1 }, | ||
78 | [NFTA_NG_SET_ID] = { .type = NLA_U32 }, | ||
79 | }; | 55 | }; |
80 | 56 | ||
81 | static int nft_ng_inc_init(const struct nft_ctx *ctx, | 57 | static int nft_ng_inc_init(const struct nft_ctx *ctx, |
@@ -101,22 +77,6 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx, | |||
101 | NFT_DATA_VALUE, sizeof(u32)); | 77 | NFT_DATA_VALUE, sizeof(u32)); |
102 | } | 78 | } |
103 | 79 | ||
104 | static int nft_ng_inc_map_init(const struct nft_ctx *ctx, | ||
105 | const struct nft_expr *expr, | ||
106 | const struct nlattr * const tb[]) | ||
107 | { | ||
108 | struct nft_ng_inc *priv = nft_expr_priv(expr); | ||
109 | u8 genmask = nft_genmask_next(ctx->net); | ||
110 | |||
111 | nft_ng_inc_init(ctx, expr, tb); | ||
112 | |||
113 | priv->map = nft_set_lookup_global(ctx->net, ctx->table, | ||
114 | tb[NFTA_NG_SET_NAME], | ||
115 | tb[NFTA_NG_SET_ID], genmask); | ||
116 | |||
117 | return PTR_ERR_OR_ZERO(priv->map); | ||
118 | } | ||
119 | |||
120 | static int nft_ng_dump(struct sk_buff *skb, enum nft_registers dreg, | 80 | static int nft_ng_dump(struct sk_buff *skb, enum nft_registers dreg, |
121 | u32 modulus, enum nft_ng_types type, u32 offset) | 81 | u32 modulus, enum nft_ng_types type, u32 offset) |
122 | { | 82 | { |
@@ -143,27 +103,10 @@ static int nft_ng_inc_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
143 | priv->offset); | 103 | priv->offset); |
144 | } | 104 | } |
145 | 105 | ||
146 | static int nft_ng_inc_map_dump(struct sk_buff *skb, | ||
147 | const struct nft_expr *expr) | ||
148 | { | ||
149 | const struct nft_ng_inc *priv = nft_expr_priv(expr); | ||
150 | |||
151 | if (nft_ng_dump(skb, priv->dreg, priv->modulus, | ||
152 | NFT_NG_INCREMENTAL, priv->offset) || | ||
153 | nla_put_string(skb, NFTA_NG_SET_NAME, priv->map->name)) | ||
154 | goto nla_put_failure; | ||
155 | |||
156 | return 0; | ||
157 | |||
158 | nla_put_failure: | ||
159 | return -1; | ||
160 | } | ||
161 | |||
162 | struct nft_ng_random { | 106 | struct nft_ng_random { |
163 | enum nft_registers dreg:8; | 107 | enum nft_registers dreg:8; |
164 | u32 modulus; | 108 | u32 modulus; |
165 | u32 offset; | 109 | u32 offset; |
166 | struct nft_set *map; | ||
167 | }; | 110 | }; |
168 | 111 | ||
169 | static u32 nft_ng_random_gen(struct nft_ng_random *priv) | 112 | static u32 nft_ng_random_gen(struct nft_ng_random *priv) |
@@ -183,25 +126,6 @@ static void nft_ng_random_eval(const struct nft_expr *expr, | |||
183 | regs->data[priv->dreg] = nft_ng_random_gen(priv); | 126 | regs->data[priv->dreg] = nft_ng_random_gen(priv); |
184 | } | 127 | } |
185 | 128 | ||
186 | static void nft_ng_random_map_eval(const struct nft_expr *expr, | ||
187 | struct nft_regs *regs, | ||
188 | const struct nft_pktinfo *pkt) | ||
189 | { | ||
190 | struct nft_ng_random *priv = nft_expr_priv(expr); | ||
191 | const struct nft_set *map = priv->map; | ||
192 | const struct nft_set_ext *ext; | ||
193 | u32 result; | ||
194 | bool found; | ||
195 | |||
196 | result = nft_ng_random_gen(priv); | ||
197 | found = map->ops->lookup(nft_net(pkt), map, &result, &ext); | ||
198 | if (!found) | ||
199 | return; | ||
200 | |||
201 | nft_data_copy(®s->data[priv->dreg], | ||
202 | nft_set_ext_data(ext), map->dlen); | ||
203 | } | ||
204 | |||
205 | static int nft_ng_random_init(const struct nft_ctx *ctx, | 129 | static int nft_ng_random_init(const struct nft_ctx *ctx, |
206 | const struct nft_expr *expr, | 130 | const struct nft_expr *expr, |
207 | const struct nlattr * const tb[]) | 131 | const struct nlattr * const tb[]) |
@@ -226,21 +150,6 @@ static int nft_ng_random_init(const struct nft_ctx *ctx, | |||
226 | NFT_DATA_VALUE, sizeof(u32)); | 150 | NFT_DATA_VALUE, sizeof(u32)); |
227 | } | 151 | } |
228 | 152 | ||
229 | static int nft_ng_random_map_init(const struct nft_ctx *ctx, | ||
230 | const struct nft_expr *expr, | ||
231 | const struct nlattr * const tb[]) | ||
232 | { | ||
233 | struct nft_ng_random *priv = nft_expr_priv(expr); | ||
234 | u8 genmask = nft_genmask_next(ctx->net); | ||
235 | |||
236 | nft_ng_random_init(ctx, expr, tb); | ||
237 | priv->map = nft_set_lookup_global(ctx->net, ctx->table, | ||
238 | tb[NFTA_NG_SET_NAME], | ||
239 | tb[NFTA_NG_SET_ID], genmask); | ||
240 | |||
241 | return PTR_ERR_OR_ZERO(priv->map); | ||
242 | } | ||
243 | |||
244 | static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr *expr) | 153 | static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr *expr) |
245 | { | 154 | { |
246 | const struct nft_ng_random *priv = nft_expr_priv(expr); | 155 | const struct nft_ng_random *priv = nft_expr_priv(expr); |
@@ -249,22 +158,6 @@ static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
249 | priv->offset); | 158 | priv->offset); |
250 | } | 159 | } |
251 | 160 | ||
252 | static int nft_ng_random_map_dump(struct sk_buff *skb, | ||
253 | const struct nft_expr *expr) | ||
254 | { | ||
255 | const struct nft_ng_random *priv = nft_expr_priv(expr); | ||
256 | |||
257 | if (nft_ng_dump(skb, priv->dreg, priv->modulus, | ||
258 | NFT_NG_RANDOM, priv->offset) || | ||
259 | nla_put_string(skb, NFTA_NG_SET_NAME, priv->map->name)) | ||
260 | goto nla_put_failure; | ||
261 | |||
262 | return 0; | ||
263 | |||
264 | nla_put_failure: | ||
265 | return -1; | ||
266 | } | ||
267 | |||
268 | static struct nft_expr_type nft_ng_type; | 161 | static struct nft_expr_type nft_ng_type; |
269 | static const struct nft_expr_ops nft_ng_inc_ops = { | 162 | static const struct nft_expr_ops nft_ng_inc_ops = { |
270 | .type = &nft_ng_type, | 163 | .type = &nft_ng_type, |
@@ -274,14 +167,6 @@ static const struct nft_expr_ops nft_ng_inc_ops = { | |||
274 | .dump = nft_ng_inc_dump, | 167 | .dump = nft_ng_inc_dump, |
275 | }; | 168 | }; |
276 | 169 | ||
277 | static const struct nft_expr_ops nft_ng_inc_map_ops = { | ||
278 | .type = &nft_ng_type, | ||
279 | .size = NFT_EXPR_SIZE(sizeof(struct nft_ng_inc)), | ||
280 | .eval = nft_ng_inc_map_eval, | ||
281 | .init = nft_ng_inc_map_init, | ||
282 | .dump = nft_ng_inc_map_dump, | ||
283 | }; | ||
284 | |||
285 | static const struct nft_expr_ops nft_ng_random_ops = { | 170 | static const struct nft_expr_ops nft_ng_random_ops = { |
286 | .type = &nft_ng_type, | 171 | .type = &nft_ng_type, |
287 | .size = NFT_EXPR_SIZE(sizeof(struct nft_ng_random)), | 172 | .size = NFT_EXPR_SIZE(sizeof(struct nft_ng_random)), |
@@ -290,14 +175,6 @@ static const struct nft_expr_ops nft_ng_random_ops = { | |||
290 | .dump = nft_ng_random_dump, | 175 | .dump = nft_ng_random_dump, |
291 | }; | 176 | }; |
292 | 177 | ||
293 | static const struct nft_expr_ops nft_ng_random_map_ops = { | ||
294 | .type = &nft_ng_type, | ||
295 | .size = NFT_EXPR_SIZE(sizeof(struct nft_ng_random)), | ||
296 | .eval = nft_ng_random_map_eval, | ||
297 | .init = nft_ng_random_map_init, | ||
298 | .dump = nft_ng_random_map_dump, | ||
299 | }; | ||
300 | |||
301 | static const struct nft_expr_ops * | 178 | static const struct nft_expr_ops * |
302 | nft_ng_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) | 179 | nft_ng_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) |
303 | { | 180 | { |
@@ -312,12 +189,8 @@ nft_ng_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) | |||
312 | 189 | ||
313 | switch (type) { | 190 | switch (type) { |
314 | case NFT_NG_INCREMENTAL: | 191 | case NFT_NG_INCREMENTAL: |
315 | if (tb[NFTA_NG_SET_NAME]) | ||
316 | return &nft_ng_inc_map_ops; | ||
317 | return &nft_ng_inc_ops; | 192 | return &nft_ng_inc_ops; |
318 | case NFT_NG_RANDOM: | 193 | case NFT_NG_RANDOM: |
319 | if (tb[NFTA_NG_SET_NAME]) | ||
320 | return &nft_ng_random_map_ops; | ||
321 | return &nft_ng_random_ops; | 194 | return &nft_ng_random_ops; |
322 | } | 195 | } |
323 | 196 | ||
diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c index ca5e5d8c5ef8..b13618c764ec 100644 --- a/net/netfilter/nft_osf.c +++ b/net/netfilter/nft_osf.c | |||
@@ -50,7 +50,7 @@ static int nft_osf_init(const struct nft_ctx *ctx, | |||
50 | int err; | 50 | int err; |
51 | u8 ttl; | 51 | u8 ttl; |
52 | 52 | ||
53 | if (nla_get_u8(tb[NFTA_OSF_TTL])) { | 53 | if (tb[NFTA_OSF_TTL]) { |
54 | ttl = nla_get_u8(tb[NFTA_OSF_TTL]); | 54 | ttl = nla_get_u8(tb[NFTA_OSF_TTL]); |
55 | if (ttl > 2) | 55 | if (ttl > 2) |
56 | return -EINVAL; | 56 | return -EINVAL; |
diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c index c6acfc2d9c84..eb4cbd244c3d 100644 --- a/net/netfilter/xt_IDLETIMER.c +++ b/net/netfilter/xt_IDLETIMER.c | |||
@@ -114,6 +114,22 @@ static void idletimer_tg_expired(struct timer_list *t) | |||
114 | schedule_work(&timer->work); | 114 | schedule_work(&timer->work); |
115 | } | 115 | } |
116 | 116 | ||
117 | static int idletimer_check_sysfs_name(const char *name, unsigned int size) | ||
118 | { | ||
119 | int ret; | ||
120 | |||
121 | ret = xt_check_proc_name(name, size); | ||
122 | if (ret < 0) | ||
123 | return ret; | ||
124 | |||
125 | if (!strcmp(name, "power") || | ||
126 | !strcmp(name, "subsystem") || | ||
127 | !strcmp(name, "uevent")) | ||
128 | return -EINVAL; | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
117 | static int idletimer_tg_create(struct idletimer_tg_info *info) | 133 | static int idletimer_tg_create(struct idletimer_tg_info *info) |
118 | { | 134 | { |
119 | int ret; | 135 | int ret; |
@@ -124,6 +140,10 @@ static int idletimer_tg_create(struct idletimer_tg_info *info) | |||
124 | goto out; | 140 | goto out; |
125 | } | 141 | } |
126 | 142 | ||
143 | ret = idletimer_check_sysfs_name(info->label, sizeof(info->label)); | ||
144 | if (ret < 0) | ||
145 | goto out_free_timer; | ||
146 | |||
127 | sysfs_attr_init(&info->timer->attr.attr); | 147 | sysfs_attr_init(&info->timer->attr.attr); |
128 | info->timer->attr.attr.name = kstrdup(info->label, GFP_KERNEL); | 148 | info->timer->attr.attr.name = kstrdup(info->label, GFP_KERNEL); |
129 | if (!info->timer->attr.attr.name) { | 149 | if (!info->timer->attr.attr.name) { |
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 6bec37ab4472..a4660c48ff01 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c | |||
@@ -1203,7 +1203,8 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key, | |||
1203 | &info->labels.mask); | 1203 | &info->labels.mask); |
1204 | if (err) | 1204 | if (err) |
1205 | return err; | 1205 | return err; |
1206 | } else if (labels_nonzero(&info->labels.mask)) { | 1206 | } else if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && |
1207 | labels_nonzero(&info->labels.mask)) { | ||
1207 | err = ovs_ct_set_labels(ct, key, &info->labels.value, | 1208 | err = ovs_ct_set_labels(ct, key, &info->labels.value, |
1208 | &info->labels.mask); | 1209 | &info->labels.mask); |
1209 | if (err) | 1210 | if (err) |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 382196e57a26..bc628acf4f4f 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
@@ -611,6 +611,7 @@ struct rxrpc_call { | |||
611 | * not hard-ACK'd packet follows this. | 611 | * not hard-ACK'd packet follows this. |
612 | */ | 612 | */ |
613 | rxrpc_seq_t tx_top; /* Highest Tx slot allocated. */ | 613 | rxrpc_seq_t tx_top; /* Highest Tx slot allocated. */ |
614 | u16 tx_backoff; /* Delay to insert due to Tx failure */ | ||
614 | 615 | ||
615 | /* TCP-style slow-start congestion control [RFC5681]. Since the SMSS | 616 | /* TCP-style slow-start congestion control [RFC5681]. Since the SMSS |
616 | * is fixed, we keep these numbers in terms of segments (ie. DATA | 617 | * is fixed, we keep these numbers in terms of segments (ie. DATA |
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c index 8e7434e92097..468efc3660c0 100644 --- a/net/rxrpc/call_event.c +++ b/net/rxrpc/call_event.c | |||
@@ -123,6 +123,7 @@ static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, | |||
123 | else | 123 | else |
124 | ack_at = expiry; | 124 | ack_at = expiry; |
125 | 125 | ||
126 | ack_at += READ_ONCE(call->tx_backoff); | ||
126 | ack_at += now; | 127 | ack_at += now; |
127 | if (time_before(ack_at, call->ack_at)) { | 128 | if (time_before(ack_at, call->ack_at)) { |
128 | WRITE_ONCE(call->ack_at, ack_at); | 129 | WRITE_ONCE(call->ack_at, ack_at); |
@@ -311,6 +312,7 @@ void rxrpc_process_call(struct work_struct *work) | |||
311 | container_of(work, struct rxrpc_call, processor); | 312 | container_of(work, struct rxrpc_call, processor); |
312 | rxrpc_serial_t *send_ack; | 313 | rxrpc_serial_t *send_ack; |
313 | unsigned long now, next, t; | 314 | unsigned long now, next, t; |
315 | unsigned int iterations = 0; | ||
314 | 316 | ||
315 | rxrpc_see_call(call); | 317 | rxrpc_see_call(call); |
316 | 318 | ||
@@ -319,6 +321,11 @@ void rxrpc_process_call(struct work_struct *work) | |||
319 | call->debug_id, rxrpc_call_states[call->state], call->events); | 321 | call->debug_id, rxrpc_call_states[call->state], call->events); |
320 | 322 | ||
321 | recheck_state: | 323 | recheck_state: |
324 | /* Limit the number of times we do this before returning to the manager */ | ||
325 | iterations++; | ||
326 | if (iterations > 5) | ||
327 | goto requeue; | ||
328 | |||
322 | if (test_and_clear_bit(RXRPC_CALL_EV_ABORT, &call->events)) { | 329 | if (test_and_clear_bit(RXRPC_CALL_EV_ABORT, &call->events)) { |
323 | rxrpc_send_abort_packet(call); | 330 | rxrpc_send_abort_packet(call); |
324 | goto recheck_state; | 331 | goto recheck_state; |
@@ -447,13 +454,16 @@ recheck_state: | |||
447 | rxrpc_reduce_call_timer(call, next, now, rxrpc_timer_restart); | 454 | rxrpc_reduce_call_timer(call, next, now, rxrpc_timer_restart); |
448 | 455 | ||
449 | /* other events may have been raised since we started checking */ | 456 | /* other events may have been raised since we started checking */ |
450 | if (call->events && call->state < RXRPC_CALL_COMPLETE) { | 457 | if (call->events && call->state < RXRPC_CALL_COMPLETE) |
451 | __rxrpc_queue_call(call); | 458 | goto requeue; |
452 | goto out; | ||
453 | } | ||
454 | 459 | ||
455 | out_put: | 460 | out_put: |
456 | rxrpc_put_call(call, rxrpc_call_put); | 461 | rxrpc_put_call(call, rxrpc_call_put); |
457 | out: | 462 | out: |
458 | _leave(""); | 463 | _leave(""); |
464 | return; | ||
465 | |||
466 | requeue: | ||
467 | __rxrpc_queue_call(call); | ||
468 | goto out; | ||
459 | } | 469 | } |
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index 189418888839..736aa9281100 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c | |||
@@ -35,6 +35,21 @@ struct rxrpc_abort_buffer { | |||
35 | static const char rxrpc_keepalive_string[] = ""; | 35 | static const char rxrpc_keepalive_string[] = ""; |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * Increase Tx backoff on transmission failure and clear it on success. | ||
39 | */ | ||
40 | static void rxrpc_tx_backoff(struct rxrpc_call *call, int ret) | ||
41 | { | ||
42 | if (ret < 0) { | ||
43 | u16 tx_backoff = READ_ONCE(call->tx_backoff); | ||
44 | |||
45 | if (tx_backoff < HZ) | ||
46 | WRITE_ONCE(call->tx_backoff, tx_backoff + 1); | ||
47 | } else { | ||
48 | WRITE_ONCE(call->tx_backoff, 0); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | /* | ||
38 | * Arrange for a keepalive ping a certain time after we last transmitted. This | 53 | * Arrange for a keepalive ping a certain time after we last transmitted. This |
39 | * lets the far side know we're still interested in this call and helps keep | 54 | * lets the far side know we're still interested in this call and helps keep |
40 | * the route through any intervening firewall open. | 55 | * the route through any intervening firewall open. |
@@ -210,6 +225,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping, | |||
210 | else | 225 | else |
211 | trace_rxrpc_tx_packet(call->debug_id, &pkt->whdr, | 226 | trace_rxrpc_tx_packet(call->debug_id, &pkt->whdr, |
212 | rxrpc_tx_point_call_ack); | 227 | rxrpc_tx_point_call_ack); |
228 | rxrpc_tx_backoff(call, ret); | ||
213 | 229 | ||
214 | if (call->state < RXRPC_CALL_COMPLETE) { | 230 | if (call->state < RXRPC_CALL_COMPLETE) { |
215 | if (ret < 0) { | 231 | if (ret < 0) { |
@@ -218,7 +234,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping, | |||
218 | rxrpc_propose_ACK(call, pkt->ack.reason, | 234 | rxrpc_propose_ACK(call, pkt->ack.reason, |
219 | ntohs(pkt->ack.maxSkew), | 235 | ntohs(pkt->ack.maxSkew), |
220 | ntohl(pkt->ack.serial), | 236 | ntohl(pkt->ack.serial), |
221 | true, true, | 237 | false, true, |
222 | rxrpc_propose_ack_retry_tx); | 238 | rxrpc_propose_ack_retry_tx); |
223 | } else { | 239 | } else { |
224 | spin_lock_bh(&call->lock); | 240 | spin_lock_bh(&call->lock); |
@@ -300,7 +316,7 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call) | |||
300 | else | 316 | else |
301 | trace_rxrpc_tx_packet(call->debug_id, &pkt.whdr, | 317 | trace_rxrpc_tx_packet(call->debug_id, &pkt.whdr, |
302 | rxrpc_tx_point_call_abort); | 318 | rxrpc_tx_point_call_abort); |
303 | 319 | rxrpc_tx_backoff(call, ret); | |
304 | 320 | ||
305 | rxrpc_put_connection(conn); | 321 | rxrpc_put_connection(conn); |
306 | return ret; | 322 | return ret; |
@@ -413,6 +429,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb, | |||
413 | else | 429 | else |
414 | trace_rxrpc_tx_packet(call->debug_id, &whdr, | 430 | trace_rxrpc_tx_packet(call->debug_id, &whdr, |
415 | rxrpc_tx_point_call_data_nofrag); | 431 | rxrpc_tx_point_call_data_nofrag); |
432 | rxrpc_tx_backoff(call, ret); | ||
416 | if (ret == -EMSGSIZE) | 433 | if (ret == -EMSGSIZE) |
417 | goto send_fragmentable; | 434 | goto send_fragmentable; |
418 | 435 | ||
@@ -445,9 +462,18 @@ done: | |||
445 | rxrpc_reduce_call_timer(call, expect_rx_by, nowj, | 462 | rxrpc_reduce_call_timer(call, expect_rx_by, nowj, |
446 | rxrpc_timer_set_for_normal); | 463 | rxrpc_timer_set_for_normal); |
447 | } | 464 | } |
448 | } | ||
449 | 465 | ||
450 | rxrpc_set_keepalive(call); | 466 | rxrpc_set_keepalive(call); |
467 | } else { | ||
468 | /* Cancel the call if the initial transmission fails, | ||
469 | * particularly if that's due to network routing issues that | ||
470 | * aren't going away anytime soon. The layer above can arrange | ||
471 | * the retransmission. | ||
472 | */ | ||
473 | if (!test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags)) | ||
474 | rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, | ||
475 | RX_USER_ABORT, ret); | ||
476 | } | ||
451 | 477 | ||
452 | _leave(" = %d [%u]", ret, call->peer->maxdata); | 478 | _leave(" = %d [%u]", ret, call->peer->maxdata); |
453 | return ret; | 479 | return ret; |
@@ -506,6 +532,7 @@ send_fragmentable: | |||
506 | else | 532 | else |
507 | trace_rxrpc_tx_packet(call->debug_id, &whdr, | 533 | trace_rxrpc_tx_packet(call->debug_id, &whdr, |
508 | rxrpc_tx_point_call_data_frag); | 534 | rxrpc_tx_point_call_data_frag); |
535 | rxrpc_tx_backoff(call, ret); | ||
509 | 536 | ||
510 | up_write(&conn->params.local->defrag_sem); | 537 | up_write(&conn->params.local->defrag_sem); |
511 | goto done; | 538 | goto done; |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 1dae5f2b358f..c8cf4d10c435 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -258,7 +258,8 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, | |||
258 | if (is_redirect) { | 258 | if (is_redirect) { |
259 | skb2->tc_redirected = 1; | 259 | skb2->tc_redirected = 1; |
260 | skb2->tc_from_ingress = skb2->tc_at_ingress; | 260 | skb2->tc_from_ingress = skb2->tc_at_ingress; |
261 | 261 | if (skb2->tc_from_ingress) | |
262 | skb2->tstamp = 0; | ||
262 | /* let's the caller reinsert the packet, if possible */ | 263 | /* let's the caller reinsert the packet, if possible */ |
263 | if (use_reinsert) { | 264 | if (use_reinsert) { |
264 | res->ingress = want_ingress; | 265 | res->ingress = want_ingress; |
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 9aada2d0ef06..c6c327874abc 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c | |||
@@ -709,11 +709,23 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key, | |||
709 | struct netlink_ext_ack *extack) | 709 | struct netlink_ext_ack *extack) |
710 | { | 710 | { |
711 | const struct nlattr *nla_enc_key, *nla_opt_key, *nla_opt_msk = NULL; | 711 | const struct nlattr *nla_enc_key, *nla_opt_key, *nla_opt_msk = NULL; |
712 | int option_len, key_depth, msk_depth = 0; | 712 | int err, option_len, key_depth, msk_depth = 0; |
713 | |||
714 | err = nla_validate_nested(tb[TCA_FLOWER_KEY_ENC_OPTS], | ||
715 | TCA_FLOWER_KEY_ENC_OPTS_MAX, | ||
716 | enc_opts_policy, extack); | ||
717 | if (err) | ||
718 | return err; | ||
713 | 719 | ||
714 | nla_enc_key = nla_data(tb[TCA_FLOWER_KEY_ENC_OPTS]); | 720 | nla_enc_key = nla_data(tb[TCA_FLOWER_KEY_ENC_OPTS]); |
715 | 721 | ||
716 | if (tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]) { | 722 | if (tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]) { |
723 | err = nla_validate_nested(tb[TCA_FLOWER_KEY_ENC_OPTS_MASK], | ||
724 | TCA_FLOWER_KEY_ENC_OPTS_MAX, | ||
725 | enc_opts_policy, extack); | ||
726 | if (err) | ||
727 | return err; | ||
728 | |||
717 | nla_opt_msk = nla_data(tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]); | 729 | nla_opt_msk = nla_data(tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]); |
718 | msk_depth = nla_len(tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]); | 730 | msk_depth = nla_len(tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]); |
719 | } | 731 | } |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 57b3ad9394ad..2c38e3d07924 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -648,15 +648,6 @@ deliver: | |||
648 | */ | 648 | */ |
649 | skb->dev = qdisc_dev(sch); | 649 | skb->dev = qdisc_dev(sch); |
650 | 650 | ||
651 | #ifdef CONFIG_NET_CLS_ACT | ||
652 | /* | ||
653 | * If it's at ingress let's pretend the delay is | ||
654 | * from the network (tstamp will be updated). | ||
655 | */ | ||
656 | if (skb->tc_redirected && skb->tc_from_ingress) | ||
657 | skb->tstamp = 0; | ||
658 | #endif | ||
659 | |||
660 | if (q->slot.slot_next) { | 651 | if (q->slot.slot_next) { |
661 | q->slot.packets_left--; | 652 | q->slot.packets_left--; |
662 | q->slot.bytes_left -= qdisc_pkt_len(skb); | 653 | q->slot.bytes_left -= qdisc_pkt_len(skb); |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 9cb854b05342..c37e1c2dec9d 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -212,7 +212,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) | |||
212 | INIT_LIST_HEAD(&q->retransmit); | 212 | INIT_LIST_HEAD(&q->retransmit); |
213 | INIT_LIST_HEAD(&q->sacked); | 213 | INIT_LIST_HEAD(&q->sacked); |
214 | INIT_LIST_HEAD(&q->abandoned); | 214 | INIT_LIST_HEAD(&q->abandoned); |
215 | sctp_sched_set_sched(asoc, SCTP_SS_FCFS); | 215 | sctp_sched_set_sched(asoc, SCTP_SS_DEFAULT); |
216 | } | 216 | } |
217 | 217 | ||
218 | /* Free the outqueue structure and any related pending chunks. | 218 | /* Free the outqueue structure and any related pending chunks. |
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index d8831b988b1e..ab4a3be1542a 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -281,13 +281,7 @@ static bool generic_key_to_expire(struct rpc_cred *cred) | |||
281 | { | 281 | { |
282 | struct auth_cred *acred = &container_of(cred, struct generic_cred, | 282 | struct auth_cred *acred = &container_of(cred, struct generic_cred, |
283 | gc_base)->acred; | 283 | gc_base)->acred; |
284 | bool ret; | 284 | return test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); |
285 | |||
286 | get_rpccred(cred); | ||
287 | ret = test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); | ||
288 | put_rpccred(cred); | ||
289 | |||
290 | return ret; | ||
291 | } | 285 | } |
292 | 286 | ||
293 | static const struct rpc_credops generic_credops = { | 287 | static const struct rpc_credops generic_credops = { |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 30f970cdc7f6..5d3f252659f1 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -1239,36 +1239,59 @@ gss_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | |||
1239 | return &gss_auth->rpc_auth; | 1239 | return &gss_auth->rpc_auth; |
1240 | } | 1240 | } |
1241 | 1241 | ||
1242 | static struct gss_cred * | ||
1243 | gss_dup_cred(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | ||
1244 | { | ||
1245 | struct gss_cred *new; | ||
1246 | |||
1247 | /* Make a copy of the cred so that we can reference count it */ | ||
1248 | new = kzalloc(sizeof(*gss_cred), GFP_NOIO); | ||
1249 | if (new) { | ||
1250 | struct auth_cred acred = { | ||
1251 | .uid = gss_cred->gc_base.cr_uid, | ||
1252 | }; | ||
1253 | struct gss_cl_ctx *ctx = | ||
1254 | rcu_dereference_protected(gss_cred->gc_ctx, 1); | ||
1255 | |||
1256 | rpcauth_init_cred(&new->gc_base, &acred, | ||
1257 | &gss_auth->rpc_auth, | ||
1258 | &gss_nullops); | ||
1259 | new->gc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE; | ||
1260 | new->gc_service = gss_cred->gc_service; | ||
1261 | new->gc_principal = gss_cred->gc_principal; | ||
1262 | kref_get(&gss_auth->kref); | ||
1263 | rcu_assign_pointer(new->gc_ctx, ctx); | ||
1264 | gss_get_ctx(ctx); | ||
1265 | } | ||
1266 | return new; | ||
1267 | } | ||
1268 | |||
1242 | /* | 1269 | /* |
1243 | * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call | 1270 | * gss_send_destroy_context will cause the RPCSEC_GSS to send a NULL RPC call |
1244 | * to the server with the GSS control procedure field set to | 1271 | * to the server with the GSS control procedure field set to |
1245 | * RPC_GSS_PROC_DESTROY. This should normally cause the server to release | 1272 | * RPC_GSS_PROC_DESTROY. This should normally cause the server to release |
1246 | * all RPCSEC_GSS state associated with that context. | 1273 | * all RPCSEC_GSS state associated with that context. |
1247 | */ | 1274 | */ |
1248 | static int | 1275 | static void |
1249 | gss_destroying_context(struct rpc_cred *cred) | 1276 | gss_send_destroy_context(struct rpc_cred *cred) |
1250 | { | 1277 | { |
1251 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 1278 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
1252 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | 1279 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); |
1253 | struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); | 1280 | struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); |
1281 | struct gss_cred *new; | ||
1254 | struct rpc_task *task; | 1282 | struct rpc_task *task; |
1255 | 1283 | ||
1256 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) | 1284 | new = gss_dup_cred(gss_auth, gss_cred); |
1257 | return 0; | 1285 | if (new) { |
1258 | 1286 | ctx->gc_proc = RPC_GSS_PROC_DESTROY; | |
1259 | ctx->gc_proc = RPC_GSS_PROC_DESTROY; | ||
1260 | cred->cr_ops = &gss_nullops; | ||
1261 | |||
1262 | /* Take a reference to ensure the cred will be destroyed either | ||
1263 | * by the RPC call or by the put_rpccred() below */ | ||
1264 | get_rpccred(cred); | ||
1265 | 1287 | ||
1266 | task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC|RPC_TASK_SOFT); | 1288 | task = rpc_call_null(gss_auth->client, &new->gc_base, |
1267 | if (!IS_ERR(task)) | 1289 | RPC_TASK_ASYNC|RPC_TASK_SOFT); |
1268 | rpc_put_task(task); | 1290 | if (!IS_ERR(task)) |
1291 | rpc_put_task(task); | ||
1269 | 1292 | ||
1270 | put_rpccred(cred); | 1293 | put_rpccred(&new->gc_base); |
1271 | return 1; | 1294 | } |
1272 | } | 1295 | } |
1273 | 1296 | ||
1274 | /* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure | 1297 | /* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure |
@@ -1330,8 +1353,8 @@ static void | |||
1330 | gss_destroy_cred(struct rpc_cred *cred) | 1353 | gss_destroy_cred(struct rpc_cred *cred) |
1331 | { | 1354 | { |
1332 | 1355 | ||
1333 | if (gss_destroying_context(cred)) | 1356 | if (test_and_clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) |
1334 | return; | 1357 | gss_send_destroy_context(cred); |
1335 | gss_destroy_nullcred(cred); | 1358 | gss_destroy_nullcred(cred); |
1336 | } | 1359 | } |
1337 | 1360 | ||
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 2bbb8d38d2bf..f302c6eb8779 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -546,7 +546,7 @@ EXPORT_SYMBOL_GPL(xdr_commit_encode); | |||
546 | static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, | 546 | static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, |
547 | size_t nbytes) | 547 | size_t nbytes) |
548 | { | 548 | { |
549 | static __be32 *p; | 549 | __be32 *p; |
550 | int space_left; | 550 | int space_left; |
551 | int frag1bytes, frag2bytes; | 551 | int frag1bytes, frag2bytes; |
552 | 552 | ||
@@ -673,11 +673,10 @@ void xdr_truncate_encode(struct xdr_stream *xdr, size_t len) | |||
673 | WARN_ON_ONCE(xdr->iov); | 673 | WARN_ON_ONCE(xdr->iov); |
674 | return; | 674 | return; |
675 | } | 675 | } |
676 | if (fraglen) { | 676 | if (fraglen) |
677 | xdr->end = head->iov_base + head->iov_len; | 677 | xdr->end = head->iov_base + head->iov_len; |
678 | xdr->page_ptr--; | ||
679 | } | ||
680 | /* (otherwise assume xdr->end is already set) */ | 678 | /* (otherwise assume xdr->end is already set) */ |
679 | xdr->page_ptr--; | ||
681 | head->iov_len = len; | 680 | head->iov_len = len; |
682 | buf->len = len; | 681 | buf->len = len; |
683 | xdr->p = head->iov_base + head->iov_len; | 682 | xdr->p = head->iov_base + head->iov_len; |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 201c3b5bc96b..836727e363c4 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -1594,14 +1594,17 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1594 | if (in_range(peers_prio, l->priority + 1, TIPC_MAX_LINK_PRI)) | 1594 | if (in_range(peers_prio, l->priority + 1, TIPC_MAX_LINK_PRI)) |
1595 | l->priority = peers_prio; | 1595 | l->priority = peers_prio; |
1596 | 1596 | ||
1597 | /* ACTIVATE_MSG serves as PEER_RESET if link is already down */ | 1597 | /* If peer is going down we want full re-establish cycle */ |
1598 | if (msg_peer_stopping(hdr)) | 1598 | if (msg_peer_stopping(hdr)) { |
1599 | rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); | 1599 | rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); |
1600 | else if ((mtyp == RESET_MSG) || !link_is_up(l)) | 1600 | break; |
1601 | } | ||
1602 | /* ACTIVATE_MSG serves as PEER_RESET if link is already down */ | ||
1603 | if (mtyp == RESET_MSG || !link_is_up(l)) | ||
1601 | rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); | 1604 | rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); |
1602 | 1605 | ||
1603 | /* ACTIVATE_MSG takes up link if it was already locally reset */ | 1606 | /* ACTIVATE_MSG takes up link if it was already locally reset */ |
1604 | if ((mtyp == ACTIVATE_MSG) && (l->state == LINK_ESTABLISHING)) | 1607 | if (mtyp == ACTIVATE_MSG && l->state == LINK_ESTABLISHING) |
1605 | rc = TIPC_LINK_UP_EVT; | 1608 | rc = TIPC_LINK_UP_EVT; |
1606 | 1609 | ||
1607 | l->peer_session = msg_session(hdr); | 1610 | l->peer_session = msg_session(hdr); |