diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1999-02-24 22:33:08 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1999-02-24 22:33:08 +0000 |
commit | bc6ad109752ee01f946571f9488d7335d751b7fe (patch) | |
tree | 51a5f44fa5bf81542dfc5c8ad510f1f8cf4a6691 /sys/netinet/ip_ah_new.c | |
parent | 689ba6c5dcae1e6d1086d01cfc27fd19a8e11b03 (diff) |
Remove encap.h include; saner debugging printfs; fix buglets; work with
pfkeyv2.
Diffstat (limited to 'sys/netinet/ip_ah_new.c')
-rw-r--r-- | sys/netinet/ip_ah_new.c | 455 |
1 files changed, 177 insertions, 278 deletions
diff --git a/sys/netinet/ip_ah_new.c b/sys/netinet/ip_ah_new.c index a6061bfc4d7..ad6cfc3463e 100644 --- a/sys/netinet/ip_ah_new.c +++ b/sys/netinet/ip_ah_new.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah_new.c,v 1.21 1999/01/11 22:52:09 deraadt Exp $ */ +/* $OpenBSD: ip_ah_new.c,v 1.22 1999/02/24 22:32:59 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -65,10 +65,9 @@ #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> -#include <net/encap.h> - #include <netinet/ip_ipsp.h> #include <netinet/ip_ah.h> +#include <net/pfkeyv2.h> #ifdef ENCDEBUG #define DPRINTF(x) if (encdebug) printf x @@ -76,25 +75,23 @@ #define DPRINTF(x) #endif -extern void encap_sendnotify(int, struct tdb *, void *); - -struct ah_hash ah_new_hash[] = { - { ALG_AUTH_MD5, "HMAC-MD5-96", - AH_MD5_ALEN, +struct auth_hash ah_new_hash[] = { + { SADB_AALG_MD5HMAC96, "HMAC-MD5-96", + MD5HMAC96_KEYSIZE, AH_MD5_ALEN, sizeof(MD5_CTX), (void (*)(void *)) MD5Init, (void (*)(void *, u_int8_t *, u_int16_t)) MD5Update, (void (*)(u_int8_t *, void *)) MD5Final }, - { ALG_AUTH_SHA1, "HMAC-SHA1-96", - AH_SHA1_ALEN, + { SADB_AALG_SHA1HMAC96, "HMAC-SHA1-96", + SHA1HMAC96_KEYSIZE, AH_SHA1_ALEN, sizeof(SHA1_CTX), (void (*)(void *)) SHA1Init, (void (*)(void *, u_int8_t *, u_int16_t)) SHA1Update, (void (*)(u_int8_t *, void *)) SHA1Final }, - { ALG_AUTH_RMD160, "HMAC-RIPEMD-160-96", - AH_RMD160_ALEN, + { SADB_AALG_X_RIPEMD160HMAC96, "HMAC-RIPEMD-160-96", + RIPEMD160HMAC96_KEYSIZE, AH_RMD160_ALEN, sizeof(RMD160_CTX), (void (*)(void *)) RMD160Init, (void (*)(void *, u_int8_t *, u_int16_t)) RMD160Update, @@ -110,127 +107,66 @@ struct ah_hash ah_new_hash[] = { int ah_new_attach() { - DPRINTF(("ah_new_attach(): setting up\n")); return 0; } /* - * ah_new_init() is called when an SPI is being set up. It interprets the - * encap_msghdr present in m, and sets up the transformation data. + * ah_new_init() is called when an SPI is being set up. */ int -ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) +ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) { - struct ah_new_xdata *xd; - struct ah_new_xencap txd; - struct encap_msghdr *em; - struct ah_hash *thash; - caddr_t buffer = NULL; - int blocklen, i; - - if (m->m_len < ENCAP_MSG_FIXED_LEN) - { - if ((m = m_pullup(m, ENCAP_MSG_FIXED_LEN)) == NULL) - { - DPRINTF(("ah_new_init(): m_pullup failed\n")); - return ENOBUFS; - } - } + struct auth_hash *thash = NULL; + int i; - em = mtod(m, struct encap_msghdr *); - if (em->em_msglen - EMT_SETSPI_FLEN <= AH_NEW_XENCAP_LEN) - { - DPRINTF(("ah_new_init() initialization failed\n")); - return EINVAL; - } - - /* Just copy the standard fields */ - m_copydata(m, EMT_SETSPI_FLEN, AH_NEW_XENCAP_LEN, (caddr_t) &txd); + for (i = sizeof(ah_new_hash) / sizeof(struct auth_hash) - 1; + i >= 0; i--) + if (ii->ii_authalg == ah_new_hash[i].type) + break; - /* Check whether the hash algorithm is supported */ - for (i = sizeof(ah_new_hash) / sizeof(struct ah_hash) - 1; i >= 0; i--) - if (txd.amx_hash_algorithm == ah_new_hash[i].type) - break; if (i < 0) { - DPRINTF(("ah_new_init(): unsupported authentication algorithm %d specified\n", txd.amx_hash_algorithm)); + DPRINTF(("ah_new_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg)); return EINVAL; } - DPRINTF(("ah_new_init(): initalized TDB with hash algorithm %d: %s\n", - txd.amx_hash_algorithm, ah_new_hash[i].name)); + thash = &ah_new_hash[i]; - blocklen = HMAC_BLOCK_LEN; - if (txd.amx_keylen + EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN != em->em_msglen) + if (ii->ii_authkeylen != thash->keysize) { - DPRINTF(("ah_new_init(): message length (%d) doesn't match\n", - em->em_msglen)); + DPRINTF(("ah_new_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize)); return EINVAL; } - MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct ah_new_xdata), - M_XDATA, M_WAITOK); - if (tdbp->tdb_xdata == NULL) - { - DPRINTF(("ah_new_init(): MALLOC failed\n")); - return ENOBUFS; - } - - MALLOC(buffer, caddr_t, - (txd.amx_keylen < blocklen ? blocklen : txd.amx_keylen), - M_TEMP, M_WAITOK); - if (buffer == NULL) - { - DPRINTF(("ah_new_init(): MALLOC failed\n")); - free(tdbp->tdb_xdata, M_XDATA); - return ENOBUFS; - } - - bzero(buffer, (txd.amx_keylen < blocklen ? blocklen : txd.amx_keylen)); - bzero(tdbp->tdb_xdata, sizeof(struct ah_new_xdata)); - xd = (struct ah_new_xdata *) tdbp->tdb_xdata; - - /* Copy the key to the buffer */ - m_copydata(m, EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN, txd.amx_keylen, buffer); - - xd->amx_hash = thash; - /* Shorten the key if necessary */ - if (txd.amx_keylen > blocklen) - { - xd->amx_hash->Init(&(xd->amx_ictx)); - xd->amx_hash->Update(&(xd->amx_ictx), buffer, txd.amx_keylen); - bzero(buffer, - (txd.amx_keylen < blocklen ? blocklen : txd.amx_keylen)); - xd->amx_hash->Final(buffer, &(xd->amx_ictx)); - } - - /* Pointer to the transform */ tdbp->tdb_xform = xsp; + tdbp->tdb_authalgxform = thash; + tdbp->tdb_bitmap = 0; + tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL; - /* Pass name of auth algorithm for kernfs */ - tdbp->tdb_authname = xd->amx_hash->name; - - xd->amx_hash_algorithm = txd.amx_hash_algorithm; - xd->amx_rpl = AH_HMAC_INITIAL_RPL; - xd->amx_wnd = txd.amx_wnd; - xd->amx_bitmap = 0; + DPRINTF(("ah_new_init(): initialized TDB with hash algorithm %s\n", + thash->name)); /* Precompute the I and O pads of the HMAC */ - for (i = 0; i < blocklen; i++) - buffer[i] ^= HMAC_IPAD_VAL; - - xd->amx_hash->Init(&(xd->amx_ictx)); - xd->amx_hash->Update(&(xd->amx_ictx), buffer, blocklen); - - for (i = 0; i < blocklen; i++) - buffer[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); - - xd->amx_hash->Init(&(xd->amx_octx)); - xd->amx_hash->Update(&(xd->amx_octx), buffer, blocklen); - - bzero(buffer, blocklen); /* paranoid */ - free(buffer, M_TEMP); + for (i = 0; i < ii->ii_authkeylen; i++) + ii->ii_authkey[i] ^= HMAC_IPAD_VAL; + + MALLOC(tdbp->tdb_ictx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK); + bzero(tdbp->tdb_ictx, thash->ctxsize); + thash->Init(tdbp->tdb_ictx); + thash->Update(tdbp->tdb_ictx, ii->ii_authkey, ii->ii_authkeylen); + thash->Update(tdbp->tdb_ictx, hmac_ipad_buffer, + HMAC_BLOCK_LEN - ii->ii_authkeylen); + + for (i = 0; i < ii->ii_authkeylen; i++) + ii->ii_authkey[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); + + MALLOC(tdbp->tdb_octx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK); + bzero(tdbp->tdb_octx, thash->ctxsize); + thash->Init(tdbp->tdb_octx); + thash->Update(tdbp->tdb_octx, ii->ii_authkey, ii->ii_authkeylen); + thash->Update(tdbp->tdb_octx, hmac_opad_buffer, + HMAC_BLOCK_LEN - ii->ii_authkeylen); bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */ @@ -241,12 +177,18 @@ ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) int ah_new_zeroize(struct tdb *tdbp) { - DPRINTF(("ah_new_zeroize(): freeing memory\n")); - if (tdbp->tdb_xdata) + if (tdbp->tdb_ictx) { - FREE(tdbp->tdb_xdata, M_XDATA); - tdbp->tdb_xdata = NULL; + FREE(tdbp->tdb_ictx, M_XDATA); + tdbp->tdb_ictx = NULL; } + + if (tdbp->tdb_octx) + { + FREE(tdbp->tdb_octx, M_XDATA); + tdbp->tdb_octx = NULL; + } + return 0; } @@ -258,7 +200,7 @@ ah_new_zeroize(struct tdb *tdbp) struct mbuf * ah_new_input(struct mbuf *m, struct tdb *tdb) { - struct ah_new_xdata *xd; + struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform; struct ip *ip, ipo; struct ah_new *aho, *ah; int ohlen, len, count, off, errc; @@ -273,9 +215,6 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) u_char buffer[40]; aho = (struct ah_new *) buffer; - - xd = (struct ah_new_xdata *) tdb->tdb_xdata; - ohlen = sizeof(struct ip) + AH_NEW_FLENGTH; if (m->m_len < ohlen) @@ -310,29 +249,57 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) if (ah->ah_hl * sizeof(u_int32_t) != AH_HMAC_HASHLEN + AH_HMAC_RPLENGTH) { - DPRINTF(("ah_new_input(): bad authenticator length for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_new_input(): bad authenticator length for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi))); ahstat.ahs_badauthl++; m_freem(m); return NULL; } + /* Update the counters */ + tdb->tdb_cur_bytes += ip->ip_len - (ip->ip_hl << 2) - + ah->ah_hl * sizeof(u_int32_t); + ahstat.ahs_ibytes += ip->ip_len - (ip->ip_hl << 2) - + ah->ah_hl * sizeof(u_int32_t); + + /* 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 */ + } + /* Replay window checking */ - if (xd->amx_wnd >= 0) + if (tdb->tdb_wnd > 0) { btsx = ntohl(ah->ah_rpl); - if ((errc = checkreplaywindow32(btsx, 0, &(xd->amx_rpl), xd->amx_wnd, - &(xd->amx_bitmap))) != 0) + if ((errc = checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl), tdb->tdb_wnd, + &(tdb->tdb_bitmap))) != 0) { switch(errc) { case 1: - DPRINTF(("ah_new_input(): replay counter wrapped for packets from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_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(ah->ah_spi))); ahstat.ahs_wrap++; break; case 2: case 3: - DPRINTF(("ah_new_input(): duplicate packet received, %x->%x spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_new_input(): duplicate packet received from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi))); ahstat.ahs_replay++; break; } @@ -351,8 +318,8 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) ipo.ip_ttl = 0; ipo.ip_sum = 0; - bcopy(&(xd->amx_ictx), &ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip)); + 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)) @@ -362,13 +329,13 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) switch (optval) { case IPOPT_EOL: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off = ip->ip_hl << 2; break; case IPOPT_NOP: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off++; break; @@ -378,7 +345,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) case 134: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval); + ahx->Update(&ctx, (u_int8_t *) ip + off, optval); off += optval; break; @@ -386,16 +353,15 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) default: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, ipseczeroes, optval); + ahx->Update(&ctx, ipseczeroes, optval); off += optval; break; } } - xd->amx_hash->Update(&ctx, (unsigned char *) ah, AH_NEW_FLENGTH - - AH_HMAC_HASHLEN); - xd->amx_hash->Update(&ctx, ipseczeroes, AH_HMAC_HASHLEN); + ahx->Update(&ctx, (unsigned char *) ah, AH_NEW_FLENGTH - AH_HMAC_HASHLEN); + ahx->Update(&ctx, ipseczeroes, AH_HMAC_HASHLEN); /* * Code shamelessly stolen from m_copydata @@ -408,7 +374,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) { if (m0 == 0) { - DPRINTF(("ah_new_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_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(ah->ah_spi))); ahstat.ahs_hdrops++; m_freem(m); return NULL; @@ -425,7 +391,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) { if (m0 == 0) { - DPRINTF(("ah_new_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_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(ah->ah_spi))); ahstat.ahs_hdrops++; m_freem(m); return NULL; @@ -433,36 +399,21 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) count = min(m0->m_len - off, len); - xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count); + ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count); len -= count; off = 0; m0 = m0->m_next; } - xd->amx_hash->Final((unsigned char *) (aho->ah_data), &ctx); - bcopy(&(xd->amx_octx), &ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, (unsigned char *) (aho->ah_data), - xd->amx_hash->hashsize); - xd->amx_hash->Final((unsigned char *) (aho->ah_data), &ctx); + ahx->Final((unsigned char *) (aho->ah_data), &ctx); + bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize); + ahx->Update(&ctx, (unsigned char *) (aho->ah_data), ahx->hashsize); + ahx->Final((unsigned char *) (aho->ah_data), &ctx); if (bcmp(aho->ah_data, ah->ah_data, AH_HMAC_HASHLEN)) { - DPRINTF(("ah_new_input(): authentication failed for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); -#ifdef ENCDEBUG - if (encdebug) - { - printf("Received authenticator: "); - for (off = 0; off < AH_HMAC_HASHLEN; off++) - printf("%02x ", ah->ah_data[off]); - printf("\n"); - - printf("Computed authenticator: "); - for (off = 0; off < AH_HMAC_HASHLEN; off++) - printf("%02x ", aho->ah_data[off]); - printf("\n"); - } -#endif + DPRINTF(("ah_new_input(): authentication failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi))); ahstat.ahs_badauth++; m_freem(m); return NULL; @@ -492,44 +443,6 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) ip->ip_sum = in_cksum(m, (ip->ip_hl << 2)); - /* Update the counters */ - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); - ahstat.ahs_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return m; } @@ -537,40 +450,37 @@ int ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct mbuf **mp) { - struct ah_new_xdata *xd; + struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform; struct ip *ip, ipo; struct ah_new aho, *ah; - register int len, off, count; - register struct mbuf *m0; + register int len, off, count, ilen; union { MD5_CTX md5ctx; SHA1_CTX sha1ctx; RMD160_CTX rmd160ctx; } ctx; - int ilen, ohlen; u_int8_t optval; - u_char buffer[AH_ALEN_MAX], opts[40]; + u_char opts[40]; ahstat.ahs_output++; m = m_pullup(m, sizeof(struct ip)); if (m == NULL) { - DPRINTF(("ah_new_output(): m_pullup() failed, SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_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 *); - xd = (struct ah_new_xdata *) tdb->tdb_xdata; - if ((ip->ip_hl << 2) > sizeof(struct ip)) { if ((m = m_pullup(m, ip->ip_hl << 2)) == NULL) { - DPRINTF(("ah_new_output(): m_pullup() failed, SA &x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_output(): m_pullup() failed, SA %s/%08x\n", + ipsp_address(tdb->tdb_dst), + ntohl(tdb->tdb_spi))); ahstat.ahs_hdrops++; return ENOBUFS; } @@ -578,18 +488,44 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ip = mtod(m, struct ip *); } + /* Update the counters */ + tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); + ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); + + /* 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 */ + } + /* Save options */ m_copydata(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip), (caddr_t) opts); - DPRINTF(("ah_new_output(): using hash algorithm %s\n", xd->amx_hash->name)); + DPRINTF(("ah_new_output(): using hash algorithm %s\n", ahx->name)); ilen = ntohs(ip->ip_len); - ohlen = AH_NEW_FLENGTH; - if (ohlen + ilen > IP_MAXPACKET) { - DPRINTF(("ah_new_output(): packet in SA %x/%0x8 got too big\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + if (AH_NEW_FLENGTH + ilen > IP_MAXPACKET) + { + DPRINTF(("ah_new_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; @@ -598,7 +534,7 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ipo.ip_v = IPVERSION; ipo.ip_hl = ip->ip_hl; ipo.ip_tos = 0; - ipo.ip_len = htons(ohlen + ilen); + ipo.ip_len = htons(AH_NEW_FLENGTH + ilen); ipo.ip_id = ip->ip_id; ipo.ip_off = 0; ipo.ip_ttl = 0; @@ -614,19 +550,19 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, aho.ah_rv = 0; aho.ah_spi = tdb->tdb_spi; - if (xd->amx_rpl == 0) + if (tdb->tdb_rpl == 0) { - DPRINTF(("ah_new_output(): SA %x/%0x8 should have expired\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_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; } - aho.ah_rpl = htonl(xd->amx_rpl++); + aho.ah_rpl = htonl(tdb->tdb_rpl++); - bcopy((caddr_t)&(xd->amx_ictx), (caddr_t)&ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip)); + bcopy(tdb->tdb_ictx, (caddr_t)&ctx, ahx->ctxsize); + ahx->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip)); /* Options */ if ((ip->ip_hl << 2) > sizeof(struct ip)) @@ -636,13 +572,13 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, switch (optval) { case IPOPT_EOL: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off = ip->ip_hl << 2; break; case IPOPT_NOP: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off++; break; @@ -652,7 +588,7 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, case 134: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval); + ahx->Update(&ctx, (u_int8_t *) ip + off, optval); off += optval; break; @@ -660,14 +596,14 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, default: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, ipseczeroes, optval); + ahx->Update(&ctx, ipseczeroes, optval); off += optval; break; } } - xd->amx_hash->Update(&ctx, (unsigned char *) &aho, AH_NEW_FLENGTH); + ahx->Update(&ctx, (unsigned char *) &aho, AH_NEW_FLENGTH); off = ip->ip_hl << 2; @@ -676,44 +612,46 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, */ len = m->m_pkthdr.len - off; - m0 = m; + *mp = m; while (len > 0) { - if (m0 == 0) + if ((*mp) == 0) { - DPRINTF(("ah_new_output(): bad mbuf chain for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_output(): bad mbuf chain 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++; m_freem(m); return EMSGSIZE; } - count = min(m0->m_len - off, len); + count = min((*mp)->m_len - off, len); - xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count); + ahx->Update(&ctx, mtod(*mp, unsigned char *) + off, count); len -= count; off = 0; - m0 = m0->m_next; + *mp = (*mp)->m_next; } + *mp = NULL; + 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); + M_PREPEND(m, AH_NEW_FLENGTH, M_DONTWAIT); if (m == NULL) { - DPRINTF(("ah_new_output(): M_PREPEND() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_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)); + m = m_pullup(m, AH_NEW_FLENGTH + (ipo.ip_hl << 2)); if (m == NULL) { - DPRINTF(("ah_new_output(): m_pullup() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_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; } @@ -727,58 +665,19 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ah->ah_spi = aho.ah_spi; ah->ah_rpl = aho.ah_rpl; - xd->amx_hash->Final(buffer, &ctx); - bcopy(&(xd->amx_octx), &ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, buffer, xd->amx_hash->hashsize); - xd->amx_hash->Final(buffer, &ctx); - /* Restore the options */ - m_copyback(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip), - (caddr_t) opts); + bcopy(opts, (caddr_t) (ip + 1), (ip->ip_hl << 2) - sizeof(struct ip)); + + /* Finish computing the authenticator */ + ahx->Final(opts, &ctx); + bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize); + ahx->Update(&ctx, opts, ahx->hashsize); + ahx->Final(opts, &ctx); /* Copy the authenticator */ - bcopy(buffer, ah->ah_data, AH_HMAC_HASHLEN); + bcopy(opts, ah->ah_data, AH_HMAC_HASHLEN); *mp = m; - /* Update the counters */ - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) - - AH_NEW_FLENGTH; - ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) - AH_NEW_FLENGTH; - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return 0; } |