pf.c revision 127145
11590Srgrimes/* $FreeBSD: head/sys/contrib/pf/net/pf.c 127145 2004-03-17 21:11:02Z mlaier $ */ 21590Srgrimes/* $OpenBSD: pf.c,v 1.390 2003/09/24 17:18:03 mcbride Exp $ */ 31590Srgrimes 41590Srgrimes/* 51590Srgrimes * Copyright (c) 2001 Daniel Hartmeier 61590Srgrimes * All rights reserved. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 121590Srgrimes * - Redistributions of source code must retain the above copyright 131590Srgrimes * notice, this list of conditions and the following disclaimer. 141590Srgrimes * - Redistributions in binary form must reproduce the above 151590Srgrimes * copyright notice, this list of conditions and the following 161590Srgrimes * disclaimer in the documentation and/or other materials provided 171590Srgrimes * with the distribution. 181590Srgrimes * 191590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 201590Srgrimes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 211590Srgrimes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 221590Srgrimes * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 231590Srgrimes * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 241590Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 251590Srgrimes * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 261590Srgrimes * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 271590Srgrimes * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 291590Srgrimes * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 301590Srgrimes * POSSIBILITY OF SUCH DAMAGE. 3127443Scharnier * 321590Srgrimes * Effort sponsored in part by the Defense Advanced Research Projects 331590Srgrimes * Agency (DARPA) and Air Force Research Laboratory, Air Force 341590Srgrimes * Materiel Command, USAF, under agreement number F30602-01-2-0537. 351590Srgrimes * 361590Srgrimes */ 3727443Scharnier 381590Srgrimes#ifdef __FreeBSD__ 3927443Scharnier#include "opt_inet.h" 401590Srgrimes#include "opt_inet6.h" 4199112Sobrien#endif 4299112Sobrien 431590Srgrimes#ifdef __FreeBSD__ 4455206Speter#include "opt_bpf.h" 452215Scsgr#include "opt_pf.h" 462215Scsgr#define NBPFILTER DEV_BPF 4755206Speter#define NPFLOG DEV_PFLOG 481590Srgrimes#define NPFSYNC DEV_PFSYNC 491590Srgrimes#else 50100824Sdwmalone#include "bpfilter.h" 511590Srgrimes#include "pflog.h" 52100824Sdwmalone#include "pfsync.h" 531590Srgrimes#endif 541590Srgrimes 551590Srgrimes#include <sys/param.h> 56165758Srodrigc#include <sys/systm.h> 57176471Sdes#include <sys/mbuf.h> 58219043Sdchagin#include <sys/filio.h> 59176471Sdes#include <sys/socket.h> 60219043Sdchagin#include <sys/socketvar.h> 61176471Sdes#include <sys/kernel.h> 62176471Sdes#include <sys/time.h> 63176471Sdes#ifdef __FreeBSD__ 64176471Sdes#include <sys/sysctl.h> 65176471Sdes#else 66176471Sdes#include <sys/pool.h> 67176471Sdes#endif 68190168Sdelphij 69176471Sdes#include <net/if.h> 70190168Sdelphij#include <net/if_types.h> 71165916Sjhb#include <net/bpf.h> 7227443Scharnier#include <net/route.h> 73176471Sdes 74176471Sdes#include <netinet/in.h> 7527443Scharnier#include <netinet/in_var.h> 76176471Sdes#include <netinet/in_systm.h> 771590Srgrimes#include <netinet/ip.h> 781590Srgrimes#include <netinet/ip_var.h> 791590Srgrimes#include <netinet/tcp.h> 80176471Sdes#include <netinet/tcp_seq.h> 8127443Scharnier#include <netinet/udp.h> 8227443Scharnier#include <netinet/ip_icmp.h> 831590Srgrimes#include <netinet/in_pcb.h> 84158766Snetchild#include <netinet/tcp_timer.h> 851590Srgrimes#include <netinet/tcp_var.h> 86219043Sdchagin#include <netinet/udp_var.h> 87219043Sdchagin#include <netinet/icmp_var.h> 88100824Sdwmalone 89100824Sdwmalone#ifndef __FreeBSD__ 90219043Sdchagin#include <dev/rndvar.h> 91219043Sdchagin#endif 92100824Sdwmalone#include <net/pfvar.h> 93115759Speter#include <net/if_pflog.h> 94115759Speter#include <net/if_pfsync.h> 95100824Sdwmalone 96219138Sdchagin#ifdef INET6 97100824Sdwmalone#include <netinet/ip6.h> 98234494Sjhb#include <netinet/in_pcb.h> 99226329Sdes#include <netinet/icmp6.h> 100226329Sdes#include <netinet6/nd6.h> 101100824Sdwmalone#ifdef __FreeBSD__ 102176471Sdes#include <netinet6/ip6_var.h> 103176471Sdes#include <netinet6/in6_pcb.h> 104176471Sdes#endif 105226269Sdes#endif /* INET6 */ 106233925Sjhb 107233925Sjhb#ifdef ALTQ 108100824Sdwmalone#include <altq/if_altq.h> 109226157Sdes#endif 110100824Sdwmalone 111176471Sdes#ifdef __FreeBSD__ 112219043Sdchagin#include <machine/in_cksum.h> 113100824Sdwmalone#if (__FreeBSD_version >= 500112) 1141590Srgrimes#include <sys/limits.h> 1151590Srgrimes#else 116176471Sdes#include <machine/limits.h> 1171590Srgrimes#endif 1181590Srgrimes#include <sys/ucred.h> 119226262Sdes#endif 120226262Sdes 121226262Sdes#ifdef __FreeBSD__ 122226262Sdesextern int ip_optcopy(struct ip *, struct ip *); 123226262Sdes#if (__FreeBSD_version < 501105) 124226262Sdesint ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, 125226262Sdes u_long if_hwassist_flags, int sw_csum); 126226262Sdes#endif 127226164Sdes#endif 128219138Sdchagin 129219138Sdchagin#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x 130219138Sdchaginstruct pf_state_tree; 131219138Sdchagin 132219138Sdchagin/* 133219138Sdchagin * Global variables 134219138Sdchagin */ 135219138Sdchagin 136219138Sdchaginstruct pf_anchorqueue pf_anchors; 137219138Sdchaginstruct pf_ruleset pf_main_ruleset; 138219138Sdchaginstruct pf_altqqueue pf_altqs[2]; 139219138Sdchaginstruct pf_palist pf_pabuf; 140219138Sdchaginstruct pf_altqqueue *pf_altqs_active; 141219138Sdchaginstruct pf_altqqueue *pf_altqs_inactive; 142219138Sdchaginstruct pf_status pf_status; 143219138Sdchaginstruct ifnet *status_ifp; 144219138Sdchagin 145219138Sdchaginu_int32_t ticket_altqs_active; 146219138Sdchaginu_int32_t ticket_altqs_inactive; 147219138Sdchaginu_int32_t ticket_pabuf; 148219138Sdchagin 149219138Sdchagin#ifdef __FreeBSD__ 150219138Sdchaginstruct callout pf_expire_to; /* expire timeout */ 151219138Sdchagin#else 152219138Sdchaginstruct timeout pf_expire_to; /* expire timeout */ 153219138Sdchagin#endif 154219043Sdchagin 155219043Sdchagin 156219043Sdchagin#ifdef __FreeBSD__ 157219043Sdchaginuma_zone_t pf_tree_pl, pf_rule_pl, pf_addr_pl; 158219043Sdchaginuma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl; 159219043Sdchagin#else 160219043Sdchaginstruct pool pf_tree_pl, pf_rule_pl, pf_addr_pl; 161219043Sdchaginstruct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl; 162219043Sdchagin#endif 163100824Sdwmalone 164100824Sdwmalonevoid pf_dynaddr_update(void *); 1651590Srgrimes#ifdef __FreeBSD__ 1661590Srgrimesvoid pf_dynaddr_update_event(void *arg, struct ifnet *ifp); 167100824Sdwmalone#endif 1681590Srgrimesvoid pf_print_host(struct pf_addr *, u_int16_t, u_int8_t); 169112201Sjhbvoid pf_print_state(struct pf_state *); 170115759Spetervoid pf_print_flags(u_int8_t); 171219043Sdchagin 1721590Srgrimesu_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t, 173226153Sdes u_int8_t); 17411823Sachevoid pf_change_ap(struct pf_addr *, u_int16_t *, 175219043Sdchagin u_int16_t *, u_int16_t *, struct pf_addr *, 176226153Sdes u_int16_t, u_int8_t, sa_family_t); 177219043Sdchagin#ifdef INET6 178219043Sdchaginvoid pf_change_a6(struct pf_addr *, u_int16_t *, 179219043Sdchagin struct pf_addr *, u_int8_t); 1801590Srgrimes#endif /* INET6 */ 1811590Srgrimesvoid pf_change_icmp(struct pf_addr *, u_int16_t *, 1821590Srgrimes struct pf_addr *, struct pf_addr *, u_int16_t, 1831590Srgrimes u_int16_t *, u_int16_t *, u_int16_t *, 1841590Srgrimes u_int16_t *, u_int8_t, sa_family_t); 1851590Srgrimesvoid pf_send_tcp(const struct pf_rule *, sa_family_t, 1861590Srgrimes const struct pf_addr *, const struct pf_addr *, 1871590Srgrimes u_int16_t, u_int16_t, u_int32_t, u_int32_t, 1881590Srgrimes u_int8_t, u_int16_t, u_int16_t, u_int8_t); 1891590Srgrimesvoid pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t, 1901590Srgrimes sa_family_t, struct pf_rule *); 1911590Srgrimesstruct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *, 1921590Srgrimes int, int, struct ifnet *, 1931590Srgrimes struct pf_addr *, u_int16_t, struct pf_addr *, 1941590Srgrimes u_int16_t, int); 195115759Speterstruct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *, 196115759Speter int, int, struct ifnet *, 197115759Speter struct pf_addr *, u_int16_t, 198176471Sdes struct pf_addr *, u_int16_t, 199176471Sdes struct pf_addr *, u_int16_t *); 200176471Sdesint pf_test_tcp(struct pf_rule **, struct pf_state **, 201152331Srwatson int, struct ifnet *, struct mbuf *, int, int, 202152331Srwatson void *, struct pf_pdesc *, struct pf_rule **, 203152331Srwatson struct pf_ruleset **); 204123187Speterint pf_test_udp(struct pf_rule **, struct pf_state **, 205123187Speter int, struct ifnet *, struct mbuf *, int, int, 206123187Speter void *, struct pf_pdesc *, struct pf_rule **, 207151930Srwatson struct pf_ruleset **); 208151930Srwatsonint pf_test_icmp(struct pf_rule **, struct pf_state **, 209151930Srwatson int, struct ifnet *, struct mbuf *, int, int, 2101590Srgrimes void *, struct pf_pdesc *, struct pf_rule **, 2111590Srgrimes struct pf_ruleset **); 2121590Srgrimesint pf_test_other(struct pf_rule **, struct pf_state **, 2131590Srgrimes int, struct ifnet *, struct mbuf *, int, void *, 2141590Srgrimes struct pf_pdesc *, struct pf_rule **, 2151590Srgrimes struct pf_ruleset **); 2161590Srgrimesint pf_test_fragment(struct pf_rule **, int, 2171590Srgrimes struct ifnet *, struct mbuf *, void *, 21827443Scharnier struct pf_pdesc *, struct pf_rule **, 21927443Scharnier struct pf_ruleset **); 2201590Srgrimesint pf_test_state_tcp(struct pf_state **, int, 2211590Srgrimes struct ifnet *, struct mbuf *, int, int, 2221590Srgrimes void *, struct pf_pdesc *, u_short *); 2231590Srgrimesint pf_test_state_udp(struct pf_state **, int, 2241590Srgrimes struct ifnet *, struct mbuf *, int, int, 22519853Sfenner void *, struct pf_pdesc *); 2261590Srgrimesint pf_test_state_icmp(struct pf_state **, int, 2271590Srgrimes struct ifnet *, struct mbuf *, int, int, 228226153Sdes void *, struct pf_pdesc *); 22927443Scharnierint pf_test_state_other(struct pf_state **, int, 23027443Scharnier struct ifnet *, struct pf_pdesc *); 23127443Scharnierstruct pf_tag *pf_get_tag(struct mbuf *); 23227443Scharnierint pf_match_tag(struct mbuf *, struct pf_rule *, 233219043Sdchagin struct pf_rule *, struct pf_rule *, 234112201Sjhb struct pf_tag *, int *); 2351590Srgrimesvoid pf_hash(struct pf_addr *, struct pf_addr *, 236112201Sjhb struct pf_poolhashkey *, sa_family_t); 237112201Sjhbint pf_map_addr(u_int8_t, struct pf_pool *, 238151930Srwatson struct pf_addr *, struct pf_addr *, 239226153Sdes struct pf_addr *); 240203551Sjhint pf_get_sport(sa_family_t, u_int8_t, struct pf_pool *, 241203551Sjh struct pf_addr *, struct pf_addr *, u_int16_t, 242203551Sjh struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t); 243203551Sjhvoid pf_route(struct mbuf **, struct pf_rule *, int, 244203551Sjh struct ifnet *, struct pf_state *); 245151930Srwatsonvoid pf_route6(struct mbuf **, struct pf_rule *, int, 246151930Srwatson struct ifnet *, struct pf_state *); 247226153Sdesint pf_socket_lookup(uid_t *, gid_t *, int, sa_family_t, 248203551Sjh int, struct pf_pdesc *); 249112201Sjhbu_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t, 250112201Sjhb sa_family_t); 251112201Sjhbu_int16_t pf_get_mss(struct mbuf *, int, u_int16_t, 252112201Sjhb sa_family_t); 2531590Srgrimesu_int16_t pf_calc_mss(struct pf_addr *, sa_family_t, 254236577Sjhb u_int16_t); 255236577Sjhbvoid pf_set_rt_ifp(struct pf_state *, 256115759Speter struct pf_addr *); 25727443Scharnierint pf_check_proto_cksum(struct mbuf *, int, int, 25827443Scharnier u_int8_t, sa_family_t); 2591590Srgrimesint pf_addr_wrap_neq(struct pf_addr_wrap *, 260226153Sdes struct pf_addr_wrap *); 26127443Scharnier 26227443Scharnier#ifdef __FreeBSD__ 2631590Srgrimesint in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len); 2641590Srgrimes 26527443Scharnierstruct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX]; 26627443Scharnier#else 267219043Sdchaginstruct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = 268219043Sdchagin { { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } }; 269219043Sdchagin#endif 270236577Sjhb 271236577Sjhb#define STATE_LOOKUP() \ 272115759Speter do { \ 2731590Srgrimes if (direction == PF_IN) \ 2741590Srgrimes *state = pf_find_state(&tree_ext_gwy, &key); \ 275112201Sjhb else \ 2761590Srgrimes *state = pf_find_state(&tree_lan_ext, &key); \ 2771590Srgrimes if (*state == NULL) \ 278219138Sdchagin return (PF_DROP); \ 279219138Sdchagin if (direction == PF_OUT && \ 280219138Sdchagin (((*state)->rule.ptr->rt == PF_ROUTETO && \ 281219138Sdchagin (*state)->rule.ptr->direction == PF_OUT) || \ 282219138Sdchagin ((*state)->rule.ptr->rt == PF_REPLYTO && \ 283219138Sdchagin (*state)->rule.ptr->direction == PF_IN)) && \ 2841590Srgrimes (*state)->rt_ifp != NULL && \ 2851590Srgrimes (*state)->rt_ifp != ifp) \ 286219138Sdchagin return (PF_PASS); \ 287219138Sdchagin } while (0) 288219138Sdchagin 289219138Sdchagin#define STATE_TRANSLATE(s) \ 290219138Sdchagin (s)->lan.addr.addr32[0] != (s)->gwy.addr.addr32[0] || \ 291219138Sdchagin ((s)->af == AF_INET6 && \ 2921590Srgrimes ((s)->lan.addr.addr32[1] != (s)->gwy.addr.addr32[1] || \ 2931590Srgrimes (s)->lan.addr.addr32[2] != (s)->gwy.addr.addr32[2] || \ 294189707Sjhb (s)->lan.addr.addr32[3] != (s)->gwy.addr.addr32[3])) || \ 2951590Srgrimes (s)->lan.port != (s)->gwy.port 2961590Srgrimes 2971590Srgrimesstatic __inline int pf_state_compare(struct pf_tree_node *, 2981590Srgrimes struct pf_tree_node *); 2991590Srgrimes 3001590Srgrimesstruct pf_state_tree tree_lan_ext, tree_ext_gwy; 301219138SdchaginRB_GENERATE(pf_state_tree, pf_tree_node, entry, pf_state_compare); 3021590Srgrimes 3031590Srgrimes#ifdef __FreeBSD__ 304234494Sjhbstatic int 305234494Sjhb#else 306234494Sjhbstatic __inline int 307234494Sjhb#endif 3081590Srgrimespf_state_compare(struct pf_tree_node *a, struct pf_tree_node *b) 30918400Sphk{ 31018470Sphk int diff; 31118400Sphk 312176471Sdes if ((diff = a->proto - b->proto) != 0) 313176471Sdes return (diff); 314176471Sdes if ((diff = a->af - b->af) != 0) 315226269Sdes return (diff); 316226269Sdes switch (a->af) { 317233925Sjhb#ifdef INET 318233925Sjhb case AF_INET: 319233925Sjhb if (a->addr[0].addr32[0] > b->addr[0].addr32[0]) 320233925Sjhb return (1); 321233925Sjhb if (a->addr[0].addr32[0] < b->addr[0].addr32[0]) 322233925Sjhb return (-1); 323233925Sjhb if (a->addr[1].addr32[0] > b->addr[1].addr32[0]) 324112203Sjhb return (1); 325112203Sjhb if (a->addr[1].addr32[0] < b->addr[1].addr32[0]) 326112203Sjhb return (-1); 3271590Srgrimes break; 3281590Srgrimes#endif /* INET */ 329226153Sdes#ifdef INET6 3301590Srgrimes case AF_INET6: 331100824Sdwmalone if (a->addr[0].addr32[3] > b->addr[0].addr32[3]) 3321590Srgrimes return (1); 3331590Srgrimes if (a->addr[0].addr32[3] < b->addr[0].addr32[3]) 334100824Sdwmalone return (-1); 335100824Sdwmalone if (a->addr[1].addr32[3] > b->addr[1].addr32[3]) 3361590Srgrimes return (1); 3371590Srgrimes if (a->addr[1].addr32[3] < b->addr[1].addr32[3]) 3381590Srgrimes return (-1); 3391590Srgrimes if (a->addr[0].addr32[2] > b->addr[0].addr32[2]) 340226153Sdes return (1); 3411590Srgrimes if (a->addr[0].addr32[2] < b->addr[0].addr32[2]) 3421590Srgrimes return (-1); 3431590Srgrimes if (a->addr[1].addr32[2] > b->addr[1].addr32[2]) 3441590Srgrimes return (1); 3451590Srgrimes if (a->addr[1].addr32[2] < b->addr[1].addr32[2]) 346219043Sdchagin return (-1); 347219043Sdchagin if (a->addr[0].addr32[1] > b->addr[0].addr32[1]) 348219043Sdchagin return (1); 349219043Sdchagin if (a->addr[0].addr32[1] < b->addr[0].addr32[1]) 350219043Sdchagin return (-1); 351219043Sdchagin if (a->addr[1].addr32[1] > b->addr[1].addr32[1]) 352219043Sdchagin return (1); 353219043Sdchagin if (a->addr[1].addr32[1] < b->addr[1].addr32[1]) 354219043Sdchagin return (-1); 355219043Sdchagin if (a->addr[0].addr32[0] > b->addr[0].addr32[0]) 356219043Sdchagin return (1); 357219043Sdchagin if (a->addr[0].addr32[0] < b->addr[0].addr32[0]) 358219043Sdchagin return (-1); 359219043Sdchagin if (a->addr[1].addr32[0] > b->addr[1].addr32[0]) 360219043Sdchagin return (1); 361219043Sdchagin if (a->addr[1].addr32[0] < b->addr[1].addr32[0]) 362219043Sdchagin return (-1); 363219043Sdchagin break; 364219043Sdchagin#endif /* INET6 */ 365219043Sdchagin } 366219043Sdchagin 367219043Sdchagin if ((diff = a->port[0] - b->port[0]) != 0) 368219043Sdchagin return (diff); 369219043Sdchagin if ((diff = a->port[1] - b->port[1]) != 0) 370219043Sdchagin return (diff); 371219043Sdchagin 372219043Sdchagin return (0); 373219043Sdchagin} 374219043Sdchagin 375219043Sdchagin#ifdef INET6 376219043Sdchaginvoid 377219043Sdchaginpf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af) 378219043Sdchagin{ 379219043Sdchagin switch (af) { 380219043Sdchagin#ifdef INET 381219043Sdchagin case AF_INET: 382219043Sdchagin dst->addr32[0] = src->addr32[0]; 383219043Sdchagin break; 384219043Sdchagin#endif /* INET */ 385219043Sdchagin case AF_INET6: 386219043Sdchagin dst->addr32[0] = src->addr32[0]; 387219043Sdchagin dst->addr32[1] = src->addr32[1]; 388219043Sdchagin dst->addr32[2] = src->addr32[2]; 389219043Sdchagin dst->addr32[3] = src->addr32[3]; 390219043Sdchagin break; 391219043Sdchagin } 392219043Sdchagin} 393219043Sdchagin#endif 394219043Sdchagin 395219043Sdchaginstruct pf_state * 396219043Sdchaginpf_find_state(struct pf_state_tree *tree, struct pf_tree_node *key) 397219043Sdchagin{ 398219043Sdchagin struct pf_tree_node *k; 399219043Sdchagin 400219043Sdchagin pf_status.fcounters[FCNT_STATE_SEARCH]++; 401219043Sdchagin k = RB_FIND(pf_state_tree, tree, key); 402219043Sdchagin if (k) 403219043Sdchagin return (k->state); 404219043Sdchagin else 405219043Sdchagin return (NULL); 406219043Sdchagin} 407219043Sdchagin 408219043Sdchaginint 409219043Sdchaginpf_insert_state(struct pf_state *state) 410219043Sdchagin{ 411219043Sdchagin struct pf_tree_node *keya, *keyb; 412219043Sdchagin 413219043Sdchagin keya = pool_get(&pf_tree_pl, PR_NOWAIT); 414219043Sdchagin if (keya == NULL) 415219043Sdchagin return (-1); 416219043Sdchagin keya->state = state; 417219043Sdchagin keya->proto = state->proto; 418219043Sdchagin keya->af = state->af; 419219043Sdchagin PF_ACPY(&keya->addr[0], &state->lan.addr, state->af); 420219043Sdchagin keya->port[0] = state->lan.port; 421219043Sdchagin PF_ACPY(&keya->addr[1], &state->ext.addr, state->af); 422219043Sdchagin keya->port[1] = state->ext.port; 423219043Sdchagin 424100824Sdwmalone /* Thou MUST NOT insert multiple duplicate keys */ 425100824Sdwmalone if (RB_INSERT(pf_state_tree, &tree_lan_ext, keya) != NULL) { 4261590Srgrimes if (pf_status.debug >= PF_DEBUG_MISC) { 4271590Srgrimes printf("pf: state insert failed: tree_lan_ext"); 4281590Srgrimes printf(" lan: "); 429100824Sdwmalone pf_print_host(&state->lan.addr, state->lan.port, 4301590Srgrimes state->af); 4311590Srgrimes printf(" gwy: "); 4321590Srgrimes pf_print_host(&state->gwy.addr, state->gwy.port, 4331590Srgrimes state->af); 4341590Srgrimes printf(" ext: "); 4351590Srgrimes pf_print_host(&state->ext.addr, state->ext.port, 4361590Srgrimes state->af); 4371590Srgrimes printf("\n"); 4381590Srgrimes } 4391590Srgrimes pool_put(&pf_tree_pl, keya); 4401590Srgrimes return (-1); 4411590Srgrimes } 4421590Srgrimes 4431590Srgrimes keyb = pool_get(&pf_tree_pl, PR_NOWAIT); 4441590Srgrimes if (keyb == NULL) { 4451590Srgrimes /* Need to pull out the other state */ 4461590Srgrimes RB_REMOVE(pf_state_tree, &tree_lan_ext, keya); 4471590Srgrimes pool_put(&pf_tree_pl, keya); 448171333Sjhb return (-1); 4491590Srgrimes } 45018400Sphk keyb->state = state; 45118400Sphk keyb->proto = state->proto; 45218400Sphk keyb->af = state->af; 453176471Sdes PF_ACPY(&keyb->addr[0], &state->ext.addr, state->af); 454176471Sdes keyb->port[0] = state->ext.port; 455176471Sdes PF_ACPY(&keyb->addr[1], &state->gwy.addr, state->af); 456189707Sjhb keyb->port[1] = state->gwy.port; 457189707Sjhb 458189707Sjhb if (RB_INSERT(pf_state_tree, &tree_ext_gwy, keyb) != NULL) { 459219043Sdchagin if (pf_status.debug >= PF_DEBUG_MISC) { 460219043Sdchagin printf("pf: state insert failed: tree_ext_gwy"); 461219043Sdchagin printf(" lan: "); 462219043Sdchagin pf_print_host(&state->lan.addr, state->lan.port, 463226269Sdes state->af); 464226269Sdes printf(" gwy: "); 465226269Sdes pf_print_host(&state->gwy.addr, state->gwy.port, 466233925Sjhb state->af); 467233925Sjhb printf(" ext: "); 468233925Sjhb pf_print_host(&state->ext.addr, state->ext.port, 469233925Sjhb state->af); 470233925Sjhb printf("\n"); 471233925Sjhb } 4721590Srgrimes RB_REMOVE(pf_state_tree, &tree_lan_ext, keya); 473226153Sdes pool_put(&pf_tree_pl, keya); 4741590Srgrimes pool_put(&pf_tree_pl, keyb); 4751590Srgrimes return (-1); 4761590Srgrimes } 477151930Srwatson 478151930Srwatson pf_status.fcounters[FCNT_STATE_INSERT]++; 479151930Srwatson pf_status.states++; 480151930Srwatson#if NPFSYNC 481151930Srwatson pfsync_insert_state(state); 482151930Srwatson#endif 483151930Srwatson return (0); 484151930Srwatson} 485151930Srwatson 486226153Sdesvoid 487203551Sjhpf_purge_timeout(void *arg) 488203551Sjh{ 489151930Srwatson#ifdef __FreeBSD__ 490226153Sdes struct callout *to = arg; 491151930Srwatson#else 4921590Srgrimes struct timeout *to = arg; 493123187Speter#endif 494123187Speter int s; 495123187Speter 496123187Speter#ifdef __FreeBSD__ 497123187Speter PF_LOCK(); 4981590Srgrimes#endif 4991590Srgrimes s = splsoftnet(); 5001590Srgrimes pf_purge_expired_states(); 5011590Srgrimes pf_purge_expired_fragments(); 5021590Srgrimes splx(s); 503226153Sdes#ifdef __FreeBSD__ 504203551Sjh PF_UNLOCK(); 5051590Srgrimes#endif 506226153Sdes 5071590Srgrimes#ifdef __FreeBSD__ 5081590Srgrimes callout_reset(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz, 5091590Srgrimes pf_purge_timeout, to); 5101590Srgrimes#else 5114721Sphk timeout_add(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz); 5121590Srgrimes#endif 5131590Srgrimes} 5141590Srgrimes 515100824Sdwmaloneu_int32_t 516219043Sdchaginpf_state_expires(const struct pf_state *state) 5171590Srgrimes{ 518100824Sdwmalone u_int32_t timeout; 519100824Sdwmalone u_int32_t start; 520226269Sdes u_int32_t end; 5211590Srgrimes u_int32_t states; 522219043Sdchagin 523219043Sdchagin /* handle all PFTM_* > PFTM_MAX here */ 524226153Sdes if (state->timeout == PFTM_PURGE) 5251590Srgrimes#ifdef __FreeBSD__ 526226153Sdes return (time_second); 52747957Sdt#else 5281590Srgrimes return (time.tv_sec); 5291590Srgrimes#endif 530219043Sdchagin if (state->timeout == PFTM_UNTIL_PACKET) 531219043Sdchagin return (0); 532226148Sdes#ifdef __FreeBSD__ 533226148Sdes KASSERT((state->timeout < PFTM_MAX), 534226150Sdes ("pf_state_expires: timeout > PFTM_MAX")); 535226157Sdes#else 536226157Sdes KASSERT(state->timeout < PFTM_MAX); 5371590Srgrimes#endif 5381590Srgrimes timeout = state->rule.ptr->timeout[state->timeout]; 5391590Srgrimes if (!timeout) 540226148Sdes timeout = pf_default_rule.timeout[state->timeout]; 541226148Sdes start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START]; 542226148Sdes if (start) { 543226153Sdes end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END]; 544226164Sdes states = state->rule.ptr->states; 5451590Srgrimes } else { 5461590Srgrimes start = pf_default_rule.timeout[PFTM_ADAPTIVE_START]; 5471590Srgrimes end = pf_default_rule.timeout[PFTM_ADAPTIVE_END]; 548226148Sdes states = pf_status.states; 549226148Sdes } 550226148Sdes if (end && states > start && start < end) { 551226150Sdes if (states < end) 552226153Sdes return (state->expire + timeout * (end - states) / 553226164Sdes (end - start)); 554158766Snetchild else 555158766Snetchild#ifdef __FreeBSD__ 556226148Sdes return (time_second); 557226148Sdes#else 558226150Sdes return (time.tv_sec); 559226153Sdes#endif 560226164Sdes } 561226148Sdes return (state->expire + timeout); 562226148Sdes} 563226148Sdes 564226148Sdesvoid 565226150Sdespf_purge_expired_states(void) 566226150Sdes{ 567226153Sdes struct pf_tree_node *cur, *peer, *next; 568226164Sdes struct pf_tree_node key; 569158766Snetchild 570158766Snetchild for (cur = RB_MIN(pf_state_tree, &tree_ext_gwy); cur; cur = next) { 571226148Sdes next = RB_NEXT(pf_state_tree, &tree_ext_gwy, cur); 572226148Sdes 573226148Sdes#ifdef __FreeBSD__ 574226148Sdes if (pf_state_expires(cur->state) <= (u_int32_t)time_second) { 575226150Sdes#else 576226153Sdes if (pf_state_expires(cur->state) <= time.tv_sec) { 577226164Sdes#endif 578158766Snetchild if (cur->state->src.state == PF_TCPS_PROXY_DST) 579158766Snetchild pf_send_tcp(cur->state->rule.ptr, 580226148Sdes cur->state->af, 581226148Sdes &cur->state->ext.addr, 582226150Sdes &cur->state->lan.addr, 583226153Sdes cur->state->ext.port, 584226164Sdes cur->state->lan.port, 585158766Snetchild cur->state->src.seqhi, 586158766Snetchild cur->state->src.seqlo + 1, 587226148Sdes 0, 588226148Sdes TH_RST|TH_ACK, 0, 0); 589226150Sdes RB_REMOVE(pf_state_tree, &tree_ext_gwy, cur); 590226150Sdes 591226153Sdes /* Need this key's peer (in the other tree) */ 592226164Sdes key.state = cur->state; 593158766Snetchild key.proto = cur->state->proto; 594158766Snetchild key.af = cur->state->af; 595226148Sdes PF_ACPY(&key.addr[0], &cur->state->lan.addr, 596226148Sdes cur->state->af); 597226150Sdes key.port[0] = cur->state->lan.port; 598226150Sdes PF_ACPY(&key.addr[1], &cur->state->ext.addr, 599226153Sdes cur->state->af); 600226164Sdes key.port[1] = cur->state->ext.port; 601158766Snetchild 602158766Snetchild peer = RB_FIND(pf_state_tree, &tree_lan_ext, &key); 603226148Sdes#ifdef __FreeBSD__ 604226148Sdes KASSERT((peer), ("peer null :%s", __FUNCTION__)); 605226150Sdes KASSERT((peer->state == cur->state), 606226153Sdes ("peer->state != cur->state: %s", __FUNCTION__)); 607226164Sdes#else 608158766Snetchild KASSERT(peer); 609158766Snetchild KASSERT(peer->state == cur->state); 610226148Sdes#endif 611226148Sdes RB_REMOVE(pf_state_tree, &tree_lan_ext, peer); 612226148Sdes 613226150Sdes#if NPFSYNC 614226150Sdes pfsync_delete_state(cur->state); 615226153Sdes#endif 616226164Sdes if (--cur->state->rule.ptr->states <= 0) 617158766Snetchild pf_rm_rule(NULL, cur->state->rule.ptr); 618158766Snetchild if (cur->state->nat_rule.ptr != NULL) 619226148Sdes if (--cur->state->nat_rule.ptr->states <= 0) 620226148Sdes pf_rm_rule(NULL, 621226148Sdes cur->state->nat_rule.ptr); 622226150Sdes if (cur->state->anchor.ptr != NULL) 623226150Sdes if (--cur->state->anchor.ptr->states <= 0) 624226150Sdes pf_rm_rule(NULL, 625226153Sdes cur->state->anchor.ptr); 626226164Sdes pf_normalize_tcp_cleanup(cur->state); 627158766Snetchild pool_put(&pf_state_pl, cur->state); 628158766Snetchild pool_put(&pf_tree_pl, cur); 629226148Sdes pool_put(&pf_tree_pl, peer); 630226148Sdes pf_status.fcounters[FCNT_STATE_REMOVALS]++; 631226148Sdes pf_status.states--; 632226148Sdes } 633226150Sdes } 634226153Sdes} 635226164Sdes 636158766Snetchildint 637158766Snetchildpf_tbladdr_setup(struct pf_ruleset *rs, struct pf_addr_wrap *aw) 638226148Sdes{ 639226148Sdes if (aw->type != PF_ADDR_TABLE) 640226150Sdes return (0); 641226153Sdes if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname)) == NULL) 642226164Sdes return (1); 643158766Snetchild return (0); 644158766Snetchild} 645226148Sdes 646226148Sdesvoid 647226153Sdespf_tbladdr_remove(struct pf_addr_wrap *aw) 648226164Sdes{ 649158766Snetchild if (aw->type != PF_ADDR_TABLE || aw->p.tbl == NULL) 650158766Snetchild return; 651226148Sdes pfr_detach_table(aw->p.tbl); 652226148Sdes aw->p.tbl = NULL; 653226153Sdes} 654226164Sdes 655158766Snetchildvoid 656158766Snetchildpf_tbladdr_copyout(struct pf_addr_wrap *aw) 657226148Sdes{ 658226148Sdes struct pfr_ktable *kt = aw->p.tbl; 659226150Sdes 660226150Sdes if (aw->type != PF_ADDR_TABLE || kt == NULL) 661226153Sdes return; 662226164Sdes if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) 663158766Snetchild kt = kt->pfrkt_root; 664158766Snetchild aw->p.tbl = NULL; 665226148Sdes aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ? 666171221Speter kt->pfrkt_cnt : -1; 667226148Sdes} 668226150Sdes 669226150Sdesint 670226153Sdespf_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) 671226164Sdes{ 672226153Sdes if (aw->type != PF_ADDR_DYNIFTL) 673171221Speter return (0); 674171221Speter aw->p.dyn = pool_get(&pf_addr_pl, PR_NOWAIT); 675226164Sdes if (aw->p.dyn == NULL) 676171221Speter return (1); 677171221Speter bcopy(aw->v.ifname, aw->p.dyn->ifname, sizeof(aw->p.dyn->ifname)); 678226148Sdes aw->p.dyn->ifp = ifunit(aw->p.dyn->ifname); 679171221Speter if (aw->p.dyn->ifp == NULL) { 680226148Sdes pool_put(&pf_addr_pl, aw->p.dyn); 681226150Sdes aw->p.dyn = NULL; 682226150Sdes return (1); 683226153Sdes } 684226164Sdes aw->p.dyn->addr = &aw->v.a.addr; 685226153Sdes aw->p.dyn->af = af; 686158766Snetchild aw->p.dyn->undefined = 1; 687158766Snetchild#ifndef __FreeBSD__ 688226164Sdes aw->p.dyn->hook_cookie = hook_establish( 689158766Snetchild aw->p.dyn->ifp->if_addrhooks, 1, 690158766Snetchild pf_dynaddr_update, aw->p.dyn); 691226148Sdes if (aw->p.dyn->hook_cookie == NULL) { 692226148Sdes pool_put(&pf_addr_pl, aw->p.dyn); 693226150Sdes aw->p.dyn = NULL; 694226150Sdes return (1); 695226153Sdes } 696226164Sdes#else 697158766Snetchild PF_UNLOCK(); 698158766Snetchild aw->p.dyn->hook_cookie = EVENTHANDLER_REGISTER(ifaddr_event, 699226148Sdes pf_dynaddr_update_event, aw->p.dyn, EVENTHANDLER_PRI_ANY); 700226148Sdes PF_LOCK(); 701226150Sdes if (aw->p.dyn->hook_cookie == NULL) { 702226150Sdes pool_put(&pf_addr_pl, aw->p.dyn); 703226153Sdes aw->p.dyn = NULL; 704226164Sdes return (1); 705158766Snetchild } 706158766Snetchild#endif 707226148Sdes pf_dynaddr_update(aw->p.dyn); 708226148Sdes return (0); 709226150Sdes} 710226150Sdes 711226153Sdes#ifdef __FreeBSD__ 712226164Sdesvoid 713158766Snetchildpf_dynaddr_update_event(void *arg, struct ifnet *ifp) 714158766Snetchild{ 715226148Sdes PF_LOCK(); 716226148Sdes pf_dynaddr_update(arg); 717226150Sdes PF_UNLOCK(); 718226153Sdes} 719226164Sdes#endif 720226148Sdes 721226148Sdesvoid 722226148Sdespf_dynaddr_update(void *p) 723226148Sdes{ 724165758Srodrigc struct pf_addr_dyn *ad = (struct pf_addr_dyn *)p; 725226153Sdes struct ifaddr *ia; 726226164Sdes int s, changed = 0; 727165758Srodrigc 728158766Snetchild if (ad == NULL || ad->ifp == NULL) 729158766Snetchild panic("pf_dynaddr_update"); 730226153Sdes s = splsoftnet(); 731226164Sdes TAILQ_FOREACH(ia, &ad->ifp->if_addrlist, ifa_list) 732158766Snetchild if (ia->ifa_addr != NULL && 733158766Snetchild ia->ifa_addr->sa_family == ad->af) { 734165758Srodrigc if (ad->af == AF_INET) { 735165758Srodrigc struct in_addr *a, *b; 736226153Sdes 737226164Sdes a = &ad->addr->v4; 738165758Srodrigc b = &((struct sockaddr_in *)ia->ifa_addr) 739165758Srodrigc ->sin_addr; 740165758Srodrigc if (ad->undefined || 741158766Snetchild memcmp(a, b, sizeof(*a))) { 742226148Sdes bcopy(b, a, sizeof(*a)); 743226148Sdes changed = 1; 744226148Sdes } 745226148Sdes } else if (ad->af == AF_INET6) { 746226150Sdes struct in6_addr *a, *b; 747226153Sdes 748226164Sdes a = &ad->addr->v6; 749226151Sdes b = &((struct sockaddr_in6 *)ia->ifa_addr) 750175138Sjhb ->sin6_addr; 751175138Sjhb if (ad->undefined || 752226153Sdes memcmp(a, b, sizeof(*a))) { 753226164Sdes bcopy(b, a, sizeof(*a)); 754175138Sjhb changed = 1; 755158766Snetchild } 756158766Snetchild } 757226148Sdes if (changed) 758171221Speter ad->undefined = 0; 759226148Sdes break; 760226150Sdes } 761158766Snetchild if (ia == NULL) 762226150Sdes ad->undefined = 1; 763226150Sdes splx(s); 764226153Sdes} 765226164Sdes 766158766Snetchildvoid 767158766Snetchildpf_dynaddr_remove(struct pf_addr_wrap *aw) 768226148Sdes{ 769171221Speter if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL) 770226148Sdes return; 771226150Sdes#ifndef __FreeBSD__ 772171221Speter hook_disestablish(aw->p.dyn->ifp->if_addrhooks, 773226150Sdes aw->p.dyn->hook_cookie); 774226153Sdes#else 775226164Sdes PF_UNLOCK(); 776171221Speter EVENTHANDLER_DEREGISTER(ifaddr_event, aw->p.dyn->hook_cookie); 777171221Speter PF_LOCK(); 778226148Sdes#endif 779226148Sdes pool_put(&pf_addr_pl, aw->p.dyn); 780226150Sdes aw->p.dyn = NULL; 781226153Sdes} 782226164Sdes 783158766Snetchildvoid 784158766Snetchildpf_dynaddr_copyout(struct pf_addr_wrap *aw) 785226148Sdes{ 786226148Sdes if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL) 787226148Sdes return; 788226150Sdes bcopy(aw->p.dyn->ifname, aw->v.ifname, sizeof(aw->v.ifname)); 789226153Sdes aw->p.dyn = (struct pf_addr_dyn *)1; 790226164Sdes} 791158766Snetchild 792158766Snetchildvoid 793226148Sdespf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af) 794226148Sdes{ 795226150Sdes switch (af) { 796226153Sdes#ifdef INET 797226164Sdes case AF_INET: { 798158766Snetchild u_int32_t a = ntohl(addr->addr32[0]); 799158766Snetchild printf("%u.%u.%u.%u", (a>>24)&255, (a>>16)&255, 800226148Sdes (a>>8)&255, a&255); 801226148Sdes if (p) { 802226153Sdes p = ntohs(p); 803226164Sdes printf(":%u", p); 804158766Snetchild } 805158766Snetchild break; 806226153Sdes } 807226164Sdes#endif /* INET */ 808158766Snetchild#ifdef INET6 809158766Snetchild case AF_INET6: { 810158766Snetchild u_int16_t b; 811226148Sdes u_int8_t i, curstart = 255, curend = 0, 812226148Sdes maxstart = 0, maxend = 0; 813226148Sdes for (i = 0; i < 8; i++) { 814226153Sdes if (!addr->addr16[i]) { 815226164Sdes if (curstart == 255) 816158766Snetchild curstart = i; 817158766Snetchild else 818158766Snetchild curend = i; 819226148Sdes } else { 820226148Sdes if (curstart) { 821226150Sdes if ((curend - curstart) > 822226153Sdes (maxend - maxstart)) { 823226164Sdes maxstart = curstart; 824158766Snetchild maxend = curend; 825158766Snetchild curstart = 255; 826158766Snetchild } 827226148Sdes } 828226148Sdes } 829226153Sdes } 830226164Sdes for (i = 0; i < 8; i++) { 831158766Snetchild if (i >= maxstart && i <= maxend) { 832158766Snetchild if (maxend != 7) { 833158766Snetchild if (i == maxstart) 834226148Sdes printf(":"); 835226148Sdes } else { 836226153Sdes if (i == maxend) 837226164Sdes printf(":"); 838158766Snetchild } 839158766Snetchild } else { 840158766Snetchild b = ntohs(addr->addr16[i]); 841226148Sdes printf("%x", b); 842226148Sdes if (i < 7) 843226150Sdes printf(":"); 844226150Sdes } 845226153Sdes } 846226164Sdes if (p) { 847158766Snetchild p = ntohs(p); 848158766Snetchild printf("[%u]", p); 849226148Sdes } 850226148Sdes break; 851226150Sdes } 852226150Sdes#endif /* INET6 */ 853226153Sdes } 854226164Sdes} 855158766Snetchild 856158766Snetchildvoid 857226148Sdespf_print_state(struct pf_state *s) 858226148Sdes{ 859226150Sdes switch (s->proto) { 860226153Sdes case IPPROTO_TCP: 861226164Sdes printf("TCP "); 862158766Snetchild break; 863158766Snetchild case IPPROTO_UDP: 864226148Sdes printf("UDP "); 865226148Sdes break; 866226150Sdes case IPPROTO_ICMP: 867226150Sdes printf("ICMP "); 868226153Sdes break; 869226164Sdes case IPPROTO_ICMPV6: 870158766Snetchild printf("ICMPV6 "); 871158766Snetchild break; 872226148Sdes default: 873226148Sdes printf("%u ", s->proto); 874226150Sdes break; 875226153Sdes } 876226164Sdes pf_print_host(&s->lan.addr, s->lan.port, s->af); 877158766Snetchild printf(" "); 878158766Snetchild pf_print_host(&s->gwy.addr, s->gwy.port, s->af); 879226148Sdes printf(" "); 880226148Sdes pf_print_host(&s->ext.addr, s->ext.port, s->af); 881226150Sdes printf(" [lo=%u high=%u win=%u modulator=%u", s->src.seqlo, 882226150Sdes s->src.seqhi, s->src.max_win, s->src.seqdiff); 883226153Sdes if (s->src.wscale && s->dst.wscale) 884226164Sdes printf(" wscale=%u", s->src.wscale & PF_WSCALE_MASK); 885158766Snetchild printf("]"); 886158766Snetchild printf(" [lo=%u high=%u win=%u modulator=%u", s->dst.seqlo, 887226148Sdes s->dst.seqhi, s->dst.max_win, s->dst.seqdiff); 888226148Sdes if (s->src.wscale && s->dst.wscale) 889226153Sdes printf(" wscale=%u", s->dst.wscale & PF_WSCALE_MASK); 890226164Sdes printf("]"); 891158766Snetchild printf(" %u:%u", s->src.state, s->dst.state); 892158766Snetchild} 893158766Snetchild 894226148Sdesvoid 895226148Sdespf_print_flags(u_int8_t f) 896226153Sdes{ 897226164Sdes if (f) 898158766Snetchild printf(" "); 899158766Snetchild if (f & TH_FIN) 900158766Snetchild printf("F"); 901226148Sdes if (f & TH_SYN) 902226148Sdes printf("S"); 903226153Sdes if (f & TH_RST) 904226164Sdes printf("R"); 905158766Snetchild if (f & TH_PUSH) 906158766Snetchild printf("P"); 907226148Sdes if (f & TH_ACK) 908226148Sdes printf("A"); 909226150Sdes if (f & TH_URG) 910226153Sdes printf("U"); 911226164Sdes if (f & TH_ECE) 912158766Snetchild printf("E"); 913158766Snetchild if (f & TH_CWR) 914226148Sdes printf("W"); 915226148Sdes} 916226148Sdes 917226153Sdes#define PF_SET_SKIP_STEPS(i) \ 918226164Sdes do { \ 919158766Snetchild while (head[i] != cur) { \ 920158766Snetchild head[i]->skip[i].ptr = cur; \ 921226148Sdes head[i] = TAILQ_NEXT(head[i], entries); \ 922226148Sdes } \ 923226150Sdes } while (0) 924226150Sdes 925226150Sdesvoid 926226150Sdespf_calc_skip_steps(struct pf_rulequeue *rules) 927226150Sdes{ 928226150Sdes struct pf_rule *cur, *prev, *head[PF_SKIP_COUNT]; 929226153Sdes int i; 930226164Sdes 931158766Snetchild cur = TAILQ_FIRST(rules); 932158766Snetchild prev = cur; 933226148Sdes for (i = 0; i < PF_SKIP_COUNT; ++i) 934226148Sdes head[i] = cur; 935226150Sdes while (cur != NULL) { 936226153Sdes 937226164Sdes if (cur->ifp != prev->ifp || cur->ifnot != prev->ifnot) 938158766Snetchild PF_SET_SKIP_STEPS(PF_SKIP_IFP); 939158766Snetchild if (cur->direction != prev->direction) 940226148Sdes PF_SET_SKIP_STEPS(PF_SKIP_DIR); 941226148Sdes if (cur->af != prev->af) 942226153Sdes PF_SET_SKIP_STEPS(PF_SKIP_AF); 943226164Sdes if (cur->proto != prev->proto) 944158766Snetchild PF_SET_SKIP_STEPS(PF_SKIP_PROTO); 945158766Snetchild if (cur->src.not != prev->src.not || 946158766Snetchild pf_addr_wrap_neq(&cur->src.addr, &prev->src.addr)) 947226148Sdes PF_SET_SKIP_STEPS(PF_SKIP_SRC_ADDR); 948226148Sdes if (cur->src.port[0] != prev->src.port[0] || 949226148Sdes cur->src.port[1] != prev->src.port[1] || 950226148Sdes cur->src.port_op != prev->src.port_op) 951226148Sdes PF_SET_SKIP_STEPS(PF_SKIP_SRC_PORT); 952226148Sdes if (cur->dst.not != prev->dst.not || 953226148Sdes pf_addr_wrap_neq(&cur->dst.addr, &prev->dst.addr)) 954226148Sdes PF_SET_SKIP_STEPS(PF_SKIP_DST_ADDR); 955226148Sdes if (cur->dst.port[0] != prev->dst.port[0] || 956226148Sdes cur->dst.port[1] != prev->dst.port[1] || 957226148Sdes cur->dst.port_op != prev->dst.port_op) 958226148Sdes PF_SET_SKIP_STEPS(PF_SKIP_DST_PORT); 959226148Sdes 960226150Sdes prev = cur; 961226153Sdes cur = TAILQ_NEXT(cur, entries); 962226164Sdes } 963158766Snetchild for (i = 0; i < PF_SKIP_COUNT; ++i) 964158766Snetchild PF_SET_SKIP_STEPS(i); 965226148Sdes} 966226148Sdes 967226153Sdesint 968226164Sdespf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2) 969158766Snetchild{ 970158766Snetchild if (aw1->type != aw2->type) 971158766Snetchild return (1); 972226148Sdes switch (aw1->type) { 973226148Sdes case PF_ADDR_ADDRMASK: 974226150Sdes if (PF_ANEQ(&aw1->v.a.addr, &aw2->v.a.addr, 0)) 975226153Sdes return (1); 976226164Sdes if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0)) 977158766Snetchild return (1); 978158766Snetchild return (0); 979226148Sdes case PF_ADDR_DYNIFTL: 980226148Sdes if (aw1->p.dyn->ifp != aw2->p.dyn->ifp) 981226150Sdes return (1); 982226150Sdes if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0)) 983226153Sdes return (1); 984226164Sdes return (0); 985158766Snetchild case PF_ADDR_NOROUTE: 986158766Snetchild return (0); 987226148Sdes case PF_ADDR_TABLE: 988226148Sdes return (aw1->p.tbl != aw2->p.tbl); 989226150Sdes default: 990226150Sdes printf("invalid address type: %d\n", aw1->type); 991226153Sdes return (1); 992226164Sdes } 993158766Snetchild} 994158766Snetchild 995226148Sdesvoid 996226148Sdespf_rule_set_qid(struct pf_rulequeue *rules) 997226150Sdes{ 998226153Sdes struct pf_rule *rule; 999226164Sdes 1000158766Snetchild TAILQ_FOREACH(rule, rules, entries) 1001158766Snetchild if (rule->qname[0] != 0) { 1002226148Sdes rule->qid = pf_qname_to_qid(rule->qname); 1003226148Sdes if (rule->pqname[0] != 0) 1004226150Sdes rule->pqid = pf_qname_to_qid(rule->pqname); 1005226153Sdes else 1006226164Sdes rule->pqid = rule->qid; 1007158766Snetchild } 1008158766Snetchild} 1009226148Sdes 1010226269Sdesu_int32_t 1011226269Sdespf_qname_to_qid(char *qname) 1012226269Sdes{ 1013226269Sdes struct pf_altq *altq; 1014226269Sdes 1015226269Sdes TAILQ_FOREACH(altq, pf_altqs_active, entries) 1016226269Sdes if (!strcmp(altq->qname, qname)) 1017226269Sdes return (altq->qid); 1018226269Sdes 1019226269Sdes return (0); 1020226269Sdes} 1021226269Sdes 1022226269Sdesvoid 1023226269Sdespf_update_anchor_rules() 1024226269Sdes{ 1025226269Sdes struct pf_rule *rule; 1026226269Sdes int i; 1027226269Sdes 1028226269Sdes for (i = 0; i < PF_RULESET_MAX; ++i) 1029226269Sdes TAILQ_FOREACH(rule, pf_main_ruleset.rules[i].active.ptr, 1030226269Sdes entries) 1031226269Sdes if (rule->anchorname[0]) 1032226269Sdes rule->anchor = pf_find_anchor(rule->anchorname); 1033226269Sdes else 1034226269Sdes rule->anchor = NULL; 1035226269Sdes} 1036226269Sdes 1037226159Sdesu_int16_t 1038232072Sjhbpf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new, u_int8_t udp) 1039232128Sjhb{ 1040232128Sjhb u_int32_t l; 1041232128Sjhb 1042232072Sjhb if (udp && !cksum) 1043232072Sjhb return (0x0000); 1044232072Sjhb l = cksum + old - new; 1045232072Sjhb l = (l >> 16) + (l & 65535); 1046232072Sjhb l = l & 65535; 10471590Srgrimes if (udp && !l) 10481590Srgrimes return (0xFFFF); 1049199024Sattilio return (l); 1050226150Sdes} 10511590Srgrimes 1052226153Sdesvoid 10531590Srgrimespf_change_ap(struct pf_addr *a, u_int16_t *p, u_int16_t *ic, u_int16_t *pc, 1054226153Sdes struct pf_addr *an, u_int16_t pn, u_int8_t u, sa_family_t af) 10551590Srgrimes{ 10561590Srgrimes struct pf_addr ao; 1057100824Sdwmalone u_int16_t po = *p; 1058219043Sdchagin 10591590Srgrimes PF_ACPY(&ao, a, af); 1060100824Sdwmalone PF_ACPY(a, an, af); 1061100824Sdwmalone 1062100824Sdwmalone *p = pn; 10631590Srgrimes 1064219043Sdchagin switch (af) { 1065219043Sdchagin#ifdef INET 1066226153Sdes case AF_INET: 10671590Srgrimes *ic = pf_cksum_fixup(pf_cksum_fixup(*ic, 1068226153Sdes ao.addr16[0], an->addr16[0], 0), 10691590Srgrimes ao.addr16[1], an->addr16[1], 0); 10701590Srgrimes *p = pn; 10711590Srgrimes *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc, 1072226153Sdes ao.addr16[0], an->addr16[0], u), 10731590Srgrimes ao.addr16[1], an->addr16[1], u), 1074226153Sdes po, pn, u); 10751590Srgrimes break; 10761590Srgrimes#endif /* INET */ 1077226153Sdes#ifdef INET6 10781590Srgrimes case AF_INET6: 1079226153Sdes *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup( 10801590Srgrimes pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup( 10811590Srgrimes pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc, 1082226153Sdes ao.addr16[0], an->addr16[0], u), 10831590Srgrimes ao.addr16[1], an->addr16[1], u), 1084226153Sdes ao.addr16[2], an->addr16[2], u), 10851590Srgrimes ao.addr16[3], an->addr16[3], u), 1086226153Sdes ao.addr16[4], an->addr16[4], u), 10871590Srgrimes ao.addr16[5], an->addr16[5], u), 1088226153Sdes ao.addr16[6], an->addr16[6], u), 10891590Srgrimes ao.addr16[7], an->addr16[7], u), 1090226153Sdes po, pn, u); 10911590Srgrimes break; 10921590Srgrimes#endif /* INET6 */ 1093100824Sdwmalone } 1094100824Sdwmalone} 10951590Srgrimes 1096226153Sdes 10971590Srgrimes/* Changes a u_int32_t. Uses a void * so there are no align restrictions */ 10981590Srgrimesvoid 1099100824Sdwmalonepf_change_a(void *a, u_int16_t *c, u_int32_t an, u_int8_t u) 1100115759Speter{ 11011590Srgrimes u_int32_t ao; 1102115759Speter 1103115759Speter memcpy(&ao, a, sizeof(ao)); 1104115759Speter memcpy(a, &an, sizeof(u_int32_t)); 1105115759Speter *c = pf_cksum_fixup(pf_cksum_fixup(*c, ao / 65536, an / 65536, u), 1106115759Speter ao % 65536, an % 65536, u); 1107115759Speter} 1108115759Speter 1109115759Speter#ifdef INET6 1110115759Spetervoid 1111115759Speterpf_change_a6(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u) 1112115759Speter{ 1113115759Speter struct pf_addr ao; 1114115759Speter 1115115759Speter PF_ACPY(&ao, a, AF_INET6); 1116115759Speter PF_ACPY(a, an, AF_INET6); 1117115759Speter 1118115759Speter *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup( 1119115759Speter pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup( 1120115759Speter pf_cksum_fixup(pf_cksum_fixup(*c, 1121115759Speter ao.addr16[0], an->addr16[0], u), 1122115759Speter ao.addr16[1], an->addr16[1], u), 1123115759Speter ao.addr16[2], an->addr16[2], u), 1124115759Speter ao.addr16[3], an->addr16[3], u), 1125115759Speter ao.addr16[4], an->addr16[4], u), 1126115759Speter ao.addr16[5], an->addr16[5], u), 1127115759Speter ao.addr16[6], an->addr16[6], u), 1128115759Speter ao.addr16[7], an->addr16[7], u); 1129115759Speter} 1130115759Speter#endif /* INET6 */ 1131115759Speter 1132115759Spetervoid 1133115759Speterpf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa, 1134115759Speter struct pf_addr *na, u_int16_t np, u_int16_t *pc, u_int16_t *h2c, 1135115759Speter u_int16_t *ic, u_int16_t *hc, u_int8_t u, sa_family_t af) 1136115759Speter{ 1137115759Speter struct pf_addr oia, ooa; 1138115759Speter 1139115759Speter PF_ACPY(&oia, ia, af); 1140115759Speter PF_ACPY(&ooa, oa, af); 1141115759Speter 1142115759Speter /* Change inner protocol port, fix inner protocol checksum. */ 1143115759Speter if (ip != NULL) { 1144115759Speter u_int16_t oip = *ip; 1145115759Speter u_int32_t opc; 1146115759Speter 1147115759Speter if (pc != NULL) 1148115759Speter opc = *pc; 1149100824Sdwmalone *ip = np; 1150100824Sdwmalone if (pc != NULL) 11511590Srgrimes *pc = pf_cksum_fixup(*pc, oip, *ip, u); 11521590Srgrimes *ic = pf_cksum_fixup(*ic, oip, *ip, 0); 1153226153Sdes if (pc != NULL) 11541590Srgrimes *ic = pf_cksum_fixup(*ic, opc, *pc, 0); 11551590Srgrimes } 1156226153Sdes /* Change inner ip address, fix inner ip and icmp checksums. */ 11571590Srgrimes PF_ACPY(ia, na, af); 11581590Srgrimes switch (af) { 11591590Srgrimes#ifdef INET 11601590Srgrimes case AF_INET: { 11611590Srgrimes u_int32_t oh2c = *h2c; 11621590Srgrimes 1163226153Sdes *h2c = pf_cksum_fixup(pf_cksum_fixup(*h2c, 11641590Srgrimes oia.addr16[0], ia->addr16[0], 0), 11651590Srgrimes oia.addr16[1], ia->addr16[1], 0); 11661590Srgrimes *ic = pf_cksum_fixup(pf_cksum_fixup(*ic, 11671590Srgrimes oia.addr16[0], ia->addr16[0], 0), 11681590Srgrimes oia.addr16[1], ia->addr16[1], 0); 1169226153Sdes *ic = pf_cksum_fixup(*ic, oh2c, *h2c, 0); 11701590Srgrimes break; 11711590Srgrimes } 11721590Srgrimes#endif /* INET */ 11731590Srgrimes#ifdef INET6 11741590Srgrimes case AF_INET6: 11751590Srgrimes *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup( 11761590Srgrimes pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup( 11771590Srgrimes pf_cksum_fixup(pf_cksum_fixup(*ic, 1178226153Sdes oia.addr16[0], ia->addr16[0], u), 11791590Srgrimes oia.addr16[1], ia->addr16[1], u), 11801590Srgrimes oia.addr16[2], ia->addr16[2], u), 11811590Srgrimes oia.addr16[3], ia->addr16[3], u), 11821590Srgrimes oia.addr16[4], ia->addr16[4], u), 1183226153Sdes oia.addr16[5], ia->addr16[5], u), 11841590Srgrimes oia.addr16[6], ia->addr16[6], u), 11851590Srgrimes oia.addr16[7], ia->addr16[7], u); 11861590Srgrimes break; 1187226153Sdes#endif /* INET6 */ 1188226153Sdes } 11891590Srgrimes /* Change outer ip address, fix outer ip or icmpv6 checksum. */ 11901590Srgrimes PF_ACPY(oa, na, af); 1191115759Speter switch (af) { 1192115759Speter#ifdef INET 1193115759Speter case AF_INET: 1194115759Speter *hc = pf_cksum_fixup(pf_cksum_fixup(*hc, 1195115759Speter ooa.addr16[0], oa->addr16[0], 0), 1196115759Speter ooa.addr16[1], oa->addr16[1], 0); 1197115759Speter break; 1198115759Speter#endif /* INET */ 1199115759Speter#ifdef INET6 1200115759Speter case AF_INET6: 1201115759Speter *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup( 1202115759Speter pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup( 1203115759Speter pf_cksum_fixup(pf_cksum_fixup(*ic, 1204115759Speter ooa.addr16[0], oa->addr16[0], u), 1205115759Speter ooa.addr16[1], oa->addr16[1], u), 1206115759Speter ooa.addr16[2], oa->addr16[2], u), 1207115759Speter ooa.addr16[3], oa->addr16[3], u), 1208115759Speter ooa.addr16[4], oa->addr16[4], u), 1209115759Speter ooa.addr16[5], oa->addr16[5], u), 1210115759Speter ooa.addr16[6], oa->addr16[6], u), 1211152331Srwatson ooa.addr16[7], oa->addr16[7], u); 1212152331Srwatson break; 1213115759Speter#endif /* INET6 */ 1214115759Speter } 1215115759Speter} 1216115759Speter 1217115759Spetervoid 1218115759Speterpf_send_tcp(const struct pf_rule *r, sa_family_t af, 1219115759Speter const struct pf_addr *saddr, const struct pf_addr *daddr, 1220115759Speter u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, 1221115759Speter u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl) 1222115759Speter{ 1223115759Speter struct mbuf *m; 1224115759Speter struct m_tag *mtag; 1225115759Speter int len, tlen; 1226115759Speter#ifdef INET 1227115759Speter struct ip *h; 1228115759Speter#endif /* INET */ 1229100824Sdwmalone#ifdef INET6 12301590Srgrimes struct ip6_hdr *h6; 12311590Srgrimes#endif /* INET6 */ 12321590Srgrimes struct tcphdr *th; 12331590Srgrimes#ifdef __FreeBSD__ 12341590Srgrimes struct ip *ip; 12351590Srgrimes#if (__FreeBSD_version < 501114) 12361590Srgrimes struct route ro; 12371590Srgrimes#endif 1238100824Sdwmalone#endif 1239219138Sdchagin char *opt; 12401590Srgrimes 1241219138Sdchagin /* maximum segment size tcp option */ 1242226153Sdes tlen = sizeof(struct tcphdr); 1243160294Skib if (mss) 1244226153Sdes tlen += 4; 1245240820Sjilles 1246240820Sjilles switch (af) { 1247240820Sjilles#ifdef INET 1248240820Sjilles case AF_INET: 1249240820Sjilles len = sizeof(struct ip) + tlen; 1250240820Sjilles break; 1251240820Sjilles#endif /* INET */ 1252240820Sjilles#ifdef INET6 1253240820Sjilles case AF_INET6: 1254100824Sdwmalone len = sizeof(struct ip6_hdr) + tlen; 12551590Srgrimes break; 12561590Srgrimes#endif /* INET6 */ 1257100824Sdwmalone } 1258234494Sjhb 12591590Srgrimes /* create outgoing mbuf */ 1260226153Sdes mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT); 12611590Srgrimes if (mtag == NULL) 12621590Srgrimes return; 12631590Srgrimes m = m_gethdr(M_DONTWAIT, MT_HEADER); 1264234494Sjhb if (m == NULL) { 1265234494Sjhb m_tag_free(mtag); 1266234494Sjhb return; 1267234494Sjhb } 1268234494Sjhb m_tag_prepend(m, mtag); 1269234494Sjhb#ifdef ALTQ 1270234494Sjhb if (r != NULL && r->qid) { 1271165916Sjhb struct altq_tag *atag; 1272165916Sjhb 1273165916Sjhb mtag = m_tag_get(PACKET_TAG_PF_QID, sizeof(*atag), M_NOWAIT); 1274165916Sjhb if (mtag != NULL) { 1275165916Sjhb atag = (struct altq_tag *)(mtag + 1); 1276165916Sjhb atag->qid = r->qid; 1277165916Sjhb /* add hints for ecn */ 1278165916Sjhb atag->af = af; 1279165916Sjhb atag->hdr = mtod(m, struct ip *); 1280165916Sjhb m_tag_prepend(m, mtag); 1281165916Sjhb } 1282165916Sjhb } 1283165916Sjhb#endif 1284165916Sjhb m->m_data += max_linkhdr; 1285165916Sjhb m->m_pkthdr.len = m->m_len = len; 1286165916Sjhb m->m_pkthdr.rcvif = NULL; 1287165916Sjhb bzero(m->m_data, len); 1288165916Sjhb switch (af) { 1289165916Sjhb#ifdef INET 1290165916Sjhb case AF_INET: 1291165916Sjhb h = mtod(m, struct ip *); 1292165916Sjhb 1293165916Sjhb /* IP header fields included in the TCP checksum */ 1294165916Sjhb h->ip_p = IPPROTO_TCP; 1295165916Sjhb h->ip_len = htons(tlen); 1296165916Sjhb h->ip_src.s_addr = saddr->v4.s_addr; 1297165916Sjhb h->ip_dst.s_addr = daddr->v4.s_addr; 1298165916Sjhb 1299165916Sjhb th = (struct tcphdr *)((caddr_t)h + sizeof(struct ip)); 1300165916Sjhb break; 1301165916Sjhb#endif /* INET */ 1302165916Sjhb#ifdef INET6 1303165916Sjhb case AF_INET6: 1304165916Sjhb h6 = mtod(m, struct ip6_hdr *); 1305165916Sjhb 1306165916Sjhb /* IP header fields included in the TCP checksum */ 1307165916Sjhb h6->ip6_nxt = IPPROTO_TCP; 1308165916Sjhb h6->ip6_plen = htons(tlen); 1309165916Sjhb memcpy(&h6->ip6_src, &saddr->v6, sizeof(struct in6_addr)); 1310165916Sjhb memcpy(&h6->ip6_dst, &daddr->v6, sizeof(struct in6_addr)); 1311165916Sjhb 1312165916Sjhb th = (struct tcphdr *)((caddr_t)h6 + sizeof(struct ip6_hdr)); 1313165916Sjhb break; 1314165916Sjhb#endif /* INET6 */ 1315165916Sjhb } 1316165916Sjhb 1317165916Sjhb /* TCP header */ 1318165916Sjhb th->th_sport = sport; 1319165916Sjhb th->th_dport = dport; 1320165916Sjhb th->th_seq = htonl(seq); 1321165916Sjhb th->th_ack = htonl(ack); 1322165916Sjhb th->th_off = tlen >> 2; 1323165916Sjhb th->th_flags = flags; 1324165916Sjhb th->th_win = htons(win); 1325165916Sjhb 1326165916Sjhb if (mss) { 1327165916Sjhb opt = (char *)(th + 1); 1328165916Sjhb opt[0] = TCPOPT_MAXSEG; 1329165916Sjhb opt[1] = 4; 1330165916Sjhb HTONS(mss); 1331165916Sjhb bcopy((caddr_t)&mss, (caddr_t)(opt + 2), 2); 1332165916Sjhb } 1333165916Sjhb 1334165916Sjhb switch (af) { 1335165916Sjhb#ifdef INET 1336165916Sjhb case AF_INET: 1337165916Sjhb /* TCP checksum */ 1338165916Sjhb th->th_sum = in_cksum(m, len); 1339165916Sjhb 1340165916Sjhb /* Finish the IP header */ 1341165916Sjhb h->ip_v = 4; 1342165916Sjhb h->ip_hl = sizeof(*h) >> 2; 1343165916Sjhb h->ip_tos = IPTOS_LOWDELAY; 1344165916Sjhb#ifdef __FreeBSD__ 1345165916Sjhb h->ip_off = htons(path_mtu_discovery ? IP_DF : 0); 1346165916Sjhb#else 1347165916Sjhb h->ip_off = htons(ip_mtudisc ? IP_DF : 0); 1348165916Sjhb#endif 1349165916Sjhb h->ip_len = htons(len); 1350165916Sjhb h->ip_ttl = ttl ? ttl : ip_defttl; 1351165916Sjhb h->ip_sum = 0; 1352165916Sjhb#ifdef __FreeBSD__ 1353165916Sjhb ip = mtod(m, struct ip *); 1354165916Sjhb /* 1355165916Sjhb * XXX 1356165916Sjhb * OpenBSD changed ip_len/ip_off byte ordering! 1357165916Sjhb * Because FreeBSD assumes host byte ordering we need to 1358165916Sjhb * change here. 1359165916Sjhb */ 1360165916Sjhb NTOHS(ip->ip_len); 1361165916Sjhb NTOHS(ip->ip_off); 1362165916Sjhb#if (__FreeBSD_version < 501114) 1363165916Sjhb bzero(&ro, sizeof(ro)); 1364165916Sjhb ip_rtaddr(ip->ip_dst, &ro); 1365165916Sjhb PF_UNLOCK(); 1366165916Sjhb ip_output(m, (void *)NULL, &ro, 0, (void *)NULL, 1367165916Sjhb (void *)NULL); 1368165916Sjhb PF_LOCK(); 1369165916Sjhb if(ro.ro_rt) { 1370165916Sjhb RTFREE(ro.ro_rt); 1371165916Sjhb } 1372165812Sjhb#else /* __FreeBSD_version >= 501114 */ 1373165812Sjhb PF_UNLOCK(); 1374165812Sjhb ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL, 1375165812Sjhb (void *)NULL); 1376165812Sjhb PF_LOCK(); 1377165812Sjhb#endif 1378100824Sdwmalone#else /* ! __FreeBSD__ */ 1379226329Sdes ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL, 1380165812Sjhb (void *)NULL); 1381165812Sjhb#endif 1382165812Sjhb break; 1383199265Scperciva#endif /* INET */ 1384199265Scperciva#ifdef INET6 1385199265Scperciva case AF_INET6: 1386199265Scperciva /* TCP checksum */ 1387199265Scperciva th->th_sum = in6_cksum(m, IPPROTO_TCP, 1388199265Scperciva sizeof(struct ip6_hdr), tlen); 1389199265Scperciva 1390199265Scperciva h6->ip6_vfc |= IPV6_VERSION; 1391165812Sjhb h6->ip6_hlim = IPV6_DEFHLIM; 1392165812Sjhb 1393165812Sjhb#ifdef __FreeBSD__ 1394100824Sdwmalone PF_UNLOCK(); 139518400Sphk ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); 1396165812Sjhb PF_LOCK(); 1397165916Sjhb#else 1398165916Sjhb ip6_output(m, NULL, NULL, 0, NULL, NULL); 1399165916Sjhb#endif 1400165916Sjhb break; 1401165916Sjhb#endif /* INET6 */ 1402165812Sjhb } 1403226329Sdes} 1404165812Sjhb 1405165812Sjhbvoid 1406165812Sjhbpf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af, 1407226153Sdes struct pf_rule *r) 140818470Sphk{ 1409127402Sphk struct m_tag *mtag; 1410226153Sdes struct mbuf *m0; 1411127402Sphk#ifdef __FreeBSD__ 1412226153Sdes struct ip *ip; 1413226153Sdes#endif 141418400Sphk 141518400Sphk mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT); 1416100824Sdwmalone if (mtag == NULL) 1417176471Sdes return; 1418176471Sdes#ifdef __FreeBSD__ 1419176471Sdes m0 = m_copypacket(m, M_DONTWAIT); 1420176471Sdes#else 1421176471Sdes m0 = m_copy(m, 0, M_COPYALL); 1422176471Sdes#endif 1423176471Sdes if (m0 == NULL) { 1424176471Sdes m_tag_free(mtag); 1425176471Sdes return; 1426176471Sdes } 1427176471Sdes m_tag_prepend(m0, mtag); 1428176471Sdes 1429176471Sdes#ifdef ALTQ 1430176471Sdes if (r->qid) { 1431176471Sdes struct altq_tag *atag; 1432176471Sdes 1433176471Sdes mtag = m_tag_get(PACKET_TAG_PF_QID, sizeof(*atag), M_NOWAIT); 1434176471Sdes if (mtag != NULL) { 1435176471Sdes atag = (struct altq_tag *)(mtag + 1); 1436176471Sdes atag->qid = r->qid; 1437176471Sdes /* add hints for ecn */ 1438226329Sdes atag->af = af; 1439176471Sdes atag->hdr = mtod(m0, struct ip *); 1440176471Sdes m_tag_prepend(m0, mtag); 1441176471Sdes } 1442176471Sdes } 1443176471Sdes#endif 1444176471Sdes 1445226329Sdes switch (af) { 1446176471Sdes#ifdef INET 1447226329Sdes case AF_INET: 1448226329Sdes#ifdef __FreeBSD__ 1449176471Sdes /* icmp_error() expects host byte ordering */ 1450226329Sdes ip = mtod(m0, struct ip *); 1451226329Sdes NTOHS(ip->ip_len); 1452176471Sdes NTOHS(ip->ip_off); 1453176471Sdes PF_UNLOCK(); 1454176471Sdes#endif 1455176471Sdes icmp_error(m0, type, code, 0, NULL); 1456226329Sdes#ifdef __FreeBSD__ 1457176471Sdes PF_LOCK(); 1458176471Sdes#endif 1459226329Sdes break; 1460226329Sdes#endif /* INET */ 1461176471Sdes#ifdef INET6 1462226329Sdes case AF_INET6: 1463226329Sdes#ifdef __FreeBSD__ 1464226329Sdes PF_UNLOCK(); 1465176471Sdes#endif 1466176471Sdes icmp6_error(m0, type, code, 0); 1467176471Sdes#ifdef __FreeBSD__ 1468176471Sdes PF_LOCK(); 1469176471Sdes#endif 1470226329Sdes break; 1471176471Sdes#endif /* INET6 */ 1472226329Sdes } 1473226329Sdes} 1474176471Sdes 1475226329Sdes/* 1476226329Sdes * Return 1 if the addresses a and b match (with mask m), otherwise return 0. 1477176471Sdes * If n is 0, they match if they are equal. If n is != 0, they match if they 1478176471Sdes * are different. 1479176471Sdes */ 1480176471Sdesint 1481226329Sdespf_match_addr(u_int8_t n, struct pf_addr *a, struct pf_addr *m, 1482176471Sdes struct pf_addr *b, sa_family_t af) 1483226329Sdes{ 1484226329Sdes int match = 0; 1485176471Sdes 1486176471Sdes switch (af) { 1487226329Sdes#ifdef INET 1488226329Sdes case AF_INET: 1489176471Sdes if ((a->addr32[0] & m->addr32[0]) == 1490176471Sdes (b->addr32[0] & m->addr32[0])) 1491176471Sdes match++; 1492176471Sdes break; 1493226329Sdes#endif /* INET */ 1494176471Sdes#ifdef INET6 1495226329Sdes case AF_INET6: 1496226329Sdes if (((a->addr32[0] & m->addr32[0]) == 1497176471Sdes (b->addr32[0] & m->addr32[0])) && 1498226329Sdes ((a->addr32[1] & m->addr32[1]) == 1499176471Sdes (b->addr32[1] & m->addr32[1])) && 1500176471Sdes ((a->addr32[2] & m->addr32[2]) == 1501176471Sdes (b->addr32[2] & m->addr32[2])) && 1502176471Sdes ((a->addr32[3] & m->addr32[3]) == 1503176471Sdes (b->addr32[3] & m->addr32[3]))) 1504176471Sdes match++; 1505176471Sdes break; 1506176471Sdes#endif /* INET6 */ 1507176471Sdes } 1508176471Sdes if (match) { 1509176471Sdes if (n) 1510176471Sdes return (0); 1511176471Sdes else 1512176471Sdes return (1); 1513176471Sdes } else { 1514176471Sdes if (n) 1515176471Sdes return (1); 1516176471Sdes else 1517176471Sdes return (0); 1518176471Sdes } 1519176471Sdes} 1520176471Sdes 1521176471Sdesint 1522176471Sdespf_match(u_int8_t op, u_int32_t a1, u_int32_t a2, u_int32_t p) 1523176471Sdes{ 1524176471Sdes switch (op) { 1525176471Sdes case PF_OP_IRG: 1526176471Sdes return ((p > a1) && (p < a2)); 1527176471Sdes case PF_OP_XRG: 1528176471Sdes return ((p < a1) || (p > a2)); 1529176471Sdes case PF_OP_RRG: 1530176471Sdes return ((p >= a1) && (p <= a2)); 1531176471Sdes case PF_OP_EQ: 1532176471Sdes return (p == a1); 1533176471Sdes case PF_OP_NE: 1534176471Sdes return (p != a1); 1535205793Sed case PF_OP_LT: 1536176471Sdes return (p < a1); 1537205793Sed case PF_OP_LE: 1538226153Sdes return (p <= a1); 1539176471Sdes case PF_OP_GT: 1540176471Sdes return (p > a1); 1541205793Sed case PF_OP_GE: 1542205793Sed return (p >= a1); 1543176471Sdes } 1544176471Sdes return (0); /* never reached */ 1545176471Sdes} 1546176471Sdes 1547205793Sedint 1548176471Sdespf_match_port(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t p) 1549205793Sed{ 1550226153Sdes NTOHS(a1); 1551176471Sdes NTOHS(a2); 1552176471Sdes NTOHS(p); 1553205793Sed return (pf_match(op, a1, a2, p)); 1554205793Sed} 1555176471Sdes 1556176471Sdesint 1557176471Sdespf_match_uid(u_int8_t op, uid_t a1, uid_t a2, uid_t u) 1558176471Sdes{ 1559205793Sed if (u == UID_MAX && op != PF_OP_EQ && op != PF_OP_NE) 1560176471Sdes return (0); 1561205793Sed return (pf_match(op, a1, a2, u)); 1562226153Sdes} 1563176471Sdes 1564176471Sdesint 1565205793Sedpf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g) 1566205793Sed{ 1567176471Sdes if (g == GID_MAX && op != PF_OP_EQ && op != PF_OP_NE) 1568176471Sdes return (0); 1569176471Sdes return (pf_match(op, a1, a2, g)); 1570176471Sdes} 1571205793Sed 1572176471Sdesstruct pf_tag * 1573205793Sedpf_get_tag(struct mbuf *m) 1574226153Sdes{ 1575176471Sdes struct m_tag *mtag; 1576176471Sdes 1577205793Sed if ((mtag = m_tag_find(m, PACKET_TAG_PF_TAG, NULL)) != NULL) 1578205793Sed return ((struct pf_tag *)(mtag + 1)); 1579176471Sdes else 1580176471Sdes return (NULL); 1581176471Sdes} 1582176471Sdes 1583176471Sdesint 1584176471Sdespf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_rule *nat, 1585176471Sdes struct pf_rule *rdr, struct pf_tag *pftag, int *tag) 1586176471Sdes{ 1587176471Sdes if (*tag == -1) { /* find mbuf tag */ 1588176471Sdes pftag = pf_get_tag(m); 1589176471Sdes if (pftag != NULL) 1590176471Sdes *tag = pftag->tag; 1591176471Sdes else 1592176471Sdes *tag = 0; 1593204045Simp if (nat != NULL && nat->tag) 1594204045Simp *tag = nat->tag; 1595176471Sdes if (rdr != NULL && rdr->tag) 1596176471Sdes *tag = rdr->tag; 1597176471Sdes } 1598176471Sdes 1599176471Sdes return ((!r->match_tag_not && r->match_tag == *tag) || 1600176471Sdes (r->match_tag_not && r->match_tag != *tag)); 1601176471Sdes} 1602176471Sdes 1603176471Sdesint 1604176471Sdespf_tag_packet(struct mbuf *m, struct pf_tag *pftag, int tag) 1605176471Sdes{ 1606176471Sdes struct m_tag *mtag; 1607176471Sdes 1608176471Sdes if (tag <= 0) 1609226329Sdes return (0); 1610226329Sdes 1611176471Sdes if (pftag == NULL) { 1612176471Sdes mtag = m_tag_get(PACKET_TAG_PF_TAG, sizeof(*pftag), M_NOWAIT); 1613176471Sdes if (mtag == NULL) 1614176471Sdes return (1); 1615204045Simp ((struct pf_tag *)(mtag + 1))->tag = tag; 1616204045Simp m_tag_prepend(m, mtag); 1617176471Sdes } else 1618204045Simp pftag->tag = tag; 1619204045Simp 1620204045Simp return (0); 1621176471Sdes} 1622204045Simp 1623176471Sdes#define PF_STEP_INTO_ANCHOR(r, a, s, n) \ 1624204045Simp do { \ 1625176471Sdes if ((r) == NULL || (r)->anchor == NULL || \ 1626176471Sdes (s) != NULL || (a) != NULL) \ 1627176471Sdes panic("PF_STEP_INTO_ANCHOR"); \ 1628176471Sdes (a) = (r); \ 1629176471Sdes (s) = TAILQ_FIRST(&(r)->anchor->rulesets); \ 1630176471Sdes (r) = NULL; \ 1631176471Sdes while ((s) != NULL && ((r) = \ 1632176471Sdes TAILQ_FIRST((s)->rules[n].active.ptr)) == NULL) \ 1633226269Sdes (s) = TAILQ_NEXT((s), entries); \ 1634226269Sdes if ((r) == NULL) { \ 1635226269Sdes (r) = TAILQ_NEXT((a), entries); \ 1636226495Sdes (a) = NULL; \ 1637226495Sdes } \ 1638226495Sdes } while (0) 1639226495Sdes 1640226495Sdes#define PF_STEP_OUT_OF_ANCHOR(r, a, s, n) \ 1641226495Sdes do { \ 1642226495Sdes if ((r) != NULL || (a) == NULL || (s) == NULL) \ 1643226495Sdes panic("PF_STEP_OUT_OF_ANCHOR"); \ 1644226495Sdes (s) = TAILQ_NEXT((s), entries); \ 1645226495Sdes while ((s) != NULL && ((r) = \ 1646226495Sdes TAILQ_FIRST((s)->rules[n].active.ptr)) == NULL) \ 1647226505Sdes (s) = TAILQ_NEXT((s), entries); \ 1648226505Sdes if ((r) == NULL) { \ 1649226495Sdes (r) = TAILQ_NEXT((a), entries); \ 1650226495Sdes (a) = NULL; \ 1651226495Sdes } \ 1652226495Sdes } while (0) 1653226495Sdes 1654226495Sdes#ifdef INET6 1655226495Sdesvoid 1656226495Sdespf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr, 1657226495Sdes struct pf_addr *rmask, struct pf_addr *saddr, sa_family_t af) 1658226495Sdes{ 1659226495Sdes switch (af) { 1660226495Sdes#ifdef INET 1661226495Sdes case AF_INET: 1662226495Sdes naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) | 1663226495Sdes ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]); 1664226495Sdes break; 1665226495Sdes#endif /* INET */ 1666233925Sjhb case AF_INET6: 1667226269Sdes naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) | 1668226269Sdes ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]); 1669233925Sjhb naddr->addr32[1] = (raddr->addr32[1] & rmask->addr32[1]) | 1670233925Sjhb ((rmask->addr32[1] ^ 0xffffffff ) & saddr->addr32[1]); 1671233925Sjhb naddr->addr32[2] = (raddr->addr32[2] & rmask->addr32[2]) | 1672233925Sjhb ((rmask->addr32[2] ^ 0xffffffff ) & saddr->addr32[2]); 1673233925Sjhb naddr->addr32[3] = (raddr->addr32[3] & rmask->addr32[3]) | 1674233925Sjhb ((rmask->addr32[3] ^ 0xffffffff ) & saddr->addr32[3]); 1675233925Sjhb break; 1676233925Sjhb } 1677233925Sjhb} 1678233925Sjhb 1679233925Sjhbvoid 1680233925Sjhbpf_addr_inc(struct pf_addr *addr, u_int8_t af) 1681233925Sjhb{ 1682233925Sjhb switch (af) { 1683233925Sjhb#ifdef INET 1684233925Sjhb case AF_INET: 1685233925Sjhb addr->addr32[0] = htonl(ntohl(addr->addr32[0]) + 1); 1686219138Sdchagin break; 1687176471Sdes#endif /* INET */ 1688219138Sdchagin case AF_INET6: 1689219138Sdchagin if (addr->addr32[3] == 0xffffffff) { 1690219138Sdchagin addr->addr32[3] = 0; 1691219138Sdchagin if (addr->addr32[2] == 0xffffffff) { 1692219138Sdchagin addr->addr32[2] = 0; 1693219138Sdchagin if (addr->addr32[1] == 0xffffffff) { 1694219138Sdchagin addr->addr32[1] = 0; 1695219138Sdchagin addr->addr32[0] = 1696219138Sdchagin htonl(ntohl(addr->addr32[0]) + 1); 1697219138Sdchagin } else 1698219138Sdchagin addr->addr32[1] = 1699219138Sdchagin htonl(ntohl(addr->addr32[1]) + 1); 1700219138Sdchagin } else 1701219138Sdchagin addr->addr32[2] = 1702219138Sdchagin htonl(ntohl(addr->addr32[2]) + 1); 1703219138Sdchagin } else 1704219138Sdchagin addr->addr32[3] = 1705219138Sdchagin htonl(ntohl(addr->addr32[3]) + 1); 1706219138Sdchagin break; 1707219138Sdchagin } 1708219138Sdchagin} 1709219138Sdchagin#endif /* INET6 */ 1710219138Sdchagin 1711219138Sdchagin#define mix(a,b,c) \ 1712219138Sdchagin do { \ 1713219138Sdchagin a -= b; a -= c; a ^= (c >> 13); \ 1714219138Sdchagin b -= c; b -= a; b ^= (a << 8); \ 1715219138Sdchagin c -= a; c -= b; c ^= (b >> 13); \ 1716219138Sdchagin a -= b; a -= c; a ^= (c >> 12); \ 1717219138Sdchagin b -= c; b -= a; b ^= (a << 16); \ 1718219138Sdchagin c -= a; c -= b; c ^= (b >> 5); \ 1719219138Sdchagin a -= b; a -= c; a ^= (c >> 3); \ 1720219138Sdchagin b -= c; b -= a; b ^= (a << 10); \ 1721219138Sdchagin c -= a; c -= b; c ^= (b >> 15); \ 1722219138Sdchagin } while (0) 1723226153Sdes 1724219138Sdchagin/* 1725219138Sdchagin * hash function based on bridge_hash in if_bridge.c 1726219138Sdchagin */ 1727219138Sdchaginvoid 1728226153Sdespf_hash(struct pf_addr *inaddr, struct pf_addr *hash, 1729219138Sdchagin struct pf_poolhashkey *key, sa_family_t af) 1730219138Sdchagin{ 1731219138Sdchagin u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0]; 1732219138Sdchagin 1733219138Sdchagin switch (af) { 1734219138Sdchagin#ifdef INET 1735219138Sdchagin case AF_INET: 1736219138Sdchagin a += inaddr->addr32[0]; 1737219138Sdchagin b += key->key32[1]; 1738219138Sdchagin mix(a, b, c); 1739219138Sdchagin hash->addr32[0] = c + key->key32[2]; 1740219138Sdchagin break; 1741219138Sdchagin#endif /* INET */ 1742219138Sdchagin#ifdef INET6 1743219138Sdchagin case AF_INET6: 1744219138Sdchagin a += inaddr->addr32[0]; 1745219138Sdchagin b += inaddr->addr32[2]; 1746219138Sdchagin mix(a, b, c); 1747219138Sdchagin hash->addr32[0] = c; 1748100824Sdwmalone a += inaddr->addr32[1]; 17491590Srgrimes b += inaddr->addr32[3]; 1750219043Sdchagin c += key->key32[1]; 1751177856Sru mix(a, b, c); 17521590Srgrimes hash->addr32[1] = c; 17531590Srgrimes a += inaddr->addr32[2]; 1754 b += inaddr->addr32[1]; 1755 c += key->key32[2]; 1756 mix(a, b, c); 1757 hash->addr32[2] = c; 1758 a += inaddr->addr32[3]; 1759 b += inaddr->addr32[0]; 1760 c += key->key32[3]; 1761 mix(a, b, c); 1762 hash->addr32[3] = c; 1763 break; 1764#endif /* INET6 */ 1765 } 1766} 1767 1768int 1769pf_map_addr(u_int8_t af, struct pf_pool *rpool, struct pf_addr *saddr, 1770 struct pf_addr *naddr, struct pf_addr *init_addr) 1771{ 1772 unsigned char hash[16]; 1773 struct pf_addr *raddr; 1774 struct pf_addr *rmask; 1775 struct pf_pooladdr *acur = rpool->cur; 1776 1777 if (rpool->cur->addr.type == PF_ADDR_NOROUTE) 1778 return (1); 1779 if (rpool->cur->addr.type == PF_ADDR_DYNIFTL && 1780 rpool->cur->addr.p.dyn->undefined) 1781 return (1); 1782 if (rpool->cur->addr.type == PF_ADDR_TABLE) { 1783 if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) 1784 return (1); /* unsupported */ 1785 } else { 1786 raddr = &rpool->cur->addr.v.a.addr; 1787 rmask = &rpool->cur->addr.v.a.mask; 1788 } 1789 1790 switch (rpool->opts & PF_POOL_TYPEMASK) { 1791 case PF_POOL_NONE: 1792 PF_ACPY(naddr, raddr, af); 1793 break; 1794 case PF_POOL_BITMASK: 1795 PF_POOLMASK(naddr, raddr, rmask, saddr, af); 1796 break; 1797 case PF_POOL_RANDOM: 1798 if (init_addr != NULL && PF_AZERO(init_addr, af)) { 1799 switch (af) { 1800#ifdef INET 1801 case AF_INET: 1802 rpool->counter.addr32[0] = arc4random(); 1803 break; 1804#endif /* INET */ 1805#ifdef INET6 1806 case AF_INET6: 1807 if (rmask->addr32[3] != 0xffffffff) 1808 rpool->counter.addr32[3] = arc4random(); 1809 else 1810 break; 1811 if (rmask->addr32[2] != 0xffffffff) 1812 rpool->counter.addr32[2] = arc4random(); 1813 else 1814 break; 1815 if (rmask->addr32[1] != 0xffffffff) 1816 rpool->counter.addr32[1] = arc4random(); 1817 else 1818 break; 1819 if (rmask->addr32[0] != 0xffffffff) 1820 rpool->counter.addr32[0] = arc4random(); 1821 break; 1822#endif /* INET6 */ 1823 } 1824 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af); 1825 PF_ACPY(init_addr, naddr, af); 1826 1827 } else { 1828 PF_AINC(&rpool->counter, af); 1829 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af); 1830 } 1831 break; 1832 case PF_POOL_SRCHASH: 1833 pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af); 1834 PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af); 1835 break; 1836 case PF_POOL_ROUNDROBIN: 1837 if (rpool->cur->addr.type == PF_ADDR_TABLE) { 1838 if (!pfr_pool_get(rpool->cur->addr.p.tbl, 1839 &rpool->tblidx, &rpool->counter, 1840 &raddr, &rmask, af)) 1841 goto get_addr; 1842 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) 1843 goto get_addr; 1844 1845 try_next: 1846 if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL) 1847 rpool->cur = TAILQ_FIRST(&rpool->list); 1848 if (rpool->cur->addr.type == PF_ADDR_TABLE) { 1849 rpool->tblidx = -1; 1850 if (pfr_pool_get(rpool->cur->addr.p.tbl, 1851 &rpool->tblidx, &rpool->counter, 1852 &raddr, &rmask, af)) { 1853 /* table contain no address of type 'af' */ 1854 if (rpool->cur != acur) 1855 goto try_next; 1856 return (1); 1857 } 1858 } else { 1859 raddr = &rpool->cur->addr.v.a.addr; 1860 rmask = &rpool->cur->addr.v.a.mask; 1861 PF_ACPY(&rpool->counter, raddr, af); 1862 } 1863 1864 get_addr: 1865 PF_ACPY(naddr, &rpool->counter, af); 1866 PF_AINC(&rpool->counter, af); 1867 break; 1868 } 1869 1870 if (pf_status.debug >= PF_DEBUG_MISC && 1871 (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { 1872 printf("pf_map_addr: selected address: "); 1873 pf_print_host(naddr, 0, af); 1874 printf("\n"); 1875 } 1876 1877 return (0); 1878} 1879 1880int 1881pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_pool *rpool, 1882 struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport, 1883 struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high) 1884{ 1885 struct pf_tree_node key; 1886 struct pf_addr init_addr; 1887 u_int16_t cut; 1888 1889 bzero(&init_addr, sizeof(init_addr)); 1890 if (pf_map_addr(af, rpool, saddr, naddr, &init_addr)) 1891 return (1); 1892 1893 do { 1894 key.af = af; 1895 key.proto = proto; 1896 PF_ACPY(&key.addr[0], daddr, key.af); 1897 PF_ACPY(&key.addr[1], naddr, key.af); 1898 key.port[0] = dport; 1899 1900 /* 1901 * port search; start random, step; 1902 * similar 2 portloop in in_pcbbind 1903 */ 1904 if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP)) { 1905 key.port[1] = 0; 1906 if (pf_find_state(&tree_ext_gwy, &key) == NULL) 1907 return (0); 1908 } else if (low == 0 && high == 0) { 1909 key.port[1] = *nport; 1910 if (pf_find_state(&tree_ext_gwy, &key) == NULL) { 1911 return (0); 1912 } 1913 } else if (low == high) { 1914 key.port[1] = htons(low); 1915 if (pf_find_state(&tree_ext_gwy, &key) == NULL) { 1916 *nport = htons(low); 1917 return (0); 1918 } 1919 } else { 1920 u_int16_t tmp; 1921 1922 if (low > high) { 1923 tmp = low; 1924 low = high; 1925 high = tmp; 1926 } 1927 /* low < high */ 1928 cut = arc4random() % (1 + high - low) + low; 1929 /* low <= cut <= high */ 1930 for (tmp = cut; tmp <= high; ++(tmp)) { 1931 key.port[1] = htons(tmp); 1932 if (pf_find_state(&tree_ext_gwy, &key) == 1933 NULL) { 1934 *nport = htons(tmp); 1935 return (0); 1936 } 1937 } 1938 for (tmp = cut - 1; tmp >= low; --(tmp)) { 1939 key.port[1] = htons(tmp); 1940 if (pf_find_state(&tree_ext_gwy, &key) == 1941 NULL) { 1942 *nport = htons(tmp); 1943 return (0); 1944 } 1945 } 1946 } 1947 1948 switch (rpool->opts & PF_POOL_TYPEMASK) { 1949 case PF_POOL_RANDOM: 1950 case PF_POOL_ROUNDROBIN: 1951 if (pf_map_addr(af, rpool, saddr, naddr, &init_addr)) 1952 return (1); 1953 break; 1954 case PF_POOL_NONE: 1955 case PF_POOL_SRCHASH: 1956 case PF_POOL_BITMASK: 1957 default: 1958 return (1); 1959 break; 1960 } 1961 } while (! PF_AEQ(&init_addr, naddr, af) ); 1962 1963 return (1); /* none available */ 1964} 1965 1966struct pf_rule * 1967pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off, 1968 int direction, struct ifnet *ifp, struct pf_addr *saddr, u_int16_t sport, 1969 struct pf_addr *daddr, u_int16_t dport, int rs_num) 1970{ 1971 struct pf_rule *r, *rm = NULL, *anchorrule = NULL; 1972 struct pf_ruleset *ruleset = NULL; 1973 1974 r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr); 1975 while (r && rm == NULL) { 1976 struct pf_rule_addr *src = NULL, *dst = NULL; 1977 struct pf_addr_wrap *xdst = NULL; 1978 1979 if (r->action == PF_BINAT && direction == PF_IN) { 1980 src = &r->dst; 1981 if (r->rpool.cur != NULL) 1982 xdst = &r->rpool.cur->addr; 1983 } else { 1984 src = &r->src; 1985 dst = &r->dst; 1986 } 1987 1988 r->evaluations++; 1989 if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) || 1990 (r->ifp == ifp && r->ifnot))) 1991 r = r->skip[PF_SKIP_IFP].ptr; 1992 else if (r->direction && r->direction != direction) 1993 r = r->skip[PF_SKIP_DIR].ptr; 1994 else if (r->af && r->af != pd->af) 1995 r = r->skip[PF_SKIP_AF].ptr; 1996 else if (r->proto && r->proto != pd->proto) 1997 r = r->skip[PF_SKIP_PROTO].ptr; 1998 else if (PF_MISMATCHAW(&src->addr, saddr, pd->af, src->not)) 1999 r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR : 2000 PF_SKIP_DST_ADDR].ptr; 2001 else if (src->port_op && !pf_match_port(src->port_op, 2002 src->port[0], src->port[1], sport)) 2003 r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT : 2004 PF_SKIP_DST_PORT].ptr; 2005 else if (dst != NULL && 2006 PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->not)) 2007 r = r->skip[PF_SKIP_DST_ADDR].ptr; 2008 else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af, 0)) 2009 r = TAILQ_NEXT(r, entries); 2010 else if (dst != NULL && dst->port_op && 2011 !pf_match_port(dst->port_op, dst->port[0], 2012 dst->port[1], dport)) 2013 r = r->skip[PF_SKIP_DST_PORT].ptr; 2014 else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto != 2015 IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m, 2016 off, pd->hdr.tcp), r->os_fingerprint))) 2017 r = TAILQ_NEXT(r, entries); 2018 else if (r->anchorname[0] && r->anchor == NULL) 2019 r = TAILQ_NEXT(r, entries); 2020 else if (r->anchor == NULL) 2021 rm = r; 2022 else 2023 PF_STEP_INTO_ANCHOR(r, anchorrule, ruleset, rs_num); 2024 if (r == NULL && anchorrule != NULL) 2025 PF_STEP_OUT_OF_ANCHOR(r, anchorrule, ruleset, 2026 rs_num); 2027 } 2028 if (rm != NULL && (rm->action == PF_NONAT || 2029 rm->action == PF_NORDR || rm->action == PF_NOBINAT)) 2030 return (NULL); 2031 return (rm); 2032} 2033 2034struct pf_rule * 2035pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, 2036 struct ifnet *ifp, 2037 struct pf_addr *saddr, u_int16_t sport, 2038 struct pf_addr *daddr, u_int16_t dport, 2039 struct pf_addr *naddr, u_int16_t *nport) 2040{ 2041 struct pf_rule *r = NULL; 2042 2043 if (direction == PF_OUT) { 2044 r = pf_match_translation(pd, m, off, direction, ifp, saddr, 2045 sport, daddr, dport, PF_RULESET_BINAT); 2046 if (r == NULL) 2047 r = pf_match_translation(pd, m, off, direction, ifp, 2048 saddr, sport, daddr, dport, PF_RULESET_NAT); 2049 } else { 2050 r = pf_match_translation(pd, m, off, direction, ifp, saddr, 2051 sport, daddr, dport, PF_RULESET_RDR); 2052 if (r == NULL) 2053 r = pf_match_translation(pd, m, off, direction, ifp, 2054 saddr, sport, daddr, dport, PF_RULESET_BINAT); 2055 } 2056 2057 if (r != NULL) { 2058 switch (r->action) { 2059 case PF_NONAT: 2060 case PF_NOBINAT: 2061 case PF_NORDR: 2062 return (NULL); 2063 break; 2064 case PF_NAT: 2065 if (pf_get_sport(pd->af, pd->proto, &r->rpool, saddr, 2066 daddr, dport, naddr, nport, r->rpool.proxy_port[0], 2067 r->rpool.proxy_port[1])) { 2068 DPFPRINTF(PF_DEBUG_MISC, 2069 ("pf: NAT proxy port allocation " 2070 "(%u-%u) failed\n", 2071 r->rpool.proxy_port[0], 2072 r->rpool.proxy_port[1])); 2073 return (NULL); 2074 } 2075 break; 2076 case PF_BINAT: 2077 switch (direction) { 2078 case PF_OUT: 2079 if (r->rpool.cur->addr.type == 2080 PF_ADDR_DYNIFTL && 2081 r->rpool.cur->addr.p.dyn->undefined) 2082 return (NULL); 2083 else 2084 PF_POOLMASK(naddr, 2085 &r->rpool.cur->addr.v.a.addr, 2086 &r->rpool.cur->addr.v.a.mask, 2087 saddr, pd->af); 2088 break; 2089 case PF_IN: 2090 if (r->src.addr.type == PF_ADDR_DYNIFTL && 2091 r->src.addr.p.dyn->undefined) 2092 return (NULL); 2093 else 2094 PF_POOLMASK(naddr, 2095 &r->src.addr.v.a.addr, 2096 &r->src.addr.v.a.mask, daddr, 2097 pd->af); 2098 break; 2099 } 2100 break; 2101 case PF_RDR: { 2102 if (pf_map_addr(r->af, &r->rpool, saddr, naddr, NULL)) 2103 return (NULL); 2104 2105 if (r->rpool.proxy_port[1]) { 2106 u_int32_t tmp_nport; 2107 2108 tmp_nport = ((ntohs(dport) - 2109 ntohs(r->dst.port[0])) % 2110 (r->rpool.proxy_port[1] - 2111 r->rpool.proxy_port[0] + 1)) + 2112 r->rpool.proxy_port[0]; 2113 2114 /* wrap around if necessary */ 2115 if (tmp_nport > 65535) 2116 tmp_nport -= 65535; 2117 *nport = htons((u_int16_t)tmp_nport); 2118 } else if (r->rpool.proxy_port[0]) 2119 *nport = htons(r->rpool.proxy_port[0]); 2120 break; 2121 } 2122 default: 2123 return (NULL); 2124 break; 2125 } 2126 } 2127 2128 return (r); 2129} 2130 2131int 2132pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, sa_family_t af, 2133 int proto, struct pf_pdesc *pd) 2134{ 2135 struct pf_addr *saddr, *daddr; 2136 u_int16_t sport, dport; 2137#ifdef __FreeBSD__ 2138 struct inpcbinfo *pi; 2139#else 2140 struct inpcbtable *tb; 2141#endif 2142 struct inpcb *inp; 2143 2144 *uid = UID_MAX; 2145 *gid = GID_MAX; 2146 switch (proto) { 2147 case IPPROTO_TCP: 2148 sport = pd->hdr.tcp->th_sport; 2149 dport = pd->hdr.tcp->th_dport; 2150#ifdef __FreeBSD__ 2151 pi = &tcbinfo; 2152#else 2153 tb = &tcbtable; 2154#endif 2155 break; 2156 case IPPROTO_UDP: 2157 sport = pd->hdr.udp->uh_sport; 2158 dport = pd->hdr.udp->uh_dport; 2159#ifdef __FreeBSD__ 2160 pi = &udbinfo; 2161#else 2162 tb = &udbtable; 2163#endif 2164 break; 2165 default: 2166 return (0); 2167 } 2168 if (direction == PF_IN) { 2169 saddr = pd->src; 2170 daddr = pd->dst; 2171 } else { 2172 u_int16_t p; 2173 2174 p = sport; 2175 sport = dport; 2176 dport = p; 2177 saddr = pd->dst; 2178 daddr = pd->src; 2179 } 2180 switch(af) { 2181 case AF_INET: 2182#ifdef __FreeBSD__ 2183#if (__FreeBSD_version >= 500043) 2184 INP_INFO_RLOCK(pi); /* XXX LOR */ 2185#endif 2186 inp = in_pcblookup_hash(pi, saddr->v4, sport, daddr->v4, 2187 dport, 0, NULL); 2188 if (inp == NULL) { 2189 inp = in_pcblookup_hash(pi, saddr->v4, sport, 2190 daddr->v4, dport, INPLOOKUP_WILDCARD, NULL); 2191 if(inp == NULL) { 2192#if (__FreeBSD_version >= 500043) 2193 INP_INFO_RUNLOCK(pi); 2194#endif 2195 return (0); 2196 } 2197 } 2198#else 2199 inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport); 2200 if (inp == NULL) { 2201 inp = in_pcblookup(tb, &saddr->v4, sport, &daddr->v4, 2202 dport, INPLOOKUP_WILDCARD); 2203 if (inp == NULL) 2204 return (0); 2205 } 2206#endif 2207 break; 2208#ifdef INET6 2209 case AF_INET6: 2210#ifdef __FreeBSD__ 2211#if (__FreeBSD_version >= 500043) 2212 INP_INFO_RLOCK(pi); 2213#endif 2214 inp = in6_pcblookup_hash(pi, &saddr->v6, sport, 2215 &daddr->v6, dport, 0, NULL); 2216 if (inp == NULL) { 2217 inp = in6_pcblookup_hash(pi, &saddr->v6, sport, 2218 &daddr->v6, dport, INPLOOKUP_WILDCARD, NULL); 2219 if (inp == NULL) { 2220#if (__FreeBSD_version >= 500043) 2221 INP_INFO_RUNLOCK(pi); 2222#endif 2223 return (0); 2224 } 2225 } 2226#else 2227 inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6, 2228 dport); 2229 if (inp == NULL) { 2230 inp = in_pcblookup(tb, &saddr->v6, sport, &daddr->v6, 2231 dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); 2232 if (inp == NULL) 2233 return (0); 2234 } 2235#endif 2236 break; 2237#endif /* INET6 */ 2238 2239 default: 2240 return (0); 2241 } 2242#ifdef __FreeBSD__ 2243#if (__FreeBSD_version >= 500043) 2244 INP_LOCK(inp); 2245#endif 2246 *uid = inp->inp_socket->so_cred->cr_uid; 2247 *gid = inp->inp_socket->so_cred->cr_groups[0]; 2248#if (__FreeBSD_version >= 500043) 2249 INP_UNLOCK(inp); 2250 INP_INFO_RUNLOCK(pi); 2251#endif 2252#else 2253 *uid = inp->inp_socket->so_euid; 2254 *gid = inp->inp_socket->so_egid; 2255#endif 2256 return (1); 2257} 2258 2259u_int8_t 2260pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af) 2261{ 2262 int hlen; 2263 u_int8_t hdr[60]; 2264 u_int8_t *opt, optlen; 2265 u_int8_t wscale = 0; 2266 2267 hlen = th_off << 2; /* hlen <= sizeof(hdr) */ 2268 if (hlen <= sizeof(struct tcphdr)) 2269 return (0); 2270 if (!pf_pull_hdr(m, off, hdr, hlen, NULL, NULL, af)) 2271 return (0); 2272 opt = hdr + sizeof(struct tcphdr); 2273 hlen -= sizeof(struct tcphdr); 2274 while (hlen >= 3) { 2275 switch (*opt) { 2276 case TCPOPT_EOL: 2277 case TCPOPT_NOP: 2278 ++opt; 2279 --hlen; 2280 break; 2281 case TCPOPT_WINDOW: 2282 wscale = opt[2]; 2283 if (wscale > TCP_MAX_WINSHIFT) 2284 wscale = TCP_MAX_WINSHIFT; 2285 wscale |= PF_WSCALE_FLAG; 2286 /* fallthrough */ 2287 default: 2288 optlen = opt[1]; 2289 if (optlen < 2) 2290 optlen = 2; 2291 hlen -= optlen; 2292 opt += optlen; 2293 } 2294 } 2295 return (wscale); 2296} 2297 2298u_int16_t 2299pf_get_mss(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af) 2300{ 2301 int hlen; 2302 u_int8_t hdr[60]; 2303 u_int8_t *opt, optlen; 2304 u_int16_t mss = tcp_mssdflt; 2305 2306 hlen = th_off << 2; /* hlen <= sizeof(hdr) */ 2307 if (hlen <= sizeof(struct tcphdr)) 2308 return (0); 2309 if (!pf_pull_hdr(m, off, hdr, hlen, NULL, NULL, af)) 2310 return (0); 2311 opt = hdr + sizeof(struct tcphdr); 2312 hlen -= sizeof(struct tcphdr); 2313 while (hlen >= TCPOLEN_MAXSEG) { 2314 switch (*opt) { 2315 case TCPOPT_EOL: 2316 case TCPOPT_NOP: 2317 ++opt; 2318 --hlen; 2319 break; 2320 case TCPOPT_MAXSEG: 2321 bcopy((caddr_t)(opt + 2), (caddr_t)&mss, 2); 2322 /* fallthrough */ 2323 default: 2324 optlen = opt[1]; 2325 if (optlen < 2) 2326 optlen = 2; 2327 hlen -= optlen; 2328 opt += optlen; 2329 } 2330 } 2331 return (mss); 2332} 2333 2334u_int16_t 2335pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer) 2336{ 2337#ifdef INET 2338 struct sockaddr_in *dst; 2339 struct route ro; 2340#endif /* INET */ 2341#ifdef INET6 2342 struct sockaddr_in6 *dst6; 2343 struct route_in6 ro6; 2344#endif /* INET6 */ 2345 struct rtentry *rt = NULL; 2346 int hlen; 2347 u_int16_t mss = tcp_mssdflt; 2348 2349 switch (af) { 2350#ifdef INET 2351 case AF_INET: 2352 hlen = sizeof(struct ip); 2353 bzero(&ro, sizeof(ro)); 2354 dst = (struct sockaddr_in *)&ro.ro_dst; 2355 dst->sin_family = AF_INET; 2356 dst->sin_len = sizeof(*dst); 2357 dst->sin_addr = addr->v4; 2358#ifdef __FreeBSD__ 2359#ifdef RTF_PRCLONING 2360 rtalloc_ign(&ro, (RTF_CLONING | RTF_PRCLONING)); 2361#else /* !RTF_PRCLONING */ 2362 rtalloc_ign(&ro, RTF_CLONING); 2363#endif 2364#else /* ! __FreeBSD__ */ 2365 rtalloc_noclone(&ro, NO_CLONING); 2366#endif 2367 rt = ro.ro_rt; 2368 break; 2369#endif /* INET */ 2370#ifdef INET6 2371 case AF_INET6: 2372 hlen = sizeof(struct ip6_hdr); 2373 bzero(&ro6, sizeof(ro6)); 2374 dst6 = (struct sockaddr_in6 *)&ro6.ro_dst; 2375 dst6->sin6_family = AF_INET6; 2376 dst6->sin6_len = sizeof(*dst6); 2377 dst6->sin6_addr = addr->v6; 2378#ifdef __FreeBSD__ 2379#ifdef RTF_PRCLONING 2380 rtalloc_ign((struct route *)&ro6, 2381 (RTF_CLONING | RTF_PRCLONING)); 2382#else /* !RTF_PRCLONING */ 2383 rtalloc_ign((struct route *)&ro6, RTF_CLONING); 2384#endif 2385#else /* ! __FreeBSD__ */ 2386 rtalloc_noclone((struct route *)&ro6, NO_CLONING); 2387#endif 2388 rt = ro6.ro_rt; 2389 break; 2390#endif /* INET6 */ 2391 } 2392 2393 if (rt && rt->rt_ifp) { 2394 mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr); 2395 mss = max(tcp_mssdflt, mss); 2396 RTFREE(rt); 2397 } 2398 mss = min(mss, offer); 2399 mss = max(mss, 64); /* sanity - at least max opt space */ 2400 return (mss); 2401} 2402 2403void 2404pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr) 2405{ 2406 struct pf_rule *r = s->rule.ptr; 2407 2408 s->rt_ifp = NULL; 2409 if (!r->rt || r->rt == PF_FASTROUTE) 2410 return; 2411 switch (s->af) { 2412#ifdef INET 2413 case AF_INET: 2414 pf_map_addr(AF_INET, &r->rpool, saddr, 2415 &s->rt_addr, NULL); 2416 s->rt_ifp = r->rpool.cur->ifp; 2417 break; 2418#endif /* INET */ 2419#ifdef INET6 2420 case AF_INET6: 2421 pf_map_addr(AF_INET6, &r->rpool, saddr, 2422 &s->rt_addr, NULL); 2423 s->rt_ifp = r->rpool.cur->ifp; 2424 break; 2425#endif /* INET6 */ 2426 } 2427} 2428 2429int 2430pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction, 2431 struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h, 2432 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm) 2433{ 2434 struct pf_rule *nat = NULL, *rdr = NULL; 2435 struct pf_addr *saddr = pd->src, *daddr = pd->dst; 2436 struct pf_addr baddr, naddr; 2437 struct tcphdr *th = pd->hdr.tcp; 2438 u_int16_t bport, nport = 0; 2439 sa_family_t af = pd->af; 2440 int lookup = -1; 2441 uid_t uid; 2442 gid_t gid; 2443 struct pf_rule *r, *a = NULL; 2444 struct pf_ruleset *ruleset = NULL; 2445 u_short reason; 2446 int rewrite = 0; 2447 struct pf_tag *pftag = NULL; 2448 int tag = -1; 2449 u_int16_t mss = tcp_mssdflt; 2450 2451 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); 2452 2453 if (direction == PF_OUT) { 2454 bport = nport = th->th_sport; 2455 /* check outgoing packet for BINAT/NAT */ 2456 if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, 2457 saddr, th->th_sport, daddr, th->th_dport, 2458 &naddr, &nport)) != NULL) { 2459 PF_ACPY(&baddr, saddr, af); 2460 pf_change_ap(saddr, &th->th_sport, pd->ip_sum, 2461 &th->th_sum, &naddr, nport, 0, af); 2462 rewrite++; 2463 if (nat->natpass) 2464 r = NULL; 2465 } 2466 } else { 2467 bport = nport = th->th_dport; 2468 /* check incoming packet for BINAT/RDR */ 2469 if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 2470 th->th_sport, daddr, th->th_dport, 2471 &naddr, &nport)) != NULL) { 2472 PF_ACPY(&baddr, daddr, af); 2473 pf_change_ap(daddr, &th->th_dport, pd->ip_sum, 2474 &th->th_sum, &naddr, nport, 0, af); 2475 rewrite++; 2476 if (rdr->natpass) 2477 r = NULL; 2478 } 2479 } 2480 2481 while (r != NULL) { 2482 r->evaluations++; 2483 if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) || 2484 (r->ifp == ifp && r->ifnot))) 2485 r = r->skip[PF_SKIP_IFP].ptr; 2486 else if (r->direction && r->direction != direction) 2487 r = r->skip[PF_SKIP_DIR].ptr; 2488 else if (r->af && r->af != af) 2489 r = r->skip[PF_SKIP_AF].ptr; 2490 else if (r->proto && r->proto != IPPROTO_TCP) 2491 r = r->skip[PF_SKIP_PROTO].ptr; 2492 else if (PF_MISMATCHAW(&r->src.addr, saddr, af, r->src.not)) 2493 r = r->skip[PF_SKIP_SRC_ADDR].ptr; 2494 else if (r->src.port_op && !pf_match_port(r->src.port_op, 2495 r->src.port[0], r->src.port[1], th->th_sport)) 2496 r = r->skip[PF_SKIP_SRC_PORT].ptr; 2497 else if (PF_MISMATCHAW(&r->dst.addr, daddr, af, r->dst.not)) 2498 r = r->skip[PF_SKIP_DST_ADDR].ptr; 2499 else if (r->dst.port_op && !pf_match_port(r->dst.port_op, 2500 r->dst.port[0], r->dst.port[1], th->th_dport)) 2501 r = r->skip[PF_SKIP_DST_PORT].ptr; 2502 else if (r->tos && !(r->tos & pd->tos)) 2503 r = TAILQ_NEXT(r, entries); 2504 else if (r->rule_flag & PFRULE_FRAGMENT) 2505 r = TAILQ_NEXT(r, entries); 2506 else if ((r->flagset & th->th_flags) != r->flags) 2507 r = TAILQ_NEXT(r, entries); 2508 else if (r->uid.op && (lookup != -1 || (lookup = 2509 pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP, 2510 pd), 1)) && 2511 !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], 2512 uid)) 2513 r = TAILQ_NEXT(r, entries); 2514 else if (r->gid.op && (lookup != -1 || (lookup = 2515 pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP, 2516 pd), 1)) && 2517 !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], 2518 gid)) 2519 r = TAILQ_NEXT(r, entries); 2520 else if (r->match_tag && 2521 !pf_match_tag(m, r, nat, rdr, pftag, &tag)) 2522 r = TAILQ_NEXT(r, entries); 2523 else if (r->anchorname[0] && r->anchor == NULL) 2524 r = TAILQ_NEXT(r, entries); 2525 else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match( 2526 pf_osfp_fingerprint(pd, m, off, th), r->os_fingerprint)) 2527 r = TAILQ_NEXT(r, entries); 2528 else { 2529 if (r->tag) 2530 tag = r->tag; 2531 if (r->anchor == NULL) { 2532 *rm = r; 2533 *am = a; 2534 *rsm = ruleset; 2535 if ((*rm)->quick) 2536 break; 2537 r = TAILQ_NEXT(r, entries); 2538 } else 2539 PF_STEP_INTO_ANCHOR(r, a, ruleset, 2540 PF_RULESET_FILTER); 2541 } 2542 if (r == NULL && a != NULL) 2543 PF_STEP_OUT_OF_ANCHOR(r, a, ruleset, 2544 PF_RULESET_FILTER); 2545 } 2546 r = *rm; 2547 a = *am; 2548 ruleset = *rsm; 2549 2550 r->packets++; 2551 r->bytes += pd->tot_len; 2552 if (a != NULL) { 2553 a->packets++; 2554 a->bytes += pd->tot_len; 2555 } 2556 REASON_SET(&reason, PFRES_MATCH); 2557 2558 if (r->log) { 2559 if (rewrite) 2560 m_copyback(m, off, sizeof(*th), (caddr_t)th); 2561 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); 2562 } 2563 2564 if ((r->action == PF_DROP) && 2565 ((r->rule_flag & PFRULE_RETURNRST) || 2566 (r->rule_flag & PFRULE_RETURNICMP) || 2567 (r->rule_flag & PFRULE_RETURN))) { 2568 /* undo NAT changes, if they have taken place */ 2569 if (nat != NULL) { 2570 pf_change_ap(saddr, &th->th_sport, pd->ip_sum, 2571 &th->th_sum, &baddr, bport, 0, af); 2572 rewrite++; 2573 } else if (rdr != NULL) { 2574 pf_change_ap(daddr, &th->th_dport, pd->ip_sum, 2575 &th->th_sum, &baddr, bport, 0, af); 2576 rewrite++; 2577 } 2578 if (((r->rule_flag & PFRULE_RETURNRST) || 2579 (r->rule_flag & PFRULE_RETURN)) && 2580 !(th->th_flags & TH_RST)) { 2581 u_int32_t ack = ntohl(th->th_seq) + pd->p_len; 2582 2583 if (th->th_flags & TH_SYN) 2584 ack++; 2585 if (th->th_flags & TH_FIN) 2586 ack++; 2587 pf_send_tcp(r, af, pd->dst, 2588 pd->src, th->th_dport, th->th_sport, 2589 ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0, 2590 r->return_ttl); 2591 } else if ((af == AF_INET) && r->return_icmp) 2592 pf_send_icmp(m, r->return_icmp >> 8, 2593 r->return_icmp & 255, af, r); 2594 else if ((af == AF_INET6) && r->return_icmp6) 2595 pf_send_icmp(m, r->return_icmp6 >> 8, 2596 r->return_icmp6 & 255, af, r); 2597 } 2598 2599 if (r->action == PF_DROP) 2600 return (PF_DROP); 2601 2602 if (pf_tag_packet(m, pftag, tag)) { 2603 REASON_SET(&reason, PFRES_MEMORY); 2604 return (PF_DROP); 2605 } 2606 2607 if (r->keep_state || nat != NULL || rdr != NULL || 2608 (pd->flags & PFDESC_TCP_NORM)) { 2609 /* create new state */ 2610 u_int16_t len; 2611 struct pf_state *s = NULL; 2612 2613 len = pd->tot_len - off - (th->th_off << 2); 2614 if (!r->max_states || r->states < r->max_states) 2615 s = pool_get(&pf_state_pl, PR_NOWAIT); 2616 if (s == NULL) { 2617 REASON_SET(&reason, PFRES_MEMORY); 2618 return (PF_DROP); 2619 } 2620 bzero(s, sizeof(*s)); 2621 r->states++; 2622 if (a != NULL) 2623 a->states++; 2624 s->rule.ptr = r; 2625 if (nat != NULL) 2626 s->nat_rule.ptr = nat; 2627 else 2628 s->nat_rule.ptr = rdr; 2629 if (s->nat_rule.ptr != NULL) 2630 s->nat_rule.ptr->states++; 2631 s->anchor.ptr = a; 2632 s->allow_opts = r->allow_opts; 2633 s->log = r->log & 2; 2634 s->proto = IPPROTO_TCP; 2635 s->direction = direction; 2636 s->af = af; 2637 if (direction == PF_OUT) { 2638 PF_ACPY(&s->gwy.addr, saddr, af); 2639 s->gwy.port = th->th_sport; /* sport */ 2640 PF_ACPY(&s->ext.addr, daddr, af); 2641 s->ext.port = th->th_dport; 2642 if (nat != NULL) { 2643 PF_ACPY(&s->lan.addr, &baddr, af); 2644 s->lan.port = bport; 2645 } else { 2646 PF_ACPY(&s->lan.addr, &s->gwy.addr, af); 2647 s->lan.port = s->gwy.port; 2648 } 2649 } else { 2650 PF_ACPY(&s->lan.addr, daddr, af); 2651 s->lan.port = th->th_dport; 2652 PF_ACPY(&s->ext.addr, saddr, af); 2653 s->ext.port = th->th_sport; 2654 if (rdr != NULL) { 2655 PF_ACPY(&s->gwy.addr, &baddr, af); 2656 s->gwy.port = bport; 2657 } else { 2658 PF_ACPY(&s->gwy.addr, &s->lan.addr, af); 2659 s->gwy.port = s->lan.port; 2660 } 2661 } 2662 2663 s->src.seqlo = ntohl(th->th_seq); 2664 s->src.seqhi = s->src.seqlo + len + 1; 2665 if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN && 2666 r->keep_state == PF_STATE_MODULATE) { 2667 /* Generate sequence number modulator */ 2668 while ((s->src.seqdiff = arc4random()) == 0) 2669 ; 2670 pf_change_a(&th->th_seq, &th->th_sum, 2671 htonl(s->src.seqlo + s->src.seqdiff), 0); 2672 rewrite = 1; 2673 } else 2674 s->src.seqdiff = 0; 2675 if (th->th_flags & TH_SYN) { 2676 s->src.seqhi++; 2677 s->src.wscale = pf_get_wscale(m, off, th->th_off, af); 2678 } 2679 s->src.max_win = MAX(ntohs(th->th_win), 1); 2680 if (s->src.wscale & PF_WSCALE_MASK) { 2681 /* Remove scale factor from initial window */ 2682 int win = s->src.max_win; 2683 win += 1 << (s->src.wscale & PF_WSCALE_MASK); 2684 s->src.max_win = (win - 1) >> 2685 (s->src.wscale & PF_WSCALE_MASK); 2686 } 2687 if (th->th_flags & TH_FIN) 2688 s->src.seqhi++; 2689 s->dst.seqhi = 1; 2690 s->dst.max_win = 1; 2691 s->src.state = TCPS_SYN_SENT; 2692 s->dst.state = TCPS_CLOSED; 2693#ifdef __FreeBSD__ 2694 s->creation = time_second; 2695 s->expire = time_second; 2696#else 2697 s->creation = time.tv_sec; 2698 s->expire = time.tv_sec; 2699#endif 2700 s->timeout = PFTM_TCP_FIRST_PACKET; 2701 s->packets[0] = 1; 2702 s->bytes[0] = pd->tot_len; 2703 pf_set_rt_ifp(s, saddr); 2704 2705 if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m, 2706 off, pd, th, &s->src, &s->dst)) { 2707 REASON_SET(&reason, PFRES_MEMORY); 2708 pool_put(&pf_state_pl, s); 2709 return (PF_DROP); 2710 } 2711 if ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub && 2712 pf_normalize_tcp_stateful(m, off, pd, &reason, th, &s->src, 2713 &s->dst, &rewrite)) { 2714 pf_normalize_tcp_cleanup(s); 2715 pool_put(&pf_state_pl, s); 2716 return (PF_DROP); 2717 } 2718 if (pf_insert_state(s)) { 2719 pf_normalize_tcp_cleanup(s); 2720 REASON_SET(&reason, PFRES_MEMORY); 2721 pool_put(&pf_state_pl, s); 2722 return (PF_DROP); 2723 } else 2724 *sm = s; 2725 if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN && 2726 r->keep_state == PF_STATE_SYNPROXY) { 2727 s->src.state = PF_TCPS_PROXY_SRC; 2728 if (nat != NULL) 2729 pf_change_ap(saddr, &th->th_sport, 2730 pd->ip_sum, &th->th_sum, &baddr, 2731 bport, 0, af); 2732 else if (rdr != NULL) 2733 pf_change_ap(daddr, &th->th_dport, 2734 pd->ip_sum, &th->th_sum, &baddr, 2735 bport, 0, af); 2736 s->src.seqhi = arc4random(); 2737 /* Find mss option */ 2738 mss = pf_get_mss(m, off, th->th_off, af); 2739 mss = pf_calc_mss(saddr, af, mss); 2740 mss = pf_calc_mss(daddr, af, mss); 2741 s->src.mss = mss; 2742 pf_send_tcp(r, af, daddr, saddr, th->th_dport, 2743 th->th_sport, s->src.seqhi, 2744 ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, s->src.mss, 0); 2745 return (PF_SYNPROXY_DROP); 2746 } 2747 } 2748 2749 /* copy back packet headers if we performed NAT operations */ 2750 if (rewrite) 2751 m_copyback(m, off, sizeof(*th), (caddr_t)th); 2752 2753 return (PF_PASS); 2754} 2755 2756int 2757pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction, 2758 struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h, 2759 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm) 2760{ 2761 struct pf_rule *nat = NULL, *rdr = NULL; 2762 struct pf_addr *saddr = pd->src, *daddr = pd->dst; 2763 struct pf_addr baddr, naddr; 2764 struct udphdr *uh = pd->hdr.udp; 2765 u_int16_t bport, nport = 0; 2766 sa_family_t af = pd->af; 2767 int lookup = -1; 2768 uid_t uid; 2769 gid_t gid; 2770 struct pf_rule *r, *a = NULL; 2771 struct pf_ruleset *ruleset = NULL; 2772 u_short reason; 2773 int rewrite = 0; 2774 struct pf_tag *pftag = NULL; 2775 int tag = -1; 2776 2777 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); 2778 2779 if (direction == PF_OUT) { 2780 bport = nport = uh->uh_sport; 2781 /* check outgoing packet for BINAT/NAT */ 2782 if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, 2783 saddr, uh->uh_sport, daddr, uh->uh_dport, 2784 &naddr, &nport)) != NULL) { 2785 PF_ACPY(&baddr, saddr, af); 2786 pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum, 2787 &uh->uh_sum, &naddr, nport, 1, af); 2788 rewrite++; 2789 if (nat->natpass) 2790 r = NULL; 2791 } 2792 } else { 2793 bport = nport = uh->uh_dport; 2794 /* check incoming packet for BINAT/RDR */ 2795 if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 2796 uh->uh_sport, daddr, uh->uh_dport, &naddr, &nport)) 2797 != NULL) { 2798 PF_ACPY(&baddr, daddr, af); 2799 pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum, 2800 &uh->uh_sum, &naddr, nport, 1, af); 2801 rewrite++; 2802 if (rdr->natpass) 2803 r = NULL; 2804 } 2805 } 2806 2807 while (r != NULL) { 2808 r->evaluations++; 2809 if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) || 2810 (r->ifp == ifp && r->ifnot))) 2811 r = r->skip[PF_SKIP_IFP].ptr; 2812 else if (r->direction && r->direction != direction) 2813 r = r->skip[PF_SKIP_DIR].ptr; 2814 else if (r->af && r->af != af) 2815 r = r->skip[PF_SKIP_AF].ptr; 2816 else if (r->proto && r->proto != IPPROTO_UDP) 2817 r = r->skip[PF_SKIP_PROTO].ptr; 2818 else if (PF_MISMATCHAW(&r->src.addr, saddr, af, r->src.not)) 2819 r = r->skip[PF_SKIP_SRC_ADDR].ptr; 2820 else if (r->src.port_op && !pf_match_port(r->src.port_op, 2821 r->src.port[0], r->src.port[1], uh->uh_sport)) 2822 r = r->skip[PF_SKIP_SRC_PORT].ptr; 2823 else if (PF_MISMATCHAW(&r->dst.addr, daddr, af, r->dst.not)) 2824 r = r->skip[PF_SKIP_DST_ADDR].ptr; 2825 else if (r->dst.port_op && !pf_match_port(r->dst.port_op, 2826 r->dst.port[0], r->dst.port[1], uh->uh_dport)) 2827 r = r->skip[PF_SKIP_DST_PORT].ptr; 2828 else if (r->tos && !(r->tos & pd->tos)) 2829 r = TAILQ_NEXT(r, entries); 2830 else if (r->rule_flag & PFRULE_FRAGMENT) 2831 r = TAILQ_NEXT(r, entries); 2832 else if (r->uid.op && (lookup != -1 || (lookup = 2833 pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP, 2834 pd), 1)) && 2835 !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], 2836 uid)) 2837 r = TAILQ_NEXT(r, entries); 2838 else if (r->gid.op && (lookup != -1 || (lookup = 2839 pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP, 2840 pd), 1)) && 2841 !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], 2842 gid)) 2843 r = TAILQ_NEXT(r, entries); 2844 else if (r->match_tag && 2845 !pf_match_tag(m, r, nat, rdr, pftag, &tag)) 2846 r = TAILQ_NEXT(r, entries); 2847 else if (r->anchorname[0] && r->anchor == NULL) 2848 r = TAILQ_NEXT(r, entries); 2849 else if (r->os_fingerprint != PF_OSFP_ANY) 2850 r = TAILQ_NEXT(r, entries); 2851 else { 2852 if (r->tag) 2853 tag = r->tag; 2854 if (r->anchor == NULL) { 2855 *rm = r; 2856 *am = a; 2857 *rsm = ruleset; 2858 if ((*rm)->quick) 2859 break; 2860 r = TAILQ_NEXT(r, entries); 2861 } else 2862 PF_STEP_INTO_ANCHOR(r, a, ruleset, 2863 PF_RULESET_FILTER); 2864 } 2865 if (r == NULL && a != NULL) 2866 PF_STEP_OUT_OF_ANCHOR(r, a, ruleset, 2867 PF_RULESET_FILTER); 2868 } 2869 r = *rm; 2870 a = *am; 2871 ruleset = *rsm; 2872 2873 r->packets++; 2874 r->bytes += pd->tot_len; 2875 if (a != NULL) { 2876 a->packets++; 2877 a->bytes += pd->tot_len; 2878 } 2879 REASON_SET(&reason, PFRES_MATCH); 2880 2881 if (r->log) { 2882 if (rewrite) 2883 m_copyback(m, off, sizeof(*uh), (caddr_t)uh); 2884 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); 2885 } 2886 2887 if ((r->action == PF_DROP) && 2888 ((r->rule_flag & PFRULE_RETURNICMP) || 2889 (r->rule_flag & PFRULE_RETURN))) { 2890 /* undo NAT changes, if they have taken place */ 2891 if (nat != NULL) { 2892 pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum, 2893 &uh->uh_sum, &baddr, bport, 1, af); 2894 rewrite++; 2895 } else if (rdr != NULL) { 2896 pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum, 2897 &uh->uh_sum, &baddr, bport, 1, af); 2898 rewrite++; 2899 } 2900 if ((af == AF_INET) && r->return_icmp) 2901 pf_send_icmp(m, r->return_icmp >> 8, 2902 r->return_icmp & 255, af, r); 2903 else if ((af == AF_INET6) && r->return_icmp6) 2904 pf_send_icmp(m, r->return_icmp6 >> 8, 2905 r->return_icmp6 & 255, af, r); 2906 } 2907 2908 if (r->action == PF_DROP) 2909 return (PF_DROP); 2910 2911 if (pf_tag_packet(m, pftag, tag)) { 2912 REASON_SET(&reason, PFRES_MEMORY); 2913 return (PF_DROP); 2914 } 2915 2916 if (r->keep_state || nat != NULL || rdr != NULL) { 2917 /* create new state */ 2918 struct pf_state *s = NULL; 2919 2920 if (!r->max_states || r->states < r->max_states) 2921 s = pool_get(&pf_state_pl, PR_NOWAIT); 2922 if (s == NULL) { 2923 REASON_SET(&reason, PFRES_MEMORY); 2924 return (PF_DROP); 2925 } 2926 bzero(s, sizeof(*s)); 2927 r->states++; 2928 if (a != NULL) 2929 a->states++; 2930 s->rule.ptr = r; 2931 if (nat != NULL) 2932 s->nat_rule.ptr = nat; 2933 else 2934 s->nat_rule.ptr = rdr; 2935 if (s->nat_rule.ptr != NULL) 2936 s->nat_rule.ptr->states++; 2937 s->anchor.ptr = a; 2938 s->allow_opts = r->allow_opts; 2939 s->log = r->log & 2; 2940 s->proto = IPPROTO_UDP; 2941 s->direction = direction; 2942 s->af = af; 2943 if (direction == PF_OUT) { 2944 PF_ACPY(&s->gwy.addr, saddr, af); 2945 s->gwy.port = uh->uh_sport; 2946 PF_ACPY(&s->ext.addr, daddr, af); 2947 s->ext.port = uh->uh_dport; 2948 if (nat != NULL) { 2949 PF_ACPY(&s->lan.addr, &baddr, af); 2950 s->lan.port = bport; 2951 } else { 2952 PF_ACPY(&s->lan.addr, &s->gwy.addr, af); 2953 s->lan.port = s->gwy.port; 2954 } 2955 } else { 2956 PF_ACPY(&s->lan.addr, daddr, af); 2957 s->lan.port = uh->uh_dport; 2958 PF_ACPY(&s->ext.addr, saddr, af); 2959 s->ext.port = uh->uh_sport; 2960 if (rdr != NULL) { 2961 PF_ACPY(&s->gwy.addr, &baddr, af); 2962 s->gwy.port = bport; 2963 } else { 2964 PF_ACPY(&s->gwy.addr, &s->lan.addr, af); 2965 s->gwy.port = s->lan.port; 2966 } 2967 } 2968 s->src.state = PFUDPS_SINGLE; 2969 s->dst.state = PFUDPS_NO_TRAFFIC; 2970#ifdef __FreeBSD__ 2971 s->creation = time_second; 2972 s->expire = time_second; 2973#else 2974 s->creation = time.tv_sec; 2975 s->expire = time.tv_sec; 2976#endif 2977 s->timeout = PFTM_UDP_FIRST_PACKET; 2978 s->packets[0] = 1; 2979 s->bytes[0] = pd->tot_len; 2980 pf_set_rt_ifp(s, saddr); 2981 if (pf_insert_state(s)) { 2982 REASON_SET(&reason, PFRES_MEMORY); 2983 pool_put(&pf_state_pl, s); 2984 return (PF_DROP); 2985 } else 2986 *sm = s; 2987 } 2988 2989 /* copy back packet headers if we performed NAT operations */ 2990 if (rewrite) 2991 m_copyback(m, off, sizeof(*uh), (caddr_t)uh); 2992 2993 return (PF_PASS); 2994} 2995 2996int 2997pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction, 2998 struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h, 2999 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm) 3000{ 3001 struct pf_rule *nat = NULL, *rdr = NULL; 3002 struct pf_addr *saddr = pd->src, *daddr = pd->dst; 3003 struct pf_addr baddr, naddr; 3004 struct pf_rule *r, *a = NULL; 3005 struct pf_ruleset *ruleset = NULL; 3006 u_short reason; 3007 u_int16_t icmpid; 3008 sa_family_t af = pd->af; 3009 u_int8_t icmptype, icmpcode; 3010 int state_icmp = 0; 3011 struct pf_tag *pftag = NULL; 3012 int tag = -1; 3013#ifdef INET6 3014 int rewrite = 0; 3015#endif /* INET6 */ 3016 3017 switch (pd->proto) { 3018#ifdef INET 3019 case IPPROTO_ICMP: 3020 icmptype = pd->hdr.icmp->icmp_type; 3021 icmpcode = pd->hdr.icmp->icmp_code; 3022 icmpid = pd->hdr.icmp->icmp_id; 3023 3024 if (icmptype == ICMP_UNREACH || 3025 icmptype == ICMP_SOURCEQUENCH || 3026 icmptype == ICMP_REDIRECT || 3027 icmptype == ICMP_TIMXCEED || 3028 icmptype == ICMP_PARAMPROB) 3029 state_icmp++; 3030 break; 3031#endif /* INET */ 3032#ifdef INET6 3033 case IPPROTO_ICMPV6: 3034 icmptype = pd->hdr.icmp6->icmp6_type; 3035 icmpcode = pd->hdr.icmp6->icmp6_code; 3036 icmpid = pd->hdr.icmp6->icmp6_id; 3037 3038 if (icmptype == ICMP6_DST_UNREACH || 3039 icmptype == ICMP6_PACKET_TOO_BIG || 3040 icmptype == ICMP6_TIME_EXCEEDED || 3041 icmptype == ICMP6_PARAM_PROB) 3042 state_icmp++; 3043 break; 3044#endif /* INET6 */ 3045 } 3046 3047 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); 3048 3049 if (direction == PF_OUT) { 3050 /* check outgoing packet for BINAT/NAT */ 3051 if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, saddr, 0, 3052 daddr, 0, &naddr, NULL)) != NULL) { 3053 PF_ACPY(&baddr, saddr, af); 3054 switch (af) { 3055#ifdef INET 3056 case AF_INET: 3057 pf_change_a(&saddr->v4.s_addr, pd->ip_sum, 3058 naddr.v4.s_addr, 0); 3059 break; 3060#endif /* INET */ 3061#ifdef INET6 3062 case AF_INET6: 3063 pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum, 3064 &naddr, 0); 3065 rewrite++; 3066 break; 3067#endif /* INET6 */ 3068 } 3069 if (nat->natpass) 3070 r = NULL; 3071 } 3072 } else { 3073 /* check incoming packet for BINAT/RDR */ 3074 if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 0, 3075 daddr, 0, &naddr, NULL)) != NULL) { 3076 PF_ACPY(&baddr, daddr, af); 3077 switch (af) { 3078#ifdef INET 3079 case AF_INET: 3080 pf_change_a(&daddr->v4.s_addr, 3081 pd->ip_sum, naddr.v4.s_addr, 0); 3082 break; 3083#endif /* INET */ 3084#ifdef INET6 3085 case AF_INET6: 3086 pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum, 3087 &naddr, 0); 3088 rewrite++; 3089 break; 3090#endif /* INET6 */ 3091 } 3092 if (rdr->natpass) 3093 r = NULL; 3094 } 3095 } 3096 3097 while (r != NULL) { 3098 r->evaluations++; 3099 if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) || 3100 (r->ifp == ifp && r->ifnot))) 3101 r = r->skip[PF_SKIP_IFP].ptr; 3102 else if (r->direction && r->direction != direction) 3103 r = r->skip[PF_SKIP_DIR].ptr; 3104 else if (r->af && r->af != af) 3105 r = r->skip[PF_SKIP_AF].ptr; 3106 else if (r->proto && r->proto != pd->proto) 3107 r = r->skip[PF_SKIP_PROTO].ptr; 3108 else if (PF_MISMATCHAW(&r->src.addr, saddr, af, r->src.not)) 3109 r = r->skip[PF_SKIP_SRC_ADDR].ptr; 3110 else if (PF_MISMATCHAW(&r->dst.addr, daddr, af, r->dst.not)) 3111 r = r->skip[PF_SKIP_DST_ADDR].ptr; 3112 else if (r->type && r->type != icmptype + 1) 3113 r = TAILQ_NEXT(r, entries); 3114 else if (r->code && r->code != icmpcode + 1) 3115 r = TAILQ_NEXT(r, entries); 3116 else if (r->tos && !(r->tos & pd->tos)) 3117 r = TAILQ_NEXT(r, entries); 3118 else if (r->rule_flag & PFRULE_FRAGMENT) 3119 r = TAILQ_NEXT(r, entries); 3120 else if (r->match_tag && 3121 !pf_match_tag(m, r, nat, rdr, pftag, &tag)) 3122 r = TAILQ_NEXT(r, entries); 3123 else if (r->anchorname[0] && r->anchor == NULL) 3124 r = TAILQ_NEXT(r, entries); 3125 else if (r->os_fingerprint != PF_OSFP_ANY) 3126 r = TAILQ_NEXT(r, entries); 3127 else { 3128 if (r->tag) 3129 tag = r->tag; 3130 if (r->anchor == NULL) { 3131 *rm = r; 3132 *am = a; 3133 *rsm = ruleset; 3134 if ((*rm)->quick) 3135 break; 3136 r = TAILQ_NEXT(r, entries); 3137 } else 3138 PF_STEP_INTO_ANCHOR(r, a, ruleset, 3139 PF_RULESET_FILTER); 3140 } 3141 if (r == NULL && a != NULL) 3142 PF_STEP_OUT_OF_ANCHOR(r, a, ruleset, 3143 PF_RULESET_FILTER); 3144 } 3145 r = *rm; 3146 a = *am; 3147 ruleset = *rsm; 3148 3149 r->packets++; 3150 r->bytes += pd->tot_len; 3151 if (a != NULL) { 3152 a->packets++; 3153 a->bytes += pd->tot_len; 3154 } 3155 REASON_SET(&reason, PFRES_MATCH); 3156 3157 if (r->log) { 3158#ifdef INET6 3159 if (rewrite) 3160 m_copyback(m, off, sizeof(struct icmp6_hdr), 3161 (caddr_t)pd->hdr.icmp6); 3162#endif /* INET6 */ 3163 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); 3164 } 3165 3166 if (r->action != PF_PASS) 3167 return (PF_DROP); 3168 3169 if (pf_tag_packet(m, pftag, tag)) { 3170 REASON_SET(&reason, PFRES_MEMORY); 3171 return (PF_DROP); 3172 } 3173 3174 if (!state_icmp && (r->keep_state || 3175 nat != NULL || rdr != NULL)) { 3176 /* create new state */ 3177 struct pf_state *s = NULL; 3178 3179 if (!r->max_states || r->states < r->max_states) 3180 s = pool_get(&pf_state_pl, PR_NOWAIT); 3181 if (s == NULL) { 3182 REASON_SET(&reason, PFRES_MEMORY); 3183 return (PF_DROP); 3184 } 3185 bzero(s, sizeof(*s)); 3186 r->states++; 3187 if (a != NULL) 3188 a->states++; 3189 s->rule.ptr = r; 3190 if (nat != NULL) 3191 s->nat_rule.ptr = nat; 3192 else 3193 s->nat_rule.ptr = rdr; 3194 if (s->nat_rule.ptr != NULL) 3195 s->nat_rule.ptr->states++; 3196 s->anchor.ptr = a; 3197 s->allow_opts = r->allow_opts; 3198 s->log = r->log & 2; 3199 s->proto = pd->proto; 3200 s->direction = direction; 3201 s->af = af; 3202 if (direction == PF_OUT) { 3203 PF_ACPY(&s->gwy.addr, saddr, af); 3204 s->gwy.port = icmpid; 3205 PF_ACPY(&s->ext.addr, daddr, af); 3206 s->ext.port = icmpid; 3207 if (nat != NULL) 3208 PF_ACPY(&s->lan.addr, &baddr, af); 3209 else 3210 PF_ACPY(&s->lan.addr, &s->gwy.addr, af); 3211 s->lan.port = icmpid; 3212 } else { 3213 PF_ACPY(&s->lan.addr, daddr, af); 3214 s->lan.port = icmpid; 3215 PF_ACPY(&s->ext.addr, saddr, af); 3216 s->ext.port = icmpid; 3217 if (rdr != NULL) 3218 PF_ACPY(&s->gwy.addr, &baddr, af); 3219 else 3220 PF_ACPY(&s->gwy.addr, &s->lan.addr, af); 3221 s->gwy.port = icmpid; 3222 } 3223 3224#ifdef __FreeBSD__ 3225 s->creation = time_second; 3226 s->expire = time_second; 3227#else 3228 s->creation = time.tv_sec; 3229 s->expire = time.tv_sec; 3230#endif 3231 s->timeout = PFTM_ICMP_FIRST_PACKET; 3232 s->packets[0] = 1; 3233 s->bytes[0] = pd->tot_len; 3234 pf_set_rt_ifp(s, saddr); 3235 if (pf_insert_state(s)) { 3236 REASON_SET(&reason, PFRES_MEMORY); 3237 pool_put(&pf_state_pl, s); 3238 return (PF_DROP); 3239 } else 3240 *sm = s; 3241 } 3242 3243#ifdef INET6 3244 /* copy back packet headers if we performed IPv6 NAT operations */ 3245 if (rewrite) 3246 m_copyback(m, off, sizeof(struct icmp6_hdr), 3247 (caddr_t)pd->hdr.icmp6); 3248#endif /* INET6 */ 3249 3250 return (PF_PASS); 3251} 3252 3253int 3254pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction, 3255 struct ifnet *ifp, struct mbuf *m, int off, void *h, struct pf_pdesc *pd, 3256 struct pf_rule **am, struct pf_ruleset **rsm) 3257{ 3258 struct pf_rule *nat = NULL, *rdr = NULL; 3259 struct pf_rule *r, *a = NULL; 3260 struct pf_ruleset *ruleset = NULL; 3261 struct pf_addr *saddr = pd->src, *daddr = pd->dst; 3262 struct pf_addr baddr, naddr; 3263 sa_family_t af = pd->af; 3264 u_short reason; 3265 struct pf_tag *pftag = NULL; 3266 int tag = -1; 3267 3268 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); 3269 3270 if (direction == PF_OUT) { 3271 /* check outgoing packet for BINAT/NAT */ 3272 if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, saddr, 0, 3273 daddr, 0, &naddr, NULL)) != NULL) { 3274 PF_ACPY(&baddr, saddr, af); 3275 switch (af) { 3276#ifdef INET 3277 case AF_INET: 3278 pf_change_a(&saddr->v4.s_addr, pd->ip_sum, 3279 naddr.v4.s_addr, 0); 3280 break; 3281#endif /* INET */ 3282#ifdef INET6 3283 case AF_INET6: 3284 PF_ACPY(saddr, &naddr, af); 3285 break; 3286#endif /* INET6 */ 3287 } 3288 if (nat->natpass) 3289 r = NULL; 3290 } 3291 } else { 3292 /* check incoming packet for BINAT/RDR */ 3293 if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 0, 3294 daddr, 0, &naddr, NULL)) != NULL) { 3295 PF_ACPY(&baddr, daddr, af); 3296 switch (af) { 3297#ifdef INET 3298 case AF_INET: 3299 pf_change_a(&daddr->v4.s_addr, 3300 pd->ip_sum, naddr.v4.s_addr, 0); 3301 break; 3302#endif /* INET */ 3303#ifdef INET6 3304 case AF_INET6: 3305 PF_ACPY(daddr, &naddr, af); 3306 break; 3307#endif /* INET6 */ 3308 } 3309 if (rdr->natpass) 3310 r = NULL; 3311 } 3312 } 3313 3314 while (r != NULL) { 3315 r->evaluations++; 3316 if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) || 3317 (r->ifp == ifp && r->ifnot))) 3318 r = r->skip[PF_SKIP_IFP].ptr; 3319 else if (r->direction && r->direction != direction) 3320 r = r->skip[PF_SKIP_DIR].ptr; 3321 else if (r->af && r->af != af) 3322 r = r->skip[PF_SKIP_AF].ptr; 3323 else if (r->proto && r->proto != pd->proto) 3324 r = r->skip[PF_SKIP_PROTO].ptr; 3325 else if (PF_MISMATCHAW(&r->src.addr, pd->src, af, r->src.not)) 3326 r = r->skip[PF_SKIP_SRC_ADDR].ptr; 3327 else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af, r->dst.not)) 3328 r = r->skip[PF_SKIP_DST_ADDR].ptr; 3329 else if (r->tos && !(r->tos & pd->tos)) 3330 r = TAILQ_NEXT(r, entries); 3331 else if (r->rule_flag & PFRULE_FRAGMENT) 3332 r = TAILQ_NEXT(r, entries); 3333 else if (r->match_tag && 3334 !pf_match_tag(m, r, nat, rdr, pftag, &tag)) 3335 r = TAILQ_NEXT(r, entries); 3336 else if (r->anchorname[0] && r->anchor == NULL) 3337 r = TAILQ_NEXT(r, entries); 3338 else if (r->os_fingerprint != PF_OSFP_ANY) 3339 r = TAILQ_NEXT(r, entries); 3340 else { 3341 if (r->tag) 3342 tag = r->tag; 3343 if (r->anchor == NULL) { 3344 *rm = r; 3345 *am = a; 3346 *rsm = ruleset; 3347 if ((*rm)->quick) 3348 break; 3349 r = TAILQ_NEXT(r, entries); 3350 } else 3351 PF_STEP_INTO_ANCHOR(r, a, ruleset, 3352 PF_RULESET_FILTER); 3353 } 3354 if (r == NULL && a != NULL) 3355 PF_STEP_OUT_OF_ANCHOR(r, a, ruleset, 3356 PF_RULESET_FILTER); 3357 } 3358 r = *rm; 3359 a = *am; 3360 ruleset = *rsm; 3361 3362 r->packets++; 3363 r->bytes += pd->tot_len; 3364 if (a != NULL) { 3365 a->packets++; 3366 a->bytes += pd->tot_len; 3367 } 3368 REASON_SET(&reason, PFRES_MATCH); 3369 if (r->log) 3370 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); 3371 3372 if ((r->action == PF_DROP) && 3373 ((r->rule_flag & PFRULE_RETURNICMP) || 3374 (r->rule_flag & PFRULE_RETURN))) { 3375 struct pf_addr *a = NULL; 3376 3377 if (nat != NULL) 3378 a = saddr; 3379 else if (rdr != NULL) 3380 a = daddr; 3381 if (a != NULL) { 3382 switch (af) { 3383#ifdef INET 3384 case AF_INET: 3385 pf_change_a(&a->v4.s_addr, pd->ip_sum, 3386 baddr.v4.s_addr, 0); 3387 break; 3388#endif /* INET */ 3389#ifdef INET6 3390 case AF_INET6: 3391 PF_ACPY(a, &baddr, af); 3392 break; 3393#endif /* INET6 */ 3394 } 3395 } 3396 if ((af == AF_INET) && r->return_icmp) 3397 pf_send_icmp(m, r->return_icmp >> 8, 3398 r->return_icmp & 255, af, r); 3399 else if ((af == AF_INET6) && r->return_icmp6) 3400 pf_send_icmp(m, r->return_icmp6 >> 8, 3401 r->return_icmp6 & 255, af, r); 3402 } 3403 3404 if (r->action != PF_PASS) 3405 return (PF_DROP); 3406 3407 if (pf_tag_packet(m, pftag, tag)) { 3408 REASON_SET(&reason, PFRES_MEMORY); 3409 return (PF_DROP); 3410 } 3411 3412 if (r->keep_state || nat != NULL || rdr != NULL) { 3413 /* create new state */ 3414 struct pf_state *s = NULL; 3415 3416 if (!r->max_states || r->states < r->max_states) 3417 s = pool_get(&pf_state_pl, PR_NOWAIT); 3418 if (s == NULL) { 3419 REASON_SET(&reason, PFRES_MEMORY); 3420 return (PF_DROP); 3421 } 3422 bzero(s, sizeof(*s)); 3423 r->states++; 3424 if (a != NULL) 3425 a->states++; 3426 s->rule.ptr = r; 3427 if (nat != NULL) 3428 s->nat_rule.ptr = nat; 3429 else 3430 s->nat_rule.ptr = rdr; 3431 if (s->nat_rule.ptr != NULL) 3432 s->nat_rule.ptr->states++; 3433 s->anchor.ptr = a; 3434 s->allow_opts = r->allow_opts; 3435 s->log = r->log & 2; 3436 s->proto = pd->proto; 3437 s->direction = direction; 3438 s->af = af; 3439 if (direction == PF_OUT) { 3440 PF_ACPY(&s->gwy.addr, saddr, af); 3441 PF_ACPY(&s->ext.addr, daddr, af); 3442 if (nat != NULL) 3443 PF_ACPY(&s->lan.addr, &baddr, af); 3444 else 3445 PF_ACPY(&s->lan.addr, &s->gwy.addr, af); 3446 } else { 3447 PF_ACPY(&s->lan.addr, daddr, af); 3448 PF_ACPY(&s->ext.addr, saddr, af); 3449 if (rdr != NULL) 3450 PF_ACPY(&s->gwy.addr, &baddr, af); 3451 else 3452 PF_ACPY(&s->gwy.addr, &s->lan.addr, af); 3453 } 3454 s->src.state = PFOTHERS_SINGLE; 3455 s->dst.state = PFOTHERS_NO_TRAFFIC; 3456#ifdef __FreeBSD__ 3457 s->creation = time_second; 3458 s->expire = time_second; 3459#else 3460 s->creation = time.tv_sec; 3461 s->expire = time.tv_sec; 3462#endif 3463 s->timeout = PFTM_OTHER_FIRST_PACKET; 3464 s->packets[0] = 1; 3465 s->bytes[0] = pd->tot_len; 3466 pf_set_rt_ifp(s, saddr); 3467 if (pf_insert_state(s)) { 3468 REASON_SET(&reason, PFRES_MEMORY); 3469 if (r->log) 3470 PFLOG_PACKET(ifp, h, m, af, direction, reason, 3471 r, a, ruleset); 3472 pool_put(&pf_state_pl, s); 3473 return (PF_DROP); 3474 } else 3475 *sm = s; 3476 } 3477 3478 return (PF_PASS); 3479} 3480 3481int 3482pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp, 3483 struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am, 3484 struct pf_ruleset **rsm) 3485{ 3486 struct pf_rule *r, *a = NULL; 3487 struct pf_ruleset *ruleset = NULL; 3488 sa_family_t af = pd->af; 3489 u_short reason; 3490 struct pf_tag *pftag = NULL; 3491 int tag = -1; 3492 3493 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); 3494 while (r != NULL) { 3495 r->evaluations++; 3496 if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) || 3497 (r->ifp == ifp && r->ifnot))) 3498 r = r->skip[PF_SKIP_IFP].ptr; 3499 else if (r->direction && r->direction != direction) 3500 r = r->skip[PF_SKIP_DIR].ptr; 3501 else if (r->af && r->af != af) 3502 r = r->skip[PF_SKIP_AF].ptr; 3503 else if (r->proto && r->proto != pd->proto) 3504 r = r->skip[PF_SKIP_PROTO].ptr; 3505 else if (PF_MISMATCHAW(&r->src.addr, pd->src, af, r->src.not)) 3506 r = r->skip[PF_SKIP_SRC_ADDR].ptr; 3507 else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af, r->dst.not)) 3508 r = r->skip[PF_SKIP_DST_ADDR].ptr; 3509 else if (r->tos && !(r->tos & pd->tos)) 3510 r = TAILQ_NEXT(r, entries); 3511 else if (r->src.port_op || r->dst.port_op || 3512 r->flagset || r->type || r->code || 3513 r->os_fingerprint != PF_OSFP_ANY) 3514 r = TAILQ_NEXT(r, entries); 3515 else if (r->match_tag && 3516 !pf_match_tag(m, r, NULL, NULL, pftag, &tag)) 3517 r = TAILQ_NEXT(r, entries); 3518 else if (r->anchorname[0] && r->anchor == NULL) 3519 r = TAILQ_NEXT(r, entries); 3520 else { 3521 if (r->anchor == NULL) { 3522 *rm = r; 3523 *am = a; 3524 *rsm = ruleset; 3525 if ((*rm)->quick) 3526 break; 3527 r = TAILQ_NEXT(r, entries); 3528 } else 3529 PF_STEP_INTO_ANCHOR(r, a, ruleset, 3530 PF_RULESET_FILTER); 3531 } 3532 if (r == NULL && a != NULL) 3533 PF_STEP_OUT_OF_ANCHOR(r, a, ruleset, 3534 PF_RULESET_FILTER); 3535 } 3536 r = *rm; 3537 a = *am; 3538 ruleset = *rsm; 3539 3540 r->packets++; 3541 r->bytes += pd->tot_len; 3542 if (a != NULL) { 3543 a->packets++; 3544 a->bytes += pd->tot_len; 3545 } 3546 REASON_SET(&reason, PFRES_MATCH); 3547 if (r->log) 3548 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset); 3549 3550 if (r->action != PF_PASS) 3551 return (PF_DROP); 3552 3553 if (pf_tag_packet(m, pftag, tag)) { 3554 REASON_SET(&reason, PFRES_MEMORY); 3555 return (PF_DROP); 3556 } 3557 3558 return (PF_PASS); 3559} 3560 3561int 3562pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp, 3563 struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd, 3564 u_short *reason) 3565{ 3566 struct pf_tree_node key; 3567 struct tcphdr *th = pd->hdr.tcp; 3568 u_int16_t win = ntohs(th->th_win); 3569 u_int32_t ack, end, seq; 3570 u_int8_t sws, dws; 3571 int ackskew, dirndx; 3572 int copyback = 0; 3573 struct pf_state_peer *src, *dst; 3574 3575 key.af = pd->af; 3576 key.proto = IPPROTO_TCP; 3577 PF_ACPY(&key.addr[0], pd->src, key.af); 3578 PF_ACPY(&key.addr[1], pd->dst, key.af); 3579 key.port[0] = th->th_sport; 3580 key.port[1] = th->th_dport; 3581 3582 STATE_LOOKUP(); 3583 3584 if (direction == (*state)->direction) { 3585 src = &(*state)->src; 3586 dst = &(*state)->dst; 3587 dirndx = 0; 3588 } else { 3589 src = &(*state)->dst; 3590 dst = &(*state)->src; 3591 dirndx = 1; 3592 } 3593 3594 if ((*state)->src.state == PF_TCPS_PROXY_SRC) { 3595 if (direction != (*state)->direction) 3596 return (PF_SYNPROXY_DROP); 3597 if (th->th_flags & TH_SYN) { 3598 if (ntohl(th->th_seq) != (*state)->src.seqlo) 3599 return (PF_DROP); 3600 pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst, 3601 pd->src, th->th_dport, th->th_sport, 3602 (*state)->src.seqhi, ntohl(th->th_seq) + 1, 3603 TH_SYN|TH_ACK, 0, (*state)->src.mss, 0); 3604 return (PF_SYNPROXY_DROP); 3605 } else if (!(th->th_flags & TH_ACK) || 3606 (ntohl(th->th_ack) != (*state)->src.seqhi + 1) || 3607 (ntohl(th->th_seq) != (*state)->src.seqlo + 1)) 3608 return (PF_DROP); 3609 else 3610 (*state)->src.state = PF_TCPS_PROXY_DST; 3611 } 3612 if ((*state)->src.state == PF_TCPS_PROXY_DST) { 3613 struct pf_state_host *src, *dst; 3614 3615 if (direction == PF_OUT) { 3616 src = &(*state)->gwy; 3617 dst = &(*state)->ext; 3618 } else { 3619 src = &(*state)->ext; 3620 dst = &(*state)->lan; 3621 } 3622 if (direction == (*state)->direction) { 3623 if (((th->th_flags & (TH_SYN|TH_ACK)) != TH_ACK) || 3624 (ntohl(th->th_ack) != (*state)->src.seqhi + 1) || 3625 (ntohl(th->th_seq) != (*state)->src.seqlo + 1)) 3626 return (PF_DROP); 3627 (*state)->src.max_win = MAX(ntohs(th->th_win), 1); 3628 if ((*state)->dst.seqhi == 1) 3629 (*state)->dst.seqhi = arc4random(); 3630 pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr, 3631 &dst->addr, src->port, dst->port, 3632 (*state)->dst.seqhi, 0, TH_SYN, 0, (*state)->src.mss, 0); 3633 return (PF_SYNPROXY_DROP); 3634 } else if (((th->th_flags & (TH_SYN|TH_ACK)) != 3635 (TH_SYN|TH_ACK)) || 3636 (ntohl(th->th_ack) != (*state)->dst.seqhi + 1)) 3637 return (PF_DROP); 3638 else { 3639 (*state)->dst.max_win = MAX(ntohs(th->th_win), 1); 3640 (*state)->dst.seqlo = ntohl(th->th_seq); 3641 pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst, 3642 pd->src, th->th_dport, th->th_sport, 3643 ntohl(th->th_ack), ntohl(th->th_seq) + 1, 3644 TH_ACK, (*state)->src.max_win, 0, 0); 3645 pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr, 3646 &dst->addr, src->port, dst->port, 3647 (*state)->src.seqhi + 1, (*state)->src.seqlo + 1, 3648 TH_ACK, (*state)->dst.max_win, 0, 0); 3649 (*state)->src.seqdiff = (*state)->dst.seqhi - 3650 (*state)->src.seqlo; 3651 (*state)->dst.seqdiff = (*state)->src.seqhi - 3652 (*state)->dst.seqlo; 3653 (*state)->src.seqhi = (*state)->src.seqlo + 3654 (*state)->src.max_win; 3655 (*state)->dst.seqhi = (*state)->dst.seqlo + 3656 (*state)->dst.max_win; 3657 (*state)->src.wscale = (*state)->dst.wscale = 0; 3658 (*state)->src.state = (*state)->dst.state = 3659 TCPS_ESTABLISHED; 3660 return (PF_SYNPROXY_DROP); 3661 } 3662 } 3663 3664 if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) { 3665 sws = src->wscale & PF_WSCALE_MASK; 3666 dws = dst->wscale & PF_WSCALE_MASK; 3667 } else 3668 sws = dws = 0; 3669 3670 /* 3671 * Sequence tracking algorithm from Guido van Rooij's paper: 3672 * http://www.madison-gurkha.com/publications/tcp_filtering/ 3673 * tcp_filtering.ps 3674 */ 3675 3676 seq = ntohl(th->th_seq); 3677 if (src->seqlo == 0) { 3678 /* First packet from this end. Set its state */ 3679 3680 if ((pd->flags & PFDESC_TCP_NORM || dst->scrub) && 3681 src->scrub == NULL) { 3682 if (pf_normalize_tcp_init(m, off, pd, th, src, dst)) { 3683 REASON_SET(reason, PFRES_MEMORY); 3684 return (PF_DROP); 3685 } 3686 } 3687 3688 /* Deferred generation of sequence number modulator */ 3689 if (dst->seqdiff && !src->seqdiff) { 3690 while ((src->seqdiff = arc4random()) == 0) 3691 ; 3692 ack = ntohl(th->th_ack) - dst->seqdiff; 3693 pf_change_a(&th->th_seq, &th->th_sum, htonl(seq + 3694 src->seqdiff), 0); 3695 pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0); 3696 copyback = 1; 3697 } else { 3698 ack = ntohl(th->th_ack); 3699 } 3700 3701 end = seq + pd->p_len; 3702 if (th->th_flags & TH_SYN) { 3703 end++; 3704 if (dst->wscale & PF_WSCALE_FLAG) { 3705 src->wscale = pf_get_wscale(m, off, th->th_off, 3706 pd->af); 3707 if (src->wscale & PF_WSCALE_FLAG) { 3708 /* Remove scale factor from initial 3709 * window */ 3710 sws = src->wscale & PF_WSCALE_MASK; 3711 win = ((u_int32_t)win + (1 << sws) - 1) 3712 >> sws; 3713 dws = dst->wscale & PF_WSCALE_MASK; 3714 } else { 3715 /* fixup other window */ 3716 dst->max_win <<= dst->wscale & 3717 PF_WSCALE_MASK; 3718 /* in case of a retrans SYN|ACK */ 3719 dst->wscale = 0; 3720 } 3721 } 3722 } 3723 if (th->th_flags & TH_FIN) 3724 end++; 3725 3726 src->seqlo = seq; 3727 if (src->state < TCPS_SYN_SENT) 3728 src->state = TCPS_SYN_SENT; 3729 3730 /* 3731 * May need to slide the window (seqhi may have been set by 3732 * the crappy stack check or if we picked up the connection 3733 * after establishment) 3734 */ 3735 if (src->seqhi == 1 || 3736 SEQ_GEQ(end + MAX(1, dst->max_win << dws), src->seqhi)) 3737 src->seqhi = end + MAX(1, dst->max_win << dws); 3738 if (win > src->max_win) 3739 src->max_win = win; 3740 3741 } else { 3742 ack = ntohl(th->th_ack) - dst->seqdiff; 3743 if (src->seqdiff) { 3744 /* Modulate sequence numbers */ 3745 pf_change_a(&th->th_seq, &th->th_sum, htonl(seq + 3746 src->seqdiff), 0); 3747 pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0); 3748 copyback = 1; 3749 } 3750 end = seq + pd->p_len; 3751 if (th->th_flags & TH_SYN) 3752 end++; 3753 if (th->th_flags & TH_FIN) 3754 end++; 3755 } 3756 3757 if ((th->th_flags & TH_ACK) == 0) { 3758 /* Let it pass through the ack skew check */ 3759 ack = dst->seqlo; 3760 } else if ((ack == 0 && 3761 (th->th_flags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) || 3762 /* broken tcp stacks do not set ack */ 3763 (dst->state < TCPS_SYN_SENT)) { 3764 /* 3765 * Many stacks (ours included) will set the ACK number in an 3766 * FIN|ACK if the SYN times out -- no sequence to ACK. 3767 */ 3768 ack = dst->seqlo; 3769 } 3770 3771 if (seq == end) { 3772 /* Ease sequencing restrictions on no data packets */ 3773 seq = src->seqlo; 3774 end = seq; 3775 } 3776 3777 ackskew = dst->seqlo - ack; 3778 3779#define MAXACKWINDOW (0xffff + 1500) /* 1500 is an arbitrary fudge factor */ 3780 if (SEQ_GEQ(src->seqhi, end) && 3781 /* Last octet inside other's window space */ 3782 SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) && 3783 /* Retrans: not more than one window back */ 3784 (ackskew >= -MAXACKWINDOW) && 3785 /* Acking not more than one reassembled fragment backwards */ 3786 (ackskew <= (MAXACKWINDOW << sws))) { 3787 /* Acking not more than one window forward */ 3788 3789 (*state)->packets[dirndx]++; 3790 (*state)->bytes[dirndx] += pd->tot_len; 3791 3792 /* update max window */ 3793 if (src->max_win < win) 3794 src->max_win = win; 3795 /* synchronize sequencing */ 3796 if (SEQ_GT(end, src->seqlo)) 3797 src->seqlo = end; 3798 /* slide the window of what the other end can send */ 3799 if (SEQ_GEQ(ack + (win << sws), dst->seqhi)) 3800 dst->seqhi = ack + MAX((win << sws), 1); 3801 3802 3803 /* update states */ 3804 if (th->th_flags & TH_SYN) 3805 if (src->state < TCPS_SYN_SENT) 3806 src->state = TCPS_SYN_SENT; 3807 if (th->th_flags & TH_FIN) 3808 if (src->state < TCPS_CLOSING) 3809 src->state = TCPS_CLOSING; 3810 if (th->th_flags & TH_ACK) { 3811 if (dst->state == TCPS_SYN_SENT) 3812 dst->state = TCPS_ESTABLISHED; 3813 else if (dst->state == TCPS_CLOSING) 3814 dst->state = TCPS_FIN_WAIT_2; 3815 } 3816 if (th->th_flags & TH_RST) 3817 src->state = dst->state = TCPS_TIME_WAIT; 3818 3819 /* update expire time */ 3820#ifdef __FreeBSD__ 3821 (*state)->expire = time_second; 3822#else 3823 (*state)->expire = time.tv_sec; 3824#endif 3825 if (src->state >= TCPS_FIN_WAIT_2 && 3826 dst->state >= TCPS_FIN_WAIT_2) 3827 (*state)->timeout = PFTM_TCP_CLOSED; 3828 else if (src->state >= TCPS_FIN_WAIT_2 || 3829 dst->state >= TCPS_FIN_WAIT_2) 3830 (*state)->timeout = PFTM_TCP_FIN_WAIT; 3831 else if (src->state < TCPS_ESTABLISHED || 3832 dst->state < TCPS_ESTABLISHED) 3833 (*state)->timeout = PFTM_TCP_OPENING; 3834 else if (src->state >= TCPS_CLOSING || 3835 dst->state >= TCPS_CLOSING) 3836 (*state)->timeout = PFTM_TCP_CLOSING; 3837 else 3838 (*state)->timeout = PFTM_TCP_ESTABLISHED; 3839 3840 /* Fall through to PASS packet */ 3841 3842 } else if ((dst->state < TCPS_SYN_SENT || 3843 dst->state >= TCPS_FIN_WAIT_2 || 3844 src->state >= TCPS_FIN_WAIT_2) && 3845 SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) && 3846 /* Within a window forward of the originating packet */ 3847 SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW)) { 3848 /* Within a window backward of the originating packet */ 3849 3850 /* 3851 * This currently handles three situations: 3852 * 1) Stupid stacks will shotgun SYNs before their peer 3853 * replies. 3854 * 2) When PF catches an already established stream (the 3855 * firewall rebooted, the state table was flushed, routes 3856 * changed...) 3857 * 3) Packets get funky immediately after the connection 3858 * closes (this should catch Solaris spurious ACK|FINs 3859 * that web servers like to spew after a close) 3860 * 3861 * This must be a little more careful than the above code 3862 * since packet floods will also be caught here. We don't 3863 * update the TTL here to mitigate the damage of a packet 3864 * flood and so the same code can handle awkward establishment 3865 * and a loosened connection close. 3866 * In the establishment case, a correct peer response will 3867 * validate the connection, go through the normal state code 3868 * and keep updating the state TTL. 3869 */ 3870 3871 if (pf_status.debug >= PF_DEBUG_MISC) { 3872 printf("pf: loose state match: "); 3873 pf_print_state(*state); 3874 pf_print_flags(th->th_flags); 3875 printf(" seq=%u ack=%u len=%u ackskew=%d pkts=%d:%d\n", 3876 seq, ack, pd->p_len, ackskew, 3877 (*state)->packets[0], (*state)->packets[1]); 3878 } 3879 3880 (*state)->packets[dirndx]++; 3881 (*state)->bytes[dirndx] += pd->tot_len; 3882 3883 /* update max window */ 3884 if (src->max_win < win) 3885 src->max_win = win; 3886 /* synchronize sequencing */ 3887 if (SEQ_GT(end, src->seqlo)) 3888 src->seqlo = end; 3889 /* slide the window of what the other end can send */ 3890 if (SEQ_GEQ(ack + (win << sws), dst->seqhi)) 3891 dst->seqhi = ack + MAX((win << sws), 1); 3892 3893 /* 3894 * Cannot set dst->seqhi here since this could be a shotgunned 3895 * SYN and not an already established connection. 3896 */ 3897 3898 if (th->th_flags & TH_FIN) 3899 if (src->state < TCPS_CLOSING) 3900 src->state = TCPS_CLOSING; 3901 if (th->th_flags & TH_RST) 3902 src->state = dst->state = TCPS_TIME_WAIT; 3903 3904 /* Fall through to PASS packet */ 3905 3906 } else { 3907 if ((*state)->dst.state == TCPS_SYN_SENT && 3908 (*state)->src.state == TCPS_SYN_SENT) { 3909 /* Send RST for state mismatches during handshake */ 3910 if (!(th->th_flags & TH_RST)) { 3911 u_int32_t ack = ntohl(th->th_seq) + pd->p_len; 3912 3913 if (th->th_flags & TH_SYN) 3914 ack++; 3915 if (th->th_flags & TH_FIN) 3916 ack++; 3917 pf_send_tcp((*state)->rule.ptr, pd->af, 3918 pd->dst, pd->src, th->th_dport, 3919 th->th_sport, ntohl(th->th_ack), ack, 3920 TH_RST|TH_ACK, 0, 0, 3921 (*state)->rule.ptr->return_ttl); 3922 } 3923 src->seqlo = 0; 3924 src->seqhi = 1; 3925 src->max_win = 1; 3926 } else if (pf_status.debug >= PF_DEBUG_MISC) { 3927 printf("pf: BAD state: "); 3928 pf_print_state(*state); 3929 pf_print_flags(th->th_flags); 3930 printf(" seq=%u ack=%u len=%u ackskew=%d pkts=%d:%d " 3931 "dir=%s,%s\n", seq, ack, pd->p_len, ackskew, 3932 (*state)->packets[0], (*state)->packets[1], 3933 direction == PF_IN ? "in" : "out", 3934 direction == (*state)->direction ? "fwd" : "rev"); 3935 printf("pf: State failure on: %c %c %c %c | %c %c\n", 3936 SEQ_GEQ(src->seqhi, end) ? ' ' : '1', 3937 SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) ? 3938 ' ': '2', 3939 (ackskew >= -MAXACKWINDOW) ? ' ' : '3', 3940 (ackskew <= (MAXACKWINDOW << sws)) ? ' ' : '4', 3941 SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) ?' ' :'5', 3942 SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW) ?' ' :'6'); 3943 } 3944 return (PF_DROP); 3945 } 3946 3947 if (dst->scrub || src->scrub) { 3948 if (pf_normalize_tcp_stateful(m, off, pd, reason, th, src, dst, 3949 ©back)) 3950 return (PF_DROP); 3951 } 3952 3953 /* Any packets which have gotten here are to be passed */ 3954 3955 /* translate source/destination address, if necessary */ 3956 if (STATE_TRANSLATE(*state)) { 3957 if (direction == PF_OUT) 3958 pf_change_ap(pd->src, &th->th_sport, pd->ip_sum, 3959 &th->th_sum, &(*state)->gwy.addr, 3960 (*state)->gwy.port, 0, pd->af); 3961 else 3962 pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum, 3963 &th->th_sum, &(*state)->lan.addr, 3964 (*state)->lan.port, 0, pd->af); 3965 m_copyback(m, off, sizeof(*th), (caddr_t)th); 3966 } else if (copyback) { 3967 /* Copyback sequence modulation or stateful scrub changes */ 3968 m_copyback(m, off, sizeof(*th), (caddr_t)th); 3969 } 3970 3971 (*state)->rule.ptr->packets++; 3972 (*state)->rule.ptr->bytes += pd->tot_len; 3973 if ((*state)->nat_rule.ptr != NULL) { 3974 (*state)->nat_rule.ptr->packets++; 3975 (*state)->nat_rule.ptr->bytes += pd->tot_len; 3976 } 3977 if ((*state)->anchor.ptr != NULL) { 3978 (*state)->anchor.ptr->packets++; 3979 (*state)->anchor.ptr->bytes += pd->tot_len; 3980 } 3981 return (PF_PASS); 3982} 3983 3984int 3985pf_test_state_udp(struct pf_state **state, int direction, struct ifnet *ifp, 3986 struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd) 3987{ 3988 struct pf_state_peer *src, *dst; 3989 struct pf_tree_node key; 3990 struct udphdr *uh = pd->hdr.udp; 3991 int dirndx; 3992 3993 key.af = pd->af; 3994 key.proto = IPPROTO_UDP; 3995 PF_ACPY(&key.addr[0], pd->src, key.af); 3996 PF_ACPY(&key.addr[1], pd->dst, key.af); 3997 key.port[0] = uh->uh_sport; 3998 key.port[1] = uh->uh_dport; 3999 4000 STATE_LOOKUP(); 4001 4002 if (direction == (*state)->direction) { 4003 src = &(*state)->src; 4004 dst = &(*state)->dst; 4005 dirndx = 0; 4006 } else { 4007 src = &(*state)->dst; 4008 dst = &(*state)->src; 4009 dirndx = 1; 4010 } 4011 4012 (*state)->packets[dirndx]++; 4013 (*state)->bytes[dirndx] += pd->tot_len; 4014 4015 /* update states */ 4016 if (src->state < PFUDPS_SINGLE) 4017 src->state = PFUDPS_SINGLE; 4018 if (dst->state == PFUDPS_SINGLE) 4019 dst->state = PFUDPS_MULTIPLE; 4020 4021 /* update expire time */ 4022#ifdef __FreeBSD__ 4023 (*state)->expire = time_second; 4024#else 4025 (*state)->expire = time.tv_sec; 4026#endif 4027 if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE) 4028 (*state)->timeout = PFTM_UDP_MULTIPLE; 4029 else 4030 (*state)->timeout = PFTM_UDP_SINGLE; 4031 4032 /* translate source/destination address, if necessary */ 4033 if (STATE_TRANSLATE(*state)) { 4034 if (direction == PF_OUT) 4035 pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum, 4036 &uh->uh_sum, &(*state)->gwy.addr, 4037 (*state)->gwy.port, 1, pd->af); 4038 else 4039 pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum, 4040 &uh->uh_sum, &(*state)->lan.addr, 4041 (*state)->lan.port, 1, pd->af); 4042 m_copyback(m, off, sizeof(*uh), (caddr_t)uh); 4043 } 4044 4045 (*state)->rule.ptr->packets++; 4046 (*state)->rule.ptr->bytes += pd->tot_len; 4047 if ((*state)->nat_rule.ptr != NULL) { 4048 (*state)->nat_rule.ptr->packets++; 4049 (*state)->nat_rule.ptr->bytes += pd->tot_len; 4050 } 4051 if ((*state)->anchor.ptr != NULL) { 4052 (*state)->anchor.ptr->packets++; 4053 (*state)->anchor.ptr->bytes += pd->tot_len; 4054 } 4055 return (PF_PASS); 4056} 4057 4058int 4059pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp, 4060 struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd) 4061{ 4062 struct pf_addr *saddr = pd->src, *daddr = pd->dst; 4063 u_int16_t icmpid, *icmpsum; 4064 u_int8_t icmptype; 4065 int state_icmp = 0, dirndx; 4066 4067 switch (pd->proto) { 4068#ifdef INET 4069 case IPPROTO_ICMP: 4070 icmptype = pd->hdr.icmp->icmp_type; 4071 icmpid = pd->hdr.icmp->icmp_id; 4072 icmpsum = &pd->hdr.icmp->icmp_cksum; 4073 4074 if (icmptype == ICMP_UNREACH || 4075 icmptype == ICMP_SOURCEQUENCH || 4076 icmptype == ICMP_REDIRECT || 4077 icmptype == ICMP_TIMXCEED || 4078 icmptype == ICMP_PARAMPROB) 4079 state_icmp++; 4080 break; 4081#endif /* INET */ 4082#ifdef INET6 4083 case IPPROTO_ICMPV6: 4084 icmptype = pd->hdr.icmp6->icmp6_type; 4085 icmpid = pd->hdr.icmp6->icmp6_id; 4086 icmpsum = &pd->hdr.icmp6->icmp6_cksum; 4087 4088 if (icmptype == ICMP6_DST_UNREACH || 4089 icmptype == ICMP6_PACKET_TOO_BIG || 4090 icmptype == ICMP6_TIME_EXCEEDED || 4091 icmptype == ICMP6_PARAM_PROB) 4092 state_icmp++; 4093 break; 4094#endif /* INET6 */ 4095 } 4096 4097 if (!state_icmp) { 4098 4099 /* 4100 * ICMP query/reply message not related to a TCP/UDP packet. 4101 * Search for an ICMP state. 4102 */ 4103 struct pf_tree_node key; 4104 4105 key.af = pd->af; 4106 key.proto = pd->proto; 4107 PF_ACPY(&key.addr[0], saddr, key.af); 4108 PF_ACPY(&key.addr[1], daddr, key.af); 4109 key.port[0] = icmpid; 4110 key.port[1] = icmpid; 4111 4112 STATE_LOOKUP(); 4113 4114 dirndx = (direction == (*state)->direction) ? 0 : 1; 4115 (*state)->packets[dirndx]++; 4116 (*state)->bytes[dirndx] += pd->tot_len; 4117#ifdef __FreeBSD__ 4118 (*state)->expire = time_second; 4119#else 4120 (*state)->expire = time.tv_sec; 4121#endif 4122 (*state)->timeout = PFTM_ICMP_ERROR_REPLY; 4123 4124 /* translate source/destination address, if necessary */ 4125 if (PF_ANEQ(&(*state)->lan.addr, &(*state)->gwy.addr, pd->af)) { 4126 if (direction == PF_OUT) { 4127 switch (pd->af) { 4128#ifdef INET 4129 case AF_INET: 4130 pf_change_a(&saddr->v4.s_addr, 4131 pd->ip_sum, 4132 (*state)->gwy.addr.v4.s_addr, 0); 4133 break; 4134#endif /* INET */ 4135#ifdef INET6 4136 case AF_INET6: 4137 pf_change_a6(saddr, 4138 &pd->hdr.icmp6->icmp6_cksum, 4139 &(*state)->gwy.addr, 0); 4140 m_copyback(m, off, 4141 sizeof(struct icmp6_hdr), 4142 (caddr_t)pd->hdr.icmp6); 4143 break; 4144#endif /* INET6 */ 4145 } 4146 } else { 4147 switch (pd->af) { 4148#ifdef INET 4149 case AF_INET: 4150 pf_change_a(&daddr->v4.s_addr, 4151 pd->ip_sum, 4152 (*state)->lan.addr.v4.s_addr, 0); 4153 break; 4154#endif /* INET */ 4155#ifdef INET6 4156 case AF_INET6: 4157 pf_change_a6(daddr, 4158 &pd->hdr.icmp6->icmp6_cksum, 4159 &(*state)->lan.addr, 0); 4160 m_copyback(m, off, 4161 sizeof(struct icmp6_hdr), 4162 (caddr_t)pd->hdr.icmp6); 4163 break; 4164#endif /* INET6 */ 4165 } 4166 } 4167 } 4168 4169 return (PF_PASS); 4170 4171 } else { 4172 /* 4173 * ICMP error message in response to a TCP/UDP packet. 4174 * Extract the inner TCP/UDP header and search for that state. 4175 */ 4176 4177 struct pf_pdesc pd2; 4178#ifdef INET 4179 struct ip h2; 4180#endif /* INET */ 4181#ifdef INET6 4182 struct ip6_hdr h2_6; 4183 int terminal = 0; 4184#endif /* INET6 */ 4185 int ipoff2; 4186 int off2; 4187 4188 pd2.af = pd->af; 4189 switch (pd->af) { 4190#ifdef INET 4191 case AF_INET: 4192 /* offset of h2 in mbuf chain */ 4193 ipoff2 = off + ICMP_MINLEN; 4194 4195 if (!pf_pull_hdr(m, ipoff2, &h2, sizeof(h2), 4196 NULL, NULL, pd2.af)) { 4197 DPFPRINTF(PF_DEBUG_MISC, 4198 ("pf: ICMP error message too short " 4199 "(ip)\n")); 4200 return (PF_DROP); 4201 } 4202 /* 4203 * ICMP error messages don't refer to non-first 4204 * fragments 4205 */ 4206 if (h2.ip_off & htons(IP_OFFMASK)) 4207 return (PF_DROP); 4208 4209 /* offset of protocol header that follows h2 */ 4210 off2 = ipoff2 + (h2.ip_hl << 2); 4211 4212 pd2.proto = h2.ip_p; 4213 pd2.src = (struct pf_addr *)&h2.ip_src; 4214 pd2.dst = (struct pf_addr *)&h2.ip_dst; 4215 pd2.ip_sum = &h2.ip_sum; 4216 break; 4217#endif /* INET */ 4218#ifdef INET6 4219 case AF_INET6: 4220 ipoff2 = off + sizeof(struct icmp6_hdr); 4221 4222 if (!pf_pull_hdr(m, ipoff2, &h2_6, sizeof(h2_6), 4223 NULL, NULL, pd2.af)) { 4224 DPFPRINTF(PF_DEBUG_MISC, 4225 ("pf: ICMP error message too short " 4226 "(ip6)\n")); 4227 return (PF_DROP); 4228 } 4229 pd2.proto = h2_6.ip6_nxt; 4230 pd2.src = (struct pf_addr *)&h2_6.ip6_src; 4231 pd2.dst = (struct pf_addr *)&h2_6.ip6_dst; 4232 pd2.ip_sum = NULL; 4233 off2 = ipoff2 + sizeof(h2_6); 4234 do { 4235 switch (pd2.proto) { 4236 case IPPROTO_FRAGMENT: 4237 /* 4238 * ICMPv6 error messages for 4239 * non-first fragments 4240 */ 4241 return (PF_DROP); 4242 case IPPROTO_AH: 4243 case IPPROTO_HOPOPTS: 4244 case IPPROTO_ROUTING: 4245 case IPPROTO_DSTOPTS: { 4246 /* get next header and header length */ 4247 struct ip6_ext opt6; 4248 4249 if (!pf_pull_hdr(m, off2, &opt6, 4250 sizeof(opt6), NULL, NULL, pd2.af)) { 4251 DPFPRINTF(PF_DEBUG_MISC, 4252 ("pf: ICMPv6 short opt\n")); 4253 return (PF_DROP); 4254 } 4255 if (pd2.proto == IPPROTO_AH) 4256 off2 += (opt6.ip6e_len + 2) * 4; 4257 else 4258 off2 += (opt6.ip6e_len + 1) * 8; 4259 pd2.proto = opt6.ip6e_nxt; 4260 /* goto the next header */ 4261 break; 4262 } 4263 default: 4264 terminal++; 4265 break; 4266 } 4267 } while (!terminal); 4268 break; 4269#endif /* INET6 */ 4270 } 4271 4272 switch (pd2.proto) { 4273 case IPPROTO_TCP: { 4274 struct tcphdr th; 4275 u_int32_t seq; 4276 struct pf_tree_node key; 4277 struct pf_state_peer *src, *dst; 4278 u_int8_t dws; 4279 4280 /* 4281 * Only the first 8 bytes of the TCP header can be 4282 * expected. Don't access any TCP header fields after 4283 * th_seq, an ackskew test is not possible. 4284 */ 4285 if (!pf_pull_hdr(m, off2, &th, 8, NULL, NULL, pd2.af)) { 4286 DPFPRINTF(PF_DEBUG_MISC, 4287 ("pf: ICMP error message too short " 4288 "(tcp)\n")); 4289 return (PF_DROP); 4290 } 4291 4292 key.af = pd2.af; 4293 key.proto = IPPROTO_TCP; 4294 PF_ACPY(&key.addr[0], pd2.dst, pd2.af); 4295 key.port[0] = th.th_dport; 4296 PF_ACPY(&key.addr[1], pd2.src, pd2.af); 4297 key.port[1] = th.th_sport; 4298 4299 STATE_LOOKUP(); 4300 4301 if (direction == (*state)->direction) { 4302 src = &(*state)->dst; 4303 dst = &(*state)->src; 4304 } else { 4305 src = &(*state)->src; 4306 dst = &(*state)->dst; 4307 } 4308 4309 if (src->wscale && dst->wscale && !(th.th_flags & TH_SYN)) 4310 dws = dst->wscale & PF_WSCALE_MASK; 4311 else 4312 dws = 0; 4313 4314 /* Demodulate sequence number */ 4315 seq = ntohl(th.th_seq) - src->seqdiff; 4316 if (src->seqdiff) 4317 pf_change_a(&th.th_seq, &th.th_sum, 4318 htonl(seq), 0); 4319 4320 if (!SEQ_GEQ(src->seqhi, seq) || 4321 !SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws))) { 4322 if (pf_status.debug >= PF_DEBUG_MISC) { 4323 printf("pf: BAD ICMP %d:%d ", 4324 icmptype, pd->hdr.icmp->icmp_code); 4325 pf_print_host(pd->src, 0, pd->af); 4326 printf(" -> "); 4327 pf_print_host(pd->dst, 0, pd->af); 4328 printf(" state: "); 4329 pf_print_state(*state); 4330 printf(" seq=%u\n", seq); 4331 } 4332 return (PF_DROP); 4333 } 4334 4335 if (STATE_TRANSLATE(*state)) { 4336 if (direction == PF_IN) { 4337 pf_change_icmp(pd2.src, &th.th_sport, 4338 saddr, &(*state)->lan.addr, 4339 (*state)->lan.port, NULL, 4340 pd2.ip_sum, icmpsum, 4341 pd->ip_sum, 0, pd2.af); 4342 } else { 4343 pf_change_icmp(pd2.dst, &th.th_dport, 4344 saddr, &(*state)->gwy.addr, 4345 (*state)->gwy.port, NULL, 4346 pd2.ip_sum, icmpsum, 4347 pd->ip_sum, 0, pd2.af); 4348 } 4349 switch (pd2.af) { 4350#ifdef INET 4351 case AF_INET: 4352 m_copyback(m, off, ICMP_MINLEN, 4353 (caddr_t)pd->hdr.icmp); 4354 m_copyback(m, ipoff2, sizeof(h2), 4355 (caddr_t)&h2); 4356 break; 4357#endif /* INET */ 4358#ifdef INET6 4359 case AF_INET6: 4360 m_copyback(m, off, 4361 sizeof(struct icmp6_hdr), 4362 (caddr_t)pd->hdr.icmp6); 4363 m_copyback(m, ipoff2, sizeof(h2_6), 4364 (caddr_t)&h2_6); 4365 break; 4366#endif /* INET6 */ 4367 } 4368 m_copyback(m, off2, 8, (caddr_t)&th); 4369 } else if (src->seqdiff) { 4370 m_copyback(m, off2, 8, (caddr_t)&th); 4371 } 4372 4373 return (PF_PASS); 4374 break; 4375 } 4376 case IPPROTO_UDP: { 4377 struct udphdr uh; 4378 struct pf_tree_node key; 4379 4380 if (!pf_pull_hdr(m, off2, &uh, sizeof(uh), 4381 NULL, NULL, pd2.af)) { 4382 DPFPRINTF(PF_DEBUG_MISC, 4383 ("pf: ICMP error message too short " 4384 "(udp)\n")); 4385 return (PF_DROP); 4386 } 4387 4388 key.af = pd2.af; 4389 key.proto = IPPROTO_UDP; 4390 PF_ACPY(&key.addr[0], pd2.dst, pd2.af); 4391 key.port[0] = uh.uh_dport; 4392 PF_ACPY(&key.addr[1], pd2.src, pd2.af); 4393 key.port[1] = uh.uh_sport; 4394 4395 STATE_LOOKUP(); 4396 4397 if (STATE_TRANSLATE(*state)) { 4398 if (direction == PF_IN) { 4399 pf_change_icmp(pd2.src, &uh.uh_sport, 4400 daddr, &(*state)->lan.addr, 4401 (*state)->lan.port, &uh.uh_sum, 4402 pd2.ip_sum, icmpsum, 4403 pd->ip_sum, 1, pd2.af); 4404 } else { 4405 pf_change_icmp(pd2.dst, &uh.uh_dport, 4406 saddr, &(*state)->gwy.addr, 4407 (*state)->gwy.port, &uh.uh_sum, 4408 pd2.ip_sum, icmpsum, 4409 pd->ip_sum, 1, pd2.af); 4410 } 4411 switch (pd2.af) { 4412#ifdef INET 4413 case AF_INET: 4414 m_copyback(m, off, ICMP_MINLEN, 4415 (caddr_t)pd->hdr.icmp); 4416 m_copyback(m, ipoff2, sizeof(h2), 4417 (caddr_t)&h2); 4418 break; 4419#endif /* INET */ 4420#ifdef INET6 4421 case AF_INET6: 4422 m_copyback(m, off, 4423 sizeof(struct icmp6_hdr), 4424 (caddr_t)pd->hdr.icmp6); 4425 m_copyback(m, ipoff2, sizeof(h2_6), 4426 (caddr_t)&h2_6); 4427 break; 4428#endif /* INET6 */ 4429 } 4430 m_copyback(m, off2, sizeof(uh), 4431 (caddr_t)&uh); 4432 } 4433 4434 return (PF_PASS); 4435 break; 4436 } 4437#ifdef INET 4438 case IPPROTO_ICMP: { 4439 struct icmp iih; 4440 struct pf_tree_node key; 4441 4442 if (!pf_pull_hdr(m, off2, &iih, ICMP_MINLEN, 4443 NULL, NULL, pd2.af)) { 4444 DPFPRINTF(PF_DEBUG_MISC, 4445 ("pf: ICMP error message too short i" 4446 "(icmp)\n")); 4447 return (PF_DROP); 4448 } 4449 4450 key.af = pd2.af; 4451 key.proto = IPPROTO_ICMP; 4452 PF_ACPY(&key.addr[0], pd2.dst, pd2.af); 4453 key.port[0] = iih.icmp_id; 4454 PF_ACPY(&key.addr[1], pd2.src, pd2.af); 4455 key.port[1] = iih.icmp_id; 4456 4457 STATE_LOOKUP(); 4458 4459 if (STATE_TRANSLATE(*state)) { 4460 if (direction == PF_IN) { 4461 pf_change_icmp(pd2.src, &iih.icmp_id, 4462 daddr, &(*state)->lan.addr, 4463 (*state)->lan.port, NULL, 4464 pd2.ip_sum, icmpsum, 4465 pd->ip_sum, 0, AF_INET); 4466 } else { 4467 pf_change_icmp(pd2.dst, &iih.icmp_id, 4468 saddr, &(*state)->gwy.addr, 4469 (*state)->gwy.port, NULL, 4470 pd2.ip_sum, icmpsum, 4471 pd->ip_sum, 0, AF_INET); 4472 } 4473 m_copyback(m, off, ICMP_MINLEN, 4474 (caddr_t)pd->hdr.icmp); 4475 m_copyback(m, ipoff2, sizeof(h2), 4476 (caddr_t)&h2); 4477 m_copyback(m, off2, ICMP_MINLEN, 4478 (caddr_t)&iih); 4479 } 4480 4481 return (PF_PASS); 4482 break; 4483 } 4484#endif /* INET */ 4485#ifdef INET6 4486 case IPPROTO_ICMPV6: { 4487 struct icmp6_hdr iih; 4488 struct pf_tree_node key; 4489 4490 if (!pf_pull_hdr(m, off2, &iih, 4491 sizeof(struct icmp6_hdr), NULL, NULL, pd2.af)) { 4492 DPFPRINTF(PF_DEBUG_MISC, 4493 ("pf: ICMP error message too short " 4494 "(icmp6)\n")); 4495 return (PF_DROP); 4496 } 4497 4498 key.af = pd2.af; 4499 key.proto = IPPROTO_ICMPV6; 4500 PF_ACPY(&key.addr[0], pd2.dst, pd2.af); 4501 key.port[0] = iih.icmp6_id; 4502 PF_ACPY(&key.addr[1], pd2.src, pd2.af); 4503 key.port[1] = iih.icmp6_id; 4504 4505 STATE_LOOKUP(); 4506 4507 if (STATE_TRANSLATE(*state)) { 4508 if (direction == PF_IN) { 4509 pf_change_icmp(pd2.src, &iih.icmp6_id, 4510 daddr, &(*state)->lan.addr, 4511 (*state)->lan.port, NULL, 4512 pd2.ip_sum, icmpsum, 4513 pd->ip_sum, 0, AF_INET6); 4514 } else { 4515 pf_change_icmp(pd2.dst, &iih.icmp6_id, 4516 saddr, &(*state)->gwy.addr, 4517 (*state)->gwy.port, NULL, 4518 pd2.ip_sum, icmpsum, 4519 pd->ip_sum, 0, AF_INET6); 4520 } 4521 m_copyback(m, off, sizeof(struct icmp6_hdr), 4522 (caddr_t)pd->hdr.icmp6); 4523 m_copyback(m, ipoff2, sizeof(h2_6), 4524 (caddr_t)&h2_6); 4525 m_copyback(m, off2, sizeof(struct icmp6_hdr), 4526 (caddr_t)&iih); 4527 } 4528 4529 return (PF_PASS); 4530 break; 4531 } 4532#endif /* INET6 */ 4533 default: { 4534 struct pf_tree_node key; 4535 4536 key.af = pd2.af; 4537 key.proto = pd2.proto; 4538 PF_ACPY(&key.addr[0], pd2.dst, pd2.af); 4539 key.port[0] = 0; 4540 PF_ACPY(&key.addr[1], pd2.src, pd2.af); 4541 key.port[1] = 0; 4542 4543 STATE_LOOKUP(); 4544 4545 if (STATE_TRANSLATE(*state)) { 4546 if (direction == PF_IN) { 4547 pf_change_icmp(pd2.src, NULL, 4548 daddr, &(*state)->lan.addr, 4549 0, NULL, 4550 pd2.ip_sum, icmpsum, 4551 pd->ip_sum, 0, pd2.af); 4552 } else { 4553 pf_change_icmp(pd2.dst, NULL, 4554 saddr, &(*state)->gwy.addr, 4555 0, NULL, 4556 pd2.ip_sum, icmpsum, 4557 pd->ip_sum, 0, pd2.af); 4558 } 4559 switch (pd2.af) { 4560#ifdef INET 4561 case AF_INET: 4562 m_copyback(m, off, ICMP_MINLEN, 4563 (caddr_t)pd->hdr.icmp); 4564 m_copyback(m, ipoff2, sizeof(h2), 4565 (caddr_t)&h2); 4566 break; 4567#endif /* INET */ 4568#ifdef INET6 4569 case AF_INET6: 4570 m_copyback(m, off, 4571 sizeof(struct icmp6_hdr), 4572 (caddr_t)pd->hdr.icmp6); 4573 m_copyback(m, ipoff2, sizeof(h2_6), 4574 (caddr_t)&h2_6); 4575 break; 4576#endif /* INET6 */ 4577 } 4578 } 4579 4580 return (PF_PASS); 4581 break; 4582 } 4583 } 4584 } 4585} 4586 4587int 4588pf_test_state_other(struct pf_state **state, int direction, struct ifnet *ifp, 4589 struct pf_pdesc *pd) 4590{ 4591 struct pf_state_peer *src, *dst; 4592 struct pf_tree_node key; 4593 int dirndx; 4594 4595 key.af = pd->af; 4596 key.proto = pd->proto; 4597 PF_ACPY(&key.addr[0], pd->src, key.af); 4598 PF_ACPY(&key.addr[1], pd->dst, key.af); 4599 key.port[0] = 0; 4600 key.port[1] = 0; 4601 4602 STATE_LOOKUP(); 4603 4604 if (direction == (*state)->direction) { 4605 src = &(*state)->src; 4606 dst = &(*state)->dst; 4607 dirndx = 0; 4608 } else { 4609 src = &(*state)->dst; 4610 dst = &(*state)->src; 4611 dirndx = 1; 4612 } 4613 4614 (*state)->packets[dirndx]++; 4615 (*state)->bytes[dirndx] += pd->tot_len; 4616 4617 /* update states */ 4618 if (src->state < PFOTHERS_SINGLE) 4619 src->state = PFOTHERS_SINGLE; 4620 if (dst->state == PFOTHERS_SINGLE) 4621 dst->state = PFOTHERS_MULTIPLE; 4622 4623 /* update expire time */ 4624#ifdef __FreeBSD__ 4625 (*state)->expire = time_second; 4626#else 4627 (*state)->expire = time.tv_sec; 4628#endif 4629 if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE) 4630 (*state)->timeout = PFTM_OTHER_MULTIPLE; 4631 else 4632 (*state)->timeout = PFTM_OTHER_SINGLE; 4633 4634 /* translate source/destination address, if necessary */ 4635 if (STATE_TRANSLATE(*state)) { 4636 if (direction == PF_OUT) 4637 switch (pd->af) { 4638#ifdef INET 4639 case AF_INET: 4640 pf_change_a(&pd->src->v4.s_addr, 4641 pd->ip_sum, (*state)->gwy.addr.v4.s_addr, 4642 0); 4643 break; 4644#endif /* INET */ 4645#ifdef INET6 4646 case AF_INET6: 4647 PF_ACPY(pd->src, &(*state)->gwy.addr, pd->af); 4648 break; 4649#endif /* INET6 */ 4650 } 4651 else 4652 switch (pd->af) { 4653#ifdef INET 4654 case AF_INET: 4655 pf_change_a(&pd->dst->v4.s_addr, 4656 pd->ip_sum, (*state)->lan.addr.v4.s_addr, 4657 0); 4658 break; 4659#endif /* INET */ 4660#ifdef INET6 4661 case AF_INET6: 4662 PF_ACPY(pd->dst, &(*state)->lan.addr, pd->af); 4663 break; 4664#endif /* INET6 */ 4665 } 4666 } 4667 4668 (*state)->rule.ptr->packets++; 4669 (*state)->rule.ptr->bytes += pd->tot_len; 4670 if ((*state)->nat_rule.ptr != NULL) { 4671 (*state)->nat_rule.ptr->packets++; 4672 (*state)->nat_rule.ptr->bytes += pd->tot_len; 4673 } 4674 if ((*state)->anchor.ptr != NULL) { 4675 (*state)->anchor.ptr->packets++; 4676 (*state)->anchor.ptr->bytes += pd->tot_len; 4677 } 4678 return (PF_PASS); 4679} 4680 4681/* 4682 * ipoff and off are measured from the start of the mbuf chain. 4683 * h must be at "ipoff" on the mbuf chain. 4684 */ 4685void * 4686pf_pull_hdr(struct mbuf *m, int off, void *p, int len, 4687 u_short *actionp, u_short *reasonp, sa_family_t af) 4688{ 4689 switch (af) { 4690#ifdef INET 4691 case AF_INET: { 4692 struct ip *h = mtod(m, struct ip *); 4693 u_int16_t fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3; 4694 4695 if (fragoff) { 4696 if (fragoff >= len) 4697 ACTION_SET(actionp, PF_PASS); 4698 else { 4699 ACTION_SET(actionp, PF_DROP); 4700 REASON_SET(reasonp, PFRES_FRAG); 4701 } 4702 return (NULL); 4703 } 4704 if (m->m_pkthdr.len < off + len || ntohs(h->ip_len) < off + len) { 4705 ACTION_SET(actionp, PF_DROP); 4706 REASON_SET(reasonp, PFRES_SHORT); 4707 return (NULL); 4708 } 4709 break; 4710 } 4711#endif /* INET */ 4712#ifdef INET6 4713 case AF_INET6: { 4714 struct ip6_hdr *h = mtod(m, struct ip6_hdr *); 4715 4716 if (m->m_pkthdr.len < off + len || 4717 (ntohs(h->ip6_plen) + sizeof(struct ip6_hdr)) < 4718 (unsigned)(off + len)) { 4719 ACTION_SET(actionp, PF_DROP); 4720 REASON_SET(reasonp, PFRES_SHORT); 4721 return (NULL); 4722 } 4723 break; 4724 } 4725#endif /* INET6 */ 4726 } 4727 m_copydata(m, off, len, p); 4728 return (p); 4729} 4730 4731int 4732pf_routable(struct pf_addr *addr, sa_family_t af) 4733{ 4734 struct sockaddr_in *dst; 4735 struct route ro; 4736 int ret = 0; 4737 4738 bzero(&ro, sizeof(ro)); 4739 dst = satosin(&ro.ro_dst); 4740 dst->sin_family = af; 4741 dst->sin_len = sizeof(*dst); 4742 dst->sin_addr = addr->v4; 4743#ifdef __FreeBSD__ 4744#ifdef RTF_PRCLONING 4745 rtalloc_ign(&ro, (RTF_CLONING|RTF_PRCLONING)); 4746#else /* !RTF_PRCLONING */ 4747 rtalloc_ign(&ro, RTF_CLONING); 4748#endif 4749#else /* ! __FreeBSD__ */ 4750 rtalloc_noclone(&ro, NO_CLONING); 4751#endif 4752 4753 if (ro.ro_rt != NULL) { 4754 ret = 1; 4755 RTFREE(ro.ro_rt); 4756 } 4757 4758 return (ret); 4759} 4760 4761#ifdef INET 4762 4763#if defined(__FreeBSD__) && (__FreeBSD_version < 501105) 4764int 4765ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, 4766 u_long if_hwassist_flags, int sw_csum) 4767{ 4768 int error = 0; 4769 int hlen = ip->ip_hl << 2; 4770 int len = (mtu - hlen) & ~7; /* size of payload in each fragment */ 4771 int off; 4772 struct mbuf *m0 = *m_frag; /* the original packet */ 4773 int firstlen; 4774 struct mbuf **mnext; 4775 int nfrags; 4776 4777 if (ip->ip_off & IP_DF) { /* Fragmentation not allowed */ 4778 ipstat.ips_cantfrag++; 4779 return EMSGSIZE; 4780 } 4781 4782 /* 4783 * Must be able to put at least 8 bytes per fragment. 4784 */ 4785 if (len < 8) 4786 return EMSGSIZE; 4787 4788 /* 4789 * If the interface will not calculate checksums on 4790 * fragmented packets, then do it here. 4791 */ 4792 if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA && 4793 (if_hwassist_flags & CSUM_IP_FRAGS) == 0) { 4794 in_delayed_cksum(m0); 4795 m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 4796 } 4797 4798 if (len > PAGE_SIZE) { 4799 /* 4800 * Fragment large datagrams such that each segment 4801 * contains a multiple of PAGE_SIZE amount of data, 4802 * plus headers. This enables a receiver to perform 4803 * page-flipping zero-copy optimizations. 4804 * 4805 * XXX When does this help given that sender and receiver 4806 * could have different page sizes, and also mtu could 4807 * be less than the receiver's page size ? 4808 */ 4809 int newlen; 4810 struct mbuf *m; 4811 4812 for (m = m0, off = 0; m && (off+m->m_len) <= mtu; m = m->m_next) 4813 off += m->m_len; 4814 4815 /* 4816 * firstlen (off - hlen) must be aligned on an 4817 * 8-byte boundary 4818 */ 4819 if (off < hlen) 4820 goto smart_frag_failure; 4821 off = ((off - hlen) & ~7) + hlen; 4822 newlen = (~PAGE_MASK) & mtu; 4823 if ((newlen + sizeof (struct ip)) > mtu) { 4824 /* we failed, go back the default */ 4825smart_frag_failure: 4826 newlen = len; 4827 off = hlen + len; 4828 } 4829 len = newlen; 4830 4831 } else { 4832 off = hlen + len; 4833 } 4834 4835 firstlen = off - hlen; 4836 mnext = &m0->m_nextpkt; /* pointer to next packet */ 4837 4838 /* 4839 * Loop through length of segment after first fragment, 4840 * make new header and copy data of each part and link onto chain. 4841 * Here, m0 is the original packet, m is the fragment being created. 4842 * The fragments are linked off the m_nextpkt of the original 4843 * packet, which after processing serves as the first fragment. 4844 */ 4845 for (nfrags = 1; off < ip->ip_len; off += len, nfrags++) { 4846 struct ip *mhip; /* ip header on the fragment */ 4847 struct mbuf *m; 4848 int mhlen = sizeof (struct ip); 4849 4850 MGETHDR(m, M_DONTWAIT, MT_HEADER); 4851 if (m == 0) { 4852 error = ENOBUFS; 4853 ipstat.ips_odropped++; 4854 goto done; 4855 } 4856 m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG; 4857 /* 4858 * In the first mbuf, leave room for the link header, then 4859 * copy the original IP header including options. The payload 4860 * goes into an additional mbuf chain returned by m_copy(). 4861 */ 4862 m->m_data += max_linkhdr; 4863 mhip = mtod(m, struct ip *); 4864 *mhip = *ip; 4865 if (hlen > sizeof (struct ip)) { 4866 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 4867 mhip->ip_v = IPVERSION; 4868 mhip->ip_hl = mhlen >> 2; 4869 } 4870 m->m_len = mhlen; 4871 /* XXX do we need to add ip->ip_off below ? */ 4872 mhip->ip_off = ((off - hlen) >> 3) + ip->ip_off; 4873 if (off + len >= ip->ip_len) { /* last fragment */ 4874 len = ip->ip_len - off; 4875 m->m_flags |= M_LASTFRAG; 4876 } else 4877 mhip->ip_off |= IP_MF; 4878 mhip->ip_len = htons((u_short)(len + mhlen)); 4879 m->m_next = m_copy(m0, off, len); 4880 if (m->m_next == 0) { /* copy failed */ 4881 m_free(m); 4882 error = ENOBUFS; /* ??? */ 4883 ipstat.ips_odropped++; 4884 goto done; 4885 } 4886 m->m_pkthdr.len = mhlen + len; 4887 m->m_pkthdr.rcvif = (struct ifnet *)0; 4888#ifdef MAC 4889 mac_create_fragment(m0, m); 4890#endif 4891 m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags; 4892 mhip->ip_off = htons(mhip->ip_off); 4893 mhip->ip_sum = 0; 4894 if (sw_csum & CSUM_DELAY_IP) 4895 mhip->ip_sum = in_cksum(m, mhlen); 4896 *mnext = m; 4897 mnext = &m->m_nextpkt; 4898 } 4899 ipstat.ips_ofragments += nfrags; 4900 4901 /* set first marker for fragment chain */ 4902 m0->m_flags |= M_FIRSTFRAG | M_FRAG; 4903 m0->m_pkthdr.csum_data = nfrags; 4904 4905 /* 4906 * Update first fragment by trimming what's been copied out 4907 * and updating header. 4908 */ 4909 m_adj(m0, hlen + firstlen - ip->ip_len); 4910 m0->m_pkthdr.len = hlen + firstlen; 4911 ip->ip_len = htons((u_short)m0->m_pkthdr.len); 4912 ip->ip_off |= IP_MF; 4913 ip->ip_off = htons(ip->ip_off); 4914 ip->ip_sum = 0; 4915 if (sw_csum & CSUM_DELAY_IP) 4916 ip->ip_sum = in_cksum(m0, hlen); 4917 4918done: 4919 *m_frag = m0; 4920 return error; 4921} 4922#endif /* __FreeBSD__ && __FreeBSD_version > 501105 */ 4923 4924void 4925pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, 4926 struct pf_state *s) 4927{ 4928 struct mbuf *m0, *m1; 4929 struct route iproute; 4930 struct route *ro; 4931 struct sockaddr_in *dst; 4932 struct ip *ip; 4933 struct ifnet *ifp = NULL; 4934 struct m_tag *mtag; 4935 struct pf_addr naddr; 4936 int error = 0; 4937#ifdef __FreeBSD__ 4938 int sw_csum; 4939#endif 4940 4941 if (m == NULL || *m == NULL || r == NULL || 4942 (dir != PF_IN && dir != PF_OUT) || oifp == NULL) 4943 panic("pf_route: invalid parameters"); 4944 4945 if (r->rt == PF_DUPTO) { 4946 m0 = *m; 4947 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL); 4948 if (mtag == NULL) { 4949 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT); 4950 if (mtag == NULL) 4951 goto bad; 4952 m_tag_prepend(m0, mtag); 4953 } 4954#ifdef __FreeBSD__ 4955 m0 = m_dup(*m, M_DONTWAIT); 4956#else 4957 m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT); 4958#endif 4959 if (m0 == NULL) 4960 return; 4961 } else { 4962 if ((r->rt == PF_REPLYTO) == (r->direction == dir)) 4963 return; 4964 m0 = *m; 4965 } 4966 4967 if (m0->m_len < sizeof(struct ip)) 4968 panic("pf_route: m0->m_len < sizeof(struct ip)"); 4969 ip = mtod(m0, struct ip *); 4970 4971 ro = &iproute; 4972 bzero((caddr_t)ro, sizeof(*ro)); 4973 dst = satosin(&ro->ro_dst); 4974 dst->sin_family = AF_INET; 4975 dst->sin_len = sizeof(*dst); 4976 dst->sin_addr = ip->ip_dst; 4977 4978 if (r->rt == PF_FASTROUTE) { 4979 rtalloc(ro); 4980 if (ro->ro_rt == 0) { 4981 ipstat.ips_noroute++; 4982 goto bad; 4983 } 4984 4985 ifp = ro->ro_rt->rt_ifp; 4986 ro->ro_rt->rt_use++; 4987 4988 if (ro->ro_rt->rt_flags & RTF_GATEWAY) 4989 dst = satosin(ro->ro_rt->rt_gateway); 4990 } else { 4991 if (TAILQ_EMPTY(&r->rpool.list)) 4992 panic("pf_route: TAILQ_EMPTY(&r->rpool.list)"); 4993 if (s == NULL) { 4994 pf_map_addr(AF_INET, &r->rpool, 4995 (struct pf_addr *)&ip->ip_src, 4996 &naddr, NULL); 4997 if (!PF_AZERO(&naddr, AF_INET)) 4998 dst->sin_addr.s_addr = naddr.v4.s_addr; 4999 ifp = r->rpool.cur->ifp; 5000 } else { 5001 if (!PF_AZERO(&s->rt_addr, AF_INET)) 5002 dst->sin_addr.s_addr = 5003 s->rt_addr.v4.s_addr; 5004 ifp = s->rt_ifp; 5005 } 5006 } 5007 5008 if (ifp == NULL) 5009 goto bad; 5010 5011 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL); 5012 if (mtag == NULL) { 5013 struct m_tag *mtag; 5014 5015 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT); 5016 if (mtag == NULL) 5017 goto bad; 5018 m_tag_prepend(m0, mtag); 5019 } 5020 5021 if (oifp != ifp && mtag == NULL) { 5022#ifdef __FreeBSD__ 5023 PF_UNLOCK(); 5024 if (pf_test(PF_OUT, ifp, &m0) != PF_PASS) { 5025 PF_LOCK(); 5026 goto bad; 5027 } else if (m0 == NULL) { 5028 PF_LOCK(); 5029 goto done; 5030 } 5031 PF_LOCK(); 5032#else 5033 if (pf_test(PF_OUT, ifp, &m0) != PF_PASS) 5034 goto bad; 5035 else if (m0 == NULL) 5036 goto done; 5037#endif 5038 if (m0->m_len < sizeof(struct ip)) 5039 panic("pf_route: m0->m_len < sizeof(struct ip)"); 5040 ip = mtod(m0, struct ip *); 5041 } 5042 5043#ifdef __FreeBSD__ 5044 /* Copied from FreeBSD 5.1-CURRENT ip_output. */ 5045 m0->m_pkthdr.csum_flags |= CSUM_IP; 5046 sw_csum = m0->m_pkthdr.csum_flags & ~ifp->if_hwassist; 5047 if (sw_csum & CSUM_DELAY_DATA) { 5048 /* 5049 * XXX: in_delayed_cksum assumes HBO for ip->ip_len (at least) 5050 */ 5051 NTOHS(ip->ip_len); 5052 NTOHS(ip->ip_off); /* XXX: needed? */ 5053 in_delayed_cksum(m0); 5054 HTONS(ip->ip_len); 5055 HTONS(ip->ip_off); 5056 sw_csum &= ~CSUM_DELAY_DATA; 5057 } 5058 m0->m_pkthdr.csum_flags &= ifp->if_hwassist; 5059 5060 if (ntohs(ip->ip_len) <= ifp->if_mtu || 5061 (ifp->if_hwassist & CSUM_FRAGMENT && 5062 ((ip->ip_off & htons(IP_DF)) == 0))) { 5063 /* 5064 * ip->ip_len = htons(ip->ip_len); 5065 * ip->ip_off = htons(ip->ip_off); 5066 */ 5067 ip->ip_sum = 0; 5068 if (sw_csum & CSUM_DELAY_IP) { 5069 /* From KAME */ 5070 if (ip->ip_v == IPVERSION && 5071 (ip->ip_hl << 2) == sizeof(*ip)) { 5072 ip->ip_sum = in_cksum_hdr(ip); 5073 } else { 5074 ip->ip_sum = in_cksum(m0, ip->ip_hl << 2); 5075 } 5076 } 5077 PF_UNLOCK(); 5078 error = (*ifp->if_output)(ifp, m0, sintosa(dst), ro->ro_rt); 5079 PF_LOCK(); 5080 goto done; 5081 } 5082 5083#else 5084 /* Copied from ip_output. */ 5085 if (ntohs(ip->ip_len) <= ifp->if_mtu) { 5086 if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) && 5087 ifp->if_bridge == NULL) { 5088 m0->m_pkthdr.csum |= M_IPV4_CSUM_OUT; 5089 ipstat.ips_outhwcsum++; 5090 } else { 5091 ip->ip_sum = 0; 5092 ip->ip_sum = in_cksum(m0, ip->ip_hl << 2); 5093 } 5094 /* Update relevant hardware checksum stats for TCP/UDP */ 5095 if (m0->m_pkthdr.csum & M_TCPV4_CSUM_OUT) 5096 tcpstat.tcps_outhwcsum++; 5097 else if (m0->m_pkthdr.csum & M_UDPV4_CSUM_OUT) 5098 udpstat.udps_outhwcsum++; 5099 error = (*ifp->if_output)(ifp, m0, sintosa(dst), NULL); 5100 goto done; 5101 } 5102#endif 5103 /* 5104 * Too large for interface; fragment if possible. 5105 * Must be able to put at least 8 bytes per fragment. 5106 */ 5107 if (ip->ip_off & htons(IP_DF)) { 5108 ipstat.ips_cantfrag++; 5109 if (r->rt != PF_DUPTO) { 5110#ifdef __FreeBSD__ 5111 /* icmp_error() expects host byte ordering */ 5112 NTOHS(ip->ip_len); 5113 NTOHS(ip->ip_off); 5114 PF_UNLOCK(); 5115#endif 5116 icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0, 5117 ifp); 5118#ifdef __FreeBSD__ 5119 PF_LOCK(); 5120#endif 5121 goto done; 5122 } else 5123 goto bad; 5124 } 5125 5126 m1 = m0; 5127#ifdef __FreeBSD__ 5128 /* 5129 * XXX: is cheaper + less error prone than own function 5130 */ 5131 NTOHS(ip->ip_len); 5132 NTOHS(ip->ip_off); 5133 error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist, sw_csum); 5134#else 5135 error = ip_fragment(m0, ifp, ifp->if_mtu); 5136#endif 5137#ifdef __FreeBSD__ 5138 if (error) 5139#else 5140 if (error == EMSGSIZE) 5141#endif 5142 goto bad; 5143 5144 for (m0 = m1; m0; m0 = m1) { 5145 m1 = m0->m_nextpkt; 5146 m0->m_nextpkt = 0; 5147#ifdef __FreeBSD__ 5148 if (error == 0) { 5149 PF_UNLOCK(); 5150 error = (*ifp->if_output)(ifp, m0, sintosa(dst), 5151 NULL); 5152 PF_LOCK(); 5153 } else 5154#else 5155 if (error == 0) 5156 error = (*ifp->if_output)(ifp, m0, sintosa(dst), 5157 NULL); 5158 else 5159#endif 5160 m_freem(m0); 5161 } 5162 5163 if (error == 0) 5164 ipstat.ips_fragmented++; 5165 5166done: 5167 if (r->rt != PF_DUPTO) 5168 *m = NULL; 5169 if (ro == &iproute && ro->ro_rt) 5170 RTFREE(ro->ro_rt); 5171 return; 5172 5173bad: 5174 m_freem(m0); 5175 goto done; 5176} 5177#endif /* INET */ 5178 5179#ifdef INET6 5180void 5181pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, 5182 struct pf_state *s) 5183{ 5184 struct mbuf *m0; 5185 struct m_tag *mtag; 5186 struct route_in6 ip6route; 5187 struct route_in6 *ro; 5188 struct sockaddr_in6 *dst; 5189 struct ip6_hdr *ip6; 5190 struct ifnet *ifp = NULL; 5191 struct pf_addr naddr; 5192 int error = 0; 5193 5194 if (m == NULL || *m == NULL || r == NULL || 5195 (dir != PF_IN && dir != PF_OUT) || oifp == NULL) 5196 panic("pf_route6: invalid parameters"); 5197 5198 if (r->rt == PF_DUPTO) { 5199 m0 = *m; 5200 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL); 5201 if (mtag == NULL) { 5202 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT); 5203 if (mtag == NULL) 5204 goto bad; 5205 m_tag_prepend(m0, mtag); 5206 } 5207#ifdef __FreeBSD__ 5208 m0 = m_dup(*m, M_DONTWAIT); 5209#else 5210 m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT); 5211#endif 5212 if (m0 == NULL) 5213 return; 5214 } else { 5215 if ((r->rt == PF_REPLYTO) == (r->direction == dir)) 5216 return; 5217 m0 = *m; 5218 } 5219 5220 if (m0->m_len < sizeof(struct ip6_hdr)) 5221 panic("pf_route6: m0->m_len < sizeof(struct ip6_hdr)"); 5222 ip6 = mtod(m0, struct ip6_hdr *); 5223 5224 ro = &ip6route; 5225 bzero((caddr_t)ro, sizeof(*ro)); 5226 dst = (struct sockaddr_in6 *)&ro->ro_dst; 5227 dst->sin6_family = AF_INET6; 5228 dst->sin6_len = sizeof(*dst); 5229 dst->sin6_addr = ip6->ip6_dst; 5230 5231 /* Cheat. */ 5232 if (r->rt == PF_FASTROUTE) { 5233 mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT); 5234 if (mtag == NULL) 5235 goto bad; 5236 m_tag_prepend(m0, mtag); 5237#ifdef __FreeBSD__ 5238 PF_UNLOCK(); 5239 ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL); 5240 PF_LOCK(); 5241#else 5242 ip6_output(m0, NULL, NULL, 0, NULL, NULL); 5243#endif 5244 return; 5245 } 5246 5247 if (TAILQ_EMPTY(&r->rpool.list)) 5248 panic("pf_route6: TAILQ_EMPTY(&r->rpool.list)"); 5249 if (s == NULL) { 5250 pf_map_addr(AF_INET6, &r->rpool, 5251 (struct pf_addr *)&ip6->ip6_src, &naddr, NULL); 5252 if (!PF_AZERO(&naddr, AF_INET6)) 5253 PF_ACPY((struct pf_addr *)&dst->sin6_addr, 5254 &naddr, AF_INET6); 5255 ifp = r->rpool.cur->ifp; 5256 } else { 5257 if (!PF_AZERO(&s->rt_addr, AF_INET6)) 5258 PF_ACPY((struct pf_addr *)&dst->sin6_addr, 5259 &s->rt_addr, AF_INET6); 5260 ifp = s->rt_ifp; 5261 } 5262 5263 if (ifp == NULL) 5264 goto bad; 5265 5266 if (oifp != ifp) { 5267 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL); 5268 if (mtag == NULL) { 5269 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT); 5270 if (mtag == NULL) 5271 goto bad; 5272 m_tag_prepend(m0, mtag); 5273#ifdef __FreeBSD__ 5274 PF_UNLOCK(); 5275 if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) { 5276 PF_LOCK(); 5277 goto bad; 5278 } else if (m0 == NULL) { 5279 PF_LOCK(); 5280 goto done; 5281 } 5282 PF_LOCK(); 5283#else 5284 if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) 5285 goto bad; 5286 else if (m0 == NULL) 5287 goto done; 5288#endif 5289 } 5290 } 5291 5292 /* 5293 * If the packet is too large for the outgoing interface, 5294 * send back an icmp6 error. 5295 */ 5296 if (IN6_IS_ADDR_LINKLOCAL(&dst->sin6_addr)) 5297 dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index); 5298 if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) { 5299#ifdef __FreeBSD__ 5300 PF_UNLOCK(); 5301#endif 5302 error = nd6_output(ifp, ifp, m0, dst, NULL); 5303#ifdef __FreeBSD__ 5304 PF_LOCK(); 5305#endif 5306 } else { 5307 in6_ifstat_inc(ifp, ifs6_in_toobig); 5308#ifdef __FreeBSD__ 5309 if (r->rt != PF_DUPTO) { 5310 PF_UNLOCK(); 5311 icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu); 5312 PF_LOCK(); 5313 } else 5314#else 5315 if (r->rt != PF_DUPTO) 5316 icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu); 5317 else 5318#endif 5319 goto bad; 5320 } 5321 5322done: 5323 if (r->rt != PF_DUPTO) 5324 *m = NULL; 5325 return; 5326 5327bad: 5328 m_freem(m0); 5329 goto done; 5330} 5331#endif /* INET6 */ 5332 5333 5334#ifdef __FreeBSD__ 5335/* 5336 * XXX 5337 * FreeBSD supports cksum offload for the following drivers. 5338 * em(4), gx(4), lge(4), nge(4), ti(4), xl(4) 5339 * If we can make full use of it we would outperform ipfw/ipfilter in 5340 * very heavy traffic. 5341 * I have not tested 'cause I don't have NICs that supports cksum offload. 5342 * (There might be problems. Typical phenomena would be 5343 * 1. No route message for UDP packet. 5344 * 2. No connection acceptance from external hosts regardless of rule set.) 5345 */ 5346int 5347pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af) 5348{ 5349 u_int16_t sum = 0; 5350 int hw_assist = 0; 5351 struct ip *ip; 5352 5353 if (off < sizeof(struct ip) || len < sizeof(struct udphdr)) 5354 return (1); 5355 if (m->m_pkthdr.len < off + len) 5356 return (1); 5357 5358 switch (p) { 5359 case IPPROTO_TCP: 5360 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { 5361 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) { 5362 sum = m->m_pkthdr.csum_data; 5363 } else { 5364 ip = mtod(m, struct ip *); 5365 sum = in_pseudo(ip->ip_src.s_addr, 5366 ip->ip_dst.s_addr, 5367 htonl(m->m_pkthdr.csum_data + 5368 IPPROTO_TCP) + ip->ip_len); 5369 } 5370 sum ^= 0xffff; 5371 ++hw_assist; 5372 } 5373 break; 5374 case IPPROTO_UDP: 5375 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { 5376 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) { 5377 sum = m->m_pkthdr.csum_data; 5378 } else { 5379 ip = mtod(m, struct ip *); 5380 sum = in_pseudo(ip->ip_src.s_addr, 5381 ip->ip_dst.s_addr, htonl((u_short)len + 5382 m->m_pkthdr.csum_data + IPPROTO_UDP)); 5383 } 5384 sum ^= 0xffff; 5385 ++hw_assist; 5386 } 5387 break; 5388 case IPPROTO_ICMP: 5389#ifdef INET6 5390 case IPPROTO_ICMPV6: 5391#endif /* INET6 */ 5392 break; 5393 default: 5394 return (1); 5395 } 5396 5397 if (!hw_assist) { 5398 switch (af) { 5399 case AF_INET: 5400 if (p == IPPROTO_ICMP) { 5401 if (m->m_len < off) 5402 return (1); 5403 m->m_data += off; 5404 m->m_len -= off; 5405 sum = in_cksum(m, len); 5406 m->m_data -= off; 5407 m->m_len += off; 5408 } else { 5409 if (m->m_len < sizeof(struct ip)) 5410 return (1); 5411 sum = in4_cksum(m, p, off, len); 5412 if (sum == 0) { 5413 m->m_pkthdr.csum_flags |= 5414 (CSUM_DATA_VALID | 5415 CSUM_PSEUDO_HDR); 5416 m->m_pkthdr.csum_data = 0xffff; 5417 } 5418 } 5419 break; 5420#ifdef INET6 5421 case AF_INET6: 5422 if (m->m_len < sizeof(struct ip6_hdr)) 5423 return (1); 5424 sum = in6_cksum(m, p, off, len); 5425 /* 5426 * XXX 5427 * IPv6 H/W cksum off-load not supported yet! 5428 * 5429 * if (sum == 0) { 5430 * m->m_pkthdr.csum_flags |= 5431 * (CSUM_DATA_VALID|CSUM_PSEUDO_HDR); 5432 * m->m_pkthdr.csum_data = 0xffff; 5433 *} 5434 */ 5435 break; 5436#endif /* INET6 */ 5437 default: 5438 return (1); 5439 } 5440 } 5441 if (sum) { 5442 switch (p) { 5443 case IPPROTO_TCP: 5444 tcpstat.tcps_rcvbadsum++; 5445 break; 5446 case IPPROTO_UDP: 5447 udpstat.udps_badsum++; 5448 break; 5449 case IPPROTO_ICMP: 5450 icmpstat.icps_checksum++; 5451 break; 5452#ifdef INET6 5453 case IPPROTO_ICMPV6: 5454 icmp6stat.icp6s_checksum++; 5455 break; 5456#endif /* INET6 */ 5457 } 5458 return (1); 5459 } 5460 return (0); 5461} 5462#else 5463/* 5464 * check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag 5465 * off is the offset where the protocol header starts 5466 * len is the total length of protocol header plus payload 5467 * returns 0 when the checksum is valid, otherwise returns 1. 5468 */ 5469int 5470pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af) 5471{ 5472 u_int16_t flag_ok, flag_bad; 5473 u_int16_t sum; 5474 5475 switch (p) { 5476 case IPPROTO_TCP: 5477 flag_ok = M_TCP_CSUM_IN_OK; 5478 flag_bad = M_TCP_CSUM_IN_BAD; 5479 break; 5480 case IPPROTO_UDP: 5481 flag_ok = M_UDP_CSUM_IN_OK; 5482 flag_bad = M_UDP_CSUM_IN_BAD; 5483 break; 5484 case IPPROTO_ICMP: 5485#ifdef INET6 5486 case IPPROTO_ICMPV6: 5487#endif /* INET6 */ 5488 flag_ok = flag_bad = 0; 5489 break; 5490 default: 5491 return (1); 5492 } 5493 if (m->m_pkthdr.csum & flag_ok) 5494 return (0); 5495 if (m->m_pkthdr.csum & flag_bad) 5496 return (1); 5497 if (off < sizeof(struct ip) || len < sizeof(struct udphdr)) 5498 return (1); 5499 if (m->m_pkthdr.len < off + len) 5500 return (1); 5501 switch (af) { 5502 case AF_INET: 5503 if (p == IPPROTO_ICMP) { 5504 if (m->m_len < off) 5505 return (1); 5506 m->m_data += off; 5507 m->m_len -= off; 5508 sum = in_cksum(m, len); 5509 m->m_data -= off; 5510 m->m_len += off; 5511 } else { 5512 if (m->m_len < sizeof(struct ip)) 5513 return (1); 5514 sum = in4_cksum(m, p, off, len); 5515 } 5516 break; 5517#ifdef INET6 5518 case AF_INET6: 5519 if (m->m_len < sizeof(struct ip6_hdr)) 5520 return (1); 5521 sum = in6_cksum(m, p, off, len); 5522 break; 5523#endif /* INET6 */ 5524 default: 5525 return (1); 5526 } 5527 if (sum) { 5528 m->m_pkthdr.csum |= flag_bad; 5529 switch (p) { 5530 case IPPROTO_TCP: 5531 tcpstat.tcps_rcvbadsum++; 5532 break; 5533 case IPPROTO_UDP: 5534 udpstat.udps_badsum++; 5535 break; 5536 case IPPROTO_ICMP: 5537 icmpstat.icps_checksum++; 5538 break; 5539#ifdef INET6 5540 case IPPROTO_ICMPV6: 5541 icmp6stat.icp6s_checksum++; 5542 break; 5543#endif /* INET6 */ 5544 } 5545 return (1); 5546 } 5547 m->m_pkthdr.csum |= flag_ok; 5548 return (0); 5549} 5550#endif 5551 5552#ifdef INET 5553int 5554pf_test(int dir, struct ifnet *ifp, struct mbuf **m0) 5555{ 5556 u_short action, reason = 0, log = 0; 5557 struct mbuf *m = *m0; 5558 struct ip *h; 5559 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr; 5560 struct pf_state *s = NULL; 5561 struct pf_ruleset *ruleset = NULL; 5562 struct pf_pdesc pd; 5563 int off; 5564 int pqid = 0; 5565 5566#ifdef __FreeBSD__ 5567 PF_LOCK(); 5568#endif 5569 if (!pf_status.running || 5570 (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) { 5571#ifdef __FreeBSD__ 5572 PF_UNLOCK(); 5573#endif 5574 return (PF_PASS); 5575 } 5576 5577#if defined(__FreeBSD__) && (__FreeBSD_version >= 501000) 5578 M_ASSERTPKTHDR(m); 5579#else 5580#ifdef DIAGNOSTIC 5581 if ((m->m_flags & M_PKTHDR) == 0) 5582 panic("non-M_PKTHDR is passed to pf_test"); 5583#endif 5584#endif 5585 5586 if (m->m_pkthdr.len < (int)sizeof(*h)) { 5587 action = PF_DROP; 5588 REASON_SET(&reason, PFRES_SHORT); 5589 log = 1; 5590 goto done; 5591 } 5592 5593 /* We do IP header normalization and packet reassembly here */ 5594 if (pf_normalize_ip(m0, dir, ifp, &reason) != PF_PASS) { 5595 action = PF_DROP; 5596 goto done; 5597 } 5598 m = *m0; 5599 h = mtod(m, struct ip *); 5600 5601 off = h->ip_hl << 2; 5602 if (off < (int)sizeof(*h)) { 5603 action = PF_DROP; 5604 REASON_SET(&reason, PFRES_SHORT); 5605 log = 1; 5606 goto done; 5607 } 5608 5609 memset(&pd, 0, sizeof(pd)); 5610 pd.src = (struct pf_addr *)&h->ip_src; 5611 pd.dst = (struct pf_addr *)&h->ip_dst; 5612 pd.ip_sum = &h->ip_sum; 5613 pd.proto = h->ip_p; 5614 pd.af = AF_INET; 5615 pd.tos = h->ip_tos; 5616 pd.tot_len = ntohs(h->ip_len); 5617 5618 /* handle fragments that didn't get reassembled by normalization */ 5619 if (h->ip_off & htons(IP_MF | IP_OFFMASK)) { 5620 action = pf_test_fragment(&r, dir, ifp, m, h, 5621 &pd, &a, &ruleset); 5622 goto done; 5623 } 5624 5625 switch (h->ip_p) { 5626 5627 case IPPROTO_TCP: { 5628 struct tcphdr th; 5629 5630 pd.hdr.tcp = &th; 5631 if (!pf_pull_hdr(m, off, &th, sizeof(th), 5632 &action, &reason, AF_INET)) { 5633 log = action != PF_PASS; 5634 goto done; 5635 } 5636 if (dir == PF_IN && pf_check_proto_cksum(m, off, 5637 ntohs(h->ip_len) - off, IPPROTO_TCP, AF_INET)) { 5638 action = PF_DROP; 5639 goto done; 5640 } 5641 pd.p_len = pd.tot_len - off - (th.th_off << 2); 5642 if ((th.th_flags & TH_ACK) && pd.p_len == 0) 5643 pqid = 1; 5644 action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd); 5645 if (action == PF_DROP) 5646 break; 5647 action = pf_test_state_tcp(&s, dir, ifp, m, 0, off, h, &pd, 5648 &reason); 5649 if (action == PF_PASS) { 5650 r = s->rule.ptr; 5651 log = s->log; 5652 } else if (s == NULL) 5653 action = pf_test_tcp(&r, &s, dir, ifp, 5654 m, 0, off, h, &pd, &a, &ruleset); 5655 break; 5656 } 5657 5658 case IPPROTO_UDP: { 5659 struct udphdr uh; 5660 5661 pd.hdr.udp = &uh; 5662 if (!pf_pull_hdr(m, off, &uh, sizeof(uh), 5663 &action, &reason, AF_INET)) { 5664 log = action != PF_PASS; 5665 goto done; 5666 } 5667 if (dir == PF_IN && uh.uh_sum && pf_check_proto_cksum(m, 5668 off, ntohs(h->ip_len) - off, IPPROTO_UDP, AF_INET)) { 5669 action = PF_DROP; 5670 goto done; 5671 } 5672 action = pf_test_state_udp(&s, dir, ifp, m, 0, off, h, &pd); 5673 if (action == PF_PASS) { 5674 r = s->rule.ptr; 5675 a = s->anchor.ptr; 5676 log = s->log; 5677 } else if (s == NULL) 5678 action = pf_test_udp(&r, &s, dir, ifp, 5679 m, 0, off, h, &pd, &a, &ruleset); 5680 break; 5681 } 5682 5683 case IPPROTO_ICMP: { 5684 struct icmp ih; 5685 5686 pd.hdr.icmp = &ih; 5687 if (!pf_pull_hdr(m, off, &ih, ICMP_MINLEN, 5688 &action, &reason, AF_INET)) { 5689 log = action != PF_PASS; 5690 goto done; 5691 } 5692 if (dir == PF_IN && pf_check_proto_cksum(m, off, 5693 ntohs(h->ip_len) - off, IPPROTO_ICMP, AF_INET)) { 5694 action = PF_DROP; 5695 goto done; 5696 } 5697 action = pf_test_state_icmp(&s, dir, ifp, m, 0, off, h, &pd); 5698 if (action == PF_PASS) { 5699 r = s->rule.ptr; 5700 r->packets++; 5701 r->bytes += ntohs(h->ip_len); 5702 a = s->anchor.ptr; 5703 if (a != NULL) { 5704 a->packets++; 5705 a->bytes += ntohs(h->ip_len); 5706 } 5707 log = s->log; 5708 } else if (s == NULL) 5709 action = pf_test_icmp(&r, &s, dir, ifp, 5710 m, 0, off, h, &pd, &a, &ruleset); 5711 break; 5712 } 5713 5714 default: 5715 action = pf_test_state_other(&s, dir, ifp, &pd); 5716 if (action == PF_PASS) { 5717 r = s->rule.ptr; 5718 a = s->anchor.ptr; 5719 log = s->log; 5720 } else if (s == NULL) 5721 action = pf_test_other(&r, &s, dir, ifp, m, off, h, 5722 &pd, &a, &ruleset); 5723 break; 5724 } 5725 5726 if (ifp == status_ifp) { 5727 pf_status.bcounters[0][dir == PF_OUT] += pd.tot_len; 5728 pf_status.pcounters[0][dir == PF_OUT][action != PF_PASS]++; 5729 } 5730 5731done: 5732 tr = r; 5733 if (r == &pf_default_rule && s != NULL && s->nat_rule.ptr != NULL) 5734 tr = s->nat_rule.ptr; 5735 if (tr->src.addr.type == PF_ADDR_TABLE) 5736 pfr_update_stats(tr->src.addr.p.tbl, 5737 (s == NULL || s->direction == dir) ? pd.src : pd.dst, pd.af, 5738 pd.tot_len, dir == PF_OUT, r->action == PF_PASS, 5739 tr->src.not); 5740 if (tr->dst.addr.type == PF_ADDR_TABLE) 5741 pfr_update_stats(tr->dst.addr.p.tbl, 5742 (s == NULL || s->direction == dir) ? pd.dst : pd.src, pd.af, 5743 pd.tot_len, dir == PF_OUT, r->action == PF_PASS, 5744 tr->dst.not); 5745 5746 if (action == PF_PASS && h->ip_hl > 5 && 5747 !((s && s->allow_opts) || r->allow_opts)) { 5748 action = PF_DROP; 5749 REASON_SET(&reason, PFRES_SHORT); 5750 log = 1; 5751 DPFPRINTF(PF_DEBUG_MISC, 5752 ("pf: dropping packet with ip options\n")); 5753 } 5754 5755#ifdef ALTQ 5756 if (action == PF_PASS && r->qid) { 5757 struct m_tag *mtag; 5758 struct altq_tag *atag; 5759 5760 mtag = m_tag_get(PACKET_TAG_PF_QID, sizeof(*atag), M_NOWAIT); 5761 if (mtag != NULL) { 5762 atag = (struct altq_tag *)(mtag + 1); 5763 if (pqid || pd.tos == IPTOS_LOWDELAY) 5764 atag->qid = r->pqid; 5765 else 5766 atag->qid = r->qid; 5767 /* add hints for ecn */ 5768 atag->af = AF_INET; 5769 atag->hdr = h; 5770 m_tag_prepend(m, mtag); 5771 } 5772 } 5773#endif 5774 5775 if (log) 5776 PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, a, ruleset); 5777 5778 if (action == PF_SYNPROXY_DROP) { 5779 m_freem(*m0); 5780 *m0 = NULL; 5781 action = PF_PASS; 5782 } else if (r->rt) 5783 /* pf_route can free the mbuf causing *m0 to become NULL */ 5784 pf_route(m0, r, dir, ifp, s); 5785 5786#ifdef __FreeBSD__ 5787 PF_UNLOCK(); 5788#endif 5789 5790 return (action); 5791} 5792#endif /* INET */ 5793 5794#ifdef INET6 5795int 5796pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0) 5797{ 5798 u_short action, reason = 0, log = 0; 5799 struct mbuf *m = *m0; 5800 struct ip6_hdr *h; 5801 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr; 5802 struct pf_state *s = NULL; 5803 struct pf_ruleset *ruleset = NULL; 5804 struct pf_pdesc pd; 5805 int off, terminal = 0; 5806 5807#ifdef __FreeBSD__ 5808 PF_LOCK(); 5809#endif 5810 5811 if (!pf_status.running || 5812 (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) { 5813#ifdef __FreeBSD__ 5814 PF_UNLOCK(); 5815#endif 5816 return (PF_PASS); 5817 } 5818 5819#if defined(__FreeBSD__) && (__FreeBSD_version >= 501000) 5820 M_ASSERTPKTHDR(m); 5821#else 5822#ifdef DIAGNOSTIC 5823 if ((m->m_flags & M_PKTHDR) == 0) 5824 panic("non-M_PKTHDR is passed to pf_test"); 5825#endif 5826#endif 5827 5828 if (m->m_pkthdr.len < (int)sizeof(*h)) { 5829 action = PF_DROP; 5830 REASON_SET(&reason, PFRES_SHORT); 5831 log = 1; 5832 goto done; 5833 } 5834 5835 /* We do IP header normalization and packet reassembly here */ 5836 if (pf_normalize_ip6(m0, dir, ifp, &reason) != PF_PASS) { 5837 action = PF_DROP; 5838 goto done; 5839 } 5840 m = *m0; 5841 h = mtod(m, struct ip6_hdr *); 5842 5843 memset(&pd, 0, sizeof(pd)); 5844 pd.src = (struct pf_addr *)&h->ip6_src; 5845 pd.dst = (struct pf_addr *)&h->ip6_dst; 5846 pd.ip_sum = NULL; 5847 pd.af = AF_INET6; 5848 pd.tos = 0; 5849 pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr); 5850 5851 off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr); 5852 pd.proto = h->ip6_nxt; 5853 do { 5854 switch (pd.proto) { 5855 case IPPROTO_FRAGMENT: 5856 action = pf_test_fragment(&r, dir, ifp, m, h, 5857 &pd, &a, &ruleset); 5858 if (action == PF_DROP) 5859 REASON_SET(&reason, PFRES_FRAG); 5860 goto done; 5861 case IPPROTO_AH: 5862 case IPPROTO_HOPOPTS: 5863 case IPPROTO_ROUTING: 5864 case IPPROTO_DSTOPTS: { 5865 /* get next header and header length */ 5866 struct ip6_ext opt6; 5867 5868 if (!pf_pull_hdr(m, off, &opt6, sizeof(opt6), 5869 NULL, NULL, pd.af)) { 5870 DPFPRINTF(PF_DEBUG_MISC, 5871 ("pf: IPv6 short opt\n")); 5872 action = PF_DROP; 5873 REASON_SET(&reason, PFRES_SHORT); 5874 log = 1; 5875 goto done; 5876 } 5877 if (pd.proto == IPPROTO_AH) 5878 off += (opt6.ip6e_len + 2) * 4; 5879 else 5880 off += (opt6.ip6e_len + 1) * 8; 5881 pd.proto = opt6.ip6e_nxt; 5882 /* goto the next header */ 5883 break; 5884 } 5885 default: 5886 terminal++; 5887 break; 5888 } 5889 } while (!terminal); 5890 5891 switch (pd.proto) { 5892 5893 case IPPROTO_TCP: { 5894 struct tcphdr th; 5895 5896 pd.hdr.tcp = &th; 5897 if (!pf_pull_hdr(m, off, &th, sizeof(th), 5898 &action, &reason, AF_INET6)) { 5899 log = action != PF_PASS; 5900 goto done; 5901 } 5902 if (dir == PF_IN && pf_check_proto_cksum(m, off, 5903 ntohs(h->ip6_plen), IPPROTO_TCP, AF_INET6)) { 5904 action = PF_DROP; 5905 goto done; 5906 } 5907 pd.p_len = pd.tot_len - off - (th.th_off << 2); 5908 action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd); 5909 if (action == PF_DROP) 5910 break; 5911 action = pf_test_state_tcp(&s, dir, ifp, m, 0, off, h, &pd, 5912 &reason); 5913 if (action == PF_PASS) { 5914 r = s->rule.ptr; 5915 log = s->log; 5916 } else if (s == NULL) 5917 action = pf_test_tcp(&r, &s, dir, ifp, 5918 m, 0, off, h, &pd, &a, &ruleset); 5919 break; 5920 } 5921 5922 case IPPROTO_UDP: { 5923 struct udphdr uh; 5924 5925 pd.hdr.udp = &uh; 5926 if (!pf_pull_hdr(m, off, &uh, sizeof(uh), 5927 &action, &reason, AF_INET6)) { 5928 log = action != PF_PASS; 5929 goto done; 5930 } 5931 if (dir == PF_IN && uh.uh_sum && pf_check_proto_cksum(m, 5932 off, ntohs(h->ip6_plen), IPPROTO_UDP, AF_INET6)) { 5933 action = PF_DROP; 5934 goto done; 5935 } 5936 action = pf_test_state_udp(&s, dir, ifp, m, 0, off, h, &pd); 5937 if (action == PF_PASS) { 5938 r = s->rule.ptr; 5939 log = s->log; 5940 } else if (s == NULL) 5941 action = pf_test_udp(&r, &s, dir, ifp, 5942 m, 0, off, h, &pd, &a, &ruleset); 5943 break; 5944 } 5945 5946 case IPPROTO_ICMPV6: { 5947 struct icmp6_hdr ih; 5948 5949 pd.hdr.icmp6 = &ih; 5950 if (!pf_pull_hdr(m, off, &ih, sizeof(ih), 5951 &action, &reason, AF_INET6)) { 5952 log = action != PF_PASS; 5953 goto done; 5954 } 5955 if (dir == PF_IN && pf_check_proto_cksum(m, off, 5956 ntohs(h->ip6_plen), IPPROTO_ICMPV6, AF_INET6)) { 5957 action = PF_DROP; 5958 goto done; 5959 } 5960 action = pf_test_state_icmp(&s, dir, ifp, 5961 m, 0, off, h, &pd); 5962 if (action == PF_PASS) { 5963 r = s->rule.ptr; 5964 r->packets++; 5965 r->bytes += h->ip6_plen; 5966 log = s->log; 5967 } else if (s == NULL) 5968 action = pf_test_icmp(&r, &s, dir, ifp, 5969 m, 0, off, h, &pd, &a, &ruleset); 5970 break; 5971 } 5972 5973 default: 5974 action = pf_test_other(&r, &s, dir, ifp, m, off, h, 5975 &pd, &a, &ruleset); 5976 break; 5977 } 5978 5979 if (ifp == status_ifp) { 5980 pf_status.bcounters[1][dir == PF_OUT] += pd.tot_len; 5981 pf_status.pcounters[1][dir == PF_OUT][action != PF_PASS]++; 5982 } 5983 5984done: 5985 tr = r; 5986 if (r == &pf_default_rule && s != NULL && s->nat_rule.ptr != NULL) 5987 tr = s->nat_rule.ptr; 5988 if (tr->src.addr.type == PF_ADDR_TABLE) 5989 pfr_update_stats(tr->src.addr.p.tbl, 5990 (s == NULL || s->direction == dir) ? pd.src : pd.dst, pd.af, 5991 pd.tot_len, dir == PF_OUT, r->action == PF_PASS, 5992 tr->src.not); 5993 if (tr->dst.addr.type == PF_ADDR_TABLE) 5994 pfr_update_stats(tr->dst.addr.p.tbl, 5995 (s == NULL || s->direction == dir) ? pd.dst : pd.src, pd.af, 5996 pd.tot_len, dir == PF_OUT, r->action == PF_PASS, 5997 tr->dst.not); 5998 5999 /* XXX handle IPv6 options, if not allowed. not implemented. */ 6000 6001#ifdef ALTQ 6002 if (action == PF_PASS && r->qid) { 6003 struct m_tag *mtag; 6004 struct altq_tag *atag; 6005 6006 mtag = m_tag_get(PACKET_TAG_PF_QID, sizeof(*atag), M_NOWAIT); 6007 if (mtag != NULL) { 6008 atag = (struct altq_tag *)(mtag + 1); 6009 if (pd.tos == IPTOS_LOWDELAY) 6010 atag->qid = r->pqid; 6011 else 6012 atag->qid = r->qid; 6013 /* add hints for ecn */ 6014 atag->af = AF_INET6; 6015 atag->hdr = h; 6016 m_tag_prepend(m, mtag); 6017 } 6018 } 6019#endif 6020 6021 if (log) 6022 PFLOG_PACKET(ifp, h, m, AF_INET6, dir, reason, r, a, ruleset); 6023 6024 if (action == PF_SYNPROXY_DROP) { 6025 m_freem(*m0); 6026 *m0 = NULL; 6027 action = PF_PASS; 6028 } else if (r->rt) 6029 /* pf_route6 can free the mbuf causing *m0 to become NULL */ 6030 pf_route6(m0, r, dir, ifp, s); 6031 6032#ifdef __FreeBSD__ 6033 PF_UNLOCK(); 6034#endif 6035 return (action); 6036} 6037#endif /* INET6 */ 6038