From owner-svn-src-projects@freebsd.org Wed Nov 23 12:20:39 2016 Return-Path: Delivered-To: svn-src-projects@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5F745C4EB22 for ; Wed, 23 Nov 2016 12:20:39 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2298AA69; Wed, 23 Nov 2016 12:20:39 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uANCKcaH014713; Wed, 23 Nov 2016 12:20:38 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uANCKcrZ014712; Wed, 23 Nov 2016 12:20:38 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201611231220.uANCKcrZ014712@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Wed, 23 Nov 2016 12:20:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r309056 - projects/ipsec/sys/netipsec X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Nov 2016 12:20:39 -0000 Author: ae Date: Wed Nov 23 12:20:38 2016 New Revision: 309056 URL: https://svnweb.freebsd.org/changeset/base/309056 Log: Update inbound IPsec packet processing for IPv4/IPv6. Use new xform_history structure to save information about used SA. Keep reference to SA until xform callback is not finished. If xform_input fails to queue crypto request, release reference. Otherwise xform callback will release it after sending mbuf to netisr. Modified: projects/ipsec/sys/netipsec/ipsec_input.c Modified: projects/ipsec/sys/netipsec/ipsec_input.c ============================================================================== --- projects/ipsec/sys/netipsec/ipsec_input.c Wed Nov 23 11:56:22 2016 (r309055) +++ projects/ipsec/sys/netipsec/ipsec_input.c Wed Nov 23 12:20:38 2016 (r309056) @@ -209,7 +209,7 @@ ipsec_common_input(struct mbuf *m, int s } /* NB: only pass dst since key_allocsa follows RFC2401 */ - sav = KEY_ALLOCSA(&dst_address, sproto, spi); + sav = key_allocsa(&dst_address, sproto, spi); if (sav == NULL) { DPRINTF(("%s: no key association found for SA %s/%08lx/%u\n", __func__, ipsec_address(&dst_address, buf, sizeof(buf)), @@ -234,8 +234,9 @@ ipsec_common_input(struct mbuf *m, int s * everything else. */ error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff); - KEY_FREESAV(&sav); - return error; + if (error != 0) + key_freesav(&sav); + return (error); } #ifdef INET @@ -309,21 +310,19 @@ int ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int protoff) { - char buf[INET6_ADDRSTRLEN]; + char buf[IPSEC_ADDRSTRLEN]; struct ipsec_ctx_data ctx; - int prot, af, sproto, isr_prot; - struct ip *ip; - struct m_tag *mtag; - struct tdb_ident *tdbi; + struct xform_history *xh; struct secasindex *saidx; - int error; + struct m_tag *mtag; + struct ip *ip; + int error, prot, af, sproto, isr_prot; #ifdef INET6 #ifdef notyet - char ip6buf[INET6_ADDRSTRLEN]; + char ip6buf[IPSEC_ADDRSTRLEN]; #endif #endif - IPSEC_ASSERT(m != NULL, ("null mbuf")); IPSEC_ASSERT(sav != NULL, ("null SA")); IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); saidx = &sav->sah->saidx; @@ -360,7 +359,7 @@ ipsec4_common_input_cb(struct mbuf *m, s IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET, IPSEC_ENC_BEFORE); if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0) goto bad; - ip = mtod(m, struct ip *); + ip = mtod(m, struct ip *); /* update pointer */ /* IP-in-IP encapsulation */ if (prot == IPPROTO_IPIP && @@ -445,8 +444,8 @@ ipsec4_common_input_cb(struct mbuf *m, s /* * When mode is wildcard, inner protocol is IPv6 and * we have no INET6 support - drop this packet a bit later. - * In other cases we assume transport mode and outer - * header was already stripped in xform_xxx_cb. + * In other cases we assume transport mode. Set prot to + * correctly choose netisr. */ prot = IPPROTO_IPIP; } @@ -457,7 +456,7 @@ ipsec4_common_input_cb(struct mbuf *m, s */ if (sproto != IPPROTO_IPCOMP) { mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, - sizeof(struct tdb_ident), M_NOWAIT); + sizeof(struct xform_history), M_NOWAIT); if (mtag == NULL) { DPRINTF(("%s: failed to get tag\n", __func__)); IPSEC_ISTAT(sproto, hdrops); @@ -465,14 +464,11 @@ ipsec4_common_input_cb(struct mbuf *m, s goto bad; } - tdbi = (struct tdb_ident *)(mtag + 1); - bcopy(&saidx->dst, &tdbi->dst, saidx->dst.sa.sa_len); - tdbi->proto = sproto; - tdbi->spi = sav->spi; - /* Cache those two for enc(4) in xform_ipip. */ - tdbi->alg_auth = sav->alg_auth; - tdbi->alg_enc = sav->alg_enc; - + xh = (struct xform_history *)(mtag + 1); + bcopy(&saidx->dst, &xh->dst, saidx->dst.sa.sa_len); + xh->spi = sav->spi; + xh->proto = sproto; + xh->mode = saidx->mode; m_tag_prepend(m, mtag); } @@ -509,17 +505,20 @@ ipsec4_common_input_cb(struct mbuf *m, s IPSEC_INIT_CTX(&ctx, &m, sav, af, IPSEC_ENC_AFTER); if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0) goto bad; + error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m); + key_freesav(&sav); if (error) { IPSEC_ISTAT(sproto, qfull); DPRINTF(("%s: queue full; proto %u packet dropped\n", __func__, sproto)); - return error; } - return 0; + return (error); bad: - m_freem(m); - return error; + key_freesav(&sav); + if (m != NULL) + m_freem(m); + return (error); } void @@ -582,21 +581,20 @@ int ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int protoff) { - char buf[INET6_ADDRSTRLEN]; + char buf[IPSEC_ADDRSTRLEN]; struct ipsec_ctx_data ctx; - int prot, af, sproto; + struct xform_history *xh; + struct secasindex *saidx; struct ip6_hdr *ip6; struct m_tag *mtag; - struct tdb_ident *tdbi; - struct secasindex *saidx; + int prot, af, sproto; int nxt, isr_prot; - u_int8_t nxt8; int error, nest; + uint8_t nxt8; #ifdef notyet - char ip6buf[INET6_ADDRSTRLEN]; + char ip6buf[IPSEC_ADDRSTRLEN]; #endif - IPSEC_ASSERT(m != NULL, ("null mbuf")); IPSEC_ASSERT(sav != NULL, ("null SA")); IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); saidx = &sav->sah->saidx; @@ -620,12 +618,13 @@ ipsec6_common_input_cb(struct mbuf *m, s goto bad; } - ip6 = mtod(m, struct ip6_hdr *); - ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); - IPSEC_INIT_CTX(&ctx, &m, sav, af, IPSEC_ENC_BEFORE); if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0) goto bad; + + ip6 = mtod(m, struct ip6_hdr *); + ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); + /* Save protocol */ m_copydata(m, protoff, 1, &nxt8); prot = nxt8; @@ -715,7 +714,7 @@ ipsec6_common_input_cb(struct mbuf *m, s */ if (sproto != IPPROTO_IPCOMP) { mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, - sizeof(struct tdb_ident), M_NOWAIT); + sizeof(struct xform_history), M_NOWAIT); if (mtag == NULL) { DPRINTF(("%s: failed to get tag\n", __func__)); IPSEC_ISTAT(sproto, hdrops); @@ -723,20 +722,16 @@ ipsec6_common_input_cb(struct mbuf *m, s goto bad; } - tdbi = (struct tdb_ident *)(mtag + 1); - bcopy(&saidx->dst, &tdbi->dst, sizeof(union sockaddr_union)); - tdbi->proto = sproto; - tdbi->spi = sav->spi; - /* Cache those two for enc(4) in xform_ipip. */ - tdbi->alg_auth = sav->alg_auth; - tdbi->alg_enc = sav->alg_enc; - + xh = (struct xform_history *)(mtag + 1); + bcopy(&saidx->dst, &xh->dst, saidx->dst.sa.sa_len); + xh->spi = sav->spi; + xh->proto = sproto; + xh->mode = saidx->mode; m_tag_prepend(m, mtag); } key_sa_recordxfer(sav, m); - #ifdef INET if (prot == IPPROTO_IPIP) af = AF_INET; @@ -768,6 +763,7 @@ ipsec6_common_input_cb(struct mbuf *m, s goto bad; } error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m); + key_freesav(&sav); if (error) { IPSEC_ISTAT(sproto, qfull); DPRINTF(("%s: queue full; proto %u packet dropped\n", @@ -810,13 +806,14 @@ ipsec6_common_input_cb(struct mbuf *m, s } nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt); } - return 0; + key_freesav(&sav); + return (0); bad: + key_freesav(&sav); if (m) m_freem(m); - return error; + return (error); } - void esp6_ctlinput(int cmd, struct sockaddr *sa, void *d) { @@ -884,11 +881,11 @@ esp6_ctlinput(int cmd, struct sockaddr * * Check to see if we have a valid SA corresponding to * the address in the ICMP message payload. */ - sav = KEY_ALLOCSA((union sockaddr_union *)sa, + sav = key_allocsa((union sockaddr_union *)sa, IPPROTO_ESP, spi); valid = (sav != NULL); if (sav) - KEY_FREESAV(&sav); + key_freesav(&sav); /* XXX Further validation? */