pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,  	      struct mbuf **mp){    struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;    struct ip *ip, ipo;    struct ah_old *ah, aho;    register int len, off, count;    register struct mbuf *m0;    union {	 MD5_CTX md5ctx;	 SHA1_CTX sha1ctx;    } ctx;    int ilen, ohlen, alen;    u_int8_t optval;    u_char opts[40];    alen = ahx->hashsize;    ahstat.ahs_output++;    m = m_pullup(m, sizeof(struct ip));    if (m == NULL)    {	DPRINTF(("ah_old_output(): m_pullup() failed, SA %s/%08x\n",		 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));	ahstat.ahs_hdrops++;      	return ENOBUFS;    }    ip = mtod(m, struct ip *);	    /* Update the counters */    tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) -			  AH_OLD_FLENGTH - alen;    ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) -			 AH_OLD_FLENGTH - 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 EINVAL;    }    /* 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 */      }    if ((ip->ip_hl << 2) > sizeof(struct ip))    {	if ((m = m_pullup(m, ip->ip_hl << 2)) == NULL)	{	    DPRINTF(("ah_old_output(): m_pullup() failed, SA %s/%08x\n",		     ipsp_address(tdb->tdb_dst),		     ntohl(tdb->tdb_spi)));	    ahstat.ahs_hdrops++;	    return ENOBUFS;	}		ip = mtod(m, struct ip *);    }    /* Save the options */    m_copydata(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),	       (caddr_t) opts);    ilen = ntohs(ip->ip_len);    ohlen = AH_OLD_FLENGTH + alen;    if (ohlen + ilen > IP_MAXPACKET)    {	DPRINTF(("ah_old_output(): packet in SA %s/%0x8 got too big\n",		 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));	m_freem(m);	ahstat.ahs_toobig++;        return EMSGSIZE;    }	    ipo.ip_v = IPVERSION;    ipo.ip_hl = ip->ip_hl;    ipo.ip_tos = 0;    ipo.ip_len = htons(ohlen + ilen);    ipo.ip_id = ip->ip_id;    ipo.ip_off = htons(ntohs(ip->ip_off) & IP_DF);    ipo.ip_ttl = 0;    ipo.ip_p = IPPROTO_AH;    ipo.ip_sum = 0;    ipo.ip_src = ip->ip_src;    ipo.ip_dst = ip->ip_dst;    aho.ah_nh = ip->ip_p;    aho.ah_hl = alen >> 2;    aho.ah_rv = 0;    aho.ah_spi = tdb->tdb_spi;    bcopy(tdb->tdb_ictx, &ctx, ahx->ctxsize);    ahx->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));    /* Options */    if ((ip->ip_hl << 2) > sizeof(struct ip))      for (off = sizeof(struct ip); off < (ip->ip_hl << 2);)      {	  optval = ((u_int8_t *) ip)[off];	  switch (optval)	  {              case IPOPT_EOL:		  ahx->Update(&ctx, ipseczeroes, 1);                  off = ip->ip_hl << 2;                  break;              case IPOPT_NOP:		  ahx->Update(&ctx, ipseczeroes, 1);                  off++;                  break;              case IPOPT_SECURITY:              case 133:              case 134:                  optval = ((u_int8_t *) ip)[off + 1];		  ahx->Update(&ctx, (u_int8_t *) ip + off, optval);                  off += optval;                  break;              default:                  optval = ((u_int8_t *) ip)[off + 1];		  ahx->Update(&ctx, ipseczeroes, optval);                  off += optval;                  break;          }      }    ahx->Update(&ctx, (unsigned char *) &aho, AH_OLD_FLENGTH);    ahx->Update(&ctx, ipseczeroes, alen);    /* Skip the IP header and any options */    off = ip->ip_hl << 2;    /*     * Code shamelessly stolen from m_copydata     */    len = m->m_pkthdr.len - off;	    m0 = m;    while (len > 0)    {	if (m0 == 0)	{	    DPRINTF(("ah_old_output(): M_PREPEND() 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;	}		count = min(m0->m_len - off, len);	ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count);	len -= count;	off = 0;	m0 = m0->m_next;    }    ahx->Update(&ctx, (unsigned char *) tdb->tdb_amxkey, tdb->tdb_amxkeylen);    ipo.ip_tos = ip->ip_tos;    ipo.ip_id = ip->ip_id;    ipo.ip_off = ip->ip_off;    ipo.ip_ttl = ip->ip_ttl;/*  ipo.ip_len = ntohs(ipo.ip_len); */	    M_PREPEND(m, ohlen, M_DONTWAIT);    if (m == NULL)    {	DPRINTF(("ah_old_output(): M_PREPEND() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));        return ENOBUFS;    }    m = m_pullup(m, ohlen + (ipo.ip_hl << 2));    if (m == NULL)    {	DPRINTF(("ah_old_output(): 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)));	ahstat.ahs_hdrops++;        return ENOBUFS;    }    ip = mtod(m, struct ip *);    ah = (struct ah_old *) ((u_int8_t *) ip + (ipo.ip_hl << 2));    *ip = ipo;    ah->ah_nh = aho.ah_nh;    ah->ah_hl = aho.ah_hl;    ah->ah_rv = aho.ah_rv;    ah->ah_spi = aho.ah_spi;    /* Restore the options */    m_copyback(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),	       (caddr_t) opts);    ahx->Final(ah->ah_data, &ctx);    *mp = m;    return 0;}