コード例 #1
0
ファイル: if_utun.c プロジェクト: Bitesher/xnu
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;
}
コード例 #2
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;
}
コード例 #3
0
ファイル: if_utun.c プロジェクト: onlynone/xnu
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;
}
コード例 #4
0
ファイル: in_gre.c プロジェクト: cyranodb/mac-gre
/*
 * 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;
}
コード例 #5
0
ファイル: in_gre.c プロジェクト: cyranodb/mac-gre
/*
 * 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;
}