diff options
author | Renato Botelho <renato@netgate.com> | 2015-08-17 13:52:54 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2015-08-17 13:52:54 -0300 |
commit | 8c10ee0bff0e7760d19267e2de3afb739ff7fcd2 (patch) | |
tree | f85eaa26b420d7b405c37b3428062480d9347b72 | |
parent | d5796de6931d14d3ff44cefd4ce4dfab8e88c7ba (diff) | |
download | FreeBSD-src-8c10ee0bff0e7760d19267e2de3afb739ff7fcd2.zip FreeBSD-src-8c10ee0bff0e7760d19267e2de3afb739ff7fcd2.tar.gz |
Importing pfSense patch dummynet.RELENG_10.diff
-rw-r--r-- | sbin/pfctl/parse.y | 62 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 8 | ||||
-rw-r--r-- | sys/net/pfvar.h | 5 | ||||
-rw-r--r-- | sys/netpfil/ipfw/ip_dn_io.c | 1 | ||||
-rw-r--r-- | sys/netpfil/ipfw/ip_dummynet.c | 1 | ||||
-rw-r--r-- | sys/netpfil/pf/pf.c | 315 |
6 files changed, 374 insertions, 18 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 420b849..716d1b8 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -239,6 +239,9 @@ struct filter_opts { char *tag; char *match_tag; u_int8_t match_tag_not; + u_int32_t dnpipe; + u_int32_t pdnpipe; + u_int32_t free_flags; u_int rtableid; struct { struct node_host *addr; @@ -450,6 +453,7 @@ int parseport(char *, struct range *r, int); %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY %token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT %token QUEUE PRIORITY QLIMIT RTABLE +%token DNPIPE DNQUEUE %token LOAD RULESET_OPTIMIZATION %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY @@ -1600,14 +1604,22 @@ bandwidth : STRING { bps = strtod($1, &cp); if (cp != NULL) { - if (!strcmp(cp, "b")) + if (!strcmp(cp, "b") || !strcmp(cp, "bit")) ; /* nothing */ - else if (!strcmp(cp, "Kb")) + else if (!strcmp(cp, "Kb") || !strcmp(cp, "Kbit")) bps *= 1000; - else if (!strcmp(cp, "Mb")) + else if (!strcmp(cp, "Mb") || !strcmp(cp, "Mbit")) bps *= 1000 * 1000; - else if (!strcmp(cp, "Gb")) + else if (!strcmp(cp, "Gb") || !strcmp(cp, "Gbit")) bps *= 1000 * 1000 * 1000; + else if (!strcmp(cp, "B") || !strcmp(cp, "Byte")) + ; /* nothing */ + else if (!strcmp(cp, "KB") || !strcmp(cp, "Kbyte")) + bps *= 1024; + else if (!strcmp(cp, "MB") || !strcmp(cp, "Mbyte")) + bps *= 1024 * 1024; + else if (!strcmp(cp, "GB") || !strcmp(cp, "Gbyte")) + bps *= 1024 * 1024 * 1024; else if (!strcmp(cp, "%")) { if (bps < 0 || bps > 100) { yyerror("bandwidth spec " @@ -2255,6 +2267,15 @@ pfrule : action dir logquick interface route af proto fromto } #endif + if ($9.dnpipe) { + r.dnpipe = $9.dnpipe; + if ($9.free_flags & PFRULE_DN_IS_PIPE) + r.free_flags |= PFRULE_DN_IS_PIPE; + else + r.free_flags |= PFRULE_DN_IS_QUEUE; + r.pdnpipe = $9.pdnpipe; + } + expand_rule(&r, $4, $5.host, $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, $9.uid, $9.gid, $9.icmpspec, ""); @@ -2352,6 +2373,32 @@ filter_opt : USER uids { } filter_opts.queues = $1; } + | DNPIPE number { + filter_opts.dnpipe = $2; + filter_opts.free_flags |= PFRULE_DN_IS_PIPE; + } + | DNPIPE '(' number ')' { + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_PIPE; + } + | DNPIPE '(' number comma number ')' { + filter_opts.pdnpipe = $5; + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_PIPE; + } + | DNQUEUE number { + filter_opts.dnpipe = $2; + filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; + } + | DNQUEUE '(' number comma number ')' { + filter_opts.pdnpipe = $5; + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; + } + | DNQUEUE '(' number ')' { + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; + } | TAG string { filter_opts.tag = $2; } @@ -4503,6 +4550,11 @@ filter_consistent(struct pf_rule *r, int anchor_call) yyerror("tos and dscp cannot be used together"); problems++; } + if (r->dnpipe && r->pdnpipe && !r->direction) { + yyerror("dummynet cannot be specified without direction"); + problems++; + } + return (-problems); } @@ -5295,6 +5347,8 @@ lookup(char *s) { "debug", DEBUG}, { "divert-reply", DIVERTREPLY}, { "divert-to", DIVERTTO}, + { "dnpipe", DNPIPE}, + { "dnqueue", DNQUEUE}, { "drop", DROP}, { "drop-ovl", FRAGDROP}, { "dscp", DSCP}, diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 3d8f8bc..b4a6eb9 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1001,6 +1001,14 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) } if (r->label[0]) printf(" label \"%s\"", r->label); + if (r->dnpipe && r->pdnpipe) + printf(" %s(%d, %d)", + r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", + r->dnpipe, r->pdnpipe); + else if (r->dnpipe) + printf(" %s %d", + r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", + r->dnpipe); if (r->qname[0] && r->pqname[0]) printf(" queue(%s, %s)", r->qname, r->pqname); else if (r->qname[0]) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 56097068..728f1d4 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -522,6 +522,11 @@ struct pf_rule { } max_src_conn_rate; u_int32_t qid; u_int32_t pqid; + u_int32_t dnpipe; + u_int32_t pdnpipe; +#define PFRULE_DN_IS_PIPE 0x00000010 +#define PFRULE_DN_IS_QUEUE 0x00000020 + u_int32_t free_flags; u_int32_t rt_listid; u_int32_t nr; u_int32_t prob; diff --git a/sys/netpfil/ipfw/ip_dn_io.c b/sys/netpfil/ipfw/ip_dn_io.c index 9a4b486..c842ce0 100644 --- a/sys/netpfil/ipfw/ip_dn_io.c +++ b/sys/netpfil/ipfw/ip_dn_io.c @@ -651,6 +651,7 @@ dummynet_send(struct mbuf *m) * to carry reinject info. */ dst = pkt->dn_dir; + pkt->rule.info |= IPFW_IS_DUMMYNET; ifp = pkt->ifp; tag->m_tag_cookie = MTAG_IPFW_RULE; tag->m_tag_id = 0; diff --git a/sys/netpfil/ipfw/ip_dummynet.c b/sys/netpfil/ipfw/ip_dummynet.c index 4de2156..b4b87c7 100644 --- a/sys/netpfil/ipfw/ip_dummynet.c +++ b/sys/netpfil/ipfw/ip_dummynet.c @@ -2290,7 +2290,6 @@ static moduledata_t dummynet_mod = { #define DN_SI_SUB SI_SUB_PROTO_IFATTACHDOMAIN #define DN_MODEV_ORD (SI_ORDER_ANY - 128) /* after ipfw */ DECLARE_MODULE(dummynet, dummynet_mod, DN_SI_SUB, DN_MODEV_ORD); -MODULE_DEPEND(dummynet, ipfw, 2, 2, 2); MODULE_VERSION(dummynet, 3); /* diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index d2faffa..5e0293d 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -86,6 +86,8 @@ __FBSDID("$FreeBSD$"); #include <netinet/udp_var.h> #include <netpfil/ipfw/ip_fw_private.h> /* XXX: only for DIR_IN/DIR_OUT */ +#include <netinet/ip_fw.h> +#include <netinet/ip_dummynet.h> #ifdef INET6 #include <netinet/ip6.h> @@ -258,7 +260,8 @@ static int pf_test_state_icmp(struct pf_state **, int, struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *, u_short *); static int pf_test_state_other(struct pf_state **, int, - struct pfi_kif *, struct mbuf *, struct pf_pdesc *); + struct pfi_kif *, struct mbuf *, int, + struct pf_pdesc *); static u_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t, sa_family_t); static u_int16_t pf_get_mss(struct mbuf *, int, u_int16_t, @@ -281,6 +284,10 @@ static u_int pf_purge_expired_states(u_int, int); static void pf_purge_unlinked_rules(void); static int pf_mtag_uminit(void *, int, int); static void pf_mtag_free(struct m_tag *); +static void pf_packet_redo_nat(struct mbuf *, struct pf_pdesc *, + int, struct pf_state *, int); +static void pf_packet_undo_nat(struct mbuf *, struct pf_pdesc *, + int, struct pf_state *, int); #ifdef INET static void pf_route(struct mbuf **, struct pf_rule *, int, struct ifnet *, struct pf_state *, @@ -300,16 +307,19 @@ VNET_DECLARE(int, pf_end_threads); VNET_DEFINE(struct pf_limit, pf_limits[PF_LIMIT_MAX]); -#define PACKET_LOOPED(pd) ((pd)->pf_mtag && \ - (pd)->pf_mtag->flags & PF_PACKET_LOOPED) +#define PACKET_LOOPED(mtag) ((mtag)->flags & PF_PACKET_LOOPED) #define STATE_LOOKUP(i, k, d, s, pd) \ do { \ (s) = pf_find_state((i), (k), (d)); \ if ((s) == NULL) \ return (PF_DROP); \ - if (PACKET_LOOPED(pd)) \ + if (PACKET_LOOPED(pd->pf_mtag)) { \ + if ((s)->key[PF_SK_WIRE] != (s)->key[PF_SK_STACK]) { \ + pf_packet_redo_nat(m, pd, off, s, direction); \ + } \ return (PF_PASS); \ + } \ if ((d) == PF_OUT && \ (((s)->rule.ptr->rt == PF_ROUTETO && \ (s)->rule.ptr->direction == PF_OUT) || \ @@ -407,6 +417,160 @@ pf_addr_cmp(struct pf_addr *a, struct pf_addr *b, sa_family_t af) return (0); } +static void +pf_packet_undo_nat(struct mbuf *m, struct pf_pdesc *pd, int off, + struct pf_state *state, int direction) +{ + struct pf_state_key *nk; + + if (state == NULL || state->nat_rule.ptr == NULL) + return; + + if (state->nat_rule.ptr->action == PF_RDR || + state->nat_rule.ptr->action == PF_BINAT) + nk = (state)->key[PF_SK_WIRE]; + else + nk = (state)->key[PF_SK_STACK]; + + switch (pd->proto) { + case IPPROTO_TCP: { + struct tcphdr *th = pd->hdr.tcp; + + if (direction == PF_OUT) { + pf_change_ap(pd->src, &th->th_sport, pd->ip_sum, + &th->th_sum, &nk->addr[pd->sidx], + nk->port[pd->sidx], 0, pd->af); + } else { + pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum, + &th->th_sum, &nk->addr[pd->didx], + nk->port[pd->didx], 0, pd->af); + } + m_copyback(m, off, sizeof(*th), (caddr_t)th); + } + break; + case IPPROTO_UDP: { + struct udphdr *uh = pd->hdr.udp; + + if (direction == PF_OUT) { + pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum, + &uh->uh_sum, &nk->addr[pd->sidx], + nk->port[pd->sidx], 1, pd->af); + } else { + pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum, + &uh->uh_sum, &nk->addr[pd->didx], + nk->port[pd->didx], 1, pd->af); + } + m_copyback(m, off, sizeof(*uh), (caddr_t)uh); + } + break; + /* case IPPROTO_ICMP: */ + /* XXX: If we want to do this for icmp is probably wrong!?! */ + /* break; */ + default: + if (direction == PF_OUT) { + switch (pd->af) { + case AF_INET: + pf_change_a(&pd->src->v4.s_addr, + pd->ip_sum, nk->addr[pd->sidx].v4.s_addr, + 0); + break; + case AF_INET6: + PF_ACPY(pd->src, &nk->addr[pd->sidx], pd->af); + break; + } + } else { + switch (pd->af) { + case AF_INET: + pf_change_a(&pd->dst->v4.s_addr, + pd->ip_sum, nk->addr[pd->didx].v4.s_addr, + 0); + break; + case AF_INET6: + PF_ACPY(pd->dst, &nk->addr[pd->didx], pd->af); + break; + } + } + break; + } +} + +static void +pf_packet_redo_nat(struct mbuf *m, struct pf_pdesc *pd, int off, + struct pf_state *state, int direction) +{ + struct pf_state_key *nk; + + if (state == NULL || state->nat_rule.ptr == NULL) + return; + + if (state->nat_rule.ptr->action == PF_RDR || + state->nat_rule.ptr->action == PF_BINAT) + nk = (state)->key[PF_SK_STACK]; + else + nk = (state)->key[PF_SK_WIRE]; + + switch (pd->proto) { + case IPPROTO_TCP: { + struct tcphdr *th = pd->hdr.tcp; + + if (direction == PF_OUT) { + pf_change_ap(pd->src, &th->th_sport, pd->ip_sum, + &th->th_sum, &nk->addr[pd->sidx], + nk->port[pd->sidx], 0, pd->af); + } else { + pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum, + &th->th_sum, &nk->addr[pd->didx], + nk->port[pd->didx], 0, pd->af); + } + m_copyback(m, off, sizeof(*th), (caddr_t)th); + } + break; + case IPPROTO_UDP: { + struct udphdr *uh = pd->hdr.udp; + + if (direction == PF_OUT) { + pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum, + &uh->uh_sum, &nk->addr[pd->sidx], + nk->port[pd->sidx], 1, pd->af); + } else { + pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum, + &uh->uh_sum, &nk->addr[pd->didx], + nk->port[pd->didx], 1, pd->af); + } + m_copyback(m, off, sizeof(*uh), (caddr_t)uh); + } + break; + /* case IPPROTO_ICMP: */ + /* XXX: If we want to do this for icmp is probably wrong!?! */ + /* break; */ + default: + if (direction == PF_OUT) { + switch (pd->af) { + case AF_INET: + pf_change_a(&pd->src->v4.s_addr, + pd->ip_sum, nk->addr[pd->sidx].v4.s_addr, + 0); + break; + case AF_INET6: + PF_ACPY(pd->src, &nk->addr[pd->sidx], pd->af); + break; + } + } else { + switch (pd->af) { + case AF_INET: + pf_change_a(&pd->dst->v4.s_addr, + pd->ip_sum, nk->addr[pd->didx].v4.s_addr, + 0); + break; + case AF_INET6: + PF_ACPY(pd->dst, &nk->addr[pd->didx], pd->af); + break; + } + } + break; + } +} + static __inline uint32_t pf_hashkey(struct pf_state_key *sk) { @@ -5018,7 +5182,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif, static int pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif, - struct mbuf *m, struct pf_pdesc *pd) + struct mbuf *m, int off, struct pf_pdesc *pd) { struct pf_state_peer *src, *dst; struct pf_state_key_cmp key; @@ -5711,7 +5875,9 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) struct pf_state *s = NULL; struct pf_ruleset *ruleset = NULL; struct pf_pdesc pd; - int off, dirndx, pqid = 0; + int off = 0, dirndx, pqid = 0; + int loopedfrom = 0; + struct ip_fw_args dnflow; M_ASSERTPKTHDR(m); @@ -5737,22 +5903,24 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) PF_RULES_RLOCK(); - if (ip_divert_ptr != NULL && + if ((ip_divert_ptr != NULL || ip_dn_io_ptr != NULL) && ((ipfwtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) { struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(ipfwtag+1); + pd.pf_mtag->flags |= PF_PACKET_LOOPED; + if (rr->info & IPFW_IS_DUMMYNET) + loopedfrom = 1; if (rr->info & IPFW_IS_DIVERT && rr->rulenum == 0) { if (pd.pf_mtag == NULL && ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { action = PF_DROP; goto done; } - pd.pf_mtag->flags |= PF_PACKET_LOOPED; - m_tag_delete(m, ipfwtag); } if (pd.pf_mtag && pd.pf_mtag->flags & PF_FASTFWD_OURS_PRESENT) { m->m_flags |= M_FASTFWD_OURS; pd.pf_mtag->flags &= ~PF_FASTFWD_OURS_PRESENT; } + m_tag_delete(m, ipfwtag); } else if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) { /* We do IP header normalization and packet reassembly here */ action = PF_DROP; @@ -5795,6 +5963,10 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) struct tcphdr th; pd.hdr.tcp = &th; + dnflow.f_id._flags = th.th_flags; + dnflow.f_id.dst_port = ntohs(th.th_dport); + dnflow.f_id.src_port = ntohs(th.th_sport); + if (!pf_pull_hdr(m, off, &th, sizeof(th), &action, &reason, AF_INET)) { log = action != PF_PASS; @@ -5824,6 +5996,9 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) struct udphdr uh; pd.hdr.udp = &uh; + dnflow.f_id.dst_port = ntohs(uh.uh_dport); + dnflow.f_id.src_port = ntohs(uh.uh_sport); + if (!pf_pull_hdr(m, off, &uh, sizeof(uh), &action, &reason, AF_INET)) { log = action != PF_PASS; @@ -5882,7 +6057,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) #endif default: - action = pf_test_state_other(&s, dir, kif, m, &pd); + action = pf_test_state_other(&s, dir, kif, m, off, &pd); if (action == PF_PASS) { if (pfsync_update_state_ptr != NULL) pfsync_update_state_ptr(s); @@ -5931,6 +6106,55 @@ done: } #endif /* ALTQ */ + if (r->dnpipe && ip_dn_io_ptr != NULL && loopedfrom != 1) { + if (dir != r->direction && r->pdnpipe) { + dnflow.rule.info = r->pdnpipe; + } else if (dir == r->direction) { + dnflow.rule.info = r->dnpipe; + } else + goto continueprocessing; + + if (r->free_flags & PFRULE_DN_IS_PIPE) + dnflow.rule.info |= IPFW_IS_PIPE; + dnflow.f_id.addr_type = 4; /* IPv4 type */ + dnflow.f_id.proto = pd.proto; + if (dir == PF_OUT && s != NULL && s->nat_rule.ptr != NULL && + s->nat_rule.ptr->action == PF_NAT) + dnflow.f_id.src_ip = + ntohl(s->key[(s->direction == PF_IN)]-> + addr[(s->direction == PF_OUT)].v4.s_addr); + else + dnflow.f_id.src_ip = ntohl(h->ip_src.s_addr); + dnflow.f_id.dst_ip = ntohl(h->ip_dst.s_addr); + dnflow.f_id.extra = dnflow.rule.info; + + if (m->m_flags & M_FASTFWD_OURS) { + pd.pf_mtag->flags |= PF_FASTFWD_OURS_PRESENT; + m->m_flags &= ~M_FASTFWD_OURS; + } + + if (s != NULL && s->nat_rule.ptr) + pf_packet_undo_nat(m, &pd, off, s, dir); + + ip_dn_io_ptr(m0, + (dir == PF_IN) ? DIR_IN : DIR_OUT, + &dnflow); + /* This is dummynet fast io processing */ + if (*m0 != NULL) { + m_tag_delete(*m0, m_tag_first(*m0)); + pd.pf_mtag->flags &= ~PF_PACKET_LOOPED; + if (s != NULL && s->nat_rule.ptr) + pf_packet_redo_nat(m, &pd, off, s, dir); + } else { + *m0 = NULL; + if (s) + PF_STATE_UNLOCK(s); + return (action); + } + } else + pd.pf_mtag->flags &= ~PF_PACKET_LOOPED; +continueprocessing: + /* * connections redirected to loopback should not match sockets * bound specifically to loopback due to security implications, @@ -6084,7 +6308,10 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) struct pf_state *s = NULL; struct pf_ruleset *ruleset = NULL; struct pf_pdesc pd; - int off, terminal = 0, dirndx, rh_cnt = 0; + int off = 0, terminal = 0, dirndx, rh_cnt = 0; + int loopedfrom = 0; + struct m_tag *dn_tag; + struct ip_fw_args dnflow; int fwdir = dir; M_ASSERTPKTHDR(m); @@ -6115,8 +6342,20 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) PF_RULES_RLOCK(); + if (ip_dn_io_ptr != NULL && + ((dn_tag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) { + struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(dn_tag+1); + pd.pf_mtag->flags |= PF_PACKET_LOOPED; + if (rr->info & IPFW_IS_DUMMYNET) + loopedfrom = 1; + if (pd.pf_mtag->flags & PF_FASTFWD_OURS_PRESENT) { + m->m_flags |= M_FASTFWD_OURS; + pd.pf_mtag->flags &= ~PF_FASTFWD_OURS_PRESENT; + } + m_tag_delete(m, dn_tag); + } /* We do IP header normalization and packet reassembly here */ - if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) { + else if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) { action = PF_DROP; goto done; } @@ -6225,6 +6464,10 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) struct tcphdr th; pd.hdr.tcp = &th; + dnflow.f_id._flags = th.th_flags; + dnflow.f_id.dst_port = th.th_dport; + dnflow.f_id.src_port = th.th_sport; + if (!pf_pull_hdr(m, off, &th, sizeof(th), &action, &reason, AF_INET6)) { log = action != PF_PASS; @@ -6252,6 +6495,9 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) struct udphdr uh; pd.hdr.udp = &uh; + dnflow.f_id.dst_port = uh.uh_dport; + dnflow.f_id.src_port = uh.uh_sport; + if (!pf_pull_hdr(m, off, &uh, sizeof(uh), &action, &reason, AF_INET6)) { log = action != PF_PASS; @@ -6308,7 +6554,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) } default: - action = pf_test_state_other(&s, dir, kif, m, &pd); + action = pf_test_state_other(&s, dir, kif, m, off, &pd); if (action == PF_PASS) { if (pfsync_update_state_ptr != NULL) pfsync_update_state_ptr(s); @@ -6362,6 +6608,49 @@ done: } #endif /* ALTQ */ + if (r->dnpipe && ip_dn_io_ptr != NULL && loopedfrom != 1) { + if (dir != r->direction && r->pdnpipe) { + dnflow.rule.info = r->pdnpipe; + } else if (dir == r->direction) { + dnflow.rule.info = r->dnpipe; + } else + goto continueprocessing6; + + if (r->free_flags & PFRULE_DN_IS_PIPE) + dnflow.rule.info |= IPFW_IS_PIPE; + dnflow.f_id.addr_type = 6; /* IPv4 type */ + dnflow.f_id.proto = pd.proto; + dnflow.f_id.src_ip = 0; + dnflow.f_id.dst_ip = 0; + if (dir == PF_OUT && s != NULL && s->nat_rule.ptr != NULL && + s->nat_rule.ptr->action == PF_NAT) + dnflow.f_id.src_ip6 = s->key[(s->direction == PF_IN)]->addr[0].v6; + else + dnflow.f_id.src_ip6 = h->ip6_src; + dnflow.f_id.dst_ip6 = h->ip6_dst; + + if (s != NULL && s->nat_rule.ptr) + pf_packet_undo_nat(m, &pd, off, s, dir); + + ip_dn_io_ptr(m0, + ((dir == PF_IN) ? DIR_IN : DIR_OUT) | PROTO_IPV6, + &dnflow); + /* This is dummynet fast io processing */ + if (*m0 != NULL) { + m_tag_delete(*m0, m_tag_first(*m0)); + pd.pf_mtag->flags &= ~PF_PACKET_LOOPED; + if (s != NULL && s->nat_rule.ptr) + pf_packet_redo_nat(m, &pd, off, s, dir); + } else { + *m0 = NULL; + if (s) + PF_STATE_UNLOCK(s); + return (action); + } + } else + pd.pf_mtag->flags &= ~PF_PACKET_LOOPED; +continueprocessing6: + if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP || pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL && (s->nat_rule.ptr->action == PF_RDR || |