summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'sbin')
-rw-r--r--sbin/pfctl/parse.y455
-rw-r--r--sbin/pfctl/pfctl_parser.c303
-rw-r--r--sbin/pfctl/pfctl_parser.h10
3 files changed, 585 insertions, 183 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index e266dafdb5c..3cd689ce45b 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.31 2001/09/12 16:37:14 markus Exp $ */
+/* $OpenBSD: parse.y,v 1.32 2001/09/15 03:54:40 frantzen Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -33,6 +33,7 @@
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
#include <net/pfvar.h>
#include <arpa/inet.h>
@@ -65,8 +66,9 @@ struct node_proto {
};
struct node_host {
- u_int32_t addr;
- u_int32_t mask;
+ struct pf_addr addr;
+ struct pf_addr mask;
+ u_int8_t af;
u_int8_t not;
struct node_host *next;
};
@@ -77,6 +79,13 @@ struct node_port {
struct node_port *next;
};
+struct node_icmp {
+ u_int8_t code;
+ u_int8_t type;
+ u_int8_t proto;
+ struct node_icmp *next;
+};
+
struct peer {
struct node_host *host;
struct node_port *port;
@@ -85,19 +94,22 @@ struct peer {
int rule_consistent(struct pf_rule *);
int yyparse(void);
struct pf_rule_addr *new_addr(void);
-u_int32_t ipmask(u_int8_t);
+void ipmask(struct pf_addr *, u_int8_t, int);
void expand_rule_hosts(struct pf_rule *,
struct node_if *, struct node_proto *,
struct node_host *, struct node_port *,
- struct node_host *, struct node_port *);
+ struct node_host *, struct node_port *,
+ struct node_icmp *);
void expand_rule_protos(struct pf_rule *,
struct node_if *, struct node_proto *,
struct node_host *, struct node_port *,
- struct node_host *, struct node_port *);
+ struct node_host *, struct node_port *,
+ struct node_icmp *);
void expand_rule(struct pf_rule *,
struct node_if *, struct node_proto *,
struct node_host *, struct node_port *,
- struct node_host *, struct node_port *);
+ struct node_host *, struct node_port *,
+ struct node_icmp *);
struct sym {
struct sym *next;
@@ -126,6 +138,7 @@ typedef struct {
} range;
struct node_if *interface;
struct node_proto *proto;
+ struct node_icmp *icmp;
struct node_host *host;
struct node_port *port;
struct peer peer;
@@ -139,20 +152,22 @@ typedef struct {
%}
%token PASS BLOCK SCRUB RETURN IN OUT LOG LOGALL QUICK ON FROM TO FLAGS
-%token RETURNRST RETURNICMP PROTO ALL ANY ICMPTYPE CODE KEEP MODULATE STATE
-%token PORT RDR NAT ARROW NODF MINTTL ERROR BINAT
-%token <v.string> STRING
-%token <v.number> NUMBER
+%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
+%token <v.string> STRING
+%token <v.number> NUMBER
%token <v.i> PORTUNARY PORTBINARY
%type <v.interface> interface if_list if_item_not if_item
-%type <v.number> port icmptype minttl
-%type <v.i> dir log quick keep nodf
-%type <v.b> action icmpspec flag flags blockspec
+%type <v.number> port icmptype icmp6type minttl
+%type <v.i> dir log quick af keep nodf
+%type <v.b> action flag flags blockspec
%type <v.range> dport rport
%type <v.proto> proto proto_list proto_item
+%type <v.icmp> icmpspec icmp_list icmp6_list icmp_item icmp6_item
%type <v.fromto> fromto
%type <v.peer> ipportspec
-%type <v.host> ipspec xhost host address host_list
+%type <v.host> ipspec xhost host address host_list IPV6ADDR
%type <v.port> portspec port_list port_item
%%
@@ -176,7 +191,7 @@ varset : STRING PORTUNARY STRING
}
;
-pfrule : action dir log quick interface proto fromto flags icmpspec keep nodf minttl
+pfrule : action dir log quick interface af proto fromto flags icmpspec keep nodf minttl
{
struct pf_rule r;
@@ -195,19 +210,19 @@ pfrule : action dir log quick interface proto fromto flags icmpspec keep nodf m
r.log = $3;
r.quick = $4;
- r.flags = $8.b1;
- r.flagset = $8.b2;
- r.type = $9.b1;
- r.code = $9.b2;
- r.keep_state = $10;
+ r.af = $6;
+ r.flags = $9.b1;
+ r.flagset = $9.b2;
+
+ r.keep_state = $11;
- if ($11)
- r.rule_flag |= PFRULE_NODF;
if ($12)
- r.min_ttl = $12;
+ r.rule_flag |= PFRULE_NODF;
+ if ($13)
+ r.min_ttl = $13;
- expand_rule(&r, $5, $6, $7.src.host, $7.src.port,
- $7.dst.host, $7.dst.port);
+ expand_rule(&r, $5, $7, $8.src.host, $8.src.port,
+ $8.dst.host, $8.dst.port, $10);
}
;
@@ -222,10 +237,27 @@ blockspec : /* empty */ { $$.b2 = 0; $$.w = 0; }
$$.b2 = 0;
$$.w = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
}
+ | RETURNICMP6 {
+ $$.b2 = 0;
+ $$.w = (ICMP6_DST_UNREACH << 8) |
+ ICMP6_DST_UNREACH_NOPORT;
+ }
| RETURNICMP '(' STRING ')' {
struct icmpcodeent *p;
- if ((p = geticmpcodebyname(ICMP_UNREACH, $3)) == NULL) {
+ if ((p = geticmpcodebyname(ICMP_UNREACH, $3,
+ IPPROTO_ICMP)) == NULL) {
+ yyerror("unknown icmp code %s", $3);
+ YYERROR;
+ }
+ $$.w = (p->type << 8) | p->code;
+ $$.b2 = 0;
+ }
+ | RETURNICMP6 '(' STRING ')' {
+ struct icmpcodeent *p;
+
+ if ((p = geticmpcodebyname(ICMP6_DST_UNREACH, $3,
+ IPPROTO_ICMPV6)) == NULL) {
yyerror("unknown icmp code %s", $3);
YYERROR;
}
@@ -269,6 +301,10 @@ if_item : STRING {
}
;
+af : /* empty */ { $$ = 0; }
+ | INET { $$ = AF_INET; }
+ | INET6 { $$ = AF_INET6; }
+
proto : /* empty */ { $$ = NULL; }
| PROTO proto_item { $$ = $2; }
| PROTO '{' proto_list '}' { $$ = $3; }
@@ -340,29 +376,51 @@ xhost : '!' host { $$ = $2; $$->not = 1; }
host : address {
$$ = $1;
- $$->mask = 0xffffffff;
+ if ($$->af == AF_INET)
+ ipmask(&$$->mask, 32, AF_INET);
+ else
+ ipmask(&$$->mask, 128, AF_INET6);
}
| address '/' NUMBER {
- if ($3 < 0 || $3 > 32) {
- yyerror("illegal netmask value %d", $3);
- YYERROR;
+ if ($$->af == AF_INET) {
+ if ($3 < 0 || $3 > 32) {
+ yyerror("illegal netmask value %d", $3);
+ YYERROR;
+ }
+ } else {
+ if ($3 < 0 || $3 > 128) {
+ yyerror("illegal netmask value %d", $3);
+ YYERROR;
+ }
}
$$ = $1;
- $$->mask = ipmask($3);
+ ipmask(&$$->mask, $3, $$->af);
}
;
address : STRING {
struct hostent *hp;
- if ((hp = gethostbyname($1)) == NULL) {
- yyerror("cannot resolve %s", $1);
- YYERROR;
+ if ((hp = gethostbyname2($1, AF_INET)) == NULL) {
+ if ((hp = gethostbyname2($1, AF_INET6))
+ == NULL) {
+ yyerror("cannot resolve %s", $1);
+ YYERROR;
+ } else {
+ $$ = calloc(1, sizeof(struct node_host));
+ if ($$ == NULL)
+ err(1, "address: calloc");
+ $$->af = AF_INET6;
+ memcpy(&$$->addr, hp->h_addr,
+ sizeof(struct pf_addr));
+ }
+ } else {
+ $$ = calloc(1, sizeof(struct node_host));
+ if ($$ == NULL)
+ err(1, "address: calloc");
+ $$->af = AF_INET;
+ memcpy(&$$->addr, hp->h_addr, sizeof(u_int32_t));
}
- $$ = calloc(1, sizeof(struct node_host));
- if ($$ == NULL)
- err(1, "address: calloc");
- memcpy(&$$->addr, hp->h_addr, sizeof(u_int32_t));
}
| NUMBER '.' NUMBER '.' NUMBER '.' NUMBER {
if ($1 < 0 || $3 < 0 || $5 < 0 || $7 < 0 ||
@@ -374,8 +432,11 @@ address : STRING {
$$ = calloc(1, sizeof(struct node_host));
if ($$ == NULL)
err(1, "address: calloc");
- $$->addr = htonl(($1 << 24) | ($3 << 16) | ($5 << 8) | $7);
+ $$->af = AF_INET;
+ $$->addr.addr32[0] = htonl(($1 << 24) |
+ ($3 << 16) | ($5 << 8) | $7);
}
+ | IPV6ADDR { $$ = $1; }
;
portspec : port_item { $$ = $1; }
@@ -453,32 +514,105 @@ flags : /* empty */ { $$.b1 = 0; $$.b2 = 0; }
| FLAGS "/" flag { $$.b1 = 0; $$.b2 = $3.b1; }
;
-icmpspec : /* empty */ { $$.b1 = 0; $$.b2 = 0; }
- | ICMPTYPE icmptype { $$.b1 = $2; $$.b2 = 0; }
- | ICMPTYPE icmptype CODE NUMBER {
- if ($4 < 0 || $4 > 255) {
- yyerror("illegal icmp code %d", $4);
+icmpspec : /* empty */ { $$ = NULL; }
+ | ICMPTYPE icmp_item { $$ = $2; }
+ | ICMPTYPE '{' icmp_list '}' { $$ = $3; }
+ | ICMP6TYPE icmp6_item { $$ = $2; }
+ | ICMP6TYPE '{' icmp6_list '}' { $$ = $3; }
+ ;
+
+icmp_list : icmp_item { $$ = $1; }
+ | icmp_list ',' icmp_item { $3->next = $1; $$ = $3; }
+ ;
+
+icmp6_list : icmp6_item { $$ = $1; }
+ | icmp6_list ',' icmp6_item { $3->next = $1; $$ = $3; }
+ ;
+
+icmp_item : icmptype {
+ $$ = malloc(sizeof(struct node_icmp));
+ if ($$ == NULL)
+ err(1, "icmp_item: malloc");
+ $$->type = $1;
+ $$->code = 0;
+ $$->proto = IPPROTO_ICMP;
+ $$->next = NULL;
+ }
+ | icmptype CODE NUMBER {
+ $$ = malloc(sizeof(struct node_icmp));
+ if ($$ == NULL)
+ err(1, "icmp_item: malloc");
+ if ($3 < 0 || $3 > 255) {
+ yyerror("illegal icmp code %d", $3);
YYERROR;
}
- $$.b1 = $2;
- $$.b2 = $4 + 1;
+ $$->code = $1;
+ $$->type = $3 + 1;
+ $$->proto = IPPROTO_ICMP;
+ $$->next = NULL;
}
- | ICMPTYPE icmptype CODE STRING {
+ | icmptype CODE STRING {
struct icmpcodeent *p;
- $$.b1 = $2;
- if ((p = geticmpcodebyname($2, $4)) == NULL) {
- yyerror("unknown icmp-code %s", $4);
+ $$ = malloc(sizeof(struct node_icmp));
+ if ($$ == NULL)
+ err(1, "icmp_item: malloc");
+ $$->type = $1;
+ if ((p = geticmpcodebyname($1, $3,
+ IPPROTO_ICMP)) == NULL) {
+ yyerror("unknown icmp-code %s", $3);
YYERROR;
}
- $$.b2 = p->code + 1;
+ $$->code = p->code + 1;
+ $$->proto = IPPROTO_ICMP;
+ $$->next = NULL;
+ }
+ ;
+
+icmp6_item : icmp6type {
+ $$ = malloc(sizeof(struct node_icmp));
+ if ($$ == NULL)
+ err(1, "icmp_item: malloc");
+ $$->type = $1;
+ $$->code = 0;
+ $$->proto = IPPROTO_ICMPV6;
+ $$->next = NULL;
+ }
+ | icmp6type CODE NUMBER {
+ $$ = malloc(sizeof(struct node_icmp));
+ if ($$ == NULL)
+ err(1, "icmp_item: malloc");
+ if ($3 < 0 || $3 > 255) {
+ yyerror("illegal icmp6 code %d", $3);
+ YYERROR;
+ }
+ $$->type = $1;
+ $$->code = $3 + 1;
+ $$->proto = IPPROTO_ICMPV6;
+ $$->next = NULL;
+ }
+ | icmp6type CODE STRING {
+ struct icmpcodeent *p;
+
+ $$ = malloc(sizeof(struct node_icmp));
+ if ($$ == NULL)
+ err(1, "icmp_item: malloc");
+ $$->type = $1;
+ if ((p = geticmpcodebyname($1, $3,
+ IPPROTO_ICMPV6)) == NULL) {
+ yyerror("unknown icmp6-code %s", $3);
+ YYERROR;
+ }
+ $$->code = p->code + 1;
+ $$->proto = IPPROTO_ICMPV6;
+ $$->next = NULL;
}
;
icmptype : STRING {
struct icmptypeent *p;
- if ((p = geticmptypebyname($1)) == NULL) {
+ if ((p = geticmptypebyname($1, IPPROTO_ICMP)) == NULL) {
yyerror("unknown icmp-type %s", $1);
YYERROR;
}
@@ -493,6 +627,24 @@ icmptype : STRING {
}
;
+icmp6type : STRING {
+ struct icmptypeent *p;
+
+ if ((p = geticmptypebyname($1,
+ IPPROTO_ICMPV6)) == NULL) {
+ yyerror("unknown ipv6-icmp-type %s", $1);
+ YYERROR;
+ }
+ $$ = p->type + 1;
+ }
+ | NUMBER {
+ if ($1 < 0 || $1 > 255) {
+ yyerror("illegal icmp6 type %d", $1);
+ YYERROR;
+ }
+ $$ = $1 + 1;
+ }
+ ;
keep : /* empty */ { $$ = 0; }
| KEEP STATE { $$ = PF_STATE_NORMAL; }
@@ -532,15 +684,30 @@ natrule : NAT interface proto FROM ipspec TO ipspec ARROW address
nat.proto = $3->proto;
free($3);
}
+ if ($5 != NULL && $7 != NULL) {
+ if ($5->af && $7->af && $5->af != $7->af) {
+ yyerror("nat ip versions must match");
+ YYERROR;
+ } else {
+ if ($5->af)
+ nat.af = $5->af;
+ else if ($7->af)
+ nat.af = $7->af;
+ }
+ }
if ($5 != NULL) {
- nat.saddr = $5->addr;
- nat.smask = $5->mask;
+ memcpy(&nat.saddr, &$5->addr,
+ sizeof(nat.saddr));
+ memcpy(&nat.smask, &$5->mask,
+ sizeof(nat.smask));
nat.snot = $5->not;
free($5);
}
if ($7 != NULL) {
- nat.daddr = $7->addr;
- nat.dmask = $7->mask;
+ memcpy(&nat.daddr, &$7->addr,
+ sizeof(nat.daddr));
+ memcpy(&nat.dmask, &$7->mask,
+ sizeof(nat.dmask));
nat.dnot = $7->not;
free($7);
}
@@ -549,7 +716,13 @@ natrule : NAT interface proto FROM ipspec TO ipspec ARROW address
yyerror("nat rule requires redirection address");
YYERROR;
}
- nat.raddr = $9->addr;
+ /* we don't support IPv4 <-> IPv6 nat... yet */
+ if (nat.af && $9->af != nat.af) {
+ yyerror("nat ip versions must match");
+ YYERROR;
+ } else
+ nat.af = $9->af;
+ memcpy(&nat.raddr, &$9->addr, sizeof(nat.raddr));
free($9);
pfctl_add_nat(pf, &nat);
}
@@ -573,13 +746,27 @@ binatrule : BINAT interface proto FROM address TO ipspec ARROW address
binat.proto = $3->proto;
free($3);
}
+ if ($5 != NULL && $7 != NULL) {
+ if ($5->af && $7->af && $5->af != $7->af) {
+ yyerror("nat ip versions must match");
+ YYERROR;
+ } else {
+ if ($5->af)
+ binat.af = $5->af;
+ else if ($7->af)
+ binat.af = $7->af;
+ }
+ }
if ($5 != NULL) {
- binat.saddr = $5->addr;
+ memcpy(&binat.saddr, &$5->addr,
+ sizeof(binat.saddr));
free($5);
}
if ($7 != NULL) {
- binat.daddr = $7->addr;
- binat.dmask = $7->mask;
+ memcpy(&binat.daddr, &$7->addr,
+ sizeof(binat.daddr));
+ memcpy(&binat.dmask, &$7->mask,
+ sizeof(binat.dmask));
binat.dnot = $7->not;
free($7);
}
@@ -588,7 +775,7 @@ binatrule : BINAT interface proto FROM address TO ipspec ARROW address
yyerror("binat rule requires redirection address");
YYERROR;
}
- binat.raddr = $9->addr;
+ memcpy(&binat.raddr, &$9->addr, sizeof(binat.raddr));
free($9);
pfctl_add_binat(pf, &binat);
}
@@ -612,15 +799,30 @@ rdrrule : RDR interface proto FROM ipspec TO ipspec dport ARROW address rport
rdr.proto = $3->proto;
free($3);
}
+ if ($5 != NULL && $7 != NULL) {
+ if ($5->af && $7->af && $5->af != $7->af) {
+ yyerror("rdr ip versions must match");
+ YYERROR;
+ } else {
+ if ($5->af)
+ rdr.af = $5->af;
+ else if ($7->af)
+ rdr.af = $7->af;
+ }
+ }
if ($5 != NULL) {
- rdr.saddr = $5->addr;
- rdr.smask = $5->mask;
+ memcpy(&rdr.saddr, &$5->addr,
+ sizeof(rdr.saddr));
+ memcpy(&rdr.smask, &$5->mask,
+ sizeof(rdr.smask));
rdr.snot = $5->not;
free($5);
}
if ($7 != NULL) {
- rdr.daddr = $7->addr;
- rdr.dmask = $7->mask;
+ memcpy(&rdr.daddr, &$7->addr,
+ sizeof(rdr.daddr));
+ memcpy(&rdr.dmask, &$7->mask,
+ sizeof(rdr.dmask));
rdr.dnot = $7->not;
free($7);
}
@@ -633,7 +835,12 @@ rdrrule : RDR interface proto FROM ipspec TO ipspec dport ARROW address rport
yyerror("rdr rule requires redirection address");
YYERROR;
}
- rdr.raddr = $10->addr;
+ if (rdr.af && $10->af != rdr.af) {
+ yyerror("rdr ip versions must match");
+ YYERROR;
+ } else
+ rdr.af = $10->af;
+ memcpy(&rdr.raddr, &$10->addr, sizeof(rdr.raddr));
free($10);
rdr.rport = $11.a;
@@ -726,10 +933,20 @@ rule_consistent(struct pf_rule *r)
yyerror("port only applies to tcp/udp");
problems++;
}
- if (r->proto != IPPROTO_ICMP && (r->type || r->code)) {
+ if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
+ (r->type || r->code)) {
yyerror("icmp-type/code only applies to icmp");
problems++;
}
+ if (!r->af && (r->type || r->code)) {
+ yyerror("must indicate address family with icmp-type/code");
+ problems++;
+ }
+ if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
+ (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
+ yyerror("icmp version does not match address family");
+ problems++;
+ }
if (r->keep_state == PF_STATE_MODULATE && r->proto &&
r->proto != IPPROTO_TCP) {
yyerror("modulate state can only be applied to TCP rules");
@@ -761,10 +978,12 @@ rule_consistent(struct pf_rule *r)
void expand_rule_hosts(struct pf_rule *r,
struct node_if *interface, struct node_proto *proto,
struct node_host *src_hosts, struct node_port *src_ports,
- struct node_host *dst_hosts, struct node_port *dst_ports)
+ struct node_host *dst_hosts, struct node_port *dst_ports,
+ struct node_icmp *icmp_type)
{
struct node_host *src_host, *dst_host;
struct node_port *src_port, *dst_port;
+ int nomatch = 0;
src_host = src_hosts;
while (src_host != NULL) {
@@ -789,7 +1008,28 @@ void expand_rule_hosts(struct pf_rule *r,
r->dst.port[0] = dst_port->port[0];
r->dst.port[1] = dst_port->port[1];
r->dst.port_op = dst_port->op;
- if (rule_consistent(r) < 0)
+ r->type = icmp_type->type;
+ r->code = icmp_type->code;
+
+ if (src_host->af &&
+ dst_host->af &&
+ (src_host->af !=
+ dst_host->af)) {
+ yyerror("address family"
+ " mismatch");
+ nomatch++;
+ } else if (src_host->af)
+ r->af = src_host->af;
+ else if (dst_host->af)
+ r->af = dst_host->af;
+
+ if (icmp_type->proto &&
+ r->proto != icmp_type->proto) {
+ yyerror("icmp-type mismatch");
+ nomatch++;
+ }
+
+ if (rule_consistent(r) < 0 || nomatch)
yyerror("skipping rule "
"due to errors");
else
@@ -807,14 +1047,20 @@ void expand_rule_hosts(struct pf_rule *r,
void expand_rule_protos(struct pf_rule *r,
struct node_if *interface, struct node_proto *protos,
struct node_host *src_hosts, struct node_port *src_ports,
- struct node_host *dst_hosts, struct node_port *dst_ports)
+ struct node_host *dst_hosts, struct node_port *dst_ports,
+ struct node_icmp *icmp_types)
{
struct node_proto *proto;
+ struct node_icmp *icmp_type;
proto = protos;
while (proto != NULL) {
- expand_rule_hosts(r, interface, proto, src_hosts,
- src_ports, dst_hosts, dst_ports);
+ icmp_type = icmp_types;
+ while (icmp_type != NULL) {
+ expand_rule_hosts(r, interface, proto, src_hosts,
+ src_ports, dst_hosts, dst_ports, icmp_type);
+ icmp_type = icmp_type->next;
+ }
proto = proto->next;
}
}
@@ -823,7 +1069,8 @@ void
expand_rule(struct pf_rule *r,
struct node_if *interfaces, struct node_proto *protos,
struct node_host *src_hosts, struct node_port *src_ports,
- struct node_host *dst_hosts, struct node_port *dst_ports)
+ struct node_host *dst_hosts, struct node_port *dst_ports,
+ struct node_icmp *icmp_types)
{
struct node_if *interface;
@@ -833,11 +1080,12 @@ expand_rule(struct pf_rule *r,
CHECK_ROOT(struct node_port, src_ports);
CHECK_ROOT(struct node_host, dst_hosts);
CHECK_ROOT(struct node_port, dst_ports);
+ CHECK_ROOT(struct node_icmp, icmp_types);
interface = interfaces;
while (interface != NULL) {
expand_rule_protos(r, interface, protos, src_hosts,
- src_ports, dst_hosts, dst_ports);
+ src_ports, dst_hosts, dst_ports, icmp_types);
interface = interface->next;
}
@@ -847,6 +1095,8 @@ expand_rule(struct pf_rule *r,
FREE_LIST(struct node_port, src_ports);
FREE_LIST(struct node_host, dst_hosts);
FREE_LIST(struct node_port, dst_ports);
+ FREE_LIST(struct node_icmp, icmp_types);
+
}
#undef FREE_LIST
@@ -868,7 +1118,10 @@ lookup(char *s)
{ "flags", FLAGS},
{ "from", FROM},
{ "icmp-type", ICMPTYPE},
+ { "ipv6-icmp-type", ICMP6TYPE},
{ "in", IN},
+ { "inet", INET},
+ { "inet6", INET6},
{ "keep", KEEP},
{ "log", LOG},
{ "log-all", LOGALL},
@@ -885,6 +1138,7 @@ lookup(char *s)
{ "rdr", RDR},
{ "return", RETURN},
{ "return-icmp",RETURNICMP},
+ { "return-icmp6",RETURNICMP6},
{ "return-rst", RETURNRST},
{ "scrub", SCRUB},
{ "state", STATE},
@@ -1085,6 +1339,42 @@ top:
break;
}
+ /* Need to parse v6 addresses before tokenizing numbers. ick */
+ if (isxdigit(c) || c == ':') {
+ struct node_host *node = NULL;
+ u_int32_t addr[4];
+ char lookahead[46];
+ int i = 0, notv6addr = 0;
+
+ lookahead[i] = c;
+
+ while (i < sizeof(lookahead) &&
+ (isxdigit(c) || c == ':' || c == '.')) {
+ lookahead[++i] = c = lgetc(fin);
+ }
+
+ /* quick check avoids calling inet_pton too often */
+ if (isalnum(c)) {
+ notv6addr++;
+ }
+ lungetc(lookahead[i], fin);
+ lookahead[i] = '\0';
+
+ if(!notv6addr && inet_pton(AF_INET6, lookahead, &addr) == 1) {
+ node = calloc(1, sizeof(struct node_host));
+ node->af = AF_INET6;
+ memcpy (&node->addr, &addr, sizeof(addr));
+ yylval.v.host = node;
+ return IPV6ADDR;
+ } else {
+ free(node);
+ while (i > 1) {
+ lungetc(lookahead[--i], fin);
+ }
+ c = lookahead[--i];
+ }
+ }
+
if (isdigit(c)) {
int index = 0, base = 10;
u_int64_t n = 0;
@@ -1181,15 +1471,18 @@ parse_nat(FILE *input, struct pfctl *xpf)
return (errors ? -1 : 0);
}
-u_int32_t
-ipmask(u_int8_t b)
+void
+ipmask(struct pf_addr *m, u_int8_t b, int af)
{
- u_int32_t m = 0;
- int i;
+ int i, j = 0;
+ while (b >= 32) {
+ m->addr32[j++] = 0xffffffff;
+ b -= 32;
+ }
for (i = 31; i > 31-b; --i)
- m |= (1 << i);
- return (htonl(m));
+ m->addr32[j] |= (1 << i);
+ m->addr32[j] = htonl(m->addr32[j]);
}
struct pf_rule_addr *
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 859d9402b5b..b85403aadc2 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.47 2001/09/06 18:05:46 jasoni Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.48 2001/09/15 03:54:40 frantzen Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -37,6 +37,7 @@
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
#define TCPSTATES
#include <netinet/tcp_fsm.h>
#include <net/pfvar.h>
@@ -53,8 +54,9 @@
#include "pfctl_parser.h"
-void print_addr (u_int32_t);
-void print_host (struct pf_state_host *);
+int unmask (struct pf_addr *, int);
+void print_addr (struct pf_addr *, struct pf_addr *, int);
+void print_host (struct pf_state_host *, int);
void print_seq (struct pf_state_peer *);
void print_port (u_int8_t, u_int16_t, u_int16_t, char *);
void print_flags (u_int8_t);
@@ -90,6 +92,35 @@ struct icmptypeent icmp_type[] = {
};
+struct icmptypeent icmp6_type[] = {
+ { "unreach", ICMP6_DST_UNREACH },
+ { "toobig", ICMP6_PACKET_TOO_BIG },
+ { "timex", ICMP6_TIME_EXCEEDED },
+ { "paramprob", ICMP6_PARAM_PROB },
+ { "echoreq", ICMP6_ECHO_REQUEST },
+ { "echorep", ICMP6_ECHO_REPLY },
+ { "groupqry", ICMP6_MEMBERSHIP_QUERY },
+ { "listqry", MLD6_LISTENER_QUERY },
+ { "grouprep", ICMP6_MEMBERSHIP_REPORT },
+ { "listenrep", MLD6_LISTENER_REPORT },
+ { "groupterm", ICMP6_MEMBERSHIP_REDUCTION },
+ { "listendone", MLD6_LISTENER_DONE },
+ { "routersol", ND_ROUTER_SOLICIT },
+ { "routeradv", ND_ROUTER_ADVERT },
+ { "neighbrsol", ND_NEIGHBOR_SOLICIT },
+ { "neighbradv", ND_NEIGHBOR_ADVERT },
+ { "redir", ND_REDIRECT },
+ { "routrrenum", ICMP6_ROUTER_RENUMBERING },
+ { "wrureq", ICMP6_WRUREQUEST },
+ { "wrurep", ICMP6_WRUREPLY },
+ { "fqdnreq", ICMP6_FQDN_QUERY },
+ { "fqdnrep", ICMP6_FQDN_REPLY },
+ { "niqry", ICMP6_NI_QUERY },
+ { "nirep", ICMP6_NI_REPLY },
+ { "mtraceresp", MLD6_MTRACE_RESP },
+ { "mtrace", MLD6_MTRACE }
+};
+
struct icmpcodeent icmp_code[] = {
{ "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET },
{ "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST },
@@ -123,69 +154,154 @@ struct icmpcodeent icmp_code[] = {
{ "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED }
};
+struct icmpcodeent icmp6_code[] = {
+ { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE },
+ { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN },
+ { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR },
+ { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE },
+ { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR },
+ { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT },
+ { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT },
+ { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY },
+ { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER },
+ { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER },
+ { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK },
+ { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER }
+};
+
+
struct icmptypeent *
-geticmptypebynumber(u_int8_t type)
+geticmptypebynumber(u_int8_t type, u_int8_t proto)
{
unsigned i;
- for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
- if(type == icmp_type[i].type)
- return (&icmp_type[i]);
+ if (proto == IPPROTO_ICMP) {
+ for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
+ if(type == icmp_type[i].type)
+ return (&icmp_type[i]);
+ }
+ } else {
+ for(i=0; i < (sizeof (icmp6_type) /
+ sizeof(icmp6_type[0])); i++) {
+ if(type == icmp6_type[i].type)
+ return (&icmp6_type[i]);
+ }
}
- return (0);
+ return (NULL);
}
struct icmptypeent *
-geticmptypebyname(char *w)
+geticmptypebyname(char *w, u_int8_t proto)
{
unsigned i;
- for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
- if(!strcmp(w, icmp_type[i].name))
- return (&icmp_type[i]);
+ if (proto == IPPROTO_ICMP) {
+ for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
+ if(!strcmp(w, icmp_type[i].name))
+ return (&icmp_type[i]);
+ }
+ } else {
+ for(i=0; i < (sizeof (icmp6_type) /
+ sizeof(icmp6_type[0])); i++) {
+ if(!strcmp(w, icmp6_type[i].name))
+ return (&icmp6_type[i]);
+ }
}
- return (0);
+ return (NULL);
}
struct icmpcodeent *
-geticmpcodebynumber(u_int8_t type, u_int8_t code)
+geticmpcodebynumber(u_int8_t type, u_int8_t code, u_int8_t proto)
{
unsigned i;
- for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
- if (type == icmp_code[i].type && code == icmp_code[i].code)
- return (&icmp_code[i]);
+ if (proto == IPPROTO_ICMP) {
+ for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
+ if (type == icmp_code[i].type &&
+ code == icmp_code[i].code)
+ return (&icmp_code[i]);
+ }
+ } else {
+ for(i=0; i < (sizeof (icmp6_code) /
+ sizeof(icmp6_code[0])); i++) {
+ if (type == icmp6_code[i].type &&
+ code == icmp6_code[i].code)
+ return (&icmp6_code[i]);
+ }
}
- return (0);
+ return (NULL);
}
struct icmpcodeent *
-geticmpcodebyname(u_long type, char *w)
+geticmpcodebyname(u_long type, char *w, u_int8_t proto)
{
unsigned i;
- for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
- if (type == icmp_code[i].type && !strcmp(w, icmp_code[i].name))
- return (&icmp_code[i]);
+ if (proto == IPPROTO_ICMP) {
+ for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
+ if (type == icmp_code[i].type &&
+ !strcmp(w, icmp_code[i].name))
+ return (&icmp_code[i]);
+ }
+ } else {
+ for(i=0; i < (sizeof (icmp6_code) /
+ sizeof(icmp6_code[0])); i++) {
+ if (type == icmp6_code[i].type &&
+ !strcmp(w, icmp6_code[i].name))
+ return (&icmp6_code[i]);
+ }
+ }
+ return (NULL);
+}
+
+int
+unmask(struct pf_addr *m, int af)
+{
+ int i = 31, j = 0, b = 0, msize;
+ u_int32_t tmp;
+
+ if (af == AF_INET)
+ msize = 1;
+ else
+ msize = 4;
+ while (j < msize && m->addr32[j] == 0xffffffff) {
+ b += 32;
+ j++;
}
- return (0);
+ if (j < msize) {
+ tmp = ntohl(m->addr32[j]);
+ for (i = 31; tmp & (1 << i); --i)
+ b++;
+ }
+ return (b);
}
void
-print_addr(u_int32_t a)
+print_addr(struct pf_addr *addr, struct pf_addr *mask, int af)
{
- a = ntohl(a);
- printf("%u.%u.%u.%u", (a>>24)&255, (a>>16)&255, (a>>8)&255, a&255);
+ char buf[48];
+ const char *bf;
+
+ bf = inet_ntop(af, addr, buf, sizeof(buf));
+ printf("%s", bf);
+ if (mask != NULL) {
+ if (!PF_AZERO(mask, af))
+ printf("/%u", unmask(mask, af));
+ }
}
void
-print_host(struct pf_state_host *h)
+print_host(struct pf_state_host *h, int af)
{
- u_int32_t a = ntohl(h->addr);
u_int16_t p = ntohs(h->port);
- printf("%u.%u.%u.%u:%u", (a>>24)&255, (a>>16)&255, (a>>8)&255, a&255, p);
+ print_addr(&h->addr, NULL, af);
+ if (af == AF_INET)
+ printf(":%u", p);
+ else
+ printf("[%u]", p);
}
+
void
print_seq(struct pf_state_peer *p)
@@ -250,31 +366,23 @@ print_nat(struct pf_nat *n)
printf("%s ", n->ifname);
}
printf("from ");
- if (n->saddr || n->smask) {
+ if (!PF_AZERO(&n->saddr, n->af) || !PF_AZERO(&n->smask, n->af)) {
if (n->snot)
printf("! ");
- print_addr(n->saddr);
- if (n->smask != 0xFFFFFFFF) {
- printf("/");
- print_addr(n->smask);
- }
+ print_addr(&n->saddr, &n->smask, n->af);
printf(" ");
} else
printf("any ");
printf("to ");
- if (n->daddr || n->dmask) {
- if (n->dnot)
+ if (!PF_AZERO(&n->daddr, n->af) || !PF_AZERO(&n->dmask, n->af)) {
+ if (n->snot)
printf("! ");
- print_addr(n->daddr);
- if (n->dmask != 0xFFFFFFFF) {
- printf("/");
- print_addr(n->dmask);
- }
+ print_addr(&n->daddr, &n->dmask, n->af);
printf(" ");
} else
printf("any ");
printf("-> ");
- print_addr(n->raddr);
+ print_addr(&n->raddr, NULL, n->af);
printf(" ");
switch (n->proto) {
case IPPROTO_TCP:
@@ -310,22 +418,18 @@ print_binat(struct pf_binat *b)
break;
}
printf("from ");
- print_addr(b->saddr);
+ print_addr(&b->saddr, NULL, b->af);
printf(" ");
printf("to ");
- if (b->daddr || b->dmask) {
+ if (!PF_AZERO(&b->daddr, b->af) || !PF_AZERO(&b->dmask, b->af)) {
if (b->dnot)
printf("! ");
- print_addr(b->daddr);
- if (b->dmask != 0xFFFFFFFF) {
- printf("/");
- print_addr(b->dmask);
- }
+ print_addr(&b->daddr, &b->dmask, b->af);
printf(" ");
} else
printf("any ");
printf("-> ");
- print_addr(b->raddr);
+ print_addr(&b->raddr, NULL, b->af);
printf("\n");
}
@@ -348,26 +452,18 @@ print_rdr(struct pf_rdr *r)
break;
}
printf("from ");
- if (r->saddr || r->smask) {
+ if (!PF_AZERO(&r->saddr, r->af) || !PF_AZERO(&r->smask, r->af)) {
if (r->snot)
printf("! ");
- print_addr(r->saddr);
- if (r->smask != 0xFFFFFFFF) {
- printf("/");
- print_addr(r->smask);
- }
+ print_addr(&r->saddr, &r->smask, r->af);
printf(" ");
} else
printf("any ");
printf("to ");
- if (r->daddr || r->dmask) {
- if (r->dnot)
+ if (!PF_AZERO(&r->daddr, r->af) || !PF_AZERO(&r->dmask, r->af)) {
+ if (r->snot)
printf("! ");
- print_addr(r->daddr);
- if (r->dmask != 0xFFFFFFFF) {
- printf("/");
- print_addr(r->dmask);
- }
+ print_addr(&r->daddr, &r->dmask, r->af);
printf(" ");
} else
printf("any ");
@@ -375,7 +471,7 @@ print_rdr(struct pf_rdr *r)
if (r->opts & PF_DPORT_RANGE)
printf(":%u", ntohs(r->dport2));
printf(" -> ");
- print_addr(r->raddr);
+ print_addr(&r->raddr, NULL, r->af);
printf(" ");
printf("port %u", ntohs(r->rport));
if (r->opts & PF_RPORT_RANGE)
@@ -407,14 +503,22 @@ print_status(struct pf_status *s)
printf("Misc");
break;
}
- printf("\nBytes In: %-10llu Bytes Out: %-10llu\n",
- s->bcounters[PF_IN], s->bcounters[PF_OUT]);
- printf("Inbound Packets: Passed: %-10llu Dropped: %-10llu\n",
- s->pcounters[PF_IN][PF_PASS],
- s->pcounters[PF_IN][PF_DROP]);
- printf("Outbound Packets: Passed: %-10llu Dropped: %-10llu\n",
- s->pcounters[PF_OUT][PF_PASS],
- s->pcounters[PF_OUT][PF_DROP]);
+ printf("\nBytes In IPv4: %-10llu Bytes Out: %-10llu\n",
+ s->bcounters[0][PF_IN], s->bcounters[0][PF_OUT]);
+ printf(" IPv6: %-10llu Bytes Out: %-10llu\n",
+ s->bcounters[1][PF_IN], s->bcounters[1][PF_OUT]);
+ printf("Inbound Packets IPv4: Passed: %-10llu Dropped: %-10llu\n",
+ s->pcounters[0][PF_IN][PF_PASS],
+ s->pcounters[0][PF_IN][PF_DROP]);
+ printf(" IPv6: Passed: %-10llu Dropped: %-10llu\n",
+ s->pcounters[1][PF_IN][PF_PASS],
+ s->pcounters[1][PF_IN][PF_DROP]);
+ printf("Outbound Packets IPv4: Passed: %-10llu Dropped: %-10llu\n",
+ s->pcounters[0][PF_OUT][PF_PASS],
+ s->pcounters[0][PF_OUT][PF_DROP]);
+ printf(" IPv6: Passed: %-10llu Dropped: %-10llu\n",
+ s->pcounters[1][PF_OUT][PF_PASS],
+ s->pcounters[1][PF_OUT][PF_DROP]);
printf("States: %u\n", s->states);
printf("pf Counters\n");
for (i = 0; i < FCNT_MAX; i++)
@@ -446,6 +550,7 @@ print_state(struct pf_state *s)
case IPPROTO_UDP:
printf("UDP ");
break;
+ case IPPROTO_ICMPV6:
case IPPROTO_ICMP:
printf("ICMP ");
break;
@@ -453,19 +558,20 @@ print_state(struct pf_state *s)
printf("???? ");
break;
}
- if ((s->lan.addr != s->gwy.addr) || (s->lan.port != s->gwy.port)) {
- print_host(&s->lan);
+ if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
+ (s->lan.port != s->gwy.port)) {
+ print_host(&s->lan, s->af);
if (s->direction == PF_OUT)
printf(" -> ");
else
printf(" <- ");
}
- print_host(&s->gwy);
+ print_host(&s->gwy, s->af);
if (s->direction == PF_OUT)
printf(" -> ");
else
printf(" <- ");
- print_host(&s->ext);
+ print_host(&s->ext, s->af);
printf(" ");
if (s->proto == IPPROTO_TCP) {
@@ -515,7 +621,7 @@ print_rule(struct pf_rule *r)
printf("return-icmp");
ic = geticmpcodebynumber(r->return_icmp >> 8,
- r->return_icmp & 255);
+ r->return_icmp & 255, r->proto);
if ((ic == NULL) || (ic->type != ICMP_UNREACH))
printf("(%u,%u) ", r->return_icmp >> 8,
r->return_icmp & 255);
@@ -538,6 +644,12 @@ print_rule(struct pf_rule *r)
printf("quick ");
if (r->ifname[0])
printf("on %s ", r->ifname);
+ if (r->af) {
+ if (r->af == AF_INET)
+ printf("inet ");
+ else
+ printf("inet6 ");
+ }
if (r->proto) {
struct protoent *p = getprotobynumber(r->proto);
if (p != NULL)
@@ -545,20 +657,20 @@ print_rule(struct pf_rule *r)
else
printf("proto %u ", r->proto);
}
- if (!r->src.addr && !r->src.mask && !r->src.port_op && !r->dst.addr && ! r->dst.mask && !r->dst.port_op)
+ if (PF_AZERO(&r->src.addr, AF_INET6) &&
+ PF_AZERO(&r->src.mask, AF_INET6) &&
+ !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 (!r->src.addr && !r->src.mask)
+ if (PF_AZERO(&r->src.addr, AF_INET6) &&
+ PF_AZERO(&r->src.mask, AF_INET6))
printf("any ");
else {
if (r->src.not)
printf("! ");
- print_addr(r->src.addr);
- if (r->src.mask != 0xFFFFFFFF) {
- printf("/");
- print_addr(r->src.mask);
- }
+ print_addr(&r->src.addr, &r->src.mask, r->af);
printf(" ");
}
if (r->src.port_op)
@@ -567,16 +679,13 @@ print_rule(struct pf_rule *r)
r->proto == IPPROTO_TCP ? "tcp" : "udp");
printf("to ");
- if (!r->dst.addr && !r->dst.mask)
+ if (PF_AZERO(&r->dst.addr, AF_INET6) &&
+ PF_AZERO(&r->dst.mask, AF_INET6))
printf("any ");
else {
if (r->dst.not)
printf("! ");
- print_addr(r->dst.addr);
- if (r->dst.mask != 0xFFFFFFFF) {
- printf("/");
- print_addr(r->dst.mask);
- }
+ print_addr(&r->dst.addr, &r->dst.mask, r->af);
printf(" ");
}
if (r->dst.port_op)
@@ -594,7 +703,7 @@ print_rule(struct pf_rule *r)
if (r->type) {
struct icmptypeent *p;
- p = geticmptypebynumber(r->type-1);
+ p = geticmptypebynumber(r->type-1, r->proto);
if (p != NULL)
printf("icmp-type %s ", p->name);
else
@@ -602,7 +711,7 @@ print_rule(struct pf_rule *r)
if (r->code) {
struct icmpcodeent *p;
- p = geticmpcodebynumber(r->type-1, r->code-1);
+ p = geticmpcodebynumber(r->type-1, r->code-1, r->proto);
if (p != NULL)
printf("code %s ", p->name);
else
@@ -625,13 +734,13 @@ int
parse_flags(char *s)
{
char *p, *q;
- u_int8_t f = 0;
+ u_int8_t f = 0;
- for (p = s; *p; p++) {
+ for (p = s; *p; p++) {
if ((q = strchr(tcpflags, *p)) == NULL)
return -1;
else
f |= 1 << (q - tcpflags);
- }
- return (f ? f : 63);
+ }
+ return (f ? f : 63);
}
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index 19ec3c76760..67984ac96fc 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.h,v 1.9 2001/09/06 18:05:46 jasoni Exp $ */
+/* $OpenBSD: pfctl_parser.h,v 1.10 2001/09/15 03:54:40 frantzen Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -69,9 +69,9 @@ struct icmpcodeent {
u_int8_t code;
};
-struct icmptypeent *geticmptypebynumber(u_int8_t);
-struct icmptypeent *geticmptypebyname(char *);
-struct icmpcodeent *geticmpcodebynumber(u_int8_t, u_int8_t);
-struct icmpcodeent *geticmpcodebyname(u_long, char *);
+struct icmptypeent *geticmptypebynumber(u_int8_t, u_int8_t);
+struct icmptypeent *geticmptypebyname(char *, u_int8_t);
+struct icmpcodeent *geticmpcodebynumber(u_int8_t, u_int8_t, u_int8_t);
+struct icmpcodeent *geticmpcodebyname(u_long, char *, u_int8_t);
#endif /* _PFCTL_PARSER_H_ */