1/* $FreeBSD: head/sys/contrib/pf/net/pf.c 126261 2004-02-26 02:34:12Z mlaier $ */ |
2/* $OpenBSD: pf.c,v 1.390 2003/09/24 17:18:03 mcbride Exp $ */ 3 4/* 5 * Copyright (c) 2001 Daniel Hartmeier 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 --- 20 unchanged lines hidden (view full) --- 30 * POSSIBILITY OF SUCH DAMAGE. 31 * 32 * Effort sponsored in part by the Defense Advanced Research Projects 33 * Agency (DARPA) and Air Force Research Laboratory, Air Force 34 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 35 * 36 */ 37 |
38#if defined(__FreeBSD__) 39#include "opt_inet.h" 40#include "opt_inet6.h" 41#endif 42 43#if defined(__FreeBSD__) && __FreeBSD__ >= 5 44#include "opt_bpf.h" 45#define NBPFILTER DEV_BPF 46#include "opt_pf.h" 47#define NPFLOG DEV_PFLOG 48#define NPFSYNC DEV_PFSYNC 49#else |
50#include "bpfilter.h" 51#include "pflog.h" 52#include "pfsync.h" |
53#endif |
54 55#include <sys/param.h> 56#include <sys/systm.h> 57#include <sys/mbuf.h> 58#include <sys/filio.h> 59#include <sys/socket.h> 60#include <sys/socketvar.h> 61#include <sys/kernel.h> 62#include <sys/time.h> |
63#if defined(__FreeBSD__) 64#include <sys/sysctl.h> 65#else |
66#include <sys/pool.h> |
67#endif |
68 69#include <net/if.h> 70#include <net/if_types.h> 71#include <net/bpf.h> 72#include <net/route.h> 73 74#include <netinet/in.h> 75#include <netinet/in_var.h> --- 5 unchanged lines hidden (view full) --- 81#include <netinet/udp.h> 82#include <netinet/ip_icmp.h> 83#include <netinet/in_pcb.h> 84#include <netinet/tcp_timer.h> 85#include <netinet/tcp_var.h> 86#include <netinet/udp_var.h> 87#include <netinet/icmp_var.h> 88 |
89#if !defined(__FreeBSD__) |
90#include <dev/rndvar.h> |
91#endif |
92#include <net/pfvar.h> 93#include <net/if_pflog.h> 94#include <net/if_pfsync.h> 95 96#ifdef INET6 97#include <netinet/ip6.h> 98#include <netinet/in_pcb.h> 99#include <netinet/icmp6.h> 100#include <netinet6/nd6.h> |
101#if defined(__FreeBSD__) 102#include <netinet6/ip6_var.h> 103#include <netinet6/in6_pcb.h> 104#endif |
105#endif /* INET6 */ 106 107#ifdef ALTQ 108#include <altq/if_altq.h> 109#endif 110 |
111#if defined(__FreeBSD__) 112#include <machine/in_cksum.h> 113#if (__FreeBSD_version >= 500112) 114#include <sys/limits.h> 115#else 116#include <machine/limits.h> 117#endif 118#include <sys/ucred.h> 119#endif |
120 |
121#if defined(__FreeBSD__) 122extern int ip_optcopy(struct ip *, struct ip *); 123#if (__FreeBSD_version < 501105) 124int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, 125 u_long if_hwassist_flags, int sw_csum); 126#endif 127#endif 128 |
129#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x 130struct pf_state_tree; 131 132/* 133 * Global variables 134 */ 135 136struct pf_anchorqueue pf_anchors; --- 4 unchanged lines hidden (view full) --- 141struct pf_altqqueue *pf_altqs_inactive; 142struct pf_status pf_status; 143struct ifnet *status_ifp; 144 145u_int32_t ticket_altqs_active; 146u_int32_t ticket_altqs_inactive; 147u_int32_t ticket_pabuf; 148 |
149#if defined(__FreeBSD__) 150struct callout pf_expire_to; /* expire timeout */ 151#else |
152struct timeout pf_expire_to; /* expire timeout */ |
153#endif |
154 |
155 156#if defined(__FreeBSD__) 157uma_zone_t pf_tree_pl, pf_rule_pl, pf_addr_pl; 158uma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl; 159#else |
160struct pool pf_tree_pl, pf_rule_pl, pf_addr_pl; 161struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl; |
162#endif |
163 164void pf_dynaddr_update(void *); |
165#if defined(__FreeBSD__) && defined(HOOK_HACK) 166void pf_dynaddr_update_event(void *arg, struct ifnet *ifp); 167#endif |
168void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t); 169void pf_print_state(struct pf_state *); 170void pf_print_flags(u_int8_t); 171 172u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t, 173 u_int8_t); 174void pf_change_ap(struct pf_addr *, u_int16_t *, 175 u_int16_t *, u_int16_t *, struct pf_addr *, --- 78 unchanged lines hidden (view full) --- 254 u_int16_t); 255void pf_set_rt_ifp(struct pf_state *, 256 struct pf_addr *); 257int pf_check_proto_cksum(struct mbuf *, int, int, 258 u_int8_t, sa_family_t); 259int pf_addr_wrap_neq(struct pf_addr_wrap *, 260 struct pf_addr_wrap *); 261 |
262#if defined(__FreeBSD__) 263int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len); 264#endif |
265 |
266#if defined(__FreeBSD__) 267struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX]; 268#else |
269struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = 270 { { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } }; |
271#endif |
272 273#define STATE_LOOKUP() \ 274 do { \ 275 if (direction == PF_IN) \ 276 *state = pf_find_state(&tree_ext_gwy, &key); \ 277 else \ 278 *state = pf_find_state(&tree_lan_ext, &key); \ 279 if (*state == NULL) \ --- 199 unchanged lines hidden (view full) --- 479 pfsync_insert_state(state); 480#endif 481 return (0); 482} 483 484void 485pf_purge_timeout(void *arg) 486{ |
487#if defined(__FreeBSD__) 488 struct callout *to = arg; 489#else |
490 struct timeout *to = arg; |
491#endif |
492 int s; 493 |
494#if defined(__FreeBSD__) 495 PF_LOCK(); 496#endif |
497 s = splsoftnet(); 498 pf_purge_expired_states(); 499 pf_purge_expired_fragments(); 500 splx(s); |
501#if defined(__FreeBSD__) 502 PF_UNLOCK(); 503#endif |
504 |
505#if defined(__FreeBSD__) 506 callout_reset(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz, 507 pf_purge_timeout, to); 508#else |
509 timeout_add(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz); |
510#endif |
511} 512 513u_int32_t 514pf_state_expires(const struct pf_state *state) 515{ 516 u_int32_t timeout; 517 u_int32_t start; 518 u_int32_t end; 519 u_int32_t states; 520 521 /* handle all PFTM_* > PFTM_MAX here */ 522 if (state->timeout == PFTM_PURGE) |
523#if defined(__FreeBSD__) 524 return (time_second); 525#else |
526 return (time.tv_sec); |
527#endif |
528 if (state->timeout == PFTM_UNTIL_PACKET) 529 return (0); |
530#if defined(__FreeBSD__) 531 KASSERT((state->timeout < PFTM_MAX), 532 ("pf_state_expires: timeout > PFTM_MAX")); 533#else |
534 KASSERT(state->timeout < PFTM_MAX); |
535#endif |
536 timeout = state->rule.ptr->timeout[state->timeout]; 537 if (!timeout) 538 timeout = pf_default_rule.timeout[state->timeout]; 539 start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START]; 540 if (start) { 541 end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END]; 542 states = state->rule.ptr->states; 543 } else { 544 start = pf_default_rule.timeout[PFTM_ADAPTIVE_START]; 545 end = pf_default_rule.timeout[PFTM_ADAPTIVE_END]; 546 states = pf_status.states; 547 } 548 if (end && states > start && start < end) { 549 if (states < end) 550 return (state->expire + timeout * (end - states) / 551 (end - start)); 552 else |
553#if defined(__FreeBSD__) 554 return (time_second); 555#else |
556 return (time.tv_sec); |
557#endif |
558 } 559 return (state->expire + timeout); 560} 561 562void 563pf_purge_expired_states(void) 564{ 565 struct pf_tree_node *cur, *peer, *next; 566 struct pf_tree_node key; 567 568 for (cur = RB_MIN(pf_state_tree, &tree_ext_gwy); cur; cur = next) { 569 next = RB_NEXT(pf_state_tree, &tree_ext_gwy, cur); 570 |
571#if defined(__FreeBSD__) 572 if (pf_state_expires(cur->state) <= (u_int32_t)time_second) { 573#else |
574 if (pf_state_expires(cur->state) <= time.tv_sec) { |
575#endif |
576 if (cur->state->src.state == PF_TCPS_PROXY_DST) 577 pf_send_tcp(cur->state->rule.ptr, 578 cur->state->af, 579 &cur->state->ext.addr, 580 &cur->state->lan.addr, 581 cur->state->ext.port, 582 cur->state->lan.port, 583 cur->state->src.seqhi, --- 9 unchanged lines hidden (view full) --- 593 PF_ACPY(&key.addr[0], &cur->state->lan.addr, 594 cur->state->af); 595 key.port[0] = cur->state->lan.port; 596 PF_ACPY(&key.addr[1], &cur->state->ext.addr, 597 cur->state->af); 598 key.port[1] = cur->state->ext.port; 599 600 peer = RB_FIND(pf_state_tree, &tree_lan_ext, &key); |
601#if defined(__FreeBSD__) 602 KASSERT((peer), ("peer null :%s", __FUNCTION__)); 603 KASSERT((peer->state == cur->state), 604 ("peer->state != cur->state: %s", __FUNCTION__)); 605#else |
606 KASSERT(peer); 607 KASSERT(peer->state == cur->state); |
608#endif |
609 RB_REMOVE(pf_state_tree, &tree_lan_ext, peer); 610 611#if NPFSYNC 612 pfsync_delete_state(cur->state); 613#endif 614 if (--cur->state->rule.ptr->states <= 0) 615 pf_rm_rule(NULL, cur->state->rule.ptr); 616 if (cur->state->nat_rule.ptr != NULL) --- 60 unchanged lines hidden (view full) --- 677 if (aw->p.dyn->ifp == NULL) { 678 pool_put(&pf_addr_pl, aw->p.dyn); 679 aw->p.dyn = NULL; 680 return (1); 681 } 682 aw->p.dyn->addr = &aw->v.a.addr; 683 aw->p.dyn->af = af; 684 aw->p.dyn->undefined = 1; |
685#if !defined(__FreeBSD__) |
686 aw->p.dyn->hook_cookie = hook_establish( 687 aw->p.dyn->ifp->if_addrhooks, 1, 688 pf_dynaddr_update, aw->p.dyn); 689 if (aw->p.dyn->hook_cookie == NULL) { 690 pool_put(&pf_addr_pl, aw->p.dyn); 691 aw->p.dyn = NULL; 692 return (1); 693 } |
694#elif defined(__FreeBSD__) && defined(HOOK_HACK) 695 PF_UNLOCK(); 696 aw->p.dyn->hook_cookie = EVENTHANDLER_REGISTER(ifaddr_event, 697 pf_dynaddr_update_event, aw->p.dyn, EVENTHANDLER_PRI_ANY); 698 PF_LOCK(); 699 if (aw->p.dyn->hook_cookie == NULL) { 700 pool_put(&pf_addr_pl, aw->p.dyn); 701 aw->p.dyn = NULL; 702 return (1); 703 } 704#else 705 /* 706 * XXX 707 * We have no hook_establish(9)/dohooks(9) kernel interfaces. 708 * This means that we do not aware of interface address changes(add, 709 * remove, etc). User should update pf rule manually after interface 710 * address changed. This may not be possible solution if you use xDSL. 711 * ipfw/ipfw2's approach with this situation(with me keyword) is not 712 * very efficient due to analyzing interface address during runtime. 713 * Another solution is to use a user-land daemon watching address 714 * changes with socket interface. Neither one is good. 715 * Supporting hook_establish(9) requries modification of in_control() 716 * located in netinet/in.c. 717 */ 718#endif |
719 pf_dynaddr_update(aw->p.dyn); 720 return (0); 721} 722 |
723#if defined(__FreeBSD__) && defined(HOOK_HACK) |
724void |
725pf_dynaddr_update_event(void *arg, struct ifnet *ifp) 726{ 727 PF_LOCK(); 728 pf_dynaddr_update(arg); 729 PF_UNLOCK(); 730} 731#endif 732 733void |
734pf_dynaddr_update(void *p) 735{ 736 struct pf_addr_dyn *ad = (struct pf_addr_dyn *)p; 737 struct ifaddr *ia; 738 int s, changed = 0; 739 740 if (ad == NULL || ad->ifp == NULL) 741 panic("pf_dynaddr_update"); --- 33 unchanged lines hidden (view full) --- 775 splx(s); 776} 777 778void 779pf_dynaddr_remove(struct pf_addr_wrap *aw) 780{ 781 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL) 782 return; |
783#if !defined(__FreeBSD__) |
784 hook_disestablish(aw->p.dyn->ifp->if_addrhooks, 785 aw->p.dyn->hook_cookie); |
786#elif defined(__FreeBSD__) && defined(HOOK_HACK) 787 PF_UNLOCK(); 788 EVENTHANDLER_DEREGISTER(ifaddr_event, aw->p.dyn->hook_cookie); 789 PF_LOCK(); 790#else 791 /* 792 * XXX 793 * We have no hook_establish(9)/dohooks(9) kernel interfaces. 794 * See comments above function, pf_dynaddr_setup(). 795 */ 796#endif |
797 pool_put(&pf_addr_pl, aw->p.dyn); 798 aw->p.dyn = NULL; 799} 800 801void 802pf_dynaddr_copyout(struct pf_addr_wrap *aw) 803{ 804 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL) --- 438 unchanged lines hidden (view full) --- 1243 int len, tlen; 1244#ifdef INET 1245 struct ip *h; 1246#endif /* INET */ 1247#ifdef INET6 1248 struct ip6_hdr *h6; 1249#endif /* INET6 */ 1250 struct tcphdr *th; |
1251#if defined(__FreeBSD__) 1252 struct ip *ip; 1253#if (__FreeBSD_version < 501114) 1254 struct route ro; 1255#endif 1256#endif |
1257 char *opt; 1258 1259 /* maximum segment size tcp option */ 1260 tlen = sizeof(struct tcphdr); 1261 if (mss) 1262 tlen += 4; 1263 1264 switch (af) { --- 89 unchanged lines hidden (view full) --- 1354 case AF_INET: 1355 /* TCP checksum */ 1356 th->th_sum = in_cksum(m, len); 1357 1358 /* Finish the IP header */ 1359 h->ip_v = 4; 1360 h->ip_hl = sizeof(*h) >> 2; 1361 h->ip_tos = IPTOS_LOWDELAY; |
1362#if defined(__FreeBSD__) 1363 h->ip_off = htons(path_mtu_discovery ? IP_DF : 0); 1364#else |
1365 h->ip_off = htons(ip_mtudisc ? IP_DF : 0); |
1366#endif 1367 h->ip_len = htons(len); |
1368 h->ip_ttl = ttl ? ttl : ip_defttl; 1369 h->ip_sum = 0; |
1370#if defined(__FreeBSD__) 1371 ip = mtod(m, struct ip *); 1372 /* 1373 * XXX 1374 * OpenBSD changed ip_len/ip_off byte ordering! 1375 * Because FreeBSD assumes host byte ordering we need to 1376 * change here. 1377 */ 1378 NTOHS(ip->ip_len); 1379 NTOHS(ip->ip_off); 1380#if (__FreeBSD_version < 501114) 1381 bzero(&ro, sizeof(ro)); 1382 ip_rtaddr(ip->ip_dst, &ro); 1383 PF_UNLOCK(); 1384 ip_output(m, (void *)NULL, &ro, 0, (void *)NULL, 1385 (void *)NULL); 1386 PF_LOCK(); 1387 if(ro.ro_rt) { 1388 RTFREE(ro.ro_rt); 1389 } 1390#else /* __FreeBSD_version >= 501114 */ 1391 PF_UNLOCK(); |
1392 ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL, |
1393 (void *)NULL); 1394 PF_LOCK(); 1395#endif 1396#else /* ! __FreeBSD__ */ 1397 ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL, |
1398 (void *)NULL); |
1399#endif |
1400 break; 1401#endif /* INET */ 1402#ifdef INET6 1403 case AF_INET6: 1404 /* TCP checksum */ 1405 th->th_sum = in6_cksum(m, IPPROTO_TCP, 1406 sizeof(struct ip6_hdr), tlen); 1407 1408 h6->ip6_vfc |= IPV6_VERSION; 1409 h6->ip6_hlim = IPV6_DEFHLIM; 1410 |
1411#if defined(__FreeBSD__) 1412 PF_UNLOCK(); 1413 ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); 1414 PF_LOCK(); 1415#else |
1416 ip6_output(m, NULL, NULL, 0, NULL, NULL); |
1417#endif |
1418 break; 1419#endif /* INET6 */ 1420 } 1421} 1422 1423void 1424pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af, 1425 struct pf_rule *r) 1426{ 1427 struct m_tag *mtag; 1428 struct mbuf *m0; |
1429#if defined(__FreeBSD__) 1430 struct ip *ip; 1431#endif |
1432 1433 mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT); 1434 if (mtag == NULL) 1435 return; |
1436#if defined(__FreeBSD__) 1437 m0 = m_copypacket(m, M_DONTWAIT); 1438#else |
1439 m0 = m_copy(m, 0, M_COPYALL); |
1440#endif |
1441 if (m0 == NULL) { 1442 m_tag_free(mtag); 1443 return; 1444 } 1445 m_tag_prepend(m0, mtag); 1446 1447#ifdef ALTQ 1448 if (r->qid) { --- 9 unchanged lines hidden (view full) --- 1458 m_tag_prepend(m0, mtag); 1459 } 1460 } 1461#endif 1462 1463 switch (af) { 1464#ifdef INET 1465 case AF_INET: |
1466#if defined(__FreeBSD__) 1467 /* icmp_error() expects host byte ordering */ 1468 ip = mtod(m0, struct ip *); 1469 NTOHS(ip->ip_len); 1470 NTOHS(ip->ip_off); 1471 PF_UNLOCK(); 1472#endif 1473 icmp_error(m0, type, code, 0, NULL); 1474#if defined(__FreeBSD__) 1475 PF_LOCK(); 1476#endif |
1477 break; 1478#endif /* INET */ 1479#ifdef INET6 1480 case AF_INET6: |
1481#if defined(__FreeBSD__) 1482 PF_UNLOCK(); 1483#endif |
1484 icmp6_error(m0, type, code, 0); |
1485#if defined(__FreeBSD__) 1486 PF_LOCK(); 1487#endif |
1488 break; 1489#endif /* INET6 */ 1490 } 1491} 1492 1493/* 1494 * Return 1 if the addresses a and b match (with mask m), otherwise return 0. 1495 * If n is 0, they match if they are equal. If n is != 0, they match if they --- 610 unchanged lines hidden (view full) --- 2106 break; 2107 case PF_IN: 2108 if (r->src.addr.type == PF_ADDR_DYNIFTL && 2109 r->src.addr.p.dyn->undefined) 2110 return (NULL); 2111 else 2112 PF_POOLMASK(naddr, 2113 &r->src.addr.v.a.addr, |
2114 &r->src.addr.v.a.mask, daddr, |
2115 pd->af); 2116 break; 2117 } 2118 break; 2119 case PF_RDR: { 2120 if (pf_map_addr(r->af, &r->rpool, saddr, naddr, NULL)) 2121 return (NULL); 2122 --- 24 unchanged lines hidden (view full) --- 2147} 2148 2149int 2150pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, sa_family_t af, 2151 int proto, struct pf_pdesc *pd) 2152{ 2153 struct pf_addr *saddr, *daddr; 2154 u_int16_t sport, dport; |
2155#if defined(__FreeBSD__) 2156 struct inpcbinfo *pi; 2157#else |
2158 struct inpcbtable *tb; |
2159#endif |
2160 struct inpcb *inp; 2161 2162 *uid = UID_MAX; 2163 *gid = GID_MAX; 2164 switch (proto) { 2165 case IPPROTO_TCP: 2166 sport = pd->hdr.tcp->th_sport; 2167 dport = pd->hdr.tcp->th_dport; |
2168#if defined(__FreeBSD__) 2169 pi = &tcbinfo; 2170#else |
2171 tb = &tcbtable; |
2172#endif |
2173 break; 2174 case IPPROTO_UDP: 2175 sport = pd->hdr.udp->uh_sport; 2176 dport = pd->hdr.udp->uh_dport; |
2177#if defined(__FreeBSD__) 2178 pi = &udbinfo; 2179#else |
2180 tb = &udbtable; |
2181#endif |
2182 break; 2183 default: 2184 return (0); 2185 } 2186 if (direction == PF_IN) { 2187 saddr = pd->src; 2188 daddr = pd->dst; 2189 } else { 2190 u_int16_t p; 2191 2192 p = sport; 2193 sport = dport; 2194 dport = p; 2195 saddr = pd->dst; 2196 daddr = pd->src; 2197 } 2198 switch(af) { 2199 case AF_INET: |
2200#if defined(__FreeBSD__) 2201#if (__FreeBSD_version >= 500043) 2202 INP_INFO_RLOCK(pi); /* XXX LOR */ 2203#endif 2204 inp = in_pcblookup_hash(pi, saddr->v4, sport, daddr->v4, 2205 dport, 0, NULL); 2206 if (inp == NULL) { 2207 inp = in_pcblookup_hash(pi, saddr->v4, sport, 2208 daddr->v4, dport, INPLOOKUP_WILDCARD, NULL); 2209 if(inp == NULL) { 2210#if (__FreeBSD_version >= 500043) 2211 INP_INFO_RUNLOCK(pi); 2212#endif 2213 return (0); 2214 } 2215 } 2216#else |
2217 inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport); 2218 if (inp == NULL) { 2219 inp = in_pcblookup(tb, &saddr->v4, sport, &daddr->v4, 2220 dport, INPLOOKUP_WILDCARD); 2221 if (inp == NULL) 2222 return (0); 2223 } |
2224#endif |
2225 break; 2226#ifdef INET6 2227 case AF_INET6: |
2228#if defined(__FreeBSD__) 2229#if (__FreeBSD_version >= 500043) 2230 INP_INFO_RLOCK(pi); 2231#endif 2232 inp = in6_pcblookup_hash(pi, &saddr->v6, sport, 2233 &daddr->v6, dport, 0, NULL); 2234 if (inp == NULL) { 2235 inp = in6_pcblookup_hash(pi, &saddr->v6, sport, 2236 &daddr->v6, dport, INPLOOKUP_WILDCARD, NULL); 2237 if (inp == NULL) { 2238#if (__FreeBSD_version >= 500043) 2239 INP_INFO_RUNLOCK(pi); 2240#endif 2241 return (0); 2242 } 2243 } 2244#else |
2245 inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6, 2246 dport); 2247 if (inp == NULL) { 2248 inp = in_pcblookup(tb, &saddr->v6, sport, &daddr->v6, 2249 dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); 2250 if (inp == NULL) 2251 return (0); 2252 } |
2253#endif |
2254 break; 2255#endif /* INET6 */ 2256 2257 default: 2258 return (0); 2259 } |
2260#if defined(__FreeBSD__) 2261#if (__FreeBSD_version >= 500043) 2262 INP_LOCK(inp); 2263#endif 2264 *uid = inp->inp_socket->so_cred->cr_uid; 2265 *gid = inp->inp_socket->so_cred->cr_groups[0]; 2266#if (__FreeBSD_version >= 500043) 2267 INP_UNLOCK(inp); 2268 INP_INFO_RUNLOCK(pi); 2269#endif 2270#else |
2271 *uid = inp->inp_socket->so_euid; 2272 *gid = inp->inp_socket->so_egid; |
2273#endif |
2274 return (1); 2275} 2276 2277u_int8_t 2278pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af) 2279{ 2280 int hlen; 2281 u_int8_t hdr[60]; --- 86 unchanged lines hidden (view full) --- 2368#ifdef INET 2369 case AF_INET: 2370 hlen = sizeof(struct ip); 2371 bzero(&ro, sizeof(ro)); 2372 dst = (struct sockaddr_in *)&ro.ro_dst; 2373 dst->sin_family = AF_INET; 2374 dst->sin_len = sizeof(*dst); 2375 dst->sin_addr = addr->v4; |
2376#if defined(__FreeBSD__) 2377#ifdef RTF_PRCLONING 2378 rtalloc_ign(&ro, (RTF_CLONING | RTF_PRCLONING)); 2379#else /* !RTF_PRCLONING */ 2380 rtalloc_ign(&ro, RTF_CLONING); 2381#endif 2382#else /* ! __FreeBSD__ */ |
2383 rtalloc_noclone(&ro, NO_CLONING); |
2384#endif |
2385 rt = ro.ro_rt; 2386 break; 2387#endif /* INET */ 2388#ifdef INET6 2389 case AF_INET6: 2390 hlen = sizeof(struct ip6_hdr); 2391 bzero(&ro6, sizeof(ro6)); 2392 dst6 = (struct sockaddr_in6 *)&ro6.ro_dst; 2393 dst6->sin6_family = AF_INET6; 2394 dst6->sin6_len = sizeof(*dst6); 2395 dst6->sin6_addr = addr->v6; |
2396#if defined(__FreeBSD__) 2397#ifdef RTF_PRCLONING 2398 rtalloc_ign((struct route *)&ro6, 2399 (RTF_CLONING | RTF_PRCLONING)); 2400#else /* !RTF_PRCLONING */ 2401 rtalloc_ign((struct route *)&ro6, RTF_CLONING); 2402#endif 2403#else /* ! __FreeBSD__ */ |
2404 rtalloc_noclone((struct route *)&ro6, NO_CLONING); |
2405#endif |
2406 rt = ro6.ro_rt; 2407 break; 2408#endif /* INET6 */ 2409 } 2410 2411 if (rt && rt->rt_ifp) { 2412 mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr); 2413 mss = max(tcp_mssdflt, mss); --- 156 unchanged lines hidden (view full) --- 2570 if (a != NULL) { 2571 a->packets++; 2572 a->bytes += pd->tot_len; 2573 } 2574 REASON_SET(&reason, PFRES_MATCH); 2575 2576 if (r->log) { 2577 if (rewrite) |
2578 m_copyback(m, off, sizeof(*th), (caddr_t)th); |
2579 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); 2580 } 2581 2582 if ((r->action == PF_DROP) && 2583 ((r->rule_flag & PFRULE_RETURNRST) || 2584 (r->rule_flag & PFRULE_RETURNICMP) || 2585 (r->rule_flag & PFRULE_RETURN))) { 2586 /* undo NAT changes, if they have taken place */ --- 116 unchanged lines hidden (view full) --- 2703 (s->src.wscale & PF_WSCALE_MASK); 2704 } 2705 if (th->th_flags & TH_FIN) 2706 s->src.seqhi++; 2707 s->dst.seqhi = 1; 2708 s->dst.max_win = 1; 2709 s->src.state = TCPS_SYN_SENT; 2710 s->dst.state = TCPS_CLOSED; |
2711#if defined(__FreeBSD__) 2712 s->creation = time_second; 2713 s->expire = time_second; 2714#else |
2715 s->creation = time.tv_sec; 2716 s->expire = time.tv_sec; |
2717#endif |
2718 s->timeout = PFTM_TCP_FIRST_PACKET; 2719 s->packets[0] = 1; 2720 s->bytes[0] = pd->tot_len; 2721 pf_set_rt_ifp(s, saddr); 2722 2723 if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m, 2724 off, pd, th, &s->src, &s->dst)) { 2725 REASON_SET(&reason, PFRES_MEMORY); --- 35 unchanged lines hidden (view full) --- 2761 th->th_sport, s->src.seqhi, 2762 ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, s->src.mss, 0); 2763 return (PF_SYNPROXY_DROP); 2764 } 2765 } 2766 2767 /* copy back packet headers if we performed NAT operations */ 2768 if (rewrite) |
2769 m_copyback(m, off, sizeof(*th), (caddr_t)th); |
2770 2771 return (PF_PASS); 2772} 2773 2774int 2775pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction, 2776 struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h, 2777 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm) --- 115 unchanged lines hidden (view full) --- 2893 if (a != NULL) { 2894 a->packets++; 2895 a->bytes += pd->tot_len; 2896 } 2897 REASON_SET(&reason, PFRES_MATCH); 2898 2899 if (r->log) { 2900 if (rewrite) |
2901 m_copyback(m, off, sizeof(*uh), (caddr_t)uh); |
2902 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); 2903 } 2904 2905 if ((r->action == PF_DROP) && 2906 ((r->rule_flag & PFRULE_RETURNICMP) || 2907 (r->rule_flag & PFRULE_RETURN))) { 2908 /* undo NAT changes, if they have taken place */ 2909 if (nat != NULL) { --- 70 unchanged lines hidden (view full) --- 2980 s->gwy.port = bport; 2981 } else { 2982 PF_ACPY(&s->gwy.addr, &s->lan.addr, af); 2983 s->gwy.port = s->lan.port; 2984 } 2985 } 2986 s->src.state = PFUDPS_SINGLE; 2987 s->dst.state = PFUDPS_NO_TRAFFIC; |
2988#if defined(__FreeBSD__) 2989 s->creation = time_second; 2990 s->expire = time_second; 2991#else |
2992 s->creation = time.tv_sec; 2993 s->expire = time.tv_sec; |
2994#endif |
2995 s->timeout = PFTM_UDP_FIRST_PACKET; 2996 s->packets[0] = 1; 2997 s->bytes[0] = pd->tot_len; 2998 pf_set_rt_ifp(s, saddr); 2999 if (pf_insert_state(s)) { 3000 REASON_SET(&reason, PFRES_MEMORY); 3001 pool_put(&pf_state_pl, s); 3002 return (PF_DROP); 3003 } else 3004 *sm = s; 3005 } 3006 3007 /* copy back packet headers if we performed NAT operations */ 3008 if (rewrite) |
3009 m_copyback(m, off, sizeof(*uh), (caddr_t)uh); |
3010 3011 return (PF_PASS); 3012} 3013 3014int 3015pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction, 3016 struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h, 3017 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm) --- 153 unchanged lines hidden (view full) --- 3171 a->bytes += pd->tot_len; 3172 } 3173 REASON_SET(&reason, PFRES_MATCH); 3174 3175 if (r->log) { 3176#ifdef INET6 3177 if (rewrite) 3178 m_copyback(m, off, sizeof(struct icmp6_hdr), |
3179 (caddr_t)pd->hdr.icmp6); |
3180#endif /* INET6 */ 3181 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); 3182 } 3183 3184 if (r->action != PF_PASS) 3185 return (PF_DROP); 3186 3187 if (pf_tag_packet(m, pftag, tag)) { --- 45 unchanged lines hidden (view full) --- 3233 PF_ACPY(&s->ext.addr, saddr, af); 3234 s->ext.port = icmpid; 3235 if (rdr != NULL) 3236 PF_ACPY(&s->gwy.addr, &baddr, af); 3237 else 3238 PF_ACPY(&s->gwy.addr, &s->lan.addr, af); 3239 s->gwy.port = icmpid; 3240 } |
3241 3242#if defined(__FreeBSD__) 3243 s->creation = time_second; 3244 s->expire = time_second; 3245#else |
3246 s->creation = time.tv_sec; 3247 s->expire = time.tv_sec; |
3248#endif |
3249 s->timeout = PFTM_ICMP_FIRST_PACKET; 3250 s->packets[0] = 1; 3251 s->bytes[0] = pd->tot_len; 3252 pf_set_rt_ifp(s, saddr); 3253 if (pf_insert_state(s)) { 3254 REASON_SET(&reason, PFRES_MEMORY); 3255 pool_put(&pf_state_pl, s); 3256 return (PF_DROP); 3257 } else 3258 *sm = s; 3259 } 3260 3261#ifdef INET6 3262 /* copy back packet headers if we performed IPv6 NAT operations */ 3263 if (rewrite) 3264 m_copyback(m, off, sizeof(struct icmp6_hdr), |
3265 (caddr_t)pd->hdr.icmp6); |
3266#endif /* INET6 */ 3267 3268 return (PF_PASS); 3269} 3270 3271int 3272pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction, 3273 struct ifnet *ifp, struct mbuf *m, int off, void *h, struct pf_pdesc *pd, --- 192 unchanged lines hidden (view full) --- 3466 PF_ACPY(&s->ext.addr, saddr, af); 3467 if (rdr != NULL) 3468 PF_ACPY(&s->gwy.addr, &baddr, af); 3469 else 3470 PF_ACPY(&s->gwy.addr, &s->lan.addr, af); 3471 } 3472 s->src.state = PFOTHERS_SINGLE; 3473 s->dst.state = PFOTHERS_NO_TRAFFIC; |
3474#if defined(__FreeBSD__) 3475 s->creation = time_second; 3476 s->expire = time_second; 3477#else |
3478 s->creation = time.tv_sec; 3479 s->expire = time.tv_sec; |
3480#endif |
3481 s->timeout = PFTM_OTHER_FIRST_PACKET; 3482 s->packets[0] = 1; 3483 s->bytes[0] = pd->tot_len; 3484 pf_set_rt_ifp(s, saddr); 3485 if (pf_insert_state(s)) { 3486 REASON_SET(&reason, PFRES_MEMORY); 3487 if (r->log) 3488 PFLOG_PACKET(ifp, h, m, af, direction, reason, --- 341 unchanged lines hidden (view full) --- 3830 dst->state = TCPS_ESTABLISHED; 3831 else if (dst->state == TCPS_CLOSING) 3832 dst->state = TCPS_FIN_WAIT_2; 3833 } 3834 if (th->th_flags & TH_RST) 3835 src->state = dst->state = TCPS_TIME_WAIT; 3836 3837 /* update expire time */ |
3838#if defined(__FreeBSD__) 3839 (*state)->expire = time_second; 3840#else |
3841 (*state)->expire = time.tv_sec; |
3842#endif |
3843 if (src->state >= TCPS_FIN_WAIT_2 && 3844 dst->state >= TCPS_FIN_WAIT_2) 3845 (*state)->timeout = PFTM_TCP_CLOSED; 3846 else if (src->state >= TCPS_FIN_WAIT_2 || 3847 dst->state >= TCPS_FIN_WAIT_2) 3848 (*state)->timeout = PFTM_TCP_FIN_WAIT; 3849 else if (src->state < TCPS_ESTABLISHED || 3850 dst->state < TCPS_ESTABLISHED) --- 124 unchanged lines hidden (view full) --- 3975 if (direction == PF_OUT) 3976 pf_change_ap(pd->src, &th->th_sport, pd->ip_sum, 3977 &th->th_sum, &(*state)->gwy.addr, 3978 (*state)->gwy.port, 0, pd->af); 3979 else 3980 pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum, 3981 &th->th_sum, &(*state)->lan.addr, 3982 (*state)->lan.port, 0, pd->af); |
3983 m_copyback(m, off, sizeof(*th), (caddr_t)th); |
3984 } else if (copyback) { 3985 /* Copyback sequence modulation or stateful scrub changes */ |
3986 m_copyback(m, off, sizeof(*th), (caddr_t)th); |
3987 } 3988 3989 (*state)->rule.ptr->packets++; 3990 (*state)->rule.ptr->bytes += pd->tot_len; 3991 if ((*state)->nat_rule.ptr != NULL) { 3992 (*state)->nat_rule.ptr->packets++; 3993 (*state)->nat_rule.ptr->bytes += pd->tot_len; 3994 } --- 37 unchanged lines hidden (view full) --- 4032 4033 /* update states */ 4034 if (src->state < PFUDPS_SINGLE) 4035 src->state = PFUDPS_SINGLE; 4036 if (dst->state == PFUDPS_SINGLE) 4037 dst->state = PFUDPS_MULTIPLE; 4038 4039 /* update expire time */ |
4040#if defined(__FreeBSD__) 4041 (*state)->expire = time_second; 4042#else |
4043 (*state)->expire = time.tv_sec; |
4044#endif |
4045 if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE) 4046 (*state)->timeout = PFTM_UDP_MULTIPLE; 4047 else 4048 (*state)->timeout = PFTM_UDP_SINGLE; 4049 4050 /* translate source/destination address, if necessary */ 4051 if (STATE_TRANSLATE(*state)) { 4052 if (direction == PF_OUT) 4053 pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum, 4054 &uh->uh_sum, &(*state)->gwy.addr, 4055 (*state)->gwy.port, 1, pd->af); 4056 else 4057 pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum, 4058 &uh->uh_sum, &(*state)->lan.addr, 4059 (*state)->lan.port, 1, pd->af); |
4060 m_copyback(m, off, sizeof(*uh), (caddr_t)uh); |
4061 } 4062 4063 (*state)->rule.ptr->packets++; 4064 (*state)->rule.ptr->bytes += pd->tot_len; 4065 if ((*state)->nat_rule.ptr != NULL) { 4066 (*state)->nat_rule.ptr->packets++; 4067 (*state)->nat_rule.ptr->bytes += pd->tot_len; 4068 } --- 58 unchanged lines hidden (view full) --- 4127 key.port[0] = icmpid; 4128 key.port[1] = icmpid; 4129 4130 STATE_LOOKUP(); 4131 4132 dirndx = (direction == (*state)->direction) ? 0 : 1; 4133 (*state)->packets[dirndx]++; 4134 (*state)->bytes[dirndx] += pd->tot_len; |
4135#if defined(__FreeBSD__) 4136 (*state)->expire = time_second; 4137#else |
4138 (*state)->expire = time.tv_sec; |
4139#endif |
4140 (*state)->timeout = PFTM_ICMP_ERROR_REPLY; 4141 4142 /* translate source/destination address, if necessary */ 4143 if (PF_ANEQ(&(*state)->lan.addr, &(*state)->gwy.addr, pd->af)) { 4144 if (direction == PF_OUT) { 4145 switch (pd->af) { 4146#ifdef INET 4147 case AF_INET: --- 4 unchanged lines hidden (view full) --- 4152#endif /* INET */ 4153#ifdef INET6 4154 case AF_INET6: 4155 pf_change_a6(saddr, 4156 &pd->hdr.icmp6->icmp6_cksum, 4157 &(*state)->gwy.addr, 0); 4158 m_copyback(m, off, 4159 sizeof(struct icmp6_hdr), |
4160 (caddr_t)pd->hdr.icmp6); |
4161 break; 4162#endif /* INET6 */ 4163 } 4164 } else { 4165 switch (pd->af) { 4166#ifdef INET 4167 case AF_INET: 4168 pf_change_a(&daddr->v4.s_addr, 4169 pd->ip_sum, 4170 (*state)->lan.addr.v4.s_addr, 0); 4171 break; 4172#endif /* INET */ 4173#ifdef INET6 4174 case AF_INET6: 4175 pf_change_a6(daddr, 4176 &pd->hdr.icmp6->icmp6_cksum, 4177 &(*state)->lan.addr, 0); 4178 m_copyback(m, off, 4179 sizeof(struct icmp6_hdr), |
4180 (caddr_t)pd->hdr.icmp6); |
4181 break; 4182#endif /* INET6 */ 4183 } 4184 } 4185 } 4186 4187 return (PF_PASS); 4188 --- 174 unchanged lines hidden (view full) --- 4363 (*state)->gwy.port, NULL, 4364 pd2.ip_sum, icmpsum, 4365 pd->ip_sum, 0, pd2.af); 4366 } 4367 switch (pd2.af) { 4368#ifdef INET 4369 case AF_INET: 4370 m_copyback(m, off, ICMP_MINLEN, |
4371 (caddr_t)pd->hdr.icmp); |
4372 m_copyback(m, ipoff2, sizeof(h2), |
4373 (caddr_t)&h2); |
4374 break; 4375#endif /* INET */ 4376#ifdef INET6 4377 case AF_INET6: 4378 m_copyback(m, off, 4379 sizeof(struct icmp6_hdr), |
4380 (caddr_t)pd->hdr.icmp6); |
4381 m_copyback(m, ipoff2, sizeof(h2_6), |
4382 (caddr_t)&h2_6); |
4383 break; 4384#endif /* INET6 */ 4385 } |
4386 m_copyback(m, off2, 8, (caddr_t)&th); |
4387 } else if (src->seqdiff) { |
4388 m_copyback(m, off2, 8, (caddr_t)&th); |
4389 } 4390 4391 return (PF_PASS); 4392 break; 4393 } 4394 case IPPROTO_UDP: { 4395 struct udphdr uh; 4396 struct pf_tree_node key; --- 28 unchanged lines hidden (view full) --- 4425 (*state)->gwy.port, &uh.uh_sum, 4426 pd2.ip_sum, icmpsum, 4427 pd->ip_sum, 1, pd2.af); 4428 } 4429 switch (pd2.af) { 4430#ifdef INET 4431 case AF_INET: 4432 m_copyback(m, off, ICMP_MINLEN, |
4433 (caddr_t)pd->hdr.icmp); 4434 m_copyback(m, ipoff2, sizeof(h2), 4435 (caddr_t)&h2); |
4436 break; 4437#endif /* INET */ 4438#ifdef INET6 4439 case AF_INET6: 4440 m_copyback(m, off, 4441 sizeof(struct icmp6_hdr), |
4442 (caddr_t)pd->hdr.icmp6); |
4443 m_copyback(m, ipoff2, sizeof(h2_6), |
4444 (caddr_t)&h2_6); |
4445 break; 4446#endif /* INET6 */ 4447 } |
4448 m_copyback(m, off2, sizeof(uh), 4449 (caddr_t)&uh); |
4450 } 4451 4452 return (PF_PASS); 4453 break; 4454 } 4455#ifdef INET 4456 case IPPROTO_ICMP: { 4457 struct icmp iih; --- 25 unchanged lines hidden (view full) --- 4483 pd->ip_sum, 0, AF_INET); 4484 } else { 4485 pf_change_icmp(pd2.dst, &iih.icmp_id, 4486 saddr, &(*state)->gwy.addr, 4487 (*state)->gwy.port, NULL, 4488 pd2.ip_sum, icmpsum, 4489 pd->ip_sum, 0, AF_INET); 4490 } |
4491 m_copyback(m, off, ICMP_MINLEN, 4492 (caddr_t)pd->hdr.icmp); 4493 m_copyback(m, ipoff2, sizeof(h2), 4494 (caddr_t)&h2); 4495 m_copyback(m, off2, ICMP_MINLEN, 4496 (caddr_t)&iih); |
4497 } 4498 4499 return (PF_PASS); 4500 break; 4501 } 4502#endif /* INET */ 4503#ifdef INET6 4504 case IPPROTO_ICMPV6: { --- 27 unchanged lines hidden (view full) --- 4532 } else { 4533 pf_change_icmp(pd2.dst, &iih.icmp6_id, 4534 saddr, &(*state)->gwy.addr, 4535 (*state)->gwy.port, NULL, 4536 pd2.ip_sum, icmpsum, 4537 pd->ip_sum, 0, AF_INET6); 4538 } 4539 m_copyback(m, off, sizeof(struct icmp6_hdr), |
4540 (caddr_t)pd->hdr.icmp6); 4541 m_copyback(m, ipoff2, sizeof(h2_6), 4542 (caddr_t)&h2_6); |
4543 m_copyback(m, off2, sizeof(struct icmp6_hdr), |
4544 (caddr_t)&iih); |
4545 } 4546 4547 return (PF_PASS); 4548 break; 4549 } 4550#endif /* INET6 */ 4551 default: { 4552 struct pf_tree_node key; --- 20 unchanged lines hidden (view full) --- 4573 0, NULL, 4574 pd2.ip_sum, icmpsum, 4575 pd->ip_sum, 0, pd2.af); 4576 } 4577 switch (pd2.af) { 4578#ifdef INET 4579 case AF_INET: 4580 m_copyback(m, off, ICMP_MINLEN, |
4581 (caddr_t)pd->hdr.icmp); 4582 m_copyback(m, ipoff2, sizeof(h2), 4583 (caddr_t)&h2); |
4584 break; 4585#endif /* INET */ 4586#ifdef INET6 4587 case AF_INET6: 4588 m_copyback(m, off, 4589 sizeof(struct icmp6_hdr), |
4590 (caddr_t)pd->hdr.icmp6); |
4591 m_copyback(m, ipoff2, sizeof(h2_6), |
4592 (caddr_t)&h2_6); |
4593 break; 4594#endif /* INET6 */ 4595 } 4596 } 4597 4598 return (PF_PASS); 4599 break; 4600 } --- 33 unchanged lines hidden (view full) --- 4634 4635 /* update states */ 4636 if (src->state < PFOTHERS_SINGLE) 4637 src->state = PFOTHERS_SINGLE; 4638 if (dst->state == PFOTHERS_SINGLE) 4639 dst->state = PFOTHERS_MULTIPLE; 4640 4641 /* update expire time */ |
4642#if defined(__FreeBSD__) 4643 (*state)->expire = time_second; 4644#else |
4645 (*state)->expire = time.tv_sec; |
4646#endif |
4647 if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE) 4648 (*state)->timeout = PFTM_OTHER_MULTIPLE; 4649 else 4650 (*state)->timeout = PFTM_OTHER_SINGLE; 4651 4652 /* translate source/destination address, if necessary */ 4653 if (STATE_TRANSLATE(*state)) { 4654 if (direction == PF_OUT) --- 98 unchanged lines hidden (view full) --- 4753 struct route ro; 4754 int ret = 0; 4755 4756 bzero(&ro, sizeof(ro)); 4757 dst = satosin(&ro.ro_dst); 4758 dst->sin_family = af; 4759 dst->sin_len = sizeof(*dst); 4760 dst->sin_addr = addr->v4; |
4761#if defined(__FreeBSD__) 4762#ifdef RTF_PRCLONING 4763 rtalloc_ign(&ro, (RTF_CLONING|RTF_PRCLONING)); 4764#else /* !RTF_PRCLONING */ 4765 rtalloc_ign(&ro, RTF_CLONING); 4766#endif 4767#else /* ! __FreeBSD__ */ |
4768 rtalloc_noclone(&ro, NO_CLONING); |
4769#endif |
4770 4771 if (ro.ro_rt != NULL) { 4772 ret = 1; 4773 RTFREE(ro.ro_rt); 4774 } 4775 4776 return (ret); 4777} 4778 4779#ifdef INET |
4780 4781#if defined(__FreeBSD__) && (__FreeBSD_version < 501105) 4782int 4783ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, 4784 u_long if_hwassist_flags, int sw_csum) 4785{ 4786 int error = 0; 4787 int hlen = ip->ip_hl << 2; 4788 int len = (mtu - hlen) & ~7; /* size of payload in each fragment */ 4789 int off; 4790 struct mbuf *m0 = *m_frag; /* the original packet */ 4791 int firstlen; 4792 struct mbuf **mnext; 4793 int nfrags; 4794 4795 if (ip->ip_off & IP_DF) { /* Fragmentation not allowed */ 4796 ipstat.ips_cantfrag++; 4797 return EMSGSIZE; 4798 } 4799 4800 /* 4801 * Must be able to put at least 8 bytes per fragment. 4802 */ 4803 if (len < 8) 4804 return EMSGSIZE; 4805 4806 /* 4807 * If the interface will not calculate checksums on 4808 * fragmented packets, then do it here. 4809 */ 4810 if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA && 4811 (if_hwassist_flags & CSUM_IP_FRAGS) == 0) { 4812 in_delayed_cksum(m0); 4813 m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 4814 } 4815 4816 if (len > PAGE_SIZE) { 4817 /* 4818 * Fragment large datagrams such that each segment 4819 * contains a multiple of PAGE_SIZE amount of data, 4820 * plus headers. This enables a receiver to perform 4821 * page-flipping zero-copy optimizations. 4822 * 4823 * XXX When does this help given that sender and receiver 4824 * could have different page sizes, and also mtu could 4825 * be less than the receiver's page size ? 4826 */ 4827 int newlen; 4828 struct mbuf *m; 4829 4830 for (m = m0, off = 0; m && (off+m->m_len) <= mtu; m = m->m_next) 4831 off += m->m_len; 4832 4833 /* 4834 * firstlen (off - hlen) must be aligned on an 4835 * 8-byte boundary 4836 */ 4837 if (off < hlen) 4838 goto smart_frag_failure; 4839 off = ((off - hlen) & ~7) + hlen; 4840 newlen = (~PAGE_MASK) & mtu; 4841 if ((newlen + sizeof (struct ip)) > mtu) { 4842 /* we failed, go back the default */ 4843smart_frag_failure: 4844 newlen = len; 4845 off = hlen + len; 4846 } 4847 len = newlen; 4848 4849 } else { 4850 off = hlen + len; 4851 } 4852 4853 firstlen = off - hlen; 4854 mnext = &m0->m_nextpkt; /* pointer to next packet */ 4855 4856 /* 4857 * Loop through length of segment after first fragment, 4858 * make new header and copy data of each part and link onto chain. 4859 * Here, m0 is the original packet, m is the fragment being created. 4860 * The fragments are linked off the m_nextpkt of the original 4861 * packet, which after processing serves as the first fragment. 4862 */ 4863 for (nfrags = 1; off < ip->ip_len; off += len, nfrags++) { 4864 struct ip *mhip; /* ip header on the fragment */ 4865 struct mbuf *m; 4866 int mhlen = sizeof (struct ip); 4867 4868 MGETHDR(m, M_DONTWAIT, MT_HEADER); 4869 if (m == 0) { 4870 error = ENOBUFS; 4871 ipstat.ips_odropped++; 4872 goto done; 4873 } 4874 m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG; 4875 /* 4876 * In the first mbuf, leave room for the link header, then 4877 * copy the original IP header including options. The payload 4878 * goes into an additional mbuf chain returned by m_copy(). 4879 */ 4880 m->m_data += max_linkhdr; 4881 mhip = mtod(m, struct ip *); 4882 *mhip = *ip; 4883 if (hlen > sizeof (struct ip)) { 4884 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 4885 mhip->ip_v = IPVERSION; 4886 mhip->ip_hl = mhlen >> 2; 4887 } 4888 m->m_len = mhlen; 4889 /* XXX do we need to add ip->ip_off below ? */ 4890 mhip->ip_off = ((off - hlen) >> 3) + ip->ip_off; 4891 if (off + len >= ip->ip_len) { /* last fragment */ 4892 len = ip->ip_len - off; 4893 m->m_flags |= M_LASTFRAG; 4894 } else 4895 mhip->ip_off |= IP_MF; 4896 mhip->ip_len = htons((u_short)(len + mhlen)); 4897 m->m_next = m_copy(m0, off, len); 4898 if (m->m_next == 0) { /* copy failed */ 4899 m_free(m); 4900 error = ENOBUFS; /* ??? */ 4901 ipstat.ips_odropped++; 4902 goto done; 4903 } 4904 m->m_pkthdr.len = mhlen + len; 4905 m->m_pkthdr.rcvif = (struct ifnet *)0; 4906#ifdef MAC 4907 mac_create_fragment(m0, m); 4908#endif 4909 m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags; 4910 mhip->ip_off = htons(mhip->ip_off); 4911 mhip->ip_sum = 0; 4912 if (sw_csum & CSUM_DELAY_IP) 4913 mhip->ip_sum = in_cksum(m, mhlen); 4914 *mnext = m; 4915 mnext = &m->m_nextpkt; 4916 } 4917 ipstat.ips_ofragments += nfrags; 4918 4919 /* set first marker for fragment chain */ 4920 m0->m_flags |= M_FIRSTFRAG | M_FRAG; 4921 m0->m_pkthdr.csum_data = nfrags; 4922 4923 /* 4924 * Update first fragment by trimming what's been copied out 4925 * and updating header. 4926 */ 4927 m_adj(m0, hlen + firstlen - ip->ip_len); 4928 m0->m_pkthdr.len = hlen + firstlen; 4929 ip->ip_len = htons((u_short)m0->m_pkthdr.len); 4930 ip->ip_off |= IP_MF; 4931 ip->ip_off = htons(ip->ip_off); 4932 ip->ip_sum = 0; 4933 if (sw_csum & CSUM_DELAY_IP) 4934 ip->ip_sum = in_cksum(m0, hlen); 4935 4936done: 4937 *m_frag = m0; 4938 return error; 4939} 4940#endif /* __FreeBSD__ && __FreeBSD_version > 501105 */ 4941 |
4942void 4943pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, 4944 struct pf_state *s) 4945{ 4946 struct mbuf *m0, *m1; 4947 struct route iproute; 4948 struct route *ro; 4949 struct sockaddr_in *dst; 4950 struct ip *ip; 4951 struct ifnet *ifp = NULL; 4952 struct m_tag *mtag; 4953 struct pf_addr naddr; 4954 int error = 0; |
4955#if defined(__FreeBSD__) 4956 int sw_csum; 4957#endif |
4958 4959 if (m == NULL || *m == NULL || r == NULL || 4960 (dir != PF_IN && dir != PF_OUT) || oifp == NULL) 4961 panic("pf_route: invalid parameters"); 4962 4963 if (r->rt == PF_DUPTO) { 4964 m0 = *m; 4965 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL); 4966 if (mtag == NULL) { 4967 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT); 4968 if (mtag == NULL) 4969 goto bad; 4970 m_tag_prepend(m0, mtag); 4971 } |
4972#if defined(__FreeBSD__) 4973 m0 = m_dup(*m, M_DONTWAIT); 4974#else |
4975 m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT); |
4976#endif |
4977 if (m0 == NULL) 4978 return; 4979 } else { 4980 if ((r->rt == PF_REPLYTO) == (r->direction == dir)) 4981 return; 4982 m0 = *m; 4983 } 4984 --- 47 unchanged lines hidden (view full) --- 5032 5033 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT); 5034 if (mtag == NULL) 5035 goto bad; 5036 m_tag_prepend(m0, mtag); 5037 } 5038 5039 if (oifp != ifp && mtag == NULL) { |
5040#if defined(__FreeBSD__) 5041 PF_UNLOCK(); 5042 if (pf_test(PF_OUT, ifp, &m0) != PF_PASS) { 5043 PF_LOCK(); 5044 goto bad; 5045 } else if (m0 == NULL) { 5046 PF_LOCK(); 5047 goto done; 5048 } 5049 PF_LOCK(); 5050#else |
5051 if (pf_test(PF_OUT, ifp, &m0) != PF_PASS) 5052 goto bad; 5053 else if (m0 == NULL) 5054 goto done; |
5055#endif |
5056 if (m0->m_len < sizeof(struct ip)) 5057 panic("pf_route: m0->m_len < sizeof(struct ip)"); 5058 ip = mtod(m0, struct ip *); 5059 } 5060 |
5061#if defined(__FreeBSD__) 5062 /* Copied from FreeBSD 5.1-CURRENT ip_output. */ 5063 m0->m_pkthdr.csum_flags |= CSUM_IP; 5064 sw_csum = m0->m_pkthdr.csum_flags & ~ifp->if_hwassist; 5065 if (sw_csum & CSUM_DELAY_DATA) { 5066 /* 5067 * XXX: in_delayed_cksum assumes HBO for ip->ip_len (at least) 5068 */ 5069 NTOHS(ip->ip_len); 5070 NTOHS(ip->ip_off); /* XXX: needed? */ 5071 in_delayed_cksum(m0); 5072 HTONS(ip->ip_len); 5073 HTONS(ip->ip_off); 5074 sw_csum &= ~CSUM_DELAY_DATA; 5075 } 5076 m0->m_pkthdr.csum_flags &= ifp->if_hwassist; 5077 5078 if (ntohs(ip->ip_len) <= ifp->if_mtu || 5079 (ifp->if_hwassist & CSUM_FRAGMENT && 5080 ((ip->ip_off & htons(IP_DF)) == 0))) { 5081 /* 5082 * ip->ip_len = htons(ip->ip_len); 5083 * ip->ip_off = htons(ip->ip_off); 5084 */ 5085 ip->ip_sum = 0; 5086 if (sw_csum & CSUM_DELAY_IP) { 5087 /* From KAME */ 5088 if (ip->ip_v == IPVERSION && 5089 (ip->ip_hl << 2) == sizeof(*ip)) { 5090 ip->ip_sum = in_cksum_hdr(ip); 5091 } else { 5092 ip->ip_sum = in_cksum(m0, ip->ip_hl << 2); 5093 } 5094 } 5095 PF_UNLOCK(); 5096 error = (*ifp->if_output)(ifp, m0, sintosa(dst), ro->ro_rt); 5097 PF_LOCK(); 5098 goto done; 5099 } 5100 5101#else |
5102 /* Copied from ip_output. */ 5103 if (ntohs(ip->ip_len) <= ifp->if_mtu) { 5104 if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) && 5105 ifp->if_bridge == NULL) { 5106 m0->m_pkthdr.csum |= M_IPV4_CSUM_OUT; 5107 ipstat.ips_outhwcsum++; 5108 } else { 5109 ip->ip_sum = 0; 5110 ip->ip_sum = in_cksum(m0, ip->ip_hl << 2); 5111 } 5112 /* Update relevant hardware checksum stats for TCP/UDP */ 5113 if (m0->m_pkthdr.csum & M_TCPV4_CSUM_OUT) 5114 tcpstat.tcps_outhwcsum++; 5115 else if (m0->m_pkthdr.csum & M_UDPV4_CSUM_OUT) 5116 udpstat.udps_outhwcsum++; 5117 error = (*ifp->if_output)(ifp, m0, sintosa(dst), NULL); 5118 goto done; 5119 } |
5120#endif |
5121 /* 5122 * Too large for interface; fragment if possible. 5123 * Must be able to put at least 8 bytes per fragment. 5124 */ 5125 if (ip->ip_off & htons(IP_DF)) { 5126 ipstat.ips_cantfrag++; 5127 if (r->rt != PF_DUPTO) { |
5128#if defined(__FreeBSD__) 5129 /* icmp_error() expects host byte ordering */ 5130 NTOHS(ip->ip_len); 5131 NTOHS(ip->ip_off); 5132 PF_UNLOCK(); 5133#endif |
5134 icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0, 5135 ifp); |
5136#if defined(__FreeBSD__) 5137 PF_LOCK(); 5138#endif |
5139 goto done; 5140 } else 5141 goto bad; 5142 } 5143 5144 m1 = m0; |
5145#if defined(__FreeBSD__) 5146 /* 5147 * XXX: is cheaper + less error prone than own function 5148 */ 5149 NTOHS(ip->ip_len); 5150 NTOHS(ip->ip_off); 5151 error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist, sw_csum); 5152#else |
5153 error = ip_fragment(m0, ifp, ifp->if_mtu); |
5154#endif 5155#if defined(__FreeBSD__) 5156 if (error) 5157#else |
5158 if (error == EMSGSIZE) |
5159#endif |
5160 goto bad; 5161 5162 for (m0 = m1; m0; m0 = m1) { 5163 m1 = m0->m_nextpkt; 5164 m0->m_nextpkt = 0; |
5165#if defined(__FreeBSD__) 5166 if (error == 0) { 5167 PF_UNLOCK(); 5168 error = (*ifp->if_output)(ifp, m0, sintosa(dst), 5169 NULL); 5170 PF_LOCK(); 5171 } else 5172#else |
5173 if (error == 0) 5174 error = (*ifp->if_output)(ifp, m0, sintosa(dst), 5175 NULL); 5176 else |
5177#endif |
5178 m_freem(m0); 5179 } 5180 5181 if (error == 0) 5182 ipstat.ips_fragmented++; 5183 5184done: 5185 if (r->rt != PF_DUPTO) --- 31 unchanged lines hidden (view full) --- 5217 m0 = *m; 5218 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL); 5219 if (mtag == NULL) { 5220 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT); 5221 if (mtag == NULL) 5222 goto bad; 5223 m_tag_prepend(m0, mtag); 5224 } |
5225#if defined(__FreeBSD__) 5226 m0 = m_dup(*m, M_DONTWAIT); 5227#else |
5228 m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT); |
5229#endif |
5230 if (m0 == NULL) 5231 return; 5232 } else { 5233 if ((r->rt == PF_REPLYTO) == (r->direction == dir)) 5234 return; 5235 m0 = *m; 5236 } 5237 --- 9 unchanged lines hidden (view full) --- 5247 dst->sin6_addr = ip6->ip6_dst; 5248 5249 /* Cheat. */ 5250 if (r->rt == PF_FASTROUTE) { 5251 mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT); 5252 if (mtag == NULL) 5253 goto bad; 5254 m_tag_prepend(m0, mtag); |
5255#if defined(__FreeBSD__) 5256 PF_UNLOCK(); 5257 ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL); 5258 PF_LOCK(); 5259#else |
5260 ip6_output(m0, NULL, NULL, 0, NULL, NULL); |
5261#endif |
5262 return; 5263 } 5264 5265 if (TAILQ_EMPTY(&r->rpool.list)) 5266 panic("pf_route6: TAILQ_EMPTY(&r->rpool.list)"); 5267 if (s == NULL) { 5268 pf_map_addr(AF_INET6, &r->rpool, 5269 (struct pf_addr *)&ip6->ip6_src, &naddr, NULL); --- 13 unchanged lines hidden (view full) --- 5283 5284 if (oifp != ifp) { 5285 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL); 5286 if (mtag == NULL) { 5287 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT); 5288 if (mtag == NULL) 5289 goto bad; 5290 m_tag_prepend(m0, mtag); |
5291#if defined(__FreeBSD__) 5292 PF_UNLOCK(); 5293 if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) { 5294 PF_LOCK(); 5295 goto bad; 5296 } else if (m0 == NULL) { 5297 PF_LOCK(); 5298 goto done; 5299 } 5300 PF_LOCK(); 5301#else |
5302 if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) 5303 goto bad; 5304 else if (m0 == NULL) 5305 goto done; |
5306#endif |
5307 } 5308 } 5309 5310 /* 5311 * If the packet is too large for the outgoing interface, 5312 * send back an icmp6 error. 5313 */ 5314 if (IN6_IS_ADDR_LINKLOCAL(&dst->sin6_addr)) 5315 dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index); 5316 if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) { |
5317#if defined(__FreeBSD__) 5318 PF_UNLOCK(); 5319#endif |
5320 error = nd6_output(ifp, ifp, m0, dst, NULL); |
5321#if defined(__FreeBSD__) 5322 PF_LOCK(); 5323#endif |
5324 } else { 5325 in6_ifstat_inc(ifp, ifs6_in_toobig); |
5326#if defined(__FreeBSD__) 5327 if (r->rt != PF_DUPTO) { 5328 PF_UNLOCK(); 5329 icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu); 5330 PF_LOCK(); 5331 } else 5332#else |
5333 if (r->rt != PF_DUPTO) 5334 icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu); 5335 else |
5336#endif |
5337 goto bad; 5338 } 5339 5340done: 5341 if (r->rt != PF_DUPTO) 5342 *m = NULL; 5343 return; 5344 5345bad: 5346 m_freem(m0); 5347 goto done; 5348} 5349#endif /* INET6 */ 5350 5351 |
5352#if defined(__FreeBSD__) |
5353/* |
5354 * XXX 5355 * FreeBSD supports cksum offload for the following drivers. 5356 * em(4), gx(4), lge(4), nge(4), ti(4), xl(4) 5357 * If we can make full use of it we would outperform ipfw/ipfilter in 5358 * very heavy traffic. 5359 * I have not tested 'cause I don't have NICs that supports cksum offload. 5360 * (There might be problems. Typical phenomena would be 5361 * 1. No route message for UDP packet. 5362 * 2. No connection acceptance from external hosts regardless of rule set.) 5363 */ 5364int 5365pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af) 5366{ 5367 u_int16_t sum = 0; 5368 int hw_assist = 0; 5369 struct ip *ip; 5370 5371 if (off < sizeof(struct ip) || len < sizeof(struct udphdr)) 5372 return (1); 5373 if (m->m_pkthdr.len < off + len) 5374 return (1); 5375 5376 switch (p) { 5377 case IPPROTO_TCP: 5378 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { 5379 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) { 5380 sum = m->m_pkthdr.csum_data; 5381 } else { 5382 ip = mtod(m, struct ip *); 5383 sum = in_pseudo(ip->ip_src.s_addr, 5384 ip->ip_dst.s_addr, 5385 htonl(m->m_pkthdr.csum_data + 5386 IPPROTO_TCP) + ip->ip_len); 5387 } 5388 sum ^= 0xffff; 5389 ++hw_assist; 5390 } 5391 break; 5392 case IPPROTO_UDP: 5393 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { 5394 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) { 5395 sum = m->m_pkthdr.csum_data; 5396 } else { 5397 ip = mtod(m, struct ip *); 5398 sum = in_pseudo(ip->ip_src.s_addr, 5399 ip->ip_dst.s_addr, htonl((u_short)len + 5400 m->m_pkthdr.csum_data + IPPROTO_UDP)); 5401 } 5402 sum ^= 0xffff; 5403 ++hw_assist; 5404 } 5405 break; 5406 case IPPROTO_ICMP: 5407#ifdef INET6 5408 case IPPROTO_ICMPV6: 5409#endif /* INET6 */ 5410 break; 5411 default: 5412 return (1); 5413 } 5414 5415 if (!hw_assist) { 5416 switch (af) { 5417 case AF_INET: 5418 if (p == IPPROTO_ICMP) { 5419 if (m->m_len < off) 5420 return (1); 5421 m->m_data += off; 5422 m->m_len -= off; 5423 sum = in_cksum(m, len); 5424 m->m_data -= off; 5425 m->m_len += off; 5426 } else { 5427 if (m->m_len < sizeof(struct ip)) 5428 return (1); 5429 sum = in4_cksum(m, p, off, len); 5430 if (sum == 0) { 5431 m->m_pkthdr.csum_flags |= 5432 (CSUM_DATA_VALID | 5433 CSUM_PSEUDO_HDR); 5434 m->m_pkthdr.csum_data = 0xffff; 5435 } 5436 } 5437 break; 5438#ifdef INET6 5439 case AF_INET6: 5440 if (m->m_len < sizeof(struct ip6_hdr)) 5441 return (1); 5442 sum = in6_cksum(m, p, off, len); 5443 /* 5444 * XXX 5445 * IPv6 H/W cksum off-load not supported yet! 5446 * 5447 * if (sum == 0) { 5448 * m->m_pkthdr.csum_flags |= 5449 * (CSUM_DATA_VALID|CSUM_PSEUDO_HDR); 5450 * m->m_pkthdr.csum_data = 0xffff; 5451 *} 5452 */ 5453 break; 5454#endif /* INET6 */ 5455 default: 5456 return (1); 5457 } 5458 } 5459 if (sum) { 5460 switch (p) { 5461 case IPPROTO_TCP: 5462 tcpstat.tcps_rcvbadsum++; 5463 break; 5464 case IPPROTO_UDP: 5465 udpstat.udps_badsum++; 5466 break; 5467 case IPPROTO_ICMP: 5468 icmpstat.icps_checksum++; 5469 break; 5470#ifdef INET6 5471 case IPPROTO_ICMPV6: 5472 icmp6stat.icp6s_checksum++; 5473 break; 5474#endif /* INET6 */ 5475 } 5476 return (1); 5477 } 5478 return (0); 5479} 5480#else 5481/* |
5482 * check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag 5483 * off is the offset where the protocol header starts 5484 * len is the total length of protocol header plus payload 5485 * returns 0 when the checksum is valid, otherwise returns 1. 5486 */ 5487int 5488pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af) 5489{ --- 70 unchanged lines hidden (view full) --- 5560 break; 5561#endif /* INET6 */ 5562 } 5563 return (1); 5564 } 5565 m->m_pkthdr.csum |= flag_ok; 5566 return (0); 5567} |
5568#endif |
5569 5570#ifdef INET 5571int 5572pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) 5573{ 5574 u_short action, reason = 0, log = 0; 5575 struct mbuf *m = *m0; 5576 struct ip *h; 5577 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr; 5578 struct pf_state *s = NULL; 5579 struct pf_ruleset *ruleset = NULL; 5580 struct pf_pdesc pd; 5581 int off; 5582 int pqid = 0; 5583 |
5584#if defined(__FreeBSD__) 5585 PF_LOCK(); 5586#endif |
5587 if (!pf_status.running || |
5588 (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) { 5589#if defined(__FreeBSD__) 5590 PF_UNLOCK(); 5591#endif 5592 return (PF_PASS); 5593 } |
5594 |
5595#if defined(__FreeBSD__) && (__FreeBSD_version >= 501000) 5596 M_ASSERTPKTHDR(m); 5597#else |
5598#ifdef DIAGNOSTIC 5599 if ((m->m_flags & M_PKTHDR) == 0) 5600 panic("non-M_PKTHDR is passed to pf_test"); 5601#endif |
5602#endif |
5603 5604 if (m->m_pkthdr.len < (int)sizeof(*h)) { 5605 action = PF_DROP; 5606 REASON_SET(&reason, PFRES_SHORT); 5607 log = 1; 5608 goto done; 5609 } 5610 --- 185 unchanged lines hidden (view full) --- 5796 if (action == PF_SYNPROXY_DROP) { 5797 m_freem(*m0); 5798 *m0 = NULL; 5799 action = PF_PASS; 5800 } else if (r->rt) 5801 /* pf_route can free the mbuf causing *m0 to become NULL */ 5802 pf_route(m0, r, dir, ifp, s); 5803 |
5804#if defined(__FreeBSD__) 5805 PF_UNLOCK(); 5806#endif 5807 |
5808 return (action); 5809} 5810#endif /* INET */ 5811 5812#ifdef INET6 5813int 5814pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) 5815{ 5816 u_short action, reason = 0, log = 0; 5817 struct mbuf *m = *m0; 5818 struct ip6_hdr *h; 5819 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr; 5820 struct pf_state *s = NULL; 5821 struct pf_ruleset *ruleset = NULL; 5822 struct pf_pdesc pd; 5823 int off, terminal = 0; 5824 |
5825#if defined(__FreeBSD__) 5826 PF_LOCK(); 5827#endif 5828 |
5829 if (!pf_status.running || |
5830 (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) { 5831#if defined(__FreeBSD__) 5832 PF_UNLOCK(); 5833#endif |
5834 return (PF_PASS); |
5835 } |
5836 |
5837#if defined(__FreeBSD__) && (__FreeBSD_version >= 501000) 5838 M_ASSERTPKTHDR(m); 5839#else |
5840#ifdef DIAGNOSTIC 5841 if ((m->m_flags & M_PKTHDR) == 0) 5842 panic("non-M_PKTHDR is passed to pf_test"); 5843#endif |
5844#endif |
5845 5846 if (m->m_pkthdr.len < (int)sizeof(*h)) { 5847 action = PF_DROP; 5848 REASON_SET(&reason, PFRES_SHORT); 5849 log = 1; 5850 goto done; 5851 } 5852 --- 189 unchanged lines hidden (view full) --- 6042 if (action == PF_SYNPROXY_DROP) { 6043 m_freem(*m0); 6044 *m0 = NULL; 6045 action = PF_PASS; 6046 } else if (r->rt) 6047 /* pf_route6 can free the mbuf causing *m0 to become NULL */ 6048 pf_route6(m0, r, dir, ifp, s); 6049 |
6050#if defined(__FreeBSD__) 6051 PF_UNLOCK(); 6052#endif |
6053 return (action); 6054} 6055#endif /* INET6 */ |