summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2002-10-07 13:15:03 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2002-10-07 13:15:03 +0000
commite0065b2ad661965723cdcd0635446e0cc33b3bf6 (patch)
tree4c7d7eb1c52e4218bd4c9fdbb51fe7c9f5ffba72 /sbin
parentd06dba9ad473b167b4612045b483d44682afd80d (diff)
make return-icmp work for rules covering both v4 and v6
-new field "return_icmp6" in pf_rule -parser accepts block return-icmp(ipv4-icmpcode, ipv6-icmpcode) ok and some input dhartmei@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/pfctl/parse.y84
-rw-r--r--sbin/pfctl/pfctl_parser.c50
2 files changed, 81 insertions, 53 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 6f649cfbdae..09a3cb05106 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.159 2002/10/07 12:59:55 henning Exp $ */
+/* $OpenBSD: parse.y,v 1.160 2002/10/07 13:15:02 henning Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -57,6 +57,9 @@ static int debug = 0;
static int lineno = 1;
static int errors = 0;
static int rulestate = 0;
+static u_int16_t returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
+static u_int16_t returnicmp6default = (ICMP6_DST_UNREACH << 8)
+ | ICMP6_DST_UNREACH_NOPORT;
enum {
PFCTL_STATE_NONE = 0,
@@ -195,6 +198,7 @@ void ifa_load(void);
struct node_host *ifa_exists(char *);
struct node_host *ifa_lookup(char *, enum pfctl_iflookup_mode);
struct node_host *ifa_pick_ip(struct node_host *, u_int8_t);
+u_int16_t parseicmpspec(char *, u_int8_t);
typedef struct {
union {
@@ -205,6 +209,7 @@ typedef struct {
u_int8_t b1;
u_int8_t b2;
u_int16_t w;
+ u_int16_t w2;
} b;
struct range {
int a;
@@ -461,6 +466,7 @@ pfrule : action dir logquick interface route af proto fromto
} else {
r.rule_flag |= PFRULE_RETURNICMP;
r.return_icmp = $1.w;
+ r.return_icmp6 = $1.w2;
}
r.direction = $2;
r.log = $3.log;
@@ -560,49 +566,39 @@ action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
| BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; }
;
-blockspec : /* empty */ { $$.b2 = 0; $$.w = 0; }
- | RETURNRST { $$.b2 = 1; $$.w = 0; }
+blockspec : /* empty */ { $$.b2 = 0; $$.w = 0; $$.w2 = 0; }
+ | RETURNRST { $$.b2 = 1; $$.w = 0; $$.w2 = 0; }
| RETURNRST '(' TTL number ')' {
$$.w = $4;
+ $$.w2 = 0;
$$.b2 = 1;
}
| RETURNICMP {
$$.b2 = 0;
- $$.w = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
+ $$.w = returnicmpdefault;
+ $$.w2 = returnicmp6default;
}
| RETURNICMP6 {
$$.b2 = 0;
- $$.w = (ICMP6_DST_UNREACH << 8) |
- ICMP6_DST_UNREACH_NOPORT;
+ $$.w = returnicmpdefault;
+ $$.w2 = returnicmp6default;
}
| RETURNICMP '(' STRING ')' {
- const struct icmpcodeent *p;
- u_long ulval;
-
- if (atoul($3, &ulval) == -1) {
- if ((p = geticmpcodebyname(ICMP_UNREACH, $3,
- AF_INET)) == NULL) {
- yyerror("unknown icmp code %s", $3);
- YYERROR;
- }
- ulval = p->code;
- }
- $$.w = (ICMP_UNREACH << 8) | ulval;
+ if (!($$.w = parseicmpspec($3, AF_INET)))
+ YYERROR;
+ $$.w2 = returnicmp6default;
$$.b2 = 0;
}
| RETURNICMP6 '(' STRING ')' {
- const struct icmpcodeent *p;
- u_long ulval;
-
- if (atoul($3, &ulval) == -1) {
- if ((p = geticmpcodebyname(ICMP6_DST_UNREACH, $3,
- AF_INET6)) == NULL) {
- yyerror("unknown icmp code %s", $3);
- YYERROR;
- }
- ulval = p->code;
- }
- $$.w = (ICMP6_DST_UNREACH << 8) | ulval;
+ $$.w = returnicmpdefault;
+ if (!($$.w2 = parseicmpspec($3, AF_INET6)))
+ YYERROR;
+ $$.b2 = 0;
+ }
+ | RETURNICMP '(' STRING comma STRING ')' {
+ if (!($$.w = parseicmpspec($3, AF_INET)))
+ YYERROR;
+ if (!($$.w2 = parseicmpspec($5, AF_INET6)));
$$.b2 = 0;
}
;
@@ -1778,12 +1774,6 @@ rule_consistent(struct pf_rule *r)
yyerror("icmp version does not match address family");
problems++;
}
- if (!(r->rule_flag & PFRULE_RETURNRST) && r->return_icmp &&
- ((r->af != AF_INET6 && (r->return_icmp>>8) != ICMP_UNREACH) ||
- (r->af == AF_INET6 && (r->return_icmp>>8) != ICMP6_DST_UNREACH))) {
- yyerror("return-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");
@@ -2985,3 +2975,25 @@ getservice(char *n)
return (s->s_port);
}
}
+
+u_int16_t
+parseicmpspec(char *w, u_int8_t af)
+{
+ const struct icmpcodeent *p;
+ u_long ulval;
+ u_int8_t icmptype;
+
+ if (af == AF_INET)
+ icmptype = returnicmpdefault >> 8;
+ else
+ icmptype = returnicmp6default >> 8;
+
+ if (atoul(w, &ulval) == -1) {
+ if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
+ yyerror("unknown icmp code %s", w);
+ return (0);
+ }
+ ulval = p->code;
+ }
+ return (icmptype << 8 | ulval);
+}
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index ba3714ef5fe..3f59537f450 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.96 2002/10/07 12:39:29 dhartmei Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.97 2002/10/07 13:15:02 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -637,25 +637,41 @@ print_rule(struct pf_rule *r)
printf("return-rst ");
else
printf("return-rst(ttl %d) ", r->return_ttl);
- } else if (r->return_icmp) {
- const struct icmpcodeent *ic;
+ } else if (r->rule_flag & PFRULE_RETURNICMP) {
+ const struct icmpcodeent *ic, *ic6;
- if (r->af != AF_INET6)
+ ic = geticmpcodebynumber(r->return_icmp >> 8,
+ r->return_icmp & 255, AF_INET);
+ ic6 = geticmpcodebynumber(r->return_icmp6 >> 8,
+ r->return_icmp6 & 255, AF_INET6);
+
+ switch(r->af) {
+ case AF_INET:
printf("return-icmp");
- else
+ if (ic == NULL)
+ printf("(%u) ", r->return_icmp & 255);
+ else
+ printf("(%s) ", ic->name);
+ break;
+ case AF_INET6:
printf("return-icmp6");
- ic = geticmpcodebynumber(r->return_icmp >> 8,
- r->return_icmp & 255, r->af);
-
- if (ic == NULL)
- printf("(%u) ", r->return_icmp & 255);
- else if ((r->af != AF_INET6 && ic->code !=
- ICMP_UNREACH_PORT) ||
- (r->af == AF_INET6 && ic->code !=
- ICMP6_DST_UNREACH_NOPORT))
- printf("(%s) ", ic->name);
- else
- printf(" ");
+ if (ic6 == NULL)
+ printf("(%u) ", r->return_icmp6 & 255);
+ else
+ printf("(%s) ", ic6->name);
+ break;
+ default:
+ printf("return-icmp");
+ if (ic == NULL)
+ printf("(%u, ", r->return_icmp & 255);
+ else
+ printf("(%s, ", ic->name);
+ if (ic6 == NULL)
+ printf("%u) ", r->return_icmp6 & 255);
+ else
+ printf("%s) ", ic6->name);
+ break;
+ }
}
} else {
printf("scrub ");