root/netinet/ip_ipcomp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ipcomp_attach
  2. ipcomp_init
  3. ipcomp_zeroize
  4. ipcomp_input
  5. ipcomp_input_cb
  6. ipcomp_output
  7. ipcomp_output_cb

    1 /* $OpenBSD: ip_ipcomp.c,v 1.20 2006/03/25 22:41:48 djm 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/bpf.h>
   39 
   40 #include <dev/rndvar.h>
   41 
   42 #ifdef INET
   43 #include <netinet/in.h>
   44 #include <netinet/in_systm.h>
   45 #include <netinet/ip.h>
   46 #endif                          /* INET */
   47 
   48 #ifdef INET6
   49 #ifndef INET
   50 #include <netinet/in.h>
   51 #endif
   52 #include <netinet/ip6.h>
   53 #endif                          /* INET6 */
   54 
   55 #include <netinet/ip_ipsp.h>
   56 #include <netinet/ip_ipcomp.h>
   57 #include <net/pfkeyv2.h>
   58 #include <net/if_enc.h>
   59 
   60 #include <crypto/cryptodev.h>
   61 #include <crypto/deflate.h>
   62 #include <crypto/xform.h>
   63 
   64 #include "bpfilter.h"
   65 
   66 #ifdef ENCDEBUG
   67 #define DPRINTF(x)      if (encdebug) printf x
   68 #else
   69 #define DPRINTF(x)
   70 #endif
   71 
   72 struct ipcompstat ipcompstat;
   73 
   74 /*
   75  * ipcomp_attach() is called from the transformation code
   76  */
   77 int
   78 ipcomp_attach(void)
   79 {
   80         return 0;
   81 }
   82 
   83 /*
   84  * ipcomp_init() is called when an CPI is being set up.
   85  */
   86 int
   87 ipcomp_init(tdbp, xsp, ii)
   88         struct tdb     *tdbp;
   89         struct xformsw *xsp;
   90         struct ipsecinit *ii;
   91 {
   92         struct comp_algo *tcomp = NULL;
   93         struct cryptoini cric;
   94 
   95         switch (ii->ii_compalg) {
   96         case SADB_X_CALG_DEFLATE:
   97                 tcomp = &comp_algo_deflate;
   98                 break;
   99         case SADB_X_CALG_LZS:
  100                 tcomp = &comp_algo_lzs;
  101                 break;
  102 
  103         default:
  104                 DPRINTF(("ipcomp_init(): unsupported compression algorithm %d specified\n",
  105                     ii->ii_compalg));
  106                 return EINVAL;
  107         }
  108 
  109         tdbp->tdb_compalgxform = tcomp;
  110 
  111         DPRINTF(("ipcomp_init(): initialized TDB with ipcomp algorithm %s\n",
  112             tcomp->name));
  113 
  114         tdbp->tdb_xform = xsp;
  115         tdbp->tdb_bitmap = 0;
  116 
  117         /* Initialize crypto session */
  118         bzero(&cric, sizeof(cric));
  119         cric.cri_alg = tdbp->tdb_compalgxform->type;
  120 
  121         return crypto_newsession(&tdbp->tdb_cryptoid, &cric, 0);
  122 }
  123 
  124 /*
  125  * ipcomp_zeroize() used when IPCA is deleted
  126  */
  127 int
  128 ipcomp_zeroize(tdbp)
  129         struct tdb *tdbp;
  130 {
  131         int err;
  132 
  133         err = crypto_freesession(tdbp->tdb_cryptoid);
  134         tdbp->tdb_cryptoid = 0;
  135         return err;
  136 }
  137 
  138 /*
  139  * ipcomp_input() gets called to uncompress an input packet
  140  */
  141 int
  142 ipcomp_input(m, tdb, skip, protoff)
  143         struct mbuf    *m;
  144         struct tdb     *tdb;
  145         int             skip;
  146         int             protoff;
  147 {
  148         struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
  149         struct tdb_crypto *tc;
  150         int hlen;
  151 
  152         struct cryptodesc *crdc = NULL;
  153         struct cryptop *crp;
  154 
  155         hlen = IPCOMP_HLENGTH;
  156 
  157         /* Get crypto descriptors */
  158         crp = crypto_getreq(1);
  159         if (crp == NULL) {
  160                 m_freem(m);
  161                 DPRINTF(("ipcomp_input(): failed to acquire crypto descriptors\n"));
  162                 ipcompstat.ipcomps_crypto++;
  163                 return ENOBUFS;
  164         }
  165         /* Get IPsec-specific opaque pointer */
  166         MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
  167             M_XDATA, M_NOWAIT);
  168         if (tc == NULL) {
  169                 m_freem(m);
  170                 crypto_freereq(crp);
  171                 DPRINTF(("ipcomp_input(): failed to allocate tdb_crypto\n"));
  172                 ipcompstat.ipcomps_crypto++;
  173                 return ENOBUFS;
  174         }
  175         bzero(tc, sizeof(struct tdb_crypto));
  176         crdc = crp->crp_desc;
  177 
  178         crdc->crd_skip = skip + hlen;
  179         crdc->crd_len = m->m_pkthdr.len - (skip + hlen);
  180         crdc->crd_inject = skip;
  181 
  182         tc->tc_ptr = 0;
  183 
  184         /* Decompression operation */
  185         crdc->crd_alg = ipcompx->type;
  186 
  187         /* Crypto operation descriptor */
  188         crp->crp_ilen = m->m_pkthdr.len - (skip + hlen);
  189         crp->crp_flags = CRYPTO_F_IMBUF;
  190         crp->crp_buf = (caddr_t) m;
  191         crp->crp_callback = (int (*) (struct cryptop *)) ipcomp_input_cb;
  192         crp->crp_sid = tdb->tdb_cryptoid;
  193         crp->crp_opaque = (caddr_t) tc;
  194 
  195         /* These are passed as-is to the callback */
  196         tc->tc_skip = skip;
  197         tc->tc_protoff = protoff;
  198         tc->tc_spi = tdb->tdb_spi;
  199         tc->tc_proto = IPPROTO_IPCOMP;
  200         bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
  201 
  202         return crypto_dispatch(crp);
  203 }
  204 
  205 /*
  206  * IPComp input callback, called directly by the crypto driver
  207  */
  208 int
  209 ipcomp_input_cb(op)
  210         void *op;
  211 {
  212         int error, s, skip, protoff, roff, hlen = IPCOMP_HLENGTH, clen;
  213         u_int8_t nproto;
  214         struct mbuf *m, *m1, *mo;
  215         struct cryptodesc *crd;
  216         struct comp_algo *ipcompx;
  217         struct tdb_crypto *tc;
  218         struct cryptop *crp;
  219         struct tdb *tdb;
  220         struct ipcomp  *ipcomp;
  221         caddr_t addr;
  222 
  223         crp = (struct cryptop *) op;
  224         crd = crp->crp_desc;
  225 
  226         tc = (struct tdb_crypto *) crp->crp_opaque;
  227         skip = tc->tc_skip;
  228         protoff = tc->tc_protoff;
  229 
  230         m = (struct mbuf *) crp->crp_buf;
  231         if (m == NULL) {
  232                 /* Shouldn't happen... */
  233                 FREE(tc, M_XDATA);
  234                 crypto_freereq(crp);
  235                 ipcompstat.ipcomps_crypto++;
  236                 DPRINTF(("ipcomp_input_cb(): bogus returned buffer from crypto\n"));
  237                 return (EINVAL);
  238         }
  239 
  240         s = spltdb();
  241 
  242         tdb = gettdb(tc->tc_spi, &tc->tc_dst, tc->tc_proto);
  243         if (tdb == NULL) {
  244                 FREE(tc, M_XDATA);
  245                 ipcompstat.ipcomps_notdb++;
  246                 DPRINTF(("ipcomp_input_cb(): TDB expired while in crypto"));
  247                 error = EPERM;
  248                 goto baddone;
  249         }
  250         ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
  251 
  252         /* update the counters */
  253         tdb->tdb_cur_bytes += m->m_pkthdr.len - (skip + hlen);
  254         ipcompstat.ipcomps_ibytes += m->m_pkthdr.len - (skip + hlen);
  255 
  256         /* Hard expiration */
  257         if ((tdb->tdb_flags & TDBF_BYTES) &&
  258             (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
  259                 FREE(tc, M_XDATA);
  260                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
  261                 tdb_delete(tdb);
  262                 error = ENXIO;
  263                 goto baddone;
  264         }
  265         /* Notify on soft expiration */
  266         if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
  267             (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
  268                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
  269                 tdb->tdb_flags &= ~TDBF_SOFT_BYTES;     /* Turn off checking */
  270         }
  271 
  272         /* Check for crypto errors */
  273         if (crp->crp_etype) {
  274                 if (crp->crp_etype == EAGAIN) {
  275                         /* Reset the session ID */
  276                         if (tdb->tdb_cryptoid != 0)
  277                                 tdb->tdb_cryptoid = crp->crp_sid;
  278                         splx(s);
  279                         return crypto_dispatch(crp);
  280                 }
  281                 FREE(tc, M_XDATA);
  282                 ipcompstat.ipcomps_noxform++;
  283                 DPRINTF(("ipcomp_input_cb(): crypto error %d\n",
  284                     crp->crp_etype));
  285                 error = crp->crp_etype;
  286                 goto baddone;
  287         }
  288         FREE(tc, M_XDATA);
  289 
  290         /* Length of data after processing */
  291         clen = crp->crp_olen;
  292 
  293         /* In case it's not done already, adjust the size of the mbuf chain */
  294         m->m_pkthdr.len = clen + hlen + skip;
  295 
  296         if ((m->m_len < skip + hlen) && (m = m_pullup(m, skip + hlen)) == 0) {
  297                 error = ENOBUFS;
  298                 goto baddone;
  299         }
  300 
  301         /* Find the beginning of the IPCOMP header */
  302         m1 = m_getptr(m, skip, &roff);
  303         if (m1 == NULL) {
  304                 ipcompstat.ipcomps_hdrops++;
  305                 DPRINTF(("ipcomp_input_cb(): bad mbuf chain, IPCA %s/%08x\n",
  306                     ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
  307                 error = EINVAL;
  308                 goto baddone;
  309         }
  310         /* Keep the next protocol field */
  311         addr = (caddr_t) mtod(m, struct ip *) + skip;
  312         ipcomp = (struct ipcomp *) addr;
  313         nproto = ipcomp->ipcomp_nh;
  314 
  315         /* Remove the IPCOMP header from the mbuf */
  316         if (roff == 0) {
  317                 /* The IPCOMP header is at the beginning of m1 */
  318                 m_adj(m1, hlen);
  319                 if (!(m1->m_flags & M_PKTHDR))
  320                         m->m_pkthdr.len -= hlen;
  321         } else if (roff + hlen >= m1->m_len) {
  322                 if (roff + hlen > m1->m_len) {
  323                         /* Adjust the next mbuf by the remainder */
  324                         m_adj(m1->m_next, roff + hlen - m1->m_len);
  325 
  326                         /*
  327                          * The second mbuf is guaranteed not to have a
  328                          * pkthdr...
  329                          */
  330                         m->m_pkthdr.len -= (roff + hlen - m1->m_len);
  331                 }
  332                 /* Now, let's unlink the mbuf chain for a second... */
  333                 mo = m1->m_next;
  334                 m1->m_next = NULL;
  335 
  336                 /* ...and trim the end of the first part of the chain...sick */
  337                 m_adj(m1, -(m1->m_len - roff));
  338                 if (!(m1->m_flags & M_PKTHDR))
  339                         m->m_pkthdr.len -= (m1->m_len - roff);
  340 
  341                 /* Finally, let's relink */
  342                 m1->m_next = mo;
  343         } else {
  344                 bcopy(mtod(m1, u_char *) + roff + hlen,
  345                     mtod(m1, u_char *) + roff,
  346                     m1->m_len - (roff + hlen));
  347                 m1->m_len -= hlen;
  348                 m->m_pkthdr.len -= hlen;
  349         }
  350 
  351         /* Release the crypto descriptors */
  352         crypto_freereq(crp);
  353 
  354         /* Restore the Next Protocol field */
  355         m_copyback(m, protoff, sizeof(u_int8_t), &nproto);
  356 
  357         /* Back to generic IPsec input processing */
  358         error = ipsec_common_input_cb(m, tdb, skip, protoff, NULL);
  359         splx(s);
  360         return error;
  361 
  362 baddone:
  363         splx(s);
  364 
  365         if (m)
  366                 m_freem(m);
  367 
  368         crypto_freereq(crp);
  369 
  370         return error;
  371 }
  372 
  373 /*
  374  * IPComp output routine, called by ipsp_process_packet()
  375  */
  376 int
  377 ipcomp_output(m, tdb, mp, skip, protoff)
  378         struct mbuf    *m;
  379         struct tdb     *tdb;
  380         struct mbuf   **mp;
  381         int             skip;
  382         int             protoff;
  383 {
  384         struct comp_algo *ipcompx = (struct comp_algo *) tdb->tdb_compalgxform;
  385         int             hlen;
  386         struct cryptodesc *crdc = NULL;
  387         struct cryptop *crp;
  388         struct tdb_crypto *tc;
  389         struct mbuf    *mi, *mo;
  390 #if NBPFILTER > 0
  391         struct ifnet   *ifn = &(encif[0].sc_if);
  392 
  393         if (ifn->if_bpf) {
  394                 struct enchdr   hdr;
  395 
  396                 bzero(&hdr, sizeof(hdr));
  397 
  398                 hdr.af = tdb->tdb_dst.sa.sa_family;
  399                 hdr.spi = tdb->tdb_spi;
  400 
  401                 bpf_mtap_hdr(ifn->if_bpf, (char *)&hdr, ENC_HDRLEN, m,
  402                     BPF_DIRECTION_OUT);
  403         }
  404 #endif
  405         hlen = IPCOMP_HLENGTH;
  406 
  407         ipcompstat.ipcomps_output++;
  408 
  409         switch (tdb->tdb_dst.sa.sa_family) {
  410 #ifdef INET
  411         case AF_INET:
  412                 /* Check for IPv4 maximum packet size violations */
  413                 /*
  414                  * Since compression is going to reduce the size, no need to
  415                  * worry
  416                  */
  417                 if (m->m_pkthdr.len + hlen > IP_MAXPACKET) {
  418                         DPRINTF(("ipcomp_output(): packet in IPCA %s/%08x got too big\n",
  419                             ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
  420                         m_freem(m);
  421                         ipcompstat.ipcomps_toobig++;
  422                         return EMSGSIZE;
  423                 }
  424                 break;
  425 #endif /* INET */
  426 
  427 #ifdef INET6
  428         case AF_INET6:
  429                 /* Check for IPv6 maximum packet size violations */
  430                 if (m->m_pkthdr.len + hlen > IPV6_MAXPACKET) {
  431                         DPRINTF(("ipcomp_output(): packet in IPCA %s/%08x got too big\n",
  432                             ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
  433                         m_freem(m);
  434                         ipcompstat.ipcomps_toobig++;
  435                         return EMSGSIZE;
  436                 }
  437 #endif /* INET6 */
  438 
  439         default:
  440                 DPRINTF(("ipcomp_output(): unknown/unsupported protocol family %d, IPCA %s/%08x\n",
  441                     tdb->tdb_dst.sa.sa_family, ipsp_address(tdb->tdb_dst),
  442                     ntohl(tdb->tdb_spi)));
  443                 m_freem(m);
  444                 ipcompstat.ipcomps_nopf++;
  445                 return EPFNOSUPPORT;
  446         }
  447 
  448         /* Update the counters */
  449 
  450         tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
  451         ipcompstat.ipcomps_obytes += m->m_pkthdr.len - skip;
  452 
  453         /* Hard byte expiration */
  454         if ((tdb->tdb_flags & TDBF_BYTES) &&
  455             (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
  456                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
  457                 tdb_delete(tdb);
  458                 m_freem(m);
  459                 return EINVAL;
  460         }
  461         /* Soft byte expiration */
  462         if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
  463             (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
  464                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
  465                 tdb->tdb_flags &= ~TDBF_SOFT_BYTES;     /* Turn off checking */
  466         }
  467         /*
  468          * Loop through mbuf chain; if we find a readonly mbuf,
  469          * replace the rest of the chain.
  470          */
  471         mo = NULL;
  472         mi = m;
  473         while (mi != NULL && !M_READONLY(mi)) {
  474                 mo = mi;
  475                 mi = mi->m_next;
  476         }
  477 
  478         if (mi != NULL) {
  479                 /* Replace the rest of the mbuf chain. */
  480                 struct mbuf    *n = m_copym2(mi, 0, M_COPYALL, M_DONTWAIT);
  481 
  482                 if (n == NULL) {
  483                         DPRINTF(("ipcomp_output(): bad mbuf chain, IPCA %s/%08x\n",
  484                             ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
  485                         ipcompstat.ipcomps_hdrops++;
  486                         m_freem(m);
  487                         return ENOBUFS;
  488                 }
  489                 if (mo != NULL)
  490                         mo->m_next = n;
  491                 else
  492                         m = n;
  493 
  494                 m_freem(mi);
  495         }
  496         /* Ok now, we can pass to the crypto processing */
  497 
  498         /* Get crypto descriptors */
  499         crp = crypto_getreq(1);
  500         if (crp == NULL) {
  501                 m_freem(m);
  502                 DPRINTF(("ipcomp_output(): failed to acquire crypto descriptors\n"));
  503                 ipcompstat.ipcomps_crypto++;
  504                 return ENOBUFS;
  505         }
  506         crdc = crp->crp_desc;
  507 
  508         /* Compression descriptor */
  509         crdc->crd_skip = skip;
  510         crdc->crd_len = m->m_pkthdr.len - skip;
  511         crdc->crd_flags = CRD_F_COMP;
  512         crdc->crd_inject = skip;
  513 
  514         /* Compression operation */
  515         crdc->crd_alg = ipcompx->type;
  516 
  517         /* IPsec-specific opaque crypto info */
  518         MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
  519             M_XDATA, M_NOWAIT);
  520         if (tc == NULL) {
  521                 m_freem(m);
  522                 crypto_freereq(crp);
  523                 DPRINTF(("ipcomp_output(): failed to allocate tdb_crypto\n"));
  524                 ipcompstat.ipcomps_crypto++;
  525                 return ENOBUFS;
  526         }
  527         bzero(tc, sizeof(struct tdb_crypto));
  528 
  529         tc->tc_spi = tdb->tdb_spi;
  530         tc->tc_proto = tdb->tdb_sproto;
  531         tc->tc_skip = skip;
  532         bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
  533 
  534         /* Crypto operation descriptor */
  535         crp->crp_ilen = m->m_pkthdr.len;        /* Total input length */
  536         crp->crp_flags = CRYPTO_F_IMBUF;
  537         crp->crp_buf = (caddr_t) m;
  538         crp->crp_callback = (int (*) (struct cryptop *)) ipcomp_output_cb;
  539         crp->crp_opaque = (caddr_t) tc;
  540         crp->crp_sid = tdb->tdb_cryptoid;
  541 
  542         return crypto_dispatch(crp);
  543 }
  544 
  545 /*
  546  * IPComp output callback, called directly from the crypto driver
  547  */
  548 int
  549 ipcomp_output_cb(cp)
  550         void *cp;
  551 {
  552         struct cryptop *crp = (struct cryptop *) cp;
  553         struct tdb_crypto *tc;
  554         struct tdb *tdb;
  555         struct mbuf *m, *mo;
  556         int error, s, skip, rlen;
  557         u_int16_t cpi;
  558 #ifdef INET
  559         struct ip *ip;
  560 #endif
  561 #ifdef INET6
  562         struct ip6_hdr *ip6;
  563 #endif
  564         struct ipcomp  *ipcomp;
  565 
  566         tc = (struct tdb_crypto *) crp->crp_opaque;
  567         skip = tc->tc_skip;
  568         rlen = crp->crp_ilen - skip;
  569 
  570         m = (struct mbuf *) crp->crp_buf;
  571         if (m == NULL) {
  572                 /* Shouldn't happen... */
  573                 FREE(tc, M_XDATA);
  574                 crypto_freereq(crp);
  575                 ipcompstat.ipcomps_crypto++;
  576                 DPRINTF(("ipcomp_output_cb(): bogus returned buffer from "
  577                     "crypto\n"));
  578                 return (EINVAL);
  579         }
  580 
  581         s = spltdb();
  582 
  583         tdb = gettdb(tc->tc_spi, &tc->tc_dst, tc->tc_proto);
  584         if (tdb == NULL) {
  585                 FREE(tc, M_XDATA);
  586                 ipcompstat.ipcomps_notdb++;
  587                 DPRINTF(("ipcomp_output_cb(): TDB expired while in crypto\n"));
  588                 error = EPERM;
  589                 goto baddone;
  590         }
  591 
  592         /* Check for crypto errors. */
  593         if (crp->crp_etype) {
  594                 if (crp->crp_etype == EAGAIN) {
  595                         /* Reset the session ID */
  596                         if (tdb->tdb_cryptoid != 0)
  597                                 tdb->tdb_cryptoid = crp->crp_sid;
  598                         splx(s);
  599                         return crypto_dispatch(crp);
  600                 }
  601                 FREE(tc, M_XDATA);
  602                 ipcompstat.ipcomps_noxform++;
  603                 DPRINTF(("ipcomp_output_cb(): crypto error %d\n",
  604                     crp->crp_etype));
  605                 error = crp->crp_etype;
  606                 goto baddone;
  607         }
  608         FREE(tc, M_XDATA);
  609 
  610         /* Check sizes. */
  611         if (rlen < crp->crp_olen) {
  612                 /* Compression was useless, we have lost time. */
  613                 crypto_freereq(crp);
  614                 error = ipsp_process_done(m, tdb);
  615                 splx(s);
  616                 return error;
  617         }
  618 
  619         /* Inject IPCOMP header */
  620         mo = m_inject(m, skip, IPCOMP_HLENGTH, M_DONTWAIT);
  621         if (mo == NULL) {
  622                 DPRINTF(("ipcomp_output_cb(): failed to inject IPCOMP header "
  623                     "for IPCA %s/%08x\n",
  624                     ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
  625                 ipcompstat.ipcomps_wrap++;
  626                 error = ENOBUFS;
  627                 goto baddone;
  628         }
  629 
  630         /* Initialize the IPCOMP header */
  631         ipcomp = mtod(mo, struct ipcomp *);
  632         bzero(ipcomp, sizeof(struct ipcomp));
  633         cpi = (u_int16_t) ntohl(tdb->tdb_spi);
  634         ipcomp->ipcomp_cpi = htons(cpi);
  635 
  636         /* m_pullup before ? */
  637         switch (tdb->tdb_dst.sa.sa_family) {
  638 #ifdef INET
  639         case AF_INET:
  640                 ip = mtod(m, struct ip *);
  641                 ipcomp->ipcomp_nh = ip->ip_p;
  642                 ip->ip_p = IPPROTO_IPCOMP;
  643                 break;
  644 #endif /* INET */
  645 #ifdef INET6
  646         case AF_INET6:
  647                 ip6 = mtod(m, struct ip6_hdr *);
  648                 ipcomp->ipcomp_nh = ip6->ip6_nxt;
  649                 ip6->ip6_nxt = IPPROTO_IPCOMP;
  650                 break;
  651 #endif
  652         default:
  653                 DPRINTF(("ipcomp_output_cb(): unsupported protocol family %d, "
  654                     "IPCA %s/%08x\n",
  655                     tdb->tdb_dst.sa.sa_family, ipsp_address(tdb->tdb_dst),
  656                     ntohl(tdb->tdb_spi)));
  657                 ipcompstat.ipcomps_nopf++;
  658                 error = EPFNOSUPPORT;
  659                 goto baddone;
  660                 break;
  661         }
  662 
  663         /* Release the crypto descriptor. */
  664         crypto_freereq(crp);
  665 
  666         error = ipsp_process_done(m, tdb);
  667         splx(s);
  668         return error;
  669 
  670 baddone:
  671         splx(s);
  672 
  673         if (m)
  674                 m_freem(m);
  675 
  676         crypto_freereq(crp);
  677 
  678         return error;
  679 }

/* [<][>][^][v][top][bottom][index][help] */