diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/fib_frontend.c | 6 | ||||
-rw-r--r-- | net/ipv4/inet_fragment.c | 57 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 1 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel.c | 2 | ||||
-rw-r--r-- | net/ipv4/ipconfig.c | 13 | ||||
-rw-r--r-- | net/ipv4/ipmr.c | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_ULOG.c | 4 | ||||
-rw-r--r-- | net/ipv4/udp_diag.c | 6 |
8 files changed, 70 insertions, 29 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 0e74398bc8e6..c7629a209f9d 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -957,8 +957,8 @@ static void nl_fib_input(struct sk_buff *skb) | |||
957 | 957 | ||
958 | net = sock_net(skb->sk); | 958 | net = sock_net(skb->sk); |
959 | nlh = nlmsg_hdr(skb); | 959 | nlh = nlmsg_hdr(skb); |
960 | if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len || | 960 | if (skb->len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len || |
961 | nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn))) | 961 | nlmsg_len(nlh) < sizeof(*frn)) |
962 | return; | 962 | return; |
963 | 963 | ||
964 | skb = skb_clone(skb, GFP_KERNEL); | 964 | skb = skb_clone(skb, GFP_KERNEL); |
@@ -966,7 +966,7 @@ static void nl_fib_input(struct sk_buff *skb) | |||
966 | return; | 966 | return; |
967 | nlh = nlmsg_hdr(skb); | 967 | nlh = nlmsg_hdr(skb); |
968 | 968 | ||
969 | frn = (struct fib_result_nl *) NLMSG_DATA(nlh); | 969 | frn = (struct fib_result_nl *) nlmsg_data(nlh); |
970 | tb = fib_get_table(net, frn->tb_id_in); | 970 | tb = fib_get_table(net, frn->tb_id_in); |
971 | 971 | ||
972 | nl_fib_lookup(frn, tb); | 972 | nl_fib_lookup(frn, tb); |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 1206ca64b0ea..e97d66a1fdde 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -52,20 +52,27 @@ static void inet_frag_secret_rebuild(unsigned long dummy) | |||
52 | unsigned long now = jiffies; | 52 | unsigned long now = jiffies; |
53 | int i; | 53 | int i; |
54 | 54 | ||
55 | /* Per bucket lock NOT needed here, due to write lock protection */ | ||
55 | write_lock(&f->lock); | 56 | write_lock(&f->lock); |
57 | |||
56 | get_random_bytes(&f->rnd, sizeof(u32)); | 58 | get_random_bytes(&f->rnd, sizeof(u32)); |
57 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { | 59 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { |
60 | struct inet_frag_bucket *hb; | ||
58 | struct inet_frag_queue *q; | 61 | struct inet_frag_queue *q; |
59 | struct hlist_node *n; | 62 | struct hlist_node *n; |
60 | 63 | ||
61 | hlist_for_each_entry_safe(q, n, &f->hash[i], list) { | 64 | hb = &f->hash[i]; |
65 | hlist_for_each_entry_safe(q, n, &hb->chain, list) { | ||
62 | unsigned int hval = f->hashfn(q); | 66 | unsigned int hval = f->hashfn(q); |
63 | 67 | ||
64 | if (hval != i) { | 68 | if (hval != i) { |
69 | struct inet_frag_bucket *hb_dest; | ||
70 | |||
65 | hlist_del(&q->list); | 71 | hlist_del(&q->list); |
66 | 72 | ||
67 | /* Relink to new hash chain. */ | 73 | /* Relink to new hash chain. */ |
68 | hlist_add_head(&q->list, &f->hash[hval]); | 74 | hb_dest = &f->hash[hval]; |
75 | hlist_add_head(&q->list, &hb_dest->chain); | ||
69 | } | 76 | } |
70 | } | 77 | } |
71 | } | 78 | } |
@@ -78,9 +85,12 @@ void inet_frags_init(struct inet_frags *f) | |||
78 | { | 85 | { |
79 | int i; | 86 | int i; |
80 | 87 | ||
81 | for (i = 0; i < INETFRAGS_HASHSZ; i++) | 88 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { |
82 | INIT_HLIST_HEAD(&f->hash[i]); | 89 | struct inet_frag_bucket *hb = &f->hash[i]; |
83 | 90 | ||
91 | spin_lock_init(&hb->chain_lock); | ||
92 | INIT_HLIST_HEAD(&hb->chain); | ||
93 | } | ||
84 | rwlock_init(&f->lock); | 94 | rwlock_init(&f->lock); |
85 | 95 | ||
86 | f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | 96 | f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ |
@@ -122,9 +132,18 @@ EXPORT_SYMBOL(inet_frags_exit_net); | |||
122 | 132 | ||
123 | static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f) | 133 | static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f) |
124 | { | 134 | { |
125 | write_lock(&f->lock); | 135 | struct inet_frag_bucket *hb; |
136 | unsigned int hash; | ||
137 | |||
138 | read_lock(&f->lock); | ||
139 | hash = f->hashfn(fq); | ||
140 | hb = &f->hash[hash]; | ||
141 | |||
142 | spin_lock(&hb->chain_lock); | ||
126 | hlist_del(&fq->list); | 143 | hlist_del(&fq->list); |
127 | write_unlock(&f->lock); | 144 | spin_unlock(&hb->chain_lock); |
145 | |||
146 | read_unlock(&f->lock); | ||
128 | inet_frag_lru_del(fq); | 147 | inet_frag_lru_del(fq); |
129 | } | 148 | } |
130 | 149 | ||
@@ -226,27 +245,32 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, | |||
226 | struct inet_frag_queue *qp_in, struct inet_frags *f, | 245 | struct inet_frag_queue *qp_in, struct inet_frags *f, |
227 | void *arg) | 246 | void *arg) |
228 | { | 247 | { |
248 | struct inet_frag_bucket *hb; | ||
229 | struct inet_frag_queue *qp; | 249 | struct inet_frag_queue *qp; |
230 | #ifdef CONFIG_SMP | 250 | #ifdef CONFIG_SMP |
231 | #endif | 251 | #endif |
232 | unsigned int hash; | 252 | unsigned int hash; |
233 | 253 | ||
234 | write_lock(&f->lock); | 254 | read_lock(&f->lock); /* Protects against hash rebuild */ |
235 | /* | 255 | /* |
236 | * While we stayed w/o the lock other CPU could update | 256 | * While we stayed w/o the lock other CPU could update |
237 | * the rnd seed, so we need to re-calculate the hash | 257 | * the rnd seed, so we need to re-calculate the hash |
238 | * chain. Fortunatelly the qp_in can be used to get one. | 258 | * chain. Fortunatelly the qp_in can be used to get one. |
239 | */ | 259 | */ |
240 | hash = f->hashfn(qp_in); | 260 | hash = f->hashfn(qp_in); |
261 | hb = &f->hash[hash]; | ||
262 | spin_lock(&hb->chain_lock); | ||
263 | |||
241 | #ifdef CONFIG_SMP | 264 | #ifdef CONFIG_SMP |
242 | /* With SMP race we have to recheck hash table, because | 265 | /* With SMP race we have to recheck hash table, because |
243 | * such entry could be created on other cpu, while we | 266 | * such entry could be created on other cpu, while we |
244 | * promoted read lock to write lock. | 267 | * released the hash bucket lock. |
245 | */ | 268 | */ |
246 | hlist_for_each_entry(qp, &f->hash[hash], list) { | 269 | hlist_for_each_entry(qp, &hb->chain, list) { |
247 | if (qp->net == nf && f->match(qp, arg)) { | 270 | if (qp->net == nf && f->match(qp, arg)) { |
248 | atomic_inc(&qp->refcnt); | 271 | atomic_inc(&qp->refcnt); |
249 | write_unlock(&f->lock); | 272 | spin_unlock(&hb->chain_lock); |
273 | read_unlock(&f->lock); | ||
250 | qp_in->last_in |= INET_FRAG_COMPLETE; | 274 | qp_in->last_in |= INET_FRAG_COMPLETE; |
251 | inet_frag_put(qp_in, f); | 275 | inet_frag_put(qp_in, f); |
252 | return qp; | 276 | return qp; |
@@ -258,8 +282,9 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, | |||
258 | atomic_inc(&qp->refcnt); | 282 | atomic_inc(&qp->refcnt); |
259 | 283 | ||
260 | atomic_inc(&qp->refcnt); | 284 | atomic_inc(&qp->refcnt); |
261 | hlist_add_head(&qp->list, &f->hash[hash]); | 285 | hlist_add_head(&qp->list, &hb->chain); |
262 | write_unlock(&f->lock); | 286 | spin_unlock(&hb->chain_lock); |
287 | read_unlock(&f->lock); | ||
263 | inet_frag_lru_add(nf, qp); | 288 | inet_frag_lru_add(nf, qp); |
264 | return qp; | 289 | return qp; |
265 | } | 290 | } |
@@ -300,17 +325,23 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, | |||
300 | struct inet_frags *f, void *key, unsigned int hash) | 325 | struct inet_frags *f, void *key, unsigned int hash) |
301 | __releases(&f->lock) | 326 | __releases(&f->lock) |
302 | { | 327 | { |
328 | struct inet_frag_bucket *hb; | ||
303 | struct inet_frag_queue *q; | 329 | struct inet_frag_queue *q; |
304 | int depth = 0; | 330 | int depth = 0; |
305 | 331 | ||
306 | hlist_for_each_entry(q, &f->hash[hash], list) { | 332 | hb = &f->hash[hash]; |
333 | |||
334 | spin_lock(&hb->chain_lock); | ||
335 | hlist_for_each_entry(q, &hb->chain, list) { | ||
307 | if (q->net == nf && f->match(q, key)) { | 336 | if (q->net == nf && f->match(q, key)) { |
308 | atomic_inc(&q->refcnt); | 337 | atomic_inc(&q->refcnt); |
338 | spin_unlock(&hb->chain_lock); | ||
309 | read_unlock(&f->lock); | 339 | read_unlock(&f->lock); |
310 | return q; | 340 | return q; |
311 | } | 341 | } |
312 | depth++; | 342 | depth++; |
313 | } | 343 | } |
344 | spin_unlock(&hb->chain_lock); | ||
314 | read_unlock(&f->lock); | 345 | read_unlock(&f->lock); |
315 | 346 | ||
316 | if (depth <= INETFRAGS_MAXDEPTH) | 347 | if (depth <= INETFRAGS_MAXDEPTH) |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index ad662e906f7e..e5dfd2843f28 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -660,7 +660,6 @@ static void __gre_tunnel_init(struct net_device *dev) | |||
660 | 660 | ||
661 | dev->needed_headroom = LL_MAX_HEADER + sizeof(struct iphdr) + 4; | 661 | dev->needed_headroom = LL_MAX_HEADER + sizeof(struct iphdr) + 4; |
662 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4; | 662 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4; |
663 | dev->iflink = 0; | ||
664 | 663 | ||
665 | dev->features |= NETIF_F_NETNS_LOCAL | GRE_FEATURES; | 664 | dev->features |= NETIF_F_NETNS_LOCAL | GRE_FEATURES; |
666 | dev->hw_features |= GRE_FEATURES; | 665 | dev->hw_features |= GRE_FEATURES; |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 9d96b6853f21..e4147ec1665a 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -284,7 +284,7 @@ static struct net_device *__ip_tunnel_create(struct net *net, | |||
284 | if (parms->name[0]) | 284 | if (parms->name[0]) |
285 | strlcpy(name, parms->name, IFNAMSIZ); | 285 | strlcpy(name, parms->name, IFNAMSIZ); |
286 | else { | 286 | else { |
287 | if (strlen(ops->kind) + 3 >= IFNAMSIZ) { | 287 | if (strlen(ops->kind) > (IFNAMSIZ - 3)) { |
288 | err = -E2BIG; | 288 | err = -E2BIG; |
289 | goto failed; | 289 | goto failed; |
290 | } | 290 | } |
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index bf6c5cf31aed..efa1138fa523 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -206,7 +206,7 @@ static int __init ic_open_devs(void) | |||
206 | struct ic_device *d, **last; | 206 | struct ic_device *d, **last; |
207 | struct net_device *dev; | 207 | struct net_device *dev; |
208 | unsigned short oflags; | 208 | unsigned short oflags; |
209 | unsigned long start; | 209 | unsigned long start, next_msg; |
210 | 210 | ||
211 | last = &ic_first_dev; | 211 | last = &ic_first_dev; |
212 | rtnl_lock(); | 212 | rtnl_lock(); |
@@ -263,12 +263,23 @@ static int __init ic_open_devs(void) | |||
263 | 263 | ||
264 | /* wait for a carrier on at least one device */ | 264 | /* wait for a carrier on at least one device */ |
265 | start = jiffies; | 265 | start = jiffies; |
266 | next_msg = start + msecs_to_jiffies(CONF_CARRIER_TIMEOUT/12); | ||
266 | while (jiffies - start < msecs_to_jiffies(CONF_CARRIER_TIMEOUT)) { | 267 | while (jiffies - start < msecs_to_jiffies(CONF_CARRIER_TIMEOUT)) { |
268 | int wait, elapsed; | ||
269 | |||
267 | for_each_netdev(&init_net, dev) | 270 | for_each_netdev(&init_net, dev) |
268 | if (ic_is_init_dev(dev) && netif_carrier_ok(dev)) | 271 | if (ic_is_init_dev(dev) && netif_carrier_ok(dev)) |
269 | goto have_carrier; | 272 | goto have_carrier; |
270 | 273 | ||
271 | msleep(1); | 274 | msleep(1); |
275 | |||
276 | if time_before(jiffies, next_msg) | ||
277 | continue; | ||
278 | |||
279 | elapsed = jiffies_to_msecs(jiffies - start); | ||
280 | wait = (CONF_CARRIER_TIMEOUT - elapsed + 500)/1000; | ||
281 | pr_info("Waiting up to %d more seconds for network.\n", wait); | ||
282 | next_msg = jiffies + msecs_to_jiffies(CONF_CARRIER_TIMEOUT/12); | ||
272 | } | 283 | } |
273 | have_carrier: | 284 | have_carrier: |
274 | rtnl_unlock(); | 285 | rtnl_unlock(); |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index fd61fe16679f..9d9610ae7855 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -626,9 +626,9 @@ static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c) | |||
626 | if (ip_hdr(skb)->version == 0) { | 626 | if (ip_hdr(skb)->version == 0) { |
627 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); | 627 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); |
628 | nlh->nlmsg_type = NLMSG_ERROR; | 628 | nlh->nlmsg_type = NLMSG_ERROR; |
629 | nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr)); | 629 | nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr)); |
630 | skb_trim(skb, nlh->nlmsg_len); | 630 | skb_trim(skb, nlh->nlmsg_len); |
631 | e = NLMSG_DATA(nlh); | 631 | e = nlmsg_data(nlh); |
632 | e->error = -ETIMEDOUT; | 632 | e->error = -ETIMEDOUT; |
633 | memset(&e->msg, 0, sizeof(e->msg)); | 633 | memset(&e->msg, 0, sizeof(e->msg)); |
634 | 634 | ||
@@ -910,14 +910,14 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, | |||
910 | if (ip_hdr(skb)->version == 0) { | 910 | if (ip_hdr(skb)->version == 0) { |
911 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); | 911 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); |
912 | 912 | ||
913 | if (__ipmr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { | 913 | if (__ipmr_fill_mroute(mrt, skb, c, nlmsg_data(nlh)) > 0) { |
914 | nlh->nlmsg_len = skb_tail_pointer(skb) - | 914 | nlh->nlmsg_len = skb_tail_pointer(skb) - |
915 | (u8 *)nlh; | 915 | (u8 *)nlh; |
916 | } else { | 916 | } else { |
917 | nlh->nlmsg_type = NLMSG_ERROR; | 917 | nlh->nlmsg_type = NLMSG_ERROR; |
918 | nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr)); | 918 | nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr)); |
919 | skb_trim(skb, nlh->nlmsg_len); | 919 | skb_trim(skb, nlh->nlmsg_len); |
920 | e = NLMSG_DATA(nlh); | 920 | e = nlmsg_data(nlh); |
921 | e->error = -EMSGSIZE; | 921 | e->error = -EMSGSIZE; |
922 | memset(&e->msg, 0, sizeof(e->msg)); | 922 | memset(&e->msg, 0, sizeof(e->msg)); |
923 | } | 923 | } |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 642ecfb711bc..8799c836ccaa 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/skbuff.h> | 37 | #include <linux/skbuff.h> |
38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
39 | #include <linux/timer.h> | 39 | #include <linux/timer.h> |
40 | #include <linux/netlink.h> | 40 | #include <net/netlink.h> |
41 | #include <linux/netdevice.h> | 41 | #include <linux/netdevice.h> |
42 | #include <linux/mm.h> | 42 | #include <linux/mm.h> |
43 | #include <linux/moduleparam.h> | 43 | #include <linux/moduleparam.h> |
@@ -187,7 +187,7 @@ static void ipt_ulog_packet(unsigned int hooknum, | |||
187 | else | 187 | else |
188 | copy_len = loginfo->copy_range; | 188 | copy_len = loginfo->copy_range; |
189 | 189 | ||
190 | size = NLMSG_SPACE(sizeof(*pm) + copy_len); | 190 | size = nlmsg_total_size(sizeof(*pm) + copy_len); |
191 | 191 | ||
192 | ub = &ulog->ulog_buffers[groupnum]; | 192 | ub = &ulog->ulog_buffers[groupnum]; |
193 | 193 | ||
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 505b30ad9182..369a781851ad 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
@@ -64,9 +64,9 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, | |||
64 | goto out; | 64 | goto out; |
65 | 65 | ||
66 | err = -ENOMEM; | 66 | err = -ENOMEM; |
67 | rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) + | 67 | rep = nlmsg_new(sizeof(struct inet_diag_msg) + |
68 | sizeof(struct inet_diag_meminfo) + | 68 | sizeof(struct inet_diag_meminfo) + 64, |
69 | 64)), GFP_KERNEL); | 69 | GFP_KERNEL); |
70 | if (!rep) | 70 | if (!rep) |
71 | goto out; | 71 | goto out; |
72 | 72 | ||