summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/pfctl/parse.y34
-rw-r--r--sbin/pfctl/pfctl_parser.c4
-rw-r--r--sys/net/pf.c29
-rw-r--r--sys/net/pf_ioctl.c24
-rw-r--r--sys/net/pfvar.h4
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;