Line data Source code
1 : /* $OpenBSD: xform_ipcomp.c,v 1.7 2015/03/16 20:26:24 miod 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 : /*
31 : * This file contains a wrapper around the deflate algo compression
32 : * functions using the zlib library
33 : */
34 :
35 : #include <sys/param.h>
36 : #include <sys/malloc.h>
37 : #include <sys/systm.h>
38 : #include <lib/libz/zutil.h>
39 :
40 : #define Z_METHOD 8
41 : #define Z_MEMLEVEL 8
42 : #define ZBUF 10
43 :
44 : u_int32_t deflate_global(u_int8_t *, u_int32_t, int, u_int8_t **);
45 :
46 : struct deflate_buf {
47 : u_int8_t *out;
48 : u_int32_t size;
49 : int flag;
50 : };
51 :
52 : int window_inflate = -1 * MAX_WBITS;
53 : int window_deflate = -12;
54 :
55 : /*
56 : * This function takes a block of data and (de)compress it using the deflate
57 : * algorithm
58 : */
59 :
60 : u_int32_t
61 0 : deflate_global(u_int8_t *data, u_int32_t size, int decomp, u_int8_t **out)
62 : {
63 0 : z_stream zbuf;
64 : u_int8_t *output;
65 : u_int32_t count, result;
66 : int error, i = 0, j;
67 0 : struct deflate_buf buf[ZBUF];
68 :
69 0 : bzero(&zbuf, sizeof(z_stream));
70 0 : for (j = 0; j < ZBUF; j++)
71 0 : buf[j].flag = 0;
72 :
73 0 : zbuf.next_in = data; /* data that is going to be processed */
74 0 : zbuf.zalloc = zcalloc;
75 0 : zbuf.zfree = zcfree;
76 0 : zbuf.opaque = Z_NULL;
77 0 : zbuf.avail_in = size; /* Total length of data to be processed */
78 :
79 0 : if (decomp) {
80 : /*
81 : * Choose a buffer with 4x the size of the input buffer
82 : * for the size of the output buffer in the case of
83 : * decompression. If it's not sufficient, it will need to be
84 : * updated while the decompression is going on
85 : */
86 0 : if (size < 32 * 1024)
87 0 : size *= 4;
88 : }
89 0 : buf[i].out = malloc((u_long)size, M_CRYPTO_DATA, M_NOWAIT);
90 0 : if (buf[i].out == NULL)
91 : goto bad;
92 0 : buf[i].size = size;
93 0 : buf[i].flag = 1;
94 : i++;
95 :
96 0 : zbuf.next_out = buf[0].out;
97 0 : zbuf.avail_out = buf[0].size;
98 :
99 0 : error = decomp ?
100 0 : inflateInit2(&zbuf, window_inflate) :
101 0 : deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
102 : window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
103 :
104 0 : if (error != Z_OK)
105 : goto bad;
106 0 : for (;;) {
107 0 : error = decomp ?
108 0 : inflate(&zbuf, Z_PARTIAL_FLUSH) :
109 0 : deflate(&zbuf, Z_FINISH);
110 0 : if (error == Z_STREAM_END)
111 : break;
112 0 : if (error != Z_OK)
113 : goto bad;
114 0 : if (zbuf.avail_out == 0 && i < (ZBUF - 1)) {
115 : /* we need more output space, allocate size */
116 0 : if (size < 32 * 1024)
117 0 : size *= 2;
118 0 : buf[i].out = malloc((u_long)size, M_CRYPTO_DATA,
119 : M_NOWAIT);
120 0 : if (buf[i].out == NULL)
121 : goto bad;
122 0 : zbuf.next_out = buf[i].out;
123 0 : buf[i].size = size;
124 0 : buf[i].flag = 1;
125 0 : zbuf.avail_out = buf[i].size;
126 0 : i++;
127 : } else
128 : goto bad; /* out of buffers */
129 : }
130 0 : result = count = zbuf.total_out;
131 :
132 0 : *out = malloc((u_long)result, M_CRYPTO_DATA, M_NOWAIT);
133 0 : if (*out == NULL)
134 : goto bad;
135 0 : if (decomp)
136 0 : inflateEnd(&zbuf);
137 : else
138 0 : deflateEnd(&zbuf);
139 0 : output = *out;
140 0 : for (j = 0; buf[j].flag != 0; j++) {
141 0 : if (count > buf[j].size) {
142 0 : bcopy(buf[j].out, *out, buf[j].size);
143 0 : *out += buf[j].size;
144 0 : free(buf[j].out, M_CRYPTO_DATA, 0);
145 0 : count -= buf[j].size;
146 0 : } else {
147 : /* it should be the last buffer */
148 0 : bcopy(buf[j].out, *out, count);
149 0 : *out += count;
150 0 : free(buf[j].out, M_CRYPTO_DATA, 0);
151 : count = 0;
152 : }
153 : }
154 0 : *out = output;
155 0 : return result;
156 :
157 : bad:
158 0 : *out = NULL;
159 0 : for (j = 0; buf[j].flag != 0; j++)
160 0 : free(buf[j].out, M_CRYPTO_DATA, 0);
161 0 : if (decomp)
162 0 : inflateEnd(&zbuf);
163 : else
164 0 : deflateEnd(&zbuf);
165 0 : return 0;
166 0 : }
|