diff options
Diffstat (limited to 'net/ipv6/reassembly.c')
-rw-r--r-- | net/ipv6/reassembly.c | 35 |
1 files changed, 17 insertions, 18 deletions
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 15e1456b3f18..b67a45fb93e9 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -203,7 +203,7 @@ static inline void frag_free_queue(struct frag_queue *fq, int *work) | |||
203 | 203 | ||
204 | static inline struct frag_queue *frag_alloc_queue(void) | 204 | static inline struct frag_queue *frag_alloc_queue(void) |
205 | { | 205 | { |
206 | struct frag_queue *fq = kmalloc(sizeof(struct frag_queue), GFP_ATOMIC); | 206 | struct frag_queue *fq = kzalloc(sizeof(struct frag_queue), GFP_ATOMIC); |
207 | 207 | ||
208 | if(!fq) | 208 | if(!fq) |
209 | return NULL; | 209 | return NULL; |
@@ -288,6 +288,7 @@ static void ip6_evictor(void) | |||
288 | static void ip6_frag_expire(unsigned long data) | 288 | static void ip6_frag_expire(unsigned long data) |
289 | { | 289 | { |
290 | struct frag_queue *fq = (struct frag_queue *) data; | 290 | struct frag_queue *fq = (struct frag_queue *) data; |
291 | struct net_device *dev; | ||
291 | 292 | ||
292 | spin_lock(&fq->lock); | 293 | spin_lock(&fq->lock); |
293 | 294 | ||
@@ -299,22 +300,22 @@ static void ip6_frag_expire(unsigned long data) | |||
299 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); | 300 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); |
300 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 301 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
301 | 302 | ||
302 | /* Send error only if the first segment arrived. */ | 303 | /* Don't send error if the first segment did not arrive. */ |
303 | if (fq->last_in&FIRST_IN && fq->fragments) { | 304 | if (!(fq->last_in&FIRST_IN) || !fq->fragments) |
304 | struct net_device *dev = dev_get_by_index(fq->iif); | 305 | goto out; |
305 | 306 | ||
306 | /* | 307 | dev = dev_get_by_index(fq->iif); |
307 | But use as source device on which LAST ARRIVED | 308 | if (!dev) |
308 | segment was received. And do not use fq->dev | 309 | goto out; |
309 | pointer directly, device might already disappeared. | 310 | |
310 | */ | 311 | /* |
311 | if (dev) { | 312 | But use as source device on which LAST ARRIVED |
312 | fq->fragments->dev = dev; | 313 | segment was received. And do not use fq->dev |
313 | icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, | 314 | pointer directly, device might already disappeared. |
314 | dev); | 315 | */ |
315 | dev_put(dev); | 316 | fq->fragments->dev = dev; |
316 | } | 317 | icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); |
317 | } | 318 | dev_put(dev); |
318 | out: | 319 | out: |
319 | spin_unlock(&fq->lock); | 320 | spin_unlock(&fq->lock); |
320 | fq_put(fq, NULL); | 321 | fq_put(fq, NULL); |
@@ -368,8 +369,6 @@ ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr | |||
368 | if ((fq = frag_alloc_queue()) == NULL) | 369 | if ((fq = frag_alloc_queue()) == NULL) |
369 | goto oom; | 370 | goto oom; |
370 | 371 | ||
371 | memset(fq, 0, sizeof(struct frag_queue)); | ||
372 | |||
373 | fq->id = id; | 372 | fq->id = id; |
374 | ipv6_addr_copy(&fq->saddr, src); | 373 | ipv6_addr_copy(&fq->saddr, src); |
375 | ipv6_addr_copy(&fq->daddr, dst); | 374 | ipv6_addr_copy(&fq->daddr, dst); |