summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordhartmei <dhartmei@openbsd.org>2001-08-11 12:04:59 +0000
committerdhartmei <dhartmei@openbsd.org>2001-08-11 12:04:59 +0000
commitae58c8ac5920a8830fb6fb32809d61bde09297fd (patch)
tree1826a82bcde2b2ff2c8270709747442ced080903
parentSome fixes from NetBSD. (diff)
downloadwireguard-openbsd-ae58c8ac5920a8830fb6fb32809d61bde09297fd.tar.xz
wireguard-openbsd-ae58c8ac5920a8830fb6fb32809d61bde09297fd.zip
Add support for ICMP errors referring to ICMP queries/replies. Fixes
'ICMP error message for bad proto' messages. Reported by Mark Grimes and Steve Rumble. Add debugging level with ioctl interface and pfctl switch. Default is 'None'.
-rw-r--r--sbin/pfctl/pfctl.813
-rw-r--r--sbin/pfctl/pfctl.c56
-rw-r--r--sbin/pfctl/pfctl_parser.c17
-rw-r--r--sys/net/pf.c169
-rw-r--r--sys/net/pf_norm.c4
-rw-r--r--sys/net/pfvar.h6
6 files changed, 203 insertions, 62 deletions
diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8
index eb01bc71a6f..9fa525bdd20 100644
--- a/sbin/pfctl/pfctl.8
+++ b/sbin/pfctl/pfctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pfctl.8,v 1.26 2001/08/03 16:03:02 mpech Exp $
+.\" $OpenBSD: pfctl.8,v 1.27 2001/08/11 12:05:00 dhartmei Exp $
.\"
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
.\"
@@ -38,6 +38,7 @@
.Op Fl N Ar file
.Op Fl R Ar file
.Op Fl s Ar modifier
+.Op Fl x Ar level
.Sh DESCRIPTION
The
.Nm
@@ -125,6 +126,16 @@ Show all of the above.
.El
.It Fl v
Show rules as they are parsed.
+.It Fl x Ar level
+Set the debug level to one of the following.
+Level names may be abbreviated:
+.Bl -tag -width "x urgent " -compact
+.It Fl x Ar none
+Don't generate debug messages.
+.It Fl x Ar urgent
+Generate debug messages only for serious errors.
+.It Fl x Ar misc
+Generate debug messages for various errors.
.El
.Sh FILES
.Bl -tag -width "/etc/nat.conf" -compact
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 79edf2e06e4..b405e19d0f2 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.31 2001/08/11 09:54:59 deraadt Exp $ */
+/* $OpenBSD: pfctl.c,v 1.32 2001/08/11 12:05:00 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -67,6 +67,7 @@ int pfctl_show_status(int);
int pfctl_rules(int, char *, int);
int pfctl_nat(int, char *, int);
int pfctl_log(int, char *, int);
+int pfctl_debug(int, u_int32_t, int);
int opts = 0;
char *clearopt;
@@ -74,6 +75,7 @@ char *logopt;
char *natopt;
char *rulesopt;
char *showopt;
+char *debugopt;
char *infile;
@@ -84,7 +86,7 @@ usage()
fprintf(stderr, "usage: %s [-dehnqv] [-F set] [-l interface] ",
__progname);
- fprintf(stderr, "[-N file] [-R file] [-s set]\n");
+ fprintf(stderr, "[-N file] [-R file] [-s set] [-x level]\n");
exit(1);
}
@@ -383,6 +385,32 @@ pfctl_log(int dev, char *ifname, int opts)
}
int
+pfctl_debug(int dev, u_int32_t level, int opts)
+{
+ if (ioctl(dev, DIOCSETDEBUG, &level))
+ err(1, "DIOCSETDEBUG");
+ if ((opts & PF_OPT_QUIET) == 0) {
+ printf("debug level set to '");
+ switch (level) {
+ case PF_DEBUG_NONE:
+ printf("none");
+ break;
+ case PF_DEBUG_URGENT:
+ printf("urgent");
+ break;
+ case PF_DEBUG_MISC:
+ printf("misc");
+ break;
+ default:
+ printf("<invalid>");
+ break;
+ }
+ printf("'\n");
+ }
+ return (0);
+}
+
+int
main(int argc, char *argv[])
{
extern char *optarg;
@@ -394,7 +422,7 @@ main(int argc, char *argv[])
if (argc < 2)
usage();
- while ((ch = getopt(argc, argv, "deqF:hl:nN:R:s:v")) != -1) {
+ while ((ch = getopt(argc, argv, "deqF:hl:nN:R:s:vx:")) != -1) {
switch (ch) {
case 'd':
opts |= PF_OPT_DISABLE;
@@ -426,6 +454,9 @@ main(int argc, char *argv[])
case 'v':
opts |= PF_OPT_VERBOSE;
break;
+ case 'x':
+ debugopt = optarg;
+ break;
case 'h':
default:
usage();
@@ -446,7 +477,7 @@ main(int argc, char *argv[])
} else {
/* turn off options */
opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
- clearopt = logopt = showopt = NULL;
+ clearopt = logopt = showopt = debugopt = NULL;
}
if (opts & PF_OPT_DISABLE)
@@ -522,6 +553,23 @@ main(int argc, char *argv[])
if (pfctl_enable(dev, opts))
error = 1;
+ if (debugopt != NULL) {
+ switch (*debugopt) {
+ case 'n':
+ pfctl_debug(dev, PF_DEBUG_NONE, opts);
+ break;
+ case 'u':
+ pfctl_debug(dev, PF_DEBUG_URGENT, opts);
+ break;
+ case 'm':
+ pfctl_debug(dev, PF_DEBUG_MISC, opts);
+ break;
+ default:
+ warnx("Unknown debug level '%s'", debugopt);
+ error = 1;
+ }
+ }
+
close(dev);
exit(error);
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index f9f4266eb92..1fff22a4774 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.39 2001/07/19 00:07:36 krw Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.40 2001/08/11 12:05:00 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -348,10 +348,21 @@ print_status(struct pf_status *s)
time_t t = time(NULL);
int i;
- printf("Status: %s Time: %u Since: %u\n",
+ printf("Status: %s Time: %u Since: %u Debug: ",
s->running ? "Enabled" : "Disabled",
t, s->since);
- printf("Bytes In: %-10llu Bytes Out: %-10llu\n",
+ switch (s->debug) {
+ case 0:
+ printf("None");
+ break;
+ case 1:
+ printf("Urgent");
+ break;
+ case 2:
+ 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],
diff --git a/sys/net/pf.c b/sys/net/pf.c
index be4fa7cc86f..909ab981a66 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.122 2001/08/01 23:07:36 provos Exp $ */
+/* $OpenBSD: pf.c,v 1.123 2001/08/11 12:05:00 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -63,8 +63,7 @@
#include "bpfilter.h"
#include "pflog.h"
-int pf_debug = 0;
-#define DPFPRINTF(x) if (pf_debug) printf x
+#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
/*
* Tree data structure
@@ -498,19 +497,22 @@ pf_insert_state(struct pf_state *state)
key.port[1] = state->ext.port;
/* sanity checks can be removed later, should never occur */
if ((s = pf_find_state(tree_lan_ext, &key)) != NULL) {
- printf("pf: ERROR! insert invalid\n");
- printf(" key already in tree_lan_ext\n");
- printf(" key: proto = %u, lan = ", state->proto);
- pf_print_host(key.addr[0].s_addr, key.port[0]);
- printf(", ext = ");
- pf_print_host(key.addr[1].s_addr, key.port[1]);
- printf("\n state: ");
- pf_print_state(s);
- printf("\n");
+ if (pf_status.debug >= PF_DEBUG_URGENT) {
+ printf("pf: ERROR! insert invalid\n");
+ printf(" key already in tree_lan_ext\n");
+ printf(" key: proto = %u, lan = ", state->proto);
+ pf_print_host(key.addr[0].s_addr, key.port[0]);
+ printf(", ext = ");
+ pf_print_host(key.addr[1].s_addr, key.port[1]);
+ printf("\n state: ");
+ pf_print_state(s);
+ printf("\n");
+ }
} else {
pf_tree_insert(&tree_lan_ext, NULL, &key, state);
if (pf_find_state(tree_lan_ext, &key) != state)
- printf("pf: ERROR! insert failed\n");
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf: ERROR! insert failed\n"));
}
key.proto = state->proto;
@@ -519,19 +521,22 @@ pf_insert_state(struct pf_state *state)
key.addr[1].s_addr = state->gwy.addr;
key.port[1] = state->gwy.port;
if ((s = pf_find_state(tree_ext_gwy, &key)) != NULL) {
- printf("pf: ERROR! insert invalid\n");
- printf(" key already in tree_ext_gwy\n");
- printf(" key: proto = %u, ext = ", state->proto);
- pf_print_host(key.addr[0].s_addr, key.port[0]);
- printf(", gwy = ");
- pf_print_host(key.addr[1].s_addr, key.port[1]);
- printf("\n state: ");
- pf_print_state(s);
- printf("\n");
+ if (pf_status.debug >= PF_DEBUG_URGENT) {
+ printf("pf: ERROR! insert invalid\n");
+ printf(" key already in tree_ext_gwy\n");
+ printf(" key: proto = %u, ext = ", state->proto);
+ pf_print_host(key.addr[0].s_addr, key.port[0]);
+ printf(", gwy = ");
+ pf_print_host(key.addr[1].s_addr, key.port[1]);
+ printf("\n state: ");
+ pf_print_state(s);
+ printf("\n");
+ }
} else {
pf_tree_insert(&tree_ext_gwy, NULL, &key, state);
if (pf_find_state(tree_ext_gwy, &key) != state)
- printf("pf: ERROR! insert failed\n");
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf: ERROR! insert failed\n"));
}
pf_status.fcounters[FCNT_STATE_INSERT]++;
pf_status.states++;
@@ -553,10 +558,12 @@ pf_purge_expired_states(void)
key.port[1] = cur->state->ext.port;
/* remove state from second tree */
if (pf_find_state(tree_lan_ext, &key) != cur->state)
- printf("pf: ERROR: remove invalid!\n");
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf: ERROR: remove invalid!\n"));
pf_tree_remove(&tree_lan_ext, NULL, &key);
if (pf_find_state(tree_lan_ext, &key) != NULL)
- printf("pf: ERROR: remove failed\n");
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf: ERROR: remove failed\n"));
if (STATE_TRANSLATE(cur->state))
pf_put_sport(cur->state->proto,
htons(cur->state->gwy.port));
@@ -573,8 +580,8 @@ pf_purge_expired_states(void)
pf_tree_remove(&tree_ext_gwy, NULL, &cur->key);
cur = pf_tree_search(tree_ext_gwy, &key);
if (cur == NULL)
- printf(
- "pf: ERROR: next not refound\n");
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf: ERROR: next not found\n"));
} else {
pf_tree_remove(&tree_ext_gwy, NULL, &cur->key);
cur = NULL;
@@ -733,7 +740,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pf_status.states = states;
microtime(&pftv);
pf_status.since = pftv.tv_sec;
- printf("pf: started\n");
+ DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
}
break;
@@ -742,7 +749,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = ENOENT;
else {
pf_status.running = 0;
- printf("pf: stopped\n");
+ DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
}
break;
@@ -1136,6 +1143,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pf_status.states = states;
break;
}
+
case DIOCNATLOOK: {
struct pf_natlook *pnl = (struct pf_natlook *)addr;
struct pf_state *st;
@@ -1181,6 +1189,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
break;
}
+
+ case DIOCSETDEBUG: {
+ u_int32_t *level = (u_int32_t *)addr;
+ pf_status.debug = *level;
+ break;
+ }
+
default:
error = ENODEV;
break;
@@ -2238,18 +2253,18 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp,
return (PF_PASS);
} else {
- /* XXX Remove these printfs before release */
- printf("pf: BAD state: ");
- pf_print_state(*state);
- pf_print_flags(th->th_flags);
- printf(" seq=%lu ack=%lu len=%u ", seq, ack, len);
- printf("\n");
- printf("State failure: %c %c %c %c\n",
- SEQ_GEQ(src->seqhi, end) ? ' ' : '1',
- SEQ_GEQ(seq, src->seqlo - dst->max_win) ? ' ': '2',
- (ackskew >= -MAXACKWINDOW) ? ' ' : '3',
- (ackskew <= MAXACKWINDOW) ? ' ' : '4');
-
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: BAD state: ");
+ pf_print_state(*state);
+ pf_print_flags(th->th_flags);
+ printf(" seq=%lu ack=%lu len=%u ", seq, ack, len);
+ printf("\n");
+ printf("State failure: %c %c %c %c\n",
+ SEQ_GEQ(src->seqhi, end) ? ' ' : '1',
+ SEQ_GEQ(seq, src->seqlo - dst->max_win) ? ' ': '2',
+ (ackskew >= -MAXACKWINDOW) ? ' ' : '3',
+ (ackskew <= MAXACKWINDOW) ? ' ' : '4');
+ }
return (PF_DROP);
}
}
@@ -2374,7 +2389,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
ipoff2 = off + ICMP_MINLEN; /* offset of h2 in mbuf chain */
if (!pf_pull_hdr(m, ipoff2, &h2, sizeof(h2), NULL, NULL)) {
- printf("pf: ICMP error message too short (ip)\n");
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short (ip)\n"));
return (PF_DROP);
}
@@ -2398,8 +2414,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
* th_seq, an ackskew test is not possible.
*/
if (!pf_pull_hdr(m, off2, &th, 8, NULL, NULL)) {
- printf("pf: "
- "ICMP error message too short (tcp)\n");
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short (tcp)\n"));
return (PF_DROP);
}
seq = ntohl(th.th_seq);
@@ -2427,10 +2443,11 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
if (!SEQ_GEQ(src->seqhi, seq) ||
!SEQ_GEQ(seq, src->seqlo - dst->max_win)) {
-
- printf("pf: BAD ICMP state: ");
- pf_print_state(*state);
- printf(" seq=%lu\n", seq);
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: BAD ICMP state: ");
+ pf_print_state(*state);
+ printf(" seq=%lu\n", seq);
+ }
return (PF_DROP);
}
@@ -2466,7 +2483,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
if (!pf_pull_hdr(m, off2, &uh, sizeof(uh),
NULL, NULL)) {
- printf("pf: ICMP error message too short (udp)\n");
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short (udp)\n"));
return (PF_DROP);
}
@@ -2509,8 +2527,59 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
return (PF_PASS);
break;
}
+ case IPPROTO_ICMP: {
+ struct icmp iih;
+ struct pf_tree_key key;
+
+ if (!pf_pull_hdr(m, off2, &iih, ICMP_MINLEN,
+ NULL, NULL)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short (icmp)\n"));
+ return (PF_DROP);
+ }
+
+ key.proto = IPPROTO_ICMP;
+ key.addr[0] = h2.ip_dst;
+ key.port[0] = iih.icmp_id;
+ key.addr[1] = h2.ip_src;
+ key.port[1] = iih.icmp_id;
+
+ if (direction == PF_IN)
+ *state = pf_find_state(tree_ext_gwy, &key);
+ else
+ *state = pf_find_state(tree_lan_ext, &key);
+ if (*state == NULL)
+ return (PF_DROP);
+
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_IN) {
+ pf_change_icmp(&h2.ip_src.s_addr,
+ &iih.icmp_id, &h->ip_dst.s_addr,
+ (*state)->lan.addr,
+ (*state)->lan.port, NULL,
+ &h2.ip_sum, &ih->icmp_cksum,
+ &h->ip_sum);
+ } else {
+ pf_change_icmp(&h2.ip_dst.s_addr,
+ &iih.icmp_id, &h->ip_src.s_addr,
+ (*state)->gwy.addr,
+ (*state)->gwy.port, NULL,
+ &h2.ip_sum, &ih->icmp_cksum,
+ &h->ip_sum);
+ }
+ m_copyback(m, off, ICMP_MINLEN, (caddr_t)ih);
+ m_copyback(m, ipoff2, sizeof(h2),
+ (caddr_t)&h2);
+ m_copyback(m, off2, ICMP_MINLEN,
+ (caddr_t)&iih);
+ }
+
+ return (PF_PASS);
+ break;
+ }
default:
- printf("pf: ICMP error message for bad proto\n");
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message for bad proto\n"));
return (PF_DROP);
}
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index 53e99c59717..2d847cf497f 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.5 2001/08/02 06:59:25 deraadt Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.6 2001/08/11 12:05:00 dhartmei Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -93,7 +93,7 @@ int pf_normalize_tcp(int, struct ifnet *, struct mbuf *,
#define PFFRAG_FRENT_HIWAT 5000 /* Number of fragment entries */
#define PFFRAG_FRAG_HIWAT 1000 /* Number of fragmented packets */
-#define DPFPRINTF(x) if (pf_debug) printf x
+#define DPFPRINTF(x) if (pf_status.debug) printf x
#if NPFLOG > 0
#define PFLOG_PACKET(x,a,b,c,d,e) \
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index fff97b45bf0..2724ffdc7ce 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.38 2001/08/01 23:07:36 provos Exp $ */
+/* $OpenBSD: pfvar.h,v 1.39 2001/08/11 12:04:59 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -40,6 +40,7 @@ enum { PF_IN=0, PF_OUT=1 };
enum { PF_PASS=0, PF_DROP=1, PF_SCRUB=2 };
enum { PF_OP_IRG=1, PF_OP_EQ=2, PF_OP_NE=3, PF_OP_LT=4,
PF_OP_LE=5, PF_OP_GT=6, PF_OP_GE=7, PF_OP_XRG=8 };
+enum { PF_DEBUG_NONE=0, PF_DEBUG_URGENT=1, PF_DEBUG_MISC=2 };
struct pf_rule_addr {
u_int32_t addr;
@@ -233,6 +234,7 @@ struct pf_status {
u_int32_t running;
u_int32_t states;
u_int32_t since;
+ u_int32_t debug;
};
/*
@@ -293,6 +295,7 @@ struct pfioc_if {
#define DIOCGETSTATUS _IOWR('D', 21, struct pf_status)
#define DIOCCLRSTATUS _IO ('D', 22)
#define DIOCNATLOOK _IOWR('D', 23, struct pf_natlook)
+#define DIOCSETDEBUG _IOWR('D', 24, u_int32_t)
#ifdef _KERNEL
@@ -316,7 +319,6 @@ void pf_purge_expired_fragments(void);
extern struct pf_rulequeue *pf_rules_active;
extern struct pf_status pf_status;
-extern int pf_debug;
#endif /* _KERNEL */
#endif /* _NET_PFVAR_H_ */