summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/pfctl/pfctl_parser.c54
-rw-r--r--sys/net/pf.c98
-rw-r--r--sys/net/pfvar.h9
-rw-r--r--sys/netinet/ip_icmp.c9
-rw-r--r--sys/sys/mbuf.h3
5 files changed, 117 insertions, 56 deletions
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 074407a5640..082719c69d3 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.24 2001/07/01 17:16:02 kjell Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.25 2001/07/01 23:04:45 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -405,12 +405,26 @@ print_rule(struct pf_rule *r)
printf("@%d ", r->nr + 1);
if (r->action == PF_PASS)
printf("pass ");
- else if (r->action == PF_DROP || r->action == PF_DROP_RST)
+ else if (r->action == PF_DROP) {
printf("block ");
- else
+ if (r->return_rst)
+ printf("return-rst ");
+ else if (r->return_icmp) {
+ struct icmpcodeent *ic;
+
+ printf("return-icmp");
+ ic = geticmpcodebynumber(r->return_icmp >> 8,
+ r->return_icmp & 255);
+ if ((ic == NULL) || (ic->type != ICMP_UNREACH))
+ printf("(%u,%u) ", r->return_icmp >> 8,
+ r->return_icmp & 255);
+ else if (ic->code != ICMP_UNREACH_PORT)
+ printf("(%s) ", ic->name);
+ else
+ printf(" ");
+ }
+ } else
printf("scrub ");
- if (r->action == 2)
- printf("return-rst ");
if (r->direction == 0)
printf("in ");
else
@@ -626,10 +640,32 @@ parse_rule(int n, char *l, struct pf_rule *r)
}
w = next_word(&l);
- /* return-rst */
- if ((r->action == PF_DROP) && !strcmp(w, "return-rst")) {
- r->action = PF_DROP_RST;
- w = next_word(&l);
+ /* return-rst/return-icmp */
+ if (r->action == PF_DROP) {
+ if (!strcmp(w, "return-rst")) {
+ r->return_rst = 1;
+ w = next_word(&l);
+ } else if (!strncmp(w, "return-icmp", 11)) {
+ w += 11;
+ if ((strlen(w) > 2) && (w[0] == '(') &&
+ (w[strlen(w)-1] == ')')) {
+ struct icmpcodeent *ic;
+
+ w[strlen(w)-1] = 0;
+ w++;
+ ic = geticmpcodebyname(ICMP_UNREACH, w);
+ if (ic == NULL) {
+ error(n, "expected icmp code, got %s\n",
+ w);
+ return (0);
+ }
+ r->return_icmp = ic->type << 8;
+ r->return_icmp |= ic->code;
+ } else
+ r->return_icmp = (ICMP_UNREACH << 8) |
+ ICMP_UNREACH_PORT;
+ w = next_word(&l);
+ }
}
/* in / out */
diff --git a/sys/net/pf.c b/sys/net/pf.c
index acd5f1de851..b32f26807b2 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.91 2001/07/01 17:16:03 kjell Exp $ */
+/* $OpenBSD: pf.c,v 1.92 2001/07/01 23:04:44 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -177,8 +177,8 @@ void pf_change_a(u_int32_t *, u_int16_t *, u_int32_t);
void pf_change_icmp(u_int32_t *, u_int16_t *, u_int32_t *,
u_int32_t, u_int16_t, u_int16_t *, u_int16_t *,
u_int16_t *, u_int16_t *);
-void pf_send_reset(int, struct ifnet *, struct ip *, int,
- struct tcphdr *);
+void pf_send_reset(struct ip *, int, struct tcphdr *);
+void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t);
int pf_match_addr(u_int8_t, u_int32_t, u_int32_t,
u_int32_t);
int pf_match_port(u_int8_t, u_int16_t, u_int16_t,
@@ -1203,10 +1203,10 @@ pf_change_icmp(u_int32_t *ia, u_int16_t *ip, u_int32_t *oa, u_int32_t na,
}
void
-pf_send_reset(int direction, struct ifnet *ifp, struct ip *h, int off,
- struct tcphdr *th)
+pf_send_reset(struct ip *h, int off, struct tcphdr *th)
{
struct mbuf *m;
+ struct m_tag *mtag;
int len = sizeof(struct ip) + sizeof(struct tcphdr);
struct ip *h2;
struct tcphdr *th2;
@@ -1216,9 +1216,13 @@ pf_send_reset(int direction, struct ifnet *ifp, struct ip *h, int off,
return;
/* create outgoing mbuf */
+ mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
+ if (mtag == NULL)
+ return;
m = m_gethdr(M_DONTWAIT, MT_HEADER);
if (m == NULL)
return;
+ m_tag_prepend(m, mtag);
m->m_data += max_linkhdr;
m->m_pkthdr.len = m->m_len = len;
m->m_pkthdr.rcvif = NULL;
@@ -1260,33 +1264,23 @@ pf_send_reset(int direction, struct ifnet *ifp, struct ip *h, int off,
/* IP header checksum */
h2->ip_sum = in_cksum(m, sizeof(struct ip));
- if (direction == PF_IN) {
- /* set up route and send RST out through the same interface */
- struct route iproute;
- struct route *ro = &iproute;
- struct sockaddr_in *dst;
- int error;
-
- bzero(ro, sizeof(*ro));
- dst = (struct sockaddr_in *)&ro->ro_dst;
- dst->sin_family = AF_INET;
- dst->sin_addr = h2->ip_dst;
- dst->sin_len = sizeof(*dst);
- rtalloc(ro);
- if (ro->ro_rt != NULL)
- ro->ro_rt->rt_use++;
- error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
- ro->ro_rt);
- } else {
- /* send RST through the loopback interface */
- struct sockaddr_in dst;
+ ip_output(m, NULL, NULL, 0, NULL);
+}
- dst.sin_family = AF_INET;
- dst.sin_addr = h2->ip_dst;
- dst.sin_len = sizeof(struct sockaddr_in);
- m->m_pkthdr.rcvif = ifp;
- looutput(lo0ifp, m, sintosa(&dst), NULL);
- }
+void
+pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code)
+{
+ struct m_tag *mtag;
+ struct mbuf *m0;
+
+ mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
+ if (mtag == NULL)
+ return;
+ m0 = m_copy(m, 0, M_COPYALL);
+ if (m0 == NULL)
+ return;
+ m_tag_prepend(m0, mtag);
+ icmp_error(m0, type, code, 0, 0);
}
int
@@ -1442,7 +1436,8 @@ pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf *m,
if (rm->log)
PFLOG_PACKET(h, m, AF_INET, direction, reason, rm);
- if (rm->action == PF_DROP_RST) {
+ if ((rm->action == PF_DROP) &&
+ (rm->return_rst || rm->return_icmp)) {
/* undo NAT/RST changes, if they have taken place */
if (nat != NULL) {
pf_change_ap(&h->ip_src.s_addr, &th->th_sport,
@@ -1454,9 +1449,11 @@ pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf *m,
&h->ip_sum, &th->th_sum, baddr, bport);
rewrite++;
}
-
- pf_send_reset(direction, ifp, h, off, th);
- return (PF_DROP);
+ if (rm->return_rst)
+ pf_send_reset(h, off, th);
+ else
+ pf_send_icmp(m, rm->return_icmp >> 8,
+ rm->return_icmp & 255);
}
if (rm->action == PF_DROP)
@@ -1594,7 +1591,26 @@ pf_test_udp(int direction, struct ifnet *ifp, struct mbuf *m,
if (rm->log)
PFLOG_PACKET(h, m, AF_INET, direction, reason, rm);
- if (rm->action != PF_PASS)
+ if ((rm->action == PF_DROP) && rm->return_icmp) {
+ struct mbuf *m0;
+ struct m_tag *mtag;
+
+ /* undo NAT/RST changes, if they have taken place */
+ if (nat != NULL) {
+ pf_change_ap(&h->ip_src.s_addr, &uh->uh_sport,
+ &h->ip_sum, &uh->uh_sum, baddr, bport);
+ rewrite++;
+ }
+ else if (rdr != NULL) {
+ pf_change_ap(&h->ip_dst.s_addr, &uh->uh_dport,
+ &h->ip_sum, &uh->uh_sum, baddr, bport);
+ rewrite++;
+ }
+ pf_send_icmp(m, rm->return_icmp >> 8,
+ rm->return_icmp & 255);
+ }
+
+ if (rm->action == PF_DROP)
return (PF_DROP);
}
@@ -2081,7 +2097,7 @@ pf_test_state_icmp(int direction, struct ifnet *ifp, struct mbuf *m,
switch (h2.ip_p) {
case IPPROTO_TCP: {
struct tcphdr th;
- u_int32_t seq, end;
+ u_int32_t seq;
struct pf_state *s;
struct pf_tree_key key;
struct pf_state_peer *src, *dst;
@@ -2098,9 +2114,6 @@ pf_test_state_icmp(int direction, struct ifnet *ifp, struct mbuf *m,
return (NULL);
}
seq = ntohl(th.th_seq);
- end = seq + h2.ip_len - ((h2.ip_hl + th.th_off)<<2) +
- ((th.th_flags & TH_SYN) ? 1 : 0) +
- ((th.th_flags & TH_FIN) ? 1 : 0);
key.proto = IPPROTO_TCP;
key.addr[0] = h2.ip_dst;
@@ -2116,7 +2129,7 @@ pf_test_state_icmp(int direction, struct ifnet *ifp, struct mbuf *m,
src = (direction == s->direction) ? &s->dst : &s->src;
dst = (direction == s->direction) ? &s->src : &s->dst;
- if (!SEQ_GEQ(src->seqhi, end) ||
+ if (!SEQ_GEQ(src->seqhi, seq) ||
!SEQ_GEQ(seq, src->seqlo - dst->max_win)) {
printf("pf: BAD ICMP state: ");
@@ -2664,7 +2677,8 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
struct pf_state *s;
int off;
- if (!pf_status.running)
+ if (!pf_status.running ||
+ (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL))
return (PF_PASS);
#ifdef DIAGNOSTIC
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 0ca01b88afb..a60d86fd6ae 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.27 2001/07/01 17:16:03 kjell Exp $ */
+/* $OpenBSD: pfvar.h,v 1.28 2001/07/01 23:04:44 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -37,7 +37,7 @@
#include <sys/queue.h>
enum { PF_IN=0, PF_OUT=1 };
-enum { PF_PASS=0, PF_DROP=1, PF_DROP_RST=2, PF_SCRUB=3 };
+enum { PF_PASS=0, PF_DROP=1, PF_SCRUB=2 };
enum { PF_OP_GL=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 };
@@ -56,6 +56,9 @@ struct pf_rule {
struct pf_rule_addr dst;
TAILQ_ENTRY(pf_rule) entries;
+ u_int16_t nr;
+ u_int16_t return_icmp;
+
u_int8_t action;
u_int8_t direction;
u_int8_t log;
@@ -68,7 +71,7 @@ struct pf_rule {
u_int8_t flags;
u_int8_t flagset;
- u_int16_t nr;
+ u_int8_t return_rst;
};
struct pf_state_host {
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index cc4eb966601..2e38599bfd1 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_icmp.c,v 1.39 2001/06/29 18:08:39 provos Exp $ */
+/* $OpenBSD: ip_icmp.c,v 1.40 2001/07/01 23:04:44 dhartmei Exp $ */
/* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */
/*
@@ -127,6 +127,7 @@ icmp_error(n, type, code, dest, destifp)
register unsigned oiplen = oip->ip_hl << 2;
register struct icmp *icp;
struct mbuf *m;
+ struct m_tag *mtag;
unsigned icmplen, mblen;
#ifdef ICMPPRINTFS
@@ -247,6 +248,12 @@ icmp_error(n, type, code, dest, destifp)
nip->ip_p = IPPROTO_ICMP;
nip->ip_src = oip->ip_src;
nip->ip_dst = oip->ip_dst;
+ /* move PF_GENERATED m_tag to new packet, if it exists */
+ mtag = m_tag_find(n, PACKET_TAG_PF_GENERATED, NULL);
+ if (mtag != NULL) {
+ m_tag_unlink(n, mtag);
+ m_tag_prepend(m, mtag);
+ }
icmp_reflect(m);
freeit:
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index ed3d948784f..c7638afa64b 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mbuf.h,v 1.48 2001/06/27 03:49:55 angelos Exp $ */
+/* $OpenBSD: mbuf.h,v 1.49 2001/07/01 23:04:44 dhartmei Exp $ */
/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */
/*
@@ -595,6 +595,7 @@ struct m_tag *m_tag_next __P((struct mbuf *, struct m_tag *));
#define PACKET_TAG_GIF 8 /* GIF processing done */
#define PACKET_TAG_GRE 9 /* GRE processing done */
#define PACKET_TAG_IN_PACKET_CHECKSUM 10 /* NIC checksumming done */
+#define PACKET_TAG_PF_GENERATED 11 /* PF generated, pass always */
#ifdef MBTYPES
int mbtypes[] = { /* XXX */