diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_ah.c | 32 | ||||
-rw-r--r-- | sys/netinet/ip_esp.c | 34 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.c | 357 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 33 | ||||
-rw-r--r-- | sys/netinet/ipsec_input.c | 29 | ||||
-rw-r--r-- | sys/netinet/ipsec_output.c | 9 |
6 files changed, 161 insertions, 333 deletions
diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c index d9d7da6b3ee..7845272b22c 100644 --- a/sys/netinet/ip_ah.c +++ b/sys/netinet/ip_ah.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ip_ah.c,v 1.46 2001/02/20 06:48:06 itojun Exp $ */ +/* $OpenBSD: ip_ah.c,v 1.47 2001/03/15 06:30:58 mickey Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and + * Angelos D. Keromytis (kermit@csd.uch.gr) and * Niels Provos (provos@physnet.uni-hamburg.de). * * The original version of this code was written by John Ioannidis @@ -23,7 +23,7 @@ * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or - * modification of this software. + * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to @@ -263,7 +263,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) m_freem(m); return EINVAL; } - + switch (ptr[off]) { case IPOPT_EOL: @@ -372,7 +372,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) /* 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) { @@ -574,7 +574,7 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff) (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, TDBEXP_TIMEOUT); + tdb_delete(tdb); m_freem(m); return ENXIO; } @@ -676,7 +676,7 @@ 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; @@ -778,7 +778,7 @@ ah_input_cb(void *op) } /* Remove the AH header from the mbuf */ - if (roff == 0) + if (roff == 0) { /* The AH header was conveniently at the beginning of the mbuf */ m_adj(m1, rplen + ahx->authsize); @@ -816,7 +816,7 @@ ah_input_cb(void *op) } 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. @@ -954,7 +954,7 @@ ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip, (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, TDBEXP_TIMEOUT); + tdb_delete(tdb); m_freem(m); return EINVAL; } @@ -968,24 +968,24 @@ ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip, } /* - * Loop through mbuf chain; if we find an M_EXT mbuf with + * 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) || + while (mi != NULL && + (!(mi->m_flags & M_EXT) || (mi->m_ext.ext_ref == NULL && mclrefcnt[mtocl(mi->m_ext.ext_buf)] <= 1))) { mo = mi; mi = mi->m_next; } - + if (mi != NULL) { /* Replace the rest of the mbuf chain. */ struct mbuf *n = m_copym2(mi, 0, M_COPYALL, M_DONTWAIT); - + if (n == NULL) { ahstat.ahs_hdrops++; @@ -1017,7 +1017,7 @@ ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip, * 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); diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c index 8b232b8d7b9..df0c90f4255 100644 --- a/sys/netinet/ip_esp.c +++ b/sys/netinet/ip_esp.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ip_esp.c,v 1.51 2000/11/17 04:15:42 angelos Exp $ */ +/* $OpenBSD: ip_esp.c,v 1.52 2001/03/15 06:30:59 mickey Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and + * Angelos D. Keromytis (kermit@csd.uch.gr) and * Niels Provos (provos@physnet.uni-hamburg.de). * * The original version of this code was written by John Ioannidis @@ -18,11 +18,11 @@ * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. - * + * * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or - * modification of this software. + * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to @@ -148,7 +148,7 @@ esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) 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)); @@ -191,13 +191,13 @@ esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) 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_xform = xsp; tdbp->tdb_bitmap = 0; tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL; @@ -359,7 +359,7 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff) (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, TDBEXP_TIMEOUT); + tdb_delete(tdb); m_freem(m); return ENXIO; } @@ -585,7 +585,7 @@ esp_input_cb(void *op) } /* Remove the ESP header and IV from the mbuf. */ - if (roff == 0) + if (roff == 0) { /* The ESP header was conveniently at the beginning of the mbuf */ m_adj(m1, hlen); @@ -623,7 +623,7 @@ esp_input_cb(void *op) } 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. @@ -811,7 +811,7 @@ esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip, (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, TDBEXP_TIMEOUT); + tdb_delete(tdb); m_freem(m); return EINVAL; } @@ -825,24 +825,24 @@ esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip, } /* - * Loop through mbuf chain; if we find an M_EXT mbuf with + * 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) || + while (mi != NULL && + (!(mi->m_flags & M_EXT) || (mi->m_ext.ext_ref == NULL && mclrefcnt[mtocl(mi->m_ext.ext_buf)] <= 1))) { mo = mi; mi = mi->m_next; } - + if (mi != NULL) { /* Replace the rest of the mbuf chain. */ struct mbuf *n = m_copym2(mi, 0, M_COPYALL, M_DONTWAIT); - + if (n == NULL) { espstat.esps_hdrops++; @@ -1132,7 +1132,7 @@ 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)); diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c index a8239aff0b3..135f36048bd 100644 --- a/sys/netinet/ip_ipsp.c +++ b/sys/netinet/ip_ipsp.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ip_ipsp.c,v 1.108 2001/03/13 01:23:18 angelos Exp $ */ +/* $OpenBSD: ip_ipsp.c,v 1.109 2001/03/15 06:30:59 mickey Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr), + * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Niklas Hallqvist (niklas@appli.se). * @@ -24,7 +24,7 @@ * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or - * modification of this software. + * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to @@ -94,6 +94,10 @@ void tdb_hashstats(void); int ipsp_kern __P((int, char **, int)); u_int8_t get_sa_require __P((struct inpcb *)); void tdb_rehash __P((void)); +void tdb_timeout __P((void *v)); +void tdb_firstuse __P((void *v)); +void tdb_soft_timeout __P((void *v)); +void tdb_soft_firstuse __P((void *v)); extern int ipsec_auth_default_level; extern int ipsec_esp_trans_default_level; @@ -104,9 +108,6 @@ int ipsec_in_use = 0; u_int64_t ipsec_last_added = 0; u_int32_t kernfs_epoch = 0; -struct expclusterlist_head expclusterlist = - TAILQ_HEAD_INITIALIZER(expclusterlist); -struct explist_head explist = TAILQ_HEAD_INITIALIZER(explist); struct ipsec_policy_head ipsec_policy_head = TAILQ_HEAD_INITIALIZER(ipsec_policy_head); struct ipsec_acquire_head ipsec_acquire_head = @@ -119,7 +120,7 @@ struct ipsec_acquire_head ipsec_acquire_head = struct xformsw xformsw[] = { { XF_IP4, 0, "IPv4 Simple Encapsulation", ipe4_attach, ipe4_init, ipe4_zeroize, - (int (*)(struct mbuf *, struct tdb *, int, int))ipe4_input, + (int (*)(struct mbuf *, struct tdb *, int, int))ipe4_input, ipip_output, }, { XF_AH, XFT_AUTH, "IPsec AH", ah_attach, ah_init, ah_zeroize, @@ -137,7 +138,7 @@ struct xformsw xformsw[] = { struct xformsw *xformswNXFORMSW = &xformsw[sizeof(xformsw)/sizeof(xformsw[0])]; -unsigned char ipseczeroes[IPSEC_ZEROES_SIZE]; /* zeroes! */ +unsigned char ipseczeroes[IPSEC_ZEROES_SIZE]; /* zeroes! */ #define TDB_HASHSIZE_INIT 32 static struct tdb **tdbh = NULL; @@ -222,7 +223,7 @@ reserve_spi(u_int32_t sspi, u_int32_t tspi, union sockaddr_union *src, get_random_bytes((void *) &spi, sizeof(spi)); spi = sspi + (spi % (tspi - sspi)); } - + /* Don't allocate reserved SPIs. */ if (spi >= SPI_RESERVED_MIN && spi <= SPI_RESERVED_MAX) continue; @@ -239,7 +240,7 @@ reserve_spi(u_int32_t sspi, u_int32_t tspi, union sockaddr_union *src, MALLOC(tdbp, struct tdb *, sizeof(struct tdb), M_TDB, M_WAITOK); bzero((caddr_t) tdbp, sizeof(struct tdb)); - + tdbp->tdb_spi = spi; bcopy(&dst->sa, &tdbp->tdb_dst.sa, SA_LEN(&dst->sa)); bcopy(&src->sa, &tdbp->tdb_src.sa, SA_LEN(&src->sa)); @@ -250,12 +251,18 @@ reserve_spi(u_int32_t sspi, u_int32_t tspi, union sockaddr_union *src, tdbp->tdb_epoch = kernfs_epoch - 1; puttdb(tdbp); + /* Initialize timeouts */ + timeout_set(&tdbp->tdb_timer_tmo, tdb_timeout, tdbp); + timeout_set(&tdbp->tdb_first_tmo, tdb_firstuse, tdbp); + timeout_set(&tdbp->tdb_stimer_tmo, tdb_soft_timeout, tdbp); + timeout_set(&tdbp->tdb_sfirst_tmo, tdb_soft_firstuse, tdbp); + /* Setup a "silent" expiration (since TDBF_INVALID's set) */ if (ipsec_keep_invalid > 0) { tdbp->tdb_flags |= TDBF_TIMER; - tdbp->tdb_exp_timeout = time.tv_sec + ipsec_keep_invalid; - tdb_expiration(tdbp, TDBEXP_EARLY | TDBEXP_TIMEOUT); + tdbp->tdb_exp_timeout = ipsec_keep_invalid; + timeout_add(&tdbp->tdb_timer_tmo, hz * ipsec_keep_invalid); } return spi; @@ -266,7 +273,7 @@ reserve_spi(u_int32_t sspi, u_int32_t tspi, union sockaddr_union *src, } /* - * An IPSP SAID is really the concatenation of the SPI found in the + * An IPSP SAID is really the concatenation of the SPI found in the * packet, the destination address of the packet and the IPsec protocol. * When we receive an IPSP packet, we need to look up its tunnel descriptor * block, based on the SPI in the packet and the destination address (which @@ -286,7 +293,7 @@ gettdb(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto) hashval = tdb_hash(spi, dst, proto); for (tdbp = tdbh[hashval]; tdbp != NULL; tdbp = tdbp->tdb_hnext) - if ((tdbp->tdb_spi == spi) && + if ((tdbp->tdb_spi == spi) && !bcmp(&tdbp->tdb_dst, dst, SA_LEN(&dst->sa)) && (tdbp->tdb_sproto == proto)) break; @@ -438,246 +445,58 @@ tdb_walk(int (*walker)(struct tdb *, void *, int), void *arg) * Called at splsoftclock(). */ void -handle_expirations(void *arg) +tdb_timeout(void *v) { - struct tdb *tdb; - - for (tdb = TAILQ_FIRST(&explist); - tdb && tdb->tdb_timeout <= time.tv_sec; - tdb = TAILQ_FIRST(&explist)) - { - /* Hard expirations first */ - if ((tdb->tdb_flags & TDBF_TIMER) && - (tdb->tdb_exp_timeout <= time.tv_sec)) - { - /* If it's an "invalid" TDB do a silent expiration. */ - if (!(tdb->tdb_flags & TDBF_INVALID)) - pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); - continue; - } - else - if ((tdb->tdb_flags & TDBF_FIRSTUSE) && - (tdb->tdb_first_use + tdb->tdb_exp_first_use <= time.tv_sec)) - { - /* If the TDB hasn't been used, don't renew it */ - if (tdb->tdb_first_use != 0) - pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); - tdb_delete(tdb, 0); - continue; - } + struct tdb *tdb = v; - /* Soft expirations */ - if ((tdb->tdb_flags & TDBF_SOFT_TIMER) && - (tdb->tdb_soft_timeout <= time.tv_sec)) - { - pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); - tdb->tdb_flags &= ~TDBF_SOFT_TIMER; - tdb_expiration(tdb, TDBEXP_EARLY); - } - else - if ((tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) && - (tdb->tdb_first_use + tdb->tdb_soft_first_use <= - time.tv_sec)) - { - /* If the TDB hasn't been used, don't renew it */ - if (tdb->tdb_first_use != 0) - pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); - tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE; - tdb_expiration(tdb, TDBEXP_EARLY); - } - } + if (!(tdb->tdb_flags & TDBF_TIMER)) + return; - /* If any tdb is left on the expiration queue, set the timer. */ - if (tdb) - timeout(handle_expirations, (void *) NULL, - hz * (tdb->tdb_timeout - time.tv_sec)); + /* If it's an "invalid" TDB do a silent expiration. */ + if (!(tdb->tdb_flags & TDBF_INVALID)) + pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); + tdb_delete(tdb); } -/* - * Ensure the tdb is in the right place in the expiration list. - */ void -tdb_expiration(struct tdb *tdb, int flags) +tdb_firstuse(void *v) { - struct tdb *t, *former_expirer, *next_expirer; - int will_be_first, sole_reason, early; - u_int64_t next_timeout = 0; - int s = spltdb(); - - /* Find the earliest expiration. */ - if ((tdb->tdb_flags & TDBF_FIRSTUSE) && tdb->tdb_first_use != 0 && - (next_timeout == 0 || - next_timeout > tdb->tdb_first_use + tdb->tdb_exp_first_use)) - next_timeout = tdb->tdb_first_use + tdb->tdb_exp_first_use; - if ((tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) && tdb->tdb_first_use != 0 && - (next_timeout == 0 || - next_timeout > tdb->tdb_first_use + tdb->tdb_soft_first_use)) - next_timeout = tdb->tdb_first_use + tdb->tdb_soft_first_use; - if ((tdb->tdb_flags & TDBF_TIMER) && - (next_timeout == 0 || next_timeout > tdb->tdb_exp_timeout)) - next_timeout = tdb->tdb_exp_timeout; - if ((tdb->tdb_flags & TDBF_SOFT_TIMER) && - (next_timeout == 0 || next_timeout > tdb->tdb_soft_timeout)) - next_timeout = tdb->tdb_soft_timeout; - - /* No change? */ - if (next_timeout == tdb->tdb_timeout) - { - splx(s); - return; - } + struct tdb *tdb = v; - /* - * Find out some useful facts: Will our tdb be first to expire? - * Was our tdb the sole reason for the old timeout? - */ - former_expirer = TAILQ_FIRST(&expclusterlist); - next_expirer = TAILQ_NEXT(tdb, tdb_explink); - will_be_first = (next_timeout != 0 && - (former_expirer == NULL || - next_timeout < former_expirer->tdb_timeout)); - sole_reason = (tdb == former_expirer && - (next_expirer == NULL || - tdb->tdb_timeout != next_expirer->tdb_timeout)); + if (!(tdb->tdb_flags & TDBF_SOFT_FIRSTUSE)) + return; - /* - * We need to untimeout if either: - * - there is an expiration pending and the new timeout is earlier than - * what already exists or - * - the existing first expiration is due to our old timeout value solely - */ - if ((former_expirer != NULL && will_be_first) || sole_reason) - untimeout(handle_expirations, (void *) NULL); - - /* - * We need to timeout if we've been asked to and if either - * - our tdb has a timeout and no former expiration exist or - * - the new timeout is earlier than what already exists or - * - the existing first expiration is due to our old timeout value solely - * and another expiration is in the pipe. - */ - if ((flags & TDBEXP_TIMEOUT) && - (will_be_first || (sole_reason && next_expirer != NULL))) - timeout(handle_expirations, (void *) NULL, - hz * ((will_be_first ? next_timeout : - next_expirer->tdb_timeout) - time.tv_sec)); - - /* Our old position, if any, is not relevant anymore. */ - if (tdb->tdb_timeout != 0) - { - if (tdb->tdb_expnext.tqe_prev != NULL) - { - if (next_expirer && tdb->tdb_timeout == next_expirer->tdb_timeout) - TAILQ_INSERT_BEFORE(tdb, next_expirer, tdb_expnext); - TAILQ_REMOVE(&expclusterlist, tdb, tdb_expnext); - tdb->tdb_expnext.tqe_prev = NULL; - } - - TAILQ_REMOVE(&explist, tdb, tdb_explink); - } + /* If the TDB hasn't been used, don't renew it */ + if (tdb->tdb_first_use != 0) + pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); + tdb_delete(tdb); +} - tdb->tdb_timeout = next_timeout; +void +tdb_soft_timeout(void *v) +{ + struct tdb *tdb = v; - if (next_timeout == 0) - { - splx(s); - return; - } + if (!(tdb->tdb_flags & TDBF_SOFT_TIMER)) + return; - /* - * Search front-to-back if we believe we will end up early, otherwise - * back-to-front. - */ - early = will_be_first || (flags & TDBEXP_EARLY); - for (t = (early ? TAILQ_FIRST(&expclusterlist) : - TAILQ_LAST(&expclusterlist, expclusterlist_head)); - t != NULL && (early ? (t->tdb_timeout <= next_timeout) : - (t->tdb_timeout > next_timeout)); - t = (early ? TAILQ_NEXT(t, tdb_expnext) : - TAILQ_PREV(t, expclusterlist_head, tdb_expnext))) - ; - if (t == (early ? TAILQ_FIRST(&expclusterlist) : NULL)) - { - /* We are to become the first expiration. */ - TAILQ_INSERT_HEAD(&expclusterlist, tdb, tdb_expnext); - TAILQ_INSERT_HEAD(&explist, tdb, tdb_explink); - } - else - { - if (early) - t = (t ? TAILQ_PREV(t, expclusterlist_head, tdb_expnext) : - TAILQ_LAST(&expclusterlist, expclusterlist_head)); - if (TAILQ_NEXT(t, tdb_expnext)) - TAILQ_INSERT_BEFORE(TAILQ_NEXT(t, tdb_expnext), tdb, tdb_explink); - else - TAILQ_INSERT_TAIL(&explist, tdb, tdb_explink); - if (t->tdb_timeout < next_timeout) - TAILQ_INSERT_AFTER(&expclusterlist, t, tdb, tdb_expnext); - } + /* Soft expirations */ + pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); + tdb->tdb_flags &= ~TDBF_SOFT_TIMER; +} -#ifdef DIAGNOSTIC - /* - * Check various invariants. - */ - if (tdb->tdb_expnext.tqe_prev != NULL) - { - t = TAILQ_FIRST(&expclusterlist); - if (t != tdb && t->tdb_timeout >= tdb->tdb_timeout) - panic("tdb_expiration: " - "expclusterlist first link out of order (%p, %p)", - tdb, t); - t = TAILQ_PREV(tdb, expclusterlist_head, tdb_expnext); - if (t != NULL && t->tdb_timeout >= tdb->tdb_timeout) - panic("tdb_expiration: " - "expclusterlist prev link out of order (%p, %p)", - tdb, t); - else if (t == NULL && tdb != TAILQ_FIRST(&expclusterlist)) - panic("tdb_expiration: " - "expclusterlist first link out of order (%p, %p)", - tdb, TAILQ_FIRST(&expclusterlist)); - t = TAILQ_NEXT(tdb, tdb_expnext); - if (t != NULL && t->tdb_timeout <= tdb->tdb_timeout) - panic("tdb_expiration: " - "expclusterlist next link out of order (%p, %p)", - tdb, t); - else if (t == NULL && - tdb != TAILQ_LAST(&expclusterlist, expclusterlist_head)) - panic("tdb_expiration: " - "expclusterlist last link out of order (%p, %p)", - tdb, TAILQ_LAST(&expclusterlist, expclusterlist_head)); - t = TAILQ_LAST(&expclusterlist, expclusterlist_head); - if (t != tdb && t->tdb_timeout <= tdb->tdb_timeout) - panic("tdb_expiration: " - "expclusterlist last link out of order (%p, %p)", - tdb, t); - } +void +tdb_soft_firstuse(void *v) +{ + struct tdb *tdb = v; - t = TAILQ_FIRST(&explist); - if (t != NULL && t->tdb_timeout > tdb->tdb_timeout) - panic("tdb_expiration: explist first link out of order (%p, %p)", tdb, - t); - - t = TAILQ_PREV(tdb, explist_head, tdb_explink); - if (t != NULL && t->tdb_timeout > tdb->tdb_timeout) - panic("tdb_expiration: explist prev link out of order (%p, %p)", tdb, t); - else if (t == NULL && tdb != TAILQ_FIRST(&explist)) - panic("tdb_expiration: explist first link out of order (%p, %p)", tdb, - TAILQ_FIRST(&explist)); - - t = TAILQ_NEXT(tdb, tdb_explink); - if (t != NULL && t->tdb_timeout < tdb->tdb_timeout) - panic("tdb_expiration: explist next link out of order (%p, %p)", tdb, t); - else if (t == NULL && tdb != TAILQ_LAST(&explist, explist_head)) - panic("tdb_expiration: explist last link out of order (%p, %p)", tdb, - TAILQ_LAST(&explist, explist_head)); - - t = TAILQ_LAST(&explist, explist_head); - if (t != tdb && t->tdb_timeout < tdb->tdb_timeout) - panic("tdb_expiration: explist last link out of order (%p, %p)", tdb, t); -#endif + if (!(tdb->tdb_flags & TDBF_SOFT_FIRSTUSE)) + return; - splx(s); + /* If the TDB hasn't been used, don't renew it */ + if (tdb->tdb_first_use != 0) + pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); + tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE; } /* @@ -767,7 +586,7 @@ puttdb(struct tdb *tdbp) } hashval = tdb_hash(tdbp->tdb_spi, &tdbp->tdb_dst, tdbp->tdb_sproto); - + /* * Rehash if this tdb would cause a bucket to have more than two items * and if the number of tdbs exceed 10% of the bucket count. This @@ -804,7 +623,7 @@ puttdb(struct tdb *tdbp) * Caller is responsible to set at least spltdb(). */ void -tdb_delete(struct tdb *tdbp, int expflags) +tdb_delete(struct tdb *tdbp) { struct ipsec_policy *ipo; struct tdb *tdbpp; @@ -891,13 +710,13 @@ tdb_delete(struct tdb *tdbp, int expflags) ipo->ipo_last_searched = 0; /* Force a re-search */ } - /* Remove us from the expiration lists. */ - if (tdbp->tdb_timeout != 0) - { - tdbp->tdb_flags &= ~(TDBF_FIRSTUSE | TDBF_SOFT_FIRSTUSE | TDBF_TIMER | - TDBF_SOFT_TIMER); - tdb_expiration(tdbp, expflags); - } + /* Remove expiration timeouts. */ + tdbp->tdb_flags &= ~(TDBF_FIRSTUSE | TDBF_SOFT_FIRSTUSE | TDBF_TIMER | + TDBF_SOFT_TIMER); + timeout_del(&tdbp->tdb_timer_tmo); + timeout_del(&tdbp->tdb_first_tmo); + timeout_del(&tdbp->tdb_stimer_tmo); + timeout_del(&tdbp->tdb_sfirst_tmo); if (tdbp->tdb_srcid) { @@ -942,6 +761,12 @@ tdb_init(struct tdb *tdbp, u_int16_t alg, struct ipsecinit *ii) tdbp->tdb_established = time.tv_sec; tdbp->tdb_epoch = kernfs_epoch - 1; + /* Initialize timeouts */ + timeout_set(&tdbp->tdb_timer_tmo, tdb_timeout, tdbp); + timeout_set(&tdbp->tdb_first_tmo, tdb_firstuse, tdbp); + timeout_set(&tdbp->tdb_stimer_tmo, tdb_soft_timeout, tdbp); + timeout_set(&tdbp->tdb_sfirst_tmo, tdb_soft_firstuse, tdbp); + /* Init Incoming SA-Binding Queues */ TAILQ_INIT(&tdbp->tdb_inp); @@ -958,7 +783,7 @@ tdb_init(struct tdb *tdbp, u_int16_t alg, struct ipsecinit *ii) return err; } - DPRINTF(("tdb_init(): no alg %d for spi %08x, addr %s, proto %d\n", + DPRINTF(("tdb_init(): no alg %d for spi %08x, addr %s, proto %d\n", alg, ntohl(tdbp->tdb_spi), ipsp_address(tdbp->tdb_dst), tdbp->tdb_sproto)); @@ -988,7 +813,7 @@ ipsp_kern(int off, char **bufp, int len) ipsec_in_use); return l; } - + if (tdbh == NULL) return 0; @@ -1107,7 +932,7 @@ ipsp_kern(int off, char **bufp, int len) l += sprintf(buffer + l, "\tCrypto ID: %qu\n", tdb->tdb_cryptoid); if (tdb->tdb_xform) - l += sprintf(buffer + l, "\txform = <%s>\n", + l += sprintf(buffer + l, "\txform = <%s>\n", tdb->tdb_xform->xf_name); if (tdb->tdb_encalgxform) @@ -1140,24 +965,26 @@ ipsp_kern(int off, char **bufp, int len) l += sprintf(buffer + l, "\t%qu bytes processed by this SA\n", tdb->tdb_cur_bytes); - + l += sprintf(buffer + l, "\tExpirations:\n"); if (tdb->tdb_flags & TDBF_TIMER) l += sprintf(buffer + l, "\t\tHard expiration(1) in %qu seconds\n", - tdb->tdb_exp_timeout - time.tv_sec); - + tdb->tdb_established + tdb->tdb_exp_timeout - + time.tv_sec); + if (tdb->tdb_flags & TDBF_SOFT_TIMER) l += sprintf(buffer + l, "\t\tSoft expiration(1) in %qu seconds\n", - tdb->tdb_soft_timeout - time.tv_sec); - + tdb->tdb_established + tdb->tdb_soft_timeout - + time.tv_sec); + if (tdb->tdb_flags & TDBF_BYTES) l += sprintf(buffer + l, "\t\tHard expiration after %qu bytes\n", tdb->tdb_exp_bytes); - + if (tdb->tdb_flags & TDBF_SOFT_BYTES) l += sprintf(buffer + l, "\t\tSoft expiration after %qu bytes\n", @@ -1167,7 +994,7 @@ ipsp_kern(int off, char **bufp, int len) l += sprintf(buffer + l, "\t\tHard expiration after %u flows\n", tdb->tdb_exp_allocations); - + if (tdb->tdb_flags & TDBF_SOFT_ALLOCATIONS) l += sprintf(buffer + l, "\t\tSoft expiration after %u flows\n", @@ -1224,10 +1051,10 @@ u_int8_t get_sa_require(struct inpcb *inp) { u_int8_t sareq = 0; - + if (inp != NULL) { - sareq |= inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_USE ? + sareq |= inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_USE ? NOTIFY_SATYPE_AUTH : 0; sareq |= inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_USE ? NOTIFY_SATYPE_CONF : 0; @@ -1236,14 +1063,14 @@ get_sa_require(struct inpcb *inp) } else { - sareq |= ipsec_auth_default_level >= IPSEC_LEVEL_USE ? + sareq |= ipsec_auth_default_level >= IPSEC_LEVEL_USE ? NOTIFY_SATYPE_AUTH : 0; - sareq |= ipsec_esp_trans_default_level >= IPSEC_LEVEL_USE ? + sareq |= ipsec_esp_trans_default_level >= IPSEC_LEVEL_USE ? NOTIFY_SATYPE_CONF : 0; - sareq |= ipsec_esp_network_default_level >= IPSEC_LEVEL_USE ? + sareq |= ipsec_esp_network_default_level >= IPSEC_LEVEL_USE ? NOTIFY_SATYPE_TUNNEL : 0; } - + return (sareq); } @@ -1274,7 +1101,7 @@ inet_ntoa4(struct in_addr ina) static char buf[4][4 * sizeof "123" + 4]; unsigned char *ucp = (unsigned char *) &ina; static int i = 3; - + i = (i + 1) % 4; sprintf(buf[i], "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff); diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h index e37f5a8828c..7f834d72728 100644 --- a/sys/netinet/ip_ipsp.h +++ b/sys/netinet/ip_ipsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.h,v 1.79 2001/03/04 20:34:00 angelos Exp $ */ +/* $OpenBSD: ip_ipsp.h,v 1.80 2001/03/15 06:31:00 mickey Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -24,7 +24,7 @@ * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or - * modification of this software. + * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to @@ -46,6 +46,7 @@ #include <sys/types.h> #include <sys/queue.h> +#include <sys/timeout.h> #include <netinet/in.h> union sockaddr_union @@ -144,7 +145,7 @@ struct sockaddr_encap * system is concerned. By using only one bit in the type field * for each type, we sort-of make sure that different types of * encapsulation addresses won't be matched against the wrong type. - * + * */ #define SENT_IP4 0x0001 /* data is two struct in_addr */ @@ -212,7 +213,7 @@ struct ipsec_policy #define NOTIFY_SOFT_EXPIRE 0 /* Soft expiration of SA */ #define NOTIFY_HARD_EXPIRE 1 /* Hard expiration of SA */ #define NOTIFY_REQUEST_SA 2 /* Establish an SA */ - + #define NOTIFY_SATYPE_CONF 1 /* SA should do encryption */ #define NOTIFY_SATYPE_AUTH 2 /* SA should do authentication */ #define NOTIFY_SATYPE_TUNNEL 4 /* SA should use tunneling */ @@ -266,11 +267,13 @@ struct tdb /* tunnel descriptor block */ u_int32_t tdb_flags; /* Flags related to this TDB */ - TAILQ_ENTRY(tdb) tdb_expnext; /* Expiration cluster list link */ - TAILQ_ENTRY(tdb) tdb_explink; /* Expiration ordered list link */ + struct timeout tdb_timer_tmo; + struct timeout tdb_first_tmo; + struct timeout tdb_stimer_tmo; + struct timeout tdb_sfirst_tmo; u_int32_t tdb_exp_allocations; /* Expire after so many flows */ - u_int32_t tdb_soft_allocations; /* Expiration warning */ + u_int32_t tdb_soft_allocations; /* Expiration warning */ u_int32_t tdb_cur_allocations; /* Total number of allocations */ u_int64_t tdb_exp_bytes; /* Expire after so many bytes passed */ @@ -280,7 +283,6 @@ struct tdb /* tunnel descriptor block */ u_int64_t tdb_exp_timeout; /* When does the SPI expire */ u_int64_t tdb_soft_timeout; /* Send a soft-expire warning */ u_int64_t tdb_established; /* When was the SPI established */ - u_int64_t tdb_timeout; /* Next absolute expiration time. */ u_int64_t tdb_first_use; /* When was it first used */ u_int64_t tdb_soft_first_use; /* Soft warning */ @@ -350,7 +352,7 @@ struct ipsecinit u_int8_t ii_encalg; u_int8_t ii_authalg; }; - + struct xformsw { u_short xf_type; /* Unique ID of xform */ @@ -383,7 +385,7 @@ htonq(u_int64_t q) register u_int32_t u, l; u = q >> 32; l = (u_int32_t) q; - + return htonl(u) | ((u_int64_t)htonl(l) << 32); } @@ -396,7 +398,7 @@ htonq(u_int64_t q) #else #error "Please fix <machine/endian.h>" -#endif +#endif #ifdef _KERNEL @@ -437,8 +439,6 @@ extern struct auth_hash auth_hash_hmac_md5_96; extern struct auth_hash auth_hash_hmac_sha1_96; extern struct auth_hash auth_hash_hmac_ripemd_160_96; -extern TAILQ_HEAD(expclusterlist_head, tdb) expclusterlist; -extern TAILQ_HEAD(explist_head, tdb) explist; extern TAILQ_HEAD(ipsec_policy_head, ipsec_policy) ipsec_policy_head; extern TAILQ_HEAD(ipsec_acquire_head, ipsec_acquire) ipsec_acquire_head; @@ -478,14 +478,9 @@ extern struct tdb *gettdbbyaddr(union sockaddr_union *, u_int8_t, extern struct tdb *gettdbbysrc(union sockaddr_union *, u_int8_t, struct mbuf *, int); extern void puttdb(struct tdb *); -extern void tdb_delete(struct tdb *, int); +extern void tdb_delete(struct tdb *); extern int tdb_init(struct tdb *, u_int16_t, struct ipsecinit *); -extern void tdb_expiration(struct tdb *, int); -/* Flag values for the last argument of tdb_expiration(). */ -#define TDBEXP_EARLY 1 /* The tdb is likely to end up early. */ -#define TDBEXP_TIMEOUT 2 /* Maintain expiration timeout. */ extern int tdb_walk(int (*)(struct tdb *, void *, int), void *); -extern void handle_expirations(void *); /* XF_IP4 */ extern int ipe4_attach(void); diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c index de37437259d..65dd05c11ff 100644 --- a/sys/netinet/ipsec_input.c +++ b/sys/netinet/ipsec_input.c @@ -1,11 +1,11 @@ -/* $OpenBSD: ipsec_input.c,v 1.32 2000/09/19 03:20:59 angelos Exp $ */ +/* $OpenBSD: ipsec_input.c,v 1.33 2001/03/15 06:31:00 mickey Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and + * Angelos D. Keromytis (kermit@csd.uch.gr) and * Niels Provos (provos@physnet.uni-hamburg.de). * - * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, @@ -18,11 +18,11 @@ * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. - * + * * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or - * modification of this software. + * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to @@ -193,7 +193,7 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto) IPSEC_ISTAT(espstat.esps_notdb, ahstat.ahs_notdb); return ENOENT; } - + if (tdbp->tdb_flags & TDBF_INVALID) { splx(s); @@ -228,7 +228,10 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto) if (tdbp->tdb_first_use == 0) { tdbp->tdb_first_use = time.tv_sec; - tdb_expiration(tdbp, TDBEXP_TIMEOUT); + if (tdbp->tdb_flags & TDBF_FIRSTUSE) + timeout_add(&tdbp->tdb_first_tmo, hz * tdbp->tdb_exp_first_use); + if (tdbp->tdb_flags & TDBF_SOFT_FIRSTUSE) + timeout_add(&tdbp->tdb_sfirst_tmo, hz * tdbp->tdb_soft_first_use); } /* @@ -348,7 +351,7 @@ ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff) } #endif /* INET6 */ - /* + /* * Check that the source address is an expected one, if we know what * it's supposed to be. This avoids source address spoofing. */ @@ -432,7 +435,7 @@ ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff) } } - /* + /* * Check that the source address is an expected one, if we know what * it's supposed to be. This avoids source address spoofing. */ @@ -490,7 +493,7 @@ ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff) bpfif = (struct ifnet *) tdbp->tdb_interface; else bpfif = &encif[0].sc_if; - if (bpfif->if_bpf) + if (bpfif->if_bpf) { /* * We need to prepend the address family as @@ -509,7 +512,7 @@ ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff) m1.m_next = m; m1.m_len = ENC_HDRLEN; m1.m_data = (char *) &hdr; - + bpf_mtap(bpfif->if_bpf, &m1); } #endif @@ -621,7 +624,7 @@ ah4_input_cb(struct mbuf *m, ...) struct ifqueue *ifq = &ipintrq; /* - * Interface pointer is already in first mbuf; chop off the + * Interface pointer is already in first mbuf; chop off the * `outer' header and reschedule. */ @@ -664,7 +667,7 @@ esp4_input_cb(struct mbuf *m, ...) struct ifqueue *ifq = &ipintrq; /* - * Interface pointer is already in first mbuf; chop off the + * Interface pointer is already in first mbuf; chop off the * `outer' header and reschedule. */ if (IF_QFULL(ifq)) diff --git a/sys/netinet/ipsec_output.c b/sys/netinet/ipsec_output.c index 3bc9239757c..724a7b7ded5 100644 --- a/sys/netinet/ipsec_output.c +++ b/sys/netinet/ipsec_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsec_output.c,v 1.2 2000/09/19 08:38:59 angelos Exp $ */ +/* $OpenBSD: ipsec_output.c,v 1.3 2001/03/15 06:31:00 mickey Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) @@ -8,7 +8,7 @@ * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or - * modification of this software. + * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to @@ -127,7 +127,10 @@ ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int af, int tunalready) if (tdb->tdb_first_use == 0) { tdb->tdb_first_use = time.tv_sec; - tdb_expiration(tdb, TDBEXP_TIMEOUT); + if (tdb->tdb_flags & TDBF_FIRSTUSE) + timeout_add(&tdb->tdb_first_tmo, hz * tdb->tdb_exp_first_use); + if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) + timeout_add(&tdb->tdb_sfirst_tmo, hz * tdb->tdb_soft_first_use); } /* |