Пример #1
0
/*
 * bpf_mtap into the ipfw interface.
 * eh == NULL when mbuf is a packet, then use the fake_eh
 * the ip_len need to be twisted before and after bpf copy.
 */
void
ipfw_log(struct mbuf *m, struct ether_header *eh, uint16_t id)
{
	struct ifnet *the_if = NULL;

	if (fw_verbose) {
#ifndef WITHOUT_BPF
		LOGIF_RLOCK();
		the_if = log_if_table[id];
		if (the_if == NULL || the_if->if_bpf == NULL) {
			LOGIF_RUNLOCK();
			return;
		}
		if (eh != NULL) {
			bpf_gettoken();
			bpf_mtap_hdr(the_if->if_bpf, (caddr_t)eh,
					ETHER_HDR_LEN, m, 0);
			bpf_reltoken();

		} else {
			struct ip *ip;
			ip = mtod(m, struct ip *);
			/* twist the ip_len for the bpf copy */
			ip->ip_len =htons(ip->ip_len);

			bpf_gettoken();
			bpf_mtap_hdr(the_if->if_bpf, (caddr_t)fake_eh,
					ETHER_HDR_LEN, m, 0);
			bpf_reltoken();
			ip->ip_len =ntohs(ip->ip_len);

		}
		LOGIF_RUNLOCK();
#endif	/* !WITHOUT_BPF */
	}
}
Пример #2
0
/*
 * The output routine. Takes a packet and encapsulates it in the protocol
 * given by sc->g_proto. See also RFC 1701 and RFC 2004
 */
static int
gre_output_serialized(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
		      struct rtentry *rt)
{
	int error = 0;
	struct gre_softc *sc = ifp->if_softc;
	struct greip *gh;
	struct ip *ip;
	u_short etype = 0;
	struct mobile_h mob_h;
	struct route *ro;
	struct sockaddr_in *ro_dst;

	ASSERT_NETISR_NCPUS(mycpuid);

	/*
	 * gre may cause infinite recursion calls when misconfigured.
	 * We'll prevent this by introducing upper limit.
	 */
	if (++(sc->called) > max_gre_nesting) {
		kprintf("%s: gre_output: recursively called too many "
		       "times(%d)\n", if_name(&sc->sc_if), sc->called);
		m_freem(m);
		error = EIO;    /* is there better errno? */
		goto end;
	}

	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 0 ||
	    sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
		m_freem(m);
		error = ENETDOWN;
		goto end;
	}

	ro = &sc->route_pcpu[mycpuid];
	ro_dst = (struct sockaddr_in *)&ro->ro_dst;
	if (ro->ro_rt != NULL &&
	    ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
	     ro_dst->sin_addr.s_addr != sc->g_dst.s_addr)) {
		RTFREE(ro->ro_rt);
		ro->ro_rt = NULL;
	}
	if (ro->ro_rt == NULL) {
		error = gre_compute_route(sc, ro);
		if (error) {
			m_freem(m);
			goto end;
		}
	}

	gh = NULL;
	ip = NULL;

	if (ifp->if_bpf) {
		bpf_gettoken();
		if (ifp->if_bpf) {
			uint32_t af = dst->sa_family;

			bpf_ptap(ifp->if_bpf, m, &af, sizeof(af));
		}
		bpf_reltoken();
	}

	m->m_flags &= ~(M_BCAST|M_MCAST);

	if (sc->g_proto == IPPROTO_MOBILE) {
		if (dst->sa_family == AF_INET) {
			struct mbuf *m0;
			int msiz;

			ip = mtod(m, struct ip *);

			/*
			 * RFC2004 specifies that fragmented datagrams shouldn't
			 * be encapsulated.
			 */
			if (ip->ip_off & (IP_MF | IP_OFFMASK)) {
				m_freem(m);
				error = EINVAL;    /* is there better errno? */
				goto end;
			}
			memset(&mob_h, 0, MOB_H_SIZ_L);
			mob_h.proto = (ip->ip_p) << 8;
			mob_h.odst = ip->ip_dst.s_addr;
			ip->ip_dst.s_addr = sc->g_dst.s_addr;

			/*
			 * If the packet comes from our host, we only change
			 * the destination address in the IP header.
			 * Else we also need to save and change the source
			 */
			if (in_hosteq(ip->ip_src, sc->g_src)) {
				msiz = MOB_H_SIZ_S;
			} else {
				mob_h.proto |= MOB_H_SBIT;
				mob_h.osrc = ip->ip_src.s_addr;
				ip->ip_src.s_addr = sc->g_src.s_addr;
				msiz = MOB_H_SIZ_L;
			}
			mob_h.proto = htons(mob_h.proto);
			mob_h.hcrc = gre_in_cksum((u_short *)&mob_h, msiz);

			if ((m->m_data - msiz) < m->m_pktdat) {
				/* need new mbuf */
				MGETHDR(m0, M_NOWAIT, MT_HEADER);
				if (m0 == NULL) {
					m_freem(m);
					error = ENOBUFS;
					goto end;
				}
				m0->m_next = m;
				m->m_data += sizeof(struct ip);
				m->m_len -= sizeof(struct ip);
				m0->m_pkthdr.len = m->m_pkthdr.len + msiz;
				m0->m_len = msiz + sizeof(struct ip);
				m0->m_data += max_linkhdr;
				memcpy(mtod(m0, caddr_t), (caddr_t)ip,
				       sizeof(struct ip));
				m = m0;
			} else {  /* we have some space left in the old one */
				m->m_data -= msiz;
				m->m_len += msiz;
				m->m_pkthdr.len += msiz;
				bcopy(ip, mtod(m, caddr_t),
					sizeof(struct ip));
			}
			ip = mtod(m, struct ip *);
			memcpy((caddr_t)(ip + 1), &mob_h, (unsigned)msiz);
			ip->ip_len = ntohs(ip->ip_len) + msiz;
		} else {  /* AF_INET */
			m_freem(m);
			error = EINVAL;
			goto end;
		}
	} else if (sc->g_proto == IPPROTO_GRE) {