summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>2001-06-26 06:19:00 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>2001-06-26 06:19:00 +0000
commit97dcba5b2f6f34385ffbae1a6c2d741e3f9589a3 (patch)
tree4a7f2fac474f6d614c2d280c2cd29b53ccc93ea0 /sys/netinet
parent523e298b4ae65ffcfc379531551a4f2d32ce0fd8 (diff)
KNF
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_ah.c1997
-rw-r--r--sys/netinet/ip_esp.c1879
2 files changed, 1933 insertions, 1943 deletions
diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c
index 7b7ae76c3d8..9dccd3e0373 100644
--- a/sys/netinet/ip_ah.c
+++ b/sys/netinet/ip_ah.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah.c,v 1.62 2001/06/25 05:11:58 angelos Exp $ */
+/* $OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -74,12 +74,12 @@
#endif
/*
- * ah_attach() is called from the transformation initialization code
+ * ah_attach() is called from the transformation initialization code.
*/
int
ah_attach()
{
- return 0;
+ return 0;
}
/*
@@ -88,64 +88,64 @@ ah_attach()
int
ah_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
- struct auth_hash *thash = NULL;
- struct cryptoini cria;
+ struct auth_hash *thash = NULL;
+ struct cryptoini cria;
- /* Authentication operation */
- switch (ii->ii_authalg)
- {
+ /* Authentication operation. */
+ switch (ii->ii_authalg) {
case SADB_AALG_MD5HMAC:
- thash = &auth_hash_hmac_md5_96;
- break;
+ thash = &auth_hash_hmac_md5_96;
+ break;
case SADB_AALG_SHA1HMAC:
- thash = &auth_hash_hmac_sha1_96;
- break;
+ thash = &auth_hash_hmac_sha1_96;
+ break;
case SADB_AALG_RIPEMD160HMAC:
- thash = &auth_hash_hmac_ripemd_160_96;
- break;
+ thash = &auth_hash_hmac_ripemd_160_96;
+ break;
case SADB_X_AALG_MD5:
- thash = &auth_hash_key_md5;
- break;
+ thash = &auth_hash_key_md5;
+ break;
case SADB_X_AALG_SHA1:
- thash = &auth_hash_key_sha1;
- break;
+ thash = &auth_hash_key_sha1;
+ break;
default:
- DPRINTF(("ah_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
- return EINVAL;
- }
+ DPRINTF(("ah_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
+ return EINVAL;
+ }
- if ((ii->ii_authkeylen != thash->keysize) && (thash->keysize != 0))
- {
- DPRINTF(("ah_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
- return EINVAL;
- }
+ if (ii->ii_authkeylen != thash->keysize && thash->keysize != 0) {
+ DPRINTF(("ah_init(): keylength %d doesn't match algorithm "
+ "%s keysize (%d)\n", ii->ii_authkeylen, thash->name,
+ thash->keysize));
+ return EINVAL;
+ }
- tdbp->tdb_xform = xsp;
- tdbp->tdb_authalgxform = thash;
- tdbp->tdb_bitmap = 0;
- tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
+ tdbp->tdb_xform = xsp;
+ tdbp->tdb_authalgxform = thash;
+ tdbp->tdb_bitmap = 0;
+ tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
- DPRINTF(("ah_init(): initialized TDB with hash algorithm %s\n",
- thash->name));
+ DPRINTF(("ah_init(): initialized TDB with hash algorithm %s\n",
+ thash->name));
- tdbp->tdb_amxkeylen = ii->ii_authkeylen;
- MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen, M_XDATA,
- M_WAITOK);
+ tdbp->tdb_amxkeylen = ii->ii_authkeylen;
+ MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen, M_XDATA,
+ M_WAITOK);
- bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+ bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
- /* Initialize crypto session */
- bzero(&cria, sizeof(cria));
- cria.cri_alg = tdbp->tdb_authalgxform->type;
- cria.cri_klen = ii->ii_authkeylen * 8;
- cria.cri_key = ii->ii_authkey;
+ /* Initialize crypto session. */
+ bzero(&cria, sizeof(cria));
+ cria.cri_alg = tdbp->tdb_authalgxform->type;
+ cria.cri_klen = ii->ii_authkeylen * 8;
+ cria.cri_key = ii->ii_authkey;
- return crypto_newsession(&tdbp->tdb_cryptoid, &cria, 0);
+ return crypto_newsession(&tdbp->tdb_cryptoid, &cria, 0);
}
/*
@@ -154,18 +154,17 @@ ah_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
int
ah_zeroize(struct tdb *tdbp)
{
- int err;
-
- if (tdbp->tdb_amxkey)
- {
- bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
- FREE(tdbp->tdb_amxkey, M_XDATA);
- tdbp->tdb_amxkey = NULL;
- }
-
- err = crypto_freesession(tdbp->tdb_cryptoid);
- tdbp->tdb_cryptoid = 0;
- return err;
+ int err;
+
+ if (tdbp->tdb_amxkey) {
+ bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+ FREE(tdbp->tdb_amxkey, M_XDATA);
+ tdbp->tdb_amxkey = NULL;
+ }
+
+ err = crypto_freesession(tdbp->tdb_cryptoid);
+ tdbp->tdb_cryptoid = 0;
+ return err;
}
/*
@@ -174,312 +173,313 @@ ah_zeroize(struct tdb *tdbp)
int
ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
{
- struct mbuf *m = *m0;
- unsigned char *ptr;
- int off, count;
+ struct mbuf *m = *m0;
+ unsigned char *ptr;
+ int off, count;
#ifdef INET
- struct ip *ip;
+ struct ip *ip;
#endif /* INET */
#ifdef INET6
- struct ip6_ext *ip6e;
- struct ip6_hdr ip6;
- int alloc, len, ad;
+ struct ip6_ext *ip6e;
+ struct ip6_hdr ip6;
+ int alloc, len, ad;
#endif /* INET6 */
- switch (proto)
- {
+ switch (proto) {
#ifdef INET
case AF_INET:
- /*
- * This is the least painful way of dealing with IPv4 header
- * and option processing -- just make sure they're in
- * contiguous memory.
- */
- *m0 = m = m_pullup(m, skip);
- if (m == NULL)
- {
- DPRINTF(("ah_massage_headers(): m_pullup() failed\n"));
- ahstat.ahs_hdrops++;
- return ENOBUFS;
- }
-
- /* Fix the IP header */
- ip = mtod(m, struct ip *);
- ip->ip_tos = 0;
- ip->ip_ttl = 0;
- ip->ip_sum = 0;
-
- /*
- * On input, fix ip_len which has been byte-swapped
- * at ip_input()
- */
- if (!out)
- {
- ip->ip_len += skip;
- HTONS(ip->ip_len);
-
- if ((alg == CRYPTO_MD5_KPDK) || (alg == CRYPTO_SHA1_KPDK))
- ip->ip_off = htons(ip->ip_off & IP_DF);
- else
- ip->ip_off = 0;
- }
- else
- {
- if ((alg == CRYPTO_MD5_KPDK) || (alg == CRYPTO_SHA1_KPDK))
- ip->ip_off = htons(ntohs(ip->ip_off) & IP_DF);
- else
- ip->ip_off = 0;
- }
-
- ptr = mtod(m, unsigned char *) + sizeof(struct ip);
-
- /* IPv4 option processing */
- for (off = sizeof(struct ip); off < skip;)
- {
- if (ptr[off] == IPOPT_EOL || ptr[off] == IPOPT_NOP ||
- off + 1 < skip)
- ;
- else
- {
- DPRINTF(("ah_massage_headers(): illegal IPv4 option length for option %d\n", ptr[off]));
- ahstat.ahs_hdrops++;
- m_freem(m);
- return EINVAL;
+ /*
+ * This is the least painful way of dealing with IPv4 header
+ * and option processing -- just make sure they're in
+ * contiguous memory.
+ */
+ *m0 = m = m_pullup(m, skip);
+ if (m == NULL) {
+ DPRINTF(("ah_massage_headers(): m_pullup() failed\n"));
+ ahstat.ahs_hdrops++;
+ return ENOBUFS;
}
- switch (ptr[off])
- {
- case IPOPT_EOL:
- off = skip; /* End the loop */
- break;
-
- case IPOPT_NOP:
- off++;
- break;
-
- case IPOPT_SECURITY: /* 0x82 */
- case 0x85: /* Extended security */
- case 0x86: /* Commercial security */
- case 0x94: /* Router alert */
- case 0x95: /* RFC1770 */
- /* Sanity check for option length */
- if (ptr[off + 1] < 2)
- {
- DPRINTF(("ah_massage_headers(): illegal IPv4 option length for option %d\n", ptr[off]));
- ahstat.ahs_hdrops++;
- m_freem(m);
- return EINVAL;
- }
-
- off += ptr[off + 1];
- break;
+ /* Fix the IP header */
+ ip = mtod(m, struct ip *);
+ ip->ip_tos = 0;
+ ip->ip_ttl = 0;
+ ip->ip_sum = 0;
+
+ /*
+ * On input, fix ip_len which has been byte-swapped
+ * at ip_input().
+ */
+ if (!out) {
+ ip->ip_len += skip;
+ HTONS(ip->ip_len);
+
+ if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK)
+ ip->ip_off = htons(ip->ip_off & IP_DF);
+ else
+ ip->ip_off = 0;
+ } else {
+ if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK)
+ ip->ip_off = htons(ntohs(ip->ip_off) & IP_DF);
+ else
+ ip->ip_off = 0;
+ }
- case IPOPT_LSRR:
- case IPOPT_SSRR:
- /* Sanity check for option length */
- if (ptr[off + 1] < 2)
- {
- DPRINTF(("ah_massage_headers(): illegal IPv4 option length for option %d\n", ptr[off]));
- ahstat.ahs_hdrops++;
- m_freem(m);
- return EINVAL;
+ ptr = mtod(m, unsigned char *) + sizeof(struct ip);
+
+ /* IPv4 option processing */
+ for (off = sizeof(struct ip); off < skip;) {
+ if (ptr[off] == IPOPT_EOL || ptr[off] == IPOPT_NOP ||
+ off + 1 < skip)
+ ;
+ else {
+ DPRINTF(("ah_massage_headers(): illegal IPv4 "
+ "option length for option %d\n",
+ ptr[off]));
+
+ ahstat.ahs_hdrops++;
+ m_freem(m);
+ return EINVAL;
}
- /*
- * On output, if we have either of the source routing
- * options, we should swap the destination address of
- * the IP header with the last address specified in
- * the option, as that is what the destination's
- * IP header will look like.
- */
- if (out)
- bcopy(ptr + off + ptr[off + 1] -
- sizeof(struct in_addr),
- &(ip->ip_dst), sizeof(struct in_addr));
-
- /* Fall through */
- default:
- /* Sanity check for option length */
- if (ptr[off + 1] < 2)
- {
- DPRINTF(("ah_massage_headers(): illegal IPv4 option length for option %d\n", ptr[off]));
- ahstat.ahs_hdrops++;
- m_freem(m);
- return EINVAL;
+ switch (ptr[off]) {
+ case IPOPT_EOL:
+ off = skip; /* End the loop. */
+ break;
+
+ case IPOPT_NOP:
+ off++;
+ break;
+
+ case IPOPT_SECURITY: /* 0x82 */
+ case 0x85: /* Extended security. */
+ case 0x86: /* Commercial security. */
+ case 0x94: /* Router alert */
+ case 0x95: /* RFC1770 */
+ /* Sanity check for option length. */
+ if (ptr[off + 1] < 2) {
+ DPRINTF(("ah_massage_headers(): "
+ "illegal IPv4 option length for "
+ "option %d\n", ptr[off]));
+
+ ahstat.ahs_hdrops++;
+ m_freem(m);
+ return EINVAL;
+ }
+
+ off += ptr[off + 1];
+ break;
+
+ case IPOPT_LSRR:
+ case IPOPT_SSRR:
+ /* Sanity check for option length. */
+ if (ptr[off + 1] < 2) {
+ DPRINTF(("ah_massage_headers(): "
+ "illegal IPv4 option length for "
+ "option %d\n", ptr[off]));
+
+ ahstat.ahs_hdrops++;
+ m_freem(m);
+ return EINVAL;
+ }
+
+ /*
+ * On output, if we have either of the
+ * source routing options, we should
+ * swap the destination address of the
+ * IP header with the last address
+ * specified in the option, as that is
+ * what the destination's IP header
+ * will look like.
+ */
+ if (out)
+ bcopy(ptr + off + ptr[off + 1] -
+ sizeof(struct in_addr),
+ &(ip->ip_dst), sizeof(struct in_addr));
+
+ /* Fall through */
+ default:
+ /* Sanity check for option length. */
+ if (ptr[off + 1] < 2) {
+ DPRINTF(("ah_massage_headers(): "
+ "illegal IPv4 option length for "
+ "option %d\n", ptr[off]));
+ ahstat.ahs_hdrops++;
+ m_freem(m);
+ return EINVAL;
+ }
+
+ /* Zeroize all other options. */
+ count = ptr[off + 1];
+ bcopy(ipseczeroes, ptr, count);
+ off += count;
+ break;
}
- /* Zeroize all other options */
- count = ptr[off + 1];
- bcopy(ipseczeroes, ptr, count);
- off += count;
- break;
- }
+ /* Sanity check. */
+ if (off > skip) {
+ DPRINTF(("ah_massage_headers(): malformed "
+ "IPv4 options header\n"));
- /* Sanity check */
- if (off > skip)
- {
- DPRINTF(("ah_massage_headers(): malformed IPv4 options header\n"));
- ahstat.ahs_hdrops++;
- m_freem(m);
- return EINVAL;
+ ahstat.ahs_hdrops++;
+ m_freem(m);
+ return EINVAL;
+ }
}
- }
- break;
+ break;
#endif /* INET */
#ifdef INET6
case AF_INET6: /* Ugly... */
- /* Copy and "cook" the IPv6 header */
- m_copydata(m, 0, sizeof(ip6), (caddr_t) &ip6);
+ /* Copy and "cook" the IPv6 header. */
+ m_copydata(m, 0, sizeof(ip6), (caddr_t) &ip6);
- /* We don't do IPv6 Jumbograms */
- if (ip6.ip6_plen == 0)
- {
- DPRINTF(("ah_massage_headers(): unsupported IPv6 jumbogram"));
- ahstat.ahs_hdrops++;
- m_freem(m);
- return EMSGSIZE;
- }
-
- ip6.ip6_flow = 0;
- ip6.ip6_hlim = 0;
- ip6.ip6_vfc &= ~IPV6_VERSION_MASK;
- ip6.ip6_vfc |= IPV6_VERSION;
-
- /* scoped address handling */
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_src))
- ip6.ip6_src.s6_addr16[1] = 0;
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_dst))
- ip6.ip6_dst.s6_addr16[1] = 0;
-
- /* Done with IPv6 header */
- m_copyback(m, 0, sizeof(struct ip6_hdr), (caddr_t) &ip6);
-
- /* Let's deal with the remaining headers (if any) */
- if (skip - sizeof(struct ip6_hdr) > 0)
- {
- if (m->m_len <= skip)
- {
- MALLOC(ptr, unsigned char *, skip - sizeof(struct ip6_hdr),
- M_XDATA, M_NOWAIT);
- if (ptr == NULL)
- {
- DPRINTF(("ah_massage_headers(): failed to allocate memory for IPv6 headers\n"));
+ /* We don't do IPv6 Jumbograms. */
+ if (ip6.ip6_plen == 0) {
+ DPRINTF(("ah_massage_headers(): unsupported IPv6 "
+ "jumbogram"));
ahstat.ahs_hdrops++;
m_freem(m);
- return ENOBUFS;
- }
-
- /* Copy all the protocol headers after the IPv6 header */
- m_copydata(m, sizeof(struct ip6_hdr),
- skip - sizeof(struct ip6_hdr), ptr);
- alloc = 1;
+ return EMSGSIZE;
}
- else
- {
- /* No need to allocate memory */
- ptr = mtod(m, unsigned char *) + sizeof(struct ip6_hdr);
- alloc = 0;
- }
- }
- else
- break;
-
- off = ip6.ip6_nxt & 0xff; /* Next header type */
-
- for (len = 0; len < skip - sizeof(struct ip6_hdr);)
- switch (off)
- {
- case IPPROTO_HOPOPTS:
- case IPPROTO_DSTOPTS:
- ip6e = (struct ip6_ext *) (ptr + len);
-
- /*
- * Process the mutable/immutable options -- borrows
- * heavily from the KAME code.
- */
- for (count = len + sizeof(struct ip6_ext);
- count < len + ((ip6e->ip6e_len + 1) << 3);)
- {
- if (ptr[count] == IP6OPT_PAD1)
- {
- count++;
- continue; /* Skip padding */
- }
-
- /* Sanity check */
- if (count > len + ((ip6e->ip6e_len + 1) << 3))
- {
- DPRINTF(("ah_massage_headers(): malformed IPv6 options header\n"));
- ahstat.ahs_hdrops++;
- m_freem(m);
-
- /* Free, if we allocated */
- if (alloc)
- FREE(ptr, M_XDATA);
-
- return EINVAL;
- }
-
- ad = ptr[count + 1];
-
- /* If mutable option, zeroize */
- if (ptr[count] & IP6OPT_MUTABLE)
- bcopy(ipseczeroes, ptr + count, ptr[count + 1]);
-
- count += ad;
-
- /* Sanity check */
- if (count > skip - sizeof(struct ip6_hdr))
- {
- DPRINTF(("ah_massage_headers(): malformed IPv6 options header\n"));
- ahstat.ahs_hdrops++;
- m_freem(m);
-
- /* Free, if we allocated */
- if (alloc)
- FREE(ptr, M_XDATA);
-
- return EINVAL;
- }
- }
-
- len += ((ip6e->ip6e_len + 1) << 3); /* Advance */
- off = ip6e->ip6e_nxt;
- break;
-
- case IPPROTO_ROUTING:
- /* Always include routing headers in computation */
- ip6e = (struct ip6_ext *) (ptr + len);
- len += ((ip6e->ip6e_len + 1) << 3); /* Advance */
- off = ip6e->ip6e_nxt;
- break;
-
- default:
- DPRINTF(("ah_massage_headers(): unexpected IPv6 header type %d\n", off));
- if (alloc)
+
+ ip6.ip6_flow = 0;
+ ip6.ip6_hlim = 0;
+ ip6.ip6_vfc &= ~IPV6_VERSION_MASK;
+ ip6.ip6_vfc |= IPV6_VERSION;
+
+ /* Scoped address handling. */
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_src))
+ ip6.ip6_src.s6_addr16[1] = 0;
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_dst))
+ ip6.ip6_dst.s6_addr16[1] = 0;
+
+ /* Done with IPv6 header. */
+ m_copyback(m, 0, sizeof(struct ip6_hdr), (caddr_t) &ip6);
+
+ /* Let's deal with the remaining headers (if any). */
+ if (skip - sizeof(struct ip6_hdr) > 0) {
+ if (m->m_len <= skip) {
+ MALLOC(ptr, unsigned char *,
+ skip - sizeof(struct ip6_hdr),
+ M_XDATA, M_NOWAIT);
+ if (ptr == NULL) {
+ DPRINTF(("ah_massage_headers(): failed to allocate memory for IPv6 headers\n"));
+ ahstat.ahs_hdrops++;
+ m_freem(m);
+ return ENOBUFS;
+ }
+
+ /*
+ * Copy all the protocol headers after
+ * the IPv6 header.
+ */
+ m_copydata(m, sizeof(struct ip6_hdr),
+ skip - sizeof(struct ip6_hdr), ptr);
+ alloc = 1;
+ } else {
+ /* No need to allocate memory. */
+ ptr = mtod(m, unsigned char *) +
+ sizeof(struct ip6_hdr);
+ alloc = 0;
+ }
+ } else
+ break;
+
+ off = ip6.ip6_nxt & 0xff; /* Next header type. */
+
+ for (len = 0; len < skip - sizeof(struct ip6_hdr);)
+ switch (off) {
+ case IPPROTO_HOPOPTS:
+ case IPPROTO_DSTOPTS:
+ ip6e = (struct ip6_ext *) (ptr + len);
+
+ /*
+ * Process the mutable/immutable
+ * options -- borrows heavily from the
+ * KAME code.
+ */
+ for (count = len + sizeof(struct ip6_ext);
+ count < len + ((ip6e->ip6e_len + 1) << 3);) {
+ if (ptr[count] == IP6OPT_PAD1) {
+ count++;
+ continue; /* Skip padding. */
+ }
+
+ /* Sanity check. */
+ if (count > len +
+ ((ip6e->ip6e_len + 1) << 3)) {
+ ahstat.ahs_hdrops++;
+ m_freem(m);
+
+ /* Free, if we allocated. */
+ if (alloc)
+ FREE(ptr, M_XDATA);
+ return EINVAL;
+ }
+
+ ad = ptr[count + 1];
+
+ /* If mutable option, zeroize. */
+ if (ptr[count] & IP6OPT_MUTABLE)
+ bcopy(ipseczeroes, ptr + count,
+ ptr[count + 1]);
+
+ count += ad;
+
+ /* Sanity check. */
+ if (count >
+ skip - sizeof(struct ip6_hdr)) {
+ ahstat.ahs_hdrops++;
+ m_freem(m);
+
+ /* Free, if we allocated. */
+ if (alloc)
+ FREE(ptr, M_XDATA);
+ return EINVAL;
+ }
+ }
+
+ /* Advance. */
+ len += ((ip6e->ip6e_len + 1) << 3);
+ off = ip6e->ip6e_nxt;
+ break;
+
+ case IPPROTO_ROUTING:
+ /*
+ * Always include routing headers in
+ * computation.
+ */
+ ip6e = (struct ip6_ext *) (ptr + len);
+ len += ((ip6e->ip6e_len + 1) << 3);
+ off = ip6e->ip6e_nxt;
+ break;
+
+ default:
+ DPRINTF(("ah_massage_headers(): unexpected "
+ "IPv6 header type %d\n", off));
+ if (alloc)
+ FREE(ptr, M_XDATA);
+ ahstat.ahs_hdrops++;
+ m_freem(m);
+ return EINVAL;
+ }
+
+ /* Copyback and free, if we allocated. */
+ if (alloc) {
+ m_copyback(m, sizeof(struct ip6_hdr),
+ skip - sizeof(struct ip6_hdr), ptr);
FREE(ptr, M_XDATA);
- ahstat.ahs_hdrops++;
- m_freem(m);
- return EINVAL;
- }
-
- /* Copyback and free, if we allocated */
- if (alloc)
- {
- m_copyback(m, sizeof(struct ip6_hdr),
- skip - sizeof(struct ip6_hdr), ptr);
- FREE(ptr, M_XDATA);
- }
-
- break;
+ }
+
+ break;
#endif /* INET6 */
- }
+ }
- return 0;
+ return 0;
}
/*
@@ -489,184 +489,193 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
int
ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
{
- struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
- struct tdb_ident *tdbi;
- struct tdb_crypto *tc;
- struct m_tag *mtag;
- u_int32_t btsx;
- u_int8_t hl;
- int rplen;
-
- struct cryptodesc *crda = NULL;
- struct cryptop *crp;
-
- if (!(tdb->tdb_flags & TDBF_NOREPLAY))
- rplen = AH_FLENGTH + sizeof(u_int32_t);
- else
- rplen = AH_FLENGTH;
-
- /* Save the AH header, we use it throughout */
- m_copydata(m, skip + offsetof(struct ah, ah_hl), sizeof(u_int8_t),
- (caddr_t) &hl);
-
- /* Replay window checking, if applicable */
- if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY)))
- {
- m_copydata(m, skip + offsetof(struct ah, ah_rpl), sizeof(u_int32_t),
- (caddr_t) &btsx);
- btsx = ntohl(btsx);
-
- switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl),
- tdb->tdb_wnd, &(tdb->tdb_bitmap)))
- {
- case 0: /* All's well */
- break;
+ struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
+ struct tdb_ident *tdbi;
+ struct tdb_crypto *tc;
+ struct m_tag *mtag;
+ u_int32_t btsx;
+ u_int8_t hl;
+ int rplen;
+
+ struct cryptodesc *crda = NULL;
+ struct cryptop *crp;
+
+ if (!(tdb->tdb_flags & TDBF_NOREPLAY))
+ rplen = AH_FLENGTH + sizeof(u_int32_t);
+ else
+ rplen = AH_FLENGTH;
+
+ /* Save the AH header, we use it throughout. */
+ m_copydata(m, skip + offsetof(struct ah, ah_hl), sizeof(u_int8_t),
+ (caddr_t) &hl);
+
+ /* Replay window checking, if applicable. */
+ if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY))) {
+ m_copydata(m, skip + offsetof(struct ah, ah_rpl),
+ sizeof(u_int32_t), (caddr_t) &btsx);
+ btsx = ntohl(btsx);
+
+ switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl),
+ tdb->tdb_wnd, &(tdb->tdb_bitmap))) {
+ case 0: /* All's well. */
+ break;
- case 1:
- DPRINTF(("ah_input(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- ahstat.ahs_wrap++;
+ case 1:
+ DPRINTF(("ah_input(): replay counter wrapped for "
+ "SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
+ ntohl(tdb->tdb_spi)));
+
+ ahstat.ahs_wrap++;
+ m_freem(m);
+ return ENOBUFS;
+
+ case 2:
+ case 3:
+ DPRINTF(("ah_input(): duplicate packet received in "
+ "SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
+ ntohl(tdb->tdb_spi)));
+
+ ahstat.ahs_replay++;
+ m_freem(m);
+ return ENOBUFS;
+
+ default:
+ DPRINTF(("ah_input(): bogus value from "
+ "checkreplaywindow32() in SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+
+ ahstat.ahs_replay++;
+ m_freem(m);
+ return ENOBUFS;
+ }
+ }
+
+ /* Verify AH header length. */
+ if (hl * sizeof(u_int32_t) != ahx->authsize + rplen - AH_FLENGTH) {
+ DPRINTF(("ah_input(): bad authenticator length %d for packet "
+ "in SA %s/%08x\n", hl * sizeof(u_int32_t),
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+
+ ahstat.ahs_badauthl++;
m_freem(m);
- return ENOBUFS;
+ return EACCES;
+ }
+
+ /* Update the counters. */
+ tdb->tdb_cur_bytes +=
+ (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
+ ahstat.ahs_ibytes += (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
- case 2:
- case 3:
- DPRINTF(("ah_input(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- ahstat.ahs_replay++;
+ /* 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);
m_freem(m);
- return ENOBUFS;
+ return ENXIO;
+ }
- default:
- DPRINTF(("ah_input(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- ahstat.ahs_replay++;
- m_freem(m);
- return ENOBUFS;
+ /* 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. */
}
- }
-
- /* Verify AH header length */
- if (hl * sizeof(u_int32_t) != ahx->authsize + rplen - AH_FLENGTH)
- {
- DPRINTF(("ah_input(): bad authenticator length %d for packet in SA %s/%08x\n", hl * sizeof(u_int32_t), ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- ahstat.ahs_badauthl++;
- m_freem(m);
- return EACCES;
- }
-
- /* Update the counters */
- tdb->tdb_cur_bytes += (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
- ahstat.ahs_ibytes += (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
-
- /* 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);
- m_freem(m);
- return ENXIO;
- }
-
- /* 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 */
- }
-
- /* Get crypto descriptors */
- crp = crypto_getreq(1);
- if (crp == NULL)
- {
- m_freem(m);
- DPRINTF(("ah_input(): failed to acquire crypto descriptors\n"));
- ahstat.ahs_crypto++;
- return ENOBUFS;
- }
-
- crda = crp->crp_desc;
-
- crda->crd_skip = 0;
- crda->crd_len = m->m_pkthdr.len;
- crda->crd_inject = skip + rplen;
-
- /* Authentication operation */
- crda->crd_alg = ahx->type;
- crda->crd_key = tdb->tdb_amxkey;
- crda->crd_klen = tdb->tdb_amxkeylen * 8;
-
- /* Find out if we've already done crypto */
- for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
- mtag != NULL;
- mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag))
- {
- tdbi = (struct tdb_ident *) (mtag + 1);
- if (tdbi->proto == tdb->tdb_sproto && tdbi->spi == tdb->tdb_spi &&
- !bcmp(&tdbi->dst, &tdb->tdb_dst, sizeof(union sockaddr_union)))
- break;
- }
-
- /* Allocate IPsec-specific opaque crypto info */
- if (mtag == NULL)
- MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto) + skip +
- rplen + ahx->authsize, M_XDATA, M_NOWAIT);
- else /* Hash verification has already been done successfully */
- MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto), M_XDATA,
- M_NOWAIT);
- if (tc == NULL)
- {
- m_freem(m);
- crypto_freereq(crp);
- DPRINTF(("ah_input(): failed to allocate tdb_crypto\n"));
- ahstat.ahs_crypto++;
- return ENOBUFS;
- }
- bzero(tc, sizeof(struct tdb_crypto));
+ /* Get crypto descriptors. */
+ crp = crypto_getreq(1);
+ if (crp == NULL) {
+ m_freem(m);
+ DPRINTF(("ah_input(): failed to acquire crypto "
+ "descriptors\n"));
+ ahstat.ahs_crypto++;
+ return ENOBUFS;
+ }
- /* Only save information if crypto processing is needed */
- if (mtag == NULL)
- {
- /*
- * Save the authenticator, the skipped portion of the packet,
- * and the AH header.
- */
- m_copydata(m, 0, skip + rplen + ahx->authsize, (caddr_t) (tc + 1));
+ crda = crp->crp_desc;
+
+ crda->crd_skip = 0;
+ crda->crd_len = m->m_pkthdr.len;
+ crda->crd_inject = skip + rplen;
+
+ /* Authentication operation. */
+ crda->crd_alg = ahx->type;
+ crda->crd_key = tdb->tdb_amxkey;
+ crda->crd_klen = tdb->tdb_amxkeylen * 8;
+
+ /* Find out if we've already done crypto. */
+ for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
+ mtag != NULL;
+ mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) {
+ tdbi = (struct tdb_ident *) (mtag + 1);
+ if (tdbi->proto == tdb->tdb_sproto &&
+ tdbi->spi == tdb->tdb_spi &&
+ !bcmp(&tdbi->dst, &tdb->tdb_dst,
+ sizeof(union sockaddr_union)))
+ break;
+ }
- /* Zeroize the authenticator on the packet */
- m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes);
+ /* Allocate IPsec-specific opaque crypto info. */
+ if (mtag == NULL)
+ MALLOC(tc, struct tdb_crypto *,
+ sizeof(struct tdb_crypto) + skip +
+ rplen + ahx->authsize, M_XDATA, M_NOWAIT);
+ else /* Hash verification has already been done successfully. */
+ MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
+ M_XDATA, M_NOWAIT);
+ if (tc == NULL) {
+ m_freem(m);
+ crypto_freereq(crp);
+ DPRINTF(("ah_input(): failed to allocate tdb_crypto\n"));
+ ahstat.ahs_crypto++;
+ return ENOBUFS;
+ }
- /* "Massage" the packet headers for crypto processing */
- if ((btsx = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family,
- skip, ahx->type, 0)) != 0)
- {
- /* mbuf will be free'd by callee */
- FREE(tc, M_XDATA);
- crypto_freereq(crp);
- return btsx;
+ bzero(tc, sizeof(struct tdb_crypto));
+
+ /* Only save information if crypto processing is needed. */
+ if (mtag == NULL) {
+ /*
+ * Save the authenticator, the skipped portion of the packet,
+ * and the AH header.
+ */
+ m_copydata(m, 0, skip + rplen + ahx->authsize,
+ (caddr_t) (tc + 1));
+
+ /* Zeroize the authenticator on the packet. */
+ m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes);
+
+ /* "Massage" the packet headers for crypto processing. */
+ if ((btsx = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family,
+ skip, ahx->type, 0)) != 0) {
+ /* mbuf will be free'd by callee. */
+ FREE(tc, M_XDATA);
+ crypto_freereq(crp);
+ return btsx;
+ }
}
- }
-
- /* 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_input_cb;
- crp->crp_sid = tdb->tdb_cryptoid;
- crp->crp_opaque = (caddr_t) tc;
-
- /* These are passed as-is to the callback */
- tc->tc_skip = skip;
- tc->tc_protoff = protoff;
- tc->tc_spi = tdb->tdb_spi;
- tc->tc_proto = tdb->tdb_sproto;
- tc->tc_ptr = (caddr_t) mtag; /* Save the mtag we've identified */
- bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
-
- if (mtag == NULL)
- return crypto_dispatch(crp);
- else
- return ah_input_cb(crp);
+
+ /* 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_input_cb;
+ crp->crp_sid = tdb->tdb_cryptoid;
+ crp->crp_opaque = (caddr_t) tc;
+
+ /* These are passed as-is to the callback. */
+ tc->tc_skip = skip;
+ tc->tc_protoff = protoff;
+ tc->tc_spi = tdb->tdb_spi;
+ tc->tc_proto = tdb->tdb_sproto;
+ tc->tc_ptr = (caddr_t) mtag; /* Save the mtag we've identified. */
+ bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
+
+ if (mtag == NULL)
+ return crypto_dispatch(crp);
+ else
+ return ah_input_cb(crp);
}
/*
@@ -675,188 +684,191 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
int
ah_input_cb(void *op)
{
- int roff, rplen, error, skip, protoff;
- unsigned char calc[AH_ALEN_MAX];
- struct mbuf *m1, *m0, *m;
- struct cryptodesc *crd;
- struct auth_hash *ahx;
- struct tdb_crypto *tc;
- struct cryptop *crp;
- struct m_tag *mtag;
- struct tdb *tdb;
- u_int8_t prot;
- caddr_t ptr;
- int s, err;
-
- 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)
- {
- ahstat.ahs_notdb++;
- DPRINTF(("ah_input_cb(): TDB is expired while in crypto"));
- goto baddone;
- }
-
- ahx = (struct auth_hash *) tdb->tdb_authalgxform;
-
- /* Check for crypto errors */
- if (crp->crp_etype)
- {
- if (tdb->tdb_cryptoid != 0)
- tdb->tdb_cryptoid = crp->crp_sid;
-
- if (crp->crp_etype == EAGAIN)
- {
- splx(s);
- return crypto_dispatch(crp);
- }
-
- ahstat.ahs_noxform++;
- DPRINTF(("ah_input_cb(): crypto error %d\n", crp->crp_etype));
- error = crp->crp_etype;
- goto baddone;
- }
- else
- {
- crypto_freereq(crp); /* No longer needed */
- crp = NULL;
- }
-
- /* Shouldn't happen... */
- if (m == NULL)
- {
- ahstat.ahs_crypto++;
- DPRINTF(("ah_input_cb(): bogus returned buffer from crypto\n"));
- error = EINVAL;
- goto baddone;
- }
-
- if (!(tdb->tdb_flags & TDBF_NOREPLAY))
- rplen = AH_FLENGTH + sizeof(u_int32_t);
- else
- rplen = AH_FLENGTH;
-
- /* Copy authenticator off the packet. */
- m_copydata(m, skip + rplen, ahx->authsize, calc);
-
- /*
- * If we have an mtag, we don't need to verify the authenticator --
- * it has been verified by an IPsec-aware NIC.
- */
- if (mtag == NULL)
- {
- ptr = (caddr_t) (tc + 1);
+ int roff, rplen, error, skip, protoff;
+ unsigned char calc[AH_ALEN_MAX];
+ struct mbuf *m1, *m0, *m;
+ struct cryptodesc *crd;
+ struct auth_hash *ahx;
+ struct tdb_crypto *tc;
+ struct cryptop *crp;
+ struct m_tag *mtag;
+ struct tdb *tdb;
+ u_int8_t prot;
+ caddr_t ptr;
+ int s, err;
+
+ 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) {
+ ahstat.ahs_notdb++;
+ DPRINTF(("ah_input_cb(): TDB is expired while in crypto"));
+ goto baddone;
+ }
- /* Verify authenticator */
- if (bcmp(ptr + skip + rplen, calc, ahx->authsize))
- {
- DPRINTF(("ah_input(): authentication failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- ahstat.ahs_badauth++;
- error = EACCES;
- goto baddone;
+ ahx = (struct auth_hash *) tdb->tdb_authalgxform;
+
+ /* Check for crypto errors. */
+ if (crp->crp_etype) {
+ if (tdb->tdb_cryptoid != 0)
+ tdb->tdb_cryptoid = crp->crp_sid;
+
+ if (crp->crp_etype == EAGAIN) {
+ splx(s);
+ return crypto_dispatch(crp);
+ }
+
+ ahstat.ahs_noxform++;
+ DPRINTF(("ah_input_cb(): crypto error %d\n", crp->crp_etype));
+ error = crp->crp_etype;
+ goto baddone;
+ } else {
+ crypto_freereq(crp); /* No longer needed. */
+ crp = NULL;
+ }
+
+ /* Shouldn't happen... */
+ if (m == NULL) {
+ ahstat.ahs_crypto++;
+ DPRINTF(("ah_input_cb(): bogus returned buffer from "
+ "crypto\n"));
+ error = EINVAL;
+ goto baddone;
+ }
+
+ if (!(tdb->tdb_flags & TDBF_NOREPLAY))
+ rplen = AH_FLENGTH + sizeof(u_int32_t);
+ else
+ rplen = AH_FLENGTH;
+
+ /* Copy authenticator off the packet. */
+ m_copydata(m, skip + rplen, ahx->authsize, calc);
+
+ /*
+ * If we have an mtag, we don't need to verify the authenticator --
+ * it has been verified by an IPsec-aware NIC.
+ */
+ if (mtag == NULL) {
+ ptr = (caddr_t) (tc + 1);
+
+ /* Verify authenticator. */
+ if (bcmp(ptr + skip + rplen, calc, ahx->authsize)) {
+ DPRINTF(("ah_input(): authentication failed for "
+ "packet in SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+
+ ahstat.ahs_badauth++;
+ error = EACCES;
+ goto baddone;
+ }
+
+ /* Fix the Next Protocol field. */
+ ((u_int8_t *) ptr)[protoff] = ((u_int8_t *) ptr)[skip];
+
+ /* Copyback the saved (uncooked) network headers. */
+ m_copyback(m, 0, skip, ptr);
+ } else {
+ /* Fix the Next Protocol field. */
+ m_copydata(m, skip, sizeof(u_int8_t), &prot);
+ m_copyback(m, protoff, sizeof(u_int8_t), &prot);
+ }
+
+ /* Record the beginning of the AH header. */
+ m1 = m_getptr(m, skip, &roff);
+ if (m1 == NULL) {
+ ahstat.ahs_hdrops++;
+ splx(s);
+ m_freem(m);
+
+ DPRINTF(("ah_input(): bad mbuf chain for packet in SA "
+ "%s/%08x\n", ipsp_address(tdb->tdb_dst),
+ ntohl(tdb->tdb_spi)));
+
+ return EINVAL;
}
- /* Fix the Next Protocol field */
- ((u_int8_t *) ptr)[protoff] = ((u_int8_t *) ptr)[skip];
-
- /* Copyback the saved (uncooked) network headers */
- m_copyback(m, 0, skip, ptr);
- }
- else
- {
- /* Fix the Next Protocol field */
- m_copydata(m, skip, sizeof(u_int8_t), &prot);
- m_copyback(m, protoff, sizeof(u_int8_t), &prot);
- }
-
- /* Record the beginning of the AH header */
- m1 = m_getptr(m, skip, &roff);
- if (m1 == NULL)
- {
- ahstat.ahs_hdrops++;
- splx(s);
- DPRINTF(("ah_input(): bad mbuf chain for packet in SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- return EINVAL;
- }
-
- /* Remove the AH header from the mbuf */
- if (roff == 0)
- {
- /* The AH header was conveniently at the beginning of the mbuf */
- m_adj(m1, rplen + ahx->authsize);
- if (!(m1->m_flags & M_PKTHDR))
- m->m_pkthdr.len -= rplen + ahx->authsize;
- }
- else
- if (roff + rplen + ahx->authsize >= m1->m_len)
- {
- /*
- * Part or all of the AH header is at the end of this mbuf, so first
- * let's remove the remainder of the AH header from the
- * beginning of the remainder of the mbuf chain, if any.
- */
- if (roff + rplen + ahx->authsize > m1->m_len)
- {
- /* Adjust the next mbuf by the remainder */
- m_adj(m1->m_next, roff + rplen + ahx->authsize - m1->m_len);
-
- /* The second mbuf is guaranteed not to have a pkthdr... */
- m->m_pkthdr.len -= (roff + rplen + ahx->authsize - m1->m_len);
- }
-
- /* Now, let's unlink the mbuf chain for a second...*/
- m0 = 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 = m0;
- }
- else
- {
- /*
- * The AH 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 + rplen + ahx->authsize,
- mtod(m1, u_char *) + roff,
- m1->m_len - (roff + rplen + ahx->authsize));
- m1->m_len -= rplen + ahx->authsize;
- m->m_pkthdr.len -= rplen + ahx->authsize;
- }
-
- err = ipsec_common_input_cb(m, tdb, skip, protoff, mtag);
- splx(s);
- return err;
+ /* Remove the AH header from the mbuf. */
+ if (roff == 0) {
+ /*
+ * The AH header was conveniently at the beginning of
+ * the mbuf.
+ */
+ m_adj(m1, rplen + ahx->authsize);
+ if (!(m1->m_flags & M_PKTHDR))
+ m->m_pkthdr.len -= rplen + ahx->authsize;
+ } else
+ if (roff + rplen + ahx->authsize >= m1->m_len) {
+ /*
+ * Part or all of the AH header is at the end
+ * of this mbuf, so first let's remove the
+ * remainder of the AH header from the
+ * beginning of the remainder of the mbuf
+ * chain, if any.
+ */
+ if (roff + rplen + ahx->authsize > m1->m_len) {
+ /* Adjust the next mbuf by the remainder. */
+ m_adj(m1->m_next, roff + rplen +
+ ahx->authsize - m1->m_len);
+
+ /*
+ * The second mbuf is guaranteed not
+ * to have a pkthdr...
+ */
+ m->m_pkthdr.len -=
+ (roff + rplen + ahx->authsize - m1->m_len);
+ }
+
+ /* Now, let's unlink the mbuf chain for a second... */
+ m0 = 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 = m0;
+ } else {
+ /*
+ * The AH 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 + rplen +
+ ahx->authsize, mtod(m1, u_char *) + roff,
+ m1->m_len - (roff + rplen + ahx->authsize));
+ m1->m_len -= rplen + ahx->authsize;
+ m->m_pkthdr.len -= rplen + ahx->authsize;
+ }
+
+ err = ipsec_common_input_cb(m, tdb, skip, protoff, mtag);
+ splx(s);
+ return err;
baddone:
- splx(s);
+ splx(s);
- if (m != NULL)
- m_freem(m);
+ if (m != NULL)
+ m_freem(m);
- if (crp != NULL)
- crypto_freereq(crp);
+ if (crp != NULL)
+ crypto_freereq(crp);
- return error;
+ return error;
}
/*
@@ -864,294 +876,289 @@ ah_input_cb(void *op)
*/
int
ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
- int protoff)
+ int protoff)
{
- struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
- struct cryptodesc *crda;
- struct tdb_crypto *tc;
- struct mbuf *mo, *mi;
- struct cryptop *crp;
- u_int16_t iplen;
- int len, rplen;
- u_int8_t prot;
- struct ah *ah;
+ struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
+ struct cryptodesc *crda;
+ struct tdb_crypto *tc;
+ struct mbuf *mo, *mi;
+ struct cryptop *crp;
+ u_int16_t iplen;
+ int len, rplen;
+ u_int8_t prot;
+ struct ah *ah;
#if NBPFILTER > 0
- {
- struct ifnet *ifn;
- struct enchdr hdr;
- struct mbuf m1;
+ {
+ struct ifnet *ifn;
+ struct enchdr hdr;
+ struct mbuf m1;
- bzero (&hdr, sizeof(hdr));
+ bzero (&hdr, sizeof(hdr));
- hdr.af = tdb->tdb_dst.sa.sa_family;
- hdr.spi = tdb->tdb_spi;
- hdr.flags |= M_AUTH;
+ 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;
+ m1.m_next = m;
+ m1.m_len = ENC_HDRLEN;
+ m1.m_data = (char *) &hdr;
- ifn = &(encif[0].sc_if);
+ ifn = &(encif[0].sc_if);
- if (ifn->if_bpf)
- bpf_mtap(ifn->if_bpf, &m1);
- }
+ 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)
- {
+ 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;
+ /* 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;
+ /* 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);
- 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) || !MCLISREFERENCED(mi)))
- {
- 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;
-
- /* Allocate IPsec-specific opaque crypto info */
- if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
- MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto) + skip,
- M_XDATA, M_NOWAIT);
- else
- MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto), M_XDATA,
- M_NOWAIT);
- if (tc == NULL)
- {
- m_freem(m);
- crypto_freereq(crp);
- DPRINTF(("ah_output(): failed to allocate tdb_crypto\n"));
- ahstat.ahs_crypto++;
- return ENOBUFS;
- }
+ 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;
+ }
- bzero(tc, sizeof(struct tdb_crypto));
+ /* 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);
+ m_freem(m);
+ return EINVAL;
+ }
- /* Save the skipped portion of the packet */
- if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
- {
- m_copydata(m, 0, skip, (caddr_t) (tc + 1));
+ /* 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 */
+ }
/*
- * 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.
+ * Loop through mbuf chain; if we find an M_EXT mbuf with
+ * more than one reference, replace the rest of the chain.
*/
- switch (tdb->tdb_dst.sa.sa_family)
- {
+ mi = m;
+ while (mi != NULL &&
+ (!(mi->m_flags & M_EXT) || !MCLISREFERENCED(mi))) {
+ 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;
+
+ /* Allocate IPsec-specific opaque crypto info. */
+ if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
+ MALLOC(tc, struct tdb_crypto *,
+ sizeof(struct tdb_crypto) + skip, M_XDATA, M_NOWAIT);
+ else
+ MALLOC(tc, struct tdb_crypto *,
+ sizeof(struct tdb_crypto), M_XDATA, M_NOWAIT);
+ if (tc == NULL) {
+ m_freem(m);
+ crypto_freereq(crp);
+ DPRINTF(("ah_output(): failed to allocate tdb_crypto\n"));
+ ahstat.ahs_crypto++;
+ return ENOBUFS;
+ }
+
+ bzero(tc, sizeof(struct tdb_crypto));
+
+ /* Save the skipped portion of the packet. */
+ if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0) {
+ m_copydata(m, 0, skip, (caddr_t) (tc + 1));
+
+ /*
+ * 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(((caddr_t)(tc + 1)) + 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;
+ case AF_INET:
+ bcopy(((caddr_t)(tc + 1)) +
+ 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(((caddr_t)(tc + 1)) + 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;
+ case AF_INET6:
+ bcopy(((caddr_t)(tc + 1)) +
+ 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 */
- }
+ }
- /* Fix the Next Header field in saved header. */
- ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH;
+ /* Fix the Next Header field in saved header. */
+ ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH;
- /* Update the Next Protocol field in the IP header. */
- prot = IPPROTO_AH;
- m_copyback(m, protoff, sizeof(u_int8_t), (caddr_t) &prot);
+ /* Update the Next Protocol field in the IP header. */
+ prot = IPPROTO_AH;
+ m_copyback(m, protoff, sizeof(u_int8_t), (caddr_t) &prot);
- /* "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(tc, M_XDATA);
- crypto_freereq(crp);
- return len;
+ /* "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(tc, M_XDATA);
+ crypto_freereq(crp);
+ return len;
+ }
+ } else {
+ /* Update the Next Protocol field in the IP header. */
+ prot = IPPROTO_AH;
+ m_copyback(m, protoff, sizeof(u_int8_t), (caddr_t) &prot);
}
- }
- else
- {
- /* Update the Next Protocol field in the IP header. */
- prot = IPPROTO_AH;
- m_copyback(m, protoff, sizeof(u_int8_t), (caddr_t) &prot);
- }
-
- /* 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;
- crp->crp_opaque = (caddr_t) tc;
-
- /* These are passed as-is to the callback */
- tc->tc_skip = skip;
- tc->tc_protoff = protoff;
- tc->tc_spi = tdb->tdb_spi;
- tc->tc_proto = tdb->tdb_sproto;
- bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
-
- if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
- return crypto_dispatch(crp);
- else
- return ah_output_cb(crp);
+
+ /* 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;
+ crp->crp_opaque = (caddr_t) tc;
+
+ /* These are passed as-is to the callback. */
+ tc->tc_skip = skip;
+ tc->tc_protoff = protoff;
+ tc->tc_spi = tdb->tdb_spi;
+ tc->tc_proto = tdb->tdb_sproto;
+ bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
+
+ if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
+ return crypto_dispatch(crp);
+ else
+ return ah_output_cb(crp);
}
/*
@@ -1160,78 +1167,78 @@ ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
int
ah_output_cb(void *op)
{
- int skip, protoff, error;
- struct tdb_crypto *tc;
- struct cryptop *crp;
- struct tdb *tdb;
- struct mbuf *m;
- caddr_t ptr;
- int err, s;
-
- crp = (struct cryptop *) op;
- tc = (struct tdb_crypto *) crp->crp_opaque;
- skip = tc->tc_skip;
- protoff = tc->tc_protoff;
- ptr = (caddr_t) (tc + 1);
- 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)
- {
- ahstat.ahs_notdb++;
- DPRINTF(("ah_output_cb(): TDB is expired while in crypto\n"));
- goto baddone;
- }
-
- /* Check for crypto errors */
- if (crp->crp_etype)
- {
- if (tdb->tdb_cryptoid != 0)
- tdb->tdb_cryptoid = crp->crp_sid;
-
- if (crp->crp_etype == EAGAIN)
- {
- splx(s);
- return crypto_dispatch(crp);
- }
-
- ahstat.ahs_noxform++;
- DPRINTF(("ah_output_cb(): crypto error %d\n", crp->crp_etype));
- error = crp->crp_etype;
- goto baddone;
- }
-
- /* Shouldn't happen... */
- if (m == NULL)
- {
- ahstat.ahs_crypto++;
- DPRINTF(("ah_output_cb(): bogus returned buffer from crypto\n"));
- error = EINVAL;
- goto baddone;
- }
-
- /* Copy original headers (with the new protocol number) back in place */
- if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
- m_copyback(m, 0, skip, ptr);
-
- /* No longer needed */
- crypto_freereq(crp);
-
- err = ipsp_process_done(m, tdb);
- splx(s);
- return err;
+ int skip, protoff, error;
+ struct tdb_crypto *tc;
+ struct cryptop *crp;
+ struct tdb *tdb;
+ struct mbuf *m;
+ caddr_t ptr;
+ int err, s;
+
+ crp = (struct cryptop *) op;
+ tc = (struct tdb_crypto *) crp->crp_opaque;
+ skip = tc->tc_skip;
+ protoff = tc->tc_protoff;
+ ptr = (caddr_t) (tc + 1);
+ 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) {
+ ahstat.ahs_notdb++;
+ DPRINTF(("ah_output_cb(): TDB is expired while in crypto\n"));
+ goto baddone;
+ }
+
+ /* Check for crypto errors. */
+ if (crp->crp_etype) {
+ if (tdb->tdb_cryptoid != 0)
+ tdb->tdb_cryptoid = crp->crp_sid;
+
+ if (crp->crp_etype == EAGAIN) {
+ splx(s);
+ return crypto_dispatch(crp);
+ }
+
+ ahstat.ahs_noxform++;
+ DPRINTF(("ah_output_cb(): crypto error %d\n", crp->crp_etype));
+ error = crp->crp_etype;
+ goto baddone;
+ }
+
+ /* Shouldn't happen... */
+ if (m == NULL) {
+ ahstat.ahs_crypto++;
+ DPRINTF(("ah_output_cb(): bogus returned buffer from "
+ "crypto\n"));
+ error = EINVAL;
+ goto baddone;
+ }
+
+ /*
+ * Copy original headers (with the new protocol number) back
+ * in place.
+ */
+ if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
+ m_copyback(m, 0, skip, ptr);
+
+ /* No longer needed. */
+ crypto_freereq(crp);
+
+ err = ipsp_process_done(m, tdb);
+ splx(s);
+ return err;
baddone:
- splx(s);
+ splx(s);
- if (m != NULL)
- m_freem(m);
+ if (m != NULL)
+ m_freem(m);
- crypto_freereq(crp);
+ crypto_freereq(crp);
- return error;
+ return error;
}
diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c
index dfabee511eb..87e8b516062 100644
--- a/sys/netinet/ip_esp.c
+++ b/sys/netinet/ip_esp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.c,v 1.68 2001/06/25 05:11:58 angelos Exp $ */
+/* $OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -80,7 +80,7 @@
int
esp_attach()
{
- return 0;
+ return 0;
}
/*
@@ -89,143 +89,143 @@ esp_attach()
int
esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
- struct enc_xform *txform = NULL;
- struct auth_hash *thash = NULL;
- struct cryptoini cria, crie;
-
- if (ii->ii_encalg)
- {
- switch (ii->ii_encalg)
- {
- case SADB_EALG_DESCBC:
- txform = &enc_xform_des;
- break;
-
- case SADB_EALG_3DESCBC:
- txform = &enc_xform_3des;
- break;
-
- case SADB_X_EALG_AES:
- txform = &enc_xform_rijndael128;
- break;
-
- case SADB_X_EALG_BLF:
- txform = &enc_xform_blf;
- break;
-
- case SADB_X_EALG_CAST:
- txform = &enc_xform_cast5;
- break;
-
- case SADB_X_EALG_SKIPJACK:
- txform = &enc_xform_skipjack;
- break;
+ struct enc_xform *txform = NULL;
+ struct auth_hash *thash = NULL;
+ struct cryptoini cria, crie;
- default:
- DPRINTF(("esp_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg));
- return EINVAL;
- }
-
- if (ii->ii_enckeylen < txform->minkey)
+ if (ii->ii_encalg)
{
- DPRINTF(("esp_init(): keylength %d too small (min length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->minkey, txform->name));
- return EINVAL;
+ switch (ii->ii_encalg)
+ {
+ case SADB_EALG_DESCBC:
+ txform = &enc_xform_des;
+ break;
+
+ case SADB_EALG_3DESCBC:
+ txform = &enc_xform_3des;
+ break;
+
+ case SADB_X_EALG_AES:
+ txform = &enc_xform_rijndael128;
+ break;
+
+ case SADB_X_EALG_BLF:
+ txform = &enc_xform_blf;
+ break;
+
+ case SADB_X_EALG_CAST:
+ txform = &enc_xform_cast5;
+ break;
+
+ case SADB_X_EALG_SKIPJACK:
+ txform = &enc_xform_skipjack;
+ break;
+
+ default:
+ DPRINTF(("esp_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg));
+ return EINVAL;
+ }
+
+ if (ii->ii_enckeylen < txform->minkey)
+ {
+ DPRINTF(("esp_init(): keylength %d too small (min length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->minkey, txform->name));
+ return EINVAL;
+ }
+
+ if (ii->ii_enckeylen > txform->maxkey)
+ {
+ DPRINTF(("esp_init(): keylength %d too large (max length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->maxkey, txform->name));
+ return EINVAL;
+ }
+
+ tdbp->tdb_encalgxform = txform;
+
+ DPRINTF(("esp_init(): initialized TDB with enc algorithm %s\n",
+ txform->name));
+
+ tdbp->tdb_ivlen = txform->blocksize;
+ if (tdbp->tdb_flags & TDBF_HALFIV)
+ tdbp->tdb_ivlen /= 2;
}
- if (ii->ii_enckeylen > txform->maxkey)
+ if (ii->ii_authalg)
{
- DPRINTF(("esp_init(): keylength %d too large (max length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->maxkey, txform->name));
- return EINVAL;
+ switch (ii->ii_authalg)
+ {
+ case SADB_AALG_MD5HMAC:
+ thash = &auth_hash_hmac_md5_96;
+ break;
+
+ case SADB_AALG_SHA1HMAC:
+ thash = &auth_hash_hmac_sha1_96;
+ break;
+
+ case SADB_AALG_RIPEMD160HMAC:
+ thash = &auth_hash_hmac_ripemd_160_96;
+ break;
+
+ default:
+ DPRINTF(("esp_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
+ return EINVAL;
+ }
+
+ if (ii->ii_authkeylen != thash->keysize)
+ {
+ DPRINTF(("esp_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
+ return EINVAL;
+ }
+
+ tdbp->tdb_authalgxform = thash;
+
+ DPRINTF(("esp_init(): initialized TDB with hash algorithm %s\n",
+ thash->name));
}
- tdbp->tdb_encalgxform = txform;
-
- DPRINTF(("esp_init(): initialized TDB with enc algorithm %s\n",
- txform->name));
+ tdbp->tdb_xform = xsp;
+ tdbp->tdb_bitmap = 0;
+ tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
- tdbp->tdb_ivlen = txform->blocksize;
- if (tdbp->tdb_flags & TDBF_HALFIV)
- tdbp->tdb_ivlen /= 2;
- }
-
- if (ii->ii_authalg)
- {
- switch (ii->ii_authalg)
+ /* Initialize crypto session */
+ if (tdbp->tdb_encalgxform)
{
- case SADB_AALG_MD5HMAC:
- thash = &auth_hash_hmac_md5_96;
- break;
+ /* Save the raw keys */
+ tdbp->tdb_emxkeylen = ii->ii_enckeylen;
+ MALLOC(tdbp->tdb_emxkey, u_int8_t *, tdbp->tdb_emxkeylen, M_XDATA,
+ M_WAITOK);
+ bcopy(ii->ii_enckey, tdbp->tdb_emxkey, tdbp->tdb_emxkeylen);
- case SADB_AALG_SHA1HMAC:
- thash = &auth_hash_hmac_sha1_96;
- break;
+ bzero(&crie, sizeof(crie));
- case SADB_AALG_RIPEMD160HMAC:
- thash = &auth_hash_hmac_ripemd_160_96;
- break;
+ crie.cri_alg = tdbp->tdb_encalgxform->type;
- default:
- DPRINTF(("esp_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
- return EINVAL;
+ if (tdbp->tdb_authalgxform)
+ crie.cri_next = &cria;
+ else
+ crie.cri_next = NULL;
+
+ crie.cri_klen = ii->ii_enckeylen * 8;
+ crie.cri_key = ii->ii_enckey;
+ /* XXX Rounds ? */
}
- if (ii->ii_authkeylen != thash->keysize)
+ if (tdbp->tdb_authalgxform)
{
- DPRINTF(("esp_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
- return EINVAL;
+ /* Save the raw keys */
+ tdbp->tdb_amxkeylen = ii->ii_authkeylen;
+ MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen, M_XDATA,
+ M_WAITOK);
+ bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+
+ bzero(&cria, sizeof(cria));
+
+ cria.cri_alg = tdbp->tdb_authalgxform->type;
+ cria.cri_next = NULL;
+ cria.cri_klen = ii->ii_authkeylen * 8;
+ cria.cri_key = ii->ii_authkey;
}
- tdbp->tdb_authalgxform = thash;
-
- DPRINTF(("esp_init(): initialized TDB with hash algorithm %s\n",
- thash->name));
- }
-
- tdbp->tdb_xform = xsp;
- tdbp->tdb_bitmap = 0;
- tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
-
- /* Initialize crypto session */
- if (tdbp->tdb_encalgxform)
- {
- /* Save the raw keys */
- tdbp->tdb_emxkeylen = ii->ii_enckeylen;
- MALLOC(tdbp->tdb_emxkey, u_int8_t *, tdbp->tdb_emxkeylen, M_XDATA,
- M_WAITOK);
- bcopy(ii->ii_enckey, tdbp->tdb_emxkey, tdbp->tdb_emxkeylen);
-
- bzero(&crie, sizeof(crie));
-
- crie.cri_alg = tdbp->tdb_encalgxform->type;
-
- if (tdbp->tdb_authalgxform)
- crie.cri_next = &cria;
- else
- crie.cri_next = NULL;
-
- crie.cri_klen = ii->ii_enckeylen * 8;
- crie.cri_key = ii->ii_enckey;
- /* XXX Rounds ? */
- }
-
- if (tdbp->tdb_authalgxform)
- {
- /* Save the raw keys */
- tdbp->tdb_amxkeylen = ii->ii_authkeylen;
- MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen, M_XDATA,
- M_WAITOK);
- bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
-
- bzero(&cria, sizeof(cria));
-
- cria.cri_alg = tdbp->tdb_authalgxform->type;
- cria.cri_next = NULL;
- cria.cri_klen = ii->ii_authkeylen * 8;
- cria.cri_key = ii->ii_authkey;
- }
-
- return crypto_newsession(&tdbp->tdb_cryptoid,
- (tdbp->tdb_encalgxform ? &crie : &cria), 0);
+ return crypto_newsession(&tdbp->tdb_cryptoid,
+ (tdbp->tdb_encalgxform ? &crie : &cria), 0);
}
/*
@@ -234,25 +234,25 @@ esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
int
esp_zeroize(struct tdb *tdbp)
{
- int err;
-
- if (tdbp->tdb_amxkey)
- {
- bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
- FREE(tdbp->tdb_amxkey, M_XDATA);
- tdbp->tdb_amxkey = NULL;
- }
-
- if (tdbp->tdb_emxkey)
- {
- bzero(tdbp->tdb_emxkey, tdbp->tdb_emxkeylen);
- FREE(tdbp->tdb_emxkey, M_XDATA);
- tdbp->tdb_emxkey = NULL;
- }
-
- err = crypto_freesession(tdbp->tdb_cryptoid);
- tdbp->tdb_cryptoid = 0;
- return err;
+ int err;
+
+ if (tdbp->tdb_amxkey)
+ {
+ bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+ FREE(tdbp->tdb_amxkey, M_XDATA);
+ tdbp->tdb_amxkey = NULL;
+ }
+
+ if (tdbp->tdb_emxkey)
+ {
+ bzero(tdbp->tdb_emxkey, tdbp->tdb_emxkeylen);
+ FREE(tdbp->tdb_emxkey, M_XDATA);
+ tdbp->tdb_emxkey = NULL;
+ }
+
+ err = crypto_freesession(tdbp->tdb_cryptoid);
+ tdbp->tdb_cryptoid = 0;
+ return err;
}
#define MAXBUFSIZ (AH_ALEN_MAX > ESP_MAX_IVS ? AH_ALEN_MAX : ESP_MAX_IVS)
@@ -263,205 +263,205 @@ esp_zeroize(struct tdb *tdbp)
int
esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
{
- struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
- struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
- struct tdb_ident *tdbi;
- struct tdb_crypto *tc;
- int plen, alen, hlen;
- struct m_tag *mtag;
- u_int32_t btsx;
-
- struct cryptodesc *crde = NULL, *crda = NULL;
- struct cryptop *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 */
-
- if (esph)
- alen = AH_HMAC_HASHLEN;
- else
- alen = 0;
-
- if (espx)
- {
- /*
- * Verify payload length is multiple of encryption algorithm
- * block size.
- */
- plen = m->m_pkthdr.len - (skip + hlen + alen);
- if ((plen & (espx->blocksize - 1)) || (plen <= 0))
+ struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
+ struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
+ struct tdb_ident *tdbi;
+ struct tdb_crypto *tc;
+ int plen, alen, hlen;
+ struct m_tag *mtag;
+ u_int32_t btsx;
+
+ struct cryptodesc *crde = NULL, *crda = NULL;
+ struct cryptop *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 */
+
+ if (esph)
+ alen = AH_HMAC_HASHLEN;
+ else
+ alen = 0;
+
+ if (espx)
{
- DPRINTF(("esp_input(): payload of %d octets not a multiple of %d octets, SA %s/%08x\n", plen, espx->blocksize, ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_badilen++;
- m_freem(m);
- return EINVAL;
+ /*
+ * Verify payload length is multiple of encryption algorithm
+ * block size.
+ */
+ plen = m->m_pkthdr.len - (skip + hlen + alen);
+ if ((plen & (espx->blocksize - 1)) || (plen <= 0))
+ {
+ DPRINTF(("esp_input(): payload of %d octets not a multiple of %d octets, SA %s/%08x\n", plen, espx->blocksize, ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_badilen++;
+ m_freem(m);
+ return EINVAL;
+ }
}
- }
-
- /* 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)))
+ /* Replay window checking, if appropriate */
+ if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY)))
{
- case 0: /* All's well */
- break;
+ 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)))
+ {
+ case 0: /* All's well */
+ break;
+
+ case 1:
+ DPRINTF(("esp_input(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_wrap++;
+ m_freem(m);
+ return EACCES;
+
+ case 2:
+ case 3:
+ DPRINTF(("esp_input(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_replay++;
+ m_freem(m);
+ return EACCES;
+
+ default:
+ DPRINTF(("esp_input(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_replay++;
+ m_freem(m);
+ return EACCES;
+ }
+ }
- case 1:
- DPRINTF(("esp_input(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_wrap++;
- m_freem(m);
- return EACCES;
+ /* Update the counters */
+ tdb->tdb_cur_bytes += m->m_pkthdr.len - skip - hlen - alen;
+ espstat.esps_ibytes += m->m_pkthdr.len - skip - hlen - alen;
- case 2:
- case 3:
- DPRINTF(("esp_input(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_replay++;
+ /* 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);
m_freem(m);
- return EACCES;
+ return ENXIO;
+ }
- default:
- DPRINTF(("esp_input(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_replay++;
- m_freem(m);
- return EACCES;
+ /* Notify on soft 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 */
}
- }
-
- /* Update the counters */
- tdb->tdb_cur_bytes += m->m_pkthdr.len - skip - hlen - alen;
- espstat.esps_ibytes += m->m_pkthdr.len - skip - hlen - alen;
-
- /* 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);
- m_freem(m);
- return ENXIO;
- }
-
- /* Notify on soft 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 */
- }
-
- /* Find out if we've already done crypto */
- for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
- mtag != NULL;
- mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag))
- {
- tdbi = (struct tdb_ident *) (mtag + 1);
- if (tdbi->proto == tdb->tdb_sproto && tdbi->spi == tdb->tdb_spi &&
- !bcmp(&tdbi->dst, &tdb->tdb_dst, sizeof(union sockaddr_union)))
- break;
- }
-
- /* Get crypto descriptors */
- crp = crypto_getreq(esph && espx ? 2 : 1);
- if (crp == NULL)
- {
- m_freem(m);
- DPRINTF(("esp_input(): failed to acquire crypto descriptors\n"));
- espstat.esps_crypto++;
- return ENOBUFS;
- }
-
- /* Get IPsec-specific opaque pointer */
- if (esph == NULL || mtag != NULL)
- MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
- M_XDATA, M_NOWAIT);
- else
- MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto) + alen,
- M_XDATA, M_NOWAIT);
- if (tc == NULL)
- {
- m_freem(m);
- crypto_freereq(crp);
- DPRINTF(("esp_input(): failed to allocate tdb_crypto\n"));
- espstat.esps_crypto++;
- return ENOBUFS;
- }
- bzero(tc, sizeof(struct tdb_crypto));
- tc->tc_ptr = (caddr_t) mtag;
+ /* Find out if we've already done crypto */
+ for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
+ mtag != NULL;
+ mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag))
+ {
+ tdbi = (struct tdb_ident *) (mtag + 1);
+ if (tdbi->proto == tdb->tdb_sproto && tdbi->spi == tdb->tdb_spi &&
+ !bcmp(&tdbi->dst, &tdb->tdb_dst, sizeof(union sockaddr_union)))
+ break;
+ }
- if (esph)
- {
- crda = crp->crp_desc;
- crde = crda->crd_next;
+ /* Get crypto descriptors */
+ crp = crypto_getreq(esph && espx ? 2 : 1);
+ if (crp == NULL)
+ {
+ m_freem(m);
+ DPRINTF(("esp_input(): failed to acquire crypto descriptors\n"));
+ espstat.esps_crypto++;
+ return ENOBUFS;
+ }
- /* Authentication descriptor */
- crda->crd_skip = skip;
- crda->crd_len = m->m_pkthdr.len - (skip + alen);
- crda->crd_inject = m->m_pkthdr.len - alen;
+ /* Get IPsec-specific opaque pointer */
+ if (esph == NULL || mtag != NULL)
+ MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
+ M_XDATA, M_NOWAIT);
+ else
+ MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto) + alen,
+ M_XDATA, M_NOWAIT);
+ if (tc == NULL)
+ {
+ m_freem(m);
+ crypto_freereq(crp);
+ DPRINTF(("esp_input(): failed to allocate tdb_crypto\n"));
+ espstat.esps_crypto++;
+ return ENOBUFS;
+ }
- crda->crd_alg = esph->type;
- crda->crd_key = tdb->tdb_amxkey;
- crda->crd_klen = tdb->tdb_amxkeylen * 8;
+ bzero(tc, sizeof(struct tdb_crypto));
+ tc->tc_ptr = (caddr_t) mtag;
- /* Copy the authenticator */
- if (mtag == NULL)
- m_copydata(m, m->m_pkthdr.len - alen, alen, (caddr_t) (tc + 1));
- }
- else
- crde = crp->crp_desc;
-
- /* 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 *)) esp_input_cb;
- crp->crp_sid = tdb->tdb_cryptoid;
- crp->crp_opaque = (caddr_t) tc;
-
- /* These are passed as-is to the callback */
- tc->tc_skip = skip;
- tc->tc_protoff = protoff;
- tc->tc_spi = tdb->tdb_spi;
- tc->tc_proto = tdb->tdb_sproto;
- bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
-
- /* Decryption descriptor */
- if (espx)
- {
- crde->crd_skip = skip + hlen;
- crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
- crde->crd_inject = skip + hlen - tdb->tdb_ivlen;
-
- if (tdb->tdb_flags & TDBF_HALFIV)
+ if (esph)
{
- /* Copy half-IV from packet */
- m_copydata(m, crde->crd_inject, tdb->tdb_ivlen, crde->crd_iv);
+ crda = crp->crp_desc;
+ crde = crda->crd_next;
- /* Cook IV */
- for (btsx = 0; btsx < tdb->tdb_ivlen; btsx++)
- crde->crd_iv[tdb->tdb_ivlen + btsx] = ~crde->crd_iv[btsx];
+ /* Authentication descriptor */
+ crda->crd_skip = skip;
+ crda->crd_len = m->m_pkthdr.len - (skip + alen);
+ crda->crd_inject = m->m_pkthdr.len - alen;
- crde->crd_flags |= CRD_F_IV_EXPLICIT;
- }
+ crda->crd_alg = esph->type;
+ crda->crd_key = tdb->tdb_amxkey;
+ crda->crd_klen = tdb->tdb_amxkeylen * 8;
- crde->crd_alg = espx->type;
- crde->crd_key = tdb->tdb_emxkey;
- crde->crd_klen = tdb->tdb_emxkeylen * 8;
- /* XXX Rounds ? */
- }
+ /* Copy the authenticator */
+ if (mtag == NULL)
+ m_copydata(m, m->m_pkthdr.len - alen, alen, (caddr_t) (tc + 1));
+ }
+ else
+ crde = crp->crp_desc;
+
+ /* 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 *)) esp_input_cb;
+ crp->crp_sid = tdb->tdb_cryptoid;
+ crp->crp_opaque = (caddr_t) tc;
+
+ /* These are passed as-is to the callback */
+ tc->tc_skip = skip;
+ tc->tc_protoff = protoff;
+ tc->tc_spi = tdb->tdb_spi;
+ tc->tc_proto = tdb->tdb_sproto;
+ bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
+
+ /* Decryption descriptor */
+ if (espx)
+ {
+ crde->crd_skip = skip + hlen;
+ crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
+ crde->crd_inject = skip + hlen - tdb->tdb_ivlen;
+
+ if (tdb->tdb_flags & TDBF_HALFIV)
+ {
+ /* Copy half-IV from packet */
+ m_copydata(m, crde->crd_inject, tdb->tdb_ivlen, crde->crd_iv);
+
+ /* Cook IV */
+ for (btsx = 0; btsx < tdb->tdb_ivlen; btsx++)
+ crde->crd_iv[tdb->tdb_ivlen + btsx] = ~crde->crd_iv[btsx];
+
+ crde->crd_flags |= CRD_F_IV_EXPLICIT;
+ }
+
+ crde->crd_alg = espx->type;
+ crde->crd_key = tdb->tdb_emxkey;
+ crde->crd_klen = tdb->tdb_emxkeylen * 8;
+ /* XXX Rounds ? */
+ }
- if (mtag == NULL)
- return crypto_dispatch(crp);
- else
- return esp_input_cb(crp);
+ if (mtag == NULL)
+ return crypto_dispatch(crp);
+ else
+ return esp_input_cb(crp);
}
/*
@@ -470,216 +470,216 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
int
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;
- 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)
+ 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;
+ 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)
{
- /* 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;
+ espstat.esps_crypto++;
+ DPRINTF(("esp_input_cb(): bogus returned buffer from crypto\n"));
+ error = EINVAL;
goto baddone;
- }
}
- /* Remove trailing authenticator */
- m_adj(m, -(esph->authsize));
- }
-
- /* 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))
+ /* 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));
+ }
+
+ /* 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))
{
- 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;
+ 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));
+ /* 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);
+ /* 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;
+ /* Back to generic IPsec input processing */
+ err = ipsec_common_input_cb(m, tdb, skip, protoff, mtag);
+ splx(s);
+ return err;
baddone:
- splx(s);
+ splx(s);
- if (m)
- m_freem(m);
+ if (m != NULL)
+ m_freem(m);
- crypto_freereq(crp);
+ crypto_freereq(crp);
- return error;
+ return error;
}
/*
@@ -687,302 +687,296 @@ esp_input_cb(void *op)
*/
int
esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
- int protoff)
+ int protoff)
{
- struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
- struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
- int ilen, hlen, rlen, plen, padding, blks, alen;
- struct mbuf *mi, *mo = (struct mbuf *) NULL;
- struct tdb_crypto *tc;
- unsigned char *pad;
- u_int8_t prot;
+ struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
+ struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
+ int ilen, hlen, rlen, plen, padding, blks, alen;
+ struct mbuf *mi, *mo = (struct mbuf *) NULL;
+ struct tdb_crypto *tc;
+ unsigned char *pad;
+ u_int8_t prot;
- struct cryptodesc *crde = NULL, *crda = NULL;
- struct cryptop *crp;
+ struct cryptodesc *crde = NULL, *crda = NULL;
+ struct cryptop *crp;
#if NBPFILTER > 0
- {
- struct ifnet *ifn;
- struct enchdr hdr;
- struct mbuf m1;
+ {
+ struct ifnet *ifn;
+ struct enchdr hdr;
+ struct mbuf m1;
- bzero (&hdr, sizeof(hdr));
+ bzero (&hdr, sizeof(hdr));
- hdr.af = tdb->tdb_dst.sa.sa_family;
- hdr.spi = tdb->tdb_spi;
- if (espx)
- hdr.flags |= M_CONF;
- if (esph)
- hdr.flags |= M_AUTH;
+ hdr.af = tdb->tdb_dst.sa.sa_family;
+ hdr.spi = tdb->tdb_spi;
+ if (espx)
+ hdr.flags |= M_CONF;
+ if (esph)
+ hdr.flags |= M_AUTH;
- m1.m_next = m;
- m1.m_len = ENC_HDRLEN;
- m1.m_data = (char *) &hdr;
+ m1.m_next = m;
+ m1.m_len = ENC_HDRLEN;
+ m1.m_data = (char *) &hdr;
- ifn = &(encif[0].sc_if);
+ ifn = &(encif[0].sc_if);
- if (ifn->if_bpf)
- bpf_mtap(ifn->if_bpf, &m1);
- }
+ if (ifn->if_bpf)
+ bpf_mtap(ifn->if_bpf, &m1);
+ }
#endif
- if (tdb->tdb_flags & TDBF_NOREPLAY)
- hlen = sizeof(u_int32_t) + tdb->tdb_ivlen;
- else
- hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
-
- rlen = m->m_pkthdr.len - skip; /* Raw payload length */
- if (espx)
- blks = espx->blocksize;
- else
- blks = 4; /* If no encryption is used, we have to be 4-byte aligned */
-
- padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
- plen = rlen + padding; /* Padded payload length */
-
- if (esph)
- alen = AH_HMAC_HASHLEN;
- else
- alen = 0;
-
- espstat.esps_output++;
-
- /* Check for replay counter wrap-around in automatic (not manual) keying */
- if ((!(tdb->tdb_flags & TDBF_NOREPLAY)) &&
- (tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0))
- {
- DPRINTF(("esp_output(): SA %s/%08x should have expired\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- espstat.esps_wrap++;
- return EACCES;
- }
-
- switch (tdb->tdb_dst.sa.sa_family)
- {
+ if (tdb->tdb_flags & TDBF_NOREPLAY)
+ hlen = sizeof(u_int32_t) + tdb->tdb_ivlen;
+ else
+ hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
+
+ rlen = m->m_pkthdr.len - skip; /* Raw payload length. */
+ if (espx)
+ blks = espx->blocksize;
+ else
+ blks = 4; /* If no encryption, we have to be 4-byte aligned. */
+
+ padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
+ plen = rlen + padding; /* Padded payload length. */
+
+ if (esph)
+ alen = AH_HMAC_HASHLEN;
+ else
+ alen = 0;
+
+ espstat.esps_output++;
+
+ /*
+ * Check for replay counter wrap-around in automatic (not
+ * manual) keying.
+ */
+ if ((!(tdb->tdb_flags & TDBF_NOREPLAY)) &&
+ (tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0)) {
+ DPRINTF(("esp_output(): SA %s/%08x should have expired\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ m_freem(m);
+ espstat.esps_wrap++;
+ return EACCES;
+ }
+
+ switch (tdb->tdb_dst.sa.sa_family) {
#ifdef INET
case AF_INET:
- /* Check for IP maximum packet size violations */
- if (skip + hlen + rlen + padding + alen > IP_MAXPACKET)
- {
- DPRINTF(("esp_output(): packet in SA %s/%08x got too big\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- espstat.esps_toobig++;
- return EMSGSIZE;
- }
- break;
+ /* Check for IP maximum packet size violations. */
+ if (skip + hlen + rlen + padding + alen > IP_MAXPACKET) {
+ DPRINTF(("esp_output(): packet in SA %s/%08x got "
+ "too big\n", ipsp_address(tdb->tdb_dst),
+ ntohl(tdb->tdb_spi)));
+ m_freem(m);
+ espstat.esps_toobig++;
+ return EMSGSIZE;
+ }
+ break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- /* Check for IPv6 maximum packet size violations */
- if (skip + hlen + rlen + padding + alen > IPV6_MAXPACKET)
- {
- DPRINTF(("esp_output(): packet in SA %s/%08x got too big\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- espstat.esps_toobig++;
- return EMSGSIZE;
- }
- break;
+ /* Check for IPv6 maximum packet size violations. */
+ if (skip + hlen + rlen + padding + alen > IPV6_MAXPACKET) {
+ DPRINTF(("esp_output(): packet in SA %s/%08x got too "
+ "big\n", ipsp_address(tdb->tdb_dst),
+ ntohl(tdb->tdb_spi)));
+ m_freem(m);
+ espstat.esps_toobig++;
+ return EMSGSIZE;
+ }
+ break;
#endif /* INET6 */
default:
- DPRINTF(("esp_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);
- espstat.esps_nopf++;
- return EPFNOSUPPORT;
- }
-
- /* Update the counters */
- tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
- espstat.esps_obytes += m->m_pkthdr.len - skip;
-
- /* Hard byte 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);
- m_freem(m);
- return EINVAL;
- }
-
- /* Soft byte 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) || !MCLISREFERENCED(mi)))
- {
- 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)
- {
- DPRINTF(("esp_output(): bad mbuf chain, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- m_freem(m);
- return ENOBUFS;
- }
-
- if (mo != NULL)
- mo->m_next = n;
- else
- m = n;
-
- m_freem(mi);
- }
-
- /* Inject ESP header */
- mo = m_inject(m, skip, hlen, M_DONTWAIT);
- if (mo == NULL)
- {
- DPRINTF(("esp_output(): failed to inject ESP header for SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- espstat.esps_wrap++;
- return ENOBUFS;
- }
-
- /* Initialize ESP header */
- bcopy((caddr_t) &tdb->tdb_spi, mtod(mo, caddr_t), sizeof(u_int32_t));
- if (!(tdb->tdb_flags & TDBF_NOREPLAY))
- {
- u_int32_t replay = htonl(tdb->tdb_rpl++);
- bcopy((caddr_t) &replay, mtod(mo, caddr_t) + sizeof(u_int32_t),
- sizeof(u_int32_t));
- }
-
- /*
- * Add padding -- better to do it ourselves than use the crypto engine,
- * although if/when we support compression, we'd have to do that.
- */
- pad = (u_char *) m_pad(m, padding + alen);
- if (pad == NULL)
- {
- DPRINTF(("esp_output(): m_pad() failed for SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- return ENOBUFS;
- }
-
- /* Self-describing padding ? */
- if (!(tdb->tdb_flags & TDBF_RANDOMPADDING))
- for (ilen = 0; ilen < padding - 2; ilen++)
- pad[ilen] = ilen + 1;
- else
- get_random_bytes((void *) pad, padding - 2); /* Random padding */
-
- /* Fix padding length and Next Protocol in padding itself */
- pad[padding - 2] = padding - 2;
- m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1);
-
- /* Fix Next Protocol in IPv4/IPv6 header */
- prot = IPPROTO_ESP;
- m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot);
-
- /* Get crypto descriptors */
- crp = crypto_getreq(esph && espx ? 2 : 1);
- if (crp == NULL)
- {
- m_freem(m);
- DPRINTF(("esp_output(): failed to acquire crypto descriptors\n"));
- espstat.esps_crypto++;
- return ENOBUFS;
- }
-
- if (espx)
- {
- crde = crp->crp_desc;
- crda = crde->crd_next;
-
- /* Encryption descriptor */
- crde->crd_skip = skip + hlen;
- crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
- crde->crd_flags = CRD_F_ENCRYPT;
- crde->crd_inject = skip + hlen - tdb->tdb_ivlen;
+ DPRINTF(("esp_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);
+ espstat.esps_nopf++;
+ return EPFNOSUPPORT;
+ }
- if (tdb->tdb_flags & TDBF_HALFIV)
- {
- /* Copy half-iv in the packet */
- m_copyback(m, crde->crd_inject, tdb->tdb_ivlen, tdb->tdb_iv);
+ /* Update the counters. */
+ tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
+ espstat.esps_obytes += m->m_pkthdr.len - skip;
- /* Cook half-iv */
- bcopy(tdb->tdb_iv, crde->crd_iv, tdb->tdb_ivlen);
- for (ilen = 0; ilen < tdb->tdb_ivlen; ilen++)
- crde->crd_iv[tdb->tdb_ivlen + ilen] = ~crde->crd_iv[ilen];
+ /* Hard byte 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);
+ m_freem(m);
+ return EINVAL;
+ }
- crde->crd_flags |= CRD_F_IV_PRESENT | CRD_F_IV_EXPLICIT;
+ /* Soft byte 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. */
}
- /* Encryption operation */
- crde->crd_alg = espx->type;
- crde->crd_key = tdb->tdb_emxkey;
- crde->crd_klen = tdb->tdb_emxkeylen * 8;
- /* XXX Rounds ? */
- }
- else
- crda = crp->crp_desc;
-
- /* IPsec-specific opaque crypto info */
- MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
- M_XDATA, M_NOWAIT);
- if (tc == NULL)
- {
- m_freem(m);
- crypto_freereq(crp);
- DPRINTF(("esp_output(): failed to allocate tdb_crypto\n"));
- espstat.esps_crypto++;
- return ENOBUFS;
- }
-
- bzero(tc, sizeof(struct tdb_crypto));
- tc->tc_spi = tdb->tdb_spi;
- tc->tc_proto = tdb->tdb_sproto;
- bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
-
- /* 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 *)) esp_output_cb;
- crp->crp_opaque = (caddr_t) tc;
- crp->crp_sid = tdb->tdb_cryptoid;
-
- if (esph)
- {
- /* Authentication descriptor */
- crda->crd_skip = skip;
- crda->crd_len = m->m_pkthdr.len - (skip + alen);
- crda->crd_inject = m->m_pkthdr.len - alen;
-
- /* Authentication operation */
- crda->crd_alg = esph->type;
- crda->crd_key = tdb->tdb_amxkey;
- crda->crd_klen = tdb->tdb_amxkeylen * 8;
- }
-
- if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
- return crypto_dispatch(crp);
- else
- return esp_output_cb(crp);
+ /*
+ * 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) || !MCLISREFERENCED(mi))) {
+ 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) {
+ DPRINTF(("esp_output(): bad mbuf chain, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_hdrops++;
+ m_freem(m);
+ return ENOBUFS;
+ }
+
+ if (mo != NULL)
+ mo->m_next = n;
+ else
+ m = n;
+
+ m_freem(mi);
+ }
+
+ /* Inject ESP header. */
+ mo = m_inject(m, skip, hlen, M_DONTWAIT);
+ if (mo == NULL) {
+ DPRINTF(("esp_output(): failed to inject ESP header for "
+ "SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
+ ntohl(tdb->tdb_spi)));
+ m_freem(m);
+ espstat.esps_wrap++;
+ return ENOBUFS;
+ }
+
+ /* Initialize ESP header. */
+ bcopy((caddr_t) &tdb->tdb_spi, mtod(mo, caddr_t), sizeof(u_int32_t));
+ if (!(tdb->tdb_flags & TDBF_NOREPLAY)) {
+ u_int32_t replay = htonl(tdb->tdb_rpl++);
+ bcopy((caddr_t) &replay, mtod(mo, caddr_t) + sizeof(u_int32_t),
+ sizeof(u_int32_t));
+ }
+
+ /*
+ * Add padding -- better to do it ourselves than use the crypto engine,
+ * although if/when we support compression, we'd have to do that.
+ */
+ pad = (u_char *) m_pad(m, padding + alen);
+ if (pad == NULL) {
+ DPRINTF(("esp_output(): m_pad() failed for SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ return ENOBUFS;
+ }
+
+ /* Self-describing or random padding ? */
+ if (!(tdb->tdb_flags & TDBF_RANDOMPADDING))
+ for (ilen = 0; ilen < padding - 2; ilen++)
+ pad[ilen] = ilen + 1;
+ else
+ get_random_bytes((void *) pad, padding - 2);
+
+ /* Fix padding length and Next Protocol in padding itself. */
+ pad[padding - 2] = padding - 2;
+ m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1);
+
+ /* Fix Next Protocol in IPv4/IPv6 header. */
+ prot = IPPROTO_ESP;
+ m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot);
+
+ /* Get crypto descriptors. */
+ crp = crypto_getreq(esph && espx ? 2 : 1);
+ if (crp == NULL) {
+ m_freem(m);
+ DPRINTF(("esp_output(): failed to acquire crypto "
+ "descriptors\n"));
+ espstat.esps_crypto++;
+ return ENOBUFS;
+ }
+
+ if (espx) {
+ crde = crp->crp_desc;
+ crda = crde->crd_next;
+
+ /* Encryption descriptor. */
+ crde->crd_skip = skip + hlen;
+ crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
+ crde->crd_flags = CRD_F_ENCRYPT;
+ crde->crd_inject = skip + hlen - tdb->tdb_ivlen;
+
+ if (tdb->tdb_flags & TDBF_HALFIV) {
+ /* Copy half-iv in the packet. */
+ m_copyback(m, crde->crd_inject, tdb->tdb_ivlen,
+ tdb->tdb_iv);
+
+ /* Cook half-iv. */
+ bcopy(tdb->tdb_iv, crde->crd_iv, tdb->tdb_ivlen);
+ for (ilen = 0; ilen < tdb->tdb_ivlen; ilen++)
+ crde->crd_iv[tdb->tdb_ivlen + ilen] =
+ ~crde->crd_iv[ilen];
+
+ crde->crd_flags |=
+ CRD_F_IV_PRESENT | CRD_F_IV_EXPLICIT;
+ }
+
+ /* Encryption operation. */
+ crde->crd_alg = espx->type;
+ crde->crd_key = tdb->tdb_emxkey;
+ crde->crd_klen = tdb->tdb_emxkeylen * 8;
+ /* XXX Rounds ? */
+ } else
+ crda = crp->crp_desc;
+
+ /* IPsec-specific opaque crypto info. */
+ MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
+ M_XDATA, M_NOWAIT);
+ if (tc == NULL) {
+ m_freem(m);
+ crypto_freereq(crp);
+ DPRINTF(("esp_output(): failed to allocate tdb_crypto\n"));
+ espstat.esps_crypto++;
+ return ENOBUFS;
+ }
+
+ bzero(tc, sizeof(struct tdb_crypto));
+ tc->tc_spi = tdb->tdb_spi;
+ tc->tc_proto = tdb->tdb_sproto;
+ bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
+
+ /* 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 *)) esp_output_cb;
+ crp->crp_opaque = (caddr_t) tc;
+ crp->crp_sid = tdb->tdb_cryptoid;
+
+ if (esph) {
+ /* Authentication descriptor. */
+ crda->crd_skip = skip;
+ crda->crd_len = m->m_pkthdr.len - (skip + alen);
+ crda->crd_inject = m->m_pkthdr.len - alen;
+
+ /* Authentication operation. */
+ crda->crd_alg = esph->type;
+ crda->crd_key = tdb->tdb_amxkey;
+ crda->crd_klen = tdb->tdb_amxkeylen * 8;
+ }
+
+ if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
+ return crypto_dispatch(crp);
+ else
+ return esp_output_cb(crp);
}
/*
@@ -991,81 +985,79 @@ esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
int
esp_output_cb(void *op)
{
- struct cryptop *crp = (struct cryptop *) op;
- struct tdb_crypto *tc;
- struct tdb *tdb;
- struct mbuf *m;
- int error, s;
-
- tc = (struct tdb_crypto *) crp->crp_opaque;
- 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_output_cb(): TDB is expired while in crypto\n"));
- goto baddone;
- }
-
- /* Check for crypto errors */
- if (crp->crp_etype)
- {
- /* Reset 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_output_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_output_cb(): bogus returned buffer from crypto\n"));
- error = EINVAL;
- goto baddone;
- }
-
- /* Release crypto descriptors */
- crypto_freereq(crp);
-
- /*
- * If we're doing half-iv, keep a copy of the last few bytes of the
- * encrypted part, for use as the next IV. Note that HALF-IV is only
- * supposed to be used without authentication (the old ESP specs).
- */
- if (tdb->tdb_flags & TDBF_HALFIV)
- m_copydata(m, m->m_pkthdr.len - tdb->tdb_ivlen, tdb->tdb_ivlen,
- tdb->tdb_iv);
-
- /* Call the IPsec input callback */
- error = ipsp_process_done(m, tdb);
- splx(s);
- return error;
+ struct cryptop *crp = (struct cryptop *) op;
+ struct tdb_crypto *tc;
+ struct tdb *tdb;
+ struct mbuf *m;
+ int error, s;
+
+ tc = (struct tdb_crypto *) crp->crp_opaque;
+ 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_output_cb(): TDB is expired while in crypto\n"));
+ goto baddone;
+ }
+
+ /* Check for crypto errors. */
+ if (crp->crp_etype) {
+ /* Reset 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_output_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_output_cb(): bogus returned buffer from "
+ "crypto\n"));
+ error = EINVAL;
+ goto baddone;
+ }
+
+ /* Release crypto descriptors. */
+ crypto_freereq(crp);
+
+ /*
+ * If we're doing half-iv, keep a copy of the last few bytes of the
+ * encrypted part, for use as the next IV. Note that HALF-IV is only
+ * supposed to be used without authentication (the old ESP specs).
+ */
+ if (tdb->tdb_flags & TDBF_HALFIV)
+ m_copydata(m, m->m_pkthdr.len - tdb->tdb_ivlen, tdb->tdb_ivlen,
+ tdb->tdb_iv);
+
+ /* Call the IPsec input callback. */
+ error = ipsp_process_done(m, tdb);
+ splx(s);
+ return error;
baddone:
- splx(s);
+ splx(s);
- if (m)
- m_freem(m);
+ if (m != NULL)
+ m_freem(m);
- crypto_freereq(crp);
+ crypto_freereq(crp);
- return error;
+ return error;
}
/*
@@ -1076,41 +1068,38 @@ esp_output_cb(void *op)
*/
int
checkreplaywindow32(u_int32_t seq, u_int32_t initial, u_int32_t *lastseq,
- u_int32_t window, u_int32_t *bitmap)
+ u_int32_t window, u_int32_t *bitmap)
{
- u_int32_t diff;
+ u_int32_t diff;
- seq -= initial;
+ seq -= initial;
- if (seq == 0)
- return 1;
+ if (seq == 0)
+ return 1;
- if (seq > *lastseq - initial)
- {
- diff = seq - (*lastseq - initial);
- if (diff < window)
- *bitmap = ((*bitmap) << diff) | 1;
- else
- *bitmap = 1;
- *lastseq = seq + initial;
+ if (seq > *lastseq - initial) {
+ diff = seq - (*lastseq - initial);
+ if (diff < window)
+ *bitmap = ((*bitmap) << diff) | 1;
+ else
+ *bitmap = 1;
+ *lastseq = seq + initial;
+ return 0;
+ }
+
+ diff = *lastseq - initial - seq;
+ if (diff >= window) {
+ espstat.esps_wrap++;
+ return 2;
+ }
+
+ if ((*bitmap) & (((u_int32_t) 1) << diff)) {
+ espstat.esps_replay++;
+ return 3;
+ }
+
+ *bitmap |= (((u_int32_t) 1) << diff);
return 0;
- }
-
- diff = *lastseq - initial - seq;
- if (diff >= window)
- {
- espstat.esps_wrap++;
- return 2;
- }
-
- if ((*bitmap) & (((u_int32_t) 1) << diff))
- {
- espstat.esps_replay++;
- return 3;
- }
-
- *bitmap |= (((u_int32_t) 1) << diff);
- return 0;
}
/*
@@ -1122,71 +1111,65 @@ checkreplaywindow32(u_int32_t seq, u_int32_t initial, u_int32_t *lastseq,
caddr_t
m_pad(struct mbuf *m, int n)
{
- register struct mbuf *m0, *m1;
- register int len, pad;
- caddr_t retval;
-
- if (n <= 0) /* no stupid arguments */
- {
- DPRINTF(("m_pad(): pad length invalid (%d)\n", n));
- return NULL;
- }
-
- len = m->m_pkthdr.len;
- pad = n;
-
- m0 = m;
-
- while (m0->m_len < len)
- {
- len -= m0->m_len;
- m0 = m0->m_next;
- }
-
- if (m0->m_len != len)
- {
- DPRINTF(("m_pad(): length mismatch (should be %d instead of %d)\n",
- m->m_pkthdr.len, m->m_pkthdr.len + m0->m_len - len));
- m_freem(m);
- return NULL;
- }
-
- /* Check for zero-length trailing mbufs, and find the last one */
- for (m1 = m0; m1->m_next; m1 = m1->m_next)
- {
- if (m1->m_next->m_len != 0)
- {
- DPRINTF(("m_pad(): length mismatch (should be %d instead of %d)\n",
- m->m_pkthdr.len, m->m_pkthdr.len + m1->m_next->m_len));
- m_freem(m);
- return NULL;
+ register struct mbuf *m0, *m1;
+ register int len, pad;
+ caddr_t retval;
+
+ if (n <= 0) { /* No stupid arguments. */
+ DPRINTF(("m_pad(): pad length invalid (%d)\n", n));
+ return NULL;
}
- m0 = m1->m_next;
- }
+ len = m->m_pkthdr.len;
+ pad = n;
+ m0 = m;
- if ((m0->m_flags & M_EXT) ||
- (m0->m_data + m0->m_len + pad >= &(m0->m_dat[MLEN])))
- {
- /*
- * Add an mbuf to the chain
- */
- MGET(m1, M_DONTWAIT, MT_DATA);
- if (m1 == 0)
- {
- m_freem(m0);
- DPRINTF(("m_pad(): cannot append\n"));
- return NULL;
+ while (m0->m_len < len) {
+ len -= m0->m_len;
+ m0 = m0->m_next;
}
- m0->m_next = m1;
- m0 = m1;
- m0->m_len = 0;
- }
+ if (m0->m_len != len) {
+ DPRINTF(("m_pad(): length mismatch (should be %d instead of "
+ "%d)\n", m->m_pkthdr.len,
+ m->m_pkthdr.len + m0->m_len - len));
+
+ m_freem(m);
+ return NULL;
+ }
+
+ /* Check for zero-length trailing mbufs, and find the last one. */
+ for (m1 = m0; m1->m_next; m1 = m1->m_next) {
+ if (m1->m_next->m_len != 0) {
+ DPRINTF(("m_pad(): length mismatch (should be %d "
+ "instead of %d)\n", m->m_pkthdr.len,
+ m->m_pkthdr.len + m1->m_next->m_len));
+
+ m_freem(m);
+ return NULL;
+ }
+
+ m0 = m1->m_next;
+ }
+
+ if ((m0->m_flags & M_EXT) ||
+ m0->m_data + m0->m_len + pad >= &(m0->m_dat[MLEN])) {
+ /* Add an mbuf to the chain. */
+ MGET(m1, M_DONTWAIT, MT_DATA);
+ if (m1 == 0) {
+ m_freem(m0);
+ DPRINTF(("m_pad(): cannot append\n"));
+ return NULL;
+ }
+
+ m0->m_next = m1;
+ m0 = m1;
+ m0->m_len = 0;
+ }
- retval = m0->m_data + m0->m_len;
- m0->m_len += pad;
- m->m_pkthdr.len += pad;
+ retval = m0->m_data + m0->m_len;
+ m0->m_len += pad;
+ m->m_pkthdr.len += pad;
- return retval;
+ return retval;
}