Exemplo n.º 1
0
/*
 * m_megapullup() - this function is a big hack.
 * Thankfully, it's only used in ng_nat and ipfw+nat.
 *
 * It allocates an mbuf with cluster and copies the specified part of the chain
 * into cluster, so that it is all contiguous and can be accessed via a plain
 * (char *) pointer. This is required, because libalias doesn't know how to
 * handle mbuf chains.
 *
 * On success, m_megapullup returns an mbuf (possibly with cluster) containing
 * the input packet, on failure NULL. The input packet is always consumed.
 */
struct mbuf *
m_megapullup(struct mbuf *m, int len) {
	struct mbuf *mcl;

	if (len > m->m_pkthdr.len)
		goto bad;

	if (m->m_next == NULL && M_WRITABLE(m))
		return (m);

	mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
	if (mcl == NULL)
		goto bad;
	m_align(mcl, len);
	m_move_pkthdr(mcl, m);
	m_copydata(m, 0, len, mtod(mcl, caddr_t));
	mcl->m_len = mcl->m_pkthdr.len = len;
	m_freem(m);

	return (mcl);
bad:
	m_freem(m);
	return (NULL);
}
Exemplo n.º 2
0
static struct mbuf *
rtwn_rx_copy_to_mbuf(struct rtwn_softc *sc, struct r92c_rx_stat *stat,
    int totlen)
{
	struct ieee80211com *ic = &sc->sc_ic;
	struct mbuf *m;
	uint32_t rxdw0;
	int pktlen;

	RTWN_ASSERT_LOCKED(sc);

	/* Dump Rx descriptor. */
	RTWN_DPRINTF(sc, RTWN_DEBUG_RECV_DESC,
	    "%s: dw: 0 %08X, 1 %08X, 2 %08X, 3 %08X, 4 %08X, tsfl %08X\n",
	    __func__, le32toh(stat->rxdw0), le32toh(stat->rxdw1),
	    le32toh(stat->rxdw2), le32toh(stat->rxdw3), le32toh(stat->rxdw4),
	    le32toh(stat->tsf_low));

	/*
	 * don't pass packets to the ieee80211 framework if the driver isn't
	 * RUNNING.
	 */
	if (!(sc->sc_flags & RTWN_RUNNING))
		return (NULL);

	rxdw0 = le32toh(stat->rxdw0);
	if (__predict_false(rxdw0 & (R92C_RXDW0_CRCERR | R92C_RXDW0_ICVERR))) {
		/*
		 * This should not happen since we setup our Rx filter
		 * to not receive these frames.
		 */
		RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
		    "%s: RX flags error (%s)\n", __func__,
		    rxdw0 & R92C_RXDW0_CRCERR ? "CRC" : "ICV");
		goto fail;
	}

	pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN);
	if (__predict_false(pktlen < sizeof(struct ieee80211_frame_ack))) {
		/*
		 * Should not happen (because of Rx filter setup).
		 */
		RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
		    "%s: frame is too short: %d\n", __func__, pktlen);
		goto fail;
	}

	m = m_get2(totlen, M_NOWAIT, MT_DATA, M_PKTHDR);
	if (__predict_false(m == NULL)) {
		device_printf(sc->sc_dev, "%s: could not allocate RX mbuf\n",
		    __func__);
		goto fail;
	}

	/* Finalize mbuf. */
	memcpy(mtod(m, uint8_t *), (uint8_t *)stat, totlen);
	m->m_pkthdr.len = m->m_len = totlen;

	if (rtwn_check_frame(sc, m) != 0) {
		m_freem(m);
		goto fail;
	}

	return (m);
fail:
	counter_u64_add(ic->ic_ierrors, 1);
	return (NULL);
}