crp->crp_opaque2 = (caddr_t) skip; crp->crp_opaque3 = (caddr_t) protoff;
(long) crp->crp_opaque2 = skip; (long) crp->crp_opaque3 = protoff;
ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,	  int protoff){    struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;    struct cryptodesc *crda;    struct mbuf *mo, *mi;    struct cryptop *crp;    u_int16_t iplen;    int len, rplen;    struct ah *ah;#if NBPFILTER > 0    {	struct ifnet *ifn;	struct enchdr hdr;	struct mbuf m1;	bzero (&hdr, sizeof(hdr));	hdr.af = tdb->tdb_dst.sa.sa_family;	hdr.spi = tdb->tdb_spi;	hdr.flags |= M_AUTH;	m1.m_next = m;	m1.m_len = ENC_HDRLEN;	m1.m_data = (char *) &hdr;	if (tdb->tdb_interface)	  ifn = (struct ifnet *) tdb->tdb_interface;	else	  ifn = &(encif[0].sc_if);	if (ifn->if_bpf)	  bpf_mtap(ifn->if_bpf, &m1);    }#endif    ahstat.ahs_output++;    /* Check for replay counter wrap-around in automatic (not manual) keying */    if ((tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0) &&	(!(tdb->tdb_flags & TDBF_NOREPLAY)))    {	DPRINTF(("ah_output(): SA %s/%08x should have expired\n",		 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));	m_freem(m);	ahstat.ahs_wrap++;	return NULL;    }    if (!(tdb->tdb_flags & TDBF_NOREPLAY))      rplen = AH_FLENGTH + sizeof(u_int32_t);    else      rplen = AH_FLENGTH;    switch (tdb->tdb_dst.sa.sa_family)    {#ifdef INET	case AF_INET:	    /* Check for IP maximum packet size violations */	    if (rplen + ahx->authsize + m->m_pkthdr.len > IP_MAXPACKET)	    {		DPRINTF(("ah_output(): packet in SA %s/%08x got too big\n",			 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));		m_freem(m);		ahstat.ahs_toobig++;		return EMSGSIZE;	    }	    break;#endif /* INET */#ifdef INET6	case AF_INET6:	    /* Check for IPv6 maximum packet size violations */	    if (rplen + ahx->authsize + m->m_pkthdr.len > IPV6_MAXPACKET)	    {		DPRINTF(("ah_output(): packet in SA %s/%08x got too big\n",			 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));		m_freem(m);		ahstat.ahs_toobig++;		return EMSGSIZE;	    }	    break;#endif /* INET6 */	default:	    DPRINTF(("ah_output(): unknown/unsupported protocol family %d, SA %s/%08x\n", tdb->tdb_dst.sa.sa_family, ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));	    m_freem(m);	    ahstat.ahs_nopf++;	    return EPFNOSUPPORT;    }    /* Update the counters */    tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;    ahstat.ahs_obytes += m->m_pkthdr.len - skip;    /* Hard expiration */    if ((tdb->tdb_flags & TDBF_BYTES) &&	(tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))      {	  pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);	  tdb_delete(tdb, 0, TDBEXP_TIMEOUT);	  m_freem(m);	  return EINVAL;      }    /* Notify on expiration */    if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&	(tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))    {	pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);	tdb->tdb_flags &= ~TDBF_SOFT_BYTES;      /* Turn off checking */    }    /*     * Loop through mbuf chain; if we find an M_EXT mbuf with      * more than one reference, replace the rest of the chain.     */    mi = m;    while (mi != NULL && 	   (!(mi->m_flags & M_EXT) || 	    (mi->m_ext.ext_ref == NULL &&	     mclrefcnt[mtocl(mi->m_ext.ext_buf)] <= 1)))    {        mo = mi;        mi = mi->m_next;    }         if (mi != NULL)    {        /* Replace the rest of the mbuf chain. */        struct mbuf *n = m_copym2(mi, 0, M_COPYALL, M_DONTWAIT);              if (n == NULL)        {	    ahstat.ahs_hdrops++;	    m_freem(m);	    return ENOBUFS;        }        if (mo != NULL)	  mo->m_next = n;        else	  m = n;        m_freem(mi);    }    /* Inject AH header */    mi = m_inject(m, skip, rplen + ahx->authsize, M_DONTWAIT);    if (mi == NULL)    {	DPRINTF(("ah_output(): failed to inject AH header for SA %s/%08x\n",		 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));	m_freem(m);	ahstat.ahs_wrap++;	return ENOBUFS;    }    /*     * The AH header is guaranteed by m_inject() to be in contiguous memory,     * at the beginning of the returned mbuf.     */    ah = mtod(mi, struct ah *);        /* Initialize the AH header */    m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &ah->ah_nh);    ah->ah_hl = (rplen + ahx->authsize - AH_FLENGTH) / sizeof(u_int32_t);    ah->ah_rv = 0;    ah->ah_spi = tdb->tdb_spi;    /* Zeroize authenticator */    m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes);    if (!(tdb->tdb_flags & TDBF_NOREPLAY))      ah->ah_rpl = htonl(tdb->tdb_rpl++);    /* Get crypto descriptors */    crp = crypto_getreq(1);    if (crp == NULL)    {	m_freem(m);	DPRINTF(("ah_output(): failed to acquire crypto descriptors\n"));	ahstat.ahs_crypto++;	return ENOBUFS;    }    crda = crp->crp_desc;    crda->crd_skip = 0;    crda->crd_inject = skip + rplen;    crda->crd_len = m->m_pkthdr.len;    /* Authentication operation */    crda->crd_alg = ahx->type;    crda->crd_key = tdb->tdb_amxkey;    crda->crd_klen = tdb->tdb_amxkeylen * 8;    /* Save the skipped portion of the packet */    MALLOC(crp->crp_opaque4, caddr_t, skip, M_XDATA, M_DONTWAIT);    if (crp->crp_opaque4 == 0)    {	m_freem(m);	crypto_freereq(crp);	DPRINTF(("ah_output(): failed to allocate auth array\n"));	ahstat.ahs_crypto++;	return ENOBUFS;    }    else      m_copydata(m, 0, skip, crp->crp_opaque4);    /*     * Fix IP header length on the header used for authentication. We don't     * need to fix the original header length as it will be fixed by our     * caller.     */    switch (tdb->tdb_dst.sa.sa_family)    {#ifdef INET	case AF_INET:	    bcopy(crp->crp_opaque4 + offsetof(struct ip, ip_len),		  (caddr_t) &iplen, sizeof(u_int16_t));	    iplen = htons(ntohs(iplen) + rplen + ahx->authsize);	    m_copyback(m, offsetof(struct ip, ip_len), sizeof(u_int16_t),		       (caddr_t) &iplen);	    break;#endif /* INET */#ifdef INET6	case AF_INET6:	    bcopy(crp->crp_opaque4 + offsetof(struct ip6_hdr, ip6_plen),		  (caddr_t) &iplen, sizeof(u_int16_t));	    iplen = htons(ntohs(iplen) + rplen + ahx->authsize);	    m_copyback(m, offsetof(struct ip6_hdr, ip6_plen),		       sizeof(u_int16_t), (caddr_t) &iplen);	    break;#endif /* INET6 */    }    tdb->tdb_ref++;    /* Update the Next Protocol field in the IP header and the saved data */    len = IPPROTO_AH;    m_copyback(m, protoff, sizeof(u_int8_t), (caddr_t) &len);    ((u_int8_t *) crp->crp_opaque4)[protoff] = IPPROTO_AH;    /* "Massage" the packet headers for crypto processing */    if ((len = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family,				  skip, ahx->type, 1)) != 0)    {	/* mbuf will be free'd by callee */	FREE(crp->crp_opaque4, M_XDATA);	crypto_freereq(crp);	return len;    }    /* Crypto operation descriptor */    crp->crp_ilen = m->m_pkthdr.len; /* Total input length */    crp->crp_flags = CRYPTO_F_IMBUF;    crp->crp_buf = (caddr_t) m;    crp->crp_callback = (int (*) (struct cryptop *)) ah_output_cb;    crp->crp_sid = tdb->tdb_cryptoid;    /* These are passed as-is to the callback */    crp->crp_opaque1 = (caddr_t) tdb;    crp->crp_opaque2 = (caddr_t) skip;    crp->crp_opaque3 = (caddr_t) protoff;    return crypto_dispatch(crp);}