Deleted Added
full compact
pf_norm.c (126259) pf_norm.c (126261)
1/* $FreeBSD: head/sys/contrib/pf/net/pf_norm.c 126261 2004-02-26 02:34:12Z mlaier $ */
1/* $OpenBSD: pf_norm.c,v 1.75 2003/08/29 01:49:08 dhartmei Exp $ */
2
3/*
4 * Copyright 2001 Niels Provos <provos@citi.umich.edu>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 11 unchanged lines hidden (view full) ---

20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
2/* $OpenBSD: pf_norm.c,v 1.75 2003/08/29 01:49:08 dhartmei Exp $ */
3
4/*
5 * Copyright 2001 Niels Provos <provos@citi.umich.edu>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions

--- 11 unchanged lines hidden (view full) ---

21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#if defined(__FreeBSD__)
30#include "opt_inet.h"
31#include "opt_inet6.h"
32#include "opt_random_ip_id.h" /* or ip_var does not export it */
33#include "opt_pf.h"
34#define NPFLOG DEV_PFLOG
35#else
28#include "pflog.h"
36#include "pflog.h"
37#endif
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/mbuf.h>
33#include <sys/filio.h>
34#include <sys/fcntl.h>
35#include <sys/socket.h>
36#include <sys/kernel.h>
37#include <sys/time.h>
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/mbuf.h>
42#include <sys/filio.h>
43#include <sys/fcntl.h>
44#include <sys/socket.h>
45#include <sys/kernel.h>
46#include <sys/time.h>
47#if !defined(__FreeBSD__)
38#include <sys/pool.h>
48#include <sys/pool.h>
49#endif
39
50
51#if !defined(__FreeBSD__)
40#include <dev/rndvar.h>
52#include <dev/rndvar.h>
53#endif
41#include <net/if.h>
42#include <net/if_types.h>
43#include <net/bpf.h>
44#include <net/route.h>
45#include <net/if_pflog.h>
46
47#include <netinet/in.h>
48#include <netinet/in_var.h>

--- 6 unchanged lines hidden (view full) ---

55#include <netinet/ip_icmp.h>
56
57#ifdef INET6
58#include <netinet/ip6.h>
59#endif /* INET6 */
60
61#include <net/pfvar.h>
62
54#include <net/if.h>
55#include <net/if_types.h>
56#include <net/bpf.h>
57#include <net/route.h>
58#include <net/if_pflog.h>
59
60#include <netinet/in.h>
61#include <netinet/in_var.h>

--- 6 unchanged lines hidden (view full) ---

68#include <netinet/ip_icmp.h>
69
70#ifdef INET6
71#include <netinet/ip6.h>
72#endif /* INET6 */
73
74#include <net/pfvar.h>
75
76#if defined(__FreeBSD__) && defined(INET6)
77/*
78 * XXX: This should go to netinet/ip6.h (KAME)
79 */
80/* IPv6 options: common part */
81struct ip6_opt {
82 u_int8_t ip6o_type;
83 u_int8_t ip6o_len;
84} __packed;
85
86/* Jumbo Payload Option */
87struct ip6_opt_jumbo {
88 u_int8_t ip6oj_type;
89 u_int8_t ip6oj_len;
90 u_int8_t ip6oj_jumbo_len[4];
91} __packed;
92
93/* NSAP Address Option */
94struct ip6_opt_nsap {
95 u_int8_t ip6on_type;
96 u_int8_t ip6on_len;
97 u_int8_t ip6on_src_nsap_len;
98 u_int8_t ip6on_dst_nsap_len;
99 /* followed by source NSAP */
100 /* followed by destination NSAP */
101} __packed;
102
103/* Tunnel Limit Option */
104struct ip6_opt_tunnel {
105 u_int8_t ip6ot_type;
106 u_int8_t ip6ot_len;
107 u_int8_t ip6ot_encap_limit;
108} __packed;
109
110/* Router Alert Option */
111struct ip6_opt_router {
112 u_int8_t ip6or_type;
113 u_int8_t ip6or_len;
114 u_int8_t ip6or_value[2];
115} __packed;
116#endif /* __FreeBSD__ && INET6 */
117
118#if !defined(__FreeBSD__)
63struct pf_frent {
64 LIST_ENTRY(pf_frent) fr_next;
65 struct ip *fr_ip;
66 struct mbuf *fr_m;
67};
68
69struct pf_frcache {
70 LIST_ENTRY(pf_frcache) fr_next;
71 uint16_t fr_off;
72 uint16_t fr_end;
73};
119struct pf_frent {
120 LIST_ENTRY(pf_frent) fr_next;
121 struct ip *fr_ip;
122 struct mbuf *fr_m;
123};
124
125struct pf_frcache {
126 LIST_ENTRY(pf_frcache) fr_next;
127 uint16_t fr_off;
128 uint16_t fr_end;
129};
130#endif
74
75#define PFFRAG_SEENLAST 0x0001 /* Seen the last fragment for this */
76#define PFFRAG_NOBUFFER 0x0002 /* Non-buffering fragment cache */
77#define PFFRAG_DROP 0x0004 /* Drop all fragments */
78#define BUFFER_FRAGMENTS(fr) (!((fr)->fr_flags & PFFRAG_NOBUFFER))
79
131
132#define PFFRAG_SEENLAST 0x0001 /* Seen the last fragment for this */
133#define PFFRAG_NOBUFFER 0x0002 /* Non-buffering fragment cache */
134#define PFFRAG_DROP 0x0004 /* Drop all fragments */
135#define BUFFER_FRAGMENTS(fr) (!((fr)->fr_flags & PFFRAG_NOBUFFER))
136
137#if !defined(__FreeBSD__)
80struct pf_fragment {
81 RB_ENTRY(pf_fragment) fr_entry;
82 TAILQ_ENTRY(pf_fragment) frag_next;
83 struct in_addr fr_src;
84 struct in_addr fr_dst;
85 u_int8_t fr_p; /* protocol of this fragment */
86 u_int8_t fr_flags; /* status flags */
87 u_int16_t fr_id; /* fragment id for reassemble */
88 u_int16_t fr_max; /* fragment data max */
89 u_int32_t fr_timeout;
90#define fr_queue fr_u.fru_queue
91#define fr_cache fr_u.fru_cache
92 union {
93 LIST_HEAD(pf_fragq, pf_frent) fru_queue; /* buffering */
94 LIST_HEAD(pf_cacheq, pf_frcache) fru_cache; /* non-buf */
95 } fr_u;
96};
138struct pf_fragment {
139 RB_ENTRY(pf_fragment) fr_entry;
140 TAILQ_ENTRY(pf_fragment) frag_next;
141 struct in_addr fr_src;
142 struct in_addr fr_dst;
143 u_int8_t fr_p; /* protocol of this fragment */
144 u_int8_t fr_flags; /* status flags */
145 u_int16_t fr_id; /* fragment id for reassemble */
146 u_int16_t fr_max; /* fragment data max */
147 u_int32_t fr_timeout;
148#define fr_queue fr_u.fru_queue
149#define fr_cache fr_u.fru_cache
150 union {
151 LIST_HEAD(pf_fragq, pf_frent) fru_queue; /* buffering */
152 LIST_HEAD(pf_cacheq, pf_frcache) fru_cache; /* non-buf */
153 } fr_u;
154};
155#endif
97
98TAILQ_HEAD(pf_fragqueue, pf_fragment) pf_fragqueue;
99TAILQ_HEAD(pf_cachequeue, pf_fragment) pf_cachequeue;
100
101static __inline int pf_frag_compare(struct pf_fragment *,
102 struct pf_fragment *);
103RB_HEAD(pf_frag_tree, pf_fragment) pf_frag_tree, pf_cache_tree;
104RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
105RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
106
107/* Private prototypes */
156
157TAILQ_HEAD(pf_fragqueue, pf_fragment) pf_fragqueue;
158TAILQ_HEAD(pf_cachequeue, pf_fragment) pf_cachequeue;
159
160static __inline int pf_frag_compare(struct pf_fragment *,
161 struct pf_fragment *);
162RB_HEAD(pf_frag_tree, pf_fragment) pf_frag_tree, pf_cache_tree;
163RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
164RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
165
166/* Private prototypes */
167#ifndef RANDOM_IP_ID
168extern u_int16_t ip_randomid(void);
169#endif
108void pf_ip2key(struct pf_fragment *, struct ip *);
109void pf_remove_fragment(struct pf_fragment *);
110void pf_flush_fragments(void);
111void pf_free_fragment(struct pf_fragment *);
112struct pf_fragment *pf_find_fragment(struct ip *, struct pf_frag_tree *);
113struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment **,
114 struct pf_frent *, int);
115struct mbuf *pf_fragcache(struct mbuf **, struct ip*,
116 struct pf_fragment **, int, int, int *);
117u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t);
118int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
119 struct tcphdr *, int);
120
121#define DPFPRINTF(x) if (pf_status.debug >= PF_DEBUG_MISC) \
122 { printf("%s: ", __func__); printf x ;}
123
124/* Globals */
170void pf_ip2key(struct pf_fragment *, struct ip *);
171void pf_remove_fragment(struct pf_fragment *);
172void pf_flush_fragments(void);
173void pf_free_fragment(struct pf_fragment *);
174struct pf_fragment *pf_find_fragment(struct ip *, struct pf_frag_tree *);
175struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment **,
176 struct pf_frent *, int);
177struct mbuf *pf_fragcache(struct mbuf **, struct ip*,
178 struct pf_fragment **, int, int, int *);
179u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t);
180int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
181 struct tcphdr *, int);
182
183#define DPFPRINTF(x) if (pf_status.debug >= PF_DEBUG_MISC) \
184 { printf("%s: ", __func__); printf x ;}
185
186/* Globals */
187#if defined(__FreeBSD__)
188uma_zone_t pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
189uma_zone_t pf_state_scrub_pl;
190#else
125struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
126struct pool pf_state_scrub_pl;
191struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
192struct pool pf_state_scrub_pl;
193#endif
127int pf_nfrents, pf_ncache;
128
129void
130pf_normalize_init(void)
131{
194int pf_nfrents, pf_ncache;
195
196void
197pf_normalize_init(void)
198{
199#if defined(__FreeBSD__)
200 /*
201 * XXX
202 * No high water mark support(It's hint not hard limit).
203 * uma_zone_set_max(pf_frag_pl, PFFRAG_FRAG_HIWAT);
204 */
205 uma_zone_set_max(pf_frent_pl, PFFRAG_FRENT_HIWAT);
206 uma_zone_set_max(pf_cache_pl, PFFRAG_FRCACHE_HIWAT);
207 uma_zone_set_max(pf_cent_pl, PFFRAG_FRCENT_HIWAT);
208#else
132 pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent",
133 NULL);
134 pool_init(&pf_frag_pl, sizeof(struct pf_fragment), 0, 0, 0, "pffrag",
135 NULL);
136 pool_init(&pf_cache_pl, sizeof(struct pf_fragment), 0, 0, 0,
137 "pffrcache", NULL);
138 pool_init(&pf_cent_pl, sizeof(struct pf_frcache), 0, 0, 0, "pffrcent",
139 NULL);
140 pool_init(&pf_state_scrub_pl, sizeof(struct pf_state_scrub), 0, 0, 0,
141 "pfstscr", NULL);
142
143 pool_sethiwat(&pf_frag_pl, PFFRAG_FRAG_HIWAT);
144 pool_sethardlimit(&pf_frent_pl, PFFRAG_FRENT_HIWAT, NULL, 0);
145 pool_sethardlimit(&pf_cache_pl, PFFRAG_FRCACHE_HIWAT, NULL, 0);
146 pool_sethardlimit(&pf_cent_pl, PFFRAG_FRCENT_HIWAT, NULL, 0);
209 pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent",
210 NULL);
211 pool_init(&pf_frag_pl, sizeof(struct pf_fragment), 0, 0, 0, "pffrag",
212 NULL);
213 pool_init(&pf_cache_pl, sizeof(struct pf_fragment), 0, 0, 0,
214 "pffrcache", NULL);
215 pool_init(&pf_cent_pl, sizeof(struct pf_frcache), 0, 0, 0, "pffrcent",
216 NULL);
217 pool_init(&pf_state_scrub_pl, sizeof(struct pf_state_scrub), 0, 0, 0,
218 "pfstscr", NULL);
219
220 pool_sethiwat(&pf_frag_pl, PFFRAG_FRAG_HIWAT);
221 pool_sethardlimit(&pf_frent_pl, PFFRAG_FRENT_HIWAT, NULL, 0);
222 pool_sethardlimit(&pf_cache_pl, PFFRAG_FRCACHE_HIWAT, NULL, 0);
223 pool_sethardlimit(&pf_cent_pl, PFFRAG_FRCENT_HIWAT, NULL, 0);
224#endif
147
148 TAILQ_INIT(&pf_fragqueue);
149 TAILQ_INIT(&pf_cachequeue);
150}
151
152static __inline int
153pf_frag_compare(struct pf_fragment *a, struct pf_fragment *b)
154{

--- 13 unchanged lines hidden (view full) ---

168 return (1);
169 return (0);
170}
171
172void
173pf_purge_expired_fragments(void)
174{
175 struct pf_fragment *frag;
225
226 TAILQ_INIT(&pf_fragqueue);
227 TAILQ_INIT(&pf_cachequeue);
228}
229
230static __inline int
231pf_frag_compare(struct pf_fragment *a, struct pf_fragment *b)
232{

--- 13 unchanged lines hidden (view full) ---

246 return (1);
247 return (0);
248}
249
250void
251pf_purge_expired_fragments(void)
252{
253 struct pf_fragment *frag;
254#if defined(__FreeBSD__)
255 u_int32_t expire = time_second -
256 pf_default_rule.timeout[PFTM_FRAG];
257#else
176 u_int32_t expire = time.tv_sec -
177 pf_default_rule.timeout[PFTM_FRAG];
258 u_int32_t expire = time.tv_sec -
259 pf_default_rule.timeout[PFTM_FRAG];
260#endif
178
179 while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
261
262 while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
263#if defined(__FreeBSD__)
264 KASSERT((BUFFER_FRAGMENTS(frag)),
265 ("BUFFER_FRAGMENTS(frag) == 0: %s", __FUNCTION__));
266#else
180 KASSERT(BUFFER_FRAGMENTS(frag));
267 KASSERT(BUFFER_FRAGMENTS(frag));
268#endif
181 if (frag->fr_timeout > expire)
182 break;
183
184 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
185 pf_free_fragment(frag);
186 }
187
188 while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
269 if (frag->fr_timeout > expire)
270 break;
271
272 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
273 pf_free_fragment(frag);
274 }
275
276 while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
277#if defined(__FreeBSD__)
278 KASSERT((!BUFFER_FRAGMENTS(frag)),
279 ("BUFFER_FRAGMENTS(frag) != 0: %s", __FUNCTION__));
280#else
189 KASSERT(!BUFFER_FRAGMENTS(frag));
281 KASSERT(!BUFFER_FRAGMENTS(frag));
282#endif
190 if (frag->fr_timeout > expire)
191 break;
192
193 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
194 pf_free_fragment(frag);
283 if (frag->fr_timeout > expire)
284 break;
285
286 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
287 pf_free_fragment(frag);
288#if defined(__FreeBSD__)
289 KASSERT((TAILQ_EMPTY(&pf_cachequeue) ||
290 TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag),
291 ("!(TAILQ_EMPTY() || TAILQ_LAST() == farg): %s",
292 __FUNCTION__));
293#else
195 KASSERT(TAILQ_EMPTY(&pf_cachequeue) ||
196 TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag);
294 KASSERT(TAILQ_EMPTY(&pf_cachequeue) ||
295 TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag);
296#endif
197 }
198}
199
200/*
201 * Try to flush old fragments to make space for new ones
202 */
203
204void

--- 42 unchanged lines hidden (view full) ---

247 pool_put(&pf_frent_pl, frent);
248 pf_nfrents--;
249 }
250 } else {
251 for (frcache = LIST_FIRST(&frag->fr_cache); frcache;
252 frcache = LIST_FIRST(&frag->fr_cache)) {
253 LIST_REMOVE(frcache, fr_next);
254
297 }
298}
299
300/*
301 * Try to flush old fragments to make space for new ones
302 */
303
304void

--- 42 unchanged lines hidden (view full) ---

347 pool_put(&pf_frent_pl, frent);
348 pf_nfrents--;
349 }
350 } else {
351 for (frcache = LIST_FIRST(&frag->fr_cache); frcache;
352 frcache = LIST_FIRST(&frag->fr_cache)) {
353 LIST_REMOVE(frcache, fr_next);
354
355#if defined(__FreeBSD__)
356 KASSERT((LIST_EMPTY(&frag->fr_cache) ||
357 LIST_FIRST(&frag->fr_cache)->fr_off >
358 frcache->fr_end),
359 ("! (LIST_EMPTY() || LIST_FIRST()->fr_off >"
360 " frcache->fr_end): %s", __FUNCTION__));
361#else
255 KASSERT(LIST_EMPTY(&frag->fr_cache) ||
256 LIST_FIRST(&frag->fr_cache)->fr_off >
257 frcache->fr_end);
362 KASSERT(LIST_EMPTY(&frag->fr_cache) ||
363 LIST_FIRST(&frag->fr_cache)->fr_off >
364 frcache->fr_end);
365#endif
258
259 pool_put(&pf_cent_pl, frcache);
260 pf_ncache--;
261 }
262 }
263
264 pf_remove_fragment(frag);
265}

--- 13 unchanged lines hidden (view full) ---

279 struct pf_fragment key;
280 struct pf_fragment *frag;
281
282 pf_ip2key(&key, ip);
283
284 frag = RB_FIND(pf_frag_tree, tree, &key);
285 if (frag != NULL) {
286 /* XXX Are we sure we want to update the timeout? */
366
367 pool_put(&pf_cent_pl, frcache);
368 pf_ncache--;
369 }
370 }
371
372 pf_remove_fragment(frag);
373}

--- 13 unchanged lines hidden (view full) ---

387 struct pf_fragment key;
388 struct pf_fragment *frag;
389
390 pf_ip2key(&key, ip);
391
392 frag = RB_FIND(pf_frag_tree, tree, &key);
393 if (frag != NULL) {
394 /* XXX Are we sure we want to update the timeout? */
395#if defined(__FreeBSD__)
396 frag->fr_timeout = time_second;
397#else
287 frag->fr_timeout = time.tv_sec;
398 frag->fr_timeout = time.tv_sec;
399#endif
288 if (BUFFER_FRAGMENTS(frag)) {
289 TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
290 TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next);
291 } else {
292 TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
293 TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next);
294 }
295 }

--- 26 unchanged lines hidden (view full) ---

322 struct pf_frent *frea, *next;
323 struct pf_frent *frep = NULL;
324 struct ip *ip = frent->fr_ip;
325 int hlen = ip->ip_hl << 2;
326 u_int16_t off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
327 u_int16_t ip_len = ntohs(ip->ip_len) - ip->ip_hl * 4;
328 u_int16_t max = ip_len + off;
329
400 if (BUFFER_FRAGMENTS(frag)) {
401 TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
402 TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next);
403 } else {
404 TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
405 TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next);
406 }
407 }

--- 26 unchanged lines hidden (view full) ---

434 struct pf_frent *frea, *next;
435 struct pf_frent *frep = NULL;
436 struct ip *ip = frent->fr_ip;
437 int hlen = ip->ip_hl << 2;
438 u_int16_t off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
439 u_int16_t ip_len = ntohs(ip->ip_len) - ip->ip_hl * 4;
440 u_int16_t max = ip_len + off;
441
442#if defined(__FreeBSD__)
443 KASSERT((*frag == NULL || BUFFER_FRAGMENTS(*frag)),
444 ("! (*frag == NULL || BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__));
445#else
330 KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag));
446 KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag));
447#endif
331
332 /* Strip off ip header */
333 m->m_data += hlen;
334 m->m_len -= hlen;
335
336 /* Create a new reassembly queue for this packet */
337 if (*frag == NULL) {
338 *frag = pool_get(&pf_frag_pl, PR_NOWAIT);

--- 5 unchanged lines hidden (view full) ---

344 }
345
346 (*frag)->fr_flags = 0;
347 (*frag)->fr_max = 0;
348 (*frag)->fr_src = frent->fr_ip->ip_src;
349 (*frag)->fr_dst = frent->fr_ip->ip_dst;
350 (*frag)->fr_p = frent->fr_ip->ip_p;
351 (*frag)->fr_id = frent->fr_ip->ip_id;
448
449 /* Strip off ip header */
450 m->m_data += hlen;
451 m->m_len -= hlen;
452
453 /* Create a new reassembly queue for this packet */
454 if (*frag == NULL) {
455 *frag = pool_get(&pf_frag_pl, PR_NOWAIT);

--- 5 unchanged lines hidden (view full) ---

461 }
462
463 (*frag)->fr_flags = 0;
464 (*frag)->fr_max = 0;
465 (*frag)->fr_src = frent->fr_ip->ip_src;
466 (*frag)->fr_dst = frent->fr_ip->ip_dst;
467 (*frag)->fr_p = frent->fr_ip->ip_p;
468 (*frag)->fr_id = frent->fr_ip->ip_id;
469#if defined(__FreeBSD__)
470 (*frag)->fr_timeout = time_second;
471#else
352 (*frag)->fr_timeout = time.tv_sec;
472 (*frag)->fr_timeout = time.tv_sec;
473#endif
353 LIST_INIT(&(*frag)->fr_queue);
354
355 RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag);
356 TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next);
357
358 /* We do not have a previous fragment */
359 frep = NULL;
360 goto insert;

--- 4 unchanged lines hidden (view full) ---

365 * - off contains the real shifted offset.
366 */
367 LIST_FOREACH(frea, &(*frag)->fr_queue, fr_next) {
368 if (FR_IP_OFF(frea) > off)
369 break;
370 frep = frea;
371 }
372
474 LIST_INIT(&(*frag)->fr_queue);
475
476 RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag);
477 TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next);
478
479 /* We do not have a previous fragment */
480 frep = NULL;
481 goto insert;

--- 4 unchanged lines hidden (view full) ---

486 * - off contains the real shifted offset.
487 */
488 LIST_FOREACH(frea, &(*frag)->fr_queue, fr_next) {
489 if (FR_IP_OFF(frea) > off)
490 break;
491 frep = frea;
492 }
493
494#if defined(__FreeBSD__)
495 KASSERT((frep != NULL || frea != NULL),
496 ("!(frep != NULL || frea != NULL): %s", __FUNCTION__));;
497#else
373 KASSERT(frep != NULL || frea != NULL);
498 KASSERT(frep != NULL || frea != NULL);
499#endif
374
375 if (frep != NULL &&
376 FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl *
377 4 > off)
378 {
379 u_int16_t precut;
380
381 precut = FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) -

--- 68 unchanged lines hidden (view full) ---

450 }
451 }
452 DPFPRINTF(("%d < %d?\n", off, (*frag)->fr_max));
453 if (off < (*frag)->fr_max)
454 return (NULL);
455
456 /* We have all the data */
457 frent = LIST_FIRST(&(*frag)->fr_queue);
500
501 if (frep != NULL &&
502 FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl *
503 4 > off)
504 {
505 u_int16_t precut;
506
507 precut = FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) -

--- 68 unchanged lines hidden (view full) ---

576 }
577 }
578 DPFPRINTF(("%d < %d?\n", off, (*frag)->fr_max));
579 if (off < (*frag)->fr_max)
580 return (NULL);
581
582 /* We have all the data */
583 frent = LIST_FIRST(&(*frag)->fr_queue);
584#if defined(__FreeBSD__)
585 KASSERT((frent != NULL), ("frent == NULL: %s", __FUNCTION__));
586#else
458 KASSERT(frent != NULL);
587 KASSERT(frent != NULL);
588#endif
459 if ((frent->fr_ip->ip_hl << 2) + off > IP_MAXPACKET) {
460 DPFPRINTF(("drop: too big: %d\n", off));
461 pf_free_fragment(*frag);
462 *frag = NULL;
463 return (NULL);
464 }
465 next = LIST_NEXT(frent, fr_next);
466

--- 52 unchanged lines hidden (view full) ---

519{
520 struct mbuf *m = *m0;
521 struct pf_frcache *frp, *fra, *cur = NULL;
522 int ip_len = ntohs(h->ip_len) - (h->ip_hl << 2);
523 u_int16_t off = ntohs(h->ip_off) << 3;
524 u_int16_t max = ip_len + off;
525 int hosed = 0;
526
589 if ((frent->fr_ip->ip_hl << 2) + off > IP_MAXPACKET) {
590 DPFPRINTF(("drop: too big: %d\n", off));
591 pf_free_fragment(*frag);
592 *frag = NULL;
593 return (NULL);
594 }
595 next = LIST_NEXT(frent, fr_next);
596

--- 52 unchanged lines hidden (view full) ---

649{
650 struct mbuf *m = *m0;
651 struct pf_frcache *frp, *fra, *cur = NULL;
652 int ip_len = ntohs(h->ip_len) - (h->ip_hl << 2);
653 u_int16_t off = ntohs(h->ip_off) << 3;
654 u_int16_t max = ip_len + off;
655 int hosed = 0;
656
657#if defined(__FreeBSD__)
658 KASSERT((*frag == NULL || !BUFFER_FRAGMENTS(*frag)),
659 ("!(*frag == NULL || !BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__));
660#else
527 KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag));
661 KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag));
662#endif
528
529 /* Create a new range queue for this packet */
530 if (*frag == NULL) {
531 *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
532 if (*frag == NULL) {
533 pf_flush_fragments();
534 *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
535 if (*frag == NULL)

--- 10 unchanged lines hidden (view full) ---

546 pf_ncache++;
547
548 (*frag)->fr_flags = PFFRAG_NOBUFFER;
549 (*frag)->fr_max = 0;
550 (*frag)->fr_src = h->ip_src;
551 (*frag)->fr_dst = h->ip_dst;
552 (*frag)->fr_p = h->ip_p;
553 (*frag)->fr_id = h->ip_id;
663
664 /* Create a new range queue for this packet */
665 if (*frag == NULL) {
666 *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
667 if (*frag == NULL) {
668 pf_flush_fragments();
669 *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
670 if (*frag == NULL)

--- 10 unchanged lines hidden (view full) ---

681 pf_ncache++;
682
683 (*frag)->fr_flags = PFFRAG_NOBUFFER;
684 (*frag)->fr_max = 0;
685 (*frag)->fr_src = h->ip_src;
686 (*frag)->fr_dst = h->ip_dst;
687 (*frag)->fr_p = h->ip_p;
688 (*frag)->fr_id = h->ip_id;
689#if defined(__FreeBSD__)
690 (*frag)->fr_timeout = time_second;
691#else
554 (*frag)->fr_timeout = time.tv_sec;
692 (*frag)->fr_timeout = time.tv_sec;
693#endif
555
556 cur->fr_off = off;
557 cur->fr_end = max;
558 LIST_INIT(&(*frag)->fr_cache);
559 LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next);
560
561 RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag);
562 TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next);

--- 9 unchanged lines hidden (view full) ---

572 */
573 frp = NULL;
574 LIST_FOREACH(fra, &(*frag)->fr_cache, fr_next) {
575 if (fra->fr_off > off)
576 break;
577 frp = fra;
578 }
579
694
695 cur->fr_off = off;
696 cur->fr_end = max;
697 LIST_INIT(&(*frag)->fr_cache);
698 LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next);
699
700 RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag);
701 TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next);

--- 9 unchanged lines hidden (view full) ---

711 */
712 frp = NULL;
713 LIST_FOREACH(fra, &(*frag)->fr_cache, fr_next) {
714 if (fra->fr_off > off)
715 break;
716 frp = fra;
717 }
718
719#if defined(__FreeBSD__)
720 KASSERT((frp != NULL || fra != NULL),
721 ("!(frp != NULL || fra != NULL): %s", __FUNCTION__));
722#else
580 KASSERT(frp != NULL || fra != NULL);
723 KASSERT(frp != NULL || fra != NULL);
724#endif
581
582 if (frp != NULL) {
583 int precut;
584
585 precut = frp->fr_end - off;
586 if (precut >= ip_len) {
587 /* Fragment is entirely a duplicate */
588 DPFPRINTF(("fragcache[%d]: dead (%d-%d) %d-%d\n",

--- 25 unchanged lines hidden (view full) ---

614 if (!drop) {
615 /* XXX Optimization opportunity
616 * This is a very heavy way to trim the payload.
617 * we could do it much faster by diddling mbuf
618 * internals but that would be even less legible
619 * than this mbuf magic. For my next trick,
620 * I'll pull a rabbit out of my laptop.
621 */
725
726 if (frp != NULL) {
727 int precut;
728
729 precut = frp->fr_end - off;
730 if (precut >= ip_len) {
731 /* Fragment is entirely a duplicate */
732 DPFPRINTF(("fragcache[%d]: dead (%d-%d) %d-%d\n",

--- 25 unchanged lines hidden (view full) ---

758 if (!drop) {
759 /* XXX Optimization opportunity
760 * This is a very heavy way to trim the payload.
761 * we could do it much faster by diddling mbuf
762 * internals but that would be even less legible
763 * than this mbuf magic. For my next trick,
764 * I'll pull a rabbit out of my laptop.
765 */
766#if defined(__FreeBSD__)
767 *m0 = m_dup(m, M_DONTWAIT);
768 /* From KAME Project : We have missed this! */
769 m_adj(*m0, (h->ip_hl << 2) -
770 (*m0)->m_pkthdr.len);
771#else
622 *m0 = m_copym2(m, 0, h->ip_hl << 2, M_NOWAIT);
772 *m0 = m_copym2(m, 0, h->ip_hl << 2, M_NOWAIT);
773#endif
623 if (*m0 == NULL)
624 goto no_mem;
774 if (*m0 == NULL)
775 goto no_mem;
776#if defined(__FreeBSD__)
777 KASSERT(((*m0)->m_next == NULL),
778 ("(*m0)->m_next != NULL: %s",
779 __FUNCTION__));
780#else
625 KASSERT((*m0)->m_next == NULL);
781 KASSERT((*m0)->m_next == NULL);
782#endif
626 m_adj(m, precut + (h->ip_hl << 2));
627 m_cat(*m0, m);
628 m = *m0;
629 if (m->m_flags & M_PKTHDR) {
630 int plen = 0;
631 struct mbuf *t;
632 for (t = m; t; t = t->m_next)
633 plen += t->m_len;
634 m->m_pkthdr.len = plen;
635 }
636
637
638 h = mtod(m, struct ip *);
639
783 m_adj(m, precut + (h->ip_hl << 2));
784 m_cat(*m0, m);
785 m = *m0;
786 if (m->m_flags & M_PKTHDR) {
787 int plen = 0;
788 struct mbuf *t;
789 for (t = m; t; t = t->m_next)
790 plen += t->m_len;
791 m->m_pkthdr.len = plen;
792 }
793
794
795 h = mtod(m, struct ip *);
796
640
797#if defined(__FreeBSD__)
798 KASSERT(((int)m->m_len == ntohs(h->ip_len) - precut),
799 ("m->m_len != ntohs(h->ip_len) - precut: %s",
800 __FUNCTION__));
801#else
641 KASSERT((int)m->m_len == ntohs(h->ip_len) - precut);
802 KASSERT((int)m->m_len == ntohs(h->ip_len) - precut);
803#endif
642 h->ip_off = htons(ntohs(h->ip_off) + (precut >> 3));
643 h->ip_len = htons(ntohs(h->ip_len) - precut);
644 } else {
645 hosed++;
646 }
647 } else {
648 /* There is a gap between fragments */
649

--- 38 unchanged lines hidden (view full) ---

688 if (m->m_flags & M_PKTHDR) {
689 int plen = 0;
690 struct mbuf *t;
691 for (t = m; t; t = t->m_next)
692 plen += t->m_len;
693 m->m_pkthdr.len = plen;
694 }
695 h = mtod(m, struct ip *);
804 h->ip_off = htons(ntohs(h->ip_off) + (precut >> 3));
805 h->ip_len = htons(ntohs(h->ip_len) - precut);
806 } else {
807 hosed++;
808 }
809 } else {
810 /* There is a gap between fragments */
811

--- 38 unchanged lines hidden (view full) ---

850 if (m->m_flags & M_PKTHDR) {
851 int plen = 0;
852 struct mbuf *t;
853 for (t = m; t; t = t->m_next)
854 plen += t->m_len;
855 m->m_pkthdr.len = plen;
856 }
857 h = mtod(m, struct ip *);
858#if defined(__FreeBSD__)
859 KASSERT(((int)m->m_len == ntohs(h->ip_len) - aftercut),
860 ("m->m_len != ntohs(h->ip_len) - aftercut: %s",
861 __FUNCTION__));
862#else
696 KASSERT((int)m->m_len == ntohs(h->ip_len) - aftercut);
863 KASSERT((int)m->m_len == ntohs(h->ip_len) - aftercut);
864#endif
697 h->ip_len = htons(ntohs(h->ip_len) - aftercut);
698 } else {
699 hosed++;
700 }
701 } else {
702 /* There is a gap between fragments */
703 DPFPRINTF(("fragcache[%d]: gap %d %d-%d (%d-%d)\n",
704 h->ip_id, -aftercut, off, max, fra->fr_off,

--- 21 unchanged lines hidden (view full) ---

726 fra->fr_off = cur->fr_off;
727 LIST_REMOVE(cur, fr_next);
728 pool_put(&pf_cent_pl, cur);
729 pf_ncache--;
730 cur = NULL;
731
732 } else if (frp && fra->fr_off <= frp->fr_end) {
733 /* Need to merge in a modified 'frp' */
865 h->ip_len = htons(ntohs(h->ip_len) - aftercut);
866 } else {
867 hosed++;
868 }
869 } else {
870 /* There is a gap between fragments */
871 DPFPRINTF(("fragcache[%d]: gap %d %d-%d (%d-%d)\n",
872 h->ip_id, -aftercut, off, max, fra->fr_off,

--- 21 unchanged lines hidden (view full) ---

894 fra->fr_off = cur->fr_off;
895 LIST_REMOVE(cur, fr_next);
896 pool_put(&pf_cent_pl, cur);
897 pf_ncache--;
898 cur = NULL;
899
900 } else if (frp && fra->fr_off <= frp->fr_end) {
901 /* Need to merge in a modified 'frp' */
902#if defined(__FreeBSD__)
903 KASSERT((cur == NULL), ("cur != NULL: %s",
904 __FUNCTION__));
905#else
734 KASSERT(cur == NULL);
906 KASSERT(cur == NULL);
907#endif
735 DPFPRINTF(("fragcache[%d]: adjacent(merge "
736 "%d-%d) %d-%d (%d-%d)\n",
737 h->ip_id, frp->fr_off, frp->fr_end, off,
738 max, fra->fr_off, fra->fr_end));
739 fra->fr_off = frp->fr_off;
740 LIST_REMOVE(frp, fr_next);
741 pool_put(&pf_cent_pl, frp);
742 pf_ncache--;

--- 535 unchanged lines hidden (view full) ---

1278 }
1279
1280 /* Process options */
1281 if (r->max_mss && pf_normalize_tcpopt(r, m, th, off))
1282 rewrite = 1;
1283
1284 /* copy back packet headers if we sanitized */
1285 if (rewrite)
908 DPFPRINTF(("fragcache[%d]: adjacent(merge "
909 "%d-%d) %d-%d (%d-%d)\n",
910 h->ip_id, frp->fr_off, frp->fr_end, off,
911 max, fra->fr_off, fra->fr_end));
912 fra->fr_off = frp->fr_off;
913 LIST_REMOVE(frp, fr_next);
914 pool_put(&pf_cent_pl, frp);
915 pf_ncache--;

--- 535 unchanged lines hidden (view full) ---

1451 }
1452
1453 /* Process options */
1454 if (r->max_mss && pf_normalize_tcpopt(r, m, th, off))
1455 rewrite = 1;
1456
1457 /* copy back packet headers if we sanitized */
1458 if (rewrite)
1286 m_copyback(m, off, sizeof(*th), th);
1459 m_copyback(m, off, sizeof(*th), (caddr_t)th);
1287
1288 return (PF_PASS);
1289
1290 tcp_drop:
1291 REASON_SET(&reason, PFRES_NORM);
1292 if (rm != NULL && r->log)
1293 PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, NULL, NULL);
1294 return (PF_DROP);
1295}
1296
1297int
1298pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
1299 struct tcphdr *th, struct pf_state_peer *src, struct pf_state_peer *dst)
1300{
1301 u_int8_t hdr[60];
1302 u_int8_t *opt;
1303
1460
1461 return (PF_PASS);
1462
1463 tcp_drop:
1464 REASON_SET(&reason, PFRES_NORM);
1465 if (rm != NULL && r->log)
1466 PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, NULL, NULL);
1467 return (PF_DROP);
1468}
1469
1470int
1471pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
1472 struct tcphdr *th, struct pf_state_peer *src, struct pf_state_peer *dst)
1473{
1474 u_int8_t hdr[60];
1475 u_int8_t *opt;
1476
1477#if defined(__FreeBSD__)
1478 KASSERT((src->scrub == NULL),
1479 ("pf_normalize_tcp_init: src->scrub != NULL"));
1480#else
1304 KASSERT(src->scrub == NULL);
1481 KASSERT(src->scrub == NULL);
1482#endif
1305
1306 src->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
1307 if (src->scrub == NULL)
1308 return (1);
1309 bzero(src->scrub, sizeof(*src->scrub));
1310
1311 switch (pd->af) {
1312#ifdef INET

--- 67 unchanged lines hidden (view full) ---

1380pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
1381 u_short *reason, struct tcphdr *th, struct pf_state_peer *src,
1382 struct pf_state_peer *dst, int *writeback)
1383{
1384 u_int8_t hdr[60];
1385 u_int8_t *opt;
1386 int copyback = 0;
1387
1483
1484 src->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
1485 if (src->scrub == NULL)
1486 return (1);
1487 bzero(src->scrub, sizeof(*src->scrub));
1488
1489 switch (pd->af) {
1490#ifdef INET

--- 67 unchanged lines hidden (view full) ---

1558pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
1559 u_short *reason, struct tcphdr *th, struct pf_state_peer *src,
1560 struct pf_state_peer *dst, int *writeback)
1561{
1562 u_int8_t hdr[60];
1563 u_int8_t *opt;
1564 int copyback = 0;
1565
1566#if defined(__FreeBSD__)
1567 KASSERT((src->scrub || dst->scrub),
1568 ("pf_normalize_tcp_statefull: src->scrub && dst->scrub!"));
1569#else
1388 KASSERT(src->scrub || dst->scrub);
1570 KASSERT(src->scrub || dst->scrub);
1571#endif
1389
1390 /*
1391 * Enforce the minimum TTL seen for this connection. Negate a common
1392 * technique to evade an intrusion detection system and confuse
1393 * firewall state code.
1394 */
1395 switch (pd->af) {
1396#ifdef INET

--- 132 unchanged lines hidden ---
1572
1573 /*
1574 * Enforce the minimum TTL seen for this connection. Negate a common
1575 * technique to evade an intrusion detection system and confuse
1576 * firewall state code.
1577 */
1578 switch (pd->af) {
1579#ifdef INET

--- 132 unchanged lines hidden ---