OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
c_zlib.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <openssl/objects.h>
5 #include <openssl/comp.h>
6 #include <openssl/err.h>
7 
8 COMP_METHOD *COMP_zlib(void );
9 
10 static COMP_METHOD zlib_method_nozlib={
11  NID_undef,
12  "(undef)",
13  NULL,
14  NULL,
15  NULL,
16  NULL,
17  NULL,
18  NULL,
19  };
20 
21 #ifndef ZLIB
22 #undef ZLIB_SHARED
23 #else
24 
25 #include <zlib.h>
26 
27 static int zlib_stateful_init(COMP_CTX *ctx);
28 static void zlib_stateful_finish(COMP_CTX *ctx);
29 static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
30  unsigned int olen, unsigned char *in, unsigned int ilen);
31 static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
32  unsigned int olen, unsigned char *in, unsigned int ilen);
33 
34 
35 /* memory allocations functions for zlib intialization */
36 static void* zlib_zalloc(void* opaque, unsigned int no, unsigned int size)
37 {
38  void *p;
39 
40  p=OPENSSL_malloc(no*size);
41  if (p)
42  memset(p, 0, no*size);
43  return p;
44 }
45 
46 
47 static void zlib_zfree(void* opaque, void* address)
48 {
49  OPENSSL_free(address);
50 }
51 
52 #if 0
53 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
54  unsigned int olen, unsigned char *in, unsigned int ilen);
55 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
56  unsigned int olen, unsigned char *in, unsigned int ilen);
57 
58 static int zz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
59  uLong sourceLen);
60 
61 static COMP_METHOD zlib_stateless_method={
64  NULL,
65  NULL,
66  zlib_compress_block,
67  zlib_expand_block,
68  NULL,
69  NULL,
70  };
71 #endif
72 
73 static COMP_METHOD zlib_stateful_method={
76  zlib_stateful_init,
77  zlib_stateful_finish,
78  zlib_stateful_compress_block,
79  zlib_stateful_expand_block,
80  NULL,
81  NULL,
82  };
83 
84 /*
85  * When OpenSSL is built on Windows, we do not want to require that
86  * the ZLIB.DLL be available in order for the OpenSSL DLLs to
87  * work. Therefore, all ZLIB routines are loaded at run time
88  * and we do not link to a .LIB file when ZLIB_SHARED is set.
89  */
90 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
91 # include <windows.h>
92 #endif /* !(OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32) */
93 
94 #ifdef ZLIB_SHARED
95 #include <openssl/dso.h>
96 
97 /* Function pointers */
98 typedef int (*compress_ft)(Bytef *dest,uLongf *destLen,
99  const Bytef *source, uLong sourceLen);
100 typedef int (*inflateEnd_ft)(z_streamp strm);
101 typedef int (*inflate_ft)(z_streamp strm, int flush);
102 typedef int (*inflateInit__ft)(z_streamp strm,
103  const char * version, int stream_size);
104 typedef int (*deflateEnd_ft)(z_streamp strm);
105 typedef int (*deflate_ft)(z_streamp strm, int flush);
106 typedef int (*deflateInit__ft)(z_streamp strm, int level,
107  const char * version, int stream_size);
108 typedef const char * (*zError__ft)(int err);
109 static compress_ft p_compress=NULL;
110 static inflateEnd_ft p_inflateEnd=NULL;
111 static inflate_ft p_inflate=NULL;
112 static inflateInit__ft p_inflateInit_=NULL;
113 static deflateEnd_ft p_deflateEnd=NULL;
114 static deflate_ft p_deflate=NULL;
115 static deflateInit__ft p_deflateInit_=NULL;
116 static zError__ft p_zError=NULL;
117 
118 static int zlib_loaded = 0; /* only attempt to init func pts once */
119 static DSO *zlib_dso = NULL;
120 
121 #define compress p_compress
122 #define inflateEnd p_inflateEnd
123 #define inflate p_inflate
124 #define inflateInit_ p_inflateInit_
125 #define deflateEnd p_deflateEnd
126 #define deflate p_deflate
127 #define deflateInit_ p_deflateInit_
128 #define zError p_zError
129 #endif /* ZLIB_SHARED */
130 
131 struct zlib_state
132  {
133  z_stream istream;
134  z_stream ostream;
135  };
136 
137 static int zlib_stateful_ex_idx = -1;
138 
139 static int zlib_stateful_init(COMP_CTX *ctx)
140  {
141  int err;
142  struct zlib_state *state =
143  (struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state));
144 
145  if (state == NULL)
146  goto err;
147 
148  state->istream.zalloc = zlib_zalloc;
149  state->istream.zfree = zlib_zfree;
150  state->istream.opaque = Z_NULL;
151  state->istream.next_in = Z_NULL;
152  state->istream.next_out = Z_NULL;
153  state->istream.avail_in = 0;
154  state->istream.avail_out = 0;
155  err = inflateInit_(&state->istream,
156  ZLIB_VERSION, sizeof(z_stream));
157  if (err != Z_OK)
158  goto err;
159 
160  state->ostream.zalloc = zlib_zalloc;
161  state->ostream.zfree = zlib_zfree;
162  state->ostream.opaque = Z_NULL;
163  state->ostream.next_in = Z_NULL;
164  state->ostream.next_out = Z_NULL;
165  state->ostream.avail_in = 0;
166  state->ostream.avail_out = 0;
167  err = deflateInit_(&state->ostream,Z_DEFAULT_COMPRESSION,
168  ZLIB_VERSION, sizeof(z_stream));
169  if (err != Z_OK)
170  goto err;
171 
173  CRYPTO_set_ex_data(&ctx->ex_data,zlib_stateful_ex_idx,state);
174  return 1;
175  err:
176  if (state) OPENSSL_free(state);
177  return 0;
178  }
179 
180 static void zlib_stateful_finish(COMP_CTX *ctx)
181  {
182  struct zlib_state *state =
183  (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
184  zlib_stateful_ex_idx);
185  inflateEnd(&state->istream);
186  deflateEnd(&state->ostream);
187  OPENSSL_free(state);
189  }
190 
191 static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
192  unsigned int olen, unsigned char *in, unsigned int ilen)
193  {
194  int err = Z_OK;
195  struct zlib_state *state =
196  (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
197  zlib_stateful_ex_idx);
198 
199  if (state == NULL)
200  return -1;
201 
202  state->ostream.next_in = in;
203  state->ostream.avail_in = ilen;
204  state->ostream.next_out = out;
205  state->ostream.avail_out = olen;
206  if (ilen > 0)
207  err = deflate(&state->ostream, Z_SYNC_FLUSH);
208  if (err != Z_OK)
209  return -1;
210 #ifdef DEBUG_ZLIB
211  fprintf(stderr,"compress(%4d)->%4d %s\n",
212  ilen,olen - state->ostream.avail_out,
213  (ilen != olen - state->ostream.avail_out)?"zlib":"clear");
214 #endif
215  return olen - state->ostream.avail_out;
216  }
217 
218 static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
219  unsigned int olen, unsigned char *in, unsigned int ilen)
220  {
221  int err = Z_OK;
222 
223  struct zlib_state *state =
224  (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
225  zlib_stateful_ex_idx);
226 
227  if (state == NULL)
228  return 0;
229 
230  state->istream.next_in = in;
231  state->istream.avail_in = ilen;
232  state->istream.next_out = out;
233  state->istream.avail_out = olen;
234  if (ilen > 0)
235  err = inflate(&state->istream, Z_SYNC_FLUSH);
236  if (err != Z_OK)
237  return -1;
238 #ifdef DEBUG_ZLIB
239  fprintf(stderr,"expand(%4d)->%4d %s\n",
240  ilen,olen - state->istream.avail_out,
241  (ilen != olen - state->istream.avail_out)?"zlib":"clear");
242 #endif
243  return olen - state->istream.avail_out;
244  }
245 
246 #if 0
247 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
248  unsigned int olen, unsigned char *in, unsigned int ilen)
249  {
250  unsigned long l;
251  int i;
252  int clear=1;
253 
254  if (ilen > 128)
255  {
256  out[0]=1;
257  l=olen-1;
258  i=compress(&(out[1]),&l,in,(unsigned long)ilen);
259  if (i != Z_OK)
260  return(-1);
261  if (ilen > l)
262  {
263  clear=0;
264  l++;
265  }
266  }
267  if (clear)
268  {
269  out[0]=0;
270  memcpy(&(out[1]),in,ilen);
271  l=ilen+1;
272  }
273 #ifdef DEBUG_ZLIB
274  fprintf(stderr,"compress(%4d)->%4d %s\n",
275  ilen,(int)l,(clear)?"clear":"zlib");
276 #endif
277  return((int)l);
278  }
279 
280 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
281  unsigned int olen, unsigned char *in, unsigned int ilen)
282  {
283  unsigned long l;
284  int i;
285 
286  if (in[0])
287  {
288  l=olen;
289  i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1);
290  if (i != Z_OK)
291  return(-1);
292  }
293  else
294  {
295  memcpy(out,&(in[1]),ilen-1);
296  l=ilen-1;
297  }
298 #ifdef DEBUG_ZLIB
299  fprintf(stderr,"expand (%4d)->%4d %s\n",
300  ilen,(int)l,in[0]?"zlib":"clear");
301 #endif
302  return((int)l);
303  }
304 
305 static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source,
306  uLong sourceLen)
307 {
308  z_stream stream;
309  int err;
310 
311  stream.next_in = (Bytef*)source;
312  stream.avail_in = (uInt)sourceLen;
313  /* Check for source > 64K on 16-bit machine: */
314  if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
315 
316  stream.next_out = dest;
317  stream.avail_out = (uInt)*destLen;
318  if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
319 
320  stream.zalloc = (alloc_func)0;
321  stream.zfree = (free_func)0;
322 
323  err = inflateInit_(&stream,
324  ZLIB_VERSION, sizeof(z_stream));
325  if (err != Z_OK) return err;
326 
327  err = inflate(&stream, Z_FINISH);
328  if (err != Z_STREAM_END) {
329  inflateEnd(&stream);
330  return err;
331  }
332  *destLen = stream.total_out;
333 
334  err = inflateEnd(&stream);
335  return err;
336 }
337 #endif
338 
339 #endif
340 
342  {
343  COMP_METHOD *meth = &zlib_method_nozlib;
344 
345 #ifdef ZLIB_SHARED
346  if (!zlib_loaded)
347  {
348 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
349  zlib_dso = DSO_load(NULL, "ZLIB1", NULL, 0);
350 #else
351  zlib_dso = DSO_load(NULL, "z", NULL, 0);
352 #endif
353  if (zlib_dso != NULL)
354  {
355  p_compress
356  = (compress_ft) DSO_bind_func(zlib_dso,
357  "compress");
358  p_inflateEnd
359  = (inflateEnd_ft) DSO_bind_func(zlib_dso,
360  "inflateEnd");
361  p_inflate
362  = (inflate_ft) DSO_bind_func(zlib_dso,
363  "inflate");
364  p_inflateInit_
365  = (inflateInit__ft) DSO_bind_func(zlib_dso,
366  "inflateInit_");
367  p_deflateEnd
368  = (deflateEnd_ft) DSO_bind_func(zlib_dso,
369  "deflateEnd");
370  p_deflate
371  = (deflate_ft) DSO_bind_func(zlib_dso,
372  "deflate");
373  p_deflateInit_
374  = (deflateInit__ft) DSO_bind_func(zlib_dso,
375  "deflateInit_");
376  p_zError
377  = (zError__ft) DSO_bind_func(zlib_dso,
378  "zError");
379 
380  if (p_compress && p_inflateEnd && p_inflate
381  && p_inflateInit_ && p_deflateEnd
382  && p_deflate && p_deflateInit_ && p_zError)
383  zlib_loaded++;
384  }
385  }
386 
387 #endif
388 #ifdef ZLIB_SHARED
389  if (zlib_loaded)
390 #endif
391 #if defined(ZLIB) || defined(ZLIB_SHARED)
392  {
393  /* init zlib_stateful_ex_idx here so that in a multi-process
394  * application it's enough to intialize openssl before forking
395  * (idx will be inherited in all the children) */
396  if (zlib_stateful_ex_idx == -1)
397  {
399  if (zlib_stateful_ex_idx == -1)
400  zlib_stateful_ex_idx =
402  0,NULL,NULL,NULL,NULL);
404  if (zlib_stateful_ex_idx == -1)
405  goto err;
406  }
407 
408  meth = &zlib_stateful_method;
409  }
410 err:
411 #endif
412 
413  return(meth);
414  }
415 
417  {
418 #ifdef ZLIB_SHARED
419  if (zlib_dso)
420  DSO_free(zlib_dso);
421 #endif
422  }
423 
424 #ifdef ZLIB
425 
426 /* Zlib based compression/decompression filter BIO */
427 
428 typedef struct
429  {
430  unsigned char *ibuf; /* Input buffer */
431  int ibufsize; /* Buffer size */
432  z_stream zin; /* Input decompress context */
433  unsigned char *obuf; /* Output buffer */
434  int obufsize; /* Output buffer size */
435  unsigned char *optr; /* Position in output buffer */
436  int ocount; /* Amount of data in output buffer */
437  int odone; /* deflate EOF */
438  int comp_level; /* Compression level to use */
439  z_stream zout; /* Output compression context */
440  } BIO_ZLIB_CTX;
441 
442 #define ZLIB_DEFAULT_BUFSIZE 1024
443 
444 static int bio_zlib_new(BIO *bi);
445 static int bio_zlib_free(BIO *bi);
446 static int bio_zlib_read(BIO *b, char *out, int outl);
447 static int bio_zlib_write(BIO *b, const char *in, int inl);
448 static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr);
449 static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp);
450 
451 static BIO_METHOD bio_meth_zlib =
452  {
454  "zlib",
455  bio_zlib_write,
456  bio_zlib_read,
457  NULL,
458  NULL,
459  bio_zlib_ctrl,
460  bio_zlib_new,
461  bio_zlib_free,
462  bio_zlib_callback_ctrl
463  };
464 
465 BIO_METHOD *BIO_f_zlib(void)
466  {
467  return &bio_meth_zlib;
468  }
469 
470 
471 static int bio_zlib_new(BIO *bi)
472  {
473  BIO_ZLIB_CTX *ctx;
474 #ifdef ZLIB_SHARED
475  (void)COMP_zlib();
476  if (!zlib_loaded)
477  {
479  return 0;
480  }
481 #endif
482  ctx = OPENSSL_malloc(sizeof(BIO_ZLIB_CTX));
483  if(!ctx)
484  {
486  return 0;
487  }
488  ctx->ibuf = NULL;
489  ctx->obuf = NULL;
490  ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE;
491  ctx->obufsize = ZLIB_DEFAULT_BUFSIZE;
492  ctx->zin.zalloc = Z_NULL;
493  ctx->zin.zfree = Z_NULL;
494  ctx->zin.next_in = NULL;
495  ctx->zin.avail_in = 0;
496  ctx->zin.next_out = NULL;
497  ctx->zin.avail_out = 0;
498  ctx->zout.zalloc = Z_NULL;
499  ctx->zout.zfree = Z_NULL;
500  ctx->zout.next_in = NULL;
501  ctx->zout.avail_in = 0;
502  ctx->zout.next_out = NULL;
503  ctx->zout.avail_out = 0;
504  ctx->odone = 0;
505  ctx->comp_level = Z_DEFAULT_COMPRESSION;
506  bi->init = 1;
507  bi->ptr = (char *)ctx;
508  bi->flags = 0;
509  return 1;
510  }
511 
512 static int bio_zlib_free(BIO *bi)
513  {
514  BIO_ZLIB_CTX *ctx;
515  if(!bi) return 0;
516  ctx = (BIO_ZLIB_CTX *)bi->ptr;
517  if(ctx->ibuf)
518  {
519  /* Destroy decompress context */
520  inflateEnd(&ctx->zin);
521  OPENSSL_free(ctx->ibuf);
522  }
523  if(ctx->obuf)
524  {
525  /* Destroy compress context */
526  deflateEnd(&ctx->zout);
527  OPENSSL_free(ctx->obuf);
528  }
529  OPENSSL_free(ctx);
530  bi->ptr = NULL;
531  bi->init = 0;
532  bi->flags = 0;
533  return 1;
534  }
535 
536 static int bio_zlib_read(BIO *b, char *out, int outl)
537  {
538  BIO_ZLIB_CTX *ctx;
539  int ret;
540  z_stream *zin;
541  if(!out || !outl) return 0;
542  ctx = (BIO_ZLIB_CTX *)b->ptr;
543  zin = &ctx->zin;
545  if(!ctx->ibuf)
546  {
547  ctx->ibuf = OPENSSL_malloc(ctx->ibufsize);
548  if(!ctx->ibuf)
549  {
551  return 0;
552  }
553  inflateInit(zin);
554  zin->next_in = ctx->ibuf;
555  zin->avail_in = 0;
556  }
557 
558  /* Copy output data directly to supplied buffer */
559  zin->next_out = (unsigned char *)out;
560  zin->avail_out = (unsigned int)outl;
561  for(;;)
562  {
563  /* Decompress while data available */
564  while(zin->avail_in)
565  {
566  ret = inflate(zin, 0);
567  if((ret != Z_OK) && (ret != Z_STREAM_END))
568  {
571  ERR_add_error_data(2, "zlib error:",
572  zError(ret));
573  return 0;
574  }
575  /* If EOF or we've read everything then return */
576  if((ret == Z_STREAM_END) || !zin->avail_out)
577  return outl - zin->avail_out;
578  }
579 
580  /* No data in input buffer try to read some in,
581  * if an error then return the total data read.
582  */
583  ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize);
584  if(ret <= 0)
585  {
586  /* Total data read */
587  int tot = outl - zin->avail_out;
589  if(ret < 0) return (tot > 0) ? tot : ret;
590  return tot;
591  }
592  zin->avail_in = ret;
593  zin->next_in = ctx->ibuf;
594  }
595  }
596 
597 static int bio_zlib_write(BIO *b, const char *in, int inl)
598  {
599  BIO_ZLIB_CTX *ctx;
600  int ret;
601  z_stream *zout;
602  if(!in || !inl) return 0;
603  ctx = (BIO_ZLIB_CTX *)b->ptr;
604  if(ctx->odone) return 0;
605  zout = &ctx->zout;
607  if(!ctx->obuf)
608  {
609  ctx->obuf = OPENSSL_malloc(ctx->obufsize);
610  /* Need error here */
611  if(!ctx->obuf)
612  {
614  return 0;
615  }
616  ctx->optr = ctx->obuf;
617  ctx->ocount = 0;
618  deflateInit(zout, ctx->comp_level);
619  zout->next_out = ctx->obuf;
620  zout->avail_out = ctx->obufsize;
621  }
622  /* Obtain input data directly from supplied buffer */
623  zout->next_in = (void *)in;
624  zout->avail_in = inl;
625  for(;;)
626  {
627  /* If data in output buffer write it first */
628  while(ctx->ocount) {
629  ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
630  if(ret <= 0)
631  {
632  /* Total data written */
633  int tot = inl - zout->avail_in;
635  if(ret < 0) return (tot > 0) ? tot : ret;
636  return tot;
637  }
638  ctx->optr += ret;
639  ctx->ocount -= ret;
640  }
641 
642  /* Have we consumed all supplied data? */
643  if(!zout->avail_in)
644  return inl;
645 
646  /* Compress some more */
647 
648  /* Reset buffer */
649  ctx->optr = ctx->obuf;
650  zout->next_out = ctx->obuf;
651  zout->avail_out = ctx->obufsize;
652  /* Compress some more */
653  ret = deflate(zout, 0);
654  if(ret != Z_OK)
655  {
658  ERR_add_error_data(2, "zlib error:", zError(ret));
659  return 0;
660  }
661  ctx->ocount = ctx->obufsize - zout->avail_out;
662  }
663  }
664 
665 static int bio_zlib_flush(BIO *b)
666  {
667  BIO_ZLIB_CTX *ctx;
668  int ret;
669  z_stream *zout;
670  ctx = (BIO_ZLIB_CTX *)b->ptr;
671  /* If no data written or already flush show success */
672  if(!ctx->obuf || (ctx->odone && !ctx->ocount)) return 1;
673  zout = &ctx->zout;
675  /* No more input data */
676  zout->next_in = NULL;
677  zout->avail_in = 0;
678  for(;;)
679  {
680  /* If data in output buffer write it first */
681  while(ctx->ocount)
682  {
683  ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
684  if(ret <= 0)
685  {
687  return ret;
688  }
689  ctx->optr += ret;
690  ctx->ocount -= ret;
691  }
692  if(ctx->odone) return 1;
693 
694  /* Compress some more */
695 
696  /* Reset buffer */
697  ctx->optr = ctx->obuf;
698  zout->next_out = ctx->obuf;
699  zout->avail_out = ctx->obufsize;
700  /* Compress some more */
701  ret = deflate(zout, Z_FINISH);
702  if(ret == Z_STREAM_END) ctx->odone = 1;
703  else if(ret != Z_OK)
704  {
707  ERR_add_error_data(2, "zlib error:", zError(ret));
708  return 0;
709  }
710  ctx->ocount = ctx->obufsize - zout->avail_out;
711  }
712  }
713 
714 static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
715  {
716  BIO_ZLIB_CTX *ctx;
717  int ret, *ip;
718  int ibs, obs;
719  if(!b->next_bio) return 0;
720  ctx = (BIO_ZLIB_CTX *)b->ptr;
721  switch (cmd)
722  {
723 
724  case BIO_CTRL_RESET:
725  ctx->ocount = 0;
726  ctx->odone = 0;
727  ret = 1;
728  break;
729 
730  case BIO_CTRL_FLUSH:
731  ret = bio_zlib_flush(b);
732  if (ret > 0)
733  ret = BIO_flush(b->next_bio);
734  break;
735 
736  case BIO_C_SET_BUFF_SIZE:
737  ibs = -1;
738  obs = -1;
739  if (ptr != NULL)
740  {
741  ip = ptr;
742  if (*ip == 0)
743  ibs = (int) num;
744  else
745  obs = (int) num;
746  }
747  else
748  {
749  ibs = (int)num;
750  obs = ibs;
751  }
752 
753  if (ibs != -1)
754  {
755  if (ctx->ibuf)
756  {
757  OPENSSL_free(ctx->ibuf);
758  ctx->ibuf = NULL;
759  }
760  ctx->ibufsize = ibs;
761  }
762 
763  if (obs != -1)
764  {
765  if (ctx->obuf)
766  {
767  OPENSSL_free(ctx->obuf);
768  ctx->obuf = NULL;
769  }
770  ctx->obufsize = obs;
771  }
772  ret = 1;
773  break;
774 
777  ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
779  break;
780 
781  default:
782  ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
783  break;
784 
785  }
786 
787  return ret;
788  }
789 
790 
791 static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
792  {
793  if(!b->next_bio)
794  return 0;
795  return
796  BIO_callback_ctrl(b->next_bio, cmd, fp);
797  }
798 
799 #endif