LCOV - code coverage report
Current view: top level - netinet - ip_ipcomp.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 217 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: ip_ipcomp.c,v 1.66 2018/09/13 12:29:43 mpi Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *   notice, this list of conditions and the following disclaimer.
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *   notice, this list of conditions and the following disclaimer in the
      14             :  *   documentation and/or other materials provided with the distribution.
      15             :  * 3. The name of the author may not be used to endorse or promote products
      16             :  *   derived from this software without specific prior written permission.
      17             :  *
      18             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      19             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      20             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      21             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      22             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      23             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      24             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      25             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      26             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      27             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      28             :  */
      29             : 
      30             : /* IP payload compression protocol (IPComp), see RFC 2393 */
      31             : 
      32             : #include <sys/param.h>
      33             : #include <sys/systm.h>
      34             : #include <sys/mbuf.h>
      35             : #include <sys/socket.h>
      36             : 
      37             : #include <net/if.h>
      38             : #include <net/if_var.h>
      39             : #include <net/bpf.h>
      40             : 
      41             : #include <netinet/in.h>
      42             : #include <netinet/ip.h>
      43             : #include <netinet/ip_var.h>
      44             : 
      45             : #ifdef INET6
      46             : #include <netinet/ip6.h>
      47             : #endif                          /* INET6 */
      48             : 
      49             : #include <netinet/ip_ipsp.h>
      50             : #include <netinet/ip_ipcomp.h>
      51             : #include <net/pfkeyv2.h>
      52             : #include <net/if_enc.h>
      53             : 
      54             : #include <crypto/cryptodev.h>
      55             : #include <crypto/xform.h>
      56             : 
      57             : #include "bpfilter.h"
      58             : 
      59             : #ifdef ENCDEBUG
      60             : #define DPRINTF(x)      if (encdebug) printf x
      61             : #else
      62             : #define DPRINTF(x)
      63             : #endif
      64             : 
      65             : /*
      66             :  * ipcomp_attach() is called from the transformation code
      67             :  */
      68             : int
      69           0 : ipcomp_attach(void)
      70             : {
      71           0 :         return 0;
      72             : }
      73             : 
      74             : /*
      75             :  * ipcomp_init() is called when an CPI is being set up.
      76             :  */
      77             : int
      78           0 : ipcomp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
      79             : {
      80             :         struct comp_algo *tcomp = NULL;
      81           0 :         struct cryptoini cric;
      82             : 
      83           0 :         switch (ii->ii_compalg) {
      84             :         case SADB_X_CALG_DEFLATE:
      85             :                 tcomp = &comp_algo_deflate;
      86           0 :                 break;
      87             :         case SADB_X_CALG_LZS:
      88             :                 tcomp = &comp_algo_lzs;
      89           0 :                 break;
      90             : 
      91             :         default:
      92             :                 DPRINTF(("%s: unsupported compression algorithm %d specified\n",
      93             :                     __func__, ii->ii_compalg));
      94           0 :                 return EINVAL;
      95             :         }
      96             : 
      97           0 :         tdbp->tdb_compalgxform = tcomp;
      98             : 
      99             :         DPRINTF(("%s: initialized TDB with ipcomp algorithm %s\n", __func__,
     100             :             tcomp->name));
     101             : 
     102           0 :         tdbp->tdb_xform = xsp;
     103             : 
     104             :         /* Initialize crypto session */
     105           0 :         memset(&cric, 0, sizeof(cric));
     106           0 :         cric.cri_alg = tdbp->tdb_compalgxform->type;
     107             : 
     108           0 :         return crypto_newsession(&tdbp->tdb_cryptoid, &cric, 0);
     109           0 : }
     110             : 
     111             : /*
     112             :  * ipcomp_zeroize() used when IPCA is deleted
     113             :  */
     114             : int
     115           0 : ipcomp_zeroize(struct tdb *tdbp)
     116             : {
     117             :         int err;
     118             : 
     119           0 :         err = crypto_freesession(tdbp->tdb_cryptoid);
     120           0 :         tdbp->tdb_cryptoid = 0;
     121           0 :         return err;
     122             : }
     123             : 
     124             : /*
     125             :  * ipcomp_input() gets called to uncompress an input packet
     126             :  */
     127             : int
     128           0 : ipcomp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
     129             : {
     130           0 :         struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
     131             :         struct tdb_crypto *tc;
     132             :         int hlen;
     133             : 
     134             :         struct cryptodesc *crdc = NULL;
     135             :         struct cryptop *crp;
     136             : 
     137             :         hlen = IPCOMP_HLENGTH;
     138             : 
     139             :         /* Get crypto descriptors */
     140           0 :         crp = crypto_getreq(1);
     141           0 :         if (crp == NULL) {
     142           0 :                 m_freem(m);
     143             :                 DPRINTF(("%s: failed to acquire crypto descriptors\n", __func__));
     144           0 :                 ipcompstat_inc(ipcomps_crypto);
     145           0 :                 return ENOBUFS;
     146             :         }
     147             :         /* Get IPsec-specific opaque pointer */
     148           0 :         tc = malloc(sizeof(*tc), M_XDATA, M_NOWAIT | M_ZERO);
     149           0 :         if (tc == NULL) {
     150           0 :                 m_freem(m);
     151           0 :                 crypto_freereq(crp);
     152             :                 DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
     153           0 :                 ipcompstat_inc(ipcomps_crypto);
     154           0 :                 return ENOBUFS;
     155             :         }
     156           0 :         crdc = &crp->crp_desc[0];
     157             : 
     158           0 :         crdc->crd_skip = skip + hlen;
     159           0 :         crdc->crd_len = m->m_pkthdr.len - (skip + hlen);
     160           0 :         crdc->crd_inject = skip;
     161             : 
     162             :         /* Decompression operation */
     163           0 :         crdc->crd_alg = ipcompx->type;
     164             : 
     165             :         /* Crypto operation descriptor */
     166           0 :         crp->crp_ilen = m->m_pkthdr.len - (skip + hlen);
     167           0 :         crp->crp_flags = CRYPTO_F_IMBUF;
     168           0 :         crp->crp_buf = (caddr_t)m;
     169           0 :         crp->crp_callback = ipsec_input_cb;
     170           0 :         crp->crp_sid = tdb->tdb_cryptoid;
     171           0 :         crp->crp_opaque = (caddr_t)tc;
     172             : 
     173             :         /* These are passed as-is to the callback */
     174           0 :         tc->tc_skip = skip;
     175           0 :         tc->tc_protoff = protoff;
     176           0 :         tc->tc_spi = tdb->tdb_spi;
     177           0 :         tc->tc_proto = IPPROTO_IPCOMP;
     178           0 :         tc->tc_rdomain = tdb->tdb_rdomain;
     179           0 :         tc->tc_dst = tdb->tdb_dst;
     180             : 
     181           0 :         return crypto_dispatch(crp);
     182           0 : }
     183             : 
     184             : int
     185           0 : ipcomp_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int clen)
     186             : {
     187           0 :         int skip, protoff, roff, hlen = IPCOMP_HLENGTH;
     188           0 :         u_int8_t nproto;
     189             :         u_int64_t ibytes;
     190             :         struct mbuf *m1, *mo;
     191             :         struct ipcomp  *ipcomp;
     192             :         caddr_t addr;
     193             : #ifdef ENCDEBUG
     194             :         char buf[INET6_ADDRSTRLEN];
     195             : #endif
     196             : 
     197           0 :         NET_ASSERT_LOCKED();
     198             : 
     199           0 :         skip = tc->tc_skip;
     200           0 :         protoff = tc->tc_protoff;
     201             : 
     202             :         /* update the counters */
     203           0 :         ibytes = m->m_pkthdr.len - (skip + hlen);
     204           0 :         tdb->tdb_cur_bytes += ibytes;
     205           0 :         tdb->tdb_ibytes += ibytes;
     206           0 :         ipcompstat_add(ipcomps_ibytes, ibytes);
     207             : 
     208             :         /* Hard expiration */
     209           0 :         if ((tdb->tdb_flags & TDBF_BYTES) &&
     210           0 :             (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
     211           0 :                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
     212           0 :                 tdb_delete(tdb);
     213           0 :                 goto baddone;
     214             :         }
     215             :         /* Notify on soft expiration */
     216           0 :         if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
     217           0 :             (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
     218           0 :                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
     219           0 :                 tdb->tdb_flags &= ~TDBF_SOFT_BYTES;      /* Turn off checking */
     220           0 :         }
     221             : 
     222             :         /* In case it's not done already, adjust the size of the mbuf chain */
     223           0 :         m->m_pkthdr.len = clen + hlen + skip;
     224             : 
     225           0 :         if ((m->m_len < skip + hlen) && (m = m_pullup(m, skip + hlen)) == 0) {
     226           0 :                 ipcompstat_inc(ipcomps_hdrops);
     227           0 :                 goto baddone;
     228             :         }
     229             : 
     230             :         /* Find the beginning of the IPCOMP header */
     231           0 :         m1 = m_getptr(m, skip, &roff);
     232           0 :         if (m1 == NULL) {
     233             :                 DPRINTF(("%s: bad mbuf chain, IPCA %s/%08x\n", __func__,
     234             :                     ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     235             :                     ntohl(tdb->tdb_spi)));
     236           0 :                 ipcompstat_inc(ipcomps_hdrops);
     237           0 :                 goto baddone;
     238             :         }
     239             :         /* Keep the next protocol field */
     240           0 :         addr = (caddr_t) mtod(m, struct ip *) + skip;
     241           0 :         ipcomp = (struct ipcomp *) addr;
     242           0 :         nproto = ipcomp->ipcomp_nh;
     243             : 
     244             :         /* Remove the IPCOMP header from the mbuf */
     245           0 :         if (roff == 0) {
     246             :                 /* The IPCOMP header is at the beginning of m1 */
     247           0 :                 m_adj(m1, hlen);
     248             :                 /*
     249             :                  * If m1 is the first mbuf, it has set M_PKTHDR and m_adj()
     250             :                  * has already adjusted the packet header length for us.
     251             :                  */
     252           0 :                 if (m1 != m)
     253           0 :                         m->m_pkthdr.len -= hlen;
     254           0 :         } else if (roff + hlen >= m1->m_len) {
     255             :                 int adjlen;
     256             : 
     257           0 :                 if (roff + hlen > m1->m_len) {
     258           0 :                         adjlen = roff + hlen - m1->m_len;
     259             : 
     260             :                         /* Adjust the next mbuf by the remainder */
     261           0 :                         m_adj(m1->m_next, adjlen);
     262             : 
     263             :                         /*
     264             :                          * The second mbuf is guaranteed not to have a
     265             :                          * pkthdr...
     266             :                          */
     267           0 :                         m->m_pkthdr.len -= adjlen;
     268           0 :                 }
     269             :                 /* Now, let's unlink the mbuf chain for a second... */
     270           0 :                 mo = m1->m_next;
     271           0 :                 m1->m_next = NULL;
     272             : 
     273             :                 /* ...and trim the end of the first part of the chain...sick */
     274           0 :                 adjlen = m1->m_len - roff;
     275           0 :                 m_adj(m1, -adjlen);
     276             :                 /*
     277             :                  * If m1 is the first mbuf, it has set M_PKTHDR and m_adj()
     278             :                  * has already adjusted the packet header length for us.
     279             :                  */
     280           0 :                 if (m1 != m)
     281           0 :                         m->m_pkthdr.len -= adjlen;
     282             : 
     283             :                 /* Finally, let's relink */
     284           0 :                 m1->m_next = mo;
     285           0 :         } else {
     286           0 :                 memmove(mtod(m1, u_char *) + roff,
     287             :                     mtod(m1, u_char *) + roff + hlen,
     288             :                     m1->m_len - (roff + hlen));
     289           0 :                 m1->m_len -= hlen;
     290           0 :                 m->m_pkthdr.len -= hlen;
     291             :         }
     292             : 
     293             :         /* Release the crypto descriptors */
     294           0 :         free(tc, M_XDATA, 0);
     295             : 
     296             :         /* Restore the Next Protocol field */
     297           0 :         m_copyback(m, protoff, sizeof(u_int8_t), &nproto, M_NOWAIT);
     298             : 
     299             :         /* Back to generic IPsec input processing */
     300           0 :         return ipsec_common_input_cb(m, tdb, skip, protoff);
     301             : 
     302             :  baddone:
     303           0 :         m_freem(m);
     304           0 :         free(tc, M_XDATA, 0);
     305           0 :         return -1;
     306           0 : }
     307             : 
     308             : /*
     309             :  * IPComp output routine, called by ipsp_process_packet()
     310             :  */
     311             : int
     312           0 : ipcomp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
     313             :     int protoff)
     314             : {
     315           0 :         struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
     316             :         int error, hlen;
     317             :         struct cryptodesc *crdc = NULL;
     318             :         struct cryptop *crp = NULL;
     319             :         struct tdb_crypto *tc;
     320             :         struct mbuf    *mi;
     321             : #ifdef ENCDEBUG
     322             :         char buf[INET6_ADDRSTRLEN];
     323             : #endif
     324             : #if NBPFILTER > 0
     325             :         struct ifnet *encif;
     326             : 
     327           0 :         if ((encif = enc_getif(0, tdb->tdb_tap)) != NULL) {
     328           0 :                 encif->if_opackets++;
     329           0 :                 encif->if_obytes += m->m_pkthdr.len;
     330             : 
     331           0 :                 if (encif->if_bpf) {
     332           0 :                         struct enchdr hdr;
     333             : 
     334           0 :                         memset(&hdr, 0, sizeof(hdr));
     335             : 
     336           0 :                         hdr.af = tdb->tdb_dst.sa.sa_family;
     337           0 :                         hdr.spi = tdb->tdb_spi;
     338             : 
     339           0 :                         bpf_mtap_hdr(encif->if_bpf, (char *)&hdr,
     340             :                             ENC_HDRLEN, m, BPF_DIRECTION_OUT, NULL);
     341           0 :                 }
     342             :         }
     343             : #endif
     344             :         hlen = IPCOMP_HLENGTH;
     345             : 
     346           0 :         ipcompstat_inc(ipcomps_output);
     347             : 
     348           0 :         switch (tdb->tdb_dst.sa.sa_family) {
     349             :         case AF_INET:
     350             :                 /* Check for IPv4 maximum packet size violations */
     351             :                 /*
     352             :                  * Since compression is going to reduce the size, no need to
     353             :                  * worry
     354             :                  */
     355           0 :                 if (m->m_pkthdr.len + hlen > IP_MAXPACKET) {
     356             :                         DPRINTF(("%s: packet in IPCA %s/%08x got too big\n",
     357             :                             __func__, ipsp_address(&tdb->tdb_dst, buf,
     358             :                             sizeof(buf)), ntohl(tdb->tdb_spi)));
     359           0 :                         ipcompstat_inc(ipcomps_toobig);
     360             :                         error = EMSGSIZE;
     361           0 :                         goto drop;
     362             :                 }
     363             :                 break;
     364             : 
     365             : #ifdef INET6
     366             :         case AF_INET6:
     367             :                 /* Check for IPv6 maximum packet size violations */
     368           0 :                 if (m->m_pkthdr.len + hlen > IPV6_MAXPACKET) {
     369             :                         DPRINTF(("%s: packet in IPCA %s/%08x got too big\n",
     370             :                             __func__, ipsp_address(&tdb->tdb_dst, buf,
     371             :                             sizeof(buf)), ntohl(tdb->tdb_spi)));
     372           0 :                         ipcompstat_inc(ipcomps_toobig);
     373             :                         error = EMSGSIZE;
     374           0 :                         goto drop;
     375             :                 }
     376             :                 break;
     377             : #endif /* INET6 */
     378             : 
     379             :         default:
     380             :                 DPRINTF(("%s: unknown/unsupported protocol family %d, "
     381             :                     "IPCA %s/%08x\n", __func__, tdb->tdb_dst.sa.sa_family,
     382             :                     ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     383             :                     ntohl(tdb->tdb_spi)));
     384           0 :                 ipcompstat_inc(ipcomps_nopf);
     385             :                 error = EPFNOSUPPORT;
     386           0 :                 goto drop;
     387             :         }
     388             : 
     389             :         /* Update the counters */
     390             : 
     391           0 :         tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
     392           0 :         ipcompstat_add(ipcomps_obytes, m->m_pkthdr.len - skip);
     393             : 
     394             :         /* Hard byte expiration */
     395           0 :         if ((tdb->tdb_flags & TDBF_BYTES) &&
     396           0 :             (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
     397           0 :                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
     398           0 :                 tdb_delete(tdb);
     399             :                 error = EINVAL;
     400           0 :                 goto drop;
     401             :         }
     402             :         /* Soft byte expiration */
     403           0 :         if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
     404           0 :             (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
     405           0 :                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
     406           0 :                 tdb->tdb_flags &= ~TDBF_SOFT_BYTES;      /* Turn off checking */
     407           0 :         }
     408             :         /*
     409             :          * Loop through mbuf chain; if we find a readonly mbuf,
     410             :          * copy the packet.
     411             :          */
     412             :         mi = m;
     413           0 :         while (mi != NULL && !M_READONLY(mi))
     414           0 :                 mi = mi->m_next;
     415             : 
     416           0 :         if (mi != NULL) {
     417           0 :                 struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT);
     418             : 
     419           0 :                 if (n == NULL) {
     420             :                         DPRINTF(("%s: bad mbuf chain, IPCA %s/%08x\n", __func__,
     421             :                             ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     422             :                             ntohl(tdb->tdb_spi)));
     423           0 :                         ipcompstat_inc(ipcomps_hdrops);
     424             :                         error = ENOBUFS;
     425           0 :                         goto drop;
     426             :                 }
     427             : 
     428           0 :                 m_freem(m);
     429             :                 m = n;
     430           0 :         }
     431             :         /* Ok now, we can pass to the crypto processing */
     432             : 
     433             :         /* Get crypto descriptors */
     434           0 :         crp = crypto_getreq(1);
     435           0 :         if (crp == NULL) {
     436             :                 DPRINTF(("%s: failed to acquire crypto descriptors\n", __func__));
     437           0 :                 ipcompstat_inc(ipcomps_crypto);
     438             :                 error = ENOBUFS;
     439           0 :                 goto drop;
     440             :         }
     441           0 :         crdc = &crp->crp_desc[0];
     442             : 
     443             :         /* Compression descriptor */
     444           0 :         crdc->crd_skip = skip;
     445           0 :         crdc->crd_len = m->m_pkthdr.len - skip;
     446           0 :         crdc->crd_flags = CRD_F_COMP;
     447           0 :         crdc->crd_inject = skip;
     448             : 
     449             :         /* Compression operation */
     450           0 :         crdc->crd_alg = ipcompx->type;
     451             : 
     452             :         /* IPsec-specific opaque crypto info */
     453           0 :         tc = malloc(sizeof(*tc), M_XDATA, M_NOWAIT | M_ZERO);
     454           0 :         if (tc == NULL) {
     455             :                 DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
     456           0 :                 ipcompstat_inc(ipcomps_crypto);
     457             :                 error = ENOBUFS;
     458           0 :                 goto drop;
     459             :         }
     460             : 
     461           0 :         tc->tc_spi = tdb->tdb_spi;
     462           0 :         tc->tc_proto = tdb->tdb_sproto;
     463           0 :         tc->tc_skip = skip;
     464           0 :         tc->tc_rdomain = tdb->tdb_rdomain;
     465           0 :         tc->tc_dst = tdb->tdb_dst;
     466             : 
     467             :         /* Crypto operation descriptor */
     468           0 :         crp->crp_ilen = m->m_pkthdr.len;  /* Total input length */
     469           0 :         crp->crp_flags = CRYPTO_F_IMBUF;
     470           0 :         crp->crp_buf = (caddr_t)m;
     471           0 :         crp->crp_callback = ipsec_output_cb;
     472           0 :         crp->crp_opaque = (caddr_t)tc;
     473           0 :         crp->crp_sid = tdb->tdb_cryptoid;
     474             : 
     475           0 :         return crypto_dispatch(crp);
     476             : 
     477             :  drop:
     478           0 :         m_freem(m);
     479           0 :         crypto_freereq(crp);
     480           0 :         return error;
     481           0 : }
     482             : 
     483             : /*
     484             :  * IPComp output callback.
     485             :  */
     486             : int
     487           0 : ipcomp_output_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m,
     488             :     int ilen, int olen)
     489             : {
     490             :         struct mbuf *mo;
     491           0 :         int skip, rlen, roff;
     492             :         u_int16_t cpi;
     493             :         struct ip *ip;
     494             : #ifdef INET6
     495             :         struct ip6_hdr *ip6;
     496             : #endif
     497             :         struct ipcomp  *ipcomp;
     498             : #ifdef ENCDEBUG
     499             :         char buf[INET6_ADDRSTRLEN];
     500             : #endif
     501             : 
     502           0 :         skip = tc->tc_skip;
     503           0 :         rlen = ilen - skip;
     504             : 
     505             :         /* Check sizes. */
     506           0 :         if (rlen <= olen + IPCOMP_HLENGTH) {
     507             :                 /* Compression was useless, we have lost time. */
     508           0 :                 ipcompstat_inc(ipcomps_minlen); /* misnomer, but like to count */
     509           0 :                 goto skiphdr;
     510             :         }
     511             : 
     512             :         /* Inject IPCOMP header */
     513           0 :         mo = m_makespace(m, skip, IPCOMP_HLENGTH, &roff);
     514           0 :         if (mo == NULL) {
     515             :                 DPRINTF(("%s: failed to inject IPCOMP header for "
     516             :                     "IPCA %s/%08x\n", __func__, ipsp_address(&tdb->tdb_dst, buf,
     517             :                      sizeof(buf)), ntohl(tdb->tdb_spi)));
     518           0 :                 ipcompstat_inc(ipcomps_wrap);
     519           0 :                 goto baddone;
     520             :         }
     521             : 
     522             :         /* Initialize the IPCOMP header */
     523           0 :         ipcomp = (struct ipcomp *)(mtod(mo, caddr_t) + roff);
     524           0 :         memset(ipcomp, 0, sizeof(struct ipcomp));
     525           0 :         cpi = (u_int16_t) ntohl(tdb->tdb_spi);
     526           0 :         ipcomp->ipcomp_cpi = htons(cpi);
     527             : 
     528             :         /* m_pullup before ? */
     529           0 :         switch (tdb->tdb_dst.sa.sa_family) {
     530             :         case AF_INET:
     531           0 :                 ip = mtod(m, struct ip *);
     532           0 :                 ipcomp->ipcomp_nh = ip->ip_p;
     533           0 :                 ip->ip_p = IPPROTO_IPCOMP;
     534           0 :                 break;
     535             : #ifdef INET6
     536             :         case AF_INET6:
     537           0 :                 ip6 = mtod(m, struct ip6_hdr *);
     538           0 :                 ipcomp->ipcomp_nh = ip6->ip6_nxt;
     539           0 :                 ip6->ip6_nxt = IPPROTO_IPCOMP;
     540           0 :                 break;
     541             : #endif
     542             :         default:
     543             :                 DPRINTF(("%s: unsupported protocol family %d, IPCA %s/%08x\n",
     544             :                     __func__, tdb->tdb_dst.sa.sa_family,
     545             :                     ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     546             :                     ntohl(tdb->tdb_spi)));
     547           0 :                 ipcompstat_inc(ipcomps_nopf);
     548           0 :                 goto baddone;
     549             :         }
     550             : 
     551             :  skiphdr:
     552             :         /* Release the crypto descriptor. */
     553           0 :         free(tc, M_XDATA, 0);
     554             : 
     555           0 :         if (ipsp_process_done(m, tdb)) {
     556           0 :                 ipcompstat_inc(ipcomps_outfail);
     557           0 :                 return -1;
     558             :         }
     559           0 :         return 0;
     560             : 
     561             :  baddone:
     562           0 :         m_freem(m);
     563           0 :         free(tc, M_XDATA, 0);
     564           0 :         return -1;
     565           0 : }

Generated by: LCOV version 1.13