summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r--sys/netinet/ip_input.c282
1 files changed, 65 insertions, 217 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 0ae3c16..fc4ab6e 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -32,9 +32,6 @@
#include "opt_bootp.h"
#include "opt_ipfw.h"
-#include "opt_ipdn.h"
-#include "opt_ipdivert.h"
-#include "opt_ipfilter.h"
#include "opt_ipstealth.h"
#include "opt_ipsec.h"
#include "opt_mac.h"
@@ -72,8 +69,8 @@
#include <sys/socketvar.h>
+/* XXX: Temporary until ipfw_ether and ipfw_bridge are converted. */
#include <netinet/ip_fw.h>
-#include <netinet/ip_divert.h>
#include <netinet/ip_dummynet.h>
#ifdef IPSEC
@@ -208,15 +205,14 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, stealth, CTLFLAG_RW,
&ipstealth, 0, "");
#endif
-
-/* Firewall hooks */
-ip_fw_chk_t *ip_fw_chk_ptr;
-int fw_enable = 1 ;
+/*
+ * ipfw_ether and ipfw_bridge hooks.
+ * XXX: Temporary until those are converted to pfil_hooks as well.
+ */
+ip_fw_chk_t *ip_fw_chk_ptr = NULL;
+ip_dn_io_t *ip_dn_io_ptr = NULL;
int fw_one_pass = 1;
-/* Dummynet hooks */
-ip_dn_io_t *ip_dn_io_ptr;
-
/*
* XXX this is ugly -- the following two global variables are
* used to store packet state while it travels through the stack.
@@ -240,12 +236,9 @@ static struct ip_srcrt {
} ip_srcrt;
static void save_rte(u_char *, struct in_addr);
-static int ip_dooptions(struct mbuf *m, int,
- struct sockaddr_in *next_hop);
-static void ip_forward(struct mbuf *m, int srcrt,
- struct sockaddr_in *next_hop);
+static int ip_dooptions(struct mbuf *m, int);
+static void ip_forward(struct mbuf *m, int srcrt);
static void ip_freef(struct ipqhead *, struct ipq *);
-static struct mbuf *ip_reass(struct mbuf *);
/*
* IP initialization: fill in IP protocol switch table.
@@ -301,13 +294,8 @@ ip_input(struct mbuf *m)
struct ip *ip = NULL;
struct in_ifaddr *ia = NULL;
struct ifaddr *ifa;
- int i, checkif, hlen = 0;
+ int checkif, hlen = 0;
u_short sum;
- struct in_addr pkt_dst;
-#ifdef IPDIVERT
- u_int32_t divert_info; /* packet divert/tee info */
-#endif
- struct ip_fw_args args;
int dchg = 0; /* dest changed after fw */
#ifdef PFIL_HOOKS
struct in_addr odst; /* original dst address */
@@ -319,26 +307,20 @@ ip_input(struct mbuf *m)
int s, error;
#endif /* FAST_IPSEC */
- args.eh = NULL;
- args.oif = NULL;
-
M_ASSERTPKTHDR(m);
- args.next_hop = m_claim_next(m, PACKET_TAG_IPFORWARD);
- args.rule = ip_dn_claim_rule(m);
-
if (m->m_flags & M_FASTFWD_OURS) {
- /* ip_fastforward firewall changed dest to local */
+ /*
+ * ip_fastforward firewall changed dest to local.
+ * We expect ip_len and ip_off in host byte order.
+ */
m->m_flags &= ~M_FASTFWD_OURS; /* for reflected mbufs */
+ /* Set up some basic stuff */
+ ip = mtod(m, struct ip *);
+ hlen = ip->ip_hl << 2;
goto ours;
}
- if (args.rule) { /* dummynet already filtered us */
- ip = mtod(m, struct ip *);
- hlen = ip->ip_hl << 2;
- goto iphack ;
- }
-
ipstat.ips_total++;
if (m->m_pkthdr.len < sizeof(struct ip))
@@ -441,20 +423,6 @@ tooshort:
goto pass;
#endif
- /*
- * IpHack's section.
- * Right now when no processing on packet has done
- * and it is still fresh out of network we do our black
- * deals with it.
- * - Firewall: deny/allow/divert
- * - Xlate: translate packet's addr/port (NAT).
- * - Pipe: pass pkt through dummynet.
- * - Wrap: fake packet's addr/port <unimpl.>
- * - Encapsulate: put it in another IP and send out. <unimp.>
- */
-
-iphack:
-
#ifdef PFIL_HOOKS
/*
* Run through list of hooks for input packets.
@@ -469,50 +437,23 @@ iphack:
return;
if (m == NULL) /* consumed by filter */
return;
+
ip = mtod(m, struct ip *);
dchg = (odst.s_addr != ip->ip_dst.s_addr);
-#endif /* PFIL_HOOKS */
- if (fw_enable && IPFW_LOADED) {
- /*
- * If we've been forwarded from the output side, then
- * skip the firewall a second time
- */
- if (args.next_hop)
- goto ours;
+#ifdef IPFIREWALL_FORWARD
+ if (m->m_flags & M_FASTFWD_OURS) {
+ m->m_flags &= ~M_FASTFWD_OURS;
+ goto ours;
+ }
+ dchg = (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL);
+#endif /* IPFIREWALL_FORWARD */
- args.m = m;
- i = ip_fw_chk_ptr(&args);
- m = args.m;
+#endif /* PFIL_HOOKS */
- if ( (i & IP_FW_PORT_DENY_FLAG) || m == NULL) { /* drop */
- if (m)
- m_freem(m);
- return;
- }
- ip = mtod(m, struct ip *); /* just in case m changed */
- if (i == 0 && args.next_hop == NULL) /* common case */
- goto pass;
- if (DUMMYNET_LOADED && (i & IP_FW_PORT_DYNT_FLAG) != 0) {
- /* Send packet to the appropriate pipe */
- ip_dn_io_ptr(m, i&0xffff, DN_TO_IP_IN, &args);
- return;
- }
-#ifdef IPDIVERT
- if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) {
- /* Divert or tee packet */
- goto ours;
- }
-#endif
- if (i == 0 && args.next_hop != NULL)
- goto pass;
- /*
- * if we get here, the packet must be dropped
- */
- m_freem(m);
- return;
- }
+#if defined(FAST_IPSEC) && !defined(IPSEC_FILTERGIF)
pass:
+#endif
/*
* Process options and, if not destined for us,
@@ -520,8 +461,7 @@ pass:
* error was detected (causing an icmp message
* to be sent and the original packet to be freed).
*/
- ip_nhops = 0; /* for source routed packets */
- if (hlen > sizeof (struct ip) && ip_dooptions(m, 0, args.next_hop))
+ if (hlen > sizeof (struct ip) && ip_dooptions(m, 0))
return;
/* greedy RSVP, snatches any PATH packet of the RSVP protocol and no
@@ -544,12 +484,6 @@ pass:
goto ours;
/*
- * Cache the destination address of the packet; this may be
- * changed by use of 'ipfw fwd'.
- */
- pkt_dst = args.next_hop ? args.next_hop->sin_addr : ip->ip_dst;
-
- /*
* Enable a consistency check between the destination address
* and the arrival interface for a unicast packet (the RFC 1122
* strong ES model) if IP forwarding is disabled and the packet
@@ -566,18 +500,18 @@ pass:
checkif = ip_checkinterface && (ipforwarding == 0) &&
m->m_pkthdr.rcvif != NULL &&
((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) &&
- (args.next_hop == NULL) && (dchg == 0);
+ (dchg == 0);
/*
* Check for exact addresses in the hash bucket.
*/
- LIST_FOREACH(ia, INADDR_HASH(pkt_dst.s_addr), ia_hash) {
+ LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) {
/*
* If the address matches, verify that the packet
* arrived via the correct interface if checking is
* enabled.
*/
- if (IA_SIN(ia)->sin_addr.s_addr == pkt_dst.s_addr &&
+ if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr &&
(!checkif || ia->ia_ifp == m->m_pkthdr.rcvif))
goto ours;
}
@@ -596,9 +530,9 @@ pass:
continue;
ia = ifatoia(ifa);
if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
- pkt_dst.s_addr)
+ ip->ip_dst.s_addr)
goto ours;
- if (ia->ia_netbroadcast.s_addr == pkt_dst.s_addr)
+ if (ia->ia_netbroadcast.s_addr == ip->ip_dst.s_addr)
goto ours;
#ifdef BOOTP_COMPAT
if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY)
@@ -706,7 +640,7 @@ pass:
goto bad;
}
#endif /* FAST_IPSEC */
- ip_forward(m, dchg, args.next_hop);
+ ip_forward(m, dchg);
}
return;
@@ -717,7 +651,7 @@ ours:
* if the packet is destined for us.
*/
if (ipstealth && hlen > sizeof (struct ip) &&
- ip_dooptions(m, 1, args.next_hop))
+ ip_dooptions(m, 1))
return;
#endif /* IPSTEALTH */
@@ -738,20 +672,6 @@ ours:
ip = mtod(m, struct ip *);
/* Get the header length of the reassembled packet */
hlen = ip->ip_hl << 2;
-#ifdef IPDIVERT
- /* Restore original checksum before diverting packet */
- if (divert_find_info(m) != 0) {
- ip->ip_len = htons(ip->ip_len);
- ip->ip_off = htons(ip->ip_off);
- ip->ip_sum = 0;
- if (hlen == sizeof(struct ip))
- ip->ip_sum = in_cksum_hdr(ip);
- else
- ip->ip_sum = in_cksum(m, hlen);
- ip->ip_off = ntohs(ip->ip_off);
- ip->ip_len = ntohs(ip->ip_len);
- }
-#endif
}
/*
@@ -760,46 +680,6 @@ ours:
*/
ip->ip_len -= hlen;
-#ifdef IPDIVERT
- /*
- * Divert or tee packet to the divert protocol if required.
- */
- divert_info = divert_find_info(m);
- if (divert_info != 0) {
- struct mbuf *clone;
-
- /* Clone packet if we're doing a 'tee' */
- if ((divert_info & IP_FW_PORT_TEE_FLAG) != 0)
- clone = divert_clone(m);
- else
- clone = NULL;
-
- /* Restore packet header fields to original values */
- ip->ip_len += hlen;
- ip->ip_len = htons(ip->ip_len);
- ip->ip_off = htons(ip->ip_off);
-
- /* Deliver packet to divert input routine */
- divert_packet(m, 1);
- ipstat.ips_delivered++;
-
- /* If 'tee', continue with original packet */
- if (clone == NULL)
- return;
- m = clone;
- ip = mtod(m, struct ip *);
- ip->ip_len += hlen;
- /*
- * Jump backwards to complete processing of the
- * packet. We do not need to clear args.next_hop
- * as that will not be used again and the cloned packet
- * doesn't contain a divert packet tag so we won't
- * re-entry this block.
- */
- goto pass;
- }
-#endif
-
#ifdef IPSEC
/*
* enforce IPsec policy checking if we are seeing last header.
@@ -856,15 +736,7 @@ DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
* Switch out to protocol's input routine.
*/
ipstat.ips_delivered++;
- if (args.next_hop && ip->ip_p == IPPROTO_TCP) {
- /* attach next hop info for TCP */
- struct m_tag *mtag = m_tag_get(PACKET_TAG_IPFORWARD,
- sizeof(struct sockaddr_in *), M_NOWAIT);
- if (mtag == NULL)
- goto bad;
- *(struct sockaddr_in **)(mtag+1) = args.next_hop;
- m_tag_prepend(m, mtag);
- }
+
(*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
return;
bad:
@@ -1092,18 +964,6 @@ found:
inserted:
-#ifdef IPDIVERT
- if (ip->ip_off != 0) {
- /*
- * Strip any divert information; only the info
- * on the first fragment is used/kept.
- */
- struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
- if (mtag)
- m_tag_delete(m, mtag);
- }
-#endif
-
/*
* Check for complete reassembly and perform frag per packet
* limiting.
@@ -1298,7 +1158,7 @@ ip_drain()
* 0 if the packet should be processed further.
*/
static int
-ip_dooptions(struct mbuf *m, int pass, struct sockaddr_in *next_hop)
+ip_dooptions(struct mbuf *m, int pass)
{
struct ip *ip = mtod(m, struct ip *);
u_char *cp;
@@ -1557,7 +1417,7 @@ dropit:
}
}
if (forward && ipforwarding) {
- ip_forward(m, 1, next_hop);
+ ip_forward(m, 1);
return (1);
}
return (0);
@@ -1737,35 +1597,25 @@ u_char inetctlerrmap[PRC_NCMDS] = {
* The srcrt parameter indicates whether the packet is being forwarded
* via a source route.
*/
-static void
-ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
+void
+ip_forward(struct mbuf *m, int srcrt)
{
struct ip *ip = mtod(m, struct ip *);
- struct in_ifaddr *ia;
+ struct in_ifaddr *ia = NULL;
int error, type = 0, code = 0;
struct mbuf *mcopy;
- n_long dest;
- struct in_addr pkt_dst;
- struct ifnet *destifp;
-#if defined(IPSEC) || defined(FAST_IPSEC)
- struct ifnet dummyifp;
-#endif
-
- /*
- * Cache the destination address of the packet; this may be
- * changed by use of 'ipfw fwd'.
- */
- pkt_dst = next_hop ? next_hop->sin_addr : ip->ip_dst;
+ struct in_addr dest;
+ struct ifnet *destifp, dummyifp;
#ifdef DIAGNOSTIC
if (ipprintfs)
printf("forward: src %lx dst %lx ttl %x\n",
- (u_long)ip->ip_src.s_addr, (u_long)pkt_dst.s_addr,
+ (u_long)ip->ip_src.s_addr, (u_long)ip->ip_dst.s_addr,
ip->ip_ttl);
#endif
- if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(pkt_dst) == 0) {
+ if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) {
ipstat.ips_cantforward++;
m_freem(m);
return;
@@ -1782,7 +1632,7 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
}
#endif
- if ((ia = ip_rtaddr(pkt_dst)) == NULL) {
+ if (!srcrt && (ia = ip_rtaddr(ip->ip_dst)) == NULL) {
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
return;
}
@@ -1837,8 +1687,8 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
* Also, don't send redirect if forwarding using a default route
* or a route modified by a redirect.
*/
- dest = 0;
- if (ipsendredirects && ia->ia_ifp == m->m_pkthdr.rcvif) {
+ dest.s_addr = 0;
+ if (!srcrt && ipsendredirects && ia->ia_ifp == m->m_pkthdr.rcvif) {
struct sockaddr_in *sin;
struct route ro;
struct rtentry *rt;
@@ -1847,29 +1697,28 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
sin = (struct sockaddr_in *)&ro.ro_dst;
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
- sin->sin_addr = pkt_dst;
+ sin->sin_addr = ip->ip_dst;
rtalloc_ign(&ro, RTF_CLONING);
rt = ro.ro_rt;
if (rt && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
- satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
- ipsendredirects && !srcrt && !next_hop) {
+ satosin(rt_key(rt))->sin_addr.s_addr != 0) {
#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa))
u_long src = ntohl(ip->ip_src.s_addr);
if (RTA(rt) &&
(src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) {
if (rt->rt_flags & RTF_GATEWAY)
- dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
+ dest.s_addr = satosin(rt->rt_gateway)->sin_addr.s_addr;
else
- dest = pkt_dst.s_addr;
+ dest.s_addr = ip->ip_dst.s_addr;
/* Router requirements says to only send host redirects */
type = ICMP_REDIRECT;
code = ICMP_REDIRECT_HOST;
#ifdef DIAGNOSTIC
if (ipprintfs)
- printf("redirect (%d) to %lx\n", code, (u_long)dest);
+ printf("redirect (%d) to %lx\n", code, (u_long)dest.s_addr);
#endif
}
}
@@ -1877,16 +1726,6 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
RTFREE(rt);
}
- if (next_hop) {
- struct m_tag *mtag = m_tag_get(PACKET_TAG_IPFORWARD,
- sizeof(struct sockaddr_in *), M_NOWAIT);
- if (mtag == NULL) {
- m_freem(m);
- return;
- }
- *(struct sockaddr_in **)(mtag+1) = next_hop;
- m_tag_prepend(m, mtag);
- }
error = ip_output(m, (struct mbuf *)0, NULL, IP_FORWARDING, 0, NULL);
if (error)
ipstat.ips_cantforward++;
@@ -1985,7 +1824,16 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
break;
} else
#endif /*IPSEC || FAST_IPSEC*/
- destifp = ia->ia_ifp;
+ /*
+ * When doing source routing 'ia' can be NULL. Fall back
+ * to the minimum guaranteed routeable packet size and use
+ * the same hack as IPSEC to setup a dummyifp for icmp.
+ */
+ if (ia == NULL) {
+ dummyifp.if_mtu = IP_MSS;
+ destifp = &dummyifp;
+ } else
+ destifp = ia->ia_ifp;
#if defined(IPSEC) || defined(FAST_IPSEC)
}
#endif /*IPSEC || FAST_IPSEC*/
@@ -2014,7 +1862,7 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
m_freem(mcopy);
return;
}
- icmp_error(mcopy, type, code, dest, destifp);
+ icmp_error(mcopy, type, code, dest.s_addr, destifp);
}
void
OpenPOWER on IntegriCloud