pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
esp_new_input(struct mbuf *m, struct tdb *tdb){    struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;    struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;    u_char iv[ESP_MAX_IVS], niv[ESP_MAX_IVS];    u_char blk[ESP_MAX_BLKS], *lblk, opts[40];    int ohlen, oplen, plen, alen, ilen, i, blks, rest;    int count, off, errc;    struct mbuf *mi, *mo;    u_char *idat, *odat, *ivp, *ivn;    struct esp_new *esp;    struct ip *ip, ipo;    u_int32_t btsx;    union {	 MD5_CTX md5ctx;	 SHA1_CTX sha1ctx;	 RMD160_CTX rmd160ctx;    } ctx;    u_char buf[AH_ALEN_MAX], buf2[AH_ALEN_MAX];    blks = espx->blocksize;    if (esph)      alen = AH_HMAC_HASHLEN;    else      alen = 0;    if (m->m_len < sizeof(struct ip))    {	if ((m = m_pullup(m, sizeof(struct ip))) == NULL)	{	    DPRINTF(("esp_new_input(): (possibly too short) packet dropped\n"));	    espstat.esps_hdrops++;	    return NULL;	}    }    ip = mtod(m, struct ip *);    ohlen = (ip->ip_hl << 2) + ESP_NEW_FLENGTH;    /* Make sure the IP header, any IP options, and the ESP header are here */    if (m->m_len < ohlen + blks)    {	if ((m = m_pullup(m, ohlen + blks)) == NULL)	{            DPRINTF(("esp_new_input(): m_pullup() failed\n"));	    espstat.esps_hdrops++;            return NULL;	}	ip = mtod(m, struct ip *);    }    /* Update the counters */    tdb->tdb_cur_bytes += ip->ip_len - ohlen - alen;    espstat.esps_ibytes += ip->ip_len - ohlen - alen;    /* Hard expiration */    if ((tdb->tdb_flags & TDBF_BYTES) &&	(tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))    {/* XXX   encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);*/	tdb_delete(tdb, 0);	m_freem(m);	return NULL;    }    /* Notify on expiration */    if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&	(tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))    {/* XXX   encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);*/	tdb->tdb_flags &= ~TDBF_SOFT_BYTES;       /* Turn off checking */    }    esp = (struct esp_new *) ((u_int8_t *) ip + (ip->ip_hl << 2));    ipo = *ip;    /* Replay window checking */    if (tdb->tdb_wnd > 0)    {	btsx = ntohl(esp->esp_rpl);	if ((errc = checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl), tdb->tdb_wnd,					&(tdb->tdb_bitmap))) != 0)	{	    switch(errc)	    {		case 1:		    DPRINTF(("esp_new_input(): replay counter wrapped for packets from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi)));		    espstat.esps_wrap++;		    break;		case 2:	        case 3:		    DPRINTF(("esp_new_input(): duplicate packet received from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi)));		    espstat.esps_replay++;		    break;	    }	    m_freem(m);	    return NULL;	}    }    /* Skip the IP header, IP options, SPI, SN and IV and minus Auth Data */    plen = m->m_pkthdr.len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) - 	   tdb->tdb_ivlen - alen;    if ((plen & (blks - 1)) || (plen <= 0))    {	DPRINTF(("esp_new_input(): payload not a multiple of %d octets for packet from %s to %s, spi %08x\n", blks, inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));	espstat.esps_badilen++;	m_freem(m);	return NULL;    }    if (esph)    {	bcopy(tdb->tdb_ictx, &ctx, esph->ctxsize);	/* Auth covers SPI + SN + IV */	oplen = plen + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen; 	off = (ip->ip_hl << 2);	/* Copy the authentication data */	m_copydata(m, m->m_pkthdr.len - alen, alen, buf);	mo = m;	while (oplen > 0)	{	    if (mo == 0)	    {		DPRINTF(("esp_new_input(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi)));		espstat.esps_hdrops++;		m_freem(m);		return NULL;	    }	    count = min(mo->m_len - off, oplen);	    esph->Update(&ctx, mtod(mo, unsigned char *) + off, count);	    oplen -= count;	    off = 0;	    mo = mo->m_next;	}	esph->Final(buf2, &ctx);	bcopy(tdb->tdb_octx, &ctx, esph->ctxsize);	esph->Update(&ctx, buf2, esph->hashsize);	esph->Final(buf2, &ctx);	if (bcmp(buf2, buf, AH_HMAC_HASHLEN))	{	    DPRINTF(("esp_new_input(): authentication failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi)));	    espstat.esps_badauth++;	    m_freem(m);	    return NULL;	}    }    oplen = plen;    ilen = m->m_len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t);    idat = mtod(m, unsigned char *) + (ip->ip_hl << 2) + 2 * sizeof(u_int32_t);    bcopy(idat, iv, tdb->tdb_ivlen);    ilen -= tdb->tdb_ivlen;    idat += tdb->tdb_ivlen;    mi = m;    /*     * At this point:     *   plen is # of encapsulated payload octets     *   ilen is # of octets left in this mbuf     *   idat is first encapsulated payload octed in this mbuf     *   same for olen and odat     *   ivp points to the IV, ivn buffers the next IV.     *   mi points to the first mbuf     *     * From now on until the end of the mbuf chain:     *   . move the next eight octets of the chain into ivn     *   . decrypt idat and xor with ivp     *   . swap ivp and ivn.     *   . repeat     */    ivp = iv;    ivn = niv;    rest = ilen % blks;    while (plen > 0)		/* while not done */    {	if (ilen < blks) 	{	    if (rest)	    {		bcopy(idat, blk, rest);		odat = idat;	    }	    do {		mi = (mo = mi)->m_next;		if (mi == NULL)		{		    DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));		    espstat.esps_hdrops++;		    m_freem(m);		    return NULL;		}	    } while (mi->m_len == 0);	    if (mi->m_len < blks - rest)	    {		if ((mi = m_pullup(mi, blks - rest)) == NULL) 		{		    DPRINTF(("esp_new_input(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));		    m_freem(m);		    espstat.esps_hdrops++;		    return NULL;		}		/* 		 * m_pullup was not called at the beginning of the chain		 * but might return a new mbuf, link it into the chain.		 */		mo->m_next = mi;	    }		    	    ilen = mi->m_len;	    idat = mtod(mi, u_char *);	    if (rest)	    {		bcopy(idat, blk + rest, blks - rest);		bcopy(blk, ivn, blks);		    		espx->decrypt(tdb, blk);		for (i = 0; i < blks; i++)		    blk[i] ^= ivp[i];		ivp = ivn;		ivn = (ivp == iv) ? niv : iv;		bcopy(blk, odat, rest);		bcopy(blk + rest, idat, blks - rest);		lblk = blk;   /* last block touched */				idat += blks - rest;		ilen -= blks - rest;		plen -= blks;	    }	    rest = ilen % blks;	}	while (ilen >= blks && plen > 0)	{	    bcopy(idat, ivn, blks);	    espx->decrypt(tdb, idat);	    for (i = 0; i < blks; i++)		idat[i] ^= ivp[i];	    ivp = ivn;	    ivn = (ivp == iv) ? niv : iv;	    lblk = idat;   /* last block touched */	    idat += blks;	    ilen -= blks;	    plen -= blks;	}    }    /* Save the options */    m_copydata(m, sizeof(struct ip), (ipo.ip_hl << 2) - sizeof(struct ip),	       (caddr_t) opts);    if (lblk != blk)      bcopy(lblk, blk, blks);    /*     * Now, the entire chain has been decrypted. As a side effect,     * blk[blks - 1] contains the next protocol, and blk[blks - 2] contains     * the amount of padding the original chain had. Chop off the     * appropriate parts of the chain, and return.     * Verify correct decryption by checking the last padding bytes.     */    if (blk[blks - 2] + 2 + alen > m->m_pkthdr.len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) - tdb->tdb_ivlen)    {	DPRINTF(("esp_new_input(): invalid padding length %d for packet from %s to %s, spi %08x\n", blk[blks - 2], inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));	espstat.esps_badilen++;	m_freem(m);	return NULL;    }    if ((blk[blks - 2] != blk[blks - 3]) && (blk[blks - 2] != 0))    {	DPRINTF(("esp_new_input(): decryption failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));	m_freem(m);	return NULL;    }     m_adj(m, - blk[blks - 2] - 2 - alen);		/* Old type padding */    m_adj(m, 2 * sizeof(u_int32_t) + tdb->tdb_ivlen);    if (m->m_len < (ipo.ip_hl << 2))    {	m = m_pullup(m, (ipo.ip_hl << 2));	if (m == NULL)	{	    DPRINTF(("esp_new_input(): m_pullup() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));	    espstat.esps_hdrops++;	    return NULL;	}    }    ip = mtod(m, struct ip *);    ipo.ip_p = blk[blks - 1];    ipo.ip_id = htons(ipo.ip_id);    ipo.ip_off = 0;    ipo.ip_len += (ipo.ip_hl << 2) -  2 * sizeof(u_int32_t) - tdb->tdb_ivlen -		  blk[blks - 2] - 2 - alen;    ipo.ip_len = htons(ipo.ip_len);    ipo.ip_sum = 0;    *ip = ipo;    /* Copy the options back */    m_copyback(m, sizeof(struct ip), (ipo.ip_hl << 2) - sizeof(struct ip),	       (caddr_t) opts);    ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));    return m;}