Changeset View
Changeset View
Standalone View
Standalone View
sys/netipsec/key.c
| Show First 20 Lines • Show All 1,362 Lines • ▼ Show 20 Lines | key_freesav(struct secasvar **psav) | ||||
| *psav = NULL; | *psav = NULL; | ||||
| key_delsav(sav); | key_delsav(sav); | ||||
| } | } | ||||
| /* | /* | ||||
| * Unlink SA from SAH and SPI hash under SAHTREE_WLOCK. | * Unlink SA from SAH and SPI hash under SAHTREE_WLOCK. | ||||
| * Expect that SA has extra reference due to lookup. | * Expect that SA has extra reference due to lookup. | ||||
| * Release this references, also release SAH reference after unlink. | * Release this references, also release SAH reference after unlink. | ||||
ae: The comment become stale. | |||||
| */ | */ | ||||
| static void | static void | ||||
| key_unlinksav(struct secasvar *sav) | key_unlinksav(struct secasvar *sav) | ||||
| { | { | ||||
| struct secashead *sah; | |||||
| KEYDBG(KEY_STAMP, | KEYDBG(KEY_STAMP, | ||||
| printf("%s: SA(%p)\n", __func__, sav)); | printf("%s: SA(%p)\n", __func__, sav)); | ||||
| CURVNET_ASSERT_SET(); | CURVNET_ASSERT_SET(); | ||||
| SAHTREE_UNLOCK_ASSERT(); | SAHTREE_UNLOCK_ASSERT(); | ||||
| SAHTREE_WLOCK(); | SAHTREE_WLOCK(); | ||||
| if (sav->state == SADB_SASTATE_DEAD) { | if (sav->state == SADB_SASTATE_DEAD) { | ||||
| /* SA is already unlinked */ | /* SA is already unlinked */ | ||||
| SAHTREE_WUNLOCK(); | SAHTREE_WUNLOCK(); | ||||
| return; | return; | ||||
| } | } | ||||
| /* Unlink from SAH */ | /* Unlink from SAH */ | ||||
| if (sav->state == SADB_SASTATE_LARVAL) | if (sav->state == SADB_SASTATE_LARVAL) | ||||
| TAILQ_REMOVE(&sav->sah->savtree_larval, sav, chain); | TAILQ_REMOVE(&sav->sah->savtree_larval, sav, chain); | ||||
| else | else | ||||
| TAILQ_REMOVE(&sav->sah->savtree_alive, sav, chain); | TAILQ_REMOVE(&sav->sah->savtree_alive, sav, chain); | ||||
| /* Unlink from SPI hash */ | /* Unlink from SPI hash */ | ||||
| LIST_REMOVE(sav, spihash); | LIST_REMOVE(sav, spihash); | ||||
| sav->state = SADB_SASTATE_DEAD; | sav->state = SADB_SASTATE_DEAD; | ||||
| sah = sav->sah; | |||||
| SAHTREE_WUNLOCK(); | SAHTREE_WUNLOCK(); | ||||
| key_freesav(&sav); | key_freesav(&sav); | ||||
| /* Since we are unlinked, release reference to SAH */ | |||||
| key_freesah(&sah); | |||||
| } | } | ||||
| /* %%% SPD management */ | /* %%% SPD management */ | ||||
| /* | /* | ||||
| * search SPD | * search SPD | ||||
| * OUT: NULL : not found | * OUT: NULL : not found | ||||
| * others : found, pointer to a SP. | * others : found, pointer to a SP. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 1,715 Lines • ▼ Show 20 Lines | |||||
| key_delsav(struct secasvar *sav) | key_delsav(struct secasvar *sav) | ||||
| { | { | ||||
| IPSEC_ASSERT(sav != NULL, ("null sav")); | IPSEC_ASSERT(sav != NULL, ("null sav")); | ||||
| IPSEC_ASSERT(sav->state == SADB_SASTATE_DEAD, | IPSEC_ASSERT(sav->state == SADB_SASTATE_DEAD, | ||||
| ("attempt to free non DEAD SA %p", sav)); | ("attempt to free non DEAD SA %p", sav)); | ||||
| IPSEC_ASSERT(sav->refcnt == 0, ("reference count %u > 0", | IPSEC_ASSERT(sav->refcnt == 0, ("reference count %u > 0", | ||||
| sav->refcnt)); | sav->refcnt)); | ||||
| key_freesah(&sav->sah); | |||||
| /* | /* | ||||
| * SA must be unlinked from the chain and hashtbl. | * SA must be unlinked from the chain and hashtbl. | ||||
| * If SA was cloned, we leave all fields untouched, | * If SA was cloned, we leave all fields untouched, | ||||
| * except NAT-T config. | * except NAT-T config. | ||||
| */ | */ | ||||
| key_cleansav(sav); | key_cleansav(sav); | ||||
| if ((sav->flags & SADB_X_EXT_F_CLONED) == 0) { | if ((sav->flags & SADB_X_EXT_F_CLONED) == 0) { | ||||
| rm_destroy(sav->lock); | rm_destroy(sav->lock); | ||||
| ▲ Show 20 Lines • Show All 1,521 Lines • ▼ Show 20 Lines | key_flush_sad(time_t now) | ||||
| } | } | ||||
| SAHTREE_WUNLOCK(); | SAHTREE_WUNLOCK(); | ||||
| /* Send SPDEXPIRE messages */ | /* Send SPDEXPIRE messages */ | ||||
| sav = LIST_FIRST(&hexpireq); | sav = LIST_FIRST(&hexpireq); | ||||
| while (sav != NULL) { | while (sav != NULL) { | ||||
| nextsav = LIST_NEXT(sav, drainq); | nextsav = LIST_NEXT(sav, drainq); | ||||
| key_expire(sav, 1); | key_expire(sav, 1); | ||||
| key_freesah(&sav->sah); /* release reference from SAV */ | |||||
| key_freesav(&sav); /* release extra reference */ | key_freesav(&sav); /* release extra reference */ | ||||
| key_freesav(&sav); /* release last reference */ | key_freesav(&sav); /* release last reference */ | ||||
| sav = nextsav; | sav = nextsav; | ||||
| } | } | ||||
| sav = LIST_FIRST(&sexpireq); | sav = LIST_FIRST(&sexpireq); | ||||
| while (sav != NULL) { | while (sav != NULL) { | ||||
| nextsav = LIST_NEXT(sav, drainq); | nextsav = LIST_NEXT(sav, drainq); | ||||
| key_expire(sav, 0); | key_expire(sav, 0); | ||||
| key_freesav(&sav); /* release extra reference */ | key_freesav(&sav); /* release extra reference */ | ||||
| sav = nextsav; | sav = nextsav; | ||||
| } | } | ||||
| /* Free stale LARVAL SAs */ | /* Free stale LARVAL SAs */ | ||||
| sav = LIST_FIRST(&drainq); | sav = LIST_FIRST(&drainq); | ||||
| while (sav != NULL) { | while (sav != NULL) { | ||||
| nextsav = LIST_NEXT(sav, drainq); | nextsav = LIST_NEXT(sav, drainq); | ||||
| key_freesah(&sav->sah); /* release reference from SAV */ | |||||
| key_freesav(&sav); /* release extra reference */ | key_freesav(&sav); /* release extra reference */ | ||||
| key_freesav(&sav); /* release last reference */ | key_freesav(&sav); /* release last reference */ | ||||
| sav = nextsav; | sav = nextsav; | ||||
| } | } | ||||
| /* Free SAs that were unlinked/changed by someone else */ | /* Free SAs that were unlinked/changed by someone else */ | ||||
| sav = LIST_FIRST(&freeq); | sav = LIST_FIRST(&freeq); | ||||
| while (sav != NULL) { | while (sav != NULL) { | ||||
| nextsav = LIST_NEXT(sav, drainq); | nextsav = LIST_NEXT(sav, drainq); | ||||
| ▲ Show 20 Lines • Show All 511 Lines • ▼ Show 20 Lines | if (sav->sah->saidx.proto != IPPROTO_ESP || | ||||
| SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_TYPE) || | SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_TYPE) || | ||||
| SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_SPORT) || | SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_SPORT) || | ||||
| SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_DPORT)) { | SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_DPORT)) { | ||||
| ipseclog((LOG_DEBUG, | ipseclog((LOG_DEBUG, | ||||
| "%s: invalid message: missing required header.\n", | "%s: invalid message: missing required header.\n", | ||||
| __func__)); | __func__)); | ||||
| return (EINVAL); | return (EINVAL); | ||||
| } | } | ||||
| /* We hold reference to SA, thus SAH will be referenced too. */ | |||||
| sah = sav->sah; | sah = sav->sah; | ||||
| SAH_ADDREF(sah); | |||||
| isnew = 0; | isnew = 0; | ||||
| } | } | ||||
| newsav = malloc(sizeof(struct secasvar), M_IPSEC_SA, | newsav = malloc(sizeof(struct secasvar), M_IPSEC_SA, | ||||
| M_NOWAIT | M_ZERO); | M_NOWAIT | M_ZERO); | ||||
| if (newsav == NULL) { | if (newsav == NULL) { | ||||
| ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); | ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); | ||||
| error = ENOBUFS; | error = ENOBUFS; | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | key_updateaddresses(struct socket *so, struct mbuf *m, | ||||
| if (isnew == 2) { | if (isnew == 2) { | ||||
| TAILQ_INSERT_HEAD(&V_sahtree, sah, chain); | TAILQ_INSERT_HEAD(&V_sahtree, sah, chain); | ||||
| LIST_INSERT_HEAD(SAHADDRHASH_HASH(saidx), sah, addrhash); | LIST_INSERT_HEAD(SAHADDRHASH_HASH(saidx), sah, addrhash); | ||||
| sah->state = SADB_SASTATE_MATURE; | sah->state = SADB_SASTATE_MATURE; | ||||
| SAH_ADDREF(sah); /* newsav references new SAH */ | SAH_ADDREF(sah); /* newsav references new SAH */ | ||||
| } | } | ||||
| /* | /* | ||||
| * isnew == 1 -> @sah was referenced by key_getsah(). | * isnew == 1 -> @sah was referenced by key_getsah(). | ||||
| * isnew == 0 -> we use the same @sah, that was used by @sav, | * isnew == 0 -> we use the same @sah, that was used by @sav, | ||||
aeUnsubmitted Not Done Inline Actionsanother stale comment. ae: another stale comment. | |||||
| * and we use its reference for @newsav. | * and we use its reference for @newsav. | ||||
| */ | */ | ||||
| SECASVAR_WLOCK(sav); | SECASVAR_WLOCK(sav); | ||||
| /* XXX: replace cntr with pointer? */ | /* XXX: replace cntr with pointer? */ | ||||
| newsav->cntr = sav->cntr; | newsav->cntr = sav->cntr; | ||||
| sav->flags |= SADB_X_EXT_F_CLONED; | sav->flags |= SADB_X_EXT_F_CLONED; | ||||
| SECASVAR_WUNLOCK(sav); | SECASVAR_WUNLOCK(sav); | ||||
| Show All 11 Lines | key_updateaddresses(struct socket *so, struct mbuf *m, | ||||
| if (n == NULL) { | if (n == NULL) { | ||||
| ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); | ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); | ||||
| return (ENOBUFS); | return (ENOBUFS); | ||||
| } | } | ||||
| m_freem(m); | m_freem(m); | ||||
| key_sendup_mbuf(so, n, KEY_SENDUP_ALL); | key_sendup_mbuf(so, n, KEY_SENDUP_ALL); | ||||
| return (0); | return (0); | ||||
| fail: | fail: | ||||
| if (isnew != 0) | |||||
| key_freesah(&sah); | key_freesah(&sah); | ||||
| if (newsav != NULL) { | if (newsav != NULL) { | ||||
| if (newsav->natt != NULL) | if (newsav->natt != NULL) | ||||
| free(newsav->natt, M_IPSEC_MISC); | free(newsav->natt, M_IPSEC_MISC); | ||||
| free(newsav, M_IPSEC_SA); | free(newsav, M_IPSEC_SA); | ||||
| } | } | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 799 Lines • ▼ Show 20 Lines | key_delete_all(struct socket *so, struct mbuf *m, | ||||
| SAHTREE_WUNLOCK(); | SAHTREE_WUNLOCK(); | ||||
| /* Now we can release reference for all SAs in drainq */ | /* Now we can release reference for all SAs in drainq */ | ||||
| sav = TAILQ_FIRST(&drainq); | sav = TAILQ_FIRST(&drainq); | ||||
| while (sav != NULL) { | while (sav != NULL) { | ||||
| KEYDBG(KEY_STAMP, | KEYDBG(KEY_STAMP, | ||||
| printf("%s: SA(%p)\n", __func__, sav)); | printf("%s: SA(%p)\n", __func__, sav)); | ||||
| KEYDBG(KEY_DATA, kdebug_secasv(sav)); | KEYDBG(KEY_DATA, kdebug_secasv(sav)); | ||||
| nextsav = TAILQ_NEXT(sav, chain); | nextsav = TAILQ_NEXT(sav, chain); | ||||
| key_freesah(&sav->sah); /* release reference from SAV */ | |||||
| key_freesav(&sav); /* release last reference */ | key_freesav(&sav); /* release last reference */ | ||||
| sav = nextsav; | sav = nextsav; | ||||
| } | } | ||||
| { | { | ||||
| struct mbuf *n; | struct mbuf *n; | ||||
| struct sadb_msg *newmsg; | struct sadb_msg *newmsg; | ||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | key_delete_xform(const struct xformsw *xsp) | ||||
| /* Now we can release reference for all SAs in drainq */ | /* Now we can release reference for all SAs in drainq */ | ||||
| sav = TAILQ_FIRST(&drainq); | sav = TAILQ_FIRST(&drainq); | ||||
| while (sav != NULL) { | while (sav != NULL) { | ||||
| KEYDBG(KEY_STAMP, | KEYDBG(KEY_STAMP, | ||||
| printf("%s: SA(%p)\n", __func__, sav)); | printf("%s: SA(%p)\n", __func__, sav)); | ||||
| KEYDBG(KEY_DATA, kdebug_secasv(sav)); | KEYDBG(KEY_DATA, kdebug_secasv(sav)); | ||||
| nextsav = TAILQ_NEXT(sav, chain); | nextsav = TAILQ_NEXT(sav, chain); | ||||
| key_freesah(&sav->sah); /* release reference from SAV */ | |||||
| key_freesav(&sav); /* release last reference */ | key_freesav(&sav); /* release last reference */ | ||||
| sav = nextsav; | sav = nextsav; | ||||
| } | } | ||||
| } | } | ||||
| /* | /* | ||||
| * SADB_GET processing | * SADB_GET processing | ||||
| * receive | * receive | ||||
| ▲ Show 20 Lines • Show All 1,252 Lines • ▼ Show 20 Lines | key_freesah_flushed(struct secashead_queue *flushq) | ||||
| sah = TAILQ_FIRST(flushq); | sah = TAILQ_FIRST(flushq); | ||||
| while (sah != NULL) { | while (sah != NULL) { | ||||
| sav = TAILQ_FIRST(&sah->savtree_larval); | sav = TAILQ_FIRST(&sah->savtree_larval); | ||||
| while (sav != NULL) { | while (sav != NULL) { | ||||
| nextsav = TAILQ_NEXT(sav, chain); | nextsav = TAILQ_NEXT(sav, chain); | ||||
| TAILQ_REMOVE(&sah->savtree_larval, sav, chain); | TAILQ_REMOVE(&sah->savtree_larval, sav, chain); | ||||
| key_freesav(&sav); /* release last reference */ | key_freesav(&sav); /* release last reference */ | ||||
| key_freesah(&sah); /* release reference from SAV */ | |||||
| sav = nextsav; | sav = nextsav; | ||||
| } | } | ||||
| sav = TAILQ_FIRST(&sah->savtree_alive); | sav = TAILQ_FIRST(&sah->savtree_alive); | ||||
| while (sav != NULL) { | while (sav != NULL) { | ||||
| nextsav = TAILQ_NEXT(sav, chain); | nextsav = TAILQ_NEXT(sav, chain); | ||||
| TAILQ_REMOVE(&sah->savtree_alive, sav, chain); | TAILQ_REMOVE(&sah->savtree_alive, sav, chain); | ||||
| key_freesav(&sav); /* release last reference */ | key_freesav(&sav); /* release last reference */ | ||||
| key_freesah(&sah); /* release reference from SAV */ | |||||
| sav = nextsav; | sav = nextsav; | ||||
| } | } | ||||
| nextsah = TAILQ_NEXT(sah, chain); | nextsah = TAILQ_NEXT(sah, chain); | ||||
| key_freesah(&sah); /* release last reference */ | key_freesah(&sah); /* release last reference */ | ||||
| sah = nextsah; | sah = nextsah; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,159 Lines • Show Last 20 Lines | |||||
The comment become stale.