SUBDIRS += pppd/plugins
endif
-DIST_SUBDIRS = $(SUBDIRS) common include modules scripts
-
-#
-# *HACK*
-# This is to work around the kernel module for PPP on Sun Solaris
-if SUNOS
-all-am:
- (cd solaris ; $(MAKE) -f Makefile)
-
-clean-generic:
- (cd solaris ; $(MAKE) -f Makefile clean)
-
-install-am:
- (cd solaris ; $(MAKE) -f Makefile install)
-endif
+DIST_SUBDIRS = $(SUBDIRS) include scripts
install-data-hook:
(cd $(DESTDIR)/$(sysconfdir)/$(PACKAGE) ; \
SETUP \
Submitting-patches.md
-EXTRA_SOLARIS = \
- solaris/Makedefs \
- solaris/Makedefs.gcc \
- solaris/Makedefs.sol2 \
- solaris/Makefile.sol2 \
- solaris/Makefile.sol2-64 \
- solaris/Makefile.sol2-64x \
- solaris/Makefile.sol2gcc \
- solaris/Makefile.sol2gcc-64 \
- solaris/Makefile.sol2gcc-64x \
- solaris/Makefile.top \
- solaris/ppp_ahdlc.c \
- solaris/ppp_ahdlc_mod.c \
- solaris/ppp.c \
- solaris/ppp_comp.c \
- solaris/ppp_comp_mod.c \
- solaris/ppp.conf \
- solaris/ppp_mod.c \
- solaris/ppp_mod.h
-
EXTRA_DIST= \
$(sample_DATA) \
- $(EXTRA_README) \
- $(EXTRA_SOLARIS)
+ $(EXTRA_README)
+++ /dev/null
-EXTRA_ZLIB = \
- zlib.c \
- zlib.h
-
-EXTRA_DIST = \
- $(EXTRA_ZLIB)
+++ /dev/null
-/*
- * This file is derived from various .h and .c files from the zlib-1.0.4
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets. See zlib.h for conditions of
- * distribution and use.
- *
- * Changes that have been made include:
- * - added Z_PACKET_FLUSH (see zlib.h for details)
- * - added inflateIncomp and deflateOutputPending
- * - allow strm->next_out to be NULL, meaning discard the output
- *
- * $Id: zlib.c,v 1.12 2002/04/02 13:34:03 dfs Exp $
- */
-
-/*
- * ==FILEVERSION 971210==
- *
- * This marker is used by the Linux installation script to determine
- * whether an up-to-date version of this file is already installed.
- */
-
-#define NO_DUMMY_DECL
-#define NO_ZCFUNCS
-#define MY_ZCALLOC
-
-#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL))
-#define inflate inflate_ppp /* FreeBSD already has an inflate :-( */
-#endif
-
-
-/* +++ zutil.h */
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-1996 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-/* From: zutil.h,v 1.16 1996/07/24 13:41:13 me Exp $ */
-
-#ifndef _Z_UTIL_H
-#define _Z_UTIL_H
-
-#include "zlib.h"
-
-#if defined(KERNEL) || defined(_KERNEL)
-/* Assume this is a *BSD or SVR4 kernel */
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/systm.h>
-#undef u
-# define HAVE_MEMCPY
-# define memcpy(d, s, n) bcopy((s), (d), (n))
-# define memset(d, v, n) bzero((d), (n))
-# define memcmp bcmp
-
-#else
-#if defined(__KERNEL__)
-/* Assume this is a Linux kernel */
-#include <linux/string.h>
-#define HAVE_MEMCPY
-
-#else /* not kernel */
-
-#if defined(MSDOS)||defined(VMS)||defined(CRAY)||defined(WIN32)||defined(RISCOS)
-# include <stddef.h>
-# include <errno.h>
-#else
- extern int errno;
-#endif
-#ifdef STDC
-# include <string.h>
-# include <stdlib.h>
-#endif
-#endif /* __KERNEL__ */
-#endif /* _KERNEL || KERNEL */
-
-#ifndef local
-# define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-typedef unsigned char uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long ulg;
-
-extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
-/* (size given to avoid silly warnings with Visual C++) */
-
-#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
-
-#define ERR_RETURN(strm,err) \
- return (strm->msg = (char*)ERR_MSG(err), (err))
-/* To be used only when the state is known to be valid */
-
- /* common constants */
-
-#ifndef DEF_WBITS
-# define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-# define DEF_MEM_LEVEL 8
-#else
-# define DEF_MEM_LEVEL MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES 2
-/* The three kinds of block type */
-
-#define MIN_MATCH 3
-#define MAX_MATCH 258
-/* The minimum and maximum match lengths */
-
-#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
-
- /* target dependencies */
-
-#ifdef MSDOS
-# define OS_CODE 0x00
-# ifdef __TURBOC__
-# include <alloc.h>
-# else /* MSC or DJGPP */
-# include <malloc.h>
-# endif
-#endif
-
-#ifdef OS2
-# define OS_CODE 0x06
-#endif
-
-#ifdef WIN32 /* Window 95 & Windows NT */
-# define OS_CODE 0x0b
-#endif
-
-#if defined(VAXC) || defined(VMS)
-# define OS_CODE 0x02
-# define FOPEN(name, mode) \
- fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
-#endif
-
-#ifdef AMIGA
-# define OS_CODE 0x01
-#endif
-
-#if defined(ATARI) || defined(atarist)
-# define OS_CODE 0x05
-#endif
-
-#ifdef MACOS
-# define OS_CODE 0x07
-#endif
-
-#ifdef __50SERIES /* Prime/PRIMOS */
-# define OS_CODE 0x0F
-#endif
-
-#ifdef TOPS20
-# define OS_CODE 0x0a
-#endif
-
-#if defined(_BEOS_) || defined(RISCOS)
-# define fdopen(fd,mode) NULL /* No fdopen() */
-#endif
-
- /* Common defaults */
-
-#ifndef OS_CODE
-# define OS_CODE 0x03 /* assume Unix */
-#endif
-
-#ifndef FOPEN
-# define FOPEN(name, mode) fopen((name), (mode))
-#endif
-
- /* functions */
-
-#ifdef HAVE_STRERROR
- extern char *strerror OF((int));
-# define zstrerror(errnum) strerror(errnum)
-#else
-# define zstrerror(errnum) ""
-#endif
-
-#if defined(pyr)
-# define NO_MEMCPY
-#endif
-#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(_MSC_VER)
- /* Use our own functions for small and medium model with MSC <= 5.0.
- * You may have to use the same strategy for Borland C (untested).
- */
-# define NO_MEMCPY
-#endif
-#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
-# define HAVE_MEMCPY
-#endif
-#ifdef HAVE_MEMCPY
-# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
-# define zmemcpy _fmemcpy
-# define zmemcmp _fmemcmp
-# define zmemzero(dest, len) _fmemset(dest, 0, len)
-# else
-# define zmemcpy memcpy
-# define zmemcmp memcmp
-# define zmemzero(dest, len) memset(dest, 0, len)
-# endif
-#else
- extern void zmemcpy OF((Bytef* dest, Bytef* source, uInt len));
- extern int zmemcmp OF((Bytef* s1, Bytef* s2, uInt len));
- extern void zmemzero OF((Bytef* dest, uInt len));
-#endif
-
-/* Diagnostic functions */
-#ifdef DEBUG_ZLIB
-# include <stdio.h>
-# ifndef verbose
-# define verbose 0
-# endif
- extern void z_error OF((char *m));
-# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
-# define Trace(x) fprintf x
-# define Tracev(x) {if (verbose) fprintf x ;}
-# define Tracevv(x) {if (verbose>1) fprintf x ;}
-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-# define Assert(cond,msg)
-# define Trace(x)
-# define Tracev(x)
-# define Tracevv(x)
-# define Tracec(c,x)
-# define Tracecv(c,x)
-#endif
-
-
-typedef uLong (*check_func) OF((uLong check, const Bytef *buf, uInt len));
-
-voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
-void zcfree OF((voidpf opaque, voidpf ptr));
-
-#define ZALLOC(strm, items, size) \
- (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
-#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
-
-#endif /* _Z_UTIL_H */
-/* --- zutil.h */
-
-/* +++ deflate.h */
-/* deflate.h -- internal compression state
- * Copyright (C) 1995-1996 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-/* From: deflate.h,v 1.10 1996/07/02 12:41:00 me Exp $ */
-
-#ifndef _DEFLATE_H
-#define _DEFLATE_H
-
-/* #include "zutil.h" */
-
-/* ===========================================================================
- * Internal compression state.
- */
-
-#define LENGTH_CODES 29
-/* number of length codes, not counting the special END_BLOCK code */
-
-#define LITERALS 256
-/* number of literal bytes 0..255 */
-
-#define L_CODES (LITERALS+1+LENGTH_CODES)
-/* number of Literal or Length codes, including the END_BLOCK code */
-
-#define D_CODES 30
-/* number of distance codes */
-
-#define BL_CODES 19
-/* number of codes used to transfer the bit lengths */
-
-#define HEAP_SIZE (2*L_CODES+1)
-/* maximum heap size */
-
-#define MAX_BITS 15
-/* All codes must not exceed MAX_BITS bits */
-
-#define INIT_STATE 42
-#define BUSY_STATE 113
-#define FINISH_STATE 666
-/* Stream status */
-
-
-/* Data structure describing a single value and its code string. */
-typedef struct ct_data_s {
- union {
- ush freq; /* frequency count */
- ush code; /* bit string */
- } fc;
- union {
- ush dad; /* father node in Huffman tree */
- ush len; /* length of bit string */
- } dl;
-} FAR ct_data;
-
-#define Freq fc.freq
-#define Code fc.code
-#define Dad dl.dad
-#define Len dl.len
-
-typedef struct static_tree_desc_s static_tree_desc;
-
-typedef struct tree_desc_s {
- ct_data *dyn_tree; /* the dynamic tree */
- int max_code; /* largest code with non zero frequency */
- static_tree_desc *stat_desc; /* the corresponding static tree */
-} FAR tree_desc;
-
-typedef ush Pos;
-typedef Pos FAR Posf;
-typedef unsigned IPos;
-
-/* A Pos is an index in the character window. We use short instead of int to
- * save space in the various tables. IPos is used only for parameter passing.
- */
-
-typedef struct deflate_state {
- z_streamp strm; /* pointer back to this zlib stream */
- int status; /* as the name implies */
- Bytef *pending_buf; /* output still pending */
- ulg pending_buf_size; /* size of pending_buf */
- Bytef *pending_out; /* next pending byte to output to the stream */
- int pending; /* nb of bytes in the pending buffer */
- int noheader; /* suppress zlib header and adler32 */
- Byte data_type; /* UNKNOWN, BINARY or ASCII */
- Byte method; /* STORED (for zip only) or DEFLATED */
- int last_flush; /* value of flush param for previous deflate call */
-
- /* used by deflate.c: */
-
- uInt w_size; /* LZ77 window size (32K by default) */
- uInt w_bits; /* log2(w_size) (8..16) */
- uInt w_mask; /* w_size - 1 */
-
- Bytef *window;
- /* Sliding window. Input bytes are read into the second half of the window,
- * and move to the first half later to keep a dictionary of at least wSize
- * bytes. With this organization, matches are limited to a distance of
- * wSize-MAX_MATCH bytes, but this ensures that IO is always
- * performed with a length multiple of the block size. Also, it limits
- * the window size to 64K, which is quite useful on MSDOS.
- * To do: use the user input buffer as sliding window.
- */
-
- ulg window_size;
- /* Actual size of window: 2*wSize, except when the user input buffer
- * is directly used as sliding window.
- */
-
- Posf *prev;
- /* Link to older string with same hash index. To limit the size of this
- * array to 64K, this link is maintained only for the last 32K strings.
- * An index in this array is thus a window index modulo 32K.
- */
-
- Posf *head; /* Heads of the hash chains or NIL. */
-
- uInt ins_h; /* hash index of string to be inserted */
- uInt hash_size; /* number of elements in hash table */
- uInt hash_bits; /* log2(hash_size) */
- uInt hash_mask; /* hash_size-1 */
-
- uInt hash_shift;
- /* Number of bits by which ins_h must be shifted at each input
- * step. It must be such that after MIN_MATCH steps, the oldest
- * byte no longer takes part in the hash key, that is:
- * hash_shift * MIN_MATCH >= hash_bits
- */
-
- long block_start;
- /* Window position at the beginning of the current output block. Gets
- * negative when the window is moved backwards.
- */
-
- uInt match_length; /* length of best match */
- IPos prev_match; /* previous match */
- int match_available; /* set if previous match exists */
- uInt strstart; /* start of string to insert */
- uInt match_start; /* start of matching string */
- uInt lookahead; /* number of valid bytes ahead in window */
-
- uInt prev_length;
- /* Length of the best match at previous step. Matches not greater than this
- * are discarded. This is used in the lazy match evaluation.
- */
-
- uInt max_chain_length;
- /* To speed up deflation, hash chains are never searched beyond this
- * length. A higher limit improves compression ratio but degrades the
- * speed.
- */
-
- uInt max_lazy_match;
- /* Attempt to find a better match only when the current match is strictly
- * smaller than this value. This mechanism is used only for compression
- * levels >= 4.
- */
-# define max_insert_length max_lazy_match
- /* Insert new strings in the hash table only if the match length is not
- * greater than this length. This saves time but degrades compression.
- * max_insert_length is used only for compression levels <= 3.
- */
-
- int level; /* compression level (1..9) */
- int strategy; /* favor or force Huffman coding*/
-
- uInt good_match;
- /* Use a faster search when the previous match is longer than this */
-
- int nice_match; /* Stop searching when current match exceeds this */
-
- /* used by trees.c: */
- /* Didn't use ct_data typedef below to supress compiler warning */
- struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
- struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
- struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
-
- struct tree_desc_s l_desc; /* desc. for literal tree */
- struct tree_desc_s d_desc; /* desc. for distance tree */
- struct tree_desc_s bl_desc; /* desc. for bit length tree */
-
- ush bl_count[MAX_BITS+1];
- /* number of codes at each bit length for an optimal tree */
-
- int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
- int heap_len; /* number of elements in the heap */
- int heap_max; /* element of largest frequency */
- /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
- * The same heap array is used to build all trees.
- */
-
- uch depth[2*L_CODES+1];
- /* Depth of each subtree used as tie breaker for trees of equal frequency
- */
-
- uchf *l_buf; /* buffer for literals or lengths */
-
- uInt lit_bufsize;
- /* Size of match buffer for literals/lengths. There are 4 reasons for
- * limiting lit_bufsize to 64K:
- * - frequencies can be kept in 16 bit counters
- * - if compression is not successful for the first block, all input
- * data is still in the window so we can still emit a stored block even
- * when input comes from standard input. (This can also be done for
- * all blocks if lit_bufsize is not greater than 32K.)
- * - if compression is not successful for a file smaller than 64K, we can
- * even emit a stored file instead of a stored block (saving 5 bytes).
- * This is applicable only for zip (not gzip or zlib).
- * - creating new Huffman trees less frequently may not provide fast
- * adaptation to changes in the input data statistics. (Take for
- * example a binary file with poorly compressible code followed by
- * a highly compressible string table.) Smaller buffer sizes give
- * fast adaptation but have of course the overhead of transmitting
- * trees more frequently.
- * - I can't count above 4
- */
-
- uInt last_lit; /* running index in l_buf */
-
- ushf *d_buf;
- /* Buffer for distances. To simplify the code, d_buf and l_buf have
- * the same number of elements. To use different lengths, an extra flag
- * array would be necessary.
- */
-
- ulg opt_len; /* bit length of current block with optimal trees */
- ulg static_len; /* bit length of current block with static trees */
- ulg compressed_len; /* total bit length of compressed file */
- uInt matches; /* number of string matches in current block */
- int last_eob_len; /* bit length of EOB code for last block */
-
-#ifdef DEBUG_ZLIB
- ulg bits_sent; /* bit length of the compressed data */
-#endif
-
- ush bi_buf;
- /* Output buffer. bits are inserted starting at the bottom (least
- * significant bits).
- */
- int bi_valid;
- /* Number of valid bits in bi_buf. All bits above the last valid bit
- * are always zero.
- */
-
-} FAR deflate_state;
-
-/* Output a byte on the stream.
- * IN assertion: there is enough room in pending_buf.
- */
-#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
-
-
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
-#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
-/* In order to simplify the code, particularly on 16 bit machines, match
- * distances are limited to MAX_DIST instead of WSIZE.
- */
-
- /* in trees.c */
-void _tr_init OF((deflate_state *s));
-int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
-ulg _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
- int eof));
-void _tr_align OF((deflate_state *s));
-void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
- int eof));
-void _tr_stored_type_only OF((deflate_state *));
-
-#endif
-/* --- deflate.h */
-
-/* +++ deflate.c */
-/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-1996 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- * ALGORITHM
- *
- * The "deflation" process depends on being able to identify portions
- * of the input text which are identical to earlier input (within a
- * sliding window trailing behind the input currently being processed).
- *
- * The most straightforward technique turns out to be the fastest for
- * most input files: try all possible matches and select the longest.
- * The key feature of this algorithm is that insertions into the string
- * dictionary are very simple and thus fast, and deletions are avoided
- * completely. Insertions are performed at each input character, whereas
- * string matches are performed only when the previous match ends. So it
- * is preferable to spend more time in matches to allow very fast string
- * insertions and avoid deletions. The matching algorithm for small
- * strings is inspired from that of Rabin & Karp. A brute force approach
- * is used to find longer strings when a small match has been found.
- * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
- * (by Leonid Broukhis).
- * A previous version of this file used a more sophisticated algorithm
- * (by Fiala and Greene) which is guaranteed to run in linear amortized
- * time, but has a larger average cost, uses more memory and is patented.
- * However the F&G algorithm may be faster for some highly redundant
- * files if the parameter max_chain_length (described below) is too large.
- *
- * ACKNOWLEDGEMENTS
- *
- * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
- * I found it in 'freeze' written by Leonid Broukhis.
- * Thanks to many people for bug reports and testing.
- *
- * REFERENCES
- *
- * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
- * Available in ftp://ds.internic.net/rfc/rfc1951.txt
- *
- * A description of the Rabin and Karp algorithm is given in the book
- * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
- *
- * Fiala,E.R., and Greene,D.H.
- * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
- *
- */
-
-/* From: deflate.c,v 1.15 1996/07/24 13:40:58 me Exp $ */
-
-/* #include "deflate.h" */
-
-char deflate_copyright[] = " deflate 1.0.4 Copyright 1995-1996 Jean-loup Gailly ";
-/*
- If you use the zlib library in a product, an acknowledgment is welcome
- in the documentation of your product. If for some reason you cannot
- include such an acknowledgment, I would appreciate that you keep this
- copyright string in the executable of your product.
- */
-
-/* ===========================================================================
- * Function prototypes.
- */
-typedef enum {
- need_more, /* block not completed, need more input or more output */
- block_done, /* block flush performed */
- finish_started, /* finish started, need only more output at next deflate */
- finish_done /* finish done, accept no more input or output */
-} block_state;
-
-typedef block_state (*compress_func) OF((deflate_state *s, int flush));
-/* Compression function. Returns the block state after the call. */
-
-local void fill_window OF((deflate_state *s));
-local block_state deflate_stored OF((deflate_state *s, int flush));
-local block_state deflate_fast OF((deflate_state *s, int flush));
-local block_state deflate_slow OF((deflate_state *s, int flush));
-local void lm_init OF((deflate_state *s));
-local void putShortMSB OF((deflate_state *s, uInt b));
-local void flush_pending OF((z_streamp strm));
-local int read_buf OF((z_streamp strm, charf *buf, unsigned size));
-#ifdef ASMV
- void match_init OF((void)); /* asm code initialization */
- uInt longest_match OF((deflate_state *s, IPos cur_match));
-#else
-local uInt longest_match OF((deflate_state *s, IPos cur_match));
-#endif
-
-#ifdef DEBUG_ZLIB
-local void check_match OF((deflate_state *s, IPos start, IPos match,
- int length));
-#endif
-
-/* ===========================================================================
- * Local data
- */
-
-#define NIL 0
-/* Tail of hash chains */
-
-#ifndef TOO_FAR
-# define TOO_FAR 4096
-#endif
-/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
-
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
-/* Values for max_lazy_match, good_match and max_chain_length, depending on
- * the desired pack level (0..9). The values given below have been tuned to
- * exclude worst case performance for pathological files. Better values may be
- * found for specific files.
- */
-typedef struct config_s {
- ush good_length; /* reduce lazy search above this match length */
- ush max_lazy; /* do not perform lazy search above this match length */
- ush nice_length; /* quit search above this match length */
- ush max_chain;
- compress_func func;
-} config;
-
-local config configuration_table[10] = {
-/* good lazy nice chain */
-/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
-/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */
-/* 2 */ {4, 5, 16, 8, deflate_fast},
-/* 3 */ {4, 6, 32, 32, deflate_fast},
-
-/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
-/* 5 */ {8, 16, 32, 32, deflate_slow},
-/* 6 */ {8, 16, 128, 128, deflate_slow},
-/* 7 */ {8, 32, 128, 256, deflate_slow},
-/* 8 */ {32, 128, 258, 1024, deflate_slow},
-/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
-
-/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
- * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
- * meaning.
- */
-
-#define EQUAL 0
-/* result of memcmp for equal strings */
-
-#ifndef NO_DUMMY_DECL
-struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
-#endif
-
-/* ===========================================================================
- * Update a hash value with the given input byte
- * IN assertion: all calls to to UPDATE_HASH are made with consecutive
- * input characters, so that a running hash key can be computed from the
- * previous key instead of complete recalculation each time.
- */
-#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
-
-
-/* ===========================================================================
- * Insert string str in the dictionary and set match_head to the previous head
- * of the hash chain (the most recent string with same hash key). Return
- * the previous length of the hash chain.
- * IN assertion: all calls to to INSERT_STRING are made with consecutive
- * input characters and the first MIN_MATCH bytes of str are valid
- * (except for the last MIN_MATCH-1 bytes of the input file).
- */
-#define INSERT_STRING(s, str, match_head) \
- (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
- s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
- s->head[s->ins_h] = (Pos)(str))
-
-/* ===========================================================================
- * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
- * prev[] will be initialized on the fly.
- */
-#define CLEAR_HASH(s) \
- s->head[s->hash_size-1] = NIL; \
- zmemzero((charf *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
-
-/* ========================================================================= */
-int deflateInit_(strm, level, version, stream_size)
- z_streamp strm;
- int level;
- const char *version;
- int stream_size;
-{
- return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
- Z_DEFAULT_STRATEGY, version, stream_size);
- /* To do: ignore strm->next_in if we use it as window */
-}
-
-/* ========================================================================= */
-int deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
- version, stream_size)
- z_streamp strm;
- int level;
- int method;
- int windowBits;
- int memLevel;
- int strategy;
- const char *version;
- int stream_size;
-{
- deflate_state *s;
- int noheader = 0;
- static char* my_version = ZLIB_VERSION;
-
- ushf *overlay;
- /* We overlay pending_buf and d_buf+l_buf. This works since the average
- * output size for (length,distance) codes is <= 24 bits.
- */
-
- if (version == Z_NULL || version[0] != my_version[0] ||
- stream_size != sizeof(z_stream)) {
- return Z_VERSION_ERROR;
- }
- if (strm == Z_NULL) return Z_STREAM_ERROR;
-
- strm->msg = Z_NULL;
-#ifndef NO_ZCFUNCS
- if (strm->zalloc == Z_NULL) {
- strm->zalloc = zcalloc;
- strm->opaque = (voidpf)0;
- }
- if (strm->zfree == Z_NULL) strm->zfree = zcfree;
-#endif
-
- if (level == Z_DEFAULT_COMPRESSION) level = 6;
-
- if (windowBits < 0) { /* undocumented feature: suppress zlib header */
- noheader = 1;
- windowBits = -windowBits;
- }
- if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
- windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
- strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
- return Z_STREAM_ERROR;
- }
- s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
- if (s == Z_NULL) return Z_MEM_ERROR;
- strm->state = (struct internal_state FAR *)s;
- s->strm = strm;
-
- s->noheader = noheader;
- s->w_bits = windowBits;
- s->w_size = 1 << s->w_bits;
- s->w_mask = s->w_size - 1;
-
- s->hash_bits = memLevel + 7;
- s->hash_size = 1 << s->hash_bits;
- s->hash_mask = s->hash_size - 1;
- s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
-
- s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
- s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
- s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
-
- s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
-
- overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
- s->pending_buf = (uchf *) overlay;
- s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
-
- if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
- s->pending_buf == Z_NULL) {
- strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
- deflateEnd (strm);
- return Z_MEM_ERROR;
- }
- s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
- s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
-
- s->level = level;
- s->strategy = strategy;
- s->method = (Byte)method;
-
- return deflateReset(strm);
-}
-
-/* ========================================================================= */
-int deflateSetDictionary (strm, dictionary, dictLength)
- z_streamp strm;
- const Bytef *dictionary;
- uInt dictLength;
-{
- deflate_state *s;
- uInt length = dictLength;
- uInt n;
- IPos hash_head = 0;
-
- if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL)
- return Z_STREAM_ERROR;
-
- s = (deflate_state *) strm->state;
- if (s->status != INIT_STATE) return Z_STREAM_ERROR;
-
- strm->adler = adler32(strm->adler, dictionary, dictLength);
-
- if (length < MIN_MATCH) return Z_OK;
- if (length > MAX_DIST(s)) {
- length = MAX_DIST(s);
-#ifndef USE_DICT_HEAD
- dictionary += dictLength - length; /* use the tail of the dictionary */
-#endif
- }
- zmemcpy((charf *)s->window, dictionary, length);
- s->strstart = length;
- s->block_start = (long)length;
-
- /* Insert all strings in the hash table (except for the last two bytes).
- * s->lookahead stays null, so s->ins_h will be recomputed at the next
- * call of fill_window.
- */
- s->ins_h = s->window[0];
- UPDATE_HASH(s, s->ins_h, s->window[1]);
- for (n = 0; n <= length - MIN_MATCH; n++) {
- INSERT_STRING(s, n, hash_head);
- }
- if (hash_head) hash_head = 0; /* to make compiler happy */
- return Z_OK;
-}
-
-/* ========================================================================= */
-int deflateReset (strm)
- z_streamp strm;
-{
- deflate_state *s;
-
- if (strm == Z_NULL || strm->state == Z_NULL ||
- strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
-
- strm->total_in = strm->total_out = 0;
- strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
- strm->data_type = Z_UNKNOWN;
-
- s = (deflate_state *)strm->state;
- s->pending = 0;
- s->pending_out = s->pending_buf;
-
- if (s->noheader < 0) {
- s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
- }
- s->status = s->noheader ? BUSY_STATE : INIT_STATE;
- strm->adler = 1;
- s->last_flush = Z_NO_FLUSH;
-
- _tr_init(s);
- lm_init(s);
-
- return Z_OK;
-}
-
-/* ========================================================================= */
-int deflateParams(strm, level, strategy)
- z_streamp strm;
- int level;
- int strategy;
-{
- deflate_state *s;
- compress_func func;
- int err = Z_OK;
-
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
- s = (deflate_state *) strm->state;
-
- if (level == Z_DEFAULT_COMPRESSION) {
- level = 6;
- }
- if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
- return Z_STREAM_ERROR;
- }
- func = configuration_table[s->level].func;
-
- if (func != configuration_table[level].func && strm->total_in != 0) {
- /* Flush the last buffer: */
- err = deflate(strm, Z_PARTIAL_FLUSH);
- }
- if (s->level != level) {
- s->level = level;
- s->max_lazy_match = configuration_table[level].max_lazy;
- s->good_match = configuration_table[level].good_length;
- s->nice_match = configuration_table[level].nice_length;
- s->max_chain_length = configuration_table[level].max_chain;
- }
- s->strategy = strategy;
- return err;
-}
-
-/* =========================================================================
- * Put a short in the pending buffer. The 16-bit value is put in MSB order.
- * IN assertion: the stream state is correct and there is enough room in
- * pending_buf.
- */
-local void putShortMSB (s, b)
- deflate_state *s;
- uInt b;
-{
- put_byte(s, (Byte)(b >> 8));
- put_byte(s, (Byte)(b & 0xff));
-}
-
-/* =========================================================================
- * Flush as much pending output as possible. All deflate() output goes
- * through this function so some applications may wish to modify it
- * to avoid allocating a large strm->next_out buffer and copying into it.
- * (See also read_buf()).
- */
-local void flush_pending(strm)
- z_streamp strm;
-{
- deflate_state *s = (deflate_state *) strm->state;
- unsigned len = s->pending;
-
- if (len > strm->avail_out) len = strm->avail_out;
- if (len == 0) return;
-
- if (strm->next_out != Z_NULL) {
- zmemcpy(strm->next_out, s->pending_out, len);
- strm->next_out += len;
- }
- s->pending_out += len;
- strm->total_out += len;
- strm->avail_out -= len;
- s->pending -= len;
- if (s->pending == 0) {
- s->pending_out = s->pending_buf;
- }
-}
-
-/* ========================================================================= */
-int deflate (strm, flush)
- z_streamp strm;
- int flush;
-{
- int old_flush; /* value of flush param for previous deflate call */
- deflate_state *s;
-
- if (strm == Z_NULL || strm->state == Z_NULL ||
- flush > Z_FINISH || flush < 0) {
- return Z_STREAM_ERROR;
- }
- s = (deflate_state *) strm->state;
-
- if ((strm->next_in == Z_NULL && strm->avail_in != 0) ||
- (s->status == FINISH_STATE && flush != Z_FINISH)) {
- ERR_RETURN(strm, Z_STREAM_ERROR);
- }
- if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
-
- s->strm = strm; /* just in case */
- old_flush = s->last_flush;
- s->last_flush = flush;
-
- /* Write the zlib header */
- if (s->status == INIT_STATE) {
-
- uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
- uInt level_flags = (s->level-1) >> 1;
-
- if (level_flags > 3) level_flags = 3;
- header |= (level_flags << 6);
- if (s->strstart != 0) header |= PRESET_DICT;
- header += 31 - (header % 31);
-
- s->status = BUSY_STATE;
- putShortMSB(s, header);
-
- /* Save the adler32 of the preset dictionary: */
- if (s->strstart != 0) {
- putShortMSB(s, (uInt)(strm->adler >> 16));
- putShortMSB(s, (uInt)(strm->adler & 0xffff));
- }
- strm->adler = 1L;
- }
-
- /* Flush as much pending output as possible */
- if (s->pending != 0) {
- flush_pending(strm);
- if (strm->avail_out == 0) {
- /* Since avail_out is 0, deflate will be called again with
- * more output space, but possibly with both pending and
- * avail_in equal to zero. There won't be anything to do,
- * but this is not an error situation so make sure we
- * return OK instead of BUF_ERROR at next call of deflate:
- */
- s->last_flush = -1;
- return Z_OK;
- }
-
- /* Make sure there is something to do and avoid duplicate consecutive
- * flushes. For repeated and useless calls with Z_FINISH, we keep
- * returning Z_STREAM_END instead of Z_BUFF_ERROR.
- */
- } else if (strm->avail_in == 0 && flush <= old_flush &&
- flush != Z_FINISH) {
- ERR_RETURN(strm, Z_BUF_ERROR);
- }
-
- /* User must not provide more input after the first FINISH: */
- if (s->status == FINISH_STATE && strm->avail_in != 0) {
- ERR_RETURN(strm, Z_BUF_ERROR);
- }
-
- /* Start a new block or continue the current one.
- */
- if (strm->avail_in != 0 || s->lookahead != 0 ||
- (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
- block_state bstate;
-
- bstate = (*(configuration_table[s->level].func))(s, flush);
-
- if (bstate == finish_started || bstate == finish_done) {
- s->status = FINISH_STATE;
- }
- if (bstate == need_more || bstate == finish_started) {
- if (strm->avail_out == 0) {
- s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
- }
- return Z_OK;
- /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
- * of deflate should use the same flush parameter to make sure
- * that the flush is complete. So we don't have to output an
- * empty block here, this will be done at next call. This also
- * ensures that for a very small output buffer, we emit at most
- * one empty block.
- */
- }
- if (bstate == block_done) {
- if (flush == Z_PARTIAL_FLUSH) {
- _tr_align(s);
- } else if (flush == Z_PACKET_FLUSH) {
- /* Output just the 3-bit `stored' block type value,
- but not a zero length. */
- _tr_stored_type_only(s);
- } else { /* FULL_FLUSH or SYNC_FLUSH */
- _tr_stored_block(s, (char*)0, 0L, 0);
- /* For a full flush, this empty block will be recognized
- * as a special marker by inflate_sync().
- */
- if (flush == Z_FULL_FLUSH) {
- CLEAR_HASH(s); /* forget history */
- }
- }
- flush_pending(strm);
- if (strm->avail_out == 0) {
- s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
- return Z_OK;
- }
- }
- }
- Assert(strm->avail_out > 0, "bug2");
-
- if (flush != Z_FINISH) return Z_OK;
- if (s->noheader) return Z_STREAM_END;
-
- /* Write the zlib trailer (adler32) */
- putShortMSB(s, (uInt)(strm->adler >> 16));
- putShortMSB(s, (uInt)(strm->adler & 0xffff));
- flush_pending(strm);
- /* If avail_out is zero, the application will call deflate again
- * to flush the rest.
- */
- s->noheader = -1; /* write the trailer only once! */
- return s->pending != 0 ? Z_OK : Z_STREAM_END;
-}
-
-/* ========================================================================= */
-int deflateEnd (strm)
- z_streamp strm;
-{
- int status;
- deflate_state *s;
-
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
- s = (deflate_state *) strm->state;
-
- status = s->status;
- if (status != INIT_STATE && status != BUSY_STATE &&
- status != FINISH_STATE) {
- return Z_STREAM_ERROR;
- }
-
- /* Deallocate in reverse order of allocations: */
- TRY_FREE(strm, s->pending_buf);
- TRY_FREE(strm, s->head);
- TRY_FREE(strm, s->prev);
- TRY_FREE(strm, s->window);
-
- ZFREE(strm, s);
- strm->state = Z_NULL;
-
- return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
-}
-
-/* =========================================================================
- * Copy the source state to the destination state.
- */
-int deflateCopy (dest, source)
- z_streamp dest;
- z_streamp source;
-{
- deflate_state *ds;
- deflate_state *ss;
- ushf *overlay;
-
- if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL)
- return Z_STREAM_ERROR;
- ss = (deflate_state *) source->state;
-
- zmemcpy(dest, source, sizeof(*dest));
-
- ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
- if (ds == Z_NULL) return Z_MEM_ERROR;
- dest->state = (struct internal_state FAR *) ds;
- zmemcpy(ds, ss, sizeof(*ds));
- ds->strm = dest;
-
- ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
- ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
- ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
- overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
- ds->pending_buf = (uchf *) overlay;
-
- if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
- ds->pending_buf == Z_NULL) {
- deflateEnd (dest);
- return Z_MEM_ERROR;
- }
- /* ??? following zmemcpy doesn't work for 16-bit MSDOS */
- zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
- zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
- zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
- zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
-
- ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
- ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
- ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
-
- ds->l_desc.dyn_tree = ds->dyn_ltree;
- ds->d_desc.dyn_tree = ds->dyn_dtree;
- ds->bl_desc.dyn_tree = ds->bl_tree;
-
- return Z_OK;
-}
-
-/* ===========================================================================
- * Return the number of bytes of output which are immediately available
- * for output from the decompressor.
- */
-int deflateOutputPending (strm)
- z_streamp strm;
-{
- if (strm == Z_NULL || strm->state == Z_NULL) return 0;
-
- return ((deflate_state *)(strm->state))->pending;
-}
-
-/* ===========================================================================
- * Read a new buffer from the current input stream, update the adler32
- * and total number of bytes read. All deflate() input goes through
- * this function so some applications may wish to modify it to avoid
- * allocating a large strm->next_in buffer and copying from it.
- * (See also flush_pending()).
- */
-local int read_buf(strm, buf, size)
- z_streamp strm;
- charf *buf;
- unsigned size;
-{
- unsigned len = strm->avail_in;
-
- if (len > size) len = size;
- if (len == 0) return 0;
-
- strm->avail_in -= len;
-
- if (!((deflate_state *)(strm->state))->noheader) {
- strm->adler = adler32(strm->adler, strm->next_in, len);
- }
- zmemcpy(buf, strm->next_in, len);
- strm->next_in += len;
- strm->total_in += len;
-
- return (int)len;
-}
-
-/* ===========================================================================
- * Initialize the "longest match" routines for a new zlib stream
- */
-local void lm_init (s)
- deflate_state *s;
-{
- s->window_size = (ulg)2L*s->w_size;
-
- CLEAR_HASH(s);
-
- /* Set the default configuration parameters:
- */
- s->max_lazy_match = configuration_table[s->level].max_lazy;
- s->good_match = configuration_table[s->level].good_length;
- s->nice_match = configuration_table[s->level].nice_length;
- s->max_chain_length = configuration_table[s->level].max_chain;
-
- s->strstart = 0;
- s->block_start = 0L;
- s->lookahead = 0;
- s->match_length = s->prev_length = MIN_MATCH-1;
- s->match_available = 0;
- s->ins_h = 0;
-#ifdef ASMV
- match_init(); /* initialize the asm code */
-#endif
-}
-
-/* ===========================================================================
- * Set match_start to the longest match starting at the given string and
- * return its length. Matches shorter or equal to prev_length are discarded,
- * in which case the result is equal to prev_length and match_start is
- * garbage.
- * IN assertions: cur_match is the head of the hash chain for the current
- * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
- * OUT assertion: the match length is not greater than s->lookahead.
- */
-#ifndef ASMV
-/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
- * match.S. The code will be functionally equivalent.
- */
-local uInt longest_match(s, cur_match)
- deflate_state *s;
- IPos cur_match; /* current match */
-{
- unsigned chain_length = s->max_chain_length;/* max hash chain length */
- register Bytef *scan = s->window + s->strstart; /* current string */
- register Bytef *match; /* matched string */
- register int len; /* length of current match */
- int best_len = s->prev_length; /* best match length so far */
- int nice_match = s->nice_match; /* stop if match long enough */
- IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
- s->strstart - (IPos)MAX_DIST(s) : NIL;
- /* Stop when cur_match becomes <= limit. To simplify the code,
- * we prevent matches with the string of window index 0.
- */
- Posf *prev = s->prev;
- uInt wmask = s->w_mask;
-
-#ifdef UNALIGNED_OK
- /* Compare two bytes at a time. Note: this is not always beneficial.
- * Try with and without -DUNALIGNED_OK to check.
- */
- register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
- register ush scan_start = *(ushf*)scan;
- register ush scan_end = *(ushf*)(scan+best_len-1);
-#else
- register Bytef *strend = s->window + s->strstart + MAX_MATCH;
- register Byte scan_end1 = scan[best_len-1];
- register Byte scan_end = scan[best_len];
-#endif
-
- /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
- * It is easy to get rid of this optimization if necessary.
- */
- Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
- /* Do not waste too much time if we already have a good match: */
- if (s->prev_length >= s->good_match) {
- chain_length >>= 2;
- }
- /* Do not look for matches beyond the end of the input. This is necessary
- * to make deflate deterministic.
- */
- if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
- Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
- do {
- Assert(cur_match < s->strstart, "no future");
- match = s->window + cur_match;
-
- /* Skip to next match if the match length cannot increase
- * or if the match length is less than 2:
- */
-#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
- /* This code assumes sizeof(unsigned short) == 2. Do not use
- * UNALIGNED_OK if your compiler uses a different size.
- */
- if (*(ushf*)(match+best_len-1) != scan_end ||
- *(ushf*)match != scan_start) continue;
-
- /* It is not necessary to compare scan[2] and match[2] since they are
- * always equal when the other bytes match, given that the hash keys
- * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
- * strstart+3, +5, ... up to strstart+257. We check for insufficient
- * lookahead only every 4th comparison; the 128th check will be made
- * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
- * necessary to put more guard bytes at the end of the window, or
- * to check more often for insufficient lookahead.
- */
- Assert(scan[2] == match[2], "scan[2]?");
- scan++, match++;
- do {
- } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
- *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
- *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
- *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
- scan < strend);
- /* The funny "do {}" generates better code on most compilers */
-
- /* Here, scan <= window+strstart+257 */
- Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
- if (*scan == *match) scan++;
-
- len = (MAX_MATCH - 1) - (int)(strend-scan);
- scan = strend - (MAX_MATCH-1);
-
-#else /* UNALIGNED_OK */
-
- if (match[best_len] != scan_end ||
- match[best_len-1] != scan_end1 ||
- *match != *scan ||
- *++match != scan[1]) continue;
-
- /* The check at best_len-1 can be removed because it will be made
- * again later. (This heuristic is not always a win.)
- * It is not necessary to compare scan[2] and match[2] since they
- * are always equal when the other bytes match, given that
- * the hash keys are equal and that HASH_BITS >= 8.
- */
- scan += 2, match++;
- Assert(*scan == *match, "match[2]?");
-
- /* We check for insufficient lookahead only every 8th comparison;
- * the 256th check will be made at strstart+258.
- */
- do {
- } while (*++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- scan < strend);
-
- Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
- len = MAX_MATCH - (int)(strend - scan);
- scan = strend - MAX_MATCH;
-
-#endif /* UNALIGNED_OK */
-
- if (len > best_len) {
- s->match_start = cur_match;
- best_len = len;
- if (len >= nice_match) break;
-#ifdef UNALIGNED_OK
- scan_end = *(ushf*)(scan+best_len-1);
-#else
- scan_end1 = scan[best_len-1];
- scan_end = scan[best_len];
-#endif
- }
- } while ((cur_match = prev[cur_match & wmask]) > limit
- && --chain_length != 0);
-
- if ((uInt)best_len <= s->lookahead) return best_len;
- return s->lookahead;
-}
-#endif /* ASMV */
-
-#ifdef DEBUG_ZLIB
-/* ===========================================================================
- * Check that the match at match_start is indeed a match.
- */
-local void check_match(s, start, match, length)
- deflate_state *s;
- IPos start, match;
- int length;
-{
- /* check that the match is indeed a match */
- if (zmemcmp((charf *)s->window + match,
- (charf *)s->window + start, length) != EQUAL) {
- fprintf(stderr, " start %u, match %u, length %d\n",
- start, match, length);
- do {
- fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
- } while (--length != 0);
- z_error("invalid match");
- }
- if (z_verbose > 1) {
- fprintf(stderr,"\\[%d,%d]", start-match, length);
- do { putc(s->window[start++], stderr); } while (--length != 0);
- }
-}
-#else
-# define check_match(s, start, match, length)
-#endif
-
-/* ===========================================================================
- * Fill the window when the lookahead becomes insufficient.
- * Updates strstart and lookahead.
- *
- * IN assertion: lookahead < MIN_LOOKAHEAD
- * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
- * At least one byte has been read, or avail_in == 0; reads are
- * performed for at least two bytes (required for the zip translate_eol
- * option -- not supported here).
- */
-local void fill_window(s)
- deflate_state *s;
-{
- register unsigned n, m;
- register Posf *p;
- unsigned more; /* Amount of free space at the end of the window. */
- uInt wsize = s->w_size;
-
- do {
- more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
-
- /* Deal with !@#$% 64K limit: */
- if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
- more = wsize;
-
- } else if (more == (unsigned)(-1)) {
- /* Very unlikely, but possible on 16 bit machine if strstart == 0
- * and lookahead == 1 (input done one byte at time)
- */
- more--;
-
- /* If the window is almost full and there is insufficient lookahead,
- * move the upper half to the lower one to make room in the upper half.
- */
- } else if (s->strstart >= wsize+MAX_DIST(s)) {
-
- zmemcpy((charf *)s->window, (charf *)s->window+wsize,
- (unsigned)wsize);
- s->match_start -= wsize;
- s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
- s->block_start -= (long) wsize;
-
- /* Slide the hash table (could be avoided with 32 bit values
- at the expense of memory usage). We slide even when level == 0
- to keep the hash table consistent if we switch back to level > 0
- later. (Using level 0 permanently is not an optimal usage of
- zlib, so we don't care about this pathological case.)
- */
- n = s->hash_size;
- p = &s->head[n];
- do {
- m = *--p;
- *p = (Pos)(m >= wsize ? m-wsize : NIL);
- } while (--n);
-
- n = wsize;
- p = &s->prev[n];
- do {
- m = *--p;
- *p = (Pos)(m >= wsize ? m-wsize : NIL);
- /* If n is not on any hash chain, prev[n] is garbage but
- * its value will never be used.
- */
- } while (--n);
- more += wsize;
- }
- if (s->strm->avail_in == 0) return;
-
- /* If there was no sliding:
- * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
- * more == window_size - lookahead - strstart
- * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
- * => more >= window_size - 2*WSIZE + 2
- * In the BIG_MEM or MMAP case (not yet supported),
- * window_size == input_size + MIN_LOOKAHEAD &&
- * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
- * Otherwise, window_size == 2*WSIZE so more >= 2.
- * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
- */
- Assert(more >= 2, "more < 2");
-
- n = read_buf(s->strm, (charf *)s->window + s->strstart + s->lookahead,
- more);
- s->lookahead += n;
-
- /* Initialize the hash value now that we have some input: */
- if (s->lookahead >= MIN_MATCH) {
- s->ins_h = s->window[s->strstart];
- UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
-#if MIN_MATCH != 3
- Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
- }
- /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
- * but this is not important since only literal bytes will be emitted.
- */
-
- } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
-}
-
-/* ===========================================================================
- * Flush the current block, with given end-of-file flag.
- * IN assertion: strstart is set to the end of the current match.
- */
-#define FLUSH_BLOCK_ONLY(s, eof) { \
- _tr_flush_block(s, (s->block_start >= 0L ? \
- (charf *)&s->window[(unsigned)s->block_start] : \
- (charf *)Z_NULL), \
- (ulg)((long)s->strstart - s->block_start), \
- (eof)); \
- s->block_start = s->strstart; \
- flush_pending(s->strm); \
- Tracev((stderr,"[FLUSH]")); \
-}
-
-/* Same but force premature exit if necessary. */
-#define FLUSH_BLOCK(s, eof) { \
- FLUSH_BLOCK_ONLY(s, eof); \
- if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
-}
-
-/* ===========================================================================
- * Copy without compression as much as possible from the input stream, return
- * the current block state.
- * This function does not insert new strings in the dictionary since
- * uncompressible data is probably not useful. This function is used
- * only for the level=0 compression option.
- * NOTE: this function should be optimized to avoid extra copying from
- * window to pending_buf.
- */
-local block_state deflate_stored(s, flush)
- deflate_state *s;
- int flush;
-{
- /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
- * to pending_buf_size, and each stored block has a 5 byte header:
- */
- ulg max_block_size = 0xffff;
- ulg max_start;
-
- if (max_block_size > s->pending_buf_size - 5) {
- max_block_size = s->pending_buf_size - 5;
- }
-
- /* Copy as much as possible from input to output: */
- for (;;) {
- /* Fill the window as much as possible: */
- if (s->lookahead <= 1) {
-
- Assert(s->strstart < s->w_size+MAX_DIST(s) ||
- s->block_start >= (long)s->w_size, "slide too late");
-
- fill_window(s);
- if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
-
- if (s->lookahead == 0) break; /* flush the current block */
- }
- Assert(s->block_start >= 0L, "block gone");
-
- s->strstart += s->lookahead;
- s->lookahead = 0;
-
- /* Emit a stored block if pending_buf will be full: */
- max_start = s->block_start + max_block_size;
- if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
- /* strstart == 0 is possible when wraparound on 16-bit machine */
- s->lookahead = (uInt)(s->strstart - max_start);
- s->strstart = (uInt)max_start;
- FLUSH_BLOCK(s, 0);
- }
- /* Flush if we may have to slide, otherwise block_start may become
- * negative and the data will be gone:
- */
- if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
- FLUSH_BLOCK(s, 0);
- }
- }
- FLUSH_BLOCK(s, flush == Z_FINISH);
- return flush == Z_FINISH ? finish_done : block_done;
-}
-
-/* ===========================================================================
- * Compress as much as possible from the input stream, return the current
- * block state.
- * This function does not perform lazy evaluation of matches and inserts
- * new strings in the dictionary only for unmatched strings or for short
- * matches. It is used only for the fast compression options.
- */
-local block_state deflate_fast(s, flush)
- deflate_state *s;
- int flush;
-{
- IPos hash_head = NIL; /* head of the hash chain */
- int bflush; /* set if current block must be flushed */
-
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- if (s->lookahead < MIN_LOOKAHEAD) {
- fill_window(s);
- if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
- return need_more;
- }
- if (s->lookahead == 0) break; /* flush the current block */
- }
-
- /* Insert the string window[strstart .. strstart+2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- if (s->lookahead >= MIN_MATCH) {
- INSERT_STRING(s, s->strstart, hash_head);
- }
-
- /* Find the longest match, discarding those <= prev_length.
- * At this point we have always match_length < MIN_MATCH
- */
- if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- if (s->strategy != Z_HUFFMAN_ONLY) {
- s->match_length = longest_match (s, hash_head);
- }
- /* longest_match() sets match_start */
- }
- if (s->match_length >= MIN_MATCH) {
- check_match(s, s->strstart, s->match_start, s->match_length);
-
- bflush = _tr_tally(s, s->strstart - s->match_start,
- s->match_length - MIN_MATCH);
-
- s->lookahead -= s->match_length;
-
- /* Insert new strings in the hash table only if the match length
- * is not too large. This saves time but degrades compression.
- */
- if (s->match_length <= s->max_insert_length &&
- s->lookahead >= MIN_MATCH) {
- s->match_length--; /* string at strstart already in hash table */
- do {
- s->strstart++;
- INSERT_STRING(s, s->strstart, hash_head);
- /* strstart never exceeds WSIZE-MAX_MATCH, so there are
- * always MIN_MATCH bytes ahead.
- */
- } while (--s->match_length != 0);
- s->strstart++;
- } else {
- s->strstart += s->match_length;
- s->match_length = 0;
- s->ins_h = s->window[s->strstart];
- UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
-#if MIN_MATCH != 3
- Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
- /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
- * matter since it will be recomputed at next deflate call.
- */
- }
- } else {
- /* No match, output a literal byte */
- Tracevv((stderr,"%c", s->window[s->strstart]));
- bflush = _tr_tally (s, 0, s->window[s->strstart]);
- s->lookahead--;
- s->strstart++;
- }
- if (bflush) FLUSH_BLOCK(s, 0);
- }
- FLUSH_BLOCK(s, flush == Z_FINISH);
- return flush == Z_FINISH ? finish_done : block_done;
-}
-
-/* ===========================================================================
- * Same as above, but achieves better compression. We use a lazy
- * evaluation for matches: a match is finally adopted only if there is
- * no better match at the next window position.
- */
-local block_state deflate_slow(s, flush)
- deflate_state *s;
- int flush;
-{
- IPos hash_head = NIL; /* head of hash chain */
- int bflush; /* set if current block must be flushed */
-
- /* Process the input block. */
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- if (s->lookahead < MIN_LOOKAHEAD) {
- fill_window(s);
- if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
- return need_more;
- }
- if (s->lookahead == 0) break; /* flush the current block */
- }
-
- /* Insert the string window[strstart .. strstart+2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- if (s->lookahead >= MIN_MATCH) {
- INSERT_STRING(s, s->strstart, hash_head);
- }
-
- /* Find the longest match, discarding those <= prev_length.
- */
- s->prev_length = s->match_length, s->prev_match = s->match_start;
- s->match_length = MIN_MATCH-1;
-
- if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
- s->strstart - hash_head <= MAX_DIST(s)) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- if (s->strategy != Z_HUFFMAN_ONLY) {
- s->match_length = longest_match (s, hash_head);
- }
- /* longest_match() sets match_start */
-
- if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
- (s->match_length == MIN_MATCH &&
- s->strstart - s->match_start > TOO_FAR))) {
-
- /* If prev_match is also MIN_MATCH, match_start is garbage
- * but we will ignore the current match anyway.
- */
- s->match_length = MIN_MATCH-1;
- }
- }
- /* If there was a match at the previous step and the current
- * match is not better, output the previous match:
- */
- if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
- uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
- /* Do not insert strings in hash table beyond this. */
-
- check_match(s, s->strstart-1, s->prev_match, s->prev_length);
-
- bflush = _tr_tally(s, s->strstart -1 - s->prev_match,
- s->prev_length - MIN_MATCH);
-
- /* Insert in hash table all strings up to the end of the match.
- * strstart-1 and strstart are already inserted. If there is not
- * enough lookahead, the last two strings are not inserted in
- * the hash table.
- */
- s->lookahead -= s->prev_length-1;
- s->prev_length -= 2;
- do {
- if (++s->strstart <= max_insert) {
- INSERT_STRING(s, s->strstart, hash_head);
- }
- } while (--s->prev_length != 0);
- s->match_available = 0;
- s->match_length = MIN_MATCH-1;
- s->strstart++;
-
- if (bflush) FLUSH_BLOCK(s, 0);
-
- } else if (s->match_available) {
- /* If there was no match at the previous position, output a
- * single literal. If there was a match but the current match
- * is longer, truncate the previous match to a single literal.
- */
- Tracevv((stderr,"%c", s->window[s->strstart-1]));
- if (_tr_tally (s, 0, s->window[s->strstart-1])) {
- FLUSH_BLOCK_ONLY(s, 0);
- }
- s->strstart++;
- s->lookahead--;
- if (s->strm->avail_out == 0) return need_more;
- } else {
- /* There is no previous match to compare with, wait for
- * the next step to decide.
- */
- s->match_available = 1;
- s->strstart++;
- s->lookahead--;
- }
- }
- Assert (flush != Z_NO_FLUSH, "no flush?");
- if (s->match_available) {
- Tracevv((stderr,"%c", s->window[s->strstart-1]));
- _tr_tally (s, 0, s->window[s->strstart-1]);
- s->match_available = 0;
- }
- FLUSH_BLOCK(s, flush == Z_FINISH);
- return flush == Z_FINISH ? finish_done : block_done;
-}
-/* --- deflate.c */
-
-/* +++ trees.c */
-/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-1996 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- * ALGORITHM
- *
- * The "deflation" process uses several Huffman trees. The more
- * common source values are represented by shorter bit sequences.
- *
- * Each code tree is stored in a compressed form which is itself
- * a Huffman encoding of the lengths of all the code strings (in
- * ascending order by source values). The actual code strings are
- * reconstructed from the lengths in the inflate process, as described
- * in the deflate specification.
- *
- * REFERENCES
- *
- * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
- * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
- *
- * Storer, James A.
- * Data Compression: Methods and Theory, pp. 49-50.
- * Computer Science Press, 1988. ISBN 0-7167-8156-5.
- *
- * Sedgewick, R.
- * Algorithms, p290.
- * Addison-Wesley, 1983. ISBN 0-201-06672-6.
- */
-
-/* From: trees.c,v 1.11 1996/07/24 13:41:06 me Exp $ */
-
-/* #include "deflate.h" */
-
-#ifdef DEBUG_ZLIB
-# include <ctype.h>
-#endif
-
-/* ===========================================================================
- * Constants
- */
-
-#define MAX_BL_BITS 7
-/* Bit length codes must not exceed MAX_BL_BITS bits */
-
-#define END_BLOCK 256
-/* end of block literal code */
-
-#define REP_3_6 16
-/* repeat previous bit length 3-6 times (2 bits of repeat count) */
-
-#define REPZ_3_10 17
-/* repeat a zero length 3-10 times (3 bits of repeat count) */
-
-#define REPZ_11_138 18
-/* repeat a zero length 11-138 times (7 bits of repeat count) */
-
-local int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
- = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
-
-local int extra_dbits[D_CODES] /* extra bits for each distance code */
- = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
-
-local int extra_blbits[BL_CODES]/* extra bits for each bit length code */
- = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
-
-local uch bl_order[BL_CODES]
- = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
-/* The lengths of the bit length codes are sent in order of decreasing
- * probability, to avoid transmitting the lengths for unused bit length codes.
- */
-
-#define Buf_size (8 * 2*sizeof(char))
-/* Number of bits used within bi_buf. (bi_buf might be implemented on
- * more than 16 bits on some systems.)
- */
-
-/* ===========================================================================
- * Local data. These are initialized only once.
- */
-
-local ct_data static_ltree[L_CODES+2];
-/* The static literal tree. Since the bit lengths are imposed, there is no
- * need for the L_CODES extra codes used during heap construction. However
- * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
- * below).
- */
-
-local ct_data static_dtree[D_CODES];
-/* The static distance tree. (Actually a trivial tree since all codes use
- * 5 bits.)
- */
-
-local uch dist_code[512];
-/* distance codes. The first 256 values correspond to the distances
- * 3 .. 258, the last 256 values correspond to the top 8 bits of
- * the 15 bit distances.
- */
-
-local uch length_code[MAX_MATCH-MIN_MATCH+1];
-/* length code for each normalized match length (0 == MIN_MATCH) */
-
-local int base_length[LENGTH_CODES];
-/* First normalized length for each code (0 = MIN_MATCH) */
-
-local int base_dist[D_CODES];
-/* First normalized distance for each code (0 = distance of 1) */
-
-struct static_tree_desc_s {
- ct_data *static_tree; /* static tree or NULL */
- intf *extra_bits; /* extra bits for each code or NULL */
- int extra_base; /* base index for extra_bits */
- int elems; /* max number of elements in the tree */
- int max_length; /* max bit length for the codes */
-};
-
-local static_tree_desc static_l_desc =
-{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
-
-local static_tree_desc static_d_desc =
-{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
-
-local static_tree_desc static_bl_desc =
-{(ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
-
-/* ===========================================================================
- * Local (static) routines in this file.
- */
-
-local void tr_static_init OF((void));
-local void init_block OF((deflate_state *s));
-local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
-local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
-local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
-local void build_tree OF((deflate_state *s, tree_desc *desc));
-local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
-local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
-local int build_bl_tree OF((deflate_state *s));
-local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
- int blcodes));
-local void compress_block OF((deflate_state *s, ct_data *ltree,
- ct_data *dtree));
-local void set_data_type OF((deflate_state *s));
-local unsigned bi_reverse OF((unsigned value, int length));
-local void bi_windup OF((deflate_state *s));
-local void bi_flush OF((deflate_state *s));
-local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
- int header));
-
-#ifndef DEBUG_ZLIB
-# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
- /* Send a code of the given tree. c and tree must not have side effects */
-
-#else /* DEBUG_ZLIB */
-# define send_code(s, c, tree) \
- { if (verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
- send_bits(s, tree[c].Code, tree[c].Len); }
-#endif
-
-#define d_code(dist) \
- ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
-/* Mapping from a distance to a distance code. dist is the distance - 1 and
- * must not have side effects. dist_code[256] and dist_code[257] are never
- * used.
- */
-
-/* ===========================================================================
- * Output a short LSB first on the stream.
- * IN assertion: there is enough room in pendingBuf.
- */
-#define put_short(s, w) { \
- put_byte(s, (uch)((w) & 0xff)); \
- put_byte(s, (uch)((ush)(w) >> 8)); \
-}
-
-/* ===========================================================================
- * Send a value on a given number of bits.
- * IN assertion: length <= 16 and value fits in length bits.
- */
-#ifdef DEBUG_ZLIB
-local void send_bits OF((deflate_state *s, int value, int length));
-
-local void send_bits(s, value, length)
- deflate_state *s;
- int value; /* value to send */
- int length; /* number of bits */
-{
- Tracevv((stderr," l %2d v %4x ", length, value));
- Assert(length > 0 && length <= 15, "invalid length");
- s->bits_sent += (ulg)length;
-
- /* If not enough room in bi_buf, use (valid) bits from bi_buf and
- * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
- * unused bits in value.
- */
- if (s->bi_valid > (int)Buf_size - length) {
- s->bi_buf |= (value << s->bi_valid);
- put_short(s, s->bi_buf);
- s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
- s->bi_valid += length - Buf_size;
- } else {
- s->bi_buf |= value << s->bi_valid;
- s->bi_valid += length;
- }
-}
-#else /* !DEBUG_ZLIB */
-
-#define send_bits(s, value, length) \
-{ int len = length;\
- if (s->bi_valid > (int)Buf_size - len) {\
- int val = value;\
- s->bi_buf |= (val << s->bi_valid);\
- put_short(s, s->bi_buf);\
- s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
- s->bi_valid += len - Buf_size;\
- } else {\
- s->bi_buf |= (value) << s->bi_valid;\
- s->bi_valid += len;\
- }\
-}
-#endif /* DEBUG_ZLIB */
-
-
-#define MAX(a,b) (a >= b ? a : b)
-/* the arguments must not have side effects */
-
-/* ===========================================================================
- * Initialize the various 'constant' tables. In a multi-threaded environment,
- * this function may be called by two threads concurrently, but this is
- * harmless since both invocations do exactly the same thing.
- */
-local void tr_static_init()
-{
- static int static_init_done = 0;
- int n; /* iterates over tree elements */
- int bits; /* bit counter */
- int length; /* length value */
- int code; /* code value */
- int dist; /* distance index */
- ush bl_count[MAX_BITS+1];
- /* number of codes at each bit length for an optimal tree */
-
- if (static_init_done) return;
-
- /* Initialize the mapping length (0..255) -> length code (0..28) */
- length = 0;
- for (code = 0; code < LENGTH_CODES-1; code++) {
- base_length[code] = length;
- for (n = 0; n < (1<<extra_lbits[code]); n++) {
- length_code[length++] = (uch)code;
- }
- }
- Assert (length == 256, "tr_static_init: length != 256");
- /* Note that the length 255 (match length 258) can be represented
- * in two different ways: code 284 + 5 bits or code 285, so we
- * overwrite length_code[255] to use the best encoding:
- */
- length_code[length-1] = (uch)code;
-
- /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
- dist = 0;
- for (code = 0 ; code < 16; code++) {
- base_dist[code] = dist;
- for (n = 0; n < (1<<extra_dbits[code]); n++) {
- dist_code[dist++] = (uch)code;
- }
- }
- Assert (dist == 256, "tr_static_init: dist != 256");
- dist >>= 7; /* from now on, all distances are divided by 128 */
- for ( ; code < D_CODES; code++) {
- base_dist[code] = dist << 7;
- for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
- dist_code[256 + dist++] = (uch)code;
- }
- }
- Assert (dist == 256, "tr_static_init: 256+dist != 512");
-
- /* Construct the codes of the static literal tree */
- for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
- n = 0;
- while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
- while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
- while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
- while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
- /* Codes 286 and 287 do not exist, but we must include them in the
- * tree construction to get a canonical Huffman tree (longest code
- * all ones)
- */
- gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
-
- /* The static distance tree is trivial: */
- for (n = 0; n < D_CODES; n++) {
- static_dtree[n].Len = 5;
- static_dtree[n].Code = bi_reverse((unsigned)n, 5);
- }
- static_init_done = 1;
-}
-
-/* ===========================================================================
- * Initialize the tree data structures for a new zlib stream.
- */
-void _tr_init(s)
- deflate_state *s;
-{
- tr_static_init();
-
- s->compressed_len = 0L;
-
- s->l_desc.dyn_tree = s->dyn_ltree;
- s->l_desc.stat_desc = &static_l_desc;
-
- s->d_desc.dyn_tree = s->dyn_dtree;
- s->d_desc.stat_desc = &static_d_desc;
-
- s->bl_desc.dyn_tree = s->bl_tree;
- s->bl_desc.stat_desc = &static_bl_desc;
-
- s->bi_buf = 0;
- s->bi_valid = 0;
- s->last_eob_len = 8; /* enough lookahead for inflate */
-#ifdef DEBUG_ZLIB
- s->bits_sent = 0L;
-#endif
-
- /* Initialize the first block of the first file: */
- init_block(s);
-}
-
-/* ===========================================================================
- * Initialize a new block.
- */
-local void init_block(s)
- deflate_state *s;
-{
- int n; /* iterates over tree elements */
-
- /* Initialize the trees. */
- for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
- for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
- for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
-
- s->dyn_ltree[END_BLOCK].Freq = 1;
- s->opt_len = s->static_len = 0L;
- s->last_lit = s->matches = 0;
-}
-
-#define SMALLEST 1
-/* Index within the heap array of least frequent node in the Huffman tree */
-
-
-/* ===========================================================================
- * Remove the smallest element from the heap and recreate the heap with
- * one less element. Updates heap and heap_len.
- */
-#define pqremove(s, tree, top) \
-{\
- top = s->heap[SMALLEST]; \
- s->heap[SMALLEST] = s->heap[s->heap_len--]; \
- pqdownheap(s, tree, SMALLEST); \
-}
-
-/* ===========================================================================
- * Compares to subtrees, using the tree depth as tie breaker when
- * the subtrees have equal frequency. This minimizes the worst case length.
- */
-#define smaller(tree, n, m, depth) \
- (tree[n].Freq < tree[m].Freq || \
- (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
-
-/* ===========================================================================
- * Restore the heap property by moving down the tree starting at node k,
- * exchanging a node with the smallest of its two sons if necessary, stopping
- * when the heap property is re-established (each father smaller than its
- * two sons).
- */
-local void pqdownheap(s, tree, k)
- deflate_state *s;
- ct_data *tree; /* the tree to restore */
- int k; /* node to move down */
-{
- int v = s->heap[k];
- int j = k << 1; /* left son of k */
- while (j <= s->heap_len) {
- /* Set j to the smallest of the two sons: */
- if (j < s->heap_len &&
- smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
- j++;
- }
- /* Exit if v is smaller than both sons */
- if (smaller(tree, v, s->heap[j], s->depth)) break;
-
- /* Exchange v with the smallest son */
- s->heap[k] = s->heap[j]; k = j;
-
- /* And continue down the tree, setting j to the left son of k */
- j <<= 1;
- }
- s->heap[k] = v;
-}
-
-/* ===========================================================================
- * Compute the optimal bit lengths for a tree and update the total bit length
- * for the current block.
- * IN assertion: the fields freq and dad are set, heap[heap_max] and
- * above are the tree nodes sorted by increasing frequency.
- * OUT assertions: the field len is set to the optimal bit length, the
- * array bl_count contains the frequencies for each bit length.
- * The length opt_len is updated; static_len is also updated if stree is
- * not null.
- */
-local void gen_bitlen(s, desc)
- deflate_state *s;
- tree_desc *desc; /* the tree descriptor */
-{
- ct_data *tree = desc->dyn_tree;
- int max_code = desc->max_code;
- ct_data *stree = desc->stat_desc->static_tree;
- intf *extra = desc->stat_desc->extra_bits;
- int base = desc->stat_desc->extra_base;
- int max_length = desc->stat_desc->max_length;
- int h; /* heap index */
- int n, m; /* iterate over the tree elements */
- int bits; /* bit length */
- int xbits; /* extra bits */
- ush f; /* frequency */
- int overflow = 0; /* number of elements with bit length too large */
-
- for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
-
- /* In a first pass, compute the optimal bit lengths (which may
- * overflow in the case of the bit length tree).
- */
- tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
-
- for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
- n = s->heap[h];
- bits = tree[tree[n].Dad].Len + 1;
- if (bits > max_length) bits = max_length, overflow++;
- tree[n].Len = (ush)bits;
- /* We overwrite tree[n].Dad which is no longer needed */
-
- if (n > max_code) continue; /* not a leaf node */
-
- s->bl_count[bits]++;
- xbits = 0;
- if (n >= base) xbits = extra[n-base];
- f = tree[n].Freq;
- s->opt_len += (ulg)f * (bits + xbits);
- if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
- }
- if (overflow == 0) return;
-
- Trace((stderr,"\nbit length overflow\n"));
- /* This happens for example on obj2 and pic of the Calgary corpus */
-
- /* Find the first bit length which could increase: */
- do {
- bits = max_length-1;
- while (s->bl_count[bits] == 0) bits--;
- s->bl_count[bits]--; /* move one leaf down the tree */
- s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
- s->bl_count[max_length]--;
- /* The brother of the overflow item also moves one step up,
- * but this does not affect bl_count[max_length]
- */
- overflow -= 2;
- } while (overflow > 0);
-
- /* Now recompute all bit lengths, scanning in increasing frequency.
- * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
- * lengths instead of fixing only the wrong ones. This idea is taken
- * from 'ar' written by Haruhiko Okumura.)
- */
- for (bits = max_length; bits != 0; bits--) {
- n = s->bl_count[bits];
- while (n != 0) {
- m = s->heap[--h];
- if (m > max_code) continue;
- if (tree[m].Len != (unsigned) bits) {
- Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
- s->opt_len += ((long)bits - (long)tree[m].Len)
- *(long)tree[m].Freq;
- tree[m].Len = (ush)bits;
- }
- n--;
- }
- }
-}
-
-/* ===========================================================================
- * Generate the codes for a given tree and bit counts (which need not be
- * optimal).
- * IN assertion: the array bl_count contains the bit length statistics for
- * the given tree and the field len is set for all tree elements.
- * OUT assertion: the field code is set for all tree elements of non
- * zero code length.
- */
-local void gen_codes (tree, max_code, bl_count)
- ct_data *tree; /* the tree to decorate */
- int max_code; /* largest code with non zero frequency */
- ushf *bl_count; /* number of codes at each bit length */
-{
- ush next_code[MAX_BITS+1]; /* next code value for each bit length */
- ush code = 0; /* running code value */
- int bits; /* bit index */
- int n; /* code index */
-
- /* The distribution counts are first used to generate the code values
- * without bit reversal.
- */
- for (bits = 1; bits <= MAX_BITS; bits++) {
- next_code[bits] = code = (code + bl_count[bits-1]) << 1;
- }
- /* Check that the bit counts in bl_count are consistent. The last code
- * must be all ones.
- */
- Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
- "inconsistent bit counts");
- Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
-
- for (n = 0; n <= max_code; n++) {
- int len = tree[n].Len;
- if (len == 0) continue;
- /* Now reverse the bits */
- tree[n].Code = bi_reverse(next_code[len]++, len);
-
- Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
- n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
- }
-}
-
-/* ===========================================================================
- * Construct one Huffman tree and assigns the code bit strings and lengths.
- * Update the total bit length for the current block.
- * IN assertion: the field freq is set for all tree elements.
- * OUT assertions: the fields len and code are set to the optimal bit length
- * and corresponding code. The length opt_len is updated; static_len is
- * also updated if stree is not null. The field max_code is set.
- */
-local void build_tree(s, desc)
- deflate_state *s;
- tree_desc *desc; /* the tree descriptor */
-{
- ct_data *tree = desc->dyn_tree;
- ct_data *stree = desc->stat_desc->static_tree;
- int elems = desc->stat_desc->elems;
- int n, m; /* iterate over heap elements */
- int max_code = -1; /* largest code with non zero frequency */
- int node; /* new node being created */
-
- /* Construct the initial heap, with least frequent element in
- * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
- * heap[0] is not used.
- */
- s->heap_len = 0, s->heap_max = HEAP_SIZE;
-
- for (n = 0; n < elems; n++) {
- if (tree[n].Freq != 0) {
- s->heap[++(s->heap_len)] = max_code = n;
- s->depth[n] = 0;
- } else {
- tree[n].Len = 0;
- }
- }
-
- /* The pkzip format requires that at least one distance code exists,
- * and that at least one bit should be sent even if there is only one
- * possible code. So to avoid special checks later on we force at least
- * two codes of non zero frequency.
- */
- while (s->heap_len < 2) {
- node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
- tree[node].Freq = 1;
- s->depth[node] = 0;
- s->opt_len--; if (stree) s->static_len -= stree[node].Len;
- /* node is 0 or 1 so it does not have extra bits */
- }
- desc->max_code = max_code;
-
- /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
- * establish sub-heaps of increasing lengths:
- */
- for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
-
- /* Construct the Huffman tree by repeatedly combining the least two
- * frequent nodes.
- */
- node = elems; /* next internal node of the tree */
- do {
- pqremove(s, tree, n); /* n = node of least frequency */
- m = s->heap[SMALLEST]; /* m = node of next least frequency */
-
- s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
- s->heap[--(s->heap_max)] = m;
-
- /* Create a new node father of n and m */
- tree[node].Freq = tree[n].Freq + tree[m].Freq;
- s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
- tree[n].Dad = tree[m].Dad = (ush)node;
-#ifdef DUMP_BL_TREE
- if (tree == s->bl_tree) {
- fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
- node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
- }
-#endif
- /* and insert the new node in the heap */
- s->heap[SMALLEST] = node++;
- pqdownheap(s, tree, SMALLEST);
-
- } while (s->heap_len >= 2);
-
- s->heap[--(s->heap_max)] = s->heap[SMALLEST];
-
- /* At this point, the fields freq and dad are set. We can now
- * generate the bit lengths.
- */
- gen_bitlen(s, (tree_desc *)desc);
-
- /* The field len is now set, we can generate the bit codes */
- gen_codes ((ct_data *)tree, max_code, s->bl_count);
-}
-
-/* ===========================================================================
- * Scan a literal or distance tree to determine the frequencies of the codes
- * in the bit length tree.
- */
-local void scan_tree (s, tree, max_code)
- deflate_state *s;
- ct_data *tree; /* the tree to be scanned */
- int max_code; /* and its largest code of non zero frequency */
-{
- int n; /* iterates over all tree elements */
- int prevlen = -1; /* last emitted length */
- int curlen; /* length of current code */
- int nextlen = tree[0].Len; /* length of next code */
- int count = 0; /* repeat count of the current code */
- int max_count = 7; /* max repeat count */
- int min_count = 4; /* min repeat count */
-
- if (nextlen == 0) max_count = 138, min_count = 3;
- tree[max_code+1].Len = (ush)0xffff; /* guard */
-
- for (n = 0; n <= max_code; n++) {
- curlen = nextlen; nextlen = tree[n+1].Len;
- if (++count < max_count && curlen == nextlen) {
- continue;
- } else if (count < min_count) {
- s->bl_tree[curlen].Freq += count;
- } else if (curlen != 0) {
- if (curlen != prevlen) s->bl_tree[curlen].Freq++;
- s->bl_tree[REP_3_6].Freq++;
- } else if (count <= 10) {
- s->bl_tree[REPZ_3_10].Freq++;
- } else {
- s->bl_tree[REPZ_11_138].Freq++;
- }
- count = 0; prevlen = curlen;
- if (nextlen == 0) {
- max_count = 138, min_count = 3;
- } else if (curlen == nextlen) {
- max_count = 6, min_count = 3;
- } else {
- max_count = 7, min_count = 4;
- }
- }
-}
-
-/* ===========================================================================
- * Send a literal or distance tree in compressed form, using the codes in
- * bl_tree.
- */
-local void send_tree (s, tree, max_code)
- deflate_state *s;
- ct_data *tree; /* the tree to be scanned */
- int max_code; /* and its largest code of non zero frequency */
-{
- int n; /* iterates over all tree elements */
- int prevlen = -1; /* last emitted length */
- int curlen; /* length of current code */
- int nextlen = tree[0].Len; /* length of next code */
- int count = 0; /* repeat count of the current code */
- int max_count = 7; /* max repeat count */
- int min_count = 4; /* min repeat count */
-
- /* tree[max_code+1].Len = -1; */ /* guard already set */
- if (nextlen == 0) max_count = 138, min_count = 3;
-
- for (n = 0; n <= max_code; n++) {
- curlen = nextlen; nextlen = tree[n+1].Len;
- if (++count < max_count && curlen == nextlen) {
- continue;
- } else if (count < min_count) {
- do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
-
- } else if (curlen != 0) {
- if (curlen != prevlen) {
- send_code(s, curlen, s->bl_tree); count--;
- }
- Assert(count >= 3 && count <= 6, " 3_6?");
- send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
-
- } else if (count <= 10) {
- send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
-
- } else {
- send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
- }
- count = 0; prevlen = curlen;
- if (nextlen == 0) {
- max_count = 138, min_count = 3;
- } else if (curlen == nextlen) {
- max_count = 6, min_count = 3;
- } else {
- max_count = 7, min_count = 4;
- }
- }
-}
-
-/* ===========================================================================
- * Construct the Huffman tree for the bit lengths and return the index in
- * bl_order of the last bit length code to send.
- */
-local int build_bl_tree(s)
- deflate_state *s;
-{
- int max_blindex; /* index of last bit length code of non zero freq */
-
- /* Determine the bit length frequencies for literal and distance trees */
- scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
- scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
-
- /* Build the bit length tree: */
- build_tree(s, (tree_desc *)(&(s->bl_desc)));
- /* opt_len now includes the length of the tree representations, except
- * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
- */
-
- /* Determine the number of bit length codes to send. The pkzip format
- * requires that at least 4 bit length codes be sent. (appnote.txt says
- * 3 but the actual value used is 4.)
- */
- for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
- if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
- }
- /* Update opt_len to include the bit length tree and counts */
- s->opt_len += 3*(max_blindex+1) + 5+5+4;
- Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
- s->opt_len, s->static_len));
-
- return max_blindex;
-}
-
-/* ===========================================================================
- * Send the header for a block using dynamic Huffman trees: the counts, the
- * lengths of the bit length codes, the literal tree and the distance tree.
- * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
- */
-local void send_all_trees(s, lcodes, dcodes, blcodes)
- deflate_state *s;
- int lcodes, dcodes, blcodes; /* number of codes for each tree */
-{
- int rank; /* index in bl_order */
-
- Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
- Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
- "too many codes");
- Tracev((stderr, "\nbl counts: "));
- send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
- send_bits(s, dcodes-1, 5);
- send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
- for (rank = 0; rank < blcodes; rank++) {
- Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
- send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
- }
- Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
-
- send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
- Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
-
- send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
- Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
-}
-
-/* ===========================================================================
- * Send a stored block
- */
-void _tr_stored_block(s, buf, stored_len, eof)
- deflate_state *s;
- charf *buf; /* input block */
- ulg stored_len; /* length of input block */
- int eof; /* true if this is the last block for a file */
-{
- send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
- s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
- s->compressed_len += (stored_len + 4) << 3;
-
- copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
-}
-
-/* Send just the `stored block' type code without any length bytes or data.
- */
-void _tr_stored_type_only(s)
- deflate_state *s;
-{
- send_bits(s, (STORED_BLOCK << 1), 3);
- bi_windup(s);
- s->compressed_len = (s->compressed_len + 3) & ~7L;
-}
-
-
-/* ===========================================================================
- * Send one empty static block to give enough lookahead for inflate.
- * This takes 10 bits, of which 7 may remain in the bit buffer.
- * The current inflate code requires 9 bits of lookahead. If the
- * last two codes for the previous block (real code plus EOB) were coded
- * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
- * the last real code. In this case we send two empty static blocks instead
- * of one. (There are no problems if the previous block is stored or fixed.)
- * To simplify the code, we assume the worst case of last real code encoded
- * on one bit only.
- */
-void _tr_align(s)
- deflate_state *s;
-{
- send_bits(s, STATIC_TREES<<1, 3);
- send_code(s, END_BLOCK, static_ltree);
- s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
- bi_flush(s);
- /* Of the 10 bits for the empty block, we have already sent
- * (10 - bi_valid) bits. The lookahead for the last real code (before
- * the EOB of the previous block) was thus at least one plus the length
- * of the EOB plus what we have just sent of the empty static block.
- */
- if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
- send_bits(s, STATIC_TREES<<1, 3);
- send_code(s, END_BLOCK, static_ltree);
- s->compressed_len += 10L;
- bi_flush(s);
- }
- s->last_eob_len = 7;
-}
-
-/* ===========================================================================
- * Determine the best encoding for the current block: dynamic trees, static
- * trees or store, and output the encoded block to the zip file. This function
- * returns the total compressed length for the file so far.
- */
-ulg _tr_flush_block(s, buf, stored_len, eof)
- deflate_state *s;
- charf *buf; /* input block, or NULL if too old */
- ulg stored_len; /* length of input block */
- int eof; /* true if this is the last block for a file */
-{
- ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
- int max_blindex = 0; /* index of last bit length code of non zero freq */
-
- /* Build the Huffman trees unless a stored block is forced */
- if (s->level > 0) {
-
- /* Check if the file is ascii or binary */
- if (s->data_type == Z_UNKNOWN) set_data_type(s);
-
- /* Construct the literal and distance trees */
- build_tree(s, (tree_desc *)(&(s->l_desc)));
- Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
- s->static_len));
-
- build_tree(s, (tree_desc *)(&(s->d_desc)));
- Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
- s->static_len));
- /* At this point, opt_len and static_len are the total bit lengths of
- * the compressed block data, excluding the tree representations.
- */
-
- /* Build the bit length tree for the above two trees, and get the index
- * in bl_order of the last bit length code to send.
- */
- max_blindex = build_bl_tree(s);
-
- /* Determine the best encoding. Compute first the block length in bytes*/
- opt_lenb = (s->opt_len+3+7)>>3;
- static_lenb = (s->static_len+3+7)>>3;
-
- Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
- opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
- s->last_lit));
-
- if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
-
- } else {
- Assert(buf != (char*)0, "lost buf");
- opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
- }
-
- /* If compression failed and this is the first and last block,
- * and if the .zip file can be seeked (to rewrite the local header),
- * the whole file is transformed into a stored file:
- */
-#ifdef STORED_FILE_OK
-# ifdef FORCE_STORED_FILE
- if (eof && s->compressed_len == 0L) { /* force stored file */
-# else
- if (stored_len <= opt_lenb && eof && s->compressed_len==0L && seekable()) {
-# endif
- /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
- if (buf == (charf*)0) error ("block vanished");
-
- copy_block(s, buf, (unsigned)stored_len, 0); /* without header */
- s->compressed_len = stored_len << 3;
- s->method = STORED;
- } else
-#endif /* STORED_FILE_OK */
-
-#ifdef FORCE_STORED
- if (buf != (char*)0) { /* force stored block */
-#else
- if (stored_len+4 <= opt_lenb && buf != (char*)0) {
- /* 4: two words for the lengths */
-#endif
- /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
- * Otherwise we can't have processed more than WSIZE input bytes since
- * the last block flush, because compression would have been
- * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
- * transform a block into a stored block.
- */
- _tr_stored_block(s, buf, stored_len, eof);
-
-#ifdef FORCE_STATIC
- } else if (static_lenb >= 0) { /* force static trees */
-#else
- } else if (static_lenb == opt_lenb) {
-#endif
- send_bits(s, (STATIC_TREES<<1)+eof, 3);
- compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
- s->compressed_len += 3 + s->static_len;
- } else {
- send_bits(s, (DYN_TREES<<1)+eof, 3);
- send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
- max_blindex+1);
- compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
- s->compressed_len += 3 + s->opt_len;
- }
- Assert (s->compressed_len == s->bits_sent, "bad compressed size");
- init_block(s);
-
- if (eof) {
- bi_windup(s);
- s->compressed_len += 7; /* align on byte boundary */
- }
- Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
- s->compressed_len-7*eof));
-
- return s->compressed_len >> 3;
-}
-
-/* ===========================================================================
- * Save the match info and tally the frequency counts. Return true if
- * the current block must be flushed.
- */
-int _tr_tally (s, dist, lc)
- deflate_state *s;
- unsigned dist; /* distance of matched string */
- unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
-{
- s->d_buf[s->last_lit] = (ush)dist;
- s->l_buf[s->last_lit++] = (uch)lc;
- if (dist == 0) {
- /* lc is the unmatched char */
- s->dyn_ltree[lc].Freq++;
- } else {
- s->matches++;
- /* Here, lc is the match length - MIN_MATCH */
- dist--; /* dist = match distance - 1 */
- Assert((ush)dist < (ush)MAX_DIST(s) &&
- (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
- (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
-
- s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++;
- s->dyn_dtree[d_code(dist)].Freq++;
- }
-
- /* Try to guess if it is profitable to stop the current block here */
- if (s->level > 2 && (s->last_lit & 0xfff) == 0) {
- /* Compute an upper bound for the compressed length */
- ulg out_length = (ulg)s->last_lit*8L;
- ulg in_length = (ulg)((long)s->strstart - s->block_start);
- int dcode;
- for (dcode = 0; dcode < D_CODES; dcode++) {
- out_length += (ulg)s->dyn_dtree[dcode].Freq *
- (5L+extra_dbits[dcode]);
- }
- out_length >>= 3;
- Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
- s->last_lit, in_length, out_length,
- 100L - out_length*100L/in_length));
- if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
- }
- return (s->last_lit == s->lit_bufsize-1);
- /* We avoid equality with lit_bufsize because of wraparound at 64K
- * on 16 bit machines and because stored blocks are restricted to
- * 64K-1 bytes.
- */
-}
-
-/* ===========================================================================
- * Send the block data compressed using the given Huffman trees
- */
-local void compress_block(s, ltree, dtree)
- deflate_state *s;
- ct_data *ltree; /* literal tree */
- ct_data *dtree; /* distance tree */
-{
- unsigned dist; /* distance of matched string */
- int lc; /* match length or unmatched char (if dist == 0) */
- unsigned lx = 0; /* running index in l_buf */
- unsigned code; /* the code to send */
- int extra; /* number of extra bits to send */
-
- if (s->last_lit != 0) do {
- dist = s->d_buf[lx];
- lc = s->l_buf[lx++];
- if (dist == 0) {
- send_code(s, lc, ltree); /* send a literal byte */
- Tracecv(isgraph(lc), (stderr," '%c' ", lc));
- } else {
- /* Here, lc is the match length - MIN_MATCH */
- code = length_code[lc];
- send_code(s, code+LITERALS+1, ltree); /* send the length code */
- extra = extra_lbits[code];
- if (extra != 0) {
- lc -= base_length[code];
- send_bits(s, lc, extra); /* send the extra length bits */
- }
- dist--; /* dist is now the match distance - 1 */
- code = d_code(dist);
- Assert (code < D_CODES, "bad d_code");
-
- send_code(s, code, dtree); /* send the distance code */
- extra = extra_dbits[code];
- if (extra != 0) {
- dist -= base_dist[code];
- send_bits(s, dist, extra); /* send the extra distance bits */
- }
- } /* literal or match pair ? */
-
- /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
- Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
-
- } while (lx < s->last_lit);
-
- send_code(s, END_BLOCK, ltree);
- s->last_eob_len = ltree[END_BLOCK].Len;
-}
-
-/* ===========================================================================
- * Set the data type to ASCII or BINARY, using a crude approximation:
- * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
- * IN assertion: the fields freq of dyn_ltree are set and the total of all
- * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
- */
-local void set_data_type(s)
- deflate_state *s;
-{
- int n = 0;
- unsigned ascii_freq = 0;
- unsigned bin_freq = 0;
- while (n < 7) bin_freq += s->dyn_ltree[n++].Freq;
- while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq;
- while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
- s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
-}
-
-/* ===========================================================================
- * Reverse the first len bits of a code, using straightforward code (a faster
- * method would use a table)
- * IN assertion: 1 <= len <= 15
- */
-local unsigned bi_reverse(code, len)
- unsigned code; /* the value to invert */
- int len; /* its bit length */
-{
- register unsigned res = 0;
- do {
- res |= code & 1;
- code >>= 1, res <<= 1;
- } while (--len > 0);
- return res >> 1;
-}
-
-/* ===========================================================================
- * Flush the bit buffer, keeping at most 7 bits in it.
- */
-local void bi_flush(s)
- deflate_state *s;
-{
- if (s->bi_valid == 16) {
- put_short(s, s->bi_buf);
- s->bi_buf = 0;
- s->bi_valid = 0;
- } else if (s->bi_valid >= 8) {
- put_byte(s, (Byte)s->bi_buf);
- s->bi_buf >>= 8;
- s->bi_valid -= 8;
- }
-}
-
-/* ===========================================================================
- * Flush the bit buffer and align the output on a byte boundary
- */
-local void bi_windup(s)
- deflate_state *s;
-{
- if (s->bi_valid > 8) {
- put_short(s, s->bi_buf);
- } else if (s->bi_valid > 0) {
- put_byte(s, (Byte)s->bi_buf);
- }
- s->bi_buf = 0;
- s->bi_valid = 0;
-#ifdef DEBUG_ZLIB
- s->bits_sent = (s->bits_sent+7) & ~7;
-#endif
-}
-
-/* ===========================================================================
- * Copy a stored block, storing first the length and its
- * one's complement if requested.
- */
-local void copy_block(s, buf, len, header)
- deflate_state *s;
- charf *buf; /* the input data */
- unsigned len; /* its length */
- int header; /* true if block header must be written */
-{
- bi_windup(s); /* align on byte boundary */
- s->last_eob_len = 8; /* enough lookahead for inflate */
-
- if (header) {
- put_short(s, (ush)len);
- put_short(s, (ush)~len);
-#ifdef DEBUG_ZLIB
- s->bits_sent += 2*16;
-#endif
- }
-#ifdef DEBUG_ZLIB
- s->bits_sent += (ulg)len<<3;
-#endif
- /* bundle up the put_byte(s, *buf++) calls */
- zmemcpy(&s->pending_buf[s->pending], buf, len);
- s->pending += len;
-}
-/* --- trees.c */
-
-/* +++ inflate.c */
-/* inflate.c -- zlib interface to inflate modules
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* #include "zutil.h" */
-
-/* +++ infblock.h */
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_blocks_state;
-typedef struct inflate_blocks_state FAR inflate_blocks_statef;
-
-extern inflate_blocks_statef * inflate_blocks_new OF((
- z_streamp z,
- check_func c, /* check function */
- uInt w)); /* window size */
-
-extern int inflate_blocks OF((
- inflate_blocks_statef *,
- z_streamp ,
- int)); /* initial return code */
-
-extern void inflate_blocks_reset OF((
- inflate_blocks_statef *,
- z_streamp ,
- uLongf *)); /* check value on output */
-
-extern int inflate_blocks_free OF((
- inflate_blocks_statef *,
- z_streamp ,
- uLongf *)); /* check value on output */
-
-extern void inflate_set_dictionary OF((
- inflate_blocks_statef *s,
- const Bytef *d, /* dictionary */
- uInt n)); /* dictionary length */
-
-extern int inflate_addhistory OF((
- inflate_blocks_statef *,
- z_streamp));
-
-extern int inflate_packet_flush OF((
- inflate_blocks_statef *));
-/* --- infblock.h */
-
-#ifndef NO_DUMMY_DECL
-struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
-#endif
-
-/* inflate private state */
-struct internal_state {
-
- /* mode */
- enum {
- METHOD, /* waiting for method byte */
- FLAG, /* waiting for flag byte */
- DICT4, /* four dictionary check bytes to go */
- DICT3, /* three dictionary check bytes to go */
- DICT2, /* two dictionary check bytes to go */
- DICT1, /* one dictionary check byte to go */
- DICT0, /* waiting for inflateSetDictionary */
- BLOCKS, /* decompressing blocks */
- CHECK4, /* four check bytes to go */
- CHECK3, /* three check bytes to go */
- CHECK2, /* two check bytes to go */
- CHECK1, /* one check byte to go */
- DONE, /* finished check, done */
- BAD} /* got an error--stay here */
- mode; /* current inflate mode */
-
- /* mode dependent information */
- union {
- uInt method; /* if FLAGS, method byte */
- struct {
- uLong was; /* computed check value */
- uLong need; /* stream check value */
- } check; /* if CHECK, check values to compare */
- uInt marker; /* if BAD, inflateSync's marker bytes count */
- } sub; /* submode */
-
- /* mode independent information */
- int nowrap; /* flag for no wrapper */
- uInt wbits; /* log2(window size) (8..15, defaults to 15) */
- inflate_blocks_statef
- *blocks; /* current inflate_blocks state */
-
-};
-
-
-int inflateReset(z)
-z_streamp z;
-{
- uLong c;
-
- if (z == Z_NULL || z->state == Z_NULL)
- return Z_STREAM_ERROR;
- z->total_in = z->total_out = 0;
- z->msg = Z_NULL;
- z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
- inflate_blocks_reset(z->state->blocks, z, &c);
- Trace((stderr, "inflate: reset\n"));
- return Z_OK;
-}
-
-
-int inflateEnd(z)
-z_streamp z;
-{
- uLong c;
-
- if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
- return Z_STREAM_ERROR;
- if (z->state->blocks != Z_NULL)
- inflate_blocks_free(z->state->blocks, z, &c);
- ZFREE(z, z->state);
- z->state = Z_NULL;
- Trace((stderr, "inflate: end\n"));
- return Z_OK;
-}
-
-
-int inflateInit2_(z, w, version, stream_size)
-z_streamp z;
-int w;
-const char *version;
-int stream_size;
-{
- if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
- stream_size != sizeof(z_stream))
- return Z_VERSION_ERROR;
-
- /* initialize state */
- if (z == Z_NULL)
- return Z_STREAM_ERROR;
- z->msg = Z_NULL;
-#ifndef NO_ZCFUNCS
- if (z->zalloc == Z_NULL)
- {
- z->zalloc = zcalloc;
- z->opaque = (voidpf)0;
- }
- if (z->zfree == Z_NULL) z->zfree = zcfree;
-#endif
- if ((z->state = (struct internal_state FAR *)
- ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
- return Z_MEM_ERROR;
- z->state->blocks = Z_NULL;
-
- /* handle undocumented nowrap option (no zlib header or check) */
- z->state->nowrap = 0;
- if (w < 0)
- {
- w = - w;
- z->state->nowrap = 1;
- }
-
- /* set window size */
- if (w < 8 || w > 15)
- {
- inflateEnd(z);
- return Z_STREAM_ERROR;
- }
- z->state->wbits = (uInt)w;
-
- /* create inflate_blocks state */
- if ((z->state->blocks =
- inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
- == Z_NULL)
- {
- inflateEnd(z);
- return Z_MEM_ERROR;
- }
- Trace((stderr, "inflate: allocated\n"));
-
- /* reset state */
- inflateReset(z);
- return Z_OK;
-}
-
-
-int inflateInit_(z, version, stream_size)
-z_streamp z;
-const char *version;
-int stream_size;
-{
- return inflateInit2_(z, DEF_WBITS, version, stream_size);
-}
-
-
-#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
-#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
-
-int inflate(z, f)
-z_streamp z;
-int f;
-{
- int r;
- uInt b;
-
- if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL || f < 0)
- return Z_STREAM_ERROR;
- r = Z_BUF_ERROR;
- while (1) switch (z->state->mode)
- {
- case METHOD:
- NEEDBYTE
- if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
- {
- z->state->mode = BAD;
- z->msg = (char*)"unknown compression method";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
- {
- z->state->mode = BAD;
- z->msg = (char*)"invalid window size";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- z->state->mode = FLAG;
- case FLAG:
- NEEDBYTE
- b = NEXTBYTE;
- if (((z->state->sub.method << 8) + b) % 31)
- {
- z->state->mode = BAD;
- z->msg = (char*)"incorrect header check";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- Trace((stderr, "inflate: zlib header ok\n"));
- if (!(b & PRESET_DICT))
- {
- z->state->mode = BLOCKS;
- break;
- }
- z->state->mode = DICT4;
- case DICT4:
- NEEDBYTE
- z->state->sub.check.need = (uLong)NEXTBYTE << 24;
- z->state->mode = DICT3;
- case DICT3:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 16;
- z->state->mode = DICT2;
- case DICT2:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 8;
- z->state->mode = DICT1;
- case DICT1:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE;
- z->adler = z->state->sub.check.need;
- z->state->mode = DICT0;
- return Z_NEED_DICT;
- case DICT0:
- z->state->mode = BAD;
- z->msg = (char*)"need dictionary";
- z->state->sub.marker = 0; /* can try inflateSync */
- return Z_STREAM_ERROR;
- case BLOCKS:
- r = inflate_blocks(z->state->blocks, z, r);
- if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
- r = inflate_packet_flush(z->state->blocks);
- if (r == Z_DATA_ERROR)
- {
- z->state->mode = BAD;
- z->state->sub.marker = 0; /* can try inflateSync */
- break;
- }
- if (r != Z_STREAM_END)
- return r;
- r = Z_OK;
- inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
- if (z->state->nowrap)
- {
- z->state->mode = DONE;
- break;
- }
- z->state->mode = CHECK4;
- case CHECK4:
- NEEDBYTE
- z->state->sub.check.need = (uLong)NEXTBYTE << 24;
- z->state->mode = CHECK3;
- case CHECK3:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 16;
- z->state->mode = CHECK2;
- case CHECK2:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 8;
- z->state->mode = CHECK1;
- case CHECK1:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE;
-
- if (z->state->sub.check.was != z->state->sub.check.need)
- {
- z->state->mode = BAD;
- z->msg = (char*)"incorrect data check";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- Trace((stderr, "inflate: zlib check ok\n"));
- z->state->mode = DONE;
- case DONE:
- return Z_STREAM_END;
- case BAD:
- return Z_DATA_ERROR;
- default:
- return Z_STREAM_ERROR;
- }
-
- empty:
- if (f != Z_PACKET_FLUSH)
- return r;
- z->state->mode = BAD;
- z->msg = (char *)"need more for packet flush";
- z->state->sub.marker = 0; /* can try inflateSync */
- return Z_DATA_ERROR;
-}
-
-
-int inflateSetDictionary(z, dictionary, dictLength)
-z_streamp z;
-const Bytef *dictionary;
-uInt dictLength;
-{
- uInt length = dictLength;
-
- if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
- return Z_STREAM_ERROR;
-
- if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
- z->adler = 1L;
-
- if (length >= ((uInt)1<<z->state->wbits))
- {
- length = (1<<z->state->wbits)-1;
- dictionary += dictLength - length;
- }
- inflate_set_dictionary(z->state->blocks, dictionary, length);
- z->state->mode = BLOCKS;
- return Z_OK;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output. The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS). On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-
-int inflateIncomp(z)
-z_stream *z;
-{
- if (z->state->mode != BLOCKS)
- return Z_DATA_ERROR;
- return inflate_addhistory(z->state->blocks, z);
-}
-
-
-int inflateSync(z)
-z_streamp z;
-{
- uInt n; /* number of bytes to look at */
- Bytef *p; /* pointer to bytes */
- uInt m; /* number of marker bytes found in a row */
- uLong r, w; /* temporaries to save total_in and total_out */
-
- /* set up */
- if (z == Z_NULL || z->state == Z_NULL)
- return Z_STREAM_ERROR;
- if (z->state->mode != BAD)
- {
- z->state->mode = BAD;
- z->state->sub.marker = 0;
- }
- if ((n = z->avail_in) == 0)
- return Z_BUF_ERROR;
- p = z->next_in;
- m = z->state->sub.marker;
-
- /* search */
- while (n && m < 4)
- {
- if (*p == (Byte)(m < 2 ? 0 : 0xff))
- m++;
- else if (*p)
- m = 0;
- else
- m = 4 - m;
- p++, n--;
- }
-
- /* restore */
- z->total_in += p - z->next_in;
- z->next_in = p;
- z->avail_in = n;
- z->state->sub.marker = m;
-
- /* return no joy or set up to restart on a new block */
- if (m != 4)
- return Z_DATA_ERROR;
- r = z->total_in; w = z->total_out;
- inflateReset(z);
- z->total_in = r; z->total_out = w;
- z->state->mode = BLOCKS;
- return Z_OK;
-}
-
-#undef NEEDBYTE
-#undef NEXTBYTE
-/* --- inflate.c */
-
-/* +++ infblock.c */
-/* infblock.c -- interpret and process block types to last block
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* #include "zutil.h" */
-/* #include "infblock.h" */
-
-/* +++ inftrees.h */
-/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-/* Huffman code lookup table entry--this entry is four bytes for machines
- that have 16-bit pointers (e.g. PC's in the small or medium model). */
-
-typedef struct inflate_huft_s FAR inflate_huft;
-
-struct inflate_huft_s {
- union {
- struct {
- Byte Exop; /* number of extra bits or operation */
- Byte Bits; /* number of bits in this code or subcode */
- } what;
- Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
- } word; /* 16-bit, 8 bytes for 32-bit machines) */
- union {
- uInt Base; /* literal, length base, or distance base */
- inflate_huft *Next; /* pointer to next level of table */
- } more;
-};
-
-#ifdef DEBUG_ZLIB
- extern uInt inflate_hufts;
-#endif
-
-extern int inflate_trees_bits OF((
- uIntf *, /* 19 code lengths */
- uIntf *, /* bits tree desired/actual depth */
- inflate_huft * FAR *, /* bits tree result */
- z_streamp )); /* for zalloc, zfree functions */
-
-extern int inflate_trees_dynamic OF((
- uInt, /* number of literal/length codes */
- uInt, /* number of distance codes */
- uIntf *, /* that many (total) code lengths */
- uIntf *, /* literal desired/actual bit depth */
- uIntf *, /* distance desired/actual bit depth */
- inflate_huft * FAR *, /* literal/length tree result */
- inflate_huft * FAR *, /* distance tree result */
- z_streamp )); /* for zalloc, zfree functions */
-
-extern int inflate_trees_fixed OF((
- uIntf *, /* literal desired/actual bit depth */
- uIntf *, /* distance desired/actual bit depth */
- inflate_huft * FAR *, /* literal/length tree result */
- inflate_huft * FAR *)); /* distance tree result */
-
-extern int inflate_trees_free OF((
- inflate_huft *, /* tables to free */
- z_streamp )); /* for zfree function */
-
-/* --- inftrees.h */
-
-/* +++ infcodes.h */
-/* infcodes.h -- header to use infcodes.c
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_codes_state;
-typedef struct inflate_codes_state FAR inflate_codes_statef;
-
-extern inflate_codes_statef *inflate_codes_new OF((
- uInt, uInt,
- inflate_huft *, inflate_huft *,
- z_streamp ));
-
-extern int inflate_codes OF((
- inflate_blocks_statef *,
- z_streamp ,
- int));
-
-extern void inflate_codes_free OF((
- inflate_codes_statef *,
- z_streamp ));
-
-/* --- infcodes.h */
-
-/* +++ infutil.h */
-/* infutil.h -- types and macros common to blocks and codes
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-#ifndef _INFUTIL_H
-#define _INFUTIL_H
-
-typedef enum {
- TYPE, /* get type bits (3, including end bit) */
- LENS, /* get lengths for stored */
- STORED, /* processing stored block */
- TABLE, /* get table lengths */
- BTREE, /* get bit lengths tree for a dynamic block */
- DTREE, /* get length, distance trees for a dynamic block */
- CODES, /* processing fixed or dynamic block */
- DRY, /* output remaining window bytes */
- DONEB, /* finished last block, done */
- BADB} /* got a data error--stuck here */
-inflate_block_mode;
-
-/* inflate blocks semi-private state */
-struct inflate_blocks_state {
-
- /* mode */
- inflate_block_mode mode; /* current inflate_block mode */
-
- /* mode dependent information */
- union {
- uInt left; /* if STORED, bytes left to copy */
- struct {
- uInt table; /* table lengths (14 bits) */
- uInt index; /* index into blens (or border) */
- uIntf *blens; /* bit lengths of codes */
- uInt bb; /* bit length tree depth */
- inflate_huft *tb; /* bit length decoding tree */
- } trees; /* if DTREE, decoding info for trees */
- struct {
- inflate_huft *tl;
- inflate_huft *td; /* trees to free */
- inflate_codes_statef
- *codes;
- } decode; /* if CODES, current state */
- } sub; /* submode */
- uInt last; /* true if this block is the last block */
-
- /* mode independent information */
- uInt bitk; /* bits in bit buffer */
- uLong bitb; /* bit buffer */
- Bytef *window; /* sliding window */
- Bytef *end; /* one byte after sliding window */
- Bytef *read; /* window read pointer */
- Bytef *write; /* window write pointer */
- check_func checkfn; /* check function */
- uLong check; /* check on output */
-
-};
-
-
-/* defines for inflate input/output */
-/* update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE {UPDATE return inflate_flush(s,z,r);}
-/* get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
-#define NEXTBYTE (n--,*p++)
-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define DUMPBITS(j) {b>>=(j);k-=(j);}
-/* output bytes */
-#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
-#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
-#define WWRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
-#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
-#define NEEDOUT {if(m==0){WWRAP if(m==0){FLUSH WWRAP if(m==0) LEAVE}}r=Z_OK;}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/* load local pointers */
-#define LOAD {LOADIN LOADOUT}
-
-/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
-extern uInt inflate_mask[17];
-
-/* copy as much as possible from the sliding window to the output area */
-extern int inflate_flush OF((
- inflate_blocks_statef *,
- z_streamp ,
- int));
-
-#ifndef NO_DUMMY_DECL
-struct internal_state {int dummy;}; /* for buggy compilers */
-#endif
-
-#endif
-/* --- infutil.h */
-
-#ifndef NO_DUMMY_DECL
-struct inflate_codes_state {int dummy;}; /* for buggy compilers */
-#endif
-
-/* Table for deflate from PKZIP's appnote.txt. */
-local const uInt border[] = { /* Order of the bit length code lengths */
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/*
- Notes beyond the 1.93a appnote.txt:
-
- 1. Distance pointers never point before the beginning of the output
- stream.
- 2. Distance pointers can point back across blocks, up to 32k away.
- 3. There is an implied maximum of 7 bits for the bit length table and
- 15 bits for the actual data.
- 4. If only one code exists, then it is encoded using one bit. (Zero
- would be more efficient, but perhaps a little confusing.) If two
- codes exist, they are coded using one bit each (0 and 1).
- 5. There is no way of sending zero distance codes--a dummy must be
- sent if there are none. (History: a pre 2.0 version of PKZIP would
- store blocks with no distance codes, but this was discovered to be
- too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
- zero distance codes, which is sent as one code of zero bits in
- length.
- 6. There are up to 286 literal/length codes. Code 256 represents the
- end-of-block. Note however that the static length tree defines
- 288 codes just to fill out the Huffman codes. Codes 286 and 287
- cannot be used though, since there is no length base or extra bits
- defined for them. Similarily, there are up to 30 distance codes.
- However, static trees define 32 codes (all 5 bits) to fill out the
- Huffman codes, but the last two had better not show up in the data.
- 7. Unzip can check dynamic Huffman blocks for complete code sets.
- The exception is that a single code would not be complete (see #4).
- 8. The five bits following the block type is really the number of
- literal codes sent minus 257.
- 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
- (1+6+6). Therefore, to output three times the length, you output
- three codes (1+1+1), whereas to output four times the same length,
- you only need two codes (1+3). Hmm.
- 10. In the tree reconstruction algorithm, Code = Code + Increment
- only if BitLength(i) is not zero. (Pretty obvious.)
- 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
- 12. Note: length code 284 can represent 227-258, but length code 285
- really is 258. The last length deserves its own, short code
- since it gets used a lot in very redundant files. The length
- 258 is special since 258 - 3 (the min match length) is 255.
- 13. The literal/length and distance code bit lengths are read as a
- single stream of lengths. It is possible (and advantageous) for
- a repeat code (16, 17, or 18) to go across the boundary between
- the two sets of lengths.
- */
-
-
-void inflate_blocks_reset(s, z, c)
-inflate_blocks_statef *s;
-z_streamp z;
-uLongf *c;
-{
- if (s->checkfn != Z_NULL)
- *c = s->check;
- if (s->mode == BTREE || s->mode == DTREE)
- ZFREE(z, s->sub.trees.blens);
- if (s->mode == CODES)
- {
- inflate_codes_free(s->sub.decode.codes, z);
- inflate_trees_free(s->sub.decode.td, z);
- inflate_trees_free(s->sub.decode.tl, z);
- }
- s->mode = TYPE;
- s->bitk = 0;
- s->bitb = 0;
- s->read = s->write = s->window;
- if (s->checkfn != Z_NULL)
- z->adler = s->check = (*s->checkfn)(0L, Z_NULL, 0);
- Trace((stderr, "inflate: blocks reset\n"));
-}
-
-
-inflate_blocks_statef *inflate_blocks_new(z, c, w)
-z_streamp z;
-check_func c;
-uInt w;
-{
- inflate_blocks_statef *s;
-
- if ((s = (inflate_blocks_statef *)ZALLOC
- (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
- return s;
- if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
- {
- ZFREE(z, s);
- return Z_NULL;
- }
- s->end = s->window + w;
- s->checkfn = c;
- s->mode = TYPE;
- Trace((stderr, "inflate: blocks allocated\n"));
- inflate_blocks_reset(s, z, &s->check);
- return s;
-}
-
-
-#ifdef DEBUG_ZLIB
- extern uInt inflate_hufts;
-#endif
-int inflate_blocks(s, z, r)
-inflate_blocks_statef *s;
-z_streamp z;
-int r;
-{
- uInt t; /* temporary storage */
- uLong b; /* bit buffer */
- uInt k; /* bits in bit buffer */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
-
- /* copy input/output information to locals (UPDATE macro restores) */
- LOAD
-
- /* process input based on current state */
- while (1) switch (s->mode)
- {
- case TYPE:
- NEEDBITS(3)
- t = (uInt)b & 7;
- s->last = t & 1;
- switch (t >> 1)
- {
- case 0: /* stored */
- Trace((stderr, "inflate: stored block%s\n",
- s->last ? " (last)" : ""));
- DUMPBITS(3)
- t = k & 7; /* go to byte boundary */
- DUMPBITS(t)
- s->mode = LENS; /* get length of stored block */
- break;
- case 1: /* fixed */
- Trace((stderr, "inflate: fixed codes block%s\n",
- s->last ? " (last)" : ""));
- {
- uInt bl, bd;
- inflate_huft *tl, *td;
-
- inflate_trees_fixed(&bl, &bd, &tl, &td);
- s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
- if (s->sub.decode.codes == Z_NULL)
- {
- r = Z_MEM_ERROR;
- LEAVE
- }
- s->sub.decode.tl = Z_NULL; /* don't try to free these */
- s->sub.decode.td = Z_NULL;
- }
- DUMPBITS(3)
- s->mode = CODES;
- break;
- case 2: /* dynamic */
- Trace((stderr, "inflate: dynamic codes block%s\n",
- s->last ? " (last)" : ""));
- DUMPBITS(3)
- s->mode = TABLE;
- break;
- case 3: /* illegal */
- DUMPBITS(3)
- s->mode = BADB;
- z->msg = (char*)"invalid block type";
- r = Z_DATA_ERROR;
- LEAVE
- }
- break;
- case LENS:
- NEEDBITS(32)
- if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
- {
- s->mode = BADB;
- z->msg = (char*)"invalid stored block lengths";
- r = Z_DATA_ERROR;
- LEAVE
- }
- s->sub.left = (uInt)b & 0xffff;
- b = k = 0; /* dump bits */
- Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
- s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
- break;
- case STORED:
- if (n == 0)
- LEAVE
- NEEDOUT
- t = s->sub.left;
- if (t > n) t = n;
- if (t > m) t = m;
- zmemcpy(q, p, t);
- p += t; n -= t;
- q += t; m -= t;
- if ((s->sub.left -= t) != 0)
- break;
- Tracev((stderr, "inflate: stored end, %lu total out\n",
- z->total_out + (q >= s->read ? q - s->read :
- (s->end - s->read) + (q - s->window))));
- s->mode = s->last ? DRY : TYPE;
- break;
- case TABLE:
- NEEDBITS(14)
- s->sub.trees.table = t = (uInt)b & 0x3fff;
-#ifndef PKZIP_BUG_WORKAROUND
- if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
- {
- s->mode = BADB;
- z->msg = (char*)"too many length or distance symbols";
- r = Z_DATA_ERROR;
- LEAVE
- }
-#endif
- t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
- if (t < 19)
- t = 19;
- if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
- {
- r = Z_MEM_ERROR;
- LEAVE
- }
- DUMPBITS(14)
- s->sub.trees.index = 0;
- Tracev((stderr, "inflate: table sizes ok\n"));
- s->mode = BTREE;
- case BTREE:
- while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
- {
- NEEDBITS(3)
- s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
- DUMPBITS(3)
- }
- while (s->sub.trees.index < 19)
- s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
- s->sub.trees.bb = 7;
- t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
- &s->sub.trees.tb, z);
- if (t != Z_OK)
- {
- r = t;
- if (r == Z_DATA_ERROR) {
- s->mode = BADB;
- ZFREE(z, s->sub.trees.blens);
- }
- LEAVE
- }
- s->sub.trees.index = 0;
- Tracev((stderr, "inflate: bits tree ok\n"));
- s->mode = DTREE;
- case DTREE:
- while (t = s->sub.trees.table,
- s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
- {
- inflate_huft *h;
- uInt i, j, c;
-
- t = s->sub.trees.bb;
- NEEDBITS(t)
- h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
- t = h->word.what.Bits;
- c = h->more.Base;
- if (c < 16)
- {
- DUMPBITS(t)
- s->sub.trees.blens[s->sub.trees.index++] = c;
- }
- else /* c == 16..18 */
- {
- i = c == 18 ? 7 : c - 14;
- j = c == 18 ? 11 : 3;
- NEEDBITS(t + i)
- DUMPBITS(t)
- j += (uInt)b & inflate_mask[i];
- DUMPBITS(i)
- i = s->sub.trees.index;
- t = s->sub.trees.table;
- if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
- (c == 16 && i < 1))
- {
- inflate_trees_free(s->sub.trees.tb, z);
- ZFREE(z, s->sub.trees.blens);
- s->mode = BADB;
- z->msg = (char*)"invalid bit length repeat";
- r = Z_DATA_ERROR;
- LEAVE
- }
- c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
- do {
- s->sub.trees.blens[i++] = c;
- } while (--j);
- s->sub.trees.index = i;
- }
- }
- inflate_trees_free(s->sub.trees.tb, z);
- s->sub.trees.tb = Z_NULL;
- {
- uInt bl, bd;
- inflate_huft *tl, *td;
- inflate_codes_statef *c;
-
- bl = 9; /* must be <= 9 for lookahead assumptions */
- bd = 6; /* must be <= 9 for lookahead assumptions */
- t = s->sub.trees.table;
-#ifdef DEBUG_ZLIB
- inflate_hufts = 0;
-#endif
- t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
- s->sub.trees.blens, &bl, &bd, &tl, &td, z);
- if (t != Z_OK)
- {
- if (t == (uInt)Z_DATA_ERROR) {
- s->mode = BADB;
- ZFREE(z, s->sub.trees.blens);
- }
- r = t;
- LEAVE
- }
- ZFREE(z, s->sub.trees.blens);
- Tracev((stderr, "inflate: trees ok, %d * %d bytes used\n",
- inflate_hufts, sizeof(inflate_huft)));
- if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
- {
- inflate_trees_free(td, z);
- inflate_trees_free(tl, z);
- r = Z_MEM_ERROR;
- LEAVE
- }
- s->sub.decode.codes = c;
- s->sub.decode.tl = tl;
- s->sub.decode.td = td;
- }
- s->mode = CODES;
- case CODES:
- UPDATE
- if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
- return inflate_flush(s, z, r);
- r = Z_OK;
- inflate_codes_free(s->sub.decode.codes, z);
- inflate_trees_free(s->sub.decode.td, z);
- inflate_trees_free(s->sub.decode.tl, z);
- LOAD
- Tracev((stderr, "inflate: codes end, %lu total out\n",
- z->total_out + (q >= s->read ? q - s->read :
- (s->end - s->read) + (q - s->window))));
- if (!s->last)
- {
- s->mode = TYPE;
- break;
- }
- if (k > 7) /* return unused byte, if any */
- {
- Assert(k < 16, "inflate_codes grabbed too many bytes")
- k -= 8;
- n++;
- p--; /* can always return one */
- }
- s->mode = DRY;
- case DRY:
- FLUSH
- if (s->read != s->write)
- LEAVE
- s->mode = DONEB;
- case DONEB:
- r = Z_STREAM_END;
- LEAVE
- case BADB:
- r = Z_DATA_ERROR;
- LEAVE
- default:
- r = Z_STREAM_ERROR;
- LEAVE
- }
-}
-
-
-int inflate_blocks_free(s, z, c)
-inflate_blocks_statef *s;
-z_streamp z;
-uLongf *c;
-{
- inflate_blocks_reset(s, z, c);
- ZFREE(z, s->window);
- ZFREE(z, s);
- Trace((stderr, "inflate: blocks freed\n"));
- return Z_OK;
-}
-
-
-void inflate_set_dictionary(s, d, n)
-inflate_blocks_statef *s;
-const Bytef *d;
-uInt n;
-{
- zmemcpy((charf *)s->window, d, n);
- s->read = s->write = s->window + n;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output. The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS). On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-int inflate_addhistory(s, z)
-inflate_blocks_statef *s;
-z_stream *z;
-{
- uLong b; /* bit buffer */ /* NOT USED HERE */
- uInt k; /* bits in bit buffer */ /* NOT USED HERE */
- uInt t; /* temporary storage */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
-
- if (s->read != s->write)
- return Z_STREAM_ERROR;
- if (s->mode != TYPE)
- return Z_DATA_ERROR;
-
- /* we're ready to rock */
- LOAD
- /* while there is input ready, copy to output buffer, moving
- * pointers as needed.
- */
- while (n) {
- t = n; /* how many to do */
- /* is there room until end of buffer? */
- if (t > m) t = m;
- /* update check information */
- if (s->checkfn != Z_NULL)
- s->check = (*s->checkfn)(s->check, q, t);
- zmemcpy(q, p, t);
- q += t;
- p += t;
- n -= t;
- z->total_out += t;
- s->read = q; /* drag read pointer forward */
-/* WWRAP */ /* expand WWRAP macro by hand to handle s->read */
- if (q == s->end) {
- s->read = q = s->window;
- m = WAVAIL;
- }
- }
- UPDATE
- return Z_OK;
-}
-
-
-/*
- * At the end of a Deflate-compressed PPP packet, we expect to have seen
- * a `stored' block type value but not the (zero) length bytes.
- */
-int inflate_packet_flush(s)
- inflate_blocks_statef *s;
-{
- if (s->mode != LENS)
- return Z_DATA_ERROR;
- s->mode = TYPE;
- return Z_OK;
-}
-/* --- infblock.c */
-
-/* +++ inftrees.c */
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* #include "zutil.h" */
-/* #include "inftrees.h" */
-
-char inflate_copyright[] = " inflate 1.0.4 Copyright 1995-1996 Mark Adler ";
-/*
- If you use the zlib library in a product, an acknowledgment is welcome
- in the documentation of your product. If for some reason you cannot
- include such an acknowledgment, I would appreciate that you keep this
- copyright string in the executable of your product.
- */
-
-#ifndef NO_DUMMY_DECL
-struct internal_state {int dummy;}; /* for buggy compilers */
-#endif
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-
-local int huft_build OF((
- uIntf *, /* code lengths in bits */
- uInt, /* number of codes */
- uInt, /* number of "simple" codes */
- const uIntf *, /* list of base values for non-simple codes */
- const uIntf *, /* list of extra bits for non-simple codes */
- inflate_huft * FAR*,/* result: starting table */
- uIntf *, /* maximum lookup bits (returns actual) */
- z_streamp )); /* for zalloc function */
-
-local voidpf falloc OF((
- voidpf, /* opaque pointer (not used) */
- uInt, /* number of items */
- uInt)); /* size of item */
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
- /* see note #13 above about 258 */
-local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
-local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
- 8193, 12289, 16385, 24577};
-local const uInt cpdext[30] = { /* Extra bits for distance codes */
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
- 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
- 12, 12, 13, 13};
-
-/*
- Huffman code decoding is performed using a multi-level table lookup.
- The fastest way to decode is to simply build a lookup table whose
- size is determined by the longest code. However, the time it takes
- to build this table can also be a factor if the data being decoded
- is not very long. The most common codes are necessarily the
- shortest codes, so those codes dominate the decoding time, and hence
- the speed. The idea is you can have a shorter table that decodes the
- shorter, more probable codes, and then point to subsidiary tables for
- the longer codes. The time it costs to decode the longer codes is
- then traded against the time it takes to make longer tables.
-
- This results of this trade are in the variables lbits and dbits
- below. lbits is the number of bits the first level table for literal/
- length codes can decode in one step, and dbits is the same thing for
- the distance codes. Subsequent tables are also less than or equal to
- those sizes. These values may be adjusted either when all of the
- codes are shorter than that, in which case the longest code length in
- bits is used, or when the shortest code is *longer* than the requested
- table size, in which case the length of the shortest code in bits is
- used.
-
- There are two different values for the two tables, since they code a
- different number of possibilities each. The literal/length table
- codes 286 possible values, or in a flat code, a little over eight
- bits. The distance table codes 30 possible values, or a little less
- than five bits, flat. The optimum values for speed end up being
- about one bit more than those, so lbits is 8+1 and dbits is 5+1.
- The optimum values may differ though from machine to machine, and
- possibly even between compilers. Your mileage may vary.
- */
-
-
-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
-#define BMAX 15 /* maximum bit length of any code */
-#define N_MAX 288 /* maximum number of codes in any set */
-
-#ifdef DEBUG_ZLIB
- uInt inflate_hufts;
-#endif
-
-local int huft_build(b, n, s, d, e, t, m, zs)
-uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
-uInt n; /* number of codes (assumed <= N_MAX) */
-uInt s; /* number of simple-valued codes (0..s-1) */
-const uIntf *d; /* list of base values for non-simple codes */
-const uIntf *e; /* list of extra bits for non-simple codes */
-inflate_huft * FAR *t; /* result: starting table */
-uIntf *m; /* maximum lookup bits, returns actual */
-z_streamp zs; /* for zalloc function */
-/* Given a list of code lengths and a maximum table size, make a set of
- tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
- if the given code set is incomplete (the tables are still built in this
- case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
- lengths), or Z_MEM_ERROR if not enough memory. */
-{
-
- uInt a; /* counter for codes of length k */
- uInt c[BMAX+1]; /* bit length count table */
- uInt f; /* i repeats in table every f entries */
- int g; /* maximum code length */
- int h; /* table level */
- register uInt i; /* counter, current code */
- register uInt j; /* counter */
- register int k; /* number of bits in current code */
- int l; /* bits per table (returned in m) */
- register uIntf *p; /* pointer into c[], b[], or v[] */
- inflate_huft *q; /* points to current table */
- struct inflate_huft_s r; /* table entry for structure assignment */
- inflate_huft *u[BMAX]; /* table stack */
- uInt v[N_MAX]; /* values in order of bit length */
- register int w; /* bits before this table == (l * h) */
- uInt x[BMAX+1]; /* bit offsets, then code stack */
- uIntf *xp; /* pointer into x */
- int y; /* number of dummy codes added */
- uInt z; /* number of entries in current table */
-
-
- /* Generate counts for each bit length */
- p = c;
-#define C0 *p++ = 0;
-#define C2 C0 C0 C0 C0
-#define C4 C2 C2 C2 C2
- C4 /* clear c[]--assume BMAX+1 is 16 */
- p = b; i = n;
- do {
- c[*p++]++; /* assume all entries <= BMAX */
- } while (--i);
- if (c[0] == n) /* null input--all zero length codes */
- {
- *t = (inflate_huft *)Z_NULL;
- *m = 0;
- return Z_OK;
- }
-
-
- /* Find minimum and maximum length, bound *m by those */
- l = *m;
- for (j = 1; j <= BMAX; j++)
- if (c[j])
- break;
- k = j; /* minimum code length */
- if ((uInt)l < j)
- l = j;
- for (i = BMAX; i; i--)
- if (c[i])
- break;
- g = i; /* maximum code length */
- if ((uInt)l > i)
- l = i;
- *m = l;
-
-
- /* Adjust last length count to fill out codes, if needed */
- for (y = 1 << j; j < i; j++, y <<= 1)
- if ((y -= c[j]) < 0)
- return Z_DATA_ERROR;
- if ((y -= c[i]) < 0)
- return Z_DATA_ERROR;
- c[i] += y;
-
-
- /* Generate starting offsets into the value table for each length */
- x[1] = j = 0;
- p = c + 1; xp = x + 2;
- while (--i) { /* note that i == g from above */
- *xp++ = (j += *p++);
- }
-
-
- /* Make a table of values in order of bit lengths */
- p = b; i = 0;
- do {
- if ((j = *p++) != 0)
- v[x[j]++] = i;
- } while (++i < n);
- n = x[g]; /* set n to length of v */
-
-
- /* Generate the Huffman codes and for each, make the table entries */
- x[0] = i = 0; /* first Huffman code is zero */
- p = v; /* grab values in bit order */
- h = -1; /* no tables yet--level -1 */
- w = -l; /* bits decoded == (l * h) */
- u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
- q = (inflate_huft *)Z_NULL; /* ditto */
- z = 0; /* ditto */
-
- /* go through the bit lengths (k already is bits in shortest code) */
- for (; k <= g; k++)
- {
- a = c[k];
- while (a--)
- {
- /* here i is the Huffman code of length k bits for value *p */
- /* make tables up to required level */
- while (k > w + l)
- {
- h++;
- w += l; /* previous table always l bits */
-
- /* compute minimum size table less than or equal to l bits */
- z = g - w;
- z = z > (uInt)l ? l : z; /* table size upper limit */
- if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
- { /* too few codes for k-w bit table */
- f -= a + 1; /* deduct codes from patterns left */
- xp = c + k;
- if (j < z)
- while (++j < z) /* try smaller tables up to z bits */
- {
- if ((f <<= 1) <= *++xp)
- break; /* enough codes to use up j bits */
- f -= *xp; /* else deduct codes from patterns */
- }
- }
- z = 1 << j; /* table entries for j-bit table */
-
- /* allocate and link in new table */
- if ((q = (inflate_huft *)ZALLOC
- (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
- {
- if (h)
- inflate_trees_free(u[0], zs);
- return Z_MEM_ERROR; /* not enough memory */
- }
-#ifdef DEBUG_ZLIB
- inflate_hufts += z + 1;
-#endif
- *t = q + 1; /* link to list for huft_free() */
- *(t = &(q->next)) = Z_NULL;
- u[h] = ++q; /* table starts after link */
-
- /* connect to last table, if there is one */
- if (h)
- {
- x[h] = i; /* save pattern for backing up */
- r.bits = (Byte)l; /* bits to dump before this table */
- r.exop = (Byte)j; /* bits in this table */
- r.next = q; /* pointer to this table */
- j = i >> (w - l); /* (get around Turbo C bug) */
- u[h-1][j] = r; /* connect to last table */
- }
- }
-
- /* set up table entry in r */
- r.bits = (Byte)(k - w);
- if (p >= v + n)
- r.exop = 128 + 64; /* out of values--invalid code */
- else if (*p < s)
- {
- r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
- r.base = *p++; /* simple code is just the value */
- }
- else
- {
- r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
- r.base = d[*p++ - s];
- }
-
- /* fill code-like entries with r */
- f = 1 << (k - w);
- for (j = i >> w; j < z; j += f)
- q[j] = r;
-
- /* backwards increment the k-bit code i */
- for (j = 1 << (k - 1); i & j; j >>= 1)
- i ^= j;
- i ^= j;
-
- /* backup over finished tables */
- while ((i & ((1 << w) - 1)) != x[h])
- {
- h--; /* don't need to update q */
- w -= l;
- }
- }
- }
-
-
- /* Return Z_BUF_ERROR if we were given an incomplete table */
- return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-}
-
-
-int inflate_trees_bits(c, bb, tb, z)
-uIntf *c; /* 19 code lengths */
-uIntf *bb; /* bits tree desired/actual depth */
-inflate_huft * FAR *tb; /* bits tree result */
-z_streamp z; /* for zfree function */
-{
- int r;
-
- r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
- if (r == Z_DATA_ERROR)
- z->msg = (char*)"oversubscribed dynamic bit lengths tree";
- else if (r == Z_BUF_ERROR || *bb == 0)
- {
- inflate_trees_free(*tb, z);
- z->msg = (char*)"incomplete dynamic bit lengths tree";
- r = Z_DATA_ERROR;
- }
- return r;
-}
-
-
-int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
-uInt nl; /* number of literal/length codes */
-uInt nd; /* number of distance codes */
-uIntf *c; /* that many (total) code lengths */
-uIntf *bl; /* literal desired/actual bit depth */
-uIntf *bd; /* distance desired/actual bit depth */
-inflate_huft * FAR *tl; /* literal/length tree result */
-inflate_huft * FAR *td; /* distance tree result */
-z_streamp z; /* for zfree function */
-{
- int r;
-
- /* build literal/length tree */
- r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z);
- if (r != Z_OK || *bl == 0)
- {
- if (r == Z_DATA_ERROR)
- z->msg = (char*)"oversubscribed literal/length tree";
- else if (r != Z_MEM_ERROR)
- {
- inflate_trees_free(*tl, z);
- z->msg = (char*)"incomplete literal/length tree";
- r = Z_DATA_ERROR;
- }
- return r;
- }
-
- /* build distance tree */
- r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z);
- if (r != Z_OK || (*bd == 0 && nl > 257))
- {
- if (r == Z_DATA_ERROR)
- z->msg = (char*)"oversubscribed distance tree";
- else if (r == Z_BUF_ERROR) {
-#ifdef PKZIP_BUG_WORKAROUND
- r = Z_OK;
- }
-#else
- inflate_trees_free(*td, z);
- z->msg = (char*)"incomplete distance tree";
- r = Z_DATA_ERROR;
- }
- else if (r != Z_MEM_ERROR)
- {
- z->msg = (char*)"empty distance tree with lengths";
- r = Z_DATA_ERROR;
- }
- inflate_trees_free(*tl, z);
- return r;
-#endif
- }
-
- /* done */
- return Z_OK;
-}
-
-
-/* build fixed tables only once--keep them here */
-local int fixed_built = 0;
-#define FIXEDH 530 /* number of hufts used by fixed tables */
-local inflate_huft fixed_mem[FIXEDH];
-local uInt fixed_bl;
-local uInt fixed_bd;
-local inflate_huft *fixed_tl;
-local inflate_huft *fixed_td;
-
-
-local voidpf falloc(q, n, s)
-voidpf q; /* opaque pointer */
-uInt n; /* number of items */
-uInt s; /* size of item */
-{
- Assert(s == sizeof(inflate_huft) && n <= *(intf *)q,
- "inflate_trees falloc overflow");
- *(intf *)q -= n+s-s; /* s-s to avoid warning */
- return (voidpf)(fixed_mem + *(intf *)q);
-}
-
-
-int inflate_trees_fixed(bl, bd, tl, td)
-uIntf *bl; /* literal desired/actual bit depth */
-uIntf *bd; /* distance desired/actual bit depth */
-inflate_huft * FAR *tl; /* literal/length tree result */
-inflate_huft * FAR *td; /* distance tree result */
-{
- /* build fixed tables if not already (multiple overlapped executions ok) */
- if (!fixed_built)
- {
- int k; /* temporary variable */
- unsigned c[288]; /* length list for huft_build */
- z_stream z; /* for falloc function */
- int f = FIXEDH; /* number of hufts left in fixed_mem */
-
- /* set up fake z_stream for memory routines */
- z.zalloc = falloc;
- z.zfree = Z_NULL;
- z.opaque = (voidpf)&f;
-
- /* literal table */
- for (k = 0; k < 144; k++)
- c[k] = 8;
- for (; k < 256; k++)
- c[k] = 9;
- for (; k < 280; k++)
- c[k] = 7;
- for (; k < 288; k++)
- c[k] = 8;
- fixed_bl = 7;
- huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
-
- /* distance table */
- for (k = 0; k < 30; k++)
- c[k] = 5;
- fixed_bd = 5;
- huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
-
- /* done */
- Assert(f == 0, "invalid build of fixed tables");
- fixed_built = 1;
- }
- *bl = fixed_bl;
- *bd = fixed_bd;
- *tl = fixed_tl;
- *td = fixed_td;
- return Z_OK;
-}
-
-
-int inflate_trees_free(t, z)
-inflate_huft *t; /* table to free */
-z_streamp z; /* for zfree function */
-/* Free the malloc'ed tables built by huft_build(), which makes a linked
- list of the tables it made, with the links in a dummy first entry of
- each table. */
-{
- register inflate_huft *p, *q, *r;
-
- /* Reverse linked list */
- p = Z_NULL;
- q = t;
- while (q != Z_NULL)
- {
- r = (q - 1)->next;
- (q - 1)->next = p;
- p = q;
- q = r;
- }
- /* Go through linked list, freeing from the malloced (t[-1]) address. */
- while (p != Z_NULL)
- {
- q = (--p)->next;
- ZFREE(z,p);
- p = q;
- }
- return Z_OK;
-}
-/* --- inftrees.c */
-
-/* +++ infcodes.c */
-/* infcodes.c -- process literals and length/distance pairs
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* #include "zutil.h" */
-/* #include "inftrees.h" */
-/* #include "infblock.h" */
-/* #include "infcodes.h" */
-/* #include "infutil.h" */
-
-/* +++ inffast.h */
-/* inffast.h -- header to use inffast.c
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-extern int inflate_fast OF((
- uInt,
- uInt,
- inflate_huft *,
- inflate_huft *,
- inflate_blocks_statef *,
- z_streamp ));
-/* --- inffast.h */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* inflate codes private state */
-struct inflate_codes_state {
-
- /* mode */
- enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
- START, /* x: set up for LEN */
- LEN, /* i: get length/literal/eob next */
- LENEXT, /* i: getting length extra (have base) */
- DIST, /* i: get distance next */
- DISTEXT, /* i: getting distance extra */
- COPY, /* o: copying bytes in window, waiting for space */
- LIT, /* o: got literal, waiting for output space */
- WASH, /* o: got eob, possibly still output waiting */
- END, /* x: got eob and all data flushed */
- BADCODE} /* x: got error */
- mode; /* current inflate_codes mode */
-
- /* mode dependent information */
- uInt len;
- union {
- struct {
- inflate_huft *tree; /* pointer into tree */
- uInt need; /* bits needed */
- } code; /* if LEN or DIST, where in tree */
- uInt lit; /* if LIT, literal */
- struct {
- uInt get; /* bits to get for extra */
- uInt dist; /* distance back to copy from */
- } copy; /* if EXT or COPY, where and how much */
- } sub; /* submode */
-
- /* mode independent information */
- Byte lbits; /* ltree bits decoded per branch */
- Byte dbits; /* dtree bits decoder per branch */
- inflate_huft *ltree; /* literal/length/eob tree */
- inflate_huft *dtree; /* distance tree */
-
-};
-
-
-inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
-uInt bl, bd;
-inflate_huft *tl;
-inflate_huft *td; /* need separate declaration for Borland C++ */
-z_streamp z;
-{
- inflate_codes_statef *c;
-
- if ((c = (inflate_codes_statef *)
- ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
- {
- c->mode = START;
- c->lbits = (Byte)bl;
- c->dbits = (Byte)bd;
- c->ltree = tl;
- c->dtree = td;
- Tracev((stderr, "inflate: codes new\n"));
- }
- return c;
-}
-
-
-int inflate_codes(s, z, r)
-inflate_blocks_statef *s;
-z_streamp z;
-int r;
-{
- uInt j; /* temporary storage */
- inflate_huft *t; /* temporary pointer */
- uInt e; /* extra bits or operation */
- uLong b; /* bit buffer */
- uInt k; /* bits in bit buffer */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
- Bytef *f; /* pointer to copy strings from */
- inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
-
- /* copy input/output information to locals (UPDATE macro restores) */
- LOAD
-
- /* process input and output based on current state */
- while (1) switch (c->mode)
- { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
- case START: /* x: set up for LEN */
-#ifndef SLOW
- if (m >= 258 && n >= 10)
- {
- UPDATE
- r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
- LOAD
- if (r != Z_OK)
- {
- c->mode = r == Z_STREAM_END ? WASH : BADCODE;
- break;
- }
- }
-#endif /* !SLOW */
- c->sub.code.need = c->lbits;
- c->sub.code.tree = c->ltree;
- c->mode = LEN;
- case LEN: /* i: get length/literal/eob next */
- j = c->sub.code.need;
- NEEDBITS(j)
- t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
- DUMPBITS(t->bits)
- e = (uInt)(t->exop);
- if (e == 0) /* literal */
- {
- c->sub.lit = t->base;
- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
- "inflate: literal '%c'\n" :
- "inflate: literal 0x%02x\n", t->base));
- c->mode = LIT;
- break;
- }
- if (e & 16) /* length */
- {
- c->sub.copy.get = e & 15;
- c->len = t->base;
- c->mode = LENEXT;
- break;
- }
- if ((e & 64) == 0) /* next table */
- {
- c->sub.code.need = e;
- c->sub.code.tree = t->next;
- break;
- }
- if (e & 32) /* end of block */
- {
- Tracevv((stderr, "inflate: end of block\n"));
- c->mode = WASH;
- break;
- }
- c->mode = BADCODE; /* invalid code */
- z->msg = (char*)"invalid literal/length code";
- r = Z_DATA_ERROR;
- LEAVE
- case LENEXT: /* i: getting length extra (have base) */
- j = c->sub.copy.get;
- NEEDBITS(j)
- c->len += (uInt)b & inflate_mask[j];
- DUMPBITS(j)
- c->sub.code.need = c->dbits;
- c->sub.code.tree = c->dtree;
- Tracevv((stderr, "inflate: length %u\n", c->len));
- c->mode = DIST;
- case DIST: /* i: get distance next */
- j = c->sub.code.need;
- NEEDBITS(j)
- t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
- DUMPBITS(t->bits)
- e = (uInt)(t->exop);
- if (e & 16) /* distance */
- {
- c->sub.copy.get = e & 15;
- c->sub.copy.dist = t->base;
- c->mode = DISTEXT;
- break;
- }
- if ((e & 64) == 0) /* next table */
- {
- c->sub.code.need = e;
- c->sub.code.tree = t->next;
- break;
- }
- c->mode = BADCODE; /* invalid code */
- z->msg = (char*)"invalid distance code";
- r = Z_DATA_ERROR;
- LEAVE
- case DISTEXT: /* i: getting distance extra */
- j = c->sub.copy.get;
- NEEDBITS(j)
- c->sub.copy.dist += (uInt)b & inflate_mask[j];
- DUMPBITS(j)
- Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
- c->mode = COPY;
- case COPY: /* o: copying bytes in window, waiting for space */
-#ifndef __TURBOC__ /* Turbo C bug for following expression */
- f = (uInt)(q - s->window) < c->sub.copy.dist ?
- s->end - (c->sub.copy.dist - (q - s->window)) :
- q - c->sub.copy.dist;
-#else
- f = q - c->sub.copy.dist;
- if ((uInt)(q - s->window) < c->sub.copy.dist)
- f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
-#endif
- while (c->len)
- {
- NEEDOUT
- OUTBYTE(*f++)
- if (f == s->end)
- f = s->window;
- c->len--;
- }
- c->mode = START;
- break;
- case LIT: /* o: got literal, waiting for output space */
- NEEDOUT
- OUTBYTE(c->sub.lit)
- c->mode = START;
- break;
- case WASH: /* o: got eob, possibly more output */
- FLUSH
- if (s->read != s->write)
- LEAVE
- c->mode = END;
- case END:
- r = Z_STREAM_END;
- LEAVE
- case BADCODE: /* x: got error */
- r = Z_DATA_ERROR;
- LEAVE
- default:
- r = Z_STREAM_ERROR;
- LEAVE
- }
-}
-
-
-void inflate_codes_free(c, z)
-inflate_codes_statef *c;
-z_streamp z;
-{
- ZFREE(z, c);
- Tracev((stderr, "inflate: codes free\n"));
-}
-/* --- infcodes.c */
-
-/* +++ infutil.c */
-/* inflate_util.c -- data and routines common to blocks and codes
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* #include "zutil.h" */
-/* #include "infblock.h" */
-/* #include "inftrees.h" */
-/* #include "infcodes.h" */
-/* #include "infutil.h" */
-
-#ifndef NO_DUMMY_DECL
-struct inflate_codes_state {int dummy;}; /* for buggy compilers */
-#endif
-
-/* And'ing with mask[n] masks the lower n bits */
-uInt inflate_mask[17] = {
- 0x0000,
- 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
- 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-
-/* copy as much as possible from the sliding window to the output area */
-int inflate_flush(s, z, r)
-inflate_blocks_statef *s;
-z_streamp z;
-int r;
-{
- uInt n;
- Bytef *p;
- Bytef *q;
-
- /* local copies of source and destination pointers */
- p = z->next_out;
- q = s->read;
-
- /* compute number of bytes to copy as far as end of window */
- n = (uInt)((q <= s->write ? s->write : s->end) - q);
- if (n > z->avail_out) n = z->avail_out;
- if (n && r == Z_BUF_ERROR) r = Z_OK;
-
- /* update counters */
- z->avail_out -= n;
- z->total_out += n;
-
- /* update check information */
- if (s->checkfn != Z_NULL)
- z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
- /* copy as far as end of window */
- if (p != Z_NULL) {
- zmemcpy(p, q, n);
- p += n;
- }
- q += n;
-
- /* see if more to copy at beginning of window */
- if (q == s->end)
- {
- /* wrap pointers */
- q = s->window;
- if (s->write == s->end)
- s->write = s->window;
-
- /* compute bytes to copy */
- n = (uInt)(s->write - q);
- if (n > z->avail_out) n = z->avail_out;
- if (n && r == Z_BUF_ERROR) r = Z_OK;
-
- /* update counters */
- z->avail_out -= n;
- z->total_out += n;
-
- /* update check information */
- if (s->checkfn != Z_NULL)
- z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
- /* copy */
- if (p != Z_NULL) {
- zmemcpy(p, q, n);
- p += n;
- }
- q += n;
- }
-
- /* update pointers */
- z->next_out = p;
- s->read = q;
-
- /* done */
- return r;
-}
-/* --- infutil.c */
-
-/* +++ inffast.c */
-/* inffast.c -- process literals and length/distance pairs fast
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* #include "zutil.h" */
-/* #include "inftrees.h" */
-/* #include "infblock.h" */
-/* #include "infcodes.h" */
-/* #include "infutil.h" */
-/* #include "inffast.h" */
-
-#ifndef NO_DUMMY_DECL
-struct inflate_codes_state {int dummy;}; /* for buggy compilers */
-#endif
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* macros for bit input with no checking and for returning unused bytes */
-#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
-
-/* Called with number of bytes left to write in window at least 258
- (the maximum string length) and number of input bytes available
- at least ten. The ten bytes are six bytes for the longest length/
- distance pair plus four bytes for overloading the bit buffer. */
-
-int inflate_fast(bl, bd, tl, td, s, z)
-uInt bl, bd;
-inflate_huft *tl;
-inflate_huft *td; /* need separate declaration for Borland C++ */
-inflate_blocks_statef *s;
-z_streamp z;
-{
- inflate_huft *t; /* temporary pointer */
- uInt e; /* extra bits or operation */
- uLong b; /* bit buffer */
- uInt k; /* bits in bit buffer */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
- uInt ml; /* mask for literal/length tree */
- uInt md; /* mask for distance tree */
- uInt c; /* bytes to copy */
- uInt d; /* distance back to copy from */
- Bytef *r; /* copy source pointer */
-
- /* load input, output, bit values */
- LOAD
-
- /* initialize masks */
- ml = inflate_mask[bl];
- md = inflate_mask[bd];
-
- /* do until not enough input or output space for fast loop */
- do { /* assume called with m >= 258 && n >= 10 */
- /* get literal/length code */
- GRABBITS(20) /* max bits for literal/length code */
- if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
- {
- DUMPBITS(t->bits)
- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
- "inflate: * literal '%c'\n" :
- "inflate: * literal 0x%02x\n", t->base));
- *q++ = (Byte)t->base;
- m--;
- continue;
- }
- do {
- DUMPBITS(t->bits)
- if (e & 16)
- {
- /* get extra bits for length */
- e &= 15;
- c = t->base + ((uInt)b & inflate_mask[e]);
- DUMPBITS(e)
- Tracevv((stderr, "inflate: * length %u\n", c));
-
- /* decode distance base of block to copy */
- GRABBITS(15); /* max bits for distance code */
- e = (t = td + ((uInt)b & md))->exop;
- do {
- DUMPBITS(t->bits)
- if (e & 16)
- {
- /* get extra bits to add to distance base */
- e &= 15;
- GRABBITS(e) /* get extra bits (up to 13) */
- d = t->base + ((uInt)b & inflate_mask[e]);
- DUMPBITS(e)
- Tracevv((stderr, "inflate: * distance %u\n", d));
-
- /* do the copy */
- m -= c;
- if ((uInt)(q - s->window) >= d) /* offset before dest */
- { /* just copy */
- r = q - d;
- *q++ = *r++; c--; /* minimum count is three, */
- *q++ = *r++; c--; /* so unroll loop a little */
- }
- else /* else offset after destination */
- {
- e = d - (uInt)(q - s->window); /* bytes from offset to end */
- r = s->end - e; /* pointer to offset */
- if (c > e) /* if source crosses, */
- {
- c -= e; /* copy to end of window */
- do {
- *q++ = *r++;
- } while (--e);
- r = s->window; /* copy rest from start of window */
- }
- }
- do { /* copy all or what's left */
- *q++ = *r++;
- } while (--c);
- break;
- }
- else if ((e & 64) == 0)
- e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
- else
- {
- z->msg = (char*)"invalid distance code";
- UNGRAB
- UPDATE
- return Z_DATA_ERROR;
- }
- } while (1);
- break;
- }
- if ((e & 64) == 0)
- {
- if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
- {
- DUMPBITS(t->bits)
- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
- "inflate: * literal '%c'\n" :
- "inflate: * literal 0x%02x\n", t->base));
- *q++ = (Byte)t->base;
- m--;
- break;
- }
- }
- else if (e & 32)
- {
- Tracevv((stderr, "inflate: * end of block\n"));
- UNGRAB
- UPDATE
- return Z_STREAM_END;
- }
- else
- {
- z->msg = (char*)"invalid literal/length code";
- UNGRAB
- UPDATE
- return Z_DATA_ERROR;
- }
- } while (1);
- } while (m >= 258 && n >= 10);
-
- /* not enough input or output--restore pointers and return */
- UNGRAB
- UPDATE
- return Z_OK;
-}
-/* --- inffast.c */
-
-/* +++ zutil.c */
-/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-1996 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* From: zutil.c,v 1.17 1996/07/24 13:41:12 me Exp $ */
-
-#ifdef DEBUG_ZLIB
-#include <stdio.h>
-#endif
-
-/* #include "zutil.h" */
-
-#ifndef NO_DUMMY_DECL
-struct internal_state {int dummy;}; /* for buggy compilers */
-#endif
-
-#ifndef STDC
-extern void exit OF((int));
-#endif
-
-const char *z_errmsg[10] = {
-"need dictionary", /* Z_NEED_DICT 2 */
-"stream end", /* Z_STREAM_END 1 */
-"", /* Z_OK 0 */
-"file error", /* Z_ERRNO (-1) */
-"stream error", /* Z_STREAM_ERROR (-2) */
-"data error", /* Z_DATA_ERROR (-3) */
-"insufficient memory", /* Z_MEM_ERROR (-4) */
-"buffer error", /* Z_BUF_ERROR (-5) */
-"incompatible version",/* Z_VERSION_ERROR (-6) */
-""};
-
-
-const char *zlibVersion()
-{
- return ZLIB_VERSION;
-}
-
-#ifdef DEBUG_ZLIB
-void z_error (m)
- char *m;
-{
- fprintf(stderr, "%s\n", m);
- exit(1);
-}
-#endif
-
-#ifndef HAVE_MEMCPY
-
-void zmemcpy(dest, source, len)
- Bytef* dest;
- Bytef* source;
- uInt len;
-{
- if (len == 0) return;
- do {
- *dest++ = *source++; /* ??? to be unrolled */
- } while (--len != 0);
-}
-
-int zmemcmp(s1, s2, len)
- Bytef* s1;
- Bytef* s2;
- uInt len;
-{
- uInt j;
-
- for (j = 0; j < len; j++) {
- if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
- }
- return 0;
-}
-
-void zmemzero(dest, len)
- Bytef* dest;
- uInt len;
-{
- if (len == 0) return;
- do {
- *dest++ = 0; /* ??? to be unrolled */
- } while (--len != 0);
-}
-#endif
-
-#ifdef __TURBOC__
-#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
-/* Small and medium model in Turbo C are for now limited to near allocation
- * with reduced MAX_WBITS and MAX_MEM_LEVEL
- */
-# define MY_ZCALLOC
-
-/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
- * and farmalloc(64K) returns a pointer with an offset of 8, so we
- * must fix the pointer. Warning: the pointer must be put back to its
- * original form in order to free it, use zcfree().
- */
-
-#define MAX_PTR 10
-/* 10*64K = 640K */
-
-local int next_ptr = 0;
-
-typedef struct ptr_table_s {
- voidpf org_ptr;
- voidpf new_ptr;
-} ptr_table;
-
-local ptr_table table[MAX_PTR];
-/* This table is used to remember the original form of pointers
- * to large buffers (64K). Such pointers are normalized with a zero offset.
- * Since MSDOS is not a preemptive multitasking OS, this table is not
- * protected from concurrent access. This hack doesn't work anyway on
- * a protected system like OS/2. Use Microsoft C instead.
- */
-
-voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
-{
- voidpf buf = opaque; /* just to make some compilers happy */
- ulg bsize = (ulg)items*size;
-
- /* If we allocate less than 65520 bytes, we assume that farmalloc
- * will return a usable pointer which doesn't have to be normalized.
- */
- if (bsize < 65520L) {
- buf = farmalloc(bsize);
- if (*(ush*)&buf != 0) return buf;
- } else {
- buf = farmalloc(bsize + 16L);
- }
- if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
- table[next_ptr].org_ptr = buf;
-
- /* Normalize the pointer to seg:0 */
- *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
- *(ush*)&buf = 0;
- table[next_ptr++].new_ptr = buf;
- return buf;
-}
-
-void zcfree (voidpf opaque, voidpf ptr)
-{
- int n;
- if (*(ush*)&ptr != 0) { /* object < 64K */
- farfree(ptr);
- return;
- }
- /* Find the original pointer */
- for (n = 0; n < next_ptr; n++) {
- if (ptr != table[n].new_ptr) continue;
-
- farfree(table[n].org_ptr);
- while (++n < next_ptr) {
- table[n-1] = table[n];
- }
- next_ptr--;
- return;
- }
- ptr = opaque; /* just to make some compilers happy */
- Assert(0, "zcfree: ptr not found");
-}
-#endif
-#endif /* __TURBOC__ */
-
-
-#if defined(M_I86) && !defined(__32BIT__)
-/* Microsoft C in 16-bit mode */
-
-# define MY_ZCALLOC
-
-#if (!defined(_MSC_VER) || (_MSC_VER < 600))
-# define _halloc halloc
-# define _hfree hfree
-#endif
-
-voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
-{
- if (opaque) opaque = 0; /* to make compiler happy */
- return _halloc((long)items, size);
-}
-
-void zcfree (voidpf opaque, voidpf ptr)
-{
- if (opaque) opaque = 0; /* to make compiler happy */
- _hfree(ptr);
-}
-
-#endif /* MSC */
-
-
-#ifndef MY_ZCALLOC /* Any system without a special alloc function */
-
-#ifndef STDC
-extern voidp calloc OF((uInt items, uInt size));
-extern void free OF((voidpf ptr));
-#endif
-
-voidpf zcalloc (opaque, items, size)
- voidpf opaque;
- unsigned items;
- unsigned size;
-{
- if (opaque) items += size - size; /* make compiler happy */
- return (voidpf)calloc(items, size);
-}
-
-void zcfree (opaque, ptr)
- voidpf opaque;
- voidpf ptr;
-{
- free(ptr);
- if (opaque) return; /* make compiler happy */
-}
-
-#endif /* MY_ZCALLOC */
-/* --- zutil.c */
-
-/* +++ adler32.c */
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-1996 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* From: adler32.c,v 1.10 1996/05/22 11:52:18 me Exp $ */
-
-/* #include "zlib.h" */
-
-#define BASE 65521L /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
-#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf) DO8(buf,0); DO8(buf,8);
-
-/* ========================================================================= */
-uLong adler32(adler, buf, len)
- uLong adler;
- const Bytef *buf;
- uInt len;
-{
- unsigned long s1 = adler & 0xffff;
- unsigned long s2 = (adler >> 16) & 0xffff;
- int k;
-
- if (buf == Z_NULL) return 1L;
-
- while (len > 0) {
- k = len < NMAX ? len : NMAX;
- len -= k;
- while (k >= 16) {
- DO16(buf);
- buf += 16;
- k -= 16;
- }
- if (k != 0) do {
- s1 += *buf++;
- s2 += s1;
- } while (--k);
- s1 %= BASE;
- s2 %= BASE;
- }
- return (s2 << 16) | s1;
-}
-/* --- adler32.c */
+++ /dev/null
-/* $Id: zlib.h,v 1.7 1997/11/27 06:03:33 paulus Exp $ */
-
-/*
- * This file is derived from zlib.h and zconf.h from the zlib-1.0.4
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets.
- */
-
-/*
- * ==FILEVERSION 971127==
- *
- * This marker is used by the Linux installation script to determine
- * whether an up-to-date version of this file is already installed.
- */
-
-
-/* +++ zlib.h */
-/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.0.4, Jul 24th, 1996.
-
- Copyright (C) 1995-1996 Jean-loup Gailly and Mark Adler
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- Jean-loup Gailly Mark Adler
- gzip@prep.ai.mit.edu madler@alumni.caltech.edu
-
-
- The data format used by the zlib library is described by RFCs (Request for
- Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
- (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
-*/
-
-#ifndef _ZLIB_H
-#define _ZLIB_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* +++ zconf.h */
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-1996 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* From: zconf.h,v 1.20 1996/07/02 15:09:28 me Exp $ */
-
-#ifndef _ZCONF_H
-#define _ZCONF_H
-
-/*
- * If you *really* need a unique prefix for all types and library functions,
- * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
- */
-#ifdef Z_PREFIX
-# define deflateInit_ z_deflateInit_
-# define deflate z_deflate
-# define deflateEnd z_deflateEnd
-# define inflateInit_ z_inflateInit_
-# define inflate z_inflate
-# define inflateEnd z_inflateEnd
-# define deflateInit2_ z_deflateInit2_
-# define deflateSetDictionary z_deflateSetDictionary
-# define deflateCopy z_deflateCopy
-# define deflateReset z_deflateReset
-# define deflateParams z_deflateParams
-# define inflateInit2_ z_inflateInit2_
-# define inflateSetDictionary z_inflateSetDictionary
-# define inflateSync z_inflateSync
-# define inflateReset z_inflateReset
-# define compress z_compress
-# define uncompress z_uncompress
-# define adler32 z_adler32
-# define crc32 z_crc32
-# define get_crc_table z_get_crc_table
-
-# define Byte z_Byte
-# define uInt z_uInt
-# define uLong z_uLong
-# define Bytef z_Bytef
-# define charf z_charf
-# define intf z_intf
-# define uIntf z_uIntf
-# define uLongf z_uLongf
-# define voidpf z_voidpf
-# define voidp z_voidp
-#endif
-
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-# define WIN32
-#endif
-#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
-# ifndef __32BIT__
-# define __32BIT__
-# endif
-#endif
-#if defined(__MSDOS__) && !defined(MSDOS)
-# define MSDOS
-#endif
-
-/*
- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
- * than 64k bytes at a time (needed on systems with 16-bit int).
- */
-#if defined(MSDOS) && !defined(__32BIT__)
-# define MAXSEG_64K
-#endif
-#ifdef MSDOS
-# define UNALIGNED_OK
-#endif
-
-#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
-# define STDC
-#endif
-#if (defined(__STDC__) || defined(__cplusplus)) && !defined(STDC)
-# define STDC
-#endif
-
-#ifndef STDC
-# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
-# define const
-# endif
-#endif
-
-/* Some Mac compilers merge all .h files incorrectly: */
-#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
-# define NO_DUMMY_DECL
-#endif
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-# ifdef MAXSEG_64K
-# define MAX_MEM_LEVEL 8
-# else
-# define MAX_MEM_LEVEL 9
-# endif
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
-#ifndef MAX_WBITS
-# define MAX_WBITS 15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
- 1 << (windowBits+2) + 1 << (memLevel+9)
- that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
- make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
- The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
- /* Type declarations */
-
-#ifndef OF /* function prototypes */
-# ifdef STDC
-# define OF(args) args
-# else
-# define OF(args) ()
-# endif
-#endif
-
-/* The following definitions for FAR are needed only for MSDOS mixed
- * model programming (small or medium model with some far allocations).
- * This was tested only with MSC; for other MSDOS compilers you may have
- * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
- * just define FAR to be empty.
- */
-#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
- /* MSC small or medium model */
-# define SMALL_MEDIUM
-# ifdef _MSC_VER
-# define FAR __far
-# else
-# define FAR far
-# endif
-#endif
-#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
-# ifndef __32BIT__
-# define SMALL_MEDIUM
-# define FAR __far
-# endif
-#endif
-#ifndef FAR
-# define FAR
-#endif
-
-typedef unsigned char Byte; /* 8 bits */
-typedef unsigned int uInt; /* 16 bits or more */
-typedef unsigned long uLong; /* 32 bits or more */
-
-#if defined(__BORLANDC__) && defined(SMALL_MEDIUM)
- /* Borland C/C++ ignores FAR inside typedef */
-# define Bytef Byte FAR
-#else
- typedef Byte FAR Bytef;
-#endif
-typedef char FAR charf;
-typedef int FAR intf;
-typedef uInt FAR uIntf;
-typedef uLong FAR uLongf;
-
-#ifdef STDC
- typedef void FAR *voidpf;
- typedef void *voidp;
-#else
- typedef Byte FAR *voidpf;
- typedef Byte *voidp;
-#endif
-
-
-/* Compile with -DZLIB_DLL for Windows DLL support */
-#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL)
-# include <windows.h>
-# define EXPORT WINAPI
-#else
-# define EXPORT
-#endif
-
-#endif /* _ZCONF_H */
-/* --- zconf.h */
-
-#define ZLIB_VERSION "1.0.4P"
-
-/*
- The 'zlib' compression library provides in-memory compression and
- decompression functions, including integrity checks of the uncompressed
- data. This version of the library supports only one compression method
- (deflation) but other algorithms may be added later and will have the same
- stream interface.
-
- For compression the application must provide the output buffer and
- may optionally provide the input buffer for optimization. For decompression,
- the application must provide the input buffer and may optionally provide
- the output buffer for optimization.
-
- Compression can be done in a single step if the buffers are large
- enough (for example if an input file is mmap'ed), or can be done by
- repeated calls of the compression function. In the latter case, the
- application must provide more input and/or consume the output
- (providing more output space) before each call.
-
- The library does not install any signal handler. It is recommended to
- add at least a handler for SIGSEGV when decompressing; the library checks
- the consistency of the input data whenever possible but may go nuts
- for some forms of corrupted input.
-*/
-
-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
-typedef void (*free_func) OF((voidpf opaque, voidpf address));
-
-struct internal_state;
-
-typedef struct z_stream_s {
- Bytef *next_in; /* next input byte */
- uInt avail_in; /* number of bytes available at next_in */
- uLong total_in; /* total nb of input bytes read so far */
-
- Bytef *next_out; /* next output byte should be put there */
- uInt avail_out; /* remaining free space at next_out */
- uLong total_out; /* total nb of bytes output so far */
-
- char *msg; /* last error message, NULL if no error */
- struct internal_state FAR *state; /* not visible by applications */
-
- alloc_func zalloc; /* used to allocate the internal state */
- free_func zfree; /* used to free the internal state */
- voidpf opaque; /* private data object passed to zalloc and zfree */
-
- int data_type; /* best guess about the data type: ascii or binary */
- uLong adler; /* adler32 value of the uncompressed data */
- uLong reserved; /* reserved for future use */
-} z_stream;
-
-typedef z_stream FAR *z_streamp;
-
-/*
- The application must update next_in and avail_in when avail_in has
- dropped to zero. It must update next_out and avail_out when avail_out
- has dropped to zero. The application must initialize zalloc, zfree and
- opaque before calling the init function. All other fields are set by the
- compression library and must not be updated by the application.
-
- The opaque value provided by the application will be passed as the first
- parameter for calls of zalloc and zfree. This can be useful for custom
- memory management. The compression library attaches no meaning to the
- opaque value.
-
- zalloc must return Z_NULL if there is not enough memory for the object.
- On 16-bit systems, the functions zalloc and zfree must be able to allocate
- exactly 65536 bytes, but will not be required to allocate more than this
- if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
- pointers returned by zalloc for objects of exactly 65536 bytes *must*
- have their offset normalized to zero. The default allocation function
- provided by this library ensures this (see zutil.c). To reduce memory
- requirements and avoid any allocation of 64K objects, at the expense of
- compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-
- The fields total_in and total_out can be used for statistics or
- progress reports. After compression, total_in holds the total size of
- the uncompressed data and may be saved for use in the decompressor
- (particularly if the decompressor wants to decompress everything in
- a single step).
-*/
-
- /* constants */
-
-#define Z_NO_FLUSH 0
-#define Z_PARTIAL_FLUSH 1
-#define Z_PACKET_FLUSH 2
-#define Z_SYNC_FLUSH 3
-#define Z_FULL_FLUSH 4
-#define Z_FINISH 5
-/* Allowed flush values; see deflate() below for details */
-
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_NEED_DICT 2
-#define Z_ERRNO (-1)
-#define Z_STREAM_ERROR (-2)
-#define Z_DATA_ERROR (-3)
-#define Z_MEM_ERROR (-4)
-#define Z_BUF_ERROR (-5)
-#define Z_VERSION_ERROR (-6)
-/* Return codes for the compression/decompression functions. Negative
- * values are errors, positive values are used for special but normal events.
- */
-
-#define Z_NO_COMPRESSION 0
-#define Z_BEST_SPEED 1
-#define Z_BEST_COMPRESSION 9
-#define Z_DEFAULT_COMPRESSION (-1)
-/* compression levels */
-
-#define Z_FILTERED 1
-#define Z_HUFFMAN_ONLY 2
-#define Z_DEFAULT_STRATEGY 0
-/* compression strategy; see deflateInit2() below for details */
-
-#define Z_BINARY 0
-#define Z_ASCII 1
-#define Z_UNKNOWN 2
-/* Possible values of the data_type field */
-
-#define Z_DEFLATED 8
-/* The deflate compression method (the only one supported in this version) */
-
-#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
-
-#define zlib_version zlibVersion()
-/* for compatibility with versions < 1.0.2 */
-
- /* basic functions */
-
-extern const char * EXPORT zlibVersion OF((void));
-/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
- If the first character differs, the library code actually used is
- not compatible with the zlib.h header file used by the application.
- This check is automatically made by deflateInit and inflateInit.
- */
-
-/*
-extern int EXPORT deflateInit OF((z_streamp strm, int level));
-
- Initializes the internal stream state for compression. The fields
- zalloc, zfree and opaque must be initialized before by the caller.
- If zalloc and zfree are set to Z_NULL, deflateInit updates them to
- use default allocation functions.
-
- The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
- 1 gives best speed, 9 gives best compression, 0 gives no compression at
- all (the input data is simply copied a block at a time).
- Z_DEFAULT_COMPRESSION requests a default compromise between speed and
- compression (currently equivalent to level 6).
-
- deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
- enough memory, Z_STREAM_ERROR if level is not a valid compression level,
- Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
- with the version assumed by the caller (ZLIB_VERSION).
- msg is set to null if there is no error message. deflateInit does not
- perform any compression: this will be done by deflate().
-*/
-
-
-extern int EXPORT deflate OF((z_streamp strm, int flush));
-/*
- Performs one or both of the following actions:
-
- - Compress more input starting at next_in and update next_in and avail_in
- accordingly. If not all input can be processed (because there is not
- enough room in the output buffer), next_in and avail_in are updated and
- processing will resume at this point for the next call of deflate().
-
- - Provide more output starting at next_out and update next_out and avail_out
- accordingly. This action is forced if the parameter flush is non zero.
- Forcing flush frequently degrades the compression ratio, so this parameter
- should be set only when necessary (in interactive applications).
- Some output may be provided even if flush is not set.
-
- Before the call of deflate(), the application should ensure that at least
- one of the actions is possible, by providing more input and/or consuming
- more output, and updating avail_in or avail_out accordingly; avail_out
- should never be zero before the call. The application can consume the
- compressed output when it wants, for example when the output buffer is full
- (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
- and with zero avail_out, it must be called again after making room in the
- output buffer because there might be more output pending.
-
- If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression
- block is terminated and flushed to the output buffer so that the
- decompressor can get all input data available so far. For method 9, a future
- variant on method 8, the current block will be flushed but not terminated.
- Z_SYNC_FLUSH has the same effect as partial flush except that the compressed
- output is byte aligned (the compressor can clear its internal bit buffer)
- and the current block is always terminated; this can be useful if the
- compressor has to be restarted from scratch after an interruption (in which
- case the internal state of the compressor may be lost).
- If flush is set to Z_FULL_FLUSH, the compression block is terminated, a
- special marker is output and the compression dictionary is discarded; this
- is useful to allow the decompressor to synchronize if one compressed block
- has been damaged (see inflateSync below). Flushing degrades compression and
- so should be used only when necessary. Using Z_FULL_FLUSH too often can
- seriously degrade the compression. If deflate returns with avail_out == 0,
- this function must be called again with the same value of the flush
- parameter and more output space (updated avail_out), until the flush is
- complete (deflate returns with non-zero avail_out).
-
- If the parameter flush is set to Z_PACKET_FLUSH, the compression
- block is terminated, and a zero-length stored block is output,
- omitting the length bytes (the effect of this is that the 3-bit type
- code 000 for a stored block is output, and the output is then
- byte-aligned). This is designed for use at the end of a PPP packet.
-
- If the parameter flush is set to Z_FINISH, pending input is processed,
- pending output is flushed and deflate returns with Z_STREAM_END if there
- was enough output space; if deflate returns with Z_OK, this function must be
- called again with Z_FINISH and more output space (updated avail_out) but no
- more input data, until it returns with Z_STREAM_END or an error. After
- deflate has returned Z_STREAM_END, the only possible operations on the
- stream are deflateReset or deflateEnd.
-
- Z_FINISH can be used immediately after deflateInit if all the compression
- is to be done in a single step. In this case, avail_out must be at least
- 0.1% larger than avail_in plus 12 bytes. If deflate does not return
- Z_STREAM_END, then it must be called again as described above.
-
- deflate() may update data_type if it can make a good guess about
- the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
- binary. This field is only for information purposes and does not affect
- the compression algorithm in any manner.
-
- deflate() returns Z_OK if some progress has been made (more input
- processed or more output produced), Z_STREAM_END if all input has been
- consumed and all output has been produced (only when flush is set to
- Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
- if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible.
-*/
-
-
-extern int EXPORT deflateEnd OF((z_streamp strm));
-/*
- All dynamically allocated data structures for this stream are freed.
- This function discards any unprocessed input and does not flush any
- pending output.
-
- deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
- stream state was inconsistent, Z_DATA_ERROR if the stream was freed
- prematurely (some input or output was discarded). In the error case,
- msg may be set but then points to a static string (which must not be
- deallocated).
-*/
-
-
-/*
-extern int EXPORT inflateInit OF((z_streamp strm));
-
- Initializes the internal stream state for decompression. The fields
- zalloc, zfree and opaque must be initialized before by the caller. If
- zalloc and zfree are set to Z_NULL, inflateInit updates them to use default
- allocation functions.
-
- inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
- enough memory, Z_VERSION_ERROR if the zlib library version is incompatible
- with the version assumed by the caller. msg is set to null if there is no
- error message. inflateInit does not perform any decompression: this will be
- done by inflate().
-*/
-
-
-extern int EXPORT inflate OF((z_streamp strm, int flush));
-/*
- Performs one or both of the following actions:
-
- - Decompress more input starting at next_in and update next_in and avail_in
- accordingly. If not all input can be processed (because there is not
- enough room in the output buffer), next_in is updated and processing
- will resume at this point for the next call of inflate().
-
- - Provide more output starting at next_out and update next_out and avail_out
- accordingly. inflate() provides as much output as possible, until there
- is no more input data or no more space in the output buffer (see below
- about the flush parameter).
-
- Before the call of inflate(), the application should ensure that at least
- one of the actions is possible, by providing more input and/or consuming
- more output, and updating the next_* and avail_* values accordingly.
- The application can consume the uncompressed output when it wants, for
- example when the output buffer is full (avail_out == 0), or after each
- call of inflate(). If inflate returns Z_OK and with zero avail_out, it
- must be called again after making room in the output buffer because there
- might be more output pending.
-
- If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
- inflate flushes as much output as possible to the output buffer. The
- flushing behavior of inflate is not specified for values of the flush
- parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
- current implementation actually flushes as much output as possible
- anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
- has been consumed, it is expecting to see the length field of a stored
- block; if not, it returns Z_DATA_ERROR.
-
- inflate() should normally be called until it returns Z_STREAM_END or an
- error. However if all decompression is to be performed in a single step
- (a single call of inflate), the parameter flush should be set to
- Z_FINISH. In this case all pending input is processed and all pending
- output is flushed; avail_out must be large enough to hold all the
- uncompressed data. (The size of the uncompressed data may have been saved
- by the compressor for this purpose.) The next operation on this stream must
- be inflateEnd to deallocate the decompression state. The use of Z_FINISH
- is never required, but can be used to inform inflate that a faster routine
- may be used for the single inflate() call.
-
- inflate() returns Z_OK if some progress has been made (more input
- processed or more output produced), Z_STREAM_END if the end of the
- compressed data has been reached and all uncompressed output has been
- produced, Z_NEED_DICT if a preset dictionary is needed at this point (see
- inflateSetDictionary below), Z_DATA_ERROR if the input data was corrupted,
- Z_STREAM_ERROR if the stream structure was inconsistent (for example if
- next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
- Z_BUF_ERROR if no progress is possible or if there was not enough room in
- the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case, the
- application may then call inflateSync to look for a good compression block.
- In the Z_NEED_DICT case, strm->adler is set to the Adler32 value of the
- dictionary chosen by the compressor.
-*/
-
-
-extern int EXPORT inflateEnd OF((z_streamp strm));
-/*
- All dynamically allocated data structures for this stream are freed.
- This function discards any unprocessed input and does not flush any
- pending output.
-
- inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
- was inconsistent. In the error case, msg may be set but then points to a
- static string (which must not be deallocated).
-*/
-
- /* Advanced functions */
-
-/*
- The following functions are needed only in some special applications.
-*/
-
-/*
-extern int EXPORT deflateInit2 OF((z_streamp strm,
- int level,
- int method,
- int windowBits,
- int memLevel,
- int strategy));
-
- This is another version of deflateInit with more compression options. The
- fields next_in, zalloc, zfree and opaque must be initialized before by
- the caller.
-
- The method parameter is the compression method. It must be Z_DEFLATED in
- this version of the library. (Method 9 will allow a 64K history buffer and
- partial block flushes.)
-
- The windowBits parameter is the base two logarithm of the window size
- (the size of the history buffer). It should be in the range 8..15 for this
- version of the library (the value 16 will be allowed for method 9). Larger
- values of this parameter result in better compression at the expense of
- memory usage. The default value is 15 if deflateInit is used instead.
-
- The memLevel parameter specifies how much memory should be allocated
- for the internal compression state. memLevel=1 uses minimum memory but
- is slow and reduces compression ratio; memLevel=9 uses maximum memory
- for optimal speed. The default value is 8. See zconf.h for total memory
- usage as a function of windowBits and memLevel.
-
- The strategy parameter is used to tune the compression algorithm. Use the
- value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
- filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
- string match). Filtered data consists mostly of small values with a
- somewhat random distribution. In this case, the compression algorithm is
- tuned to compress them better. The effect of Z_FILTERED is to force more
- Huffman coding and less string matching; it is somewhat intermediate
- between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
- the compression ratio but not the correctness of the compressed output even
- if it is not set appropriately.
-
- If next_in is not null, the library will use this buffer to hold also
- some history information; the buffer must either hold the entire input
- data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in
- is null, the library will allocate its own history buffer (and leave next_in
- null). next_out need not be provided here but must be provided by the
- application for the next call of deflate().
-
- If the history buffer is provided by the application, next_in must
- must never be changed by the application since the compressor maintains
- information inside this buffer from call to call; the application
- must provide more input only by increasing avail_in. next_in is always
- reset by the library in this case.
-
- deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
- not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
- an invalid method). msg is set to null if there is no error message.
- deflateInit2 does not perform any compression: this will be done by
- deflate().
-*/
-
-extern int EXPORT deflateSetDictionary OF((z_streamp strm,
- const Bytef *dictionary,
- uInt dictLength));
-/*
- Initializes the compression dictionary (history buffer) from the given
- byte sequence without producing any compressed output. This function must
- be called immediately after deflateInit or deflateInit2, before any call
- of deflate. The compressor and decompressor must use exactly the same
- dictionary (see inflateSetDictionary).
- The dictionary should consist of strings (byte sequences) that are likely
- to be encountered later in the data to be compressed, with the most commonly
- used strings preferably put towards the end of the dictionary. Using a
- dictionary is most useful when the data to be compressed is short and
- can be predicted with good accuracy; the data can then be compressed better
- than with the default empty dictionary. In this version of the library,
- only the last 32K bytes of the dictionary are used.
- Upon return of this function, strm->adler is set to the Adler32 value
- of the dictionary; the decompressor may later use this value to determine
- which dictionary has been used by the compressor. (The Adler32 value
- applies to the whole dictionary even if only a subset of the dictionary is
- actually used by the compressor.)
-
- deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
- parameter is invalid (such as NULL dictionary) or the stream state
- is inconsistent (for example if deflate has already been called for this
- stream). deflateSetDictionary does not perform any compression: this will
- be done by deflate().
-*/
-
-extern int EXPORT deflateCopy OF((z_streamp dest,
- z_streamp source));
-/*
- Sets the destination stream as a complete copy of the source stream. If
- the source stream is using an application-supplied history buffer, a new
- buffer is allocated for the destination stream. The compressed output
- buffer is always application-supplied. It's the responsibility of the
- application to provide the correct values of next_out and avail_out for the
- next call of deflate.
-
- This function can be useful when several compression strategies will be
- tried, for example when there are several ways of pre-processing the input
- data with a filter. The streams that will be discarded should then be freed
- by calling deflateEnd. Note that deflateCopy duplicates the internal
- compression state which can be quite large, so this strategy is slow and
- can consume lots of memory.
-
- deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
- enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
- (such as zalloc being NULL). msg is left unchanged in both source and
- destination.
-*/
-
-extern int EXPORT deflateReset OF((z_streamp strm));
-/*
- This function is equivalent to deflateEnd followed by deflateInit,
- but does not free and reallocate all the internal compression state.
- The stream will keep the same compression level and any other attributes
- that may have been set by deflateInit2.
-
- deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
- stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-extern int EXPORT deflateParams OF((z_streamp strm, int level, int strategy));
-/*
- Dynamically update the compression level and compression strategy.
- This can be used to switch between compression and straight copy of
- the input data, or to switch to a different kind of input data requiring
- a different strategy. If the compression level is changed, the input
- available so far is compressed with the old level (and may be flushed);
- the new level will take effect only at the next call of deflate().
-
- Before the call of deflateParams, the stream state must be set as for
- a call of deflate(), since the currently available input may have to
- be compressed and flushed. In particular, strm->avail_out must be non-zero.
-
- deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
- stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
- if strm->avail_out was zero.
-*/
-
-extern int EXPORT deflateOutputPending OF((z_streamp strm));
-/*
- Returns the number of bytes of output which are immediately
- available from the compressor (i.e. without any further input
- or flush).
-*/
-
-/*
-extern int EXPORT inflateInit2 OF((z_streamp strm,
- int windowBits));
-
- This is another version of inflateInit with more compression options. The
- fields next_out, zalloc, zfree and opaque must be initialized before by
- the caller.
-
- The windowBits parameter is the base two logarithm of the maximum window
- size (the size of the history buffer). It should be in the range 8..15 for
- this version of the library (the value 16 will be allowed soon). The
- default value is 15 if inflateInit is used instead. If a compressed stream
- with a larger window size is given as input, inflate() will return with
- the error code Z_DATA_ERROR instead of trying to allocate a larger window.
-
- If next_out is not null, the library will use this buffer for the history
- buffer; the buffer must either be large enough to hold the entire output
- data, or have at least 1<<windowBits bytes. If next_out is null, the
- library will allocate its own buffer (and leave next_out null). next_in
- need not be provided here but must be provided by the application for the
- next call of inflate().
-
- If the history buffer is provided by the application, next_out must
- never be changed by the application since the decompressor maintains
- history information inside this buffer from call to call; the application
- can only reset next_out to the beginning of the history buffer when
- avail_out is zero and all output has been consumed.
-
- inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
- not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
- windowBits < 8). msg is set to null if there is no error message.
- inflateInit2 does not perform any decompression: this will be done by
- inflate().
-*/
-
-extern int EXPORT inflateSetDictionary OF((z_streamp strm,
- const Bytef *dictionary,
- uInt dictLength));
-/*
- Initializes the decompression dictionary (history buffer) from the given
- uncompressed byte sequence. This function must be called immediately after
- a call of inflate if this call returned Z_NEED_DICT. The dictionary chosen
- by the compressor can be determined from the Adler32 value returned by this
- call of inflate. The compressor and decompressor must use exactly the same
- dictionary (see deflateSetDictionary).
-
- inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
- parameter is invalid (such as NULL dictionary) or the stream state is
- inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
- expected one (incorrect Adler32 value). inflateSetDictionary does not
- perform any decompression: this will be done by subsequent calls of
- inflate().
-*/
-
-extern int EXPORT inflateSync OF((z_streamp strm));
-/*
- Skips invalid compressed data until the special marker (see deflate()
- above) can be found, or until all available input is skipped. No output
- is provided.
-
- inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
- if no more input was provided, Z_DATA_ERROR if no marker has been found,
- or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
- case, the application may save the current current value of total_in which
- indicates where valid compressed data was found. In the error case, the
- application may repeatedly call inflateSync, providing more input each time,
- until success or end of the input data.
-*/
-
-extern int EXPORT inflateReset OF((z_streamp strm));
-/*
- This function is equivalent to inflateEnd followed by inflateInit,
- but does not free and reallocate all the internal decompression state.
- The stream will keep attributes that may have been set by inflateInit2.
-
- inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
- stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-extern int inflateIncomp OF((z_stream *strm));
-/*
- This function adds the data at next_in (avail_in bytes) to the output
- history without performing any output. There must be no pending output,
- and the decompressor must be expecting to see the start of a block.
- Calling this function is equivalent to decompressing a stored block
- containing the data at next_in (except that the data is not output).
-*/
-
- /* utility functions */
-
-/*
- The following utility functions are implemented on top of the
- basic stream-oriented functions. To simplify the interface, some
- default options are assumed (compression level, window size,
- standard memory allocation functions). The source code of these
- utility functions can easily be modified if you need special options.
-*/
-
-extern int EXPORT compress OF((Bytef *dest, uLongf *destLen,
- const Bytef *source, uLong sourceLen));
-/*
- Compresses the source buffer into the destination buffer. sourceLen is
- the byte length of the source buffer. Upon entry, destLen is the total
- size of the destination buffer, which must be at least 0.1% larger than
- sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
- compressed buffer.
- This function can be used to compress a whole file at once if the
- input file is mmap'ed.
- compress returns Z_OK if success, Z_MEM_ERROR if there was not
- enough memory, Z_BUF_ERROR if there was not enough room in the output
- buffer.
-*/
-
-extern int EXPORT uncompress OF((Bytef *dest, uLongf *destLen,
- const Bytef *source, uLong sourceLen));
-/*
- Decompresses the source buffer into the destination buffer. sourceLen is
- the byte length of the source buffer. Upon entry, destLen is the total
- size of the destination buffer, which must be large enough to hold the
- entire uncompressed data. (The size of the uncompressed data must have
- been saved previously by the compressor and transmitted to the decompressor
- by some mechanism outside the scope of this compression library.)
- Upon exit, destLen is the actual size of the compressed buffer.
- This function can be used to decompress a whole file at once if the
- input file is mmap'ed.
-
- uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
- enough memory, Z_BUF_ERROR if there was not enough room in the output
- buffer, or Z_DATA_ERROR if the input data was corrupted.
-*/
-
-
-typedef voidp gzFile;
-
-extern gzFile EXPORT gzopen OF((const char *path, const char *mode));
-/*
- Opens a gzip (.gz) file for reading or writing. The mode parameter
- is as in fopen ("rb" or "wb") but can also include a compression level
- ("wb9"). gzopen can be used to read a file which is not in gzip format;
- in this case gzread will directly read from the file without decompression.
- gzopen returns NULL if the file could not be opened or if there was
- insufficient memory to allocate the (de)compression state; errno
- can be checked to distinguish the two cases (if errno is zero, the
- zlib error is Z_MEM_ERROR).
-*/
-
-extern gzFile EXPORT gzdopen OF((int fd, const char *mode));
-/*
- gzdopen() associates a gzFile with the file descriptor fd. File
- descriptors are obtained from calls like open, dup, creat, pipe or
- fileno (in the file has been previously opened with fopen).
- The mode parameter is as in gzopen.
- The next call of gzclose on the returned gzFile will also close the
- file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
- descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
- gzdopen returns NULL if there was insufficient memory to allocate
- the (de)compression state.
-*/
-
-extern int EXPORT gzread OF((gzFile file, voidp buf, unsigned len));
-/*
- Reads the given number of uncompressed bytes from the compressed file.
- If the input file was not in gzip format, gzread copies the given number
- of bytes into the buffer.
- gzread returns the number of uncompressed bytes actually read (0 for
- end of file, -1 for error). */
-
-extern int EXPORT gzwrite OF((gzFile file, const voidp buf, unsigned len));
-/*
- Writes the given number of uncompressed bytes into the compressed file.
- gzwrite returns the number of uncompressed bytes actually written
- (0 in case of error).
-*/
-
-extern int EXPORT gzflush OF((gzFile file, int flush));
-/*
- Flushes all pending output into the compressed file. The parameter
- flush is as in the deflate() function. The return value is the zlib
- error number (see function gzerror below). gzflush returns Z_OK if
- the flush parameter is Z_FINISH and all output could be flushed.
- gzflush should be called only when strictly necessary because it can
- degrade compression.
-*/
-
-extern int EXPORT gzclose OF((gzFile file));
-/*
- Flushes all pending output if necessary, closes the compressed file
- and deallocates all the (de)compression state. The return value is the zlib
- error number (see function gzerror below).
-*/
-
-extern const char * EXPORT gzerror OF((gzFile file, int *errnum));
-/*
- Returns the error message for the last error which occurred on the
- given compressed file. errnum is set to zlib error number. If an
- error occurred in the file system and not in the compression library,
- errnum is set to Z_ERRNO and the application may consult errno
- to get the exact error code.
-*/
-
- /* checksum functions */
-
-/*
- These functions are not related to compression but are exported
- anyway because they might be useful in applications using the
- compression library.
-*/
-
-extern uLong EXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
-
-/*
- Update a running Adler-32 checksum with the bytes buf[0..len-1] and
- return the updated checksum. If buf is NULL, this function returns
- the required initial value for the checksum.
- An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
- much faster. Usage example:
-
- uLong adler = adler32(0L, Z_NULL, 0);
-
- while (read_buffer(buffer, length) != EOF) {
- adler = adler32(adler, buffer, length);
- }
- if (adler != original_adler) error();
-*/
-
-extern uLong EXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
-/*
- Update a running crc with the bytes buf[0..len-1] and return the updated
- crc. If buf is NULL, this function returns the required initial value
- for the crc. Pre- and post-conditioning (one's complement) is performed
- within this function so it shouldn't be done by the application.
- Usage example:
-
- uLong crc = crc32(0L, Z_NULL, 0);
-
- while (read_buffer(buffer, length) != EOF) {
- crc = crc32(crc, buffer, length);
- }
- if (crc != original_crc) error();
-*/
-
-
- /* various hacks, don't look :) */
-
-/* deflateInit and inflateInit are macros to allow checking the zlib version
- * and the compiler's view of z_stream:
- */
-extern int EXPORT deflateInit_ OF((z_streamp strm, int level,
- const char *version, int stream_size));
-extern int EXPORT inflateInit_ OF((z_streamp strm,
- const char *version, int stream_size));
-extern int EXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
- int windowBits, int memLevel, int strategy,
- const char *version, int stream_size));
-extern int EXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
- const char *version, int stream_size));
-#define deflateInit(strm, level) \
- deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit(strm) \
- inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
-#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
- deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
- (strategy), ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit2(strm, windowBits) \
- inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
-
-#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
- struct internal_state {int dummy;}; /* hack for buggy compilers */
-#endif
-
-uLongf *get_crc_table OF((void)); /* can be used by asm versions of crc32() */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ZLIB_H */
-/* --- zlib.h */
chat/Makefile
contrib/Makefile
contrib/pppgetpass/Makefile
- common/Makefile
include/Makefile
- modules/Makefile
pppd/Makefile
pppd/pppd.pc
pppd/plugins/Makefile
AC_OUTPUT
-AS_IF([test "x${build_sunos}" = "xyes" ], [[
- echo "
-Setting up SunOS kernel module(s)"
- mkmkf() {
- rm -f $2
- if [ -f $1 ]; then
- echo " $2 <= $1"
- sed -e "s,@DESTDIR@,$prefix,g" \
- -e "s,@SYSCONF@,$sysconfdir,g" \
- -e "s,@CC@,$CC,g" \
- -e "s|@CFLAGS@|$CFLAGS|g" $1 > $2
- fi
- }
-
- release=`uname -r`
- karch=`/usr/bin/isainfo -k`
- makext="sol2"
- archvariant=
-
- case "$karch" in
- amd64)
- archvariant='-64x'
- ;;
- sparcv9)
- archvariant='-64'
- ;;
- *)
- ;;
- esac
-
- usegcc=$CC
- if [ -x /opt/SUNWspro/bin/cc -a "$usegcc" != gcc ] &&
- /opt/SUNWspro/bin/cc -flags >/dev/null 2>&1; then
- if [ "$archvariant" = "-64x" ]; then
- ( cd /tmp; echo "int x;" > ppp$$.c
- /opt/SUNWspro/bin/cc -c -errwarn -xchip=opteron -m64 ppp$$.c >/dev/null 2>&1 || (
- echo "WorkShop C is unable to make 64 bit modules, and your $karch system needs"
- echo "them. Consider upgrading cc on this machine."
- rm -f ppp$$.c
- exit 1
- ) || exit 1
- rm -f ppp$$.c ppp$$.o
- ) || exit 1
- fi
- elif gcc --version >/dev/null 2>&1; then
- archvariant=gcc$archvariant
- compiletype=.gcc
- if [ "$archvariant" = "gcc-64" -o"$archvariant" = "gcc-64x" ]; then
- ( cd /tmp; touch ppp$$.c
- gcc -c -m64 ppp$$.c >/dev/null 2>&1 || (
- echo "gcc is unable to make 64 bit modules, and your $karch system needs them."
- echo "Consider upgrading gcc on this machine, or switching to Sun WorkShop."
- rm -f ppp$$.c
- exit 1
- ) || exit 1
- rm -f ppp$$.c ppp$$.o
- ) || exit 1
- fi
- else
- echo "C compiler not found; hoping for the best."
- fi
-
- mkmkf solaris/Makedefs$compiletype Makedefs.com
- mkmkf solaris/Makefile.sol2$archvariant solaris/Makefile
-]])
-
echo "
$PACKAGE_NAME version $PACKAGE_VERSION
Prefix...............: $prefix
+++ /dev/null
-EXTRA_MODULE = \
- bsd-comp.c \
- deflate.c \
- if_ppp.c \
- ppp_ahdlc.c \
- ppp.c \
- ppp_comp.c \
- ppp_mod.h \
- vjcompress.c
-
-EXTRA_DIST = \
- $(EXTRA_MODULE)
+++ /dev/null
-/* Because this code is derived from the 4.3BSD compress source:
- *
- *
- * Copyright (c) 1985, 1986 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * James A. Woods, derived from original work by Spencer Thomas
- * and Joseph Orost.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * This version is for use with STREAMS under SunOS 4.x,
- * Digital UNIX, AIX 4.x, and SVR4 systems including Solaris 2.
- *
- * $Id: bsd-comp.c,v 1.21 2004/01/17 05:47:55 carlsonj Exp $
- */
-
-#ifdef AIX4
-#include <net/net_globals.h>
-#endif
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stream.h>
-#include <net/ppp_defs.h>
-#include "ppp_mod.h"
-
-#ifdef SVR4
-#include <sys/byteorder.h>
-#ifndef _BIG_ENDIAN
-#define BSD_LITTLE_ENDIAN
-#endif
-#endif
-
-#ifdef __osf__
-#undef FIRST
-#undef LAST
-#define BSD_LITTLE_ENDIAN
-#endif
-
-#ifdef SOL2
-#include <sys/sunddi.h>
-#endif
-
-#define PACKETPTR mblk_t *
-#include <net/ppp-comp.h>
-
-#if DO_BSD_COMPRESS
-
-/*
- * PPP "BSD compress" compression
- * The differences between this compression and the classic BSD LZW
- * source are obvious from the requirement that the classic code worked
- * with files while this handles arbitrarily long streams that
- * are broken into packets. They are:
- *
- * When the code size expands, a block of junk is not emitted by
- * the compressor and not expected by the decompressor.
- *
- * New codes are not necessarily assigned every time an old
- * code is output by the compressor. This is because a packet
- * end forces a code to be emitted, but does not imply that a
- * new sequence has been seen.
- *
- * The compression ratio is checked at the first end of a packet
- * after the appropriate gap. Besides simplifying and speeding
- * things up, this makes it more likely that the transmitter
- * and receiver will agree when the dictionary is cleared when
- * compression is not going well.
- */
-
-/*
- * A dictionary for doing BSD compress.
- */
-struct bsd_db {
- int totlen; /* length of this structure */
- u_int hsize; /* size of the hash table */
- u_char hshift; /* used in hash function */
- u_char n_bits; /* current bits/code */
- u_char maxbits;
- u_char debug;
- u_char unit;
- u_short seqno; /* sequence number of next packet */
- u_int hdrlen; /* header length to preallocate */
- u_int mru;
- u_int maxmaxcode; /* largest valid code */
- u_int max_ent; /* largest code in use */
- u_int in_count; /* uncompressed bytes, aged */
- u_int bytes_out; /* compressed bytes, aged */
- u_int ratio; /* recent compression ratio */
- u_int checkpoint; /* when to next check the ratio */
- u_int clear_count; /* times dictionary cleared */
- u_int incomp_count; /* incompressible packets */
- u_int incomp_bytes; /* incompressible bytes */
- u_int uncomp_count; /* uncompressed packets */
- u_int uncomp_bytes; /* uncompressed bytes */
- u_int comp_count; /* compressed packets */
- u_int comp_bytes; /* compressed bytes */
- u_short *lens; /* array of lengths of codes */
- struct bsd_dict {
- union { /* hash value */
- u_int32_t fcode;
- struct {
-#ifdef BSD_LITTLE_ENDIAN
- u_short prefix; /* preceding code */
- u_char suffix; /* last character of new code */
- u_char pad;
-#else
- u_char pad;
- u_char suffix; /* last character of new code */
- u_short prefix; /* preceding code */
-#endif
- } hs;
- } f;
- u_short codem1; /* output of hash table -1 */
- u_short cptr; /* map code to hash table entry */
- } dict[1];
-};
-
-#define BSD_OVHD 2 /* BSD compress overhead/packet */
-#define BSD_INIT_BITS BSD_MIN_BITS
-
-static void *bsd_comp_alloc(u_char *options, int opt_len);
-static void *bsd_decomp_alloc(u_char *options, int opt_len);
-static void bsd_free(void *state);
-static int bsd_comp_init(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int debug);
-static int bsd_decomp_init(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int mru, int debug);
-static int bsd_compress(void *state, mblk_t **mret,
- mblk_t *mp, int slen, int maxolen);
-static void bsd_incomp(void *state, mblk_t *dmsg);
-static int bsd_decompress(void *state, mblk_t *cmp, mblk_t **dmpp);
-static void bsd_reset(void *state);
-static void bsd_comp_stats(void *state, struct compstat *stats);
-
-/*
- * Procedures exported to ppp_comp.c.
- */
-struct compressor ppp_bsd_compress = {
- CI_BSD_COMPRESS, /* compress_proto */
- bsd_comp_alloc, /* comp_alloc */
- bsd_free, /* comp_free */
- bsd_comp_init, /* comp_init */
- bsd_reset, /* comp_reset */
- bsd_compress, /* compress */
- bsd_comp_stats, /* comp_stat */
- bsd_decomp_alloc, /* decomp_alloc */
- bsd_free, /* decomp_free */
- bsd_decomp_init, /* decomp_init */
- bsd_reset, /* decomp_reset */
- bsd_decompress, /* decompress */
- bsd_incomp, /* incomp */
- bsd_comp_stats, /* decomp_stat */
-};
-
-/*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
-#define CLEAR 256 /* table clear output code */
-#define FIRST 257 /* first free entry */
-#define LAST 255
-
-#define MAXCODE(b) ((1 << (b)) - 1)
-#define BADCODEM1 MAXCODE(BSD_MAX_BITS)
-
-#define BSD_HASH(prefix,suffix,hshift) ((((u_int32_t)(suffix)) << (hshift)) \
- ^ (u_int32_t)(prefix))
-#define BSD_KEY(prefix,suffix) ((((u_int32_t)(suffix)) << 16) \
- + (u_int32_t)(prefix))
-
-#define CHECK_GAP 10000 /* Ratio check interval */
-
-#define RATIO_SCALE_LOG 8
-#define RATIO_SCALE (1<<RATIO_SCALE_LOG)
-#define RATIO_MAX (0x7fffffff>>RATIO_SCALE_LOG)
-
-#define DECOMP_CHUNK 256
-
-/*
- * clear the dictionary
- */
-static void
-bsd_clear(db)
- struct bsd_db *db;
-{
- db->clear_count++;
- db->max_ent = FIRST-1;
- db->n_bits = BSD_INIT_BITS;
- db->ratio = 0;
- db->bytes_out = 0;
- db->in_count = 0;
- db->checkpoint = CHECK_GAP;
-}
-
-/*
- * If the dictionary is full, then see if it is time to reset it.
- *
- * Compute the compression ratio using fixed-point arithmetic
- * with 8 fractional bits.
- *
- * Since we have an infinite stream instead of a single file,
- * watch only the local compression ratio.
- *
- * Since both peers must reset the dictionary at the same time even in
- * the absence of CLEAR codes (while packets are incompressible), they
- * must compute the same ratio.
- */
-static int /* 1=output CLEAR */
-bsd_check(db)
- struct bsd_db *db;
-{
- u_int new_ratio;
-
- if (db->in_count >= db->checkpoint) {
- /* age the ratio by limiting the size of the counts */
- if (db->in_count >= RATIO_MAX
- || db->bytes_out >= RATIO_MAX) {
- db->in_count -= db->in_count/4;
- db->bytes_out -= db->bytes_out/4;
- }
-
- db->checkpoint = db->in_count + CHECK_GAP;
-
- if (db->max_ent >= db->maxmaxcode) {
- /* Reset the dictionary only if the ratio is worse,
- * or if it looks as if it has been poisoned
- * by incompressible data.
- *
- * This does not overflow, because
- * db->in_count <= RATIO_MAX.
- */
- new_ratio = db->in_count << RATIO_SCALE_LOG;
- if (db->bytes_out != 0)
- new_ratio /= db->bytes_out;
-
- if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) {
- bsd_clear(db);
- return 1;
- }
- db->ratio = new_ratio;
- }
- }
- return 0;
-}
-
-/*
- * Return statistics.
- */
-static void
-bsd_comp_stats(state, stats)
- void *state;
- struct compstat *stats;
-{
- struct bsd_db *db = (struct bsd_db *) state;
- u_int out;
-
- stats->unc_bytes = db->uncomp_bytes;
- stats->unc_packets = db->uncomp_count;
- stats->comp_bytes = db->comp_bytes;
- stats->comp_packets = db->comp_count;
- stats->inc_bytes = db->incomp_bytes;
- stats->inc_packets = db->incomp_count;
- stats->ratio = db->in_count;
- out = db->bytes_out;
- if (stats->ratio <= 0x7fffff)
- stats->ratio <<= 8;
- else
- out >>= 8;
- if (out != 0)
- stats->ratio /= out;
-}
-
-/*
- * Reset state, as on a CCP ResetReq.
- */
-static void
-bsd_reset(state)
- void *state;
-{
- struct bsd_db *db = (struct bsd_db *) state;
-
- db->seqno = 0;
- bsd_clear(db);
- db->clear_count = 0;
-}
-
-/*
- * Allocate space for a (de) compressor.
- */
-static void *
-bsd_alloc(options, opt_len, decomp)
- u_char *options;
- int opt_len, decomp;
-{
- int bits;
- u_int newlen, hsize, hshift, maxmaxcode;
- struct bsd_db *db;
-
- if (opt_len != 3 || options[0] != CI_BSD_COMPRESS || options[1] != 3
- || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
- return NULL;
-
- bits = BSD_NBITS(options[2]);
- switch (bits) {
- case 9: /* needs 82152 for both directions */
- case 10: /* needs 84144 */
- case 11: /* needs 88240 */
- case 12: /* needs 96432 */
- hsize = 5003;
- hshift = 4;
- break;
- case 13: /* needs 176784 */
- hsize = 9001;
- hshift = 5;
- break;
- case 14: /* needs 353744 */
- hsize = 18013;
- hshift = 6;
- break;
- case 15: /* needs 691440 */
- hsize = 35023;
- hshift = 7;
- break;
- case 16: /* needs 1366160--far too much, */
- /* hsize = 69001; */ /* and 69001 is too big for cptr */
- /* hshift = 8; */ /* in struct bsd_db */
- /* break; */
- default:
- return NULL;
- }
-
- maxmaxcode = MAXCODE(bits);
- newlen = sizeof(*db) + (hsize-1) * (sizeof(db->dict[0]));
-#ifdef __osf__
- db = (struct bsd_db *) ALLOC_SLEEP(newlen);
-#else
- db = (struct bsd_db *) ALLOC_NOSLEEP(newlen);
-#endif
- if (!db)
- return NULL;
- bzero(db, sizeof(*db) - sizeof(db->dict));
-
- if (!decomp) {
- db->lens = NULL;
- } else {
-#ifdef __osf__
- db->lens = (u_short *) ALLOC_SLEEP((maxmaxcode+1) * sizeof(db->lens[0]));
-#else
- db->lens = (u_short *) ALLOC_NOSLEEP((maxmaxcode+1) * sizeof(db->lens[0]));
-#endif
- if (!db->lens) {
- FREE(db, newlen);
- return NULL;
- }
- }
-
- db->totlen = newlen;
- db->hsize = hsize;
- db->hshift = hshift;
- db->maxmaxcode = maxmaxcode;
- db->maxbits = bits;
-
- return (void *) db;
-}
-
-static void
-bsd_free(state)
- void *state;
-{
- struct bsd_db *db = (struct bsd_db *) state;
-
- if (db->lens)
- FREE(db->lens, (db->maxmaxcode+1) * sizeof(db->lens[0]));
- FREE(db, db->totlen);
-}
-
-static void *
-bsd_comp_alloc(options, opt_len)
- u_char *options;
- int opt_len;
-{
- return bsd_alloc(options, opt_len, 0);
-}
-
-static void *
-bsd_decomp_alloc(options, opt_len)
- u_char *options;
- int opt_len;
-{
- return bsd_alloc(options, opt_len, 1);
-}
-
-/*
- * Initialize the database.
- */
-static int
-bsd_init(db, options, opt_len, unit, hdrlen, mru, debug, decomp)
- struct bsd_db *db;
- u_char *options;
- int opt_len, unit, hdrlen, mru, debug, decomp;
-{
- int i;
-
- if (opt_len < CILEN_BSD_COMPRESS
- || options[0] != CI_BSD_COMPRESS || options[1] != CILEN_BSD_COMPRESS
- || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION
- || BSD_NBITS(options[2]) != db->maxbits
- || decomp && db->lens == NULL)
- return 0;
-
- if (decomp) {
- i = LAST+1;
- while (i != 0)
- db->lens[--i] = 1;
- }
- i = db->hsize;
- while (i != 0) {
- db->dict[--i].codem1 = BADCODEM1;
- db->dict[i].cptr = 0;
- }
-
- db->unit = unit;
- db->hdrlen = hdrlen;
- db->mru = mru;
- if (debug)
- db->debug = 1;
-
- bsd_reset(db);
-
- return 1;
-}
-
-static int
-bsd_comp_init(state, options, opt_len, unit, hdrlen, debug)
- void *state;
- u_char *options;
- int opt_len, unit, hdrlen, debug;
-{
- return bsd_init((struct bsd_db *) state, options, opt_len,
- unit, hdrlen, 0, debug, 0);
-}
-
-static int
-bsd_decomp_init(state, options, opt_len, unit, hdrlen, mru, debug)
- void *state;
- u_char *options;
- int opt_len, unit, hdrlen, mru, debug;
-{
- return bsd_init((struct bsd_db *) state, options, opt_len,
- unit, hdrlen, mru, debug, 1);
-}
-
-
-/*
- * compress a packet
- * One change from the BSD compress command is that when the
- * code size expands, we do not output a bunch of padding.
- *
- * N.B. at present, we ignore the hdrlen specified in the comp_init call.
- */
-static int /* new slen */
-bsd_compress(state, mretp, mp, slen, maxolen)
- void *state;
- mblk_t **mretp; /* return compressed mbuf chain here */
- mblk_t *mp; /* from here */
- int slen; /* uncompressed length */
- int maxolen; /* max compressed length */
-{
- struct bsd_db *db = (struct bsd_db *) state;
- int hshift = db->hshift;
- u_int max_ent = db->max_ent;
- u_int n_bits = db->n_bits;
- u_int bitno = 32;
- u_int32_t accm = 0, fcode;
- struct bsd_dict *dictp;
- u_char c;
- int hval, disp, ent, ilen;
- mblk_t *np, *mret;
- u_char *rptr, *wptr;
- u_char *cp_end;
- int olen;
- mblk_t *m, **mnp;
-
-#define PUTBYTE(v) { \
- if (wptr) { \
- *wptr++ = (v); \
- if (wptr >= cp_end) { \
- m->b_wptr = wptr; \
- m = m->b_cont; \
- if (m) { \
- wptr = m->b_wptr; \
- cp_end = m->b_datap->db_lim; \
- } else \
- wptr = NULL; \
- } \
- } \
- ++olen; \
-}
-
-#define OUTPUT(ent) { \
- bitno -= n_bits; \
- accm |= ((ent) << bitno); \
- do { \
- PUTBYTE(accm >> 24); \
- accm <<= 8; \
- bitno += 8; \
- } while (bitno <= 24); \
-}
-
- /*
- * First get the protocol and check that we're
- * interested in this packet.
- */
- *mretp = NULL;
- rptr = mp->b_rptr;
- if (rptr + PPP_HDRLEN > mp->b_wptr) {
- if (!pullupmsg(mp, PPP_HDRLEN))
- return 0;
- rptr = mp->b_rptr;
- }
- ent = PPP_PROTOCOL(rptr); /* get the protocol */
- if (ent < 0x21 || ent > 0xf9)
- return 0;
-
- /* Don't generate compressed packets which are larger than
- the uncompressed packet. */
- if (maxolen > slen)
- maxolen = slen;
-
- /* Allocate enough message blocks to give maxolen total space. */
- mnp = &mret;
- for (olen = maxolen; olen > 0; ) {
- m = allocb((olen < 4096? olen: 4096), BPRI_MED);
- *mnp = m;
- if (m == NULL) {
- if (mret != NULL) {
- freemsg(mret);
- mnp = &mret;
- }
- break;
- }
- mnp = &m->b_cont;
- olen -= m->b_datap->db_lim - m->b_wptr;
- }
- *mnp = NULL;
-
- if ((m = mret) != NULL) {
- wptr = m->b_wptr;
- cp_end = m->b_datap->db_lim;
- } else
- wptr = cp_end = NULL;
- olen = 0;
-
- /*
- * Copy the PPP header over, changing the protocol,
- * and install the 2-byte sequence number.
- */
- if (wptr) {
- wptr[0] = PPP_ADDRESS(rptr);
- wptr[1] = PPP_CONTROL(rptr);
- wptr[2] = 0; /* change the protocol */
- wptr[3] = PPP_COMP;
- wptr[4] = db->seqno >> 8;
- wptr[5] = db->seqno;
- wptr += PPP_HDRLEN + BSD_OVHD;
- }
- ++db->seqno;
- rptr += PPP_HDRLEN;
-
- slen = mp->b_wptr - rptr;
- ilen = slen + 1;
- np = mp->b_cont;
- for (;;) {
- if (slen <= 0) {
- if (!np)
- break;
- rptr = np->b_rptr;
- slen = np->b_wptr - rptr;
- np = np->b_cont;
- if (!slen)
- continue; /* handle 0-length buffers */
- ilen += slen;
- }
-
- slen--;
- c = *rptr++;
- fcode = BSD_KEY(ent, c);
- hval = BSD_HASH(ent, c, hshift);
- dictp = &db->dict[hval];
-
- /* Validate and then check the entry. */
- if (dictp->codem1 >= max_ent)
- goto nomatch;
- if (dictp->f.fcode == fcode) {
- ent = dictp->codem1+1;
- continue; /* found (prefix,suffix) */
- }
-
- /* continue probing until a match or invalid entry */
- disp = (hval == 0) ? 1 : hval;
- do {
- hval += disp;
- if (hval >= db->hsize)
- hval -= db->hsize;
- dictp = &db->dict[hval];
- if (dictp->codem1 >= max_ent)
- goto nomatch;
- } while (dictp->f.fcode != fcode);
- ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */
- continue;
-
- nomatch:
- OUTPUT(ent); /* output the prefix */
-
- /* code -> hashtable */
- if (max_ent < db->maxmaxcode) {
- struct bsd_dict *dictp2;
- /* expand code size if needed */
- if (max_ent >= MAXCODE(n_bits))
- db->n_bits = ++n_bits;
-
- /* Invalidate old hash table entry using
- * this code, and then take it over.
- */
- dictp2 = &db->dict[max_ent+1];
- if (db->dict[dictp2->cptr].codem1 == max_ent)
- db->dict[dictp2->cptr].codem1 = BADCODEM1;
- dictp2->cptr = hval;
- dictp->codem1 = max_ent;
- dictp->f.fcode = fcode;
-
- db->max_ent = ++max_ent;
- }
- ent = c;
- }
-
- OUTPUT(ent); /* output the last code */
- db->bytes_out += olen;
- db->in_count += ilen;
- if (bitno < 32)
- ++db->bytes_out; /* count complete bytes */
-
- if (bsd_check(db))
- OUTPUT(CLEAR); /* do not count the CLEAR */
-
- /*
- * Pad dribble bits of last code with ones.
- * Do not emit a completely useless byte of ones.
- */
- if (bitno != 32)
- PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
-
- /*
- * Increase code size if we would have without the packet
- * boundary and as the decompressor will.
- */
- if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
- db->n_bits++;
-
- db->uncomp_bytes += ilen;
- ++db->uncomp_count;
- if (olen + PPP_HDRLEN + BSD_OVHD > maxolen && mret != NULL) {
- /* throw away the compressed stuff if it is longer than uncompressed */
- freemsg(mret);
- mret = NULL;
- ++db->incomp_count;
- db->incomp_bytes += ilen;
- } else if (wptr != NULL) {
- m->b_wptr = wptr;
- if (m->b_cont) {
- freemsg(m->b_cont);
- m->b_cont = NULL;
- }
- ++db->comp_count;
- db->comp_bytes += olen + BSD_OVHD;
- }
-
- *mretp = mret;
- return olen + PPP_HDRLEN + BSD_OVHD;
-#undef OUTPUT
-#undef PUTBYTE
-}
-
-
-/*
- * Update the "BSD Compress" dictionary on the receiver for
- * incompressible data by pretending to compress the incoming data.
- */
-static void
-bsd_incomp(state, dmsg)
- void *state;
- mblk_t *dmsg;
-{
- struct bsd_db *db = (struct bsd_db *) state;
- u_int hshift = db->hshift;
- u_int max_ent = db->max_ent;
- u_int n_bits = db->n_bits;
- struct bsd_dict *dictp;
- u_int32_t fcode;
- u_char c;
- long hval, disp;
- int slen, ilen;
- u_int bitno = 7;
- u_char *rptr;
- u_int ent;
-
- rptr = dmsg->b_rptr;
- if (rptr + PPP_HDRLEN > dmsg->b_wptr) {
- if (!pullupmsg(dmsg, PPP_HDRLEN))
- return;
- rptr = dmsg->b_rptr;
- }
- ent = PPP_PROTOCOL(rptr); /* get the protocol */
- if (ent < 0x21 || ent > 0xf9)
- return;
-
- db->seqno++;
- ilen = 1; /* count the protocol as 1 byte */
- rptr += PPP_HDRLEN;
- for (;;) {
- slen = dmsg->b_wptr - rptr;
- if (slen <= 0) {
- dmsg = dmsg->b_cont;
- if (!dmsg)
- break;
- rptr = dmsg->b_rptr;
- continue; /* skip zero-length buffers */
- }
- ilen += slen;
-
- do {
- c = *rptr++;
- fcode = BSD_KEY(ent, c);
- hval = BSD_HASH(ent, c, hshift);
- dictp = &db->dict[hval];
-
- /* validate and then check the entry */
- if (dictp->codem1 >= max_ent)
- goto nomatch;
- if (dictp->f.fcode == fcode) {
- ent = dictp->codem1+1;
- continue; /* found (prefix,suffix) */
- }
-
- /* continue probing until a match or invalid entry */
- disp = (hval == 0) ? 1 : hval;
- do {
- hval += disp;
- if (hval >= db->hsize)
- hval -= db->hsize;
- dictp = &db->dict[hval];
- if (dictp->codem1 >= max_ent)
- goto nomatch;
- } while (dictp->f.fcode != fcode);
- ent = dictp->codem1+1;
- continue; /* finally found (prefix,suffix) */
-
- nomatch: /* output (count) the prefix */
- bitno += n_bits;
-
- /* code -> hashtable */
- if (max_ent < db->maxmaxcode) {
- struct bsd_dict *dictp2;
- /* expand code size if needed */
- if (max_ent >= MAXCODE(n_bits))
- db->n_bits = ++n_bits;
-
- /* Invalidate previous hash table entry
- * assigned this code, and then take it over.
- */
- dictp2 = &db->dict[max_ent+1];
- if (db->dict[dictp2->cptr].codem1 == max_ent)
- db->dict[dictp2->cptr].codem1 = BADCODEM1;
- dictp2->cptr = hval;
- dictp->codem1 = max_ent;
- dictp->f.fcode = fcode;
-
- db->max_ent = ++max_ent;
- db->lens[max_ent] = db->lens[ent]+1;
- }
- ent = c;
- } while (--slen != 0);
- }
- bitno += n_bits; /* output (count) the last code */
- db->bytes_out += bitno/8;
- db->in_count += ilen;
- (void)bsd_check(db);
-
- ++db->incomp_count;
- db->incomp_bytes += ilen;
- ++db->uncomp_count;
- db->uncomp_bytes += ilen;
-
- /* Increase code size if we would have without the packet
- * boundary and as the decompressor will.
- */
- if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
- db->n_bits++;
-}
-
-
-/*
- * Decompress "BSD Compress"
- *
- * Because of patent problems, we return DECOMP_ERROR for errors
- * found by inspecting the input data and for system problems, but
- * DECOMP_FATALERROR for any errors which could possibly be said to
- * be being detected "after" decompression. For DECOMP_ERROR,
- * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
- * infringing a patent of Motorola's if we do, so we take CCP down
- * instead.
- *
- * Given that the frame has the correct sequence number and a good FCS,
- * errors such as invalid codes in the input most likely indicate a
- * bug, so we return DECOMP_FATALERROR for them in order to turn off
- * compression, even though they are detected by inspecting the input.
- */
-static int
-bsd_decompress(state, cmsg, dmpp)
- void *state;
- mblk_t *cmsg, **dmpp;
-{
- struct bsd_db *db = (struct bsd_db *) state;
- u_int max_ent = db->max_ent;
- u_int32_t accm = 0;
- u_int bitno = 32; /* 1st valid bit in accm */
- u_int n_bits = db->n_bits;
- u_int tgtbitno = 32-n_bits; /* bitno when we have a code */
- struct bsd_dict *dictp;
- int explen, i, seq, len;
- u_int incode, oldcode, finchar;
- u_char *p, *rptr, *wptr;
- mblk_t *dmsg, *mret;
- int adrs, ctrl, ilen;
- int dlen, space, codelen, extra;
-
- /*
- * Get at least the BSD Compress header in the first buffer
- */
- rptr = cmsg->b_rptr;
- if (rptr + PPP_HDRLEN + BSD_OVHD >= cmsg->b_wptr) {
- if (!pullupmsg(cmsg, PPP_HDRLEN + BSD_OVHD + 1)) {
- if (db->debug)
- printf("bsd_decomp%d: failed to pullup\n", db->unit);
- return DECOMP_ERROR;
- }
- rptr = cmsg->b_rptr;
- }
-
- /*
- * Save the address/control from the PPP header
- * and then get the sequence number.
- */
- adrs = PPP_ADDRESS(rptr);
- ctrl = PPP_CONTROL(rptr);
- rptr += PPP_HDRLEN;
- seq = (rptr[0] << 8) + rptr[1];
- rptr += BSD_OVHD;
- ilen = len = cmsg->b_wptr - rptr;
-
- /*
- * Check the sequence number and give up if it is not what we expect.
- */
- if (seq != db->seqno++) {
- if (db->debug)
- printf("bsd_decomp%d: bad sequence # %d, expected %d\n",
- db->unit, seq, db->seqno - 1);
- return DECOMP_ERROR;
- }
-
- /*
- * Allocate one message block to start with.
- */
- if ((dmsg = allocb(DECOMP_CHUNK + db->hdrlen, BPRI_MED)) == NULL)
- return DECOMP_ERROR;
- mret = dmsg;
- dmsg->b_wptr += db->hdrlen;
- dmsg->b_rptr = wptr = dmsg->b_wptr;
-
- /* Fill in the ppp header, but not the last byte of the protocol
- (that comes from the decompressed data). */
- wptr[0] = adrs;
- wptr[1] = ctrl;
- wptr[2] = 0;
- wptr += PPP_HDRLEN - 1;
- space = dmsg->b_datap->db_lim - wptr;
-
- oldcode = CLEAR;
- explen = 0;
- for (;;) {
- if (len == 0) {
- cmsg = cmsg->b_cont;
- if (!cmsg) /* quit at end of message */
- break;
- rptr = cmsg->b_rptr;
- len = cmsg->b_wptr - rptr;
- ilen += len;
- continue; /* handle 0-length buffers */
- }
-
- /*
- * Accumulate bytes until we have a complete code.
- * Then get the next code, relying on the 32-bit,
- * unsigned accm to mask the result.
- */
- bitno -= 8;
- accm |= *rptr++ << bitno;
- --len;
- if (tgtbitno < bitno)
- continue;
- incode = accm >> tgtbitno;
- accm <<= n_bits;
- bitno += n_bits;
-
- if (incode == CLEAR) {
- /*
- * The dictionary must only be cleared at
- * the end of a packet. But there could be an
- * empty message block at the end.
- */
- if (len > 0 || cmsg->b_cont != 0) {
- if (cmsg->b_cont)
- len += msgdsize(cmsg->b_cont);
- if (len > 0) {
- freemsg(dmsg);
- if (db->debug)
- printf("bsd_decomp%d: bad CLEAR\n", db->unit);
- return DECOMP_FATALERROR;
- }
- }
- bsd_clear(db);
- explen = ilen = 0;
- break;
- }
-
- if (incode > max_ent + 2 || incode > db->maxmaxcode
- || incode > max_ent && oldcode == CLEAR) {
- freemsg(dmsg);
- if (db->debug) {
- printf("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
- db->unit, incode, oldcode);
- printf("max_ent=0x%x dlen=%d seqno=%d\n",
- max_ent, dlen, db->seqno);
- }
- return DECOMP_FATALERROR; /* probably a bug */
- }
-
- /* Special case for KwKwK string. */
- if (incode > max_ent) {
- finchar = oldcode;
- extra = 1;
- } else {
- finchar = incode;
- extra = 0;
- }
-
- codelen = db->lens[finchar];
- explen += codelen + extra;
- if (explen > db->mru + 1) {
- freemsg(dmsg);
- if (db->debug)
- printf("bsd_decomp%d: ran out of mru\n", db->unit);
- return DECOMP_FATALERROR;
- }
-
- /*
- * Decode this code and install it in the decompressed buffer.
- */
- space -= codelen + extra;
- if (space < 0) {
- /* Allocate another message block. */
- dmsg->b_wptr = wptr;
- dlen = codelen + extra;
- if (dlen < DECOMP_CHUNK)
- dlen = DECOMP_CHUNK;
- if ((dmsg->b_cont = allocb(dlen, BPRI_MED)) == NULL) {
- freemsg(dmsg);
- return DECOMP_ERROR;
- }
- dmsg = dmsg->b_cont;
- wptr = dmsg->b_wptr;
- space = dmsg->b_datap->db_lim - wptr - codelen - extra;
- }
- p = (wptr += codelen);
- while (finchar > LAST) {
- dictp = &db->dict[db->dict[finchar].cptr];
-#ifdef DEBUG
- --codelen;
- if (codelen <= 0) {
- freemsg(dmsg);
- printf("bsd_decomp%d: fell off end of chain ", db->unit);
- printf("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
- incode, finchar, db->dict[finchar].cptr, max_ent);
- return DECOMP_FATALERROR;
- }
- if (dictp->codem1 != finchar-1) {
- freemsg(dmsg);
- printf("bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",
- db->unit, incode, finchar);
- printf("oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode,
- db->dict[finchar].cptr, dictp->codem1);
- return DECOMP_FATALERROR;
- }
-#endif
- *--p = dictp->f.hs.suffix;
- finchar = dictp->f.hs.prefix;
- }
- *--p = finchar;
-
-#ifdef DEBUG
- if (--codelen != 0)
- printf("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
- db->unit, codelen, incode, max_ent);
-#endif
-
- if (extra) /* the KwKwK case again */
- *wptr++ = finchar;
-
- /*
- * If not first code in a packet, and
- * if not out of code space, then allocate a new code.
- *
- * Keep the hash table correct so it can be used
- * with uncompressed packets.
- */
- if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
- struct bsd_dict *dictp2;
- u_int32_t fcode;
- int hval, disp;
-
- fcode = BSD_KEY(oldcode,finchar);
- hval = BSD_HASH(oldcode,finchar,db->hshift);
- dictp = &db->dict[hval];
-
- /* look for a free hash table entry */
- if (dictp->codem1 < max_ent) {
- disp = (hval == 0) ? 1 : hval;
- do {
- hval += disp;
- if (hval >= db->hsize)
- hval -= db->hsize;
- dictp = &db->dict[hval];
- } while (dictp->codem1 < max_ent);
- }
-
- /*
- * Invalidate previous hash table entry
- * assigned this code, and then take it over
- */
- dictp2 = &db->dict[max_ent+1];
- if (db->dict[dictp2->cptr].codem1 == max_ent) {
- db->dict[dictp2->cptr].codem1 = BADCODEM1;
- }
- dictp2->cptr = hval;
- dictp->codem1 = max_ent;
- dictp->f.fcode = fcode;
-
- db->max_ent = ++max_ent;
- db->lens[max_ent] = db->lens[oldcode]+1;
-
- /* Expand code size if needed. */
- if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
- db->n_bits = ++n_bits;
- tgtbitno = 32-n_bits;
- }
- }
- oldcode = incode;
- }
- dmsg->b_wptr = wptr;
-
- /*
- * Keep the checkpoint right so that incompressible packets
- * clear the dictionary at the right times.
- */
- db->bytes_out += ilen;
- db->in_count += explen;
- if (bsd_check(db) && db->debug) {
- printf("bsd_decomp%d: peer should have cleared dictionary\n",
- db->unit);
- }
-
- ++db->comp_count;
- db->comp_bytes += ilen + BSD_OVHD;
- ++db->uncomp_count;
- db->uncomp_bytes += explen;
-
- *dmpp = mret;
- return DECOMP_OK;
-}
-#endif /* DO_BSD_COMPRESS */
+++ /dev/null
-/*
- * ppp_deflate.c - interface the zlib procedures for Deflate compression
- * and decompression (as used by gzip) to the PPP code.
- * This version is for use with STREAMS under SunOS 4.x, Solaris 2,
- * SVR4, OSF/1 and AIX 4.x.
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * $Id: deflate.c,v 1.12 2004/01/17 05:47:55 carlsonj Exp $
- */
-
-#ifdef AIX4
-#include <net/net_globals.h>
-#endif
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stream.h>
-#include <net/ppp_defs.h>
-#include "ppp_mod.h"
-
-#define PACKETPTR mblk_t *
-#include <net/ppp-comp.h>
-
-#ifdef __osf__
-#include "zlib.h"
-#else
-#include "../common/zlib.h"
-#endif
-
-#ifdef SOL2
-#include <sys/sunddi.h>
-#endif
-
-#if DO_DEFLATE
-
-#define DEFLATE_DEBUG 1
-
-/*
- * State for a Deflate (de)compressor.
- */
-struct deflate_state {
- int seqno;
- int w_size;
- int unit;
- int hdrlen;
- int mru;
- int debug;
- z_stream strm;
- struct compstat stats;
-};
-
-#define DEFLATE_OVHD 2 /* Deflate overhead/packet */
-
-static void *z_alloc(void *, u_int items, u_int size);
-static void *z_alloc_init(void *, u_int items, u_int size);
-static void z_free(void *, void *ptr);
-static void *z_comp_alloc(u_char *options, int opt_len);
-static void *z_decomp_alloc(u_char *options, int opt_len);
-static void z_comp_free(void *state);
-static void z_decomp_free(void *state);
-static int z_comp_init(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int debug);
-static int z_decomp_init(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int mru, int debug);
-static int z_compress(void *state, mblk_t **mret,
- mblk_t *mp, int slen, int maxolen);
-static void z_incomp(void *state, mblk_t *dmsg);
-static int z_decompress(void *state, mblk_t *cmp,
- mblk_t **dmpp);
-static void z_comp_reset(void *state);
-static void z_decomp_reset(void *state);
-static void z_comp_stats(void *state, struct compstat *stats);
-
-/*
- * Procedures exported to ppp_comp.c.
- */
-struct compressor ppp_deflate = {
- CI_DEFLATE, /* compress_proto */
- z_comp_alloc, /* comp_alloc */
- z_comp_free, /* comp_free */
- z_comp_init, /* comp_init */
- z_comp_reset, /* comp_reset */
- z_compress, /* compress */
- z_comp_stats, /* comp_stat */
- z_decomp_alloc, /* decomp_alloc */
- z_decomp_free, /* decomp_free */
- z_decomp_init, /* decomp_init */
- z_decomp_reset, /* decomp_reset */
- z_decompress, /* decompress */
- z_incomp, /* incomp */
- z_comp_stats, /* decomp_stat */
-};
-
-struct compressor ppp_deflate_draft = {
- CI_DEFLATE_DRAFT, /* compress_proto */
- z_comp_alloc, /* comp_alloc */
- z_comp_free, /* comp_free */
- z_comp_init, /* comp_init */
- z_comp_reset, /* comp_reset */
- z_compress, /* compress */
- z_comp_stats, /* comp_stat */
- z_decomp_alloc, /* decomp_alloc */
- z_decomp_free, /* decomp_free */
- z_decomp_init, /* decomp_init */
- z_decomp_reset, /* decomp_reset */
- z_decompress, /* decompress */
- z_incomp, /* incomp */
- z_comp_stats, /* decomp_stat */
-};
-
-#define DECOMP_CHUNK 512
-
-/*
- * Space allocation and freeing routines for use by zlib routines.
- */
-struct zchunk {
- u_int size;
- u_int guard;
-};
-
-#define GUARD_MAGIC 0x77a6011a
-
-static void *
-z_alloc_init(notused, items, size)
- void *notused;
- u_int items, size;
-{
- struct zchunk *z;
-
- size = items * size + sizeof(struct zchunk);
-#ifdef __osf__
- z = (struct zchunk *) ALLOC_SLEEP(size);
-#else
- z = (struct zchunk *) ALLOC_NOSLEEP(size);
-#endif
- z->size = size;
- z->guard = GUARD_MAGIC;
- return (void *) (z + 1);
-}
-
-static void *
-z_alloc(notused, items, size)
- void *notused;
- u_int items, size;
-{
- struct zchunk *z;
-
- size = items * size + sizeof(struct zchunk);
- z = (struct zchunk *) ALLOC_NOSLEEP(size);
- z->size = size;
- z->guard = GUARD_MAGIC;
- return (void *) (z + 1);
-}
-
-static void
-z_free(notused, ptr)
- void *notused;
- void *ptr;
-{
- struct zchunk *z = ((struct zchunk *) ptr) - 1;
-
- if (z->guard != GUARD_MAGIC) {
- printf("ppp: z_free of corrupted chunk at %x (%x, %x)\n",
- z, z->size, z->guard);
- return;
- }
- FREE(z, z->size);
-}
-
-/*
- * Allocate space for a compressor.
- */
-static void *
-z_comp_alloc(options, opt_len)
- u_char *options;
- int opt_len;
-{
- struct deflate_state *state;
- int w_size;
-
- if (opt_len != CILEN_DEFLATE
- || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
- || options[1] != CILEN_DEFLATE
- || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
- || options[3] != DEFLATE_CHK_SEQUENCE)
- return NULL;
- w_size = DEFLATE_SIZE(options[2]);
- /*
- * N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using
- * 8 will cause kernel crashes because of a bug in zlib.
- */
- if (w_size < 9 || w_size > DEFLATE_MAX_SIZE)
- return NULL;
-
-
-#ifdef __osf__
- state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state));
-#else
- state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
-#endif
-
- if (state == NULL)
- return NULL;
-
- state->strm.next_in = NULL;
- state->strm.zalloc = (alloc_func) z_alloc_init;
- state->strm.zfree = (free_func) z_free;
- if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
- -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
- FREE(state, sizeof(*state));
- return NULL;
- }
-
- state->strm.zalloc = (alloc_func) z_alloc;
- state->w_size = w_size;
- bzero(&state->stats, sizeof(state->stats));
- return (void *) state;
-}
-
-static void
-z_comp_free(arg)
- void *arg;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- deflateEnd(&state->strm);
- FREE(state, sizeof(*state));
-}
-
-static int
-z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
- void *arg;
- u_char *options;
- int opt_len, unit, hdrlen, debug;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- if (opt_len < CILEN_DEFLATE
- || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
- || options[1] != CILEN_DEFLATE
- || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
- || DEFLATE_SIZE(options[2]) != state->w_size
- || options[3] != DEFLATE_CHK_SEQUENCE)
- return 0;
-
- state->seqno = 0;
- state->unit = unit;
- state->hdrlen = hdrlen;
- state->debug = debug;
-
- deflateReset(&state->strm);
-
- return 1;
-}
-
-static void
-z_comp_reset(arg)
- void *arg;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- state->seqno = 0;
- deflateReset(&state->strm);
-}
-
-static int
-z_compress(arg, mret, mp, orig_len, maxolen)
- void *arg;
- mblk_t **mret; /* compressed packet (out) */
- mblk_t *mp; /* uncompressed packet (in) */
- int orig_len, maxolen;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
- u_char *rptr, *wptr;
- int proto, olen, wspace, r, flush;
- mblk_t *m;
-
- /*
- * Check that the protocol is in the range we handle.
- */
- *mret = NULL;
- rptr = mp->b_rptr;
- if (rptr + PPP_HDRLEN > mp->b_wptr) {
- if (!pullupmsg(mp, PPP_HDRLEN))
- return 0;
- rptr = mp->b_rptr;
- }
- proto = PPP_PROTOCOL(rptr);
- if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
- return orig_len;
-
- /* Allocate one mblk initially. */
- if (maxolen > orig_len)
- maxolen = orig_len;
- if (maxolen <= PPP_HDRLEN + 2) {
- wspace = 0;
- m = NULL;
- } else {
- wspace = maxolen + state->hdrlen;
- if (wspace > 4096)
- wspace = 4096;
- m = allocb(wspace, BPRI_MED);
- }
- if (m != NULL) {
- *mret = m;
- if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
- m->b_rptr += state->hdrlen;
- m->b_wptr = m->b_rptr;
- wspace -= state->hdrlen;
- }
- wptr = m->b_wptr;
-
- /*
- * Copy over the PPP header and store the 2-byte sequence number.
- */
- wptr[0] = PPP_ADDRESS(rptr);
- wptr[1] = PPP_CONTROL(rptr);
- wptr[2] = PPP_COMP >> 8;
- wptr[3] = PPP_COMP;
- wptr += PPP_HDRLEN;
- wptr[0] = state->seqno >> 8;
- wptr[1] = state->seqno;
- wptr += 2;
- state->strm.next_out = wptr;
- state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
- } else {
- state->strm.next_out = NULL;
- state->strm.avail_out = 1000000;
- }
- ++state->seqno;
-
- rptr += (proto > 0xff)? 2: 3; /* skip 1st proto byte if 0 */
- state->strm.next_in = rptr;
- state->strm.avail_in = mp->b_wptr - rptr;
- mp = mp->b_cont;
- flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
- olen = 0;
- for (;;) {
- r = deflate(&state->strm, flush);
- if (r != Z_OK) {
- printf("z_compress: deflate returned %d (%s)\n",
- r, (state->strm.msg? state->strm.msg: ""));
- break;
- }
- if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
- break; /* all done */
- if (state->strm.avail_in == 0 && mp != NULL) {
- state->strm.next_in = mp->b_rptr;
- state->strm.avail_in = mp->b_wptr - mp->b_rptr;
- mp = mp->b_cont;
- if (mp == NULL)
- flush = Z_PACKET_FLUSH;
- }
- if (state->strm.avail_out == 0) {
- if (m != NULL) {
- m->b_wptr += wspace;
- olen += wspace;
- wspace = maxolen - olen;
- if (wspace <= 0) {
- wspace = 0;
- m->b_cont = NULL;
- } else {
- if (wspace < 32)
- wspace = 32;
- else if (wspace > 4096)
- wspace = 4096;
- m->b_cont = allocb(wspace, BPRI_MED);
- }
- m = m->b_cont;
- if (m != NULL) {
- state->strm.next_out = m->b_wptr;
- state->strm.avail_out = wspace;
- }
- }
- if (m == NULL) {
- state->strm.next_out = NULL;
- state->strm.avail_out = 1000000;
- }
- }
- }
- if (m != NULL) {
- m->b_wptr += wspace - state->strm.avail_out;
- olen += wspace - state->strm.avail_out;
- }
-
- /*
- * See if we managed to reduce the size of the packet.
- */
- if (olen < orig_len && m != NULL) {
- state->stats.comp_bytes += olen;
- state->stats.comp_packets++;
- } else {
- if (*mret != NULL) {
- freemsg(*mret);
- *mret = NULL;
- }
- state->stats.inc_bytes += orig_len;
- state->stats.inc_packets++;
- olen = orig_len;
- }
- state->stats.unc_bytes += orig_len;
- state->stats.unc_packets++;
-
- return olen;
-}
-
-static void
-z_comp_stats(arg, stats)
- void *arg;
- struct compstat *stats;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
- u_int out;
-
- *stats = state->stats;
- stats->ratio = stats->unc_bytes;
- out = stats->comp_bytes + stats->unc_bytes;
- if (stats->ratio <= 0x7ffffff)
- stats->ratio <<= 8;
- else
- out >>= 8;
- if (out != 0)
- stats->ratio /= out;
-}
-
-/*
- * Allocate space for a decompressor.
- */
-static void *
-z_decomp_alloc(options, opt_len)
- u_char *options;
- int opt_len;
-{
- struct deflate_state *state;
- int w_size;
-
- if (opt_len != CILEN_DEFLATE
- || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
- || options[1] != CILEN_DEFLATE
- || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
- || options[3] != DEFLATE_CHK_SEQUENCE)
- return NULL;
- w_size = DEFLATE_SIZE(options[2]);
- /*
- * N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using
- * 8 will cause kernel crashes because of a bug in zlib.
- */
- if (w_size < 9 || w_size > DEFLATE_MAX_SIZE)
- return NULL;
-
-#ifdef __osf__
- state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state));
-#else
- state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
-#endif
- if (state == NULL)
- return NULL;
-
- state->strm.next_out = NULL;
- state->strm.zalloc = (alloc_func) z_alloc_init;
- state->strm.zfree = (free_func) z_free;
- if (inflateInit2(&state->strm, -w_size) != Z_OK) {
- FREE(state, sizeof(*state));
- return NULL;
- }
-
- state->strm.zalloc = (alloc_func) z_alloc;
- state->w_size = w_size;
- bzero(&state->stats, sizeof(state->stats));
- return (void *) state;
-}
-
-static void
-z_decomp_free(arg)
- void *arg;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- inflateEnd(&state->strm);
- FREE(state, sizeof(*state));
-}
-
-static int
-z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
- void *arg;
- u_char *options;
- int opt_len, unit, hdrlen, mru, debug;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- if (opt_len < CILEN_DEFLATE
- || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
- || options[1] != CILEN_DEFLATE
- || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
- || DEFLATE_SIZE(options[2]) != state->w_size
- || options[3] != DEFLATE_CHK_SEQUENCE)
- return 0;
-
- state->seqno = 0;
- state->unit = unit;
- state->hdrlen = hdrlen;
- state->debug = debug;
- state->mru = mru;
-
- inflateReset(&state->strm);
-
- return 1;
-}
-
-static void
-z_decomp_reset(arg)
- void *arg;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- state->seqno = 0;
- inflateReset(&state->strm);
-}
-
-/*
- * Decompress a Deflate-compressed packet.
- *
- * Because of patent problems, we return DECOMP_ERROR for errors
- * found by inspecting the input data and for system problems, but
- * DECOMP_FATALERROR for any errors which could possibly be said to
- * be being detected "after" decompression. For DECOMP_ERROR,
- * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
- * infringing a patent of Motorola's if we do, so we take CCP down
- * instead.
- *
- * Given that the frame has the correct sequence number and a good FCS,
- * errors such as invalid codes in the input most likely indicate a
- * bug, so we return DECOMP_FATALERROR for them in order to turn off
- * compression, even though they are detected by inspecting the input.
- */
-static int
-z_decompress(arg, mi, mop)
- void *arg;
- mblk_t *mi, **mop;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
- mblk_t *mo, *mo_head;
- u_char *rptr, *wptr;
- int rlen, olen, ospace;
- int seq, i, flush, r, decode_proto;
- u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
-
- *mop = NULL;
- rptr = mi->b_rptr;
- for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
- while (rptr >= mi->b_wptr) {
- mi = mi->b_cont;
- if (mi == NULL)
- return DECOMP_ERROR;
- rptr = mi->b_rptr;
- }
- hdr[i] = *rptr++;
- }
-
- /* Check the sequence number. */
- seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
- if (seq != state->seqno) {
-#if !DEFLATE_DEBUG
- if (state->debug)
-#endif
- printf("z_decompress%d: bad seq # %d, expected %d\n",
- state->unit, seq, state->seqno);
- return DECOMP_ERROR;
- }
- ++state->seqno;
-
- /* Allocate an output message block. */
- mo = allocb(DECOMP_CHUNK + state->hdrlen, BPRI_MED);
- if (mo == NULL)
- return DECOMP_ERROR;
- mo_head = mo;
- mo->b_cont = NULL;
- mo->b_rptr += state->hdrlen;
- mo->b_wptr = wptr = mo->b_rptr;
- ospace = DECOMP_CHUNK;
- olen = 0;
-
- /*
- * Fill in the first part of the PPP header. The protocol field
- * comes from the decompressed data.
- */
- wptr[0] = PPP_ADDRESS(hdr);
- wptr[1] = PPP_CONTROL(hdr);
- wptr[2] = 0;
-
- /*
- * Set up to call inflate. We set avail_out to 1 initially so we can
- * look at the first byte of the output and decide whether we have
- * a 1-byte or 2-byte protocol field.
- */
- state->strm.next_in = rptr;
- state->strm.avail_in = mi->b_wptr - rptr;
- mi = mi->b_cont;
- flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
- rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD;
- state->strm.next_out = wptr + 3;
- state->strm.avail_out = 1;
- decode_proto = 1;
-
- /*
- * Call inflate, supplying more input or output as needed.
- */
- for (;;) {
- r = inflate(&state->strm, flush);
- if (r != Z_OK) {
-#if !DEFLATE_DEBUG
- if (state->debug)
-#endif
- printf("z_decompress%d: inflate returned %d (%s)\n",
- state->unit, r, (state->strm.msg? state->strm.msg: ""));
- freemsg(mo_head);
- return DECOMP_FATALERROR;
- }
- if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
- break; /* all done */
- if (state->strm.avail_in == 0 && mi != NULL) {
- state->strm.next_in = mi->b_rptr;
- state->strm.avail_in = mi->b_wptr - mi->b_rptr;
- rlen += state->strm.avail_in;
- mi = mi->b_cont;
- if (mi == NULL)
- flush = Z_PACKET_FLUSH;
- }
- if (state->strm.avail_out == 0) {
- if (decode_proto) {
- state->strm.avail_out = ospace - PPP_HDRLEN;
- if ((wptr[3] & 1) == 0) {
- /* 2-byte protocol field */
- wptr[2] = wptr[3];
- --state->strm.next_out;
- ++state->strm.avail_out;
- }
- decode_proto = 0;
- } else {
- mo->b_wptr += ospace;
- olen += ospace;
- mo->b_cont = allocb(DECOMP_CHUNK, BPRI_MED);
- mo = mo->b_cont;
- if (mo == NULL) {
- freemsg(mo_head);
- return DECOMP_ERROR;
- }
- state->strm.next_out = mo->b_rptr;
- state->strm.avail_out = ospace = DECOMP_CHUNK;
- }
- }
- }
- if (decode_proto) {
- freemsg(mo_head);
- return DECOMP_ERROR;
- }
- mo->b_wptr += ospace - state->strm.avail_out;
- olen += ospace - state->strm.avail_out;
-
-#if DEFLATE_DEBUG
- if (olen > state->mru + PPP_HDRLEN)
- printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
- state->unit, olen, state->mru + PPP_HDRLEN);
-#endif
-
- state->stats.unc_bytes += olen;
- state->stats.unc_packets++;
- state->stats.comp_bytes += rlen;
- state->stats.comp_packets++;
-
- *mop = mo_head;
- return DECOMP_OK;
-}
-
-/*
- * Incompressible data has arrived - add it to the history.
- */
-static void
-z_incomp(arg, mi)
- void *arg;
- mblk_t *mi;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
- u_char *rptr;
- int rlen, proto, r;
-
- /*
- * Check that the protocol is one we handle.
- */
- rptr = mi->b_rptr;
- if (rptr + PPP_HDRLEN > mi->b_wptr) {
- if (!pullupmsg(mi, PPP_HDRLEN))
- return;
- rptr = mi->b_rptr;
- }
- proto = PPP_PROTOCOL(rptr);
- if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
- return;
-
- ++state->seqno;
-
- /*
- * Iterate through the message blocks, adding the characters in them
- * to the decompressor's history. For the first block, we start
- * at the either the 1st or 2nd byte of the protocol field,
- * depending on whether the protocol value is compressible.
- */
- rlen = mi->b_wptr - mi->b_rptr;
- state->strm.next_in = rptr + 3;
- state->strm.avail_in = rlen - 3;
- if (proto > 0xff) {
- --state->strm.next_in;
- ++state->strm.avail_in;
- }
- for (;;) {
- r = inflateIncomp(&state->strm);
- if (r != Z_OK) {
- /* gak! */
-#if !DEFLATE_DEBUG
- if (state->debug)
-#endif
- printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
- state->unit, r, (state->strm.msg? state->strm.msg: ""));
- return;
- }
- mi = mi->b_cont;
- if (mi == NULL)
- break;
- state->strm.next_in = mi->b_rptr;
- state->strm.avail_in = mi->b_wptr - mi->b_rptr;
- rlen += state->strm.avail_in;
- }
-
- /*
- * Update stats.
- */
- state->stats.inc_bytes += rlen;
- state->stats.inc_packets++;
- state->stats.unc_bytes += rlen;
- state->stats.unc_packets++;
-}
-
-#endif /* DO_DEFLATE */
+++ /dev/null
-/*
- * if_ppp.c - a network interface connected to a STREAMS module.
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * $Id: if_ppp.c,v 1.18 2002/12/06 09:49:15 paulus Exp $
- */
-
-/*
- * This file is used under SunOS 4 and Digital UNIX.
- *
- * This file provides the glue between PPP and IP.
- */
-
-#define INET 1
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/netisr.h>
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-#include <netinet/in.h>
-#include <netinet/in_var.h>
-#ifdef __osf__
-#include <sys/ioctl.h>
-#include <net/if_types.h>
-#else
-#include <sys/sockio.h>
-#endif
-#include "ppp_mod.h"
-
-#include <sys/stream.h>
-
-#ifdef SNIT_SUPPORT
-#include <sys/time.h>
-#include <net/nit_if.h>
-#include <netinet/if_ether.h>
-#endif
-
-#ifdef __osf__
-#define SIOCSIFMTU SIOCSIPMTU
-#define SIOCGIFMTU SIOCRIPMTU
-#define IFA_ADDR(ifa) (*(ifa)->ifa_addr)
-#else
-#define IFA_ADDR(ifa) ((ifa)->ifa_addr)
-#endif
-
-#define ifr_mtu ifr_metric
-
-static int if_ppp_open(queue_t *, int, int, int);
-static int if_ppp_close(queue_t *, int);
-static int if_ppp_wput(queue_t *, mblk_t *);
-static int if_ppp_rput(queue_t *, mblk_t *);
-
-#define PPP_IF_ID 0x8021
-static struct module_info minfo = {
- PPP_IF_ID, "if_ppp", 0, INFPSZ, 4096, 128
-};
-
-static struct qinit rinit = {
- if_ppp_rput, NULL, if_ppp_open, if_ppp_close, NULL, &minfo, NULL
-};
-
-static struct qinit winit = {
- if_ppp_wput, NULL, NULL, NULL, NULL, &minfo, NULL
-};
-
-struct streamtab if_pppinfo = {
- &rinit, &winit, NULL, NULL
-};
-
-typedef struct if_ppp_state {
- int unit;
- queue_t *q;
- int flags;
-} if_ppp_t;
-
-/* Values for flags */
-#define DBGLOG 1
-
-static int if_ppp_count; /* Number of currently-active streams */
-
-static int ppp_nalloc; /* Number of elements of ifs and states */
-static struct ifnet **ifs; /* Array of pointers to interface structs */
-static if_ppp_t **states; /* Array of pointers to state structs */
-
-static int if_ppp_output(struct ifnet *, struct mbuf *,
- struct sockaddr *);
-static int if_ppp_ioctl(struct ifnet *, u_int, caddr_t);
-static struct mbuf *make_mbufs(mblk_t *, int);
-static mblk_t *make_message(struct mbuf *, int);
-
-#ifdef SNIT_SUPPORT
-/* Fake ether header for SNIT */
-static struct ether_header snit_ehdr = {{0}, {0}, ETHERTYPE_IP};
-#endif
-
-#ifndef __osf__
-static void ppp_if_detach(struct ifnet *);
-
-/*
- * Detach all the interfaces before unloading.
- * Not sure this works.
- */
-int
-if_ppp_unload()
-{
- int i;
-
- if (if_ppp_count > 0)
- return EBUSY;
- for (i = 0; i < ppp_nalloc; ++i)
- if (ifs[i] != 0)
- ppp_if_detach(ifs[i]);
- if (ifs) {
- FREE(ifs, ppp_nalloc * sizeof (struct ifnet *));
- FREE(states, ppp_nalloc * sizeof (struct if_ppp_t *));
- }
- ppp_nalloc = 0;
- return 0;
-}
-#endif /* __osf__ */
-
-/*
- * STREAMS module entry points.
- */
-static int
-if_ppp_open(q, dev, flag, sflag)
- queue_t *q;
- int dev;
- int flag, sflag;
-{
- if_ppp_t *sp;
-
- if (q->q_ptr == 0) {
- sp = (if_ppp_t *) ALLOC_SLEEP(sizeof (if_ppp_t));
- if (sp == 0)
- return OPENFAIL;
- bzero(sp, sizeof (if_ppp_t));
- q->q_ptr = (caddr_t) sp;
- WR(q)->q_ptr = (caddr_t) sp;
- sp->unit = -1; /* no interface unit attached at present */
- sp->q = WR(q);
- sp->flags = 0;
- ++if_ppp_count;
- }
- return 0;
-}
-
-static int
-if_ppp_close(q, flag)
- queue_t *q;
- int flag;
-{
- if_ppp_t *sp;
- struct ifnet *ifp;
-
- sp = (if_ppp_t *) q->q_ptr;
- if (sp != 0) {
- if (sp->flags & DBGLOG)
- printf("if_ppp closed, q=%x sp=%x\n", q, sp);
- if (sp->unit >= 0) {
- if (sp->unit < ppp_nalloc) {
- states[sp->unit] = 0;
- ifp = ifs[sp->unit];
- if (ifp != 0)
- ifp->if_flags &= ~(IFF_UP | IFF_RUNNING);
-#ifdef DEBUG
- } else {
- printf("if_ppp: unit %d nonexistent!\n", sp->unit);
-#endif
- }
- }
- FREE(sp, sizeof (if_ppp_t));
- --if_ppp_count;
- }
- return 0;
-}
-
-static int
-if_ppp_wput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- if_ppp_t *sp;
- struct iocblk *iop;
- int error, unit;
- struct ifnet *ifp;
-
- sp = (if_ppp_t *) q->q_ptr;
- switch (mp->b_datap->db_type) {
- case M_DATA:
- /*
- * Now why would we be getting data coming in here??
- */
- if (sp->flags & DBGLOG)
- printf("if_ppp: got M_DATA len=%d\n", msgdsize(mp));
- freemsg(mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
-
- if (sp->flags & DBGLOG)
- printf("if_ppp: got ioctl cmd=%x count=%d\n",
- iop->ioc_cmd, iop->ioc_count);
-
- switch (iop->ioc_cmd) {
- case PPPIO_NEWPPA: /* well almost */
- if (iop->ioc_count != sizeof(int) || sp->unit >= 0)
- break;
- if ((error = NOTSUSER()) != 0)
- break;
- unit = *(int *)mp->b_cont->b_rptr;
-
- /* Check that this unit isn't already in use */
- if (unit < ppp_nalloc && states[unit] != 0) {
- error = EADDRINUSE;
- break;
- }
-
- /* Extend ifs and states arrays if necessary. */
- error = ENOSR;
- if (unit >= ppp_nalloc) {
- int newn;
- struct ifnet **newifs;
- if_ppp_t **newstates;
-
- newn = unit + 4;
- if (sp->flags & DBGLOG)
- printf("if_ppp: extending ifs to %d\n", newn);
- newifs = (struct ifnet **)
- ALLOC_NOSLEEP(newn * sizeof (struct ifnet *));
- if (newifs == 0)
- break;
- bzero(newifs, newn * sizeof (struct ifnet *));
- newstates = (if_ppp_t **)
- ALLOC_NOSLEEP(newn * sizeof (struct if_ppp_t *));
- if (newstates == 0) {
- FREE(newifs, newn * sizeof (struct ifnet *));
- break;
- }
- bzero(newstates, newn * sizeof (struct if_ppp_t *));
- bcopy(ifs, newifs, ppp_nalloc * sizeof(struct ifnet *));
- bcopy(states, newstates, ppp_nalloc * sizeof(if_ppp_t *));
- if (ifs) {
- FREE(ifs, ppp_nalloc * sizeof(struct ifnet *));
- FREE(states, ppp_nalloc * sizeof(if_ppp_t *));
- }
- ifs = newifs;
- states = newstates;
- ppp_nalloc = newn;
- }
-
- /* Allocate a new ifnet struct if necessary. */
- ifp = ifs[unit];
- if (ifp == 0) {
- ifp = (struct ifnet *) ALLOC_NOSLEEP(sizeof (struct ifnet));
- if (ifp == 0)
- break;
- bzero(ifp, sizeof (struct ifnet));
- ifs[unit] = ifp;
- ifp->if_name = "ppp";
- ifp->if_unit = unit;
- ifp->if_mtu = PPP_MTU;
- ifp->if_flags = IFF_POINTOPOINT | IFF_RUNNING;
-#ifndef __osf__
-#ifdef IFF_MULTICAST
- ifp->if_flags |= IFF_MULTICAST;
-#endif
-#endif /* __osf__ */
- ifp->if_output = if_ppp_output;
-#ifdef __osf__
- ifp->if_version = "Point-to-Point Protocol, version 2.3.11";
- ifp->if_mediamtu = PPP_MTU;
- ifp->if_type = IFT_PPP;
- ifp->if_hdrlen = PPP_HDRLEN;
- ifp->if_addrlen = 0;
- ifp->if_flags |= IFF_NOARP | IFF_SIMPLEX | IFF_NOTRAILERS;
-#ifdef IFF_VAR_MTU
- ifp->if_flags |= IFF_VAR_MTU;
-#endif
-#ifdef NETMASTERCPU
- ifp->if_affinity = NETMASTERCPU;
-#endif
-#endif
- ifp->if_ioctl = if_ppp_ioctl;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
- if_attach(ifp);
- if (sp->flags & DBGLOG)
- printf("if_ppp: created unit %d\n", unit);
- } else {
- ifp->if_mtu = PPP_MTU;
- ifp->if_flags |= IFF_RUNNING;
- }
-
- states[unit] = sp;
- sp->unit = unit;
-
- error = 0;
- iop->ioc_count = 0;
- if (sp->flags & DBGLOG)
- printf("if_ppp: attached unit %d, sp=%x q=%x\n", unit,
- sp, sp->q);
- break;
-
- case PPPIO_DEBUG:
- error = -1;
- if (iop->ioc_count == sizeof(int)) {
- if (*(int *)mp->b_cont->b_rptr == PPPDBG_LOG + PPPDBG_IF) {
- printf("if_ppp: debug log enabled, q=%x sp=%x\n", q, sp);
- sp->flags |= DBGLOG;
- error = 0;
- iop->ioc_count = 0;
- }
- }
- break;
-
- default:
- error = -1;
- break;
- }
-
- if (sp->flags & DBGLOG)
- printf("if_ppp: ioctl result %d\n", error);
- if (error < 0)
- putnext(q, mp);
- else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
- mp->b_datap->db_type = M_IOCNAK;
- iop->ioc_count = 0;
- iop->ioc_error = error;
- qreply(q, mp);
- }
- break;
-
- default:
- putnext(q, mp);
- }
- return 0;
-}
-
-static int
-if_ppp_rput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- if_ppp_t *sp;
- int proto, s;
- struct mbuf *mb;
- struct ifqueue *inq;
- struct ifnet *ifp;
- int len;
-
- sp = (if_ppp_t *) q->q_ptr;
- switch (mp->b_datap->db_type) {
- case M_DATA:
- /*
- * Convert the message into an mbuf chain
- * and inject it into the network code.
- */
- if (sp->flags & DBGLOG)
- printf("if_ppp: rput pkt len %d data %x %x %x %x %x %x %x %x\n",
- msgdsize(mp), mp->b_rptr[0], mp->b_rptr[1], mp->b_rptr[2],
- mp->b_rptr[3], mp->b_rptr[4], mp->b_rptr[5], mp->b_rptr[6],
- mp->b_rptr[7]);
-
- if (sp->unit < 0) {
- freemsg(mp);
- break;
- }
- if (sp->unit >= ppp_nalloc || (ifp = ifs[sp->unit]) == 0) {
-#ifdef DEBUG
- printf("if_ppp: no unit %d!\n", sp->unit);
-#endif
- freemsg(mp);
- break;
- }
-
- if ((ifp->if_flags & IFF_UP) == 0) {
- freemsg(mp);
- break;
- }
- ++ifp->if_ipackets;
-
- proto = PPP_PROTOCOL(mp->b_rptr);
- adjmsg(mp, PPP_HDRLEN);
- len = msgdsize(mp);
- mb = make_mbufs(mp, sizeof(struct ifnet *));
- freemsg(mp);
- if (mb == NULL) {
- if (sp->flags & DBGLOG)
- printf("if_ppp%d: make_mbufs failed\n", ifp->if_unit);
- ++ifp->if_ierrors;
- break;
- }
-
-#ifdef SNIT_SUPPORT
- if (proto == PPP_IP && (ifp->if_flags & IFF_PROMISC)) {
- struct nit_if nif;
-
- nif.nif_header = (caddr_t) &snit_ehdr;
- nif.nif_hdrlen = sizeof(snit_ehdr);
- nif.nif_bodylen = len;
- nif.nif_promisc = 0;
- snit_intr(ifp, mb, &nif);
- }
-#endif
-
-/*
- * For Digital UNIX, there's space set aside in the header mbuf
- * for the interface info.
- *
- * For Sun it's smuggled around via a pointer at the front of the mbuf.
- */
-#ifdef __osf__
- mb->m_pkthdr.rcvif = ifp;
- mb->m_pkthdr.len = len;
-#else
- mb->m_off -= sizeof(struct ifnet *);
- mb->m_len += sizeof(struct ifnet *);
- *mtod(mb, struct ifnet **) = ifp;
-#endif
-
- inq = 0;
- switch (proto) {
- case PPP_IP:
- inq = &ipintrq;
- schednetisr(NETISR_IP);
- }
-
- if (inq != 0) {
- s = splhigh();
- if (IF_QFULL(inq)) {
- IF_DROP(inq);
- ++ifp->if_ierrors;
- if (sp->flags & DBGLOG)
- printf("if_ppp: inq full, proto=%x\n", proto);
- m_freem(mb);
- } else {
- IF_ENQUEUE(inq, mb);
- }
- splx(s);
- } else {
- if (sp->flags & DBGLOG)
- printf("if_ppp%d: proto=%x?\n", ifp->if_unit, proto);
- ++ifp->if_ierrors;
- m_freem(mb);
- }
- break;
-
- default:
- putnext(q, mp);
- }
- return 0;
-}
-
-/*
- * Network code wants to output a packet.
- * Turn it into a STREAMS message and send it down.
- */
-static int
-if_ppp_output(ifp, m0, dst)
- struct ifnet *ifp;
- struct mbuf *m0;
- struct sockaddr *dst;
-{
- mblk_t *mp;
- int proto, s;
- if_ppp_t *sp;
- u_char *p;
-
- if ((ifp->if_flags & IFF_UP) == 0) {
- m_freem(m0);
- return ENETDOWN;
- }
-
- if ((unsigned)ifp->if_unit >= ppp_nalloc) {
-#ifdef DEBUG
- printf("if_ppp_output: unit %d?\n", ifp->if_unit);
-#endif
- m_freem(m0);
- return EINVAL;
- }
- sp = states[ifp->if_unit];
- if (sp == 0) {
-#ifdef DEBUG
- printf("if_ppp_output: no queue?\n");
-#endif
- m_freem(m0);
- return ENETDOWN;
- }
-
- if (sp->flags & DBGLOG) {
- p = mtod(m0, u_char *);
- printf("if_ppp_output%d: af=%d data=%x %x %x %x %x %x %x %x q=%x\n",
- ifp->if_unit, dst->sa_family, p[0], p[1], p[2], p[3], p[4],
- p[5], p[6], p[7], sp->q);
- }
-
- switch (dst->sa_family) {
- case AF_INET:
- proto = PPP_IP;
-#ifdef SNIT_SUPPORT
- if (ifp->if_flags & IFF_PROMISC) {
- struct nit_if nif;
- struct mbuf *m;
- int len;
-
- for (len = 0, m = m0; m != NULL; m = m->m_next)
- len += m->m_len;
- nif.nif_header = (caddr_t) &snit_ehdr;
- nif.nif_hdrlen = sizeof(snit_ehdr);
- nif.nif_bodylen = len;
- nif.nif_promisc = 0;
- snit_intr(ifp, m0, &nif);
- }
-#endif
- break;
-
- default:
- m_freem(m0);
- return EAFNOSUPPORT;
- }
-
- ++ifp->if_opackets;
- mp = make_message(m0, PPP_HDRLEN);
- m_freem(m0);
- if (mp == 0) {
- ++ifp->if_oerrors;
- return ENOBUFS;
- }
- mp->b_rptr -= PPP_HDRLEN;
- mp->b_rptr[0] = PPP_ALLSTATIONS;
- mp->b_rptr[1] = PPP_UI;
- mp->b_rptr[2] = proto >> 8;
- mp->b_rptr[3] = proto;
-
- s = splstr();
- if (sp->flags & DBGLOG)
- printf("if_ppp: putnext(%x, %x), r=%x w=%x p=%x\n",
- sp->q, mp, mp->b_rptr, mp->b_wptr, proto);
- putnext(sp->q, mp);
- splx(s);
-
- return 0;
-}
-
-/*
- * Socket ioctl routine for ppp interfaces.
- */
-static int
-if_ppp_ioctl(ifp, cmd, data)
- struct ifnet *ifp;
- u_int cmd;
- caddr_t data;
-{
- int s, error;
- struct ifreq *ifr = (struct ifreq *) data;
- struct ifaddr *ifa = (struct ifaddr *) data;
- u_short mtu;
-
- error = 0;
- s = splimp();
- switch (cmd) {
- case SIOCSIFFLAGS:
- if ((ifp->if_flags & IFF_RUNNING) == 0)
- ifp->if_flags &= ~IFF_UP;
- break;
-
- case SIOCSIFADDR:
- if (IFA_ADDR(ifa).sa_family != AF_INET)
- error = EAFNOSUPPORT;
- break;
-
- case SIOCSIFDSTADDR:
- if (IFA_ADDR(ifa).sa_family != AF_INET)
- error = EAFNOSUPPORT;
- break;
-
- case SIOCSIFMTU:
- if ((error = NOTSUSER()) != 0)
- break;
-#ifdef __osf__
- /* this hack is necessary because ifioctl checks ifr_data
- * in 4.0 and 5.0, but ifr_data and ifr_metric overlay each
- * other in the definition of struct ifreq so pppd can't set both.
- */
- bcopy(ifr->ifr_data, &mtu, sizeof (u_short));
- ifr->ifr_mtu = mtu;
-#endif
-
- if (ifr->ifr_mtu < PPP_MINMTU || ifr->ifr_mtu > PPP_MAXMTU) {
- error = EINVAL;
- break;
- }
- ifp->if_mtu = ifr->ifr_mtu;
- break;
-
- case SIOCGIFMTU:
- ifr->ifr_mtu = ifp->if_mtu;
- break;
-
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- switch(ifr->ifr_addr.sa_family) {
- case AF_INET:
- break;
- default:
- error = EAFNOSUPPORT;
- break;
- }
- break;
-
- default:
- error = EINVAL;
- }
- splx(s);
- return (error);
-}
-
-/*
- * Turn a STREAMS message into an mbuf chain.
- */
-static struct mbuf *
-make_mbufs(mp, off)
- mblk_t *mp;
- int off;
-{
- struct mbuf *head, **prevp, *m;
- int len, space, n;
- unsigned char *cp, *dp;
-
- len = msgdsize(mp);
- if (len == 0)
- return 0;
- prevp = &head;
- space = 0;
- cp = mp->b_rptr;
-#ifdef __osf__
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- m->m_len = 0;
- space = MHLEN;
- *prevp = m;
- prevp = &m->m_next;
- dp = mtod(m, unsigned char *);
- len -= space;
- off = 0;
-#endif
- for (;;) {
- while (cp >= mp->b_wptr) {
- mp = mp->b_cont;
- if (mp == 0) {
- *prevp = 0;
- return head;
- }
- cp = mp->b_rptr;
- }
- n = mp->b_wptr - cp;
- if (space == 0) {
- MGET(m, M_DONTWAIT, MT_DATA);
- *prevp = m;
- if (m == 0) {
- if (head != 0)
- m_freem(head);
- return 0;
- }
- if (len + off > 2 * MLEN) {
-#ifdef __osf__
- MCLGET(m, M_DONTWAIT);
-#else
- MCLGET(m);
-#endif
- }
-#ifdef __osf__
- space = ((m->m_flags & M_EXT) ? MCLBYTES : MLEN);
-#else
- space = (m->m_off > MMAXOFF? MCLBYTES: MLEN) - off;
- m->m_off += off;
-#endif
- m->m_len = 0;
- len -= space;
- dp = mtod(m, unsigned char *);
- off = 0;
- prevp = &m->m_next;
- }
- if (n > space)
- n = space;
- bcopy(cp, dp, n);
- cp += n;
- dp += n;
- space -= n;
- m->m_len += n;
- }
-}
-
-/*
- * Turn an mbuf chain into a STREAMS message.
- */
-#define ALLOCB_MAX 4096
-
-static mblk_t *
-make_message(m, off)
- struct mbuf *m;
- int off;
-{
- mblk_t *head, **prevp, *mp;
- int len, space, n, nb;
- unsigned char *cp, *dp;
- struct mbuf *nm;
-
- len = 0;
- for (nm = m; nm != 0; nm = nm->m_next)
- len += nm->m_len;
- prevp = &head;
- space = 0;
- cp = mtod(m, unsigned char *);
- nb = m->m_len;
- for (;;) {
- while (nb <= 0) {
- m = m->m_next;
- if (m == 0) {
- *prevp = 0;
- return head;
- }
- cp = mtod(m, unsigned char *);
- nb = m->m_len;
- }
- if (space == 0) {
- space = len + off;
- if (space > ALLOCB_MAX)
- space = ALLOCB_MAX;
- mp = allocb(space, BPRI_LO);
- *prevp = mp;
- if (mp == 0) {
- if (head != 0)
- freemsg(head);
- return 0;
- }
- dp = mp->b_rptr += off;
- space -= off;
- len -= space;
- off = 0;
- prevp = &mp->b_cont;
- }
- n = nb < space? nb: space;
- bcopy(cp, dp, n);
- cp += n;
- dp += n;
- nb -= n;
- space -= n;
- mp->b_wptr = dp;
- }
-}
-
-/*
- * Digital UNIX doesn't allow for removing ifnet structures
- * from the list. But then we're not using this as a loadable
- * module anyway, so that's OK.
- *
- * Under SunOS, this should allow the module to be unloaded.
- * Unfortunately, it doesn't seem to detach all the references,
- * so your system may well crash after you unload this module :-(
- */
-#ifndef __osf__
-
-/*
- * Remove an interface from the system.
- * This routine contains magic.
- */
-#include <net/route.h>
-#include <netinet/in_pcb.h>
-#include <netinet/ip_var.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_timer.h>
-#include <netinet/tcp_var.h>
-#include <netinet/udp.h>
-#include <netinet/udp_var.h>
-
-static void
-ppp_if_detach(ifp)
- struct ifnet *ifp;
-{
- int s;
- struct inpcb *pcb;
- struct ifaddr *ifa;
- struct in_ifaddr **inap;
- struct ifnet **ifpp;
-
- s = splhigh();
-
- /*
- * Clear the interface from any routes currently cached in
- * TCP or UDP protocol control blocks.
- */
- for (pcb = tcb.inp_next; pcb != &tcb; pcb = pcb->inp_next)
- if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
- in_losing(pcb);
- for (pcb = udb.inp_next; pcb != &udb; pcb = pcb->inp_next)
- if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
- in_losing(pcb);
-
- /*
- * Delete routes through all addresses of the interface.
- */
- for (ifa = ifp->if_addrlist; ifa != 0; ifa = ifa->ifa_next) {
- rtinit(ifa, ifa, SIOCDELRT, RTF_HOST);
- rtinit(ifa, ifa, SIOCDELRT, 0);
- }
-
- /*
- * Unlink the interface's address(es) from the in_ifaddr list.
- */
- for (inap = &in_ifaddr; *inap != 0; ) {
- if ((*inap)->ia_ifa.ifa_ifp == ifp)
- *inap = (*inap)->ia_next;
- else
- inap = &(*inap)->ia_next;
- }
-
- /*
- * Delete the interface from the ifnet list.
- */
- for (ifpp = &ifnet; (*ifpp) != 0; ) {
- if (*ifpp == ifp)
- break;
- ifpp = &(*ifpp)->if_next;
- }
- if (*ifpp == 0)
- printf("couldn't find interface ppp%d in ifnet list\n", ifp->if_unit);
- else
- *ifpp = ifp->if_next;
-
- splx(s);
-}
-
-#endif /* __osf__ */
+++ /dev/null
-/*
- * ppp.c - STREAMS multiplexing pseudo-device driver for PPP.
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/errno.h>
-#ifdef __osf__
-#include <sys/ioctl.h>
-#include <sys/cmn_err.h>
-#define queclass(mp) ((mp)->b_band & QPCTL)
-#else
-#include <sys/ioccom.h>
-#endif
-#include <sys/time.h>
-#ifdef SVR4
-#include <sys/cmn_err.h>
-#include <sys/conf.h>
-#include <sys/dlpi.h>
-#include <sys/ddi.h>
-#ifdef SOL2
-#include <sys/ksynch.h>
-#include <sys/kstat.h>
-#include <sys/sunddi.h>
-#include <sys/ethernet.h>
-#else
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#endif /* SOL2 */
-#else /* not SVR4 */
-#include <sys/user.h>
-#endif /* SVR4 */
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-#include "ppp_mod.h"
-
-/*
- * Modifications marked with #ifdef PRIOQ are for priority queueing of
- * interactive traffic, and are due to Marko Zec <zec@japa.tel.fer.hr>.
- */
-#ifdef PRIOQ
-#endif /* PRIOQ */
-
-#include <netinet/in.h> /* leave this outside of PRIOQ for htons */
-
-/*
- * The IP module may use this SAP value for IP packets.
- */
-#ifndef ETHERTYPE_IP
-#define ETHERTYPE_IP 0x800
-#endif
-
-#if !defined(ETHERTYPE_IPV6)
-#define ETHERTYPE_IPV6 0x86dd
-#endif /* !defined(ETHERTYPE_IPV6) */
-
-#if !defined(ETHERTYPE_ALLSAP) && defined(SOL2)
-#define ETHERTYPE_ALLSAP 0
-#endif /* !defined(ETHERTYPE_ALLSAP) && defined(SOL2) */
-
-#if !defined(PPP_ALLSAP) && defined(SOL2)
-#define PPP_ALLSAP PPP_ALLSTATIONS
-#endif /* !defined(PPP_ALLSAP) && defined(SOL2) */
-
-extern time_t time;
-
-#ifdef SOL2
-/*
- * We use this reader-writer lock to ensure that the lower streams
- * stay connected to the upper streams while the lower-side put and
- * service procedures are running. Essentially it is an existence
- * lock for the upper stream associated with each lower stream.
- */
-krwlock_t ppp_lower_lock;
-#define LOCK_LOWER_W rw_enter(&ppp_lower_lock, RW_WRITER)
-#define LOCK_LOWER_R rw_enter(&ppp_lower_lock, RW_READER)
-#define TRYLOCK_LOWER_R rw_tryenter(&ppp_lower_lock, RW_READER)
-#define UNLOCK_LOWER rw_exit(&ppp_lower_lock)
-
-#define MT_ENTER(x) mutex_enter(x)
-#define MT_EXIT(x) mutex_exit(x)
-
-/*
- * Notes on multithreaded implementation for Solaris 2:
- *
- * We use an inner perimeter around each queue pair and an outer
- * perimeter around the whole driver. The inner perimeter is
- * entered exclusively for all entry points (open, close, put,
- * service). The outer perimeter is entered exclusively for open
- * and close and shared for put and service. This is all done for
- * us by the streams framework.
- *
- * I used to think that the perimeters were entered for the lower
- * streams' put and service routines as well as for the upper streams'.
- * Because of problems experienced by people, and after reading the
- * documentation more closely, I now don't think that is true. So we
- * now use ppp_lower_lock to give us an existence guarantee on the
- * upper stream controlling each lower stream.
- *
- * Shared entry to the outer perimeter protects the existence of all
- * the upper streams and their upperstr_t structures, and guarantees
- * that the following fields of any upperstr_t won't change:
- * nextmn, next, nextppa. It guarantees that the lowerq field of an
- * upperstr_t won't go from non-zero to zero, that the global `ppas'
- * won't change and that the no lower stream will get unlinked.
- *
- * Shared (reader) access to ppa_lower_lock guarantees that no lower
- * stream will be unlinked and that the lowerq field of all upperstr_t
- * structures won't change.
- */
-
-#else /* SOL2 */
-#define LOCK_LOWER_W 0
-#define LOCK_LOWER_R 0
-#define TRYLOCK_LOWER_R 1
-#define UNLOCK_LOWER 0
-#define MT_ENTER(x) 0
-#define MT_EXIT(x) 0
-
-#endif /* SOL2 */
-
-/*
- * Private information; one per upper stream.
- */
-typedef struct upperstr {
- minor_t mn; /* minor device number */
- struct upperstr *nextmn; /* next minor device */
- queue_t *q; /* read q associated with this upper stream */
- int flags; /* flag bits, see below */
- int state; /* current DLPI state */
- int sap; /* service access point */
- int req_sap; /* which SAP the DLPI client requested */
- struct upperstr *ppa; /* control stream for our ppa */
- struct upperstr *next; /* next stream for this ppa */
- uint ioc_id; /* last ioctl ID for this stream */
- enum NPmode npmode; /* what to do with packets on this SAP */
- unsigned char rblocked; /* flow control has blocked upper read strm */
- /* N.B. rblocked is only changed by control stream's put/srv procs */
- /*
- * There is exactly one control stream for each PPA.
- * The following fields are only used for control streams.
- */
- int ppa_id;
- queue_t *lowerq; /* write queue attached below this PPA */
- struct upperstr *nextppa; /* next control stream */
- int mru;
- int mtu;
- struct pppstat stats; /* statistics */
- time_t last_sent; /* time last NP packet sent */
- time_t last_recv; /* time last NP packet rcvd */
-#ifdef SOL2
- kmutex_t stats_lock; /* lock for stats updates */
- kstat_t *kstats; /* stats for netstat */
-#endif /* SOL2 */
-#ifdef LACHTCP
- int ifflags;
- char ifname[IFNAMSIZ];
- struct ifstats ifstats;
-#endif /* LACHTCP */
-} upperstr_t;
-
-/* Values for flags */
-#define US_PRIV 1 /* stream was opened by superuser */
-#define US_CONTROL 2 /* stream is a control stream */
-#define US_BLOCKED 4 /* flow ctrl has blocked lower write stream */
-#define US_LASTMOD 8 /* no PPP modules below us */
-#define US_DBGLOG 0x10 /* log various occurrences */
-#define US_RBLOCKED 0x20 /* flow ctrl has blocked upper read stream */
-
-#if defined(SOL2)
-#if DL_CURRENT_VERSION >= 2
-#define US_PROMISC 0x40 /* stream is promiscuous */
-#endif /* DL_CURRENT_VERSION >= 2 */
-#define US_RAWDATA 0x80 /* raw M_DATA, no DLPI header */
-#endif /* defined(SOL2) */
-
-#ifdef PRIOQ
-static u_char max_band=0;
-static u_char def_band=0;
-
-#define IPPORT_DEFAULT 65535
-
-/*
- * Port priority table
- * Highest priority ports are listed first, lowest are listed last.
- * ICMP & packets using unlisted ports will be treated as "default".
- * If IPPORT_DEFAULT is not listed here, "default" packets will be
- * assigned lowest priority.
- * Each line should be terminated with "0".
- * Line containing only "0" marks the end of the list.
- */
-
-static u_short prioq_table[]= {
- 113, 53, 0,
- 22, 23, 513, 517, 518, 0,
- 514, 21, 79, 111, 0,
- 25, 109, 110, 0,
- IPPORT_DEFAULT, 0,
- 20, 70, 80, 8001, 8008, 8080, 0, /* 8001,8008,8080 - common proxy ports */
-0 };
-
-#endif /* PRIOQ */
-
-
-static upperstr_t *minor_devs = NULL;
-static upperstr_t *ppas = NULL;
-
-#ifdef SVR4
-static int pppopen(queue_t *, dev_t *, int, int, cred_t *);
-static int pppclose(queue_t *, int, cred_t *);
-#else
-static int pppopen(queue_t *, int, int, int);
-static int pppclose(queue_t *, int);
-#endif /* SVR4 */
-static int pppurput(queue_t *, mblk_t *);
-static int pppuwput(queue_t *, mblk_t *);
-static int pppursrv(queue_t *);
-static int pppuwsrv(queue_t *);
-static int ppplrput(queue_t *, mblk_t *);
-static int ppplwput(queue_t *, mblk_t *);
-static int ppplrsrv(queue_t *);
-static int ppplwsrv(queue_t *);
-#ifndef NO_DLPI
-static void dlpi_request(queue_t *, mblk_t *, upperstr_t *);
-static void dlpi_error(queue_t *, upperstr_t *, int, int, int);
-static void dlpi_ok(queue_t *, int);
-#endif
-static int send_data(mblk_t *, upperstr_t *);
-static void new_ppa(queue_t *, mblk_t *);
-static void attach_ppa(queue_t *, mblk_t *);
-static void detach_ppa(queue_t *, mblk_t *);
-static void detach_lower(queue_t *, mblk_t *);
-static void debug_dump(queue_t *, mblk_t *);
-static upperstr_t *find_dest(upperstr_t *, int);
-#if defined(SOL2)
-static upperstr_t *find_promisc(upperstr_t *, int);
-static mblk_t *prepend_ether(upperstr_t *, mblk_t *, int);
-static mblk_t *prepend_udind(upperstr_t *, mblk_t *, int);
-static void promisc_sendup(upperstr_t *, mblk_t *, int, int);
-#endif /* defined(SOL2) */
-static int putctl2(queue_t *, int, int, int);
-static int putctl4(queue_t *, int, int, int);
-static int pass_packet(upperstr_t *ppa, mblk_t *mp, int outbound);
-#ifdef FILTER_PACKETS
-static int ip_hard_filter(upperstr_t *ppa, mblk_t *mp, int outbound);
-#endif /* FILTER_PACKETS */
-
-#define PPP_ID 0xb1a6
-static struct module_info ppp_info = {
-#ifdef PRIOQ
- PPP_ID, "ppp", 0, 512, 512, 384
-#else
- PPP_ID, "ppp", 0, 512, 512, 128
-#endif /* PRIOQ */
-};
-
-static struct qinit pppurint = {
- pppurput, pppursrv, pppopen, pppclose, NULL, &ppp_info, NULL
-};
-
-static struct qinit pppuwint = {
- pppuwput, pppuwsrv, NULL, NULL, NULL, &ppp_info, NULL
-};
-
-static struct qinit ppplrint = {
- ppplrput, ppplrsrv, NULL, NULL, NULL, &ppp_info, NULL
-};
-
-static struct qinit ppplwint = {
- ppplwput, ppplwsrv, NULL, NULL, NULL, &ppp_info, NULL
-};
-
-#ifdef LACHTCP
-extern struct ifstats *ifstats;
-int pppdevflag = 0;
-#endif
-
-struct streamtab pppinfo = {
- &pppurint, &pppuwint,
- &ppplrint, &ppplwint
-};
-
-int ppp_count;
-
-/*
- * How we maintain statistics.
- */
-#ifdef SOL2
-#define INCR_IPACKETS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++; \
- }
-#define INCR_IERRORS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++; \
- }
-#define INCR_OPACKETS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++; \
- }
-#define INCR_OERRORS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++; \
- }
-#endif
-
-#ifdef LACHTCP
-#define INCR_IPACKETS(ppa) ppa->ifstats.ifs_ipackets++;
-#define INCR_IERRORS(ppa) ppa->ifstats.ifs_ierrors++;
-#define INCR_OPACKETS(ppa) ppa->ifstats.ifs_opackets++;
-#define INCR_OERRORS(ppa) ppa->ifstats.ifs_oerrors++;
-#endif
-
-/*
- * STREAMS driver entry points.
- */
-static int
-#ifdef SVR4
-pppopen(q, devp, oflag, sflag, credp)
- queue_t *q;
- dev_t *devp;
- int oflag, sflag;
- cred_t *credp;
-#else
-pppopen(q, dev, oflag, sflag)
- queue_t *q;
- int dev; /* really dev_t */
- int oflag, sflag;
-#endif
-{
- upperstr_t *up;
- upperstr_t **prevp;
- minor_t mn;
-#ifdef PRIOQ
- u_short *ptr;
- u_char new_band;
-#endif /* PRIOQ */
-
- if (q->q_ptr)
- DRV_OPEN_OK(dev); /* device is already open */
-
-#ifdef PRIOQ
- /* Calculate max_bband & def_band from definitions in prioq.h
- This colud be done at some more approtiate time (less often)
- but this way it works well so I'll just leave it here */
-
- max_band = 1;
- def_band = 0;
- ptr = prioq_table;
- while (*ptr) {
- new_band = 1;
- while (*ptr)
- if (*ptr++ == IPPORT_DEFAULT) {
- new_band = 0;
- def_band = max_band;
- }
- max_band += new_band;
- ptr++;
- }
- if (def_band)
- def_band = max_band - def_band;
- --max_band;
-#endif /* PRIOQ */
-
- if (sflag == CLONEOPEN) {
- mn = 0;
- for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
- if (up->mn != mn)
- break;
- ++mn;
- }
- } else {
-#ifdef SVR4
- mn = getminor(*devp);
-#else
- mn = minor(dev);
-#endif
- for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
- if (up->mn >= mn)
- break;
- }
- if (up->mn == mn) {
- /* this can't happen */
- q->q_ptr = WR(q)->q_ptr = (caddr_t) up;
- DRV_OPEN_OK(dev);
- }
- }
-
- /*
- * Construct a new minor node.
- */
- up = (upperstr_t *) ALLOC_SLEEP(sizeof(upperstr_t));
- bzero((caddr_t) up, sizeof(upperstr_t));
- if (up == 0) {
- DPRINT("pppopen: out of kernel memory\n");
- OPEN_ERROR(ENXIO);
- }
- up->nextmn = *prevp;
- *prevp = up;
- up->mn = mn;
-#ifdef SVR4
- *devp = makedevice(getmajor(*devp), mn);
-#endif
- up->q = q;
- if (NOTSUSER() == 0)
- up->flags |= US_PRIV;
-#ifndef NO_DLPI
- up->state = DL_UNATTACHED;
-#endif
-#ifdef LACHTCP
- up->ifflags = IFF_UP | IFF_POINTOPOINT;
-#endif
- up->sap = -1;
- up->last_sent = up->last_recv = time;
- up->npmode = NPMODE_DROP;
- q->q_ptr = (caddr_t) up;
- WR(q)->q_ptr = (caddr_t) up;
- noenable(WR(q));
-#ifdef SOL2
- mutex_init(&up->stats_lock, NULL, MUTEX_DRIVER, NULL);
-#endif
- ++ppp_count;
-
- qprocson(q);
- DRV_OPEN_OK(makedev(major(dev), mn));
-}
-
-static int
-#ifdef SVR4
-pppclose(q, flag, credp)
- queue_t *q;
- int flag;
- cred_t *credp;
-#else
-pppclose(q, flag)
- queue_t *q;
- int flag;
-#endif
-{
- upperstr_t *up, **upp;
- upperstr_t *as, *asnext;
- upperstr_t **prevp;
-
- qprocsoff(q);
-
- up = (upperstr_t *) q->q_ptr;
- if (up == 0) {
- DPRINT("pppclose: q_ptr = 0\n");
- return 0;
- }
- if (up->flags & US_DBGLOG)
- DPRINT2("ppp/%d: close, flags=%x\n", up->mn, up->flags);
- if (up->flags & US_CONTROL) {
-#ifdef LACHTCP
- struct ifstats *ifp, *pifp;
-#endif
- if (up->lowerq != 0) {
- /* Gack! the lower stream should have be unlinked earlier! */
- DPRINT1("ppp%d: lower stream still connected on close?\n",
- up->mn);
- LOCK_LOWER_W;
- up->lowerq->q_ptr = 0;
- RD(up->lowerq)->q_ptr = 0;
- up->lowerq = 0;
- UNLOCK_LOWER;
- }
-
- /*
- * This stream represents a PPA:
- * For all streams attached to the PPA, clear their
- * references to this PPA.
- * Then remove this PPA from the list of PPAs.
- */
- for (as = up->next; as != 0; as = asnext) {
- asnext = as->next;
- as->next = 0;
- as->ppa = 0;
- if (as->flags & US_BLOCKED) {
- as->flags &= ~US_BLOCKED;
- flushq(WR(as->q), FLUSHDATA);
- }
- }
- for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa)
- if (*upp == up) {
- *upp = up->nextppa;
- break;
- }
-#ifdef LACHTCP
- /* Remove the statistics from the active list. */
- for (ifp = ifstats, pifp = 0; ifp; ifp = ifp->ifs_next) {
- if (ifp == &up->ifstats) {
- if (pifp)
- pifp->ifs_next = ifp->ifs_next;
- else
- ifstats = ifp->ifs_next;
- break;
- }
- pifp = ifp;
- }
-#endif
- } else {
- /*
- * If this stream is attached to a PPA,
- * remove it from the PPA's list.
- */
- if ((as = up->ppa) != 0) {
- for (; as->next != 0; as = as->next)
- if (as->next == up) {
- as->next = up->next;
- break;
- }
- }
- }
-
-#ifdef SOL2
- if (up->kstats)
- kstat_delete(up->kstats);
- mutex_destroy(&up->stats_lock);
-#endif
-
- q->q_ptr = NULL;
- WR(q)->q_ptr = NULL;
-
- for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) {
- if (*prevp == up) {
- *prevp = up->nextmn;
- break;
- }
- }
- FREE(up, sizeof(upperstr_t));
- --ppp_count;
-
- return 0;
-}
-
-/*
- * A message from on high. We do one of three things:
- * - qreply()
- * - put the message on the lower write stream
- * - queue it for our service routine
- */
-static int
-pppuwput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *ppa, *nps;
- struct iocblk *iop;
- struct linkblk *lb;
-#ifdef LACHTCP
- struct ifreq *ifr;
- int i;
-#endif
- queue_t *lq;
- int error, n, sap;
- mblk_t *mq;
- struct ppp_idle *pip;
-#ifdef PRIOQ
- queue_t *tlq;
-#endif /* PRIOQ */
-#ifdef NO_DLPI
- upperstr_t *os;
-#endif
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("pppuwput: q_ptr = 0!\n");
- return 0;
- }
- if (mp == 0) {
- DPRINT1("pppuwput/%d: mp = 0!\n", us->mn);
- return 0;
- }
- if (mp->b_datap == 0) {
- DPRINT1("pppuwput/%d: mp->b_datap = 0!\n", us->mn);
- return 0;
- }
- switch (mp->b_datap->db_type) {
-#ifndef NO_DLPI
- case M_PCPROTO:
- case M_PROTO:
- dlpi_request(q, mp, us);
- break;
-#endif /* NO_DLPI */
-
- case M_DATA:
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: uwput M_DATA len=%d flags=%x\n",
- us->mn, msgdsize(mp), us->flags);
- if (us->ppa == 0 || msgdsize(mp) > us->ppa->mtu + PPP_HDRLEN
-#ifndef NO_DLPI
- || (us->flags & US_CONTROL) == 0
-#endif /* NO_DLPI */
- ) {
- DPRINT1("pppuwput: junk data len=%d\n", msgdsize(mp));
- freemsg(mp);
- break;
- }
-#ifdef NO_DLPI
- if ((us->flags & US_CONTROL) == 0 && !pass_packet(us, mp, 1))
- break;
-#endif
- if (!send_data(mp, us))
- putq(q, mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: ioctl %x count=%d\n",
- us->mn, iop->ioc_cmd, iop->ioc_count);
- switch (iop->ioc_cmd) {
-#if defined(SOL2)
- case DLIOCRAW: /* raw M_DATA mode */
- us->flags |= US_RAWDATA;
- error = 0;
- break;
-#endif /* defined(SOL2) */
- case I_LINK:
- if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl I_LINK b_cont = 0!\n", us->mn);
- break;
- }
- lb = (struct linkblk *) mp->b_cont->b_rptr;
- lq = lb->l_qbot;
- if (lq == 0) {
- DPRINT1("pppuwput/%d: ioctl I_LINK l_qbot = 0!\n", us->mn);
- break;
- }
- LOCK_LOWER_W;
- us->lowerq = lq;
- lq->q_ptr = (caddr_t) q;
- RD(lq)->q_ptr = (caddr_t) us->q;
- UNLOCK_LOWER;
- iop->ioc_count = 0;
- error = 0;
- us->flags &= ~US_LASTMOD;
- /* Unblock upper streams which now feed this lower stream. */
- qenable(q);
- /* Send useful information down to the modules which
- are now linked below us. */
- putctl2(lq, M_CTL, PPPCTL_UNIT, us->ppa_id);
- putctl4(lq, M_CTL, PPPCTL_MRU, us->mru);
- putctl4(lq, M_CTL, PPPCTL_MTU, us->mtu);
-#ifdef PRIOQ
- /* Lower tty driver's queue hiwat/lowat from default 4096/128
- to 256/128 since we don't want queueing of data on
- output to physical device */
-
- freezestr(lq);
- for (tlq = lq; tlq->q_next != NULL; tlq = tlq->q_next)
- ;
- strqset(tlq, QHIWAT, 0, 256);
- strqset(tlq, QLOWAT, 0, 128);
- unfreezestr(lq);
-#endif /* PRIOQ */
- break;
-
- case I_UNLINK:
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl I_UNLINK b_cont = 0!\n", us->mn);
- break;
- }
- lb = (struct linkblk *) mp->b_cont->b_rptr;
-#if DEBUG
- if (us->lowerq != lb->l_qbot) {
- DPRINT2("ppp unlink: lowerq=%x qbot=%x\n",
- us->lowerq, lb->l_qbot);
- break;
- }
-#endif
- iop->ioc_count = 0;
- qwriter(q, mp, detach_lower, PERIM_OUTER);
- error = -1;
- break;
-
- case PPPIO_NEWPPA:
- if (us->flags & US_CONTROL)
- break;
- if ((us->flags & US_PRIV) == 0) {
- error = EPERM;
- break;
- }
- /* Arrange to return an int */
- if ((mq = mp->b_cont) == 0
- || mq->b_datap->db_lim - mq->b_rptr < sizeof(int)) {
- mq = allocb(sizeof(int), BPRI_HI);
- if (mq == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = mq;
- mq->b_cont = 0;
- }
- iop->ioc_count = sizeof(int);
- mq->b_wptr = mq->b_rptr + sizeof(int);
- qwriter(q, mp, new_ppa, PERIM_OUTER);
- error = -1;
- break;
-
- case PPPIO_ATTACH:
- /* like dlpi_attach, for programs which can't write to
- the stream (like pppstats) */
- if (iop->ioc_count != sizeof(int) || us->ppa != 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_ATTACH b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
- if (ppa->ppa_id == n)
- break;
- if (ppa == 0)
- break;
- us->ppa = ppa;
- iop->ioc_count = 0;
- qwriter(q, mp, attach_ppa, PERIM_OUTER);
- error = -1;
- break;
-
-#ifdef NO_DLPI
- case PPPIO_BIND:
- /* Attach to a given SAP. */
- if (iop->ioc_count != sizeof(int) || us->ppa == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_BIND b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- /* n must be a valid PPP network protocol number. */
- if (n < 0x21 || n > 0x3fff || (n & 0x101) != 1)
- break;
- /* check that no other stream is bound to this sap already. */
- for (os = us->ppa; os != 0; os = os->next)
- if (os->sap == n)
- break;
- if (os != 0)
- break;
- us->sap = n;
- iop->ioc_count = 0;
- error = 0;
- break;
-#endif /* NO_DLPI */
-
- case PPPIO_MRU:
- if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_MRU b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n <= 0 || n > PPP_MAXMRU)
- break;
- if (n < PPP_MRU)
- n = PPP_MRU;
- us->mru = n;
- if (us->lowerq)
- putctl4(us->lowerq, M_CTL, PPPCTL_MRU, n);
- error = 0;
- iop->ioc_count = 0;
- break;
-
- case PPPIO_MTU:
- if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_MTU b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n <= 0 || n > PPP_MAXMTU)
- break;
- us->mtu = n;
-#ifdef LACHTCP
- /* The MTU reported in netstat, not used as IP max packet size! */
- us->ifstats.ifs_mtu = n;
-#endif
- if (us->lowerq)
- putctl4(us->lowerq, M_CTL, PPPCTL_MTU, n);
- error = 0;
- iop->ioc_count = 0;
- break;
-
- case PPPIO_LASTMOD:
- us->flags |= US_LASTMOD;
- error = 0;
- break;
-
- case PPPIO_DEBUG:
- if (iop->ioc_count != sizeof(int))
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_DEBUG b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
- qwriter(q, NULL, debug_dump, PERIM_OUTER);
- iop->ioc_count = 0;
- error = -1;
- } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) {
- DPRINT1("ppp/%d: debug log enabled\n", us->mn);
- us->flags |= US_DBGLOG;
- iop->ioc_count = 0;
- error = 0;
- } else {
- if (us->ppa == 0 || us->ppa->lowerq == 0)
- break;
- putnext(us->ppa->lowerq, mp);
- error = -1;
- }
- break;
-
- case PPPIO_NPMODE:
- if (iop->ioc_count != 2 * sizeof(int))
- break;
- if ((us->flags & US_CONTROL) == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_NPMODE b_cont = 0!\n", us->mn);
- break;
- }
- sap = ((int *)mp->b_cont->b_rptr)[0];
- for (nps = us->next; nps != 0; nps = nps->next) {
- if (us->flags & US_DBGLOG)
- DPRINT2("us = 0x%x, us->next->sap = 0x%x\n", nps, nps->sap);
- if (nps->sap == sap)
- break;
- }
- if (nps == 0) {
- if (us->flags & US_DBGLOG)
- DPRINT2("ppp/%d: no stream for sap %x\n", us->mn, sap);
- break;
- }
- /* XXX possibly should use qwriter here */
- nps->npmode = (enum NPmode) ((int *)mp->b_cont->b_rptr)[1];
- if (nps->npmode != NPMODE_QUEUE && (nps->flags & US_BLOCKED) != 0)
- qenable(WR(nps->q));
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case PPPIO_GIDLE:
- if ((ppa = us->ppa) == 0)
- break;
- mq = allocb(sizeof(struct ppp_idle), BPRI_HI);
- if (mq == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = mq;
- mq->b_cont = 0;
- pip = (struct ppp_idle *) mq->b_wptr;
- pip->xmit_idle = time - ppa->last_sent;
- pip->recv_idle = time - ppa->last_recv;
- mq->b_wptr += sizeof(struct ppp_idle);
- iop->ioc_count = sizeof(struct ppp_idle);
- error = 0;
- break;
-
-#ifdef LACHTCP
- case SIOCSIFNAME:
- /* Sent from IP down to us. Attach the ifstats structure. */
- if (iop->ioc_count != sizeof(struct ifreq) || us->ppa == 0)
- break;
- ifr = (struct ifreq *)mp->b_cont->b_rptr;
- /* Find the unit number in the interface name. */
- for (i = 0; i < IFNAMSIZ; i++) {
- if (ifr->ifr_name[i] == 0 ||
- (ifr->ifr_name[i] >= '0' &&
- ifr->ifr_name[i] <= '9'))
- break;
- else
- us->ifname[i] = ifr->ifr_name[i];
- }
- us->ifname[i] = 0;
-
- /* Convert the unit number to binary. */
- for (n = 0; i < IFNAMSIZ; i++) {
- if (ifr->ifr_name[i] == 0) {
- break;
- }
- else {
- n = n * 10 + ifr->ifr_name[i] - '0';
- }
- }
-
- /* Verify the ppa. */
- if (us->ppa->ppa_id != n)
- break;
- ppa = us->ppa;
-
- /* Set up the netstat block. */
- strncpy (ppa->ifname, us->ifname, IFNAMSIZ);
-
- ppa->ifstats.ifs_name = ppa->ifname;
- ppa->ifstats.ifs_unit = n;
- ppa->ifstats.ifs_active = us->state != DL_UNBOUND;
- ppa->ifstats.ifs_mtu = ppa->mtu;
-
- /* Link in statistics used by netstat. */
- ppa->ifstats.ifs_next = ifstats;
- ifstats = &ppa->ifstats;
-
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case SIOCGIFFLAGS:
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- ((struct iocblk_in *)iop)->ioc_ifflags = us->ifflags;
- error = 0;
- break;
-
- case SIOCSIFFLAGS:
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- us->ifflags = ((struct iocblk_in *)iop)->ioc_ifflags;
- error = 0;
- break;
-
- case SIOCSIFADDR:
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- us->ifflags |= IFF_RUNNING;
- ((struct iocblk_in *)iop)->ioc_ifflags |= IFF_RUNNING;
- error = 0;
- break;
-
- case SIOCSIFMTU:
- /*
- * Vanilla SVR4 systems don't handle SIOCSIFMTU, rather
- * they take the MTU from the DL_INFO_ACK we sent in response
- * to their DL_INFO_REQ. Fortunately, they will update the
- * MTU if we send an unsolicited DL_INFO_ACK up.
- */
- if ((mq = allocb(sizeof(dl_info_req_t), BPRI_HI)) == 0)
- break; /* should do bufcall */
- ((union DL_primitives *)mq->b_rptr)->dl_primitive = DL_INFO_REQ;
- mq->b_wptr = mq->b_rptr + sizeof(dl_info_req_t);
- dlpi_request(q, mq, us);
- error = 0;
- break;
-
- case SIOCGIFNETMASK:
- case SIOCSIFNETMASK:
- case SIOCGIFADDR:
- case SIOCGIFDSTADDR:
- case SIOCSIFDSTADDR:
- case SIOCGIFMETRIC:
- error = 0;
- break;
-#endif /* LACHTCP */
-
- default:
- if (us->ppa == 0 || us->ppa->lowerq == 0)
- break;
- us->ioc_id = iop->ioc_id;
- error = -1;
- switch (iop->ioc_cmd) {
- case PPPIO_GETSTAT:
- case PPPIO_GETCSTAT:
- if (us->flags & US_LASTMOD) {
- error = EINVAL;
- break;
- }
- putnext(us->ppa->lowerq, mp);
- break;
- default:
- if (us->flags & US_PRIV)
- putnext(us->ppa->lowerq, mp);
- else {
- DPRINT1("ppp ioctl %x rejected\n", iop->ioc_cmd);
- error = EPERM;
- }
- break;
- }
- break;
- }
-
- if (error > 0) {
- iop->ioc_error = error;
- mp->b_datap->db_type = M_IOCNAK;
- qreply(q, mp);
- } else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- }
- break;
-
- case M_FLUSH:
- if (us->flags & US_DBGLOG)
- DPRINT2("ppp/%d: flush %x\n", us->mn, *mp->b_rptr);
- if (*mp->b_rptr & FLUSHW)
- flushq(q, FLUSHDATA);
- if (*mp->b_rptr & FLUSHR) {
- *mp->b_rptr &= ~FLUSHW;
- qreply(q, mp);
- } else
- freemsg(mp);
- break;
-
- default:
- freemsg(mp);
- break;
- }
- return 0;
-}
-
-#ifndef NO_DLPI
-static void
-dlpi_request(q, mp, us)
- queue_t *q;
- mblk_t *mp;
- upperstr_t *us;
-{
- union DL_primitives *d = (union DL_primitives *) mp->b_rptr;
- int size = mp->b_wptr - mp->b_rptr;
- mblk_t *reply, *np;
- upperstr_t *ppa, *os;
- int sap, len;
- dl_info_ack_t *info;
- dl_bind_ack_t *ackp;
-#if DL_CURRENT_VERSION >= 2
- dl_phys_addr_ack_t *paddrack;
- static struct ether_addr eaddr = {0};
-#endif
-
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: dlpi prim %x len=%d\n", us->mn,
- d->dl_primitive, size);
- switch (d->dl_primitive) {
- case DL_INFO_REQ:
- if (size < sizeof(dl_info_req_t))
- goto badprim;
- if ((reply = allocb(sizeof(dl_info_ack_t), BPRI_HI)) == 0)
- break; /* should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- info = (dl_info_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_info_ack_t);
- bzero((caddr_t) info, sizeof(dl_info_ack_t));
- info->dl_primitive = DL_INFO_ACK;
- info->dl_max_sdu = us->ppa? us->ppa->mtu: PPP_MAXMTU;
- info->dl_min_sdu = 1;
- info->dl_addr_length = sizeof(uint);
- info->dl_mac_type = DL_ETHER; /* a bigger lie */
- info->dl_current_state = us->state;
- info->dl_service_mode = DL_CLDLS;
- info->dl_provider_style = DL_STYLE2;
-#if DL_CURRENT_VERSION >= 2
- info->dl_sap_length = sizeof(uint);
- info->dl_version = DL_CURRENT_VERSION;
-#endif
- qreply(q, reply);
- break;
-
- case DL_ATTACH_REQ:
- if (size < sizeof(dl_attach_req_t))
- goto badprim;
- if (us->state != DL_UNATTACHED || us->ppa != 0) {
- dlpi_error(q, us, DL_ATTACH_REQ, DL_OUTSTATE, 0);
- break;
- }
- for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
- if (ppa->ppa_id == d->attach_req.dl_ppa)
- break;
- if (ppa == 0) {
- dlpi_error(q, us, DL_ATTACH_REQ, DL_BADPPA, 0);
- break;
- }
- us->ppa = ppa;
- qwriter(q, mp, attach_ppa, PERIM_OUTER);
- return;
-
- case DL_DETACH_REQ:
- if (size < sizeof(dl_detach_req_t))
- goto badprim;
- if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, us, DL_DETACH_REQ, DL_OUTSTATE, 0);
- break;
- }
- qwriter(q, mp, detach_ppa, PERIM_OUTER);
- return;
-
- case DL_BIND_REQ:
- if (size < sizeof(dl_bind_req_t))
- goto badprim;
- if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, us, DL_BIND_REQ, DL_OUTSTATE, 0);
- break;
- }
-#if 0
- /* apparently this test fails (unnecessarily?) on some systems */
- if (d->bind_req.dl_service_mode != DL_CLDLS) {
- dlpi_error(q, us, DL_BIND_REQ, DL_UNSUPPORTED, 0);
- break;
- }
-#endif
-
- /* saps must be valid PPP network protocol numbers,
- except that we accept ETHERTYPE_IP in place of PPP_IP. */
- sap = d->bind_req.dl_sap;
- us->req_sap = sap;
-
-#if defined(SOL2)
- if (us->flags & US_DBGLOG)
- DPRINT2("DL_BIND_REQ: ip gives sap = 0x%x, us = 0x%x", sap, us);
-
- if (sap == ETHERTYPE_IP) /* normal IFF_IPV4 */
- sap = PPP_IP;
- else if (sap == ETHERTYPE_IPV6) /* when IFF_IPV6 is set */
- sap = PPP_IPV6;
- else if (sap == ETHERTYPE_ALLSAP) /* snoop gives sap of 0 */
- sap = PPP_ALLSAP;
- else {
- DPRINT2("DL_BIND_REQ: unrecognized sap = 0x%x, us = 0x%x", sap, us);
- dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
- break;
- }
-#else
- if (sap == ETHERTYPE_IP)
- sap = PPP_IP;
- if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
- dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
- break;
- }
-#endif /* defined(SOL2) */
-
- /* check that no other stream is bound to this sap already. */
- for (os = us->ppa; os != 0; os = os->next)
- if (os->sap == sap)
- break;
- if (os != 0) {
- dlpi_error(q, us, DL_BIND_REQ, DL_NOADDR, 0);
- break;
- }
-
- us->sap = sap;
- us->state = DL_IDLE;
-
- if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(uint),
- BPRI_HI)) == 0)
- break; /* should do bufcall */
- ackp = (dl_bind_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_bind_ack_t) + sizeof(uint);
- reply->b_datap->db_type = M_PCPROTO;
- bzero((caddr_t) ackp, sizeof(dl_bind_ack_t));
- ackp->dl_primitive = DL_BIND_ACK;
- ackp->dl_sap = sap;
- ackp->dl_addr_length = sizeof(uint);
- ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
- *(uint *)(ackp+1) = sap;
- qreply(q, reply);
- break;
-
- case DL_UNBIND_REQ:
- if (size < sizeof(dl_unbind_req_t))
- goto badprim;
- if (us->state != DL_IDLE) {
- dlpi_error(q, us, DL_UNBIND_REQ, DL_OUTSTATE, 0);
- break;
- }
- us->sap = -1;
- us->state = DL_UNBOUND;
-#ifdef LACHTCP
- us->ppa->ifstats.ifs_active = 0;
-#endif
- dlpi_ok(q, DL_UNBIND_REQ);
- break;
-
- case DL_UNITDATA_REQ:
- if (size < sizeof(dl_unitdata_req_t))
- goto badprim;
- if (us->state != DL_IDLE) {
- dlpi_error(q, us, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
- break;
- }
- if ((ppa = us->ppa) == 0) {
- cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n");
- break;
- }
- len = mp->b_cont == 0? 0: msgdsize(mp->b_cont);
- if (len > ppa->mtu) {
- DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
- break;
- }
-
-#if defined(SOL2)
- /*
- * Should there be any promiscuous stream(s), send the data
- * up for each promiscuous stream that we recognize.
- */
- if (mp->b_cont)
- promisc_sendup(ppa, mp->b_cont, us->sap, 0);
-#endif /* defined(SOL2) */
-
- mp->b_band = 0;
-#ifdef PRIOQ
- /* Extract s_port & d_port from IP-packet, the code is a bit
- dirty here, but so am I, too... */
- if (mp->b_datap->db_type == M_PROTO && us->sap == PPP_IP
- && mp->b_cont != 0) {
- u_char *bb, *tlh;
- int iphlen, len;
- u_short *ptr;
- u_char band_unset, cur_band, syn;
- u_short s_port, d_port;
-
- bb = mp->b_cont->b_rptr; /* bb points to IP-header*/
- len = mp->b_cont->b_wptr - mp->b_cont->b_rptr;
- syn = 0;
- s_port = IPPORT_DEFAULT;
- d_port = IPPORT_DEFAULT;
- if (len >= 20) { /* 20 = minimum length of IP header */
- iphlen = (bb[0] & 0x0f) * 4;
- tlh = bb + iphlen;
- len -= iphlen;
- switch (bb[9]) {
- case IPPROTO_TCP:
- if (len >= 20) { /* min length of TCP header */
- s_port = (tlh[0] << 8) + tlh[1];
- d_port = (tlh[2] << 8) + tlh[3];
- syn = tlh[13] & 0x02;
- }
- break;
- case IPPROTO_UDP:
- if (len >= 8) { /* min length of UDP header */
- s_port = (tlh[0] << 8) + tlh[1];
- d_port = (tlh[2] << 8) + tlh[3];
- }
- break;
- }
- }
-
- /*
- * Now calculate b_band for this packet from the
- * port-priority table.
- */
- ptr = prioq_table;
- cur_band = max_band;
- band_unset = 1;
- while (*ptr) {
- while (*ptr && band_unset)
- if (s_port == *ptr || d_port == *ptr++) {
- mp->b_band = cur_band;
- band_unset = 0;
- break;
- }
- ptr++;
- cur_band--;
- }
- if (band_unset)
- mp->b_band = def_band;
- /* It may be usable to urge SYN packets a bit */
- if (syn)
- mp->b_band++;
- }
-#endif /* PRIOQ */
- /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
- if (mp->b_datap->db_ref > 1) {
- np = allocb(PPP_HDRLEN, BPRI_HI);
- if (np == 0)
- break; /* gak! */
- np->b_cont = mp->b_cont;
- mp->b_cont = 0;
- freeb(mp);
- mp = np;
- } else
- mp->b_datap->db_type = M_DATA;
- /* XXX should use dl_dest_addr_offset/length here,
- but we would have to translate ETHERTYPE_IP -> PPP_IP */
- mp->b_wptr = mp->b_rptr + PPP_HDRLEN;
- mp->b_rptr[0] = PPP_ALLSTATIONS;
- mp->b_rptr[1] = PPP_UI;
- mp->b_rptr[2] = us->sap >> 8;
- mp->b_rptr[3] = us->sap;
- if (pass_packet(us, mp, 1)) {
- if (!send_data(mp, us))
- putq(q, mp);
- }
- return;
-
-#if DL_CURRENT_VERSION >= 2
- case DL_PHYS_ADDR_REQ:
- if (size < sizeof(dl_phys_addr_req_t))
- goto badprim;
-
- /*
- * Don't check state because ifconfig sends this one down too
- */
-
- if ((reply = allocb(sizeof(dl_phys_addr_ack_t)+ETHERADDRL,
- BPRI_HI)) == 0)
- break; /* should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- paddrack = (dl_phys_addr_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_phys_addr_ack_t);
- bzero((caddr_t) paddrack, sizeof(dl_phys_addr_ack_t)+ETHERADDRL);
- paddrack->dl_primitive = DL_PHYS_ADDR_ACK;
- paddrack->dl_addr_length = ETHERADDRL;
- paddrack->dl_addr_offset = sizeof(dl_phys_addr_ack_t);
- bcopy(&eaddr, reply->b_wptr, ETHERADDRL);
- reply->b_wptr += ETHERADDRL;
- qreply(q, reply);
- break;
-
-#if defined(SOL2)
- case DL_PROMISCON_REQ:
- if (size < sizeof(dl_promiscon_req_t))
- goto badprim;
- us->flags |= US_PROMISC;
- dlpi_ok(q, DL_PROMISCON_REQ);
- break;
-
- case DL_PROMISCOFF_REQ:
- if (size < sizeof(dl_promiscoff_req_t))
- goto badprim;
- us->flags &= ~US_PROMISC;
- dlpi_ok(q, DL_PROMISCOFF_REQ);
- break;
-#else
- case DL_PROMISCON_REQ: /* fall thru */
- case DL_PROMISCOFF_REQ: /* fall thru */
-#endif /* defined(SOL2) */
-#endif /* DL_CURRENT_VERSION >= 2 */
-
-#if DL_CURRENT_VERSION >= 2
- case DL_SET_PHYS_ADDR_REQ:
- case DL_SUBS_BIND_REQ:
- case DL_SUBS_UNBIND_REQ:
- case DL_ENABMULTI_REQ:
- case DL_DISABMULTI_REQ:
- case DL_XID_REQ:
- case DL_TEST_REQ:
- case DL_REPLY_UPDATE_REQ:
- case DL_REPLY_REQ:
- case DL_DATA_ACK_REQ:
-#endif
- case DL_CONNECT_REQ:
- case DL_TOKEN_REQ:
- dlpi_error(q, us, d->dl_primitive, DL_NOTSUPPORTED, 0);
- break;
-
- case DL_CONNECT_RES:
- case DL_DISCONNECT_REQ:
- case DL_RESET_REQ:
- case DL_RESET_RES:
- dlpi_error(q, us, d->dl_primitive, DL_OUTSTATE, 0);
- break;
-
- case DL_UDQOS_REQ:
- dlpi_error(q, us, d->dl_primitive, DL_BADQOSTYPE, 0);
- break;
-
-#if DL_CURRENT_VERSION >= 2
- case DL_TEST_RES:
- case DL_XID_RES:
- break;
-#endif
-
- default:
- cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
- /* fall through */
- badprim:
- dlpi_error(q, us, d->dl_primitive, DL_BADPRIM, 0);
- break;
- }
- freemsg(mp);
-}
-
-static void
-dlpi_error(q, us, prim, err, uerr)
- queue_t *q;
- upperstr_t *us;
- int prim, err, uerr;
-{
- mblk_t *reply;
- dl_error_ack_t *errp;
-
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: dlpi error, prim=%x, err=%x\n", us->mn, prim, err);
- reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
- if (reply == 0)
- return; /* XXX should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- errp = (dl_error_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_error_ack_t);
- errp->dl_primitive = DL_ERROR_ACK;
- errp->dl_error_primitive = prim;
- errp->dl_errno = err;
- errp->dl_unix_errno = uerr;
- qreply(q, reply);
-}
-
-static void
-dlpi_ok(q, prim)
- queue_t *q;
- int prim;
-{
- mblk_t *reply;
- dl_ok_ack_t *okp;
-
- reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);
- if (reply == 0)
- return; /* XXX should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- okp = (dl_ok_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_ok_ack_t);
- okp->dl_primitive = DL_OK_ACK;
- okp->dl_correct_primitive = prim;
- qreply(q, reply);
-}
-#endif /* NO_DLPI */
-
-static int
-pass_packet(us, mp, outbound)
- upperstr_t *us;
- mblk_t *mp;
- int outbound;
-{
- int pass;
- upperstr_t *ppa;
-
- if ((ppa = us->ppa) == 0) {
- freemsg(mp);
- return 0;
- }
-
-#ifdef FILTER_PACKETS
- pass = ip_hard_filter(us, mp, outbound);
-#else
- /*
- * Here is where we might, in future, decide whether to pass
- * or drop the packet, and whether it counts as link activity.
- */
- pass = 1;
-#endif /* FILTER_PACKETS */
-
- if (pass < 0) {
- /* pass only if link already up, and don't update time */
- if (ppa->lowerq == 0) {
- freemsg(mp);
- return 0;
- }
- pass = 1;
- } else if (pass) {
- if (outbound)
- ppa->last_sent = time;
- else
- ppa->last_recv = time;
- }
-
- return pass;
-}
-
-/*
- * We have some data to send down to the lower stream (or up the
- * control stream, if we don't have a lower stream attached).
- * Returns 1 if the message was dealt with, 0 if it wasn't able
- * to be sent on and should therefore be queued up.
- */
-static int
-send_data(mp, us)
- mblk_t *mp;
- upperstr_t *us;
-{
- upperstr_t *ppa;
-
- if ((us->flags & US_BLOCKED) || us->npmode == NPMODE_QUEUE)
- return 0;
- ppa = us->ppa;
- if (ppa == 0 || us->npmode == NPMODE_DROP || us->npmode == NPMODE_ERROR) {
- if (us->flags & US_DBGLOG)
- DPRINT2("ppp/%d: dropping pkt (npmode=%d)\n", us->mn, us->npmode);
- freemsg(mp);
- return 1;
- }
- if (ppa->lowerq == 0) {
- /* try to send it up the control stream */
- if (bcanputnext(ppa->q, mp->b_band)) {
- /*
- * The message seems to get corrupted for some reason if
- * we just send the message up as it is, so we send a copy.
- */
- mblk_t *np = copymsg(mp);
- freemsg(mp);
- if (np != 0)
- putnext(ppa->q, np);
- return 1;
- }
- } else {
- if (bcanputnext(ppa->lowerq, mp->b_band)) {
- MT_ENTER(&ppa->stats_lock);
- ppa->stats.ppp_opackets++;
- ppa->stats.ppp_obytes += msgdsize(mp);
-#ifdef INCR_OPACKETS
- INCR_OPACKETS(ppa);
-#endif
- MT_EXIT(&ppa->stats_lock);
- /*
- * The lower queue is only ever detached while holding an
- * exclusive lock on the whole driver. So we can be confident
- * that the lower queue is still there.
- */
- putnext(ppa->lowerq, mp);
- return 1;
- }
- }
- us->flags |= US_BLOCKED;
- return 0;
-}
-
-/*
- * Allocate a new PPA id and link this stream into the list of PPAs.
- * This procedure is called with an exclusive lock on all queues in
- * this driver.
- */
-static void
-new_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *up, **usp;
- int ppa_id;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("new_ppa: q_ptr = 0!\n");
- return;
- }
-
- usp = &ppas;
- ppa_id = 0;
- while ((up = *usp) != 0 && ppa_id == up->ppa_id) {
- ++ppa_id;
- usp = &up->nextppa;
- }
- us->ppa_id = ppa_id;
- us->ppa = us;
- us->next = 0;
- us->nextppa = *usp;
- *usp = us;
- us->flags |= US_CONTROL;
- us->npmode = NPMODE_PASS;
-
- us->mtu = PPP_MTU;
- us->mru = PPP_MRU;
-
-#ifdef SOL2
- /*
- * Create a kstats record for our statistics, so netstat -i works.
- */
- if (us->kstats == 0) {
- char unit[32];
-
- sprintf(unit, "ppp%d", us->ppa->ppa_id);
- us->kstats = kstat_create("ppp", us->ppa->ppa_id, unit,
- "net", KSTAT_TYPE_NAMED, 4, 0);
- if (us->kstats != 0) {
- kstat_named_t *kn = KSTAT_NAMED_PTR(us->kstats);
-
- strcpy(kn[0].name, "ipackets");
- kn[0].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[1].name, "ierrors");
- kn[1].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[2].name, "opackets");
- kn[2].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[3].name, "oerrors");
- kn[3].data_type = KSTAT_DATA_ULONG;
- kstat_install(us->kstats);
- }
- }
-#endif /* SOL2 */
-
- *(int *)mp->b_cont->b_rptr = ppa_id;
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
-}
-
-static void
-attach_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *t;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("attach_ppa: q_ptr = 0!\n");
- return;
- }
-
-#ifndef NO_DLPI
- us->state = DL_UNBOUND;
-#endif
- for (t = us->ppa; t->next != 0; t = t->next)
- ;
- t->next = us;
- us->next = 0;
- if (mp->b_datap->db_type == M_IOCTL) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
-#ifndef NO_DLPI
- dlpi_ok(q, DL_ATTACH_REQ);
-#endif
- }
-}
-
-static void
-detach_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *t;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("detach_ppa: q_ptr = 0!\n");
- return;
- }
-
- for (t = us->ppa; t->next != 0; t = t->next)
- if (t->next == us) {
- t->next = us->next;
- break;
- }
- us->next = 0;
- us->ppa = 0;
-#ifndef NO_DLPI
- us->state = DL_UNATTACHED;
- dlpi_ok(q, DL_DETACH_REQ);
-#endif
-}
-
-/*
- * We call this with qwriter in order to give the upper queue procedures
- * the guarantee that the lower queue is not going to go away while
- * they are executing.
- */
-static void
-detach_lower(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("detach_lower: q_ptr = 0!\n");
- return;
- }
-
- LOCK_LOWER_W;
- us->lowerq->q_ptr = 0;
- RD(us->lowerq)->q_ptr = 0;
- us->lowerq = 0;
- UNLOCK_LOWER;
-
- /* Unblock streams which now feed back up the control stream. */
- qenable(us->q);
-
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
-}
-
-static int
-pppuwsrv(q)
- queue_t *q;
-{
- upperstr_t *us, *as;
- mblk_t *mp;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("pppuwsrv: q_ptr = 0!\n");
- return 0;
- }
-
- /*
- * If this is a control stream, then this service procedure
- * probably got enabled because of flow control in the lower
- * stream being enabled (or because of the lower stream going
- * away). Therefore we enable the service procedure of all
- * attached upper streams.
- */
- if (us->flags & US_CONTROL) {
- for (as = us->next; as != 0; as = as->next)
- qenable(WR(as->q));
- }
-
- /* Try to send on any data queued here. */
- us->flags &= ~US_BLOCKED;
- while ((mp = getq(q)) != 0) {
- if (!send_data(mp, us)) {
- putbq(q, mp);
- break;
- }
- }
-
- return 0;
-}
-
-/* should never get called... */
-static int
-ppplwput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- putnext(q, mp);
- return 0;
-}
-
-static int
-ppplwsrv(q)
- queue_t *q;
-{
- queue_t *uq;
-
- /*
- * Flow control has back-enabled this stream:
- * enable the upper write service procedure for
- * the upper control stream for this lower stream.
- */
- LOCK_LOWER_R;
- uq = (queue_t *) q->q_ptr;
- if (uq != 0)
- qenable(uq);
- UNLOCK_LOWER;
- return 0;
-}
-
-/*
- * This should only get called for control streams.
- */
-static int
-pppurput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *ppa, *us;
- int proto, len;
- struct iocblk *iop;
-
- ppa = (upperstr_t *) q->q_ptr;
- if (ppa == 0) {
- DPRINT("pppurput: q_ptr = 0!\n");
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
- case M_CTL:
- MT_ENTER(&ppa->stats_lock);
- switch (*mp->b_rptr) {
- case PPPCTL_IERROR:
-#ifdef INCR_IERRORS
- INCR_IERRORS(ppa);
-#endif
- ppa->stats.ppp_ierrors++;
- break;
- case PPPCTL_OERROR:
-#ifdef INCR_OERRORS
- INCR_OERRORS(ppa);
-#endif
- ppa->stats.ppp_oerrors++;
- break;
- }
- MT_EXIT(&ppa->stats_lock);
- freemsg(mp);
- break;
-
- case M_IOCACK:
- case M_IOCNAK:
- /*
- * Attempt to match up the response with the stream
- * that the request came from.
- */
- iop = (struct iocblk *) mp->b_rptr;
- for (us = ppa; us != 0; us = us->next)
- if (us->ioc_id == iop->ioc_id)
- break;
- if (us == 0)
- freemsg(mp);
- else
- putnext(us->q, mp);
- break;
-
- case M_HANGUP:
- /*
- * The serial device has hung up. We don't want to send
- * the M_HANGUP message up to pppd because that will stop
- * us from using the control stream any more. Instead we
- * send a zero-length message as an end-of-file indication.
- */
- freemsg(mp);
- mp = allocb(1, BPRI_HI);
- if (mp == 0) {
- DPRINT1("ppp/%d: couldn't allocate eof message!\n", ppa->mn);
- break;
- }
- putnext(ppa->q, mp);
- break;
-
- default:
- if (mp->b_datap->db_type == M_DATA) {
- len = msgdsize(mp);
- if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
- PULLUP(mp, PPP_HDRLEN);
- if (mp == 0) {
- DPRINT1("ppp_urput: msgpullup failed (len=%d)\n", len);
- break;
- }
- }
- MT_ENTER(&ppa->stats_lock);
- ppa->stats.ppp_ipackets++;
- ppa->stats.ppp_ibytes += len;
-#ifdef INCR_IPACKETS
- INCR_IPACKETS(ppa);
-#endif
- MT_EXIT(&ppa->stats_lock);
-
- proto = PPP_PROTOCOL(mp->b_rptr);
-
-#if defined(SOL2)
- /*
- * Should there be any promiscuous stream(s), send the data
- * up for each promiscuous stream that we recognize.
- */
- promisc_sendup(ppa, mp, proto, 1);
-#endif /* defined(SOL2) */
-
- if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
- /*
- * A data packet for some network protocol.
- * Queue it on the upper stream for that protocol.
- * XXX could we just putnext it? (would require thought)
- * The rblocked flag is there to ensure that we keep
- * messages in order for each network protocol.
- */
- if (!pass_packet(us, mp, 0))
- break;
- if (!us->rblocked && !canput(us->q))
- us->rblocked = 1;
- if (!us->rblocked)
- putq(us->q, mp);
- else
- putq(q, mp);
- break;
- }
- }
- /*
- * A control frame, a frame for an unknown protocol,
- * or some other message type.
- * Send it up to pppd via the control stream.
- */
- if (queclass(mp) == QPCTL || canputnext(ppa->q))
- putnext(ppa->q, mp);
- else
- putq(q, mp);
- break;
- }
-
- return 0;
-}
-
-static int
-pppursrv(q)
- queue_t *q;
-{
- upperstr_t *us, *as;
- mblk_t *mp, *hdr;
-#ifndef NO_DLPI
- dl_unitdata_ind_t *ud;
-#endif
- int proto;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("pppursrv: q_ptr = 0!\n");
- return 0;
- }
-
- if (us->flags & US_CONTROL) {
- /*
- * A control stream.
- * If there is no lower queue attached, run the write service
- * routines of other upper streams attached to this PPA.
- */
- if (us->lowerq == 0) {
- as = us;
- do {
- if (as->flags & US_BLOCKED)
- qenable(WR(as->q));
- as = as->next;
- } while (as != 0);
- }
-
- /*
- * Messages get queued on this stream's read queue if they
- * can't be queued on the read queue of the attached stream
- * that they are destined for. This is for flow control -
- * when this queue fills up, the lower read put procedure will
- * queue messages there and the flow control will propagate
- * down from there.
- */
- while ((mp = getq(q)) != 0) {
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto < 0x8000 && (as = find_dest(us, proto)) != 0) {
- if (!canput(as->q))
- break;
- putq(as->q, mp);
- } else {
- if (!canputnext(q))
- break;
- putnext(q, mp);
- }
- }
- if (mp) {
- putbq(q, mp);
- } else {
- /* can now put stuff directly on network protocol streams again */
- for (as = us->next; as != 0; as = as->next)
- as->rblocked = 0;
- }
-
- /*
- * If this stream has a lower stream attached,
- * enable the read queue's service routine.
- * XXX we should really only do this if the queue length
- * has dropped below the low-water mark.
- */
- if (us->lowerq != 0)
- qenable(RD(us->lowerq));
-
- } else {
- /*
- * A network protocol stream. Put a DLPI header on each
- * packet and send it on.
- * (Actually, it seems that the IP module will happily
- * accept M_DATA messages without the DL_UNITDATA_IND header.)
- */
- while ((mp = getq(q)) != 0) {
- if (!canputnext(q)) {
- putbq(q, mp);
- break;
- }
-#ifndef NO_DLPI
- proto = PPP_PROTOCOL(mp->b_rptr);
- mp->b_rptr += PPP_HDRLEN;
- hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint),
- BPRI_MED);
- if (hdr == 0) {
- /* XXX should put it back and use bufcall */
- freemsg(mp);
- continue;
- }
- hdr->b_datap->db_type = M_PROTO;
- ud = (dl_unitdata_ind_t *) hdr->b_wptr;
- hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint);
- hdr->b_cont = mp;
- ud->dl_primitive = DL_UNITDATA_IND;
- ud->dl_dest_addr_length = sizeof(uint);
- ud->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
- ud->dl_src_addr_length = sizeof(uint);
- ud->dl_src_addr_offset = ud->dl_dest_addr_offset + sizeof(uint);
-#if DL_CURRENT_VERSION >= 2
- ud->dl_group_address = 0;
-#endif
- /* Send the DLPI client the data with the SAP they requested,
- (e.g. ETHERTYPE_IP) rather than the PPP protocol number
- (e.g. PPP_IP) */
- ((uint *)(ud + 1))[0] = us->req_sap; /* dest SAP */
- ((uint *)(ud + 1))[1] = us->req_sap; /* src SAP */
- putnext(q, hdr);
-#else /* NO_DLPI */
- putnext(q, mp);
-#endif /* NO_DLPI */
- }
- /*
- * Now that we have consumed some packets from this queue,
- * enable the control stream's read service routine so that we
- * can process any packets for us that might have got queued
- * there for flow control reasons.
- */
- if (us->ppa)
- qenable(us->ppa->q);
- }
-
- return 0;
-}
-
-static upperstr_t *
-find_dest(ppa, proto)
- upperstr_t *ppa;
- int proto;
-{
- upperstr_t *us;
-
- for (us = ppa->next; us != 0; us = us->next)
- if (proto == us->sap)
- break;
- return us;
-}
-
-#if defined (SOL2)
-/*
- * Test upstream promiscuous conditions. As of now, only pass IPv4 and
- * Ipv6 packets upstream (let PPP packets be decoded elsewhere).
- */
-static upperstr_t *
-find_promisc(us, proto)
- upperstr_t *us;
- int proto;
-{
-
- if ((proto != PPP_IP) && (proto != PPP_IPV6))
- return (upperstr_t *)0;
-
- for ( ; us; us = us->next) {
- if ((us->flags & US_PROMISC) && (us->state == DL_IDLE))
- return us;
- }
-
- return (upperstr_t *)0;
-}
-
-/*
- * Prepend an empty Ethernet header to msg for snoop, et al.
- */
-static mblk_t *
-prepend_ether(us, mp, proto)
- upperstr_t *us;
- mblk_t *mp;
- int proto;
-{
- mblk_t *eh;
- int type;
-
- if ((eh = allocb(sizeof(struct ether_header), BPRI_HI)) == 0) {
- freemsg(mp);
- return (mblk_t *)0;
- }
-
- if (proto == PPP_IP)
- type = ETHERTYPE_IP;
- else if (proto == PPP_IPV6)
- type = ETHERTYPE_IPV6;
- else
- type = proto; /* What else? Let decoder decide */
-
- eh->b_wptr += sizeof(struct ether_header);
- bzero((caddr_t)eh->b_rptr, sizeof(struct ether_header));
- ((struct ether_header *)eh->b_rptr)->ether_type = htons((short)type);
- eh->b_cont = mp;
- return (eh);
-}
-
-/*
- * Prepend DL_UNITDATA_IND mblk to msg
- */
-static mblk_t *
-prepend_udind(us, mp, proto)
- upperstr_t *us;
- mblk_t *mp;
- int proto;
-{
- dl_unitdata_ind_t *dlu;
- mblk_t *dh;
- size_t size;
-
- size = sizeof(dl_unitdata_ind_t);
- if ((dh = allocb(size, BPRI_MED)) == 0) {
- freemsg(mp);
- return (mblk_t *)0;
- }
-
- dh->b_datap->db_type = M_PROTO;
- dh->b_wptr = dh->b_datap->db_lim;
- dh->b_rptr = dh->b_wptr - size;
-
- dlu = (dl_unitdata_ind_t *)dh->b_rptr;
- dlu->dl_primitive = DL_UNITDATA_IND;
- dlu->dl_dest_addr_length = 0;
- dlu->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
- dlu->dl_src_addr_length = 0;
- dlu->dl_src_addr_offset = sizeof(dl_unitdata_ind_t);
- dlu->dl_group_address = 0;
-
- dh->b_cont = mp;
- return (dh);
-}
-
-/*
- * For any recognized promiscuous streams, send data upstream
- */
-static void
-promisc_sendup(ppa, mp, proto, skip)
- upperstr_t *ppa;
- mblk_t *mp;
- int proto, skip;
-{
- mblk_t *dup_mp, *dup_dup_mp;
- upperstr_t *prus, *nprus;
-
- if ((prus = find_promisc(ppa, proto)) != 0) {
- if (dup_mp = dupmsg(mp)) {
-
- if (skip)
- dup_mp->b_rptr += PPP_HDRLEN;
-
- for ( ; nprus = find_promisc(prus->next, proto);
- prus = nprus) {
-
- if (dup_dup_mp = dupmsg(dup_mp)) {
- if (canputnext(prus->q)) {
- if (prus->flags & US_RAWDATA) {
- dup_dup_mp = prepend_ether(prus, dup_dup_mp, proto);
- putnext(prus->q, dup_dup_mp);
- } else {
- dup_dup_mp = prepend_udind(prus, dup_dup_mp, proto);
- putnext(prus->q, dup_dup_mp);
- }
- } else {
- DPRINT("ppp_urput: data to promisc q dropped\n");
- freemsg(dup_dup_mp);
- }
- }
- }
-
- if (canputnext(prus->q)) {
- if (prus->flags & US_RAWDATA) {
- dup_mp = prepend_ether(prus, dup_mp, proto);
- putnext(prus->q, dup_mp);
- } else {
- dup_mp = prepend_udind(prus, dup_mp, proto);
- putnext(prus->q, dup_mp);
- }
- } else {
- DPRINT("ppp_urput: data to promisc q dropped\n");
- freemsg(dup_mp);
- }
- }
- }
-}
-#endif /* defined(SOL2) */
-
-/*
- * We simply put the message on to the associated upper control stream
- * (either here or in ppplrsrv). That way we enter the perimeters
- * before looking through the list of attached streams to decide which
- * stream it should go up.
- */
-static int
-ppplrput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- queue_t *uq;
- struct iocblk *iop;
-
- switch (mp->b_datap->db_type) {
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- iop->ioc_error = EINVAL;
- mp->b_datap->db_type = M_IOCNAK;
- qreply(q, mp);
- return 0;
- case M_FLUSH:
- if (*mp->b_rptr & FLUSHR)
- flushq(q, FLUSHDATA);
- if (*mp->b_rptr & FLUSHW) {
- *mp->b_rptr &= ~FLUSHR;
- qreply(q, mp);
- } else
- freemsg(mp);
- return 0;
- }
-
- /*
- * If we can't get the lower lock straight away, queue this one
- * rather than blocking, to avoid the possibility of deadlock.
- */
- if (!TRYLOCK_LOWER_R) {
- putq(q, mp);
- return 0;
- }
-
- /*
- * Check that we're still connected to the driver.
- */
- uq = (queue_t *) q->q_ptr;
- if (uq == 0) {
- UNLOCK_LOWER;
- DPRINT1("ppplrput: q = %x, uq = 0??\n", q);
- freemsg(mp);
- return 0;
- }
-
- /*
- * Try to forward the message to the put routine for the upper
- * control stream for this lower stream.
- * If there are already messages queued here, queue this one so
- * they don't get out of order.
- */
- if (queclass(mp) == QPCTL || (qsize(q) == 0 && canput(uq)))
- put(uq, mp);
- else
- putq(q, mp);
-
- UNLOCK_LOWER;
- return 0;
-}
-
-static int
-ppplrsrv(q)
- queue_t *q;
-{
- mblk_t *mp;
- queue_t *uq;
-
- /*
- * Packets get queued here for flow control reasons
- * or if the lrput routine couldn't get the lower lock
- * without blocking.
- */
- LOCK_LOWER_R;
- uq = (queue_t *) q->q_ptr;
- if (uq == 0) {
- UNLOCK_LOWER;
- flushq(q, FLUSHALL);
- DPRINT1("ppplrsrv: q = %x, uq = 0??\n", q);
- return 0;
- }
- while ((mp = getq(q)) != 0) {
- if (queclass(mp) == QPCTL || canput(uq))
- put(uq, mp);
- else {
- putbq(q, mp);
- break;
- }
- }
- UNLOCK_LOWER;
- return 0;
-}
-
-static int
-putctl2(q, type, code, val)
- queue_t *q;
- int type, code, val;
-{
- mblk_t *mp;
-
- mp = allocb(2, BPRI_HI);
- if (mp == 0)
- return 0;
- mp->b_datap->db_type = type;
- mp->b_wptr[0] = code;
- mp->b_wptr[1] = val;
- mp->b_wptr += 2;
- putnext(q, mp);
- return 1;
-}
-
-static int
-putctl4(q, type, code, val)
- queue_t *q;
- int type, code, val;
-{
- mblk_t *mp;
-
- mp = allocb(4, BPRI_HI);
- if (mp == 0)
- return 0;
- mp->b_datap->db_type = type;
- mp->b_wptr[0] = code;
- ((short *)mp->b_wptr)[1] = val;
- mp->b_wptr += 4;
- putnext(q, mp);
- return 1;
-}
-
-static void
-debug_dump(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us;
- queue_t *uq, *lq;
-
- DPRINT("ppp upper streams:\n");
- for (us = minor_devs; us != 0; us = us->nextmn) {
- uq = us->q;
- DPRINT3(" %d: q=%x rlev=%d",
- us->mn, uq, (uq? qsize(uq): 0));
- DPRINT3(" wlev=%d flags=0x%b", (uq? qsize(WR(uq)): 0),
- us->flags, "\020\1priv\2control\3blocked\4last");
- DPRINT3(" state=%x sap=%x req_sap=%x", us->state, us->sap,
- us->req_sap);
- if (us->ppa == 0)
- DPRINT(" ppa=?\n");
- else
- DPRINT1(" ppa=%d\n", us->ppa->ppa_id);
- if (us->flags & US_CONTROL) {
- lq = us->lowerq;
- DPRINT3(" control for %d lq=%x rlev=%d",
- us->ppa_id, lq, (lq? qsize(RD(lq)): 0));
- DPRINT3(" wlev=%d mru=%d mtu=%d\n",
- (lq? qsize(lq): 0), us->mru, us->mtu);
- }
- }
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
-}
-
-#ifdef FILTER_PACKETS
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
-
-#define MAX_IPHDR 128 /* max TCP/IP header size */
-
-
-/* The following table contains a hard-coded list of protocol/port pairs.
- * Any matching packets are either discarded unconditionally, or,
- * if ok_if_link_up is non-zero when a connection does not currently exist
- * (i.e., they go through if the connection is present, but never initiate
- * a dial-out).
- * This idea came from a post by dm@garage.uun.org (David Mazieres)
- */
-static struct pktfilt_tab {
- int proto;
- u_short port;
- u_short ok_if_link_up;
-} pktfilt_tab[] = {
- { IPPROTO_UDP, 520, 1 }, /* RIP, ok to pass if link is up */
- { IPPROTO_UDP, 123, 1 }, /* NTP, don't keep up the link for it */
- { -1, 0, 0 } /* terminator entry has port == -1 */
-};
-
-
-static int
-ip_hard_filter(us, mp, outbound)
- upperstr_t *us;
- mblk_t *mp;
- int outbound;
-{
- struct ip *ip;
- struct pktfilt_tab *pft;
- mblk_t *temp_mp;
- int proto;
- int len, hlen;
-
-
- /* Note, the PPP header has already been pulled up in all cases */
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: filter, proto=0x%x, out=%d\n", us->mn, proto, outbound);
-
- switch (proto)
- {
- case PPP_IP:
- if ((mp->b_wptr - mp->b_rptr) == PPP_HDRLEN && mp->b_cont != 0) {
- temp_mp = mp->b_cont;
- len = msgdsize(temp_mp);
- hlen = (len < MAX_IPHDR) ? len : MAX_IPHDR;
- PULLUP(temp_mp, hlen);
- if (temp_mp == 0) {
- DPRINT2("ppp/%d: filter, pullup next failed, len=%d\n",
- us->mn, hlen);
- mp->b_cont = 0; /* PULLUP() freed the rest */
- freemsg(mp);
- return 0;
- }
- ip = (struct ip *)mp->b_cont->b_rptr;
- }
- else {
- len = msgdsize(mp);
- hlen = (len < (PPP_HDRLEN+MAX_IPHDR)) ? len : (PPP_HDRLEN+MAX_IPHDR);
- PULLUP(mp, hlen);
- if (mp == 0) {
- DPRINT2("ppp/%d: filter, pullup failed, len=%d\n",
- us->mn, hlen);
- return 0;
- }
- ip = (struct ip *)(mp->b_rptr + PPP_HDRLEN);
- }
-
- /* For IP traffic, certain packets (e.g., RIP) may be either
- * 1. ignored - dropped completely
- * 2. will not initiate a connection, but
- * will be passed if a connection is currently up.
- */
- for (pft=pktfilt_tab; pft->proto != -1; pft++) {
- if (ip->ip_p == pft->proto) {
- switch(pft->proto) {
- case IPPROTO_UDP:
- if (((struct udphdr *) &((int *)ip)[ip->ip_hl])->uh_dport
- == htons(pft->port)) goto endfor;
- break;
- case IPPROTO_TCP:
- if (((struct tcphdr *) &((int *)ip)[ip->ip_hl])->th_dport
- == htons(pft->port)) goto endfor;
- break;
- }
- }
- }
- endfor:
- if (pft->proto != -1) {
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: found IP pkt, proto=0x%x (%d)\n",
- us->mn, pft->proto, pft->port);
- /* Discard if not connected, or if not pass_with_link_up */
- /* else, if link is up let go by, but don't update time */
- return pft->ok_if_link_up? -1: 0;
- }
- break;
- } /* end switch (proto) */
-
- return 1;
-}
-#endif /* FILTER_PACKETS */
-
+++ /dev/null
-/*
- * ppp_ahdlc.c - STREAMS module for doing PPP asynchronous HDLC.
- *
- * Re-written by Adi Masputra <adi.masputra@sun.com>, based on
- * the original ppp_ahdlc.c
- *
- * Copyright (c) 2000 by Sun Microsystems, Inc.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies.
- *
- * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
- * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- */
-
-/*
- * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
- */
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stream.h>
-#include <sys/errno.h>
-
-#ifdef SVR4
-#include <sys/conf.h>
-#include <sys/kmem.h>
-#include <sys/cmn_err.h>
-#include <sys/ddi.h>
-#else
-#include <sys/user.h>
-#ifdef __osf__
-#include <sys/cmn_err.h>
-#endif
-#endif /* SVR4 */
-
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-#include "ppp_mod.h"
-
-/*
- * Right now, mutex is only enabled for Solaris 2.x
- */
-#if defined(SOL2)
-#define USE_MUTEX
-#endif /* SOL2 */
-
-/*
- * intpointer_t and uintpointer_t are signed and unsigned integer types
- * large enough to hold any data pointer; that is, data pointers can be
- * assigned into or from these integer types without losing precision.
- * On recent Solaris releases, these types are defined in sys/int_types.h,
- * but not on SunOS 4.x or the earlier Solaris versions.
- */
-#if defined(_LP64) || defined(_I32LPx)
-typedef long intpointer_t;
-typedef unsigned long uintpointer_t;
-#else
-typedef int intpointer_t;
-typedef unsigned int uintpointer_t;
-#endif
-
-MOD_OPEN_DECL(ahdlc_open);
-MOD_CLOSE_DECL(ahdlc_close);
-static int ahdlc_wput(queue_t *, mblk_t *);
-static int ahdlc_rput(queue_t *, mblk_t *);
-static void ahdlc_encode(queue_t *, mblk_t *);
-static void ahdlc_decode(queue_t *, mblk_t *);
-static int msg_byte(mblk_t *, unsigned int);
-
-#if defined(SOL2)
-/*
- * Don't send HDLC start flag is last transmit is within 1.5 seconds -
- * FLAG_TIME is defined is microseconds
- */
-#define FLAG_TIME 1500
-#define ABS(x) (x >= 0 ? x : (-x))
-#endif /* SOL2 */
-
-/*
- * Extract byte i of message mp
- */
-#define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
- msg_byte((mp), (i)))
-
-/*
- * Is this LCP packet one we have to transmit using LCP defaults?
- */
-#define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
-
-/*
- * Standard STREAMS declarations
- */
-static struct module_info minfo = {
- 0x7d23, "ppp_ahdl", 0, INFPSZ, 32768, 512
-};
-
-static struct qinit rinit = {
- ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
-};
-
-static struct qinit winit = {
- ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
-};
-
-#if defined(SVR4) && !defined(SOL2)
-int phdldevflag = 0;
-#define ppp_ahdlcinfo phdlinfo
-#endif /* defined(SVR4) && !defined(SOL2) */
-
-struct streamtab ppp_ahdlcinfo = {
- &rinit, /* ptr to st_rdinit */
- &winit, /* ptr to st_wrinit */
- NULL, /* ptr to st_muxrinit */
- NULL, /* ptr to st_muxwinit */
-#if defined(SUNOS4)
- NULL /* ptr to ptr to st_modlist */
-#endif /* SUNOS4 */
-};
-
-#if defined(SUNOS4)
-int ppp_ahdlc_count = 0; /* open counter */
-#endif /* SUNOS4 */
-
-/*
- * Per-stream state structure
- */
-typedef struct ahdlc_state {
-#if defined(USE_MUTEX)
- kmutex_t lock; /* lock for this structure */
-#endif /* USE_MUTEX */
- int flags; /* link flags */
- mblk_t *rx_buf; /* ptr to receive buffer */
- int rx_buf_size; /* receive buffer size */
- ushort_t infcs; /* calculated rx HDLC FCS */
- u_int32_t xaccm[8]; /* 256-bit xmit ACCM */
- u_int32_t raccm; /* 32-bit rcv ACCM */
- int mtu; /* interface MTU */
- int mru; /* link MRU */
- int unit; /* current PPP unit number */
- struct pppstat stats; /* statistic structure */
-#if defined(SOL2)
- clock_t flag_time; /* time in usec between flags */
- clock_t lbolt; /* last updated lbolt */
-#endif /* SOL2 */
-} ahdlc_state_t;
-
-/*
- * Values for flags
- */
-#define ESCAPED 0x100 /* last saw escape char on input */
-#define IFLUSH 0x200 /* flushing input due to error */
-
-/*
- * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
- */
-#define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
-
-/*
- * FCS lookup table as calculated by genfcstab.
- */
-static u_short fcstab[256] = {
- 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
- 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
- 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
- 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
- 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
- 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
- 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
- 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
- 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
- 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
- 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
- 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
- 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
- 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
- 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
- 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
- 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
- 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
- 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
- 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
- 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
- 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
- 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
- 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
- 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
- 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
- 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
- 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
- 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
- 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
- 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
- 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-static u_int32_t paritytab[8] =
-{
- 0x96696996, 0x69969669, 0x69969669, 0x96696996,
- 0x69969669, 0x96696996, 0x96696996, 0x69969669
-};
-
-/*
- * STREAMS module open (entry) point
- */
-MOD_OPEN(ahdlc_open)
-{
- ahdlc_state_t *state;
-
- /*
- * Return if it's already opened
- */
- if (q->q_ptr) {
- return 0;
- }
-
- /*
- * This can only be opened as a module
- */
- if (sflag != MODOPEN) {
- return 0;
- }
-
- state = (ahdlc_state_t *) ALLOC_NOSLEEP(sizeof(ahdlc_state_t));
- if (state == 0)
- OPEN_ERROR(ENOSR);
- bzero((caddr_t) state, sizeof(ahdlc_state_t));
-
- q->q_ptr = (caddr_t) state;
- WR(q)->q_ptr = (caddr_t) state;
-
-#if defined(USE_MUTEX)
- mutex_init(&state->lock, NULL, MUTEX_DEFAULT, NULL);
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
-
- state->xaccm[0] = ~0; /* escape 0x00 through 0x1f */
- state->xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
- state->mru = PPP_MRU; /* default of 1500 bytes */
-#if defined(SOL2)
- state->flag_time = drv_usectohz(FLAG_TIME);
-#endif /* SOL2 */
-
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
-
-#if defined(SUNOS4)
- ppp_ahdlc_count++;
-#endif /* SUNOS4 */
-
- qprocson(q);
-
- return 0;
-}
-
-/*
- * STREAMS module close (exit) point
- */
-MOD_CLOSE(ahdlc_close)
-{
- ahdlc_state_t *state;
-
- qprocsoff(q);
-
- state = (ahdlc_state_t *) q->q_ptr;
-
- if (state == 0) {
- DPRINT("state == 0 in ahdlc_close\n");
- return 0;
- }
-
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
-
- if (state->rx_buf != 0) {
- freemsg(state->rx_buf);
- state->rx_buf = 0;
- }
-
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
- mutex_destroy(&state->lock);
-#endif /* USE_MUTEX */
-
- FREE(q->q_ptr, sizeof(ahdlc_state_t));
- q->q_ptr = NULL;
- OTHERQ(q)->q_ptr = NULL;
-
-#if defined(SUNOS4)
- if (ppp_ahdlc_count)
- ppp_ahdlc_count--;
-#endif /* SUNOS4 */
-
- return 0;
-}
-
-/*
- * Write side put routine
- */
-static int
-ahdlc_wput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
- struct iocblk *iop;
- int error;
- mblk_t *np;
- struct ppp_stats *psp;
-
- state = (ahdlc_state_t *) q->q_ptr;
- if (state == 0) {
- DPRINT("state == 0 in ahdlc_wput\n");
- freemsg(mp);
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
- case M_DATA:
- /*
- * A data packet - do character-stuffing and FCS, and
- * send it onwards.
- */
- ahdlc_encode(q, mp);
- freemsg(mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- switch (iop->ioc_cmd) {
- case PPPIO_XACCM:
- if ((iop->ioc_count < sizeof(u_int32_t)) ||
- (iop->ioc_count > sizeof(ext_accm))) {
- break;
- }
- if (mp->b_cont == 0) {
- DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
- break;
- }
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
- bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
- iop->ioc_count);
- state->xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
- state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case PPPIO_RACCM:
- if (iop->ioc_count != sizeof(u_int32_t))
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
- break;
- }
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
- bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
- sizeof(u_int32_t));
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case PPPIO_GCLEAN:
- np = allocb(sizeof(int), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
- *(int *)np->b_wptr = state->flags & RCV_FLAGS;
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
- np->b_wptr += sizeof(int);
- iop->ioc_count = sizeof(int);
- error = 0;
- break;
-
- case PPPIO_GETSTAT:
- np = allocb(sizeof(struct ppp_stats), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- psp = (struct ppp_stats *) np->b_wptr;
- np->b_wptr += sizeof(struct ppp_stats);
- bzero((caddr_t)psp, sizeof(struct ppp_stats));
- psp->p = state->stats;
- iop->ioc_count = sizeof(struct ppp_stats);
- error = 0;
- break;
-
- case PPPIO_LASTMOD:
- /* we knew this anyway */
- error = 0;
- break;
-
- default:
- error = -1;
- break;
- }
-
- if (error < 0)
- putnext(q, mp);
- else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
- mp->b_datap->db_type = M_IOCNAK;
- iop->ioc_count = 0;
- iop->ioc_error = error;
- qreply(q, mp);
- }
- break;
-
- case M_CTL:
- switch (*mp->b_rptr) {
- case PPPCTL_MTU:
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
- state->mtu = ((unsigned short *)mp->b_rptr)[1];
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
- freemsg(mp);
- break;
- case PPPCTL_MRU:
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
- state->mru = ((unsigned short *)mp->b_rptr)[1];
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
- freemsg(mp);
- break;
- case PPPCTL_UNIT:
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
- state->unit = mp->b_rptr[1];
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
- break;
- default:
- putnext(q, mp);
- }
- break;
-
- default:
- putnext(q, mp);
- }
-
- return 0;
-}
-
-/*
- * Read side put routine
- */
-static int
-ahdlc_rput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
-
- state = (ahdlc_state_t *) q->q_ptr;
- if (state == 0) {
- DPRINT("state == 0 in ahdlc_rput\n");
- freemsg(mp);
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
- case M_DATA:
- ahdlc_decode(q, mp);
- break;
-
- case M_HANGUP:
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
- if (state->rx_buf != 0) {
- /* XXX would like to send this up for debugging */
- freemsg(state->rx_buf);
- state->rx_buf = 0;
- }
- state->flags = IFLUSH;
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
- putnext(q, mp);
- break;
-
- default:
- putnext(q, mp);
- }
- return 0;
-}
-
-/*
- * Extract bit c from map m, to determine if c needs to be escaped
- */
-#define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
-
-static void
-ahdlc_encode(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
- u_int32_t *xaccm, loc_xaccm[8];
- ushort_t fcs;
- size_t outmp_len;
- mblk_t *outmp, *tmp;
- uchar_t *dp, fcs_val;
- int is_lcp, code;
-#if defined(SOL2)
- clock_t lbolt;
-#endif /* SOL2 */
-
- if (msgdsize(mp) < 4) {
- return;
- }
-
- state = (ahdlc_state_t *)q->q_ptr;
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
-
- /*
- * Allocate an output buffer large enough to handle a case where all
- * characters need to be escaped
- */
- outmp_len = (msgdsize(mp) << 1) + /* input block x 2 */
- (sizeof(fcs) << 2) + /* HDLC FCS x 4 */
- (sizeof(uchar_t) << 1); /* HDLC flags x 2 */
-
- outmp = allocb(outmp_len, BPRI_MED);
- if (outmp == NULL) {
- state->stats.ppp_oerrors++;
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
- putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
- return;
- }
-
-#if defined(SOL2)
- /*
- * Check if our last transmit happenned within flag_time, using
- * the system's LBOLT value in clock ticks
- */
- if (drv_getparm(LBOLT, &lbolt) != -1) {
- if (ABS((clock_t)lbolt - state->lbolt) > state->flag_time) {
- *outmp->b_wptr++ = PPP_FLAG;
- }
- state->lbolt = lbolt;
- } else {
- *outmp->b_wptr++ = PPP_FLAG;
- }
-#else
- /*
- * If the driver below still has a message to process, skip the
- * HDLC flag, otherwise, put one in the beginning
- */
- if (qsize(q->q_next) == 0) {
- *outmp->b_wptr++ = PPP_FLAG;
- }
-#endif
-
- /*
- * All control characters must be escaped for LCP packets with code
- * values between 1 (Conf-Req) and 7 (Code-Rej).
- */
- is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) &&
- (MSG_BYTE(mp, 1) == PPP_UI) &&
- (MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) &&
- (MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) &&
- LCP_USE_DFLT(mp));
-
- xaccm = state->xaccm;
- if (is_lcp) {
- bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm));
- loc_xaccm[0] = ~0; /* force escape on 0x00 through 0x1f */
- xaccm = loc_xaccm;
- }
-
- fcs = PPP_INITFCS; /* Initial FCS is 0xffff */
-
- /*
- * Process this block and the rest (if any) attached to the this one
- */
- for (tmp = mp; tmp; tmp = tmp->b_cont) {
- if (tmp->b_datap->db_type == M_DATA) {
- for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) {
- fcs = PPP_FCS(fcs, *dp);
- if (IN_TX_MAP(*dp, xaccm)) {
- *outmp->b_wptr++ = PPP_ESCAPE;
- *outmp->b_wptr++ = *dp ^ PPP_TRANS;
- } else {
- *outmp->b_wptr++ = *dp;
- }
- }
- } else {
- continue; /* skip if db_type is something other than M_DATA */
- }
- }
-
- /*
- * Append the HDLC FCS, making sure that escaping is done on any
- * necessary bytes
- */
- fcs_val = (fcs ^ 0xffff) & 0xff;
- if (IN_TX_MAP(fcs_val, xaccm)) {
- *outmp->b_wptr++ = PPP_ESCAPE;
- *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
- } else {
- *outmp->b_wptr++ = fcs_val;
- }
-
- fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff;
- if (IN_TX_MAP(fcs_val, xaccm)) {
- *outmp->b_wptr++ = PPP_ESCAPE;
- *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
- } else {
- *outmp->b_wptr++ = fcs_val;
- }
-
- /*
- * And finally, append the HDLC flag, and send it away
- */
- *outmp->b_wptr++ = PPP_FLAG;
-
- state->stats.ppp_obytes += msgdsize(outmp);
- state->stats.ppp_opackets++;
-
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
-
- putnext(q, outmp);
- return;
-}
-
-/*
- * Checks the 32-bit receive ACCM to see if the byte needs un-escaping
- */
-#define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
- (m) & (1 << (c)))
-
-
-/*
- * Process received characters.
- */
-static void
-ahdlc_decode(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
- mblk_t *om;
- uchar_t *dp;
-
- state = (ahdlc_state_t *) q->q_ptr;
-
-#if defined(USE_MUTEX)
- mutex_enter(&state->lock);
-#endif /* USE_MUTEX */
-
- state->stats.ppp_ibytes += msgdsize(mp);
-
- for (; mp != 0; om = mp->b_cont, freeb(mp), mp = om)
- for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) {
-
- /*
- * This should detect the lack of 8-bit communication channel
- * which is necessary for PPP to work. In addition, it also
- * checks on the parity.
- */
- if (*dp & 0x80)
- state->flags |= RCV_B7_1;
- else
- state->flags |= RCV_B7_0;
-
- if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f)))
- state->flags |= RCV_ODDP;
- else
- state->flags |= RCV_EVNP;
-
- /*
- * So we have a HDLC flag ...
- */
- if (*dp == PPP_FLAG) {
-
- /*
- * If we think that it marks the beginning of the frame,
- * then continue to process the next octects
- */
- if ((state->flags & IFLUSH) ||
- (state->rx_buf == 0) ||
- (msgdsize(state->rx_buf) == 0)) {
-
- state->flags &= ~IFLUSH;
- continue;
- }
-
- /*
- * We get here because the above condition isn't true,
- * in which case the HDLC flag was there to mark the end
- * of the frame (or so we think)
- */
- om = state->rx_buf;
-
- if (state->infcs == PPP_GOODFCS) {
- state->stats.ppp_ipackets++;
- adjmsg(om, -PPP_FCSLEN);
- putnext(q, om);
- } else {
- DPRINT2("ppp%d: bad fcs (len=%d)\n",
- state->unit, msgdsize(state->rx_buf));
- freemsg(state->rx_buf);
- state->flags &= ~(IFLUSH | ESCAPED);
- state->stats.ppp_ierrors++;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- }
-
- state->rx_buf = 0;
- continue;
- }
-
- if (state->flags & IFLUSH) {
- continue;
- }
-
- /*
- * Allocate a receive buffer, large enough to store a frame (after
- * un-escaping) of at least 1500 octets. If MRU is negotiated to
- * be more than the default, then allocate that much. In addition,
- * we add an extra 32-bytes for a fudge factor
- */
- if (state->rx_buf == 0) {
- state->rx_buf_size = (state->mru < PPP_MRU ? PPP_MRU : state->mru);
- state->rx_buf_size += (sizeof(u_int32_t) << 3);
- state->rx_buf = allocb(state->rx_buf_size, BPRI_MED);
-
- /*
- * If allocation fails, try again on the next frame
- */
- if (state->rx_buf == 0) {
- state->flags |= IFLUSH;
- continue;
- }
- state->flags &= ~(IFLUSH | ESCAPED);
- state->infcs = PPP_INITFCS;
- }
-
- if (*dp == PPP_ESCAPE) {
- state->flags |= ESCAPED;
- continue;
- }
-
- /*
- * Make sure we un-escape the necessary characters, as well as the
- * ones in our receive async control character map
- */
- if (state->flags & ESCAPED) {
- *dp ^= PPP_TRANS;
- state->flags &= ~ESCAPED;
- } else if (IN_RX_MAP(*dp, state->raccm))
- continue;
-
- /*
- * Unless the peer lied to us about the negotiated MRU, we should
- * never get a frame which is too long. If it happens, toss it away
- * and grab the next incoming one
- */
- if (msgdsize(state->rx_buf) < state->rx_buf_size) {
- state->infcs = PPP_FCS(state->infcs, *dp);
- *state->rx_buf->b_wptr++ = *dp;
- } else {
- DPRINT2("ppp%d: frame too long (%d)\n",
- state->unit, msgdsize(state->rx_buf));
- freemsg(state->rx_buf);
- state->rx_buf = 0;
- state->flags |= IFLUSH;
- }
- }
-
-#if defined(USE_MUTEX)
- mutex_exit(&state->lock);
-#endif /* USE_MUTEX */
-}
-
-static int
-msg_byte(mp, i)
- mblk_t *mp;
- unsigned int i;
-{
- while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
- mp = mp->b_cont;
- if (mp == 0)
- return -1;
- return mp->b_rptr[i];
-}
+++ /dev/null
-/*
- * ppp_comp.c - STREAMS module for kernel-level compression and CCP support.
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * This file is used under SVR4, Solaris 2, SunOS 4, and Digital UNIX.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/stream.h>
-
-#ifdef SVR4
-#include <sys/conf.h>
-#include <sys/cmn_err.h>
-#include <sys/ddi.h>
-#else
-#include <sys/user.h>
-#ifdef __osf__
-#include <sys/cmn_err.h>
-#endif
-#endif /* SVR4 */
-
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-#include "ppp_mod.h"
-
-#ifdef __osf__
-#include <sys/mbuf.h>
-#include <sys/protosw.h>
-#endif
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <net/vjcompress.h>
-
-#define PACKETPTR mblk_t *
-#include <net/ppp-comp.h>
-
-MOD_OPEN_DECL(ppp_comp_open);
-MOD_CLOSE_DECL(ppp_comp_close);
-static int ppp_comp_rput(queue_t *, mblk_t *);
-static int ppp_comp_rsrv(queue_t *);
-static int ppp_comp_wput(queue_t *, mblk_t *);
-static int ppp_comp_wsrv(queue_t *);
-static void ppp_comp_ccp(queue_t *, mblk_t *, int);
-static int msg_byte(mblk_t *, unsigned int);
-
-/* Extract byte i of message mp. */
-#define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
- msg_byte((mp), (i)))
-
-/* Is this LCP packet one we have to transmit using LCP defaults? */
-#define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
-
-#define PPP_COMP_ID 0xbadf
-static struct module_info minfo = {
-#ifdef PRIOQ
- PPP_COMP_ID, "ppp_comp", 0, INFPSZ, 16512, 16384,
-#else
- PPP_COMP_ID, "ppp_comp", 0, INFPSZ, 16384, 4096,
-#endif
-};
-
-static struct qinit r_init = {
- ppp_comp_rput, ppp_comp_rsrv, ppp_comp_open, ppp_comp_close,
- NULL, &minfo, NULL
-};
-
-static struct qinit w_init = {
- ppp_comp_wput, ppp_comp_wsrv, NULL, NULL, NULL, &minfo, NULL
-};
-
-#if defined(SVR4) && !defined(SOL2)
-int pcmpdevflag = 0;
-#define ppp_compinfo pcmpinfo
-#endif
-struct streamtab ppp_compinfo = {
- &r_init, &w_init, NULL, NULL
-};
-
-int ppp_comp_count; /* number of module instances in use */
-
-#ifdef __osf__
-
-static void ppp_comp_alloc(comp_state_t *);
-typedef struct memreq {
- unsigned char comp_opts[20];
- int cmd;
- int thread_status;
- char *returned_mem;
-} memreq_t;
-
-#endif
-
-typedef struct comp_state {
- int flags;
- int mru;
- int mtu;
- int unit;
- struct compressor *xcomp;
- void *xstate;
- struct compressor *rcomp;
- void *rstate;
- struct vjcompress vj_comp;
- int vj_last_ierrors;
- struct pppstat stats;
-#ifdef __osf__
- memreq_t memreq;
- thread_t thread;
-#endif
-} comp_state_t;
-
-
-#ifdef __osf__
-extern task_t first_task;
-#endif
-
-/* Bits in flags are as defined in pppio.h. */
-#define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
-#define LAST_MOD 0x1000000 /* no ppp modules below us */
-#define DBGLOG 0x2000000 /* log debugging stuff */
-
-#define MAX_IPHDR 128 /* max TCP/IP header size */
-#define MAX_VJHDR 20 /* max VJ compressed header size (?) */
-
-#undef MIN /* just in case */
-#define MIN(a, b) ((a) < (b)? (a): (b))
-
-/*
- * List of compressors we know about.
- */
-
-#if DO_BSD_COMPRESS
-extern struct compressor ppp_bsd_compress;
-#endif
-#if DO_DEFLATE
-extern struct compressor ppp_deflate, ppp_deflate_draft;
-#endif
-
-struct compressor *ppp_compressors[] = {
-#if DO_BSD_COMPRESS
- &ppp_bsd_compress,
-#endif
-#if DO_DEFLATE
- &ppp_deflate,
- &ppp_deflate_draft,
-#endif
- NULL
-};
-
-/*
- * STREAMS module entry points.
- */
-MOD_OPEN(ppp_comp_open)
-{
- comp_state_t *cp;
-#ifdef __osf__
- thread_t thread;
-#endif
-
- if (q->q_ptr == NULL) {
- cp = (comp_state_t *) ALLOC_SLEEP(sizeof(comp_state_t));
- if (cp == NULL)
- OPEN_ERROR(ENOSR);
- bzero((caddr_t)cp, sizeof(comp_state_t));
- WR(q)->q_ptr = q->q_ptr = (caddr_t) cp;
- cp->mru = PPP_MRU;
- cp->mtu = PPP_MTU;
- cp->xstate = NULL;
- cp->rstate = NULL;
- vj_compress_init(&cp->vj_comp, -1);
-#ifdef __osf__
- if (!(thread = kernel_thread_w_arg(first_task, ppp_comp_alloc, (void *)cp)))
- OPEN_ERROR(ENOSR);
- cp->thread = thread;
-#endif
- ++ppp_comp_count;
- qprocson(q);
- }
- return 0;
-}
-
-MOD_CLOSE(ppp_comp_close)
-{
- comp_state_t *cp;
-
- qprocsoff(q);
- cp = (comp_state_t *) q->q_ptr;
- if (cp != NULL) {
- if (cp->xstate != NULL)
- (*cp->xcomp->comp_free)(cp->xstate);
- if (cp->rstate != NULL)
- (*cp->rcomp->decomp_free)(cp->rstate);
-#ifdef __osf__
- if (!cp->thread)
- printf("ppp_comp_close: NULL thread!\n");
- else
- thread_terminate(cp->thread);
-#endif
- FREE(cp, sizeof(comp_state_t));
- q->q_ptr = NULL;
- OTHERQ(q)->q_ptr = NULL;
- --ppp_comp_count;
- }
- return 0;
-}
-
-#ifdef __osf__
-
-/* thread for calling back to a compressor's memory allocator
- * Needed for Digital UNIX since it's VM can't handle requests
- * for large amounts of memory without blocking. The thread
- * provides a context in which we can call a memory allocator
- * that may block.
- */
-static void
-ppp_comp_alloc(comp_state_t *cp)
-{
- int len, cmd;
- unsigned char *compressor_options;
- thread_t thread;
- void *(*comp_allocator)();
-
-
-#if defined(MAJOR_VERSION) && (MAJOR_VERSION <= 2)
-
- /* In 2.x and earlier the argument gets passed
- * in the thread structure itself. Yuck.
- */
- thread = current_thread();
- cp = thread->reply_port;
- thread->reply_port = PORT_NULL;
-
-#endif
-
- for (;;) {
- assert_wait((vm_offset_t)&cp->memreq.thread_status, TRUE);
- thread_block();
-
- if (thread_should_halt(current_thread()))
- thread_halt_self();
- cmd = cp->memreq.cmd;
- compressor_options = &cp->memreq.comp_opts[0];
- len = compressor_options[1];
- if (cmd == PPPIO_XCOMP) {
- cp->memreq.returned_mem = cp->xcomp->comp_alloc(compressor_options, len);
- if (!cp->memreq.returned_mem) {
- cp->memreq.thread_status = ENOSR;
- } else {
- cp->memreq.thread_status = 0;
- }
- } else {
- cp->memreq.returned_mem = cp->rcomp->decomp_alloc(compressor_options, len);
- if (!cp->memreq.returned_mem) {
- cp->memreq.thread_status = ENOSR;
- } else {
- cp->memreq.thread_status = 0;
- }
- }
- }
-}
-
-#endif /* __osf__ */
-
-/* here's the deal with memory allocation under Digital UNIX.
- * Some other may also benefit from this...
- * We can't ask for huge chunks of memory in a context where
- * the caller can't be put to sleep (like, here.) The alloc
- * is likely to fail. Instead we do this: the first time we
- * get called, kick off a thread to do the allocation. Return
- * immediately to the caller with EAGAIN, as an indication that
- * they should send down the ioctl again. By the time the
- * second call comes in it's likely that the memory allocation
- * thread will have returned with the requested memory. We will
- * continue to return EAGAIN however until the thread has completed.
- * When it has, we return zero (and the memory) if the allocator
- * was successful and ENOSR otherwise.
- *
- * Callers of the RCOMP and XCOMP ioctls are encouraged (but not
- * required) to loop for some number of iterations with a small
- * delay in the loop body (for instance a 1/10-th second "sleep"
- * via select.)
- */
-static int
-ppp_comp_wput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- struct iocblk *iop;
- comp_state_t *cp;
- int error, len, n;
- int flags, mask;
- mblk_t *np;
- struct compressor **comp;
- struct ppp_stats *psp;
- struct ppp_comp_stats *csp;
- unsigned char *opt_data;
- int nxslots, nrslots;
-
- cp = (comp_state_t *) q->q_ptr;
- if (cp == 0) {
- DPRINT("cp == 0 in ppp_comp_wput\n");
- freemsg(mp);
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
-
- case M_DATA:
- putq(q, mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- switch (iop->ioc_cmd) {
-
- case PPPIO_CFLAGS:
- /* set/get CCP state */
- if (iop->ioc_count != 2 * sizeof(int))
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ppp_comp_wput/%d: PPPIO_CFLAGS b_cont = 0!\n", cp->unit);
- break;
- }
- flags = ((int *) mp->b_cont->b_rptr)[0];
- mask = ((int *) mp->b_cont->b_rptr)[1];
- cp->flags = (cp->flags & ~mask) | (flags & mask);
- if ((mask & CCP_ISOPEN) && (flags & CCP_ISOPEN) == 0) {
- if (cp->xstate != NULL) {
- (*cp->xcomp->comp_free)(cp->xstate);
- cp->xstate = NULL;
- }
- if (cp->rstate != NULL) {
- (*cp->rcomp->decomp_free)(cp->rstate);
- cp->rstate = NULL;
- }
- cp->flags &= ~CCP_ISUP;
- }
- error = 0;
- iop->ioc_count = sizeof(int);
- ((int *) mp->b_cont->b_rptr)[0] = cp->flags;
- mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof(int);
- break;
-
- case PPPIO_VJINIT:
- /*
- * Initialize VJ compressor/decompressor
- */
- if (iop->ioc_count != 2)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ppp_comp_wput/%d: PPPIO_VJINIT b_cont = 0!\n", cp->unit);
- break;
- }
- nxslots = mp->b_cont->b_rptr[0] + 1;
- nrslots = mp->b_cont->b_rptr[1] + 1;
- if (nxslots > MAX_STATES || nrslots > MAX_STATES)
- break;
- vj_compress_init(&cp->vj_comp, nxslots);
- cp->vj_last_ierrors = cp->stats.ppp_ierrors;
- error = 0;
- iop->ioc_count = 0;
- break;
-
- case PPPIO_XCOMP:
- case PPPIO_RCOMP:
- if (iop->ioc_count <= 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ppp_comp_wput/%d: PPPIO_[XR]COMP b_cont = 0!\n", cp->unit);
- break;
- }
- opt_data = mp->b_cont->b_rptr;
- len = mp->b_cont->b_wptr - opt_data;
- if (len > iop->ioc_count)
- len = iop->ioc_count;
- if (opt_data[1] < 2 || opt_data[1] > len)
- break;
- for (comp = ppp_compressors; *comp != NULL; ++comp)
- if ((*comp)->compress_proto == opt_data[0]) {
- /* here's the handler! */
- error = 0;
-#ifndef __osf__
- if (iop->ioc_cmd == PPPIO_XCOMP) {
- /* A previous call may have fetched memory for a compressor
- * that's now being retired or reset. Free it using it's
- * mechanism for freeing stuff.
- */
- if (cp->xstate != NULL) {
- (*cp->xcomp->comp_free)(cp->xstate);
- cp->xstate = NULL;
- }
- cp->xcomp = *comp;
- cp->xstate = (*comp)->comp_alloc(opt_data, len);
- if (cp->xstate == NULL)
- error = ENOSR;
- } else {
- if (cp->rstate != NULL) {
- (*cp->rcomp->decomp_free)(cp->rstate);
- cp->rstate = NULL;
- }
- cp->rcomp = *comp;
- cp->rstate = (*comp)->decomp_alloc(opt_data, len);
- if (cp->rstate == NULL)
- error = ENOSR;
- }
-#else
- if ((error = cp->memreq.thread_status) != EAGAIN)
- if (iop->ioc_cmd == PPPIO_XCOMP) {
- if (cp->xstate) {
- (*cp->xcomp->comp_free)(cp->xstate);
- cp->xstate = 0;
- }
- /* sanity check for compressor options
- */
- if (sizeof (cp->memreq.comp_opts) < len) {
- printf("can't handle options for compressor %d (%d)\n", opt_data[0],
- opt_data[1]);
- cp->memreq.thread_status = ENOSR;
- cp->memreq.returned_mem = 0;
- }
- /* fill in request for the thread and kick it off
- */
- if (cp->memreq.thread_status == 0 && !cp->memreq.returned_mem) {
- bcopy(opt_data, cp->memreq.comp_opts, len);
- cp->memreq.cmd = PPPIO_XCOMP;
- cp->xcomp = *comp;
- error = cp->memreq.thread_status = EAGAIN;
- thread_wakeup((vm_offset_t)&cp->memreq.thread_status);
- } else {
- cp->xstate = cp->memreq.returned_mem;
- cp->memreq.returned_mem = 0;
- cp->memreq.thread_status = 0;
- }
- } else {
- if (cp->rstate) {
- (*cp->rcomp->decomp_free)(cp->rstate);
- cp->rstate = NULL;
- }
- if (sizeof (cp->memreq.comp_opts) < len) {
- printf("can't handle options for compressor %d (%d)\n", opt_data[0],
- opt_data[1]);
- cp->memreq.thread_status = ENOSR;
- cp->memreq.returned_mem = 0;
- }
- if (cp->memreq.thread_status == 0 && !cp->memreq.returned_mem) {
- bcopy(opt_data, cp->memreq.comp_opts, len);
- cp->memreq.cmd = PPPIO_RCOMP;
- cp->rcomp = *comp;
- error = cp->memreq.thread_status = EAGAIN;
- thread_wakeup((vm_offset_t)&cp->memreq.thread_status);
- } else {
- cp->rstate = cp->memreq.returned_mem;
- cp->memreq.returned_mem = 0;
- cp->memreq.thread_status = 0;
- }
- }
-#endif
- break;
- }
- iop->ioc_count = 0;
- break;
-
- case PPPIO_GETSTAT:
- if ((cp->flags & LAST_MOD) == 0) {
- error = -1; /* let the ppp_ahdl module handle it */
- break;
- }
- np = allocb(sizeof(struct ppp_stats), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- psp = (struct ppp_stats *) np->b_wptr;
- np->b_wptr += sizeof(struct ppp_stats);
- iop->ioc_count = sizeof(struct ppp_stats);
- psp->p = cp->stats;
- psp->vj = cp->vj_comp.stats;
- error = 0;
- break;
-
- case PPPIO_GETCSTAT:
- np = allocb(sizeof(struct ppp_comp_stats), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- csp = (struct ppp_comp_stats *) np->b_wptr;
- np->b_wptr += sizeof(struct ppp_comp_stats);
- iop->ioc_count = sizeof(struct ppp_comp_stats);
- bzero((caddr_t)csp, sizeof(struct ppp_comp_stats));
- if (cp->xstate != 0)
- (*cp->xcomp->comp_stat)(cp->xstate, &csp->c);
- if (cp->rstate != 0)
- (*cp->rcomp->decomp_stat)(cp->rstate, &csp->d);
- error = 0;
- break;
-
- case PPPIO_DEBUG:
- if (iop->ioc_count != sizeof(int))
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ppp_comp_wput/%d: PPPIO_DEBUG b_cont = 0!\n", cp->unit);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n == PPPDBG_LOG + PPPDBG_COMP) {
- DPRINT1("ppp_comp%d: debug log enabled\n", cp->unit);
- cp->flags |= DBGLOG;
- error = 0;
- iop->ioc_count = 0;
- } else {
- error = -1;
- }
- break;
-
- case PPPIO_LASTMOD:
- cp->flags |= LAST_MOD;
- error = 0;
- break;
-
- default:
- error = -1;
- break;
- }
-
- if (error < 0)
- putnext(q, mp);
- else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
- mp->b_datap->db_type = M_IOCNAK;
- iop->ioc_error = error;
- iop->ioc_count = 0;
- qreply(q, mp);
- }
- break;
-
- case M_CTL:
- switch (*mp->b_rptr) {
- case PPPCTL_MTU:
- cp->mtu = ((unsigned short *)mp->b_rptr)[1];
- break;
- case PPPCTL_MRU:
- cp->mru = ((unsigned short *)mp->b_rptr)[1];
- break;
- case PPPCTL_UNIT:
- cp->unit = mp->b_rptr[1];
- break;
- }
- putnext(q, mp);
- break;
-
- default:
- putnext(q, mp);
- }
-
- return 0;
-}
-
-static int
-ppp_comp_wsrv(q)
- queue_t *q;
-{
- mblk_t *mp, *cmp = NULL;
- comp_state_t *cp;
- int len, proto, type, hlen, code;
- struct ip *ip;
- unsigned char *vjhdr, *dp;
-
- cp = (comp_state_t *) q->q_ptr;
- if (cp == 0) {
- DPRINT("cp == 0 in ppp_comp_wsrv\n");
- return 0;
- }
-
- while ((mp = getq(q)) != 0) {
- /* assert(mp->b_datap->db_type == M_DATA) */
-#ifdef PRIOQ
- if (!bcanputnext(q,mp->b_band))
-#else
- if (!canputnext(q))
-#endif /* PRIOQ */
- {
- putbq(q, mp);
- break;
- }
-
- /*
- * First check the packet length and work out what the protocol is.
- */
- len = msgdsize(mp);
- if (len < PPP_HDRLEN) {
- DPRINT1("ppp_comp_wsrv: bogus short packet (%d)\n", len);
- freemsg(mp);
- cp->stats.ppp_oerrors++;
- putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
- continue;
- }
- proto = (MSG_BYTE(mp, 2) << 8) + MSG_BYTE(mp, 3);
-
- /*
- * Make sure we've got enough data in the first mblk
- * and that we are its only user.
- */
- if (proto == PPP_CCP)
- hlen = len;
- else if (proto == PPP_IP)
- hlen = PPP_HDRLEN + MAX_IPHDR;
- else
- hlen = PPP_HDRLEN;
- if (hlen > len)
- hlen = len;
- if (mp->b_wptr < mp->b_rptr + hlen || mp->b_datap->db_ref > 1) {
- PULLUP(mp, hlen);
- if (mp == 0) {
- DPRINT1("ppp_comp_wsrv: pullup failed (%d)\n", hlen);
- cp->stats.ppp_oerrors++;
- putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
- continue;
- }
- }
-
- /*
- * Do VJ compression if requested.
- */
- if (proto == PPP_IP && (cp->flags & COMP_VJC)) {
- ip = (struct ip *) (mp->b_rptr + PPP_HDRLEN);
- if (ip->ip_p == IPPROTO_TCP) {
- type = vj_compress_tcp(ip, len - PPP_HDRLEN, &cp->vj_comp,
- (cp->flags & COMP_VJCCID), &vjhdr);
- switch (type) {
- case TYPE_UNCOMPRESSED_TCP:
- mp->b_rptr[3] = proto = PPP_VJC_UNCOMP;
- break;
- case TYPE_COMPRESSED_TCP:
- dp = vjhdr - PPP_HDRLEN;
- dp[1] = mp->b_rptr[1]; /* copy control field */
- dp[0] = mp->b_rptr[0]; /* copy address field */
- dp[2] = 0; /* set protocol field */
- dp[3] = proto = PPP_VJC_COMP;
- mp->b_rptr = dp;
- break;
- }
- }
- }
-
- /*
- * Do packet compression if enabled.
- */
- if (proto == PPP_CCP)
- ppp_comp_ccp(q, mp, 0);
- else if (proto != PPP_LCP && (cp->flags & CCP_COMP_RUN)
- && cp->xstate != NULL) {
- len = msgdsize(mp);
- (*cp->xcomp->compress)(cp->xstate, &cmp, mp, len,
- (cp->flags & CCP_ISUP? cp->mtu + PPP_HDRLEN: 0));
- if (cmp != NULL) {
-#ifdef PRIOQ
- cmp->b_band=mp->b_band;
-#endif /* PRIOQ */
- freemsg(mp);
- mp = cmp;
- }
- }
-
- /*
- * Do address/control and protocol compression if enabled.
- */
- if ((cp->flags & COMP_AC)
- && !(proto == PPP_LCP && LCP_USE_DFLT(mp))) {
- mp->b_rptr += 2; /* drop the address & ctrl fields */
- if (proto < 0x100 && (cp->flags & COMP_PROT))
- ++mp->b_rptr; /* drop the high protocol byte */
- } else if (proto < 0x100 && (cp->flags & COMP_PROT)) {
- /* shuffle up the address & ctrl fields */
- mp->b_rptr[2] = mp->b_rptr[1];
- mp->b_rptr[1] = mp->b_rptr[0];
- ++mp->b_rptr;
- }
-
- cp->stats.ppp_opackets++;
- cp->stats.ppp_obytes += msgdsize(mp);
- putnext(q, mp);
- }
-
- return 0;
-}
-
-static int
-ppp_comp_rput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- comp_state_t *cp;
- struct iocblk *iop;
- struct ppp_stats *psp;
-
- cp = (comp_state_t *) q->q_ptr;
- if (cp == 0) {
- DPRINT("cp == 0 in ppp_comp_rput\n");
- freemsg(mp);
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
-
- case M_DATA:
- putq(q, mp);
- break;
-
- case M_IOCACK:
- iop = (struct iocblk *) mp->b_rptr;
- switch (iop->ioc_cmd) {
- case PPPIO_GETSTAT:
- /*
- * Catch this on the way back from the ppp_ahdl module
- * so we can fill in the VJ stats.
- */
- if (mp->b_cont == 0 || iop->ioc_count != sizeof(struct ppp_stats))
- break;
- psp = (struct ppp_stats *) mp->b_cont->b_rptr;
- psp->vj = cp->vj_comp.stats;
- break;
- }
- putnext(q, mp);
- break;
-
- case M_CTL:
- switch (mp->b_rptr[0]) {
- case PPPCTL_IERROR:
- ++cp->stats.ppp_ierrors;
- break;
- case PPPCTL_OERROR:
- ++cp->stats.ppp_oerrors;
- break;
- }
- putnext(q, mp);
- break;
-
- default:
- putnext(q, mp);
- }
-
- return 0;
-}
-
-static int
-ppp_comp_rsrv(q)
- queue_t *q;
-{
- int proto, rv, i;
- mblk_t *mp, *dmp = NULL, *np;
- uchar_t *dp, *iphdr;
- comp_state_t *cp;
- int len, hlen, vjlen;
- u_int iphlen;
-
- cp = (comp_state_t *) q->q_ptr;
- if (cp == 0) {
- DPRINT("cp == 0 in ppp_comp_rsrv\n");
- return 0;
- }
-
- while ((mp = getq(q)) != 0) {
- /* assert(mp->b_datap->db_type == M_DATA) */
- if (!canputnext(q)) {
- putbq(q, mp);
- break;
- }
-
- len = msgdsize(mp);
- cp->stats.ppp_ibytes += len;
- cp->stats.ppp_ipackets++;
-
- /*
- * First work out the protocol and where the PPP header ends.
- */
- i = 0;
- proto = MSG_BYTE(mp, 0);
- if (proto == PPP_ALLSTATIONS) {
- i = 2;
- proto = MSG_BYTE(mp, 2);
- }
- if ((proto & 1) == 0) {
- ++i;
- proto = (proto << 8) + MSG_BYTE(mp, i);
- }
- hlen = i + 1;
-
- /*
- * Now reconstruct a complete, contiguous PPP header at the
- * start of the packet.
- */
- if (hlen < ((cp->flags & DECOMP_AC)? 0: 2)
- + ((cp->flags & DECOMP_PROT)? 1: 2)) {
- /* count these? */
- goto bad;
- }
- if (mp->b_rptr + hlen > mp->b_wptr) {
- adjmsg(mp, hlen); /* XXX check this call */
- hlen = 0;
- }
- if (hlen != PPP_HDRLEN) {
- /*
- * We need to put some bytes on the front of the packet
- * to make a full-length PPP header.
- * If we can put them in *mp, we do, otherwise we
- * tack another mblk on the front.
- * XXX we really shouldn't need to carry around
- * the address and control at this stage.
- */
- dp = mp->b_rptr + hlen - PPP_HDRLEN;
- if (dp < mp->b_datap->db_base || mp->b_datap->db_ref > 1) {
- np = allocb(PPP_HDRLEN, BPRI_MED);
- if (np == 0)
- goto bad;
- np->b_cont = mp;
- mp->b_rptr += hlen;
- mp = np;
- dp = mp->b_wptr;
- mp->b_wptr += PPP_HDRLEN;
- } else
- mp->b_rptr = dp;
-
- dp[0] = PPP_ALLSTATIONS;
- dp[1] = PPP_UI;
- dp[2] = proto >> 8;
- dp[3] = proto;
- }
-
- /*
- * Now see if we have a compressed packet to decompress,
- * or a CCP packet to take notice of.
- */
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto == PPP_CCP) {
- len = msgdsize(mp);
- if (mp->b_wptr < mp->b_rptr + len) {
- PULLUP(mp, len);
- if (mp == 0)
- goto bad;
- }
- ppp_comp_ccp(q, mp, 1);
- } else if (proto == PPP_COMP) {
- if ((cp->flags & CCP_ISUP)
- && (cp->flags & CCP_DECOMP_RUN) && cp->rstate
- && (cp->flags & CCP_ERR) == 0) {
- rv = (*cp->rcomp->decompress)(cp->rstate, mp, &dmp);
- switch (rv) {
- case DECOMP_OK:
- freemsg(mp);
- mp = dmp;
- if (mp == NULL) {
- /* no error, but no packet returned either. */
- continue;
- }
- break;
- case DECOMP_ERROR:
- cp->flags |= CCP_ERROR;
- ++cp->stats.ppp_ierrors;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- break;
- case DECOMP_FATALERROR:
- cp->flags |= CCP_FATALERROR;
- ++cp->stats.ppp_ierrors;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- break;
- }
- }
- } else if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
- (*cp->rcomp->incomp)(cp->rstate, mp);
- }
-
- /*
- * Now do VJ decompression.
- */
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
- len = msgdsize(mp) - PPP_HDRLEN;
- if ((cp->flags & DECOMP_VJC) == 0 || len <= 0)
- goto bad;
-
- /*
- * Advance past the ppp header.
- * Here we assume that the whole PPP header is in the first mblk.
- */
- np = mp;
- dp = np->b_rptr + PPP_HDRLEN;
- if (dp >= mp->b_wptr) {
- np = np->b_cont;
- dp = np->b_rptr;
- }
-
- /*
- * Make sure we have sufficient contiguous data at this point.
- */
- hlen = (proto == PPP_VJC_COMP)? MAX_VJHDR: MAX_IPHDR;
- if (hlen > len)
- hlen = len;
- if (np->b_wptr < dp + hlen || np->b_datap->db_ref > 1) {
- PULLUP(mp, hlen + PPP_HDRLEN);
- if (mp == 0)
- goto bad;
- np = mp;
- dp = np->b_rptr + PPP_HDRLEN;
- }
-
- if (proto == PPP_VJC_COMP) {
- /*
- * Decompress VJ-compressed packet.
- * First reset compressor if an input error has occurred.
- */
- if (cp->stats.ppp_ierrors != cp->vj_last_ierrors) {
- if (cp->flags & DBGLOG)
- DPRINT1("ppp%d: resetting VJ\n", cp->unit);
- vj_uncompress_err(&cp->vj_comp);
- cp->vj_last_ierrors = cp->stats.ppp_ierrors;
- }
-
- vjlen = vj_uncompress_tcp(dp, np->b_wptr - dp, len,
- &cp->vj_comp, &iphdr, &iphlen);
- if (vjlen < 0) {
- if (cp->flags & DBGLOG)
- DPRINT2("ppp%d: vj_uncomp_tcp failed, pkt len %d\n",
- cp->unit, len);
- ++cp->vj_last_ierrors; /* so we don't reset next time */
- goto bad;
- }
-
- /* drop ppp and vj headers off */
- if (mp != np) {
- freeb(mp);
- mp = np;
- }
- mp->b_rptr = dp + vjlen;
-
- /* allocate a new mblk for the ppp and ip headers */
- if ((np = allocb(iphlen + PPP_HDRLEN + 4, BPRI_MED)) == 0)
- goto bad;
- dp = np->b_rptr; /* prepend mblk with TCP/IP hdr */
- dp[0] = PPP_ALLSTATIONS; /* reconstruct PPP header */
- dp[1] = PPP_UI;
- dp[2] = PPP_IP >> 8;
- dp[3] = PPP_IP;
- bcopy((caddr_t)iphdr, (caddr_t)dp + PPP_HDRLEN, iphlen);
- np->b_wptr = dp + iphlen + PPP_HDRLEN;
- np->b_cont = mp;
-
- /* XXX there seems to be a bug which causes panics in strread
- if we make an mbuf with only the IP header in it :-( */
- if (mp->b_wptr - mp->b_rptr > 4) {
- bcopy((caddr_t)mp->b_rptr, (caddr_t)np->b_wptr, 4);
- mp->b_rptr += 4;
- np->b_wptr += 4;
- } else {
- bcopy((caddr_t)mp->b_rptr, (caddr_t)np->b_wptr,
- mp->b_wptr - mp->b_rptr);
- np->b_wptr += mp->b_wptr - mp->b_rptr;
- np->b_cont = mp->b_cont;
- freeb(mp);
- }
-
- mp = np;
-
- } else {
- /*
- * "Decompress" a VJ-uncompressed packet.
- */
- cp->vj_last_ierrors = cp->stats.ppp_ierrors;
- if (!vj_uncompress_uncomp(dp, hlen, &cp->vj_comp)) {
- if (cp->flags & DBGLOG)
- DPRINT2("ppp%d: vj_uncomp_uncomp failed, pkt len %d\n",
- cp->unit, len);
- ++cp->vj_last_ierrors; /* don't need to reset next time */
- goto bad;
- }
- mp->b_rptr[3] = PPP_IP; /* fix up the PPP protocol field */
- }
- }
-
- putnext(q, mp);
- continue;
-
- bad:
- if (mp != 0)
- freemsg(mp);
- cp->stats.ppp_ierrors++;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- }
-
- return 0;
-}
-
-/*
- * Handle a CCP packet being sent or received.
- * Here all the data in the packet is in a single mbuf.
- */
-static void
-ppp_comp_ccp(q, mp, rcvd)
- queue_t *q;
- mblk_t *mp;
- int rcvd;
-{
- int len, clen;
- comp_state_t *cp;
- unsigned char *dp;
-
- len = msgdsize(mp);
- if (len < PPP_HDRLEN + CCP_HDRLEN)
- return;
-
- cp = (comp_state_t *) q->q_ptr;
- dp = mp->b_rptr + PPP_HDRLEN;
- len -= PPP_HDRLEN;
- clen = CCP_LENGTH(dp);
- if (clen > len)
- return;
-
- switch (CCP_CODE(dp)) {
- case CCP_CONFREQ:
- case CCP_TERMREQ:
- case CCP_TERMACK:
- cp->flags &= ~CCP_ISUP;
- break;
-
- case CCP_CONFACK:
- if ((cp->flags & (CCP_ISOPEN | CCP_ISUP)) == CCP_ISOPEN
- && clen >= CCP_HDRLEN + CCP_OPT_MINLEN
- && clen >= CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN)) {
- if (!rcvd) {
- if (cp->xstate != NULL
- && (*cp->xcomp->comp_init)
- (cp->xstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
- cp->unit, 0, ((cp->flags & DBGLOG) != 0)))
- cp->flags |= CCP_COMP_RUN;
- } else {
- if (cp->rstate != NULL
- && (*cp->rcomp->decomp_init)
- (cp->rstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
- cp->unit, 0, cp->mru, ((cp->flags & DBGLOG) != 0)))
- cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
- }
- }
- break;
-
- case CCP_RESETACK:
- if (cp->flags & CCP_ISUP) {
- if (!rcvd) {
- if (cp->xstate && (cp->flags & CCP_COMP_RUN))
- (*cp->xcomp->comp_reset)(cp->xstate);
- } else {
- if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
- (*cp->rcomp->decomp_reset)(cp->rstate);
- cp->flags &= ~CCP_ERROR;
- }
- }
- }
- break;
- }
-}
-
-#if 0
-dump_msg(mp)
- mblk_t *mp;
-{
- dblk_t *db;
-
- while (mp != 0) {
- db = mp->b_datap;
- DPRINT2("mp=%x cont=%x ", mp, mp->b_cont);
- DPRINT3("rptr=%x wptr=%x datap=%x\n", mp->b_rptr, mp->b_wptr, db);
- DPRINT2(" base=%x lim=%x", db->db_base, db->db_lim);
- DPRINT2(" ref=%d type=%d\n", db->db_ref, db->db_type);
- mp = mp->b_cont;
- }
-}
-#endif
-
-static int
-msg_byte(mp, i)
- mblk_t *mp;
- unsigned int i;
-{
- while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
- mp = mp->b_cont;
- if (mp == 0)
- return -1;
- return mp->b_rptr[i];
-}
+++ /dev/null
-/*
- * Miscellaneous definitions for PPP STREAMS modules.
- */
-
-/*
- * Macros for allocating and freeing kernel memory.
- */
-#ifdef SVR4 /* SVR4, including Solaris 2 */
-#include <sys/kmem.h>
-#define ALLOC_SLEEP(n) kmem_alloc((n), KM_SLEEP)
-#define ALLOC_NOSLEEP(n) kmem_alloc((n), KM_NOSLEEP)
-#define FREE(p, n) kmem_free((p), (n))
-#endif
-
-#ifdef SUNOS4
-#include <sys/kmem_alloc.h> /* SunOS 4.x */
-#define ALLOC_SLEEP(n) kmem_alloc((n), KMEM_SLEEP)
-#define ALLOC_NOSLEEP(n) kmem_alloc((n), KMEM_NOSLEEP)
-#define FREE(p, n) kmem_free((p), (n))
-#define NOTSUSER() (suser()? 0: EPERM)
-#define bcanputnext(q, band) canputnext((q))
-#endif /* SunOS 4 */
-
-#ifdef __osf__
-#include <sys/malloc.h>
-
-/* caution: this mirrors macros in sys/malloc.h, and uses interfaces
- * which are subject to change.
- * The problems are that:
- * - the official MALLOC macro wants the lhs of the assignment as an argument,
- * and it takes care of the assignment itself (yuck.)
- * - PPP insists on using "FREE" which conflicts with a macro of the same name.
- *
- */
-#ifdef BUCKETINDX /* V2.0 */
-#define ALLOC_SLEEP(n) (void *)malloc((u_long)(n), BUCKETP(n), M_DEVBUF, M_WAITOK)
-#define ALLOC_NOSLEEP(n) (void *)malloc((u_long)(n), BUCKETP(n), M_DEVBUF, M_NOWAIT)
-#else
-#define ALLOC_SLEEP(n) (void *)malloc((u_long)(n), BUCKETINDEX(n), M_DEVBUF, M_WAITOK)
-#define ALLOC_NOSLEEP(n) (void *)malloc((u_long)(n), BUCKETINDEX(n), M_DEVBUF, M_NOWAIT)
-#endif
-
-#define bcanputnext(q, band) canputnext((q))
-
-#ifdef FREE
-#undef FREE
-#endif
-#define FREE(p, n) free((void *)(p), M_DEVBUF)
-
-#define NO_DLPI 1
-
-#ifndef IFT_PPP
-#define IFT_PPP 0x17
-#endif
-
-#include <sys/proc.h>
-#define NOTSUSER() (suser(u.u_procp->p_rcred, &u.u_acflag) ? EPERM : 0)
-
-/* #include "ppp_osf.h" */
-
-#endif /* __osf__ */
-
-#ifdef AIX4
-#define ALLOC_SLEEP(n) xmalloc((n), 0, pinned_heap) /* AIX V4.x */
-#define ALLOC_NOSLEEP(n) xmalloc((n), 0, pinned_heap) /* AIX V4.x */
-#define FREE(p, n) xmfree((p), pinned_heap)
-#define NOTSUSER() (suser()? 0: EPERM)
-#endif /* AIX */
-
-/*
- * Macros for printing debugging stuff.
- */
-#ifdef DEBUG
-#if defined(SVR4) || defined(__osf__)
-#if defined(SNI)
-#include <sys/strlog.h>
-#define STRLOG_ID 4712
-#define DPRINT(f) strlog(STRLOG_ID, 0, 0, SL_TRACE, f)
-#define DPRINT1(f, a1) strlog(STRLOG_ID, 0, 0, SL_TRACE, f, a1)
-#define DPRINT2(f, a1, a2) strlog(STRLOG_ID, 0, 0, SL_TRACE, f, a1, a2)
-#define DPRINT3(f, a1, a2, a3) strlog(STRLOG_ID, 0, 0, SL_TRACE, f, a1, a2, a3)
-#else
-#define DPRINT(f) cmn_err(CE_CONT, f)
-#define DPRINT1(f, a1) cmn_err(CE_CONT, f, a1)
-#define DPRINT2(f, a1, a2) cmn_err(CE_CONT, f, a1, a2)
-#define DPRINT3(f, a1, a2, a3) cmn_err(CE_CONT, f, a1, a2, a3)
-#endif /* SNI */
-#else
-#define DPRINT(f) printf(f)
-#define DPRINT1(f, a1) printf(f, a1)
-#define DPRINT2(f, a1, a2) printf(f, a1, a2)
-#define DPRINT3(f, a1, a2, a3) printf(f, a1, a2, a3)
-#endif /* SVR4 or OSF */
-
-#else
-#define DPRINT(f) 0
-#define DPRINT1(f, a1) 0
-#define DPRINT2(f, a1, a2) 0
-#define DPRINT3(f, a1, a2, a3) 0
-#endif /* DEBUG */
-
-#ifndef SVR4
-typedef unsigned char uchar_t;
-typedef unsigned short ushort_t;
-#ifndef __osf__
-typedef int minor_t;
-#endif
-#endif
-
-/*
- * If we don't have multithreading support, define substitutes.
- */
-#ifndef D_MP
-# define qprocson(q)
-# define qprocsoff(q)
-# define put(q, mp) ((*(q)->q_qinfo->qi_putp)((q), (mp)))
-# define canputnext(q) canput((q)->q_next)
-# define qwriter(q, mp, func, scope) (func)((q), (mp))
-#endif
-
-#ifdef D_MP
-/* Use msgpullup if we have other multithreading support. */
-#define PULLUP(mp, len) \
- do { \
- mblk_t *np = msgpullup((mp), (len)); \
- freemsg((mp)); \
- mp = np; \
- } while (0)
-
-#else
-/* Use pullupmsg if we don't have any multithreading support. */
-#define PULLUP(mp, len) \
- do { \
- if (!pullupmsg((mp), (len))) { \
- freemsg((mp)); \
- mp = 0; \
- } \
- } while (0)
-#endif
-
-/*
- * How to declare the open and close procedures for a module.
- */
-#ifdef SVR4
-#define MOD_OPEN_DECL(name) \
-static int name(queue_t *, dev_t *, int, int, cred_t *)
-
-#define MOD_CLOSE_DECL(name) \
-static int name(queue_t *, int, cred_t *)
-
-#define MOD_OPEN(name) \
-static int name(q, devp, flag, sflag, credp) \
- queue_t *q; \
- dev_t *devp; \
- int flag, sflag; \
- cred_t *credp;
-
-#define MOD_CLOSE(name) \
-static int name(q, flag, credp) \
- queue_t *q; \
- int flag; \
- cred_t *credp;
-
-#define OPEN_ERROR(x) return (x)
-#define DRV_OPEN_OK(dev) return 0
-
-#define NOTSUSER() (drv_priv(credp))
-
-#else /* not SVR4 */
-#define MOD_OPEN_DECL(name) \
-static int name(queue_t *, int, int, int)
-
-#define MOD_CLOSE_DECL(name) \
-static int name(queue_t *, int)
-
-#define MOD_OPEN(name) \
-static int name(q, dev, flag, sflag) \
- queue_t *q; \
- int dev; \
- int flag, sflag;
-
-#define MOD_CLOSE(name) \
-static int name(q, flag) \
- queue_t *q; \
- int flag;
-
-#define OPEN_ERROR(x) { u.u_error = (x); return OPENFAIL; }
-#define DRV_OPEN_OK(dev) return (dev)
-
-#endif /* SVR4 */
+++ /dev/null
-/*
- * Routines to compress and uncompess tcp packets (for transmission
- * over low speed serial lines.
- *
- * Copyright (c) 1989 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
- * - Initial distribution.
- *
- * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au,
- * so that the entire packet being decompressed doesn't have
- * to be in contiguous memory (just the compressed header).
- */
-
-/*
- * This version is used under SunOS 4.x, Digital UNIX, AIX 4.x,
- * and SVR4 systems including Solaris 2.
- *
- * $Id: vjcompress.c,v 1.11 2004/01/17 05:47:55 carlsonj Exp $
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-
-#ifdef SVR4
-#ifndef __GNUC__
-#include <sys/byteorder.h> /* for ntohl, etc. */
-#else
-/* make sure we don't get the gnu "fixed" one! */
-#include "/usr/include/sys/byteorder.h"
-#endif
-#endif
-
-#ifdef __osf__
-#include <net/net_globals.h>
-#endif
-#include <netinet/in.h>
-
-#ifdef AIX4
-#define _NETINET_IN_SYSTM_H_
-typedef u_long n_long;
-#else
-#include <netinet/in_systm.h>
-#endif
-
-#ifdef SOL2
-#include <sys/sunddi.h>
-#endif
-
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-
-#include <net/ppp_defs.h>
-#include <net/vjcompress.h>
-
-#ifndef VJ_NO_STATS
-#define INCR(counter) ++comp->stats.counter
-#else
-#define INCR(counter)
-#endif
-
-#define BCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n))
-#undef BCOPY
-#define BCOPY(p1, p2, n) bcopy((char *)(p1), (char *)(p2), (int)(n))
-#ifndef KERNEL
-#define ovbcopy bcopy
-#endif
-
-#ifdef __osf__
-#define getip_hl(base) (((base).ip_vhl)&0xf)
-#define getth_off(base) ((((base).th_xoff)&0xf0)>>4)
-
-#else
-#define getip_hl(base) ((base).ip_hl)
-#define getth_off(base) ((base).th_off)
-#endif
-
-void
-vj_compress_init(comp, max_state)
- struct vjcompress *comp;
- int max_state;
-{
- register u_int i;
- register struct cstate *tstate = comp->tstate;
-
- if (max_state == -1)
- max_state = MAX_STATES - 1;
- bzero((char *)comp, sizeof(*comp));
- for (i = max_state; i > 0; --i) {
- tstate[i].cs_id = i;
- tstate[i].cs_next = &tstate[i - 1];
- }
- tstate[0].cs_next = &tstate[max_state];
- tstate[0].cs_id = 0;
- comp->last_cs = &tstate[0];
- comp->last_recv = 255;
- comp->last_xmit = 255;
- comp->flags = VJF_TOSS;
-}
-
-
-/* ENCODE encodes a number that is known to be non-zero. ENCODEZ
- * checks for zero (since zero has to be encoded in the long, 3 byte
- * form).
- */
-#define ENCODE(n) { \
- if ((u_short)(n) >= 256) { \
- *cp++ = 0; \
- cp[1] = (n); \
- cp[0] = (n) >> 8; \
- cp += 2; \
- } else { \
- *cp++ = (n); \
- } \
-}
-#define ENCODEZ(n) { \
- if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
- *cp++ = 0; \
- cp[1] = (n); \
- cp[0] = (n) >> 8; \
- cp += 2; \
- } else { \
- *cp++ = (n); \
- } \
-}
-
-#define DECODEL(f) { \
- if (*cp == 0) {\
- u_int32_t tmp = ntohl(f) + ((cp[1] << 8) | cp[2]); \
- (f) = htonl(tmp); \
- cp += 3; \
- } else { \
- u_int32_t tmp = ntohl(f) + (u_int32_t)*cp++; \
- (f) = htonl(tmp); \
- } \
-}
-
-#define DECODES(f) { \
- if (*cp == 0) {\
- u_short tmp = ntohs(f) + ((cp[1] << 8) | cp[2]); \
- (f) = htons(tmp); \
- cp += 3; \
- } else { \
- u_short tmp = ntohs(f) + (u_int32_t)*cp++; \
- (f) = htons(tmp); \
- } \
-}
-
-#define DECODEU(f) { \
- if (*cp == 0) {\
- (f) = htons((cp[1] << 8) | cp[2]); \
- cp += 3; \
- } else { \
- (f) = htons((u_int32_t)*cp++); \
- } \
-}
-
-u_int
-vj_compress_tcp(ip, mlen, comp, compress_cid, vjhdrp)
- register struct ip *ip;
- u_int mlen;
- struct vjcompress *comp;
- int compress_cid;
- u_char **vjhdrp;
-{
- register struct cstate *cs = comp->last_cs->cs_next;
- register u_int hlen = getip_hl(*ip);
- register struct tcphdr *oth;
- register struct tcphdr *th;
- register u_int deltaS, deltaA;
- register u_int changes = 0;
- u_char new_seq[16];
- register u_char *cp = new_seq;
-
- /*
- * Bail if this is an IP fragment or if the TCP packet isn't
- * `compressible' (i.e., ACK isn't set or some other control bit is
- * set). (We assume that the caller has already made sure the
- * packet is IP proto TCP).
- */
- if ((ip->ip_off & htons(0x3fff)) || mlen < 40)
- return (TYPE_IP);
-
- th = (struct tcphdr *)&((int *)ip)[hlen];
- if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
- return (TYPE_IP);
- /*
- * Packet is compressible -- we're going to send either a
- * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need
- * to locate (or create) the connection state. Special case the
- * most recently used connection since it's most likely to be used
- * again & we don't have to do any reordering if it's used.
- */
- INCR(vjs_packets);
- if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
- ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
- *(int *)th != ((int *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) {
- /*
- * Wasn't the first -- search for it.
- *
- * States are kept in a circularly linked list with
- * last_cs pointing to the end of the list. The
- * list is kept in lru order by moving a state to the
- * head of the list whenever it is referenced. Since
- * the list is short and, empirically, the connection
- * we want is almost always near the front, we locate
- * states via linear search. If we don't find a state
- * for the datagram, the oldest state is (re-)used.
- */
- register struct cstate *lcs;
- register struct cstate *lastcs = comp->last_cs;
-
- do {
- lcs = cs; cs = cs->cs_next;
- INCR(vjs_searches);
- if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
- && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
- && *(int *)th == ((int *)&cs->cs_ip)[getip_hl(cs->cs_ip)])
- goto found;
- } while (cs != lastcs);
-
- /*
- * Didn't find it -- re-use oldest cstate. Send an
- * uncompressed packet that tells the other side what
- * connection number we're using for this conversation.
- * Note that since the state list is circular, the oldest
- * state points to the newest and we only need to set
- * last_cs to update the lru linkage.
- */
- INCR(vjs_misses);
- comp->last_cs = lcs;
- hlen += getth_off(*th);
- hlen <<= 2;
- if (hlen > mlen)
- return (TYPE_IP);
- goto uncompressed;
-
- found:
- /*
- * Found it -- move to the front on the connection list.
- */
- if (cs == lastcs)
- comp->last_cs = lcs;
- else {
- lcs->cs_next = cs->cs_next;
- cs->cs_next = lastcs->cs_next;
- lastcs->cs_next = cs;
- }
- }
-
- /*
- * Make sure that only what we expect to change changed. The first
- * line of the `if' checks the IP protocol version, header length &
- * type of service. The 2nd line checks the "Don't fragment" bit.
- * The 3rd line checks the time-to-live and protocol (the protocol
- * check is unnecessary but costless). The 4th line checks the TCP
- * header length. The 5th line checks IP options, if any. The 6th
- * line checks TCP options, if any. If any of these things are
- * different between the previous & current datagram, we send the
- * current datagram `uncompressed'.
- */
- oth = (struct tcphdr *)&((int *)&cs->cs_ip)[hlen];
- deltaS = hlen;
- hlen += getth_off(*th);
- hlen <<= 2;
- if (hlen > mlen)
- return (TYPE_IP);
-
- if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] ||
- ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] ||
- ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] ||
- getth_off(*th) != getth_off(*oth) ||
- (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
- (getth_off(*th) > 5 && BCMP(th + 1, oth + 1, (getth_off(*th) - 5) << 2)))
- goto uncompressed;
-
- /*
- * Figure out which of the changing fields changed. The
- * receiver expects changes in the order: urgent, window,
- * ack, seq (the order minimizes the number of temporaries
- * needed in this section of code).
- */
- if (th->th_flags & TH_URG) {
- deltaS = ntohs(th->th_urp);
- ENCODEZ(deltaS);
- changes |= NEW_U;
- } else if (th->th_urp != oth->th_urp)
- /* argh! URG not set but urp changed -- a sensible
- * implementation should never do this but RFC793
- * doesn't prohibit the change so we have to deal
- * with it. */
- goto uncompressed;
-
- if ((deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) > 0) {
- ENCODE(deltaS);
- changes |= NEW_W;
- }
-
- if ((deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack)) > 0) {
- if (deltaA > 0xffff)
- goto uncompressed;
- ENCODE(deltaA);
- changes |= NEW_A;
- }
-
- if ((deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq)) > 0) {
- if (deltaS > 0xffff)
- goto uncompressed;
- ENCODE(deltaS);
- changes |= NEW_S;
- }
-
- switch(changes) {
-
- case 0:
- /*
- * Nothing changed. If this packet contains data and the
- * last one didn't, this is probably a data packet following
- * an ack (normal on an interactive connection) and we send
- * it compressed. Otherwise it's probably a retransmit,
- * retransmitted ack or window probe. Send it uncompressed
- * in case the other side missed the compressed version.
- */
- if (ip->ip_len != cs->cs_ip.ip_len &&
- ntohs(cs->cs_ip.ip_len) == hlen)
- break;
-
- /* (fall through) */
-
- case SPECIAL_I:
- case SPECIAL_D:
- /*
- * actual changes match one of our special case encodings --
- * send packet uncompressed.
- */
- goto uncompressed;
-
- case NEW_S|NEW_A:
- if (deltaS == deltaA && deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
- /* special case for echoed terminal traffic */
- changes = SPECIAL_I;
- cp = new_seq;
- }
- break;
-
- case NEW_S:
- if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
- /* special case for data xfer */
- changes = SPECIAL_D;
- cp = new_seq;
- }
- break;
- }
-
- deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);
- if (deltaS != 1) {
- ENCODEZ(deltaS);
- changes |= NEW_I;
- }
- if (th->th_flags & TH_PUSH)
- changes |= TCP_PUSH_BIT;
- /*
- * Grab the cksum before we overwrite it below. Then update our
- * state with this packet's header.
- */
- deltaA = ntohs(th->th_sum);
- BCOPY(ip, &cs->cs_ip, hlen);
-
- /*
- * We want to use the original packet as our compressed packet.
- * (cp - new_seq) is the number of bytes we need for compressed
- * sequence numbers. In addition we need one byte for the change
- * mask, one for the connection id and two for the tcp checksum.
- * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how
- * many bytes of the original packet to toss so subtract the two to
- * get the new packet size.
- */
- deltaS = cp - new_seq;
- cp = (u_char *)ip;
- if (compress_cid == 0 || comp->last_xmit != cs->cs_id) {
- comp->last_xmit = cs->cs_id;
- hlen -= deltaS + 4;
- *vjhdrp = (cp += hlen);
- *cp++ = changes | NEW_C;
- *cp++ = cs->cs_id;
- } else {
- hlen -= deltaS + 3;
- *vjhdrp = (cp += hlen);
- *cp++ = changes;
- }
- *cp++ = deltaA >> 8;
- *cp++ = deltaA;
- BCOPY(new_seq, cp, deltaS);
- INCR(vjs_compressed);
- return (TYPE_COMPRESSED_TCP);
-
- /*
- * Update connection state cs & send uncompressed packet (that is,
- * a regular ip/tcp packet but with the 'conversation id' we hope
- * to use on future compressed packets in the protocol field).
- */
- uncompressed:
- BCOPY(ip, &cs->cs_ip, hlen);
- ip->ip_p = cs->cs_id;
- comp->last_xmit = cs->cs_id;
- return (TYPE_UNCOMPRESSED_TCP);
-}
-
-/*
- * Called when we may have missed a packet.
- */
-void
-vj_uncompress_err(comp)
- struct vjcompress *comp;
-{
- comp->flags |= VJF_TOSS;
- INCR(vjs_errorin);
-}
-
-/*
- * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP.
- */
-int
-vj_uncompress_uncomp(buf, buflen, comp)
- u_char *buf;
- int buflen;
- struct vjcompress *comp;
-{
- register u_int hlen;
- register struct cstate *cs;
- register struct ip *ip;
-
- ip = (struct ip *) buf;
- hlen = getip_hl(*ip) << 2;
- if (ip->ip_p >= MAX_STATES
- || hlen + sizeof(struct tcphdr) > buflen
- || (hlen += getth_off(*((struct tcphdr *)&((char *)ip)[hlen])) << 2)
- > buflen
- || hlen > MAX_HDR) {
- comp->flags |= VJF_TOSS;
- INCR(vjs_errorin);
- return (0);
- }
- cs = &comp->rstate[comp->last_recv = ip->ip_p];
- comp->flags &=~ VJF_TOSS;
- ip->ip_p = IPPROTO_TCP;
- BCOPY(ip, &cs->cs_ip, hlen);
- cs->cs_hlen = hlen;
- INCR(vjs_uncompressedin);
- return (1);
-}
-
-/*
- * Uncompress a packet of type TYPE_COMPRESSED_TCP.
- * The packet starts at buf and is of total length total_len.
- * The first buflen bytes are at buf; this must include the entire
- * compressed TCP/IP header. This procedure returns the length
- * of the VJ header, with a pointer to the uncompressed IP header
- * in *hdrp and its length in *hlenp.
- */
-int
-vj_uncompress_tcp(buf, buflen, total_len, comp, hdrp, hlenp)
- u_char *buf;
- int buflen, total_len;
- struct vjcompress *comp;
- u_char **hdrp;
- u_int *hlenp;
-{
- register u_char *cp;
- register u_int hlen, changes;
- register struct tcphdr *th;
- register struct cstate *cs;
- register u_short *bp;
- register u_int vjlen;
- register u_int32_t tmp;
-
- INCR(vjs_compressedin);
- cp = buf;
- changes = *cp++;
- if (changes & NEW_C) {
- /* Make sure the state index is in range, then grab the state.
- * If we have a good state index, clear the 'discard' flag. */
- if (*cp >= MAX_STATES)
- goto bad;
-
- comp->flags &=~ VJF_TOSS;
- comp->last_recv = *cp++;
- } else {
- /* this packet has an implicit state index. If we've
- * had a line error since the last time we got an
- * explicit state index, we have to toss the packet. */
- if (comp->flags & VJF_TOSS) {
- INCR(vjs_tossed);
- return (-1);
- }
- }
- cs = &comp->rstate[comp->last_recv];
- hlen = getip_hl(cs->cs_ip) << 2;
- th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
- th->th_sum = htons((*cp << 8) | cp[1]);
- cp += 2;
- if (changes & TCP_PUSH_BIT)
- th->th_flags |= TH_PUSH;
- else
- th->th_flags &=~ TH_PUSH;
-
- switch (changes & SPECIALS_MASK) {
- case SPECIAL_I:
- {
- register u_int32_t i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
- /* some compilers can't nest inline assembler.. */
- tmp = ntohl(th->th_ack) + i;
- th->th_ack = htonl(tmp);
- tmp = ntohl(th->th_seq) + i;
- th->th_seq = htonl(tmp);
- }
- break;
-
- case SPECIAL_D:
- /* some compilers can't nest inline assembler.. */
- tmp = ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
- th->th_seq = htonl(tmp);
- break;
-
- default:
- if (changes & NEW_U) {
- th->th_flags |= TH_URG;
- DECODEU(th->th_urp);
- } else
- th->th_flags &=~ TH_URG;
- if (changes & NEW_W)
- DECODES(th->th_win);
- if (changes & NEW_A)
- DECODEL(th->th_ack);
- if (changes & NEW_S)
- DECODEL(th->th_seq);
- break;
- }
- if (changes & NEW_I) {
- DECODES(cs->cs_ip.ip_id);
- } else {
- cs->cs_ip.ip_id = ntohs(cs->cs_ip.ip_id) + 1;
- cs->cs_ip.ip_id = htons(cs->cs_ip.ip_id);
- }
-
- /*
- * At this point, cp points to the first byte of data in the
- * packet. Fill in the IP total length and update the IP
- * header checksum.
- */
- vjlen = cp - buf;
- buflen -= vjlen;
- if (buflen < 0)
- /* we must have dropped some characters (crc should detect
- * this but the old slip framing won't) */
- goto bad;
-
- total_len += cs->cs_hlen - vjlen;
- cs->cs_ip.ip_len = htons(total_len);
-
- /* recompute the ip header checksum */
- bp = (u_short *) &cs->cs_ip;
- cs->cs_ip.ip_sum = 0;
- for (changes = 0; hlen > 0; hlen -= 2)
- changes += *bp++;
- changes = (changes & 0xffff) + (changes >> 16);
- changes = (changes & 0xffff) + (changes >> 16);
- cs->cs_ip.ip_sum = ~ changes;
-
- *hdrp = (u_char *) &cs->cs_ip;
- *hlenp = cs->cs_hlen;
- return vjlen;
-
- bad:
- comp->flags |= VJF_TOSS;
- INCR(vjs_errorin);
- return (-1);
-}
+++ /dev/null
-#
-# defines common to several Makefiles
-#
-
-INSTALL= /usr/sbin/install
-
-BINDIR = @DESTDIR@/bin
-MANDIR = @DESTDIR@/man
-ETCDIR = @SYSCONF@/ppp
-
-CC = /opt/SUNWspro/bin/cc
-COPTS = -O -Xa
-
-LD = /usr/ccs/bin/ld
+++ /dev/null
-#
-# defines common to several Makefiles
-#
-
-INSTALL= /usr/sbin/install
-
-BINDIR = @DESTDIR@/bin
-MANDIR = @DESTDIR@/man
-ETCDIR = @SYSCONF@/ppp
-
-CC = gcc
-COPTS = -O2
-
-LD = /usr/ccs/bin/ld
+++ /dev/null
-#
-# Generic make definitions for Solaris 2
-#
-# $Id: Makedefs.sol2,v 1.2 2002/09/07 05:15:25 carlsonj Exp $
-#
-
-include ../Makedefs.com
-
-CPPFLAGS = -D_KERNEL -DSVR4 -DSOL2 -DPRIOQ -DDEBUG -I../include
-CFLAGS = $(CPPFLAGS) $(COPTS)
-
-# lint-specific variables
-LINT = lint
-LINT_OPT_32 =
-LINT_OPT_64 = -Xarch=v9 -errchk=longptr64
-
-LINT_32 =
-LINT_32 += -erroff=E_BAD_PTR_CAST_ALIGN
-LINT_32 += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED
-LINT_32 += -erroff=E_SUSPICIOUS_COMPARISON
-LINT_32 += -erroff=E_CAST_UINT_TO_SIGNED_INT
-LINT_32 += -erroff=E_PASS_UINT_TO_SIGNED_INT
-LINT_32 += -erroff=E_INVALID_ANNOTATION_NAME
-LINT_32 += -erroff=E_FUNC_ARG_UNUSED
-# This might be needed, but zlib.c and vjcompress.c will squawk
-# when not ignored
-LINT_32 += -erroff=E_CASE_FALLTHRU
-LINT_32 += -erroff=E_RET_INT_IMPLICITLY
-LINT_32 += -erroff=E_FUNC_NO_RET_VAL
-# Some STREAMS macros will be noisy too when this isn't ignored
-LINT_32 += -erroff=E_CONSTANT_CONDITION
-LINT_32 += -erroff=E_CONST_EXPR
-
-# Extra noise suppressant for 64-bit
-EXTRA_OFF =
-EXTRA_OFF += -erroff=E_CAST_INT_TO_SMALL_INT
-EXTRA_OFF += -erroff=E_CAST_INT_CONST_TO_SMALL_INT
-EXTRA_OFF += -erroff=E_CAST_TO_PTR_FROM_INT
-EXTRA_OFF += -erroff=E_ASSIGN_INT_TO_SMALL_INT
-EXTRA_OFF += -erroff=E_ASSIGN_INT_FROM_BIG_CONST
-EXTRA_OFF += -erroff=E_CONST_PROMOTED_UNSIGNED_LL
-EXTRA_OFF += -erroff=E_CONST_PROMOTED_LONG_LONG
-EXTRA_OFF += -erroff=E_CONST_TRUNCATED_BY_ASSIGN
-EXTRA_OFF += -erroff=E_PASS_INT_FROM_BIG_CONST
-EXTRA_OFF += -erroff=E_COMP_INT_WITH_LARGE_INT
-EXTRA_OFF += -erroff=E_ASSIGN_UINT_TO_SIGNED_INT
-EXTRA_OFF += -erroff=E_ASSIGN_NARROW_CONV
-EXTRA_OFF += -erroff=E_PASS_INT_TO_SMALL_INT
-EXTRA_OFF += -erroff=E_PTR_CONV_LOSES_BITS
-
-LINT_64 = $(LINT_32)
-LINT_64 += $(EXTRA_OFF)
-
-LINTFLAGS64 = -Xa -nsxmuF -errtags=yes $(LINT_OPT_64) $(LINT_64)
-LINT64 = $(LINT) -c $(LINTFLAGS64) $(CPPFLAGS)
-
-LINTFLAGS32 = -Xa -nsxmuF -errtags=yes $(LINT_OPT_32) $(LINT_32)
-LINT32 = $(LINT) -c $(LINTFLAGS32) $(CPPFLAGS)
-
+++ /dev/null
-#
-# Makefile for STREAMS modules for Solaris 2.
-#
-# $Id: Makefile.sol2,v 1.3 2004/11/15 00:57:54 carlsonj Exp $
-#
-
-include Makedefs.sol2
-
-COPTS += -xO2 -xspace -W0,-Lt
-
-COMP_OBJS = ppp_comp.o bsd-comp.o deflate.o zlib.o vjcompress.o \
- ppp_comp_mod.o
-
-all: ppp ppp_ahdl ppp_comp
-
-ppp: ppp.o ppp_mod.o
- $(LD) -r -o $@ ppp.o ppp_mod.o
- chmod +x $@
-
-ppp_ahdl: ppp_ahdlc.o ppp_ahdlc_mod.o
- $(LD) -r -o $@ ppp_ahdlc.o ppp_ahdlc_mod.o
- chmod +x $@
-
-ppp_comp: $(COMP_OBJS)
- $(LD) -r -o $@ $(COMP_OBJS)
- chmod +x $@
-
-bsd-comp.o: ../modules/bsd-comp.c
- $(CC) $(CFLAGS) -c $?
-deflate.o: ../modules/deflate.c
- $(CC) $(CFLAGS) -c $?
-ppp.o: ppp.c
- $(CC) $(CFLAGS) -c $?
-ppp_mod.o: ppp_mod.c
- $(CC) $(CFLAGS) -c $?
-ppp_ahdlc_mod.o: ppp_ahdlc_mod.c
- $(CC) $(CFLAGS) -c $?
-ppp_ahdlc.o: ppp_ahdlc.c
- $(CC) $(CFLAGS) -c $?
-ppp_comp.o: ppp_comp.c
- $(CC) $(CFLAGS) -c $?
-ppp_comp_mod.o: ppp_comp_mod.c
- $(CC) $(CFLAGS) -c $?
-vjcompress.o: ../modules/vjcompress.c
- $(CC) $(CFLAGS) -c $?
-zlib.o: ../common/zlib.c
- $(CC) $(CFLAGS) -c $?
-
-install:
- /usr/sbin/modunload -i 0
- cp ppp ppp.conf /kernel/drv
- cp ppp_comp ppp_ahdl /kernel/strmod
- if grep clone:ppp /etc/minor_perm; then :; else \
- echo clone:ppp 0644 root sys >>/etc/minor_perm; fi
- /usr/sbin/rem_drv ppp 2>/dev/null || true
- /usr/sbin/modunload -i 0
- /usr/sbin/add_drv ppp
-
-SRCS = ppp.c ppp_mod.c ppp_ahdlc.c ppp_ahdlc_mod.c \
- ppp_comp.c ../modules/bsd-comp.c ../modules/deflate.c \
- ../common/zlib.c ../modules/vjcompress.c ppp_comp_mod.c
-
-lint:
- $(LINT32) $(SRCS)
-
-clean:
- rm -f ppp ppp_comp ppp_ahdl *.o *~ core
- rm -f *.ln
+++ /dev/null
-#
-# Makefile for 64-bit STREAMS modules for Solaris 2.
-#
-# $Id: Makefile.sol2-64,v 1.3 2004/11/15 00:57:54 carlsonj Exp $
-#
-
-include Makedefs.sol2
-
-# Sun's cc flag for LP64 compilation / linkage
-COPTS += -xchip=ultra -xarch=v9 -Wc,-xcode=abs32 -Wc,-Qiselect-regsym=0 -xO3 -xspace -W0,-Lt
-
-# subdirectory where 64-bit objects / binaries will be placed
-LP64DIR = sparcv9
-
-# Name of legacy Makefile (for 32-bit binaries)
-STD_MAKE = Makefile.sol2
-
-COMP_OBJS = $(LP64DIR)/ppp_comp.o $(LP64DIR)/bsd-comp.o \
- $(LP64DIR)/deflate.o $(LP64DIR)/zlib.o $(LP64DIR)/vjcompress.o \
- $(LP64DIR)/ppp_comp_mod.o
-
-all: std_objs $(LP64DIR) ppp ppp_ahdl ppp_comp
-
-std_objs:
- $(MAKE) -f $(STD_MAKE) all
-
-ppp: $(LP64DIR)/ppp.o $(LP64DIR)/ppp_mod.o
- $(LD) -r -o $(LP64DIR)/$@ $(LP64DIR)/ppp.o $(LP64DIR)/ppp_mod.o
- chmod +x $(LP64DIR)/$@
-
-ppp_ahdl: $(LP64DIR)/ppp_ahdlc.o $(LP64DIR)/ppp_ahdlc_mod.o
- $(LD) -r -o $(LP64DIR)/$@ $(LP64DIR)/ppp_ahdlc.o \
- $(LP64DIR)/ppp_ahdlc_mod.o
- chmod +x $(LP64DIR)/$@
-
-ppp_comp: $(COMP_OBJS)
- $(LD) -r -o $(LP64DIR)/$@ $(COMP_OBJS)
- chmod +x $(LP64DIR)/$@
-
-$(LP64DIR)/bsd-comp.o: ../modules/bsd-comp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/deflate.o: ../modules/deflate.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp.o: ppp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_mod.o: ppp_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_ahdlc_mod.o: ppp_ahdlc_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_ahdlc.o: ppp_ahdlc.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_comp.o: ppp_comp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_comp_mod.o: ppp_comp_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/vjcompress.o: ../modules/vjcompress.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/zlib.o: ../common/zlib.c
- $(CC) $(CFLAGS) -c $? -o $@
-
-$(LP64DIR):
- mkdir -m 755 -p $@
-
-install:
- /usr/sbin/modunload -i 0
- cp ppp ppp.conf /kernel/drv
- cp ppp_comp ppp_ahdl /kernel/strmod
- cp $(LP64DIR)/ppp /kernel/drv/$(LP64DIR)
- cp $(LP64DIR)/ppp_comp $(LP64DIR)/ppp_ahdl /kernel/strmod/$(LP64DIR)
- if grep clone:ppp /etc/minor_perm; then :; else \
- echo clone:ppp 0644 root sys >>/etc/minor_perm; fi
- /usr/sbin/rem_drv ppp 2>/dev/null || true
- /usr/sbin/modunload -i 0
- /usr/sbin/add_drv ppp
-
-SRCS = ppp.c ppp_mod.c ppp_ahdlc.c ppp_ahdlc_mod.c \
- ppp_comp.c ../modules/bsd-comp.c ../modules/deflate.c \
- ../common/zlib.c ../modules/vjcompress.c ppp_comp_mod.c
-
-lint:
- $(LINT64) $(SRCS)
-
-lint-32:
- $(LINT32) $(SRCS)
-
-clean:
- $(MAKE) -f $(STD_MAKE) clean
- rm -f $(LP64DIR)/ppp $(LP64DIR)/ppp_comp $(LP64DIR)/ppp_ahdl $(LP64DIR)/*.o $(LP64DIR)/*~ $(LP64DIR)/core
+++ /dev/null
-#
-# Makefile for 64-bit STREAMS modules for Solaris 2 on x64
-#
-# $Id: Makefile.sol2-64x,v 1.1 2005/06/26 23:53:17 carlsonj Exp $
-#
-
-include Makedefs.sol2
-
-# Sun's cc flag for LP64 compilation / linkage
-COPTS += -errwarn -xtarget=opteron -m64 -xmodel=kernel \
- -Ui386 -U__i386 -D__amd64 -xO2
-
-# subdirectory where 64-bit objects / binaries will be placed
-LP64DIR = amd64
-
-# Name of legacy Makefile (for 32-bit binaries)
-STD_MAKE = Makefile.sol2
-
-COMP_OBJS = $(LP64DIR)/ppp_comp.o $(LP64DIR)/bsd-comp.o \
- $(LP64DIR)/deflate.o $(LP64DIR)/zlib.o $(LP64DIR)/vjcompress.o \
- $(LP64DIR)/ppp_comp_mod.o
-
-all: std_objs $(LP64DIR) ppp ppp_ahdl ppp_comp
-
-std_objs:
- $(MAKE) -f $(STD_MAKE) all
-
-ppp: $(LP64DIR)/ppp.o $(LP64DIR)/ppp_mod.o
- $(LD) -r -o $(LP64DIR)/$@ $(LP64DIR)/ppp.o $(LP64DIR)/ppp_mod.o
- chmod +x $(LP64DIR)/$@
-
-ppp_ahdl: $(LP64DIR)/ppp_ahdlc.o $(LP64DIR)/ppp_ahdlc_mod.o
- $(LD) -r -o $(LP64DIR)/$@ $(LP64DIR)/ppp_ahdlc.o \
- $(LP64DIR)/ppp_ahdlc_mod.o
- chmod +x $(LP64DIR)/$@
-
-ppp_comp: $(COMP_OBJS)
- $(LD) -r -o $(LP64DIR)/$@ $(COMP_OBJS)
- chmod +x $(LP64DIR)/$@
-
-$(LP64DIR)/bsd-comp.o: ../modules/bsd-comp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/deflate.o: ../modules/deflate.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp.o: ppp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_mod.o: ppp_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_ahdlc_mod.o: ppp_ahdlc_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_ahdlc.o: ppp_ahdlc.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_comp.o: ppp_comp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_comp_mod.o: ppp_comp_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/vjcompress.o: ../modules/vjcompress.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/zlib.o: ../common/zlib.c
- $(CC) $(CFLAGS) -c $? -o $@
-
-$(LP64DIR):
- mkdir -m 755 -p $@
-
-install:
- /usr/sbin/modunload -i 0
- cp ppp ppp.conf /kernel/drv
- cp ppp_comp ppp_ahdl /kernel/strmod
- cp $(LP64DIR)/ppp /kernel/drv/$(LP64DIR)
- cp $(LP64DIR)/ppp_comp $(LP64DIR)/ppp_ahdl /kernel/strmod/$(LP64DIR)
- if grep clone:ppp /etc/minor_perm; then :; else \
- echo clone:ppp 0644 root sys >>/etc/minor_perm; fi
- /usr/sbin/rem_drv ppp 2>/dev/null || true
- /usr/sbin/modunload -i 0
- /usr/sbin/add_drv ppp
-
-SRCS = ppp.c ppp_mod.c ppp_ahdlc.c ppp_ahdlc_mod.c \
- ppp_comp.c ../modules/bsd-comp.c ../modules/deflate.c \
- ../common/zlib.c ../modules/vjcompress.c ppp_comp_mod.c
-
-lint:
- $(LINT64) $(SRCS)
-
-lint-32:
- $(LINT32) $(SRCS)
-
-clean:
- $(MAKE) -f $(STD_MAKE) clean
- rm -f $(LP64DIR)/ppp $(LP64DIR)/ppp_comp $(LP64DIR)/ppp_ahdl $(LP64DIR)/*.o $(LP64DIR)/*~ $(LP64DIR)/core
+++ /dev/null
-#
-# Makefile for STREAMS modules for Solaris 2.
-#
-# $Id: Makefile.sol2gcc,v 1.4 2004/11/15 00:57:54 carlsonj Exp $
-#
-
-include Makedefs.sol2
-
-COPTS += -fno-builtin
-
-COMP_OBJS = ppp_comp.o bsd-comp.o deflate.o zlib.o vjcompress.o \
- ppp_comp_mod.o
-
-all: ppp ppp_ahdl ppp_comp
-
-ppp: ppp.o ppp_mod.o
- $(LD) -r -o $@ ppp.o ppp_mod.o
- chmod +x $@
-
-ppp_ahdl: ppp_ahdlc.o ppp_ahdlc_mod.o
- $(LD) -r -o $@ ppp_ahdlc.o ppp_ahdlc_mod.o
- chmod +x $@
-
-ppp_comp: $(COMP_OBJS)
- $(LD) -r -o $@ $(COMP_OBJS)
- chmod +x $@
-
-bsd-comp.o: ../modules/bsd-comp.c
- $(CC) $(CFLAGS) -c $?
-deflate.o: ../modules/deflate.c
- $(CC) $(CFLAGS) -c $?
-ppp.o: ppp.c
- $(CC) $(CFLAGS) -c $?
-ppp_mod.o: ppp_mod.c
- $(CC) $(CFLAGS) -c $?
-ppp_ahdlc_mod.o: ppp_ahdlc_mod.c
- $(CC) $(CFLAGS) -c $?
-ppp_ahdlc.o: ppp_ahdlc.c
- $(CC) $(CFLAGS) -c $?
-ppp_comp.o: ppp_comp.c
- $(CC) $(CFLAGS) -c $?
-ppp_comp_mod.o: ppp_comp_mod.c
- $(CC) $(CFLAGS) -c $?
-vjcompress.o: ../modules/vjcompress.c
- $(CC) $(CFLAGS) -c $?
-zlib.o: ../common/zlib.c
- $(CC) $(CFLAGS) -c $?
-
-install:
- /usr/sbin/modunload -i 0
- cp ppp ppp.conf /kernel/drv
- cp ppp_comp ppp_ahdl /kernel/strmod
- if grep clone:ppp /etc/minor_perm; then :; else \
- echo clone:ppp 0644 root sys >>/etc/minor_perm; fi
- /usr/sbin/rem_drv ppp 2>/dev/null || true
- /usr/sbin/modunload -i 0
- /usr/sbin/add_drv ppp
-
-SRCS = ppp.c ppp_mod.c ppp_ahdlc.c ppp_ahdlc_mod.c \
- ppp_comp.c ../modules/bsd-comp.c ../modules/deflate.c \
- ../common/zlib.c ../modules/vjcompress.c ppp_comp_mod.c
-
-lint:
- $(LINT32) $(SRCS)
-
-clean:
- rm -f ppp ppp_comp ppp_ahdl *.o *~ core
- rm -f *.ln
+++ /dev/null
-#
-# Makefile for 64-bit STREAMS modules for Solaris 2.
-#
-# $Id: Makefile.sol2gcc-64,v 1.3 2004/11/15 00:57:54 carlsonj Exp $
-#
-
-include Makedefs.sol2
-
-# gcc flags for LP64 compilation / linkage
-COPTS += -mcpu=v9 -m64 -mcmodel=medlow -mstack-bias -fno-builtin
-
-# subdirectory where 64-bit objects / binaries will be placed
-LP64DIR = sparcv9
-
-# Name of legacy Makefile (for 32-bit binaries)
-STD_MAKE = Makefile.sol2gcc
-
-COMP_OBJS = $(LP64DIR)/ppp_comp.o $(LP64DIR)/bsd-comp.o \
- $(LP64DIR)/deflate.o $(LP64DIR)/zlib.o $(LP64DIR)/vjcompress.o \
- $(LP64DIR)/ppp_comp_mod.o
-
-all: std_objs $(LP64DIR) ppp ppp_ahdl ppp_comp
-
-std_objs:
- $(MAKE) -f $(STD_MAKE) all
-
-ppp: $(LP64DIR)/ppp.o $(LP64DIR)/ppp_mod.o
- $(LD) -r -o $(LP64DIR)/$@ $(LP64DIR)/ppp.o $(LP64DIR)/ppp_mod.o
- chmod +x $(LP64DIR)/$@
-
-ppp_ahdl: $(LP64DIR)/ppp_ahdlc.o $(LP64DIR)/ppp_ahdlc_mod.o
- $(LD) -r -o $(LP64DIR)/$@ $(LP64DIR)/ppp_ahdlc.o \
- $(LP64DIR)/ppp_ahdlc_mod.o
- chmod +x $(LP64DIR)/$@
-
-ppp_comp: $(COMP_OBJS)
- $(LD) -r -o $(LP64DIR)/$@ $(COMP_OBJS)
- chmod +x $(LP64DIR)/$@
-
-$(LP64DIR)/bsd-comp.o: ../modules/bsd-comp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/deflate.o: ../modules/deflate.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp.o: ppp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_mod.o: ppp_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_ahdlc_mod.o: ppp_ahdlc_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_ahdlc.o: ppp_ahdlc.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_comp.o: ppp_comp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_comp_mod.o: ppp_comp_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/vjcompress.o: ../modules/vjcompress.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/zlib.o: ../common/zlib.c
- $(CC) $(CFLAGS) -c $? -o $@
-
-$(LP64DIR):
- mkdir -m 755 -p $@
-
-install:
- /usr/sbin/modunload -i 0
- cp ppp ppp.conf /kernel/drv
- cp ppp_comp ppp_ahdl /kernel/strmod
- cp $(LP64DIR)/ppp /kernel/drv/$(LP64DIR)
- cp $(LP64DIR)/ppp_comp $(LP64DIR)/ppp_ahdl /kernel/strmod/$(LP64DIR)
- if grep clone:ppp /etc/minor_perm; then :; else \
- echo clone:ppp 0644 root sys >>/etc/minor_perm; fi
- /usr/sbin/rem_drv ppp 2>/dev/null || true
- /usr/sbin/modunload -i 0
- /usr/sbin/add_drv ppp
-
-SRCS = ppp.c ppp_mod.c ppp_ahdlc.c ppp_ahdlc_mod.c \
- ppp_comp.c ../modules/bsd-comp.c ../modules/deflate.c \
- ../common/zlib.c ../modules/vjcompress.c ppp_comp_mod.c
-
-lint:
- $(LINT64) $(SRCS)
-
-lint-32:
- $(LINT32) $(SRCS)
-
-clean:
- $(MAKE) -f $(STD_MAKE) clean
- rm -f $(LP64DIR)/ppp $(LP64DIR)/ppp_comp $(LP64DIR)/ppp_ahdl $(LP64DIR)/*.o $(LP64DIR)/*~ $(LP64DIR)/core
+++ /dev/null
-#
-# Makefile for 64-bit STREAMS modules for Solaris 2 on x64 with gcc.
-#
-# $Id: Makefile.sol2gcc-64x,v 1.1 2005/06/26 23:53:17 carlsonj Exp $
-#
-
-include Makedefs.sol2
-
-# gcc flags for LP64 compilation / linkage
-COPTS += -finline -fno-inline-functions -fno-builtin -fno-asm \
- -nodefaultlibs -D__sun -m64 -mtune=opteron -Ui386 \
- -U__i386 -fno-strict-aliasing -fno-unit-at-a-time \
- -fno-optimize-sibling-calls -O2 -D_ASM_INLINES \
- -ffreestanding -mcmodel=kernel -mno-red-zone -gdwarf-2 \
- -std=gnu89 -D_KERNEL -D_SYSCALL32 -D_SYSCALL32_IMPL \
- -D_ELF64 -Dsun -D__sun -D__SVR4
-
-# subdirectory where 64-bit objects / binaries will be placed
-LP64DIR = amd64
-
-# Name of legacy Makefile (for 32-bit binaries)
-STD_MAKE = Makefile.sol2gcc
-
-COMP_OBJS = $(LP64DIR)/ppp_comp.o $(LP64DIR)/bsd-comp.o \
- $(LP64DIR)/deflate.o $(LP64DIR)/zlib.o $(LP64DIR)/vjcompress.o \
- $(LP64DIR)/ppp_comp_mod.o
-
-all: std_objs $(LP64DIR) ppp ppp_ahdl ppp_comp
-
-std_objs:
- $(MAKE) -f $(STD_MAKE) all
-
-ppp: $(LP64DIR)/ppp.o $(LP64DIR)/ppp_mod.o
- $(LD) -r -o $(LP64DIR)/$@ $(LP64DIR)/ppp.o $(LP64DIR)/ppp_mod.o
- chmod +x $(LP64DIR)/$@
-
-ppp_ahdl: $(LP64DIR)/ppp_ahdlc.o $(LP64DIR)/ppp_ahdlc_mod.o
- $(LD) -r -o $(LP64DIR)/$@ $(LP64DIR)/ppp_ahdlc.o \
- $(LP64DIR)/ppp_ahdlc_mod.o
- chmod +x $(LP64DIR)/$@
-
-ppp_comp: $(COMP_OBJS)
- $(LD) -r -o $(LP64DIR)/$@ $(COMP_OBJS)
- chmod +x $(LP64DIR)/$@
-
-$(LP64DIR)/bsd-comp.o: ../modules/bsd-comp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/deflate.o: ../modules/deflate.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp.o: ppp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_mod.o: ppp_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_ahdlc_mod.o: ppp_ahdlc_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_ahdlc.o: ppp_ahdlc.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_comp.o: ppp_comp.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/ppp_comp_mod.o: ppp_comp_mod.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/vjcompress.o: ../modules/vjcompress.c
- $(CC) $(CFLAGS) -c $? -o $@
-$(LP64DIR)/zlib.o: ../common/zlib.c
- $(CC) $(CFLAGS) -c $? -o $@
-
-$(LP64DIR):
- mkdir -m 755 -p $@
-
-install:
- /usr/sbin/modunload -i 0
- cp ppp ppp.conf /kernel/drv
- cp ppp_comp ppp_ahdl /kernel/strmod
- cp $(LP64DIR)/ppp /kernel/drv/$(LP64DIR)
- cp $(LP64DIR)/ppp_comp $(LP64DIR)/ppp_ahdl /kernel/strmod/$(LP64DIR)
- if grep clone:ppp /etc/minor_perm; then :; else \
- echo clone:ppp 0644 root sys >>/etc/minor_perm; fi
- /usr/sbin/rem_drv ppp 2>/dev/null || true
- /usr/sbin/modunload -i 0
- /usr/sbin/add_drv ppp
-
-SRCS = ppp.c ppp_mod.c ppp_ahdlc.c ppp_ahdlc_mod.c \
- ppp_comp.c ../modules/bsd-comp.c ../modules/deflate.c \
- ../common/zlib.c ../modules/vjcompress.c ppp_comp_mod.c
-
-lint:
- $(LINT64) $(SRCS)
-
-lint-32:
- $(LINT32) $(SRCS)
-
-clean:
- $(MAKE) -f $(STD_MAKE) clean
- rm -f $(LP64DIR)/ppp $(LP64DIR)/ppp_comp $(LP64DIR)/ppp_ahdl $(LP64DIR)/*.o $(LP64DIR)/*~ $(LP64DIR)/core
+++ /dev/null
-#
-# ppp top level makefile for SVR4 and Solaris 2
-#
-# $Id: Makefile.top,v 1.3 2004/11/01 09:31:07 paulus Exp $
-#
-
-include Makedefs.com
-
-all:
- cd chat; $(MAKE) all
- cd pppd; $(MAKE) all
- cd pppstats; $(MAKE) all
- cd pppdump; $(MAKE) all
- cd solaris; $(MAKE) all
-
-install: $(BINDIR) $(MANDIR)/man8 install-progs
-
-install-progs:
- cd chat; $(MAKE) install
- cd pppd; $(MAKE) install
- cd pppstats; $(MAKE) install
- cd pppdump; $(MAKE) install
-
-install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \
- $(ETCDIR)/chap-secrets
-
-install-modules:
- cd solaris; $(MAKE) install
-
-$(ETCDIR)/options:
- cp etc.ppp/options $@
- chmod go-w $@
-$(ETCDIR)/pap-secrets:
- $(INSTALL) -f $(ETCDIR) -m 600 etc.ppp/pap-secrets
-$(ETCDIR)/chap-secrets:
- $(INSTALL) -f $(ETCDIR) -m 600 etc.ppp/chap-secrets
-
-$(BINDIR):
- mkdir -m 755 -p $@
-$(MANDIR)/man8:
- mkdir -m 755 -p $@
-$(ETCDIR):
- mkdir -m 755 -p $@
-
-clean:
- rm -f *~
- cd chat; $(MAKE) clean
- cd pppd; $(MAKE) clean
- cd pppstats; $(MAKE) clean
- cd pppdump; $(MAKE) clean
- cd solaris; $(MAKE) clean
-
-# no tests yet, one day...
-installcheck:
- true
+++ /dev/null
-/*
- * ppp.c - STREAMS multiplexing pseudo-device driver for PPP.
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/errno.h>
-#ifdef __osf__
-#include <sys/ioctl.h>
-#include <sys/cmn_err.h>
-#define queclass(mp) ((mp)->b_band & QPCTL)
-#else
-#include <sys/ioccom.h>
-#endif
-#include <sys/time.h>
-#ifdef SVR4
-#include <sys/cmn_err.h>
-#include <sys/conf.h>
-#include <sys/dlpi.h>
-#include <sys/ddi.h>
-#ifdef SOL2
-#include <sys/ksynch.h>
-#include <sys/kstat.h>
-#include <sys/sunddi.h>
-#include <sys/ethernet.h>
-#else
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#endif /* SOL2 */
-#else /* not SVR4 */
-#include <sys/user.h>
-#endif /* SVR4 */
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-#include "ppp_mod.h"
-
-/*
- * Modifications marked with #ifdef PRIOQ are for priority queueing of
- * interactive traffic, and are due to Marko Zec <zec@japa.tel.fer.hr>.
- */
-#ifdef PRIOQ
-#endif /* PRIOQ */
-
-#include <netinet/in.h> /* leave this outside of PRIOQ for htons */
-
-/*
- * The IP module may use this SAP value for IP packets.
- */
-#ifndef ETHERTYPE_IP
-#define ETHERTYPE_IP 0x800
-#endif
-
-#if !defined(ETHERTYPE_IPV6)
-#define ETHERTYPE_IPV6 0x86dd
-#endif /* !defined(ETHERTYPE_IPV6) */
-
-#if !defined(ETHERTYPE_ALLSAP) && defined(SOL2)
-#define ETHERTYPE_ALLSAP 0
-#endif /* !defined(ETHERTYPE_ALLSAP) && defined(SOL2) */
-
-#if !defined(PPP_ALLSAP) && defined(SOL2)
-#define PPP_ALLSAP PPP_ALLSTATIONS
-#endif /* !defined(PPP_ALLSAP) && defined(SOL2) */
-
-extern time_t time;
-
-#ifdef SOL2
-/*
- * We use this reader-writer lock to ensure that the lower streams
- * stay connected to the upper streams while the lower-side put and
- * service procedures are running. Essentially it is an existence
- * lock for the upper stream associated with each lower stream.
- */
-krwlock_t ppp_lower_lock;
-#define LOCK_LOWER_W rw_enter(&ppp_lower_lock, RW_WRITER)
-#define LOCK_LOWER_R rw_enter(&ppp_lower_lock, RW_READER)
-#define TRYLOCK_LOWER_R rw_tryenter(&ppp_lower_lock, RW_READER)
-#define UNLOCK_LOWER rw_exit(&ppp_lower_lock)
-
-#define MT_ENTER(x) mutex_enter(x)
-#define MT_EXIT(x) mutex_exit(x)
-
-/*
- * Notes on multithreaded implementation for Solaris 2:
- *
- * We use an inner perimeter around each queue pair and an outer
- * perimeter around the whole driver. The inner perimeter is
- * entered exclusively for all entry points (open, close, put,
- * service). The outer perimeter is entered exclusively for open
- * and close and shared for put and service. This is all done for
- * us by the streams framework.
- *
- * I used to think that the perimeters were entered for the lower
- * streams' put and service routines as well as for the upper streams'.
- * Because of problems experienced by people, and after reading the
- * documentation more closely, I now don't think that is true. So we
- * now use ppp_lower_lock to give us an existence guarantee on the
- * upper stream controlling each lower stream.
- *
- * Shared entry to the outer perimeter protects the existence of all
- * the upper streams and their upperstr_t structures, and guarantees
- * that the following fields of any upperstr_t won't change:
- * nextmn, next, nextppa. It guarantees that the lowerq field of an
- * upperstr_t won't go from non-zero to zero, that the global `ppas'
- * won't change and that the no lower stream will get unlinked.
- *
- * Shared (reader) access to ppa_lower_lock guarantees that no lower
- * stream will be unlinked and that the lowerq field of all upperstr_t
- * structures won't change.
- */
-
-#else /* SOL2 */
-#define LOCK_LOWER_W 0
-#define LOCK_LOWER_R 0
-#define TRYLOCK_LOWER_R 1
-#define UNLOCK_LOWER 0
-#define MT_ENTER(x) 0
-#define MT_EXIT(x) 0
-
-#endif /* SOL2 */
-
-/*
- * Private information; one per upper stream.
- */
-typedef struct upperstr {
- minor_t mn; /* minor device number */
- struct upperstr *nextmn; /* next minor device */
- queue_t *q; /* read q associated with this upper stream */
- int flags; /* flag bits, see below */
- int state; /* current DLPI state */
- int sap; /* service access point */
- int req_sap; /* which SAP the DLPI client requested */
- struct upperstr *ppa; /* control stream for our ppa */
- struct upperstr *next; /* next stream for this ppa */
- uint ioc_id; /* last ioctl ID for this stream */
- enum NPmode npmode; /* what to do with packets on this SAP */
- unsigned char rblocked; /* flow control has blocked upper read strm */
- /* N.B. rblocked is only changed by control stream's put/srv procs */
- /*
- * There is exactly one control stream for each PPA.
- * The following fields are only used for control streams.
- */
- int ppa_id;
- queue_t *lowerq; /* write queue attached below this PPA */
- struct upperstr *nextppa; /* next control stream */
- int mru;
- int mtu;
- struct pppstat stats; /* statistics */
- time_t last_sent; /* time last NP packet sent */
- time_t last_recv; /* time last NP packet rcvd */
-#ifdef SOL2
- kmutex_t stats_lock; /* lock for stats updates */
- kstat_t *kstats; /* stats for netstat */
-#endif /* SOL2 */
-#ifdef LACHTCP
- int ifflags;
- char ifname[IFNAMSIZ];
- struct ifstats ifstats;
-#endif /* LACHTCP */
-} upperstr_t;
-
-/* Values for flags */
-#define US_PRIV 1 /* stream was opened by superuser */
-#define US_CONTROL 2 /* stream is a control stream */
-#define US_BLOCKED 4 /* flow ctrl has blocked lower write stream */
-#define US_LASTMOD 8 /* no PPP modules below us */
-#define US_DBGLOG 0x10 /* log various occurrences */
-#define US_RBLOCKED 0x20 /* flow ctrl has blocked upper read stream */
-
-#if defined(SOL2)
-#if DL_CURRENT_VERSION >= 2
-#define US_PROMISC 0x40 /* stream is promiscuous */
-#endif /* DL_CURRENT_VERSION >= 2 */
-#define US_RAWDATA 0x80 /* raw M_DATA, no DLPI header */
-#endif /* defined(SOL2) */
-
-#ifdef PRIOQ
-static u_char max_band=0;
-static u_char def_band=0;
-
-#define IPPORT_DEFAULT 65535
-
-/*
- * Port priority table
- * Highest priority ports are listed first, lowest are listed last.
- * ICMP & packets using unlisted ports will be treated as "default".
- * If IPPORT_DEFAULT is not listed here, "default" packets will be
- * assigned lowest priority.
- * Each line should be terminated with "0".
- * Line containing only "0" marks the end of the list.
- */
-
-static u_short prioq_table[]= {
- 113, 53, 0,
- 22, 23, 513, 517, 518, 0,
- 514, 21, 79, 111, 0,
- 25, 109, 110, 0,
- IPPORT_DEFAULT, 0,
- 20, 70, 80, 8001, 8008, 8080, 0, /* 8001,8008,8080 - common proxy ports */
-0 };
-
-#endif /* PRIOQ */
-
-
-static upperstr_t *minor_devs = NULL;
-static upperstr_t *ppas = NULL;
-
-#ifdef SVR4
-static int pppopen(queue_t *, dev_t *, int, int, cred_t *);
-static int pppclose(queue_t *, int, cred_t *);
-#else
-static int pppopen(queue_t *, int, int, int);
-static int pppclose(queue_t *, int);
-#endif /* SVR4 */
-static int pppurput(queue_t *, mblk_t *);
-static int pppuwput(queue_t *, mblk_t *);
-static int pppursrv(queue_t *);
-static int pppuwsrv(queue_t *);
-static int ppplrput(queue_t *, mblk_t *);
-static int ppplwput(queue_t *, mblk_t *);
-static int ppplrsrv(queue_t *);
-static int ppplwsrv(queue_t *);
-#ifndef NO_DLPI
-static void dlpi_request(queue_t *, mblk_t *, upperstr_t *);
-static void dlpi_error(queue_t *, upperstr_t *, int, int, int);
-static void dlpi_ok(queue_t *, int);
-#endif
-static int send_data(mblk_t *, upperstr_t *);
-static void new_ppa(queue_t *, mblk_t *);
-static void attach_ppa(queue_t *, mblk_t *);
-#ifndef NO_DLPI
-static void detach_ppa(queue_t *, mblk_t *);
-#endif
-static void detach_lower(queue_t *, mblk_t *);
-static void debug_dump(queue_t *, mblk_t *);
-static upperstr_t *find_dest(upperstr_t *, int);
-#if defined(SOL2)
-static upperstr_t *find_promisc(upperstr_t *, int);
-static mblk_t *prepend_ether(upperstr_t *, mblk_t *, int);
-static mblk_t *prepend_udind(upperstr_t *, mblk_t *, int);
-static void promisc_sendup(upperstr_t *, mblk_t *, int, int);
-#endif /* defined(SOL2) */
-static int putctl2(queue_t *, int, int, int);
-static int putctl4(queue_t *, int, int, int);
-static int pass_packet(upperstr_t *ppa, mblk_t *mp, int outbound);
-#ifdef FILTER_PACKETS
-static int ip_hard_filter(upperstr_t *ppa, mblk_t *mp, int outbound);
-#endif /* FILTER_PACKETS */
-
-#define PPP_ID 0xb1a6
-static struct module_info ppp_info = {
-#ifdef PRIOQ
- PPP_ID, "ppp", 0, 512, 512, 384
-#else
- PPP_ID, "ppp", 0, 512, 512, 128
-#endif /* PRIOQ */
-};
-
-static struct qinit pppurint = {
- pppurput, pppursrv, pppopen, pppclose, NULL, &ppp_info, NULL
-};
-
-static struct qinit pppuwint = {
- pppuwput, pppuwsrv, NULL, NULL, NULL, &ppp_info, NULL
-};
-
-static struct qinit ppplrint = {
- ppplrput, ppplrsrv, NULL, NULL, NULL, &ppp_info, NULL
-};
-
-static struct qinit ppplwint = {
- ppplwput, ppplwsrv, NULL, NULL, NULL, &ppp_info, NULL
-};
-
-#ifdef LACHTCP
-extern struct ifstats *ifstats;
-int pppdevflag = 0;
-#endif
-
-struct streamtab pppinfo = {
- &pppurint, &pppuwint,
- &ppplrint, &ppplwint
-};
-
-int ppp_count;
-
-/*
- * How we maintain statistics.
- */
-#ifdef SOL2
-#define INCR_IPACKETS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++; \
- }
-#define INCR_IERRORS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++; \
- }
-#define INCR_OPACKETS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++; \
- }
-#define INCR_OERRORS(ppa) \
- if (ppa->kstats != 0) { \
- KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++; \
- }
-#endif
-
-#ifdef LACHTCP
-#define INCR_IPACKETS(ppa) ppa->ifstats.ifs_ipackets++;
-#define INCR_IERRORS(ppa) ppa->ifstats.ifs_ierrors++;
-#define INCR_OPACKETS(ppa) ppa->ifstats.ifs_opackets++;
-#define INCR_OERRORS(ppa) ppa->ifstats.ifs_oerrors++;
-#endif
-
-/*
- * STREAMS driver entry points.
- */
-static int
-#ifdef SVR4
-pppopen(q, devp, oflag, sflag, credp)
- queue_t *q;
- dev_t *devp;
- int oflag, sflag;
- cred_t *credp;
-#else
-pppopen(q, dev, oflag, sflag)
- queue_t *q;
- int dev; /* really dev_t */
- int oflag, sflag;
-#endif
-{
- upperstr_t *up;
- upperstr_t **prevp;
- minor_t mn;
-#ifdef PRIOQ
- u_short *ptr;
- u_char new_band;
-#endif /* PRIOQ */
-
- if (q->q_ptr)
- DRV_OPEN_OK(dev); /* device is already open */
-
-#ifdef PRIOQ
- /* Calculate max_bband & def_band from definitions in prioq.h
- This colud be done at some more approtiate time (less often)
- but this way it works well so I'll just leave it here */
-
- max_band = 1;
- def_band = 0;
- ptr = prioq_table;
- while (*ptr) {
- new_band = 1;
- while (*ptr)
- if (*ptr++ == IPPORT_DEFAULT) {
- new_band = 0;
- def_band = max_band;
- }
- max_band += new_band;
- ptr++;
- }
- if (def_band)
- def_band = max_band - def_band;
- --max_band;
-#endif /* PRIOQ */
-
- if (sflag == CLONEOPEN) {
- mn = 0;
- for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
- if (up->mn != mn)
- break;
- ++mn;
- }
- } else {
-#ifdef SVR4
- mn = getminor(*devp);
-#else
- mn = minor(dev);
-#endif
- for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
- if (up->mn >= mn)
- break;
- }
- if (up->mn == mn) {
- /* this can't happen */
- q->q_ptr = WR(q)->q_ptr = (caddr_t) up;
- DRV_OPEN_OK(dev);
- }
- }
-
- /*
- * Construct a new minor node.
- */
- up = (upperstr_t *) ALLOC_SLEEP(sizeof(upperstr_t));
- bzero((caddr_t) up, sizeof(upperstr_t));
- if (up == 0) {
- DPRINT("pppopen: out of kernel memory\n");
- OPEN_ERROR(ENXIO);
- }
- up->nextmn = *prevp;
- *prevp = up;
- up->mn = mn;
-#ifdef SVR4
- *devp = makedevice(getmajor(*devp), mn);
-#endif
- up->q = q;
- if (NOTSUSER() == 0)
- up->flags |= US_PRIV;
-#ifndef NO_DLPI
- up->state = DL_UNATTACHED;
-#endif
-#ifdef LACHTCP
- up->ifflags = IFF_UP | IFF_POINTOPOINT;
-#endif
- up->sap = -1;
- up->last_sent = up->last_recv = time;
- up->npmode = NPMODE_DROP;
- q->q_ptr = (caddr_t) up;
- WR(q)->q_ptr = (caddr_t) up;
- noenable(WR(q));
-#ifdef SOL2
- mutex_init(&up->stats_lock, NULL, MUTEX_DRIVER, NULL);
-#endif
- ++ppp_count;
-
- qprocson(q);
- DRV_OPEN_OK(makedev(major(dev), mn));
-}
-
-static int
-#ifdef SVR4
-pppclose(q, flag, credp)
- queue_t *q;
- int flag;
- cred_t *credp;
-#else
-pppclose(q, flag)
- queue_t *q;
- int flag;
-#endif
-{
- upperstr_t *up, **upp;
- upperstr_t *as, *asnext;
- upperstr_t **prevp;
-
- qprocsoff(q);
-
- up = (upperstr_t *) q->q_ptr;
- if (up == 0) {
- DPRINT("pppclose: q_ptr = 0\n");
- return 0;
- }
- if (up->flags & US_DBGLOG)
- DPRINT2("ppp/%d: close, flags=%x\n", up->mn, up->flags);
- if (up->flags & US_CONTROL) {
-#ifdef LACHTCP
- struct ifstats *ifp, *pifp;
-#endif
- if (up->lowerq != 0) {
- /* Gack! the lower stream should have be unlinked earlier! */
- DPRINT1("ppp%d: lower stream still connected on close?\n",
- up->mn);
- LOCK_LOWER_W;
- up->lowerq->q_ptr = 0;
- RD(up->lowerq)->q_ptr = 0;
- up->lowerq = 0;
- UNLOCK_LOWER;
- }
-
- /*
- * This stream represents a PPA:
- * For all streams attached to the PPA, clear their
- * references to this PPA.
- * Then remove this PPA from the list of PPAs.
- */
- for (as = up->next; as != 0; as = asnext) {
- asnext = as->next;
- as->next = 0;
- as->ppa = 0;
- if (as->flags & US_BLOCKED) {
- as->flags &= ~US_BLOCKED;
- flushq(WR(as->q), FLUSHDATA);
- }
- }
- for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa)
- if (*upp == up) {
- *upp = up->nextppa;
- break;
- }
-#ifdef LACHTCP
- /* Remove the statistics from the active list. */
- for (ifp = ifstats, pifp = 0; ifp; ifp = ifp->ifs_next) {
- if (ifp == &up->ifstats) {
- if (pifp)
- pifp->ifs_next = ifp->ifs_next;
- else
- ifstats = ifp->ifs_next;
- break;
- }
- pifp = ifp;
- }
-#endif
- } else {
- /*
- * If this stream is attached to a PPA,
- * remove it from the PPA's list.
- */
- if ((as = up->ppa) != 0) {
- for (; as->next != 0; as = as->next)
- if (as->next == up) {
- as->next = up->next;
- break;
- }
- }
- }
-
-#ifdef SOL2
- if (up->kstats)
- kstat_delete(up->kstats);
- mutex_destroy(&up->stats_lock);
-#endif
-
- q->q_ptr = NULL;
- WR(q)->q_ptr = NULL;
-
- for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) {
- if (*prevp == up) {
- *prevp = up->nextmn;
- break;
- }
- }
- FREE(up, sizeof(upperstr_t));
- --ppp_count;
-
- return 0;
-}
-
-/*
- * A message from on high. We do one of three things:
- * - qreply()
- * - put the message on the lower write stream
- * - queue it for our service routine
- */
-static int
-pppuwput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *ppa, *nps;
- struct iocblk *iop;
- struct linkblk *lb;
-#ifdef LACHTCP
- struct ifreq *ifr;
- int i;
-#endif
- queue_t *lq;
- int error, n, sap;
- mblk_t *mq;
- struct ppp_idle *pip;
-#ifdef PRIOQ
- queue_t *tlq;
-#endif /* PRIOQ */
-#ifdef NO_DLPI
- upperstr_t *os;
-#endif
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("pppuwput: q_ptr = 0!\n");
- return 0;
- }
- if (mp == 0) {
- DPRINT1("pppuwput/%d: mp = 0!\n", us->mn);
- return 0;
- }
- if (mp->b_datap == 0) {
- DPRINT1("pppuwput/%d: mp->b_datap = 0!\n", us->mn);
- return 0;
- }
- switch (mp->b_datap->db_type) {
-#ifndef NO_DLPI
- case M_PCPROTO:
- case M_PROTO:
- dlpi_request(q, mp, us);
- break;
-#endif /* NO_DLPI */
-
- case M_DATA:
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: uwput M_DATA len=%d flags=%x\n",
- us->mn, msgdsize(mp), us->flags);
- if (us->ppa == 0 || msgdsize(mp) > us->ppa->mtu + PPP_HDRLEN
-#ifndef NO_DLPI
- || (us->flags & US_CONTROL) == 0
-#endif /* NO_DLPI */
- ) {
- DPRINT1("pppuwput: junk data len=%d\n", msgdsize(mp));
- freemsg(mp);
- break;
- }
-#ifdef NO_DLPI
- /* pass_packet frees the packet on returning 0 */
- if ((us->flags & US_CONTROL) == 0 && !pass_packet(us, mp, 1))
- break;
-#endif
- if (!send_data(mp, us) && !putq(q, mp))
- freemsg(mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: ioctl %x count=%d\n",
- us->mn, iop->ioc_cmd, iop->ioc_count);
- switch (iop->ioc_cmd) {
-#if defined(SOL2)
- case DLIOCRAW: /* raw M_DATA mode */
- us->flags |= US_RAWDATA;
- error = 0;
- break;
-#endif /* defined(SOL2) */
- case I_LINK:
- if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl I_LINK b_cont = 0!\n", us->mn);
- break;
- }
- lb = (struct linkblk *) mp->b_cont->b_rptr;
- lq = lb->l_qbot;
- if (lq == 0) {
- DPRINT1("pppuwput/%d: ioctl I_LINK l_qbot = 0!\n", us->mn);
- break;
- }
- LOCK_LOWER_W;
- us->lowerq = lq;
- lq->q_ptr = (caddr_t) q;
- RD(lq)->q_ptr = (caddr_t) us->q;
- UNLOCK_LOWER;
- iop->ioc_count = 0;
- error = 0;
- us->flags &= ~US_LASTMOD;
- /* Unblock upper streams which now feed this lower stream. */
- qenable(q);
- /* Send useful information down to the modules which
- are now linked below us. */
- putctl2(lq, M_CTL, PPPCTL_UNIT, us->ppa_id);
- putctl4(lq, M_CTL, PPPCTL_MRU, us->mru);
- putctl4(lq, M_CTL, PPPCTL_MTU, us->mtu);
-#ifdef PRIOQ
- /* Lower tty driver's queue hiwat/lowat from default 4096/128
- to 256/128 since we don't want queueing of data on
- output to physical device */
-
- freezestr(lq);
- for (tlq = lq; tlq->q_next != NULL; tlq = tlq->q_next)
- ;
- strqset(tlq, QHIWAT, 0, 256);
- strqset(tlq, QLOWAT, 0, 128);
- unfreezestr(lq);
-#endif /* PRIOQ */
- break;
-
- case I_UNLINK:
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl I_UNLINK b_cont = 0!\n", us->mn);
- break;
- }
- lb = (struct linkblk *) mp->b_cont->b_rptr;
-#if DEBUG
- if (us->lowerq != lb->l_qbot) {
- DPRINT2("ppp unlink: lowerq=%x qbot=%x\n",
- us->lowerq, lb->l_qbot);
- break;
- }
-#endif
- iop->ioc_count = 0;
- qwriter(q, mp, detach_lower, PERIM_OUTER);
- /* mp is now gone */
- error = -1;
- break;
-
- case PPPIO_NEWPPA:
- if (us->flags & US_CONTROL)
- break;
- if ((us->flags & US_PRIV) == 0) {
- error = EPERM;
- break;
- }
- /* Arrange to return an int */
- if ((mq = mp->b_cont) == 0
- || mq->b_datap->db_lim - mq->b_rptr < sizeof(int)) {
- mq = allocb(sizeof(int), BPRI_HI);
- if (mq == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = mq;
- mq->b_cont = 0;
- }
- iop->ioc_count = sizeof(int);
- mq->b_wptr = mq->b_rptr + sizeof(int);
- qwriter(q, mp, new_ppa, PERIM_OUTER);
- /* mp is now gone */
- error = -1;
- break;
-
- case PPPIO_ATTACH:
- /* like dlpi_attach, for programs which can't write to
- the stream (like pppstats) */
- if (iop->ioc_count != sizeof(int) || us->ppa != 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_ATTACH b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
- if (ppa->ppa_id == n)
- break;
- if (ppa == 0)
- break;
- us->ppa = ppa;
- iop->ioc_count = 0;
- qwriter(q, mp, attach_ppa, PERIM_OUTER);
- /* mp is now gone */
- error = -1;
- break;
-
-#ifdef NO_DLPI
- case PPPIO_BIND:
- /* Attach to a given SAP. */
- if (iop->ioc_count != sizeof(int) || us->ppa == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_BIND b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- /* n must be a valid PPP network protocol number. */
- if (n < 0x21 || n > 0x3fff || (n & 0x101) != 1)
- break;
- /* check that no other stream is bound to this sap already. */
- for (os = us->ppa; os != 0; os = os->next)
- if (os->sap == n)
- break;
- if (os != 0)
- break;
- us->sap = n;
- iop->ioc_count = 0;
- error = 0;
- break;
-#endif /* NO_DLPI */
-
- case PPPIO_MRU:
- if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_MRU b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n <= 0 || n > PPP_MAXMRU)
- break;
- if (n < PPP_MRU)
- n = PPP_MRU;
- us->mru = n;
- if (us->lowerq)
- putctl4(us->lowerq, M_CTL, PPPCTL_MRU, n);
- error = 0;
- iop->ioc_count = 0;
- break;
-
- case PPPIO_MTU:
- if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_MTU b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n <= 0 || n > PPP_MAXMTU)
- break;
- us->mtu = n;
-#ifdef LACHTCP
- /* The MTU reported in netstat, not used as IP max packet size! */
- us->ifstats.ifs_mtu = n;
-#endif
- if (us->lowerq)
- putctl4(us->lowerq, M_CTL, PPPCTL_MTU, n);
- error = 0;
- iop->ioc_count = 0;
- break;
-
- case PPPIO_LASTMOD:
- us->flags |= US_LASTMOD;
- error = 0;
- break;
-
- case PPPIO_DEBUG:
- if (iop->ioc_count != sizeof(int))
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_DEBUG b_cont = 0!\n", us->mn);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
- qwriter(q, mp, debug_dump, PERIM_OUTER);
- /* mp is now gone */
- error = -1;
- } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) {
- DPRINT1("ppp/%d: debug log enabled\n", us->mn);
- us->flags |= US_DBGLOG;
- iop->ioc_count = 0;
- error = 0;
- } else {
- if (us->ppa == 0 || us->ppa->lowerq == 0)
- break;
- putnext(us->ppa->lowerq, mp);
- /* mp is now gone */
- error = -1;
- }
- break;
-
- case PPPIO_NPMODE:
- if (iop->ioc_count != 2 * sizeof(int))
- break;
- if ((us->flags & US_CONTROL) == 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("pppuwput/%d: ioctl PPPIO_NPMODE b_cont = 0!\n", us->mn);
- break;
- }
- sap = ((int *)mp->b_cont->b_rptr)[0];
- for (nps = us->next; nps != 0; nps = nps->next) {
- if (us->flags & US_DBGLOG)
- DPRINT2("us = 0x%x, us->next->sap = 0x%x\n", nps, nps->sap);
- if (nps->sap == sap)
- break;
- }
- if (nps == 0) {
- if (us->flags & US_DBGLOG)
- DPRINT2("ppp/%d: no stream for sap %x\n", us->mn, sap);
- break;
- }
- /* XXX possibly should use qwriter here */
- nps->npmode = (enum NPmode) ((int *)mp->b_cont->b_rptr)[1];
- if (nps->npmode != NPMODE_QUEUE && (nps->flags & US_BLOCKED) != 0)
- qenable(WR(nps->q));
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case PPPIO_GIDLE:
- if ((ppa = us->ppa) == 0)
- break;
- mq = allocb(sizeof(struct ppp_idle), BPRI_HI);
- if (mq == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = mq;
- mq->b_cont = 0;
- pip = (struct ppp_idle *) mq->b_wptr;
- pip->xmit_idle = time - ppa->last_sent;
- pip->recv_idle = time - ppa->last_recv;
- mq->b_wptr += sizeof(struct ppp_idle);
- iop->ioc_count = sizeof(struct ppp_idle);
- error = 0;
- break;
-
-#ifdef LACHTCP
- case SIOCSIFNAME:
- /* Sent from IP down to us. Attach the ifstats structure. */
- if (iop->ioc_count != sizeof(struct ifreq) || us->ppa == 0)
- break;
- ifr = (struct ifreq *)mp->b_cont->b_rptr;
- /* Find the unit number in the interface name. */
- for (i = 0; i < IFNAMSIZ; i++) {
- if (ifr->ifr_name[i] == 0 ||
- (ifr->ifr_name[i] >= '0' &&
- ifr->ifr_name[i] <= '9'))
- break;
- else
- us->ifname[i] = ifr->ifr_name[i];
- }
- us->ifname[i] = 0;
-
- /* Convert the unit number to binary. */
- for (n = 0; i < IFNAMSIZ; i++) {
- if (ifr->ifr_name[i] == 0) {
- break;
- }
- else {
- n = n * 10 + ifr->ifr_name[i] - '0';
- }
- }
-
- /* Verify the ppa. */
- if (us->ppa->ppa_id != n)
- break;
- ppa = us->ppa;
-
- /* Set up the netstat block. */
- strncpy (ppa->ifname, us->ifname, IFNAMSIZ);
-
- ppa->ifstats.ifs_name = ppa->ifname;
- ppa->ifstats.ifs_unit = n;
- ppa->ifstats.ifs_active = us->state != DL_UNBOUND;
- ppa->ifstats.ifs_mtu = ppa->mtu;
-
- /* Link in statistics used by netstat. */
- ppa->ifstats.ifs_next = ifstats;
- ifstats = &ppa->ifstats;
-
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case SIOCGIFFLAGS:
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- ((struct iocblk_in *)iop)->ioc_ifflags = us->ifflags;
- error = 0;
- break;
-
- case SIOCSIFFLAGS:
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- us->ifflags = ((struct iocblk_in *)iop)->ioc_ifflags;
- error = 0;
- break;
-
- case SIOCSIFADDR:
- if (!(us->flags & US_CONTROL)) {
- if (us->ppa)
- us = us->ppa;
- else
- break;
- }
- us->ifflags |= IFF_RUNNING;
- ((struct iocblk_in *)iop)->ioc_ifflags |= IFF_RUNNING;
- error = 0;
- break;
-
- case SIOCSIFMTU:
- /*
- * Vanilla SVR4 systems don't handle SIOCSIFMTU, rather
- * they take the MTU from the DL_INFO_ACK we sent in response
- * to their DL_INFO_REQ. Fortunately, they will update the
- * MTU if we send an unsolicited DL_INFO_ACK up.
- */
- if ((mq = allocb(sizeof(dl_info_req_t), BPRI_HI)) == 0)
- break; /* should do bufcall */
- ((union DL_primitives *)mq->b_rptr)->dl_primitive = DL_INFO_REQ;
- mq->b_wptr = mq->b_rptr + sizeof(dl_info_req_t);
- dlpi_request(q, mq, us);
- /* mp is now gone */
- error = -1;
- break;
-
- case SIOCGIFNETMASK:
- case SIOCSIFNETMASK:
- case SIOCGIFADDR:
- case SIOCGIFDSTADDR:
- case SIOCSIFDSTADDR:
- case SIOCGIFMETRIC:
- error = 0;
- break;
-#endif /* LACHTCP */
-
- default:
- if (us->ppa == 0 || us->ppa->lowerq == 0)
- break;
- us->ioc_id = iop->ioc_id;
- error = -1;
- switch (iop->ioc_cmd) {
- case PPPIO_GETSTAT:
- case PPPIO_GETCSTAT:
- if (us->flags & US_LASTMOD) {
- error = EINVAL;
- break;
- }
- putnext(us->ppa->lowerq, mp);
- break;
- default:
- if (us->flags & US_PRIV)
- putnext(us->ppa->lowerq, mp);
- else {
- DPRINT1("ppp ioctl %x rejected\n", iop->ioc_cmd);
- error = EPERM;
- }
- break;
- }
- break;
- }
-
- if (error > 0) {
- iop->ioc_error = error;
- mp->b_datap->db_type = M_IOCNAK;
- qreply(q, mp);
- } else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- }
- break;
-
- case M_FLUSH:
- if (us->flags & US_DBGLOG)
- DPRINT2("ppp/%d: flush %x\n", us->mn, *mp->b_rptr);
- if (*mp->b_rptr & FLUSHW)
- flushq(q, FLUSHDATA);
- if (*mp->b_rptr & FLUSHR) {
- *mp->b_rptr &= ~FLUSHW;
- qreply(q, mp);
- } else
- freemsg(mp);
- break;
-
- default:
- freemsg(mp);
- break;
- }
- return 0;
-}
-
-#ifndef NO_DLPI
-static void
-dlpi_request(q, mp, us)
- queue_t *q;
- mblk_t *mp;
- upperstr_t *us;
-{
- union DL_primitives *d = (union DL_primitives *) mp->b_rptr;
- int size = mp->b_wptr - mp->b_rptr;
- mblk_t *reply, *np;
- upperstr_t *ppa, *os;
- int sap, len;
- dl_info_ack_t *info;
- dl_bind_ack_t *ackp;
-#if DL_CURRENT_VERSION >= 2
- dl_phys_addr_ack_t *paddrack;
- static struct ether_addr eaddr = {0};
-#endif
-
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: dlpi prim %x len=%d\n", us->mn,
- d->dl_primitive, size);
- switch (d->dl_primitive) {
- case DL_INFO_REQ:
- if (size < sizeof(dl_info_req_t))
- goto badprim;
- if ((reply = allocb(sizeof(dl_info_ack_t), BPRI_HI)) == 0)
- break; /* should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- info = (dl_info_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_info_ack_t);
- bzero((caddr_t) info, sizeof(dl_info_ack_t));
- info->dl_primitive = DL_INFO_ACK;
- info->dl_max_sdu = us->ppa? us->ppa->mtu: PPP_MAXMTU;
- info->dl_min_sdu = 1;
- info->dl_addr_length = sizeof(uint);
- info->dl_mac_type = DL_ETHER; /* a bigger lie */
- info->dl_current_state = us->state;
- info->dl_service_mode = DL_CLDLS;
- info->dl_provider_style = DL_STYLE2;
-#if DL_CURRENT_VERSION >= 2
- info->dl_sap_length = sizeof(uint);
- info->dl_version = DL_CURRENT_VERSION;
-#endif
- qreply(q, reply);
- break;
-
- case DL_ATTACH_REQ:
- if (size < sizeof(dl_attach_req_t))
- goto badprim;
- if (us->state != DL_UNATTACHED || us->ppa != 0) {
- dlpi_error(q, us, DL_ATTACH_REQ, DL_OUTSTATE, 0);
- break;
- }
- for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
- if (ppa->ppa_id == d->attach_req.dl_ppa)
- break;
- if (ppa == 0) {
- dlpi_error(q, us, DL_ATTACH_REQ, DL_BADPPA, 0);
- break;
- }
- us->ppa = ppa;
- qwriter(q, mp, attach_ppa, PERIM_OUTER);
- return;
-
- case DL_DETACH_REQ:
- if (size < sizeof(dl_detach_req_t))
- goto badprim;
- if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, us, DL_DETACH_REQ, DL_OUTSTATE, 0);
- break;
- }
- qwriter(q, mp, detach_ppa, PERIM_OUTER);
- return;
-
- case DL_BIND_REQ:
- if (size < sizeof(dl_bind_req_t))
- goto badprim;
- if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, us, DL_BIND_REQ, DL_OUTSTATE, 0);
- break;
- }
-#if 0
- /* apparently this test fails (unnecessarily?) on some systems */
- if (d->bind_req.dl_service_mode != DL_CLDLS) {
- dlpi_error(q, us, DL_BIND_REQ, DL_UNSUPPORTED, 0);
- break;
- }
-#endif
-
- /* saps must be valid PPP network protocol numbers,
- except that we accept ETHERTYPE_IP in place of PPP_IP. */
- sap = d->bind_req.dl_sap;
- us->req_sap = sap;
-
-#if defined(SOL2)
- if (us->flags & US_DBGLOG)
- DPRINT2("DL_BIND_REQ: ip gives sap = 0x%x, us = 0x%x", sap, us);
-
- if (sap == ETHERTYPE_IP) /* normal IFF_IPV4 */
- sap = PPP_IP;
- else if (sap == ETHERTYPE_IPV6) /* when IFF_IPV6 is set */
- sap = PPP_IPV6;
- else if (sap == ETHERTYPE_ALLSAP) /* snoop gives sap of 0 */
- sap = PPP_ALLSAP;
- else {
- DPRINT2("DL_BIND_REQ: unrecognized sap = 0x%x, us = 0x%x", sap, us);
- dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
- break;
- }
-#else
- if (sap == ETHERTYPE_IP)
- sap = PPP_IP;
- if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
- dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
- break;
- }
-#endif /* defined(SOL2) */
-
- /* check that no other stream is bound to this sap already. */
- for (os = us->ppa; os != 0; os = os->next)
- if (os->sap == sap)
- break;
- if (os != 0) {
- dlpi_error(q, us, DL_BIND_REQ, DL_NOADDR, 0);
- break;
- }
-
- us->sap = sap;
- us->state = DL_IDLE;
-
- if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(uint),
- BPRI_HI)) == 0)
- break; /* should do bufcall */
- ackp = (dl_bind_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_bind_ack_t) + sizeof(uint);
- reply->b_datap->db_type = M_PCPROTO;
- bzero((caddr_t) ackp, sizeof(dl_bind_ack_t));
- ackp->dl_primitive = DL_BIND_ACK;
- ackp->dl_sap = sap;
- ackp->dl_addr_length = sizeof(uint);
- ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
- *(uint *)(ackp+1) = sap;
- qreply(q, reply);
- break;
-
- case DL_UNBIND_REQ:
- if (size < sizeof(dl_unbind_req_t))
- goto badprim;
- if (us->state != DL_IDLE) {
- dlpi_error(q, us, DL_UNBIND_REQ, DL_OUTSTATE, 0);
- break;
- }
- us->sap = -1;
- us->state = DL_UNBOUND;
-#ifdef LACHTCP
- us->ppa->ifstats.ifs_active = 0;
-#endif
- dlpi_ok(q, DL_UNBIND_REQ);
- break;
-
- case DL_UNITDATA_REQ:
- if (size < sizeof(dl_unitdata_req_t))
- goto badprim;
- if (us->state != DL_IDLE) {
- dlpi_error(q, us, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
- break;
- }
- if ((ppa = us->ppa) == 0) {
- cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n");
- break;
- }
- len = mp->b_cont == 0? 0: msgdsize(mp->b_cont);
- if (len > ppa->mtu) {
- DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
- break;
- }
-
-#if defined(SOL2)
- /*
- * Should there be any promiscuous stream(s), send the data
- * up for each promiscuous stream that we recognize.
- */
- if (mp->b_cont)
- promisc_sendup(ppa, mp->b_cont, us->sap, 0);
-#endif /* defined(SOL2) */
-
- mp->b_band = 0;
-#ifdef PRIOQ
- /* Extract s_port & d_port from IP-packet, the code is a bit
- dirty here, but so am I, too... */
- if (mp->b_datap->db_type == M_PROTO && us->sap == PPP_IP
- && mp->b_cont != 0) {
- u_char *bb, *tlh;
- int iphlen, len;
- u_short *ptr;
- u_char band_unset, cur_band, syn;
- u_short s_port, d_port;
-
- bb = mp->b_cont->b_rptr; /* bb points to IP-header*/
- len = mp->b_cont->b_wptr - mp->b_cont->b_rptr;
- syn = 0;
- s_port = IPPORT_DEFAULT;
- d_port = IPPORT_DEFAULT;
- if (len >= 20) { /* 20 = minimum length of IP header */
- iphlen = (bb[0] & 0x0f) * 4;
- tlh = bb + iphlen;
- len -= iphlen;
- switch (bb[9]) {
- case IPPROTO_TCP:
- if (len >= 20) { /* min length of TCP header */
- s_port = (tlh[0] << 8) + tlh[1];
- d_port = (tlh[2] << 8) + tlh[3];
- syn = tlh[13] & 0x02;
- }
- break;
- case IPPROTO_UDP:
- if (len >= 8) { /* min length of UDP header */
- s_port = (tlh[0] << 8) + tlh[1];
- d_port = (tlh[2] << 8) + tlh[3];
- }
- break;
- }
- }
-
- /*
- * Now calculate b_band for this packet from the
- * port-priority table.
- */
- ptr = prioq_table;
- cur_band = max_band;
- band_unset = 1;
- while (*ptr) {
- while (*ptr && band_unset)
- if (s_port == *ptr || d_port == *ptr++) {
- mp->b_band = cur_band;
- band_unset = 0;
- break;
- }
- ptr++;
- cur_band--;
- }
- if (band_unset)
- mp->b_band = def_band;
- /* It may be usable to urge SYN packets a bit */
- if (syn)
- mp->b_band++;
- }
-#endif /* PRIOQ */
- /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
- if (mp->b_datap->db_ref > 1) {
- np = allocb(PPP_HDRLEN, BPRI_HI);
- if (np == 0)
- break; /* gak! */
- np->b_cont = mp->b_cont;
- mp->b_cont = 0;
- freeb(mp);
- mp = np;
- } else
- mp->b_datap->db_type = M_DATA;
- /* XXX should use dl_dest_addr_offset/length here,
- but we would have to translate ETHERTYPE_IP -> PPP_IP */
- mp->b_wptr = mp->b_rptr + PPP_HDRLEN;
- mp->b_rptr[0] = PPP_ALLSTATIONS;
- mp->b_rptr[1] = PPP_UI;
- mp->b_rptr[2] = us->sap >> 8;
- mp->b_rptr[3] = us->sap;
- /* pass_packet frees the packet on returning 0 */
- if (pass_packet(us, mp, 1)) {
- if (!send_data(mp, us) && !putq(q, mp))
- freemsg(mp);
- }
- return;
-
-#if DL_CURRENT_VERSION >= 2
- case DL_PHYS_ADDR_REQ:
- if (size < sizeof(dl_phys_addr_req_t))
- goto badprim;
-
- /*
- * Don't check state because ifconfig sends this one down too
- */
-
- if ((reply = allocb(sizeof(dl_phys_addr_ack_t)+ETHERADDRL,
- BPRI_HI)) == 0)
- break; /* should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- paddrack = (dl_phys_addr_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_phys_addr_ack_t);
- bzero((caddr_t) paddrack, sizeof(dl_phys_addr_ack_t)+ETHERADDRL);
- paddrack->dl_primitive = DL_PHYS_ADDR_ACK;
- paddrack->dl_addr_length = ETHERADDRL;
- paddrack->dl_addr_offset = sizeof(dl_phys_addr_ack_t);
- bcopy(&eaddr, reply->b_wptr, ETHERADDRL);
- reply->b_wptr += ETHERADDRL;
- qreply(q, reply);
- break;
-
-#if defined(SOL2)
- case DL_PROMISCON_REQ:
- if (size < sizeof(dl_promiscon_req_t))
- goto badprim;
- us->flags |= US_PROMISC;
- dlpi_ok(q, DL_PROMISCON_REQ);
- break;
-
- case DL_PROMISCOFF_REQ:
- if (size < sizeof(dl_promiscoff_req_t))
- goto badprim;
- us->flags &= ~US_PROMISC;
- dlpi_ok(q, DL_PROMISCOFF_REQ);
- break;
-#else
- case DL_PROMISCON_REQ: /* fall thru */
- case DL_PROMISCOFF_REQ: /* fall thru */
-#endif /* defined(SOL2) */
-#endif /* DL_CURRENT_VERSION >= 2 */
-
-#if DL_CURRENT_VERSION >= 2
- case DL_SET_PHYS_ADDR_REQ:
- case DL_SUBS_BIND_REQ:
- case DL_SUBS_UNBIND_REQ:
- case DL_ENABMULTI_REQ:
- case DL_DISABMULTI_REQ:
- case DL_XID_REQ:
- case DL_TEST_REQ:
- case DL_REPLY_UPDATE_REQ:
- case DL_REPLY_REQ:
- case DL_DATA_ACK_REQ:
-#endif
- case DL_CONNECT_REQ:
- case DL_TOKEN_REQ:
- dlpi_error(q, us, d->dl_primitive, DL_NOTSUPPORTED, 0);
- break;
-
- case DL_CONNECT_RES:
- case DL_DISCONNECT_REQ:
- case DL_RESET_REQ:
- case DL_RESET_RES:
- dlpi_error(q, us, d->dl_primitive, DL_OUTSTATE, 0);
- break;
-
- case DL_UDQOS_REQ:
- dlpi_error(q, us, d->dl_primitive, DL_BADQOSTYPE, 0);
- break;
-
-#if DL_CURRENT_VERSION >= 2
- case DL_TEST_RES:
- case DL_XID_RES:
- break;
-#endif
-
- default:
- if (us->flags & US_DBGLOG)
- DPRINT1("ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
- /* fall through */
- badprim:
- dlpi_error(q, us, d->dl_primitive, DL_BADPRIM, 0);
- break;
- }
- freemsg(mp);
-}
-
-static void
-dlpi_error(q, us, prim, err, uerr)
- queue_t *q;
- upperstr_t *us;
- int prim, err, uerr;
-{
- mblk_t *reply;
- dl_error_ack_t *errp;
-
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: dlpi error, prim=%x, err=%x\n", us->mn, prim, err);
- reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
- if (reply == 0)
- return; /* XXX should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- errp = (dl_error_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_error_ack_t);
- errp->dl_primitive = DL_ERROR_ACK;
- errp->dl_error_primitive = prim;
- errp->dl_errno = err;
- errp->dl_unix_errno = uerr;
- qreply(q, reply);
-}
-
-static void
-dlpi_ok(q, prim)
- queue_t *q;
- int prim;
-{
- mblk_t *reply;
- dl_ok_ack_t *okp;
-
- reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);
- if (reply == 0)
- return; /* XXX should do bufcall */
- reply->b_datap->db_type = M_PCPROTO;
- okp = (dl_ok_ack_t *) reply->b_wptr;
- reply->b_wptr += sizeof(dl_ok_ack_t);
- okp->dl_primitive = DL_OK_ACK;
- okp->dl_correct_primitive = prim;
- qreply(q, reply);
-}
-#endif /* NO_DLPI */
-
-/*
- * If return value is 0, then the packet has already been freed.
- */
-static int
-pass_packet(us, mp, outbound)
- upperstr_t *us;
- mblk_t *mp;
- int outbound;
-{
- int pass;
- upperstr_t *ppa;
-
- if ((ppa = us->ppa) == 0) {
- freemsg(mp);
- return 0;
- }
-
-#ifdef FILTER_PACKETS
- pass = ip_hard_filter(us, mp, outbound);
-#else
- /*
- * Here is where we might, in future, decide whether to pass
- * or drop the packet, and whether it counts as link activity.
- */
- pass = 1;
-#endif /* FILTER_PACKETS */
-
- if (pass < 0) {
- /* pass only if link already up, and don't update time */
- if (ppa->lowerq == 0) {
- freemsg(mp);
- return 0;
- }
- pass = 1;
- } else if (pass) {
- if (outbound)
- ppa->last_sent = time;
- else
- ppa->last_recv = time;
- }
-
- return pass;
-}
-
-/*
- * We have some data to send down to the lower stream (or up the
- * control stream, if we don't have a lower stream attached).
- * Returns 1 if the message was dealt with, 0 if it wasn't able
- * to be sent on and should therefore be queued up.
- */
-static int
-send_data(mp, us)
- mblk_t *mp;
- upperstr_t *us;
-{
- upperstr_t *ppa;
-
- if ((us->flags & US_BLOCKED) || us->npmode == NPMODE_QUEUE)
- return 0;
- ppa = us->ppa;
- if (ppa == 0 || us->npmode == NPMODE_DROP || us->npmode == NPMODE_ERROR) {
- if (us->flags & US_DBGLOG)
- DPRINT2("ppp/%d: dropping pkt (npmode=%d)\n", us->mn, us->npmode);
- freemsg(mp);
- return 1;
- }
- if (ppa->lowerq == 0) {
- /* try to send it up the control stream */
- if (bcanputnext(ppa->q, mp->b_band)) {
- /*
- * The message seems to get corrupted for some reason if
- * we just send the message up as it is, so we send a copy.
- */
- mblk_t *np = copymsg(mp);
- freemsg(mp);
- if (np != 0)
- putnext(ppa->q, np);
- return 1;
- }
- } else {
- if (bcanputnext(ppa->lowerq, mp->b_band)) {
- MT_ENTER(&ppa->stats_lock);
- ppa->stats.ppp_opackets++;
- ppa->stats.ppp_obytes += msgdsize(mp);
-#ifdef INCR_OPACKETS
- INCR_OPACKETS(ppa);
-#endif
- MT_EXIT(&ppa->stats_lock);
- /*
- * The lower queue is only ever detached while holding an
- * exclusive lock on the whole driver. So we can be confident
- * that the lower queue is still there.
- */
- putnext(ppa->lowerq, mp);
- return 1;
- }
- }
- us->flags |= US_BLOCKED;
- return 0;
-}
-
-/*
- * Allocate a new PPA id and link this stream into the list of PPAs.
- * This procedure is called with an exclusive lock on all queues in
- * this driver.
- */
-static void
-new_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *up, **usp;
- int ppa_id;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("new_ppa: q_ptr = 0!\n");
- return;
- }
-
- usp = &ppas;
- ppa_id = 0;
- while ((up = *usp) != 0 && ppa_id == up->ppa_id) {
- ++ppa_id;
- usp = &up->nextppa;
- }
- us->ppa_id = ppa_id;
- us->ppa = us;
- us->next = 0;
- us->nextppa = *usp;
- *usp = us;
- us->flags |= US_CONTROL;
- us->npmode = NPMODE_PASS;
-
- us->mtu = PPP_MTU;
- us->mru = PPP_MRU;
-
-#ifdef SOL2
- /*
- * Create a kstats record for our statistics, so netstat -i works.
- */
- if (us->kstats == 0) {
- char unit[32];
-
- sprintf(unit, "ppp%d", us->ppa->ppa_id);
- us->kstats = kstat_create("ppp", us->ppa->ppa_id, unit,
- "net", KSTAT_TYPE_NAMED, 4, 0);
- if (us->kstats != 0) {
- kstat_named_t *kn = KSTAT_NAMED_PTR(us->kstats);
-
- strcpy(kn[0].name, "ipackets");
- kn[0].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[1].name, "ierrors");
- kn[1].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[2].name, "opackets");
- kn[2].data_type = KSTAT_DATA_ULONG;
- strcpy(kn[3].name, "oerrors");
- kn[3].data_type = KSTAT_DATA_ULONG;
- kstat_install(us->kstats);
- }
- }
-#endif /* SOL2 */
-
- *(int *)mp->b_cont->b_rptr = ppa_id;
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
-}
-
-static void
-attach_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *t;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("attach_ppa: q_ptr = 0!\n");
- return;
- }
-
-#ifndef NO_DLPI
- us->state = DL_UNBOUND;
-#endif
- for (t = us->ppa; t->next != 0; t = t->next)
- ;
- t->next = us;
- us->next = 0;
- if (mp->b_datap->db_type == M_IOCTL) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
-#ifndef NO_DLPI
- dlpi_ok(q, DL_ATTACH_REQ);
-#endif
- freemsg(mp);
- }
-}
-
-#ifndef NO_DLPI
-static void
-detach_ppa(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us, *t;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("detach_ppa: q_ptr = 0!\n");
- return;
- }
-
- for (t = us->ppa; t->next != 0; t = t->next)
- if (t->next == us) {
- t->next = us->next;
- break;
- }
- us->next = 0;
- us->ppa = 0;
- us->state = DL_UNATTACHED;
- dlpi_ok(q, DL_DETACH_REQ);
- freemsg(mp);
-}
-#endif
-
-/*
- * We call this with qwriter in order to give the upper queue procedures
- * the guarantee that the lower queue is not going to go away while
- * they are executing.
- */
-static void
-detach_lower(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("detach_lower: q_ptr = 0!\n");
- return;
- }
-
- LOCK_LOWER_W;
- us->lowerq->q_ptr = 0;
- RD(us->lowerq)->q_ptr = 0;
- us->lowerq = 0;
- UNLOCK_LOWER;
-
- /* Unblock streams which now feed back up the control stream. */
- qenable(us->q);
-
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
-}
-
-static int
-pppuwsrv(q)
- queue_t *q;
-{
- upperstr_t *us, *as;
- mblk_t *mp;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("pppuwsrv: q_ptr = 0!\n");
- return 0;
- }
-
- /*
- * If this is a control stream, then this service procedure
- * probably got enabled because of flow control in the lower
- * stream being enabled (or because of the lower stream going
- * away). Therefore we enable the service procedure of all
- * attached upper streams.
- */
- if (us->flags & US_CONTROL) {
- for (as = us->next; as != 0; as = as->next)
- qenable(WR(as->q));
- }
-
- /* Try to send on any data queued here. */
- us->flags &= ~US_BLOCKED;
- while ((mp = getq(q)) != 0) {
- if (!send_data(mp, us)) {
- putbq(q, mp);
- break;
- }
- }
-
- return 0;
-}
-
-/* should never get called... */
-static int
-ppplwput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- putnext(q, mp);
- return 0;
-}
-
-static int
-ppplwsrv(q)
- queue_t *q;
-{
- queue_t *uq;
-
- /*
- * Flow control has back-enabled this stream:
- * enable the upper write service procedure for
- * the upper control stream for this lower stream.
- */
- LOCK_LOWER_R;
- uq = (queue_t *) q->q_ptr;
- if (uq != 0)
- qenable(uq);
- UNLOCK_LOWER;
- return 0;
-}
-
-/*
- * This should only get called for control streams.
- */
-static int
-pppurput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *ppa, *us;
- int proto, len;
- struct iocblk *iop;
-
- ppa = (upperstr_t *) q->q_ptr;
- if (ppa == 0) {
- DPRINT("pppurput: q_ptr = 0!\n");
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
- case M_CTL:
- MT_ENTER(&ppa->stats_lock);
- switch (*mp->b_rptr) {
- case PPPCTL_IERROR:
-#ifdef INCR_IERRORS
- INCR_IERRORS(ppa);
-#endif
- ppa->stats.ppp_ierrors++;
- break;
- case PPPCTL_OERROR:
-#ifdef INCR_OERRORS
- INCR_OERRORS(ppa);
-#endif
- ppa->stats.ppp_oerrors++;
- break;
- }
- MT_EXIT(&ppa->stats_lock);
- freemsg(mp);
- break;
-
- case M_IOCACK:
- case M_IOCNAK:
- /*
- * Attempt to match up the response with the stream
- * that the request came from.
- */
- iop = (struct iocblk *) mp->b_rptr;
- for (us = ppa; us != 0; us = us->next)
- if (us->ioc_id == iop->ioc_id)
- break;
- if (us == 0)
- freemsg(mp);
- else
- putnext(us->q, mp);
- break;
-
- case M_HANGUP:
- /*
- * The serial device has hung up. We don't want to send
- * the M_HANGUP message up to pppd because that will stop
- * us from using the control stream any more. Instead we
- * send a zero-length message as an end-of-file indication.
- */
- freemsg(mp);
- mp = allocb(1, BPRI_HI);
- if (mp == 0) {
- DPRINT1("ppp/%d: couldn't allocate eof message!\n", ppa->mn);
- break;
- }
- putnext(ppa->q, mp);
- break;
-
- case M_DATA:
- len = msgdsize(mp);
- if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
- PULLUP(mp, PPP_HDRLEN);
- if (mp == 0) {
- DPRINT1("ppp_urput: msgpullup failed (len=%d)\n", len);
- break;
- }
- }
- MT_ENTER(&ppa->stats_lock);
- ppa->stats.ppp_ipackets++;
- ppa->stats.ppp_ibytes += len;
-#ifdef INCR_IPACKETS
- INCR_IPACKETS(ppa);
-#endif
- MT_EXIT(&ppa->stats_lock);
-
- proto = PPP_PROTOCOL(mp->b_rptr);
-
-#if defined(SOL2)
- /*
- * Should there be any promiscuous stream(s), send the data
- * up for each promiscuous stream that we recognize.
- */
- promisc_sendup(ppa, mp, proto, 1);
-#endif /* defined(SOL2) */
-
- if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
- /*
- * A data packet for some network protocol.
- * Queue it on the upper stream for that protocol.
- * XXX could we just putnext it? (would require thought)
- * The rblocked flag is there to ensure that we keep
- * messages in order for each network protocol.
- */
- /* pass_packet frees the packet on returning 0 */
- if (!pass_packet(us, mp, 0))
- break;
- if (!us->rblocked && !canput(us->q))
- us->rblocked = 1;
- if (!putq(us->rblocked ? q : us->q, mp))
- freemsg(mp);
- break;
- }
-
- /* FALLTHROUGH */
-
- default:
- /*
- * A control frame, a frame for an unknown protocol,
- * or some other message type.
- * Send it up to pppd via the control stream.
- */
- if (queclass(mp) == QPCTL || canputnext(ppa->q))
- putnext(ppa->q, mp);
- else if (!putq(q, mp))
- freemsg(mp);
- break;
- }
-
- return 0;
-}
-
-static int
-pppursrv(q)
- queue_t *q;
-{
- upperstr_t *us, *as;
- mblk_t *mp, *hdr;
-#ifndef NO_DLPI
- dl_unitdata_ind_t *ud;
-#endif
- int proto;
-
- us = (upperstr_t *) q->q_ptr;
- if (us == 0) {
- DPRINT("pppursrv: q_ptr = 0!\n");
- return 0;
- }
-
- if (us->flags & US_CONTROL) {
- /*
- * A control stream.
- * If there is no lower queue attached, run the write service
- * routines of other upper streams attached to this PPA.
- */
- if (us->lowerq == 0) {
- as = us;
- do {
- if (as->flags & US_BLOCKED)
- qenable(WR(as->q));
- as = as->next;
- } while (as != 0);
- }
-
- /*
- * Messages get queued on this stream's read queue if they
- * can't be queued on the read queue of the attached stream
- * that they are destined for. This is for flow control -
- * when this queue fills up, the lower read put procedure will
- * queue messages there and the flow control will propagate
- * down from there.
- */
- while ((mp = getq(q)) != 0) {
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto < 0x8000 && (as = find_dest(us, proto)) != 0) {
- if (!canput(as->q))
- break;
- if (!putq(as->q, mp))
- freemsg(mp);
- } else {
- if (!canputnext(q))
- break;
- putnext(q, mp);
- }
- }
- if (mp) {
- putbq(q, mp);
- } else {
- /* can now put stuff directly on network protocol streams again */
- for (as = us->next; as != 0; as = as->next)
- as->rblocked = 0;
- }
-
- /*
- * If this stream has a lower stream attached,
- * enable the read queue's service routine.
- * XXX we should really only do this if the queue length
- * has dropped below the low-water mark.
- */
- if (us->lowerq != 0)
- qenable(RD(us->lowerq));
-
- } else {
- /*
- * A network protocol stream. Put a DLPI header on each
- * packet and send it on.
- * (Actually, it seems that the IP module will happily
- * accept M_DATA messages without the DL_UNITDATA_IND header.)
- */
- while ((mp = getq(q)) != 0) {
- if (!canputnext(q)) {
- putbq(q, mp);
- break;
- }
-#ifndef NO_DLPI
- proto = PPP_PROTOCOL(mp->b_rptr);
- mp->b_rptr += PPP_HDRLEN;
- hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint),
- BPRI_MED);
- if (hdr == 0) {
- /* XXX should put it back and use bufcall */
- freemsg(mp);
- continue;
- }
- hdr->b_datap->db_type = M_PROTO;
- ud = (dl_unitdata_ind_t *) hdr->b_wptr;
- hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint);
- hdr->b_cont = mp;
- ud->dl_primitive = DL_UNITDATA_IND;
- ud->dl_dest_addr_length = sizeof(uint);
- ud->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
- ud->dl_src_addr_length = sizeof(uint);
- ud->dl_src_addr_offset = ud->dl_dest_addr_offset + sizeof(uint);
-#if DL_CURRENT_VERSION >= 2
- ud->dl_group_address = 0;
-#endif
- /* Send the DLPI client the data with the SAP they requested,
- (e.g. ETHERTYPE_IP) rather than the PPP protocol number
- (e.g. PPP_IP) */
- ((uint *)(ud + 1))[0] = us->req_sap; /* dest SAP */
- ((uint *)(ud + 1))[1] = us->req_sap; /* src SAP */
- putnext(q, hdr);
-#else /* NO_DLPI */
- putnext(q, mp);
-#endif /* NO_DLPI */
- }
- /*
- * Now that we have consumed some packets from this queue,
- * enable the control stream's read service routine so that we
- * can process any packets for us that might have got queued
- * there for flow control reasons.
- */
- if (us->ppa)
- qenable(us->ppa->q);
- }
-
- return 0;
-}
-
-static upperstr_t *
-find_dest(ppa, proto)
- upperstr_t *ppa;
- int proto;
-{
- upperstr_t *us;
-
- for (us = ppa->next; us != 0; us = us->next)
- if (proto == us->sap)
- break;
- return us;
-}
-
-#if defined (SOL2)
-/*
- * Test upstream promiscuous conditions. As of now, only pass IPv4 and
- * Ipv6 packets upstream (let PPP packets be decoded elsewhere).
- */
-static upperstr_t *
-find_promisc(us, proto)
- upperstr_t *us;
- int proto;
-{
-
- if ((proto != PPP_IP) && (proto != PPP_IPV6))
- return (upperstr_t *)0;
-
- for ( ; us; us = us->next) {
- if ((us->flags & US_PROMISC) && (us->state == DL_IDLE))
- return us;
- }
-
- return (upperstr_t *)0;
-}
-
-/*
- * Prepend an empty Ethernet header to msg for snoop, et al.
- */
-static mblk_t *
-prepend_ether(us, mp, proto)
- upperstr_t *us;
- mblk_t *mp;
- int proto;
-{
- mblk_t *eh;
- int type;
-
- if ((eh = allocb(sizeof(struct ether_header), BPRI_HI)) == 0) {
- freemsg(mp);
- return (mblk_t *)0;
- }
-
- if (proto == PPP_IP)
- type = ETHERTYPE_IP;
- else if (proto == PPP_IPV6)
- type = ETHERTYPE_IPV6;
- else
- type = proto; /* What else? Let decoder decide */
-
- eh->b_wptr += sizeof(struct ether_header);
- bzero((caddr_t)eh->b_rptr, sizeof(struct ether_header));
- ((struct ether_header *)eh->b_rptr)->ether_type = htons((short)type);
- eh->b_cont = mp;
- return (eh);
-}
-
-/*
- * Prepend DL_UNITDATA_IND mblk to msg
- */
-static mblk_t *
-prepend_udind(us, mp, proto)
- upperstr_t *us;
- mblk_t *mp;
- int proto;
-{
- dl_unitdata_ind_t *dlu;
- mblk_t *dh;
- size_t size;
-
- size = sizeof(dl_unitdata_ind_t);
- if ((dh = allocb(size, BPRI_MED)) == 0) {
- freemsg(mp);
- return (mblk_t *)0;
- }
-
- dh->b_datap->db_type = M_PROTO;
- dh->b_wptr = dh->b_datap->db_lim;
- dh->b_rptr = dh->b_wptr - size;
-
- dlu = (dl_unitdata_ind_t *)dh->b_rptr;
- dlu->dl_primitive = DL_UNITDATA_IND;
- dlu->dl_dest_addr_length = 0;
- dlu->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
- dlu->dl_src_addr_length = 0;
- dlu->dl_src_addr_offset = sizeof(dl_unitdata_ind_t);
- dlu->dl_group_address = 0;
-
- dh->b_cont = mp;
- return (dh);
-}
-
-/*
- * For any recognized promiscuous streams, send data upstream
- */
-static void
-promisc_sendup(ppa, mp, proto, skip)
- upperstr_t *ppa;
- mblk_t *mp;
- int proto, skip;
-{
- mblk_t *dup_mp, *dup_dup_mp;
- upperstr_t *prus, *nprus;
-
- if ((prus = find_promisc(ppa, proto)) != 0) {
- if (dup_mp = dupmsg(mp)) {
-
- if (skip)
- dup_mp->b_rptr += PPP_HDRLEN;
-
- for ( ; nprus = find_promisc(prus->next, proto);
- prus = nprus) {
-
- if (dup_dup_mp = dupmsg(dup_mp)) {
- if (canputnext(prus->q)) {
- if (prus->flags & US_RAWDATA) {
- dup_dup_mp = prepend_ether(prus, dup_dup_mp, proto);
- } else {
- dup_dup_mp = prepend_udind(prus, dup_dup_mp, proto);
- }
- if (dup_dup_mp == 0)
- continue;
- putnext(prus->q, dup_dup_mp);
- } else {
- DPRINT("ppp_urput: data to promisc q dropped\n");
- freemsg(dup_dup_mp);
- }
- }
- }
-
- if (canputnext(prus->q)) {
- if (prus->flags & US_RAWDATA) {
- dup_mp = prepend_ether(prus, dup_mp, proto);
- } else {
- dup_mp = prepend_udind(prus, dup_mp, proto);
- }
- if (dup_mp != 0)
- putnext(prus->q, dup_mp);
- } else {
- DPRINT("ppp_urput: data to promisc q dropped\n");
- freemsg(dup_mp);
- }
- }
- }
-}
-#endif /* defined(SOL2) */
-
-/*
- * We simply put the message on to the associated upper control stream
- * (either here or in ppplrsrv). That way we enter the perimeters
- * before looking through the list of attached streams to decide which
- * stream it should go up.
- */
-static int
-ppplrput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- queue_t *uq;
- struct iocblk *iop;
-
- switch (mp->b_datap->db_type) {
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- iop->ioc_error = EINVAL;
- mp->b_datap->db_type = M_IOCNAK;
- qreply(q, mp);
- return 0;
- case M_FLUSH:
- if (*mp->b_rptr & FLUSHR)
- flushq(q, FLUSHDATA);
- if (*mp->b_rptr & FLUSHW) {
- *mp->b_rptr &= ~FLUSHR;
- qreply(q, mp);
- } else
- freemsg(mp);
- return 0;
- }
-
- /*
- * If we can't get the lower lock straight away, queue this one
- * rather than blocking, to avoid the possibility of deadlock.
- */
- if (!TRYLOCK_LOWER_R) {
- if (!putq(q, mp))
- freemsg(mp);
- return 0;
- }
-
- /*
- * Check that we're still connected to the driver.
- */
- uq = (queue_t *) q->q_ptr;
- if (uq == 0) {
- UNLOCK_LOWER;
- DPRINT1("ppplrput: q = %x, uq = 0??\n", q);
- freemsg(mp);
- return 0;
- }
-
- /*
- * Try to forward the message to the put routine for the upper
- * control stream for this lower stream.
- * If there are already messages queued here, queue this one so
- * they don't get out of order.
- */
- if (queclass(mp) == QPCTL || (qsize(q) == 0 && canput(uq)))
- put(uq, mp);
- else if (!putq(q, mp))
- freemsg(mp);
-
- UNLOCK_LOWER;
- return 0;
-}
-
-static int
-ppplrsrv(q)
- queue_t *q;
-{
- mblk_t *mp;
- queue_t *uq;
-
- /*
- * Packets get queued here for flow control reasons
- * or if the lrput routine couldn't get the lower lock
- * without blocking.
- */
- LOCK_LOWER_R;
- uq = (queue_t *) q->q_ptr;
- if (uq == 0) {
- UNLOCK_LOWER;
- flushq(q, FLUSHALL);
- DPRINT1("ppplrsrv: q = %x, uq = 0??\n", q);
- return 0;
- }
- while ((mp = getq(q)) != 0) {
- if (queclass(mp) == QPCTL || canput(uq))
- put(uq, mp);
- else {
- putbq(q, mp);
- break;
- }
- }
- UNLOCK_LOWER;
- return 0;
-}
-
-static int
-putctl2(q, type, code, val)
- queue_t *q;
- int type, code, val;
-{
- mblk_t *mp;
-
- mp = allocb(2, BPRI_HI);
- if (mp == 0)
- return 0;
- mp->b_datap->db_type = type;
- mp->b_wptr[0] = code;
- mp->b_wptr[1] = val;
- mp->b_wptr += 2;
- putnext(q, mp);
- return 1;
-}
-
-static int
-putctl4(q, type, code, val)
- queue_t *q;
- int type, code, val;
-{
- mblk_t *mp;
-
- mp = allocb(4, BPRI_HI);
- if (mp == 0)
- return 0;
- mp->b_datap->db_type = type;
- mp->b_wptr[0] = code;
- ((short *)mp->b_wptr)[1] = val;
- mp->b_wptr += 4;
- putnext(q, mp);
- return 1;
-}
-
-static void
-debug_dump(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- upperstr_t *us;
- queue_t *uq, *lq;
-
- DPRINT("ppp upper streams:\n");
- for (us = minor_devs; us != 0; us = us->nextmn) {
- uq = us->q;
- DPRINT3(" %d: q=%x rlev=%d",
- us->mn, uq, (uq? qsize(uq): 0));
- DPRINT3(" wlev=%d flags=0x%b", (uq? qsize(WR(uq)): 0),
- us->flags, "\020\1priv\2control\3blocked\4last");
- DPRINT3(" state=%x sap=%x req_sap=%x", us->state, us->sap,
- us->req_sap);
- if (us->ppa == 0)
- DPRINT(" ppa=?\n");
- else
- DPRINT1(" ppa=%d\n", us->ppa->ppa_id);
- if (us->flags & US_CONTROL) {
- lq = us->lowerq;
- DPRINT3(" control for %d lq=%x rlev=%d",
- us->ppa_id, lq, (lq? qsize(RD(lq)): 0));
- DPRINT3(" wlev=%d mru=%d mtu=%d\n",
- (lq? qsize(lq): 0), us->mru, us->mtu);
- }
- }
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
-}
-
-#ifdef FILTER_PACKETS
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
-
-#define MAX_IPHDR 128 /* max TCP/IP header size */
-
-
-/* The following table contains a hard-coded list of protocol/port pairs.
- * Any matching packets are either discarded unconditionally, or,
- * if ok_if_link_up is non-zero when a connection does not currently exist
- * (i.e., they go through if the connection is present, but never initiate
- * a dial-out).
- * This idea came from a post by dm@garage.uun.org (David Mazieres)
- */
-static struct pktfilt_tab {
- int proto;
- u_short port;
- u_short ok_if_link_up;
-} pktfilt_tab[] = {
- { IPPROTO_UDP, 520, 1 }, /* RIP, ok to pass if link is up */
- { IPPROTO_UDP, 123, 1 }, /* NTP, don't keep up the link for it */
- { -1, 0, 0 } /* terminator entry has port == -1 */
-};
-
-
-/*
- * Packet has already been freed if return value is 0.
- */
-static int
-ip_hard_filter(us, mp, outbound)
- upperstr_t *us;
- mblk_t *mp;
- int outbound;
-{
- struct ip *ip;
- struct pktfilt_tab *pft;
- mblk_t *temp_mp;
- int proto;
- int len, hlen;
-
-
- /* Note, the PPP header has already been pulled up in all cases */
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: filter, proto=0x%x, out=%d\n", us->mn, proto, outbound);
-
- switch (proto)
- {
- case PPP_IP:
- if ((mp->b_wptr - mp->b_rptr) == PPP_HDRLEN && mp->b_cont != 0) {
- temp_mp = mp->b_cont;
- len = msgdsize(temp_mp);
- hlen = (len < MAX_IPHDR) ? len : MAX_IPHDR;
- PULLUP(temp_mp, hlen);
- if (temp_mp == 0) {
- DPRINT2("ppp/%d: filter, pullup next failed, len=%d\n",
- us->mn, hlen);
- mp->b_cont = 0; /* PULLUP() freed the rest */
- freemsg(mp);
- return 0;
- }
- ip = (struct ip *)mp->b_cont->b_rptr;
- }
- else {
- len = msgdsize(mp);
- hlen = (len < (PPP_HDRLEN+MAX_IPHDR)) ? len : (PPP_HDRLEN+MAX_IPHDR);
- PULLUP(mp, hlen);
- if (mp == 0) {
- DPRINT2("ppp/%d: filter, pullup failed, len=%d\n",
- us->mn, hlen);
- return 0;
- }
- ip = (struct ip *)(mp->b_rptr + PPP_HDRLEN);
- }
-
- /* For IP traffic, certain packets (e.g., RIP) may be either
- * 1. ignored - dropped completely
- * 2. will not initiate a connection, but
- * will be passed if a connection is currently up.
- */
- for (pft=pktfilt_tab; pft->proto != -1; pft++) {
- if (ip->ip_p == pft->proto) {
- switch(pft->proto) {
- case IPPROTO_UDP:
- if (((struct udphdr *) &((int *)ip)[ip->ip_hl])->uh_dport
- == htons(pft->port)) goto endfor;
- break;
- case IPPROTO_TCP:
- if (((struct tcphdr *) &((int *)ip)[ip->ip_hl])->th_dport
- == htons(pft->port)) goto endfor;
- break;
- }
- }
- }
- endfor:
- if (pft->proto != -1) {
- if (us->flags & US_DBGLOG)
- DPRINT3("ppp/%d: found IP pkt, proto=0x%x (%d)\n",
- us->mn, pft->proto, pft->port);
- /* Discard if not connected, or if not pass_with_link_up */
- /* else, if link is up let go by, but don't update time */
- if (pft->ok_if_link_up)
- return -1;
- freemsg(mp);
- return 0;
- }
- break;
- } /* end switch (proto) */
-
- return 1;
-}
-#endif /* FILTER_PACKETS */
-
+++ /dev/null
-name="ppp" parent="pseudo" instance=0;
+++ /dev/null
-/*
- * ppp_ahdlc.c - STREAMS module for doing PPP asynchronous HDLC.
- *
- * Re-written by Adi Masputra <adi.masputra@sun.com>, based on
- * the original ppp_ahdlc.c
- *
- * Copyright (c) 2000 by Sun Microsystems, Inc.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies.
- *
- * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
- * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * $Id: ppp_ahdlc.c,v 1.5 2005/06/27 00:59:57 carlsonj Exp $
- */
-
-/*
- * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
- */
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/errno.h>
-
-#ifdef SVR4
-#include <sys/conf.h>
-#include <sys/kmem.h>
-#include <sys/cmn_err.h>
-#include <sys/ddi.h>
-#else
-#include <sys/user.h>
-#ifdef __osf__
-#include <sys/cmn_err.h>
-#endif
-#endif /* SVR4 */
-
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-#include "ppp_mod.h"
-
-/*
- * Right now, mutex is only enabled for Solaris 2.x
- */
-#if defined(SOL2)
-#define USE_MUTEX
-#endif /* SOL2 */
-
-#ifdef USE_MUTEX
-#define MUTEX_ENTER(x) mutex_enter(x)
-#define MUTEX_EXIT(x) mutex_exit(x)
-#else
-#define MUTEX_ENTER(x)
-#define MUTEX_EXIT(x)
-#endif
-
-/*
- * intpointer_t and uintpointer_t are signed and unsigned integer types
- * large enough to hold any data pointer; that is, data pointers can be
- * assigned into or from these integer types without losing precision.
- * On recent Solaris releases, these types are defined in sys/int_types.h,
- * but not on SunOS 4.x or the earlier Solaris versions.
- */
-#if defined(_LP64) || defined(_I32LPx)
-typedef long intpointer_t;
-typedef unsigned long uintpointer_t;
-#else
-typedef int intpointer_t;
-typedef unsigned int uintpointer_t;
-#endif
-
-MOD_OPEN_DECL(ahdlc_open);
-MOD_CLOSE_DECL(ahdlc_close);
-static int ahdlc_wput(queue_t *, mblk_t *);
-static int ahdlc_rput(queue_t *, mblk_t *);
-static void ahdlc_encode(queue_t *, mblk_t *);
-static void ahdlc_decode(queue_t *, mblk_t *);
-static int msg_byte(mblk_t *, unsigned int);
-
-#if defined(SOL2)
-/*
- * Don't send HDLC start flag is last transmit is within 1.5 seconds -
- * FLAG_TIME is defined is microseconds
- */
-#define FLAG_TIME 1500
-#define ABS(x) (x >= 0 ? x : (-x))
-#endif /* SOL2 */
-
-/*
- * Extract byte i of message mp
- */
-#define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
- msg_byte((mp), (i)))
-
-/*
- * Is this LCP packet one we have to transmit using LCP defaults?
- */
-#define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
-
-/*
- * Standard STREAMS declarations
- */
-static struct module_info minfo = {
- 0x7d23, "ppp_ahdl", 0, INFPSZ, 32768, 512
-};
-
-static struct qinit rinit = {
- ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
-};
-
-static struct qinit winit = {
- ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
-};
-
-#if defined(SVR4) && !defined(SOL2)
-int phdldevflag = 0;
-#define ppp_ahdlcinfo phdlinfo
-#endif /* defined(SVR4) && !defined(SOL2) */
-
-struct streamtab ppp_ahdlcinfo = {
- &rinit, /* ptr to st_rdinit */
- &winit, /* ptr to st_wrinit */
- NULL, /* ptr to st_muxrinit */
- NULL, /* ptr to st_muxwinit */
-#if defined(SUNOS4)
- NULL /* ptr to ptr to st_modlist */
-#endif /* SUNOS4 */
-};
-
-#if defined(SUNOS4)
-int ppp_ahdlc_count = 0; /* open counter */
-#endif /* SUNOS4 */
-
-/*
- * Per-stream state structure
- */
-typedef struct ahdlc_state {
-#if defined(USE_MUTEX)
- kmutex_t lock; /* lock for this structure */
-#endif /* USE_MUTEX */
- int flags; /* link flags */
- mblk_t *rx_buf; /* ptr to receive buffer */
- int rx_buf_size; /* receive buffer size */
- ushort_t infcs; /* calculated rx HDLC FCS */
- u_int32_t xaccm[8]; /* 256-bit xmit ACCM */
- u_int32_t raccm; /* 32-bit rcv ACCM */
- int mtu; /* interface MTU */
- int mru; /* link MRU */
- int unit; /* current PPP unit number */
- struct pppstat stats; /* statistic structure */
-#if defined(SOL2)
- clock_t flag_time; /* time in usec between flags */
- clock_t lbolt; /* last updated lbolt */
-#endif /* SOL2 */
-} ahdlc_state_t;
-
-/*
- * Values for flags
- */
-#define ESCAPED 0x100 /* last saw escape char on input */
-#define IFLUSH 0x200 /* flushing input due to error */
-
-/*
- * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
- */
-#define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
-
-/*
- * FCS lookup table as calculated by genfcstab.
- */
-static u_short fcstab[256] = {
- 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
- 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
- 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
- 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
- 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
- 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
- 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
- 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
- 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
- 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
- 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
- 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
- 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
- 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
- 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
- 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
- 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
- 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
- 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
- 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
- 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
- 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
- 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
- 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
- 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
- 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
- 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
- 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
- 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
- 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
- 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
- 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-static u_int32_t paritytab[8] =
-{
- 0x96696996, 0x69969669, 0x69969669, 0x96696996,
- 0x69969669, 0x96696996, 0x96696996, 0x69969669
-};
-
-/*
- * STREAMS module open (entry) point
- */
-MOD_OPEN(ahdlc_open)
-{
- ahdlc_state_t *state;
- mblk_t *mp;
-
- /*
- * Return if it's already opened
- */
- if (q->q_ptr) {
- return 0;
- }
-
- /*
- * This can only be opened as a module
- */
- if (sflag != MODOPEN) {
- OPEN_ERROR(EINVAL);
- }
-
- state = (ahdlc_state_t *) ALLOC_NOSLEEP(sizeof(ahdlc_state_t));
- if (state == 0)
- OPEN_ERROR(ENOSR);
- bzero((caddr_t) state, sizeof(ahdlc_state_t));
-
- q->q_ptr = (caddr_t) state;
- WR(q)->q_ptr = (caddr_t) state;
-
-#if defined(USE_MUTEX)
- mutex_init(&state->lock, NULL, MUTEX_DEFAULT, NULL);
-#endif /* USE_MUTEX */
-
- state->xaccm[0] = ~0; /* escape 0x00 through 0x1f */
- state->xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
- state->mru = PPP_MRU; /* default of 1500 bytes */
-#if defined(SOL2)
- state->flag_time = drv_usectohz(FLAG_TIME);
-#endif /* SOL2 */
-
-#if defined(SUNOS4)
- ppp_ahdlc_count++;
-#endif /* SUNOS4 */
-
- qprocson(q);
-
- if ((mp = allocb(1, BPRI_HI)) != NULL) {
- mp->b_datap->db_type = M_FLUSH;
- *mp->b_wptr++ = FLUSHR;
- putnext(q, mp);
- }
-
- return 0;
-}
-
-/*
- * STREAMS module close (exit) point
- */
-MOD_CLOSE(ahdlc_close)
-{
- ahdlc_state_t *state;
-
- qprocsoff(q);
-
- state = (ahdlc_state_t *) q->q_ptr;
-
- if (state == 0) {
- DPRINT("state == 0 in ahdlc_close\n");
- return 0;
- }
-
- if (state->rx_buf != 0) {
- freemsg(state->rx_buf);
- state->rx_buf = 0;
- }
-
-#if defined(USE_MUTEX)
- mutex_destroy(&state->lock);
-#endif /* USE_MUTEX */
-
- FREE(q->q_ptr, sizeof(ahdlc_state_t));
- q->q_ptr = NULL;
- OTHERQ(q)->q_ptr = NULL;
-
-#if defined(SUNOS4)
- if (ppp_ahdlc_count)
- ppp_ahdlc_count--;
-#endif /* SUNOS4 */
-
- return 0;
-}
-
-/*
- * Write side put routine
- */
-static int
-ahdlc_wput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
- struct iocblk *iop;
- int error;
- mblk_t *np;
- struct ppp_stats *psp;
-
- state = (ahdlc_state_t *) q->q_ptr;
- if (state == 0) {
- DPRINT("state == 0 in ahdlc_wput\n");
- freemsg(mp);
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
- case M_DATA:
- /*
- * A data packet - do character-stuffing and FCS, and
- * send it onwards.
- */
- ahdlc_encode(q, mp);
- freemsg(mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- switch (iop->ioc_cmd) {
- case PPPIO_XACCM:
- if ((iop->ioc_count < sizeof(u_int32_t)) ||
- (iop->ioc_count > sizeof(ext_accm))) {
- break;
- }
- if (mp->b_cont == 0) {
- DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
- break;
- }
- MUTEX_ENTER(&state->lock);
- bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
- iop->ioc_count);
- state->xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
- state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
- MUTEX_EXIT(&state->lock);
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case PPPIO_RACCM:
- if (iop->ioc_count != sizeof(u_int32_t))
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
- break;
- }
- MUTEX_ENTER(&state->lock);
- bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
- sizeof(u_int32_t));
- MUTEX_EXIT(&state->lock);
- iop->ioc_count = 0;
- error = 0;
- break;
-
- case PPPIO_GCLEAN:
- np = allocb(sizeof(int), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- MUTEX_ENTER(&state->lock);
- *(int *)np->b_wptr = state->flags & RCV_FLAGS;
- MUTEX_EXIT(&state->lock);
- np->b_wptr += sizeof(int);
- iop->ioc_count = sizeof(int);
- error = 0;
- break;
-
- case PPPIO_GETSTAT:
- np = allocb(sizeof(struct ppp_stats), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- psp = (struct ppp_stats *) np->b_wptr;
- np->b_wptr += sizeof(struct ppp_stats);
- bzero((caddr_t)psp, sizeof(struct ppp_stats));
- psp->p = state->stats;
- iop->ioc_count = sizeof(struct ppp_stats);
- error = 0;
- break;
-
- case PPPIO_LASTMOD:
- /* we knew this anyway */
- error = 0;
- break;
-
- default:
- error = -1;
- break;
- }
-
- if (error < 0)
- putnext(q, mp);
- else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
- mp->b_datap->db_type = M_IOCNAK;
- iop->ioc_count = 0;
- iop->ioc_error = error;
- qreply(q, mp);
- }
- break;
-
- case M_CTL:
- switch (*mp->b_rptr) {
- case PPPCTL_MTU:
- MUTEX_ENTER(&state->lock);
- state->mtu = ((unsigned short *)mp->b_rptr)[1];
- MUTEX_EXIT(&state->lock);
- break;
- case PPPCTL_MRU:
- MUTEX_ENTER(&state->lock);
- state->mru = ((unsigned short *)mp->b_rptr)[1];
- MUTEX_EXIT(&state->lock);
- break;
- case PPPCTL_UNIT:
- MUTEX_ENTER(&state->lock);
- state->unit = mp->b_rptr[1];
- MUTEX_EXIT(&state->lock);
- break;
- default:
- putnext(q, mp);
- return 0;
- }
- freemsg(mp);
- break;
-
- default:
- putnext(q, mp);
- }
-
- return 0;
-}
-
-/*
- * Read side put routine
- */
-static int
-ahdlc_rput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
-
- state = (ahdlc_state_t *) q->q_ptr;
- if (state == 0) {
- DPRINT("state == 0 in ahdlc_rput\n");
- freemsg(mp);
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
- case M_DATA:
- ahdlc_decode(q, mp);
- break;
-
- case M_HANGUP:
- MUTEX_ENTER(&state->lock);
- if (state->rx_buf != 0) {
- /* XXX would like to send this up for debugging */
- freemsg(state->rx_buf);
- state->rx_buf = 0;
- }
- state->flags = IFLUSH;
- MUTEX_EXIT(&state->lock);
- putnext(q, mp);
- break;
-
- default:
- putnext(q, mp);
- }
- return 0;
-}
-
-/*
- * Extract bit c from map m, to determine if c needs to be escaped
- */
-#define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
-
-static void
-ahdlc_encode(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
- u_int32_t *xaccm, loc_xaccm[8];
- ushort_t fcs;
- size_t outmp_len;
- mblk_t *outmp, *tmp;
- uchar_t *dp, fcs_val;
- int is_lcp, code;
-#if defined(SOL2)
- clock_t lbolt;
-#endif /* SOL2 */
-
- if (msgdsize(mp) < 4) {
- return;
- }
-
- state = (ahdlc_state_t *)q->q_ptr;
- MUTEX_ENTER(&state->lock);
-
- /*
- * Allocate an output buffer large enough to handle a case where all
- * characters need to be escaped
- */
- outmp_len = (msgdsize(mp) << 1) + /* input block x 2 */
- (sizeof(fcs) << 2) + /* HDLC FCS x 4 */
- (sizeof(uchar_t) << 1); /* HDLC flags x 2 */
-
- outmp = allocb(outmp_len, BPRI_MED);
- if (outmp == NULL) {
- state->stats.ppp_oerrors++;
- MUTEX_EXIT(&state->lock);
- putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
- return;
- }
-
-#if defined(SOL2)
- /*
- * Check if our last transmit happenned within flag_time, using
- * the system's LBOLT value in clock ticks
- */
- if (drv_getparm(LBOLT, &lbolt) != -1) {
- if (ABS((clock_t)lbolt - state->lbolt) > state->flag_time) {
- *outmp->b_wptr++ = PPP_FLAG;
- }
- state->lbolt = lbolt;
- } else {
- *outmp->b_wptr++ = PPP_FLAG;
- }
-#else
- /*
- * If the driver below still has a message to process, skip the
- * HDLC flag, otherwise, put one in the beginning
- */
- if (qsize(q->q_next) == 0) {
- *outmp->b_wptr++ = PPP_FLAG;
- }
-#endif
-
- /*
- * All control characters must be escaped for LCP packets with code
- * values between 1 (Conf-Req) and 7 (Code-Rej).
- */
- is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) &&
- (MSG_BYTE(mp, 1) == PPP_UI) &&
- (MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) &&
- (MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) &&
- LCP_USE_DFLT(mp));
-
- xaccm = state->xaccm;
- if (is_lcp) {
- bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm));
- loc_xaccm[0] = ~0; /* force escape on 0x00 through 0x1f */
- xaccm = loc_xaccm;
- }
-
- fcs = PPP_INITFCS; /* Initial FCS is 0xffff */
-
- /*
- * Process this block and the rest (if any) attached to the this one
- */
- for (tmp = mp; tmp; tmp = tmp->b_cont) {
- if (tmp->b_datap->db_type == M_DATA) {
- for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) {
- fcs = PPP_FCS(fcs, *dp);
- if (IN_TX_MAP(*dp, xaccm)) {
- *outmp->b_wptr++ = PPP_ESCAPE;
- *outmp->b_wptr++ = *dp ^ PPP_TRANS;
- } else {
- *outmp->b_wptr++ = *dp;
- }
- }
- } else {
- continue; /* skip if db_type is something other than M_DATA */
- }
- }
-
- /*
- * Append the HDLC FCS, making sure that escaping is done on any
- * necessary bytes
- */
- fcs_val = (fcs ^ 0xffff) & 0xff;
- if (IN_TX_MAP(fcs_val, xaccm)) {
- *outmp->b_wptr++ = PPP_ESCAPE;
- *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
- } else {
- *outmp->b_wptr++ = fcs_val;
- }
-
- fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff;
- if (IN_TX_MAP(fcs_val, xaccm)) {
- *outmp->b_wptr++ = PPP_ESCAPE;
- *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
- } else {
- *outmp->b_wptr++ = fcs_val;
- }
-
- /*
- * And finally, append the HDLC flag, and send it away
- */
- *outmp->b_wptr++ = PPP_FLAG;
-
- state->stats.ppp_obytes += msgdsize(outmp);
- state->stats.ppp_opackets++;
-
- MUTEX_EXIT(&state->lock);
-
- putnext(q, outmp);
-}
-
-/*
- * Checks the 32-bit receive ACCM to see if the byte needs un-escaping
- */
-#define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
- (m) & (1 << (c)))
-
-
-/*
- * Process received characters.
- */
-static void
-ahdlc_decode(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- ahdlc_state_t *state;
- mblk_t *om;
- uchar_t *dp;
-
- state = (ahdlc_state_t *) q->q_ptr;
-
- MUTEX_ENTER(&state->lock);
-
- state->stats.ppp_ibytes += msgdsize(mp);
-
- for (; mp != 0; om = mp->b_cont, freeb(mp), mp = om)
- for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) {
-
- /*
- * This should detect the lack of 8-bit communication channel
- * which is necessary for PPP to work. In addition, it also
- * checks on the parity.
- */
- if (*dp & 0x80)
- state->flags |= RCV_B7_1;
- else
- state->flags |= RCV_B7_0;
-
- if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f)))
- state->flags |= RCV_ODDP;
- else
- state->flags |= RCV_EVNP;
-
- /*
- * So we have a HDLC flag ...
- */
- if (*dp == PPP_FLAG) {
-
- /*
- * If we think that it marks the beginning of the frame,
- * then continue to process the next octects
- */
- if ((state->flags & IFLUSH) ||
- (state->rx_buf == 0) ||
- (msgdsize(state->rx_buf) == 0)) {
-
- state->flags &= ~IFLUSH;
- continue;
- }
-
- /*
- * We get here because the above condition isn't true,
- * in which case the HDLC flag was there to mark the end
- * of the frame (or so we think)
- */
- om = state->rx_buf;
-
- if (state->infcs == PPP_GOODFCS) {
- state->stats.ppp_ipackets++;
- adjmsg(om, -PPP_FCSLEN);
- putnext(q, om);
- } else {
- DPRINT2("ppp%d: bad fcs (len=%d)\n",
- state->unit, msgdsize(state->rx_buf));
- freemsg(state->rx_buf);
- state->flags &= ~(IFLUSH | ESCAPED);
- state->stats.ppp_ierrors++;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- }
-
- state->rx_buf = 0;
- continue;
- }
-
- if (state->flags & IFLUSH) {
- continue;
- }
-
- /*
- * Allocate a receive buffer, large enough to store a frame (after
- * un-escaping) of at least 1500 octets. If MRU is negotiated to
- * be more than the default, then allocate that much. In addition,
- * we add an extra 32-bytes for a fudge factor
- */
- if (state->rx_buf == 0) {
- state->rx_buf_size = (state->mru < PPP_MRU ? PPP_MRU : state->mru);
- state->rx_buf_size += (sizeof(u_int32_t) << 3);
- state->rx_buf = allocb(state->rx_buf_size, BPRI_MED);
-
- /*
- * If allocation fails, try again on the next frame
- */
- if (state->rx_buf == 0) {
- state->flags |= IFLUSH;
- continue;
- }
- state->flags &= ~(IFLUSH | ESCAPED);
- state->infcs = PPP_INITFCS;
- }
-
- if (*dp == PPP_ESCAPE) {
- state->flags |= ESCAPED;
- continue;
- }
-
- /*
- * Make sure we un-escape the necessary characters, as well as the
- * ones in our receive async control character map
- */
- if (state->flags & ESCAPED) {
- *dp ^= PPP_TRANS;
- state->flags &= ~ESCAPED;
- } else if (IN_RX_MAP(*dp, state->raccm))
- continue;
-
- /*
- * Unless the peer lied to us about the negotiated MRU, we should
- * never get a frame which is too long. If it happens, toss it away
- * and grab the next incoming one
- */
- if (msgdsize(state->rx_buf) < state->rx_buf_size) {
- state->infcs = PPP_FCS(state->infcs, *dp);
- *state->rx_buf->b_wptr++ = *dp;
- } else {
- DPRINT2("ppp%d: frame too long (%d)\n",
- state->unit, msgdsize(state->rx_buf));
- freemsg(state->rx_buf);
- state->rx_buf = 0;
- state->flags |= IFLUSH;
- }
- }
-
- MUTEX_EXIT(&state->lock);
-}
-
-static int
-msg_byte(mp, i)
- mblk_t *mp;
- unsigned int i;
-{
- while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
- mp = mp->b_cont;
- if (mp == 0)
- return -1;
- return mp->b_rptr[i];
-}
+++ /dev/null
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/modctl.h>
-#include <sys/sunddi.h>
-
-extern struct streamtab ppp_ahdlcinfo;
-
-static struct fmodsw fsw = {
- "ppp_ahdl",
- &ppp_ahdlcinfo,
- D_NEW | D_MP | D_MTQPAIR
-};
-
-extern struct mod_ops mod_strmodops;
-
-static struct modlstrmod modlstrmod = {
- &mod_strmodops,
- "PPP async HDLC module",
- &fsw
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- (void *) &modlstrmod,
- NULL
-};
-
-/*
- * Entry points for modloading.
- */
-int
-_init(void)
-{
- return mod_install(&modlinkage);
-}
-
-int
-_fini(void)
-{
- return mod_remove(&modlinkage);
-}
-
-int
-_info(mip)
- struct modinfo *mip;
-{
- return mod_info(&modlinkage, mip);
-}
+++ /dev/null
-/*
- * ppp_comp.c - STREAMS module for kernel-level compression and CCP support.
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * $Id: ppp_comp.c,v 1.3 2004/01/17 05:47:55 carlsonj Exp $
- */
-
-/*
- * This file is used under SVR4, Solaris 2, SunOS 4, and Digital UNIX.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/stream.h>
-
-#ifdef SVR4
-#include <sys/conf.h>
-#include <sys/cmn_err.h>
-#include <sys/ddi.h>
-#else
-#include <sys/user.h>
-#ifdef __osf__
-#include <sys/cmn_err.h>
-#endif
-#endif /* SVR4 */
-
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-#include "ppp_mod.h"
-
-#ifdef __osf__
-#include <sys/mbuf.h>
-#include <sys/protosw.h>
-#endif
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <net/vjcompress.h>
-
-#define PACKETPTR mblk_t *
-#include <net/ppp-comp.h>
-
-MOD_OPEN_DECL(ppp_comp_open);
-MOD_CLOSE_DECL(ppp_comp_close);
-static int ppp_comp_rput(queue_t *, mblk_t *);
-static int ppp_comp_rsrv(queue_t *);
-static int ppp_comp_wput(queue_t *, mblk_t *);
-static int ppp_comp_wsrv(queue_t *);
-static void ppp_comp_ccp(queue_t *, mblk_t *, int);
-static int msg_byte(mblk_t *, unsigned int);
-
-/* Extract byte i of message mp. */
-#define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
- msg_byte((mp), (i)))
-
-/* Is this LCP packet one we have to transmit using LCP defaults? */
-#define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
-
-#define PPP_COMP_ID 0xbadf
-static struct module_info minfo = {
-#ifdef PRIOQ
- PPP_COMP_ID, "ppp_comp", 0, INFPSZ, 16512, 16384,
-#else
- PPP_COMP_ID, "ppp_comp", 0, INFPSZ, 16384, 4096,
-#endif
-};
-
-static struct qinit r_init = {
- ppp_comp_rput, ppp_comp_rsrv, ppp_comp_open, ppp_comp_close,
- NULL, &minfo, NULL
-};
-
-static struct qinit w_init = {
- ppp_comp_wput, ppp_comp_wsrv, NULL, NULL, NULL, &minfo, NULL
-};
-
-#if defined(SVR4) && !defined(SOL2)
-int pcmpdevflag = 0;
-#define ppp_compinfo pcmpinfo
-#endif
-struct streamtab ppp_compinfo = {
- &r_init, &w_init, NULL, NULL
-};
-
-int ppp_comp_count; /* number of module instances in use */
-
-#ifdef __osf__
-
-static void ppp_comp_alloc(comp_state_t *);
-typedef struct memreq {
- unsigned char comp_opts[20];
- int cmd;
- int thread_status;
- char *returned_mem;
-} memreq_t;
-
-#endif
-
-typedef struct comp_state {
- int flags;
- int mru;
- int mtu;
- int unit;
- struct compressor *xcomp;
- void *xstate;
- struct compressor *rcomp;
- void *rstate;
- struct vjcompress vj_comp;
- int vj_last_ierrors;
- struct pppstat stats;
-#ifdef __osf__
- memreq_t memreq;
- thread_t thread;
-#endif
-} comp_state_t;
-
-
-#ifdef __osf__
-extern task_t first_task;
-#endif
-
-/* Bits in flags are as defined in pppio.h. */
-#define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
-#define LAST_MOD 0x1000000 /* no ppp modules below us */
-#define DBGLOG 0x2000000 /* log debugging stuff */
-
-#define MAX_IPHDR 128 /* max TCP/IP header size */
-#define MAX_VJHDR 20 /* max VJ compressed header size (?) */
-
-#undef MIN /* just in case */
-#define MIN(a, b) ((a) < (b)? (a): (b))
-
-/*
- * List of compressors we know about.
- */
-
-#if DO_BSD_COMPRESS
-extern struct compressor ppp_bsd_compress;
-#endif
-#if DO_DEFLATE
-extern struct compressor ppp_deflate, ppp_deflate_draft;
-#endif
-
-struct compressor *ppp_compressors[] = {
-#if DO_BSD_COMPRESS
- &ppp_bsd_compress,
-#endif
-#if DO_DEFLATE
- &ppp_deflate,
- &ppp_deflate_draft,
-#endif
- NULL
-};
-
-/*
- * STREAMS module entry points.
- */
-MOD_OPEN(ppp_comp_open)
-{
- comp_state_t *cp;
-#ifdef __osf__
- thread_t thread;
-#endif
-
- if (q->q_ptr == NULL) {
- cp = (comp_state_t *) ALLOC_SLEEP(sizeof(comp_state_t));
- if (cp == NULL)
- OPEN_ERROR(ENOSR);
- bzero((caddr_t)cp, sizeof(comp_state_t));
- WR(q)->q_ptr = q->q_ptr = (caddr_t) cp;
- cp->mru = PPP_MRU;
- cp->mtu = PPP_MTU;
- cp->xstate = NULL;
- cp->rstate = NULL;
- vj_compress_init(&cp->vj_comp, -1);
-#ifdef __osf__
- if (!(thread = kernel_thread_w_arg(first_task, ppp_comp_alloc, (void *)cp)))
- OPEN_ERROR(ENOSR);
- cp->thread = thread;
-#endif
- ++ppp_comp_count;
- qprocson(q);
- }
- return 0;
-}
-
-MOD_CLOSE(ppp_comp_close)
-{
- comp_state_t *cp;
-
- qprocsoff(q);
- cp = (comp_state_t *) q->q_ptr;
- if (cp != NULL) {
- if (cp->xstate != NULL)
- (*cp->xcomp->comp_free)(cp->xstate);
- if (cp->rstate != NULL)
- (*cp->rcomp->decomp_free)(cp->rstate);
-#ifdef __osf__
- if (!cp->thread)
- printf("ppp_comp_close: NULL thread!\n");
- else
- thread_terminate(cp->thread);
-#endif
- FREE(cp, sizeof(comp_state_t));
- q->q_ptr = NULL;
- OTHERQ(q)->q_ptr = NULL;
- --ppp_comp_count;
- }
- return 0;
-}
-
-#ifdef __osf__
-
-/* thread for calling back to a compressor's memory allocator
- * Needed for Digital UNIX since it's VM can't handle requests
- * for large amounts of memory without blocking. The thread
- * provides a context in which we can call a memory allocator
- * that may block.
- */
-static void
-ppp_comp_alloc(comp_state_t *cp)
-{
- int len, cmd;
- unsigned char *compressor_options;
- thread_t thread;
- void *(*comp_allocator)();
-
-
-#if defined(MAJOR_VERSION) && (MAJOR_VERSION <= 2)
-
- /* In 2.x and earlier the argument gets passed
- * in the thread structure itself. Yuck.
- */
- thread = current_thread();
- cp = thread->reply_port;
- thread->reply_port = PORT_NULL;
-
-#endif
-
- for (;;) {
- assert_wait((vm_offset_t)&cp->memreq.thread_status, TRUE);
- thread_block();
-
- if (thread_should_halt(current_thread()))
- thread_halt_self();
- cmd = cp->memreq.cmd;
- compressor_options = &cp->memreq.comp_opts[0];
- len = compressor_options[1];
- if (cmd == PPPIO_XCOMP) {
- cp->memreq.returned_mem = cp->xcomp->comp_alloc(compressor_options, len);
- if (!cp->memreq.returned_mem) {
- cp->memreq.thread_status = ENOSR;
- } else {
- cp->memreq.thread_status = 0;
- }
- } else {
- cp->memreq.returned_mem = cp->rcomp->decomp_alloc(compressor_options, len);
- if (!cp->memreq.returned_mem) {
- cp->memreq.thread_status = ENOSR;
- } else {
- cp->memreq.thread_status = 0;
- }
- }
- }
-}
-
-#endif /* __osf__ */
-
-/* here's the deal with memory allocation under Digital UNIX.
- * Some other may also benefit from this...
- * We can't ask for huge chunks of memory in a context where
- * the caller can't be put to sleep (like, here.) The alloc
- * is likely to fail. Instead we do this: the first time we
- * get called, kick off a thread to do the allocation. Return
- * immediately to the caller with EAGAIN, as an indication that
- * they should send down the ioctl again. By the time the
- * second call comes in it's likely that the memory allocation
- * thread will have returned with the requested memory. We will
- * continue to return EAGAIN however until the thread has completed.
- * When it has, we return zero (and the memory) if the allocator
- * was successful and ENOSR otherwise.
- *
- * Callers of the RCOMP and XCOMP ioctls are encouraged (but not
- * required) to loop for some number of iterations with a small
- * delay in the loop body (for instance a 1/10-th second "sleep"
- * via select.)
- */
-static int
-ppp_comp_wput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- struct iocblk *iop;
- comp_state_t *cp;
- int error, len, n;
- int flags, mask;
- mblk_t *np;
- struct compressor **comp;
- struct ppp_stats *psp;
- struct ppp_comp_stats *csp;
- unsigned char *opt_data;
- int nxslots, nrslots;
-
- cp = (comp_state_t *) q->q_ptr;
- if (cp == 0) {
- DPRINT("cp == 0 in ppp_comp_wput\n");
- freemsg(mp);
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
-
- case M_DATA:
- putq(q, mp);
- break;
-
- case M_IOCTL:
- iop = (struct iocblk *) mp->b_rptr;
- error = EINVAL;
- switch (iop->ioc_cmd) {
-
- case PPPIO_CFLAGS:
- /* set/get CCP state */
- if (iop->ioc_count != 2 * sizeof(int))
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ppp_comp_wput/%d: PPPIO_CFLAGS b_cont = 0!\n", cp->unit);
- break;
- }
- flags = ((int *) mp->b_cont->b_rptr)[0];
- mask = ((int *) mp->b_cont->b_rptr)[1];
- cp->flags = (cp->flags & ~mask) | (flags & mask);
- if ((mask & CCP_ISOPEN) && (flags & CCP_ISOPEN) == 0) {
- if (cp->xstate != NULL) {
- (*cp->xcomp->comp_free)(cp->xstate);
- cp->xstate = NULL;
- }
- if (cp->rstate != NULL) {
- (*cp->rcomp->decomp_free)(cp->rstate);
- cp->rstate = NULL;
- }
- cp->flags &= ~CCP_ISUP;
- }
- error = 0;
- iop->ioc_count = sizeof(int);
- ((int *) mp->b_cont->b_rptr)[0] = cp->flags;
- mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof(int);
- break;
-
- case PPPIO_VJINIT:
- /*
- * Initialize VJ compressor/decompressor
- */
- if (iop->ioc_count != 2)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ppp_comp_wput/%d: PPPIO_VJINIT b_cont = 0!\n", cp->unit);
- break;
- }
- nxslots = mp->b_cont->b_rptr[0] + 1;
- nrslots = mp->b_cont->b_rptr[1] + 1;
- if (nxslots > MAX_STATES || nrslots > MAX_STATES)
- break;
- vj_compress_init(&cp->vj_comp, nxslots);
- cp->vj_last_ierrors = cp->stats.ppp_ierrors;
- error = 0;
- iop->ioc_count = 0;
- break;
-
- case PPPIO_XCOMP:
- case PPPIO_RCOMP:
- if (iop->ioc_count <= 0)
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ppp_comp_wput/%d: PPPIO_[XR]COMP b_cont = 0!\n", cp->unit);
- break;
- }
- opt_data = mp->b_cont->b_rptr;
- len = mp->b_cont->b_wptr - opt_data;
- if (len > iop->ioc_count)
- len = iop->ioc_count;
- if (opt_data[1] < 2 || opt_data[1] > len)
- break;
- for (comp = ppp_compressors; *comp != NULL; ++comp)
- if ((*comp)->compress_proto == opt_data[0]) {
- /* here's the handler! */
- error = 0;
-#ifndef __osf__
- if (iop->ioc_cmd == PPPIO_XCOMP) {
- /* A previous call may have fetched memory for a compressor
- * that's now being retired or reset. Free it using it's
- * mechanism for freeing stuff.
- */
- if (cp->xstate != NULL) {
- (*cp->xcomp->comp_free)(cp->xstate);
- cp->xstate = NULL;
- }
- cp->xcomp = *comp;
- cp->xstate = (*comp)->comp_alloc(opt_data, len);
- if (cp->xstate == NULL)
- error = ENOSR;
- } else {
- if (cp->rstate != NULL) {
- (*cp->rcomp->decomp_free)(cp->rstate);
- cp->rstate = NULL;
- }
- cp->rcomp = *comp;
- cp->rstate = (*comp)->decomp_alloc(opt_data, len);
- if (cp->rstate == NULL)
- error = ENOSR;
- }
-#else
- if ((error = cp->memreq.thread_status) != EAGAIN)
- if (iop->ioc_cmd == PPPIO_XCOMP) {
- if (cp->xstate) {
- (*cp->xcomp->comp_free)(cp->xstate);
- cp->xstate = 0;
- }
- /* sanity check for compressor options
- */
- if (sizeof (cp->memreq.comp_opts) < len) {
- printf("can't handle options for compressor %d (%d)\n", opt_data[0],
- opt_data[1]);
- cp->memreq.thread_status = ENOSR;
- cp->memreq.returned_mem = 0;
- }
- /* fill in request for the thread and kick it off
- */
- if (cp->memreq.thread_status == 0 && !cp->memreq.returned_mem) {
- bcopy(opt_data, cp->memreq.comp_opts, len);
- cp->memreq.cmd = PPPIO_XCOMP;
- cp->xcomp = *comp;
- error = cp->memreq.thread_status = EAGAIN;
- thread_wakeup((vm_offset_t)&cp->memreq.thread_status);
- } else {
- cp->xstate = cp->memreq.returned_mem;
- cp->memreq.returned_mem = 0;
- cp->memreq.thread_status = 0;
- }
- } else {
- if (cp->rstate) {
- (*cp->rcomp->decomp_free)(cp->rstate);
- cp->rstate = NULL;
- }
- if (sizeof (cp->memreq.comp_opts) < len) {
- printf("can't handle options for compressor %d (%d)\n", opt_data[0],
- opt_data[1]);
- cp->memreq.thread_status = ENOSR;
- cp->memreq.returned_mem = 0;
- }
- if (cp->memreq.thread_status == 0 && !cp->memreq.returned_mem) {
- bcopy(opt_data, cp->memreq.comp_opts, len);
- cp->memreq.cmd = PPPIO_RCOMP;
- cp->rcomp = *comp;
- error = cp->memreq.thread_status = EAGAIN;
- thread_wakeup((vm_offset_t)&cp->memreq.thread_status);
- } else {
- cp->rstate = cp->memreq.returned_mem;
- cp->memreq.returned_mem = 0;
- cp->memreq.thread_status = 0;
- }
- }
-#endif
- break;
- }
- iop->ioc_count = 0;
- break;
-
- case PPPIO_GETSTAT:
- if ((cp->flags & LAST_MOD) == 0) {
- error = -1; /* let the ppp_ahdl module handle it */
- break;
- }
- np = allocb(sizeof(struct ppp_stats), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- psp = (struct ppp_stats *) np->b_wptr;
- np->b_wptr += sizeof(struct ppp_stats);
- iop->ioc_count = sizeof(struct ppp_stats);
- psp->p = cp->stats;
- psp->vj = cp->vj_comp.stats;
- error = 0;
- break;
-
- case PPPIO_GETCSTAT:
- np = allocb(sizeof(struct ppp_comp_stats), BPRI_HI);
- if (np == 0) {
- error = ENOSR;
- break;
- }
- if (mp->b_cont != 0)
- freemsg(mp->b_cont);
- mp->b_cont = np;
- csp = (struct ppp_comp_stats *) np->b_wptr;
- np->b_wptr += sizeof(struct ppp_comp_stats);
- iop->ioc_count = sizeof(struct ppp_comp_stats);
- bzero((caddr_t)csp, sizeof(struct ppp_comp_stats));
- if (cp->xstate != 0)
- (*cp->xcomp->comp_stat)(cp->xstate, &csp->c);
- if (cp->rstate != 0)
- (*cp->rcomp->decomp_stat)(cp->rstate, &csp->d);
- error = 0;
- break;
-
- case PPPIO_DEBUG:
- if (iop->ioc_count != sizeof(int))
- break;
- if (mp->b_cont == 0) {
- DPRINT1("ppp_comp_wput/%d: PPPIO_DEBUG b_cont = 0!\n", cp->unit);
- break;
- }
- n = *(int *)mp->b_cont->b_rptr;
- if (n == PPPDBG_LOG + PPPDBG_COMP) {
- DPRINT1("ppp_comp%d: debug log enabled\n", cp->unit);
- cp->flags |= DBGLOG;
- error = 0;
- iop->ioc_count = 0;
- } else {
- error = -1;
- }
- break;
-
- case PPPIO_LASTMOD:
- cp->flags |= LAST_MOD;
- error = 0;
- break;
-
- default:
- error = -1;
- break;
- }
-
- if (error < 0)
- putnext(q, mp);
- else if (error == 0) {
- mp->b_datap->db_type = M_IOCACK;
- qreply(q, mp);
- } else {
- mp->b_datap->db_type = M_IOCNAK;
- iop->ioc_error = error;
- iop->ioc_count = 0;
- qreply(q, mp);
- }
- break;
-
- case M_CTL:
- switch (*mp->b_rptr) {
- case PPPCTL_MTU:
- cp->mtu = ((unsigned short *)mp->b_rptr)[1];
- break;
- case PPPCTL_MRU:
- cp->mru = ((unsigned short *)mp->b_rptr)[1];
- break;
- case PPPCTL_UNIT:
- cp->unit = mp->b_rptr[1];
- break;
- }
- putnext(q, mp);
- break;
-
- default:
- putnext(q, mp);
- }
-
- return 0;
-}
-
-static int
-ppp_comp_wsrv(q)
- queue_t *q;
-{
- mblk_t *mp, *cmp = NULL;
- comp_state_t *cp;
- int len, proto, type, hlen, code;
- struct ip *ip;
- unsigned char *vjhdr, *dp;
-
- cp = (comp_state_t *) q->q_ptr;
- if (cp == 0) {
- DPRINT("cp == 0 in ppp_comp_wsrv\n");
- return 0;
- }
-
- while ((mp = getq(q)) != 0) {
- /* assert(mp->b_datap->db_type == M_DATA) */
-#ifdef PRIOQ
- if (!bcanputnext(q,mp->b_band))
-#else
- if (!canputnext(q))
-#endif /* PRIOQ */
- {
- putbq(q, mp);
- break;
- }
-
- /*
- * First check the packet length and work out what the protocol is.
- */
- len = msgdsize(mp);
- if (len < PPP_HDRLEN) {
- DPRINT1("ppp_comp_wsrv: bogus short packet (%d)\n", len);
- freemsg(mp);
- cp->stats.ppp_oerrors++;
- putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
- continue;
- }
- proto = (MSG_BYTE(mp, 2) << 8) + MSG_BYTE(mp, 3);
-
- /*
- * Make sure we've got enough data in the first mblk
- * and that we are its only user.
- */
- if (proto == PPP_CCP)
- hlen = len;
- else if (proto == PPP_IP)
- hlen = PPP_HDRLEN + MAX_IPHDR;
- else
- hlen = PPP_HDRLEN;
- if (hlen > len)
- hlen = len;
- if (mp->b_wptr < mp->b_rptr + hlen || mp->b_datap->db_ref > 1) {
- PULLUP(mp, hlen);
- if (mp == 0) {
- DPRINT1("ppp_comp_wsrv: pullup failed (%d)\n", hlen);
- cp->stats.ppp_oerrors++;
- putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
- continue;
- }
- }
-
- /*
- * Do VJ compression if requested.
- */
- if (proto == PPP_IP && (cp->flags & COMP_VJC)) {
- ip = (struct ip *) (mp->b_rptr + PPP_HDRLEN);
- if (ip->ip_p == IPPROTO_TCP) {
- type = vj_compress_tcp(ip, len - PPP_HDRLEN, &cp->vj_comp,
- (cp->flags & COMP_VJCCID), &vjhdr);
- switch (type) {
- case TYPE_UNCOMPRESSED_TCP:
- mp->b_rptr[3] = proto = PPP_VJC_UNCOMP;
- break;
- case TYPE_COMPRESSED_TCP:
- dp = vjhdr - PPP_HDRLEN;
- dp[1] = mp->b_rptr[1]; /* copy control field */
- dp[0] = mp->b_rptr[0]; /* copy address field */
- dp[2] = 0; /* set protocol field */
- dp[3] = proto = PPP_VJC_COMP;
- mp->b_rptr = dp;
- break;
- }
- }
- }
-
- /*
- * Do packet compression if enabled.
- */
- if (proto == PPP_CCP)
- ppp_comp_ccp(q, mp, 0);
- else if (proto != PPP_LCP && (cp->flags & CCP_COMP_RUN)
- && cp->xstate != NULL) {
- len = msgdsize(mp);
- (*cp->xcomp->compress)(cp->xstate, &cmp, mp, len,
- (cp->flags & CCP_ISUP? cp->mtu + PPP_HDRLEN: 0));
- if (cmp != NULL) {
-#ifdef PRIOQ
- cmp->b_band=mp->b_band;
-#endif /* PRIOQ */
- freemsg(mp);
- mp = cmp;
- }
- }
-
- /*
- * Do address/control and protocol compression if enabled.
- */
- if ((cp->flags & COMP_AC)
- && !(proto == PPP_LCP && LCP_USE_DFLT(mp))) {
- mp->b_rptr += 2; /* drop the address & ctrl fields */
- if (proto < 0x100 && (cp->flags & COMP_PROT))
- ++mp->b_rptr; /* drop the high protocol byte */
- } else if (proto < 0x100 && (cp->flags & COMP_PROT)) {
- /* shuffle up the address & ctrl fields */
- mp->b_rptr[2] = mp->b_rptr[1];
- mp->b_rptr[1] = mp->b_rptr[0];
- ++mp->b_rptr;
- }
-
- cp->stats.ppp_opackets++;
- cp->stats.ppp_obytes += msgdsize(mp);
- putnext(q, mp);
- }
-
- return 0;
-}
-
-static int
-ppp_comp_rput(q, mp)
- queue_t *q;
- mblk_t *mp;
-{
- comp_state_t *cp;
- struct iocblk *iop;
- struct ppp_stats *psp;
-
- cp = (comp_state_t *) q->q_ptr;
- if (cp == 0) {
- DPRINT("cp == 0 in ppp_comp_rput\n");
- freemsg(mp);
- return 0;
- }
-
- switch (mp->b_datap->db_type) {
-
- case M_DATA:
- putq(q, mp);
- break;
-
- case M_IOCACK:
- iop = (struct iocblk *) mp->b_rptr;
- switch (iop->ioc_cmd) {
- case PPPIO_GETSTAT:
- /*
- * Catch this on the way back from the ppp_ahdl module
- * so we can fill in the VJ stats.
- */
- if (mp->b_cont == 0 || iop->ioc_count != sizeof(struct ppp_stats))
- break;
- psp = (struct ppp_stats *) mp->b_cont->b_rptr;
- psp->vj = cp->vj_comp.stats;
- break;
- }
- putnext(q, mp);
- break;
-
- case M_CTL:
- switch (mp->b_rptr[0]) {
- case PPPCTL_IERROR:
- ++cp->stats.ppp_ierrors;
- break;
- case PPPCTL_OERROR:
- ++cp->stats.ppp_oerrors;
- break;
- }
- putnext(q, mp);
- break;
-
- default:
- putnext(q, mp);
- }
-
- return 0;
-}
-
-static int
-ppp_comp_rsrv(q)
- queue_t *q;
-{
- int proto, rv, i;
- mblk_t *mp, *dmp = NULL, *np;
- uchar_t *dp, *iphdr;
- comp_state_t *cp;
- int len, hlen, vjlen;
- u_int iphlen;
-
- cp = (comp_state_t *) q->q_ptr;
- if (cp == 0) {
- DPRINT("cp == 0 in ppp_comp_rsrv\n");
- return 0;
- }
-
- while ((mp = getq(q)) != 0) {
- /* assert(mp->b_datap->db_type == M_DATA) */
- if (!canputnext(q)) {
- putbq(q, mp);
- break;
- }
-
- len = msgdsize(mp);
- cp->stats.ppp_ibytes += len;
- cp->stats.ppp_ipackets++;
-
- /*
- * First work out the protocol and where the PPP header ends.
- */
- i = 0;
- proto = MSG_BYTE(mp, 0);
- if (proto == PPP_ALLSTATIONS) {
- i = 2;
- proto = MSG_BYTE(mp, 2);
- }
- if ((proto & 1) == 0) {
- ++i;
- proto = (proto << 8) + MSG_BYTE(mp, i);
- }
- hlen = i + 1;
-
- /*
- * Now reconstruct a complete, contiguous PPP header at the
- * start of the packet.
- */
- if (hlen < ((cp->flags & DECOMP_AC)? 0: 2)
- + ((cp->flags & DECOMP_PROT)? 1: 2)) {
- /* count these? */
- goto bad;
- }
- if (mp->b_rptr + hlen > mp->b_wptr) {
- adjmsg(mp, hlen); /* XXX check this call */
- hlen = 0;
- }
- if (hlen != PPP_HDRLEN) {
- /*
- * We need to put some bytes on the front of the packet
- * to make a full-length PPP header.
- * If we can put them in *mp, we do, otherwise we
- * tack another mblk on the front.
- * XXX we really shouldn't need to carry around
- * the address and control at this stage.
- */
- dp = mp->b_rptr + hlen - PPP_HDRLEN;
- if (dp < mp->b_datap->db_base || mp->b_datap->db_ref > 1) {
- np = allocb(PPP_HDRLEN, BPRI_MED);
- if (np == 0)
- goto bad;
- np->b_cont = mp;
- mp->b_rptr += hlen;
- mp = np;
- dp = mp->b_wptr;
- mp->b_wptr += PPP_HDRLEN;
- } else
- mp->b_rptr = dp;
-
- dp[0] = PPP_ALLSTATIONS;
- dp[1] = PPP_UI;
- dp[2] = proto >> 8;
- dp[3] = proto;
- }
-
- /*
- * Now see if we have a compressed packet to decompress,
- * or a CCP packet to take notice of.
- */
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto == PPP_CCP) {
- len = msgdsize(mp);
- if (mp->b_wptr < mp->b_rptr + len) {
- PULLUP(mp, len);
- if (mp == 0)
- goto bad;
- }
- ppp_comp_ccp(q, mp, 1);
- } else if (proto == PPP_COMP) {
- if ((cp->flags & CCP_ISUP)
- && (cp->flags & CCP_DECOMP_RUN) && cp->rstate
- && (cp->flags & CCP_ERR) == 0) {
- rv = (*cp->rcomp->decompress)(cp->rstate, mp, &dmp);
- switch (rv) {
- case DECOMP_OK:
- freemsg(mp);
- mp = dmp;
- if (mp == NULL) {
- /* no error, but no packet returned either. */
- continue;
- }
- break;
- case DECOMP_ERROR:
- cp->flags |= CCP_ERROR;
- ++cp->stats.ppp_ierrors;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- break;
- case DECOMP_FATALERROR:
- cp->flags |= CCP_FATALERROR;
- ++cp->stats.ppp_ierrors;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- break;
- }
- }
- } else if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
- (*cp->rcomp->incomp)(cp->rstate, mp);
- }
-
- /*
- * Now do VJ decompression.
- */
- proto = PPP_PROTOCOL(mp->b_rptr);
- if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
- len = msgdsize(mp) - PPP_HDRLEN;
- if ((cp->flags & DECOMP_VJC) == 0 || len <= 0)
- goto bad;
-
- /*
- * Advance past the ppp header.
- * Here we assume that the whole PPP header is in the first mblk.
- */
- np = mp;
- dp = np->b_rptr + PPP_HDRLEN;
- if (dp >= mp->b_wptr) {
- np = np->b_cont;
- dp = np->b_rptr;
- }
-
- /*
- * Make sure we have sufficient contiguous data at this point.
- */
- hlen = (proto == PPP_VJC_COMP)? MAX_VJHDR: MAX_IPHDR;
- if (hlen > len)
- hlen = len;
- if (np->b_wptr < dp + hlen || np->b_datap->db_ref > 1) {
- PULLUP(mp, hlen + PPP_HDRLEN);
- if (mp == 0)
- goto bad;
- np = mp;
- dp = np->b_rptr + PPP_HDRLEN;
- }
-
- if (proto == PPP_VJC_COMP) {
- /*
- * Decompress VJ-compressed packet.
- * First reset compressor if an input error has occurred.
- */
- if (cp->stats.ppp_ierrors != cp->vj_last_ierrors) {
- if (cp->flags & DBGLOG)
- DPRINT1("ppp%d: resetting VJ\n", cp->unit);
- vj_uncompress_err(&cp->vj_comp);
- cp->vj_last_ierrors = cp->stats.ppp_ierrors;
- }
-
- vjlen = vj_uncompress_tcp(dp, np->b_wptr - dp, len,
- &cp->vj_comp, &iphdr, &iphlen);
- if (vjlen < 0) {
- if (cp->flags & DBGLOG)
- DPRINT2("ppp%d: vj_uncomp_tcp failed, pkt len %d\n",
- cp->unit, len);
- ++cp->vj_last_ierrors; /* so we don't reset next time */
- goto bad;
- }
-
- /* drop ppp and vj headers off */
- if (mp != np) {
- freeb(mp);
- mp = np;
- }
- mp->b_rptr = dp + vjlen;
-
- /* allocate a new mblk for the ppp and ip headers */
- if ((np = allocb(iphlen + PPP_HDRLEN + 4, BPRI_MED)) == 0)
- goto bad;
- dp = np->b_rptr; /* prepend mblk with TCP/IP hdr */
- dp[0] = PPP_ALLSTATIONS; /* reconstruct PPP header */
- dp[1] = PPP_UI;
- dp[2] = PPP_IP >> 8;
- dp[3] = PPP_IP;
- bcopy((caddr_t)iphdr, (caddr_t)dp + PPP_HDRLEN, iphlen);
- np->b_wptr = dp + iphlen + PPP_HDRLEN;
- np->b_cont = mp;
-
- /* XXX there seems to be a bug which causes panics in strread
- if we make an mbuf with only the IP header in it :-( */
- if (mp->b_wptr - mp->b_rptr > 4) {
- bcopy((caddr_t)mp->b_rptr, (caddr_t)np->b_wptr, 4);
- mp->b_rptr += 4;
- np->b_wptr += 4;
- } else {
- bcopy((caddr_t)mp->b_rptr, (caddr_t)np->b_wptr,
- mp->b_wptr - mp->b_rptr);
- np->b_wptr += mp->b_wptr - mp->b_rptr;
- np->b_cont = mp->b_cont;
- freeb(mp);
- }
-
- mp = np;
-
- } else {
- /*
- * "Decompress" a VJ-uncompressed packet.
- */
- cp->vj_last_ierrors = cp->stats.ppp_ierrors;
- if (!vj_uncompress_uncomp(dp, hlen, &cp->vj_comp)) {
- if (cp->flags & DBGLOG)
- DPRINT2("ppp%d: vj_uncomp_uncomp failed, pkt len %d\n",
- cp->unit, len);
- ++cp->vj_last_ierrors; /* don't need to reset next time */
- goto bad;
- }
- mp->b_rptr[3] = PPP_IP; /* fix up the PPP protocol field */
- }
- }
-
- putnext(q, mp);
- continue;
-
- bad:
- if (mp != 0)
- freemsg(mp);
- cp->stats.ppp_ierrors++;
- putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
- }
-
- return 0;
-}
-
-/*
- * Handle a CCP packet being sent or received.
- * Here all the data in the packet is in a single mbuf.
- */
-static void
-ppp_comp_ccp(q, mp, rcvd)
- queue_t *q;
- mblk_t *mp;
- int rcvd;
-{
- int len, clen;
- comp_state_t *cp;
- unsigned char *dp;
-
- len = msgdsize(mp);
- if (len < PPP_HDRLEN + CCP_HDRLEN)
- return;
-
- cp = (comp_state_t *) q->q_ptr;
- dp = mp->b_rptr + PPP_HDRLEN;
- len -= PPP_HDRLEN;
- clen = CCP_LENGTH(dp);
- if (clen > len)
- return;
-
- switch (CCP_CODE(dp)) {
- case CCP_CONFREQ:
- case CCP_TERMREQ:
- case CCP_TERMACK:
- cp->flags &= ~CCP_ISUP;
- break;
-
- case CCP_CONFACK:
- if ((cp->flags & (CCP_ISOPEN | CCP_ISUP)) == CCP_ISOPEN
- && clen >= CCP_HDRLEN + CCP_OPT_MINLEN
- && clen >= CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN)) {
- if (!rcvd) {
- if (cp->xstate != NULL
- && (*cp->xcomp->comp_init)
- (cp->xstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
- cp->unit, 0, ((cp->flags & DBGLOG) != 0)))
- cp->flags |= CCP_COMP_RUN;
- } else {
- if (cp->rstate != NULL
- && (*cp->rcomp->decomp_init)
- (cp->rstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
- cp->unit, 0, cp->mru, ((cp->flags & DBGLOG) != 0)))
- cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
- }
- }
- break;
-
- case CCP_RESETACK:
- if (cp->flags & CCP_ISUP) {
- if (!rcvd) {
- if (cp->xstate && (cp->flags & CCP_COMP_RUN))
- (*cp->xcomp->comp_reset)(cp->xstate);
- } else {
- if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
- (*cp->rcomp->decomp_reset)(cp->rstate);
- cp->flags &= ~CCP_ERROR;
- }
- }
- }
- break;
- }
-}
-
-#if 0
-dump_msg(mp)
- mblk_t *mp;
-{
- dblk_t *db;
-
- while (mp != 0) {
- db = mp->b_datap;
- DPRINT2("mp=%x cont=%x ", mp, mp->b_cont);
- DPRINT3("rptr=%x wptr=%x datap=%x\n", mp->b_rptr, mp->b_wptr, db);
- DPRINT2(" base=%x lim=%x", db->db_base, db->db_lim);
- DPRINT2(" ref=%d type=%d\n", db->db_ref, db->db_type);
- mp = mp->b_cont;
- }
-}
-#endif
-
-static int
-msg_byte(mp, i)
- mblk_t *mp;
- unsigned int i;
-{
- while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
- mp = mp->b_cont;
- if (mp == 0)
- return -1;
- return mp->b_rptr[i];
-}
+++ /dev/null
-/*
- * ppp_comp_mod.c - modload support for PPP compression STREAMS module.
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * $Id: ppp_comp_mod.c,v 1.2 2002/12/06 09:49:16 paulus Exp $
- */
-
-/*
- * This file is used under Solaris 2.
- */
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/modctl.h>
-#include <sys/sunddi.h>
-
-extern struct streamtab ppp_compinfo;
-
-static struct fmodsw fsw = {
- "ppp_comp",
- &ppp_compinfo,
- D_NEW | D_MP | D_MTQPAIR
-};
-
-extern struct mod_ops mod_strmodops;
-
-static struct modlstrmod modlstrmod = {
- &mod_strmodops,
- "PPP compression module",
- &fsw
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- (void *) &modlstrmod,
- NULL
-};
-
-/*
- * Entry points for modloading.
- */
-int
-_init(void)
-{
- return mod_install(&modlinkage);
-}
-
-int
-_fini(void)
-{
- return mod_remove(&modlinkage);
-}
-
-int
-_info(mip)
- struct modinfo *mip;
-{
- return mod_info(&modlinkage, mip);
-}
+++ /dev/null
-/*
- * ppp_mod.c - modload support for PPP pseudo-device driver.
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Paul Mackerras
- * <paulus@ozlabs.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * $Id: ppp_mod.c,v 1.3 2004/01/17 05:47:55 carlsonj Exp $
- */
-
-/*
- * This file is used under Solaris 2.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/conf.h>
-#include <sys/modctl.h>
-#include <sys/sunddi.h>
-#include <sys/ksynch.h>
-
-static int ppp_identify(dev_info_t *);
-static int ppp_attach(dev_info_t *, ddi_attach_cmd_t);
-static int ppp_detach(dev_info_t *, ddi_detach_cmd_t);
-static int ppp_devinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
-
-extern struct streamtab pppinfo;
-extern krwlock_t ppp_lower_lock;
-
-static dev_info_t *ppp_dip;
-
-static struct cb_ops cb_ppp_ops = {
- nulldev, nulldev, nodev, nodev, /* cb_open, ... */
- nodev, nodev, nodev, nodev, /* cb_dump, ... */
- nodev, nodev, nodev, nochpoll, /* cb_devmap, ... */
- ddi_prop_op, /* cb_prop_op */
- &pppinfo, /* cb_stream */
- D_NEW|D_MP|D_MTQPAIR|D_MTOUTPERIM|D_MTOCEXCL /* cb_flag */
-};
-
-static struct dev_ops ppp_ops = {
- DEVO_REV, /* devo_rev */
- 0, /* devo_refcnt */
- ppp_devinfo, /* devo_getinfo */
- ppp_identify, /* devo_identify */
- nulldev, /* devo_probe */
- ppp_attach, /* devo_attach */
- ppp_detach, /* devo_detach */
- nodev, /* devo_reset */
- &cb_ppp_ops, /* devo_cb_ops */
- NULL /* devo_bus_ops */
-};
-
-/*
- * Module linkage information
- */
-
-static struct modldrv modldrv = {
- &mod_driverops, /* says this is a pseudo driver */
- "PPP-2.4.7 multiplexing driver",
- &ppp_ops /* driver ops */
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- (void *) &modldrv,
- NULL
-};
-
-int
-_init(void)
-{
- return mod_install(&modlinkage);
-}
-
-int
-_fini(void)
-{
- return mod_remove(&modlinkage);
-}
-
-int
-_info(mip)
- struct modinfo *mip;
-{
- return mod_info(&modlinkage, mip);
-}
-
-static int
-ppp_identify(dip)
- dev_info_t *dip;
-{
- /* This entry point is not used as of Solaris 10 */
-#ifdef DDI_IDENTIFIED
- return strcmp(ddi_get_name(dip), "ppp") == 0? DDI_IDENTIFIED:
- DDI_NOT_IDENTIFIED;
-#else
- return 0;
-#endif
-}
-
-static int
-ppp_attach(dip, cmd)
- dev_info_t *dip;
- ddi_attach_cmd_t cmd;
-{
-
- if (cmd != DDI_ATTACH)
- return DDI_FAILURE;
- if (ddi_create_minor_node(dip, "ppp", S_IFCHR, 0, DDI_PSEUDO, CLONE_DEV)
- == DDI_FAILURE) {
- ddi_remove_minor_node(dip, NULL);
- return DDI_FAILURE;
- }
- rw_init(&ppp_lower_lock, NULL, RW_DRIVER, NULL);
- return DDI_SUCCESS;
-}
-
-static int
-ppp_detach(dip, cmd)
- dev_info_t *dip;
- ddi_detach_cmd_t cmd;
-{
- rw_destroy(&ppp_lower_lock);
- ddi_remove_minor_node(dip, NULL);
- return DDI_SUCCESS;
-}
-
-static int
-ppp_devinfo(dip, cmd, arg, result)
- dev_info_t *dip;
- ddi_info_cmd_t cmd;
- void *arg;
- void **result;
-{
- int error;
-
- error = DDI_SUCCESS;
- switch (cmd) {
- case DDI_INFO_DEVT2DEVINFO:
- if (ppp_dip == NULL)
- error = DDI_FAILURE;
- else
- *result = (void *) ppp_dip;
- break;
- case DDI_INFO_DEVT2INSTANCE:
- *result = NULL;
- break;
- default:
- error = DDI_FAILURE;
- }
- return error;
-}
+++ /dev/null
-/*
- * Miscellaneous definitions for PPP STREAMS modules.
- */
-
-/*
- * Macros for allocating and freeing kernel memory.
- */
-#ifdef SVR4 /* SVR4, including Solaris 2 */
-#include <sys/kmem.h>
-#define ALLOC_SLEEP(n) kmem_alloc((n), KM_SLEEP)
-#define ALLOC_NOSLEEP(n) kmem_alloc((n), KM_NOSLEEP)
-#define FREE(p, n) kmem_free((p), (n))
-#endif
-
-#ifdef SUNOS4
-#include <sys/kmem_alloc.h> /* SunOS 4.x */
-#define ALLOC_SLEEP(n) kmem_alloc((n), KMEM_SLEEP)
-#define ALLOC_NOSLEEP(n) kmem_alloc((n), KMEM_NOSLEEP)
-#define FREE(p, n) kmem_free((p), (n))
-#define NOTSUSER() (suser()? 0: EPERM)
-#define bcanputnext(q, band) canputnext((q))
-#endif /* SunOS 4 */
-
-#ifdef __osf__
-#include <sys/malloc.h>
-
-/* caution: this mirrors macros in sys/malloc.h, and uses interfaces
- * which are subject to change.
- * The problems are that:
- * - the official MALLOC macro wants the lhs of the assignment as an argument,
- * and it takes care of the assignment itself (yuck.)
- * - PPP insists on using "FREE" which conflicts with a macro of the same name.
- *
- */
-#ifdef BUCKETINDX /* V2.0 */
-#define ALLOC_SLEEP(n) (void *)malloc((u_long)(n), BUCKETP(n), M_DEVBUF, M_WAITOK)
-#define ALLOC_NOSLEEP(n) (void *)malloc((u_long)(n), BUCKETP(n), M_DEVBUF, M_NOWAIT)
-#else
-#define ALLOC_SLEEP(n) (void *)malloc((u_long)(n), BUCKETINDEX(n), M_DEVBUF, M_WAITOK)
-#define ALLOC_NOSLEEP(n) (void *)malloc((u_long)(n), BUCKETINDEX(n), M_DEVBUF, M_NOWAIT)
-#endif
-
-#define bcanputnext(q, band) canputnext((q))
-
-#ifdef FREE
-#undef FREE
-#endif
-#define FREE(p, n) free((void *)(p), M_DEVBUF)
-
-#define NO_DLPI 1
-
-#ifndef IFT_PPP
-#define IFT_PPP 0x17
-#endif
-
-#include <sys/proc.h>
-#define NOTSUSER() (suser(u.u_procp->p_rcred, &u.u_acflag) ? EPERM : 0)
-
-/* #include "ppp_osf.h" */
-
-#endif /* __osf__ */
-
-#ifdef AIX4
-#define ALLOC_SLEEP(n) xmalloc((n), 0, pinned_heap) /* AIX V4.x */
-#define ALLOC_NOSLEEP(n) xmalloc((n), 0, pinned_heap) /* AIX V4.x */
-#define FREE(p, n) xmfree((p), pinned_heap)
-#define NOTSUSER() (suser()? 0: EPERM)
-#endif /* AIX */
-
-/*
- * Macros for printing debugging stuff.
- */
-#ifdef DEBUG
-#if defined(SVR4) || defined(__osf__)
-#if defined(SNI)
-#include <sys/strlog.h>
-#define STRLOG_ID 4712
-#define DPRINT(f) strlog(STRLOG_ID, 0, 0, SL_TRACE, f)
-#define DPRINT1(f, a1) strlog(STRLOG_ID, 0, 0, SL_TRACE, f, a1)
-#define DPRINT2(f, a1, a2) strlog(STRLOG_ID, 0, 0, SL_TRACE, f, a1, a2)
-#define DPRINT3(f, a1, a2, a3) strlog(STRLOG_ID, 0, 0, SL_TRACE, f, a1, a2, a3)
-#else
-#define DPRINT(f) cmn_err(CE_CONT, f)
-#define DPRINT1(f, a1) cmn_err(CE_CONT, f, a1)
-#define DPRINT2(f, a1, a2) cmn_err(CE_CONT, f, a1, a2)
-#define DPRINT3(f, a1, a2, a3) cmn_err(CE_CONT, f, a1, a2, a3)
-#endif /* SNI */
-#else
-#define DPRINT(f) printf(f)
-#define DPRINT1(f, a1) printf(f, a1)
-#define DPRINT2(f, a1, a2) printf(f, a1, a2)
-#define DPRINT3(f, a1, a2, a3) printf(f, a1, a2, a3)
-#endif /* SVR4 or OSF */
-
-#else
-#define DPRINT(f) 0
-#define DPRINT1(f, a1) 0
-#define DPRINT2(f, a1, a2) 0
-#define DPRINT3(f, a1, a2, a3) 0
-#endif /* DEBUG */
-
-#ifndef SVR4
-typedef unsigned char uchar_t;
-typedef unsigned short ushort_t;
-#ifndef __osf__
-typedef int minor_t;
-#endif
-#endif
-
-/*
- * If we don't have multithreading support, define substitutes.
- */
-#ifndef D_MP
-# define qprocson(q)
-# define qprocsoff(q)
-# define put(q, mp) ((*(q)->q_qinfo->qi_putp)((q), (mp)))
-# define canputnext(q) canput((q)->q_next)
-# define qwriter(q, mp, func, scope) (func)((q), (mp))
-#endif
-
-#ifdef D_MP
-/* Use msgpullup if we have other multithreading support. */
-#define PULLUP(mp, len) \
- do { \
- mblk_t *np = msgpullup((mp), (len)); \
- freemsg((mp)); \
- mp = np; \
- } while (0)
-
-#else
-/* Use pullupmsg if we don't have any multithreading support. */
-#define PULLUP(mp, len) \
- do { \
- if (!pullupmsg((mp), (len))) { \
- freemsg((mp)); \
- mp = 0; \
- } \
- } while (0)
-#endif
-
-/*
- * How to declare the open and close procedures for a module.
- */
-#ifdef SVR4
-#define MOD_OPEN_DECL(name) \
-static int name(queue_t *, dev_t *, int, int, cred_t *)
-
-#define MOD_CLOSE_DECL(name) \
-static int name(queue_t *, int, cred_t *)
-
-#define MOD_OPEN(name) \
-static int name(q, devp, flag, sflag, credp) \
- queue_t *q; \
- dev_t *devp; \
- int flag, sflag; \
- cred_t *credp;
-
-#define MOD_CLOSE(name) \
-static int name(q, flag, credp) \
- queue_t *q; \
- int flag; \
- cred_t *credp;
-
-#define OPEN_ERROR(x) return (x)
-#define DRV_OPEN_OK(dev) return 0
-
-#define NOTSUSER() (drv_priv(credp))
-
-#else /* not SVR4 */
-#define MOD_OPEN_DECL(name) \
-static int name(queue_t *, int, int, int)
-
-#define MOD_CLOSE_DECL(name) \
-static int name(queue_t *, int)
-
-#define MOD_OPEN(name) \
-static int name(q, dev, flag, sflag) \
- queue_t *q; \
- int dev; \
- int flag, sflag;
-
-#define MOD_CLOSE(name) \
-static int name(q, flag) \
- queue_t *q; \
- int flag;
-
-#define OPEN_ERROR(x) { u.u_error = (x); return OPENFAIL; }
-#define DRV_OPEN_OK(dev) return (dev)
-
-#endif /* SVR4 */