Esempio 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 *);
	}
Esempio n. 2
0
static int
in_gre_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
{
	GRE_RLOCK_TRACKER;
	struct gre_softc *sc;
	struct ip *ip;

	sc = (struct gre_softc *)arg;
	if ((GRE2IFP(sc)->if_flags & IFF_UP) == 0)
		return (0);

	M_ASSERTPKTHDR(m);
	/*
	 * We expect that payload contains at least IPv4
	 * or IPv6 packet.
	 */
	if (m->m_pkthdr.len < sizeof(struct greip) + sizeof(struct ip))
		return (0);

	GRE_RLOCK(sc);
	if (sc->gre_family == 0)
		goto bad;

	KASSERT(sc->gre_family == AF_INET,
	    ("wrong gre_family: %d", sc->gre_family));

	ip = mtod(m, struct ip *);
	if (sc->gre_oip.ip_src.s_addr != ip->ip_dst.s_addr ||
	    sc->gre_oip.ip_dst.s_addr != ip->ip_src.s_addr)
		goto bad;

	GRE_RUNLOCK(sc);
	return (32 * 2);
bad:
	GRE_RUNLOCK(sc);
	return (0);
}
Esempio n. 3
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);
}