#include <netinet/in_pcb.h>
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
-#include <netinet/ip_fw.h>
-#include <netinet/ip_divert.h>
#include <netinet/kpi_ipfilter_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/bootp.h>
-#include <netinet/lro_ext.h>
#if DUMMYNET
#include <netinet/ip_dummynet.h>
#endif /* DUMMYNET */
-#if CONFIG_MACF_NET
-#include <security/mac_framework.h>
-#endif /* CONFIG_MACF_NET */
-
#if IPSEC
#include <netinet6/ipsec.h>
#include <netkey/key.h>
static void ipq_free(struct ipq *);
static void ipq_updateparams(void);
static void ip_input_second_pass(struct mbuf *, struct ifnet *,
- u_int32_t, int, int, struct ip_fw_in_args *, int);
+ int, int, struct ip_fw_in_args *);
decl_lck_mtx_data(static, ipqlock);
static lck_attr_t *ipqlock_attr;
&ipstealth, 0, "");
#endif /* IPSTEALTH */
-/* Firewall hooks */
-#if IPFIREWALL
-ip_fw_chk_t *ip_fw_chk_ptr;
-int fw_enable = 1;
-int fw_bypass = 1;
-int fw_one_pass = 0;
-#endif /* IPFIREWALL */
-
#if DUMMYNET
ip_dn_io_t *ip_dn_io_ptr;
#endif /* DUMMYNET */
static int ip_dooptions(struct mbuf *, int, struct sockaddr_in *);
static void ip_forward(struct mbuf *, int, struct sockaddr_in *);
static void frag_freef(struct ipqhead *, struct ipq *);
-#if IPDIVERT
-#ifdef IPDIVERT_44
-static struct mbuf *ip_reass(struct mbuf *, u_int32_t *, u_int16_t *);
-#else /* !IPDIVERT_44 */
-static struct mbuf *ip_reass(struct mbuf *, u_int16_t *, u_int16_t *);
-#endif /* !IPDIVERT_44 */
-#else /* !IPDIVERT */
static struct mbuf *ip_reass(struct mbuf *);
-#endif /* !IPDIVERT */
static void ip_fwd_route_copyout(struct ifnet *, struct route *);
static void ip_fwd_route_copyin(struct ifnet *, struct route *);
static inline u_short ip_cksum(struct mbuf *, int);
}
}
-void
-ip_proto_dispatch_in_wrapper(struct mbuf *m, int hlen, u_int8_t proto)
-{
- ip_proto_dispatch_in(m, hlen, proto, 0);
-}
-
__private_extern__ void
ip_proto_dispatch_in(struct mbuf *m, int hlen, u_int8_t proto,
ipfilter_t inject_ipfref)
for (i = 0; i < PKTTBL_SZ; i++) {
if (tbl[i].pkte_head != NULL) {
struct mbuf *m = tbl[i].pkte_head;
- ip_input_second_pass(m, m->m_pkthdr.rcvif, 0,
- tbl[i].pkte_npkts, tbl[i].pkte_nbytes, args, 0);
+ ip_input_second_pass(m, m->m_pkthdr.rcvif,
+ tbl[i].pkte_npkts, tbl[i].pkte_nbytes, args);
if (tbl[i].pkte_npkts > 2) {
ipstat.ips_rxc_chainsz_gt2++;
bzero(args1, sizeof(struct ip_fw_args));
*done_init = TRUE;
}
- args1->fwa_next_hop = args->fwai_next_hop;
- args1->fwa_ipfw_rule = args->fwai_ipfw_rule;
args1->fwa_pf_rule = args->fwai_pf_rule;
- args1->fwa_divert_rule = args->fwai_divert_rule;
}
static void
ip_input_cpin_args(struct ip_fw_args *args1, struct ip_fw_in_args *args)
{
- args->fwai_next_hop = args1->fwa_next_hop;
- args->fwai_ipfw_rule = args1->fwa_ipfw_rule;
args->fwai_pf_rule = args1->fwa_pf_rule;
- args->fwai_divert_rule = args1->fwa_divert_rule;
}
typedef enum {
while (tmp_mbuf != NULL) {
nxt_mbuf = mbuf_nextpkt(tmp_mbuf);
mbuf_setnextpkt(tmp_mbuf, NULL);
-
- if ((sw_lro) && (ip->ip_p == IPPROTO_TCP)) {
- tmp_mbuf = tcp_lro(tmp_mbuf, hlen);
- }
- if (tmp_mbuf) {
- ip_proto_dispatch_in(tmp_mbuf, hlen, ip->ip_p, 0);
- }
+ ip_proto_dispatch_in(tmp_mbuf, hlen, ip->ip_p, 0);
tmp_mbuf = nxt_mbuf;
if (tmp_mbuf) {
ip = mtod(tmp_mbuf, struct ip *);
/*
* First pass does all essential packet validation and places on a per flow
* queue for doing operations that have same outcome for all packets of a flow.
- * div_info is packet divert/tee info
*/
static ipinput_chain_ret_t
-ip_input_first_pass(struct mbuf *m, u_int32_t *div_info,
- struct ip_fw_in_args *args, int *ours, struct mbuf **modm)
+ip_input_first_pass(struct mbuf *m, struct ip_fw_in_args *args, struct mbuf **modm)
{
struct ip *ip;
struct ifnet *inifp;
int retval = IPINPUT_DOCHAIN;
int len = 0;
struct in_addr src_ip;
-#if IPFIREWALL
- int i;
-#endif
-#if IPFIREWALL || DUMMYNET
+#if DUMMYNET
struct m_tag *copy;
struct m_tag *p;
boolean_t delete = FALSE;
struct ip_fw_args args1;
boolean_t init = FALSE;
-#endif
+#endif /* DUMMYNET */
ipfilter_t inject_filter_ref = NULL;
-#if !IPFIREWALL
-#pragma unused (args)
-#endif
-
-#if !IPDIVERT
-#pragma unused (div_info)
-#pragma unused (ours)
-#endif
-
-#if !IPFIREWALL_FORWARD
-#pragma unused (ours)
-#endif
-
/* Check if the mbuf is still valid after interface filter processing */
MBUF_INPUT_CHECK(m, m->m_pkthdr.rcvif);
inifp = mbuf_pkthdr_rcvif(m);
m->m_pkthdr.pkt_flags &= ~PKTF_FORWARDED;
-#if IPFIREWALL || DUMMYNET
-
+#if DUMMYNET
/*
* Don't bother searching for tag(s) if there's none.
*/
p = m_tag_first(m);
while (p) {
if (p->m_tag_id == KERNEL_MODULE_TAG_ID) {
-#if DUMMYNET
if (p->m_tag_type == KERNEL_TAG_TYPE_DUMMYNET) {
struct dn_pkt_tag *dn_tag;
dn_tag = (struct dn_pkt_tag *)(p + 1);
- args->fwai_ipfw_rule = dn_tag->dn_ipfw_rule;
args->fwai_pf_rule = dn_tag->dn_pf_rule;
delete = TRUE;
}
-#endif
-
-#if IPDIVERT
- if (p->m_tag_type == KERNEL_TAG_TYPE_DIVERT) {
- struct divert_tag *div_tag;
-
- div_tag = (struct divert_tag *)(p + 1);
- args->fwai_divert_rule = div_tag->cookie;
- delete = TRUE;
- }
-#endif
-
- if (p->m_tag_type == KERNEL_TAG_TYPE_IPFORWARD) {
- struct ip_fwd_tag *ipfwd_tag;
-
- ipfwd_tag = (struct ip_fwd_tag *)(p + 1);
- args->fwai_next_hop = ipfwd_tag->next_hop;
- delete = TRUE;
- }
if (delete) {
copy = p;
}
#endif
-#if DUMMYNET
- if (args->fwai_ipfw_rule || args->fwai_pf_rule) {
+ if (args->fwai_pf_rule) {
/* dummynet already filtered us */
ip = mtod(m, struct ip *);
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
inject_filter_ref = ipf_get_inject_filter(m);
-#if IPFIREWALL
- if (args->fwai_ipfw_rule) {
- goto iphack;
- }
-#endif /* IPFIREWALL */
if (args->fwai_pf_rule) {
goto check_with_pf;
}
}
-#endif /* DUMMYNET */
ipfw_tags_done:
-#endif /* IPFIREWALL || DUMMYNET */
+#endif /* DUMMYNET */
/*
* No need to process packet twice if we've already seen it.
#if DUMMYNET
check_with_pf:
-#endif
+#endif /* DUMMYNET */
#if PF
/* Invoke inbound packet filter */
if (PF_IS_ENABLED) {
}
#endif
-#if IPFIREWALL
-#if DUMMYNET
-iphack:
-#endif /* DUMMYNET */
- /*
- * Check if we want to allow this packet to be processed.
- * Consider it to be bad if not.
- */
- if (fw_enable && IPFW_LOADED) {
-#if IPFIREWALL_FORWARD
- /*
- * If we've been forwarded from the output side, then
- * skip the firewall a second time
- */
- if (args->fwai_next_hop) {
- *ours = 1;
- return IPINPUT_DONTCHAIN;
- }
-#endif /* IPFIREWALL_FORWARD */
- ip_input_cpout_args(args, &args1, &init);
- args1.fwa_m = m;
-
- i = ip_fw_chk_ptr(&args1);
- m = args1.fwa_m;
-
- if ((i & IP_FW_PORT_DENY_FLAG) || m == NULL) { /* drop */
- if (m) {
- m_freem(m);
- }
- ip_input_update_nstat(inifp, src_ip, 1, len);
- KERNEL_DEBUG(DBG_LAYER_END, 0, 0, 0, 0, 0);
- OSAddAtomic(1, &ipstat.ips_total);
- return IPINPUT_FREED;
- }
- ip = mtod(m, struct ip *); /* just in case m changed */
- *modm = m;
- ip_input_cpin_args(&args1, args);
-
- if (i == 0 && args->fwai_next_hop == NULL) { /* common case */
- goto pass;
- }
-#if DUMMYNET
- 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, &args1,
- DN_CLIENT_IPFW);
- ip_input_update_nstat(inifp, src_ip, 1, len);
- KERNEL_DEBUG(DBG_LAYER_END, 0, 0, 0, 0, 0);
- OSAddAtomic(1, &ipstat.ips_total);
- return IPINPUT_FREED;
- }
-#endif /* DUMMYNET */
-#if IPDIVERT
- if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) {
- /* Divert or tee packet */
- *div_info = i;
- *ours = 1;
- return IPINPUT_DONTCHAIN;
- }
-#endif
-#if IPFIREWALL_FORWARD
- if (i == 0 && args->fwai_next_hop != NULL) {
- retval = IPINPUT_DONTCHAIN;
- goto pass;
- }
-#endif
- /*
- * if we get here, the packet must be dropped
- */
- ip_input_update_nstat(inifp, src_ip, 1, len);
- KERNEL_DEBUG(DBG_LAYER_END, 0, 0, 0, 0, 0);
- m_freem(m);
- OSAddAtomic(1, &ipstat.ips_total);
- return IPINPUT_FREED;
- }
-#endif /* IPFIREWALL */
-#if IPSEC | IPFIREWALL
+#if IPSEC
pass:
#endif
/*
* to be sent and the original packet to be freed).
*/
ip_nhops = 0; /* for source routed packets */
-#if IPFIREWALL
- if (hlen > sizeof(struct ip) &&
- ip_dooptions(m, 0, args->fwai_next_hop)) {
-#else /* !IPFIREWALL */
if (hlen > sizeof(struct ip) && ip_dooptions(m, 0, NULL)) {
-#endif /* !IPFIREWALL */
ip_input_update_nstat(inifp, src_ip, 1, len);
KERNEL_DEBUG(DBG_LAYER_END, 0, 0, 0, 0, 0);
OSAddAtomic(1, &ipstat.ips_total);
}
/*
- * Don't chain fragmented packets as the process of determining
- * if it is our fragment or someone else's plus the complexity of
- * divert and fw args makes it harder to do chaining.
+ * Don't chain fragmented packets
*/
if (ip->ip_off & ~(IP_DF | IP_RF)) {
return IPINPUT_DONTCHAIN;
inet_ntop(AF_INET, &ip->ip_src, src_str, sizeof(src_str));
inet_ntop(AF_INET, &ip->ip_dst, dst_str, sizeof(dst_str));
- os_log_info(OS_LOG_DEFAULT,
+ os_log(OS_LOG_DEFAULT,
"%s: no interface match for packet from %s to %s proto %u received via %s",
__func__, src_str, dst_str, ip->ip_p, inifp->if_xname);
}
}
static void
-ip_input_second_pass(struct mbuf *m, struct ifnet *inifp, u_int32_t div_info,
- int npkts_in_chain, int bytes_in_chain, struct ip_fw_in_args *args, int ours)
+ip_input_second_pass(struct mbuf *m, struct ifnet *inifp,
+ int npkts_in_chain, int bytes_in_chain, struct ip_fw_in_args *args)
{
struct mbuf *tmp_mbuf = NULL;
unsigned int hlen;
-#if !IPFIREWALL
#pragma unused (args)
-#endif
-
-#if !IPDIVERT
-#pragma unused (div_info)
-#endif
struct ip *ip = mtod(m, struct ip *);
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
ip_input_update_nstat(inifp, ip->ip_src, npkts_in_chain,
bytes_in_chain);
- if (ours) {
- goto ours;
- }
-
/*
* Check our list of addresses, to see if the packet is for us.
* If we don't have any addresses, assume any unicast packet
* 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
- * is not locally generated and the packet is not subject to
- * 'ipfw fwd'.
+ * is not locally generated
*
* XXX - Checking also should be disabled if the destination
* address is ipnat'ed to a different interface.
OSAddAtomic(1, &ipstat.ips_cantforward);
m_freem(tmp_mbuf);
} else {
-#if IPFIREWALL
- ip_forward(tmp_mbuf, 0, args->fwai_next_hop);
-#else
ip_forward(tmp_mbuf, 0, NULL);
-#endif
}
tmp_mbuf = nxt_mbuf;
}
ours:
ip = mtod(m, struct ip *); /* in case it changed */
/*
- * If offset or IP_MF are set, must reassemble.
+ * If offset is set, must reassemble.
*/
if (ip->ip_off & ~(IP_DF | IP_RF)) {
VERIFY(npkts_in_chain == 1);
- /*
- * ip_reass() will return a different mbuf, and update
- * the divert info in div_info and args->fwai_divert_rule.
- */
-#if IPDIVERT
- m = ip_reass(m, (u_int16_t *)&div_info, &args->fwai_divert_rule);
-#else
m = ip_reass(m);
-#endif
if (m == NULL) {
return;
}
ip = mtod(m, struct ip *);
/* Get the header length of the reassembled packet */
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-#if IPDIVERT
- /* Restore original checksum before diverting packet */
- if (div_info != 0) {
- VERIFY(npkts_in_chain == 1);
-#if BYTE_ORDER != BIG_ENDIAN
- HTONS(ip->ip_len);
- HTONS(ip->ip_off);
-#endif
- ip->ip_sum = 0;
- ip->ip_sum = ip_cksum_hdr_in(m, hlen);
-#if BYTE_ORDER != BIG_ENDIAN
- NTOHS(ip->ip_off);
- NTOHS(ip->ip_len);
-#endif
- }
-#endif
}
/*
*/
ip->ip_len -= hlen;
-#if IPDIVERT
- /*
- * Divert or tee packet to the divert protocol if required.
- *
- * If div_info is zero then cookie should be too, so we shouldn't
- * need to clear them here. Assume divert_packet() does so also.
- */
- if (div_info != 0) {
- struct mbuf *clone = NULL;
- VERIFY(npkts_in_chain == 1);
-
- /* Clone packet if we're doing a 'tee' */
- if (div_info & IP_FW_PORT_TEE_FLAG) {
- clone = m_dup(m, M_DONTWAIT);
- }
-
- /* Restore packet header fields to original values */
- ip->ip_len += hlen;
-
-#if BYTE_ORDER != BIG_ENDIAN
- HTONS(ip->ip_len);
- HTONS(ip->ip_off);
-#endif
- /* Deliver packet to divert input routine */
- OSAddAtomic(1, &ipstat.ips_delivered);
- divert_packet(m, 1, div_info & 0xffff, args->fwai_divert_rule);
-
- /* If 'tee', continue with original packet */
- if (clone == NULL) {
- return;
- }
- m = clone;
- ip = mtod(m, struct ip *);
- }
-#endif
-
#if IPSEC
/*
* enforce IPsec policy checking if we are seeing last header.
*/
OSAddAtomic(npkts_in_chain, &ipstat.ips_delivered);
-#if IPFIREWALL
- if (args->fwai_next_hop && ip->ip_p == IPPROTO_TCP) {
- /* TCP needs IPFORWARD info if available */
- struct m_tag *fwd_tag;
- struct ip_fwd_tag *ipfwd_tag;
-
- VERIFY(npkts_in_chain == 1);
- fwd_tag = m_tag_create(KERNEL_MODULE_TAG_ID,
- KERNEL_TAG_TYPE_IPFORWARD, sizeof(*ipfwd_tag),
- M_NOWAIT, m);
- if (fwd_tag == NULL) {
- goto bad;
- }
-
- ipfwd_tag = (struct ip_fwd_tag *)(fwd_tag + 1);
- ipfwd_tag->next_hop = args->fwai_next_hop;
-
- m_tag_prepend(m, fwd_tag);
-
- KERNEL_DEBUG(DBG_LAYER_END, ip->ip_dst.s_addr,
- ip->ip_src.s_addr, ip->ip_p, ip->ip_off, ip->ip_len);
-
- /* TCP deals with its own locking */
- ip_proto_dispatch_in(m, hlen, ip->ip_p, 0);
- } else {
- KERNEL_DEBUG(DBG_LAYER_END, ip->ip_dst.s_addr,
- ip->ip_src.s_addr, ip->ip_p, ip->ip_off, ip->ip_len);
-
- ip_input_dispatch_chain(m);
- }
-#else /* !IPFIREWALL */
ip_input_dispatch_chain(m);
-#endif /* !IPFIREWALL */
KERNEL_DEBUG(DBG_LAYER_END, 0, 0, 0, 0, 0);
return;
bad:
struct mbuf *packet = NULL;
struct mbuf *modm = NULL; /* modified mbuf */
int retval = 0;
- u_int32_t div_info = 0;
- int ours = 0;
#if (DEBUG || DEVELOPMENT)
struct timeval start_tv;
#endif /* (DEBUG || DEVELOPMENT) */
num_pkts++;
modm = NULL;
- div_info = 0;
bzero(&args, sizeof(args));
- retval = ip_input_first_pass(packet, &div_info, &args,
- &ours, &modm);
+ retval = ip_input_first_pass(packet, &args, &modm);
if (retval == IPINPUT_DOCHAIN) {
if (modm) {
net_perf_histogram(&net_perf, 1);
}
#endif /* (DEBUG || DEVELOPMENT) */
- ip_input_second_pass(packet, packet->m_pkthdr.rcvif, div_info,
- 1, packet->m_pkthdr.len, &args, ours);
+ ip_input_second_pass(packet, packet->m_pkthdr.rcvif,
+ 1, packet->m_pkthdr.len, &args);
}
if (packet_list) {
m->m_pkthdr.pkt_flags &= ~PKTF_FORWARDED;
-#if IPFIREWALL || DUMMYNET
+#if DUMMYNET
bzero(&args, sizeof(struct ip_fw_args));
/*
}
/* Grab info from mtags prepended to the chain */
-#if DUMMYNET
if ((tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID,
KERNEL_TAG_TYPE_DUMMYNET, NULL)) != NULL) {
struct dn_pkt_tag *dn_tag;
dn_tag = (struct dn_pkt_tag *)(tag + 1);
- args.fwa_ipfw_rule = dn_tag->dn_ipfw_rule;
args.fwa_pf_rule = dn_tag->dn_pf_rule;
- m_tag_delete(m, tag);
- }
-#endif /* DUMMYNET */
-
-#if IPDIVERT
- if ((tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID,
- KERNEL_TAG_TYPE_DIVERT, NULL)) != NULL) {
- struct divert_tag *div_tag;
-
- div_tag = (struct divert_tag *)(tag + 1);
- args.fwa_divert_rule = div_tag->cookie;
-
- m_tag_delete(m, tag);
- }
-#endif
-
- if ((tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID,
- KERNEL_TAG_TYPE_IPFORWARD, NULL)) != NULL) {
- struct ip_fwd_tag *ipfwd_tag;
-
- ipfwd_tag = (struct ip_fwd_tag *)(tag + 1);
- args.fwa_next_hop = ipfwd_tag->next_hop;
-
m_tag_delete(m, tag);
}
}
#endif
-#if DUMMYNET
- if (args.fwa_ipfw_rule || args.fwa_pf_rule) {
+ if (args.fwa_pf_rule) {
/* dummynet already filtered us */
ip = mtod(m, struct ip *);
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
inject_filter_ref = ipf_get_inject_filter(m);
-#if IPFIREWALL
- if (args.fwa_ipfw_rule) {
- goto iphack;
- }
-#endif /* IPFIREWALL */
if (args.fwa_pf_rule) {
goto check_with_pf;
}
}
-#endif /* DUMMYNET */
ipfw_tags_done:
-#endif /* IPFIREWALL || DUMMYNET */
+#endif /* DUMMYNET */
/*
* No need to process packet twice if we've already seen it.
}
#endif
-#if IPFIREWALL
-#if DUMMYNET
-iphack:
-#endif /* DUMMYNET */
- /*
- * Check if we want to allow this packet to be processed.
- * Consider it to be bad if not.
- */
- if (fw_enable && IPFW_LOADED) {
-#if IPFIREWALL_FORWARD
- /*
- * If we've been forwarded from the output side, then
- * skip the firewall a second time
- */
- if (args.fwa_next_hop) {
- goto ours;
- }
-#endif /* IPFIREWALL_FORWARD */
-
- args.fwa_m = m;
-
- i = ip_fw_chk_ptr(&args);
- m = args.fwa_m;
-
- 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.fwa_next_hop == NULL) { /* common case */
- goto pass;
- }
-#if DUMMYNET
- 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,
- DN_CLIENT_IPFW);
- return;
- }
-#endif /* DUMMYNET */
-#if IPDIVERT
- if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) {
- /* Divert or tee packet */
- div_info = i;
- goto ours;
- }
-#endif
-#if IPFIREWALL_FORWARD
- if (i == 0 && args.fwa_next_hop != NULL) {
- goto pass;
- }
-#endif
- /*
- * if we get here, the packet must be dropped
- */
- m_freem(m);
- return;
- }
-#endif /* IPFIREWALL */
-#if IPSEC | IPFIREWALL
pass:
-#endif
/*
* Process options and, if not destined for us,
* ship it on. ip_dooptions returns 1 when an
* to be sent and the original packet to be freed).
*/
ip_nhops = 0; /* for source routed packets */
-#if IPFIREWALL
- if (hlen > sizeof(struct ip) &&
- ip_dooptions(m, 0, args.fwa_next_hop)) {
-#else /* !IPFIREWALL */
if (hlen > sizeof(struct ip) && ip_dooptions(m, 0, NULL)) {
-#endif /* !IPFIREWALL */
return;
}
OSAddAtomic(1, &ipstat.ips_cantforward);
m_freem(m);
} else {
-#if IPFIREWALL
- ip_forward(m, 0, args.fwa_next_hop);
-#else
ip_forward(m, 0, NULL);
-#endif
}
return;
* If offset or IP_MF are set, must reassemble.
*/
if (ip->ip_off & ~(IP_DF | IP_RF)) {
- /*
- * ip_reass() will return a different mbuf, and update
- * the divert info in div_info and args.fwa_divert_rule.
- */
-#if IPDIVERT
- m = ip_reass(m, (u_int16_t *)&div_info, &args.fwa_divert_rule);
-#else
m = ip_reass(m);
-#endif
if (m == NULL) {
return;
}
ip = mtod(m, struct ip *);
/* Get the header length of the reassembled packet */
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-#if IPDIVERT
- /* Restore original checksum before diverting packet */
- if (div_info != 0) {
-#if BYTE_ORDER != BIG_ENDIAN
- HTONS(ip->ip_len);
- HTONS(ip->ip_off);
-#endif
- ip->ip_sum = 0;
- ip->ip_sum = ip_cksum_hdr_in(m, hlen);
-#if BYTE_ORDER != BIG_ENDIAN
- NTOHS(ip->ip_off);
- NTOHS(ip->ip_len);
-#endif
- }
-#endif
}
/*
*/
ip->ip_len -= hlen;
-#if IPDIVERT
- /*
- * Divert or tee packet to the divert protocol if required.
- *
- * If div_info is zero then cookie should be too, so we shouldn't
- * need to clear them here. Assume divert_packet() does so also.
- */
- if (div_info != 0) {
- struct mbuf *clone = NULL;
-
- /* Clone packet if we're doing a 'tee' */
- if (div_info & IP_FW_PORT_TEE_FLAG) {
- clone = m_dup(m, M_DONTWAIT);
- }
-
- /* Restore packet header fields to original values */
- ip->ip_len += hlen;
-
-#if BYTE_ORDER != BIG_ENDIAN
- HTONS(ip->ip_len);
- HTONS(ip->ip_off);
-#endif
- /* Deliver packet to divert input routine */
- OSAddAtomic(1, &ipstat.ips_delivered);
- divert_packet(m, 1, div_info & 0xffff, args.fwa_divert_rule);
-
- /* If 'tee', continue with original packet */
- if (clone == NULL) {
- return;
- }
- m = clone;
- ip = mtod(m, struct ip *);
- }
-#endif
#if IPSEC
/*
*/
OSAddAtomic(1, &ipstat.ips_delivered);
-#if IPFIREWALL
- if (args.fwa_next_hop && ip->ip_p == IPPROTO_TCP) {
- /* TCP needs IPFORWARD info if available */
- struct m_tag *fwd_tag;
- struct ip_fwd_tag *ipfwd_tag;
-
- fwd_tag = m_tag_create(KERNEL_MODULE_TAG_ID,
- KERNEL_TAG_TYPE_IPFORWARD, sizeof(*ipfwd_tag),
- M_NOWAIT, m);
- if (fwd_tag == NULL) {
- goto bad;
- }
-
- ipfwd_tag = (struct ip_fwd_tag *)(fwd_tag + 1);
- ipfwd_tag->next_hop = args.fwa_next_hop;
-
- m_tag_prepend(m, fwd_tag);
-
- KERNEL_DEBUG(DBG_LAYER_END, ip->ip_dst.s_addr,
- ip->ip_src.s_addr, ip->ip_p, ip->ip_off, ip->ip_len);
-
- /* TCP deals with its own locking */
- ip_proto_dispatch_in(m, hlen, ip->ip_p, 0);
- } else {
- KERNEL_DEBUG(DBG_LAYER_END, ip->ip_dst.s_addr,
- ip->ip_src.s_addr, ip->ip_p, ip->ip_off, ip->ip_len);
-
- if ((sw_lro) && (ip->ip_p == IPPROTO_TCP)) {
- m = tcp_lro(m, hlen);
- if (m == NULL) {
- return;
- }
- }
-
- ip_proto_dispatch_in(m, hlen, ip->ip_p, 0);
- }
-#else /* !IPFIREWALL */
- if ((sw_lro) && (ip->ip_p == IPPROTO_TCP)) {
- m = tcp_lro(m, hlen);
- if (m == NULL) {
- return;
- }
- }
ip_proto_dispatch_in(m, hlen, ip->ip_p, 0);
-#endif /* !IPFIREWALL */
return;
bad:
* whole datagram. If a chain for reassembly of this datagram already
* exists, then it is given as fp; otherwise have to make a chain.
*
- * When IPDIVERT enabled, keep additional state with each packet that
- * tells us if we need to divert or tee the packet we're building.
- *
* The IP header is *NOT* adjusted out of iplen (but in host byte order).
*/
static struct mbuf *
-#if IPDIVERT
-ip_reass(struct mbuf *m,
-#ifdef IPDIVERT_44
- u_int32_t *divinfo,
-#else /* IPDIVERT_44 */
- u_int16_t *divinfo,
-#endif /* IPDIVERT_44 */
- u_int16_t *divcookie)
-#else /* IPDIVERT */
ip_reass(struct mbuf *m)
-#endif /* IPDIVERT */
{
struct ip *ip;
struct mbuf *p, *q, *nq, *t;
if (ip->ip_id == fp->ipq_id &&
ip->ip_src.s_addr == fp->ipq_src.s_addr &&
ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
-#if CONFIG_MACF_NET
- mac_ipq_label_compare(m, fp) &&
-#endif
ip->ip_p == fp->ipq_p) {
goto found;
}
if (fp == NULL) {
goto dropfrag;
}
-#if CONFIG_MACF_NET
- if (mac_ipq_label_init(fp, M_NOWAIT) != 0) {
- ipq_free(fp);
- fp = NULL;
- goto dropfrag;
- }
- mac_ipq_label_associate(m, fp);
-#endif
TAILQ_INSERT_HEAD(head, fp, ipq_list);
nipq++;
fp->ipq_nfrags = 1;
fp->ipq_csum = csum;
fp->ipq_csum_flags = csum_flags;
}
-#if IPDIVERT
- /*
- * Transfer firewall instructions to the fragment structure.
- * Only trust info in the fragment at offset 0.
- */
- if (ip->ip_off == 0) {
-#ifdef IPDIVERT_44
- fp->ipq_div_info = *divinfo;
-#else
- fp->ipq_divert = *divinfo;
-#endif
- fp->ipq_div_cookie = *divcookie;
- }
- *divinfo = 0;
- *divcookie = 0;
-#endif /* IPDIVERT */
m = NULL; /* nothing to return */
goto done;
} else {
fp->ipq_nfrags++;
-#if CONFIG_MACF_NET
- mac_ipq_label_update(m, fp);
-#endif
}
#define GETIP(m) ((struct ip *)((m)->m_pkthdr.pkt_hdr))
fp->ipq_csum_flags = 0;
}
-#if IPDIVERT
- /*
- * Transfer firewall instructions to the fragment structure.
- * Only trust info in the fragment at offset 0.
- */
- if (ip->ip_off == 0) {
-#ifdef IPDIVERT_44
- fp->ipq_div_info = *divinfo;
-#else
- fp->ipq_divert = *divinfo;
-#endif
- fp->ipq_div_cookie = *divcookie;
- }
- *divinfo = 0;
- *divcookie = 0;
-#endif /* IPDIVERT */
/*
* Check for complete reassembly and perform frag per packet
CSUM_IP_CHECKED | CSUM_IP_VALID;
}
-#if IPDIVERT
- /*
- * Extract firewall instructions from the fragment structure.
- */
-#ifdef IPDIVERT_44
- *divinfo = fp->ipq_div_info;
-#else
- *divinfo = fp->ipq_divert;
-#endif
- *divcookie = fp->ipq_div_cookie;
-#endif /* IPDIVERT */
-
-#if CONFIG_MACF_NET
- mac_mbuf_label_associate_ipq(fp, m);
- mac_ipq_label_destroy(fp);
-#endif
/*
* Create header for new ip packet by modifying header of first
* packet; dequeue and discard fragment reassembly header.
return NULL;
dropfrag:
-#if IPDIVERT
- *divinfo = 0;
- *divcookie = 0;
-#endif /* IPDIVERT */
ipstat.ips_fragdropped++;
if (fp != NULL) {
fp->ipq_nfrags--;
static void
ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
{
-#if !IPFIREWALL
#pragma unused(next_hop)
-#endif
struct ip *ip = mtod(m, struct ip *);
struct sockaddr_in *sin;
struct rtentry *rt;
#endif /* PF */
dest = 0;
-#if IPFIREWALL
- /*
- * Cache the destination address of the packet; this may be
- * changed by use of 'ipfw fwd'.
- */
- pkt_dst = ((next_hop != NULL) ? next_hop->sin_addr : ip->ip_dst);
-#else /* !IPFIREWALL */
pkt_dst = ip->ip_dst;
-#endif /* !IPFIREWALL */
#if DIAGNOSTIC
if (ipprintfs) {
}
RT_UNLOCK(rt);
-#if IPFIREWALL
- if (next_hop != NULL) {
- /* Pass IPFORWARD info if available */
- struct m_tag *tag;
- struct ip_fwd_tag *ipfwd_tag;
-
- tag = m_tag_create(KERNEL_MODULE_TAG_ID,
- KERNEL_TAG_TYPE_IPFORWARD,
- sizeof(*ipfwd_tag), M_NOWAIT, m);
- if (tag == NULL) {
- error = ENOBUFS;
- m_freem(m);
- goto done;
- }
-
- ipfwd_tag = (struct ip_fwd_tag *)(tag + 1);
- ipfwd_tag->next_hop = next_hop;
-
- m_tag_prepend(m, tag);
- }
-#endif /* IPFIREWALL */
/* Mark this packet as being forwarded from another interface */
m->m_pkthdr.pkt_flags |= PKTF_FORWARDED;
}
break;
- case EACCES: /* ipfw denied packet */
+ case EACCES:
m_freem(mcopy);
goto done;
}
goto no_mbufs;
}
}
- if (inp->inp_flags & INP_RECVDSTADDR) {
+ if (inp->inp_flags & INP_RECVDSTADDR
+#if CONTENT_FILTER
+ /* Content Filter needs to see local address */
+ || (inp->inp_socket->so_cfil_db != NULL)
+#endif
+ ) {
mp = sbcreatecontrol_mbuf((caddr_t)&ip->ip_dst,
sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP, mp);
if (*mp == NULL) {