summaryrefslogtreecommitdiff
path: root/sys/net/pf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r--sys/net/pf.c334
1 files changed, 163 insertions, 171 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 944a4af3b0a..49c7a11ad29 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.96 2001/07/03 03:34:41 beck Exp $ */
+/* $OpenBSD: pf.c,v 1.97 2001/07/03 04:20:47 deraadt Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -121,29 +121,20 @@ struct timeval pftv;
struct pf_status pf_status;
struct ifnet *status_ifp;
-u_int32_t pf_last_purge = 0;
-u_int32_t ticket_rules_active = 0;
-u_int32_t ticket_rules_inactive = 0;
-u_int32_t ticket_nats_active = 0;
-u_int32_t ticket_nats_inactive = 0;
-u_int32_t ticket_rdrs_active = 0;
-u_int32_t ticket_rdrs_inactive = 0;
+u_int32_t pf_last_purge;
+u_int32_t ticket_rules_active;
+u_int32_t ticket_rules_inactive;
+u_int32_t ticket_nats_active;
+u_int32_t ticket_nats_inactive;
+u_int32_t ticket_rdrs_active;
+u_int32_t ticket_rdrs_inactive;
u_int16_t pf_next_port_tcp = 50001;
u_int16_t pf_next_port_udp = 50001;
-struct pool pf_tree_pl;
-struct pool pf_rule_pl;
-struct pool pf_nat_pl;
-struct pool pf_rdr_pl;
-struct pool pf_state_pl;
-struct pool pf_frent_pl;
-struct pool pf_frag_pl;
+struct pool pf_tree_pl, pf_rule_pl, pf_nat_pl;
+struct pool pf_rdr_pl, pf_state_pl, pf_frent_pl, pf_frag_pl;
int pf_nfrents;
-/*
- * Prototypes
- */
-
int pf_tree_key_compare(struct pf_tree_key *,
struct pf_tree_key *);
void pf_tree_rotate_left(struct pf_tree_node **);
@@ -151,7 +142,7 @@ void pf_tree_rotate_right(struct pf_tree_node **);
int pf_tree_insert(struct pf_tree_node **,
struct pf_tree_node *, struct pf_tree_key *,
struct pf_state *);
-int pf_tree_remove(struct pf_tree_node **,
+int pf_tree_remove(struct pf_tree_node **,
struct pf_tree_node *, struct pf_tree_key *);
struct pf_tree_node *pf_tree_first(struct pf_tree_node *);
struct pf_tree_node *pf_tree_next(struct pf_tree_node *);
@@ -253,9 +244,9 @@ pf_tree_key_compare(struct pf_tree_key *a, struct pf_tree_key *b)
* could use memcmp(), but with the best manual order, we can
* minimize the number of average compares. what is faster?
*/
- if (a->proto < b->proto )
+ if (a->proto < b->proto)
return (-1);
- if (a->proto > b->proto )
+ if (a->proto > b->proto)
return ( 1);
if (a->addr[0].s_addr < b->addr[0].s_addr)
return (-1);
@@ -444,14 +435,14 @@ pflog_packet(struct mbuf *m, int af, u_short dir, u_short reason,
struct pf_rule *rm)
{
#if NBPFILTER > 0
- struct ifnet *ifn, *ifp = NULL;
- struct pfloghdr hdr;
- struct mbuf m1;
+ struct ifnet *ifn, *ifp = NULL;
+ struct pfloghdr hdr;
+ struct mbuf m1;
if (m == NULL)
return(-1);
- hdr.af = htonl(af);
+ hdr.af = htonl(af);
/* Set the right interface name */
if (rm != NULL)
ifp = rm->ifp;
@@ -467,13 +458,13 @@ pflog_packet(struct mbuf *m, int af, u_short dir, u_short reason,
hdr.dir = htons(dir);
hdr.action = htons(rm->action);
- m1.m_next = m;
- m1.m_len = PFLOG_HDRLEN;
- m1.m_data = (char *) &hdr;
+ m1.m_next = m;
+ m1.m_len = PFLOG_HDRLEN;
+ m1.m_data = (char *) &hdr;
ifn = &(pflogif[0].sc_if);
- if (ifn->if_bpf)
+ if (ifn->if_bpf)
bpf_mtap(ifn->if_bpf, &m1);
#endif
@@ -551,7 +542,7 @@ pf_insert_state(struct pf_state *state)
printf("pf: ERROR! insert failed\n");
}
- key.proto = state->proto;
+ key.proto = state->proto;
key.addr[0].s_addr = state->ext.addr;
key.port[0] = state->ext.port;
key.addr[1].s_addr = state->gwy.addr;
@@ -563,7 +554,6 @@ pf_insert_state(struct pf_state *state)
if (pf_find_state(tree_ext_gwy, &key) != state)
printf("pf: ERROR! insert failed\n");
}
-
pf_status.fcounters[FCNT_STATE_INSERT]++;
pf_status.states++;
}
@@ -661,20 +651,20 @@ void
pfattach(int num)
{
/* XXX - no M_* tags, but they are not used anyway */
- pool_init(&pf_tree_pl, sizeof(struct pf_tree_node), 0, 0, 0, "pftrpl",
- 0, NULL, NULL, 0);
- pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
- 0, NULL, NULL, 0);
- pool_init(&pf_nat_pl, sizeof(struct pf_nat), 0, 0, 0, "pfnatpl",
- 0, NULL, NULL, 0);
- pool_init(&pf_rdr_pl, sizeof(struct pf_rdr), 0, 0, 0, "pfrdrpl",
- 0, NULL, NULL, 0);
- pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
- 0, NULL, NULL, 0);
- pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent",
- 0, NULL, NULL, 0);
- pool_init(&pf_frag_pl, sizeof(struct pf_fragment), 0, 0, 0, "pffrag",
- 0, NULL, NULL, 0);
+ pool_init(&pf_tree_pl, sizeof(struct pf_tree_node), 0, 0, 0, "pftrpl",
+ 0, NULL, NULL, 0);
+ pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
+ 0, NULL, NULL, 0);
+ pool_init(&pf_nat_pl, sizeof(struct pf_nat), 0, 0, 0, "pfnatpl",
+ 0, NULL, NULL, 0);
+ pool_init(&pf_rdr_pl, sizeof(struct pf_rdr), 0, 0, 0, "pfrdrpl",
+ 0, NULL, NULL, 0);
+ pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
+ 0, NULL, NULL, 0);
+ pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent",
+ 0, NULL, NULL, 0);
+ pool_init(&pf_frag_pl, sizeof(struct pf_fragment), 0, 0, 0, "pffrag",
+ 0, NULL, NULL, 0);
pool_sethiwat(&pf_frag_pl, PFFRAG_FRAG_HIWAT);
pool_sethardlimit(&pf_frent_pl, PFFRAG_FRENT_HIWAT, NULL, 0);
@@ -1131,6 +1121,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCCLRSTATUS: {
u_int8_t running = pf_status.running;
u_int32_t states = pf_status.states;
+
bzero(&pf_status, sizeof(struct pf_status));
pf_status.running = running;
pf_status.states = states;
@@ -1140,12 +1131,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_natlook *pnl = (struct pf_natlook *)addr;
struct pf_state *st;
struct pf_tree_key key;
- int direction;
-
- direction = pnl->direction;
- key.proto = pnl->proto;
+ int direction = pnl->direction;
+
+ key.proto = pnl->proto;
- /* userland gives us source and dest of connetion, reverse
+ /*
+ * userland gives us source and dest of connetion, reverse
* the lookup so we ask for what happens with the return
* traffic, enabling us to find it in the state tree.
*/
@@ -1154,21 +1145,20 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
key.addr[0].s_addr = pnl->daddr;
key.port[0] = pnl->dport;
- if (!pnl->proto || !pnl->saddr || !pnl->daddr
- || !pnl->dport || !pnl->sport)
+ if (!pnl->proto || !pnl->saddr || !pnl->daddr ||
+ !pnl->dport || !pnl->sport)
error = EINVAL;
else {
s = splsoftnet();
st = pf_find_state((direction == PF_IN) ?
- tree_ext_gwy : tree_lan_ext, &key);
+ tree_ext_gwy : tree_lan_ext, &key);
if (st != NULL) {
if (direction == PF_IN) {
pnl->rsaddr = st->lan.addr;
pnl->rsport = st->lan.port;
pnl->rdaddr = pnl->daddr;
pnl->rdport = pnl->dport;
- }
- else {
+ } else {
pnl->rdaddr = st->gwy.addr;
pnl->rdport = st->gwy.port;
pnl->rsaddr = pnl->saddr;
@@ -1192,6 +1182,7 @@ u_int16_t
pf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new)
{
u_int32_t l = cksum + old - new;
+
l = (l >> 16) + (l & 65535);
l = l & 65535;
return (l ? l : 65535);
@@ -1203,6 +1194,7 @@ pf_change_ap(u_int32_t *a, u_int16_t *p, u_int16_t *ic, u_int16_t *pc,
{
u_int32_t ao = *a;
u_int16_t po = *p;
+
*a = an;
*ic = pf_cksum_fixup(pf_cksum_fixup(*ic, ao / 65536,
an / 65536), ao % 65536, an % 65536);
@@ -1216,6 +1208,7 @@ void
pf_change_a(u_int32_t *a, u_int16_t *c, u_int32_t an)
{
u_int32_t ao = *a;
+
*a = an;
*c = pf_cksum_fixup(pf_cksum_fixup(*c, ao / 65536, an / 65536),
ao % 65536, an % 65536);
@@ -1227,12 +1220,16 @@ pf_change_icmp(u_int32_t *ia, u_int16_t *ip, u_int32_t *oa, u_int32_t na,
{
u_int32_t oia = *ia, ooa = *oa, opc, oh2c = *h2c;
u_int16_t oip = *ip;
- if (pc != NULL) opc = *pc;
+
+ if (pc != NULL)
+ opc = *pc;
/* Change inner protocol port, fix inner protocol checksum. */
*ip = np;
- if (pc != NULL) *pc = pf_cksum_fixup(*pc, oip, *ip);
+ if (pc != NULL)
+ *pc = pf_cksum_fixup(*pc, oip, *ip);
*ic = pf_cksum_fixup(*ic, oip, *ip);
- if (pc != NULL) *ic = pf_cksum_fixup(*ic, opc, *pc);
+ if (pc != NULL)
+ *ic = pf_cksum_fixup(*ic, opc, *pc);
/* Change inner ip address, fix inner ip checksum and icmp checksum. */
*ia = na;
*h2c = pf_cksum_fixup(pf_cksum_fixup(*h2c, oia / 65536, *ia / 65536),
@@ -1309,7 +1306,6 @@ pf_send_reset(struct ip *h, int off, struct tcphdr *th)
/* IP header checksum */
h2->ip_sum = in_cksum(m, sizeof(struct ip));
-
ip_output(m, NULL, NULL, 0, NULL);
}
@@ -1456,8 +1452,7 @@ pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf *m,
nport = rdr->rport;
pf_change_ap(&h->ip_dst.s_addr, &th->th_dport,
- &h->ip_sum, &th->th_sum, rdr->raddr, nport);
-
+ &h->ip_sum, &th->th_sum, rdr->raddr, nport);
rewrite++;
}
}
@@ -1491,8 +1486,7 @@ pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf *m,
pf_change_ap(&h->ip_src.s_addr, &th->th_sport,
&h->ip_sum, &th->th_sum, baddr, bport);
rewrite++;
- }
- else if (rdr != NULL) {
+ } else if (rdr != NULL) {
pf_change_ap(&h->ip_dst.s_addr, &th->th_dport,
&h->ip_sum, &th->th_sum, baddr, bport);
rewrite++;
@@ -1516,63 +1510,62 @@ pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf *m,
len = h->ip_len - off - (th->th_off << 2);
s = pool_get(&pf_state_pl, PR_NOWAIT);
- if (s == NULL) {
+ if (s == NULL)
return (PF_DROP);
- }
- s->rule = rm;
- s->log = rm && (rm->log & 2);
- s->proto = IPPROTO_TCP;
- s->direction = direction;
+
+ s->rule = rm;
+ s->log = rm && (rm->log & 2);
+ s->proto = IPPROTO_TCP;
+ s->direction = direction;
if (direction == PF_OUT) {
- s->gwy.addr = h->ip_src.s_addr;
- s->gwy.port = th->th_sport;
- s->ext.addr = h->ip_dst.s_addr;
- s->ext.port = th->th_dport;
+ s->gwy.addr = h->ip_src.s_addr;
+ s->gwy.port = th->th_sport;
+ s->ext.addr = h->ip_dst.s_addr;
+ s->ext.port = th->th_dport;
if (nat != NULL) {
- s->lan.addr = baddr;
- s->lan.port = bport;
+ s->lan.addr = baddr;
+ s->lan.port = bport;
pf_next_port_tcp++;
if (pf_next_port_tcp == 65535)
pf_next_port_tcp = 50001;
} else {
- s->lan.addr = s->gwy.addr;
- s->lan.port = s->gwy.port;
+ s->lan.addr = s->gwy.addr;
+ s->lan.port = s->gwy.port;
}
} else {
- s->lan.addr = h->ip_dst.s_addr;
- s->lan.port = th->th_dport;
- s->ext.addr = h->ip_src.s_addr;
- s->ext.port = th->th_sport;
+ s->lan.addr = h->ip_dst.s_addr;
+ s->lan.port = th->th_dport;
+ s->ext.addr = h->ip_src.s_addr;
+ s->ext.port = th->th_sport;
if (rdr != NULL) {
- s->gwy.addr = baddr;
- s->gwy.port = bport;
+ s->gwy.addr = baddr;
+ s->gwy.port = bport;
} else {
- s->gwy.addr = s->lan.addr;
- s->gwy.port = s->lan.port;
+ s->gwy.addr = s->lan.addr;
+ s->gwy.port = s->lan.port;
}
}
- s->src.seqlo = ntohl(th->th_seq) + len +
- ((th->th_flags & TH_SYN) ? 1 : 0) +
- ((th->th_flags & TH_FIN) ? 1 : 0);
- s->src.seqhi = s->src.seqlo + 1;
- s->src.max_win = MAX(ntohs(th->th_win), 1);
-
- s->dst.seqlo = 0; /* Haven't seen these yet */
- s->dst.seqhi = 1;
- s->dst.max_win = 1;
- s->src.state = 1;
- s->dst.state = 0;
- s->creation = pftv.tv_sec;
- s->expire = pftv.tv_sec + 60;
- s->packets = 1;
- s->bytes = len;
+ s->src.seqlo = ntohl(th->th_seq) + len +
+ ((th->th_flags & TH_SYN) ? 1 : 0) +
+ ((th->th_flags & TH_FIN) ? 1 : 0);
+ s->src.seqhi = s->src.seqlo + 1;
+ s->src.max_win = MAX(ntohs(th->th_win), 1);
+
+ s->dst.seqlo = 0; /* Haven't seen these yet */
+ s->dst.seqhi = 1;
+ s->dst.max_win = 1;
+ s->src.state = 1;
+ s->dst.state = 0;
+ s->creation = pftv.tv_sec;
+ s->expire = pftv.tv_sec + 60;
+ s->packets = 1;
+ s->bytes = len;
pf_insert_state(s);
}
/* copy back packet headers if we performed NAT operations */
if (rewrite)
m_copyback(m, off, sizeof(*th), (caddr_t)th);
-
return (PF_PASS);
}
@@ -1645,8 +1638,7 @@ pf_test_udp(int direction, struct ifnet *ifp, struct mbuf *m,
pf_change_ap(&h->ip_src.s_addr, &uh->uh_sport,
&h->ip_sum, &uh->uh_sum, baddr, bport);
rewrite++;
- }
- else if (rdr != NULL) {
+ } else if (rdr != NULL) {
pf_change_ap(&h->ip_dst.s_addr, &uh->uh_dport,
&h->ip_sum, &uh->uh_sum, baddr, bport);
rewrite++;
@@ -1666,53 +1658,53 @@ pf_test_udp(int direction, struct ifnet *ifp, struct mbuf *m,
len = h->ip_len - off - 8;
s = pool_get(&pf_state_pl, PR_NOWAIT);
- if (s == NULL) {
+ if (s == NULL)
return (PF_DROP);
- }
- s->rule = rm;
- s->log = rm && (rm->log & 2);
- s->proto = IPPROTO_UDP;
- s->direction = direction;
+
+ s->rule = rm;
+ s->log = rm && (rm->log & 2);
+ s->proto = IPPROTO_UDP;
+ s->direction = direction;
if (direction == PF_OUT) {
- s->gwy.addr = h->ip_src.s_addr;
- s->gwy.port = uh->uh_sport;
- s->ext.addr = h->ip_dst.s_addr;
- s->ext.port = uh->uh_dport;
+ s->gwy.addr = h->ip_src.s_addr;
+ s->gwy.port = uh->uh_sport;
+ s->ext.addr = h->ip_dst.s_addr;
+ s->ext.port = uh->uh_dport;
if (nat != NULL) {
- s->lan.addr = baddr;
- s->lan.port = bport;
+ s->lan.addr = baddr;
+ s->lan.port = bport;
pf_next_port_udp++;
if (pf_next_port_udp == 65535)
pf_next_port_udp = 50001;
} else {
- s->lan.addr = s->gwy.addr;
- s->lan.port = s->gwy.port;
+ s->lan.addr = s->gwy.addr;
+ s->lan.port = s->gwy.port;
}
} else {
- s->lan.addr = h->ip_dst.s_addr;
- s->lan.port = uh->uh_dport;
- s->ext.addr = h->ip_src.s_addr;
- s->ext.port = uh->uh_sport;
+ s->lan.addr = h->ip_dst.s_addr;
+ s->lan.port = uh->uh_dport;
+ s->ext.addr = h->ip_src.s_addr;
+ s->ext.port = uh->uh_sport;
if (rdr != NULL) {
- s->gwy.addr = baddr;
- s->gwy.port = bport;
+ s->gwy.addr = baddr;
+ s->gwy.port = bport;
} else {
- s->gwy.addr = s->lan.addr;
- s->gwy.port = s->lan.port;
+ s->gwy.addr = s->lan.addr;
+ s->gwy.port = s->lan.port;
}
}
- s->src.seqlo = 0;
- s->src.seqhi = 0;
- s->src.max_win = 0;
- s->src.state = 1;
- s->dst.seqlo = 0;
- s->dst.seqhi = 0;
- s->dst.max_win = 0;
- s->dst.state = 0;
- s->creation = pftv.tv_sec;
- s->expire = pftv.tv_sec + 30;
- s->packets = 1;
- s->bytes = len;
+ s->src.seqlo = 0;
+ s->src.seqhi = 0;
+ s->src.max_win = 0;
+ s->src.state = 1;
+ s->dst.seqlo = 0;
+ s->dst.seqhi = 0;
+ s->dst.max_win = 0;
+ s->dst.state = 0;
+ s->creation = pftv.tv_sec;
+ s->expire = pftv.tv_sec + 30;
+ s->packets = 1;
+ s->bytes = len;
pf_insert_state(s);
}
@@ -1778,37 +1770,37 @@ pf_test_icmp(int direction, struct ifnet *ifp, struct mbuf *m,
if (s == NULL) {
return (PF_DROP);
}
- s->rule = rm;
- s->log = rm && (rm->log & 2);
- s->proto = IPPROTO_ICMP;
- s->direction = direction;
+ s->rule = rm;
+ s->log = rm && (rm->log & 2);
+ s->proto = IPPROTO_ICMP;
+ s->direction = direction;
if (direction == PF_OUT) {
- s->gwy.addr = h->ip_src.s_addr;
- s->gwy.port = id;
- s->ext.addr = h->ip_dst.s_addr;
- s->ext.port = id;
- s->lan.addr = nat ? baddr : s->gwy.addr;
- s->lan.port = id;
+ s->gwy.addr = h->ip_src.s_addr;
+ s->gwy.port = id;
+ s->ext.addr = h->ip_dst.s_addr;
+ s->ext.port = id;
+ s->lan.addr = nat ? baddr : s->gwy.addr;
+ s->lan.port = id;
} else {
- s->lan.addr = h->ip_dst.s_addr;
- s->lan.port = id;
- s->ext.addr = h->ip_src.s_addr;
- s->ext.port = id;
- s->gwy.addr = s->lan.addr;
- s->gwy.port = id;
- }
- s->src.seqlo = 0;
- s->src.seqhi = 0;
- s->src.max_win = 0;
- s->src.state = 0;
- s->dst.seqlo = 0;
- s->dst.seqhi = 0;
- s->dst.max_win = 0;
- s->dst.state = 0;
- s->creation = pftv.tv_sec;
- s->expire = pftv.tv_sec + 20;
- s->packets = 1;
- s->bytes = len;
+ s->lan.addr = h->ip_dst.s_addr;
+ s->lan.port = id;
+ s->ext.addr = h->ip_src.s_addr;
+ s->ext.port = id;
+ s->gwy.addr = s->lan.addr;
+ s->gwy.port = id;
+ }
+ s->src.seqlo = 0;
+ s->src.seqhi = 0;
+ s->src.max_win = 0;
+ s->src.state = 0;
+ s->dst.seqlo = 0;
+ s->dst.seqhi = 0;
+ s->dst.max_win = 0;
+ s->dst.state = 0;
+ s->creation = pftv.tv_sec;
+ s->expire = pftv.tv_sec + 20;
+ s->packets = 1;
+ s->bytes = len;
pf_insert_state(s);
}
@@ -2131,7 +2123,7 @@ pf_test_state_icmp(int direction, struct ifnet *ifp, struct mbuf *m,
ipoff2 = off + 8; /* offset of h2 in mbuf chain */
if (!pf_pull_hdr(ifp, m, 0, ipoff2, &h2, sizeof(h2), h,
- NULL, NULL)) {
+ NULL, NULL)) {
printf("pf: ICMP error message too short (ip)\n");
return (NULL);
}
@@ -2764,7 +2756,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
struct tcphdr th;
if (!pf_pull_hdr(ifp, m, 0, off, &th, sizeof(th), h,
- &action, &reason)) {
+ &action, &reason)) {
log = action != PF_PASS;
goto done;
}
@@ -2781,7 +2773,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
struct udphdr uh;
if (!pf_pull_hdr(ifp, m, 0, off, &uh, sizeof(uh), h,
- &action, &reason)) {
+ &action, &reason)) {
log = action != PF_PASS;
goto done;
}
@@ -2798,7 +2790,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
struct icmp ih;
if (!pf_pull_hdr(ifp, m, 0, off, &ih, sizeof(ih), h,
- &action, &reason)) {
+ &action, &reason)) {
log = action != PF_PASS;
goto done;
}