summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;