diff options
Diffstat (limited to 'net/ipv4/ip_fragment.c')
-rw-r--r-- | net/ipv4/ip_fragment.c | 57 |
1 files changed, 21 insertions, 36 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 0d6cff1de5a3..928259dbc0f8 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -142,6 +142,19 @@ static int ip4_frag_equal(struct inet_frag_queue *q1, | |||
142 | qp1->user == qp2->user); | 142 | qp1->user == qp2->user); |
143 | } | 143 | } |
144 | 144 | ||
145 | static int ip4_frag_match(struct inet_frag_queue *q, void *a) | ||
146 | { | ||
147 | struct ipq *qp; | ||
148 | struct ip4_create_arg *arg = a; | ||
149 | |||
150 | qp = container_of(q, struct ipq, q); | ||
151 | return (qp->id == arg->iph->id && | ||
152 | qp->saddr == arg->iph->saddr && | ||
153 | qp->daddr == arg->iph->daddr && | ||
154 | qp->protocol == arg->iph->protocol && | ||
155 | qp->user == arg->user); | ||
156 | } | ||
157 | |||
145 | /* Memory Tracking Functions. */ | 158 | /* Memory Tracking Functions. */ |
146 | static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work) | 159 | static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work) |
147 | { | 160 | { |
@@ -235,18 +248,20 @@ out: | |||
235 | ipq_put(qp); | 248 | ipq_put(qp); |
236 | } | 249 | } |
237 | 250 | ||
238 | /* Creation primitives. */ | 251 | /* Find the correct entry in the "incomplete datagrams" queue for |
239 | 252 | * this IP datagram, and create new one, if nothing is found. | |
240 | /* Add an entry to the 'ipq' queue for a newly received IP datagram. */ | 253 | */ |
241 | static struct ipq *ip_frag_create(struct iphdr *iph, u32 user, unsigned int h) | 254 | static inline struct ipq *ip_find(struct iphdr *iph, u32 user) |
242 | { | 255 | { |
243 | struct inet_frag_queue *q; | 256 | struct inet_frag_queue *q; |
244 | struct ip4_create_arg arg; | 257 | struct ip4_create_arg arg; |
258 | unsigned int hash; | ||
245 | 259 | ||
246 | arg.iph = iph; | 260 | arg.iph = iph; |
247 | arg.user = user; | 261 | arg.user = user; |
262 | hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); | ||
248 | 263 | ||
249 | q = inet_frag_create(&ip4_frags, &arg, h); | 264 | q = inet_frag_find(&ip4_frags, &arg, hash); |
250 | if (q == NULL) | 265 | if (q == NULL) |
251 | goto out_nomem; | 266 | goto out_nomem; |
252 | 267 | ||
@@ -257,37 +272,6 @@ out_nomem: | |||
257 | return NULL; | 272 | return NULL; |
258 | } | 273 | } |
259 | 274 | ||
260 | /* Find the correct entry in the "incomplete datagrams" queue for | ||
261 | * this IP datagram, and create new one, if nothing is found. | ||
262 | */ | ||
263 | static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | ||
264 | { | ||
265 | __be16 id = iph->id; | ||
266 | __be32 saddr = iph->saddr; | ||
267 | __be32 daddr = iph->daddr; | ||
268 | __u8 protocol = iph->protocol; | ||
269 | unsigned int hash; | ||
270 | struct ipq *qp; | ||
271 | struct hlist_node *n; | ||
272 | |||
273 | read_lock(&ip4_frags.lock); | ||
274 | hash = ipqhashfn(id, saddr, daddr, protocol); | ||
275 | hlist_for_each_entry(qp, n, &ip4_frags.hash[hash], q.list) { | ||
276 | if (qp->id == id && | ||
277 | qp->saddr == saddr && | ||
278 | qp->daddr == daddr && | ||
279 | qp->protocol == protocol && | ||
280 | qp->user == user) { | ||
281 | atomic_inc(&qp->q.refcnt); | ||
282 | read_unlock(&ip4_frags.lock); | ||
283 | return qp; | ||
284 | } | ||
285 | } | ||
286 | read_unlock(&ip4_frags.lock); | ||
287 | |||
288 | return ip_frag_create(iph, user, hash); | ||
289 | } | ||
290 | |||
291 | /* Is the fragment too far ahead to be part of ipq? */ | 275 | /* Is the fragment too far ahead to be part of ipq? */ |
292 | static inline int ip_frag_too_far(struct ipq *qp) | 276 | static inline int ip_frag_too_far(struct ipq *qp) |
293 | { | 277 | { |
@@ -648,6 +632,7 @@ void __init ipfrag_init(void) | |||
648 | ip4_frags.skb_free = NULL; | 632 | ip4_frags.skb_free = NULL; |
649 | ip4_frags.qsize = sizeof(struct ipq); | 633 | ip4_frags.qsize = sizeof(struct ipq); |
650 | ip4_frags.equal = ip4_frag_equal; | 634 | ip4_frags.equal = ip4_frag_equal; |
635 | ip4_frags.match = ip4_frag_match; | ||
651 | ip4_frags.frag_expire = ip_expire; | 636 | ip4_frags.frag_expire = ip_expire; |
652 | inet_frags_init(&ip4_frags); | 637 | inet_frags_init(&ip4_frags); |
653 | } | 638 | } |