diff options
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/icmp.c | 22 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ipt_addrtype.c | 2 | ||||
| -rw-r--r-- | net/ipv4/netfilter/nf_nat_proto_common.c | 8 | ||||
| -rw-r--r-- | net/ipv4/route.c | 76 |
4 files changed, 91 insertions, 17 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 860558633b2c..55c355e63234 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
| @@ -204,18 +204,22 @@ static struct sock *icmp_sk(struct net *net) | |||
| 204 | return net->ipv4.icmp_sk[smp_processor_id()]; | 204 | return net->ipv4.icmp_sk[smp_processor_id()]; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | static inline int icmp_xmit_lock(struct sock *sk) | 207 | static inline struct sock *icmp_xmit_lock(struct net *net) |
| 208 | { | 208 | { |
| 209 | struct sock *sk; | ||
| 210 | |||
| 209 | local_bh_disable(); | 211 | local_bh_disable(); |
| 210 | 212 | ||
| 213 | sk = icmp_sk(net); | ||
| 214 | |||
| 211 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { | 215 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
| 212 | /* This can happen if the output path signals a | 216 | /* This can happen if the output path signals a |
| 213 | * dst_link_failure() for an outgoing ICMP packet. | 217 | * dst_link_failure() for an outgoing ICMP packet. |
| 214 | */ | 218 | */ |
| 215 | local_bh_enable(); | 219 | local_bh_enable(); |
| 216 | return 1; | 220 | return NULL; |
| 217 | } | 221 | } |
| 218 | return 0; | 222 | return sk; |
| 219 | } | 223 | } |
| 220 | 224 | ||
| 221 | static inline void icmp_xmit_unlock(struct sock *sk) | 225 | static inline void icmp_xmit_unlock(struct sock *sk) |
| @@ -354,15 +358,17 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
| 354 | struct ipcm_cookie ipc; | 358 | struct ipcm_cookie ipc; |
| 355 | struct rtable *rt = skb->rtable; | 359 | struct rtable *rt = skb->rtable; |
| 356 | struct net *net = dev_net(rt->u.dst.dev); | 360 | struct net *net = dev_net(rt->u.dst.dev); |
| 357 | struct sock *sk = icmp_sk(net); | 361 | struct sock *sk; |
| 358 | struct inet_sock *inet = inet_sk(sk); | 362 | struct inet_sock *inet; |
| 359 | __be32 daddr; | 363 | __be32 daddr; |
| 360 | 364 | ||
| 361 | if (ip_options_echo(&icmp_param->replyopts, skb)) | 365 | if (ip_options_echo(&icmp_param->replyopts, skb)) |
| 362 | return; | 366 | return; |
| 363 | 367 | ||
| 364 | if (icmp_xmit_lock(sk)) | 368 | sk = icmp_xmit_lock(net); |
| 369 | if (sk == NULL) | ||
| 365 | return; | 370 | return; |
| 371 | inet = inet_sk(sk); | ||
| 366 | 372 | ||
| 367 | icmp_param->data.icmph.checksum = 0; | 373 | icmp_param->data.icmph.checksum = 0; |
| 368 | 374 | ||
| @@ -419,7 +425,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
| 419 | if (!rt) | 425 | if (!rt) |
| 420 | goto out; | 426 | goto out; |
| 421 | net = dev_net(rt->u.dst.dev); | 427 | net = dev_net(rt->u.dst.dev); |
| 422 | sk = icmp_sk(net); | ||
| 423 | 428 | ||
| 424 | /* | 429 | /* |
| 425 | * Find the original header. It is expected to be valid, of course. | 430 | * Find the original header. It is expected to be valid, of course. |
| @@ -483,7 +488,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
| 483 | } | 488 | } |
| 484 | } | 489 | } |
| 485 | 490 | ||
| 486 | if (icmp_xmit_lock(sk)) | 491 | sk = icmp_xmit_lock(net); |
| 492 | if (sk == NULL) | ||
| 487 | return; | 493 | return; |
| 488 | 494 | ||
| 489 | /* | 495 | /* |
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index 49587a497229..462a22c97877 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c | |||
| @@ -70,7 +70,7 @@ addrtype_mt_v1(const struct sk_buff *skb, const struct net_device *in, | |||
| 70 | (info->flags & IPT_ADDRTYPE_INVERT_SOURCE); | 70 | (info->flags & IPT_ADDRTYPE_INVERT_SOURCE); |
| 71 | if (ret && info->dest) | 71 | if (ret && info->dest) |
| 72 | ret &= match_type(dev, iph->daddr, info->dest) ^ | 72 | ret &= match_type(dev, iph->daddr, info->dest) ^ |
| 73 | (info->flags & IPT_ADDRTYPE_INVERT_DEST); | 73 | !!(info->flags & IPT_ADDRTYPE_INVERT_DEST); |
| 74 | return ret; | 74 | return ret; |
| 75 | } | 75 | } |
| 76 | 76 | ||
diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c index 91537f11273f..6c4f11f51446 100644 --- a/net/ipv4/netfilter/nf_nat_proto_common.c +++ b/net/ipv4/netfilter/nf_nat_proto_common.c | |||
| @@ -73,9 +73,13 @@ bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 73 | range_size = ntohs(range->max.all) - min + 1; | 73 | range_size = ntohs(range->max.all) - min + 1; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | off = *rover; | ||
| 77 | if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) | 76 | if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) |
| 78 | off = net_random(); | 77 | off = secure_ipv4_port_ephemeral(tuple->src.u3.ip, tuple->dst.u3.ip, |
| 78 | maniptype == IP_NAT_MANIP_SRC | ||
| 79 | ? tuple->dst.u.all | ||
| 80 | : tuple->src.u.all); | ||
| 81 | else | ||
| 82 | off = *rover; | ||
| 79 | 83 | ||
| 80 | for (i = 0; i < range_size; i++, off++) { | 84 | for (i = 0; i < range_size; i++, off++) { |
| 81 | *portptr = htons(min + off % range_size); | 85 | *portptr = htons(min + off % range_size); |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 16fc6f454a31..cca921ea8550 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -2914,6 +2914,68 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, | |||
| 2914 | return 0; | 2914 | return 0; |
| 2915 | } | 2915 | } |
| 2916 | 2916 | ||
| 2917 | static void rt_secret_reschedule(int old) | ||
| 2918 | { | ||
| 2919 | struct net *net; | ||
| 2920 | int new = ip_rt_secret_interval; | ||
| 2921 | int diff = new - old; | ||
| 2922 | |||
| 2923 | if (!diff) | ||
| 2924 | return; | ||
| 2925 | |||
| 2926 | rtnl_lock(); | ||
| 2927 | for_each_net(net) { | ||
| 2928 | int deleted = del_timer_sync(&net->ipv4.rt_secret_timer); | ||
| 2929 | |||
| 2930 | if (!new) | ||
| 2931 | continue; | ||
| 2932 | |||
| 2933 | if (deleted) { | ||
| 2934 | long time = net->ipv4.rt_secret_timer.expires - jiffies; | ||
| 2935 | |||
| 2936 | if (time <= 0 || (time += diff) <= 0) | ||
| 2937 | time = 0; | ||
| 2938 | |||
| 2939 | net->ipv4.rt_secret_timer.expires = time; | ||
| 2940 | } else | ||
| 2941 | net->ipv4.rt_secret_timer.expires = new; | ||
| 2942 | |||
| 2943 | net->ipv4.rt_secret_timer.expires += jiffies; | ||
| 2944 | add_timer(&net->ipv4.rt_secret_timer); | ||
| 2945 | } | ||
| 2946 | rtnl_unlock(); | ||
| 2947 | } | ||
| 2948 | |||
| 2949 | static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write, | ||
| 2950 | struct file *filp, | ||
| 2951 | void __user *buffer, size_t *lenp, | ||
| 2952 | loff_t *ppos) | ||
| 2953 | { | ||
| 2954 | int old = ip_rt_secret_interval; | ||
| 2955 | int ret = proc_dointvec_jiffies(ctl, write, filp, buffer, lenp, ppos); | ||
| 2956 | |||
| 2957 | rt_secret_reschedule(old); | ||
| 2958 | |||
| 2959 | return ret; | ||
| 2960 | } | ||
| 2961 | |||
| 2962 | static int ipv4_sysctl_rt_secret_interval_strategy(ctl_table *table, | ||
| 2963 | int __user *name, | ||
| 2964 | int nlen, | ||
| 2965 | void __user *oldval, | ||
| 2966 | size_t __user *oldlenp, | ||
| 2967 | void __user *newval, | ||
| 2968 | size_t newlen) | ||
| 2969 | { | ||
| 2970 | int old = ip_rt_secret_interval; | ||
| 2971 | int ret = sysctl_jiffies(table, name, nlen, oldval, oldlenp, newval, | ||
| 2972 | newlen); | ||
| 2973 | |||
| 2974 | rt_secret_reschedule(old); | ||
| 2975 | |||
| 2976 | return ret; | ||
| 2977 | } | ||
| 2978 | |||
| 2917 | static ctl_table ipv4_route_table[] = { | 2979 | static ctl_table ipv4_route_table[] = { |
| 2918 | { | 2980 | { |
| 2919 | .ctl_name = NET_IPV4_ROUTE_GC_THRESH, | 2981 | .ctl_name = NET_IPV4_ROUTE_GC_THRESH, |
| @@ -3048,8 +3110,8 @@ static ctl_table ipv4_route_table[] = { | |||
| 3048 | .data = &ip_rt_secret_interval, | 3110 | .data = &ip_rt_secret_interval, |
| 3049 | .maxlen = sizeof(int), | 3111 | .maxlen = sizeof(int), |
| 3050 | .mode = 0644, | 3112 | .mode = 0644, |
| 3051 | .proc_handler = &proc_dointvec_jiffies, | 3113 | .proc_handler = &ipv4_sysctl_rt_secret_interval, |
| 3052 | .strategy = &sysctl_jiffies, | 3114 | .strategy = &ipv4_sysctl_rt_secret_interval_strategy, |
| 3053 | }, | 3115 | }, |
| 3054 | { .ctl_name = 0 } | 3116 | { .ctl_name = 0 } |
| 3055 | }; | 3117 | }; |
| @@ -3126,10 +3188,12 @@ static __net_init int rt_secret_timer_init(struct net *net) | |||
| 3126 | net->ipv4.rt_secret_timer.data = (unsigned long)net; | 3188 | net->ipv4.rt_secret_timer.data = (unsigned long)net; |
| 3127 | init_timer_deferrable(&net->ipv4.rt_secret_timer); | 3189 | init_timer_deferrable(&net->ipv4.rt_secret_timer); |
| 3128 | 3190 | ||
| 3129 | net->ipv4.rt_secret_timer.expires = | 3191 | if (ip_rt_secret_interval) { |
| 3130 | jiffies + net_random() % ip_rt_secret_interval + | 3192 | net->ipv4.rt_secret_timer.expires = |
| 3131 | ip_rt_secret_interval; | 3193 | jiffies + net_random() % ip_rt_secret_interval + |
| 3132 | add_timer(&net->ipv4.rt_secret_timer); | 3194 | ip_rt_secret_interval; |
| 3195 | add_timer(&net->ipv4.rt_secret_timer); | ||
| 3196 | } | ||
| 3133 | return 0; | 3197 | return 0; |
| 3134 | } | 3198 | } |
| 3135 | 3199 | ||
