FREE(tc, M_XDATA);
esp_input_cb(void *op){	u_int8_t lastthree[3], aalg[AH_HMAC_HASHLEN];	int hlen, roff, skip, protoff, error;	struct mbuf *m1, *mo, *m;	struct cryptodesc *crd;	struct auth_hash *esph;	struct enc_xform *espx;	struct tdb_crypto *tc;	struct cryptop *crp;	struct m_tag *mtag;	struct tdb *tdb;	u_int32_t btsx;	int s, err = 0;	caddr_t ptr;	crp = (struct cryptop *) op;	crd = crp->crp_desc;	tc = (struct tdb_crypto *) crp->crp_opaque;	skip = tc->tc_skip;	protoff = tc->tc_protoff;	mtag = (struct m_tag *) tc->tc_ptr;	m = (struct mbuf *) crp->crp_buf;	s = spltdb();	tdb = gettdb(tc->tc_spi, &tc->tc_dst, tc->tc_proto);	FREE(tc, M_XDATA);	if (tdb == NULL)	{		espstat.esps_notdb++;		DPRINTF(("esp_input_cb(): TDB is expired while in crypto"));		goto baddone;	}	esph = (struct auth_hash *) tdb->tdb_authalgxform;	espx = (struct enc_xform *) tdb->tdb_encalgxform;	/* Check for crypto errors */	if (crp->crp_etype)	{		/* Reset the session ID */		if (tdb->tdb_cryptoid != 0)			tdb->tdb_cryptoid = crp->crp_sid;		if (crp->crp_etype == EAGAIN)		{			splx(s);			return crypto_dispatch(crp);		}		espstat.esps_noxform++;		DPRINTF(("esp_input_cb(): crypto error %d\n", crp->crp_etype));		error = crp->crp_etype;		goto baddone;	}	/* Shouldn't happen... */	if (m == NULL)	{		espstat.esps_crypto++;		DPRINTF(("esp_input_cb(): bogus returned buffer from crypto\n"));		error = EINVAL;		goto baddone;	}	/* If authentication was performed, check now. */	if (esph != NULL)	{		/*		 * If we have a tag, it means an IPsec-aware NIC did the verification		 * for us.		 */		if (mtag != NULL)		{			/* Copy the authenticator from the packet */			m_copydata(m, m->m_pkthdr.len - esph->authsize, esph->authsize,			    aalg);			ptr = (caddr_t) (tc + 1);			/* Verify authenticator */			if (bcmp(ptr, aalg, esph->authsize))			{				DPRINTF(("esp_input_cb(): authentication failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));				espstat.esps_badauth++;				error = EACCES;				goto baddone;			}		}		/* Remove trailing authenticator */		m_adj(m, -(esph->authsize));	}	/* Replay window checking, if appropriate */	if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY)))	{		m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),		    (unsigned char *) &btsx);		btsx = ntohl(btsx);		switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl),		    tdb->tdb_wnd, &(tdb->tdb_bitmap), 1))		{		case 0: /* All's well */			break;		case 1:			DPRINTF(("esp_input_cb(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));			espstat.esps_wrap++;			error = EACCES;			goto baddone;		case 2:		case 3:			DPRINTF(("esp_input_cb(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));			error = EACCES;			goto baddone;		default:			DPRINTF(("esp_input_cb(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));			espstat.esps_replay++;			error = EACCES;			goto baddone;		}	}	/* Release the crypto descriptors */	crypto_freereq(crp);	/* Determine the ESP header length */	if (tdb->tdb_flags & TDBF_NOREPLAY)		hlen = sizeof(u_int32_t) + tdb->tdb_ivlen; /* "old" ESP */	else		hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen; /* "new" ESP */	/* Find beginning of ESP header */	m1 = m_getptr(m, skip, &roff);	if (m1 == NULL)	{		espstat.esps_hdrops++;		splx(s);		DPRINTF(("esp_input_cb(): bad mbuf chain, SA %s/%08x\n",		    ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));		m_freem(m);		return EINVAL;	}	/* Remove the ESP header and IV from the mbuf. */	if (roff == 0)	{		/* The ESP header was conveniently at the beginning of the mbuf */		m_adj(m1, hlen);		if (!(m1->m_flags & M_PKTHDR))			m->m_pkthdr.len -= hlen;	}	else		if (roff + hlen >= m1->m_len)		{			/*			 * Part or all of the ESP header is at the end of this mbuf, so			 * first let's remove the remainder of the ESP header from the			 * beginning of the remainder of the mbuf chain, if any.			 */			if (roff + hlen > m1->m_len)			{				/* Adjust the next mbuf by the remainder */				m_adj(m1->m_next, roff + hlen - m1->m_len);				/* The second mbuf is guaranteed not to have a pkthdr... */				m->m_pkthdr.len -= (roff + hlen - m1->m_len);			}			/* Now, let's unlink the mbuf chain for a second...*/			mo = m1->m_next;			m1->m_next = NULL;			/* ...and trim the end of the first part of the chain...sick */			m_adj(m1, -(m1->m_len - roff));			if (!(m1->m_flags & M_PKTHDR))				m->m_pkthdr.len -= (m1->m_len - roff);			/* Finally, let's relink */			m1->m_next = mo;		}		else		{			/*			 * The ESP header lies in the "middle" of the mbuf...do an			 * overlapping copy of the remainder of the mbuf over the ESP			 * header.			 */			bcopy(mtod(m1, u_char *) + roff + hlen, mtod(m1, u_char *) + roff,			    m1->m_len - (roff + hlen));			m1->m_len -= hlen;			m->m_pkthdr.len -= hlen;		}	/* Save the last three bytes of decrypted data */	m_copydata(m, m->m_pkthdr.len - 3, 3, lastthree);	/* Verify pad length */	if (lastthree[1] + 2 > m->m_pkthdr.len - skip)	{		espstat.esps_badilen++;		splx(s);		DPRINTF(("esp_input_cb(): invalid padding length %d for packet in SA %s/%08x\n", lastthree[1], ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));		m_freem(m);		return EINVAL;	}	/* Verify correct decryption by checking the last padding bytes */	if (!(tdb->tdb_flags & TDBF_RANDOMPADDING))	{		if ((lastthree[1] != lastthree[0]) && (lastthree[1] != 0))		{			espstat.esps_badenc++;			splx(s);			DPRINTF(("esp_input(): decryption failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));			m_freem(m);			return EINVAL;		}	}	/* Trim the mbuf chain to remove the trailing authenticator and padding */	m_adj(m, -(lastthree[1] + 2));	/* Restore the Next Protocol field */	m_copyback(m, protoff, sizeof(u_int8_t), lastthree + 2);	/* Back to generic IPsec input processing */	err = ipsec_common_input_cb(m, tdb, skip, protoff, mtag);	splx(s);	return err; baddone:	splx(s);	if (m != NULL)		m_freem(m);	crypto_freereq(crp);	return error;}