summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2002-03-27 18:16:24 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2002-03-27 18:16:24 +0000
commitf5b5f9a9d79ac00b898f03754f8633d88a7da65e (patch)
tree7b2124304dd57c38560864fefe926e31ef5f4fde
parent0383b042ec78518838e9c7faf713ed09c8414734 (diff)
implement a "no-route" keyword.
usage semantics are analogous w/ "any", meaning is "any ip address for which there is no route in the current routing table", could be used in both from and to. typical usage would be (assuming symmetrical routing): block in from no-route to any also doc "any" in the pf.conf.5, include in regress, etc. tested by me on i386 and sparc. dhartmei@ and frantzen@ ok
-rw-r--r--regress/sbin/pfctl/pf2.in2
-rw-r--r--regress/sbin/pfctl/pf2.ok19
-rw-r--r--sbin/pfctl/parse.y13
-rw-r--r--sbin/pfctl/pfctl_parser.c11
-rw-r--r--share/man/man5/pf.conf.518
-rw-r--r--sys/net/pf.c66
-rw-r--r--sys/net/pf_norm.c13
-rw-r--r--sys/net/pfvar.h4
8 files changed, 114 insertions, 32 deletions
diff --git a/regress/sbin/pfctl/pf2.in b/regress/sbin/pfctl/pf2.in
index ba509ebec67..2d1193167a9 100644
--- a/regress/sbin/pfctl/pf2.in
+++ b/regress/sbin/pfctl/pf2.in
@@ -17,6 +17,8 @@ block in log quick on tun0 from 172.16.0.0/12 to any
block in log quick on tun0 from 192.168.0.0/16 to any
block in log quick on tun0 from 255.255.255.255/32 to any
+block in log quick from no-route to any
+
pass out on tun0 inet proto icmp all icmp-type 8 code 0 keep state
pass in on tun0 inet proto icmp all icmp-type 8 code 0 keep state
diff --git a/regress/sbin/pfctl/pf2.ok b/regress/sbin/pfctl/pf2.ok
index 55f37414c8f..9842fbb21a3 100644
--- a/regress/sbin/pfctl/pf2.ok
+++ b/regress/sbin/pfctl/pf2.ok
@@ -10,12 +10,13 @@
@9 block in log quick on tun0 inet from 172.16.0.0/12 to any
@10 block in log quick on tun0 inet from 192.168.0.0/16 to any
@11 block in log quick on tun0 inet from 255.255.255.255/32 to any
-@12 pass out on tun0 inet proto icmp all icmp-type echoreq code 0 keep state
-@13 pass in on tun0 inet proto icmp all icmp-type echoreq code 0 keep state
-@14 pass out on tun0 proto udp all keep state
-@15 pass in on tun0 proto udp from any to any port = domain keep state
-@16 pass out on tun0 proto tcp all keep state
-@17 pass in on tun0 proto tcp from any to any port = ssh keep state
-@18 pass in on tun0 proto tcp from any to any port = smtp keep state
-@19 pass in on tun0 proto tcp from any to any port = domain keep state
-@20 pass in on tun0 proto tcp from any to any port = auth keep state
+@12 block in log quick from no-route to any
+@13 pass out on tun0 inet proto icmp all icmp-type echoreq code 0 keep state
+@14 pass in on tun0 inet proto icmp all icmp-type echoreq code 0 keep state
+@15 pass out on tun0 proto udp all keep state
+@16 pass in on tun0 proto udp from any to any port = domain keep state
+@17 pass out on tun0 proto tcp all keep state
+@18 pass in on tun0 proto tcp from any to any port = ssh keep state
+@19 pass in on tun0 proto tcp from any to any port = smtp keep state
+@20 pass in on tun0 proto tcp from any to any port = domain keep state
+@21 pass in on tun0 proto tcp from any to any port = auth keep state
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index ad86add008c..9b186b68e4f 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.56 2002/02/27 18:11:45 dhartmei Exp $ */
+/* $OpenBSD: parse.y,v 1.57 2002/03/27 18:16:22 mickey Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -72,6 +72,7 @@ struct node_host {
struct pf_addr mask;
u_int8_t af;
u_int8_t not;
+ u_int8_t noroute;
struct node_host *next;
};
@@ -171,6 +172,7 @@ typedef struct {
%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
%token MINTTL IPV6ADDR ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO NO LABEL
+%token NOROUTE
%token <v.string> STRING
%token <v.number> NUMBER
%token <v.i> PORTUNARY PORTBINARY
@@ -437,6 +439,12 @@ host_list : xhost { $$ = $1; }
xhost : '!' host { $$ = $2; $$->not = 1; }
| host { $$ = $1; }
+ | NOROUTE {
+ $$ = calloc(1, sizeof(struct node_host));
+ if ($$ == NULL)
+ err(1, "xhost: calloc");
+ $$->noroute = 1;
+ }
;
host : address {
@@ -1213,12 +1221,14 @@ void expand_rule_hosts(struct pf_rule *r,
r->proto = proto->proto;
r->src.addr = src_host->addr;
r->src.mask = src_host->mask;
+ r->src.noroute = src_host->noroute;
r->src.not = src_host->not;
r->src.port[0] = src_port->port[0];
r->src.port[1] = src_port->port[1];
r->src.port_op = src_port->op;
r->dst.addr = dst_host->addr;
r->dst.mask = dst_host->mask;
+ r->dst.noroute = dst_host->noroute;
r->dst.not = dst_host->not;
r->dst.port[0] = dst_port->port[0];
r->dst.port[1] = dst_port->port[1];
@@ -1373,6 +1383,7 @@ lookup(char *s)
{ "nat", NAT},
{ "no", NO},
{ "no-df", NODF},
+ { "no-route", NOROUTE},
{ "on", ON},
{ "out", OUT},
{ "pass", PASS},
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index c9043f9b523..567683785d6 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.62 2002/03/12 08:15:03 dhartmei Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.63 2002/03/27 18:16:23 mickey Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -705,12 +705,15 @@ print_rule(struct pf_rule *r)
}
if (PF_AZERO(&r->src.addr, AF_INET6) &&
PF_AZERO(&r->src.mask, AF_INET6) &&
+ !r->src.noroute && !r->dst.noroute &&
!r->src.port_op && PF_AZERO(&r->dst.addr, AF_INET6) &&
PF_AZERO(&r->dst.mask, AF_INET6) && !r->dst.port_op)
printf("all ");
else {
printf("from ");
- if (PF_AZERO(&r->src.addr, AF_INET6) &&
+ if (r->src.noroute)
+ printf("no-route ");
+ else if (PF_AZERO(&r->src.addr, AF_INET6) &&
PF_AZERO(&r->src.mask, AF_INET6))
printf("any ");
else {
@@ -725,7 +728,9 @@ print_rule(struct pf_rule *r)
r->proto == IPPROTO_TCP ? "tcp" : "udp");
printf("to ");
- if (PF_AZERO(&r->dst.addr, AF_INET6) &&
+ if (r->dst.noroute)
+ printf("no-route ");
+ else if (PF_AZERO(&r->dst.addr, AF_INET6) &&
PF_AZERO(&r->dst.mask, AF_INET6))
printf("any ");
else {
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
index b63daaa5dc4..bcf6a82154f 100644
--- a/share/man/man5/pf.conf.5
+++ b/share/man/man5/pf.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pf.conf.5,v 1.35 2002/03/17 18:22:45 dhartmei Exp $
+.\" $OpenBSD: pf.conf.5,v 1.36 2002/03/27 18:16:17 mickey Exp $
.\"
.\" Copyright (c) 2001, Daniel Hartmeier
.\" All rights reserved.
@@ -68,8 +68,8 @@ af = "inet" | "inet6" .
proto-list = ( proto-name | proto-number ) [ "," proto-list ] .
hosts = "all" |
- "from" ( "any" | host | "{" host-list "}" ) [ port ]
- "to" ( "any" | host | "{" host-list "}" ) [ port ] .
+ "from" ( "any" ! "no-route" | host | "{" host-list "}" ) [ port ]
+ "to" ( "any" | "no-route" | host | "{" host-list "}" ) [ port ] .
host = [ "!" ] address [ "/" mask-bits ] .
address = ( interface-name | host-name | ipv4-dotted-quad |
@@ -219,7 +219,14 @@ The rule applies only to packets with the specified source and destination
addresses/ports.
.Pp
Addresses can be specified in CIDR notation (matching netblocks), as
-symbolic host names or interface names.
+symbolic host names or interface names, or as any of the following keywords:
+.Bl -tag -width no-route -compact
+.It Em any
+means any address;
+.It Em no-route
+means any address which is not currently routable.
+.El
+.Pp
Host name resolution and interface to address translation are done at
rule set load-time.
When the address of an interface (or host name) changes (by DHCP or PPP,
@@ -489,6 +496,9 @@ block return-rst in log on $ext_if proto tcp all
block return-icmp out log on $ext_if proto udp all
block return-icmp in log on $ext_if proto udp all
+# block anything coming form source we have no back routes for
+block in from no-route to any
+
# block and log outgoing packets that don't have our address as source,
# they are either spoofed or something is misconfigured (NAT disabled,
# for instance), we want to be nice and don't send out garbage.
diff --git a/sys/net/pf.c b/sys/net/pf.c
index e98c6a10e39..956d70a903b 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.197 2002/03/26 20:24:51 dhartmei Exp $ */
+/* $OpenBSD: pf.c,v 1.198 2002/03/27 18:16:21 mickey Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -2983,13 +2983,19 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
r = r->skip[PF_SKIP_AF];
else if (r->proto && r->proto != IPPROTO_TCP)
r = r->skip[PF_SKIP_PROTO];
- else if (!PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not,
+ else if (r->src.noroute && pf_routable(saddr, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->src.noroute &&
+ !PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not,
&r->src.addr, &r->src.mask, saddr, af))
r = r->skip[PF_SKIP_SRC_ADDR];
else if (r->src.port_op && !pf_match_port(r->src.port_op,
r->src.port[0], r->src.port[1], th->th_sport))
r = r->skip[PF_SKIP_SRC_PORT];
- else if (!PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not,
+ else if (r->dst.noroute && pf_routable(daddr, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->dst.noroute &&
+ !PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not,
&r->dst.addr, &r->dst.mask, daddr, af))
r = r->skip[PF_SKIP_DST_ADDR];
else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
@@ -3209,14 +3215,20 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
r = r->skip[PF_SKIP_AF];
else if (r->proto && r->proto != IPPROTO_UDP)
r = r->skip[PF_SKIP_PROTO];
- else if (!PF_AZERO(&r->src.mask, af) &&
+ else if (r->src.noroute && pf_routable(saddr, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->src.noroute &&
+ !PF_AZERO(&r->src.mask, af) &&
!PF_MATCHA(r->src.not, &r->src.addr, &r->src.mask,
saddr, af))
r = r->skip[PF_SKIP_SRC_ADDR];
else if (r->src.port_op && !pf_match_port(r->src.port_op,
r->src.port[0], r->src.port[1], uh->uh_sport))
r = r->skip[PF_SKIP_SRC_PORT];
- else if (!PF_AZERO(&r->dst.mask, af) &&
+ else if (r->dst.noroute && pf_routable(daddr, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->dst.noroute &&
+ !PF_AZERO(&r->dst.mask, af) &&
!PF_MATCHA(r->dst.not, &r->dst.addr, &r->dst.mask,
daddr, af))
r = r->skip[PF_SKIP_DST_ADDR];
@@ -3479,10 +3491,16 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
r = r->skip[PF_SKIP_AF];
else if (r->proto && r->proto != pd->proto)
r = r->skip[PF_SKIP_PROTO];
- else if (!PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not,
+ else if (r->src.noroute && pf_routable(saddr, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->src.noroute &&
+ !PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not,
&r->src.addr, &r->src.mask, saddr, af))
r = r->skip[PF_SKIP_SRC_ADDR];
- else if (!PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not,
+ else if (r->dst.noroute && pf_routable(daddr, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->dst.noroute &&
+ !PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not,
&r->dst.addr, &r->dst.mask, daddr, af))
r = r->skip[PF_SKIP_DST_ADDR];
else if (r->ifp != NULL && r->ifp != ifp)
@@ -3682,10 +3700,16 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
r = r->skip[PF_SKIP_AF];
else if (r->proto && r->proto != pd->proto)
r = r->skip[PF_SKIP_PROTO];
- else if (!PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not,
+ else if (r->src.noroute && pf_routable(pd->src, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->src.noroute &&
+ !PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not,
&r->src.addr, &r->src.mask, pd->src, af))
r = r->skip[PF_SKIP_SRC_ADDR];
- else if (!PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not,
+ else if (r->dst.noroute && pf_routable(pd->dst, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->src.noroute &&
+ !PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not,
&r->dst.addr, &r->dst.mask, pd->dst, af))
r = r->skip[PF_SKIP_DST_ADDR];
else {
@@ -4712,6 +4736,30 @@ pf_pull_hdr(struct mbuf *m, int off, void *p, int len,
return (p);
}
+int
+pf_routable(addr, af)
+ struct pf_addr *addr;
+ int af;
+{
+ struct sockaddr_in *dst;
+ struct route ro;
+ int ret = 0;
+
+ bzero(&ro, sizeof(ro));
+ dst = satosin(&ro.ro_dst);
+ dst->sin_family = af;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_addr = addr->v4;
+ rtalloc_noclone(&ro, NO_CLONING);
+
+ if (ro.ro_rt != NULL) {
+ ret = 1;
+ RTFREE(ro.ro_rt);
+ }
+
+ return (ret);
+}
+
#ifdef INET
void
pf_route(struct mbuf **m, struct pf_rule *r, int dir)
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index 38de048815f..0436f6262c5 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.20 2002/02/26 07:25:33 dhartmei Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.21 2002/03/27 18:16:21 mickey Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -587,16 +587,19 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff,
r = r->skip[PF_SKIP_AF];
else if (r->proto && r->proto != pd->proto)
r = r->skip[PF_SKIP_PROTO];
- else if (!PF_AZERO(&r->src.mask, af) &&
+ else if (r->src.noroute && pf_routable(pd->src, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->src.noroute && !PF_AZERO(&r->src.mask, af) &&
!PF_MATCHA(r->src.not, &r->src.addr, &r->src.mask,
pd->src, af))
r = r->skip[PF_SKIP_SRC_ADDR];
else if (r->src.port_op && !pf_match_port(r->src.port_op,
r->src.port[0], r->src.port[1], th->th_sport))
r = r->skip[PF_SKIP_SRC_PORT];
- else if (!PF_AZERO(&r->dst.mask, af) &&
- !PF_MATCHA(r->dst.not,
- &r->dst.addr, &r->dst.mask,
+ else if (r->dst.noroute && pf_routable(pd->dst, af))
+ r = TAILQ_NEXT(r, entries);
+ else if (!r->dst.noroute && !PF_AZERO(&r->dst.mask, af) &&
+ !PF_MATCHA(r->dst.not, &r->dst.addr, &r->dst.mask,
pd->dst, af))
r = r->skip[PF_SKIP_DST_ADDR];
else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 051c40d2155..0c32f00293c 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.65 2002/03/25 22:03:01 frantzen Exp $ */
+/* $OpenBSD: pfvar.h,v 1.66 2002/03/27 18:16:21 mickey Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -187,6 +187,7 @@ struct pf_rule_addr {
u_int16_t port[2];
u_int8_t not;
u_int8_t port_op;
+ u_int8_t noroute;
};
struct pf_rule {
@@ -600,6 +601,7 @@ int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t);
void pf_normalize_init(void);
int pf_normalize_ip(struct mbuf **, int, struct ifnet *, u_short *);
void pf_purge_expired_fragments(void);
+int pf_routable(struct pf_addr *addr, int af);
extern struct pf_rulequeue *pf_rules_active;
extern struct pf_status pf_status;