summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/if_bridge.c6
-rw-r--r--sys/net/pf.c70
-rw-r--r--sys/net/pfvar.h6
-rw-r--r--sys/netinet/ip_output.c13
-rw-r--r--sys/netinet/ip_var.h3
5 files changed, 77 insertions, 21 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index f2798157ea2..213729ca43c 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.131 2004/02/10 20:20:01 itojun Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.132 2004/04/28 02:51:58 cedric Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -2427,7 +2427,7 @@ bridge_filter(struct bridge_softc *sc, int dir, struct ifnet *ifp,
#if NPF > 0
/* Finally, we get to filter the packet! */
m->m_pkthdr.rcvif = ifp;
- if (pf_test(dir, ifp, &m) != PF_PASS)
+ if (pf_test_eh(dir, ifp, &m, eh) != PF_PASS)
goto dropit;
if (m == NULL)
goto dropit;
@@ -2473,7 +2473,7 @@ bridge_filter(struct bridge_softc *sc, int dir, struct ifnet *ifp,
#endif /* IPSEC */
#if NPF > 0
- if (pf_test6(dir, ifp, &m) != PF_PASS)
+ if (pf_test6_eh(dir, ifp, &m, eh) != PF_PASS)
goto dropit;
if (m == NULL)
return (NULL);
diff --git a/sys/net/pf.c b/sys/net/pf.c
index c1e9320b0a9..6bbdcb2e4fb 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.444 2004/04/28 02:43:08 pb Exp $ */
+/* $OpenBSD: pf.c,v 1.445 2004/04/28 02:51:58 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -68,6 +68,7 @@
#include <netinet/tcp_var.h>
#include <netinet/udp_var.h>
#include <netinet/icmp_var.h>
+#include <netinet/if_ether.h>
#include <dev/rndvar.h>
#include <net/pfvar.h>
@@ -129,7 +130,8 @@ void pf_change_icmp(struct pf_addr *, u_int16_t *,
void pf_send_tcp(const struct pf_rule *, sa_family_t,
const struct pf_addr *, const struct pf_addr *,
u_int16_t, u_int16_t, u_int32_t, u_int32_t,
- u_int8_t, u_int16_t, u_int16_t, u_int8_t, int);
+ u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
+ struct ether_header *, struct ifnet *);
void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
sa_family_t, struct pf_rule *);
struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
@@ -790,7 +792,7 @@ pf_purge_expired_state(struct pf_state *cur)
&cur->ext.addr, &cur->lan.addr,
cur->ext.port, cur->lan.port,
cur->src.seqhi, cur->src.seqlo + 1,
- TH_RST|TH_ACK, 0, 0, 0, 1);
+ TH_RST|TH_ACK, 0, 0, 0, 1, NULL, NULL);
RB_REMOVE(pf_state_tree_ext_gwy,
&cur->u.s.kif->pfik_ext_gwy, cur);
RB_REMOVE(pf_state_tree_lan_ext,
@@ -826,7 +828,6 @@ pf_purge_expired_states(void)
for (cur = RB_MIN(pf_state_tree_id, &tree_id);
cur; cur = next) {
next = RB_NEXT(pf_state_tree_id, &tree_id, cur);
-
if (pf_state_expires(cur) <= time.tv_sec)
pf_purge_expired_state(cur);
}
@@ -1248,7 +1249,8 @@ void
pf_send_tcp(const struct pf_rule *r, sa_family_t af,
const struct pf_addr *saddr, const struct pf_addr *daddr,
u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
- u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag)
+ u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag,
+ struct ether_header *eh, struct ifnet *ifp)
{
struct mbuf *m;
int len, tlen;
@@ -1373,8 +1375,28 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
h->ip_off = htons(ip_mtudisc ? IP_DF : 0);
h->ip_ttl = ttl ? ttl : ip_defttl;
h->ip_sum = 0;
- ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL,
- (void *)NULL);
+ if (eh == NULL) {
+ ip_output(m, (void *)NULL, (void *)NULL, 0,
+ (void *)NULL, (void *)NULL);
+ } else {
+ struct route ro;
+ struct rtentry rt;
+ struct ether_header *e = (void *)ro.ro_dst.sa_data;
+
+ if (ifp == NULL) {
+ m_freem(m);
+ return;
+ }
+ rt.rt_ifp = ifp;
+ ro.ro_rt = &rt;
+ ro.ro_dst.sa_len = sizeof(ro.ro_dst);
+ ro.ro_dst.sa_family = pseudo_AF_HDRCMPLT;
+ bcopy(eh->ether_dhost, e->ether_shost, ETHER_ADDR_LEN);
+ bcopy(eh->ether_shost, e->ether_dhost, ETHER_ADDR_LEN);
+ e->ether_type = eh->ether_type;
+ ip_output(m, (void *)NULL, &ro, IP_ROUTETOETHER,
+ (void *)NULL, (void *)NULL);
+ }
break;
#endif /* INET */
#ifdef INET6
@@ -2588,7 +2610,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
pf_send_tcp(r, af, pd->dst,
pd->src, th->th_dport, th->th_sport,
ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
- r->return_ttl, 1);
+ r->return_ttl, 1, pd->eh, kif->pfik_ifp);
} else if ((af == AF_INET) && r->return_icmp)
pf_send_icmp(m, r->return_icmp >> 8,
r->return_icmp & 255, af, r);
@@ -2775,7 +2797,7 @@ cleanup:
s->src.mss = mss;
pf_send_tcp(r, af, daddr, saddr, th->th_dport,
th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
- TH_SYN|TH_ACK, 0, s->src.mss, 0, 1);
+ TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, NULL, NULL);
return (PF_SYNPROXY_DROP);
}
}
@@ -3711,7 +3733,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
pd->src, th->th_dport, th->th_sport,
(*state)->src.seqhi, ntohl(th->th_seq) + 1,
- TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, 1);
+ TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, 1,
+ NULL, NULL);
return (PF_SYNPROXY_DROP);
} else if (!(th->th_flags & TH_ACK) ||
(ntohl(th->th_ack) != (*state)->src.seqhi + 1) ||
@@ -3741,7 +3764,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
&dst->addr, src->port, dst->port,
(*state)->dst.seqhi, 0, TH_SYN, 0,
- (*state)->src.mss, 0, 0);
+ (*state)->src.mss, 0, 0, NULL, NULL);
return (PF_SYNPROXY_DROP);
} else if (((th->th_flags & (TH_SYN|TH_ACK)) !=
(TH_SYN|TH_ACK)) ||
@@ -3753,11 +3776,13 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
pd->src, th->th_dport, th->th_sport,
ntohl(th->th_ack), ntohl(th->th_seq) + 1,
- TH_ACK, (*state)->src.max_win, 0, 0, 1);
+ TH_ACK, (*state)->src.max_win, 0, 0, 1,
+ NULL, NULL);
pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
&dst->addr, src->port, dst->port,
(*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
- TH_ACK, (*state)->dst.max_win, 0, 0, 0);
+ TH_ACK, (*state)->dst.max_win, 0, 0, 0,
+ NULL, NULL);
(*state)->src.seqdiff = (*state)->dst.seqhi -
(*state)->src.seqlo;
(*state)->dst.seqdiff = (*state)->src.seqhi -
@@ -4023,7 +4048,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
pd->dst, pd->src, th->th_dport,
th->th_sport, ntohl(th->th_ack), ack,
TH_RST|TH_ACK, 0, 0,
- (*state)->rule.ptr->return_ttl, 1);
+ (*state)->rule.ptr->return_ttl, 1,
+ pd->eh, kif->pfik_ifp);
}
src->seqlo = 0;
src->seqhi = 1;
@@ -5276,6 +5302,13 @@ pf_add_mbuf_tag(struct mbuf *m, u_int tag)
int
pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
{
+ return pf_test_eh(dir, ifp, m0, NULL);
+}
+
+int
+pf_test_eh(int dir, struct ifnet *ifp, struct mbuf **m0,
+ struct ether_header *eh)
+{
struct pfi_kif *kif;
u_short action, reason = 0, log = 0;
struct mbuf *m = *m0;
@@ -5331,6 +5364,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
pd.af = AF_INET;
pd.tos = h->ip_tos;
pd.tot_len = ntohs(h->ip_len);
+ pd.eh = eh;
/* handle fragments that didn't get reassembled by normalization */
if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
@@ -5581,6 +5615,13 @@ done:
int
pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
{
+ return pf_test6_eh(dir, ifp, m0, NULL);
+}
+
+int
+pf_test6_eh(int dir, struct ifnet *ifp, struct mbuf **m0,
+ struct ether_header *eh)
+{
struct pfi_kif *kif;
u_short action, reason = 0, log = 0;
struct mbuf *m = *m0;
@@ -5627,6 +5668,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
pd.af = AF_INET6;
pd.tos = 0;
pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
+ pd.eh = eh;
off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr);
pd.proto = h->ip6_nxt;
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index bcafb1e220b..07224e79591 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.191 2004/04/27 18:28:07 frantzen Exp $ */
+/* $OpenBSD: pfvar.h,v 1.192 2004/04/28 02:51:58 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -846,6 +846,8 @@ struct pf_pdesc {
struct pf_rule *nat_rule; /* nat/rdr rule applied to packet */
struct pf_addr *src;
struct pf_addr *dst;
+ struct ether_header
+ *eh;
u_int16_t *ip_sum;
u_int32_t p_len; /* total length of payload */
u_int16_t flags; /* Let SCRUB trigger behavior in
@@ -1341,10 +1343,12 @@ void pf_rm_rule(struct pf_rulequeue *,
#ifdef INET
int pf_test(int, struct ifnet *, struct mbuf **);
+int pf_test_eh(int, struct ifnet *, struct mbuf **, struct ether_header *);
#endif /* INET */
#ifdef INET6
int pf_test6(int, struct ifnet *, struct mbuf **);
+int pf_test6_eh(int, struct ifnet *, struct mbuf **, struct ether_header *);
void pf_poolmask(struct pf_addr *, struct pf_addr*,
struct pf_addr *, struct pf_addr *, u_int8_t);
void pf_addr_inc(struct pf_addr *, sa_family_t);
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 9cc42341943..0d220b0af8d 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.160 2004/02/10 20:20:01 itojun Exp $ */
+/* $OpenBSD: ip_output.c,v 1.161 2004/04/28 02:51:58 cedric Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -163,6 +163,10 @@ ip_output(struct mbuf *m0, ...)
* though (e.g., traceroute) have a source address of zeroes.
*/
if (ip->ip_src.s_addr == INADDR_ANY) {
+ if (flags & IP_ROUTETOETHER) {
+ error = EINVAL;
+ goto bad;
+ }
donerouting = 1;
if (ro == 0) {
@@ -326,7 +330,12 @@ ip_output(struct mbuf *m0, ...)
done_spd:
#endif /* IPSEC */
- if (donerouting == 0) {
+ if (flags & IP_ROUTETOETHER) {
+ dst = satosin(&ro->ro_dst);
+ ifp = ro->ro_rt->rt_ifp;
+ mtu = ifp->if_mtu;
+ ro->ro_rt = NULL;
+ } else if (donerouting == 0) {
if (ro == 0) {
ro = &iproute;
bzero((caddr_t)ro, sizeof (*ro));
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 33048f2d80e..cbcc0ed8629 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_var.h,v 1.29 2003/06/02 23:28:14 millert Exp $ */
+/* $OpenBSD: ip_var.h,v 1.30 2004/04/28 02:51:58 cedric Exp $ */
/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */
/*
@@ -153,6 +153,7 @@ struct ipstat {
#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */
#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
#define IP_MTUDISC 0x0400 /* pmtu discovery, set DF */
+#define IP_ROUTETOETHER 0x0800 /* ether addresses given */
extern struct ipstat ipstat;
extern LIST_HEAD(ipqhead, ipq) ipq; /* ip reass. queue */