diff options
-rw-r--r-- | sbin/pfctl/parse.y | 34 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 4 | ||||
-rw-r--r-- | sys/net/pf.c | 29 | ||||
-rw-r--r-- | sys/net/pf_ioctl.c | 24 | ||||
-rw-r--r-- | sys/net/pfvar.h | 4 |
5 files changed, 81 insertions, 14 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index c49988a08a5..ce11b94b623 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.576 2009/12/10 15:57:20 deraadt Exp $ */ +/* $OpenBSD: parse.y,v 1.577 2009/12/24 04:24:19 dlg Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -242,6 +242,7 @@ struct filter_opts { #define FOM_SCRUB_TCP 0x0200 struct node_uid *uid; struct node_gid *gid; + struct node_if *rcv; struct { u_int8_t b1; u_int8_t b2; @@ -349,7 +350,8 @@ void expand_rule(struct pf_rule *, int, struct node_if *, struct node_proto *, struct node_os *, struct node_host *, struct node_port *, struct node_host *, struct node_port *, struct node_uid *, - struct node_gid *, struct node_icmp *, const char *); + struct node_gid *, struct node_if *, struct node_icmp *, + const char *); int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *, struct node_queue_bw bwspec, struct node_queue_opt *); @@ -463,7 +465,7 @@ int parseport(char *, struct range *r, int); %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW %token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS -%token DIVERTTO DIVERTREPLY DIVERTPACKET NATTO RDRTO +%token DIVERTTO DIVERTREPLY DIVERTPACKET NATTO RDRTO RECEIVEDON %token <v.string> STRING %token <v.number> NUMBER %token <v.i> PORTBINARY @@ -906,7 +908,7 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto expand_rule(&r, 0, $5, NULL, NULL, NULL, $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, - $9.uid, $9.gid, $9.icmpspec, + $9.uid, $9.gid, $9.rcv, $9.icmpspec, pf->astack[pf->asd + 1] ? pf->alast->name : $2); free($2); pf->astack[pf->asd + 1] = NULL; @@ -1075,7 +1077,7 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { if (h != NULL) expand_rule(&r, 0, j, NULL, NULL, NULL, NULL, NULL, h, NULL, NULL, NULL, - NULL, NULL, NULL, ""); + NULL, NULL, NULL, NULL, ""); if ((i->ifa_flags & IFF_LOOPBACK) == 0) { bzero(&r, sizeof(r)); @@ -1097,7 +1099,7 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { expand_rule(&r, 0, NULL, NULL, NULL, NULL, NULL, NULL, h, NULL, NULL, NULL, NULL, - NULL, NULL, ""); + NULL, NULL, NULL, ""); } else free(hh); } @@ -2101,7 +2103,7 @@ pfrule : action dir logquick interface af proto fromto expand_rule(&r, 0, $4, &$8.nat, &$8.rdr, &$8.rroute, $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, - $8.uid, $8.gid, $8.icmpspec, ""); + $8.uid, $8.gid, $8.rcv, $8.icmpspec, ""); } ; @@ -2311,6 +2313,13 @@ filter_opt : USER uids { if ($3.key != NULL) filter_opts.route.key = $3.key; } + | RECEIVEDON if_item { + if (filter_opts.rcv) { + yyerror("cannot respecify received-on"); + YYERROR; + } + filter_opts.rcv = $2; + } ; probability : STRING { @@ -4546,8 +4555,8 @@ expand_rule(struct pf_rule *r, int keeprule, struct node_if *interfaces, struct node_proto *protos, struct node_os *src_oses, struct node_host *src_hosts, struct node_port *src_ports, struct node_host *dst_hosts, struct node_port *dst_ports, - struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types, - const char *anchor_call) + struct node_uid *uids, struct node_gid *gids, struct node_if *rcv, + struct node_icmp *icmp_types, const char *anchor_call) { sa_family_t af = r->af; int added = 0, error = 0; @@ -4649,6 +4658,10 @@ expand_rule(struct pf_rule *r, int keeprule, struct node_if *interfaces, r->gid.op = gid->op; r->gid.gid[0] = gid->gid[0]; r->gid.gid[1] = gid->gid[1]; + if (rcv) { + strlcpy(r->rcv_ifname, rcv->ifname, + sizeof(r->rcv_ifname)); + } r->type = icmp_type->type; r->code = icmp_type->code; @@ -4759,7 +4772,7 @@ expand_rule(struct pf_rule *r, int keeprule, struct node_if *interfaces, expand_rule(&rb, 1, interface, NULL, &binat, NULL, proto, src_os, dst_host, dst_port, dsth, src_port, - uid, gid, icmp_type, anchor_call); + uid, gid, rcv, icmp_type, anchor_call); } )))))))))); @@ -4933,6 +4946,7 @@ lookup(char *s) { "rdr-to", RDRTO}, { "realtime", REALTIME}, { "reassemble", REASSEMBLE}, + { "received-on", RECEIVEDON}, { "reply-to", REPLYTO}, { "require-order", REQUIREORDER}, { "return", RETURN}, diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 04c05d56ba8..53c3daded6b 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.253 2009/12/14 12:31:45 henning Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.254 2009/12/24 04:24:19 dlg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -772,6 +772,8 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose) } print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto, verbose); + if (r->rcv_ifname[0]) + printf(" received-on %s", r->rcv_ifname); if (r->uid.op) print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user", UID_MAX); diff --git a/sys/net/pf.c b/sys/net/pf.c index 6602cb57b69..ff086df53b6 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.679 2009/12/14 12:31:45 henning Exp $ */ +/* $OpenBSD: pf.c,v 1.680 2009/12/24 04:24:19 dlg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -233,6 +233,7 @@ struct pf_state *pf_find_state(struct pfi_kif *, struct pf_state_key_cmp *, u_int, struct mbuf *); int pf_src_connlimit(struct pf_state **); int pf_check_congestion(struct ifqueue *); +int pf_match_rcvif(struct mbuf *, struct pf_rule *); extern struct pool pfr_ktable_pl; extern struct pool pfr_kentry_pl; @@ -2260,6 +2261,30 @@ pf_match_tag(struct mbuf *m, struct pf_rule *r, int *tag) } int +pf_match_rcvif(struct mbuf *m, struct pf_rule *r) +{ + struct ifnet *ifp = m->m_pkthdr.rcvif; + struct pfi_kif *kif; + + if (ifp == NULL) + return (0); + + if (ifp->if_type == IFT_CARP && ifp->if_carpdev) + kif = (struct pfi_kif *)ifp->if_carpdev->if_pf_kif; + else + kif = (struct pfi_kif *)ifp->if_pf_kif; + + if (kif == NULL) { + DPFPRINTF(PF_DEBUG_URGENT, + ("pf_test_via: kif == NULL, @%d via %s\n", r->nr, + r->rcv_ifname)); + return (0); + } + + return (pfi_kif_match(r->rcv_kif, kif)); +} + +int pf_tag_packet(struct mbuf *m, int tag, int rtableid) { if (tag <= 0 && rtableid < 0) @@ -2843,6 +2868,8 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, r = TAILQ_NEXT(r, entries); else if (r->match_tag && !pf_match_tag(m, r, &tag)) r = TAILQ_NEXT(r, entries); + else if (r->rcv_kif && !pf_match_rcvif(m, r)) + r = TAILQ_NEXT(r, entries); else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto != IPPROTO_TCP || !pf_osfp_match( pf_osfp_fingerprint(pd, m, off, th), diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index 30a5a0fc091..e0c11d9f95e 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.229 2009/12/14 12:31:45 henning Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.230 2009/12/24 04:24:19 dlg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -366,6 +366,7 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) if (rule->overload_tbl) pfr_detach_table(rule->overload_tbl); } + pfi_kif_unref(rule->rcv_kif, PFI_KIF_REF_RULE); pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE); pf_anchor_remove(rule); pf_empty_pool(&rule->rdr.list); @@ -773,6 +774,7 @@ pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule) pf_hash_rule_addr(ctx, &rule->dst); PF_MD5_UPD_STR(rule, label); PF_MD5_UPD_STR(rule, ifname); + PF_MD5_UPD_STR(rule, rcv_ifname); PF_MD5_UPD_STR(rule, match_tagname); PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */ PF_MD5_UPD_HTONL(rule, os_fingerprint, y); @@ -1076,6 +1078,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) rule->cpid = p->p_pid; rule->anchor = NULL; rule->kif = NULL; + rule->rcv_kif = NULL; TAILQ_INIT(&rule->rdr.list); TAILQ_INIT(&rule->nat.list); TAILQ_INIT(&rule->route.list); @@ -1115,6 +1118,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } pfi_kif_ref(rule->kif, PFI_KIF_REF_RULE); } + if (rule->rcv_ifname[0]) { + rule->rcv_kif = pfi_kif_get(rule->rcv_ifname); + if (rule->rcv_kif == NULL) { + error = EINVAL; + } else + pfi_kif_ref(rule->rcv_kif, PFI_KIF_REF_RULE); + } if (rule->rtableid > 0 && !rtable_exists(rule->rtableid)) error = EBUSY; @@ -1347,6 +1357,18 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } else newrule->kif = NULL; + if (newrule->rcv_ifname[0]) { + newrule->rcv_kif = + pfi_kif_get(newrule->rcv_ifname); + if (newrule->rcv_kif == NULL) { + error = EINVAL; + } else { + pfi_kif_ref(newrule->rcv_kif, + PFI_KIF_REF_RULE); + } + } else + newrule->kif = NULL; + if (newrule->rtableid > 0 && !rtable_exists(newrule->rtableid)) error = EBUSY; diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 0be8bd29c10..596e44f9277 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.302 2009/12/14 12:31:45 henning Exp $ */ +/* $OpenBSD: pfvar.h,v 1.303 2009/12/24 04:24:19 dlg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -529,6 +529,7 @@ struct pf_rule { char label[PF_RULE_LABEL_SIZE]; #define PF_QNAME_SIZE 64 char ifname[IFNAMSIZ]; + char rcv_ifname[IFNAMSIZ]; char qname[PF_QNAME_SIZE]; char pqname[PF_QNAME_SIZE]; #define PF_TAG_NAME_SIZE 64 @@ -547,6 +548,7 @@ struct pf_rule { u_int64_t bytes[2]; struct pfi_kif *kif; + struct pfi_kif *rcv_kif; struct pf_anchor *anchor; struct pfr_ktable *overload_tbl; |