diff options
Diffstat (limited to 'net/ipv4/ip_fragment.c')
-rw-r--r-- | net/ipv4/ip_fragment.c | 177 |
1 files changed, 83 insertions, 94 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 32108cf2a784..428eaa502ec2 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <net/icmp.h> | 39 | #include <net/icmp.h> |
40 | #include <net/checksum.h> | 40 | #include <net/checksum.h> |
41 | #include <net/inetpeer.h> | 41 | #include <net/inetpeer.h> |
42 | #include <net/inet_frag.h> | ||
42 | #include <linux/tcp.h> | 43 | #include <linux/tcp.h> |
43 | #include <linux/udp.h> | 44 | #include <linux/udp.h> |
44 | #include <linux/inet.h> | 45 | #include <linux/inet.h> |
@@ -74,25 +75,13 @@ struct ipfrag_skb_cb | |||
74 | 75 | ||
75 | /* Describe an entry in the "incomplete datagrams" queue. */ | 76 | /* Describe an entry in the "incomplete datagrams" queue. */ |
76 | struct ipq { | 77 | struct ipq { |
77 | struct hlist_node list; | 78 | struct inet_frag_queue q; |
78 | struct list_head lru_list; /* lru list member */ | 79 | |
79 | u32 user; | 80 | u32 user; |
80 | __be32 saddr; | 81 | __be32 saddr; |
81 | __be32 daddr; | 82 | __be32 daddr; |
82 | __be16 id; | 83 | __be16 id; |
83 | u8 protocol; | 84 | u8 protocol; |
84 | u8 last_in; | ||
85 | #define COMPLETE 4 | ||
86 | #define FIRST_IN 2 | ||
87 | #define LAST_IN 1 | ||
88 | |||
89 | struct sk_buff *fragments; /* linked list of received fragments */ | ||
90 | int len; /* total length of original datagram */ | ||
91 | int meat; | ||
92 | spinlock_t lock; | ||
93 | atomic_t refcnt; | ||
94 | struct timer_list timer; /* when will this queue expire? */ | ||
95 | ktime_t stamp; | ||
96 | int iif; | 85 | int iif; |
97 | unsigned int rid; | 86 | unsigned int rid; |
98 | struct inet_peer *peer; | 87 | struct inet_peer *peer; |
@@ -114,8 +103,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
114 | 103 | ||
115 | static __inline__ void __ipq_unlink(struct ipq *qp) | 104 | static __inline__ void __ipq_unlink(struct ipq *qp) |
116 | { | 105 | { |
117 | hlist_del(&qp->list); | 106 | hlist_del(&qp->q.list); |
118 | list_del(&qp->lru_list); | 107 | list_del(&qp->q.lru_list); |
119 | ip_frag_nqueues--; | 108 | ip_frag_nqueues--; |
120 | } | 109 | } |
121 | 110 | ||
@@ -147,15 +136,15 @@ static void ipfrag_secret_rebuild(unsigned long dummy) | |||
147 | struct ipq *q; | 136 | struct ipq *q; |
148 | struct hlist_node *p, *n; | 137 | struct hlist_node *p, *n; |
149 | 138 | ||
150 | hlist_for_each_entry_safe(q, p, n, &ipq_hash[i], list) { | 139 | hlist_for_each_entry_safe(q, p, n, &ipq_hash[i], q.list) { |
151 | unsigned int hval = ipqhashfn(q->id, q->saddr, | 140 | unsigned int hval = ipqhashfn(q->id, q->saddr, |
152 | q->daddr, q->protocol); | 141 | q->daddr, q->protocol); |
153 | 142 | ||
154 | if (hval != i) { | 143 | if (hval != i) { |
155 | hlist_del(&q->list); | 144 | hlist_del(&q->q.list); |
156 | 145 | ||
157 | /* Relink to new hash chain. */ | 146 | /* Relink to new hash chain. */ |
158 | hlist_add_head(&q->list, &ipq_hash[hval]); | 147 | hlist_add_head(&q->q.list, &ipq_hash[hval]); |
159 | } | 148 | } |
160 | } | 149 | } |
161 | } | 150 | } |
@@ -201,14 +190,14 @@ static void ip_frag_destroy(struct ipq *qp, int *work) | |||
201 | { | 190 | { |
202 | struct sk_buff *fp; | 191 | struct sk_buff *fp; |
203 | 192 | ||
204 | BUG_TRAP(qp->last_in&COMPLETE); | 193 | BUG_TRAP(qp->q.last_in&COMPLETE); |
205 | BUG_TRAP(del_timer(&qp->timer) == 0); | 194 | BUG_TRAP(del_timer(&qp->q.timer) == 0); |
206 | 195 | ||
207 | if (qp->peer) | 196 | if (qp->peer) |
208 | inet_putpeer(qp->peer); | 197 | inet_putpeer(qp->peer); |
209 | 198 | ||
210 | /* Release all fragment data. */ | 199 | /* Release all fragment data. */ |
211 | fp = qp->fragments; | 200 | fp = qp->q.fragments; |
212 | while (fp) { | 201 | while (fp) { |
213 | struct sk_buff *xp = fp->next; | 202 | struct sk_buff *xp = fp->next; |
214 | 203 | ||
@@ -222,7 +211,7 @@ static void ip_frag_destroy(struct ipq *qp, int *work) | |||
222 | 211 | ||
223 | static __inline__ void ipq_put(struct ipq *ipq, int *work) | 212 | static __inline__ void ipq_put(struct ipq *ipq, int *work) |
224 | { | 213 | { |
225 | if (atomic_dec_and_test(&ipq->refcnt)) | 214 | if (atomic_dec_and_test(&ipq->q.refcnt)) |
226 | ip_frag_destroy(ipq, work); | 215 | ip_frag_destroy(ipq, work); |
227 | } | 216 | } |
228 | 217 | ||
@@ -231,13 +220,13 @@ static __inline__ void ipq_put(struct ipq *ipq, int *work) | |||
231 | */ | 220 | */ |
232 | static void ipq_kill(struct ipq *ipq) | 221 | static void ipq_kill(struct ipq *ipq) |
233 | { | 222 | { |
234 | if (del_timer(&ipq->timer)) | 223 | if (del_timer(&ipq->q.timer)) |
235 | atomic_dec(&ipq->refcnt); | 224 | atomic_dec(&ipq->q.refcnt); |
236 | 225 | ||
237 | if (!(ipq->last_in & COMPLETE)) { | 226 | if (!(ipq->q.last_in & COMPLETE)) { |
238 | ipq_unlink(ipq); | 227 | ipq_unlink(ipq); |
239 | atomic_dec(&ipq->refcnt); | 228 | atomic_dec(&ipq->q.refcnt); |
240 | ipq->last_in |= COMPLETE; | 229 | ipq->q.last_in |= COMPLETE; |
241 | } | 230 | } |
242 | } | 231 | } |
243 | 232 | ||
@@ -261,14 +250,14 @@ static void ip_evictor(void) | |||
261 | return; | 250 | return; |
262 | } | 251 | } |
263 | tmp = ipq_lru_list.next; | 252 | tmp = ipq_lru_list.next; |
264 | qp = list_entry(tmp, struct ipq, lru_list); | 253 | qp = list_entry(tmp, struct ipq, q.lru_list); |
265 | atomic_inc(&qp->refcnt); | 254 | atomic_inc(&qp->q.refcnt); |
266 | read_unlock(&ipfrag_lock); | 255 | read_unlock(&ipfrag_lock); |
267 | 256 | ||
268 | spin_lock(&qp->lock); | 257 | spin_lock(&qp->q.lock); |
269 | if (!(qp->last_in&COMPLETE)) | 258 | if (!(qp->q.last_in&COMPLETE)) |
270 | ipq_kill(qp); | 259 | ipq_kill(qp); |
271 | spin_unlock(&qp->lock); | 260 | spin_unlock(&qp->q.lock); |
272 | 261 | ||
273 | ipq_put(qp, &work); | 262 | ipq_put(qp, &work); |
274 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 263 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
@@ -282,9 +271,9 @@ static void ip_expire(unsigned long arg) | |||
282 | { | 271 | { |
283 | struct ipq *qp = (struct ipq *) arg; | 272 | struct ipq *qp = (struct ipq *) arg; |
284 | 273 | ||
285 | spin_lock(&qp->lock); | 274 | spin_lock(&qp->q.lock); |
286 | 275 | ||
287 | if (qp->last_in & COMPLETE) | 276 | if (qp->q.last_in & COMPLETE) |
288 | goto out; | 277 | goto out; |
289 | 278 | ||
290 | ipq_kill(qp); | 279 | ipq_kill(qp); |
@@ -292,8 +281,8 @@ static void ip_expire(unsigned long arg) | |||
292 | IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); | 281 | IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); |
293 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 282 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
294 | 283 | ||
295 | if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) { | 284 | if ((qp->q.last_in&FIRST_IN) && qp->q.fragments != NULL) { |
296 | struct sk_buff *head = qp->fragments; | 285 | struct sk_buff *head = qp->q.fragments; |
297 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | 286 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ |
298 | if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) { | 287 | if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) { |
299 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 288 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); |
@@ -301,7 +290,7 @@ static void ip_expire(unsigned long arg) | |||
301 | } | 290 | } |
302 | } | 291 | } |
303 | out: | 292 | out: |
304 | spin_unlock(&qp->lock); | 293 | spin_unlock(&qp->q.lock); |
305 | ipq_put(qp, NULL); | 294 | ipq_put(qp, NULL); |
306 | } | 295 | } |
307 | 296 | ||
@@ -323,15 +312,15 @@ static struct ipq *ip_frag_intern(struct ipq *qp_in) | |||
323 | * such entry could be created on other cpu, while we | 312 | * such entry could be created on other cpu, while we |
324 | * promoted read lock to write lock. | 313 | * promoted read lock to write lock. |
325 | */ | 314 | */ |
326 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { | 315 | hlist_for_each_entry(qp, n, &ipq_hash[hash], q.list) { |
327 | if (qp->id == qp_in->id && | 316 | if (qp->id == qp_in->id && |
328 | qp->saddr == qp_in->saddr && | 317 | qp->saddr == qp_in->saddr && |
329 | qp->daddr == qp_in->daddr && | 318 | qp->daddr == qp_in->daddr && |
330 | qp->protocol == qp_in->protocol && | 319 | qp->protocol == qp_in->protocol && |
331 | qp->user == qp_in->user) { | 320 | qp->user == qp_in->user) { |
332 | atomic_inc(&qp->refcnt); | 321 | atomic_inc(&qp->q.refcnt); |
333 | write_unlock(&ipfrag_lock); | 322 | write_unlock(&ipfrag_lock); |
334 | qp_in->last_in |= COMPLETE; | 323 | qp_in->q.last_in |= COMPLETE; |
335 | ipq_put(qp_in, NULL); | 324 | ipq_put(qp_in, NULL); |
336 | return qp; | 325 | return qp; |
337 | } | 326 | } |
@@ -339,13 +328,13 @@ static struct ipq *ip_frag_intern(struct ipq *qp_in) | |||
339 | #endif | 328 | #endif |
340 | qp = qp_in; | 329 | qp = qp_in; |
341 | 330 | ||
342 | if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) | 331 | if (!mod_timer(&qp->q.timer, jiffies + sysctl_ipfrag_time)) |
343 | atomic_inc(&qp->refcnt); | 332 | atomic_inc(&qp->q.refcnt); |
344 | 333 | ||
345 | atomic_inc(&qp->refcnt); | 334 | atomic_inc(&qp->q.refcnt); |
346 | hlist_add_head(&qp->list, &ipq_hash[hash]); | 335 | hlist_add_head(&qp->q.list, &ipq_hash[hash]); |
347 | INIT_LIST_HEAD(&qp->lru_list); | 336 | INIT_LIST_HEAD(&qp->q.lru_list); |
348 | list_add_tail(&qp->lru_list, &ipq_lru_list); | 337 | list_add_tail(&qp->q.lru_list, &ipq_lru_list); |
349 | ip_frag_nqueues++; | 338 | ip_frag_nqueues++; |
350 | write_unlock(&ipfrag_lock); | 339 | write_unlock(&ipfrag_lock); |
351 | return qp; | 340 | return qp; |
@@ -360,23 +349,23 @@ static struct ipq *ip_frag_create(struct iphdr *iph, u32 user) | |||
360 | goto out_nomem; | 349 | goto out_nomem; |
361 | 350 | ||
362 | qp->protocol = iph->protocol; | 351 | qp->protocol = iph->protocol; |
363 | qp->last_in = 0; | 352 | qp->q.last_in = 0; |
364 | qp->id = iph->id; | 353 | qp->id = iph->id; |
365 | qp->saddr = iph->saddr; | 354 | qp->saddr = iph->saddr; |
366 | qp->daddr = iph->daddr; | 355 | qp->daddr = iph->daddr; |
367 | qp->user = user; | 356 | qp->user = user; |
368 | qp->len = 0; | 357 | qp->q.len = 0; |
369 | qp->meat = 0; | 358 | qp->q.meat = 0; |
370 | qp->fragments = NULL; | 359 | qp->q.fragments = NULL; |
371 | qp->iif = 0; | 360 | qp->iif = 0; |
372 | qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL; | 361 | qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL; |
373 | 362 | ||
374 | /* Initialize a timer for this entry. */ | 363 | /* Initialize a timer for this entry. */ |
375 | init_timer(&qp->timer); | 364 | init_timer(&qp->q.timer); |
376 | qp->timer.data = (unsigned long) qp; /* pointer to queue */ | 365 | qp->q.timer.data = (unsigned long) qp; /* pointer to queue */ |
377 | qp->timer.function = ip_expire; /* expire function */ | 366 | qp->q.timer.function = ip_expire; /* expire function */ |
378 | spin_lock_init(&qp->lock); | 367 | spin_lock_init(&qp->q.lock); |
379 | atomic_set(&qp->refcnt, 1); | 368 | atomic_set(&qp->q.refcnt, 1); |
380 | 369 | ||
381 | return ip_frag_intern(qp); | 370 | return ip_frag_intern(qp); |
382 | 371 | ||
@@ -400,13 +389,13 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | |||
400 | 389 | ||
401 | read_lock(&ipfrag_lock); | 390 | read_lock(&ipfrag_lock); |
402 | hash = ipqhashfn(id, saddr, daddr, protocol); | 391 | hash = ipqhashfn(id, saddr, daddr, protocol); |
403 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { | 392 | hlist_for_each_entry(qp, n, &ipq_hash[hash], q.list) { |
404 | if (qp->id == id && | 393 | if (qp->id == id && |
405 | qp->saddr == saddr && | 394 | qp->saddr == saddr && |
406 | qp->daddr == daddr && | 395 | qp->daddr == daddr && |
407 | qp->protocol == protocol && | 396 | qp->protocol == protocol && |
408 | qp->user == user) { | 397 | qp->user == user) { |
409 | atomic_inc(&qp->refcnt); | 398 | atomic_inc(&qp->q.refcnt); |
410 | read_unlock(&ipfrag_lock); | 399 | read_unlock(&ipfrag_lock); |
411 | return qp; | 400 | return qp; |
412 | } | 401 | } |
@@ -432,7 +421,7 @@ static inline int ip_frag_too_far(struct ipq *qp) | |||
432 | end = atomic_inc_return(&peer->rid); | 421 | end = atomic_inc_return(&peer->rid); |
433 | qp->rid = end; | 422 | qp->rid = end; |
434 | 423 | ||
435 | rc = qp->fragments && (end - start) > max; | 424 | rc = qp->q.fragments && (end - start) > max; |
436 | 425 | ||
437 | if (rc) { | 426 | if (rc) { |
438 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 427 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
@@ -445,22 +434,22 @@ static int ip_frag_reinit(struct ipq *qp) | |||
445 | { | 434 | { |
446 | struct sk_buff *fp; | 435 | struct sk_buff *fp; |
447 | 436 | ||
448 | if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) { | 437 | if (!mod_timer(&qp->q.timer, jiffies + sysctl_ipfrag_time)) { |
449 | atomic_inc(&qp->refcnt); | 438 | atomic_inc(&qp->q.refcnt); |
450 | return -ETIMEDOUT; | 439 | return -ETIMEDOUT; |
451 | } | 440 | } |
452 | 441 | ||
453 | fp = qp->fragments; | 442 | fp = qp->q.fragments; |
454 | do { | 443 | do { |
455 | struct sk_buff *xp = fp->next; | 444 | struct sk_buff *xp = fp->next; |
456 | frag_kfree_skb(fp, NULL); | 445 | frag_kfree_skb(fp, NULL); |
457 | fp = xp; | 446 | fp = xp; |
458 | } while (fp); | 447 | } while (fp); |
459 | 448 | ||
460 | qp->last_in = 0; | 449 | qp->q.last_in = 0; |
461 | qp->len = 0; | 450 | qp->q.len = 0; |
462 | qp->meat = 0; | 451 | qp->q.meat = 0; |
463 | qp->fragments = NULL; | 452 | qp->q.fragments = NULL; |
464 | qp->iif = 0; | 453 | qp->iif = 0; |
465 | 454 | ||
466 | return 0; | 455 | return 0; |
@@ -475,7 +464,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
475 | int ihl, end; | 464 | int ihl, end; |
476 | int err = -ENOENT; | 465 | int err = -ENOENT; |
477 | 466 | ||
478 | if (qp->last_in & COMPLETE) | 467 | if (qp->q.last_in & COMPLETE) |
479 | goto err; | 468 | goto err; |
480 | 469 | ||
481 | if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) && | 470 | if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) && |
@@ -500,22 +489,22 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
500 | /* If we already have some bits beyond end | 489 | /* If we already have some bits beyond end |
501 | * or have different end, the segment is corrrupted. | 490 | * or have different end, the segment is corrrupted. |
502 | */ | 491 | */ |
503 | if (end < qp->len || | 492 | if (end < qp->q.len || |
504 | ((qp->last_in & LAST_IN) && end != qp->len)) | 493 | ((qp->q.last_in & LAST_IN) && end != qp->q.len)) |
505 | goto err; | 494 | goto err; |
506 | qp->last_in |= LAST_IN; | 495 | qp->q.last_in |= LAST_IN; |
507 | qp->len = end; | 496 | qp->q.len = end; |
508 | } else { | 497 | } else { |
509 | if (end&7) { | 498 | if (end&7) { |
510 | end &= ~7; | 499 | end &= ~7; |
511 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 500 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) |
512 | skb->ip_summed = CHECKSUM_NONE; | 501 | skb->ip_summed = CHECKSUM_NONE; |
513 | } | 502 | } |
514 | if (end > qp->len) { | 503 | if (end > qp->q.len) { |
515 | /* Some bits beyond end -> corruption. */ | 504 | /* Some bits beyond end -> corruption. */ |
516 | if (qp->last_in & LAST_IN) | 505 | if (qp->q.last_in & LAST_IN) |
517 | goto err; | 506 | goto err; |
518 | qp->len = end; | 507 | qp->q.len = end; |
519 | } | 508 | } |
520 | } | 509 | } |
521 | if (end == offset) | 510 | if (end == offset) |
@@ -534,7 +523,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
534 | * this fragment, right? | 523 | * this fragment, right? |
535 | */ | 524 | */ |
536 | prev = NULL; | 525 | prev = NULL; |
537 | for (next = qp->fragments; next != NULL; next = next->next) { | 526 | for (next = qp->q.fragments; next != NULL; next = next->next) { |
538 | if (FRAG_CB(next)->offset >= offset) | 527 | if (FRAG_CB(next)->offset >= offset) |
539 | break; /* bingo! */ | 528 | break; /* bingo! */ |
540 | prev = next; | 529 | prev = next; |
@@ -572,7 +561,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
572 | if (!pskb_pull(next, i)) | 561 | if (!pskb_pull(next, i)) |
573 | goto err; | 562 | goto err; |
574 | FRAG_CB(next)->offset += i; | 563 | FRAG_CB(next)->offset += i; |
575 | qp->meat -= i; | 564 | qp->q.meat -= i; |
576 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | 565 | if (next->ip_summed != CHECKSUM_UNNECESSARY) |
577 | next->ip_summed = CHECKSUM_NONE; | 566 | next->ip_summed = CHECKSUM_NONE; |
578 | break; | 567 | break; |
@@ -587,9 +576,9 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
587 | if (prev) | 576 | if (prev) |
588 | prev->next = next; | 577 | prev->next = next; |
589 | else | 578 | else |
590 | qp->fragments = next; | 579 | qp->q.fragments = next; |
591 | 580 | ||
592 | qp->meat -= free_it->len; | 581 | qp->q.meat -= free_it->len; |
593 | frag_kfree_skb(free_it, NULL); | 582 | frag_kfree_skb(free_it, NULL); |
594 | } | 583 | } |
595 | } | 584 | } |
@@ -601,24 +590,24 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
601 | if (prev) | 590 | if (prev) |
602 | prev->next = skb; | 591 | prev->next = skb; |
603 | else | 592 | else |
604 | qp->fragments = skb; | 593 | qp->q.fragments = skb; |
605 | 594 | ||
606 | dev = skb->dev; | 595 | dev = skb->dev; |
607 | if (dev) { | 596 | if (dev) { |
608 | qp->iif = dev->ifindex; | 597 | qp->iif = dev->ifindex; |
609 | skb->dev = NULL; | 598 | skb->dev = NULL; |
610 | } | 599 | } |
611 | qp->stamp = skb->tstamp; | 600 | qp->q.stamp = skb->tstamp; |
612 | qp->meat += skb->len; | 601 | qp->q.meat += skb->len; |
613 | atomic_add(skb->truesize, &ip_frag_mem); | 602 | atomic_add(skb->truesize, &ip_frag_mem); |
614 | if (offset == 0) | 603 | if (offset == 0) |
615 | qp->last_in |= FIRST_IN; | 604 | qp->q.last_in |= FIRST_IN; |
616 | 605 | ||
617 | if (qp->last_in == (FIRST_IN | LAST_IN) && qp->meat == qp->len) | 606 | if (qp->q.last_in == (FIRST_IN | LAST_IN) && qp->q.meat == qp->q.len) |
618 | return ip_frag_reasm(qp, prev, dev); | 607 | return ip_frag_reasm(qp, prev, dev); |
619 | 608 | ||
620 | write_lock(&ipfrag_lock); | 609 | write_lock(&ipfrag_lock); |
621 | list_move_tail(&qp->lru_list, &ipq_lru_list); | 610 | list_move_tail(&qp->q.lru_list, &ipq_lru_list); |
622 | write_unlock(&ipfrag_lock); | 611 | write_unlock(&ipfrag_lock); |
623 | return -EINPROGRESS; | 612 | return -EINPROGRESS; |
624 | 613 | ||
@@ -634,7 +623,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
634 | struct net_device *dev) | 623 | struct net_device *dev) |
635 | { | 624 | { |
636 | struct iphdr *iph; | 625 | struct iphdr *iph; |
637 | struct sk_buff *fp, *head = qp->fragments; | 626 | struct sk_buff *fp, *head = qp->q.fragments; |
638 | int len; | 627 | int len; |
639 | int ihlen; | 628 | int ihlen; |
640 | int err; | 629 | int err; |
@@ -652,11 +641,11 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
652 | fp->next = head->next; | 641 | fp->next = head->next; |
653 | prev->next = fp; | 642 | prev->next = fp; |
654 | 643 | ||
655 | skb_morph(head, qp->fragments); | 644 | skb_morph(head, qp->q.fragments); |
656 | head->next = qp->fragments->next; | 645 | head->next = qp->q.fragments->next; |
657 | 646 | ||
658 | kfree_skb(qp->fragments); | 647 | kfree_skb(qp->q.fragments); |
659 | qp->fragments = head; | 648 | qp->q.fragments = head; |
660 | } | 649 | } |
661 | 650 | ||
662 | BUG_TRAP(head != NULL); | 651 | BUG_TRAP(head != NULL); |
@@ -664,7 +653,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
664 | 653 | ||
665 | /* Allocate a new buffer for the datagram. */ | 654 | /* Allocate a new buffer for the datagram. */ |
666 | ihlen = ip_hdrlen(head); | 655 | ihlen = ip_hdrlen(head); |
667 | len = ihlen + qp->len; | 656 | len = ihlen + qp->q.len; |
668 | 657 | ||
669 | err = -E2BIG; | 658 | err = -E2BIG; |
670 | if (len > 65535) | 659 | if (len > 65535) |
@@ -715,13 +704,13 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
715 | 704 | ||
716 | head->next = NULL; | 705 | head->next = NULL; |
717 | head->dev = dev; | 706 | head->dev = dev; |
718 | head->tstamp = qp->stamp; | 707 | head->tstamp = qp->q.stamp; |
719 | 708 | ||
720 | iph = ip_hdr(head); | 709 | iph = ip_hdr(head); |
721 | iph->frag_off = 0; | 710 | iph->frag_off = 0; |
722 | iph->tot_len = htons(len); | 711 | iph->tot_len = htons(len); |
723 | IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 712 | IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS); |
724 | qp->fragments = NULL; | 713 | qp->q.fragments = NULL; |
725 | return 0; | 714 | return 0; |
726 | 715 | ||
727 | out_nomem: | 716 | out_nomem: |
@@ -753,11 +742,11 @@ int ip_defrag(struct sk_buff *skb, u32 user) | |||
753 | if ((qp = ip_find(ip_hdr(skb), user)) != NULL) { | 742 | if ((qp = ip_find(ip_hdr(skb), user)) != NULL) { |
754 | int ret; | 743 | int ret; |
755 | 744 | ||
756 | spin_lock(&qp->lock); | 745 | spin_lock(&qp->q.lock); |
757 | 746 | ||
758 | ret = ip_frag_queue(qp, skb); | 747 | ret = ip_frag_queue(qp, skb); |
759 | 748 | ||
760 | spin_unlock(&qp->lock); | 749 | spin_unlock(&qp->q.lock); |
761 | ipq_put(qp, NULL); | 750 | ipq_put(qp, NULL); |
762 | return ret; | 751 | return ret; |
763 | } | 752 | } |