The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet6/ipcomp_core.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $FreeBSD: src/sys/netinet6/ipcomp_core.c,v 1.1.2.5 2003/01/11 19:10:59 ume Exp $        */
    2 /*      $DragonFly: src/sys/netinet6/ipcomp_core.c,v 1.7 2006/09/29 03:37:04 hsu Exp $  */
    3 /*      $KAME: ipcomp_core.c,v 1.25 2001/07/26 06:53:17 jinmei Exp $    */
    4 
    5 /*
    6  * Copyright (C) 1999 WIDE Project.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. Neither the name of the project nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 /*
   35  * RFC2393 IP payload compression protocol (IPComp).
   36  */
   37 
   38 #include "opt_inet.h"
   39 #include "opt_inet6.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/malloc.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/domain.h>
   46 #include <sys/protosw.h>
   47 #include <sys/socket.h>
   48 #include <sys/errno.h>
   49 #include <sys/time.h>
   50 #include <sys/syslog.h>
   51 #include <sys/queue.h>
   52 
   53 #include <net/if.h>
   54 #include <net/route.h>
   55 #include <netinet/in.h>
   56 #include <net/netisr.h>
   57 #include <net/zlib.h>
   58 #include <machine/cpu.h>
   59 
   60 #include <netinet6/ipcomp.h>
   61 #ifdef INET6
   62 #include <netinet6/ipcomp6.h>
   63 #endif
   64 #include <netinet6/ipsec.h>
   65 #ifdef INET6
   66 #include <netinet6/ipsec6.h>
   67 #endif
   68 
   69 #include <machine/stdarg.h>
   70 
   71 #include <net/net_osdep.h>
   72 
   73 static void *deflate_alloc (void *, u_int, u_int);
   74 static void deflate_free (void *, void *);
   75 static int deflate_common (struct mbuf *, struct mbuf *, size_t *, int);
   76 static int deflate_compress (struct mbuf *, struct mbuf *, size_t *);
   77 static int deflate_decompress (struct mbuf *, struct mbuf *, size_t *);
   78 
   79 /*
   80  * We need to use default window size (2^15 = 32Kbytes as of writing) for
   81  * inbound case.  Otherwise we get interop problem.
   82  * Use negative value to avoid Adler32 checksum.  This is an undocumented
   83  * feature in zlib (see ipsec wg mailing list archive in January 2000).
   84  */
   85 static int deflate_policy = Z_DEFAULT_COMPRESSION;
   86 static int deflate_window_out = -12;
   87 static const int deflate_window_in = -1 * MAX_WBITS;    /* don't change it */
   88 static int deflate_memlevel = MAX_MEM_LEVEL;
   89 
   90 static const struct ipcomp_algorithm ipcomp_algorithms[] = {
   91         { deflate_compress, deflate_decompress, 90 },
   92 };
   93 
   94 const struct ipcomp_algorithm *
   95 ipcomp_algorithm_lookup(int idx)
   96 {
   97 
   98         if (idx == SADB_X_CALG_DEFLATE)
   99                 return &ipcomp_algorithms[0];
  100         return NULL;
  101 }
  102 
  103 static void *
  104 deflate_alloc(void *aux, u_int items, u_int siz)
  105 {
  106         void *ptr;
  107         ptr = kmalloc(items * siz, M_TEMP, M_NOWAIT);
  108         return ptr;
  109 }
  110 
  111 static void
  112 deflate_free(void *aux, void *ptr)
  113 {
  114         kfree(ptr, M_TEMP);
  115 }
  116 
  117 static int
  118 deflate_common(struct mbuf *m, struct mbuf *md, size_t *lenp,
  119                int mode)        /* 0: compress 1: decompress */
  120 {
  121         struct mbuf *mprev;
  122         struct mbuf *p;
  123         struct mbuf *n = NULL, *n0 = NULL, **np;
  124         z_stream zs;
  125         int error = 0;
  126         int zerror;
  127         size_t offset;
  128 
  129 #define MOREBLOCK() \
  130 do { \
  131         /* keep the reply buffer into our chain */              \
  132         if (n) {                                                \
  133                 n->m_len = zs.total_out - offset;               \
  134                 offset = zs.total_out;                          \
  135                 *np = n;                                        \
  136                 np = &n->m_next;                                \
  137                 n = NULL;                                       \
  138         }                                                       \
  139                                                                 \
  140         /* get a fresh reply buffer */                          \
  141         n = m_getcl(MB_DONTWAIT, MT_DATA, 0);                   \
  142         if (!n) {                                               \
  143                 error = ENOBUFS;                                \
  144                 goto fail;                                      \
  145         }                                                       \
  146         n->m_len = 0;                                           \
  147         n->m_len = M_TRAILINGSPACE(n);                          \
  148         n->m_next = NULL;                                       \
  149         /*                                                      \
  150          * if this is the first reply buffer, reserve           \
  151          * region for ipcomp header.                            \
  152          */                                                     \
  153         if (*np == NULL) {                                      \
  154                 n->m_len -= sizeof(struct ipcomp);              \
  155                 n->m_data += sizeof(struct ipcomp);             \
  156         }                                                       \
  157                                                                 \
  158         zs.next_out = mtod(n, u_int8_t *);                      \
  159         zs.avail_out = n->m_len;                                \
  160 } while (0)
  161 
  162         for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next)
  163                 ;
  164         if (!mprev)
  165                 panic("md is not in m in deflate_common");
  166 
  167         bzero(&zs, sizeof(zs));
  168         zs.zalloc = deflate_alloc;
  169         zs.zfree = deflate_free;
  170 
  171         zerror = mode ? inflateInit2(&zs, deflate_window_in)
  172                       : deflateInit2(&zs, deflate_policy, Z_DEFLATED,
  173                                 deflate_window_out, deflate_memlevel,
  174                                 Z_DEFAULT_STRATEGY);
  175         if (zerror != Z_OK) {
  176                 error = ENOBUFS;
  177                 goto fail;
  178         }
  179 
  180         n0 = n = NULL;
  181         np = &n0;
  182         offset = 0;
  183         zerror = 0;
  184         p = md;
  185         while (p && p->m_len == 0) {
  186                 p = p->m_next;
  187         }
  188 
  189         /* input stream and output stream are available */
  190         while (p && zs.avail_in == 0) {
  191                 /* get input buffer */
  192                 if (p && zs.avail_in == 0) {
  193                         zs.next_in = mtod(p, u_int8_t *);
  194                         zs.avail_in = p->m_len;
  195                         p = p->m_next;
  196                         while (p && p->m_len == 0) {
  197                                 p = p->m_next;
  198                         }
  199                 }
  200 
  201                 /* get output buffer */
  202                 if (zs.next_out == NULL || zs.avail_out == 0) {
  203                         MOREBLOCK();
  204                 }
  205 
  206                 zerror = mode ? inflate(&zs, Z_NO_FLUSH)
  207                               : deflate(&zs, Z_NO_FLUSH);
  208 
  209                 if (zerror == Z_STREAM_END)
  210                         ; /* once more. */
  211                 else if (zerror == Z_OK) {
  212                         /* inflate: Z_OK can indicate the end of decode */
  213                         if (mode && !p && zs.avail_out != 0)
  214                                 goto terminate;
  215                         else
  216                                 ; /* once more. */
  217                 } else {
  218                         if (zs.msg) {
  219                                 ipseclog((LOG_ERR, "ipcomp_%scompress: "
  220                                     "%sflate(Z_NO_FLUSH): %s\n",
  221                                     mode ? "de" : "", mode ? "in" : "de",
  222                                     zs.msg));
  223                         } else {
  224                                 ipseclog((LOG_ERR, "ipcomp_%scompress: "
  225                                     "%sflate(Z_NO_FLUSH): unknown error (%d)\n",
  226                                     mode ? "de" : "", mode ? "in" : "de",
  227                                     zerror));
  228                         }
  229                         mode ? inflateEnd(&zs) : deflateEnd(&zs);
  230                         error = EINVAL;
  231                         goto fail;
  232                 }
  233         }
  234 
  235         if (zerror == Z_STREAM_END)
  236                 goto terminate;
  237 
  238         /* termination */
  239         while (1) {
  240                 /* get output buffer */
  241                 if (zs.next_out == NULL || zs.avail_out == 0) {
  242                         MOREBLOCK();
  243                 }
  244 
  245                 zerror = mode ? inflate(&zs, Z_SYNC_FLUSH)
  246                               : deflate(&zs, Z_FINISH);
  247 
  248                 if (zerror == Z_STREAM_END)
  249                         break;
  250                 else if (zerror == Z_OK) {
  251                         if (mode && zs.avail_out != 0)
  252                                 goto terminate;
  253                         else
  254                                 ; /* once more. */
  255                 } else {
  256                         if (zs.msg) {
  257                                 ipseclog((LOG_ERR, "ipcomp_%scompress: "
  258                                     "%sflate(Z_FINISH): %s\n",
  259                                     mode ? "de" : "", mode ? "in" : "de",
  260                                     zs.msg));
  261                         } else {
  262                                 ipseclog((LOG_ERR, "ipcomp_%scompress: "
  263                                     "%sflate(Z_FINISH): unknown error (%d)\n",
  264                                     mode ? "de" : "", mode ? "in" : "de",
  265                                     zerror));
  266                         }
  267                         mode ? inflateEnd(&zs) : deflateEnd(&zs);
  268                         error = EINVAL;
  269                         goto fail;
  270                 }
  271         }
  272 
  273 terminate:
  274         zerror = mode ? inflateEnd(&zs) : deflateEnd(&zs);
  275         if (zerror != Z_OK) {
  276                 if (zs.msg) {
  277                         ipseclog((LOG_ERR, "ipcomp_%scompress: "
  278                             "%sflateEnd: %s\n",
  279                             mode ? "de" : "", mode ? "in" : "de",
  280                             zs.msg));
  281                 } else {
  282                         ipseclog((LOG_ERR, "ipcomp_%scompress: "
  283                             "%sflateEnd: unknown error (%d)\n",
  284                             mode ? "de" : "", mode ? "in" : "de",
  285                             zerror));
  286                 }
  287                 error = EINVAL;
  288                 goto fail;
  289         }
  290         /* keep the final reply buffer into our chain */
  291         if (n) {
  292                 n->m_len = zs.total_out - offset;
  293                 offset = zs.total_out;
  294                 *np = n;
  295                 np = &n->m_next;
  296                 n = NULL;
  297         }
  298 
  299         /* switch the mbuf to the new one */
  300         mprev->m_next = n0;
  301         m_freem(md);
  302         *lenp = zs.total_out;
  303 
  304         return 0;
  305 
  306 fail:
  307         if (m)
  308                 m_freem(m);
  309         if (n)
  310                 m_freem(n);
  311         if (n0)
  312                 m_freem(n0);
  313         return error;
  314 #undef MOREBLOCK
  315 }
  316 
  317 static int
  318 deflate_compress(struct mbuf *m, struct mbuf *md, size_t *lenp)
  319 {
  320         if (!m)
  321                 panic("m == NULL in deflate_compress");
  322         if (!md)
  323                 panic("md == NULL in deflate_compress");
  324         if (!lenp)
  325                 panic("lenp == NULL in deflate_compress");
  326 
  327         return deflate_common(m, md, lenp, 0);
  328 }
  329 
  330 static int
  331 deflate_decompress(struct mbuf *m, struct mbuf *md, size_t *lenp)
  332 {
  333         if (!m)
  334                 panic("m == NULL in deflate_decompress");
  335         if (!md)
  336                 panic("md == NULL in deflate_decompress");
  337         if (!lenp)
  338                 panic("lenp == NULL in deflate_decompress");
  339 
  340         return deflate_common(m, md, lenp, 1);
  341 }

Cache object: b961b3e51111a16bbef1dbab8a73fb85


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.