Ejemplo n.º 1
0
void
gre_mobile_input(struct mbuf *m, int hlen)
{
	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. */
		m_freem(m);
		return;
	}

	if (m->m_len < sizeof(*mip)) {
		m = m_pullup(m, sizeof(*mip));
		if (m == NULL)
			return;
	}
	ip = mtod(m, struct ip *);
	mip = mtod(m, struct mobip_h *);

	GRE2IFP(sc)->if_ipackets++;
	GRE2IFP(sc)->if_ibytes += m->m_pkthdr.len;

	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 (m->m_len < (ip->ip_hl << 2) + msiz) {
		m = m_pullup(m, (ip->ip_hl << 2) + msiz);
		if (m == NULL)
			return;
		ip = mtod(m, struct ip *);
		mip = mtod(m, struct mobip_h *);
	}
Ejemplo n.º 2
0
int
gre_mobile_input(struct mbuf **mp, int *offp, int proto)
{
	static const uint32_t af = AF_INET;
	struct mbuf *m = *mp;
	struct ip *ip = mtod(m, struct ip *);
	struct mobip_h *mip = mtod(m, struct mobip_h *);
	struct gre_softc *sc;
	u_char osrc = 0;
	int msiz, hlen;

	hlen = *offp;

	if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) {
		/* No matching tunnel or tunnel is down. */
		m_freem(m);
		return(IPPROTO_DONE);
	}

	sc->sc_if.if_ipackets++;
	sc->sc_if.if_ibytes += m->m_pkthdr.len;

	if(ntohs(mip->mh.proto) & MOB_H_SBIT) {
		osrc = 1;
		msiz = MOB_H_SIZ_L;
		mip->mi.ip_src.s_addr = mip->mh.osrc;
	} else {
		msiz = MOB_H_SIZ_S;
	}
	mip->mi.ip_dst.s_addr = mip->mh.odst;
	mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8);

	if (gre_in_cksum((u_short*)&mip->mh,msiz) != 0) {
		m_freem(m);
		return(IPPROTO_DONE);
	}

	bcopy((caddr_t)(ip) + (ip->ip_hl << 2) + msiz, (caddr_t)(ip) +
	    (ip->ip_hl << 2), m->m_len - msiz - (ip->ip_hl << 2));
	m->m_len -= msiz;
	m->m_pkthdr.len -= 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));

	if (sc->sc_if.if_bpf)
		bpf_ptap(sc->sc_if.if_bpf, m, &af, sizeof(af));

	m->m_pkthdr.rcvif = &sc->sc_if;

	netisr_queue(NETISR_IP, m);
	return(IPPROTO_DONE);
}
Ejemplo n.º 3
0
static int
gre_input2(struct mbuf *m ,int hlen, u_char proto)
{
	static const uint32_t af = AF_INET;
	struct greip *gip = mtod(m, struct greip *);
	int isr;
	struct gre_softc *sc;
	u_short flags;

	if ((sc = gre_lookup(m, proto)) == NULL) {
		/* No matching tunnel or tunnel is down. */
		return (0);
	}

	sc->sc_if.if_ipackets++;
	sc->sc_if.if_ibytes += m->m_pkthdr.len;

	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)
			return(0);
		if (flags & GRE_KP)
			hlen += 4;
		if (flags & GRE_SP)
			hlen +=4;

		switch (ntohs(gip->gi_ptype)) { /* ethertypes */
		case ETHERTYPE_IP:
		case WCCP_PROTOCOL_TYPE:
			isr = NETISR_IP;
			break;
#ifdef NETATALK
		case ETHERTYPE_ATALK:
			isr = NETISR_ATALK1;
			break;
#endif
		case ETHERTYPE_IPV6:
			/* FALLTHROUGH */
		default:	   /* others not yet supported */
			return(0);
		}
		break;
	default:
		/* others not yet supported */
		return(0);
	}

	m->m_data += hlen;
	m->m_len -= hlen;
	m->m_pkthdr.len -= hlen;

	if (sc->sc_if.if_bpf)
		bpf_ptap(sc->sc_if.if_bpf, m, &af, sizeof(af));

	m->m_pkthdr.rcvif = &sc->sc_if;
	netisr_queue(isr, m);
	return(1);	/* packet is done, no further processing needed */
}
Ejemplo n.º 4
0
/*
 * Decapsulate. Does the real work and is called from gre_input()
 * (above). 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.
 */
static struct mbuf *
gre_input2(struct mbuf *m ,int hlen, u_char proto)
{
	struct greip *gip;
	int isr;
	struct gre_softc *sc;
	u_int16_t flags;
	u_int32_t af;

	if ((sc = gre_lookup(m, proto)) == NULL) {
		/* No matching tunnel or tunnel is down. */
		return (m);
	}

	if (m->m_len < sizeof(*gip)) {
		m = m_pullup(m, sizeof(*gip));
		if (m == NULL)
			return (NULL);
	}
	gip = mtod(m, struct greip *);

	GRE2IFP(sc)->if_ipackets++;
	GRE2IFP(sc)->if_ibytes += m->m_pkthdr.len;

	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)
			return (m);
		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:	/* shouldn't need a schednetisr(), */
			isr = NETISR_IP;/* as we are in ip_input */
			af = AF_INET;
			break;
#ifdef INET6
		case ETHERTYPE_IPV6:
			isr = NETISR_IPV6;
			af = AF_INET6;
			break;
#endif
#ifdef NETATALK
		case ETHERTYPE_ATALK:
			isr = NETISR_ATALK1;
			af = AF_APPLETALK;
			break;
#endif
		default:
			/* Others not yet supported. */
			return (m);
		}
		break;
	default:
		/* Others not yet supported. */
		return (m);
	}

	if (hlen > m->m_pkthdr.len) {
		m_freem(m);
		return (NULL);
	}
	/* Unlike NetBSD, in FreeBSD m_adj() adjusts m->m_pkthdr.len as well */
	m_adj(m, hlen);

	if (bpf_peers_present(GRE2IFP(sc)->if_bpf)) {
		bpf_mtap2(GRE2IFP(sc)->if_bpf, &af, sizeof(af), m);
	}

	if ((GRE2IFP(sc)->if_flags & IFF_MONITOR) != 0) {
		m_freem(m);
		return(NULL);
	}

	m->m_pkthdr.rcvif = GRE2IFP(sc);

	netisr_queue(isr, m);

	/* Packet is done, no further processing needed. */
	return (NULL);
}
Ejemplo n.º 5
0
static int
gre_input2(struct mbuf *m ,int hlen, u_char proto)
{
	struct greip *gip = mtod(m, struct greip *);
	int s;
	struct ifqueue *ifq;
	struct gre_softc *sc;
	u_short flags;

	if ((sc = gre_lookup(m, proto)) == NULL) {
		/* No matching tunnel or tunnel is down. */
		return (0);
	}

	sc->sc_if.if_ipackets++;
	sc->sc_if.if_ibytes += m->m_pkthdr.len;

	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)
			return(0);
		if (flags & GRE_KP)
			hlen += 4;
		if (flags & GRE_SP)
			hlen +=4;

		switch (ntohs(gip->gi_ptype)) { /* ethertypes */
		case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
		case WCCP_PROTOCOL_TYPE: /* we are in ip_input */
			ifq = &ipintrq;
			break;
#ifdef NS
		case ETHERTYPE_NS:
			ifq = &nsintrq;
			schednetisr(NETISR_NS);
			break;
#endif
#ifdef NETATALK
		case ETHERTYPE_ATALK:
			ifq = &atintrq1;
			schednetisr(NETISR_ATALK);
			break;
#endif
		case ETHERTYPE_IPV6:
			/* FALLTHROUGH */
		default:	   /* others not yet supported */
			return(0);
		}
		break;
	default:
		/* others not yet supported */
		return(0);
	}

	m->m_data += hlen;
	m->m_len -= hlen;
	m->m_pkthdr.len -= hlen;

	if (sc->sc_if.if_bpf) {
		struct mbuf m0;
		u_int32_t af = AF_INET;

		m0.m_next = m;
		m0.m_len = 4;
		m0.m_data = (char *)&af;

		BPF_MTAP(&(sc->sc_if), &m0);
	}

	m->m_pkthdr.rcvif = &sc->sc_if;

	s = splnet();		/* possible */
	if (_IF_QFULL(ifq)) {
		_IF_DROP(ifq);
		m_freem(m);
	} else {
		IF_ENQUEUE(ifq,m);
	}
	splx(s);

	return(1);	/* packet is done, no further processing needed */
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/*
 * 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;
}