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 --- |