errno_t utun_pkt_input (struct utun_pcb *pcb, mbuf_t m) { errno_t result; protocol_family_t protocol = 0; mbuf_pkthdr_setrcvif(m, pcb->utun_ifp); if (m_pktlen(m) >= 4) { protocol = *(u_int32_t *)mbuf_data(m); bpf_tap_in(pcb->utun_ifp, DLT_NULL, m, 0, 0); } if (pcb->utun_flags & UTUN_FLAGS_NO_INPUT) { /* flush data */ mbuf_freem(m); return 0; } // quick exit for keepalive packets if (protocol == AF_UTUN && pcb->utun_flags & UTUN_FLAGS_CRYPTO) { if (utun_pkt_crypto_output(pcb, &m) == 0) { return 0; } printf("%s: utun_pkt_crypto_output failed, flags %x\n", __FUNCTION__, pcb->utun_flags); return EINVAL; } if (!pcb->utun_ext_ifdata_stats) { struct ifnet_stat_increment_param incs; bzero(&incs, sizeof(incs)); incs.packets_in = 1; incs.bytes_in = mbuf_pkthdr_len(m); result = ifnet_input(pcb->utun_ifp, m, &incs); } else { result = ifnet_input(pcb->utun_ifp, m, NULL); } if (result != 0) { ifnet_stat_increment_in(pcb->utun_ifp, 0, 0, 1); printf("%s - ifnet_input failed: %d\n", __FUNCTION__, result); mbuf_freem(m); } return 0; }
int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst) { NOREF(pvIfData); int rc = VINF_SUCCESS; ifnet_t pIfNet = vboxNetFltDarwinRetainIfNet(pThis); if (pIfNet) { /* * Create a mbuf for the gather list and push it onto the wire. * * Note! If the interface is in the promiscuous mode we need to send the * packet down the stack so it reaches the driver and Berkeley * Packet Filter (see @bugref{5817}). */ if ((fDst & INTNETTRUNKDIR_WIRE) || vboxNetFltDarwinIsPromiscuous(pThis)) { mbuf_t pMBuf = vboxNetFltDarwinMBufFromSG(pThis, pSG); if (pMBuf) { errno_t err = ifnet_output_raw(pIfNet, PF_LINK, pMBuf); if (err) rc = RTErrConvertFromErrno(err); } else rc = VERR_NO_MEMORY; } /* * Create a mbuf for the gather list and push it onto the host stack. */ if (fDst & INTNETTRUNKDIR_HOST) { mbuf_t pMBuf = vboxNetFltDarwinMBufFromSG(pThis, pSG); if (pMBuf) { /* This is what IONetworkInterface::inputPacket does. */ unsigned const cbEthHdr = 14; mbuf_pkthdr_setheader(pMBuf, mbuf_data(pMBuf)); mbuf_pkthdr_setlen(pMBuf, mbuf_pkthdr_len(pMBuf) - cbEthHdr); mbuf_setdata(pMBuf, (uint8_t *)mbuf_data(pMBuf) + cbEthHdr, mbuf_len(pMBuf) - cbEthHdr); mbuf_pkthdr_setrcvif(pMBuf, pIfNet); /* will crash without this. */ errno_t err = ifnet_input(pIfNet, pMBuf, NULL); if (err) rc = RTErrConvertFromErrno(err); } else rc = VERR_NO_MEMORY; } vboxNetFltDarwinReleaseIfNet(pThis, pIfNet); } return rc; }
static errno_t utun_pkt_input (struct utun_pcb *pcb, mbuf_t m) { errno_t result; protocol_family_t protocol = 0; mbuf_pkthdr_setrcvif(m, pcb->utun_ifp); if (m_pktlen(m) >= (int32_t)UTUN_HEADER_SIZE(pcb)) { protocol = *(u_int32_t *)mbuf_data(m); bpf_tap_in(pcb->utun_ifp, DLT_NULL, m, 0, 0); } if (pcb->utun_flags & UTUN_FLAGS_NO_INPUT) { /* flush data */ mbuf_freem(m); return 0; } if (!pcb->utun_ext_ifdata_stats) { struct ifnet_stat_increment_param incs; bzero(&incs, sizeof(incs)); incs.packets_in = 1; incs.bytes_in = mbuf_pkthdr_len(m); result = ifnet_input(pcb->utun_ifp, m, &incs); } else { result = ifnet_input(pcb->utun_ifp, m, NULL); } if (result != 0) { ifnet_stat_increment_in(pcb->utun_ifp, 0, 0, 1); printf("%s - ifnet_input failed: %d\n", __FUNCTION__, result); mbuf_freem(m); } return 0; }
/* * Decapsulate. Does the real work and is called from in_gre_input() * (above) or ipv4_infilter(), Returns an mbuf back if packet is not * yet processed, and NULL if it needs no further processing. * proto is the protocol number of the "calling" foo_input() routine. */ mbuf_t in_gre_input(mbuf_t m, int hlen) { struct greip *gip; struct gre_softc *sc; u_int16_t flags; //static u_int32_t af; //u_int8_t proto; //proto = ((struct ip *)mbuf_data(m))->ip_p; if ((sc = gre_lookup(m, IPPROTO_GRE)) == NULL) { /* No matching tunnel or tunnel is down. */ return m; } /* from here on, we increased the sc->sc_refcnt, so do remember to decrease it before return */ if (mbuf_len(m) < sizeof(struct greip)) { mbuf_pullup(&m, sizeof(struct greip)); if (m == NULL) goto done; } gip = mbuf_data(m); //switch (proto) { // case IPPROTO_GRE: hlen += sizeof(struct gre_h); /* process GRE flags as packet can be of variable len */ flags = ntohs(gip->gi_flags); /* Checksum & Offset are present */ if ((flags & GRE_CP) | (flags & GRE_RP)) hlen += 4; /* We don't support routing fields (variable length) */ if (flags & GRE_RP) goto done; if (flags & GRE_KP) hlen += 4; if (flags & GRE_SP) hlen += 4; switch (ntohs(gip->gi_ptype)) { /* ethertypes */ case WCCP_PROTOCOL_TYPE: if (sc->wccp_ver == WCCP_V2) hlen += 4; /* FALLTHROUGH */ case ETHERTYPE_IP: //af = AF_INET; break; case ETHERTYPE_IPV6: //af = AF_INET6; break; //case ETHERTYPE_AT: // af = AF_APPLETALK; // break; default: /* Others not yet supported. */ goto done; } // break; // default: /* Others not yet supported. */ // goto done; //} if (hlen > mbuf_pkthdr_len(m)) { /* not a valid GRE packet */ mbuf_freem(m); m = NULL; goto done; } /* Unlike NetBSD, in FreeBSD(as well as Darwin) m_adj() adjusts mbuf_pkthdr_len(m) as well */ mbuf_adj(m, hlen); mbuf_pkthdr_setrcvif(m, sc->sc_ifp); mbuf_pkthdr_setheader(m, NULL); //mbuf_pkthdr_setheader(m, &af); /* it's ugly... */ struct ifnet_stat_increment_param incs; bzero(&incs, sizeof(incs)); incs.packets_in = 1; incs.bytes_in = mbuf_pkthdr_len(m); ifnet_input(sc->sc_ifp, m, &incs); m = NULL; /* ifnet_input() has freed the mbuf */ done: /* since we got sc->sc_refcnt add by one, we decrease it when done */ gre_sc_release(sc); return m; }
/* * input routine for IPPRPOTO_MOBILE * This is a little bit diffrent from the other modes, as the * encapsulating header was not prepended, but instead inserted * between IP header and payload */ mbuf_t in_mobile_input(mbuf_t m, int hlen) { #ifdef DEBUG printf("%s: got packet\n", __FUNCTION__); #endif struct ip *ip; struct mobip_h *mip; struct gre_softc *sc; int msiz; if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) { /* No matching tunnel or tunnel is down. */ return m; } /* from here on, we increased the sc->sc_refcnt, so do remember to decrease it before return */ if (mbuf_len(m) < sizeof(*mip)) { mbuf_pullup(&m, sizeof(*mip)); if (m == NULL) goto done; } ip = mbuf_data(m); mip = mbuf_data(m); if (ntohs(mip->mh.proto) & MOB_H_SBIT) { msiz = MOB_H_SIZ_L; mip->mi.ip_src.s_addr = mip->mh.osrc; } else msiz = MOB_H_SIZ_S; if (mbuf_len(m) < (ip->ip_hl << 2) + msiz) { mbuf_pullup(&m, (ip->ip_hl << 2) + msiz); if (m == NULL) goto done; ip = mbuf_data(m); mip = mbuf_data(m); } mip->mi.ip_dst.s_addr = mip->mh.odst; mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8); if (gre_in_cksum((u_int16_t *)&mip->mh, msiz) != 0) { mbuf_freem(m); m = NULL; goto done; } bcopy((caddr_t)(ip) + (ip->ip_hl << 2) + msiz, (caddr_t)(ip) + (ip->ip_hl << 2), mbuf_len(m) - msiz - (ip->ip_hl << 2)); mbuf_setdata(m, mbuf_data(m), mbuf_len(m) - msiz); mbuf_pkthdr_adjustlen(m, - msiz); /* * On FreeBSD, rip_input() supplies us with ip->ip_len * already converted into host byteorder and also decreases * it by the lengh of IP header, however, ip_input() expects * that this field is in the original format (network byteorder * and full size of IP packet), so that adjust accordingly. */ ip->ip_len = htons(ip->ip_len + sizeof(struct ip) - msiz); ip->ip_sum = 0; ip->ip_sum = in_cksum(m, (ip->ip_hl << 2)); mbuf_pkthdr_setrcvif(m, sc->sc_ifp); mbuf_pkthdr_setheader(m, NULL); struct ifnet_stat_increment_param incs; bzero(&incs, sizeof(incs)); incs.packets_in = 1; incs.bytes_in = mbuf_pkthdr_len(m); ifnet_input(sc->sc_ifp, m, &incs); m = NULL; /* ifnet_input() has freed the mbuf */ done: /* since we got sc->sc_refcnt add by one, we decrease it when done */ gre_sc_release(sc); return m; }