static errno_t vboxNetAdpDarwinOutput(ifnet_t pIface, mbuf_t pMBuf) { PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface); Assert(pThis); if (pThis->u.s.nTapMode & BPF_MODE_OUTPUT) { Log2(("vboxnetadp: out len=%d\n%.*Rhxd\n", mbuf_len(pMBuf), 14, mbuf_data(pMBuf))); bpf_tap_out(pIface, DLT_EN10MB, pMBuf, NULL, 0); } mbuf_freem_list(pMBuf); return 0; }
/* Network Interface functions */ static errno_t utun_output( ifnet_t interface, mbuf_t data) { struct utun_pcb *pcb = ifnet_softc(interface); errno_t result; if (m_pktlen(data) >= 4) { bpf_tap_out(pcb->utun_ifp, DLT_NULL, data, 0, 0); } if (pcb->utun_flags & UTUN_FLAGS_NO_OUTPUT) { /* flush data */ mbuf_freem(data); return 0; } // otherwise, fall thru to ctl_enqueumbuf if (pcb->utun_ctlref) { int length; // only pass packets to utun-crypto if crypto is enabled and 'suspend data traffic' is not. if ((pcb->utun_flags & (UTUN_FLAGS_CRYPTO | UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC)) == UTUN_FLAGS_CRYPTO) { if (utun_pkt_crypto_output(pcb, &data) == 0) { return 0; } } /* * The ABI requires the protocol in network byte order */ if (m_pktlen(data) >= 4) *(u_int32_t *)mbuf_data(data) = htonl(*(u_int32_t *)mbuf_data(data)); length = mbuf_pkthdr_len(data); result = ctl_enqueuembuf(pcb->utun_ctlref, pcb->utun_unit, data, CTL_DATA_EOR); if (result != 0) { mbuf_freem(data); printf("utun_output - ctl_enqueuembuf failed: %d\n", result); ifnet_stat_increment_out(interface, 0, 0, 1); } else { if (!pcb->utun_ext_ifdata_stats) ifnet_stat_increment_out(interface, 1, length, 0); } } else mbuf_freem(data); return 0; }
static errno_t utun_output(ifnet_t interface, mbuf_t data) { struct utun_pcb *pcb = ifnet_softc(interface); errno_t result; VERIFY(interface == pcb->utun_ifp); if (m_pktlen(data) >= (int32_t)UTUN_HEADER_SIZE(pcb)) { bpf_tap_out(pcb->utun_ifp, DLT_NULL, data, 0, 0); } if (pcb->utun_flags & UTUN_FLAGS_NO_OUTPUT) { /* flush data */ mbuf_freem(data); return 0; } // otherwise, fall thru to ctl_enqueumbuf if (pcb->utun_ctlref) { int length; /* * The ABI requires the protocol in network byte order */ if (m_pktlen(data) >= (int32_t)UTUN_HEADER_SIZE(pcb)) { *(u_int32_t *)mbuf_data(data) = htonl(*(u_int32_t *)mbuf_data(data)); } length = mbuf_pkthdr_len(data); result = ctl_enqueuembuf(pcb->utun_ctlref, pcb->utun_unit, data, CTL_DATA_EOR); if (result != 0) { mbuf_freem(data); printf("utun_output - ctl_enqueuembuf failed: %d\n", result); ifnet_stat_increment_out(interface, 0, 0, 1); } else { if (!pcb->utun_ext_ifdata_stats) ifnet_stat_increment_out(interface, 1, length, 0); } } else mbuf_freem(data); return 0; }
int pflog_packet(struct pfi_kif *kif, pbuf_t *pbuf, sa_family_t af, u_int8_t dir, u_int8_t reason, struct pf_rule *rm, struct pf_rule *am, struct pf_ruleset *ruleset, struct pf_pdesc *pd) { #if NBPFILTER > 0 struct ifnet *ifn; struct pfloghdr hdr; struct mbuf *m; LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED); if (kif == NULL || !pbuf_is_valid(pbuf) || rm == NULL || pd == NULL) return (-1); if (rm->logif >= PFLOGIFS_MAX || (ifn = pflogifs[rm->logif]) == NULL || !ifn->if_bpf) { return (0); } if ((m = pbuf_to_mbuf(pbuf, FALSE)) == NULL) return (0); bzero(&hdr, sizeof (hdr)); hdr.length = PFLOG_REAL_HDRLEN; hdr.af = af; hdr.action = rm->action; hdr.reason = reason; memcpy(hdr.ifname, kif->pfik_name, sizeof (hdr.ifname)); if (am == NULL) { hdr.rulenr = htonl(rm->nr); hdr.subrulenr = -1; } else { hdr.rulenr = htonl(am->nr); hdr.subrulenr = htonl(rm->nr); if (ruleset != NULL && ruleset->anchor != NULL) strlcpy(hdr.ruleset, ruleset->anchor->name, sizeof (hdr.ruleset)); } if (rm->log & PF_LOG_SOCKET_LOOKUP && !pd->lookup.done) pd->lookup.done = pf_socket_lookup(dir, pd); if (pd->lookup.done > 0) { hdr.uid = pd->lookup.uid; hdr.pid = pd->lookup.pid; } else { hdr.uid = UID_MAX; hdr.pid = NO_PID; } hdr.rule_uid = rm->cuid; hdr.rule_pid = rm->cpid; hdr.dir = dir; #if INET if (af == AF_INET && dir == PF_OUT) { struct ip *ip; ip = mtod(m, struct ip *); ip->ip_sum = 0; ip->ip_sum = in_cksum(m, ip->ip_hl << 2); } #endif /* INET */ atomic_add_64(&ifn->if_opackets, 1); atomic_add_64(&ifn->if_obytes, m->m_pkthdr.len); switch (dir) { case PF_IN: bpf_tap_in(ifn, DLT_PFLOG, m, &hdr, PFLOG_HDRLEN); break; case PF_OUT: bpf_tap_out(ifn, DLT_PFLOG, m, &hdr, PFLOG_HDRLEN); break; default: break; } #endif /* NBPFILTER > 0 */ return (0); }
/* Network Interface functions */ static errno_t ipsec_output(ifnet_t interface, mbuf_t data) { struct ipsec_pcb *pcb = ifnet_softc(interface); struct ipsec_output_state ipsec_state; struct route ro; struct route_in6 ro6; int length; struct ip *ip; struct ip6_hdr *ip6; struct ip_out_args ipoa; struct ip6_out_args ip6oa; int error = 0; u_int ip_version = 0; uint32_t af; int flags = 0; struct flowadv *adv = NULL; // Make sure this packet isn't looping through the interface if (necp_get_last_interface_index_from_packet(data) == interface->if_index) { error = -1; goto ipsec_output_err; } // Mark the interface so NECP can evaluate tunnel policy necp_mark_packet_from_interface(data, interface); ip = mtod(data, struct ip *); ip_version = ip->ip_v; switch (ip_version) { case 4: /* Tap */ af = AF_INET; bpf_tap_out(pcb->ipsec_ifp, DLT_NULL, data, &af, sizeof(af)); /* Apply encryption */ bzero(&ipsec_state, sizeof(ipsec_state)); ipsec_state.m = data; ipsec_state.dst = (struct sockaddr *)&ip->ip_dst; bzero(&ipsec_state.ro, sizeof(ipsec_state.ro)); error = ipsec4_interface_output(&ipsec_state, interface); data = ipsec_state.m; if (error || data == NULL) { printf("ipsec_output: ipsec4_output error %d.\n", error); goto ipsec_output_err; } /* Set traffic class, set flow */ m_set_service_class(data, pcb->ipsec_output_service_class); data->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET; data->m_pkthdr.pkt_flowid = interface->if_flowhash; data->m_pkthdr.pkt_proto = ip->ip_p; data->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC); /* Flip endian-ness for ip_output */ ip = mtod(data, struct ip *); NTOHS(ip->ip_len); NTOHS(ip->ip_off); /* Increment statistics */ length = mbuf_pkthdr_len(data); ifnet_stat_increment_out(interface, 1, length, 0); /* Send to ip_output */ bzero(&ro, sizeof(ro)); flags = IP_OUTARGS | /* Passing out args to specify interface */ IP_NOIPSEC; /* To ensure the packet doesn't go through ipsec twice */ bzero(&ipoa, sizeof(ipoa)); ipoa.ipoa_flowadv.code = 0; ipoa.ipoa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR; if (ipsec_state.outgoing_if) { ipoa.ipoa_boundif = ipsec_state.outgoing_if; ipoa.ipoa_flags |= IPOAF_BOUND_IF; } adv = &ipoa.ipoa_flowadv; (void) ip_output(data, NULL, &ro, flags, NULL, &ipoa); data = NULL; if (adv->code == FADV_FLOW_CONTROLLED || adv->code == FADV_SUSPENDED) { error = ENOBUFS; ifnet_disable_output(interface); } goto done; case 6: af = AF_INET6; bpf_tap_out(pcb->ipsec_ifp, DLT_NULL, data, &af, sizeof(af)); data = ipsec6_splithdr(data); ip6 = mtod(data, struct ip6_hdr *); bzero(&ipsec_state, sizeof(ipsec_state)); ipsec_state.m = data; ipsec_state.dst = (struct sockaddr *)&ip6->ip6_dst; bzero(&ipsec_state.ro, sizeof(ipsec_state.ro)); error = ipsec6_interface_output(&ipsec_state, interface, &ip6->ip6_nxt, ipsec_state.m); if (error == 0 && ipsec_state.tunneled == 4) /* tunneled in IPv4 - packet is gone */ goto done; data = ipsec_state.m; if (error || data == NULL) { printf("ipsec_output: ipsec6_output error %d.\n", error); goto ipsec_output_err; } /* Set traffic class, set flow */ m_set_service_class(data, pcb->ipsec_output_service_class); data->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET; data->m_pkthdr.pkt_flowid = interface->if_flowhash; data->m_pkthdr.pkt_proto = ip6->ip6_nxt; data->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC); /* Increment statistics */ length = mbuf_pkthdr_len(data); ifnet_stat_increment_out(interface, 1, length, 0); /* Send to ip6_output */ bzero(&ro6, sizeof(ro6)); flags = IPV6_OUTARGS; bzero(&ip6oa, sizeof(ip6oa)); ip6oa.ip6oa_flowadv.code = 0; ip6oa.ip6oa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR; if (ipsec_state.outgoing_if) { ip6oa.ip6oa_boundif = ipsec_state.outgoing_if; ip6oa.ip6oa_flags |= IPOAF_BOUND_IF; } adv = &ip6oa.ip6oa_flowadv; (void) ip6_output(data, NULL, &ro6, flags, NULL, NULL, &ip6oa); data = NULL; if (adv->code == FADV_FLOW_CONTROLLED || adv->code == FADV_SUSPENDED) { error = ENOBUFS; ifnet_disable_output(interface); } goto done; default: printf("ipsec_output: Received unknown packet version %d.\n", ip_version); error = -1; goto ipsec_output_err; } done: return error; ipsec_output_err: if (data) mbuf_freem(data); goto done; }