diff options
Diffstat (limited to '')
83 files changed, 0 insertions, 40517 deletions
diff --git a/c/src/exec/libnetworking/net/.cvsignore b/c/src/exec/libnetworking/net/.cvsignore deleted file mode 100644 index 282522db03..0000000000 --- a/c/src/exec/libnetworking/net/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -Makefile.in diff --git a/c/src/exec/libnetworking/net/Makefile.am b/c/src/exec/libnetworking/net/Makefile.am deleted file mode 100644 index 7490585015..0000000000 --- a/c/src/exec/libnetworking/net/Makefile.am +++ /dev/null @@ -1,51 +0,0 @@ -## -## $Id$ -## - - -include_netdir = $(includedir)/net - -LIBNAME = lib.a -LIB = $(ARCH)/$(LIBNAME) - -C_FILES = if.c if_ethersubr.c if_loop.c radix.c route.c rtsock.c raw_cb.c \ - raw_usrreq.c if_ppp.c ppp_tty.c pppcompress.c -C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) - -OBJS = $(C_O_FILES) - -include $(top_srcdir)/../automake/multilib.am -include $(top_srcdir)/../automake/compile.am -include $(top_srcdir)/../automake/lib.am - -# -# Add local stuff here using += -# - -AM_CPPFLAGS += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC \ - -DBOOTP_COMPAT - -$(LIB): $(OBJS) - $(make-library) - -all-local: $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(LIB) - -.PRECIOUS: $(LIB) - -EXTRA_DIST = if.c if_ethersubr.c if_loop.c radix.c raw_cb.c raw_usrreq.c \ - route.c rtsock.c - -include_net_HEADERS = bpf.h ethernet.h if.h if_arp.h if_dl.h if_llc.h if_ppp.h \ - if_types.h netisr.h ppp-comp.h ppp_defs.h radix.h raw_cb.h route.h \ - if_pppvar.h pppcompress.h - -PREINSTALL_FILES = $(PROJECT_INCLUDE)/net \ - $(include_net_HEADERS:%=$(PROJECT_INCLUDE)/net/%) - -$(PROJECT_INCLUDE)/net: - @$(mkinstalldirs) $@ - -$(PROJECT_INCLUDE)/net/%.h: %.h - $(INSTALL_DATA) $< $@ - -include $(top_srcdir)/../automake/local.am diff --git a/c/src/exec/libnetworking/net/bpf.h b/c/src/exec/libnetworking/net/bpf.h deleted file mode 100644 index 7847d72470..0000000000 --- a/c/src/exec/libnetworking/net/bpf.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 1990, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from the Stanford/CMU enet packet filter, - * (net/enet.c) distributed as part of 4.3BSD, and code contributed - * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence - * Berkeley Laboratory. - * - * 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. - * - * @(#)bpf.h 8.1 (Berkeley) 6/10/93 - * @(#)bpf.h 1.34 (LBL) 6/16/96 - * - * $Id$ - */ - -#ifndef _NET_BPF_H_ -#define _NET_BPF_H_ - -/* BSD style release date */ -#define BPF_RELEASE 199606 - -typedef int32_t bpf_int32; -typedef u_int32_t bpf_u_int32; - -/* - * Alignment macros. BPF_WORDALIGN rounds up to the next - * even multiple of BPF_ALIGNMENT. - */ -#define BPF_ALIGNMENT sizeof(bpf_int32) -#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) - -#define BPF_MAXINSNS 512 -#define BPF_MAXBUFSIZE 0x8000 -#define BPF_MINBUFSIZE 32 - -/* - * Structure for BIOCSETF. - */ -struct bpf_program { - u_int bf_len; - struct bpf_insn *bf_insns; -}; - -/* - * Struct returned by BIOCGSTATS. - */ -struct bpf_stat { - u_int bs_recv; /* number of packets received */ - u_int bs_drop; /* number of packets dropped */ -}; - -/* - * Struct return by BIOCVERSION. This represents the version number of - * the filter language described by the instruction encodings below. - * bpf understands a program iff kernel_major == filter_major && - * kernel_minor >= filter_minor, that is, if the value returned by the - * running kernel has the same major number and a minor number equal - * equal to or less than the filter being downloaded. Otherwise, the - * results are undefined, meaning an error may be returned or packets - * may be accepted haphazardly. - * It has nothing to do with the source code version. - */ -struct bpf_version { - u_short bv_major; - u_short bv_minor; -}; -/* Current version number of filter architecture. */ -#define BPF_MAJOR_VERSION 1 -#define BPF_MINOR_VERSION 1 - -#define BIOCGBLEN _IOR('B',102, u_int) -#define BIOCSBLEN _IOWR('B',102, u_int) -#define BIOCSETF _IOW('B',103, struct bpf_program) -#define BIOCFLUSH _IO('B',104) -#define BIOCPROMISC _IO('B',105) -#define BIOCGDLT _IOR('B',106, u_int) -#define BIOCGETIF _IOR('B',107, struct ifreq) -#define BIOCSETIF _IOW('B',108, struct ifreq) -#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) -#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) -#define BIOCGSTATS _IOR('B',111, struct bpf_stat) -#define BIOCIMMEDIATE _IOW('B',112, u_int) -#define BIOCVERSION _IOR('B',113, struct bpf_version) -#define BIOCGRSIG _IOR('B',114, u_int) -#define BIOCSRSIG _IOW('B',115, u_int) - -/* - * Structure prepended to each packet. - */ -struct bpf_hdr { - struct timeval bh_tstamp; /* time stamp */ - bpf_u_int32 bh_caplen; /* length of captured portion */ - bpf_u_int32 bh_datalen; /* original length of packet */ - u_short bh_hdrlen; /* length of bpf header (this struct - plus alignment padding) */ -}; -/* - * Because the structure above is not a multiple of 4 bytes, some compilers - * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. - * Only the kernel needs to know about it; applications use bh_hdrlen. - */ -#ifdef KERNEL -#define SIZEOF_BPF_HDR 18 -#endif - -/* - * Data-link level type codes. - */ -#define DLT_NULL 0 /* no link-layer encapsulation */ -#define DLT_EN10MB 1 /* Ethernet (10Mb) */ -#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ -#define DLT_AX25 3 /* Amateur Radio AX.25 */ -#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ -#define DLT_CHAOS 5 /* Chaos */ -#define DLT_IEEE802 6 /* IEEE 802 Networks */ -#define DLT_ARCNET 7 /* ARCNET */ -#define DLT_SLIP 8 /* Serial Line IP */ -#define DLT_PPP 9 /* Point-to-point Protocol */ -#define DLT_FDDI 10 /* FDDI */ -#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ - -/* - * The instruction encodings. - */ -/* instruction classes */ -#define BPF_CLASS(code) ((code) & 0x07) -#define BPF_LD 0x00 -#define BPF_LDX 0x01 -#define BPF_ST 0x02 -#define BPF_STX 0x03 -#define BPF_ALU 0x04 -#define BPF_JMP 0x05 -#define BPF_RET 0x06 -#define BPF_MISC 0x07 - -/* ld/ldx fields */ -#define BPF_SIZE(code) ((code) & 0x18) -#define BPF_W 0x00 -#define BPF_H 0x08 -#define BPF_B 0x10 -#define BPF_MODE(code) ((code) & 0xe0) -#define BPF_IMM 0x00 -#define BPF_ABS 0x20 -#define BPF_IND 0x40 -#define BPF_MEM 0x60 -#define BPF_LEN 0x80 -#define BPF_MSH 0xa0 - -/* alu/jmp fields */ -#define BPF_OP(code) ((code) & 0xf0) -#define BPF_ADD 0x00 -#define BPF_SUB 0x10 -#define BPF_MUL 0x20 -#define BPF_DIV 0x30 -#define BPF_OR 0x40 -#define BPF_AND 0x50 -#define BPF_LSH 0x60 -#define BPF_RSH 0x70 -#define BPF_NEG 0x80 -#define BPF_JA 0x00 -#define BPF_JEQ 0x10 -#define BPF_JGT 0x20 -#define BPF_JGE 0x30 -#define BPF_JSET 0x40 -#define BPF_SRC(code) ((code) & 0x08) -#define BPF_K 0x00 -#define BPF_X 0x08 - -/* ret - BPF_K and BPF_X also apply */ -#define BPF_RVAL(code) ((code) & 0x18) -#define BPF_A 0x10 - -/* misc */ -#define BPF_MISCOP(code) ((code) & 0xf8) -#define BPF_TAX 0x00 -#define BPF_TXA 0x80 - -/* - * The instruction data structure. - */ -struct bpf_insn { - u_short code; - u_char jt; - u_char jf; - bpf_u_int32 k; -}; - -/* - * Macros for insn array initializers. - */ -#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } -#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } - -#ifdef KERNEL -int bpf_validate __P((struct bpf_insn *, int)); -void bpf_tap __P((struct ifnet *, u_char *, u_int)); -void bpf_mtap __P((struct ifnet *, struct mbuf *)); -void bpfattach __P((struct ifnet *, u_int, u_int)); -void bpfilterattach __P((int)); -u_int bpf_filter __P((struct bpf_insn *, u_char *, u_int, u_int)); -#endif - -/* - * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). - */ -#define BPF_MEMWORDS 16 - -#endif diff --git a/c/src/exec/libnetworking/net/bsd-comp.c b/c/src/exec/libnetworking/net/bsd-comp.c deleted file mode 100644 index 294457cc2c..0000000000 --- a/c/src/exec/libnetworking/net/bsd-comp.c +++ /dev/null @@ -1,1117 +0,0 @@ -/* $Id$ */ - -/* 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 mbufs on BSD-derived systems. - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <net/if.h> -#include <net/if_types.h> -#include <net/ppp_defs.h> -#include <net/if_ppp.h> - -#define PACKETPTR struct mbuf * -#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_int16_t seqno; /* sequence # 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_int16_t *lens; /* array of lengths of codes */ - struct bsd_dict { - union { /* hash value */ - u_int32_t fcode; - struct { -#if BYTE_ORDER == LITTLE_ENDIAN - u_int16_t 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_int16_t prefix; /* preceding code */ -#endif - } hs; - } f; - u_int16_t codem1; /* output of hash table -1 */ - u_int16_t 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 __P((u_char *options, int opt_len)); -static void *bsd_decomp_alloc __P((u_char *options, int opt_len)); -static void bsd_free __P((void *state)); -static int bsd_comp_init __P((void *state, u_char *options, int opt_len, - int unit, int hdrlen, int debug)); -static int bsd_decomp_init __P((void *state, u_char *options, int opt_len, - int unit, int hdrlen, int mru, int debug)); -static int bsd_compress __P((void *state, struct mbuf **mret, - struct mbuf *mp, int slen, int maxolen)); -static void bsd_incomp __P((void *state, struct mbuf *dmsg)); -static int bsd_decompress __P((void *state, struct mbuf *cmp, - struct mbuf **dmpp)); -static void bsd_reset __P((void *state)); -static void bsd_comp_stats __P((void *state, struct compstat *stats)); - -/* - * Procedures exported to if_ppp.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) - -static void bsd_clear __P((struct bsd_db *)); -static int bsd_check __P((struct bsd_db *)); -static void *bsd_alloc __P((u_char *, int, int)); -static int bsd_init __P((struct bsd_db *, u_char *, int, int, int, int, - int, int)); - -/* - * 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 < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS - || options[1] != CILEN_BSD_COMPRESS - || 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])); - MALLOC(db, struct bsd_db *, newlen, M_DEVBUF, M_NOWAIT); - if (!db) - return NULL; - bzero(db, sizeof(*db) - sizeof(db->dict)); - - if (!decomp) { - db->lens = NULL; - } else { - MALLOC(db->lens, u_int16_t *, (maxmaxcode+1) * sizeof(db->lens[0]), - M_DEVBUF, M_NOWAIT); - if (!db->lens) { - FREE(db, M_DEVBUF); - 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, M_DEVBUF); - FREE(db, M_DEVBUF); -} - -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; -#ifndef DEBUG - if (debug) -#endif - 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. - */ -int /* new slen */ -bsd_compress(state, mret, mp, slen, maxolen) - void *state; - struct mbuf **mret; /* return compressed mbuf chain here */ - struct mbuf *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; - u_char *rptr, *wptr; - u_char *cp_end; - int olen; - struct mbuf *m; - -#define PUTBYTE(v) { \ - ++olen; \ - if (wptr) { \ - *wptr++ = (v); \ - if (wptr >= cp_end) { \ - m->m_len = wptr - mtod(m, u_char *); \ - MGET(m->m_next, M_DONTWAIT, MT_DATA); \ - m = m->m_next; \ - if (m) { \ - m->m_len = 0; \ - if (maxolen - olen > MLEN) \ - MCLGET(m, M_DONTWAIT); \ - wptr = mtod(m, u_char *); \ - cp_end = wptr + M_TRAILINGSPACE(m); \ - } else \ - wptr = NULL; \ - } \ - } \ -} - -#define OUTPUT(ent) { \ - bitno -= n_bits; \ - accm |= ((ent) << bitno); \ - do { \ - PUTBYTE(accm >> 24); \ - accm <<= 8; \ - bitno += 8; \ - } while (bitno <= 24); \ -} - - /* - * If the protocol is not in the range we're interested in, - * just return without compressing the packet. If it is, - * the protocol becomes the first byte to compress. - */ - rptr = mtod(mp, u_char *); - ent = PPP_PROTOCOL(rptr); - if (ent < 0x21 || ent > 0xf9) { - *mret = NULL; - return slen; - } - - /* Don't generate compressed packets which are larger than - the uncompressed packet. */ - if (maxolen > slen) - maxolen = slen; - - /* Allocate one mbuf to start with. */ - MGET(m, M_DONTWAIT, MT_DATA); - *mret = m; - if (m != NULL) { - m->m_len = 0; - if (maxolen + db->hdrlen > MLEN) - MCLGET(m, M_DONTWAIT); - m->m_data += db->hdrlen; - wptr = mtod(m, u_char *); - cp_end = wptr + M_TRAILINGSPACE(m); - } else - wptr = cp_end = NULL; - - /* - * Copy the PPP header over, changing the protocol, - * and install the 2-byte packet sequence number. - */ - if (wptr) { - *wptr++ = PPP_ADDRESS(rptr); /* assumes the ppp header is */ - *wptr++ = PPP_CONTROL(rptr); /* all in one mbuf */ - *wptr++ = 0; /* change the protocol */ - *wptr++ = PPP_COMP; - *wptr++ = db->seqno >> 8; - *wptr++ = db->seqno; - } - ++db->seqno; - - olen = 0; - rptr += PPP_HDRLEN; - slen = mp->m_len - PPP_HDRLEN; - ilen = slen + 1; - for (;;) { - if (slen <= 0) { - mp = mp->m_next; - if (!mp) - break; - rptr = mtod(mp, u_char *); - slen = mp->m_len; - 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); - - if (m != NULL) { - m->m_len = wptr - mtod(m, u_char *); - m->m_next = NULL; - } - - /* - * 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) { - /* throw away the compressed stuff if it is longer than uncompressed */ - if (*mret != NULL) { - m_freem(*mret); - *mret = NULL; - } - ++db->incomp_count; - db->incomp_bytes += ilen; - } else { - ++db->comp_count; - db->comp_bytes += olen + BSD_OVHD; - } - - 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; - struct mbuf *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; - u_int32_t hval, disp; - int slen, ilen; - u_int bitno = 7; - u_char *rptr; - u_int ent; - - /* - * If the protocol is not in the range we're interested in, - * just return without looking at the packet. If it is, - * the protocol becomes the first byte to "compress". - */ - rptr = mtod(dmsg, u_char *); - ent = PPP_PROTOCOL(rptr); - if (ent < 0x21 || ent > 0xf9) - return; - - db->seqno++; - ilen = 1; /* count the protocol as 1 byte */ - rptr += PPP_HDRLEN; - slen = dmsg->m_len - PPP_HDRLEN; - for (;;) { - if (slen <= 0) { - dmsg = dmsg->m_next; - if (!dmsg) - break; - rptr = mtod(dmsg, u_char *); - slen = dmsg->m_len; - continue; - } - 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. - */ -int -bsd_decompress(state, cmp, dmpp) - void *state; - struct mbuf *cmp, **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; - struct mbuf *m, *dmp, *mret; - int adrs, ctrl, ilen; - int space, codelen, extra; - - /* - * Save the address/control from the PPP header - * and then get the sequence number. - */ - *dmpp = NULL; - rptr = mtod(cmp, u_char *); - adrs = PPP_ADDRESS(rptr); - ctrl = PPP_CONTROL(rptr); - rptr += PPP_HDRLEN; - len = cmp->m_len - PPP_HDRLEN; - seq = 0; - for (i = 0; i < 2; ++i) { - while (len <= 0) { - cmp = cmp->m_next; - if (cmp == NULL) - return DECOMP_ERROR; - rptr = mtod(cmp, u_char *); - len = cmp->m_len; - } - seq = (seq << 8) + *rptr++; - --len; - } - - /* - * Check the sequence number and give up if it differs from - * the value we're expecting. - */ - 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; - } - ++db->seqno; - - /* - * Allocate one mbuf to start with. - */ - MGETHDR(dmp, M_DONTWAIT, MT_DATA); - if (dmp == NULL) - return DECOMP_ERROR; - mret = dmp; - dmp->m_len = 0; - dmp->m_next = NULL; - MCLGET(dmp, M_DONTWAIT); - dmp->m_data += db->hdrlen; - wptr = mtod(dmp, u_char *); - space = M_TRAILINGSPACE(dmp) - PPP_HDRLEN + 1; - - /* - * 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; - - ilen = len; - oldcode = CLEAR; - explen = 0; - for (;;) { - if (len == 0) { - cmp = cmp->m_next; - if (!cmp) /* quit at end of message */ - break; - rptr = mtod(cmp, u_char *); - len = cmp->m_len; - 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 mbuf at the end. - */ - if (len > 0 || cmp->m_next != NULL) { - while ((cmp = cmp->m_next) != NULL) - len += cmp->m_len; - if (len > 0) { - m_freem(mret); - if (db->debug) - printf("bsd_decomp%d: bad CLEAR\n", db->unit); - return DECOMP_FATALERROR; /* probably a bug */ - } - } - bsd_clear(db); - explen = ilen = 0; - break; - } - - if (incode > max_ent + 2 || incode > db->maxmaxcode - || (incode > max_ent && oldcode == CLEAR)) { - m_freem(mret); - if (db->debug) { - printf("bsd_decomp%d: bad code 0x%x oldcode=0x%x ", - db->unit, incode, oldcode); - printf("max_ent=0x%x explen=%d seqno=%d\n", - max_ent, explen, 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) { - m_freem(mret); - if (db->debug) { - printf("bsd_decomp%d: ran out of mru\n", db->unit); -#ifdef DEBUG - while ((cmp = cmp->m_next) != NULL) - len += cmp->m_len; - printf(" len=%d, finchar=0x%x, codelen=%d, explen=%d\n", - len, finchar, codelen, explen); -#endif - } - return DECOMP_FATALERROR; - } - - /* - * For simplicity, the decoded characters go in a single mbuf, - * so we allocate a single extra cluster mbuf if necessary. - */ - if ((space -= codelen + extra) < 0) { - dmp->m_len = wptr - mtod(dmp, u_char *); - MGET(m, M_DONTWAIT, MT_DATA); - if (m == NULL) { - m_freem(mret); - return DECOMP_ERROR; - } - m->m_len = 0; - m->m_next = NULL; - dmp->m_next = m; - MCLGET(m, M_DONTWAIT); - space = M_TRAILINGSPACE(m) - (codelen + extra); - if (space < 0) { - /* now that's what I call *compression*. */ - m_freem(mret); - return DECOMP_ERROR; - } - dmp = m; - wptr = mtod(dmp, u_char *); - } - - /* - * Decode this code and install it in the decompressed buffer. - */ - p = (wptr += codelen); - while (finchar > LAST) { - dictp = &db->dict[db->dict[finchar].cptr]; -#ifdef DEBUG - if (--codelen <= 0 || dictp->codem1 != finchar-1) - goto bad; -#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; - u_int32_t 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; - } - dmp->m_len = wptr - mtod(dmp, u_char *); - - /* - * 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; - -#ifdef DEBUG - bad: - if (codelen <= 0) { - 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); - } else if (dictp->codem1 != finchar-1) { - 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); - } - m_freem(mret); - return DECOMP_FATALERROR; -#endif /* DEBUG */ -} -#endif /* DO_BSD_COMPRESS */ diff --git a/c/src/exec/libnetworking/net/ethernet.h b/c/src/exec/libnetworking/net/ethernet.h deleted file mode 100644 index c6c07189ec..0000000000 --- a/c/src/exec/libnetworking/net/ethernet.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Fundamental constants relating to ethernet. - * - * $Id$ - * - */ - -#ifndef _NET_ETHERNET_H_ -#define _NET_ETHERNET_H_ - -/* - * The number of bytes in an ethernet (MAC) address. - */ -#define ETHER_ADDR_LEN 6 - -/* - * The number of bytes in the type field. - */ -#define ETHER_TYPE_LEN 2 - -/* - * The number of bytes in the trailing CRC field. - */ -#define ETHER_CRC_LEN 4 - -/* - * The length of the combined header. - */ -#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN) - -/* - * The minimum packet length. - */ -#define ETHER_MIN_LEN 64 - -/* - * The maximum packet length. - */ -#define ETHER_MAX_LEN 1518 - -/* - * A macro to validate a length with - */ -#define ETHER_IS_VALID_LEN(foo) \ - ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) - -/* - * Structure of a 10Mb/s Ethernet header. - */ -struct ether_header { - u_char ether_dhost[ETHER_ADDR_LEN]; - u_char ether_shost[ETHER_ADDR_LEN]; - u_short ether_type; -}; - -/* - * Structure of a 48-bit Ethernet address. - */ -struct ether_addr { - u_char octet[ETHER_ADDR_LEN]; -}; - -#endif diff --git a/c/src/exec/libnetworking/net/if.c b/c/src/exec/libnetworking/net/if.c deleted file mode 100644 index 6f42b29903..0000000000 --- a/c/src/exec/libnetworking/net/if.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)if.c 8.3 (Berkeley) 1/4/94 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/mbuf.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/protosw.h> -#include <sys/kernel.h> -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/syslog.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/if_dl.h> -#include <net/if_types.h> -#include <net/radix.h> - -/* - * System initialization - */ - -static int ifconf __P((int, caddr_t)); - void ifinit __P((void *)); -static void if_qflush __P((struct ifqueue *)); -static void if_slowtimo __P((void *)); -static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *)); - -SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL) - - -int ifqmaxlen = IFQ_MAXLEN; -struct ifnet *ifnet; - -/* - * Network interface utility routines. - * - * Routines with ifa_ifwith* names take sockaddr *'s as - * parameters. - * - * This routine assumes that it will be called at splimp() or higher. - */ -/* ARGSUSED*/ -void -ifinit(dummy) - void *dummy; -{ - register struct ifnet *ifp; - - for (ifp = ifnet; ifp; ifp = ifp->if_next) - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - if_slowtimo(0); -} - -int if_index = 0; -struct ifaddr **ifnet_addrs; - - -/* - * Attach an interface to the - * list of "active" interfaces. - */ -void -if_attach(ifp) - struct ifnet *ifp; -{ - unsigned socksize, ifasize; - int namelen, masklen; - char workbuf[64]; - register struct ifnet **p = &ifnet; - register struct sockaddr_dl *sdl; - register struct ifaddr *ifa; - static int if_indexlim = 8; - - - while (*p) - p = &((*p)->if_next); - *p = ifp; - ifp->if_index = ++if_index; - microtime(&ifp->if_lastchange); - if (ifnet_addrs == 0 || if_index >= if_indexlim) { - unsigned n = (if_indexlim <<= 1) * sizeof(ifa); - struct ifaddr **q = (struct ifaddr **) - malloc(n, M_IFADDR, M_WAITOK); - bzero((caddr_t)q, n); - if (ifnet_addrs) { - bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); - free((caddr_t)ifnet_addrs, M_IFADDR); - } - ifnet_addrs = q; - } - /* - * create a Link Level name for this device - */ - namelen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); -#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) - masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; - socksize = masklen + ifp->if_addrlen; -#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) - socksize = ROUNDUP(socksize); - if (socksize < sizeof(*sdl)) - socksize = sizeof(*sdl); - ifasize = sizeof(*ifa) + 2 * socksize; - ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); - if (ifa) { - bzero((caddr_t)ifa, ifasize); - sdl = (struct sockaddr_dl *)(ifa + 1); - sdl->sdl_len = socksize; - sdl->sdl_family = AF_LINK; - bcopy(workbuf, sdl->sdl_data, namelen); - sdl->sdl_nlen = namelen; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = ifp->if_type; - ifnet_addrs[if_index - 1] = ifa; - ifa->ifa_ifp = ifp; - ifa->ifa_next = ifp->if_addrlist; - ifa->ifa_rtrequest = link_rtrequest; - ifp->if_addrlist = ifa; - ifa->ifa_addr = (struct sockaddr *)sdl; - - sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); - ifa->ifa_netmask = (struct sockaddr *)sdl; - sdl->sdl_len = masklen; - while (namelen != 0) - sdl->sdl_data[--namelen] = 0xff; - } -} -/* - * Locate an interface based on a complete address. - */ -/*ARGSUSED*/ -struct ifaddr * -ifa_ifwithaddr(addr) - register struct sockaddr *addr; -{ - register struct ifnet *ifp; - register struct ifaddr *ifa; - -#define equal(a1, a2) \ - (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) - for (ifp = ifnet; ifp; ifp = ifp->if_next) - for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr->sa_family != addr->sa_family) - continue; - if (equal(addr, ifa->ifa_addr)) - return (ifa); - if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && - equal(ifa->ifa_broadaddr, addr)) - return (ifa); - } - return ((struct ifaddr *)0); -} -/* - * Locate the point to point interface with a given destination address. - */ -/*ARGSUSED*/ -struct ifaddr * -ifa_ifwithdstaddr(addr) - register struct sockaddr *addr; -{ - register struct ifnet *ifp; - register struct ifaddr *ifa; - - for (ifp = ifnet; ifp; ifp = ifp->if_next) - if (ifp->if_flags & IFF_POINTOPOINT) - for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr->sa_family != addr->sa_family) - continue; - if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) - return (ifa); - } - return ((struct ifaddr *)0); -} - -/* - * Find an interface on a specific network. If many, choice - * is most specific found. - */ -struct ifaddr * -ifa_ifwithnet(addr) - struct sockaddr *addr; -{ - register struct ifnet *ifp; - register struct ifaddr *ifa; - struct ifaddr *ifa_maybe = (struct ifaddr *) 0; - u_int af = addr->sa_family; - char *addr_data = addr->sa_data, *cplim; - - if (af == AF_LINK) { - register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; - if (sdl->sdl_index && sdl->sdl_index <= if_index) - return (ifnet_addrs[sdl->sdl_index - 1]); - } - for (ifp = ifnet; ifp; ifp = ifp->if_next) { - for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { - register char *cp, *cp2, *cp3; - - if (ifa->ifa_addr->sa_family != af) - next: continue; - if (ifp->if_flags & IFF_POINTOPOINT) { - if (ifa->ifa_dstaddr != 0 - && equal(addr, ifa->ifa_dstaddr)) - return (ifa); - } else { - /* - * if we have a special address handler, - * then use it instead of the generic one. - */ - if (ifa->ifa_claim_addr) { - if ((*ifa->ifa_claim_addr)(ifa, addr)) { - return (ifa); - } else { - continue; - } - } - - /* - * Scan all the bits in the ifa's address. - * If a bit dissagrees with what we are - * looking for, mask it with the netmask - * to see if it really matters. - * (A byte at a time) - */ - if (ifa->ifa_netmask == 0) - continue; - cp = addr_data; - cp2 = ifa->ifa_addr->sa_data; - cp3 = ifa->ifa_netmask->sa_data; - cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; - while (cp3 < cplim) - if ((*cp++ ^ *cp2++) & *cp3++) - goto next; - if (ifa_maybe == 0 || - rn_refines((caddr_t)ifa->ifa_netmask, - (caddr_t)ifa_maybe->ifa_netmask)) - ifa_maybe = ifa; - } - } - } - return (ifa_maybe); -} - -/* - * Find an interface address specific to an interface best matching - * a given address. - */ -struct ifaddr * -ifaof_ifpforaddr(addr, ifp) - struct sockaddr *addr; - register struct ifnet *ifp; -{ - register struct ifaddr *ifa; - register char *cp, *cp2, *cp3; - register char *cplim; - struct ifaddr *ifa_maybe = 0; - u_int af = addr->sa_family; - - if (af >= AF_MAX) - return (0); - for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr->sa_family != af) - continue; - if (ifa_maybe == 0) - ifa_maybe = ifa; - if (ifa->ifa_netmask == 0) { - if (equal(addr, ifa->ifa_addr) || - (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) - return (ifa); - continue; - } - if (ifp->if_flags & IFF_POINTOPOINT) { - if (equal(addr, ifa->ifa_dstaddr)) - return (ifa); - } else { - cp = addr->sa_data; - cp2 = ifa->ifa_addr->sa_data; - cp3 = ifa->ifa_netmask->sa_data; - cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; - for (; cp3 < cplim; cp3++) - if ((*cp++ ^ *cp2++) & *cp3) - break; - if (cp3 == cplim) - return (ifa); - } - } - return (ifa_maybe); -} - -#include <net/route.h> - -/* - * Default action when installing a route with a Link Level gateway. - * Lookup an appropriate real ifa to point to. - * This should be moved to /sys/net/link.c eventually. - */ -static void -link_rtrequest(cmd, rt, sa) - int cmd; - register struct rtentry *rt; - struct sockaddr *sa; -{ - register struct ifaddr *ifa; - struct sockaddr *dst; - struct ifnet *ifp; - - if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || - ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) - return; - ifa = ifaof_ifpforaddr(dst, ifp); - if (ifa) { - IFAFREE(rt->rt_ifa); - rt->rt_ifa = ifa; - ifa->ifa_refcnt++; - if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) - ifa->ifa_rtrequest(cmd, rt, sa); - } -} - -/* - * Mark an interface down and notify protocols of - * the transition. - * NOTE: must be called at splnet or eqivalent. - */ -void -if_down(ifp) - register struct ifnet *ifp; -{ - register struct ifaddr *ifa; - - ifp->if_flags &= ~IFF_UP; - microtime(&ifp->if_lastchange); - for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) - pfctlinput(PRC_IFDOWN, ifa->ifa_addr); - if_qflush(&ifp->if_snd); - rt_ifmsg(ifp); -} - -/* - * Mark an interface up and notify protocols of - * the transition. - * NOTE: must be called at splnet or eqivalent. - */ -void -if_up(ifp) - register struct ifnet *ifp; -{ - - ifp->if_flags |= IFF_UP; - microtime(&ifp->if_lastchange); -#ifdef notyet - register struct ifaddr *ifa; - /* this has no effect on IP, and will kill all iso connections XXX */ - for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) - pfctlinput(PRC_IFUP, ifa->ifa_addr); -#endif - rt_ifmsg(ifp); -} - -/* - * Flush an interface queue. - */ -static void -if_qflush(ifq) - register struct ifqueue *ifq; -{ - register struct mbuf *m, *n; - - n = ifq->ifq_head; - while ((m = n) != 0) { - n = m->m_act; - m_freem(m); - } - ifq->ifq_head = 0; - ifq->ifq_tail = 0; - ifq->ifq_len = 0; -} - -/* - * Handle interface watchdog timer routines. Called - * from softclock, we decrement timers (if set) and - * call the appropriate interface routine on expiration. - */ -static void -if_slowtimo(arg) - void *arg; -{ - register struct ifnet *ifp; - int s = splimp(); - - for (ifp = ifnet; ifp; ifp = ifp->if_next) { - if (ifp->if_timer == 0 || --ifp->if_timer) - continue; - if (ifp->if_watchdog) - (*ifp->if_watchdog)(ifp); - } - splx(s); - timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); -} - -/* - * Map interface name to - * interface structure pointer. - */ -struct ifnet * -ifunit(name) - register char *name; -{ - register char *cp; - register struct ifnet *ifp; - int unit; - unsigned len; - char *ep, c; - - for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) - if (*cp >= '0' && *cp <= '9') - break; - if (*cp == '\0' || cp == name + IFNAMSIZ) - return ((struct ifnet *)0); - /* - * Save first char of unit, and pointer to it, - * so we can put a null there to avoid matching - * initial substrings of interface names. - */ - len = cp - name + 1; - c = *cp; - ep = cp; - for (unit = 0; *cp >= '0' && *cp <= '9'; ) - unit = unit * 10 + *cp++ - '0'; - if (*cp != '\0') - return 0; /* no trailing garbage allowed */ - *ep = 0; - for (ifp = ifnet; ifp; ifp = ifp->if_next) { - if (bcmp(ifp->if_name, name, len)) - continue; - if (unit == ifp->if_unit) - break; - } - *ep = c; - return (ifp); -} - -/* - * Interface ioctls. - */ -int -ifioctl(so, cmd, data, p) - struct socket *so; - int cmd; - caddr_t data; - struct proc *p; -{ - register struct ifnet *ifp; - register struct ifreq *ifr; - int error; - - switch (cmd) { - - case SIOCGIFCONF: - case OSIOCGIFCONF: - return (ifconf(cmd, data)); - } - ifr = (struct ifreq *)data; - ifp = ifunit(ifr->ifr_name); - if (ifp == 0) - return (ENXIO); - switch (cmd) { - - case SIOCGIFFLAGS: - ifr->ifr_flags = ifp->if_flags; - break; - - case SIOCGIFMETRIC: - ifr->ifr_metric = ifp->if_metric; - break; - - case SIOCGIFMTU: - ifr->ifr_mtu = ifp->if_mtu; - break; - - case SIOCGIFPHYS: - ifr->ifr_phys = ifp->if_physical; - break; - - case SIOCSIFFLAGS: - error = suser(p->p_ucred, &p->p_acflag); - if (error) - return (error); - if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { - int s = splimp(); - if_down(ifp); - splx(s); - } - if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { - int s = splimp(); - if_up(ifp); - splx(s); - } - ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | - (ifr->ifr_flags &~ IFF_CANTCHANGE); - if (ifp->if_ioctl) - (void) (*ifp->if_ioctl)(ifp, cmd, data); - microtime(&ifp->if_lastchange); - break; - - case SIOCSIFMETRIC: - error = suser(p->p_ucred, &p->p_acflag); - if (error) - return (error); - ifp->if_metric = ifr->ifr_metric; - microtime(&ifp->if_lastchange); - break; - - case SIOCSIFPHYS: - error = suser(p->p_ucred, &p->p_acflag); - if (error) - return error; - if (!ifp->if_ioctl) - return EOPNOTSUPP; - error = (*ifp->if_ioctl)(ifp, cmd, data); - if (error == 0) - microtime(&ifp->if_lastchange); - return(error); - - case SIOCSIFMTU: - error = suser(p->p_ucred, &p->p_acflag); - if (error) - return (error); - if (ifp->if_ioctl == NULL) - return (EOPNOTSUPP); - /* - * 72 was chosen below because it is the size of a TCP/IP - * header (40) + the minimum mss (32). - */ - if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535) - return (EINVAL); - error = (*ifp->if_ioctl)(ifp, cmd, data); - if (error == 0) - microtime(&ifp->if_lastchange); - return(error); - - case SIOCADDMULTI: - case SIOCDELMULTI: - error = suser(p->p_ucred, &p->p_acflag); - if (error) - return (error); - if (ifp->if_ioctl == NULL) - return (EOPNOTSUPP); - error = (*ifp->if_ioctl)(ifp, cmd, data); - if (error == 0 ) - microtime(&ifp->if_lastchange); - return(error); - - case SIOCSIFMEDIA: - error = suser(p->p_ucred, &p->p_acflag); - if (error) - return (error); - if (ifp->if_ioctl == 0) - return (EOPNOTSUPP); - error = (*ifp->if_ioctl)(ifp, cmd, data); - if (error == 0) - microtime(&ifp->if_lastchange); - return error; - - case SIOCGIFMEDIA: - if (ifp->if_ioctl == 0) - return (EOPNOTSUPP); - return ((*ifp->if_ioctl)(ifp, cmd, data)); - - default: - if (so->so_proto == 0) - return (EOPNOTSUPP); -#ifndef COMPAT_43 - return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, - data, - ifp)); -#else - { - int ocmd = cmd; - - switch (cmd) { - - case SIOCSIFDSTADDR: - case SIOCSIFADDR: - case SIOCSIFBRDADDR: - case SIOCSIFNETMASK: -#if BYTE_ORDER != BIG_ENDIAN - if (ifr->ifr_addr.sa_family == 0 && - ifr->ifr_addr.sa_len < 16) { - ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; - ifr->ifr_addr.sa_len = 16; - } -#else - if (ifr->ifr_addr.sa_len == 0) - ifr->ifr_addr.sa_len = 16; -#endif - break; - - case OSIOCGIFADDR: - cmd = SIOCGIFADDR; - break; - - case OSIOCGIFDSTADDR: - cmd = SIOCGIFDSTADDR; - break; - - case OSIOCGIFBRDADDR: - cmd = SIOCGIFBRDADDR; - break; - - case OSIOCGIFNETMASK: - cmd = SIOCGIFNETMASK; - } - error = ((*so->so_proto->pr_usrreqs->pru_control)(so, - cmd, - data, - ifp)); - switch (ocmd) { - - case OSIOCGIFADDR: - case OSIOCGIFDSTADDR: - case OSIOCGIFBRDADDR: - case OSIOCGIFNETMASK: - *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; - } - return (error); - - } -#endif - - /* - * RTEMS additions for setting/getting `tap' function - */ - case SIOCSIFTAP: - ifp->if_tap = ifr->ifr_tap; - return 0; - - case SIOCGIFTAP: - ifr->ifr_tap = ifp->if_tap; - return 0; - } - return (0); -} - -/* - * Set/clear promiscuous mode on interface ifp based on the truth value - * of pswitch. The calls are reference counted so that only the first - * "on" request actually has an effect, as does the final "off" request. - * Results are undefined if the "off" and "on" requests are not matched. - */ -int -ifpromisc(ifp, pswitch) - struct ifnet *ifp; - int pswitch; -{ - struct ifreq ifr; - - if (pswitch) { - /* - * If the device is not configured up, we cannot put it in - * promiscuous mode. - */ - if ((ifp->if_flags & IFF_UP) == 0) - return (ENETDOWN); - if (ifp->if_pcount++ != 0) - return (0); - ifp->if_flags |= IFF_PROMISC; - log(LOG_INFO, "%s%d: promiscuous mode enabled\n", - ifp->if_name, ifp->if_unit); - } else { - if (--ifp->if_pcount > 0) - return (0); - ifp->if_flags &= ~IFF_PROMISC; - } - ifr.ifr_flags = ifp->if_flags; - return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); -} - -/* - * Return interface configuration - * of system. List may be used - * in later ioctl's (above) to get - * other information. - */ -/*ARGSUSED*/ -static int -ifconf(cmd, data) - int cmd; - caddr_t data; -{ - register struct ifconf *ifc = (struct ifconf *)data; - register struct ifnet *ifp = ifnet; - register struct ifaddr *ifa; - struct ifreq ifr, *ifrp; - int space = ifc->ifc_len, error = 0; - - ifrp = ifc->ifc_req; - for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { - char workbuf[64]; - int ifnlen; - - ifnlen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); - if(ifnlen + 1 > sizeof ifr.ifr_name) { - error = ENAMETOOLONG; - } else { - strcpy(ifr.ifr_name, workbuf); - } - - if ((ifa = ifp->if_addrlist) == 0) { - bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); - error = copyout((caddr_t)&ifr, (caddr_t)ifrp, - sizeof (ifr)); - if (error) - break; - space -= sizeof (ifr), ifrp++; - } else - for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { - register struct sockaddr *sa = ifa->ifa_addr; -#ifdef COMPAT_43 - if (cmd == OSIOCGIFCONF) { - struct osockaddr *osa = - (struct osockaddr *)&ifr.ifr_addr; - ifr.ifr_addr = *sa; - osa->sa_family = sa->sa_family; - error = copyout((caddr_t)&ifr, (caddr_t)ifrp, - sizeof (ifr)); - ifrp++; - } else -#endif - if (sa->sa_len <= sizeof(*sa)) { - ifr.ifr_addr = *sa; - error = copyout((caddr_t)&ifr, (caddr_t)ifrp, - sizeof (ifr)); - ifrp++; - } else { - space -= sa->sa_len - sizeof(*sa); - if (space < sizeof (ifr)) - break; - error = copyout((caddr_t)&ifr, (caddr_t)ifrp, - sizeof (ifr.ifr_name)); - if (error == 0) - error = copyout((caddr_t)sa, - (caddr_t)&ifrp->ifr_addr, sa->sa_len); - ifrp = (struct ifreq *) - (sa->sa_len + (caddr_t)&ifrp->ifr_addr); - } - if (error) - break; - space -= sizeof (ifr); - } - } - ifc->ifc_len -= space; - return (error); -} - -SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); -SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management"); diff --git a/c/src/exec/libnetworking/net/if.h b/c/src/exec/libnetworking/net/if.h deleted file mode 100644 index 39b6cc0d39..0000000000 --- a/c/src/exec/libnetworking/net/if.h +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1989, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)if.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NET_IF_H_ -#define _NET_IF_H_ - -/* - * Structures defining a network interface, providing a packet - * transport mechanism (ala level 0 of the PUP protocols). - * - * Each interface accepts output datagrams of a specified maximum - * length, and provides higher level routines with input datagrams - * received from its medium. - * - * Output occurs when the routine if_output is called, with three parameters: - * (*ifp->if_output)(ifp, m, dst, rt) - * Here m is the mbuf chain to be sent and dst is the destination address. - * The output routine encapsulates the supplied datagram if necessary, - * and then transmits it on its medium. - * - * On input, each interface unwraps the data received by it, and either - * places it on the input queue of a internetwork datagram routine - * and posts the associated software interrupt, or passes the datagram to a raw - * packet input routine. - * - * Routines exist for locating interfaces by their addresses - * or for locating a interface on a certain network, as well as more general - * routing and gateway routines maintaining information used to locate - * interfaces. These routines live in the files if.c and route.c - */ - -#ifndef _TIME_ /* XXX fast fix for SNMP, going away soon */ -#include <sys/time.h> -#endif - -#ifdef __STDC__ -/* - * Forward structure declarations for function prototypes [sic]. - */ -struct mbuf; -struct proc; -struct rtentry; -struct socket; -struct ether_header; -#endif - -/* - * Structure describing information about an interface - * which may be of interest to management entities. - */ -struct if_data { - /* generic interface information */ - u_char ifi_type; /* ethernet, tokenring, etc */ - u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */ - u_char ifi_addrlen; /* media address length */ - u_char ifi_hdrlen; /* media header length */ - u_char ifi_recvquota; /* polling quota for receive intrs */ - u_char ifi_xmitquota; /* polling quota for xmit intrs */ - u_long ifi_mtu; /* maximum transmission unit */ - u_long ifi_metric; /* routing metric (external only) */ - u_long ifi_baudrate; /* linespeed */ - /* volatile statistics */ - u_long ifi_ipackets; /* packets received on interface */ - u_long ifi_ierrors; /* input errors on interface */ - u_long ifi_opackets; /* packets sent on interface */ - u_long ifi_oerrors; /* output errors on interface */ - u_long ifi_collisions; /* collisions on csma interfaces */ - u_long ifi_ibytes; /* total number of octets received */ - u_long ifi_obytes; /* total number of octets sent */ - u_long ifi_imcasts; /* packets received via multicast */ - u_long ifi_omcasts; /* packets sent via multicast */ - u_long ifi_iqdrops; /* dropped on input, this interface */ - u_long ifi_noproto; /* destined for unsupported protocol */ - u_long ifi_recvtiming; /* usec spent receiving when timing */ - u_long ifi_xmittiming; /* usec spent xmitting when timing */ - struct timeval ifi_lastchange; /* time of last administrative change */ -}; - -/* - * Structure defining a queue for a network interface. - */ -struct ifqueue { - struct mbuf *ifq_head; - struct mbuf *ifq_tail; - int ifq_len; - int ifq_maxlen; - int ifq_drops; -}; - -/* - * Structure defining a network interface. - * - * (Would like to call this struct ``if'', but C isn't PL/1.) - */ -struct ifnet { - void *if_softc; /* pointer to driver state */ - char *if_name; /* name, e.g. ``en'' or ``lo'' */ - struct ifnet *if_next; /* all struct ifnets are chained */ - struct ifaddr *if_addrlist; /* linked list of addresses per if */ - int if_pcount; /* number of promiscuous listeners */ - struct bpf_if *if_bpf; /* packet filter structure */ - u_short if_index; /* numeric abbreviation for this if */ - short if_unit; /* sub-unit for lower level driver */ - short if_timer; /* time 'til if_watchdog called */ - short if_flags; /* up/down, broadcast, etc. */ - int if_ipending; /* interrupts pending */ - void *if_linkmib; /* link-type-specific MIB data */ - size_t if_linkmiblen; /* length of above data */ - struct if_data if_data; -/* procedure handles */ - int (*if_output) /* output routine (enqueue) */ - __P((struct ifnet *, struct mbuf *, struct sockaddr *, - struct rtentry *)); - void (*if_start) /* initiate output routine */ - __P((struct ifnet *)); - int (*if_done) /* output complete routine */ - __P((struct ifnet *)); /* (XXX not used; fake prototype) */ - int (*if_ioctl) /* ioctl routine */ - __P((struct ifnet *, int, caddr_t)); - void (*if_watchdog) /* timer routine */ - __P((struct ifnet *)); - int (*if_poll_recv) /* polled receive routine */ - __P((struct ifnet *, int *)); - int (*if_poll_xmit) /* polled transmit routine */ - __P((struct ifnet *, int *)); - void (*if_poll_intren) /* polled interrupt reenable routine */ - __P((struct ifnet *)); - void (*if_poll_slowinput) /* input routine for slow devices */ - __P((struct ifnet *, struct mbuf *)); - void (*if_init) /* Init routine */ - __P((void *)); - int (*if_tap) /* Packet filter routine */ - (struct ifnet *, struct ether_header *, struct mbuf *); - struct ifqueue if_snd; /* output queue */ - struct ifqueue *if_poll_slowq; /* input queue for slow devices */ -}; -typedef void if_init_f_t __P((void *)); - -#define if_mtu if_data.ifi_mtu -#define if_type if_data.ifi_type -#define if_physical if_data.ifi_physical -#define if_addrlen if_data.ifi_addrlen -#define if_hdrlen if_data.ifi_hdrlen -#define if_metric if_data.ifi_metric -#define if_baudrate if_data.ifi_baudrate -#define if_ipackets if_data.ifi_ipackets -#define if_ierrors if_data.ifi_ierrors -#define if_opackets if_data.ifi_opackets -#define if_oerrors if_data.ifi_oerrors -#define if_collisions if_data.ifi_collisions -#define if_ibytes if_data.ifi_ibytes -#define if_obytes if_data.ifi_obytes -#define if_imcasts if_data.ifi_imcasts -#define if_omcasts if_data.ifi_omcasts -#define if_iqdrops if_data.ifi_iqdrops -#define if_noproto if_data.ifi_noproto -#define if_lastchange if_data.ifi_lastchange -#define if_recvquota if_data.ifi_recvquota -#define if_xmitquota if_data.ifi_xmitquota -#define if_rawoutput(if, m, sa) if_output(if, m, sa, (struct rtentry *)0) - -#define IFF_UP 0x1 /* interface is up */ -#define IFF_BROADCAST 0x2 /* broadcast address valid */ -#define IFF_DEBUG 0x4 /* turn on debugging */ -#define IFF_LOOPBACK 0x8 /* is a loopback net */ -#define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */ -/*#define IFF_NOTRAILERS 0x20 * obsolete: avoid use of trailers */ -#define IFF_RUNNING 0x40 /* resources allocated */ -#define IFF_NOARP 0x80 /* no address resolution protocol */ -#define IFF_PROMISC 0x100 /* receive all packets */ -#define IFF_ALLMULTI 0x200 /* receive all multicast packets */ -#define IFF_OACTIVE 0x400 /* transmission in progress */ -#define IFF_SIMPLEX 0x800 /* can't hear own transmissions */ -#define IFF_LINK0 0x1000 /* per link layer defined bit */ -#define IFF_LINK1 0x2000 /* per link layer defined bit */ -#define IFF_LINK2 0x4000 /* per link layer defined bit */ -#define IFF_ALTPHYS IFF_LINK2 /* use alternate physical connection */ -#define IFF_MULTICAST 0x8000 /* supports multicast */ - -/* flags set internally only: */ -#define IFF_CANTCHANGE \ - (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\ - IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI) - - -/* - * These really don't belong here, but there's no other obviously appropriate - * location. - */ -#define IFP_AUI 0 -#define IFP_10BASE2 1 -#define IFP_10BASET 2 -/* etc. */ - -/* - * Bit values in if_ipending - */ -#define IFI_RECV 1 /* I want to receive */ -#define IFI_XMIT 2 /* I want to transmit */ - -/* - * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq) - * are queues of messages stored on ifqueue structures - * (defined above). Entries are added to and deleted from these structures - * by these macros, which should be called with ipl raised to splimp(). - */ -#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) -#define IF_DROP(ifq) ((ifq)->ifq_drops++) -#define IF_ENQUEUE(ifq, m) { \ -/* printf(" IF_ENQUEUE: %p %p\n", ifq, m ); */ \ - (m)->m_nextpkt = 0; \ - if ((ifq)->ifq_tail == 0) \ - (ifq)->ifq_head = m; \ - else \ - (ifq)->ifq_tail->m_nextpkt = m; \ - (ifq)->ifq_tail = m; \ - (ifq)->ifq_len++; \ -} -#define IF_PREPEND(ifq, m) { \ -/* printf(" IF_PREPEND: %p %p\n", ifq, m ); */ \ - (m)->m_nextpkt = (ifq)->ifq_head; \ - if ((ifq)->ifq_tail == 0) \ - (ifq)->ifq_tail = (m); \ - (ifq)->ifq_head = (m); \ - (ifq)->ifq_len++; \ -} -#define IF_DEQUEUE(ifq, m) { \ - (m) = (ifq)->ifq_head; \ - if (m) { \ -/* printf(" IF_DEQUEUE: %p %p\n", ifq, m ); */ \ - if (((ifq)->ifq_head = (m)->m_nextpkt) == 0) \ - (ifq)->ifq_tail = 0; \ - (m)->m_nextpkt = 0; \ - (ifq)->ifq_len--; \ - } \ -} - -#ifdef KERNEL -#define IF_ENQ_DROP(ifq, m) if_enq_drop(ifq, m) - -#if defined(__GNUC__) && defined(MT_HEADER) -static inline int -if_queue_drop(struct ifqueue *ifq, struct mbuf *m) -{ - IF_DROP(ifq); - return 0; -} - -static inline int -if_enq_drop(struct ifqueue *ifq, struct mbuf *m) -{ - if (IF_QFULL(ifq) && - !if_queue_drop(ifq, m)) - return 0; - IF_ENQUEUE(ifq, m); - return 1; -} -#else - -#ifdef MT_HEADER -int if_enq_drop __P((struct ifqueue *, struct mbuf *)); -#endif - -#endif -#endif /* KERNEL */ - -#define IFQ_MAXLEN 50 -#define IFNET_SLOWHZ 1 /* granularity is 1 second */ - -/* - * The ifaddr structure contains information about one address - * of an interface. They are maintained by the different address families, - * are allocated and attached when an address is set, and are linked - * together so all addresses for an interface can be located. - */ -struct ifaddr { - struct sockaddr *ifa_addr; /* address of interface */ - struct sockaddr *ifa_dstaddr; /* other end of p-to-p link */ -#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ - struct sockaddr *ifa_netmask; /* used to determine subnet */ - struct ifnet *ifa_ifp; /* back-pointer to interface */ - struct ifaddr *ifa_next; /* next address for interface */ - void (*ifa_rtrequest) /* check or clean routes (+ or -)'d */ - __P((int, struct rtentry *, struct sockaddr *)); - u_short ifa_flags; /* mostly rt_flags for cloning */ - short ifa_refcnt; /* references to this structure */ - int ifa_metric; /* cost of going out this interface */ -#ifdef notdef - struct rtentry *ifa_rt; /* XXXX for ROUTETOIF ????? */ -#endif - int (*ifa_claim_addr) /* check if an addr goes to this if */ - __P((struct ifaddr *, struct sockaddr *)); - -}; -#define IFA_ROUTE RTF_UP /* route installed */ - -/* - * Message format for use in obtaining information about interfaces - * from getkerninfo and the routing socket - */ -struct if_msghdr { - u_short ifm_msglen; /* to skip over non-understood messages */ - u_char ifm_version; /* future binary compatability */ - u_char ifm_type; /* message type */ - int ifm_addrs; /* like rtm_addrs */ - int ifm_flags; /* value of if_flags */ - u_short ifm_index; /* index for associated ifp */ - struct if_data ifm_data;/* statistics and other data about if */ -}; - -/* - * Message format for use in obtaining information about interface addresses - * from getkerninfo and the routing socket - */ -struct ifa_msghdr { - u_short ifam_msglen; /* to skip over non-understood messages */ - u_char ifam_version; /* future binary compatability */ - u_char ifam_type; /* message type */ - int ifam_addrs; /* like rtm_addrs */ - int ifam_flags; /* value of ifa_flags */ - u_short ifam_index; /* index for associated ifp */ - int ifam_metric; /* value of ifa_metric */ -}; - -/* - * Interface request structure used for socket - * ioctl's. All interface ioctl's must have parameter - * definitions which begin with ifr_name. The - * remainder may be interface specific. - */ -struct ifreq { -#define IFNAMSIZ 16 - char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_dstaddr; - struct sockaddr ifru_broadaddr; - short ifru_flags; - int ifru_metric; - int ifru_mtu; - int ifru_phys; - int ifru_media; - caddr_t ifru_data; - int (*ifru_tap)(struct ifnet *, struct ether_header *, struct mbuf *); - } ifr_ifru; -#define ifr_addr ifr_ifru.ifru_addr /* address */ -#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ -#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ -#define ifr_flags ifr_ifru.ifru_flags /* flags */ -#define ifr_metric ifr_ifru.ifru_metric /* metric */ -#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ -#define ifr_phys ifr_ifru.ifru_phys /* physical wire */ -#define ifr_media ifr_ifru.ifru_media /* physical media */ -#define ifr_data ifr_ifru.ifru_data /* for use by interface */ -#define ifr_tap ifr_ifru.ifru_tap /* tap function */ -}; - -struct ifaliasreq { - char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - struct sockaddr ifra_addr; - struct sockaddr ifra_broadaddr; - struct sockaddr ifra_mask; -}; - -struct ifmediareq { - char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - int ifm_current; /* current media options */ - int ifm_mask; /* don't care mask */ - int ifm_status; /* media status */ - int ifm_active; /* active options */ - int ifm_count; /* # entries in ifm_ulist array */ - int *ifm_ulist; /* media words */ -}; -/* - * Structure used in SIOCGIFCONF request. - * Used to retrieve interface configuration - * for machine (useful for programs which - * must know all networks accessible). - */ -struct ifconf { - int ifc_len; /* size of associated buffer */ - union { - caddr_t ifcu_buf; - struct ifreq *ifcu_req; - } ifc_ifcu; -#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ -#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */ -}; - -#include <net/if_arp.h> - -#ifdef KERNEL -#define IFAFREE(ifa) \ - if ((ifa)->ifa_refcnt <= 0) \ - ifafree(ifa); \ - else \ - (ifa)->ifa_refcnt--; - -extern struct ifnet *ifnet; -extern int ifqmaxlen; -extern struct ifnet loif[]; -extern int if_index; -extern struct ifaddr **ifnet_addrs; - -void ether_ifattach __P((struct ifnet *)); -void ether_input __P((struct ifnet *, struct ether_header *, struct mbuf *)); -int ether_output __P((struct ifnet *, - struct mbuf *, struct sockaddr *, struct rtentry *)); -int ether_ioctl __P((struct ifnet *, int , caddr_t )); - -void if_attach __P((struct ifnet *)); -void if_down __P((struct ifnet *)); -void if_up __P((struct ifnet *)); -#ifdef vax -void ifubareset __P((int)); -#endif -/*void ifinit __P((void));*/ /* declared in systm.h for main() */ -int ifioctl __P((struct socket *, int, caddr_t, struct proc *)); -int ifpromisc __P((struct ifnet *, int)); -struct ifnet *ifunit __P((char *)); - -int if_poll_recv_slow __P((struct ifnet *ifp, int *quotap)); -void if_poll_xmit_slow __P((struct ifnet *ifp, int *quotap)); -void if_poll_throttle __P((void)); -void if_poll_unthrottle __P((void *)); -void if_poll_init __P((void)); -void if_poll __P((void)); - -struct ifaddr *ifa_ifwithaddr __P((struct sockaddr *)); -struct ifaddr *ifa_ifwithdstaddr __P((struct sockaddr *)); -struct ifaddr *ifa_ifwithnet __P((struct sockaddr *)); -struct ifaddr *ifa_ifwithroute __P((int, struct sockaddr *, - struct sockaddr *)); -struct ifaddr *ifaof_ifpforaddr __P((struct sockaddr *, struct ifnet *)); -void ifafree __P((struct ifaddr *)); - -int looutput __P((struct ifnet *, - struct mbuf *, struct sockaddr *, struct rtentry *)); -#endif /* KERNEL */ - -#endif /* !_NET_IF_H_ */ diff --git a/c/src/exec/libnetworking/net/if_arp.h b/c/src/exec/libnetworking/net/if_arp.h deleted file mode 100644 index dd726bf856..0000000000 --- a/c/src/exec/libnetworking/net/if_arp.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)if_arp.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NET_IF_ARP_H_ -#define _NET_IF_ARP_H_ - -/* - * Address Resolution Protocol. - * - * See RFC 826 for protocol description. ARP packets are variable - * in size; the arphdr structure defines the fixed-length portion. - * Protocol type values are the same as those for 10 Mb/s Ethernet. - * It is followed by the variable-sized fields ar_sha, arp_spa, - * arp_tha and arp_tpa in that order, according to the lengths - * specified. Field names used correspond to RFC 826. - */ -struct arphdr { - u_short ar_hrd; /* format of hardware address */ -#define ARPHRD_ETHER 1 /* ethernet hardware format */ -#define ARPHRD_FRELAY 15 /* frame relay hardware format */ - u_short ar_pro; /* format of protocol address */ - u_char ar_hln; /* length of hardware address */ - u_char ar_pln; /* length of protocol address */ - u_short ar_op; /* one of: */ -#define ARPOP_REQUEST 1 /* request to resolve address */ -#define ARPOP_REPLY 2 /* response to previous request */ -#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */ -#define ARPOP_REVREPLY 4 /* response giving protocol address */ -#define ARPOP_INVREQUEST 8 /* request to identify peer */ -#define ARPOP_INVREPLY 9 /* response identifying peer */ -/* - * The remaining fields are variable in size, - * according to the sizes above. - */ -#ifdef COMMENT_ONLY - u_char ar_sha[]; /* sender hardware address */ - u_char ar_spa[]; /* sender protocol address */ - u_char ar_tha[]; /* target hardware address */ - u_char ar_tpa[]; /* target protocol address */ -#endif -}; - -/* - * ARP ioctl request - */ -struct arpreq { - struct sockaddr arp_pa; /* protocol address */ - struct sockaddr arp_ha; /* hardware address */ - int arp_flags; /* flags */ -}; -/* arp_flags and at_flags field values */ -#define ATF_INUSE 0x01 /* entry in use */ -#define ATF_COM 0x02 /* completed entry (enaddr valid) */ -#define ATF_PERM 0x04 /* permanent entry */ -#define ATF_PUBL 0x08 /* publish entry (respond for other host) */ -#define ATF_USETRAILERS 0x10 /* has requested trailers */ - -#endif /* !_NET_IF_ARP_H_ */ diff --git a/c/src/exec/libnetworking/net/if_dl.h b/c/src/exec/libnetworking/net/if_dl.h deleted file mode 100644 index 053ae3e92f..0000000000 --- a/c/src/exec/libnetworking/net/if_dl.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)if_dl.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NET_IF_DL_H_ -#define _NET_IF_DL_H_ - -/* - * A Link-Level Sockaddr may specify the interface in one of two - * ways: either by means of a system-provided index number (computed - * anew and possibly differently on every reboot), or by a human-readable - * string such as "il0" (for managerial convenience). - * - * Census taking actions, such as something akin to SIOCGCONF would return - * both the index and the human name. - * - * High volume transactions (such as giving a link-level ``from'' address - * in a recvfrom or recvmsg call) may be likely only to provide the indexed - * form, (which requires fewer copy operations and less space). - * - * The form and interpretation of the link-level address is purely a matter - * of convention between the device driver and its consumers; however, it is - * expected that all drivers for an interface of a given if_type will agree. - */ - -/* - * Structure of a Link-Level sockaddr: - */ -struct sockaddr_dl { - u_char sdl_len; /* Total length of sockaddr */ - u_char sdl_family; /* AF_DLI */ - u_short sdl_index; /* if != 0, system given index for interface */ - u_char sdl_type; /* interface type */ - u_char sdl_nlen; /* interface name length, no trailing 0 reqd. */ - u_char sdl_alen; /* link level address length */ - u_char sdl_slen; /* link layer selector length */ - char sdl_data[12]; /* minimum work area, can be larger; - contains both if name and ll address */ -}; - -#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen)) - -#ifndef KERNEL - -#include <sys/cdefs.h> - -__BEGIN_DECLS -void link_addr __P((const char *, struct sockaddr_dl *)); -char *link_ntoa __P((const struct sockaddr_dl *)); -__END_DECLS - -#endif /* !KERNEL */ - -#endif diff --git a/c/src/exec/libnetworking/net/if_ethersubr.c b/c/src/exec/libnetworking/net/if_ethersubr.c deleted file mode 100644 index 2a6446ebb6..0000000000 --- a/c/src/exec/libnetworking/net/if_ethersubr.c +++ /dev/null @@ -1,997 +0,0 @@ -/* - * Copyright (c) 1982, 1989, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/syslog.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/netisr.h> -#include <net/route.h> -#include <net/if_llc.h> -#include <net/if_dl.h> -#include <net/if_types.h> -#include <net/ethernet.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_var.h> -#endif -#include <netinet/if_ether.h> - -#ifdef IPX -#include <netipx/ipx.h> -#include <netipx/ipx_if.h> -#endif - -#ifdef NS -#include <netns/ns.h> -#include <netns/ns_if.h> -ushort ns_nettype; -int ether_outputdebug = 0; -int ether_inputdebug = 0; -#endif - -#ifdef ISO -#include <netiso/argo_debug.h> -#include <netiso/iso.h> -#include <netiso/iso_var.h> -#include <netiso/iso_snpac.h> -#endif - -/*#ifdef LLC -#include <netccitt/dll.h> -#include <netccitt/llc_var.h> -#endif*/ - -#if defined(LLC) && defined(CCITT) -extern struct ifqueue pkintrq; -#endif - -#ifdef NETATALK -#include <netatalk/at.h> -#include <netatalk/at_var.h> -#include <netatalk/at_extern.h> - -#define llc_snap_org_code llc_un.type_snap.org_code -#define llc_snap_ether_type llc_un.type_snap.ether_type - -extern u_char at_org_code[ 3 ]; -extern u_char aarp_org_code[ 3 ]; -#endif NETATALK - -u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -#define senderr(e) { error = (e); goto bad;} - -/* - * Ethernet output routine. - * Encapsulate a packet of type family for the local net. - * Use trailer local net encapsulation if enough data in first - * packet leaves a multiple of 512 bytes of data in remainder. - * Assumes that ifp is actually pointer to arpcom structure. - */ -int -ether_output(ifp, m0, dst, rt0) - register struct ifnet *ifp; - struct mbuf *m0; - struct sockaddr *dst; - struct rtentry *rt0; -{ - short type; - int s, error = 0; -#ifdef NS - u_char *cp - register struct ifqueue *inq; - register struct mbuf *m2; -#endif - u_char edst[6]; - register struct mbuf *m = m0; - register struct rtentry *rt; - struct mbuf *mcopy = (struct mbuf *)0; - register struct ether_header *eh; - int off, len = m->m_pkthdr.len; - struct arpcom *ac = (struct arpcom *)ifp; -#ifdef NETATALK - struct at_ifaddr *aa; -#endif NETATALK - - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) - senderr(ENETDOWN); - rt = rt0; - if (rt) { - if ((rt->rt_flags & RTF_UP) == 0) { - rt0 = rt = rtalloc1(dst, 1, 0UL); - if (rt0) - rt->rt_refcnt--; - else - senderr(EHOSTUNREACH); - } - if (rt->rt_flags & RTF_GATEWAY) { - if (rt->rt_gwroute == 0) - goto lookup; - if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { - rtfree(rt); rt = rt0; - lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, - 0UL); - if ((rt = rt->rt_gwroute) == 0) - senderr(EHOSTUNREACH); - } - } - if (rt->rt_flags & RTF_REJECT) - if (rt->rt_rmx.rmx_expire == 0 || - rtems_bsdnet_seconds_since_boot() < rt->rt_rmx.rmx_expire) - senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); - } - switch (dst->sa_family) { - -#ifdef INET - case AF_INET: - if (!arpresolve(ac, rt, m, dst, edst, rt0)) - return (0); /* if not yet resolved */ - /* If broadcasting on a simplex interface, loopback a copy */ - if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) - mcopy = m_copy(m, 0, (int)M_COPYALL); - off = m->m_pkthdr.len - m->m_len; - type = htons(ETHERTYPE_IP); - break; -#endif -#ifdef IPX - case AF_IPX: - { - struct ifaddr *ia; - - type = htons(ETHERTYPE_IPX); - bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), - (caddr_t)edst, sizeof (edst)); - for (ia = ifp->if_addrlist; ia != NULL; ia = ia->ifa_next) - if(ia->ifa_addr->sa_family == AF_IPX && - !bcmp((caddr_t)edst, - (caddr_t)&((struct ipx_ifaddr *)ia)->ia_addr.sipx_addr.x_host, - sizeof(edst))) - return (looutput(ifp, m, dst, rt)); - /* If broadcasting on a simplex interface, loopback a copy */ - if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) - mcopy = m_copy(m, 0, (int)M_COPYALL); - break; - } -#endif -#ifdef NETATALK - case AF_APPLETALK: - { - struct sockaddr_at *sat = (struct sockaddr_at *)dst; - - /* - * super hack.. - * Most of this loopback code should move into the appletalk - * code, but it's here for now.. remember to move it! [JRE] - * This may not get the same interface we started with - * fix asap. XXX - */ - aa = at_ifawithnet( sat ); - if (aa == NULL) { - goto bad; - } - if( aa->aa_ifa.ifa_ifp != ifp ) { - (*aa->aa_ifa.ifa_ifp->if_output)(aa->aa_ifa.ifa_ifp, - m,dst,rt); - } - if (((sat->sat_addr.s_net == ATADDR_ANYNET) - && (sat->sat_addr.s_node == ATADDR_ANYNODE)) - || ((sat->sat_addr.s_net == aa->aa_addr.sat_addr.s_net ) - && (sat->sat_addr.s_node == aa->aa_addr.sat_addr.s_node))) { - (void) looutput(ifp, m, dst, rt); - return(0); - } - - if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) { -#ifdef NETATALKDEBUG - extern char *prsockaddr(struct sockaddr *); - printf("aarpresolv: failed for %s\n", prsockaddr(dst)); -#endif NETATALKDEBUG - return (0); - } - - /* - * If broadcasting on a simplex interface, loopback a copy - */ - if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) - mcopy = m_copy(m, 0, (int)M_COPYALL); - } - /* - * In the phase 2 case, we need to prepend an mbuf for the llc header. - * Since we must preserve the value of m, which is passed to us by - * value, we m_copy() the first mbuf, and use it for our llc header. - */ - if ( aa->aa_flags & AFA_PHASE2 ) { - struct llc llc; - - M_PREPEND(m, sizeof(struct llc), M_WAIT); - len += sizeof(struct llc); - llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; - llc.llc_control = LLC_UI; - bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code)); - llc.llc_snap_ether_type = htons( ETHERTYPE_AT ); - bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc)); - type = htons(m->m_pkthdr.len); - } else { - type = htons(ETHERTYPE_AT); - } - break; -#endif NETATALK -#ifdef NS - case AF_NS: - switch(ns_nettype){ - default: - case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ - type = 0x8137; - break; - case 0x0: /* Novell 802.3 */ - type = htons( m->m_pkthdr.len); - break; - case 0xe0e0: /* Novell 802.2 and Token-Ring */ - M_PREPEND(m, 3, M_WAIT); - type = htons( m->m_pkthdr.len); - cp = mtod(m, u_char *); - *cp++ = 0xE0; - *cp++ = 0xE0; - *cp++ = 0x03; - break; - } - bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), - (caddr_t)edst, sizeof (edst)); - if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){ - m->m_pkthdr.rcvif = ifp; - schednetisr(NETISR_NS); - inq = &nsintrq; - s = splimp(); - if (IF_QFULL(inq)) { - IF_DROP(inq); - m_freem(m); - } else - IF_ENQUEUE(inq, m); - splx(s); - return (error); - } - if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){ - m2 = m_copy(m, 0, (int)M_COPYALL); - m2->m_pkthdr.rcvif = ifp; - schednetisr(NETISR_NS); - inq = &nsintrq; - s = splimp(); - if (IF_QFULL(inq)) { - IF_DROP(inq); - m_freem(m2); - } else - IF_ENQUEUE(inq, m2); - splx(s); - } - /* If broadcasting on a simplex interface, loopback a copy */ - if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)){ - mcopy = m_copy(m, 0, (int)M_COPYALL); - } - break; -#endif /* NS */ -#ifdef ISO - case AF_ISO: { - int snpalen; - struct llc *l; - register struct sockaddr_dl *sdl; - - if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && - sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { - bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); - } else if (error = - iso_snparesolve(ifp, (struct sockaddr_iso *)dst, - (char *)edst, &snpalen)) - goto bad; /* Not Resolved */ - /* If broadcasting on a simplex interface, loopback a copy */ - if (*edst & 1) - m->m_flags |= (M_BCAST|M_MCAST); - if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && - (mcopy = m_copy(m, 0, (int)M_COPYALL))) { - M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); - if (mcopy) { - eh = mtod(mcopy, struct ether_header *); - bcopy((caddr_t)edst, - (caddr_t)eh->ether_dhost, sizeof (edst)); - bcopy((caddr_t)ac->ac_enaddr, - (caddr_t)eh->ether_shost, sizeof (edst)); - } - } - M_PREPEND(m, 3, M_DONTWAIT); - if (m == NULL) - return (0); - type = htons(m->m_pkthdr.len); - l = mtod(m, struct llc *); - l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; - l->llc_control = LLC_UI; - len += 3; - IFDEBUG(D_ETHER) - int i; - printf("unoutput: sending pkt to: "); - for (i=0; i<6; i++) - printf("%x ", edst[i] & 0xff); - printf("\n"); - ENDDEBUG - } break; -#endif /* ISO */ -#ifdef LLC -/* case AF_NSAP: */ - case AF_CCITT: { - register struct sockaddr_dl *sdl = - (struct sockaddr_dl *) rt -> rt_gateway; - - if (sdl && sdl->sdl_family == AF_LINK - && sdl->sdl_alen > 0) { - bcopy(LLADDR(sdl), (char *)edst, - sizeof(edst)); - } else goto bad; /* Not a link interface ? Funny ... */ - if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && - (mcopy = m_copy(m, 0, (int)M_COPYALL))) { - M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); - if (mcopy) { - eh = mtod(mcopy, struct ether_header *); - bcopy((caddr_t)edst, - (caddr_t)eh->ether_dhost, sizeof (edst)); - bcopy((caddr_t)ac->ac_enaddr, - (caddr_t)eh->ether_shost, sizeof (edst)); - } - } - type = htons(m->m_pkthdr.len); -#ifdef LLC_DEBUG - { - int i; - register struct llc *l = mtod(m, struct llc *); - - printf("ether_output: sending LLC2 pkt to: "); - for (i=0; i<6; i++) - printf("%x ", edst[i] & 0xff); - printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", - type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, - l->llc_control & 0xff); - - } -#endif /* LLC_DEBUG */ - } break; -#endif /* LLC */ - - case AF_UNSPEC: - eh = (struct ether_header *)dst->sa_data; - (void)memcpy(edst, eh->ether_dhost, sizeof (edst)); - type = eh->ether_type; - break; - - default: - printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, - dst->sa_family); - senderr(EAFNOSUPPORT); - } - - - if (mcopy) - (void) looutput(ifp, mcopy, dst, rt); - /* - * Add local net header. If no space in first mbuf, - * allocate another. - */ - M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); - if (m == 0) - senderr(ENOBUFS); - eh = mtod(m, struct ether_header *); - (void)memcpy(&eh->ether_type, &type, - sizeof(eh->ether_type)); - (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); - (void)memcpy(eh->ether_shost, ac->ac_enaddr, - sizeof(eh->ether_shost)); - s = splimp(); - /* - * Queue message on interface, and start output if interface - * not yet active. - */ - if (IF_QFULL(&ifp->if_snd)) { - IF_DROP(&ifp->if_snd); - splx(s); - senderr(ENOBUFS); - } - IF_ENQUEUE(&ifp->if_snd, m); - if ((ifp->if_flags & IFF_OACTIVE) == 0) - (*ifp->if_start)(ifp); - splx(s); - ifp->if_obytes += len + sizeof (struct ether_header); - if (m->m_flags & M_MCAST) - ifp->if_omcasts++; - return (error); - -bad: - if (m) - m_freem(m); - return (error); -} - -/* - * Process a received Ethernet packet; - * the packet is in the mbuf chain m without - * the ether header, which is provided separately. - */ -void -ether_input(ifp, eh, m) - struct ifnet *ifp; - register struct ether_header *eh; - struct mbuf *m; -{ - register struct ifqueue *inq; - u_short ether_type; -#ifdef NS - u_short *checksum; -#endif - int s; -#if defined (ISO) || defined (LLC) || defined(NETATALK) - register struct llc *l; -#endif - - if ((ifp->if_flags & IFF_UP) == 0) { - m_freem(m); - return; - } - ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); - if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, - sizeof(etherbroadcastaddr)) == 0) - m->m_flags |= M_BCAST; - else if (eh->ether_dhost[0] & 1) - m->m_flags |= M_MCAST; - if (m->m_flags & (M_BCAST|M_MCAST)) - ifp->if_imcasts++; - - /* - * RTEMS addition -- allow application to `tap into' - * the incoming packet stream. - */ - if (ifp->if_tap && (*ifp->if_tap)(ifp, eh, m)) { - m_freem(m); - return; - } - - ether_type = ntohs(eh->ether_type); - - switch (ether_type) { -#ifdef INET - case ETHERTYPE_IP: - schednetisr(NETISR_IP); - inq = &ipintrq; - break; - - case ETHERTYPE_ARP: - schednetisr(NETISR_ARP); - inq = &arpintrq; - break; -#endif -#ifdef IPX - case ETHERTYPE_IPX: - schednetisr(NETISR_IPX); - inq = &ipxintrq; - break; -#endif -#ifdef NS - case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ - schednetisr(NETISR_NS); - inq = &nsintrq; - break; - -#endif /* NS */ -#ifdef NETATALK - case ETHERTYPE_AT: - schednetisr(NETISR_ATALK); - inq = &atintrq1; - break; - case ETHERTYPE_AARP: - /* probably this should be done with a NETISR as well */ - aarpinput((struct arpcom *)ifp, m); /* XXX */ - return; -#endif NETATALK - default: -#ifdef NS - checksum = mtod(m, ushort *); - /* Novell 802.3 */ - if ((ether_type <= ETHERMTU) && - ((*checksum == 0xffff) || (*checksum == 0xE0E0))){ - if(*checksum == 0xE0E0) { - m->m_pkthdr.len -= 3; - m->m_len -= 3; - m->m_data += 3; - } - schednetisr(NETISR_NS); - inq = &nsintrq; - break; - } -#endif /* NS */ -#if defined (ISO) || defined (LLC) || defined(NETATALK) - if (ether_type > ETHERMTU) - goto dropanyway; - l = mtod(m, struct llc *); - switch (l->llc_dsap) { -#ifdef NETATALK - case LLC_SNAP_LSAP: - switch (l->llc_control) { - case LLC_UI: - if (l->llc_ssap != LLC_SNAP_LSAP) - goto dropanyway; - - if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, - sizeof(at_org_code)) == 0 && - ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { - inq = &atintrq2; - m_adj( m, sizeof( struct llc )); - schednetisr(NETISR_ATALK); - break; - } - - if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, - sizeof(aarp_org_code)) == 0 && - ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { - m_adj( m, sizeof( struct llc )); - aarpinput((struct arpcom *)ifp, m); /* XXX */ - return; - } - - default: - goto dropanyway; - } - break; -#endif NETATALK -#ifdef ISO - case LLC_ISO_LSAP: - switch (l->llc_control) { - case LLC_UI: - /* LLC_UI_P forbidden in class 1 service */ - if ((l->llc_dsap == LLC_ISO_LSAP) && - (l->llc_ssap == LLC_ISO_LSAP)) { - /* LSAP for ISO */ - if (m->m_pkthdr.len > ether_type) - m_adj(m, ether_type - m->m_pkthdr.len); - m->m_data += 3; /* XXX */ - m->m_len -= 3; /* XXX */ - m->m_pkthdr.len -= 3; /* XXX */ - M_PREPEND(m, sizeof *eh, M_DONTWAIT); - if (m == 0) - return; - *mtod(m, struct ether_header *) = *eh; - IFDEBUG(D_ETHER) - printf("clnp packet"); - ENDDEBUG - schednetisr(NETISR_ISO); - inq = &clnlintrq; - break; - } - goto dropanyway; - - case LLC_XID: - case LLC_XID_P: - if(m->m_len < 6) - goto dropanyway; - l->llc_window = 0; - l->llc_fid = 9; - l->llc_class = 1; - l->llc_dsap = l->llc_ssap = 0; - /* Fall through to */ - case LLC_TEST: - case LLC_TEST_P: - { - struct sockaddr sa; - register struct ether_header *eh2; - int i; - u_char c = l->llc_dsap; - - l->llc_dsap = l->llc_ssap; - l->llc_ssap = c; - if (m->m_flags & (M_BCAST | M_MCAST)) - bcopy((caddr_t)ac->ac_enaddr, - (caddr_t)eh->ether_dhost, 6); - sa.sa_family = AF_UNSPEC; - sa.sa_len = sizeof(sa); - eh2 = (struct ether_header *)sa.sa_data; - for (i = 0; i < 6; i++) { - eh2->ether_shost[i] = c = eh->ether_dhost[i]; - eh2->ether_dhost[i] = - eh->ether_dhost[i] = eh->ether_shost[i]; - eh->ether_shost[i] = c; - } - ifp->if_output(ifp, m, &sa, NULL); - return; - } - default: - m_freem(m); - return; - } - break; -#endif /* ISO */ -#ifdef LLC - case LLC_X25_LSAP: - { - if (m->m_pkthdr.len > ether_type) - m_adj(m, ether_type - m->m_pkthdr.len); - M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); - if (m == 0) - return; - if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, - eh->ether_dhost, LLC_X25_LSAP, 6, - mtod(m, struct sdl_hdr *))) - panic("ETHER cons addr failure"); - mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type; -#ifdef LLC_DEBUG - printf("llc packet\n"); -#endif /* LLC_DEBUG */ - schednetisr(NETISR_CCITT); - inq = &llcintrq; - break; - } -#endif /* LLC */ - dropanyway: - default: - m_freem(m); - return; - } -#else /* ISO || LLC || NETATALK */ - m_freem(m); - return; -#endif /* ISO || LLC || NETATALK */ - } - - s = splimp(); - if (IF_QFULL(inq)) { - IF_DROP(inq); - m_freem(m); - } else - IF_ENQUEUE(inq, m); - splx(s); -} - -/* - * Perform common duties while attaching to interface list - */ -void -ether_ifattach(ifp) - register struct ifnet *ifp; -{ - register struct ifaddr *ifa; - register struct sockaddr_dl *sdl; - - ifp->if_type = IFT_ETHER; - ifp->if_addrlen = 6; - ifp->if_hdrlen = 14; - ifp->if_mtu = ETHERMTU; - if (ifp->if_baudrate == 0) - ifp->if_baudrate = 10000000; - for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) - if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && - sdl->sdl_family == AF_LINK) { - sdl->sdl_type = IFT_ETHER; - sdl->sdl_alen = ifp->if_addrlen; - bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, - LLADDR(sdl), ifp->if_addrlen); - break; - } -} - -static u_char ether_ipmulticast_min[6] = - { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; -static u_char ether_ipmulticast_max[6] = - { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; -/* - * Add an Ethernet multicast address or range of addresses to the list for a - * given interface. - */ -int -ether_addmulti(ifr, ac) - struct ifreq *ifr; - register struct arpcom *ac; -{ - register struct ether_multi *enm; - struct sockaddr_in *sin; - u_char addrlo[6]; - u_char addrhi[6]; - int set_allmulti = 0; - int s = splimp(); - - switch (ifr->ifr_addr.sa_family) { - - case AF_UNSPEC: - bcopy(ifr->ifr_addr.sa_data, addrlo, 6); - bcopy(addrlo, addrhi, 6); - break; - -#ifdef INET - case AF_INET: - sin = (struct sockaddr_in *)&(ifr->ifr_addr); - if (sin->sin_addr.s_addr == INADDR_ANY) { - /* - * An IP address of INADDR_ANY means listen to all - * of the Ethernet multicast addresses used for IP. - * (This is for the sake of IP multicast routers.) - */ - bcopy(ether_ipmulticast_min, addrlo, 6); - bcopy(ether_ipmulticast_max, addrhi, 6); - set_allmulti = 1; - } - else { - ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); - bcopy(addrlo, addrhi, 6); - } - break; -#endif - - default: - splx(s); - return (EAFNOSUPPORT); - } - - /* - * Verify that we have valid Ethernet multicast addresses. - */ - if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { - splx(s); - return (EINVAL); - } - /* - * See if the address range is already in the list. - */ - ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); - if (enm != NULL) { - /* - * Found it; just increment the reference count. - */ - ++enm->enm_refcount; - splx(s); - return (0); - } - /* - * New address or range; malloc a new multicast record - * and link it into the interface's multicast list. - */ - enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); - if (enm == NULL) { - splx(s); - return (ENOBUFS); - } - bcopy(addrlo, enm->enm_addrlo, 6); - bcopy(addrhi, enm->enm_addrhi, 6); - enm->enm_ac = ac; - enm->enm_refcount = 1; - enm->enm_next = ac->ac_multiaddrs; - ac->ac_multiaddrs = enm; - ac->ac_multicnt++; - splx(s); - if (set_allmulti) - ac->ac_if.if_flags |= IFF_ALLMULTI; - - /* - * Return ENETRESET to inform the driver that the list has changed - * and its reception filter should be adjusted accordingly. - */ - return (ENETRESET); -} - -/* - * Delete a multicast address record. - */ -int -ether_delmulti(ifr, ac) - struct ifreq *ifr; - register struct arpcom *ac; -{ - register struct ether_multi *enm; - register struct ether_multi **p; - struct sockaddr_in *sin; - u_char addrlo[6]; - u_char addrhi[6]; - int unset_allmulti = 0; - int s = splimp(); - - switch (ifr->ifr_addr.sa_family) { - - case AF_UNSPEC: - bcopy(ifr->ifr_addr.sa_data, addrlo, 6); - bcopy(addrlo, addrhi, 6); - break; - -#ifdef INET - case AF_INET: - sin = (struct sockaddr_in *)&(ifr->ifr_addr); - if (sin->sin_addr.s_addr == INADDR_ANY) { - /* - * An IP address of INADDR_ANY means stop listening - * to the range of Ethernet multicast addresses used - * for IP. - */ - bcopy(ether_ipmulticast_min, addrlo, 6); - bcopy(ether_ipmulticast_max, addrhi, 6); - unset_allmulti = 1; - } - else { - ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); - bcopy(addrlo, addrhi, 6); - } - break; -#endif - - default: - splx(s); - return (EAFNOSUPPORT); - } - - /* - * Look up the address in our list. - */ - ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); - if (enm == NULL) { - splx(s); - return (ENXIO); - } - if (--enm->enm_refcount != 0) { - /* - * Still some claims to this record. - */ - splx(s); - return (0); - } - /* - * No remaining claims to this record; unlink and free it. - */ - for (p = &enm->enm_ac->ac_multiaddrs; - *p != enm; - p = &(*p)->enm_next) - continue; - *p = (*p)->enm_next; - free(enm, M_IFMADDR); - ac->ac_multicnt--; - splx(s); - if (unset_allmulti) - ac->ac_if.if_flags &= ~IFF_ALLMULTI; - - /* - * Return ENETRESET to inform the driver that the list has changed - * and its reception filter should be adjusted accordingly. - */ - return (ENETRESET); -} - -SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); - -int -ether_ioctl(struct ifnet *ifp, int command, caddr_t data) -{ - struct ifaddr *ifa = (struct ifaddr *) data; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0; - - switch (command) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: - ifp->if_init(ifp->if_softc); /* before arpwhohas */ - arp_ifinit((struct arpcom *)ifp, ifa); - break; -#endif -#ifdef IPX - /* - * XXX - This code is probably wrong - */ - case AF_IPX: - { - register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); - struct arpcom *ac = (struct arpcom *) (ifp->if_softc); - - if (ipx_nullhost(*ina)) - ina->x_host = - *(union ipx_host *) - ac->ac_enaddr; - else { - bcopy((caddr_t) ina->x_host.c_host, - (caddr_t) ac->ac_enaddr, - sizeof(ac->ac_enaddr)); - } - - /* - * Set new address - */ - ifp->if_init(ifp->if_softc); - break; - } -#endif -#ifdef NS - /* - * XXX - This code is probably wrong - */ - case AF_NS: - { - register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); - struct arpcom *ac = (struct arpcom *) (ifp->if_softc); - - if (ns_nullhost(*ina)) - ina->x_host = - *(union ns_host *) (ac->ac_enaddr); - else { - bcopy((caddr_t) ina->x_host.c_host, - (caddr_t) ac->ac_enaddr, - sizeof(ac->ac_enaddr)); - } - - /* - * Set new address - */ - ifp->if_init(ifp->if_softc); - break; - } -#endif - default: - ifp->if_init(ifp->if_softc); - break; - } - break; - - case SIOCGIFADDR: - { - struct sockaddr *sa; - - sa = (struct sockaddr *) & ifr->ifr_data; - bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr, - (caddr_t) sa->sa_data, ETHER_ADDR_LEN); - } - break; - - case SIOCSIFMTU: - /* - * Set the interface MTU. - */ - if (ifr->ifr_mtu > ETHERMTU) { - error = EINVAL; - } else { - ifp->if_mtu = ifr->ifr_mtu; - } - break; - } - return (error); -} diff --git a/c/src/exec/libnetworking/net/if_llc.h b/c/src/exec/libnetworking/net/if_llc.h deleted file mode 100644 index 3cdf652167..0000000000 --- a/c/src/exec/libnetworking/net/if_llc.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)if_llc.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NET_IF_LLC_H_ -#define _NET_IF_LLC_H_ - -/* - * IEEE 802.2 Link Level Control headers, for use in conjunction with - * 802.{3,4,5} media access control methods. - * - * Headers here do not use bit fields due to shortcomings in many - * compilers. - */ - -struct llc { - u_char llc_dsap; - u_char llc_ssap; - union { - struct { - u_char control; - u_char format_id; - u_char class; - u_char window_x2; - } type_u; - struct { - u_char num_snd_x2; - u_char num_rcv_x2; - } type_i; - struct { - u_char control; - u_char num_rcv_x2; - } type_s; - struct { - u_char control; - struct frmrinfo { - u_char rej_pdu_0; - u_char rej_pdu_1; - u_char frmr_control; - u_char frmr_control_ext; - u_char frmr_cause; - } frmrinfo; - } type_frmr; - struct { - u_char control; - u_char org_code[3]; - u_short ether_type; - } type_snap; - struct { - u_char control; - u_char control_ext; - } type_raw; - } llc_un; -}; -#define llc_control llc_un.type_u.control -#define llc_control_ext llc_un.type_raw.control_ext -#define llc_fid llc_un.type_u.format_id -#define llc_class llc_un.type_u.class -#define llc_window llc_un.type_u.window_x2 -#define llc_frmrinfo llc_un.type_frmr.frmrinfo -#define llc_frmr_pdu0 llc_un.type_frmr.frmrinfo.rej_pdu0 -#define llc_frmr_pdu1 llc_un.type_frmr.frmrinfo.rej_pdu1 -#define llc_frmr_control llc_un.type_frmr.frmrinfo.frmr_control -#define llc_frmr_control_ext llc_un.type_frmr.frmrinfo.frmr_control_ext -#define llc_frmr_cause llc_un.type_frmr.frmrinfo.frmr_control_ext - -/* - * Don't use sizeof(struct llc_un) for LLC header sizes - */ -#define LLC_ISFRAMELEN 4 -#define LLC_UFRAMELEN 3 -#define LLC_FRMRLEN 7 - -/* - * Unnumbered LLC format commands - */ -#define LLC_UI 0x3 -#define LLC_UI_P 0x13 -#define LLC_DISC 0x43 -#define LLC_DISC_P 0x53 -#define LLC_UA 0x63 -#define LLC_UA_P 0x73 -#define LLC_TEST 0xe3 -#define LLC_TEST_P 0xf3 -#define LLC_FRMR 0x87 -#define LLC_FRMR_P 0x97 -#define LLC_DM 0x0f -#define LLC_DM_P 0x1f -#define LLC_XID 0xaf -#define LLC_XID_P 0xbf -#define LLC_SABME 0x6f -#define LLC_SABME_P 0x7f - -/* - * Supervisory LLC commands - */ -#define LLC_RR 0x01 -#define LLC_RNR 0x05 -#define LLC_REJ 0x09 - -/* - * Info format - dummy only - */ -#define LLC_INFO 0x00 - -/* - * ISO PDTR 10178 contains among others - */ -#define LLC_X25_LSAP 0x7e -#define LLC_SNAP_LSAP 0xaa -#define LLC_ISO_LSAP 0xfe - -#endif diff --git a/c/src/exec/libnetworking/net/if_loop.c b/c/src/exec/libnetworking/net/if_loop.c deleted file mode 100644 index 345730c729..0000000000 --- a/c/src/exec/libnetworking/net/if_loop.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)if_loop.c 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -/* - * Loopback interface driver for protocol testing and timing. - */ -#include "loop.h" -#if NLOOP > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/errno.h> -#include <sys/ioctl.h> -#include <sys/time.h> - -#include <net/if.h> -#include <net/if_types.h> -#include <net/netisr.h> -#include <net/route.h> -#include <net/bpf.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#endif - -#ifdef IPX -#include <netipx/ipx.h> -#include <netipx/ipx_if.h> -#endif - -#ifdef NS -#include <netns/ns.h> -#include <netns/ns_if.h> -#endif - -#ifdef ISO -#include <netiso/iso.h> -#include <netiso/iso_var.h> -#endif - -#ifdef NETATALK -#include <netinet/if_ether.h> -#include <netatalk/at.h> -#include <netatalk/at_var.h> -#endif NETATALK - -#include "bpfilter.h" - -static int loioctl __P((struct ifnet *, int, caddr_t)); -static void lortrequest __P((int, struct rtentry *, struct sockaddr *)); - - void rtems_bsdnet_loopattach __P((void *)); -PSEUDO_SET(loopattach, if_loop); - -#ifdef TINY_LOMTU -#define LOMTU (1024+512) -#else -#define LOMTU 16384 -#endif - -struct ifnet loif[NLOOP]; - -/* ARGSUSED */ -void -rtems_bsdnet_loopattach(dummy) - void *dummy; -{ - register struct ifnet *ifp; - register int i = 0; - - for (ifp = loif; i < NLOOP; ifp++) { - ifp->if_name = "lo"; - ifp->if_next = NULL; - ifp->if_unit = i++; - ifp->if_mtu = LOMTU; - ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; - ifp->if_ioctl = loioctl; - ifp->if_output = looutput; - ifp->if_type = IFT_LOOP; - ifp->if_hdrlen = 0; - ifp->if_addrlen = 0; - ifp->if_snd.ifq_maxlen = ifqmaxlen; - if_attach(ifp); -#if NBPFILTER > 0 - bpfattach(ifp, DLT_NULL, sizeof(u_int)); -#endif - } -} - -int -looutput(ifp, m, dst, rt) - struct ifnet *ifp; - register struct mbuf *m; - struct sockaddr *dst; - register struct rtentry *rt; -{ - int s, isr; - register struct ifqueue *ifq = 0; - - if ((m->m_flags & M_PKTHDR) == 0) - panic("looutput no HDR"); -#if NBPFILTER > 0 - /* BPF write needs to be handled specially */ - if (dst->sa_family == AF_UNSPEC) { - dst->sa_family = *(mtod(m, int *)); - m->m_len -= sizeof(int); - m->m_pkthdr.len -= sizeof(int); - m->m_data += sizeof(int); - } - - if (ifp->if_bpf) { - /* - * We need to prepend the address family as - * a four byte field. Cons up a dummy header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer a to it). - */ - struct mbuf m0; - u_int af = dst->sa_family; - - m0.m_next = m; - m0.m_len = 4; - m0.m_data = (char *)⁡ - - bpf_mtap(ifp, &m0); - } -#endif - m->m_pkthdr.rcvif = ifp; - - if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { - m_freem(m); - return (rt->rt_flags & RTF_BLACKHOLE ? 0 : - rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); - } - ifp->if_opackets++; - ifp->if_obytes += m->m_pkthdr.len; - switch (dst->sa_family) { - -#ifdef INET - case AF_INET: - ifq = &ipintrq; - isr = NETISR_IP; - break; -#endif -#ifdef IPX - case AF_IPX: - ifq = &ipxintrq; - isr = NETISR_IPX; - break; -#endif -#ifdef NS - case AF_NS: - ifq = &nsintrq; - isr = NETISR_NS; - break; -#endif -#ifdef ISO - case AF_ISO: - ifq = &clnlintrq; - isr = NETISR_ISO; - break; -#endif -#ifdef NETATALK - case AF_APPLETALK: - ifq = &atintrq2; - isr = NETISR_ATALK; - break; -#endif NETATALK - default: - printf("lo%d: can't handle af%d\n", ifp->if_unit, - dst->sa_family); - m_freem(m); - return (EAFNOSUPPORT); - } - s = splimp(); - if (IF_QFULL(ifq)) { - IF_DROP(ifq); - m_freem(m); - splx(s); - return (ENOBUFS); - } - IF_ENQUEUE(ifq, m); - schednetisr(isr); - ifp->if_ipackets++; - ifp->if_ibytes += m->m_pkthdr.len; - splx(s); - return (0); -} - -/* ARGSUSED */ -static void -lortrequest(cmd, rt, sa) - int cmd; - struct rtentry *rt; - struct sockaddr *sa; -{ - if (rt) { - rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ - /* - * For optimal performance, the send and receive buffers - * should be at least twice the MTU plus a little more for - * overhead. - */ - rt->rt_rmx.rmx_recvpipe = - rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; - } -} - -/* - * Process an ioctl request. - */ -/* ARGSUSED */ -static int -loioctl(ifp, cmd, data) - register struct ifnet *ifp; - int cmd; - caddr_t data; -{ - register struct ifaddr *ifa; - register struct ifreq *ifr = (struct ifreq *)data; - register int error = 0; - - switch (cmd) { - - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP | IFF_RUNNING; - ifa = (struct ifaddr *)data; - ifa->ifa_rtrequest = lortrequest; - /* - * Everything else is done at a higher level. - */ - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - if (ifr == 0) { - error = EAFNOSUPPORT; /* XXX */ - break; - } - switch (ifr->ifr_addr.sa_family) { - -#ifdef INET - case AF_INET: - break; -#endif - - default: - error = EAFNOSUPPORT; - break; - } - break; - - case SIOCSIFMTU: - ifp->if_mtu = ifr->ifr_mtu; - break; - - default: - error = EINVAL; - } - return (error); -} -#endif /* NLOOP > 0 */ diff --git a/c/src/exec/libnetworking/net/if_ppp.c b/c/src/exec/libnetworking/net/if_ppp.c deleted file mode 100644 index d4e0847655..0000000000 --- a/c/src/exec/libnetworking/net/if_ppp.c +++ /dev/null @@ -1,1744 +0,0 @@ -/* - * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. - * - * Copyright (c) 1989 Carnegie Mellon University. - * 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 Carnegie Mellon University. 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. - * - * Drew D. Perkins - * Carnegie Mellon University - * 4910 Forbes Ave. - * Pittsburgh, PA 15213 - * (412) 268-8576 - * ddp@andrew.cmu.edu - * - * Based on: - * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 - * - * Copyright (c) 1987 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. - * - * Serial Line interface - * - * Rick Adams - * Center for Seismic Studies - * 1300 N 17th Street, Suite 1450 - * Arlington, Virginia 22209 - * (703)276-7900 - * rick@seismo.ARPA - * seismo!rick - * - * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). - * Converted to 4.3BSD Beta by Chris Torek. - * Other changes made at Berkeley, based in part on code by Kirk Smith. - * - * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) - * Added VJ tcp header compression; more unified ioctls - * - * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). - * Cleaned up a lot of the mbuf-related code to fix bugs that - * caused system crashes and packet corruption. Changed pppstart - * so that it doesn't just give up with a collision if the whole - * packet doesn't fit in the output ring buffer. - * - * Added priority queueing for interactive IP packets, following - * the model of if_sl.c, plus hooks for bpf. - * Paul Mackerras (paulus@cs.anu.edu.au). - */ - -/* $Id$ */ -/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ -/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ - -#include "ppp.h" -#if NPPP > 0 - -#include <termios.h> -#include <rtems/termiostypes.h> -#include <rtems/rtems_bsdnet.h> -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/kernel.h> -#include <sys/time.h> -#include <sys/malloc.h> - -#include <net/if.h> -#include <net/if_types.h> -#include <net/netisr.h> -#include <net/route.h> -#ifdef PPP_FILTER -#include <net/bpf.h> -#endif - -#if INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#endif - -#include "bpfilter.h" -#if NBPFILTER > 0 -#include <net/bpf.h> -#endif - -#ifdef VJC -#include <net/pppcompress.h> -#endif - -#include <net/ppp_defs.h> -#include <net/if_ppp.h> -#include <net/if_pppvar.h> -#include <machine/cpu.h> - -#define splsoftnet splnet - -#ifdef PPP_COMPRESS -#define PACKETPTR struct mbuf * -#include <net/ppp-comp.h> -#endif - -static int pppsioctl __P((struct ifnet *, int, caddr_t)); -static void ppp_requeue __P((struct ppp_softc *)); -#ifdef PPP_COMPRESS -static void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd)); -static void ppp_ccp_closed __P((struct ppp_softc *)); -#endif -static struct mbuf *ppp_inproc __P((struct ppp_softc *, struct mbuf *)); -static void pppdumpm __P((struct mbuf *m0)); - -/* - * Some useful mbuf macros not in mbuf.h. - */ -#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT) - -#define M_DATASTART(m) \ - (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \ - (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) - -#define M_DATASIZE(m) \ - (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \ - (m)->m_flags & M_PKTHDR ? MHLEN: MLEN) - -/* - * We steal two bits in the mbuf m_flags, to mark high-priority packets - * for output, and received packets following lost/corrupted packets. - */ -#define M_HIGHPRI 0x2000 /* output packet for sc_fastq */ -#define M_ERRMARK 0x4000 /* steal a bit in mbuf m_flags */ - - -#ifdef PPP_COMPRESS -/* - * List of compressors we know about. - * We leave some space so maybe we can modload compressors. - */ - -extern struct compressor ppp_bsd_compress; -extern struct compressor ppp_deflate, ppp_deflate_draft; - -struct compressor *ppp_compressors[8] = { -#if DO_BSD_COMPRESS - &ppp_bsd_compress, -#endif -#if DO_DEFLATE - &ppp_deflate, - &ppp_deflate_draft, -#endif - NULL -}; -#endif /* PPP_COMPRESS */ - -extern struct ifqueue ipintrq; -static struct timeval ppp_time; - -TEXT_SET(pseudo_set, ppp_rxdaemon); - - -static rtems_task ppp_rxdaemon(rtems_task_argument arg) -{ - rtems_event_set events; - rtems_interrupt_level level; - struct ppp_softc *sc = (struct ppp_softc *)arg; - struct mbuf *mp = (struct mbuf *)0; - struct mbuf *m; - - /* enter processing loop */ - while ( 1 ) { - /* wait for event */ - rtems_event_receive(RX_PACKET|RX_MBUF|RX_EMPTY,RTEMS_WAIT|RTEMS_EVENT_ANY,RTEMS_NO_TIMEOUT,&events); - if ( events & RX_EMPTY ) { - printf("RX: QUEUE is EMPTY\n"); - events &= ~RX_EMPTY; - } - - if ( events ) { - /* get the network semaphore */ - rtems_bsdnet_semaphore_obtain(); - - /* check to see if new packet was received */ - if ( events & RX_PACKET ) { - /* get received packet mbuf chain */ - rtems_interrupt_disable(level); - IF_DEQUEUE(&sc->sc_rawq, m); - rtems_interrupt_enable(level); - - /* ensure packet was retrieved */ - if ( m != (struct mbuf *)0 ) { - /* process the received packet */ - mp = ppp_inproc(sc, m); - } - } - - /* allocate a new mbuf to replace one */ - if ( mp == NULL ) { - pppallocmbuf(sc, &mp); - } - - /* place mbuf on freeq */ - rtems_interrupt_disable(level); - IF_ENQUEUE(&sc->sc_freeq, mp); - rtems_interrupt_enable(level); - mp = (struct mbuf *)0; - - /* release the network semaphore */ - rtems_bsdnet_semaphore_release(); - - /* check to see if queue is empty */ - if ( sc->sc_rawq.ifq_head ) { - /* queue is not empty - post another event */ - rtems_event_send(sc->sc_rxtask, RX_PACKET); - } - } - } -} - -static rtems_task ppp_txdaemon(rtems_task_argument arg) -{ - rtems_event_set events; - int iprocess = (int )0; - struct ppp_softc *sc = (struct ppp_softc *)arg; - struct mbuf *mp; - struct mbuf *mf; - struct mbuf *m; - struct rtems_termios_tty *tp; - - /* enter processing loop */ - while ( 1 ) { - /* wait for event */ - rtems_event_receive(TX_PACKET|TX_TRANSMIT,RTEMS_WAIT|RTEMS_EVENT_ANY,RTEMS_NO_TIMEOUT,&events); - if ( events & TX_TRANSMIT ) { - /* received event from interrupt handler - free current mbuf */ - rtems_bsdnet_semaphore_obtain(); - m_freem(sc->sc_outm); - rtems_bsdnet_semaphore_release(); - - /* chain is done - clear the values */ - sc->sc_outm = (struct mbuf *)0; - sc->sc_outmc = (struct mbuf *)0; - - /* now set flag to fake receive of TX_PACKET event */ - /* this will check to see if we have any pending packets */ - events |= TX_PACKET; - } - - /* received event from pppasyncstart */ - if ( events & TX_PACKET ) { - /* ensure we are not busy */ - if ( sc->sc_outm == (struct mbuf *)0 ) { - /* try dequeuing a packet */ - sc->sc_outm = ppp_dequeue(sc); - if ( sc->sc_outm == NULL ) { - /* clear output flags */ - sc->sc_outflag = 0; - sc->sc_if.if_flags &= ~IFF_OACTIVE; - } - else { - /* set flag to start process */ - iprocess = 1; - sc->sc_outflag = SC_TX_BUSY; - sc->sc_if.if_flags |= IFF_OACTIVE; - } - } - } - - /* check to see if there is any processing required */ - if ( iprocess ) { - /* clear process flag */ - iprocess = (int)0; - - /* initialize output values */ - sc->sc_outfcs = PPP_INITFCS; - sc->sc_outbuf = (u_char *)0; - sc->sc_outlen = (short )0; - sc->sc_outoff = (short )0; - sc->sc_outfcslen = (short )0; - - /* loop over all mbufs in chain */ - mf = NULL; - mp = NULL; - m = sc->sc_outm; - while (( m != (struct mbuf *)0 ) && ( m->m_len > 0 )) { - /* check to see if first mbuf value has been set */ - if ( sc->sc_outmc == (struct mbuf *)0 ) { - /* set values to start with this mbuf */ - sc->sc_outmc = m; - sc->sc_outlen = m->m_len; - sc->sc_outbuf = mtod(m, u_char *); - } - - /* update the FCS value and then check next packet length */ - sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len); - - /* check next packet to see if it is empty */ - while (( m->m_next != NULL ) && ( m->m_next->m_len == 0 )) { - /* next mbuf is zero length */ - /* add empty mbuf to free chain */ - if ( mp == NULL ) { - /* item is head of free list */ - mf = m->m_next; - mp = mf; - } - else { - /* add item to end of the free list */ - mp->m_next = m->m_next; - mp = m->m_next; - } - - /* remove empty item from process chain */ - m->m_next = m->m_next->m_next; - mp->m_next = NULL; - } - - /* move to next packet */ - m = m->m_next; - } - - /* ensure there is data to be sent out */ - tp = (struct rtems_termios_tty *)sc->sc_devp; - if (( tp != NULL ) && ( sc->sc_outmc != (struct mbuf *)0 )) { - /* place FCS value into buffer */ - sc->sc_outfcsbuf[sc->sc_outfcslen++] = ~sc->sc_outfcs & 0xff; - sc->sc_outfcsbuf[sc->sc_outfcslen++] = (~sc->sc_outfcs >> 8) & 0xff; - microtime(&sc->sc_if.if_lastchange); - - /* write out frame byte to start the transmission */ - sc->sc_outchar = (u_char)PPP_FLAG; - (*tp->device.write)(tp->minor, &sc->sc_outchar, 1); - } - - /* check to see if we need to free some empty mbufs */ - if ( mf != (struct mbuf *)0 ) { - /* free empty mbufs */ - rtems_bsdnet_semaphore_obtain(); - m_freem(mf); - rtems_bsdnet_semaphore_release(); - } - } - } -} - -static void ppp_init(struct ppp_softc *sc) -{ - rtems_status_code status; - rtems_unsigned32 priority = 100; - - /* determine priority value */ - if ( rtems_bsdnet_config.network_task_priority ) { - priority = rtems_bsdnet_config.network_task_priority; - } - - /* check to see if we need to start up daemons */ - if ( sc->sc_rxtask == 0 ) { - /* start rx daemon task */ - status = rtems_task_create(rtems_build_name('R','x','P','0'+sc->sc_if.if_unit), priority, 2048, - RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), - RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, - &sc->sc_rxtask); - if (status != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred(status); - } - else { - status = rtems_task_start(sc->sc_rxtask, ppp_rxdaemon, (rtems_task_argument)sc); - if (status != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred(status); - } - } - - /* start tx daemon task */ - status = rtems_task_create(rtems_build_name('T','x','P','0'+sc->sc_if.if_unit), priority, 2048, - RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), - RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, - &sc->sc_txtask); - if (status != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred(status); - } - else { - status = rtems_task_start(sc->sc_txtask, ppp_txdaemon, (rtems_task_argument)sc); - if (status != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred(status); - } - } - } - - /* mark driver running and output inactive */ - /* ilya: IFF_RUNNING flag will be marked after the IPCP goes up */ -/* sc->sc_if.if_flags |= IFF_RUNNING; */ -} - -/* - * Called from boot code to establish ppp interfaces. - */ -int rtems_ppp_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching) -{ -/* int i = (int)0; */ - struct ppp_softc *sc; - char *name; - int number; - - - number = rtems_bsdnet_parse_driver_name (config, &name); - - if (!attaching || (number >= NPPP)) - return 0; - - sc = &ppp_softc[number]; - - if (sc->sc_if.if_name != NULL) - return 0; /* interface is already attached */ - -/* for (sc = ppp_softc; i < NPPP; sc++) { */ - sc->sc_if.if_name = name /*"ppp"*/; - sc->sc_if.if_unit = number /*i++*/; - sc->sc_if.if_mtu = PPP_MTU; - sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; - sc->sc_if.if_type = IFT_PPP; - sc->sc_if.if_hdrlen = PPP_HDRLEN; - sc->sc_if.if_ioctl = pppsioctl; - sc->sc_if.if_output = pppoutput; - sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN; - sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; - sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; - sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN; - sc->sc_freeq.ifq_maxlen = NUM_MBUFQ; - - /* initialize and attach */ - ppp_init(sc); - if_attach(&sc->sc_if); -#if NBPFILTER > 0 - bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN); -#endif -/* } */ - - return ( 1 ); -} - -/* - * Allocate a ppp interface unit and initialize it. - */ -struct ppp_softc * -pppalloc(pid) - pid_t pid; -{ - int nppp, i; - struct ppp_softc *sc; - - for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) - if (sc->sc_xfer == pid) { - sc->sc_xfer = 0; - return sc; - } - for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) - if (sc->sc_devp == NULL) - break; - if (nppp >= NPPP) - return NULL; - - sc->sc_flags = 0; - sc->sc_mru = PPP_MRU; - sc->sc_relinq = NULL; - bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats)); -#ifdef VJC - MALLOC(sc->sc_comp, struct vjcompress *, sizeof(struct vjcompress), - M_DEVBUF, M_NOWAIT); - if (sc->sc_comp) - vj_compress_init(sc->sc_comp, -1); -#endif -#ifdef PPP_COMPRESS - sc->sc_xc_state = NULL; - sc->sc_rc_state = NULL; -#endif /* PPP_COMPRESS */ - for (i = 0; i < NUM_NP; ++i) - sc->sc_npmode[i] = NPMODE_ERROR; - sc->sc_npqueue = NULL; - sc->sc_npqtail = &sc->sc_npqueue; - microtime(&ppp_time); - sc->sc_last_sent = sc->sc_last_recv = ppp_time.tv_sec; - - return sc; -} - -/* - * Deallocate a ppp unit. Must be called at splsoftnet or higher. - */ -void -pppdealloc(sc) - struct ppp_softc *sc; -{ - struct mbuf *m; - rtems_interrupt_level level; - - if_down(&sc->sc_if); - sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); - sc->sc_devp = NULL; - sc->sc_xfer = 0; - - rtems_interrupt_disable(level); - if ( sc->sc_m != NULL ) { - m_freem(sc->sc_m); - sc->sc_m = (struct mbuf *)0; - } - if ( sc->sc_outm != NULL ) { - m_freem(sc->sc_outm); - sc->sc_outm = (struct mbuf *)0; - sc->sc_outmc = (struct mbuf *)0; - sc->sc_outflag = 0; - } - do { - IF_DEQUEUE(&sc->sc_freeq, m); - if (m != NULL) { - m_freem(m); - } - } while ( m != NULL ); - do { - IF_DEQUEUE(&sc->sc_rawq, m); - if (m != NULL) { - m_freem(m); - } - } while ( m != NULL ); - rtems_interrupt_enable(level); - - for (;;) { - IF_DEQUEUE(&sc->sc_inq, m); - if (m == NULL) - break; - m_freem(m); - } - for (;;) { - IF_DEQUEUE(&sc->sc_fastq, m); - if (m == NULL) - break; - m_freem(m); - } - while ((m = sc->sc_npqueue) != NULL) { - sc->sc_npqueue = m->m_nextpkt; - m_freem(m); - } -#ifdef PPP_COMPRESS - ppp_ccp_closed(sc); - sc->sc_xc_state = NULL; - sc->sc_rc_state = NULL; -#endif /* PPP_COMPRESS */ -#ifdef PPP_FILTER - if (sc->sc_pass_filt.bf_insns != 0) { - FREE(sc->sc_pass_filt.bf_insns, M_DEVBUF); - sc->sc_pass_filt.bf_insns = 0; - sc->sc_pass_filt.bf_len = 0; - } - if (sc->sc_active_filt.bf_insns != 0) { - FREE(sc->sc_active_filt.bf_insns, M_DEVBUF); - sc->sc_active_filt.bf_insns = 0; - sc->sc_active_filt.bf_len = 0; - } -#endif /* PPP_FILTER */ -#ifdef VJC - if (sc->sc_comp != 0) { - FREE(sc->sc_comp, M_DEVBUF); - sc->sc_comp = 0; - } -#endif -} - -/* - * Ioctl routine for generic ppp devices. - */ -int -pppioctl(sc, cmd, data, flag, p) - struct ppp_softc *sc; - int cmd; - caddr_t data; - int flag; - struct proc *p; -{ - int s, flags, mru, npx, taskid; - struct npioctl *npi; - time_t t; -#ifdef PPP_FILTER - int error; - struct bpf_program *bp, *nbp; - struct bpf_insn *newcode, *oldcode; - int newcodelen; -#endif /* PPP_FILTER */ -#ifdef PPP_COMPRESS - int nb; - struct ppp_option_data *odp; - struct compressor **cp; - u_char ccp_option[CCP_MAX_OPTION_LENGTH]; -#endif - - switch (cmd) { - case FIONREAD: - *(int *)data = sc->sc_inq.ifq_len; - break; - - case PPPIOCSTASK: - taskid = *(int *)data; - sc->sc_pppdtask = taskid; - break; - - case PPPIOCGUNIT: - *(int *)data = sc->sc_if.if_unit; - break; - - case PPPIOCGFLAGS: - *(u_int *)data = sc->sc_flags; - break; - - case PPPIOCSFLAGS: - flags = *(int *)data & SC_MASK; - s = splsoftnet(); -#ifdef PPP_COMPRESS - if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) - ppp_ccp_closed(sc); -#endif - s = splimp(); - sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; - splx(s); - break; - - case PPPIOCSMRU: - mru = *(int *)data; - if ( mru >= MCLBYTES ) { - /* error - currently only handle 1 culster sized MRU */ - /* if we want to handle up to PPP_MAXMRU then we */ - /* need to reallocate all mbufs on the freeq */ - /* this can only be done with iterrupts disabled */ - return ( -1 ); - } - else if ( mru >= PPP_MRU ) { - /* update the size */ - sc->sc_mru = mru; - } - break; - - case PPPIOCGMRU: - *(int *)data = sc->sc_mru; - break; - -#ifdef VJC - case PPPIOCSMAXCID: - if (sc->sc_comp) { - s = splsoftnet(); - vj_compress_init(sc->sc_comp, *(int *)data); - splx(s); - } - break; -#endif - - case PPPIOCXFERUNIT: - sc->sc_xfer = 0; /* Always root p->p_pid;*/ - break; - -#ifdef PPP_COMPRESS - case PPPIOCSCOMPRESS: - odp = (struct ppp_option_data *) data; - nb = odp->length; - if (nb > sizeof(ccp_option)) - nb = sizeof(ccp_option); - if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) - return (error); - if (ccp_option[1] < 2) /* preliminary check on the length byte */ - return (EINVAL); - for (cp = ppp_compressors; *cp != NULL; ++cp) - if ((*cp)->compress_proto == ccp_option[0]) { - /* - * Found a handler for the protocol - try to allocate - * a compressor or decompressor. - */ - error = 0; - if (odp->transmit) { - s = splsoftnet(); - if (sc->sc_xc_state != NULL) - (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); - sc->sc_xcomp = *cp; - sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb); - if (sc->sc_xc_state == NULL) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: comp_alloc failed\n", - sc->sc_if.if_unit); - error = ENOBUFS; - } - splimp(); - sc->sc_flags &= ~SC_COMP_RUN; - splx(s); - } else { - s = splsoftnet(); - if (sc->sc_rc_state != NULL) - (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); - sc->sc_rcomp = *cp; - sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb); - if (sc->sc_rc_state == NULL) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: decomp_alloc failed\n", - sc->sc_if.if_unit); - error = ENOBUFS; - } - splimp(); - sc->sc_flags &= ~SC_DECOMP_RUN; - splx(s); - } - return (error); - } - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: no compressor for [%x %x %x], %x\n", - sc->sc_if.if_unit, ccp_option[0], ccp_option[1], - ccp_option[2], nb); - return (EINVAL); /* no handler found */ -#endif /* PPP_COMPRESS */ - - case PPPIOCGNPMODE: - case PPPIOCSNPMODE: - npi = (struct npioctl *) data; - switch (npi->protocol) { - case PPP_IP: - npx = NP_IP; - break; - default: - return EINVAL; - } - if (cmd == PPPIOCGNPMODE) { - npi->mode = sc->sc_npmode[npx]; - } else { - if (npi->mode != sc->sc_npmode[npx]) { - s = splsoftnet(); - sc->sc_npmode[npx] = npi->mode; - if (npi->mode != NPMODE_QUEUE) { - ppp_requeue(sc); - (*sc->sc_start)(sc); - } - splx(s); - } - } - break; - - case PPPIOCGIDLE: - s = splsoftnet(); - microtime(&ppp_time); - t = ppp_time.tv_sec; - ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; - ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; - splx(s); - break; - -#ifdef PPP_FILTER - case PPPIOCSPASS: - case PPPIOCSACTIVE: - nbp = (struct bpf_program *) data; - if ((unsigned) nbp->bf_len > BPF_MAXINSNS) - return EINVAL; - newcodelen = nbp->bf_len * sizeof(struct bpf_insn); - if (newcodelen != 0) { - MALLOC(newcode, struct bpf_insn *, newcodelen, M_DEVBUF, M_WAITOK); - if (newcode == 0) { - return EINVAL; /* or sumpin */ - } - if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode, - newcodelen)) != 0) { - FREE(newcode, M_DEVBUF); - return error; - } - if (!bpf_validate(newcode, nbp->bf_len)) { - FREE(newcode, M_DEVBUF); - return EINVAL; - } - } else - newcode = 0; - bp = (cmd == PPPIOCSPASS)? &sc->sc_pass_filt: &sc->sc_active_filt; - oldcode = bp->bf_insns; - s = splimp(); - bp->bf_len = nbp->bf_len; - bp->bf_insns = newcode; - splx(s); - if (oldcode != 0) - FREE(oldcode, M_DEVBUF); - break; -#endif - - default: - return (-1); - } - return (0); -} - -/* - * Process an ioctl request to the ppp network interface. - */ -static int -pppsioctl(ifp, cmd, data) - register struct ifnet *ifp; - int cmd; - caddr_t data; -{ - /*struct proc *p = curproc;*/ /* XXX */ - register struct ppp_softc *sc = &ppp_softc[ifp->if_unit]; - register struct ifaddr *ifa = (struct ifaddr *)data; - register struct ifreq *ifr = (struct ifreq *)data; - struct ppp_stats *psp; -#ifdef PPP_COMPRESS - struct ppp_comp_stats *pcp; -#endif - int s = splimp(), error = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - if ((ifp->if_flags & IFF_RUNNING) == 0) - ifp->if_flags &= ~IFF_UP; - break; - - case SIOCSIFADDR: - if (ifa->ifa_addr->sa_family != AF_INET) - error = EAFNOSUPPORT; - break; - - case SIOCSIFDSTADDR: - if (ifa->ifa_addr->sa_family != AF_INET) - error = EAFNOSUPPORT; - break; - - case SIOCSIFMTU: - sc->sc_if.if_mtu = ifr->ifr_mtu; - break; - - case SIOCGIFMTU: - ifr->ifr_mtu = sc->sc_if.if_mtu; - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - if (ifr == 0) { - error = EAFNOSUPPORT; - break; - } - switch(ifr->ifr_addr.sa_family) { -#ifdef INET - case AF_INET: - break; -#endif - default: - error = EAFNOSUPPORT; - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - printf(" MRU:%-8u", sc->sc_mru); - printf(" Bytes received:%-8u", sc->sc_stats.ppp_ibytes); - printf(" Packets received:%-8u", sc->sc_stats.ppp_ipackets); - printf(" Receive errors:%-8u\n", sc->sc_stats.ppp_ierrors); - printf(" Bytes sent:%-8u", sc->sc_stats.ppp_obytes); - printf(" Packets sent:%-8u", sc->sc_stats.ppp_opackets); - printf(" Transmit errors:%-8u\n", sc->sc_stats.ppp_oerrors); - break; - - case SIOCGPPPSTATS: - psp = &((struct ifpppstatsreq *) data)->stats; - bzero(psp, sizeof(*psp)); - psp->p = sc->sc_stats; -#if defined(VJC) && !defined(SL_NO_STATS) - if (sc->sc_comp) { - psp->vj.vjs_packets = sc->sc_comp->sls_packets; - psp->vj.vjs_compressed = sc->sc_comp->sls_compressed; - psp->vj.vjs_searches = sc->sc_comp->sls_searches; - psp->vj.vjs_misses = sc->sc_comp->sls_misses; - psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin; - psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin; - psp->vj.vjs_errorin = sc->sc_comp->sls_errorin; - psp->vj.vjs_tossed = sc->sc_comp->sls_tossed; - } -#endif /* VJC */ - break; - -#ifdef PPP_COMPRESS - case SIOCGPPPCSTATS: - pcp = &((struct ifpppcstatsreq *) data)->stats; - bzero(pcp, sizeof(*pcp)); - if (sc->sc_xc_state != NULL) - (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c); - if (sc->sc_rc_state != NULL) - (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d); - break; -#endif /* PPP_COMPRESS */ - - default: - error = EINVAL; - } - splx(s); - return (error); -} - -/* - * Queue a packet. Start transmission if not active. - * Packet is placed in Information field of PPP frame. - */ -int -pppoutput(ifp, m0, dst, rtp) - struct ifnet *ifp; - struct mbuf *m0; - struct sockaddr *dst; - struct rtentry *rtp; -{ - register struct ppp_softc *sc = &ppp_softc[ifp->if_unit]; - int protocol, address, control; - u_char *cp; - int s, error; - struct ip *ip; - struct ifqueue *ifq; - enum NPmode mode; - int len; - struct mbuf *m; - - if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0 - || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) { - error = ENETDOWN; /* sort of */ - goto bad; - } - - /* - * Compute PPP header. - */ - m0->m_flags &= ~M_HIGHPRI; - switch (dst->sa_family) { -#ifdef INET - case AF_INET: - address = PPP_ALLSTATIONS; - control = PPP_UI; - protocol = PPP_IP; - mode = sc->sc_npmode[NP_IP]; - - /* - * If this packet has the "low delay" bit set in the IP header, - * put it on the fastq instead. - */ - ip = mtod(m0, struct ip *); - if (ip->ip_tos & IPTOS_LOWDELAY) - m0->m_flags |= M_HIGHPRI; - break; -#endif - case AF_UNSPEC: - address = PPP_ADDRESS(dst->sa_data); - control = PPP_CONTROL(dst->sa_data); - protocol = PPP_PROTOCOL(dst->sa_data); - mode = NPMODE_PASS; - break; - default: - printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family); - error = EAFNOSUPPORT; - goto bad; - } - - /* - * Drop this packet, or return an error, if necessary. - */ - if (mode == NPMODE_ERROR) { - error = ENETDOWN; - goto bad; - } - if (mode == NPMODE_DROP) { - error = 0; - goto bad; - } - - /* - * Add PPP header. If no space in first mbuf, allocate another. - * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.) - */ - if (M_LEADINGSPACE(m0) < PPP_HDRLEN) { - m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT); - if (m0 == 0) { - error = ENOBUFS; - goto bad; - } - m0->m_len = 0; - } else - m0->m_data -= PPP_HDRLEN; - - cp = mtod(m0, u_char *); - *cp++ = address; - *cp++ = control; - *cp++ = protocol >> 8; - *cp++ = protocol & 0xff; - m0->m_len += PPP_HDRLEN; - - len = 0; - for (m = m0; m != 0; m = m->m_next) - len += m->m_len; - - if (sc->sc_flags & SC_LOG_OUTPKT) { - printf("ppp%d output: ", ifp->if_unit); - pppdumpm(m0); - } - - if ((protocol & 0x8000) == 0) { -#ifdef PPP_FILTER - /* - * Apply the pass and active filters to the packet, - * but only if it is a data packet. - */ - *mtod(m0, u_char *) = 1; /* indicates outbound */ - if (sc->sc_pass_filt.bf_insns != 0 - && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m0, - len, 0) == 0) { - error = 0; /* drop this packet */ - goto bad; - } - - /* - * Update the time we sent the most recent packet. - */ - if (sc->sc_active_filt.bf_insns == 0 - || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m0, len, 0)) - sc->sc_last_sent = time.tv_sec; - - *mtod(m0, u_char *) = address; -#else - /* - * Update the time we sent the most recent data packet. - */ - microtime(&ppp_time); - sc->sc_last_sent = ppp_time.tv_sec; -#endif /* PPP_FILTER */ - } - -#if NBPFILTER > 0 - /* - * See if bpf wants to look at the packet. - */ - if (sc->sc_bpf) - bpf_mtap(sc->sc_bpf, m0); -#endif - - /* - * Put the packet on the appropriate queue. - */ - s = splsoftnet(); - if (mode == NPMODE_QUEUE) { - /* XXX we should limit the number of packets on this queue */ - *sc->sc_npqtail = m0; - m0->m_nextpkt = NULL; - sc->sc_npqtail = &m0->m_nextpkt; - } else { - ifq = (m0->m_flags & M_HIGHPRI)? &sc->sc_fastq: &ifp->if_snd; - if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) { - IF_DROP(ifq); - splx(s); - sc->sc_if.if_oerrors++; - sc->sc_stats.ppp_oerrors++; - error = ENOBUFS; - goto bad; - } - IF_ENQUEUE(ifq, m0); - (*sc->sc_start)(sc); - } - ifp->if_lastchange = ppp_time; - ifp->if_opackets++; - ifp->if_obytes += len; - - splx(s); - return (0); - -bad: - m_freem(m0); - return (error); -} - -/* - * After a change in the NPmode for some NP, move packets from the - * npqueue to the send queue or the fast queue as appropriate. - * Should be called at splsoftnet. - */ -static void -ppp_requeue(sc) - struct ppp_softc *sc; -{ - struct mbuf *m, **mpp; - struct ifqueue *ifq; - enum NPmode mode; - - for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) { - switch (PPP_PROTOCOL(mtod(m, u_char *))) { - case PPP_IP: - mode = sc->sc_npmode[NP_IP]; - break; - default: - mode = NPMODE_PASS; - } - - switch (mode) { - case NPMODE_PASS: - /* - * This packet can now go on one of the queues to be sent. - */ - *mpp = m->m_nextpkt; - m->m_nextpkt = NULL; - ifq = (m->m_flags & M_HIGHPRI)? &sc->sc_fastq: &sc->sc_if.if_snd; - if (IF_QFULL(ifq)) { - IF_DROP(ifq); - sc->sc_if.if_oerrors++; - sc->sc_stats.ppp_oerrors++; - } else - IF_ENQUEUE(ifq, m); - break; - - case NPMODE_DROP: - case NPMODE_ERROR: - *mpp = m->m_nextpkt; - m_freem(m); - break; - - case NPMODE_QUEUE: - mpp = &m->m_nextpkt; - break; - } - } - sc->sc_npqtail = mpp; -} - -/* - * Get a packet to send. This procedure is intended to be called at - * splsoftnet, since it may involve time-consuming operations such as - * applying VJ compression, packet compression, address/control and/or - * protocol field compression to the packet. - */ -struct mbuf * -ppp_dequeue(sc) - struct ppp_softc *sc; -{ - struct mbuf *m; -#ifdef VJC - struct mbuf *mp; -#endif - u_char *cp; - int address, control, protocol; - - /* - * Grab a packet to send: first try the fast queue, then the - * normal queue. - */ - rtems_bsdnet_semaphore_obtain(); - IF_DEQUEUE(&sc->sc_fastq, m); - if (m == NULL) - IF_DEQUEUE(&sc->sc_if.if_snd, m); - rtems_bsdnet_semaphore_release(); - - if (m == NULL) - return NULL; - - ++sc->sc_stats.ppp_opackets; - - /* - * Extract the ppp header of the new packet. - * The ppp header will be in one mbuf. - */ - cp = mtod(m, u_char *); - address = PPP_ADDRESS(cp); - control = PPP_CONTROL(cp); - protocol = PPP_PROTOCOL(cp); - - switch (protocol) { - case PPP_IP: -#ifdef VJC - /* - * If the packet is a TCP/IP packet, see if we can compress it. - */ - if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) { - struct ip *ip; - int type; - - mp = m; - ip = (struct ip *) (cp + PPP_HDRLEN); - if (mp->m_len <= PPP_HDRLEN) { - mp = mp->m_next; - if (mp == NULL) - break; - ip = mtod(mp, struct ip *); - } - /* this code assumes the IP/TCP header is in one non-shared mbuf */ - if (ip->ip_p == IPPROTO_TCP) { - type = vj_compress_tcp(mp, ip, sc->sc_comp, - !(sc->sc_flags & SC_NO_TCP_CCID)); - switch (type) { - case TYPE_UNCOMPRESSED_TCP: - protocol = PPP_VJC_UNCOMP; - break; - case TYPE_COMPRESSED_TCP: - protocol = PPP_VJC_COMP; - cp = mtod(m, u_char *); - cp[0] = address; /* header has moved */ - cp[1] = control; - cp[2] = 0; - break; - } - cp[3] = protocol; /* update protocol in PPP header */ - } - } -#endif /* VJC */ - break; - -#ifdef PPP_COMPRESS - case PPP_CCP: - ppp_ccp(sc, m, 0); - break; -#endif /* PPP_COMPRESS */ - } - -#ifdef PPP_COMPRESS - if (protocol != PPP_LCP && protocol != PPP_CCP - && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { - struct mbuf *mcomp = NULL; - int slen, clen; - - slen = 0; - for (mp = m; mp != NULL; mp = mp->m_next) - slen += mp->m_len; - clen = (*sc->sc_xcomp->compress) - (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN); - if (mcomp != NULL) { - if (sc->sc_flags & SC_CCP_UP) { - /* Send the compressed packet instead of the original. */ - m_freem(m); - m = mcomp; - cp = mtod(m, u_char *); - protocol = cp[3]; - } else { - /* Can't transmit compressed packets until CCP is up. */ - m_freem(mcomp); - } - } - } -#endif /* PPP_COMPRESS */ - - /* - * Compress the address/control and protocol, if possible. - */ - if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && - control == PPP_UI && protocol != PPP_ALLSTATIONS && - protocol != PPP_LCP) { - /* can compress address/control */ - m->m_data += 2; - m->m_len -= 2; - } - if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { - /* can compress protocol */ - if (mtod(m, u_char *) == cp) { - cp[2] = cp[1]; /* move address/control up */ - cp[1] = cp[0]; - } - ++m->m_data; - --m->m_len; - } - - return m; -} - -/* - * Software interrupt routine, called at splsoftnet. - */ -void -pppintr(void) -{ -} - -#ifdef PPP_COMPRESS -/* - * Handle a CCP packet. `rcvd' is 1 if the packet was received, - * 0 if it is about to be transmitted. - */ -static void -ppp_ccp(sc, m, rcvd) - struct ppp_softc *sc; - struct mbuf *m; - int rcvd; -{ - u_char *dp, *ep; - struct mbuf *mp; - int slen, s; - - /* - * Get a pointer to the data after the PPP header. - */ - if (m->m_len <= PPP_HDRLEN) { - mp = m->m_next; - if (mp == NULL) - return; - dp = (mp != NULL)? mtod(mp, u_char *): NULL; - } else { - mp = m; - dp = mtod(mp, u_char *) + PPP_HDRLEN; - } - - ep = mtod(mp, u_char *) + mp->m_len; - if (dp + CCP_HDRLEN > ep) - return; - slen = CCP_LENGTH(dp); - if (dp + slen > ep) { - if (sc->sc_flags & SC_DEBUG) - printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n", - dp, slen, mtod(mp, u_char *), mp->m_len); - return; - } - - switch (CCP_CODE(dp)) { - case CCP_CONFREQ: - case CCP_TERMREQ: - case CCP_TERMACK: - /* CCP must be going down - disable compression */ - if (sc->sc_flags & SC_CCP_UP) { - s = splimp(); - sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); - splx(s); - } - break; - - case CCP_CONFACK: - if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP) - && slen >= CCP_HDRLEN + CCP_OPT_MINLEN - && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { - if (!rcvd) { - /* we're agreeing to send compressed packets. */ - if (sc->sc_xc_state != NULL - && (*sc->sc_xcomp->comp_init) - (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, - sc->sc_if.if_unit, 0, sc->sc_flags & SC_DEBUG)) { - s = splimp(); - sc->sc_flags |= SC_COMP_RUN; - splx(s); - } - } else { - /* peer is agreeing to send compressed packets. */ - if (sc->sc_rc_state != NULL - && (*sc->sc_rcomp->decomp_init) - (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, - sc->sc_if.if_unit, 0, sc->sc_mru, - sc->sc_flags & SC_DEBUG)) { - s = splimp(); - sc->sc_flags |= SC_DECOMP_RUN; - sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); - splx(s); - } - } - } - break; - - case CCP_RESETACK: - if (sc->sc_flags & SC_CCP_UP) { - if (!rcvd) { - if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) - (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state); - } else { - if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { - (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state); - s = splimp(); - sc->sc_flags &= ~SC_DC_ERROR; - splx(s); - } - } - } - break; - } -} - -/* - * CCP is down; free (de)compressor state if necessary. - */ -static void -ppp_ccp_closed(sc) - struct ppp_softc *sc; -{ - if (sc->sc_xc_state) { - (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); - sc->sc_xc_state = NULL; - } - if (sc->sc_rc_state) { - (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); - sc->sc_rc_state = NULL; - } -} -#endif /* PPP_COMPRESS */ - -/* - * Process a received PPP packet, doing decompression as necessary. - * Should be called at splsoftnet. - */ -#define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ - TYPE_UNCOMPRESSED_TCP) - -static struct mbuf * -ppp_inproc(sc, m) - struct ppp_softc *sc; - struct mbuf *m; -{ - struct mbuf *mf = (struct mbuf *)0; - struct ifnet *ifp = &sc->sc_if; - struct ifqueue *inq; - int s, ilen, proto, rv; - u_char *cp, adrs, ctrl; - struct mbuf *mp; -#ifdef PPP_COMPRESS - struct mbuf *dmp = NULL; -#endif -#ifdef VJC - u_char *iphdr; - u_int hlen; - int xlen; -#endif - - sc->sc_stats.ppp_ipackets++; - - if (sc->sc_flags & SC_LOG_INPKT) { - ilen = 0; - for (mp = m; mp != NULL; mp = mp->m_next) - ilen += mp->m_len; - printf("ppp%d: got %d bytes\n", ifp->if_unit, ilen); - pppdumpm(m); - } - - cp = mtod(m, u_char *); - adrs = PPP_ADDRESS(cp); - ctrl = PPP_CONTROL(cp); - proto = PPP_PROTOCOL(cp); - - if (m->m_flags & M_ERRMARK) { - m->m_flags &= ~M_ERRMARK; - s = splimp(); - sc->sc_flags |= SC_VJ_RESET; - splx(s); - } - -#ifdef PPP_COMPRESS - /* - * Decompress this packet if necessary, update the receiver's - * dictionary, or take appropriate action on a CCP packet. - */ - if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN) - && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) { - /* decompress this packet */ - rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); - if (rv == DECOMP_OK) { - m_freem(m); - if (dmp == NULL) { - /* no error, but no decompressed packet produced */ - return mf; - } - m = dmp; - cp = mtod(m, u_char *); - proto = PPP_PROTOCOL(cp); - - } else { - /* - * An error has occurred in decompression. - * Pass the compressed packet up to pppd, which may take - * CCP down or issue a Reset-Req. - */ - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: decompress failed %d\n", ifp->if_unit, rv); - s = splimp(); - sc->sc_flags |= SC_VJ_RESET; - if (rv == DECOMP_ERROR) - sc->sc_flags |= SC_DC_ERROR; - else - sc->sc_flags |= SC_DC_FERROR; - splx(s); - } - - } else { - if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { - (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); - } - if (proto == PPP_CCP) { - ppp_ccp(sc, m, 1); - } - } -#endif - - ilen = 0; - for (mp = m; mp != NULL; mp = mp->m_next) - ilen += mp->m_len; - -#ifdef VJC - if (sc->sc_flags & SC_VJ_RESET) { - /* - * If we've missed a packet, we must toss subsequent compressed - * packets which don't have an explicit connection ID. - */ - if (sc->sc_comp) - vj_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); - s = splimp(); - sc->sc_flags &= ~SC_VJ_RESET; - splx(s); - } - - /* - * See if we have a VJ-compressed packet to uncompress. - */ - if (proto == PPP_VJC_COMP) { - if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) - goto bad; - - xlen = vj_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, - ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP, - sc->sc_comp, &iphdr, &hlen); - - if (xlen <= 0) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: VJ uncompress failed on type comp\n", - ifp->if_unit); - goto bad; - } - - /* Copy the PPP and IP headers into a new mbuf. */ - MGETHDR(mp, M_DONTWAIT, MT_DATA); - if (mp == NULL) - goto bad; - mp->m_len = 0; - mp->m_next = NULL; - if (hlen + PPP_HDRLEN > MHLEN) { - MCLGET(mp, M_DONTWAIT); - if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) { - m_freem(mp); - goto bad; /* lose if big headers and no clusters */ - } - } - cp = mtod(mp, u_char *); - cp[0] = adrs; - cp[1] = ctrl; - cp[2] = 0; - cp[3] = PPP_IP; - proto = PPP_IP; - bcopy(iphdr, cp + PPP_HDRLEN, hlen); - mp->m_len = hlen + PPP_HDRLEN; - - /* - * Trim the PPP and VJ headers off the old mbuf - * and stick the new and old mbufs together. - */ - m->m_data += PPP_HDRLEN + xlen; - m->m_len -= PPP_HDRLEN + xlen; - if (m->m_len <= M_TRAILINGSPACE(mp)) { - bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len); - mp->m_len += m->m_len; - MFREE(m, mp->m_next); - } else - mp->m_next = m; - m = mp; - ilen += hlen - xlen; - - } else if (proto == PPP_VJC_UNCOMP) { - if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) - goto bad; - - xlen = vj_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, - ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP, - sc->sc_comp, &iphdr, &hlen); - - if (xlen < 0) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: VJ uncompress failed on type uncomp\n", - ifp->if_unit); - goto bad; - } - - proto = PPP_IP; - cp[3] = PPP_IP; - } -#endif /* VJC */ - - /* - * If the packet will fit in a header mbuf, don't waste a - * whole cluster on it. - */ - if (ilen <= MHLEN && M_IS_CLUSTER(m)) { - MGETHDR(mp, M_DONTWAIT, MT_DATA); - if (mp != NULL) { - m_copydata(m, 0, ilen, mtod(mp, caddr_t)); - /* instead of freeing - return cluster mbuf so it can be reused */ - /* m_freem(m); */ - mf = m; - m = mp; - m->m_len = ilen; - } - } - m->m_pkthdr.len = ilen; - m->m_pkthdr.rcvif = ifp; - - if ((proto & 0x8000) == 0) { -#ifdef PPP_FILTER - /* - * See whether we want to pass this packet, and - * if it counts as link activity. - */ - adrs = *mtod(m, u_char *); /* save address field */ - *mtod(m, u_char *) = 0; /* indicate inbound */ - if (sc->sc_pass_filt.bf_insns != 0 - && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m, - ilen, 0) == 0) { - /* drop this packet */ - m_freem(m); - return mf; - } - if (sc->sc_active_filt.bf_insns == 0 - || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m, ilen, 0)) - sc->sc_last_recv = time.tv_sec; - - *mtod(m, u_char *) = adrs; -#else - /* - * Record the time that we received this packet. - */ - microtime(&ppp_time); - sc->sc_last_recv = ppp_time.tv_sec; -#endif /* PPP_FILTER */ - } - -#if NBPFILTER > 0 - /* See if bpf wants to look at the packet. */ - if (sc->sc_bpf) - bpf_mtap(sc->sc_bpf, m); -#endif - - rv = 0; - switch (proto) { -#ifdef INET - case PPP_IP: - /* - * IP packet - take off the ppp header and pass it up to IP. - */ - if ((ifp->if_flags & IFF_UP) == 0 - || sc->sc_npmode[NP_IP] != NPMODE_PASS) { - /* interface is down - drop the packet. */ - m_freem(m); - return mf; - } - m->m_pkthdr.len -= PPP_HDRLEN; - m->m_data += PPP_HDRLEN; - m->m_len -= PPP_HDRLEN; - schednetisr(NETISR_IP); - inq = &ipintrq; - break; -#endif - - default: - /* - * Some other protocol - place on input queue for read(). - */ - inq = &sc->sc_inq; - rv = 1; - break; - } - - /* - * Put the packet on the appropriate input queue. - */ - s = splimp(); - if (IF_QFULL(inq)) { - IF_DROP(inq); - splx(s); - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: input queue full\n", ifp->if_unit); - ifp->if_iqdrops++; - goto bad; - } - IF_ENQUEUE(inq, m); - splx(s); - - ifp->if_ipackets++; - ifp->if_ibytes += ilen; - microtime(&ppp_time); - ifp->if_lastchange = ppp_time; - - if (rv) { - (*sc->sc_ctlp)(sc); - } - - return mf; - - bad: - m_freem(m); - sc->sc_if.if_ierrors++; - sc->sc_stats.ppp_ierrors++; - return mf; -} - -#define MAX_DUMP_BYTES 128 - -static void -pppdumpm(m0) - struct mbuf *m0; -{ - char buf[3*MAX_DUMP_BYTES+4]; - char *bp = buf; - struct mbuf *m; - static char digits[] = "0123456789abcdef"; - - for (m = m0; m; m = m->m_next) { - int l = m->m_len; - u_char *rptr = (u_char *)m->m_data; - - while (l--) { - if (bp > buf + sizeof(buf) - 4) - goto done; - *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */ - *bp++ = digits[*rptr++ & 0xf]; - } - - if (m->m_next) { - if (bp > buf + sizeof(buf) - 3) - goto done; - *bp++ = '|'; - } else - *bp++ = ' '; - } -done: - if (m) - *bp++ = '>'; - *bp = 0; - printf("%s\n", buf); -} - -#endif /* NPPP > 0 */ diff --git a/c/src/exec/libnetworking/net/if_ppp.h b/c/src/exec/libnetworking/net/if_ppp.h deleted file mode 100644 index 355778d9fd..0000000000 --- a/c/src/exec/libnetworking/net/if_ppp.h +++ /dev/null @@ -1,134 +0,0 @@ -/* $Id$ */ - -/* - * if_ppp.h - Point-to-Point Protocol definitions. - * - * Copyright (c) 1989 Carnegie Mellon University. - * 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 Carnegie Mellon University. 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. - */ - -#ifndef _IF_PPP_H_ -#define _IF_PPP_H_ - -/* - * Bit definitions for flags. - */ -#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */ -#define SC_COMP_AC 0x00000002 /* header compression (output) */ -#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */ -#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */ -#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */ -#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */ -#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */ -#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */ -#define SC_DEBUG 0x00010000 /* enable debug messages */ -#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */ -#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ -#define SC_LOG_RAWIN 0x00080000 /* log all chars received */ -#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ -#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ -#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ -#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ -#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */ -#define SC_SYNC 0x00200000 /* use synchronous HDLC framing */ -#define SC_MASK 0x0fff00ff /* bits that user can change */ - -/* - * State bits in sc_flags, not changeable by user. - */ -#define SC_TIMEOUT 0x00000400 /* timeout is currently pending */ -#define SC_VJ_RESET 0x00000800 /* need to reset VJ decomp */ -#define SC_COMP_RUN 0x00001000 /* compressor has been inited */ -#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */ -#define SC_DC_ERROR 0x00004000 /* non-fatal decomp error detected */ -#define SC_DC_FERROR 0x00008000 /* fatal decomp error detected */ -#define SC_TBUSY 0x10000000 /* xmitter doesn't need a packet yet */ -#define SC_PKTLOST 0x20000000 /* have lost or dropped a packet */ -#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */ -#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */ - -/* - * Ioctl definitions. - */ - -struct npioctl { - int protocol; /* PPP procotol, e.g. PPP_IP */ - enum NPmode mode; -}; - -/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */ -struct ppp_option_data { - u_char *ptr; - u_int length; - int transmit; -}; - -struct ifpppstatsreq { - char ifr_name[IFNAMSIZ]; - struct ppp_stats stats; -}; - -struct ifpppcstatsreq { - char ifr_name[IFNAMSIZ]; - struct ppp_comp_stats stats; -}; - -/* - * Ioctl definitions. - */ - -#define PPPIOCSTASK _IOW('t', 91, int) /* set pppd task id */ -#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */ -#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */ -#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */ -#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */ -#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */ -#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */ -#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */ -#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */ -#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */ -#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */ -#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */ -#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */ -#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */ -#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data) -#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */ -#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */ -#define PPPIOCGIDLE _IOR('t', 74, struct ppp_idle) /* get idle time */ -#ifdef PPP_FILTER -#define PPPIOCSPASS _IOW('t', 71, struct bpf_program) /* set pass filter */ -#define PPPIOCSACTIVE _IOW('t', 70, struct bpf_program) /* set active filt */ -#endif /* PPP_FILTER */ - -/* PPPIOC[GS]MTU are alternatives to SIOC[GS]IFMTU, used under Ultrix */ -#define PPPIOCGMTU _IOR('t', 73, int) /* get interface MTU */ -#define PPPIOCSMTU _IOW('t', 72, int) /* set interface MTU */ - -/* - * These two are interface ioctls so that pppstats can do them on - * a socket without having to open the serial device. - */ -#define SIOCGPPPSTATS _IOWR('i', 123, struct ifpppstatsreq) -#define SIOCGPPPCSTATS _IOWR('i', 122, struct ifpppcstatsreq) - -#if !defined(ifr_mtu) -#define ifr_mtu ifr_ifru.ifru_metric -#endif - -#if (defined(_KERNEL) || defined(KERNEL)) && !defined(NeXT) -void pppattach __P((void)); -void pppintr __P((void)); -#endif -#endif /* _IF_PPP_H_ */ diff --git a/c/src/exec/libnetworking/net/if_pppvar.h b/c/src/exec/libnetworking/net/if_pppvar.h deleted file mode 100644 index 2b4cd7d9de..0000000000 --- a/c/src/exec/libnetworking/net/if_pppvar.h +++ /dev/null @@ -1,140 +0,0 @@ -/* $Id$ */ -/* - * if_pppvar.h - private structures and declarations for PPP. - * - * Copyright (c) 1994 The Australian National University. - * 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. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * 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. - * - * Copyright (c) 1989 Carnegie Mellon University. - * 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 Carnegie Mellon University. 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. - */ - -/* - * Supported network protocols. These values are used for - * indexing sc_npmode. - */ -#define NP_IP 0 /* Internet Protocol */ -#define NUM_NP 1 /* Number of NPs. */ -#define NUM_MBUFQ 64 - - -/* - * Structure describing each ppp unit. - */ -struct ppp_softc { - struct ifnet sc_if; /* network-visible interface */ - u_int sc_flags; /* control/status bits; see if_ppp.h */ - void *sc_devp; /* pointer to device-dep structure */ - void (*sc_start) __P((struct ppp_softc *)); /* start output proc */ - void (*sc_ctlp) __P((struct ppp_softc *)); /* rcvd control pkt */ - void (*sc_relinq) __P((struct ppp_softc *)); /* relinquish ifunit */ - short sc_mru; /* max receive unit */ - pid_t sc_xfer; /* used in transferring unit */ - struct ifqueue sc_rawq; /* received packets */ - struct ifqueue sc_inq; /* queue of input packets for daemon */ - struct ifqueue sc_fastq; /* interactive output packet q */ - struct mbuf *sc_npqueue; /* output packets not to be sent yet */ - struct mbuf **sc_npqtail; /* ptr to last next ptr in npqueue */ - struct pppstat sc_stats; /* count of bytes/pkts sent/rcvd */ - caddr_t sc_bpf; /* hook for BPF */ - enum NPmode sc_npmode[NUM_NP]; /* what to do with each NP */ - struct compressor *sc_xcomp; /* transmit compressor */ - void *sc_xc_state; /* transmit compressor state */ - struct compressor *sc_rcomp; /* receive decompressor */ - void *sc_rc_state; /* receive decompressor state */ - time_t sc_last_sent; /* time (secs) last NP pkt sent */ - time_t sc_last_recv; /* time (secs) last NP pkt rcvd */ -#ifdef PPP_FILTER - struct bpf_program sc_pass_filt; /* filter for packets to pass */ - struct bpf_program sc_active_filt; /* filter for "non-idle" packets */ -#endif /* PPP_FILTER */ -#ifdef VJC - struct vjcompress *sc_comp; /* vjc control buffer */ -#endif - - /* Device-dependent part for async lines. */ - ext_accm sc_asyncmap; /* async control character map */ - u_long sc_rasyncmap; /* receive async control char map */ - struct mbuf *sc_outm; /* mbuf chain currently being output */ - struct mbuf *sc_outmc; /* mbuf currently being output */ - struct mbuf *sc_m; /* pointer to input mbuf chain */ - struct mbuf *sc_mc; /* pointer to current input mbuf */ - char *sc_mp; /* ptr to next char in input mbuf */ - short sc_ilen; /* length of input packet so far */ - u_short sc_fcs; /* FCS so far (input) */ - u_char sc_rawin[16]; /* chars as received */ - int sc_rawin_count; /* # in sc_rawin */ - u_short sc_outfcs; /* FCS so far for output packet */ - - struct ifqueue sc_freeq; /* free packets */ - short sc_outoff; /* output packet byte offset */ - short sc_outflag; /* output status flag */ - short sc_outlen; /* length of output packet */ - short sc_outfcslen; /* length of output fcs data */ - u_char sc_outfcsbuf[8]; /* output packet fcs buffer */ - u_char *sc_outbuf; /* pointer to output data */ - u_char sc_outchar; - - rtems_id sc_rxtask; - rtems_id sc_txtask; - rtems_id sc_pppdtask; -}; - -struct ppp_softc ppp_softc[NPPP]; - -struct ppp_softc *pppalloc __P((pid_t pid)); -void pppdealloc __P((struct ppp_softc *sc)); -int pppoutput __P((struct ifnet *, struct mbuf *, - struct sockaddr *, struct rtentry *)); -int pppioctl __P((struct ppp_softc *sc, int cmd, caddr_t data, - int flag, struct proc *p)); -struct mbuf *ppp_dequeue __P((struct ppp_softc *sc)); -u_short pppfcs __P((u_short fcs, u_char *cp, int len)); -void pppallocmbuf __P((struct ppp_softc *sc, struct mbuf **mp)); - - -/* define event values */ -#define RX_PACKET RTEMS_EVENT_1 -#define RX_MBUF RTEMS_EVENT_2 -#define RX_EMPTY RTEMS_EVENT_3 -#define TX_PACKET RTEMS_EVENT_1 -#define TX_TRANSMIT RTEMS_EVENT_2 -#define PPPD_EVENT RTEMS_EVENT_31 - -/* define out flag values */ -#define SC_TX_BUSY 0x0001 -#define SC_TX_FCS 0x0002 -#define SC_TX_ESCAPE 0x0004 -#define SC_TX_PENDING 0x0010 diff --git a/c/src/exec/libnetworking/net/if_types.h b/c/src/exec/libnetworking/net/if_types.h deleted file mode 100644 index 833ba471c3..0000000000 --- a/c/src/exec/libnetworking/net/if_types.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. 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. 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. - * - * @(#)if_types.h 8.2 (Berkeley) 4/20/94 - * $Id$ - */ - -#ifndef _NET_IF_TYPES_H_ -#define _NET_IF_TYPES_H_ - -/* - * Interface types for benefit of parsing media address headers. - * This list is derived from the SNMP list of ifTypes, currently - * documented in RFC1573. - */ - -#define IFT_OTHER 0x1 /* none of the following */ -#define IFT_1822 0x2 /* old-style arpanet imp */ -#define IFT_HDH1822 0x3 /* HDH arpanet imp */ -#define IFT_X25DDN 0x4 /* x25 to imp */ -#define IFT_X25 0x5 /* PDN X25 interface (RFC877) */ -#define IFT_ETHER 0x6 /* Ethernet CSMACD */ -#define IFT_ISO88023 0x7 /* CMSA CD */ -#define IFT_ISO88024 0x8 /* Token Bus */ -#define IFT_ISO88025 0x9 /* Token Ring */ -#define IFT_ISO88026 0xa /* MAN */ -#define IFT_STARLAN 0xb -#define IFT_P10 0xc /* Proteon 10MBit ring */ -#define IFT_P80 0xd /* Proteon 80MBit ring */ -#define IFT_HY 0xe /* Hyperchannel */ -#define IFT_FDDI 0xf -#define IFT_LAPB 0x10 -#define IFT_SDLC 0x11 -#define IFT_T1 0x12 -#define IFT_CEPT 0x13 /* E1 - european T1 */ -#define IFT_ISDNBASIC 0x14 -#define IFT_ISDNPRIMARY 0x15 -#define IFT_PTPSERIAL 0x16 /* Proprietary PTP serial */ -#define IFT_PPP 0x17 /* RFC 1331 */ -#define IFT_LOOP 0x18 /* loopback */ -#define IFT_EON 0x19 /* ISO over IP */ -#define IFT_XETHER 0x1a /* obsolete 3MB experimental ethernet */ -#define IFT_NSIP 0x1b /* XNS over IP */ -#define IFT_SLIP 0x1c /* IP over generic TTY */ -#define IFT_ULTRA 0x1d /* Ultra Technologies */ -#define IFT_DS3 0x1e /* Generic T3 */ -#define IFT_SIP 0x1f /* SMDS */ -#define IFT_FRELAY 0x20 /* Frame Relay DTE only */ -#define IFT_RS232 0x21 -#define IFT_PARA 0x22 /* parallel-port */ -#define IFT_ARCNET 0x23 -#define IFT_ARCNETPLUS 0x24 -#define IFT_ATM 0x25 /* ATM cells */ -#define IFT_MIOX25 0x26 -#define IFT_SONET 0x27 /* SONET or SDH */ -#define IFT_X25PLE 0x28 -#define IFT_ISO88022LLC 0x29 -#define IFT_LOCALTALK 0x2a -#define IFT_SMDSDXI 0x2b -#define IFT_FRELAYDCE 0x2c /* Frame Relay DCE */ -#define IFT_V35 0x2d -#define IFT_HSSI 0x2e -#define IFT_HIPPI 0x2f -#define IFT_MODEM 0x30 /* Generic Modem */ -#define IFT_AAL5 0x31 /* AAL5 over ATM */ -#define IFT_SONETPATH 0x32 -#define IFT_SONETVT 0x33 -#define IFT_SMDSICIP 0x34 /* SMDS InterCarrier Interface */ -#define IFT_PROPVIRTUAL 0x35 /* Proprietary Virtual/internal */ -#define IFT_PROPMUX 0x36 /* Proprietary Multiplexing */ - -#endif diff --git a/c/src/exec/libnetworking/net/netisr.h b/c/src/exec/libnetworking/net/netisr.h deleted file mode 100644 index 73269a4442..0000000000 --- a/c/src/exec/libnetworking/net/netisr.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1989, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)netisr.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NET_NETISR_H_ -#define _NET_NETISR_H_ - -/* - * The networking code runs off software interrupts. - * - * You can switch into the network by doing splnet() and return by splx(). - * The software interrupt level for the network is higher than the software - * level for the clock (so you can enter the network in routines called - * at timeout time). - */ -#if defined(vax) || defined(tahoe) -#define setsoftnet() mtpr(SIRR, 12) -#endif - -/* - * Each ``pup-level-1'' input queue has a bit in a ``netisr'' status - * word which is used to de-multiplex a single software - * interrupt used for scheduling the network code to calls - * on the lowest level routine of each protocol. - */ -#define NETISR_RAW 0 /* same as AF_UNSPEC */ -#define NETISR_IP 2 /* same as AF_INET */ -#define NETISR_IMP 3 /* same as AF_IMPLINK */ -#define NETISR_NS 6 /* same as AF_NS */ -#define NETISR_ISO 7 /* same as AF_ISO */ -#define NETISR_CCITT 10 /* same as AF_CCITT */ -#define NETISR_ATALK 16 /* same as AF_APPLETALK */ -#define NETISR_ARP 18 /* same as AF_LINK */ -#define NETISR_IPX 23 /* same as AF_IPX */ -#define NETISR_ISDN 26 /* same as AF_E164 */ -#define NETISR_PPP 27 /* PPP soft interrupt */ - -#define schednetisr(anisr) rtems_bsdnet_schednetisr(anisr) - -#ifndef LOCORE -#ifdef KERNEL -extern volatile unsigned int netisr; /* scheduling bits for network */ - -typedef void netisr_t(void); - -struct netisrtab { - int nit_num; - netisr_t *nit_isr; -}; - -#define NETISR_SET(num, isr) - -int register_netisr __P((int, netisr_t *)); - -#endif -#endif - -#endif diff --git a/c/src/exec/libnetworking/net/ppp-comp.h b/c/src/exec/libnetworking/net/ppp-comp.h deleted file mode 100644 index aa2f99b6d1..0000000000 --- a/c/src/exec/libnetworking/net/ppp-comp.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * ppp-comp.h - Definitions for doing PPP packet compression. - * - * Copyright (c) 1994 The Australian National University. - * 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. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * 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. - * - * $Id$ - */ - -#ifndef _NET_PPP_COMP_H -#define _NET_PPP_COMP_H - -/* - * The following symbols control whether we include code for - * various compression methods. - */ -#ifndef DO_BSD_COMPRESS -#define DO_BSD_COMPRESS 0 /* by default, include BSD-Compress */ -#endif -#ifndef DO_DEFLATE -#define DO_DEFLATE 0 /* by default, include Deflate */ -#endif -#define DO_PREDICTOR_1 0 -#define DO_PREDICTOR_2 0 - -/* - * Structure giving methods for compression/decompression. - */ -#ifdef PACKETPTR -struct compressor { - int compress_proto; /* CCP compression protocol number */ - - /* Allocate space for a compressor (transmit side) */ - void *(*comp_alloc) __P((u_char *options, int opt_len)); - /* Free space used by a compressor */ - void (*comp_free) __P((void *state)); - /* Initialize a compressor */ - int (*comp_init) __P((void *state, u_char *options, int opt_len, - int unit, int hdrlen, int debug)); - /* Reset a compressor */ - void (*comp_reset) __P((void *state)); - /* Compress a packet */ - int (*compress) __P((void *state, PACKETPTR *mret, - PACKETPTR mp, int orig_len, int max_len)); - /* Return compression statistics */ - void (*comp_stat) __P((void *state, struct compstat *stats)); - - /* Allocate space for a decompressor (receive side) */ - void *(*decomp_alloc) __P((u_char *options, int opt_len)); - /* Free space used by a decompressor */ - void (*decomp_free) __P((void *state)); - /* Initialize a decompressor */ - int (*decomp_init) __P((void *state, u_char *options, int opt_len, - int unit, int hdrlen, int mru, int debug)); - /* Reset a decompressor */ - void (*decomp_reset) __P((void *state)); - /* Decompress a packet. */ - int (*decompress) __P((void *state, PACKETPTR mp, - PACKETPTR *dmpp)); - /* Update state for an incompressible packet received */ - void (*incomp) __P((void *state, PACKETPTR mp)); - /* Return decompression statistics */ - void (*decomp_stat) __P((void *state, struct compstat *stats)); -}; -#endif /* PACKETPTR */ - -/* - * Return values for decompress routine. - * We need to make these distinctions so that we can disable certain - * useful functionality, namely sending a CCP reset-request as a result - * of an error detected after decompression. This is to avoid infringing - * a patent held by Motorola. - * Don't you just lurve software patents. - */ -#define DECOMP_OK 0 /* everything went OK */ -#define DECOMP_ERROR 1 /* error detected before decomp. */ -#define DECOMP_FATALERROR 2 /* error detected after decomp. */ - -/* - * CCP codes. - */ -#define CCP_CONFREQ 1 -#define CCP_CONFACK 2 -#define CCP_TERMREQ 5 -#define CCP_TERMACK 6 -#define CCP_RESETREQ 14 -#define CCP_RESETACK 15 - -/* - * Max # bytes for a CCP option - */ -#define CCP_MAX_OPTION_LENGTH 32 - -/* - * Parts of a CCP packet. - */ -#define CCP_CODE(dp) ((dp)[0]) -#define CCP_ID(dp) ((dp)[1]) -#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3]) -#define CCP_HDRLEN 4 - -#define CCP_OPT_CODE(dp) ((dp)[0]) -#define CCP_OPT_LENGTH(dp) ((dp)[1]) -#define CCP_OPT_MINLEN 2 - -/* - * Definitions for BSD-Compress. - */ -#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */ -#define CILEN_BSD_COMPRESS 3 /* length of config. option */ - -/* Macros for handling the 3rd byte of the BSD-Compress config option. */ -#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */ -#define BSD_VERSION(x) ((x) >> 5) /* version of option format */ -#define BSD_CURRENT_VERSION 1 /* current version number */ -#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n)) - -#define BSD_MIN_BITS 9 /* smallest code size supported */ -#define BSD_MAX_BITS 15 /* largest code size supported */ - -/* - * Definitions for Deflate. - */ -#define CI_DEFLATE 26 /* config option for Deflate */ -#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */ -#define CILEN_DEFLATE 4 /* length of its config option */ - -#define DEFLATE_MIN_SIZE 8 -#define DEFLATE_MAX_SIZE 15 -#define DEFLATE_METHOD_VAL 8 -#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE) -#define DEFLATE_METHOD(x) ((x) & 0x0F) -#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \ - + DEFLATE_METHOD_VAL) -#define DEFLATE_CHK_SEQUENCE 0 - -/* - * Definitions for other, as yet unsupported, compression methods. - */ -#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */ -#define CILEN_PREDICTOR_1 2 /* length of its config option */ -#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */ -#define CILEN_PREDICTOR_2 2 /* length of its config option */ - -#endif /* _NET_PPP_COMP_H */ diff --git a/c/src/exec/libnetworking/net/ppp-deflate.c b/c/src/exec/libnetworking/net/ppp-deflate.c deleted file mode 100644 index 2023735b8b..0000000000 --- a/c/src/exec/libnetworking/net/ppp-deflate.c +++ /dev/null @@ -1,683 +0,0 @@ -/* $Id$ */ - -/* - * 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 mbufs on BSD-derived systems. - * - * Copyright (c) 1994 The Australian National University. - * 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. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * 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. - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <net/ppp_defs.h> -#include <net/zlib.h> - -#define PACKETPTR struct mbuf * -#include <net/ppp-comp.h> - -#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 *zalloc __P((void *, u_int items, u_int size)); -static void zfree __P((void *, void *ptr)); -static void *z_comp_alloc __P((u_char *options, int opt_len)); -static void *z_decomp_alloc __P((u_char *options, int opt_len)); -static void z_comp_free __P((void *state)); -static void z_decomp_free __P((void *state)); -static int z_comp_init __P((void *state, u_char *options, int opt_len, - int unit, int hdrlen, int debug)); -static int z_decomp_init __P((void *state, u_char *options, int opt_len, - int unit, int hdrlen, int mru, int debug)); -static int z_compress __P((void *state, struct mbuf **mret, - struct mbuf *mp, int slen, int maxolen)); -static void z_incomp __P((void *state, struct mbuf *dmsg)); -static int z_decompress __P((void *state, struct mbuf *cmp, - struct mbuf **dmpp)); -static void z_comp_reset __P((void *state)); -static void z_decomp_reset __P((void *state)); -static void z_comp_stats __P((void *state, struct compstat *stats)); - -/* - * Procedures exported to if_ppp.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 = { - 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 */ -}; - -/* - * Space allocation and freeing routines for use by zlib routines. - */ -void * -zalloc(notused, items, size) - void *notused; - u_int items, size; -{ - void *ptr; - - MALLOC(ptr, void *, items * size, M_DEVBUF, M_NOWAIT); - return ptr; -} - -void -zfree(notused, ptr) - void *notused; - void *ptr; -{ - FREE(ptr, M_DEVBUF); -} - -/* - * 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]); - if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) - return NULL; - - MALLOC(state, struct deflate_state *, sizeof(struct deflate_state), - M_DEVBUF, M_NOWAIT); - if (state == NULL) - return NULL; - - state->strm.next_in = NULL; - state->strm.zalloc = zalloc; - state->strm.zfree = zfree; - if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL, - -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) { - FREE(state, M_DEVBUF); - return NULL; - } - - 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, M_DEVBUF); -} - -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); -} - -int -z_compress(arg, mret, mp, orig_len, maxolen) - void *arg; - struct mbuf **mret; /* compressed packet (out) */ - struct mbuf *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; - struct mbuf *m; - - /* - * Check that the protocol is in the range we handle. - */ - rptr = mtod(mp, u_char *); - proto = PPP_PROTOCOL(rptr); - if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) { - *mret = NULL; - return orig_len; - } - - /* Allocate one mbuf initially. */ - if (maxolen > orig_len) - maxolen = orig_len; - MGET(m, M_DONTWAIT, MT_DATA); - *mret = m; - if (m != NULL) { - m->m_len = 0; - if (maxolen + state->hdrlen > MLEN) - MCLGET(m, M_DONTWAIT); - wspace = M_TRAILINGSPACE(m); - if (state->hdrlen + PPP_HDRLEN + 2 < wspace) { - m->m_data += state->hdrlen; - wspace -= state->hdrlen; - } - wptr = mtod(m, u_char *); - - /* - * 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; - wptr = NULL; - wspace = 0; - } - ++state->seqno; - - rptr += (proto > 0xff)? 2: 3; /* skip 1st proto byte if 0 */ - state->strm.next_in = rptr; - state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr; - mp = mp->m_next; - 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 = mtod(mp, u_char *); - state->strm.avail_in = mp->m_len; - mp = mp->m_next; - if (mp == NULL) - flush = Z_PACKET_FLUSH; - } - if (state->strm.avail_out == 0) { - if (m != NULL) { - m->m_len = wspace; - olen += wspace; - MGET(m->m_next, M_DONTWAIT, MT_DATA); - m = m->m_next; - if (m != NULL) { - m->m_len = 0; - if (maxolen - olen > MLEN) - MCLGET(m, M_DONTWAIT); - state->strm.next_out = mtod(m, u_char *); - state->strm.avail_out = wspace = M_TRAILINGSPACE(m); - } - } - if (m == NULL) { - state->strm.next_out = NULL; - state->strm.avail_out = 1000000; - } - } - } - if (m != NULL) - olen += (m->m_len = wspace - state->strm.avail_out); - - /* - * See if we managed to reduce the size of the packet. - * If the compressor just gave us a single zero byte, it means - * the packet was incompressible. - */ - if (m != NULL && olen < orig_len - && !(olen == PPP_HDRLEN + 3 && *wptr == 0)) { - state->stats.comp_bytes += olen; - state->stats.comp_packets++; - } else { - if (*mret != NULL) { - m_freem(*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->inc_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]); - if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) - return NULL; - - MALLOC(state, struct deflate_state *, sizeof(struct deflate_state), - M_DEVBUF, M_NOWAIT); - if (state == NULL) - return NULL; - - state->strm.next_out = NULL; - state->strm.zalloc = zalloc; - state->strm.zfree = zfree; - if (inflateInit2(&state->strm, -w_size) != Z_OK) { - FREE(state, M_DEVBUF); - return NULL; - } - - 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, M_DEVBUF); -} - -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. - */ -int -z_decompress(arg, mi, mop) - void *arg; - struct mbuf *mi, **mop; -{ - struct deflate_state *state = (struct deflate_state *) arg; - struct mbuf *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 = mtod(mi, u_char *); - rlen = mi->m_len; - for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) { - while (rlen <= 0) { - mi = mi->m_next; - if (mi == NULL) - return DECOMP_ERROR; - rptr = mtod(mi, u_char *); - rlen = mi->m_len; - } - hdr[i] = *rptr++; - --rlen; - } - - /* Check the sequence number. */ - seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1]; - if (seq != state->seqno) { - if (state->debug) - printf("z_decompress%d: bad seq # %d, expected %d\n", - state->unit, seq, state->seqno); - return DECOMP_ERROR; - } - ++state->seqno; - - /* Allocate an output mbuf. */ - MGETHDR(mo, M_DONTWAIT, MT_DATA); - if (mo == NULL) - return DECOMP_ERROR; - mo_head = mo; - mo->m_len = 0; - mo->m_next = NULL; - MCLGET(mo, M_DONTWAIT); - ospace = M_TRAILINGSPACE(mo); - if (state->hdrlen + PPP_HDRLEN < ospace) { - mo->m_data += state->hdrlen; - ospace -= state->hdrlen; - } - - /* - * Fill in the first part of the PPP header. The protocol field - * comes from the decompressed data. - */ - wptr = mtod(mo, u_char *); - 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 = rlen; - mi = mi->m_next; - flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH; - rlen += PPP_HDRLEN + DEFLATE_OVHD; - state->strm.next_out = wptr + 3; - state->strm.avail_out = 1; - decode_proto = 1; - olen = PPP_HDRLEN; - - /* - * 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: "")); - m_freem(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 = mtod(mi, u_char *); - state->strm.avail_in = mi->m_len; - rlen += mi->m_len; - mi = mi->m_next; - 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; - --olen; - } - decode_proto = 0; - } else { - mo->m_len = ospace; - olen += ospace; - MGET(mo->m_next, M_DONTWAIT, MT_DATA); - mo = mo->m_next; - if (mo == NULL) { - m_freem(mo_head); - return DECOMP_ERROR; - } - MCLGET(mo, M_DONTWAIT); - state->strm.next_out = mtod(mo, u_char *); - state->strm.avail_out = ospace = M_TRAILINGSPACE(mo); - } - } - } - if (decode_proto) { - m_freem(mo_head); - return DECOMP_ERROR; - } - olen += (mo->m_len = 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; - struct mbuf *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 = mtod(mi, u_char *); - proto = PPP_PROTOCOL(rptr); - if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) - return; - - ++state->seqno; - - /* - * Iterate through the mbufs, adding the characters in them - * to the decompressor's history. For the first mbuf, we start - * at the either the 1st or 2nd byte of the protocol field, - * depending on whether the protocol value is compressible. - */ - rlen = mi->m_len; - 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->m_next; - if (mi == NULL) - break; - state->strm.next_in = mtod(mi, u_char *); - state->strm.avail_in = mi->m_len; - rlen += mi->m_len; - } - - /* - * Update stats. - */ - state->stats.inc_bytes += rlen; - state->stats.inc_packets++; - state->stats.unc_bytes += rlen; - state->stats.unc_packets++; -} - -#endif /* DO_DEFLATE */ diff --git a/c/src/exec/libnetworking/net/ppp.h b/c/src/exec/libnetworking/net/ppp.h deleted file mode 100644 index 477916dead..0000000000 --- a/c/src/exec/libnetworking/net/ppp.h +++ /dev/null @@ -1,12 +0,0 @@ - -#ifndef _PPP_H_ -#define _PPP_H_ - -#define NPPP 1 -#define NBPFILTER 0 -#undef VJC -#undef PPP_FILTER -#undef PPP_COMPRESS - -#endif - diff --git a/c/src/exec/libnetworking/net/ppp_defs.h b/c/src/exec/libnetworking/net/ppp_defs.h deleted file mode 100644 index c8367c1998..0000000000 --- a/c/src/exec/libnetworking/net/ppp_defs.h +++ /dev/null @@ -1,184 +0,0 @@ -/* $Id$ */ - -/* - * ppp_defs.h - PPP definitions. - * - * Copyright (c) 1994 The Australian National University. - * 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. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * 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. - */ - -#ifndef _PPP_DEFS_H_ -#define _PPP_DEFS_H_ - -/* - * The basic PPP frame. - */ -#define PPP_HDRLEN 4 /* octets for standard ppp header */ -#define PPP_FCSLEN 2 /* octets for FCS */ - -/* - * Packet sizes - * - * Note - lcp shouldn't be allowed to negotiate stuff outside these - * limits. See lcp.h in the pppd directory. - * (XXX - these constants should simply be shared by lcp.c instead - * of living in lcp.h) - */ -#define PPP_MTU 1500 /* Default MTU (size of Info field) */ -#define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) -#define PPP_MINMTU 64 -#define PPP_MRU 1500 /* default MRU = max length of info field */ -#define PPP_MAXMRU 65000 /* Largest MRU we allow */ -#define PPP_MINMRU 128 - -#define PPP_ADDRESS(p) (((u_char *)(p))[0]) -#define PPP_CONTROL(p) (((u_char *)(p))[1]) -#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) - -/* - * Significant octet values. - */ -#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ -#define PPP_UI 0x03 /* Unnumbered Information */ -#define PPP_FLAG 0x7e /* Flag Sequence */ -#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ -#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ - -/* - * Protocol field values. - */ -#define PPP_IP 0x21 /* Internet Protocol */ -#define PPP_AT 0x29 /* AppleTalk Protocol */ -#define PPP_IPX 0x2b /* IPX protocol */ -#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ -#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ -#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ -#define PPP_COMP 0xfd /* compressed packet */ -#define PPP_IPCP 0x8021 /* IP Control Protocol */ -#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ -#define PPP_IPXCP 0x802b /* IPX Control Protocol */ -#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ -#define PPP_CCP 0x80fd /* Compression Control Protocol */ -#define PPP_LCP 0xc021 /* Link Control Protocol */ -#define PPP_PAP 0xc023 /* Password Authentication Protocol */ -#define PPP_LQR 0xc025 /* Link Quality Report protocol */ -#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ -#define PPP_CBCP 0xc029 /* Callback Control Protocol */ - -/* - * Values for FCS calculations. - */ -#define PPP_INITFCS 0xffff /* Initial FCS value */ -#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ -#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) - -/* - * A 32-bit unsigned integral type. - */ - -#if !defined(__BIT_TYPES_DEFINED__) && !defined(_BITYPES) \ - && !defined(__FreeBSD__) && (NS_TARGET < 40) -#ifdef UINT32_T -typedef UINT32_T u_int32_t; -#else -/*typedef unsigned int u_int32_t;*/ -/*typedef unsigned short u_int16_t;*/ -#endif -#endif - -/* - * Extended asyncmap - allows any character to be escaped. - */ -typedef u_int32_t ext_accm[8]; - -/* - * What to do with network protocol (NP) packets. - */ -enum NPmode { - NPMODE_PASS, /* pass the packet through */ - NPMODE_DROP, /* silently drop the packet */ - NPMODE_ERROR, /* return an error */ - NPMODE_QUEUE /* save it up for later. */ -}; - -/* - * Statistics. - */ -struct pppstat { - unsigned int ppp_ibytes; /* bytes received */ - unsigned int ppp_ipackets; /* packets received */ - unsigned int ppp_ierrors; /* receive errors */ - unsigned int ppp_obytes; /* bytes sent */ - unsigned int ppp_opackets; /* packets sent */ - unsigned int ppp_oerrors; /* transmit errors */ -}; - -struct vjstat { - unsigned int vjs_packets; /* outbound packets */ - unsigned int vjs_compressed; /* outbound compressed packets */ - unsigned int vjs_searches; /* searches for connection state */ - unsigned int vjs_misses; /* times couldn't find conn. state */ - unsigned int vjs_uncompressedin; /* inbound uncompressed packets */ - unsigned int vjs_compressedin; /* inbound compressed packets */ - unsigned int vjs_errorin; /* inbound unknown type packets */ - unsigned int vjs_tossed; /* inbound packets tossed because of error */ -}; - -struct ppp_stats { - struct pppstat p; /* basic PPP statistics */ - struct vjstat vj; /* VJ header compression statistics */ -}; - -struct compstat { - unsigned int unc_bytes; /* total uncompressed bytes */ - unsigned int unc_packets; /* total uncompressed packets */ - unsigned int comp_bytes; /* compressed bytes */ - unsigned int comp_packets; /* compressed packets */ - unsigned int inc_bytes; /* incompressible bytes */ - unsigned int inc_packets; /* incompressible packets */ - unsigned int ratio; /* recent compression ratio << 8 */ -}; - -struct ppp_comp_stats { - struct compstat c; /* packet compression statistics */ - struct compstat d; /* packet decompression statistics */ -}; - -/* - * The following structure records the time in seconds since - * the last NP packet was sent or received. - */ -struct ppp_idle { - time_t xmit_idle; /* time since last NP packet sent */ - time_t recv_idle; /* time since last NP packet received */ -}; - -#ifndef __P -#ifdef __STDC__ -#define __P(x) x -#else -#define __P(x) () -#endif -#endif - -#endif /* _PPP_DEFS_H_ */ diff --git a/c/src/exec/libnetworking/net/ppp_tty.c b/c/src/exec/libnetworking/net/ppp_tty.c deleted file mode 100644 index 060bd3976c..0000000000 --- a/c/src/exec/libnetworking/net/ppp_tty.c +++ /dev/null @@ -1,945 +0,0 @@ -/* - * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous - * tty devices. - * - * Copyright (c) 1989 Carnegie Mellon University. - * 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 Carnegie Mellon University. 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. - * - * Drew D. Perkins - * Carnegie Mellon University - * 4910 Forbes Ave. - * Pittsburgh, PA 15213 - * (412) 268-8576 - * ddp@andrew.cmu.edu - * - * Based on: - * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 - * - * Copyright (c) 1987 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. - * - * Serial Line interface - * - * Rick Adams - * Center for Seismic Studies - * 1300 N 17th Street, Suite 1450 - * Arlington, Virginia 22209 - * (703)276-7900 - * rick@seismo.ARPA - * seismo!rick - * - * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). - * Converted to 4.3BSD Beta by Chris Torek. - * Other changes made at Berkeley, based in part on code by Kirk Smith. - * - * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) - * Added VJ tcp header compression; more unified ioctls - * - * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). - * Cleaned up a lot of the mbuf-related code to fix bugs that - * caused system crashes and packet corruption. Changed pppstart - * so that it doesn't just give up with a "collision" if the whole - * packet doesn't fit in the output ring buffer. - * - * Added priority queueing for interactive IP packets, following - * the model of if_sl.c, plus hooks for bpf. - * Paul Mackerras (paulus@cs.anu.edu.au). - */ - -/* $Id$ */ -/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ -/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ - -#include "ppp.h" -#if NPPP > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/file.h> -#include <sys/kernel.h> - -#include <net/if.h> -#include <net/if_types.h> - -#ifdef VJC -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <net/pppcompress.h> -#endif - -#include <rtems.h> -#include <rtems/libio.h> -#include <sys/ttycom.h> -#include <termios.h> -#include <rtems/termiostypes.h> - -#ifdef PPP_FILTER -#include <net/bpf.h> -#endif -#include <net/ppp_defs.h> -#include <net/if_ppp.h> -#include <net/if_pppvar.h> - - -void pppasyncattach __P((void)); -int pppopen __P((struct rtems_termios_tty *tty)); -int pppclose __P((struct rtems_termios_tty *tty)); -int pppread __P((struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args)); -int pppwrite __P((struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args)); -int ppptioctl __P((struct rtems_termios_tty *tty, rtems_libio_ioctl_args_t *args)); -int pppinput __P((int c, struct rtems_termios_tty *tty)); -int pppstart __P((struct rtems_termios_tty *tp)); -u_short pppfcs __P((u_short fcs, u_char *cp, int len)); -void pppallocmbuf __P((struct ppp_softc *sc, struct mbuf **mp)); - -static void pppasyncstart __P((struct ppp_softc *)); -static void pppasyncctlp __P((struct ppp_softc *)); -static void pppasyncrelinq __P((struct ppp_softc *)); -/*static void ppp_timeout __P((void *)); */ -/*static void pppdumpb __P((u_char *b, int l)); */ -/*static void ppplogchar __P((struct ppp_softc *, int)); */ - -/* - * Some useful mbuf macros not in mbuf.h. - */ -#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT) - -#define M_DATASTART(m) \ - (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \ - (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) - -#define M_DATASIZE(m) \ - (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \ - (m)->m_flags & M_PKTHDR ? MHLEN: MLEN) - -/* - * We steal two bits in the mbuf m_flags, to mark high-priority packets - * for output, and received packets following lost/corrupted packets. - */ -#define M_HIGHPRI 0x2000 /* output packet for sc_fastq */ -#define M_ERRMARK 0x4000 /* steal a bit in mbuf m_flags */ - -/* - * Does c need to be escaped? - */ -#define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F))) - -/* - * Procedures for using an async tty interface for PPP. - */ - -/* This is a FreeBSD-2.0 kernel. */ -#define CCOUNT(rb) (((rb).Size+(rb).Head-(rb).Tail) % (rb).Size) -#define FCOUNT(rb) ((rb).Size-CCOUNT(rb)-1) -#define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */ -#define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */ - -/* - * Define the PPP line discipline. - */ - -static struct linesw pppdisc = { - pppopen, pppclose, pppread, pppwrite, - pppinput, pppstart, ppptioctl, NULL -}; - -void -pppasyncattach() -{ - linesw[PPPDISC] = pppdisc; -} - -TEXT_SET(pseudo_set, pppasyncattach); - -/* - * Line specific open routine for async tty devices. - * Attach the given tty to the first available ppp unit. - * Called from device open routine or ttioctl. - */ -/* ARGSUSED */ -int -pppopen(struct rtems_termios_tty *tty) -{ - int i; - register struct ppp_softc *sc; - struct mbuf *m = (struct mbuf *)0; - extern int termios_baud_to_number(int); - - if (tty->t_line == PPPDISC) { - sc = (struct ppp_softc *)tty->t_sc; - if (sc != NULL && sc->sc_devp == (void *)tty) { - return (0); - } - } - - if ((sc = pppalloc(1)) == NULL) { - return ENXIO; - } - - if (sc->sc_relinq) - (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */ - - sc->sc_ilen = 0; - sc->sc_m = NULL; - bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); - sc->sc_asyncmap[0] = 0xffffffff; - sc->sc_asyncmap[3] = 0x60000000; - sc->sc_rasyncmap = 0; - sc->sc_devp = tty; - sc->sc_start = pppasyncstart; - sc->sc_ctlp = pppasyncctlp; - sc->sc_relinq = pppasyncrelinq; - sc->sc_outm = NULL; - sc->sc_outmc = NULL; - - /* preallocate mbufs for free queue */ - rtems_bsdnet_semaphore_obtain(); - for (i=0; i<NUM_MBUFQ; i++) { - pppallocmbuf(sc, &m); - if ( i == 0 ) { - /* use first mbuf for rx iterrupt handling */ - sc->sc_m = m; - } - else { - /* enqueue mbuf for later use */ - IF_ENQUEUE(&sc->sc_freeq, m); - } - m = (struct mbuf *)0; - } - rtems_bsdnet_semaphore_release(); - - /* initialize values */ - sc->sc_if.if_flags |= IFF_RUNNING; - sc->sc_if.if_baudrate = - termios_baud_to_number(tty->termios.c_cflag & CBAUD); - - tty->t_sc = (void *)sc; - - return ( RTEMS_SUCCESSFUL ); -} - -/* - * Line specific close routine, called from device close routine - * and from ttioctl. - * Detach the tty from the ppp unit. - * Mimics part of ttyclose(). - */ -int -pppclose(struct rtems_termios_tty *tty) -{ - register struct ppp_softc *sc; - - tty->t_line = 0; - sc = (struct ppp_softc *)tty->t_sc; - if (sc != NULL) { - tty->t_sc = NULL; - if (tty == (struct rtems_termios_tty *)sc->sc_devp) { - rtems_bsdnet_semaphore_obtain(); - pppasyncrelinq(sc); - pppdealloc(sc); - rtems_bsdnet_semaphore_release(); - } - } - return ( RTEMS_SUCCESSFUL ); -} - -/* - * Relinquish the interface unit to another device. - */ -static void -pppasyncrelinq(sc) - struct ppp_softc *sc; -{ -#ifdef XXX_XXX - if (sc->sc_outm) { - m_freem(sc->sc_outm); - sc->sc_outm = NULL; - } - if (sc->sc_m) { - m_freem(sc->sc_m); - sc->sc_m = NULL; - } - if (sc->sc_flags & SC_TIMEOUT) { - untimeout(ppp_timeout, (void *) sc); - sc->sc_flags &= ~SC_TIMEOUT; - } -#endif -} - -/* - * Line specific (tty) read routine. - */ -int -pppread(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args) -{ - rtems_status_code status = RTEMS_UNSATISFIED; - int count = 0; - int maximum = rw_args->count; - char *buffer = rw_args->buffer; - register struct ppp_softc *sc = (struct ppp_softc *)tty->t_sc; - struct mbuf *m; - struct mbuf *m0; - u_char *p; - - if (sc == NULL) { - return 0; - } - - /* - * Loop waiting for input, checking that nothing disasterous - * happens in the meantime. - */ - if (tty != (struct rtems_termios_tty *)sc->sc_devp || tty->t_line != PPPDISC) { - return ( status ); - } - if (sc->sc_inq.ifq_head == NULL) { - return ( status ); - } - - /* Get the packet from the input queue */ - rtems_bsdnet_semaphore_obtain(); - IF_DEQUEUE(&sc->sc_inq, m0); - - /* loop over mbuf chain */ - m = m0; - while (( m != NULL ) && ( m->m_len > 0 ) && ( count+m->m_len < maximum )) { - /* copy data into buffer */ - p = mtod(m, u_char *); - memcpy(buffer, p, m->m_len); - memset(p, 0, m->m_len); - count += m->m_len; - buffer += m->m_len; - - /* increment loop index */ - m = m->m_next; - } - - /* free mbuf chain */ - m_freem(m0); - rtems_bsdnet_semaphore_release(); - - /* update return values */ - rw_args->bytes_moved = count; - if ( count >= 0 ) { - status = RTEMS_SUCCESSFUL; - } - - /* check to see if queue is empty */ - if (sc->sc_inq.ifq_head != NULL) { - /* queue is not empty - post another event to ourself */ - rtems_event_send(sc->sc_pppdtask, PPPD_EVENT); - } - - return ( status ); -} - -/* - * Line specific (tty) write routine. - */ -int -pppwrite(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args) -{ - struct sockaddr dst; - int n; - int len; - int maximum = rw_args->count; - char *out_buffer = rw_args->buffer; - register struct ppp_softc *sc = (struct ppp_softc *)tty->t_sc; - struct mbuf *m; - struct mbuf *m0; - struct mbuf **mp; - - rtems_bsdnet_semaphore_obtain(); - for (mp = &m0; maximum; mp = &m->m_next) { - MGET(m, M_WAIT, MT_DATA); - if ((*mp = m) == NULL) { - m_freem(m0); - return (ENOBUFS); - } - m->m_len = 0; - if (maximum >= MCLBYTES / 2) { - MCLGET(m, M_DONTWAIT); - } - len = M_TRAILINGSPACE(m); - if (len > maximum) { - memcpy(mtod(m, u_char *),out_buffer,maximum); - m->m_len = maximum; - maximum = 0; - } - else { - memcpy(mtod(m, u_char *),out_buffer,len); - m->m_len = len; - maximum -= len; - out_buffer += len; - } - } - - dst.sa_family = AF_UNSPEC; - bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN); - m0->m_data += PPP_HDRLEN; - m0->m_len -= PPP_HDRLEN; - - n = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0); - rtems_bsdnet_semaphore_release(); - - return ( n ); -} - -/* - * Line specific (tty) ioctl routine. - * This discipline requires that tty device drivers call - * the line specific l_ioctl routine from their ioctl routines. - */ -/* ARGSUSED */ -int -ppptioctl(struct rtems_termios_tty *tty, rtems_libio_ioctl_args_t *args) -{ -/* int i; */ - int error = RTEMS_SUCCESSFUL; - int cmd = args->command; - caddr_t data = args->buffer; - struct ppp_softc *sc = tty->t_sc; - - switch (cmd) { - case RTEMS_IO_GET_ATTRIBUTES: - case RTEMS_IO_SET_ATTRIBUTES: - case RTEMS_IO_TCDRAIN: - case RTEMS_IO_SNDWAKEUP: - case RTEMS_IO_RCVWAKEUP: - case TIOCGETD: - case TIOCSETD: - error = rtems_termios_ioctl(args); - break; - - case PPPIOCSASYNCMAP: - sc->sc_asyncmap[0] = *(u_int *)data; - break; - - case PPPIOCGASYNCMAP: - *(u_int *)data = sc->sc_asyncmap[0]; - break; - - case PPPIOCSRASYNCMAP: - sc->sc_rasyncmap = *(u_int *)data; - break; - - case PPPIOCGRASYNCMAP: - *(u_int *)data = sc->sc_rasyncmap; - break; - - case PPPIOCSXASYNCMAP: - bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); - sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */ - sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */ - sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */ - break; - - case PPPIOCGXASYNCMAP: - bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap)); - break; - - default: - rtems_bsdnet_semaphore_obtain(); - error = pppioctl(sc, cmd, data, 0, NULL); - rtems_bsdnet_semaphore_release(); - } - return error; -} - -/* - * 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 -}; - -/* - * Calculate a new FCS given the current FCS and the new data. - */ -u_short -pppfcs(u_short fcs, u_char *cp, int len) -{ - while (len--) - fcs = PPP_FCS(fcs, *cp++); - return (fcs); -} - -/* - * This gets called at splsoftnet from if_ppp.c at various times - * when there is data ready to be sent. - */ -void pppasyncstart(struct ppp_softc *sc) -{ - /* check to see if output is not active */ - if ( sc->sc_outflag == 0 ) { - /* mark active and post tx event to daemon */ - sc->sc_outflag |= SC_TX_PENDING; - rtems_event_send(sc->sc_txtask, TX_PACKET); - } -} - -/* - * This gets called when a received packet is placed on - * the inq, at splsoftnet. - */ -static void -pppasyncctlp(sc) - struct ppp_softc *sc; -{ - /* check to see if task id was set */ - if ( sc->sc_pppdtask != 0 ) { - /* post event to daemon */ - rtems_event_send(sc->sc_pppdtask, PPPD_EVENT); - } -} - -/* - * Start output on async tty interface. If the transmit queue - * has drained sufficiently, arrange for pppasyncstart to be - * called later at splsoftnet. - * Called at spltty or higher. - */ -int -pppstart(struct rtems_termios_tty *tp) -{ - char *sendBegin; - u_long ioffset = (u_long )0; - struct mbuf *m = (struct mbuf *)0; - struct ppp_softc *sc = tp->t_sc; - - /* ensure input is valid and we are busy */ - if (( sc != NULL ) && ( sc->sc_outflag & SC_TX_BUSY )) { - /* check to see if we need to get the next buffer */ - if ( sc->sc_outoff >= sc->sc_outlen ) { - /* loop to get next non-zero length buffer */ - if ( sc->sc_outmc != NULL ) { - m = sc->sc_outmc->m_next; - } - - /* check for next mbuf in chain */ - if ( m != NULL ) { - /* update values to use this mbuf */ - sc->sc_outmc = m; - sc->sc_outbuf = mtod(m, u_char *); - sc->sc_outlen = m->m_len; - sc->sc_outoff = (short)0; - } - else if ( (sc->sc_outflag & SC_TX_FCS) == 0 ) { - /* setup to use FCS buffer */ - sc->sc_outflag |= SC_TX_FCS; - sc->sc_outbuf = sc->sc_outfcsbuf; - sc->sc_outlen = sc->sc_outfcslen; - sc->sc_outoff = (short)0; - } - else { - /* done with this packet */ - sc->sc_outflag &= ~SC_TX_BUSY; - sc->sc_outchar = (u_char)PPP_FLAG; - (*tp->device.write)(tp->minor, &sc->sc_outchar, 1); - rtems_event_send(sc->sc_txtask, TX_TRANSMIT); - } - } - - /* check to see if there is some data to write out */ - if ( sc->sc_outoff < sc->sc_outlen ) { - /* check to see if character needs to be escaped */ - sc->sc_outchar = sc->sc_outbuf[sc->sc_outoff]; - if ( ESCAPE_P(sc->sc_outchar) ) { - if ( sc->sc_outflag & SC_TX_ESCAPE ) { - /* last sent character was the escape character */ - sc->sc_outchar = sc->sc_outchar ^ PPP_TRANS; - - /* clear the escape flag and increment the offset */ - sc->sc_outflag &= ~SC_TX_ESCAPE; - ioffset++; - } - else { - /* need to send the escape character */ - sc->sc_outchar = PPP_ESCAPE; - - /* set the escape flag */ - sc->sc_outflag |= SC_TX_ESCAPE; - } - sendBegin = &sc->sc_outchar; - } - else { - /* escape not needed - increment the offset as much as possible */ - while ((!ESCAPE_P(sc->sc_outchar)) && ((sc->sc_outoff + ioffset) < sc->sc_outlen)) { - ioffset++; - sc->sc_outchar = sc->sc_outbuf[sc->sc_outoff + ioffset]; - } - sendBegin = &sc->sc_outbuf[sc->sc_outoff]; - } - - /* write out the character(s) and update the stats */ - (*tp->device.write)(tp->minor, sendBegin, (ioffset > 0) ? ioffset : 1); - sc->sc_stats.ppp_obytes += (ioffset > 0) ? ioffset : 1; - sc->sc_outoff += ioffset; - } - } - - return ( 0 ); -} - -#ifdef XXX_XXX -/* - * Timeout routine - try to start some more output. - */ -static void -ppp_timeout(x) - void *x; -{ - struct rtems_termios_tty *tty = (struct rtems_termios_tty *)x; - struct ppp_softc *sc = tty->t_sc; -/* struct rtems_termios_tty *tp = (struct rtems_termios_tty *)sc->sc_devp; */ - - sc->sc_flags &= ~SC_TIMEOUT; -/* pppstart(tp); */ -} -#endif - -/* - * Allocate enough mbuf to handle current MRU. - */ -#ifdef XXX_XXX -static void -pppgetm(sc) - register struct ppp_softc *sc; -{ - struct mbuf *m, **mp; - int len; - - mp = &sc->sc_m; - for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){ - if ((m = *mp) == NULL) { - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) - break; - *mp = m; - MCLGET(m, M_DONTWAIT); - } - len -= M_DATASIZE(m); - mp = &m->m_next; - } -} -#endif - -void -pppallocmbuf(struct ppp_softc *sc, struct mbuf **mp) -{ - int ilen; - struct mbuf *m; - - /* loop over length value */ - ilen = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; - while ( ilen > 0 ) { - /* see if this is end of the chain */ - m = *mp; - if ( m == NULL ) { - /* get mbuf header */ - MGETHDR(m, M_DONTWAIT, MT_DATA); - if ( m == NULL ) { - /* error - set condition to break out */ - printf("pppallocmbuf: MGETHDR failed\n"); - break; - } - MCLGET(m, M_DONTWAIT); - m->m_next = NULL; - *mp = m; - } - - /* update loop variables */ - mp = &m->m_next; - ilen -= M_DATASIZE(m); - } -} - -/* - * tty interface receiver interrupt. - */ -static unsigned paritytab[8] = { - 0x96696996, 0x69969669, 0x69969669, 0x96696996, - 0x69969669, 0x96696996, 0x96696996, 0x69969669 -}; - -int -pppinput(int c, struct rtems_termios_tty *tp) -{ - register struct ppp_softc *sc = tp->t_sc; - struct mbuf *m; - int ilen; - - if (sc == NULL || tp != (struct rtems_termios_tty *)sc->sc_devp) - return 0; - if (sc->sc_m == NULL) { - rtems_event_send(sc->sc_rxtask, RX_EMPTY); - IF_DEQUEUE(&sc->sc_freeq, sc->sc_m); - if ( sc->sc_m == NULL ) { - return 0; - } - } - - ++sc->sc_stats.ppp_ibytes; - - c &= 0xff; - if (c & 0x80) - sc->sc_flags |= SC_RCV_B7_1; - else - sc->sc_flags |= SC_RCV_B7_0; - if (paritytab[c >> 5] & (1 << (c & 0x1F))) - sc->sc_flags |= SC_RCV_ODDP; - else - sc->sc_flags |= SC_RCV_EVNP; - - if (c == PPP_FLAG) { - ilen = sc->sc_ilen; - sc->sc_ilen = 0; - - /* - * If SC_ESCAPED is set, then we've seen the packet - * abort sequence "}~". - */ - if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED) - || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) { - sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */ - if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){ - /* bad fcs error */ - sc->sc_if.if_ierrors++; - sc->sc_stats.ppp_ierrors++; - } else - sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED); - return 0; - } - - if (ilen < PPP_HDRLEN + PPP_FCSLEN) { - if (ilen) { - /* too short error */ - sc->sc_if.if_ierrors++; - sc->sc_stats.ppp_ierrors++; - sc->sc_flags |= SC_PKTLOST; - } - return 0; - } - - /* Remove FCS trailer. Somewhat painful... */ - ilen -= 2; - if (--sc->sc_mc->m_len == 0) { - for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next); - sc->sc_mc = m; - } - sc->sc_mc->m_len--; - - /* excise this mbuf chain - place on raw queue */ - m = sc->sc_m; - if ( sc->sc_flags & SC_PKTLOST ) { - m->m_flags |= M_ERRMARK; - sc->sc_flags &= ~SC_PKTLOST; - } - IF_ENQUEUE(&sc->sc_rawq, m); - - /* setup next mbuf chain */ - IF_DEQUEUE(&sc->sc_freeq, sc->sc_m); - - /* send rx packet event */ - rtems_event_send(sc->sc_rxtask, RX_PACKET); - return 0; - } - - if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) - return 0; - - if (sc->sc_flags & SC_ESCAPED) { - sc->sc_flags &= ~SC_ESCAPED; - c ^= PPP_TRANS; - } else if (c == PPP_ESCAPE) { - sc->sc_flags |= SC_ESCAPED; - return 0; - } - - /* - * Initialize buffer on first octet received. - * First octet could be address or protocol (when compressing - * address/control). - * Second octet is control. - * Third octet is first or second (when compressing protocol) - * octet of protocol. - * Fourth octet is second octet of protocol. - */ - if (sc->sc_ilen == 0) { - m = sc->sc_m; - m->m_len = 0; - m->m_data = M_DATASTART(sc->sc_m); - sc->sc_mc = m; - sc->sc_mp = mtod(m, char *); - sc->sc_fcs = PPP_INITFCS; - if (c != PPP_ALLSTATIONS) { - if (sc->sc_flags & SC_REJ_COMP_AC) { - /* garbage received error */ - goto flush; - } - *sc->sc_mp++ = PPP_ALLSTATIONS; - *sc->sc_mp++ = PPP_UI; - sc->sc_ilen += 2; - m->m_len += 2; - } - } - if (sc->sc_ilen == 1 && c != PPP_UI) { - /* missing UI error */ - goto flush; - } - if (sc->sc_ilen == 2 && (c & 1) == 1) { - /* a compressed protocol */ - *sc->sc_mp++ = 0; - sc->sc_ilen++; - sc->sc_mc->m_len++; - } - if (sc->sc_ilen == 3 && (c & 1) == 0) { - /* bad protocol error */ - goto flush; - } - - /* packet beyond configured mru? */ - if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) { - /* packet too big error */ - goto flush; - } - - /* is this mbuf full? */ - m = sc->sc_mc; - if (M_TRAILINGSPACE(m) <= 0) { - if (m->m_next == NULL) { - /* get next available mbuf for the chain */ - IF_DEQUEUE(&sc->sc_freeq, m->m_next); - if (m->m_next == NULL) { - /* too few mbufs */ - goto flush; - } - else { - /* send rx mbuf event */ - rtems_event_send(sc->sc_rxtask, RX_MBUF); - } - } - sc->sc_mc = m = m->m_next; - m->m_len = 0; - m->m_next = 0; - m->m_data = M_DATASTART(m); - sc->sc_mp = mtod(m, char *); - } - - ++m->m_len; - *sc->sc_mp++ = c; - sc->sc_fcs = PPP_FCS(sc->sc_fcs, c); - return 0; - - flush: - if (!(sc->sc_flags & SC_FLUSH)) { - sc->sc_if.if_ierrors++; - sc->sc_stats.ppp_ierrors++; - sc->sc_flags |= SC_FLUSH; - } - return 0; -} - -#ifdef XXX_XXX -#define MAX_DUMP_BYTES 128 - -static void -ppplogchar(sc, c) - struct ppp_softc *sc; - int c; -{ - if (c >= 0) - sc->sc_rawin[sc->sc_rawin_count++] = c; - if (sc->sc_rawin_count >= sizeof(sc->sc_rawin) - || (c < 0 && sc->sc_rawin_count > 0)) { - printf("ppp%d input: ", sc->sc_if.if_unit); - pppdumpb(sc->sc_rawin, sc->sc_rawin_count); - sc->sc_rawin_count = 0; - } -} - -static void -pppdumpb(b, l) - u_char *b; - int l; -{ - char buf[3*MAX_DUMP_BYTES+4]; - char *bp = buf; - static char digits[] = "0123456789abcdef"; - - while (l--) { - if (bp >= buf + sizeof(buf) - 3) { - *bp++ = '>'; - break; - } - *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */ - *bp++ = digits[*b++ & 0xf]; - *bp++ = ' '; - } - - *bp = 0; - printf("%s\n", buf); -} -#endif - -#endif /* NPPP > 0 */ diff --git a/c/src/exec/libnetworking/net/pppcompress.c b/c/src/exec/libnetworking/net/pppcompress.c deleted file mode 100644 index aebe441fd3..0000000000 --- a/c/src/exec/libnetworking/net/pppcompress.c +++ /dev/null @@ -1,593 +0,0 @@ -/*- - * Copyright (c) 1989 The Regents of the University of California. - * 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. 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. - * - * @(#)slcompress.c 7.7 (Berkeley) 5/7/91 - */ - -/* - * Routines to compress and uncompess tcp packets (for transmission - * over low speed serial lines. - * - * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: - * - Initial distribution. - * - * $Id$ - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/socketvar.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> - -#include <net/pppcompress.h> - -#ifndef SL_NO_STATS -#define INCR(counter) ++comp->counter; -#else -#define INCR(counter) -#endif - -#define BCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n)) -#define BCOPY(p1, p2, n) bcopy((char *)(p1), (char *)(p2), (int)(n)) -#ifndef KERNEL -#define ovbcopy bcopy -#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 ((unsigned) max_state > MAX_STATES - 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 = SLF_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) {\ - (f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \ - cp += 3; \ - } else { \ - (f) = htonl(ntohl(f) + (u_long)*cp++); \ - } \ -} - -#define DECODES(f) { \ - if (*cp == 0) {\ - (f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \ - cp += 3; \ - } else { \ - (f) = htons(ntohs(f) + (u_long)*cp++); \ - } \ -} - -#define DECODEU(f) { \ - if (*cp == 0) {\ - (f) = htons((cp[1] << 8) | cp[2]); \ - cp += 3; \ - } else { \ - (f) = htons((u_long)*cp++); \ - } \ -} - -u_int -vj_compress_tcp(m, ip, comp, compress_cid) - struct mbuf *m; - register struct ip *ip; - struct vjcompress *comp; - int compress_cid; -{ - register struct cstate *cs = comp->last_cs->cs_next; - register u_int hlen = ip->ip_hl; - 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)) || m->m_len < 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(sls_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)[cs->cs_ip.ip_hl]) { - /* - * 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(sls_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)[cs->cs_ip.ip_hl]) - 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(sls_misses) - comp->last_cs = lcs; - hlen += th->th_off; - hlen <<= 2; - 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 += th->th_off; - hlen <<= 2; - - 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] || - th->th_off != oth->th_off || - (deltaS > 5 && - BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) || - (th->th_off > 5 && - BCMP(th + 1, oth + 1, (th->th_off - 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)))) { - ENCODE(deltaS); - changes |= NEW_W; - } - - if ((deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack))) { - if (deltaA > 0xffff) - goto uncompressed; - ENCODE(deltaA); - changes |= NEW_A; - } - - if ((deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq))) { - 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; - cp += hlen; - *cp++ = changes | NEW_C; - *cp++ = cs->cs_id; - } else { - hlen -= deltaS + 3; - cp += hlen; - *cp++ = changes; - } - m->m_len -= hlen; - m->m_data += hlen; - *cp++ = deltaA >> 8; - *cp++ = deltaA; - BCOPY(new_seq, cp, deltaS); - INCR(sls_compressed) - return (TYPE_COMPRESSED_TCP); - - /* - * Update connection state cs & send uncompressed packet ('uncompressed' - * means 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); -} - - -int -vj_uncompress_tcp(bufp, len, type, comp) - u_char **bufp; - int len; - u_int type; - struct vjcompress *comp; -{ - u_char *hdr, *cp; - int hlen, vjlen; - - cp = bufp? *bufp: NULL; - vjlen = vj_uncompress_tcp_core(cp, len, len, type, comp, &hdr, &hlen); - if (vjlen < 0) - return (0); /* error */ - if (vjlen == 0) - return (len); /* was uncompressed already */ - - cp += vjlen; - len -= vjlen; - - /* - * At this point, cp points to the first byte of data in the - * packet. If we're not aligned on a 4-byte boundary, copy the - * data down so the ip & tcp headers will be aligned. Then back up - * cp by the tcp/ip header length to make room for the reconstructed - * header (we assume the packet we were handed has enough space to - * prepend 128 bytes of header). - */ - if ((int)cp & 3) { - if (len > 0) - (void) ovbcopy(cp, (caddr_t)((int)cp &~ 3), len); - cp = (u_char *)((int)cp &~ 3); - } - cp -= hlen; - len += hlen; - BCOPY(hdr, cp, hlen); - - *bufp = cp; - return (len); -} - -/* - * Uncompress a packet of total length total_len. The first buflen - * bytes are at buf; this must include the entire (compressed or - * uncompressed) 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_core(buf, buflen, total_len, type, comp, hdrp, hlenp) - u_char *buf; - int buflen, total_len; - u_int type; - 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 struct ip *ip; - register u_short *bp; - register u_int vjlen; - - switch (type) { - - case TYPE_UNCOMPRESSED_TCP: - ip = (struct ip *) buf; - if (ip->ip_p >= MAX_STATES) - goto bad; - cs = &comp->rstate[comp->last_recv = ip->ip_p]; - comp->flags &=~ SLF_TOSS; - ip->ip_p = IPPROTO_TCP; - /* - * Calculate the size of the TCP/IP header and make sure that - * we don't overflow the space we have available for it. - */ - hlen = ip->ip_hl << 2; - if (hlen + sizeof(struct tcphdr) > buflen) - goto bad; - hlen += ((struct tcphdr *)&((char *)ip)[hlen])->th_off << 2; - if (hlen > MAX_HDR || hlen > buflen) - goto bad; - BCOPY(ip, &cs->cs_ip, hlen); - cs->cs_hlen = hlen; - INCR(sls_uncompressedin) - *hdrp = (u_char *) &cs->cs_ip; - *hlenp = hlen; - return (0); - - default: - goto bad; - - case TYPE_COMPRESSED_TCP: - break; - } - /* We've got a compressed packet. */ - INCR(sls_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 &=~ SLF_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 & SLF_TOSS) { - INCR(sls_tossed) - return (-1); - } - } - cs = &comp->rstate[comp->last_recv]; - hlen = cs->cs_ip.ip_hl << 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_int i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen; - th->th_ack = htonl(ntohl(th->th_ack) + i); - th->th_seq = htonl(ntohl(th->th_seq) + i); - } - break; - - case SPECIAL_D: - th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - - cs->cs_hlen); - 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 = htons(ntohs(cs->cs_ip.ip_id) + 1); - - /* - * 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 |= SLF_TOSS; - INCR(sls_errorin) - return (-1); -} diff --git a/c/src/exec/libnetworking/net/pppcompress.h b/c/src/exec/libnetworking/net/pppcompress.h deleted file mode 100644 index 3f7687e6bb..0000000000 --- a/c/src/exec/libnetworking/net/pppcompress.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Definitions for tcp compression routines. - * - * Copyright (c) 1989 Regents of the University of California. - * 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. 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. - * - * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: - * - Initial distribution. - * - * From: slcompress.h 7.4 90/06/28 - * $Id$ - */ - -#ifndef _NET_PPPCOMPRESS_H_ -#define _NET_PPPCOMPRESS_H_ - -#define MAX_STATES 16 /* must be > 2 and < 256 */ -#define MAX_HDR MLEN /* XXX 4bsd-ism: should really be 128 */ - -/* - * Compressed packet format: - * - * The first octet contains the packet type (top 3 bits), TCP - * 'push' bit, and flags that indicate which of the 4 TCP sequence - * numbers have changed (bottom 5 bits). The next octet is a - * conversation number that associates a saved IP/TCP header with - * the compressed packet. The next two octets are the TCP checksum - * from the original datagram. The next 0 to 15 octets are - * sequence number changes, one change per bit set in the header - * (there may be no changes and there are two special cases where - * the receiver implicitly knows what changed -- see below). - * - * There are 5 numbers which can change (they are always inserted - * in the following order): TCP urgent pointer, window, - * acknowlegement, sequence number and IP ID. (The urgent pointer - * is different from the others in that its value is sent, not the - * change in value.) Since typical use of SLIP links is biased - * toward small packets (see comments on MTU/MSS below), changes - * use a variable length coding with one octet for numbers in the - * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the - * range 256 - 65535 or 0. (If the change in sequence number or - * ack is more than 65535, an uncompressed packet is sent.) - */ - -/* - * Packet types (must not conflict with IP protocol version) - * - * The top nibble of the first octet is the packet type. There are - * three possible types: IP (not proto TCP or tcp with one of the - * control flags set); uncompressed TCP (a normal IP/TCP packet but - * with the 8-bit protocol field replaced by an 8-bit connection id -- - * this type of packet syncs the sender & receiver); and compressed - * TCP (described above). - * - * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and - * is logically part of the 4-bit "changes" field that follows. Top - * three bits are actual packet type. For backward compatibility - * and in the interest of conserving bits, numbers are chosen so the - * IP protocol version number (4) which normally appears in this nibble - * means "IP packet". - */ - -/* packet types */ -#define TYPE_IP 0x40 -#define TYPE_UNCOMPRESSED_TCP 0x70 -#define TYPE_COMPRESSED_TCP 0x80 -#define TYPE_ERROR 0x00 - -/* Bits in first octet of compressed packet */ -#define NEW_C 0x40 /* flag bits for what changed in a packet */ -#define NEW_I 0x20 -#define NEW_S 0x08 -#define NEW_A 0x04 -#define NEW_W 0x02 -#define NEW_U 0x01 - -/* reserved, special-case values of above */ -#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ -#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ -#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) - -#define TCP_PUSH_BIT 0x10 - - -/* - * "state" data for each active tcp conversation on the wire. This is - * basically a copy of the entire IP/TCP header from the last packet - * we saw from the conversation together with a small identifier - * the transmit & receive ends of the line use to locate saved header. - */ -struct cstate { - struct cstate *cs_next; /* next most recently used cstate (xmit only) */ - u_short cs_hlen; /* size of hdr (receive only) */ - u_char cs_id; /* connection # associated with this state */ - u_char cs_filler; - union { - char csu_hdr[MAX_HDR]; - struct ip csu_ip; /* ip/tcp hdr from most recent packet */ - } slcs_u; -}; -#define cs_ip slcs_u.csu_ip -#define cs_hdr slcs_u.csu_hdr - -/* - * all the state data for one serial line (we need one of these - * per line). - */ -struct vjcompress { - struct cstate *last_cs; /* most recently used tstate */ - u_char last_recv; /* last rcvd conn. id */ - u_char last_xmit; /* last sent conn. id */ - u_short flags; -#ifndef SL_NO_STATS - int sls_packets; /* outbound packets */ - int sls_compressed; /* outbound compressed packets */ - int sls_searches; /* searches for connection state */ - int sls_misses; /* times couldn't find conn. state */ - int sls_uncompressedin; /* inbound uncompressed packets */ - int sls_compressedin; /* inbound compressed packets */ - int sls_errorin; /* inbound unknown type packets */ - int sls_tossed; /* inbound packets tossed because of error */ -#endif - struct cstate tstate[MAX_STATES]; /* xmit connection states */ - struct cstate rstate[MAX_STATES]; /* receive connection states */ -}; -/* flag values */ -#define SLF_TOSS 1 /* tossing rcvd frames because of input err */ - -void vj_compress_init __P((struct vjcompress *, int)); -u_int vj_compress_tcp __P((struct mbuf *, - struct ip *, struct vjcompress *, int)); -int vj_uncompress_tcp __P((u_char **, int, u_int, struct vjcompress *)); -int vj_uncompress_tcp_core __P((u_char *, int, int, u_int, - struct vjcompress *, u_char **, u_int *)); - -#endif /* _NET_PPPCOMPRESS_H_ */ diff --git a/c/src/exec/libnetworking/net/radix.c b/c/src/exec/libnetworking/net/radix.c deleted file mode 100644 index d7419ccca4..0000000000 --- a/c/src/exec/libnetworking/net/radix.c +++ /dev/null @@ -1,1031 +0,0 @@ -/* - * Copyright (c) 1988, 1989, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)radix.c 8.4 (Berkeley) 11/2/94 - * $Id$ - */ - -/* - * Routines to build and maintain radix trees for routing lookups. - */ -#ifndef _RADIX_H_ -#include <sys/param.h> -#ifdef KERNEL -#include <sys/systm.h> -#include <sys/malloc.h> -#define M_DONTWAIT M_NOWAIT -#include <sys/domain.h> -#else -#include <stdlib.h> -#endif -#include <sys/syslog.h> -#include <net/radix.h> -#endif - -static struct radix_node * - rn_lookup __P((void *v_arg, void *m_arg, - struct radix_node_head *head)); -static int rn_walktree_from __P((struct radix_node_head *h, void *a, - void *m, walktree_f_t *f, void *w)); -static int rn_walktree __P((struct radix_node_head *, walktree_f_t *, void *)); -static struct radix_node - *rn_delete __P((void *, void *, struct radix_node_head *)), - *rn_insert __P((void *, struct radix_node_head *, int *, - struct radix_node [2])), - *rn_newpair __P((void *, int, struct radix_node[2])), - *rn_search __P((void *, struct radix_node *)), - *rn_search_m __P((void *, struct radix_node *, void *)); - -static int max_keylen; -static struct radix_mask *rn_mkfreelist; -static struct radix_node_head *mask_rnhead; -static char *addmask_key; -static char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, -1}; -static char *rn_zeros, *rn_ones; - -#define rn_masktop (mask_rnhead->rnh_treetop) -#undef Bcmp -#define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l)) - -static int rn_lexobetter __P((void *m_arg, void *n_arg)); -static struct radix_mask * - rn_new_radix_mask __P((struct radix_node *tt, - struct radix_mask *next)); -static int rn_satsifies_leaf __P((char *trial, struct radix_node *leaf, - int skip)); - -/* - * The data structure for the keys is a radix tree with one way - * branching removed. The index rn_b at an internal node n represents a bit - * position to be tested. The tree is arranged so that all descendants - * of a node n have keys whose bits all agree up to position rn_b - 1. - * (We say the index of n is rn_b.) - * - * There is at least one descendant which has a one bit at position rn_b, - * and at least one with a zero there. - * - * A route is determined by a pair of key and mask. We require that the - * bit-wise logical and of the key and mask to be the key. - * We define the index of a route to associated with the mask to be - * the first bit number in the mask where 0 occurs (with bit number 0 - * representing the highest order bit). - * - * We say a mask is normal if every bit is 0, past the index of the mask. - * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b, - * and m is a normal mask, then the route applies to every descendant of n. - * If the index(m) < rn_b, this implies the trailing last few bits of k - * before bit b are all 0, (and hence consequently true of every descendant - * of n), so the route applies to all descendants of the node as well. - * - * Similar logic shows that a non-normal mask m such that - * index(m) <= index(n) could potentially apply to many children of n. - * Thus, for each non-host route, we attach its mask to a list at an internal - * node as high in the tree as we can go. - * - * The present version of the code makes use of normal routes in short- - * circuiting an explict mask and compare operation when testing whether - * a key satisfies a normal route, and also in remembering the unique leaf - * that governs a subtree. - */ - -static struct radix_node * -rn_search(v_arg, head) - void *v_arg; - struct radix_node *head; -{ - register struct radix_node *x; - register caddr_t v; - - for (x = head, v = v_arg; x->rn_b >= 0;) { - if (x->rn_bmask & v[x->rn_off]) - x = x->rn_r; - else - x = x->rn_l; - } - return (x); -}; - -static struct radix_node * -rn_search_m(v_arg, head, m_arg) - struct radix_node *head; - void *v_arg, *m_arg; -{ - register struct radix_node *x; - register caddr_t v = v_arg, m = m_arg; - - for (x = head; x->rn_b >= 0;) { - if ((x->rn_bmask & m[x->rn_off]) && - (x->rn_bmask & v[x->rn_off])) - x = x->rn_r; - else - x = x->rn_l; - } - return x; -}; - -int -rn_refines(m_arg, n_arg) - void *m_arg, *n_arg; -{ - register caddr_t m = m_arg, n = n_arg; - register caddr_t lim, lim2 = lim = n + *(u_char *)n; - int longer = (*(u_char *)n++) - (int)(*(u_char *)m++); - int masks_are_equal = 1; - - if (longer > 0) - lim -= longer; - while (n < lim) { - if (*n & ~(*m)) - return 0; - if (*n++ != *m++) - masks_are_equal = 0; - } - while (n < lim2) - if (*n++) - return 0; - if (masks_are_equal && (longer < 0)) - for (lim2 = m - longer; m < lim2; ) - if (*m++) - return 1; - return (!masks_are_equal); -} - -struct radix_node * -rn_lookup(v_arg, m_arg, head) - void *v_arg, *m_arg; - struct radix_node_head *head; -{ - register struct radix_node *x; - caddr_t netmask = 0; - - if (m_arg) { - if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0) - return (0); - netmask = x->rn_key; - } - x = rn_match(v_arg, head); - if (x && netmask) { - while (x && x->rn_mask != netmask) - x = x->rn_dupedkey; - } - return x; -} - -static int -rn_satsifies_leaf(trial, leaf, skip) - char *trial; - register struct radix_node *leaf; - int skip; -{ - register char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask; - char *cplim; - int length = min(*(u_char *)cp, *(u_char *)cp2); - - if (cp3 == 0) - cp3 = rn_ones; - else - length = min(length, *(u_char *)cp3); - cplim = cp + length; cp3 += skip; cp2 += skip; - for (cp += skip; cp < cplim; cp++, cp2++, cp3++) - if ((*cp ^ *cp2) & *cp3) - return 0; - return 1; -} - -struct radix_node * -rn_match(v_arg, head) - void *v_arg; - struct radix_node_head *head; -{ - caddr_t v = v_arg; - register struct radix_node *t = head->rnh_treetop, *x; - register caddr_t cp = v, cp2; - caddr_t cplim; - struct radix_node *saved_t, *top = t; - int off = t->rn_off, vlen = *(u_char *)cp, matched_off; - register int test, b, rn_b; - - /* - * Open code rn_search(v, top) to avoid overhead of extra - * subroutine call. - */ - for (; t->rn_b >= 0; ) { - if (t->rn_bmask & cp[t->rn_off]) - t = t->rn_r; - else - t = t->rn_l; - } - /* - * See if we match exactly as a host destination - * or at least learn how many bits match, for normal mask finesse. - * - * It doesn't hurt us to limit how many bytes to check - * to the length of the mask, since if it matches we had a genuine - * match and the leaf we have is the most specific one anyway; - * if it didn't match with a shorter length it would fail - * with a long one. This wins big for class B&C netmasks which - * are probably the most common case... - */ - if (t->rn_mask) - vlen = *(u_char *)t->rn_mask; - cp += off; cp2 = t->rn_key + off; cplim = v + vlen; - for (; cp < cplim; cp++, cp2++) - if (*cp != *cp2) - goto on1; - /* - * This extra grot is in case we are explicitly asked - * to look up the default. Ugh! - * - * Never return the root node itself, it seems to cause a - * lot of confusion. - */ - if (t->rn_flags & RNF_ROOT) - t = t->rn_dupedkey; - return t; -on1: - test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */ - for (b = 7; (test >>= 1) > 0;) - b--; - matched_off = cp - v; - b += matched_off << 3; - rn_b = -1 - b; - /* - * If there is a host route in a duped-key chain, it will be first. - */ - if ((saved_t = t)->rn_mask == 0) - t = t->rn_dupedkey; - for (; t; t = t->rn_dupedkey) - /* - * Even if we don't match exactly as a host, - * we may match if the leaf we wound up at is - * a route to a net. - */ - if (t->rn_flags & RNF_NORMAL) { - if (rn_b <= t->rn_b) - return t; - } else if (rn_satsifies_leaf(v, t, matched_off)) - return t; - t = saved_t; - /* start searching up the tree */ - do { - register struct radix_mask *m; - t = t->rn_p; - m = t->rn_mklist; - if (m) { - /* - * If non-contiguous masks ever become important - * we can restore the masking and open coding of - * the search and satisfaction test and put the - * calculation of "off" back before the "do". - */ - do { - if (m->rm_flags & RNF_NORMAL) { - if (rn_b <= m->rm_b) - return (m->rm_leaf); - } else { - off = min(t->rn_off, matched_off); - x = rn_search_m(v, t, m->rm_mask); - while (x && x->rn_mask != m->rm_mask) - x = x->rn_dupedkey; - if (x && rn_satsifies_leaf(v, x, off)) - return x; - } - m = m->rm_mklist; - } while (m); - } - } while (t != top); - return 0; -}; - -#ifdef RN_DEBUG -int rn_nodenum; -struct radix_node *rn_clist; -int rn_saveinfo; -int rn_debug = 1; -#endif - -static struct radix_node * -rn_newpair(v, b, nodes) - void *v; - int b; - struct radix_node nodes[2]; -{ - register struct radix_node *tt = nodes, *t = tt + 1; - t->rn_b = b; t->rn_bmask = 0x80 >> (b & 7); - t->rn_l = tt; t->rn_off = b >> 3; - tt->rn_b = -1; tt->rn_key = (caddr_t)v; tt->rn_p = t; - tt->rn_flags = t->rn_flags = RNF_ACTIVE; -#ifdef RN_DEBUG - tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; - tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; -#endif - return t; -} - -static struct radix_node * -rn_insert(v_arg, head, dupentry, nodes) - void *v_arg; - struct radix_node_head *head; - int *dupentry; - struct radix_node nodes[2]; -{ - caddr_t v = v_arg; - struct radix_node *top = head->rnh_treetop; - int head_off = top->rn_off, vlen = (int)*((u_char *)v); - register struct radix_node *t = rn_search(v_arg, top); - register caddr_t cp = v + head_off; - register int b; - struct radix_node *tt; - /* - * Find first bit at which v and t->rn_key differ - */ - { - register caddr_t cp2 = t->rn_key + head_off; - register int cmp_res; - caddr_t cplim = v + vlen; - - while (cp < cplim) - if (*cp2++ != *cp++) - goto on1; - *dupentry = 1; - return t; -on1: - *dupentry = 0; - cmp_res = (cp[-1] ^ cp2[-1]) & 0xff; - for (b = (cp - v) << 3; cmp_res; b--) - cmp_res >>= 1; - } - { - register struct radix_node *p, *x = top; - cp = v; - do { - p = x; - if (cp[x->rn_off] & x->rn_bmask) - x = x->rn_r; - else x = x->rn_l; - } while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */ -#ifdef RN_DEBUG - if (rn_debug) - log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p); -#endif - t = rn_newpair(v_arg, b, nodes); tt = t->rn_l; - if ((cp[p->rn_off] & p->rn_bmask) == 0) - p->rn_l = t; - else - p->rn_r = t; - x->rn_p = t; t->rn_p = p; /* frees x, p as temp vars below */ - if ((cp[t->rn_off] & t->rn_bmask) == 0) { - t->rn_r = x; - } else { - t->rn_r = tt; t->rn_l = x; - } -#ifdef RN_DEBUG - if (rn_debug) - log(LOG_DEBUG, "rn_insert: Coming Out:\n"), traverse(p); -#endif - } - return (tt); -} - -struct radix_node * -rn_addmask(n_arg, search, skip) - int search, skip; - void *n_arg; -{ - caddr_t netmask = (caddr_t)n_arg; - register struct radix_node *x; - register caddr_t cp, cplim; - register int b = 0, mlen, j; - int maskduplicated, m0, isnormal; - struct radix_node *saved_x; - static int last_zeroed = 0; - - if ((mlen = *(u_char *)netmask) > max_keylen) - mlen = max_keylen; - if (skip == 0) - skip = 1; - if (mlen <= skip) - return (mask_rnhead->rnh_nodes); - if (skip > 1) - Bcopy(rn_ones + 1, addmask_key + 1, skip - 1); - if ((m0 = mlen) > skip) - Bcopy(netmask + skip, addmask_key + skip, mlen - skip); - /* - * Trim trailing zeroes. - */ - for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;) - cp--; - mlen = cp - addmask_key; - if (mlen <= skip) { - if (m0 >= last_zeroed) - last_zeroed = mlen; - return (mask_rnhead->rnh_nodes); - } - if (m0 < last_zeroed) - Bzero(addmask_key + m0, last_zeroed - m0); - *addmask_key = last_zeroed = mlen; - x = rn_search(addmask_key, rn_masktop); - if (Bcmp(addmask_key, x->rn_key, mlen) != 0) - x = 0; - if (x || search) - return (x); - R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof (*x)); - if ((saved_x = x) == 0) - return (0); - Bzero(x, max_keylen + 2 * sizeof (*x)); - netmask = cp = (caddr_t)(x + 2); - Bcopy(addmask_key, cp, mlen); - x = rn_insert(cp, mask_rnhead, &maskduplicated, x); - if (maskduplicated) { - log(LOG_ERR, "rn_addmask: mask impossibly already in tree"); - Free(saved_x); - return (x); - } - /* - * Calculate index of mask, and check for normalcy. - */ - cplim = netmask + mlen; isnormal = 1; - for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;) - cp++; - if (cp != cplim) { - for (j = 0x80; (j & *cp) != 0; j >>= 1) - b++; - if (*cp != normal_chars[b] || cp != (cplim - 1)) - isnormal = 0; - } - b += (cp - netmask) << 3; - x->rn_b = -1 - b; - if (isnormal) - x->rn_flags |= RNF_NORMAL; - return (x); -} - -static int /* XXX: arbitrary ordering for non-contiguous masks */ -rn_lexobetter(m_arg, n_arg) - void *m_arg, *n_arg; -{ - register u_char *mp = m_arg, *np = n_arg, *lim; - - if (*mp > *np) - return 1; /* not really, but need to check longer one first */ - if (*mp == *np) - for (lim = mp + *mp; mp < lim;) - if (*mp++ > *np++) - return 1; - return 0; -} - -static struct radix_mask * -rn_new_radix_mask(tt, next) - register struct radix_node *tt; - register struct radix_mask *next; -{ - register struct radix_mask *m; - - MKGet(m); - if (m == 0) { - log(LOG_ERR, "Mask for route not entered\n"); - return (0); - } - Bzero(m, sizeof *m); - m->rm_b = tt->rn_b; - m->rm_flags = tt->rn_flags; - if (tt->rn_flags & RNF_NORMAL) - m->rm_leaf = tt; - else - m->rm_mask = tt->rn_mask; - m->rm_mklist = next; - tt->rn_mklist = m; - return m; -} - -struct radix_node * -rn_addroute(v_arg, n_arg, head, treenodes) - void *v_arg, *n_arg; - struct radix_node_head *head; - struct radix_node treenodes[2]; -{ - caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; - register struct radix_node *t, *x = 0, *tt; - struct radix_node *saved_tt, *top = head->rnh_treetop; - short b = 0, b_leaf = 0; - int keyduplicated; - caddr_t mmask; - struct radix_mask *m, **mp; - - /* - * In dealing with non-contiguous masks, there may be - * many different routes which have the same mask. - * We will find it useful to have a unique pointer to - * the mask to speed avoiding duplicate references at - * nodes and possibly save time in calculating indices. - */ - if (netmask) { - if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0) - return (0); - b_leaf = x->rn_b; - b = -1 - x->rn_b; - netmask = x->rn_key; - } - /* - * Deal with duplicated keys: attach node to previous instance - */ - saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes); - if (keyduplicated) { - for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) { - if (tt->rn_mask == netmask) - return (0); - if (netmask == 0 || - (tt->rn_mask && - ((b_leaf < tt->rn_b) || /* index(netmask) > node */ - rn_refines(netmask, tt->rn_mask) || - rn_lexobetter(netmask, tt->rn_mask)))) - break; - } - /* - * If the mask is not duplicated, we wouldn't - * find it among possible duplicate key entries - * anyway, so the above test doesn't hurt. - * - * We sort the masks for a duplicated key the same way as - * in a masklist -- most specific to least specific. - * This may require the unfortunate nuisance of relocating - * the head of the list. - */ - if (tt == saved_tt) { - struct radix_node *xx = x; - /* link in at head of list */ - (tt = treenodes)->rn_dupedkey = t; - tt->rn_flags = t->rn_flags; - tt->rn_p = x = t->rn_p; - t->rn_p = tt; /* parent */ - if (x->rn_l == t) x->rn_l = tt; else x->rn_r = tt; - saved_tt = tt; x = xx; - } else { - (tt = treenodes)->rn_dupedkey = t->rn_dupedkey; - t->rn_dupedkey = tt; - tt->rn_p = t; /* parent */ - if (tt->rn_dupedkey) /* parent */ - tt->rn_dupedkey->rn_p = tt; /* parent */ - } -#ifdef RN_DEBUG - t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; - tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; -#endif - tt->rn_key = (caddr_t) v; - tt->rn_b = -1; - tt->rn_flags = RNF_ACTIVE; - } - /* - * Put mask in tree. - */ - if (netmask) { - tt->rn_mask = netmask; - tt->rn_b = x->rn_b; - tt->rn_flags |= x->rn_flags & RNF_NORMAL; - } - t = saved_tt->rn_p; - if (keyduplicated) - goto on2; - b_leaf = -1 - t->rn_b; - if (t->rn_r == saved_tt) x = t->rn_l; else x = t->rn_r; - /* Promote general routes from below */ - if (x->rn_b < 0) { - for (mp = &t->rn_mklist; x; x = x->rn_dupedkey) - if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) { - *mp = m = rn_new_radix_mask(x, 0); - if (m) - mp = &m->rm_mklist; - } - } else if (x->rn_mklist) { - /* - * Skip over masks whose index is > that of new node - */ - for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) - if (m->rm_b >= b_leaf) - break; - t->rn_mklist = m; *mp = 0; - } -on2: - /* Add new route to highest possible ancestor's list */ - if ((netmask == 0) || (b > t->rn_b )) - return tt; /* can't lift at all */ - b_leaf = tt->rn_b; - do { - x = t; - t = t->rn_p; - } while (b <= t->rn_b && x != top); - /* - * Search through routes associated with node to - * insert new route according to index. - * Need same criteria as when sorting dupedkeys to avoid - * double loop on deletion. - */ - for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) { - if (m->rm_b < b_leaf) - continue; - if (m->rm_b > b_leaf) - break; - if (m->rm_flags & RNF_NORMAL) { - mmask = m->rm_leaf->rn_mask; - if (tt->rn_flags & RNF_NORMAL) { - log(LOG_ERR, - "Non-unique normal route, mask not entered"); - return tt; - } - } else - mmask = m->rm_mask; - if (mmask == netmask) { - m->rm_refs++; - tt->rn_mklist = m; - return tt; - } - if (rn_refines(netmask, mmask) || rn_lexobetter(netmask, mmask)) - break; - } - *mp = rn_new_radix_mask(tt, *mp); - return tt; -} - -static struct radix_node * -rn_delete(v_arg, netmask_arg, head) - void *v_arg, *netmask_arg; - struct radix_node_head *head; -{ - register struct radix_node *t, *p, *x, *tt; - struct radix_mask *m, *saved_m, **mp; - struct radix_node *dupedkey, *saved_tt, *top; - caddr_t v, netmask; - int b, head_off, vlen; - - v = v_arg; - netmask = netmask_arg; - x = head->rnh_treetop; - tt = rn_search(v, x); - head_off = x->rn_off; - vlen = *(u_char *)v; - saved_tt = tt; - top = x; - if (tt == 0 || - Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off)) - return (0); - /* - * Delete our route from mask lists. - */ - if (netmask) { - if ((x = rn_addmask(netmask, 1, head_off)) == 0) - return (0); - netmask = x->rn_key; - while (tt->rn_mask != netmask) - if ((tt = tt->rn_dupedkey) == 0) - return (0); - } - if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0) - goto on1; - if (tt->rn_flags & RNF_NORMAL) { - if (m->rm_leaf != tt || m->rm_refs > 0) { - log(LOG_ERR, "rn_delete: inconsistent annotation\n"); - return 0; /* dangling ref could cause disaster */ - } - } else { - if (m->rm_mask != tt->rn_mask) { - log(LOG_ERR, "rn_delete: inconsistent annotation\n"); - goto on1; - } - if (--m->rm_refs >= 0) - goto on1; - } - b = -1 - tt->rn_b; - t = saved_tt->rn_p; - if (b > t->rn_b) - goto on1; /* Wasn't lifted at all */ - do { - x = t; - t = t->rn_p; - } while (b <= t->rn_b && x != top); - for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) - if (m == saved_m) { - *mp = m->rm_mklist; - MKFree(m); - break; - } - if (m == 0) { - log(LOG_ERR, "rn_delete: couldn't find our annotation\n"); - if (tt->rn_flags & RNF_NORMAL) - return (0); /* Dangling ref to us */ - } -on1: - /* - * Eliminate us from tree - */ - if (tt->rn_flags & RNF_ROOT) - return (0); -#ifdef RN_DEBUG - /* Get us out of the creation list */ - for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {} - if (t) t->rn_ybro = tt->rn_ybro; -#endif - t = tt->rn_p; - dupedkey = saved_tt->rn_dupedkey; - if (dupedkey) { - /* - * at this point, tt is the deletion target and saved_tt - * is the head of the dupekey chain - */ - if (tt == saved_tt) { - /* remove from head of chain */ - x = dupedkey; x->rn_p = t; - if (t->rn_l == tt) t->rn_l = x; else t->rn_r = x; - } else { - /* find node in front of tt on the chain */ - for (x = p = saved_tt; p && p->rn_dupedkey != tt;) - p = p->rn_dupedkey; - if (p) { - p->rn_dupedkey = tt->rn_dupedkey; - if (tt->rn_dupedkey) /* parent */ - tt->rn_dupedkey->rn_p = p; /* parent */ - } else log(LOG_ERR, "rn_delete: couldn't find us\n"); - } - t = tt + 1; - if (t->rn_flags & RNF_ACTIVE) { -#ifndef RN_DEBUG - *++x = *t; p = t->rn_p; -#else - b = t->rn_info; *++x = *t; t->rn_info = b; p = t->rn_p; -#endif - if (p->rn_l == t) p->rn_l = x; else p->rn_r = x; - x->rn_l->rn_p = x; x->rn_r->rn_p = x; - } - goto out; - } - if (t->rn_l == tt) x = t->rn_r; else x = t->rn_l; - p = t->rn_p; - if (p->rn_r == t) p->rn_r = x; else p->rn_l = x; - x->rn_p = p; - /* - * Demote routes attached to us. - */ - if (t->rn_mklist) { - if (x->rn_b >= 0) { - for (mp = &x->rn_mklist; (m = *mp);) - mp = &m->rm_mklist; - *mp = t->rn_mklist; - } else { - /* If there are any key,mask pairs in a sibling - duped-key chain, some subset will appear sorted - in the same order attached to our mklist */ - for (m = t->rn_mklist; m && x; x = x->rn_dupedkey) - if (m == x->rn_mklist) { - struct radix_mask *mm = m->rm_mklist; - x->rn_mklist = 0; - if (--(m->rm_refs) < 0) - MKFree(m); - m = mm; - } - if (m) - log(LOG_ERR, "%s %p at %x\n", - "rn_delete: Orphaned Mask", m, x); - } - } - /* - * We may be holding an active internal node in the tree. - */ - x = tt + 1; - if (t != x) { -#ifndef RN_DEBUG - *t = *x; -#else - b = t->rn_info; *t = *x; t->rn_info = b; -#endif - t->rn_l->rn_p = t; t->rn_r->rn_p = t; - p = x->rn_p; - if (p->rn_l == x) p->rn_l = t; else p->rn_r = t; - } -out: - tt->rn_flags &= ~RNF_ACTIVE; - tt[1].rn_flags &= ~RNF_ACTIVE; - return (tt); -} - -/* - * This is the same as rn_walktree() except for the parameters and the - * exit. - */ -static int -rn_walktree_from(h, a, m, f, w) - struct radix_node_head *h; - void *a, *m; - walktree_f_t *f; - void *w; -{ - int error; - struct radix_node *base, *next; - u_char *xa = (u_char *)a; - u_char *xm = (u_char *)m; - register struct radix_node *rn, *last = 0 /* shut up gcc */; - int stopping = 0; - int lastb; - - /* - * rn_search_m is sort-of-open-coded here. - */ - /* printf("about to search\n"); */ - for (rn = h->rnh_treetop; rn->rn_b >= 0; ) { - last = rn; - /* printf("rn_b %d, rn_bmask %x, xm[rn_off] %x\n", - rn->rn_b, rn->rn_bmask, xm[rn->rn_off]); */ - if (!(rn->rn_bmask & xm[rn->rn_off])) { - break; - } - if (rn->rn_bmask & xa[rn->rn_off]) { - rn = rn->rn_r; - } else { - rn = rn->rn_l; - } - } - /* printf("done searching\n"); */ - - /* - * Two cases: either we stepped off the end of our mask, - * in which case last == rn, or we reached a leaf, in which - * case we want to start from the last node we looked at. - * Either way, last is the node we want to start from. - */ - rn = last; - lastb = rn->rn_b; - - /* printf("rn %p, lastb %d\n", rn, lastb);*/ - - /* - * This gets complicated because we may delete the node - * while applying the function f to it, so we need to calculate - * the successor node in advance. - */ - while (rn->rn_b >= 0) - rn = rn->rn_l; - - while (!stopping) { - /* printf("node %p (%d)\n", rn, rn->rn_b); */ - base = rn; - /* If at right child go back up, otherwise, go right */ - while (rn->rn_p->rn_r == rn && !(rn->rn_flags & RNF_ROOT)) { - rn = rn->rn_p; - - /* if went up beyond last, stop */ - if (rn->rn_b < lastb) { - stopping = 1; - /* printf("up too far\n"); */ - } - } - - /* Find the next *leaf* since next node might vanish, too */ - for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;) - rn = rn->rn_l; - next = rn; - /* Process leaves */ - while ((rn = base) != 0) { - base = rn->rn_dupedkey; - /* printf("leaf %p\n", rn); */ - if (!(rn->rn_flags & RNF_ROOT) - && (error = (*f)(rn, w))) - return (error); - } - rn = next; - - if (rn->rn_flags & RNF_ROOT) { - /* printf("root, stopping"); */ - stopping = 1; - } - - } - return 0; -} - -static int -rn_walktree(h, f, w) - struct radix_node_head *h; - walktree_f_t *f; - void *w; -{ - int error; - struct radix_node *base, *next; - register struct radix_node *rn = h->rnh_treetop; - /* - * This gets complicated because we may delete the node - * while applying the function f to it, so we need to calculate - * the successor node in advance. - */ - /* First time through node, go left */ - while (rn->rn_b >= 0) - rn = rn->rn_l; - for (;;) { - base = rn; - /* If at right child go back up, otherwise, go right */ - while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0) - rn = rn->rn_p; - /* Find the next *leaf* since next node might vanish, too */ - for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;) - rn = rn->rn_l; - next = rn; - /* Process leaves */ - while ((rn = base)) { - base = rn->rn_dupedkey; - if (!(rn->rn_flags & RNF_ROOT) && (error = (*f)(rn, w))) - return (error); - } - rn = next; - if (rn->rn_flags & RNF_ROOT) - return (0); - } - /* NOTREACHED */ -} - -int -rn_inithead(head, off) - void **head; - int off; -{ - register struct radix_node_head *rnh; - register struct radix_node *t, *tt, *ttt; - if (*head) - return (1); - R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh)); - if (rnh == 0) - return (0); - Bzero(rnh, sizeof (*rnh)); - *head = rnh; - t = rn_newpair(rn_zeros, off, rnh->rnh_nodes); - ttt = rnh->rnh_nodes + 2; - t->rn_r = ttt; - t->rn_p = t; - tt = t->rn_l; - tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE; - tt->rn_b = -1 - off; - *ttt = *tt; - ttt->rn_key = rn_ones; - rnh->rnh_addaddr = rn_addroute; - rnh->rnh_deladdr = rn_delete; - rnh->rnh_matchaddr = rn_match; - rnh->rnh_lookup = rn_lookup; - rnh->rnh_walktree = rn_walktree; - rnh->rnh_walktree_from = rn_walktree_from; - rnh->rnh_treetop = t; - return (1); -} - -void -rn_init() -{ - char *cp, *cplim; -#ifdef KERNEL - struct domain *dom; - - for (dom = domains; dom; dom = dom->dom_next) - if (dom->dom_maxrtkey > max_keylen) - max_keylen = dom->dom_maxrtkey; -#endif - if (max_keylen == 0) { - log(LOG_ERR, - "rn_init: radix functions require max_keylen be set\n"); - return; - } - R_Malloc(rn_zeros, char *, 3 * max_keylen); - if (rn_zeros == NULL) - panic("rn_init"); - Bzero(rn_zeros, 3 * max_keylen); - rn_ones = cp = rn_zeros + max_keylen; - addmask_key = cplim = rn_ones + max_keylen; - while (cp < cplim) - *cp++ = -1; - if (rn_inithead((void **)&mask_rnhead, 0) == 0) - panic("rn_init 2"); -} diff --git a/c/src/exec/libnetworking/net/radix.h b/c/src/exec/libnetworking/net/radix.h deleted file mode 100644 index 6ef9aafbac..0000000000 --- a/c/src/exec/libnetworking/net/radix.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 1988, 1989, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)radix.h 8.2 (Berkeley) 10/31/94 - * $Id$ - */ - -#ifndef _RADIX_H_ -#define _RADIX_H_ - -/* - * Radix search tree node layout. - */ - -struct radix_node { - struct radix_mask *rn_mklist; /* list of masks contained in subtree */ - struct radix_node *rn_p; /* parent */ - short rn_b; /* bit offset; -1-index(netmask) */ - char rn_bmask; /* node: mask for bit test*/ - u_char rn_flags; /* enumerated next */ -#define RNF_NORMAL 1 /* leaf contains normal route */ -#define RNF_ROOT 2 /* leaf is root leaf for tree */ -#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */ - union { - struct { /* leaf only data: */ - caddr_t rn_Key; /* object of search */ - caddr_t rn_Mask; /* netmask, if present */ - struct radix_node *rn_Dupedkey; - } rn_leaf; - struct { /* node only data: */ - int rn_Off; /* where to start compare */ - struct radix_node *rn_L;/* progeny */ - struct radix_node *rn_R;/* progeny */ - } rn_node; - } rn_u; -#ifdef RN_DEBUG - int rn_info; - struct radix_node *rn_twin; - struct radix_node *rn_ybro; -#endif -}; - -#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey -#define rn_key rn_u.rn_leaf.rn_Key -#define rn_mask rn_u.rn_leaf.rn_Mask -#define rn_off rn_u.rn_node.rn_Off -#define rn_l rn_u.rn_node.rn_L -#define rn_r rn_u.rn_node.rn_R - -/* - * Annotations to tree concerning potential routes applying to subtrees. - */ - -extern struct radix_mask { - short rm_b; /* bit offset; -1-index(netmask) */ - char rm_unused; /* cf. rn_bmask */ - u_char rm_flags; /* cf. rn_flags */ - struct radix_mask *rm_mklist; /* more masks to try */ - union { - caddr_t rmu_mask; /* the mask */ - struct radix_node *rmu_leaf; /* for normal routes */ - } rm_rmu; - int rm_refs; /* # of references to this struct */ -} *rn_mkfreelist; - -#define rm_mask rm_rmu.rmu_mask -#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */ - -#define MKGet(m) {\ - if (rn_mkfreelist) {\ - m = rn_mkfreelist; \ - rn_mkfreelist = (m)->rm_mklist; \ - } else \ - R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\ - -#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);} - -typedef int walktree_f_t __P((struct radix_node *, void *)); - -struct radix_node_head { - struct radix_node *rnh_treetop; - int rnh_addrsize; /* permit, but not require fixed keys */ - int rnh_pktsize; /* permit, but not require fixed keys */ - struct radix_node *(*rnh_addaddr) /* add based on sockaddr */ - __P((void *v, void *mask, - struct radix_node_head *head, struct radix_node nodes[])); - struct radix_node *(*rnh_addpkt) /* add based on packet hdr */ - __P((void *v, void *mask, - struct radix_node_head *head, struct radix_node nodes[])); - struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */ - __P((void *v, void *mask, struct radix_node_head *head)); - struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */ - __P((void *v, void *mask, struct radix_node_head *head)); - struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */ - __P((void *v, struct radix_node_head *head)); - struct radix_node *(*rnh_lookup) /* locate based on sockaddr */ - __P((void *v, void *mask, struct radix_node_head *head)); - struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */ - __P((void *v, struct radix_node_head *head)); - int (*rnh_walktree) /* traverse tree */ - __P((struct radix_node_head *head, walktree_f_t *f, void *w)); - int (*rnh_walktree_from) /* traverse tree below a */ - __P((struct radix_node_head *head, void *a, void *m, - walktree_f_t *f, void *w)); - void (*rnh_close) /* do something when the last ref drops */ - __P((struct radix_node *rn, struct radix_node_head *head)); - struct radix_node rnh_nodes[3]; /* empty tree for common case */ -}; - -#ifndef KERNEL -#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n)) -#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n)) -#define Bzero(p, n) bzero((char *)(p), (int)(n)); -#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n))) -#define Free(p) free((char *)p); -#else -#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) -#define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) -#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n)); -#define R_Malloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_DONTWAIT)) -#define Free(p) free((caddr_t)p, M_RTABLE); -#endif /*KERNEL*/ - -extern struct radix_node_head *mask_rnhead; - -void rn_init __P((void)); -int rn_inithead __P((void **, int)); -int rn_refines __P((void *, void *)); -struct radix_node - *rn_addmask __P((void *, int, int)), - *rn_addroute __P((void *, void *, struct radix_node_head *, - struct radix_node [2])), - *rn_match __P((void *, struct radix_node_head *)); - - -#endif /* _RADIX_H_ */ diff --git a/c/src/exec/libnetworking/net/raw_cb.c b/c/src/exec/libnetworking/net/raw_cb.c deleted file mode 100644 index 0676931cdc..0000000000 --- a/c/src/exec/libnetworking/net/raw_cb.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)raw_cb.c 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/domain.h> -#include <sys/protosw.h> -#include <sys/errno.h> - -#include <net/if.h> -#include <net/route.h> -#include <net/raw_cb.h> -#include <netinet/in.h> - -/* - * Routines to manage the raw protocol control blocks. - * - * TODO: - * hash lookups by protocol family/protocol + address family - * take care of unique address problems per AF? - * redo address binding to allow wildcards - */ - -struct rawcb rawcb; -static u_long raw_sendspace = RAWSNDQ; -static u_long raw_recvspace = RAWRCVQ; - -/* - * Allocate a control block and a nominal amount - * of buffer space for the socket. - */ -int -raw_attach(so, proto) - register struct socket *so; - int proto; -{ - register struct rawcb *rp = sotorawcb(so); - int error; - - /* - * It is assumed that raw_attach is called - * after space has been allocated for the - * rawcb. - */ - if (rp == 0) - return (ENOBUFS); - error = soreserve(so, raw_sendspace, raw_recvspace); - if (error) - return (error); - rp->rcb_socket = so; - rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; - rp->rcb_proto.sp_protocol = proto; - insque(rp, &rawcb); - return (0); -} - -/* - * Detach the raw connection block and discard - * socket resources. - */ -void -raw_detach(rp) - register struct rawcb *rp; -{ - struct socket *so = rp->rcb_socket; - - so->so_pcb = 0; - sofree(so); - remque(rp); -#ifdef notdef - if (rp->rcb_laddr) - m_freem(dtom(rp->rcb_laddr)); - rp->rcb_laddr = 0; -#endif - free((caddr_t)(rp), M_PCB); -} - -/* - * Disconnect and possibly release resources. - */ -void -raw_disconnect(rp) - struct rawcb *rp; -{ - -#ifdef notdef - if (rp->rcb_faddr) - m_freem(dtom(rp->rcb_faddr)); - rp->rcb_faddr = 0; -#endif - if (rp->rcb_socket->so_state & SS_NOFDREF) - raw_detach(rp); -} - -#ifdef notdef -int -raw_bind(so, nam) - register struct socket *so; - struct mbuf *nam; -{ - struct sockaddr *addr = mtod(nam, struct sockaddr *); - register struct rawcb *rp; - - if (ifnet == 0) - return (EADDRNOTAVAIL); - rp = sotorawcb(so); - nam = m_copym(nam, 0, M_COPYALL, M_WAITOK); - rp->rcb_laddr = mtod(nam, struct sockaddr *); - return (0); -} -#endif diff --git a/c/src/exec/libnetworking/net/raw_cb.h b/c/src/exec/libnetworking/net/raw_cb.h deleted file mode 100644 index c1ed5e5e0a..0000000000 --- a/c/src/exec/libnetworking/net/raw_cb.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)raw_cb.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NET_RAW_CB_H_ -#define _NET_RAW_CB_H_ - -/* - * Raw protocol interface control block. Used - * to tie a socket to the generic raw interface. - */ -struct rawcb { - struct rawcb *rcb_next; /* doubly linked list */ - struct rawcb *rcb_prev; - struct socket *rcb_socket; /* back pointer to socket */ - struct sockaddr *rcb_faddr; /* destination address */ - struct sockaddr *rcb_laddr; /* socket's address */ - struct sockproto rcb_proto; /* protocol family, protocol */ -}; - -#define sotorawcb(so) ((struct rawcb *)(so)->so_pcb) - -/* - * Nominal space allocated to a raw socket. - */ -#define RAWSNDQ 8192 -#define RAWRCVQ 8192 - -#ifdef KERNEL -extern struct rawcb rawcb; /* head of list */ - -int raw_attach __P((struct socket *, int)); -void raw_ctlinput __P((int, struct sockaddr *, void *)); -void raw_detach __P((struct rawcb *)); -void raw_disconnect __P((struct rawcb *)); -void raw_init __P((void)); -void raw_input __P((struct mbuf *, - struct sockproto *, struct sockaddr *, struct sockaddr *)); -int raw_usrreq __P((struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *)); -#endif - -#endif diff --git a/c/src/exec/libnetworking/net/raw_usrreq.c b/c/src/exec/libnetworking/net/raw_usrreq.c deleted file mode 100644 index fb4faf4d6d..0000000000 --- a/c/src/exec/libnetworking/net/raw_usrreq.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/domain.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/errno.h> - -#include <net/if.h> -#include <net/route.h> -#include <net/netisr.h> -#include <net/raw_cb.h> - -/* - * Initialize raw connection block q. - */ -void -raw_init() -{ - - rawcb.rcb_next = rawcb.rcb_prev = &rawcb; -} - - -/* - * Raw protocol input routine. Find the socket - * associated with the packet(s) and move them over. If - * nothing exists for this packet, drop it. - */ -/* - * Raw protocol interface. - */ -void -raw_input(m0, proto, src, dst) - struct mbuf *m0; - register struct sockproto *proto; - struct sockaddr *src, *dst; -{ - register struct rawcb *rp; - register struct mbuf *m = m0; - register int sockets = 0; - struct socket *last; - - last = 0; - for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { - if (rp->rcb_proto.sp_family != proto->sp_family) - continue; - if (rp->rcb_proto.sp_protocol && - rp->rcb_proto.sp_protocol != proto->sp_protocol) - continue; - /* - * We assume the lower level routines have - * placed the address in a canonical format - * suitable for a structure comparison. - * - * Note that if the lengths are not the same - * the comparison will fail at the first byte. - */ -#define equal(a1, a2) \ - (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) - if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) - continue; - if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) - continue; - if (last) { - struct mbuf *n; - n = m_copy(m, 0, (int)M_COPYALL); - if (n) { - if (sbappendaddr(&last->so_rcv, src, - n, (struct mbuf *)0) == 0) - /* should notify about lost packet */ - m_freem(n); - else { - sorwakeup(last); - sockets++; - } - } - } - last = rp->rcb_socket; - } - if (last) { - if (sbappendaddr(&last->so_rcv, src, - m, (struct mbuf *)0) == 0) - m_freem(m); - else { - sorwakeup(last); - sockets++; - } - } else - m_freem(m); -} - -/*ARGSUSED*/ -void -raw_ctlinput(cmd, arg, dummy) - int cmd; - struct sockaddr *arg; - void *dummy; -{ - - if (cmd < 0 || cmd > PRC_NCMDS) - return; - /* INCOMPLETE */ -} - -/*ARGSUSED*/ -int -raw_usrreq(so, req, m, nam, control) - struct socket *so; - int req; - struct mbuf *m, *nam, *control; -{ - register struct rawcb *rp = sotorawcb(so); - register int error = 0; - int len; - - if (req == PRU_CONTROL) - return (EOPNOTSUPP); - if (control && control->m_len) { - error = EOPNOTSUPP; - goto release; - } - if (rp == 0) { - error = EINVAL; - goto release; - } - switch (req) { - - /* - * Allocate a raw control block and fill in the - * necessary info to allow packets to be routed to - * the appropriate raw interface routine. - */ - case PRU_ATTACH: - if ((so->so_state & SS_PRIV) == 0) { - error = EACCES; - break; - } - error = raw_attach(so, (int)nam); - break; - - /* - * Destroy state just before socket deallocation. - * Flush data or not depending on the options. - */ - case PRU_DETACH: - if (rp == 0) { - error = ENOTCONN; - break; - } - raw_detach(rp); - break; - - /* - * If a socket isn't bound to a single address, - * the raw input routine will hand it anything - * within that protocol family (assuming there's - * nothing else around it should go to). - */ - case PRU_CONNECT: - error = EINVAL; -#if 0 - if (rp->rcb_faddr) { - error = EISCONN; - break; - } - nam = m_copym(nam, 0, M_COPYALL, M_WAIT); - rp->rcb_faddr = mtod(nam, struct sockaddr *); - soisconnected(so); -#endif - break; - - case PRU_BIND: - error = EINVAL; -#if 0 - if (rp->rcb_laddr) { - error = EINVAL; /* XXX */ - break; - } - error = raw_bind(so, nam); -#endif - break; - - case PRU_CONNECT2: - error = EOPNOTSUPP; - goto release; - - case PRU_DISCONNECT: - if (rp->rcb_faddr == 0) { - error = ENOTCONN; - break; - } - raw_disconnect(rp); - soisdisconnected(so); - break; - - /* - * Mark the connection as being incapable of further input. - */ - case PRU_SHUTDOWN: - socantsendmore(so); - break; - - /* - * Ship a packet out. The appropriate raw output - * routine handles any massaging necessary. - */ - case PRU_SEND: - if (nam) { - if (rp->rcb_faddr) { - error = EISCONN; - break; - } - rp->rcb_faddr = mtod(nam, struct sockaddr *); - } else if (rp->rcb_faddr == 0) { - error = ENOTCONN; - break; - } - error = (*so->so_proto->pr_output)(m, so); - m = NULL; - if (nam) - rp->rcb_faddr = 0; - break; - - case PRU_ABORT: - raw_disconnect(rp); - sofree(so); - soisdisconnected(so); - break; - - case PRU_SENSE: - /* - * stat: don't bother with a blocksize. - */ - return (0); - - /* - * Not supported. - */ - case PRU_RCVOOB: - case PRU_RCVD: - return(EOPNOTSUPP); - - case PRU_LISTEN: - case PRU_ACCEPT: - case PRU_SENDOOB: - error = EOPNOTSUPP; - break; - - case PRU_SOCKADDR: - if (rp->rcb_laddr == 0) { - error = EINVAL; - break; - } - len = rp->rcb_laddr->sa_len; - bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); - nam->m_len = len; - break; - - case PRU_PEERADDR: - if (rp->rcb_faddr == 0) { - error = ENOTCONN; - break; - } - len = rp->rcb_faddr->sa_len; - bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); - nam->m_len = len; - break; - - default: - panic("raw_usrreq"); - } -release: - if (m != NULL) - m_freem(m); - return (error); -} diff --git a/c/src/exec/libnetworking/net/route.c b/c/src/exec/libnetworking/net/route.c deleted file mode 100644 index 683ddafee9..0000000000 --- a/c/src/exec/libnetworking/net/route.c +++ /dev/null @@ -1,959 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1991, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)route.c 8.2 (Berkeley) 11/15/93 - * $Id$ - */ - -#include "opt_mrouting.h" - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/domain.h> -#include <sys/protosw.h> -#include <sys/ioctl.h> - -#include <net/if.h> -#include <net/route.h> -#include <net/raw_cb.h> - -#include <netinet/in.h> -#include <netinet/in_var.h> -#include <netinet/ip_mroute.h> - -#define SA(p) ((struct sockaddr *)(p)) - -struct route_cb route_cb; -static struct rtstat rtstat; -struct radix_node_head *rt_tables[AF_MAX+1]; - -static int rttrash; /* routes not in table but not freed */ - -static void rt_maskedcopy __P((struct sockaddr *, - struct sockaddr *, struct sockaddr *)); -static void rtable_init __P((void **)); - -static void -rtable_init(table) - void **table; -{ - struct domain *dom; - for (dom = domains; dom; dom = dom->dom_next) - if (dom->dom_rtattach) - dom->dom_rtattach(&table[dom->dom_family], - dom->dom_rtoffset); -} - -void -route_init() -{ - rn_init(); /* initialize all zeroes, all ones, mask table */ - rtable_init((void **)rt_tables); -} - -/* - * Packet routing routines. - */ -void -rtalloc(ro) - register struct route *ro; -{ - if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) - return; /* XXX */ - ro->ro_rt = rtalloc1(&ro->ro_dst, 1, 0UL); -} - -void -rtalloc_ign(ro, ignore) - register struct route *ro; - u_long ignore; -{ - if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) - return; /* XXX */ - ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore); -} - -/* - * Look up the route that matches the address given - * Or, at least try.. Create a cloned route if needed. - */ -struct rtentry * -rtalloc1(dst, report, ignflags) - register struct sockaddr *dst; - int report; - u_long ignflags; -{ - register struct radix_node_head *rnh = rt_tables[dst->sa_family]; - register struct rtentry *rt; - register struct radix_node *rn; - struct rtentry *newrt = 0; - struct rt_addrinfo info; - u_long nflags; - int s = splnet(), err = 0, msgtype = RTM_MISS; - - /* - * Look up the address in the table for that Address Family - */ - if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && - ((rn->rn_flags & RNF_ROOT) == 0)) { - /* - * If we find it and it's not the root node, then - * get a refernce on the rtentry associated. - */ - newrt = rt = (struct rtentry *)rn; - nflags = rt->rt_flags & ~ignflags; - if (report && (nflags & (RTF_CLONING | RTF_PRCLONING))) { - /* - * We are apparently adding (report = 0 in delete). - * If it requires that it be cloned, do so. - * (This implies it wasn't a HOST route.) - */ - err = rtrequest(RTM_RESOLVE, dst, SA(0), - SA(0), 0, &newrt); - if (err) { - /* - * If the cloning didn't succeed, maybe - * what we have will do. Return that. - */ - newrt = rt; - rt->rt_refcnt++; - goto miss; - } - if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { - /* - * If the new route specifies it be - * externally resolved, then go do that. - */ - msgtype = RTM_RESOLVE; - goto miss; - } - } else - rt->rt_refcnt++; - } else { - /* - * Either we hit the root or couldn't find any match, - * Which basically means - * "caint get there frm here" - */ - rtstat.rts_unreach++; - miss: if (report) { - /* - * If required, report the failure to the supervising - * Authorities. - * For a delete, this is not an error. (report == 0) - */ - bzero((caddr_t)&info, sizeof(info)); - info.rti_info[RTAX_DST] = dst; - rt_missmsg(msgtype, &info, 0, err); - } - } - splx(s); - return (newrt); -} - -void -rtfree(rt) - register struct rtentry *rt; -{ - register struct radix_node_head *rnh = - rt_tables[rt_key(rt)->sa_family]; - register struct ifaddr *ifa; - - if (rt == 0 || rnh == 0) - panic("rtfree"); - rt->rt_refcnt--; - if(rnh->rnh_close && rt->rt_refcnt == 0) { - rnh->rnh_close((struct radix_node *)rt, rnh); - } - if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { - if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) - panic ("rtfree 2"); - rttrash--; - if (rt->rt_refcnt < 0) { - printf("rtfree: %p not freed (neg refs)\n", rt); - return; - } - ifa = rt->rt_ifa; - IFAFREE(ifa); - if (rt->rt_parent) { - RTFREE(rt->rt_parent); - } - Free(rt_key(rt)); - Free(rt); - } -} - -void -ifafree(ifa) - register struct ifaddr *ifa; -{ - if (ifa == NULL) - panic("ifafree"); - if (ifa->ifa_refcnt == 0) - free(ifa, M_IFADDR); - else - ifa->ifa_refcnt--; -} - -/* - * Force a routing table entry to the specified - * destination to go through the given gateway. - * Normally called as a result of a routing redirect - * message from the network layer. - * - * N.B.: must be called at splnet - * - */ -void -rtredirect(dst, gateway, netmask, flags, src, rtp) - struct sockaddr *dst, *gateway, *netmask, *src; - int flags; - struct rtentry **rtp; -{ - register struct rtentry *rt; - int error = 0; - short *stat = 0; - struct rt_addrinfo info; - struct ifaddr *ifa; - - /* verify the gateway is directly reachable */ - if ((ifa = ifa_ifwithnet(gateway)) == 0) { - error = ENETUNREACH; - goto out; - } - rt = rtalloc1(dst, 0, 0UL); - /* - * If the redirect isn't from our current router for this dst, - * it's either old or wrong. If it redirects us to ourselves, - * we have a routing loop, perhaps as a result of an interface - * going down recently. - */ -#define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) - if (!(flags & RTF_DONE) && rt && - (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) - error = EINVAL; - else if (ifa_ifwithaddr(gateway)) - error = EHOSTUNREACH; - if (error) - goto done; - /* - * Create a new entry if we just got back a wildcard entry - * or the the lookup failed. This is necessary for hosts - * which use routing redirects generated by smart gateways - * to dynamically build the routing tables. - */ - if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) - goto create; - /* - * Don't listen to the redirect if it's - * for a route to an interface. - */ - if (rt->rt_flags & RTF_GATEWAY) { - if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { - /* - * Changing from route to net => route to host. - * Create new route, rather than smashing route to net. - */ - create: - flags |= RTF_GATEWAY | RTF_DYNAMIC; - error = rtrequest((int)RTM_ADD, dst, gateway, - netmask, flags, - (struct rtentry **)0); - stat = &rtstat.rts_dynamic; - } else { - /* - * Smash the current notion of the gateway to - * this destination. Should check about netmask!!! - */ - rt->rt_flags |= RTF_MODIFIED; - flags |= RTF_MODIFIED; - stat = &rtstat.rts_newgateway; - rt_setgate(rt, rt_key(rt), gateway); - } - } else - error = EHOSTUNREACH; -done: - if (rt) { - if (rtp && !error) - *rtp = rt; - else - rtfree(rt); - } -out: - if (error) - rtstat.rts_badredirect++; - else if (stat != NULL) - (*stat)++; - bzero((caddr_t)&info, sizeof(info)); - info.rti_info[RTAX_DST] = dst; - info.rti_info[RTAX_GATEWAY] = gateway; - info.rti_info[RTAX_NETMASK] = netmask; - info.rti_info[RTAX_AUTHOR] = src; - rt_missmsg(RTM_REDIRECT, &info, flags, error); -} - -/* -* Routing table ioctl interface. -*/ -int -rtioctl(req, data, p) - int req; - caddr_t data; - struct proc *p; -{ -#ifdef INET - /* Multicast goop, grrr... */ -#ifdef MROUTING - return mrt_ioctl(req, data); -#else - return mrt_ioctl(req, data, p); -#endif -#else /* INET */ - return ENXIO; -#endif /* INET */ -} - -struct ifaddr * -ifa_ifwithroute(flags, dst, gateway) - int flags; - struct sockaddr *dst, *gateway; -{ - register struct ifaddr *ifa; - if ((flags & RTF_GATEWAY) == 0) { - /* - * If we are adding a route to an interface, - * and the interface is a pt to pt link - * we should search for the destination - * as our clue to the interface. Otherwise - * we can use the local address. - */ - ifa = 0; - if (flags & RTF_HOST) { - ifa = ifa_ifwithdstaddr(dst); - } - if (ifa == 0) - ifa = ifa_ifwithaddr(gateway); - } else { - /* - * If we are adding a route to a remote net - * or host, the gateway may still be on the - * other end of a pt to pt link. - */ - ifa = ifa_ifwithdstaddr(gateway); - } - if (ifa == 0) - ifa = ifa_ifwithnet(gateway); - if (ifa == 0) { - struct rtentry *rt = rtalloc1(dst, 0, 0UL); - if (rt == 0) - return (0); - rt->rt_refcnt--; - if ((ifa = rt->rt_ifa) == 0) - return (0); - } - if (ifa->ifa_addr->sa_family != dst->sa_family) { - struct ifaddr *oifa = ifa; - ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); - if (ifa == 0) - ifa = oifa; - } - return (ifa); -} - -#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) - -static int rt_fixdelete(struct radix_node *, void *); -static int rt_fixchange(struct radix_node *, void *); - -struct rtfc_arg { - struct rtentry *rt0; - struct radix_node_head *rnh; -}; - -/* - * Do appropriate manipulations of a routing tree given - * all the bits of info needed - */ -int -rtrequest(req, dst, gateway, netmask, flags, ret_nrt) - int req, flags; - struct sockaddr *dst, *gateway, *netmask; - struct rtentry **ret_nrt; -{ - int s = splnet(); int error = 0; - register struct rtentry *rt; - register struct radix_node *rn; - register struct radix_node_head *rnh; - struct ifaddr *ifa; - struct sockaddr *ndst; -#define senderr(x) { error = x ; goto bad; } - - /* - * Find the correct routing tree to use for this Address Family - */ - if ((rnh = rt_tables[dst->sa_family]) == 0) - senderr(ESRCH); - /* - * If we are adding a host route then we don't want to put - * a netmask in the tree - */ - if (flags & RTF_HOST) - netmask = 0; - switch (req) { - case RTM_DELETE: - /* - * Remove the item from the tree and return it. - * Complain if it is not there and do no more processing. - */ - if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0) - senderr(ESRCH); - if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) - panic ("rtrequest delete"); - rt = (struct rtentry *)rn; - - /* - * Now search what's left of the subtree for any cloned - * routes which might have been formed from this node. - */ - if ((rt->rt_flags & RTF_PRCLONING) && netmask) { - rnh->rnh_walktree_from(rnh, dst, netmask, - rt_fixdelete, rt); - } - - /* - * Remove any external references we may have. - * This might result in another rtentry being freed if - * we held it's last reference. - */ - if (rt->rt_gwroute) { - rt = rt->rt_gwroute; - RTFREE(rt); - (rt = (struct rtentry *)rn)->rt_gwroute = 0; - } - - /* - * NB: RTF_UP must be set during the search above, - * because we might delete the last ref, causing - * rt to get freed prematurely. - */ - rt->rt_flags &= ~RTF_UP; - - /* - * If there is llinfo or similar associated with the - * route, give the interface a chance to deal with it.. - */ - if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) - ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); - rttrash++; - /* - * If the caller wants it, then it can have it, but it's up to it - * to free the rtentry as we won't be doing it. - */ - if (ret_nrt) - *ret_nrt = rt; - else if (rt->rt_refcnt <= 0) { - rt->rt_refcnt++; /* make a 1->0 transition */ - rtfree(rt); - } - break; - - case RTM_RESOLVE: - if (ret_nrt == 0 || (rt = *ret_nrt) == 0) - senderr(EINVAL); - ifa = rt->rt_ifa; - flags = rt->rt_flags & - ~(RTF_CLONING | RTF_PRCLONING | RTF_STATIC); - flags |= RTF_WASCLONED; - gateway = rt->rt_gateway; - if ((netmask = rt->rt_genmask) == 0) - flags |= RTF_HOST; - goto makeroute; - - case RTM_ADD: - if ((flags & RTF_GATEWAY) && !gateway) - panic("rtrequest: GATEWAY but no gateway"); - - if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0) - senderr(ENETUNREACH); - - makeroute: - R_Malloc(rt, struct rtentry *, sizeof(*rt)); - if (rt == 0) - senderr(ENOBUFS); - Bzero(rt, sizeof(*rt)); - rt->rt_flags = RTF_UP | flags; - if ((error = rt_setgate(rt, dst, gateway))) { - Free(rt); - senderr(error); - } - ndst = rt_key(rt); - if (netmask) { - rt_maskedcopy(dst, ndst, netmask); - } else - Bcopy(dst, ndst, dst->sa_len); - - /* - * This moved from below so that rnh->rnh_addaddr() can - * examine the ifa and ifp if it so desires. - */ - ifa->ifa_refcnt++; - rt->rt_ifa = ifa; - rt->rt_ifp = ifa->ifa_ifp; - - rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, - rnh, rt->rt_nodes); - if (rn == 0) { - struct rtentry *rt2; - /* - * Uh-oh, we already have one of these in the tree. - * We do a special hack: if the route that's already - * there was generated by the protocol-cloning - * mechanism, then we just blow it away and retry - * the insertion of the new one. - */ - rt2 = rtalloc1(dst, 0, RTF_PRCLONING); - if (rt2 && rt2->rt_parent) { - rtrequest(RTM_DELETE, - (struct sockaddr *)rt_key(rt2), - rt2->rt_gateway, - rt_mask(rt2), rt2->rt_flags, 0); - RTFREE(rt2); - rn = rnh->rnh_addaddr((caddr_t)ndst, - (caddr_t)netmask, - rnh, rt->rt_nodes); - } else if (rt2) { - RTFREE(rt2); - } - } - - if (rn == 0) { - if (rt->rt_gwroute) - rtfree(rt->rt_gwroute); - if (rt->rt_ifa) { - IFAFREE(rt->rt_ifa); - } - Free(rt_key(rt)); - Free(rt); - senderr(EEXIST); - } - rt->rt_parent = 0; - - if (req == RTM_RESOLVE) { - rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ - if ((*ret_nrt)->rt_flags & RTF_PRCLONING) { - rt->rt_parent = (*ret_nrt); - (*ret_nrt)->rt_refcnt++; - } - } - if (ifa->ifa_rtrequest) - ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0)); - /* - * We repeat the same procedure from rt_setgate() here because - * it doesn't fire when we call it there because the node - * hasn't been added to the tree yet. - */ - if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) { - struct rtfc_arg arg; - arg.rnh = rnh; - arg.rt0 = rt; - rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt), - rt_fixchange, &arg); - } - - if (ret_nrt) { - *ret_nrt = rt; - rt->rt_refcnt++; - } - break; - } -bad: - splx(s); - return (error); -} - -/* - * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family'' - * (i.e., the routes related to it by the operation of cloning). This - * routine is iterated over all potential former-child-routes by way of - * rnh->rnh_walktree_from() above, and those that actually are children of - * the late parent (passed in as VP here) are themselves deleted. - */ -static int -rt_fixdelete(struct radix_node *rn, void *vp) -{ - struct rtentry *rt = (struct rtentry *)rn; - struct rtentry *rt0 = vp; - - if (rt->rt_parent == rt0 && !(rt->rt_flags & RTF_PINNED)) { - return rtrequest(RTM_DELETE, rt_key(rt), - (struct sockaddr *)0, rt_mask(rt), - rt->rt_flags, (struct rtentry **)0); - } - return 0; -} - -/* - * This routine is called from rt_setgate() to do the analogous thing for - * adds and changes. There is the added complication in this case of a - * middle insert; i.e., insertion of a new network route between an older - * network route and (cloned) host routes. For this reason, a simple check - * of rt->rt_parent is insufficient; each candidate route must be tested - * against the (mask, value) of the new route (passed as before in vp) - * to see if the new route matches it. Unfortunately, this has the obnoxious - * property of also triggering for insertion /above/ a pre-existing network - * route and clones. Sigh. This may be fixed some day. - * - * XXX - it may be possible to do fixdelete() for changes and reserve this - * routine just for adds. I'm not sure why I thought it was necessary to do - * changes this way. - */ -#ifdef DEBUG -int rtfcdebug = 0; -#endif - -static int -rt_fixchange(struct radix_node *rn, void *vp) -{ - struct rtentry *rt = (struct rtentry *)rn; - struct rtfc_arg *ap = vp; - struct rtentry *rt0 = ap->rt0; - struct radix_node_head *rnh = ap->rnh; - u_char *xk1, *xm1, *xk2; - int i, len; - -#ifdef DEBUG - if (rtfcdebug) - printf("rt_fixchange: rt %p, rt0 %p\n", rt, rt0); -#endif - - if (!rt->rt_parent || (rt->rt_flags & RTF_PINNED)) { -#ifdef DEBUG - if(rtfcdebug) printf("no parent or pinned\n"); -#endif - return 0; - } - - if (rt->rt_parent == rt0) { -#ifdef DEBUG - if(rtfcdebug) printf("parent match\n"); -#endif - return rtrequest(RTM_DELETE, rt_key(rt), - (struct sockaddr *)0, rt_mask(rt), - rt->rt_flags, (struct rtentry **)0); - } - - /* - * There probably is a function somewhere which does this... - * if not, there should be. - */ - len = imin(((struct sockaddr *)rt_key(rt0))->sa_len, - ((struct sockaddr *)rt_key(rt))->sa_len); - - xk1 = (u_char *)rt_key(rt0); - xm1 = (u_char *)rt_mask(rt0); - xk2 = (u_char *)rt_key(rt); - - for (i = rnh->rnh_treetop->rn_off; i < len; i++) { - if ((xk2[i] & xm1[i]) != xk1[i]) { -#ifdef DEBUG - if(rtfcdebug) printf("no match\n"); -#endif - return 0; - } - } - - /* - * OK, this node is a clone, and matches the node currently being - * changed/added under the node's mask. So, get rid of it. - */ -#ifdef DEBUG - if(rtfcdebug) printf("deleting\n"); -#endif - return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, - rt_mask(rt), rt->rt_flags, (struct rtentry **)0); -} - -int -rt_setgate(rt0, dst, gate) - struct rtentry *rt0; - struct sockaddr *dst, *gate; -{ - caddr_t new, old; - int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); - register struct rtentry *rt = rt0; - struct radix_node_head *rnh = rt_tables[dst->sa_family]; - - /* - * A host route with the destination equal to the gateway - * will interfere with keeping LLINFO in the routing - * table, so disallow it. - */ - if (((rt0->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_LLINFO)) == - (RTF_HOST|RTF_GATEWAY)) && - (dst->sa_len == gate->sa_len) && - (bcmp(dst, gate, dst->sa_len) == 0)) { - /* - * The route might already exist if this is an RTM_CHANGE - * or a routing redirect, so try to delete it. - */ - if (rt_key(rt0)) - rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt0), - rt0->rt_gateway, rt_mask(rt0), rt0->rt_flags, 0); - return EADDRNOTAVAIL; - } - - if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) { - old = (caddr_t)rt_key(rt); - R_Malloc(new, caddr_t, dlen + glen); - if (new == 0) - return ENOBUFS; - rt->rt_nodes->rn_key = new; - } else { - new = rt->rt_nodes->rn_key; - old = 0; - } - Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); - if (old) { - Bcopy(dst, new, dlen); - Free(old); - } - if (rt->rt_gwroute) { - rt = rt->rt_gwroute; RTFREE(rt); - rt = rt0; rt->rt_gwroute = 0; - } - /* - * Cloning loop avoidance: - * In the presence of protocol-cloning and bad configuration, - * it is possible to get stuck in bottomless mutual recursion - * (rtrequest rt_setgate rtalloc1). We avoid this by not allowing - * protocol-cloning to operate for gateways (which is probably the - * correct choice anyway), and avoid the resulting reference loops - * by disallowing any route to run through itself as a gateway. - * This is obviuosly mandatory when we get rt->rt_output(). - */ - if (rt->rt_flags & RTF_GATEWAY) { - rt->rt_gwroute = rtalloc1(gate, 1, RTF_PRCLONING); - if (rt->rt_gwroute == rt) { - RTFREE(rt->rt_gwroute); - rt->rt_gwroute = 0; - return EDQUOT; /* failure */ - } - } - - /* - * This isn't going to do anything useful for host routes, so - * don't bother. Also make sure we have a reasonable mask - * (we don't yet have one during adds). - */ - if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) { - struct rtfc_arg arg; - arg.rnh = rnh; - arg.rt0 = rt; - rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt), - rt_fixchange, &arg); - } - - return 0; -} - -static void -rt_maskedcopy(src, dst, netmask) - struct sockaddr *src, *dst, *netmask; -{ - register u_char *cp1 = (u_char *)src; - register u_char *cp2 = (u_char *)dst; - register u_char *cp3 = (u_char *)netmask; - u_char *cplim = cp2 + *cp3; - u_char *cplim2 = cp2 + *cp1; - - *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ - cp3 += 2; - if (cplim > cplim2) - cplim = cplim2; - while (cp2 < cplim) - *cp2++ = *cp1++ & *cp3++; - if (cp2 < cplim2) - bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); -} - -/* - * Set up a routing table entry, normally - * for an interface. - */ -int -rtinit(ifa, cmd, flags) - register struct ifaddr *ifa; - int cmd, flags; -{ - register struct rtentry *rt; - register struct sockaddr *dst; - register struct sockaddr *deldst; - struct mbuf *m = 0; - struct rtentry *nrt = 0; - int error; - - dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; - /* - * If it's a delete, check that if it exists, it's on the correct - * interface or we might scrub a route to another ifa which would - * be confusing at best and possibly worse. - */ - if (cmd == RTM_DELETE) { - /* - * It's a delete, so it should already exist.. - * If it's a net, mask off the host bits - * (Assuming we have a mask) - */ - if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { - m = m_get(M_WAIT, MT_SONAME); - deldst = mtod(m, struct sockaddr *); - rt_maskedcopy(dst, deldst, ifa->ifa_netmask); - dst = deldst; - } - /* - * Get an rtentry that is in the routing tree and - * contains the correct info. (if this fails we can't get there). - * We set "report" to FALSE so that if it doesn't exist, - * it doesn't report an error or clone a route, etc. etc. - */ - rt = rtalloc1(dst, 0, 0UL); - if (rt) { - /* - * Ok so we found the rtentry. it has an extra reference - * for us at this stage. we won't need that so - * lop that off now. - */ - rt->rt_refcnt--; - if (rt->rt_ifa != ifa) { - /* - * If the interface in the rtentry doesn't match - * the interface we are using, then we don't - * want to delete it, so return an error. - * This seems to be the only point of - * this whole RTM_DELETE clause. - */ - if (m) - (void) m_free(m); - return (flags & RTF_HOST ? EHOSTUNREACH - : ENETUNREACH); - } - } - /* XXX */ -#if 0 - else { - /* - * One would think that as we are deleting, and we know - * it doesn't exist, we could just return at this point - * with an "ELSE" clause, but apparently not.. - */ - return (flags & RTF_HOST ? EHOSTUNREACH - : ENETUNREACH); - } -#endif - } - /* - * Do the actual request - */ - error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask, - flags | ifa->ifa_flags, &nrt); - if (m) - (void) m_free(m); - /* - * If we are deleting, and we found an entry, then - * it's been removed from the tree.. now throw it away. - */ - if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) { - /* - * notify any listenning routing agents of the change - */ - rt_newaddrmsg(cmd, ifa, error, nrt); - if (rt->rt_refcnt <= 0) { - rt->rt_refcnt++; /* need a 1->0 transition to free */ - rtfree(rt); - } - } - - /* - * We are adding, and we have a returned routing entry. - * We need to sanity check the result. - */ - if (cmd == RTM_ADD && error == 0 && (rt = nrt)) { - /* - * We just wanted to add it.. we don't actually need a reference - */ - rt->rt_refcnt--; - /* - * If it came back with an unexpected interface, then it must - * have already existed or something. (XXX) - */ - if (rt->rt_ifa != ifa) { - printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, - rt->rt_ifa); - /* - * Ask that the route we got back be removed - * from the routing tables as we are trying - * to supersede it. - */ - if (rt->rt_ifa->ifa_rtrequest) - rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); - /* - * Remove the referenve to the it's ifaddr. - */ - IFAFREE(rt->rt_ifa); - /* - * And substitute in references to the ifaddr - * we are adding. - */ - rt->rt_ifa = ifa; - rt->rt_ifp = ifa->ifa_ifp; - ifa->ifa_refcnt++; - /* - * Now add it to the routing table - * XXX could we have just left it? - * as it might have been in the right place.. - */ - if (ifa->ifa_rtrequest) - ifa->ifa_rtrequest(RTM_ADD, rt, SA(0)); - } - /* - * notify any listenning routing agents of the change - */ - rt_newaddrmsg(cmd, ifa, error, nrt); - } - return (error); -} diff --git a/c/src/exec/libnetworking/net/route.h b/c/src/exec/libnetworking/net/route.h deleted file mode 100644 index 6099b424c3..0000000000 --- a/c/src/exec/libnetworking/net/route.h +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)route.h 8.3 (Berkeley) 4/19/94 - * $Id$ - */ - -#ifndef _NET_ROUTE_H_ -#define _NET_ROUTE_H_ - -/* - * Kernel resident routing tables. - * - * The routing tables are initialized when interface addresses - * are set by making entries for all directly connected interfaces. - */ - -/* - * A route consists of a destination address and a reference - * to a routing entry. These are often held by protocols - * in their control blocks, e.g. inpcb. - */ -struct route { - struct rtentry *ro_rt; - struct sockaddr ro_dst; -}; - -/* - * These numbers are used by reliable protocols for determining - * retransmission behavior and are included in the routing structure. - */ -struct rt_metrics { - u_long rmx_locks; /* Kernel must leave these values alone */ - u_long rmx_mtu; /* MTU for this path */ - u_long rmx_hopcount; /* max hops expected */ - u_long rmx_expire; /* lifetime for route, e.g. redirect */ - u_long rmx_recvpipe; /* inbound delay-bandwidth product */ - u_long rmx_sendpipe; /* outbound delay-bandwidth product */ - u_long rmx_ssthresh; /* outbound gateway buffer limit */ - u_long rmx_rtt; /* estimated round trip time */ - u_long rmx_rttvar; /* estimated rtt variance */ - u_long rmx_pksent; /* packets sent using this route */ - u_long rmx_filler[4]; /* will be used for T/TCP later */ -}; - -/* - * rmx_rtt and rmx_rttvar are stored as microseconds; - * RTTTOPRHZ(rtt) converts to a value suitable for use - * by a protocol slowtimo counter. - */ -#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */ -#define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ)) - -/* - * XXX kernel function pointer `rt_output' is visible to applications. - */ -struct mbuf; - -/* - * We distinguish between routes to hosts and routes to networks, - * preferring the former if available. For each route we infer - * the interface to use from the gateway address supplied when - * the route was entered. Routes that forward packets through - * gateways are marked so that the output routines know to address the - * gateway rather than the ultimate destination. - */ -#ifndef RNF_NORMAL -#include <net/radix.h> -#endif -struct rtentry { - struct radix_node rt_nodes[2]; /* tree glue, and other values */ -#define rt_key(r) ((struct sockaddr *)((r)->rt_nodes->rn_key)) -#define rt_mask(r) ((struct sockaddr *)((r)->rt_nodes->rn_mask)) - struct sockaddr *rt_gateway; /* value */ - short rt_filler; /* was short flags field */ - short rt_refcnt; /* # held references */ - u_long rt_flags; /* up/down?, host/net */ - struct ifnet *rt_ifp; /* the answer: interface to use */ - struct ifaddr *rt_ifa; /* the answer: interface to use */ - struct sockaddr *rt_genmask; /* for generation of cloned routes */ - caddr_t rt_llinfo; /* pointer to link level info cache */ - struct rt_metrics rt_rmx; /* metrics used by rx'ing protocols */ - struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */ - int (*rt_output) __P((struct ifnet *, struct mbuf *, - struct sockaddr *, struct rtentry *)); - /* output routine for this (rt,if) */ - struct rtentry *rt_parent; /* cloning parent of this route */ - void *rt_filler2; /* more filler */ -}; - -/* - * Following structure necessary for 4.3 compatibility; - * We should eventually move it to a compat file. - */ -struct ortentry { - u_long rt_hash; /* to speed lookups */ - struct sockaddr rt_dst; /* key */ - struct sockaddr rt_gateway; /* value */ - short rt_flags; /* up/down?, host/net */ - short rt_refcnt; /* # held references */ - u_long rt_use; /* raw # packets forwarded */ - struct ifnet *rt_ifp; /* the answer: interface to use */ -}; - -#define rt_use rt_rmx.rmx_pksent - -#define RTF_UP 0x1 /* route usable */ -#define RTF_GATEWAY 0x2 /* destination is a gateway */ -#define RTF_HOST 0x4 /* host entry (net otherwise) */ -#define RTF_REJECT 0x8 /* host or net unreachable */ -#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */ -#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */ -#define RTF_DONE 0x40 /* message confirmed */ -/* 0x80 unused */ -#define RTF_CLONING 0x100 /* generate new routes on use */ -#define RTF_XRESOLVE 0x200 /* external daemon resolves name */ -#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */ -#define RTF_STATIC 0x800 /* manually added */ -#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */ -#define RTF_PROTO2 0x4000 /* protocol specific routing flag */ -#define RTF_PROTO1 0x8000 /* protocol specific routing flag */ - -#define RTF_PRCLONING 0x10000 /* protocol requires cloning */ -#define RTF_WASCLONED 0x20000 /* route generated through cloning */ -#define RTF_PROTO3 0x40000 /* protocol specific routing flag */ -/* 0x80000 unused */ -#define RTF_PINNED 0x100000 /* future use */ -#define RTF_LOCAL 0x200000 /* route represents a local address */ -#define RTF_BROADCAST 0x400000 /* route represents a bcast address */ -#define RTF_MULTICAST 0x800000 /* route represents a mcast address */ - /* 0x1000000 and up unassigned */ - -/* - * Routing statistics. - */ -struct rtstat { - short rts_badredirect; /* bogus redirect calls */ - short rts_dynamic; /* routes created by redirects */ - short rts_newgateway; /* routes modified by redirects */ - short rts_unreach; /* lookups which failed */ - short rts_wildcard; /* lookups satisfied by a wildcard */ -}; -/* - * Structures for routing messages. - */ -struct rt_msghdr { - u_short rtm_msglen; /* to skip over non-understood messages */ - u_char rtm_version; /* future binary compatibility */ - u_char rtm_type; /* message type */ - u_short rtm_index; /* index for associated ifp */ - int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ - int rtm_addrs; /* bitmask identifying sockaddrs in msg */ - pid_t rtm_pid; /* identify sender */ - int rtm_seq; /* for sender to identify action */ - int rtm_errno; /* why failed */ - int rtm_use; /* from rtentry */ - u_long rtm_inits; /* which metrics we are initializing */ - struct rt_metrics rtm_rmx; /* metrics themselves */ -}; - -#define RTM_VERSION 5 /* Up the ante and ignore older versions */ - -#define RTM_ADD 0x1 /* Add Route */ -#define RTM_DELETE 0x2 /* Delete Route */ -#define RTM_CHANGE 0x3 /* Change Metrics or flags */ -#define RTM_GET 0x4 /* Report Metrics */ -#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */ -#define RTM_REDIRECT 0x6 /* Told to use different route */ -#define RTM_MISS 0x7 /* Lookup failed on this address */ -#define RTM_LOCK 0x8 /* fix specified metrics */ -#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */ -#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */ -#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */ -#define RTM_NEWADDR 0xc /* address being added to iface */ -#define RTM_DELADDR 0xd /* address being removed from iface */ -#define RTM_IFINFO 0xe /* iface going up/down etc. */ - -#define RTV_MTU 0x1 /* init or lock _mtu */ -#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */ -#define RTV_EXPIRE 0x4 /* init or lock _hopcount */ -#define RTV_RPIPE 0x8 /* init or lock _recvpipe */ -#define RTV_SPIPE 0x10 /* init or lock _sendpipe */ -#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */ -#define RTV_RTT 0x40 /* init or lock _rtt */ -#define RTV_RTTVAR 0x80 /* init or lock _rttvar */ - -/* - * Bitmask values for rtm_addr. - */ -#define RTA_DST 0x1 /* destination sockaddr present */ -#define RTA_GATEWAY 0x2 /* gateway sockaddr present */ -#define RTA_NETMASK 0x4 /* netmask sockaddr present */ -#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */ -#define RTA_IFP 0x10 /* interface name sockaddr present */ -#define RTA_IFA 0x20 /* interface addr sockaddr present */ -#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */ -#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */ - -/* - * Index offsets for sockaddr array for alternate internal encoding. - */ -#define RTAX_DST 0 /* destination sockaddr present */ -#define RTAX_GATEWAY 1 /* gateway sockaddr present */ -#define RTAX_NETMASK 2 /* netmask sockaddr present */ -#define RTAX_GENMASK 3 /* cloning mask sockaddr present */ -#define RTAX_IFP 4 /* interface name sockaddr present */ -#define RTAX_IFA 5 /* interface addr sockaddr present */ -#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */ -#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */ -#define RTAX_MAX 8 /* size of array to allocate */ - -struct rt_addrinfo { - int rti_addrs; - struct sockaddr *rti_info[RTAX_MAX]; -}; - -struct route_cb { - int ip_count; - int ipx_count; - int ns_count; - int iso_count; - int any_count; -}; - -#ifdef KERNEL -#define RTFREE(rt) \ - do { \ - if ((rt)->rt_refcnt <= 1) \ - rtfree(rt); \ - else \ - (rt)->rt_refcnt--; \ - } while (0) - -extern struct route_cb route_cb; -extern struct rtstat rtstat; -extern struct radix_node_head *rt_tables[AF_MAX+1]; - -void route_init __P((void)); -void rt_ifmsg __P((struct ifnet *)); -void rt_missmsg __P((int, struct rt_addrinfo *, int, int)); -void rt_newaddrmsg __P((int, struct ifaddr *, int, struct rtentry *)); -int rt_setgate __P((struct rtentry *, - struct sockaddr *, struct sockaddr *)); -void rtalloc __P((struct route *)); -void rtalloc_ign __P((struct route *, unsigned long)); -struct rtentry * - rtalloc1 __P((struct sockaddr *, int, unsigned long)); -void rtfree __P((struct rtentry *)); -int rtinit __P((struct ifaddr *, int, int)); -int rtioctl __P((int, caddr_t, struct proc *)); -void rtredirect __P((struct sockaddr *, struct sockaddr *, - struct sockaddr *, int, struct sockaddr *, struct rtentry **)); -int rtrequest __P((int, struct sockaddr *, - struct sockaddr *, struct sockaddr *, int, struct rtentry **)); -#endif - -#endif diff --git a/c/src/exec/libnetworking/net/rtsock.c b/c/src/exec/libnetworking/net/rtsock.c deleted file mode 100644 index 57e777906a..0000000000 --- a/c/src/exec/libnetworking/net/rtsock.c +++ /dev/null @@ -1,829 +0,0 @@ -/* - * Copyright (c) 1988, 1991, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)rtsock.c 8.5 (Berkeley) 11/2/94 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/proc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/domain.h> -#include <sys/protosw.h> - -#include <net/if.h> -#include <net/route.h> -#include <net/raw_cb.h> - -static struct sockaddr route_dst = { 2, PF_ROUTE, }; -static struct sockaddr route_src = { 2, PF_ROUTE, }; -static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, }; -static struct sockproto route_proto = { PF_ROUTE, }; - -struct walkarg { - int w_tmemsize; - int w_op, w_arg; - caddr_t w_tmem; - struct sysctl_req *w_req; -}; - -static struct mbuf * - rt_msg1 __P((int, struct rt_addrinfo *)); -static int rt_msg2 __P((int, - struct rt_addrinfo *, caddr_t, struct walkarg *)); -static int rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); -static int sysctl_dumpentry __P((struct radix_node *rn, void *vw)); -static int sysctl_iflist __P((int af, struct walkarg *w)); -static int route_output __P((struct mbuf *, struct socket *)); -static int route_usrreq __P((struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *)); -static void rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *)); - -/* Sleazy use of local variables throughout file, warning!!!! */ -#define dst info.rti_info[RTAX_DST] -#define gate info.rti_info[RTAX_GATEWAY] -#define netmask info.rti_info[RTAX_NETMASK] -#define genmask info.rti_info[RTAX_GENMASK] -#define ifpaddr info.rti_info[RTAX_IFP] -#define ifaaddr info.rti_info[RTAX_IFA] -#define brdaddr info.rti_info[RTAX_BRD] - -/*ARGSUSED*/ -static int -route_usrreq(so, req, m, nam, control) - register struct socket *so; - int req; - struct mbuf *m, *nam, *control; -{ - register int error = 0; - register struct rawcb *rp = sotorawcb(so); - int s; - - if (req == PRU_ATTACH) { - MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); - so->so_pcb = (caddr_t)rp; - if (so->so_pcb) - bzero(so->so_pcb, sizeof(*rp)); - } - if (req == PRU_DETACH && rp) { - int af = rp->rcb_proto.sp_protocol; - if (af == AF_INET) - route_cb.ip_count--; - else if (af == AF_IPX) - route_cb.ipx_count--; - else if (af == AF_NS) - route_cb.ns_count--; - else if (af == AF_ISO) - route_cb.iso_count--; - route_cb.any_count--; - } - s = splnet(); - error = raw_usrreq(so, req, m, nam, control); - rp = sotorawcb(so); - if (req == PRU_ATTACH && rp) { - int af = rp->rcb_proto.sp_protocol; - if (error) { - free((caddr_t)rp, M_PCB); - splx(s); - return (error); - } - if (af == AF_INET) - route_cb.ip_count++; - else if (af == AF_IPX) - route_cb.ipx_count++; - else if (af == AF_NS) - route_cb.ns_count++; - else if (af == AF_ISO) - route_cb.iso_count++; - rp->rcb_faddr = &route_src; - route_cb.any_count++; - soisconnected(so); - so->so_options |= SO_USELOOPBACK; - } - splx(s); - return (error); -} - -/*ARGSUSED*/ -static int -route_output(m, so) - register struct mbuf *m; - struct socket *so; -{ - register struct rt_msghdr *rtm = 0; - register struct rtentry *rt = 0; - struct rtentry *saved_nrt = 0; - struct radix_node_head *rnh; - struct rt_addrinfo info; - int len, error = 0; - struct ifnet *ifp = 0; - struct ifaddr *ifa = 0; - -#define senderr(e) { error = e; goto flush;} - if (m == 0 || ((m->m_len < sizeof(long)) && - (m = m_pullup(m, sizeof(long))) == 0)) - return (ENOBUFS); - if ((m->m_flags & M_PKTHDR) == 0) - panic("route_output"); - len = m->m_pkthdr.len; - if (len < sizeof(*rtm) || - len != mtod(m, struct rt_msghdr *)->rtm_msglen) { - dst = 0; - senderr(EINVAL); - } - R_Malloc(rtm, struct rt_msghdr *, len); - if (rtm == 0) { - dst = 0; - senderr(ENOBUFS); - } - m_copydata(m, 0, len, (caddr_t)rtm); - if (rtm->rtm_version != RTM_VERSION) { - dst = 0; - senderr(EPROTONOSUPPORT); - } - info.rti_addrs = rtm->rtm_addrs; - if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) { - dst = 0; - senderr(EINVAL); - } - if (dst == 0 || (dst->sa_family >= AF_MAX) - || (gate != 0 && (gate->sa_family >= AF_MAX))) - senderr(EINVAL); - if (genmask) { - struct radix_node *t; - t = rn_addmask((caddr_t)genmask, 0, 1); - if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) - genmask = (struct sockaddr *)(t->rn_key); - else - senderr(ENOBUFS); - } - switch (rtm->rtm_type) { - - case RTM_ADD: - if (gate == 0) - senderr(EINVAL); - error = rtrequest(RTM_ADD, dst, gate, netmask, - rtm->rtm_flags, &saved_nrt); - if (error == 0 && saved_nrt) { - rt_setmetrics(rtm->rtm_inits, - &rtm->rtm_rmx, &saved_nrt->rt_rmx); - saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); - saved_nrt->rt_rmx.rmx_locks |= - (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); - saved_nrt->rt_refcnt--; - saved_nrt->rt_genmask = genmask; - } - break; - - case RTM_DELETE: - error = rtrequest(RTM_DELETE, dst, gate, netmask, - rtm->rtm_flags, &saved_nrt); - if (error == 0) { - if ((rt = saved_nrt)) - rt->rt_refcnt++; - goto report; - } - break; - - case RTM_GET: - case RTM_CHANGE: - case RTM_LOCK: - if ((rnh = rt_tables[dst->sa_family]) == 0) { - senderr(EAFNOSUPPORT); - } else if ((rt = (struct rtentry *) - rnh->rnh_lookup(dst, netmask, rnh))) - rt->rt_refcnt++; - else - senderr(ESRCH); - switch(rtm->rtm_type) { - - case RTM_GET: - report: - dst = rt_key(rt); - gate = rt->rt_gateway; - netmask = rt_mask(rt); - genmask = rt->rt_genmask; - if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { - ifp = rt->rt_ifp; - if (ifp) { - ifpaddr = ifp->if_addrlist->ifa_addr; - ifaaddr = rt->rt_ifa->ifa_addr; - rtm->rtm_index = ifp->if_index; - } else { - ifpaddr = 0; - ifaaddr = 0; - } - } - len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0, - (struct walkarg *)0); - if (len > rtm->rtm_msglen) { - struct rt_msghdr *new_rtm; - R_Malloc(new_rtm, struct rt_msghdr *, len); - if (new_rtm == 0) - senderr(ENOBUFS); - Bcopy(rtm, new_rtm, rtm->rtm_msglen); - Free(rtm); rtm = new_rtm; - } - (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, - (struct walkarg *)0); - rtm->rtm_flags = rt->rt_flags; - rtm->rtm_rmx = rt->rt_rmx; - rtm->rtm_addrs = info.rti_addrs; - break; - - case RTM_CHANGE: - if (gate && (error = rt_setgate(rt, rt_key(rt), gate))) - senderr(error); - - /* - * If they tried to change things but didn't specify - * the required gateway, then just use the old one. - * This can happen if the user tries to change the - * flags on the default route without changing the - * default gateway. Changing flags still doesn't work. - */ - if ((rt->rt_flags & RTF_GATEWAY) && !gate) - gate = rt->rt_gateway; - - /* new gateway could require new ifaddr, ifp; - flags may also be different; ifp may be specified - by ll sockaddr when protocol address is ambiguous */ - if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && - (ifp = ifa->ifa_ifp) && (ifaaddr || gate)) - ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, - ifp); - else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || - (gate && (ifa = ifa_ifwithroute(rt->rt_flags, - rt_key(rt), gate)))) - ifp = ifa->ifa_ifp; - if (ifa) { - register struct ifaddr *oifa = rt->rt_ifa; - if (oifa != ifa) { - if (oifa && oifa->ifa_rtrequest) - oifa->ifa_rtrequest(RTM_DELETE, - rt, gate); - IFAFREE(rt->rt_ifa); - rt->rt_ifa = ifa; - ifa->ifa_refcnt++; - rt->rt_ifp = ifp; - } - } - rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, - &rt->rt_rmx); - if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) - rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); - if (genmask) - rt->rt_genmask = genmask; - /* - * Fall into - */ - case RTM_LOCK: - rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); - rt->rt_rmx.rmx_locks |= - (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); - break; - } - break; - - default: - senderr(EOPNOTSUPP); - } - -flush: - if (rtm) { - if (error) - rtm->rtm_errno = error; - else - rtm->rtm_flags |= RTF_DONE; - } - if (rt) - rtfree(rt); - { - register struct rawcb *rp = 0; - /* - * Check to see if we don't want our own messages. - */ - if ((so->so_options & SO_USELOOPBACK) == 0) { - if (route_cb.any_count <= 1) { - if (rtm) - Free(rtm); - m_freem(m); - return (error); - } - /* There is another listener, so construct message */ - rp = sotorawcb(so); - } - if (rtm) { - m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); - Free(rtm); - } - if (rp) - rp->rcb_proto.sp_family = 0; /* Avoid us */ - if (dst) - route_proto.sp_protocol = dst->sa_family; - raw_input(m, &route_proto, &route_src, &route_dst); - if (rp) - rp->rcb_proto.sp_family = PF_ROUTE; - } - return (error); -} - -static void -rt_setmetrics(which, in, out) - u_long which; - register struct rt_metrics *in, *out; -{ -#define metric(f, e) if (which & (f)) out->e = in->e; - metric(RTV_RPIPE, rmx_recvpipe); - metric(RTV_SPIPE, rmx_sendpipe); - metric(RTV_SSTHRESH, rmx_ssthresh); - metric(RTV_RTT, rmx_rtt); - metric(RTV_RTTVAR, rmx_rttvar); - metric(RTV_HOPCOUNT, rmx_hopcount); - metric(RTV_MTU, rmx_mtu); - metric(RTV_EXPIRE, rmx_expire); -#undef metric -} - -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) -#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) - - -/* - * Extract the addresses of the passed sockaddrs. - * Do a little sanity checking so as to avoid bad memory references. - * This data is derived straight from userland. - */ -static int -rt_xaddrs(cp, cplim, rtinfo) - register caddr_t cp, cplim; - register struct rt_addrinfo *rtinfo; -{ - register struct sockaddr *sa; - register int i; - - bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); - for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { - if ((rtinfo->rti_addrs & (1 << i)) == 0) - continue; - sa = (struct sockaddr *)cp; - /* - * It won't fit. - */ - if ( (cp + sa->sa_len) > cplim ) { - return (EINVAL); - } - - /* - * there are no more.. quit now - * If there are more bits, they are in error. - * I've seen this. route(1) can evidently generate these. - * This causes kernel to core dump. - * for compatibility, If we see this, point to a safe address. - */ - if (sa->sa_len == 0) { - rtinfo->rti_info[i] = &sa_zero; - return (0); /* should be EINVAL but for compat */ - } - - /* accept it */ - rtinfo->rti_info[i] = sa; - ADVANCE(cp, sa); - } - return (0); -} - -static struct mbuf * -rt_msg1(type, rtinfo) - int type; - register struct rt_addrinfo *rtinfo; -{ - register struct rt_msghdr *rtm; - register struct mbuf *m; - register int i; - register struct sockaddr *sa; - int len, dlen; - - m = m_gethdr(M_DONTWAIT, MT_DATA); - if (m == 0) - return (m); - switch (type) { - - case RTM_DELADDR: - case RTM_NEWADDR: - len = sizeof(struct ifa_msghdr); - break; - - case RTM_IFINFO: - len = sizeof(struct if_msghdr); - break; - - default: - len = sizeof(struct rt_msghdr); - } - if (len > MHLEN) - panic("rt_msg1"); - m->m_pkthdr.len = m->m_len = len; - m->m_pkthdr.rcvif = 0; - rtm = mtod(m, struct rt_msghdr *); - bzero((caddr_t)rtm, len); - for (i = 0; i < RTAX_MAX; i++) { - if ((sa = rtinfo->rti_info[i]) == NULL) - continue; - rtinfo->rti_addrs |= (1 << i); - dlen = ROUNDUP(sa->sa_len); - m_copyback(m, len, dlen, (caddr_t)sa); - len += dlen; - } - if (m->m_pkthdr.len != len) { - m_freem(m); - return (NULL); - } - rtm->rtm_msglen = len; - rtm->rtm_version = RTM_VERSION; - rtm->rtm_type = type; - return (m); -} - -static int -rt_msg2(type, rtinfo, cp, w) - int type; - register struct rt_addrinfo *rtinfo; - caddr_t cp; - struct walkarg *w; -{ - register int i; - int len, dlen, second_time = 0; - caddr_t cp0; - - rtinfo->rti_addrs = 0; -again: - switch (type) { - - case RTM_DELADDR: - case RTM_NEWADDR: - len = sizeof(struct ifa_msghdr); - break; - - case RTM_IFINFO: - len = sizeof(struct if_msghdr); - break; - - default: - len = sizeof(struct rt_msghdr); - } - cp0 = cp; - if (cp0) - cp += len; - for (i = 0; i < RTAX_MAX; i++) { - register struct sockaddr *sa; - - if ((sa = rtinfo->rti_info[i]) == 0) - continue; - rtinfo->rti_addrs |= (1 << i); - dlen = ROUNDUP(sa->sa_len); - if (cp) { - bcopy((caddr_t)sa, cp, (unsigned)dlen); - cp += dlen; - } - len += dlen; - } - if (cp == 0 && w != NULL && !second_time) { - register struct walkarg *rw = w; - - if (rw->w_req) { - if (rw->w_tmemsize < len) { - if (rw->w_tmem) - free(rw->w_tmem, M_RTABLE); - rw->w_tmem = (caddr_t) - malloc(len, M_RTABLE, M_NOWAIT); - if (rw->w_tmem) - rw->w_tmemsize = len; - } - if (rw->w_tmem) { - cp = rw->w_tmem; - second_time = 1; - goto again; - } - } - } - if (cp) { - register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; - - rtm->rtm_version = RTM_VERSION; - rtm->rtm_type = type; - rtm->rtm_msglen = len; - } - return (len); -} - -/* - * This routine is called to generate a message from the routing - * socket indicating that a redirect has occured, a routing lookup - * has failed, or that a protocol has detected timeouts to a particular - * destination. - */ -void -rt_missmsg(type, rtinfo, flags, error) - int type, flags, error; - register struct rt_addrinfo *rtinfo; -{ - register struct rt_msghdr *rtm; - register struct mbuf *m; - struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; - - if (route_cb.any_count == 0) - return; - m = rt_msg1(type, rtinfo); - if (m == 0) - return; - rtm = mtod(m, struct rt_msghdr *); - rtm->rtm_flags = RTF_DONE | flags; - rtm->rtm_errno = error; - rtm->rtm_addrs = rtinfo->rti_addrs; - route_proto.sp_protocol = sa ? sa->sa_family : 0; - raw_input(m, &route_proto, &route_src, &route_dst); -} - -/* - * This routine is called to generate a message from the routing - * socket indicating that the status of a network interface has changed. - */ -void -rt_ifmsg(ifp) - register struct ifnet *ifp; -{ - register struct if_msghdr *ifm; - struct mbuf *m; - struct rt_addrinfo info; - - if (route_cb.any_count == 0) - return; - bzero((caddr_t)&info, sizeof(info)); - m = rt_msg1(RTM_IFINFO, &info); - if (m == 0) - return; - ifm = mtod(m, struct if_msghdr *); - ifm->ifm_index = ifp->if_index; - ifm->ifm_flags = (u_short)ifp->if_flags; - ifm->ifm_data = ifp->if_data; - ifm->ifm_addrs = 0; - route_proto.sp_protocol = 0; - raw_input(m, &route_proto, &route_src, &route_dst); -} - -/* - * This is called to generate messages from the routing socket - * indicating a network interface has had addresses associated with it. - * if we ever reverse the logic and replace messages TO the routing - * socket indicate a request to configure interfaces, then it will - * be unnecessary as the routing socket will automatically generate - * copies of it. - */ -void -rt_newaddrmsg(cmd, ifa, error, rt) - int cmd, error; - register struct ifaddr *ifa; - register struct rtentry *rt; -{ - struct rt_addrinfo info; - struct sockaddr *sa = 0; - int pass; - struct mbuf *m = 0; - struct ifnet *ifp = ifa->ifa_ifp; - - if (route_cb.any_count == 0) - return; - for (pass = 1; pass < 3; pass++) { - bzero((caddr_t)&info, sizeof(info)); - if ((cmd == RTM_ADD && pass == 1) || - (cmd == RTM_DELETE && pass == 2)) { - register struct ifa_msghdr *ifam; - int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; - - ifaaddr = sa = ifa->ifa_addr; - ifpaddr = ifp->if_addrlist->ifa_addr; - netmask = ifa->ifa_netmask; - brdaddr = ifa->ifa_dstaddr; - if ((m = rt_msg1(ncmd, &info)) == NULL) - continue; - ifam = mtod(m, struct ifa_msghdr *); - ifam->ifam_index = ifp->if_index; - ifam->ifam_metric = ifa->ifa_metric; - ifam->ifam_flags = ifa->ifa_flags; - ifam->ifam_addrs = info.rti_addrs; - } - if ((cmd == RTM_ADD && pass == 2) || - (cmd == RTM_DELETE && pass == 1)) { - register struct rt_msghdr *rtm; - - if (rt == 0) - continue; - netmask = rt_mask(rt); - dst = sa = rt_key(rt); - gate = rt->rt_gateway; - if ((m = rt_msg1(cmd, &info)) == NULL) - continue; - rtm = mtod(m, struct rt_msghdr *); - rtm->rtm_index = ifp->if_index; - rtm->rtm_flags |= rt->rt_flags; - rtm->rtm_errno = error; - rtm->rtm_addrs = info.rti_addrs; - } - route_proto.sp_protocol = sa ? sa->sa_family : 0; - raw_input(m, &route_proto, &route_src, &route_dst); - } -} - - -/* - * This is used in dumping the kernel table via sysctl(). - */ -int -sysctl_dumpentry(rn, vw) - struct radix_node *rn; - void *vw; -{ - register struct walkarg *w = vw; - register struct rtentry *rt = (struct rtentry *)rn; - int error = 0, size; - struct rt_addrinfo info; - - if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) - return 0; - bzero((caddr_t)&info, sizeof(info)); - dst = rt_key(rt); - gate = rt->rt_gateway; - netmask = rt_mask(rt); - genmask = rt->rt_genmask; - size = rt_msg2(RTM_GET, &info, 0, w); - if (w->w_req && w->w_tmem) { - register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; - - rtm->rtm_flags = rt->rt_flags; - rtm->rtm_use = rt->rt_use; - rtm->rtm_rmx = rt->rt_rmx; - rtm->rtm_index = rt->rt_ifp->if_index; - rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; - rtm->rtm_addrs = info.rti_addrs; - error = 0; - return (error); - } - return (error); -} - -int -sysctl_iflist(af, w) - int af; - register struct walkarg *w; -{ - register struct ifnet *ifp; - register struct ifaddr *ifa; - struct rt_addrinfo info; - int len, error = 0; - - bzero((caddr_t)&info, sizeof(info)); - for (ifp = ifnet; ifp; ifp = ifp->if_next) { - if (w->w_arg && w->w_arg != ifp->if_index) - continue; - ifa = ifp->if_addrlist; - ifpaddr = ifa->ifa_addr; - len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); - ifpaddr = 0; - if (w->w_req && w->w_tmem) { - register struct if_msghdr *ifm; - - ifm = (struct if_msghdr *)w->w_tmem; - ifm->ifm_index = ifp->if_index; - ifm->ifm_flags = (u_short)ifp->if_flags; - ifm->ifm_data = ifp->if_data; - ifm->ifm_addrs = info.rti_addrs; - error =0; - if (error) - return (error); - } - while ((ifa = ifa->ifa_next) != 0) { - if (af && af != ifa->ifa_addr->sa_family) - continue; - ifaaddr = ifa->ifa_addr; - netmask = ifa->ifa_netmask; - brdaddr = ifa->ifa_dstaddr; - len = rt_msg2(RTM_NEWADDR, &info, 0, w); - if (w->w_req && w->w_tmem) { - register struct ifa_msghdr *ifam; - - ifam = (struct ifa_msghdr *)w->w_tmem; - ifam->ifam_index = ifa->ifa_ifp->if_index; - ifam->ifam_flags = ifa->ifa_flags; - ifam->ifam_metric = ifa->ifa_metric; - ifam->ifam_addrs = info.rti_addrs; - error = 0; - if (error) - return (error); - } - } - ifaaddr = netmask = brdaddr = 0; - } - return (0); -} - -static int -sysctl_rtsock SYSCTL_HANDLER_ARGS -{ - int *name = (int *)arg1; - u_int namelen = arg2; - register struct radix_node_head *rnh; - int i, s, error = EINVAL; - u_char af; - struct walkarg w; - - name ++; - namelen--; - if (req->newptr) - return (EPERM); - if (namelen != 3) - return (EINVAL); - af = name[0]; - Bzero(&w, sizeof(w)); - w.w_op = name[1]; - w.w_arg = name[2]; - w.w_req = req; - - s = splnet(); - switch (w.w_op) { - - case NET_RT_DUMP: - case NET_RT_FLAGS: - for (i = 1; i <= AF_MAX; i++) - if ((rnh = rt_tables[i]) && (af == 0 || af == i) && - (error = rnh->rnh_walktree(rnh, - sysctl_dumpentry, &w))) - break; - break; - - case NET_RT_IFLIST: - error = sysctl_iflist(af, &w); - } - splx(s); - if (w.w_tmem) - free(w.w_tmem, M_RTABLE); - return (error); -} - -SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock,""); - -/* - * Definitions of protocols supported in the ROUTE domain. - */ - -extern struct domain routedomain; /* or at least forward */ - -static struct protosw routesw[] = { -{ SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, - 0, route_output, raw_ctlinput, 0, - route_usrreq, - raw_init -} -}; - -struct domain routedomain = - { PF_ROUTE, "route", route_init, 0, 0, - routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; - -DOMAIN_SET(route); diff --git a/c/src/exec/libnetworking/net/zlib.c b/c/src/exec/libnetworking/net/zlib.c deleted file mode 100644 index 5030768865..0000000000 --- a/c/src/exec/libnetworking/net/zlib.c +++ /dev/null @@ -1,5376 +0,0 @@ -/* - * 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$ - */ - -/* - * ==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) - { - ZFREE(z, s->sub.trees.blens); - r = t; - if (r == Z_DATA_ERROR) - s->mode = BADB; - 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); - ZFREE(z, s->sub.trees.blens); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - s->mode = BADB; - r = t; - LEAVE - } - 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 */ diff --git a/c/src/exec/libnetworking/net/zlib.h b/c/src/exec/libnetworking/net/zlib.h deleted file mode 100644 index 188ddaff9f..0000000000 --- a/c/src/exec/libnetworking/net/zlib.h +++ /dev/null @@ -1,1010 +0,0 @@ -/* $Id$ */ - -/* - * 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 */ diff --git a/c/src/exec/libnetworking/netdb.h b/c/src/exec/libnetworking/netdb.h deleted file mode 100644 index ec274f851f..0000000000 --- a/c/src/exec/libnetworking/netdb.h +++ /dev/null @@ -1,182 +0,0 @@ -/*- - * Copyright (c) 1980, 1983, 1988, 1993 - * The Regents of the University of California. 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. 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. - * - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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. - * - - * --Copyright-- - */ - -/* - * @(#)netdb.h 8.1 (Berkeley) 6/2/93 - * From: Id: netdb.h,v 8.9 1996/11/19 08:39:29 vixie Exp $ - * $Id$ - */ - -#ifndef _NETDB_H_ -#define _NETDB_H_ - -#include <sys/cdefs.h> - -#ifndef _PATH_HEQUIV -# define _PATH_HEQUIV "/etc/hosts.equiv" -#endif -#define _PATH_HOSTS "/etc/hosts" -#define _PATH_NETWORKS "/etc/networks" -#define _PATH_PROTOCOLS "/etc/protocols" -#define _PATH_SERVICES "/etc/services" - -extern int h_errno; - -/* - * Structures returned by network data base library. All addresses are - * supplied in host order, and returned in network order (suitable for - * use in system calls). - */ -struct hostent { - char *h_name; /* official name of host */ - char **h_aliases; /* alias list */ - int h_addrtype; /* host address type */ - int h_length; /* length of address */ - char **h_addr_list; /* list of addresses from name server */ -#define h_addr h_addr_list[0] /* address, for backward compatibility */ -}; - -/* - * Assumption here is that a network number - * fits in an unsigned long -- probably a poor one. - */ -struct netent { - char *n_name; /* official name of net */ - char **n_aliases; /* alias list */ - int n_addrtype; /* net address type */ - unsigned long n_net; /* network # */ -}; - -struct servent { - char *s_name; /* official service name */ - char **s_aliases; /* alias list */ - int s_port; /* port # */ - char *s_proto; /* protocol to use */ -}; - -struct protoent { - char *p_name; /* official protocol name */ - char **p_aliases; /* alias list */ - int p_proto; /* protocol # */ -}; - -/* - * Error return codes from gethostbyname() and gethostbyaddr() - * (left in extern int h_errno). - */ - -#define NETDB_INTERNAL -1 /* see errno */ -#define NETDB_SUCCESS 0 /* no problem */ -#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ -#define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */ -#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ -#define NO_DATA 4 /* Valid name, no data record of requested type */ -#define NO_ADDRESS NO_DATA /* no address, look for MX record */ - -__BEGIN_DECLS -void endhostent __P((void)); -void endnetent __P((void)); -void endprotoent __P((void)); -void endservent __P((void)); -struct hostent *gethostbyaddr __P((const char *, int, int)); -struct hostent *gethostbyname __P((const char *)); -struct hostent *gethostbyname2 __P((const char *, int)); -struct hostent *gethostent __P((void)); -struct netent *getnetbyaddr __P((unsigned long, int)); -struct netent *getnetbyname __P((const char *)); -struct netent *getnetent __P((void)); -struct protoent *getprotobyname __P((const char *)); -struct protoent *getprotobynumber __P((int)); -struct protoent *getprotoent __P((void)); -struct servent *getservbyname __P((const char *, const char *)); -struct servent *getservbyport __P((int, const char *)); -struct servent *getservent __P((void)); -void herror __P((const char *)); -__const char *hstrerror __P((int)); -void sethostent __P((int)); -/* void sethostfile __P((const char *)); */ -void setnetent __P((int)); -void setprotoent __P((int)); -void setservent __P((int)); - -/* - * PRIVATE functions specific to the FreeBSD implementation - */ - -/* DO NOT USE THESE, THEY ARE SUBJECT TO CHANGE AND ARE NOT PORTABLE!!! */ -void _sethosthtent __P((int)); -void _endhosthtent __P((void)); -void _sethostdnsent __P((int)); -void _endhostdnsent __P((void)); -void _setnethtent __P((int)); -void _endnethtent __P((void)); -void _setnetdnsent __P((int)); -void _endnetdnsent __P((void)); -struct hostent * _gethostbyhtname __P((const char *, int)); -struct hostent * _gethostbydnsname __P((const char *, int)); -struct hostent * _gethostbynisname __P((const char *, int)); -struct hostent * _gethostbyhtaddr __P((const char *, int, int)); -struct hostent * _gethostbydnsaddr __P((const char *, int, int)); -struct hostent * _gethostbynisaddr __P((const char *, int, int)); -struct netent * _getnetbyhtname __P((const char *)); -struct netent * _getnetbydnsname __P((const char *)); -struct netent * _getnetbynisname __P((const char *)); -struct netent * _getnetbyhtaddr __P((unsigned long, int)); -struct netent * _getnetbydnsaddr __P((unsigned long, int)); -struct netent * _getnetbynisaddr __P((unsigned long, int)); -void _map_v4v6_address __P((const char *src, char *dst)); -void _map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len)); -__END_DECLS - -#endif /* !_NETDB_H_ */ diff --git a/c/src/exec/libnetworking/netinet/.cvsignore b/c/src/exec/libnetworking/netinet/.cvsignore deleted file mode 100644 index 282522db03..0000000000 --- a/c/src/exec/libnetworking/netinet/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -Makefile.in diff --git a/c/src/exec/libnetworking/netinet/Makefile.am b/c/src/exec/libnetworking/netinet/Makefile.am deleted file mode 100644 index fcc93a41c4..0000000000 --- a/c/src/exec/libnetworking/netinet/Makefile.am +++ /dev/null @@ -1,56 +0,0 @@ -## -## $Id$ -## - - -include_netinetdir = $(includedir)/netinet - -LIBNAME = lib.a -LIB = $(ARCH)/$(LIBNAME) - -C_FILES = if_ether.c igmp.c in.c in_cksum.c in_pcb.c in_proto.c in_rmx.c \ - ip_divert.c ip_fw.c ip_icmp.c ip_input.c ip_mroute.c ip_output.c \ - raw_ip.c tcp_debug.c tcp_input.c tcp_output.c tcp_subr.c tcp_timer.c \ - tcp_usrreq.c udp_usrreq.c -C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) - -OBJS = $(C_O_FILES) - -include $(top_srcdir)/../automake/multilib.am -include $(top_srcdir)/../automake/compile.am -include $(top_srcdir)/../automake/lib.am - -# -# Add local stuff here using += -# - -AM_CPPFLAGS += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC \ - -DBOOTP_COMPAT - -$(LIB): $(OBJS) - $(make-library) - -all-local: $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(LIB) - -.PRECIOUS: $(LIB) - -EXTRA_DIST = if_ether.c igmp.c igmp_var.h in.c in_cksum.c in_cksum_i386.c \ - in_cksum_m68k.c in_cksum_powerpc.c in_pcb.c in_proto.c in_rmx.c \ - ip_divert.c ip_fw.c ip_icmp.c ip_input.c ip_mroute.c ip_output.c \ - raw_ip.c tcp_debug.c tcp_input.c tcp_output.c tcp_subr.c tcp_timer.c \ - tcp_usrreq.c udp_usrreq.c - -include_netinet_HEADERS = icmp_var.h if_ether.h igmp.h igmp_var.h in.h in_pcb.h in_systm.h \ - in_var.h ip.h ip_fw.h ip_icmp.h ip_mroute.h ip_var.h tcp.h tcp_debug.h \ - tcp_fsm.h tcp_seq.h tcp_timer.h tcp_var.h tcpip.h udp.h udp_var.h - -PREINSTALL_FILES = $(PROJECT_INCLUDE)/netinet \ - $(include_netinet_HEADERS:%=$(PROJECT_INCLUDE)/netinet/%) - -$(PROJECT_INCLUDE)/netinet: - @$(mkinstalldirs) $@ - -$(PROJECT_INCLUDE)/netinet/%.h: %.h - $(INSTALL_DATA) $< $@ - -include $(top_srcdir)/../automake/local.am diff --git a/c/src/exec/libnetworking/netinet/icmp_var.h b/c/src/exec/libnetworking/netinet/icmp_var.h deleted file mode 100644 index 7657f31acf..0000000000 --- a/c/src/exec/libnetworking/netinet/icmp_var.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)icmp_var.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_ICMP_VAR_H_ -#define _NETINET_ICMP_VAR_H_ - -/* - * Variables related to this implementation - * of the internet control message protocol. - */ -struct icmpstat { -/* statistics related to icmp packets generated */ - u_long icps_error; /* # of calls to icmp_error */ - u_long icps_oldshort; /* no error 'cuz old ip too short */ - u_long icps_oldicmp; /* no error 'cuz old was icmp */ - u_long icps_outhist[ICMP_MAXTYPE + 1]; -/* statistics related to input messages processed */ - u_long icps_badcode; /* icmp_code out of range */ - u_long icps_tooshort; /* packet < ICMP_MINLEN */ - u_long icps_checksum; /* bad checksum */ - u_long icps_badlen; /* calculated bound mismatch */ - u_long icps_reflect; /* number of responses */ - u_long icps_inhist[ICMP_MAXTYPE + 1]; - u_long icps_bmcastecho; /* b/mcast echo requests dropped */ - u_long icps_bmcasttstamp; /* b/mcast tstamp requests dropped */ -}; - -/* - * Names for ICMP sysctl objects - */ -#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */ -#define ICMPCTL_STATS 2 /* statistics (read-only) */ -#define ICMPCTL_MAXID 3 - -#define ICMPCTL_NAMES { \ - { 0, 0 }, \ - { "maskrepl", CTLTYPE_INT }, \ - { "stats", CTLTYPE_STRUCT }, \ -} - -#ifdef KERNEL -extern struct icmpstat icmpstat; -#endif - -#endif diff --git a/c/src/exec/libnetworking/netinet/if_ether.c b/c/src/exec/libnetworking/netinet/if_ether.c deleted file mode 100644 index 985ce6e7d9..0000000000 --- a/c/src/exec/libnetworking/netinet/if_ether.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)if_ether.c 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -/* - * Ethernet address resolution protocol. - * TODO: - * add "inuse/lock" bit (or ref. count) along with valid bit - */ - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/socket.h> -#include <sys/syslog.h> - -#include <net/if.h> -#include <net/if_dl.h> -#include <net/route.h> -#include <net/netisr.h> - -#include <netinet/in.h> -#include <netinet/in_var.h> -#include <netinet/if_ether.h> - -#define SIN(s) ((struct sockaddr_in *)s) -#define SDL(s) ((struct sockaddr_dl *)s) - -SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); - -/* timer values */ -static int arpt_prune = (5*60*1); /* walk list every 5 minutes */ -static int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ -static int arpt_down = 20; /* once declared down, don't send for 20 sec */ - -SYSCTL_INT(_net_link_ether_inet, OID_AUTO, prune_intvl, CTLFLAG_RW, - &arpt_prune, 0, ""); -SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, - &arpt_keep, 0, ""); -SYSCTL_INT(_net_link_ether_inet, OID_AUTO, host_down_time, CTLFLAG_RW, - &arpt_down, 0, ""); - -#define rt_expire rt_rmx.rmx_expire - -struct llinfo_arp { - LIST_ENTRY(llinfo_arp) la_le; - struct rtentry *la_rt; - struct mbuf *la_hold; /* last packet until resolved/timeout */ - long la_asked; /* last time we QUERIED for this addr */ -#define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */ -}; - -static LIST_HEAD(, llinfo_arp) llinfo_arp; - -struct ifqueue arpintrq = {0, 0, 0, 50}; -static int arp_inuse, arp_allocated; - -static int arp_maxtries = 5; -static int useloopback = 1; /* use loopback interface for local traffic */ -static int arp_proxyall = 0; - -SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, - &arp_maxtries, 0, ""); -SYSCTL_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW, - &useloopback, 0, ""); -SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, - &arp_proxyall, 0, ""); - -static void arp_rtrequest __P((int, struct rtentry *, struct sockaddr *)); -static void arprequest __P((struct arpcom *, u_long *, u_long *, u_char *)); -void arpintr __P((void)); -static void arptfree __P((struct llinfo_arp *)); -static void arptimer __P((void *)); -static struct llinfo_arp - *arplookup __P((u_long, int, int)); -static void in_arpinput __P((struct mbuf *)); - -/* - * Timeout routine. Age arp_tab entries periodically. - */ -/* ARGSUSED */ -static void -arptimer(ignored_arg) - void *ignored_arg; -{ - int s = splnet(); - register struct llinfo_arp *la = llinfo_arp.lh_first; - struct llinfo_arp *ola; - - timeout(arptimer, (caddr_t)0, arpt_prune * hz); - while ((ola = la) != 0) { - register struct rtentry *rt = la->la_rt; - la = la->la_le.le_next; - if (rt->rt_expire && rt->rt_expire <= rtems_bsdnet_seconds_since_boot()) - arptfree(ola); /* timer has expired, clear */ - } - splx(s); -} - -/* - * Parallel to llc_rtrequest. - */ -static void -arp_rtrequest(req, rt, sa) - int req; - register struct rtentry *rt; - struct sockaddr *sa; -{ - register struct sockaddr *gate = rt->rt_gateway; - register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; - static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; - static int arpinit_done; - - if (!arpinit_done) { - arpinit_done = 1; - LIST_INIT(&llinfo_arp); - timeout(arptimer, (caddr_t)0, hz); - } - if (rt->rt_flags & RTF_GATEWAY) - return; - switch (req) { - - case RTM_ADD: - /* - * XXX: If this is a manually added route to interface - * such as older version of routed or gated might provide, - * restore cloning bit. - */ - if ((rt->rt_flags & RTF_HOST) == 0 && - SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) - rt->rt_flags |= RTF_CLONING; - if (rt->rt_flags & RTF_CLONING) { - /* - * Case 1: This route should come from a route to iface. - */ - rt_setgate(rt, rt_key(rt), - (struct sockaddr *)&null_sdl); - gate = rt->rt_gateway; - SDL(gate)->sdl_type = rt->rt_ifp->if_type; - SDL(gate)->sdl_index = rt->rt_ifp->if_index; - rt->rt_expire = rtems_bsdnet_seconds_since_boot(); - break; - } - /* Announce a new entry if requested. */ - if (rt->rt_flags & RTF_ANNOUNCE) - arprequest((struct arpcom *)rt->rt_ifp, - &SIN(rt_key(rt))->sin_addr.s_addr, - &SIN(rt_key(rt))->sin_addr.s_addr, - (u_char *)LLADDR(SDL(gate))); - /*FALLTHROUGH*/ - case RTM_RESOLVE: - if (gate->sa_family != AF_LINK || - gate->sa_len < sizeof(null_sdl)) { - log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n"); - break; - } - SDL(gate)->sdl_type = rt->rt_ifp->if_type; - SDL(gate)->sdl_index = rt->rt_ifp->if_index; - if (la != 0) - break; /* This happens on a route change */ - /* - * Case 2: This route may come from cloning, or a manual route - * add with a LL address. - */ - R_Malloc(la, struct llinfo_arp *, sizeof(*la)); - rt->rt_llinfo = (caddr_t)la; - if (la == 0) { - log(LOG_DEBUG, "arp_rtrequest: malloc failed\n"); - break; - } - arp_inuse++, arp_allocated++; - Bzero(la, sizeof(*la)); - la->la_rt = rt; - rt->rt_flags |= RTF_LLINFO; - LIST_INSERT_HEAD(&llinfo_arp, la, la_le); - - /* - * This keeps the multicast addresses from showing up - * in `arp -a' listings as unresolved. It's not actually - * functional. Then the same for broadcast. - */ - if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr))) { - ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt))->sin_addr, - LLADDR(SDL(gate))); - SDL(gate)->sdl_alen = 6; - rt->rt_expire = 0; - } - if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) { - memcpy(LLADDR(SDL(gate)), etherbroadcastaddr, 6); - SDL(gate)->sdl_alen = 6; - rt->rt_expire = 0; - } - - if (SIN(rt_key(rt))->sin_addr.s_addr == - (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) { - /* - * This test used to be - * if (loif.if_flags & IFF_UP) - * It allowed local traffic to be forced - * through the hardware by configuring the loopback down. - * However, it causes problems during network configuration - * for boards that can't receive packets they send. - * It is now necessary to clear "useloopback" and remove - * the route to force traffic out to the hardware. - */ - rt->rt_expire = 0; - Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr, - LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6); - if (useloopback) - rt->rt_ifp = loif; - - } - break; - - case RTM_DELETE: - if (la == 0) - break; - arp_inuse--; - LIST_REMOVE(la, la_le); - rt->rt_llinfo = 0; - rt->rt_flags &= ~RTF_LLINFO; - if (la->la_hold) - m_freem(la->la_hold); - Free((caddr_t)la); - } -} - -/* - * Broadcast an ARP request. Caller specifies: - * - arp header source ip address - * - arp header target ip address - * - arp header source ethernet address - */ -static void -arprequest(ac, sip, tip, enaddr) - register struct arpcom *ac; - register u_long *sip, *tip; - register u_char *enaddr; -{ - register struct mbuf *m; - register struct ether_header *eh; - register struct ether_arp *ea; - struct sockaddr sa; - - if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) - return; - m->m_len = sizeof(*ea); - m->m_pkthdr.len = sizeof(*ea); - MH_ALIGN(m, sizeof(*ea)); - ea = mtod(m, struct ether_arp *); - eh = (struct ether_header *)sa.sa_data; - bzero((caddr_t)ea, sizeof (*ea)); - (void)memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost)); - eh->ether_type = htons(ETHERTYPE_ARP); /* if_output will not swap */ - ea->arp_hrd = htons(ARPHRD_ETHER); - ea->arp_pro = htons(ETHERTYPE_IP); - ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ - ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ - ea->arp_op = htons(ARPOP_REQUEST); - (void)memcpy(ea->arp_sha, enaddr, sizeof(ea->arp_sha)); - (void)memcpy(ea->arp_spa, sip, sizeof(ea->arp_spa)); - (void)memcpy(ea->arp_tpa, tip, sizeof(ea->arp_tpa)); - sa.sa_family = AF_UNSPEC; - sa.sa_len = sizeof(sa); - (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0); -} - -/* - * Resolve an IP address into an ethernet address. If success, - * desten is filled in. If there is no entry in arptab, - * set one up and broadcast a request for the IP address. - * Hold onto this mbuf and resend it once the address - * is finally resolved. A return value of 1 indicates - * that desten has been filled in and the packet should be sent - * normally; a 0 return indicates that the packet has been - * taken over here, either now or for later transmission. - */ -int -arpresolve(ac, rt, m, dst, desten, rt0) - register struct arpcom *ac; - register struct rtentry *rt; - struct mbuf *m; - register struct sockaddr *dst; - register u_char *desten; - struct rtentry *rt0; -{ - register struct llinfo_arp *la; - struct sockaddr_dl *sdl; - - if (m->m_flags & M_BCAST) { /* broadcast */ - (void)memcpy(desten, etherbroadcastaddr, sizeof(etherbroadcastaddr)); - return (1); - } - if (m->m_flags & M_MCAST) { /* multicast */ - ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); - return(1); - } - if (rt) - la = (struct llinfo_arp *)rt->rt_llinfo; - else { - la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0); - if (la) - rt = la->la_rt; - } - if (la == 0 || rt == 0) { - log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s\n", - inet_ntoa(SIN(dst)->sin_addr)); - m_freem(m); - return (0); - } - sdl = SDL(rt->rt_gateway); - /* - * Check the address family and length is valid, the address - * is resolved; otherwise, try to resolve. - */ - if ((rt->rt_expire == 0 || rt->rt_expire > rtems_bsdnet_seconds_since_boot()) && - sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { - bcopy(LLADDR(sdl), desten, sdl->sdl_alen); - return 1; - } - /* - * There is an arptab entry, but no ethernet address - * response yet. Replace the held mbuf with this - * latest one. - */ - if (la->la_hold) - m_freem(la->la_hold); - la->la_hold = m; - if (rt->rt_expire) { - rt->rt_flags &= ~RTF_REJECT; - if (la->la_asked == 0 || rt->rt_expire != rtems_bsdnet_seconds_since_boot()) { - rt->rt_expire = rtems_bsdnet_seconds_since_boot(); - if (la->la_asked++ < arp_maxtries) - arprequest(ac, - &(SIN(rt->rt_ifa->ifa_addr)->sin_addr.s_addr), - &(SIN(dst)->sin_addr.s_addr), - ac->ac_enaddr); - else { - rt->rt_flags |= RTF_REJECT; - rt->rt_expire += arpt_down; - la->la_asked = 0; - } - - } - } - return (0); -} - -/* - * Common length and type checks are done here, - * then the protocol-specific routine is called. - */ -void -arpintr(void) -{ - register struct mbuf *m; - register struct arphdr *ar; - int s; - - while (arpintrq.ifq_head) { - s = splimp(); - IF_DEQUEUE(&arpintrq, m); - splx(s); - if (m == 0 || (m->m_flags & M_PKTHDR) == 0) - panic("arpintr"); - if (m->m_len >= sizeof(struct arphdr) && - (ar = mtod(m, struct arphdr *)) && - ntohs(ar->ar_hrd) == ARPHRD_ETHER && - m->m_len >= - sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln) - - switch (ntohs(ar->ar_pro)) { - - case ETHERTYPE_IP: - in_arpinput(m); - continue; - } - m_freem(m); - } -} - -NETISR_SET(NETISR_ARP, arpintr); - -/* - * ARP for Internet protocols on 10 Mb/s Ethernet. - * Algorithm is that given in RFC 826. - * In addition, a sanity check is performed on the sender - * protocol address, to catch impersonators. - * We no longer handle negotiations for use of trailer protocol: - * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent - * along with IP replies if we wanted trailers sent to us, - * and also sent them in response to IP replies. - * This allowed either end to announce the desire to receive - * trailer packets. - * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, - * but formerly didn't normally send requests. - */ -static void -in_arpinput(m) - struct mbuf *m; -{ - register struct ether_arp *ea; - register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif; - struct ether_header *eh; - register struct llinfo_arp *la = 0; - register struct rtentry *rt; - struct in_ifaddr *ia, *maybe_ia = 0; - struct sockaddr_dl *sdl; - struct sockaddr sa; - struct in_addr isaddr, itaddr, myaddr; - int op; - - ea = mtod(m, struct ether_arp *); - op = ntohs(ea->arp_op); - (void)memcpy(&isaddr, ea->arp_spa, sizeof (isaddr)); - (void)memcpy(&itaddr, ea->arp_tpa, sizeof (itaddr)); - for (ia = in_ifaddr; ia; ia = ia->ia_next) - if (ia->ia_ifp == &ac->ac_if) { - maybe_ia = ia; - if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) || - (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)) - break; - } - if (maybe_ia == 0) { - m_freem(m); - return; - } - myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr; - if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr, - sizeof (ea->arp_sha))) { - m_freem(m); /* it's from me, ignore it. */ - return; - } - if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr, - sizeof (ea->arp_sha))) { - log(LOG_ERR, - "arp: ether address is broadcast for IP address %s!\n", - inet_ntoa(isaddr)); - m_freem(m); - return; - } - if (isaddr.s_addr == myaddr.s_addr) { - log(LOG_ERR, - "arp: %6D is using my IP address %s!\n", - ea->arp_sha, ":", inet_ntoa(isaddr)); - itaddr = myaddr; - goto reply; - } - la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0); - if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) { - if (sdl->sdl_alen && - bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) - log(LOG_INFO, "arp: %s moved from %6D to %6D\n", - inet_ntoa(isaddr), (u_char *)LLADDR(sdl), ":", - ea->arp_sha, ":"); - (void)memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha)); - sdl->sdl_alen = sizeof(ea->arp_sha); - if (rt->rt_expire) - rt->rt_expire = rtems_bsdnet_seconds_since_boot() + arpt_keep; - rt->rt_flags &= ~RTF_REJECT; - la->la_asked = 0; - if (la->la_hold) { - (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold, - rt_key(rt), rt); - la->la_hold = 0; - } - } -reply: - if (op != ARPOP_REQUEST) { - m_freem(m); - return; - } - if (itaddr.s_addr == myaddr.s_addr) { - /* I am the target */ - (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha)); - (void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha)); - } else { - la = arplookup(itaddr.s_addr, 0, SIN_PROXY); - if (la == NULL) { - struct sockaddr_in sin; - - if (!arp_proxyall) { - m_freem(m); - return; - } - - bzero(&sin, sizeof sin); - sin.sin_family = AF_INET; - sin.sin_len = sizeof sin; - sin.sin_addr = itaddr; - - rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); - if (!rt) { - m_freem(m); - return; - } - /* - * Don't send proxies for nodes on the same interface - * as this one came out of, or we'll get into a fight - * over who claims what Ether address. - */ - if (rt->rt_ifp == &ac->ac_if) { - rtfree(rt); - m_freem(m); - return; - } - (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha)); - (void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha)); - rtfree(rt); -#ifdef DEBUG_PROXY - printf("arp: proxying for %s\n", - inet_ntoa(itaddr)); -#endif - } else { - rt = la->la_rt; - (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha)); - sdl = SDL(rt->rt_gateway); - (void)memcpy(ea->arp_sha, LLADDR(sdl), sizeof(ea->arp_sha)); - } - } - - (void)memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa)); - (void)memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa)); - ea->arp_op = htons(ARPOP_REPLY); - ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */ - eh = (struct ether_header *)sa.sa_data; - (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost)); - eh->ether_type = htons(ETHERTYPE_ARP); - sa.sa_family = AF_UNSPEC; - sa.sa_len = sizeof(sa); - (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0); - return; -} - -/* - * Free an arp entry. - */ -static void -arptfree(la) - register struct llinfo_arp *la; -{ - register struct rtentry *rt = la->la_rt; - register struct sockaddr_dl *sdl; - if (rt == 0) - panic("arptfree"); - if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) && - sdl->sdl_family == AF_LINK) { - sdl->sdl_alen = 0; - la->la_asked = 0; - rt->rt_flags &= ~RTF_REJECT; - return; - } - rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt), - 0, (struct rtentry **)0); -} -/* - * Lookup or enter a new address in arptab. - */ -static struct llinfo_arp * -arplookup(addr, create, proxy) - u_long addr; - int create, proxy; -{ - register struct rtentry *rt; - static struct sockaddr_inarp sin = {sizeof(sin), AF_INET }; - const char *why = 0; - - sin.sin_addr.s_addr = addr; - sin.sin_other = proxy ? SIN_PROXY : 0; - rt = rtalloc1((struct sockaddr *)&sin, create, 0UL); - if (rt == 0) - return (0); - rt->rt_refcnt--; - - if (rt->rt_flags & RTF_GATEWAY) - why = "host is not on local network"; - else if ((rt->rt_flags & RTF_LLINFO) == 0) - why = "could not allocate llinfo"; - else if (rt->rt_gateway->sa_family != AF_LINK) - why = "gateway route is not ours"; - - if (why && create) { - log(LOG_DEBUG, "arplookup %s failed: %s\n", - inet_ntoa(sin.sin_addr), why); - return 0; - } else if (why) { - return 0; - } - return ((struct llinfo_arp *)rt->rt_llinfo); -} - -void -arp_ifinit(ac, ifa) - struct arpcom *ac; - struct ifaddr *ifa; -{ - if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) - arprequest(ac, &(IA_SIN(ifa)->sin_addr.s_addr), - &(IA_SIN(ifa)->sin_addr.s_addr), ac->ac_enaddr); - ifa->ifa_rtrequest = arp_rtrequest; - ifa->ifa_flags |= RTF_CLONING; -} diff --git a/c/src/exec/libnetworking/netinet/if_ether.h b/c/src/exec/libnetworking/netinet/if_ether.h deleted file mode 100644 index 22c8e97187..0000000000 --- a/c/src/exec/libnetworking/netinet/if_ether.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)if_ether.h 8.3 (Berkeley) 5/2/95 - * $Id$ - */ - -#ifndef _NETINET_IF_ETHER_H_ -#define _NETINET_IF_ETHER_H_ - -#include <net/ethernet.h> - -#define ETHERTYPE_PUP 0x0200 /* PUP protocol */ -#define ETHERTYPE_IP 0x0800 /* IP protocol */ -#define ETHERTYPE_ARP 0x0806 /* Addr. resolution protocol */ -#define ETHERTYPE_REVARP 0x8035 /* reverse Addr. resolution protocol */ - -/* - * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have - * (type-ETHERTYPE_TRAIL)*512 bytes of data followed - * by an ETHER type (as given above) and then the (variable-length) header. - */ -#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */ -#define ETHERTYPE_NTRAILER 16 - -#define ETHERMTU (ETHER_MAX_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN) -#define ETHERMIN (ETHER_MIN_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN) - -#ifdef KERNEL -/* - * Macro to map an IP multicast address to an Ethernet multicast address. - * The high-order 25 bits of the Ethernet address are statically assigned, - * and the low-order 23 bits are taken from the low end of the IP address. - */ -#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \ - /* struct in_addr *ipaddr; */ \ - /* u_char enaddr[ETHER_ADDR_LEN]; */ \ -{ \ - (enaddr)[0] = 0x01; \ - (enaddr)[1] = 0x00; \ - (enaddr)[2] = 0x5e; \ - (enaddr)[3] = ((u_char *)ipaddr)[1] & 0x7f; \ - (enaddr)[4] = ((u_char *)ipaddr)[2]; \ - (enaddr)[5] = ((u_char *)ipaddr)[3]; \ -} -#endif - -/* - * Ethernet Address Resolution Protocol. - * - * See RFC 826 for protocol description. Structure below is adapted - * to resolving internet addresses. Field names used correspond to - * RFC 826. - */ -struct ether_arp { - struct arphdr ea_hdr; /* fixed-size header */ - u_char arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */ - u_char arp_spa[4]; /* sender protocol address */ - u_char arp_tha[ETHER_ADDR_LEN]; /* target hardware address */ - u_char arp_tpa[4]; /* target protocol address */ -}; -#define arp_hrd ea_hdr.ar_hrd -#define arp_pro ea_hdr.ar_pro -#define arp_hln ea_hdr.ar_hln -#define arp_pln ea_hdr.ar_pln -#define arp_op ea_hdr.ar_op - - -/* - * Structure shared between the ethernet driver modules and - * the address resolution code. For example, each ec_softc or il_softc - * begins with this structure. - */ -struct arpcom { - /* - * The ifnet struct _must_ be at the head of this structure. - */ - struct ifnet ac_if; /* network-visible interface */ - u_char ac_enaddr[ETHER_ADDR_LEN]; /* ethernet hardware address */ - struct ether_multi *ac_multiaddrs; /* list of ether multicast addrs */ - int ac_multicnt; /* length of ac_multiaddrs list */ -}; - -struct sockaddr_inarp { - u_char sin_len; - u_char sin_family; - u_short sin_port; - struct in_addr sin_addr; - struct in_addr sin_srcaddr; - u_short sin_tos; - u_short sin_other; -#define SIN_PROXY 1 -}; -/* - * IP and ethernet specific routing flags - */ -#define RTF_USETRAILERS RTF_PROTO1 /* use trailers */ -#define RTF_ANNOUNCE RTF_PROTO2 /* announce new arp entry */ - -#ifdef KERNEL -extern u_char etherbroadcastaddr[ETHER_ADDR_LEN]; -extern u_char ether_ipmulticast_min[ETHER_ADDR_LEN]; -extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN]; -extern struct ifqueue arpintrq; - -int arpresolve __P((struct arpcom *, struct rtentry *, struct mbuf *, - struct sockaddr *, u_char *, struct rtentry *)); -void arp_ifinit __P((struct arpcom *, struct ifaddr *)); -int ether_addmulti __P((struct ifreq *, struct arpcom *)); -int ether_delmulti __P((struct ifreq *, struct arpcom *)); - -/* - * Ethernet multicast address structure. There is one of these for each - * multicast address or range of multicast addresses that we are supposed - * to listen to on a particular interface. They are kept in a linked list, - * rooted in the interface's arpcom structure. (This really has nothing to - * do with ARP, or with the Internet address family, but this appears to be - * the minimally-disrupting place to put it.) - */ -struct ether_multi { - u_char enm_addrlo[ETHER_ADDR_LEN]; /* low or only address of range */ - u_char enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */ - struct arpcom *enm_ac; /* back pointer to arpcom */ - u_int enm_refcount; /* no. claims to this addr/range */ - struct ether_multi *enm_next; /* ptr to next ether_multi */ -}; - -/* - * Structure used by macros below to remember position when stepping through - * all of the ether_multi records. - */ -struct ether_multistep { - struct ether_multi *e_enm; -}; - -/* - * Macro for looking up the ether_multi record for a given range of Ethernet - * multicast addresses connected to a given arpcom structure. If no matching - * record is found, "enm" returns NULL. - */ -#define ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm) \ - /* u_char addrlo[ETHER_ADDR_LEN]; */ \ - /* u_char addrhi[ETHER_ADDR_LEN]; */ \ - /* struct arpcom *ac; */ \ - /* struct ether_multi *enm; */ \ -{ \ - for ((enm) = (ac)->ac_multiaddrs; \ - (enm) != NULL && \ - (bcmp((enm)->enm_addrlo, (addrlo), ETHER_ADDR_LEN) != 0 || \ - bcmp((enm)->enm_addrhi, (addrhi), ETHER_ADDR_LEN) != 0); \ - (enm) = (enm)->enm_next); \ -} - -/* - * Macro to step through all of the ether_multi records, one at a time. - * The current position is remembered in "step", which the caller must - * provide. ETHER_FIRST_MULTI(), below, must be called to initialize "step" - * and get the first record. Both macros return a NULL "enm" when there - * are no remaining records. - */ -#define ETHER_NEXT_MULTI(step, enm) \ - /* struct ether_multistep step; */ \ - /* struct ether_multi *enm; */ \ -{ \ - if (((enm) = (step).e_enm) != NULL) \ - (step).e_enm = (enm)->enm_next; \ -} - -#define ETHER_FIRST_MULTI(step, ac, enm) \ - /* struct ether_multistep step; */ \ - /* struct arpcom *ac; */ \ - /* struct ether_multi *enm; */ \ -{ \ - (step).e_enm = (ac)->ac_multiaddrs; \ - ETHER_NEXT_MULTI((step), (enm)); \ -} - -#endif - -#endif diff --git a/c/src/exec/libnetworking/netinet/igmp.c b/c/src/exec/libnetworking/netinet/igmp.c deleted file mode 100644 index 2af8b7038e..0000000000 --- a/c/src/exec/libnetworking/netinet/igmp.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (c) 1988 Stephen Deering. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Stephen Deering of Stanford University. - * - * 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. - * - * @(#)igmp.c 8.1 (Berkeley) 7/19/93 - * $Id$ - */ - -/* - * Internet Group Management Protocol (IGMP) routines. - * - * Written by Steve Deering, Stanford, May 1988. - * Modified by Rosen Sharma, Stanford, Aug 1994. - * Modified by Bill Fenner, Xerox PARC, Feb 1995. - * Modified to fully comply to IGMPv2 by Bill Fenner, Oct 1995. - * - * MULTICAST Revision: 3.5.1.4 - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/protosw.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_var.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/igmp.h> -#include <netinet/igmp_var.h> - -static struct router_info * - find_rti __P((struct ifnet *ifp)); - -static struct igmpstat igmpstat; - -SYSCTL_STRUCT(_net_inet_igmp, IGMPCTL_STATS, stats, CTLFLAG_RD, - &igmpstat, igmpstat, ""); - -static int igmp_timers_are_running; -static u_long igmp_all_hosts_group; -static u_long igmp_all_rtrs_group; -static struct mbuf *router_alert; -static struct router_info *Head; - -static void igmp_sendpkt(struct in_multi *, int, unsigned long); - -void -igmp_init() -{ - struct ipoption *ra; - - /* - * To avoid byte-swapping the same value over and over again. - */ - igmp_all_hosts_group = htonl(INADDR_ALLHOSTS_GROUP); - igmp_all_rtrs_group = htonl(INADDR_ALLRTRS_GROUP); - - igmp_timers_are_running = 0; - - /* - * Construct a Router Alert option to use in outgoing packets - */ - MGET(router_alert, M_DONTWAIT, MT_DATA); - ra = mtod(router_alert, struct ipoption *); - ra->ipopt_dst.s_addr = 0; - ra->ipopt_list[0] = IPOPT_RA; /* Router Alert Option */ - ra->ipopt_list[1] = 0x04; /* 4 bytes long */ - ra->ipopt_list[2] = 0x00; - ra->ipopt_list[3] = 0x00; - router_alert->m_len = sizeof(ra->ipopt_dst) + ra->ipopt_list[1]; - - Head = (struct router_info *) 0; -} - -static struct router_info * -find_rti(ifp) - struct ifnet *ifp; -{ - register struct router_info *rti = Head; - -#ifdef IGMP_DEBUG - printf("[igmp.c, _find_rti] --> entering \n"); -#endif - while (rti) { - if (rti->rti_ifp == ifp) { -#ifdef IGMP_DEBUG - printf("[igmp.c, _find_rti] --> found old entry \n"); -#endif - return rti; - } - rti = rti->rti_next; - } - MALLOC(rti, struct router_info *, sizeof *rti, M_MRTABLE, M_NOWAIT); - rti->rti_ifp = ifp; - rti->rti_type = IGMP_V2_ROUTER; - rti->rti_time = 0; - rti->rti_next = Head; - Head = rti; -#ifdef IGMP_DEBUG - printf("[igmp.c, _find_rti] --> created an entry \n"); -#endif - return rti; -} - -void -igmp_input(m, iphlen) - register struct mbuf *m; - register int iphlen; -{ - register struct igmp *igmp; - register struct ip *ip; - register int igmplen; - register struct ifnet *ifp = m->m_pkthdr.rcvif; - register int minlen; - register struct in_multi *inm; - register struct in_ifaddr *ia; - struct in_multistep step; - struct router_info *rti; - - int timer; /** timer value in the igmp query header **/ - - ++igmpstat.igps_rcv_total; - - ip = mtod(m, struct ip *); - igmplen = ip->ip_len; - - /* - * Validate lengths - */ - if (igmplen < IGMP_MINLEN) { - ++igmpstat.igps_rcv_tooshort; - m_freem(m); - return; - } - minlen = iphlen + IGMP_MINLEN; - if ((m->m_flags & M_EXT || m->m_len < minlen) && - (m = m_pullup(m, minlen)) == 0) { - ++igmpstat.igps_rcv_tooshort; - return; - } - - /* - * Validate checksum - */ - m->m_data += iphlen; - m->m_len -= iphlen; - igmp = mtod(m, struct igmp *); - if (in_cksum(m, igmplen)) { - ++igmpstat.igps_rcv_badsum; - m_freem(m); - return; - } - m->m_data -= iphlen; - m->m_len += iphlen; - - ip = mtod(m, struct ip *); - timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE; - rti = find_rti(ifp); - - /* - * In the IGMPv2 specification, there are 3 states and a flag. - * - * In Non-Member state, we simply don't have a membership record. - * In Delaying Member state, our timer is running (inm->inm_timer) - * In Idle Member state, our timer is not running (inm->inm_timer==0) - * - * The flag is inm->inm_state, it is set to IGMP_OTHERMEMBER if - * we have heard a report from another member, or IGMP_IREPORTEDLAST - * if I sent the last report. - */ - switch (igmp->igmp_type) { - - case IGMP_MEMBERSHIP_QUERY: - ++igmpstat.igps_rcv_queries; - - if (ifp->if_flags & IFF_LOOPBACK) - break; - - if (igmp->igmp_code == 0) { - /* - * Old router. Remember that the querier on this - * interface is old, and set the timer to the - * value in RFC 1112. - */ - - rti->rti_type = IGMP_V1_ROUTER; - rti->rti_time = 0; - - timer = IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ; - - if (ip->ip_dst.s_addr != igmp_all_hosts_group || - igmp->igmp_group.s_addr != 0) { - ++igmpstat.igps_rcv_badqueries; - m_freem(m); - return; - } - } else { - /* - * New router. Simply do the new validity check. - */ - - if (igmp->igmp_group.s_addr != 0 && - !IN_MULTICAST(ntohl(igmp->igmp_group.s_addr))) { - ++igmpstat.igps_rcv_badqueries; - m_freem(m); - return; - } - } - - /* - * - Start the timers in all of our membership records - * that the query applies to for the interface on - * which the query arrived excl. those that belong - * to the "all-hosts" group (224.0.0.1). - * - Restart any timer that is already running but has - * a value longer than the requested timeout. - * - Use the value specified in the query message as - * the maximum timeout. - */ - IN_FIRST_MULTI(step, inm); - while (inm != NULL) { - if (inm->inm_ifp == ifp && - inm->inm_addr.s_addr != igmp_all_hosts_group && - (igmp->igmp_group.s_addr == 0 || - igmp->igmp_group.s_addr == inm->inm_addr.s_addr)) { - if (inm->inm_timer == 0 || - inm->inm_timer > timer) { - inm->inm_timer = - IGMP_RANDOM_DELAY(timer); - igmp_timers_are_running = 1; - } - } - IN_NEXT_MULTI(step, inm); - } - - break; - - case IGMP_V1_MEMBERSHIP_REPORT: - case IGMP_V2_MEMBERSHIP_REPORT: - /* - * For fast leave to work, we have to know that we are the - * last person to send a report for this group. Reports - * can potentially get looped back if we are a multicast - * router, so discard reports sourced by me. - */ - IFP_TO_IA(ifp, ia); - if (ia && ip->ip_src.s_addr == IA_SIN(ia)->sin_addr.s_addr) - break; - - ++igmpstat.igps_rcv_reports; - - if (ifp->if_flags & IFF_LOOPBACK) - break; - - if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr))) { - ++igmpstat.igps_rcv_badreports; - m_freem(m); - return; - } - - /* - * KLUDGE: if the IP source address of the report has an - * unspecified (i.e., zero) subnet number, as is allowed for - * a booting host, replace it with the correct subnet number - * so that a process-level multicast routing demon can - * determine which subnet it arrived from. This is necessary - * to compensate for the lack of any way for a process to - * determine the arrival interface of an incoming packet. - */ - if ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) == 0) - if (ia) ip->ip_src.s_addr = htonl(ia->ia_subnet); - - /* - * If we belong to the group being reported, stop - * our timer for that group. - */ - IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm); - - if (inm != NULL) { - inm->inm_timer = 0; - ++igmpstat.igps_rcv_ourreports; - - inm->inm_state = IGMP_OTHERMEMBER; - } - - break; - } - - /* - * Pass all valid IGMP packets up to any process(es) listening - * on a raw IGMP socket. - */ - rip_input(m, iphlen); -} - -void -igmp_joingroup(inm) - struct in_multi *inm; -{ - int s = splnet(); - - if (inm->inm_addr.s_addr == igmp_all_hosts_group - || inm->inm_ifp->if_flags & IFF_LOOPBACK) { - inm->inm_timer = 0; - inm->inm_state = IGMP_OTHERMEMBER; - } else { - inm->inm_rti = find_rti(inm->inm_ifp); - igmp_sendpkt(inm, inm->inm_rti->rti_type, 0); - inm->inm_timer = IGMP_RANDOM_DELAY( - IGMP_MAX_HOST_REPORT_DELAY*PR_FASTHZ); - inm->inm_state = IGMP_IREPORTEDLAST; - igmp_timers_are_running = 1; - } - splx(s); -} - -void -igmp_leavegroup(inm) - struct in_multi *inm; -{ - if (inm->inm_state == IGMP_IREPORTEDLAST && - inm->inm_addr.s_addr != igmp_all_hosts_group && - !(inm->inm_ifp->if_flags & IFF_LOOPBACK) && - inm->inm_rti->rti_type != IGMP_V1_ROUTER) - igmp_sendpkt(inm, IGMP_V2_LEAVE_GROUP, igmp_all_rtrs_group); -} - -void -igmp_fasttimo() -{ - register struct in_multi *inm; - struct in_multistep step; - int s; - - /* - * Quick check to see if any work needs to be done, in order - * to minimize the overhead of fasttimo processing. - */ - - if (!igmp_timers_are_running) - return; - - s = splnet(); - igmp_timers_are_running = 0; - IN_FIRST_MULTI(step, inm); - while (inm != NULL) { - if (inm->inm_timer == 0) { - /* do nothing */ - } else if (--inm->inm_timer == 0) { - igmp_sendpkt(inm, inm->inm_rti->rti_type, 0); - inm->inm_state = IGMP_IREPORTEDLAST; - } else { - igmp_timers_are_running = 1; - } - IN_NEXT_MULTI(step, inm); - } - splx(s); -} - -void -igmp_slowtimo() -{ - int s = splnet(); - register struct router_info *rti = Head; - -#ifdef IGMP_DEBUG - printf("[igmp.c,_slowtimo] -- > entering \n"); -#endif - while (rti) { - if (rti->rti_type == IGMP_V1_ROUTER) { - rti->rti_time++; - if (rti->rti_time >= IGMP_AGE_THRESHOLD) { - rti->rti_type = IGMP_V2_ROUTER; - } - } - rti = rti->rti_next; - } -#ifdef IGMP_DEBUG - printf("[igmp.c,_slowtimo] -- > exiting \n"); -#endif - splx(s); -} - -static struct route igmprt; - -static void -igmp_sendpkt(inm, type, addr) - struct in_multi *inm; - int type; - unsigned long addr; -{ - struct mbuf *m; - struct igmp *igmp; - struct ip *ip; - struct ip_moptions imo; - - MGETHDR(m, M_DONTWAIT, MT_HEADER); - if (m == NULL) - return; - - m->m_pkthdr.rcvif = loif; - m->m_pkthdr.len = sizeof(struct ip) + IGMP_MINLEN; - MH_ALIGN(m, IGMP_MINLEN + sizeof(struct ip)); - m->m_data += sizeof(struct ip); - m->m_len = IGMP_MINLEN; - igmp = mtod(m, struct igmp *); - igmp->igmp_type = type; - igmp->igmp_code = 0; - igmp->igmp_group = inm->inm_addr; - igmp->igmp_cksum = 0; - igmp->igmp_cksum = in_cksum(m, IGMP_MINLEN); - - m->m_data -= sizeof(struct ip); - m->m_len += sizeof(struct ip); - ip = mtod(m, struct ip *); - ip->ip_tos = 0; - ip->ip_len = sizeof(struct ip) + IGMP_MINLEN; - ip->ip_off = 0; - ip->ip_p = IPPROTO_IGMP; - ip->ip_src.s_addr = INADDR_ANY; - ip->ip_dst.s_addr = addr ? addr : igmp->igmp_group.s_addr; - - imo.imo_multicast_ifp = inm->inm_ifp; - imo.imo_multicast_ttl = 1; - imo.imo_multicast_vif = -1; - /* - * Request loopback of the report if we are acting as a multicast - * router, so that the process-level routing demon can hear it. - */ - imo.imo_multicast_loop = (ip_mrouter != NULL); - - /* - * XXX - * Do we have to worry about reentrancy here? Don't think so. - */ - ip_output(m, router_alert, &igmprt, 0, &imo); - - ++igmpstat.igps_snd_reports; -} diff --git a/c/src/exec/libnetworking/netinet/igmp.h b/c/src/exec/libnetworking/netinet/igmp.h deleted file mode 100644 index 01d6d09179..0000000000 --- a/c/src/exec/libnetworking/netinet/igmp.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 1988 Stephen Deering. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Stephen Deering of Stanford University. - * - * 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. - * - * @(#)igmp.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_IGMP_H_ -#define _NETINET_IGMP_H_ - -/* - * Internet Group Management Protocol (IGMP) definitions. - * - * Written by Steve Deering, Stanford, May 1988. - * - * MULTICAST Revision: 3.5.1.2 - */ - -/* - * IGMP packet format. - */ -struct igmp { - u_char igmp_type; /* version & type of IGMP message */ - u_char igmp_code; /* subtype for routing msgs */ - u_short igmp_cksum; /* IP-style checksum */ - struct in_addr igmp_group; /* group address being reported */ -}; /* (zero for queries) */ - -#define IGMP_MINLEN 8 - -/* - * Message types, including version number. - */ -#define IGMP_MEMBERSHIP_QUERY 0x11 /* membership query */ -#define IGMP_V1_MEMBERSHIP_REPORT 0x12 /* Ver. 1 membership report */ -#define IGMP_V2_MEMBERSHIP_REPORT 0x16 /* Ver. 2 membership report */ -#define IGMP_V2_LEAVE_GROUP 0x17 /* Leave-group message */ - -#define IGMP_DVMRP 0x13 /* DVMRP routing message */ -#define IGMP_PIM 0x14 /* PIM routing message */ - -#define IGMP_MTRACE_RESP 0x1e /* traceroute resp.(to sender)*/ -#define IGMP_MTRACE 0x1f /* mcast traceroute messages */ - -#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */ - /* query (in seconds) according */ - /* to RFC1112 */ - - -#define IGMP_TIMER_SCALE 10 /* denotes that the igmp code field */ - /* specifies time in 10th of seconds*/ - -/* - * The following four defininitions are for backwards compatibility. - * They should be removed as soon as all applications are updated to - * use the new constant names. - */ -#define IGMP_HOST_MEMBERSHIP_QUERY IGMP_MEMBERSHIP_QUERY -#define IGMP_HOST_MEMBERSHIP_REPORT IGMP_V1_MEMBERSHIP_REPORT -#define IGMP_HOST_NEW_MEMBERSHIP_REPORT IGMP_V2_MEMBERSHIP_REPORT -#define IGMP_HOST_LEAVE_MESSAGE IGMP_V2_LEAVE_GROUP - -#endif /* _NETINET_IGMP_H_ */ diff --git a/c/src/exec/libnetworking/netinet/igmp_var.h b/c/src/exec/libnetworking/netinet/igmp_var.h deleted file mode 100644 index f408bf2bc1..0000000000 --- a/c/src/exec/libnetworking/netinet/igmp_var.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 1988 Stephen Deering. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Stephen Deering of Stanford University. - * - * 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. - * - * @(#)igmp_var.h 8.1 (Berkeley) 7/19/93 - * $Id$ - */ - -#ifndef _NETINET_IGMP_VAR_H_ -#define _NETINET_IGMP_VAR_H_ - -/* - * Internet Group Management Protocol (IGMP), - * implementation-specific definitions. - * - * Written by Steve Deering, Stanford, May 1988. - * - * MULTICAST Revision: 3.5.1.3 - */ - -struct igmpstat { - u_int igps_rcv_total; /* total IGMP messages received */ - u_int igps_rcv_tooshort; /* received with too few bytes */ - u_int igps_rcv_badsum; /* received with bad checksum */ - u_int igps_rcv_queries; /* received membership queries */ - u_int igps_rcv_badqueries; /* received invalid queries */ - u_int igps_rcv_reports; /* received membership reports */ - u_int igps_rcv_badreports; /* received invalid reports */ - u_int igps_rcv_ourreports; /* received reports for our groups */ - u_int igps_snd_reports; /* sent membership reports */ -}; - -#ifdef KERNEL -extern struct igmpstat igmpstat; - -#define IGMP_RANDOM_DELAY(X) (random() % (X) + 1) - -/* - * States for IGMPv2's leave processing - */ -#define IGMP_OTHERMEMBER 0 -#define IGMP_IREPORTEDLAST 1 - -/* - * We must remember what version the subnet's querier is. - * We conveniently use the IGMP message type for the proper - * membership report to keep this state. - */ -#define IGMP_V1_ROUTER IGMP_V1_MEMBERSHIP_REPORT -#define IGMP_V2_ROUTER IGMP_V2_MEMBERSHIP_REPORT - -/* - * Revert to new router if we haven't heard from an old router in - * this amount of time. - */ -#define IGMP_AGE_THRESHOLD 540 - -void igmp_init __P((void)); -void igmp_input __P((struct mbuf *, int)); -void igmp_joingroup __P((struct in_multi *)); -void igmp_leavegroup __P((struct in_multi *)); -void igmp_fasttimo __P((void)); -void igmp_slowtimo __P((void)); -#endif - -/* - * Names for IGMP sysctl objects - */ -#define IGMPCTL_STATS 1 /* statistics (read-only) */ -#define IGMPCTL_MAXID 2 - -#define IGMPCTL_NAMES { \ - { 0, 0 }, \ - { "stats", CTLTYPE_STRUCT }, \ -} - -#endif - - diff --git a/c/src/exec/libnetworking/netinet/in.c b/c/src/exec/libnetworking/netinet/in.c deleted file mode 100644 index 701406f207..0000000000 --- a/c/src/exec/libnetworking/netinet/in.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1991, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)in.c 8.4 (Berkeley) 1/9/95 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/malloc.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in_systm.h> -#include <netinet/in.h> -#include <netinet/in_var.h> -#include <netinet/if_ether.h> - -#include <netinet/igmp_var.h> - -/* - * This structure is used to keep track of in_multi chains which belong to - * deleted interface addresses. - */ -static LIST_HEAD(, multi_kludge) in_mk; /* XXX BSS initialization */ - -struct multi_kludge { - LIST_ENTRY(multi_kludge) mk_entry; - struct ifnet *mk_ifp; - struct in_multihead mk_head; -}; - -static void in_socktrim __P((struct sockaddr_in *)); -static int in_ifinit __P((struct ifnet *, - struct in_ifaddr *, struct sockaddr_in *, int)); -static void in_ifscrub __P((struct ifnet *, struct in_ifaddr *)); - -static int subnetsarelocal = 0; -SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW, - &subnetsarelocal, 0, ""); -/* - * Return 1 if an internet address is for a ``local'' host - * (one to which we have a connection). If subnetsarelocal - * is true, this includes other subnets of the local net. - * Otherwise, it includes only the directly-connected (sub)nets. - */ -int -in_localaddr(in) - struct in_addr in; -{ - register u_long i = ntohl(in.s_addr); - register struct in_ifaddr *ia; - - if (subnetsarelocal) { - for (ia = in_ifaddr; ia; ia = ia->ia_next) - if ((i & ia->ia_netmask) == ia->ia_net) - return (1); - } else { - for (ia = in_ifaddr; ia; ia = ia->ia_next) - if ((i & ia->ia_subnetmask) == ia->ia_subnet) - return (1); - } - return (0); -} - -/* - * Determine whether an IP address is in a reserved set of addresses - * that may not be forwarded, or whether datagrams to that destination - * may be forwarded. - */ -int -in_canforward(in) - struct in_addr in; -{ - register u_long i = ntohl(in.s_addr); - register u_long net; - - if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i)) - return (0); - if (IN_CLASSA(i)) { - net = i & IN_CLASSA_NET; - if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) - return (0); - } - return (1); -} - -/* - * Trim a mask in a sockaddr - */ -static void -in_socktrim(ap) -struct sockaddr_in *ap; -{ - register char *cplim = (char *) &ap->sin_addr; - register char *cp = (char *) (&ap->sin_addr + 1); - - ap->sin_len = 0; - while (--cp >= cplim) - if (*cp) { - (ap)->sin_len = cp - (char *) (ap) + 1; - break; - } -} - -static int in_interfaces; /* number of external internet interfaces */ - -/* - * Generic internet control operations (ioctl's). - * Ifp is 0 if not an interface-specific ioctl. - */ -/* ARGSUSED */ -int -in_control(so, cmd, data, ifp) - struct socket *so; - u_long cmd; - caddr_t data; - register struct ifnet *ifp; -{ - register struct ifreq *ifr = (struct ifreq *)data; - register struct in_ifaddr *ia = 0, *iap; - register struct ifaddr *ifa; - struct in_ifaddr *oia; - struct in_aliasreq *ifra = (struct in_aliasreq *)data; - struct sockaddr_in oldaddr; - int error, hostIsNew, maskIsNew, s; - u_long i; - struct multi_kludge *mk; - - /* - * Find address for this interface, if it exists. - * - * If an alias address was specified, find that one instead of - * the first one on the interface. - */ - if (ifp) - for (iap = in_ifaddr; iap; iap = iap->ia_next) - if (iap->ia_ifp == ifp) { - if (((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr == - iap->ia_addr.sin_addr.s_addr) { - ia = iap; - break; - } else if (ia == NULL) { - ia = iap; - if (ifr->ifr_addr.sa_family != AF_INET) - break; - } - } - - switch (cmd) { - - case SIOCAIFADDR: - case SIOCDIFADDR: - if (ifra->ifra_addr.sin_family == AF_INET) { - for (oia = ia; ia; ia = ia->ia_next) { - if (ia->ia_ifp == ifp && - ia->ia_addr.sin_addr.s_addr == - ifra->ifra_addr.sin_addr.s_addr) - break; - } - if ((ifp->if_flags & IFF_POINTOPOINT) - && (cmd == SIOCAIFADDR) - && (ifra->ifra_dstaddr.sin_addr.s_addr - == INADDR_ANY)) { - return EDESTADDRREQ; - } - } - if (cmd == SIOCDIFADDR && ia == 0) - return (EADDRNOTAVAIL); - /* FALLTHROUGH */ - case SIOCSIFADDR: - case SIOCSIFNETMASK: - case SIOCSIFDSTADDR: - if ((so->so_state & SS_PRIV) == 0) - return (EPERM); - - if (ifp == 0) - panic("in_control"); - if (ia == (struct in_ifaddr *)0) { - oia = (struct in_ifaddr *) - malloc(sizeof *oia, M_IFADDR, M_WAITOK); - if (oia == (struct in_ifaddr *)NULL) - return (ENOBUFS); - bzero((caddr_t)oia, sizeof *oia); - ia = in_ifaddr; - /* - * Protect from ipintr() traversing address list - * while we're modifying it. - */ - s = splnet(); - - if (ia) { - for ( ; ia->ia_next; ia = ia->ia_next) - continue; - ia->ia_next = oia; - } else - in_ifaddr = oia; - ia = oia; - ifa = ifp->if_addrlist; - if (ifa) { - for ( ; ifa->ifa_next; ifa = ifa->ifa_next) - continue; - ifa->ifa_next = (struct ifaddr *) ia; - } else - ifp->if_addrlist = (struct ifaddr *) ia; - ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; - ia->ia_ifa.ifa_dstaddr - = (struct sockaddr *)&ia->ia_dstaddr; - ia->ia_ifa.ifa_netmask - = (struct sockaddr *)&ia->ia_sockmask; - ia->ia_sockmask.sin_len = 8; - if (ifp->if_flags & IFF_BROADCAST) { - ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); - ia->ia_broadaddr.sin_family = AF_INET; - } - ia->ia_ifp = ifp; - if (!(ifp->if_flags & IFF_LOOPBACK)) - in_interfaces++; - splx(s); - } - break; - - case SIOCSIFBRDADDR: - if ((so->so_state & SS_PRIV) == 0) - return (EPERM); - /* FALLTHROUGH */ - - case SIOCGIFADDR: - case SIOCGIFNETMASK: - case SIOCGIFDSTADDR: - case SIOCGIFBRDADDR: - if (ia == (struct in_ifaddr *)0) - return (EADDRNOTAVAIL); - break; - } - switch (cmd) { - - case SIOCGIFADDR: - *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; - break; - - case SIOCGIFBRDADDR: - if ((ifp->if_flags & IFF_BROADCAST) == 0) - return (EINVAL); - *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; - break; - - case SIOCGIFDSTADDR: - if ((ifp->if_flags & IFF_POINTOPOINT) == 0) - return (EINVAL); - *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; - break; - - case SIOCGIFNETMASK: - *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; - break; - - case SIOCSIFDSTADDR: - if ((ifp->if_flags & IFF_POINTOPOINT) == 0) - return (EINVAL); - oldaddr = ia->ia_dstaddr; - ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; - if (ifp->if_ioctl && (error = (*ifp->if_ioctl) - (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { - ia->ia_dstaddr = oldaddr; - return (error); - } - if (ia->ia_flags & IFA_ROUTE) { - ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; - rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); - ia->ia_ifa.ifa_dstaddr = - (struct sockaddr *)&ia->ia_dstaddr; - rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); - } - break; - - case SIOCSIFBRDADDR: - if ((ifp->if_flags & IFF_BROADCAST) == 0) - return (EINVAL); - ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; - break; - - case SIOCSIFADDR: - return (in_ifinit(ifp, ia, - (struct sockaddr_in *) &ifr->ifr_addr, 1)); - - case SIOCSIFNETMASK: - i = ifra->ifra_addr.sin_addr.s_addr; - ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); - break; - - case SIOCAIFADDR: - maskIsNew = 0; - hostIsNew = 1; - error = 0; - if (ia->ia_addr.sin_family == AF_INET) { - if (ifra->ifra_addr.sin_len == 0) { - ifra->ifra_addr = ia->ia_addr; - hostIsNew = 0; - } else if (ifra->ifra_addr.sin_addr.s_addr == - ia->ia_addr.sin_addr.s_addr) - hostIsNew = 0; - } - if (ifra->ifra_mask.sin_len) { - in_ifscrub(ifp, ia); - ia->ia_sockmask = ifra->ifra_mask; - ia->ia_subnetmask = - ntohl(ia->ia_sockmask.sin_addr.s_addr); - maskIsNew = 1; - } - if ((ifp->if_flags & IFF_POINTOPOINT) && - (ifra->ifra_dstaddr.sin_family == AF_INET)) { - in_ifscrub(ifp, ia); - ia->ia_dstaddr = ifra->ifra_dstaddr; - maskIsNew = 1; /* We lie; but the effect's the same */ - } - if (ifra->ifra_addr.sin_family == AF_INET && - (hostIsNew || maskIsNew)) - error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); - if ((ifp->if_flags & IFF_BROADCAST) && - (ifra->ifra_broadaddr.sin_family == AF_INET)) - ia->ia_broadaddr = ifra->ifra_broadaddr; - return (error); - - case SIOCDIFADDR: - mk = malloc(sizeof *mk, M_IPMADDR, M_WAITOK); - if (!mk) - return ENOBUFS; - - in_ifscrub(ifp, ia); - /* - * Protect from ipintr() traversing address list - * while we're modifying it. - */ - s = splnet(); - - if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) - ifp->if_addrlist = ifa->ifa_next; - else { - while (ifa->ifa_next && - (ifa->ifa_next != (struct ifaddr *)ia)) - ifa = ifa->ifa_next; - if (ifa->ifa_next) - ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; - else - printf("Couldn't unlink inifaddr from ifp\n"); - } - oia = ia; - if (oia == (ia = in_ifaddr)) - in_ifaddr = ia->ia_next; - else { - while (ia->ia_next && (ia->ia_next != oia)) - ia = ia->ia_next; - if (ia->ia_next) - ia->ia_next = oia->ia_next; - else - printf("Didn't unlink inifadr from list\n"); - } - - if (!oia->ia_multiaddrs.lh_first) { - IFAFREE(&oia->ia_ifa); - FREE(mk, M_IPMADDR); - splx(s); - break; - } - - /* - * Multicast address kludge: - * If there were any multicast addresses attached to this - * interface address, either move them to another address - * on this interface, or save them until such time as this - * interface is reconfigured for IP. - */ - IFP_TO_IA(oia->ia_ifp, ia); - if (ia) { /* there is another address */ - struct in_multi *inm; - for(inm = oia->ia_multiaddrs.lh_first; inm; - inm = inm->inm_entry.le_next) { - IFAFREE(&inm->inm_ia->ia_ifa); - ia->ia_ifa.ifa_refcnt++; - inm->inm_ia = ia; - LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, - inm_entry); - } - FREE(mk, M_IPMADDR); - } else { /* last address on this if deleted, save */ - struct in_multi *inm; - - LIST_INIT(&mk->mk_head); - mk->mk_ifp = ifp; - - for(inm = oia->ia_multiaddrs.lh_first; inm; - inm = inm->inm_entry.le_next) { - LIST_INSERT_HEAD(&mk->mk_head, inm, inm_entry); - } - - if (mk->mk_head.lh_first) { - LIST_INSERT_HEAD(&in_mk, mk, mk_entry); - } else { - FREE(mk, M_IPMADDR); - } - } - - IFAFREE((&oia->ia_ifa)); - splx(s); - break; - - default: - if (ifp == 0 || ifp->if_ioctl == 0) - return (EOPNOTSUPP); - return ((*ifp->if_ioctl)(ifp, cmd, data)); - } - return (0); -} - -/* - * Delete any existing route for an interface. - */ -static void -in_ifscrub(ifp, ia) - register struct ifnet *ifp; - register struct in_ifaddr *ia; -{ - - if ((ia->ia_flags & IFA_ROUTE) == 0) - return; - if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) - rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); - else - rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); - ia->ia_flags &= ~IFA_ROUTE; -} - -/* - * Initialize an interface's internet address - * and routing table entry. - */ -static int -in_ifinit(ifp, ia, sin, scrub) - register struct ifnet *ifp; - register struct in_ifaddr *ia; - struct sockaddr_in *sin; - int scrub; -{ - register u_long i = ntohl(sin->sin_addr.s_addr); - struct sockaddr_in oldaddr; - int s = splimp(), flags = RTF_UP, error; - struct multi_kludge *mk; - - oldaddr = ia->ia_addr; - ia->ia_addr = *sin; - /* - * Give the interface a chance to initialize - * if this is its first address, - * and to validate the address if necessary. - */ - if (ifp->if_ioctl && - (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { - splx(s); - ia->ia_addr = oldaddr; - return (error); - } - splx(s); - if (scrub) { - ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; - in_ifscrub(ifp, ia); - ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; - } - if (IN_CLASSA(i)) - ia->ia_netmask = IN_CLASSA_NET; - else if (IN_CLASSB(i)) - ia->ia_netmask = IN_CLASSB_NET; - else - ia->ia_netmask = IN_CLASSC_NET; - /* - * The subnet mask usually includes at least the standard network part, - * but may may be smaller in the case of supernetting. - * If it is set, we believe it. - */ - if (ia->ia_subnetmask == 0) { - ia->ia_subnetmask = ia->ia_netmask; - ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); - } else - ia->ia_netmask &= ia->ia_subnetmask; - ia->ia_net = i & ia->ia_netmask; - ia->ia_subnet = i & ia->ia_subnetmask; - in_socktrim(&ia->ia_sockmask); - /* - * Add route for the network. - */ - ia->ia_ifa.ifa_metric = ifp->if_metric; - if (ifp->if_flags & IFF_BROADCAST) { - ia->ia_broadaddr.sin_addr.s_addr = - htonl(ia->ia_subnet | ~ia->ia_subnetmask); - ia->ia_netbroadcast.s_addr = - htonl(ia->ia_net | ~ ia->ia_netmask); - } else if (ifp->if_flags & IFF_LOOPBACK) { - ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; - flags |= RTF_HOST; - } else if (ifp->if_flags & IFF_POINTOPOINT) { - if (ia->ia_dstaddr.sin_family != AF_INET) - return (0); - flags |= RTF_HOST; - } - if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) - ia->ia_flags |= IFA_ROUTE; - - LIST_INIT(&ia->ia_multiaddrs); - /* - * If the interface supports multicast, join the "all hosts" - * multicast group on that interface. - */ - if (ifp->if_flags & IFF_MULTICAST) { - struct in_addr addr; - - /* - * Continuation of multicast address hack: - * If there was a multicast group list previously saved - * for this interface, then we re-attach it to the first - * address configured on the i/f. - */ - for(mk = in_mk.lh_first; mk; mk = mk->mk_entry.le_next) { - if(mk->mk_ifp == ifp) { - struct in_multi *inm; - - for(inm = mk->mk_head.lh_first; inm; - inm = inm->inm_entry.le_next) { - IFAFREE(&inm->inm_ia->ia_ifa); - ia->ia_ifa.ifa_refcnt++; - inm->inm_ia = ia; - LIST_INSERT_HEAD(&ia->ia_multiaddrs, - inm, inm_entry); - } - LIST_REMOVE(mk, mk_entry); - free(mk, M_IPMADDR); - break; - } - } - - addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); - in_addmulti(&addr, ifp); - } - return (error); -} - - -/* - * Return 1 if the address might be a local broadcast address. - */ -int -in_broadcast(in, ifp) - struct in_addr in; - struct ifnet *ifp; -{ - register struct ifaddr *ifa; - u_long t; - - if (in.s_addr == INADDR_BROADCAST || - in.s_addr == INADDR_ANY) - return 1; - if ((ifp->if_flags & IFF_BROADCAST) == 0) - return 0; - t = ntohl(in.s_addr); - /* - * Look through the list of addresses for a match - * with a broadcast address. - */ -#define ia ((struct in_ifaddr *)ifa) - for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) - if (ifa->ifa_addr->sa_family == AF_INET && - (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr || - in.s_addr == ia->ia_netbroadcast.s_addr || - /* - * Check for old-style (host 0) broadcast. - */ - t == ia->ia_subnet || t == ia->ia_net) && - /* - * Check for an all one subnetmask. These - * only exist when an interface gets a secondary - * address. - */ - ia->ia_subnetmask != (u_long)0xffffffff) - return 1; - return (0); -#undef ia -} -/* - * Add an address to the list of IP multicast addresses for a given interface. - */ -struct in_multi * -in_addmulti(ap, ifp) - register struct in_addr *ap; - register struct ifnet *ifp; -{ - register struct in_multi *inm; - struct ifreq ifr; - struct in_ifaddr *ia; - int s = splnet(); - - /* - * See if address already in list. - */ - IN_LOOKUP_MULTI(*ap, ifp, inm); - if (inm != NULL) { - /* - * Found it; just increment the reference count. - */ - ++inm->inm_refcount; - } - else { - /* - * New address; allocate a new multicast record - * and link it into the interface's multicast list. - */ - inm = (struct in_multi *)malloc(sizeof(*inm), - M_IPMADDR, M_NOWAIT); - if (inm == NULL) { - splx(s); - return (NULL); - } - inm->inm_addr = *ap; - inm->inm_ifp = ifp; - inm->inm_refcount = 1; - IFP_TO_IA(ifp, ia); - if (ia == NULL) { - free(inm, M_IPMADDR); - splx(s); - return (NULL); - } - inm->inm_ia = ia; - ia->ia_ifa.ifa_refcnt++; /* gain a reference */ - LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_entry); - - /* - * Ask the network driver to update its multicast reception - * filter appropriately for the new address. - */ - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; - if ((ifp->if_ioctl == NULL) || - (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { - LIST_REMOVE(inm, inm_entry); - IFAFREE(&ia->ia_ifa); /* release reference */ - free(inm, M_IPMADDR); - splx(s); - return (NULL); - } - /* - * Let IGMP know that we have joined a new IP multicast group. - */ - igmp_joingroup(inm); - } - splx(s); - return (inm); -} - -/* - * Delete a multicast address record. - */ -void -in_delmulti(inm) - register struct in_multi *inm; -{ - struct ifreq ifr; - int s = splnet(); - - if (--inm->inm_refcount == 0) { - /* - * No remaining claims to this record; let IGMP know that - * we are leaving the multicast group. - */ - igmp_leavegroup(inm); - /* - * Unlink from list. - */ - LIST_REMOVE(inm, inm_entry); - IFAFREE(&inm->inm_ia->ia_ifa); /* release reference */ - - /* - * Notify the network driver to update its multicast reception - * filter. - */ - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = - inm->inm_addr; - (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, - (caddr_t)&ifr); - free(inm, M_IPMADDR); - } - splx(s); -} diff --git a/c/src/exec/libnetworking/netinet/in.h b/c/src/exec/libnetworking/netinet/in.h deleted file mode 100644 index 7cc4709697..0000000000 --- a/c/src/exec/libnetworking/netinet/in.h +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1990, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)in.h 8.3 (Berkeley) 1/3/94 - * $Id$ - */ - -#ifndef _NETINET_IN_H_ -#define _NETINET_IN_H_ - -/* - * Constants and structures defined by the internet system, - * Per RFC 790, September 1981, and numerous additions. - */ - -/* - * Protocols (RFC 1700) - */ -#define IPPROTO_IP 0 /* dummy for IP */ -#define IPPROTO_ICMP 1 /* control message protocol */ -#define IPPROTO_IGMP 2 /* group mgmt protocol */ -#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */ -#define IPPROTO_IPIP 4 /* IP encapsulation in IP */ -#define IPPROTO_TCP 6 /* tcp */ -#define IPPROTO_ST 7 /* Stream protocol II */ -#define IPPROTO_EGP 8 /* exterior gateway protocol */ -#define IPPROTO_PIGP 9 /* private interior gateway */ -#define IPPROTO_RCCMON 10 /* BBN RCC Monitoring */ -#define IPPROTO_NVPII 11 /* network voice protocol*/ -#define IPPROTO_PUP 12 /* pup */ -#define IPPROTO_ARGUS 13 /* Argus */ -#define IPPROTO_EMCON 14 /* EMCON */ -#define IPPROTO_XNET 15 /* Cross Net Debugger */ -#define IPPROTO_CHAOS 16 /* Chaos*/ -#define IPPROTO_UDP 17 /* user datagram protocol */ -#define IPPROTO_MUX 18 /* Multiplexing */ -#define IPPROTO_MEAS 19 /* DCN Measurement Subsystems */ -#define IPPROTO_HMP 20 /* Host Monitoring */ -#define IPPROTO_PRM 21 /* Packet Radio Measurement */ -#define IPPROTO_IDP 22 /* xns idp */ -#define IPPROTO_TRUNK1 23 /* Trunk-1 */ -#define IPPROTO_TRUNK2 24 /* Trunk-2 */ -#define IPPROTO_LEAF1 25 /* Leaf-1 */ -#define IPPROTO_LEAF2 26 /* Leaf-2 */ -#define IPPROTO_RDP 27 /* Reliable Data */ -#define IPPROTO_IRTP 28 /* Reliable Transaction */ -#define IPPROTO_TP 29 /* tp-4 w/ class negotiation */ -#define IPPROTO_BLT 30 /* Bulk Data Transfer */ -#define IPPROTO_NSP 31 /* Network Services */ -#define IPPROTO_INP 32 /* Merit Internodal */ -#define IPPROTO_SEP 33 /* Sequential Exchange */ -#define IPPROTO_3PC 34 /* Third Party Connect */ -#define IPPROTO_IDPR 35 /* InterDomain Policy Routing */ -#define IPPROTO_XTP 36 /* XTP */ -#define IPPROTO_DDP 37 /* Datagram Delivery */ -#define IPPROTO_CMTP 38 /* Control Message Transport */ -#define IPPROTO_TPXX 39 /* TP++ Transport */ -#define IPPROTO_IL 40 /* IL transport protocol */ -#define IPPROTO_SIP 41 /* Simple Internet Protocol */ -#define IPPROTO_SDRP 42 /* Source Demand Routing */ -#define IPPROTO_SIPSR 43 /* SIP Source Route */ -#define IPPROTO_SIPFRAG 44 /* SIP Fragment */ -#define IPPROTO_IDRP 45 /* InterDomain Routing*/ -#define IPPROTO_RSVP 46 /* resource reservation */ -#define IPPROTO_GRE 47 /* General Routing Encap. */ -#define IPPROTO_MHRP 48 /* Mobile Host Routing */ -#define IPPROTO_BHA 49 /* BHA */ -#define IPPROTO_ESP 50 /* SIPP Encap Sec. Payload */ -#define IPPROTO_AH 51 /* SIPP Auth Header */ -#define IPPROTO_INLSP 52 /* Integ. Net Layer Security */ -#define IPPROTO_SWIPE 53 /* IP with encryption */ -#define IPPROTO_NHRP 54 /* Next Hop Resolution */ -/* 55-60: Unassigned */ -#define IPPROTO_AHIP 61 /* any host internal protocol */ -#define IPPROTO_CFTP 62 /* CFTP */ -#define IPPROTO_HELLO 63 /* "hello" routing protocol */ -#define IPPROTO_SATEXPAK 64 /* SATNET/Backroom EXPAK */ -#define IPPROTO_KRYPTOLAN 65 /* Kryptolan */ -#define IPPROTO_RVD 66 /* Remote Virtual Disk */ -#define IPPROTO_IPPC 67 /* Pluribus Packet Core */ -#define IPPROTO_ADFS 68 /* Any distributed FS */ -#define IPPROTO_SATMON 69 /* Satnet Monitoring */ -#define IPPROTO_VISA 70 /* VISA Protocol */ -#define IPPROTO_IPCV 71 /* Packet Core Utility */ -#define IPPROTO_CPNX 72 /* Comp. Prot. Net. Executive */ -#define IPPROTO_CPHB 73 /* Comp. Prot. HeartBeat */ -#define IPPROTO_WSN 74 /* Wang Span Network */ -#define IPPROTO_PVP 75 /* Packet Video Protocol */ -#define IPPROTO_BRSATMON 76 /* BackRoom SATNET Monitoring */ -#define IPPROTO_ND 77 /* Sun net disk proto (temp.) */ -#define IPPROTO_WBMON 78 /* WIDEBAND Monitoring */ -#define IPPROTO_WBEXPAK 79 /* WIDEBAND EXPAK */ -#define IPPROTO_EON 80 /* ISO cnlp */ -#define IPPROTO_VMTP 81 /* VMTP */ -#define IPPROTO_SVMTP 82 /* Secure VMTP */ -#define IPPROTO_VINES 83 /* Banyon VINES */ -#define IPPROTO_TTP 84 /* TTP */ -#define IPPROTO_IGP 85 /* NSFNET-IGP */ -#define IPPROTO_DGP 86 /* dissimilar gateway prot. */ -#define IPPROTO_TCF 87 /* TCF */ -#define IPPROTO_IGRP 88 /* Cisco/GXS IGRP */ -#define IPPROTO_OSPFIGP 89 /* OSPFIGP */ -#define IPPROTO_SRPC 90 /* Strite RPC protocol */ -#define IPPROTO_LARP 91 /* Locus Address Resoloution */ -#define IPPROTO_MTP 92 /* Multicast Transport */ -#define IPPROTO_AX25 93 /* AX.25 Frames */ -#define IPPROTO_IPEIP 94 /* IP encapsulated in IP */ -#define IPPROTO_MICP 95 /* Mobile Int.ing control */ -#define IPPROTO_SCCSP 96 /* Semaphore Comm. security */ -#define IPPROTO_ETHERIP 97 /* Ethernet IP encapsulation */ -#define IPPROTO_ENCAP 98 /* encapsulation header */ -#define IPPROTO_APES 99 /* any private encr. scheme */ -#define IPPROTO_GMTP 100 /* GMTP*/ -/* 101-254: Unassigned */ -/* 255: Reserved */ -/* BSD Private, local use, namespace incursion */ -#define IPPROTO_DIVERT 254 /* divert pseudo-protocol */ -#define IPPROTO_RAW 255 /* raw IP packet */ -#define IPPROTO_MAX 256 - - -/* - * Local port number conventions: - * - * When a user does a bind(2) or connect(2) with a port number of zero, - * a non-conflicting local port address is chosen. - * The default range is IPPORT_RESERVED through - * IPPORT_USERRESERVED, although that is settable by sysctl. - * - * A user may set the IPPROTO_IP option IP_PORTRANGE to change this - * default assignment range. - * - * The value IP_PORTRANGE_DEFAULT causes the default behavior. - * - * The value IP_PORTRANGE_HIGH changes the range of candidate port numbers - * into the "high" range. These are reserved for client outbound connections - * which do not want to be filtered by any firewalls. - * - * The value IP_PORTRANGE_LOW changes the range to the "low" are - * that is (by convention) restricted to privileged processes. This - * convention is based on "vouchsafe" principles only. It is only secure - * if you trust the remote host to restrict these ports. - * - * The default range of ports and the high range can be changed by - * sysctl(3). (net.inet.ip.port{hi,low}{first,last}_auto) - * - * Changing those values has bad security implications if you are - * using a a stateless firewall that is allowing packets outside of that - * range in order to allow transparent outgoing connections. - * - * Such a firewall configuration will generally depend on the use of these - * default values. If you change them, you may find your Security - * Administrator looking for you with a heavy object. - */ - -/* - * Ports < IPPORT_RESERVED are reserved for - * privileged processes (e.g. root). (IP_PORTRANGE_LOW) - * Ports > IPPORT_USERRESERVED are reserved - * for servers, not necessarily privileged. (IP_PORTRANGE_DEFAULT) - */ -#define IPPORT_RESERVED 1024 -#define IPPORT_USERRESERVED 5000 - -/* - * Default local port range to use by setting IP_PORTRANGE_HIGH - */ -#define IPPORT_HIFIRSTAUTO 40000 -#define IPPORT_HILASTAUTO 44999 - -/* - * Scanning for a free reserved port return a value below IPPORT_RESERVED, - * but higher than IPPORT_RESERVEDSTART. Traditionally the start value was - * 512, but that conflicts with some well-known-services that firewalls may - * have a fit if we use. - */ -#define IPPORT_RESERVEDSTART 600 -#define BYTE_PACK __attribute__((packed)) -/* - * Internet address (a structure for historical reasons) - */ -struct in_addr { - u_long s_addr BYTE_PACK; -}; - -/* - * Definitions of bits in internet address integers. - * On subnets, the decomposition of addresses to host and net parts - * is done according to subnet mask, not the masks here. - */ -#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) -#define IN_CLASSA_NET 0xff000000 -#define IN_CLASSA_NSHIFT 24 -#define IN_CLASSA_HOST 0x00ffffff -#define IN_CLASSA_MAX 128 - -#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) -#define IN_CLASSB_NET 0xffff0000 -#define IN_CLASSB_NSHIFT 16 -#define IN_CLASSB_HOST 0x0000ffff -#define IN_CLASSB_MAX 65536 - -#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) -#define IN_CLASSC_NET 0xffffff00 -#define IN_CLASSC_NSHIFT 8 -#define IN_CLASSC_HOST 0x000000ff - -#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) -#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */ -#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */ -#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */ -#define IN_MULTICAST(i) IN_CLASSD(i) - -#define IN_EXPERIMENTAL(i) (((long)(i) & 0xf0000000) == 0xf0000000) -#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000) - -#define INADDR_ANY (u_long)0x00000000 -#define INADDR_BROADCAST (u_long)0xffffffff /* must be masked */ -#ifndef KERNEL -#define INADDR_NONE 0xffffffff /* -1 return */ -#endif - -#define INADDR_UNSPEC_GROUP (u_long)0xe0000000 /* 224.0.0.0 */ -#define INADDR_ALLHOSTS_GROUP (u_long)0xe0000001 /* 224.0.0.1 */ -#define INADDR_ALLRTRS_GROUP (u_long)0xe0000002 /* 224.0.0.2 */ -#define INADDR_MAX_LOCAL_GROUP (u_long)0xe00000ff /* 224.0.0.255 */ - -#define IN_LOOPBACKNET 127 /* official! */ -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK (u_long)0x7F000001 /* 127.0.0.1 */ -#endif - -/* - * Socket address, internet style. - */ -struct sockaddr_in { - u_char sin_len; - u_char sin_family; - u_short sin_port; - struct in_addr sin_addr; - char sin_zero[8]; -}; - -/* - * Structure used to describe IP options. - * Used to store options internally, to pass them to a process, - * or to restore options retrieved earlier. - * The ip_dst is used for the first-hop gateway when using a source route - * (this gets put into the header proper). - */ -struct ip_opts { - struct in_addr ip_dst; /* first hop, 0 w/o src rt */ - char ip_opts[40]; /* actually variable in size */ -}; - -/* - * Options for use with [gs]etsockopt at the IP level. - * First word of comment is data type; bool is stored in int. - */ -#define IP_OPTIONS 1 /* buf/ip_opts; set/get IP options */ -#define IP_HDRINCL 2 /* int; header is included with data */ -#define IP_TOS 3 /* int; IP type of service and preced. */ -#define IP_TTL 4 /* int; IP time to live */ -#define IP_RECVOPTS 5 /* bool; receive all IP opts w/dgram */ -#define IP_RECVRETOPTS 6 /* bool; receive IP opts for response */ -#define IP_RECVDSTADDR 7 /* bool; receive IP dst addr w/dgram */ -#define IP_RETOPTS 8 /* ip_opts; set/get IP options */ -#define IP_MULTICAST_IF 9 /* u_char; set/get IP multicast i/f */ -#define IP_MULTICAST_TTL 10 /* u_char; set/get IP multicast ttl */ -#define IP_MULTICAST_LOOP 11 /* u_char; set/get IP multicast loopback */ -#define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */ -#define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */ -#define IP_MULTICAST_VIF 14 /* set/get IP mcast virt. iface */ -#define IP_RSVP_ON 15 /* enable RSVP in kernel */ -#define IP_RSVP_OFF 16 /* disable RSVP in kernel */ -#define IP_RSVP_VIF_ON 17 /* set RSVP per-vif socket */ -#define IP_RSVP_VIF_OFF 18 /* unset RSVP per-vif socket */ -#define IP_PORTRANGE 19 /* int; range to choose for unspec port */ -#define IP_RECVIF 20 /* bool; receive reception if w/dgram */ - -#define IP_FW_ADD 50 /* add a firewall rule to chain */ -#define IP_FW_DEL 51 /* delete a firewall rule from chain */ -#define IP_FW_FLUSH 52 /* flush firewall rule chain */ -#define IP_FW_ZERO 53 /* clear single/all firewall counter(s) */ -#define IP_FW_GET 54 /* get entire firewall rule chain */ -#define IP_NAT 55 /* set/get NAT opts */ - -/* - * Defaults and limits for options - */ -#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */ -#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ -#define IP_MAX_MEMBERSHIPS 20 /* per socket */ - -/* - * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP. - */ -struct ip_mreq { - struct in_addr imr_multiaddr; /* IP multicast address of group */ - struct in_addr imr_interface; /* local IP address of interface */ -}; - -/* - * Argument for IP_PORTRANGE: - * - which range to search when port is unspecified at bind() or connect() - */ -#define IP_PORTRANGE_DEFAULT 0 /* default range */ -#define IP_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */ -#define IP_PORTRANGE_LOW 2 /* "low" - vouchsafe security */ - -/* - * Definitions for inet sysctl operations. - * - * Third level is protocol number. - * Fourth level is desired variable within that protocol. - */ -#define IPPROTO_MAXID (IPPROTO_IDP + 1) /* don't list to IPPROTO_MAX */ - -#define CTL_IPPROTO_NAMES { \ - { "ip", CTLTYPE_NODE }, \ - { "icmp", CTLTYPE_NODE }, \ - { "igmp", CTLTYPE_NODE }, \ - { "ggp", CTLTYPE_NODE }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { "tcp", CTLTYPE_NODE }, \ - { 0, 0 }, \ - { "egp", CTLTYPE_NODE }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { "pup", CTLTYPE_NODE }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { "udp", CTLTYPE_NODE }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { 0, 0 }, \ - { "idp", CTLTYPE_NODE }, \ -} - -/* - * Names for IP sysctl objects - */ -#define IPCTL_FORWARDING 1 /* act as router */ -#define IPCTL_SENDREDIRECTS 2 /* may send redirects when forwarding */ -#define IPCTL_DEFTTL 3 /* default TTL */ -#ifdef notyet -#define IPCTL_DEFMTU 4 /* default MTU */ -#endif -#define IPCTL_RTEXPIRE 5 /* cloned route expiration time */ -#define IPCTL_RTMINEXPIRE 6 /* min value for expiration time */ -#define IPCTL_RTMAXCACHE 7 /* trigger level for dynamic expire */ -#define IPCTL_SOURCEROUTE 8 /* may perform source routes */ -#define IPCTL_DIRECTEDBROADCAST 9 /* may re-broadcast received packets */ -#define IPCTL_INTRQMAXLEN 10 /* max length of netisr queue */ -#define IPCTL_INTRQDROPS 11 /* number of netisr q drops */ -#define IPCTL_ACCEPTSOURCEROUTE 13 /* may accept source routed packets */ -#define IPCTL_MAXID 13 - -#define IPCTL_NAMES { \ - { 0, 0 }, \ - { "forwarding", CTLTYPE_INT }, \ - { "redirect", CTLTYPE_INT }, \ - { "ttl", CTLTYPE_INT }, \ - { "mtu", CTLTYPE_INT }, \ - { "rtexpire", CTLTYPE_INT }, \ - { "rtminexpire", CTLTYPE_INT }, \ - { "rtmaxcache", CTLTYPE_INT }, \ - { "sourceroute", CTLTYPE_INT }, \ - { "directed-broadcast", CTLTYPE_INT }, \ - { "intr-queue-maxlen", CTLTYPE_INT }, \ - { "intr-queue-drops", CTLTYPE_INT }, \ - { "accept_sourceroute", CTLTYPE_INT }, \ -} - - -#ifdef KERNEL -struct ifnet; struct mbuf; /* forward declarations for Standard C */ - -int in_broadcast __P((struct in_addr, struct ifnet *)); -int in_canforward __P((struct in_addr)); -int in_cksum __P((struct mbuf *, int)); -int in_localaddr __P((struct in_addr)); -char *inet_ntoa __P((struct in_addr)); /* in libkern */ - -/* Firewall hooks */ -struct ip; -typedef int ip_fw_chk_t __P((struct ip**, int, struct ifnet*, int, struct mbuf**)); -typedef int ip_fw_ctl_t __P((int, struct mbuf**)); -extern ip_fw_chk_t *ip_fw_chk_ptr; -extern ip_fw_ctl_t *ip_fw_ctl_ptr; - -/* IP NAT hooks */ -typedef int ip_nat_t __P((struct ip**, struct mbuf**, struct ifnet*, int)); -typedef int ip_nat_ctl_t __P((int, struct mbuf**)); -extern ip_nat_t *ip_nat_ptr; -extern ip_nat_ctl_t *ip_nat_ctl_ptr; -#define IP_NAT_IN 0x00000001 -#define IP_NAT_OUT 0x00000002 - -#endif /* KERNEL */ - -#endif diff --git a/c/src/exec/libnetworking/netinet/in_cksum.c b/c/src/exec/libnetworking/netinet/in_cksum.c deleted file mode 100644 index c7792e0e87..0000000000 --- a/c/src/exec/libnetworking/netinet/in_cksum.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 1988, 1992, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/mbuf.h> - -/* - * Try to use a CPU specific version, then punt to the portable C one. - */ - -#if (defined(__GNUC__) && (defined(__mc68000__) || defined(__m68k__))) - -#include "in_cksum_m68k.c" - -#elif (defined(__GNUC__) && defined(__i386__)) - -#include "in_cksum_i386.c" - -#elif (defined(__GNUC__) && defined(__PPC__)) - -#include "in_cksum_powerpc.c" - -#else - -/* - * Checksum routine for Internet Protocol family headers (Portable Version). - * - * This routine is very heavily used in the network - * code and should be modified for each CPU to be as fast as possible. - */ - -#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) -#define REDUCE \ - {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} - -int -in_cksum(m, len) - register struct mbuf *m; - register int len; -{ - register u_short *w; - register int sum = 0; - register int mlen = 0; - int byte_swapped = 0; - - union { - char c[2]; - u_short s; - } s_util; - union { - u_short s[2]; - long l; - } l_util; - - for (;m && len; m = m->m_next) { - if (m->m_len == 0) - continue; - w = mtod(m, u_short *); - if (mlen == -1) { - /* - * The first byte of this mbuf is the continuation - * of a word spanning between this mbuf and the - * last mbuf. - * - * s_util.c[0] is already saved when scanning previous - * mbuf. - */ - s_util.c[1] = *(char *)w; - sum += s_util.s; - w = (u_short *)((char *)w + 1); - mlen = m->m_len - 1; - len--; - } else - mlen = m->m_len; - if (len < mlen) - mlen = len; - len -= mlen; - /* - * Force to even boundary. - */ - if ((1 & (int) w) && (mlen > 0)) { - REDUCE; - sum <<= 8; - s_util.c[0] = *(u_char *)w; - w = (u_short *)((char *)w + 1); - mlen--; - byte_swapped = 1; - } - /* - * Unroll the loop to make overhead from - * branches &c small. - */ - while ((mlen -= 32) >= 0) { - sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; - sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; - sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; - sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; - w += 16; - } - mlen += 32; - while ((mlen -= 8) >= 0) { - sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; - w += 4; - } - mlen += 8; - if (mlen == 0 && byte_swapped == 0) - continue; - REDUCE; - while ((mlen -= 2) >= 0) { - sum += *w++; - } - if (byte_swapped) { - REDUCE; - sum <<= 8; - byte_swapped = 0; - if (mlen == -1) { - s_util.c[1] = *(char *)w; - sum += s_util.s; - mlen = 0; - } else - mlen = -1; - } else if (mlen == -1) - s_util.c[0] = *(char *)w; - } - if (len) - puts("cksum: out of data"); - if (mlen == -1) { - /* The last mbuf has odd # of bytes. Follow the - standard (the odd byte may be shifted left by 8 bits - or not as determined by endian-ness of the machine) */ - s_util.c[1] = 0; - sum += s_util.s; - } - REDUCE; - return (~sum & 0xffff); -} -#endif diff --git a/c/src/exec/libnetworking/netinet/in_cksum_i386.c b/c/src/exec/libnetworking/netinet/in_cksum_i386.c deleted file mode 100644 index a64bd57832..0000000000 --- a/c/src/exec/libnetworking/netinet/in_cksum_i386.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Checksum routine for Internet Protocol family headers. - * - * This routine is very heavily used in the network - * code and should be modified for each CPU to be as fast as possible. - * - * This implementation is 386 version. - * - * $Id$ - */ - -#include <stdio.h> /* for puts */ - -#undef ADDCARRY -#define ADDCARRY(x) if ((x) > 0xffff) (x) -= 0xffff -#define REDUCE {sum = (sum & 0xffff) + (sum >> 16); ADDCARRY(sum);} - -/* - * Thanks to gcc we don't have to guess - * which registers contain sum & w. - */ -#define ADD(n) __asm__ volatile \ - ("addl " #n "(%2), %0" : "=r" (sum) : "0" (sum), "r" (w)) -#define ADDC(n) __asm__ volatile \ - ("adcl " #n "(%2), %0" : "=r" (sum) : "0" (sum), "r" (w)) -#define LOAD(n) __asm__ volatile \ - ("movb " #n "(%1), %0" : "=r" (junk) : "r" (w)) -#define MOP __asm__ volatile \ - ("adcl $0, %0" : "=r" (sum) : "0" (sum)) - -int -in_cksum(m, len) - register struct mbuf *m; - register int len; -{ - register u_short *w; - register unsigned sum = 0; - register int mlen = 0; - int byte_swapped = 0; - union { char c[2]; u_short s; } su; - - for (;m && len; m = m->m_next) { - if (m->m_len == 0) - continue; - w = mtod(m, u_short *); - if (mlen == -1) { - /* - * The first byte of this mbuf is the continuation - * of a word spanning between this mbuf and the - * last mbuf. - */ - - /* su.c[0] is already saved when scanning previous - * mbuf. sum was REDUCEd when we found mlen == -1 - */ - su.c[1] = *(u_char *)w; - sum += su.s; - w = (u_short *)((char *)w + 1); - mlen = m->m_len - 1; - len--; - } else - mlen = m->m_len; - if (len < mlen) - mlen = len; - len -= mlen; - /* - * Force to long boundary so we do longword aligned - * memory operations - */ - if (3 & (int) w) { - REDUCE; - if ((1 & (int) w) && (mlen > 0)) { - sum <<= 8; - su.c[0] = *(char *)w; - w = (u_short *)((char *)w + 1); - mlen--; - byte_swapped = 1; - } - if ((2 & (int) w) && (mlen >= 2)) { - sum += *w++; - mlen -= 2; - } - } - /* - * Advance to a 486 cache line boundary. - */ - if (4 & (int) w && mlen >= 4) { - ADD(0); - MOP; - w += 2; - mlen -= 4; - } - if (8 & (int) w && mlen >= 8) { - ADD(0); - ADDC(4); - MOP; - w += 4; - mlen -= 8; - } - /* - * Do as much of the checksum as possible 32 bits at at time. - * In fact, this loop is unrolled to make overhead from - * branches &c small. - */ - mlen -= 1; - while ((mlen -= 32) >= 0) { - u_char junk; - /* - * Add with carry 16 words and fold in the last - * carry by adding a 0 with carry. - * - * The early ADD(16) and the LOAD(32) are to load - * the next 2 cache lines in advance on 486's. The - * 486 has a penalty of 2 clock cycles for loading - * a cache line, plus whatever time the external - * memory takes to load the first word(s) addressed. - * These penalties are unavoidable. Subsequent - * accesses to a cache line being loaded (and to - * other external memory?) are delayed until the - * whole load finishes. These penalties are mostly - * avoided by not accessing external memory for - * 8 cycles after the ADD(16) and 12 cycles after - * the LOAD(32). The loop terminates when mlen - * is initially 33 (not 32) to guaranteed that - * the LOAD(32) is within bounds. - */ - ADD(16); - ADDC(0); - ADDC(4); - ADDC(8); - ADDC(12); - LOAD(32); - ADDC(20); - ADDC(24); - ADDC(28); - MOP; - w += 16; - } - mlen += 32 + 1; - if (mlen >= 32) { - ADD(16); - ADDC(0); - ADDC(4); - ADDC(8); - ADDC(12); - ADDC(20); - ADDC(24); - ADDC(28); - MOP; - w += 16; - mlen -= 32; - } - if (mlen >= 16) { - ADD(0); - ADDC(4); - ADDC(8); - ADDC(12); - MOP; - w += 8; - mlen -= 16; - } - if (mlen >= 8) { - ADD(0); - ADDC(4); - MOP; - w += 4; - mlen -= 8; - } - if (mlen == 0 && byte_swapped == 0) - continue; /* worth 1% maybe ?? */ - REDUCE; - while ((mlen -= 2) >= 0) { - sum += *w++; - } - if (byte_swapped) { - sum <<= 8; - byte_swapped = 0; - if (mlen == -1) { - su.c[1] = *(char *)w; - sum += su.s; - mlen = 0; - } else - mlen = -1; - } else if (mlen == -1) - /* - * This mbuf has odd number of bytes. - * There could be a word split betwen - * this mbuf and the next mbuf. - * Save the last byte (to prepend to next mbuf). - */ - su.c[0] = *(char *)w; - } - - if (len) - puts("cksum: out of data"); - if (mlen == -1) { - /* The last mbuf has odd # of bytes. Follow the - standard (the odd byte is shifted left by 8 bits) */ - su.c[1] = 0; - sum += su.s; - } - REDUCE; - return (~sum & 0xffff); -} diff --git a/c/src/exec/libnetworking/netinet/in_cksum_m68k.c b/c/src/exec/libnetworking/netinet/in_cksum_m68k.c deleted file mode 100644 index 58199c3adf..0000000000 --- a/c/src/exec/libnetworking/netinet/in_cksum_m68k.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 1988, 1992, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/mbuf.h> - -#if (defined (__mcf5200__)) -# define IS_COLDFIRE 1 -#else -# define IS_COLDFIRE 0 -#endif - -#define REDUCE { sum = (sum & 0xFFFF) + (sum >> 16); if (sum > 0xFFFF) sum -= 0xFFFF; } - -/* - * Motorola 68k version of Internet Protocol Checksum routine - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * August, 1998 - */ -int -in_cksum(m, len) - struct mbuf *m; - int len; -{ - unsigned short *w; - unsigned long sum = 0; - int mlen = 0; - int byte_swapped = 0; - union { - char c[2]; - u_short s; - } s_util; - - for ( ; m && len ; m = m->m_next) { - if (m->m_len == 0) - continue; - w = mtod(m, u_short *); - if (mlen == -1) { - /* - * The first byte of this mbuf is the continuation - * of a word spanning between this mbuf and the - * last mbuf. - * - * s_util.c[0] is already saved when scanning previous - * mbuf. - */ - s_util.c[1] = *(char *)w; - sum += s_util.s; - w = (u_short *)((char *)w + 1); - mlen = m->m_len - 1; - len--; - } else - mlen = m->m_len; - if (len < mlen) - mlen = len; - len -= mlen; - - /* - * Force to longword boundary. - */ - if (3 & (int)w) { - REDUCE; - if ((1 & (int) w) && (mlen > 0)) { - sum <<= 8; - s_util.c[0] = *(u_char *)w; - w = (u_short *)((char *)w + 1); - mlen--; - byte_swapped = 1; - } - if ((2 & (int) w) && (mlen >= 2)) { - sum += *w++; - mlen -= 2; - } - } - - /* - * Sum all the longwords in the buffer. - * See RFC 1071 -- Computing the Internet Checksum. - * It should work for all 68k family members. - */ - { - unsigned long tcnt = mlen, t1; - __asm__ volatile ( - "movel %2,%3\n\t" - "lsrl #6,%2 | count/64 = # loop traversals\n\t" - "andl #0x3c,%3 | Then find fractions of a chunk\n\t" - "negl %3\n\t | Each long uses 4 instruction bytes\n\t" -#if IS_COLDFIRE - "addql #1,%2 | Clear X (extended carry flag)\n\t" - "subql #1,%2 | \n\t" -#else - "andi #0xf,%%cc | Clear X (extended carry flag)\n\t" -#endif - "jmp %%pc@(lcsum2_lbl-.-2:b,%3) | Jump into loop\n" - "lcsum1_lbl: | Begin inner loop...\n\t" - "movel %1@+,%3 | 0: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | 1: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | 2: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | 3: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | 4: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | 5: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | 6: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | 7: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | 8: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | 9: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | A: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | B: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | C: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | D: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | E: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n\t" - "movel %1@+,%3 | F: Fetch 32-bit word\n\t" - "addxl %3,%0 | Add word + previous carry\n" - "lcsum2_lbl: | End of unrolled loop\n\t" -#if IS_COLDFIRE - "moveq #0,%3 | Add in last carry\n\t" - "addxl %3,%0 |\n\t" - "subql #1,%2 | Update loop count\n\t" - "bplb lcsum1_lbl | Loop (with X clear) if not done\n\t" - "movel #0xffff,%2 | Get word mask\n\t" - "movel %0,%3 | Fold 32 bit sum to 16 bits\n\t" - "swap %3 |\n\t" - "andl %2,%0 | Mask to 16-bit sum\n\t" - "andl %2,%3 | Mask to 16-bit sum\n\t" - "addl %3,%0 |\n\t" - "movel %0,%3 | Add in last carry\n\t" - "swap %3 |\n\t" - "addl %3,%0 |\n\t" - "andl %2,%0 | Mask to 16-bit sum\n\t" -#else - "dbf %2,lcsum1_lbl | (NB- dbf doesn't affect X)\n\t" - "movel %0,%3 | Fold 32 bit sum to 16 bits\n\t" - "swap %3 | (NB- swap doesn't affect X)\n\t" - "addxw %3,%0 |\n\t" - "moveq #0,%3 | Add in last carry\n\t" - "addxw %3,%0 |\n\t" - "andl #0xffff,%0 | Mask to 16-bit sum\n" -#endif - : - "=d" (sum), "=a" (w), "=d" (tcnt) , "=d" (t1) : - "0" (sum), "1" (w), "2" (tcnt) : - "cc", "memory"); - } - mlen &= 3; - - /* - * Soak up the last 1, 2 or 3 bytes - */ - while ((mlen -= 2) >= 0) - sum += *w++; - if (byte_swapped) { - REDUCE; - sum <<= 8; - byte_swapped = 0; - if (mlen == -1) { - s_util.c[1] = *(char *)w; - sum += s_util.s; - mlen = 0; - } else - mlen = -1; - } else if (mlen == -1) - s_util.c[0] = *(char *)w; - } - if (len) - sum = 0xDEAD; - if (mlen == -1) { - /* The last mbuf has odd # of bytes. Follow the - standard (the odd byte may be shifted left by 8 bits - or not as determined by endian-ness of the machine) */ - s_util.c[1] = 0; - sum += s_util.s; - } - REDUCE; - return (~sum & 0xffff); -} diff --git a/c/src/exec/libnetworking/netinet/in_cksum_powerpc.c b/c/src/exec/libnetworking/netinet/in_cksum_powerpc.c deleted file mode 100644 index fe2f04e246..0000000000 --- a/c/src/exec/libnetworking/netinet/in_cksum_powerpc.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Checksum routine for Internet Protocol family headers. - * - * This routine is very heavily used in the network - * code and should be modified for each CPU to be as fast as possible. - * - * This implementation is the PowerPC version. - * - * $Id$ - */ - -#include <stdio.h> /* for puts */ - -#undef ADDCARRY -#define ADDCARRY(x) if ((x) > 0xffff) (x) -= 0xffff -#define REDUCE {sum = (sum & 0xffff) + (sum >> 16); ADDCARRY(sum);} - -/* - * Thanks to gcc we don't have to guess - * which registers contain sum & w. - */ - -#define LDTMP(n) tmp = *((u_int *)((u_char *)w + n)) - -#define ADD(n) \ - LDTMP(n); \ - __asm__ volatile("addc %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (tmp)) - -#define ADDC(n) \ - LDTMP(n); \ - __asm__ volatile("adde %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (tmp)) - -#define MOP \ - tmp = 0; \ - __asm__ volatile("adde %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (tmp)) - -#define LOAD(n) junk = (u_char) *((volatile u_char *) w + n) - - -int -in_cksum(m, len) - register struct mbuf *m; - register int len; -{ - u_char junk; - register u_short *w; - register unsigned sum = 0; - register unsigned tmp; - register int mlen = 0; - int byte_swapped = 0; - union { char c[2]; u_short s; } su; - - for (;m && len; m = m->m_next) { - if (m->m_len == 0) - continue; - w = mtod(m, u_short *); - if (mlen == -1) { - /* - * The first byte of this mbuf is the continuation - * of a word spanning between this mbuf and the - * last mbuf. - */ - - /* su.c[0] is already saved when scanning previous - * mbuf. sum was REDUCEd when we found mlen == -1 - */ - su.c[1] = *(u_char *)w; - sum += su.s; - w = (u_short *)((char *)w + 1); - mlen = m->m_len - 1; - len--; - } else - mlen = m->m_len; - if (len < mlen) - mlen = len; - len -= mlen; - /* - * Force to long boundary so we do longword aligned - * memory operations - */ - if (3 & (int) w) { - REDUCE; - if ((1 & (int) w) && (mlen > 0)) { - sum <<= 8; - su.c[0] = *(char *)w; - w = (u_short *)((char *)w + 1); - mlen--; - byte_swapped = 1; - } - if ((2 & (int) w) && (mlen >= 2)) { - sum += *w++; - mlen -= 2; - } - } - - /* - * Do as much of the checksum as possible 32 bits at at time. - * In fact, this loop is unrolled to keep overhead from - * branches small. - */ - while (mlen >= 32) { - /* - * Add with carry 16 words and fold in the last - * carry by adding a 0 with carry. - * - * The early ADD(16) and the LOAD(32) are intended - * to help get the data into the cache. - */ - ADD(16); - ADDC(0); - ADDC(4); - ADDC(8); - ADDC(12); - LOAD(32); - ADDC(20); - ADDC(24); - ADDC(28); - MOP; - w += 16; - mlen -= 32; - } - if (mlen >= 16) { - ADD(0); - ADDC(4); - ADDC(8); - ADDC(12); - MOP; - w += 8; - mlen -= 16; - } - if (mlen >= 8) { - ADD(0); - ADDC(4); - MOP; - w += 4; - mlen -= 8; - } - if (mlen == 0 && byte_swapped == 0) - continue; /* worth 1% maybe ?? */ - REDUCE; - while ((mlen -= 2) >= 0) { - sum += *w++; - } - if (byte_swapped) { - sum <<= 8; - byte_swapped = 0; - if (mlen == -1) { - su.c[1] = *(char *)w; - sum += su.s; - mlen = 0; - } else - mlen = -1; - } else if (mlen == -1) - /* - * This mbuf has odd number of bytes. - * There could be a word split betwen - * this mbuf and the next mbuf. - * Save the last byte (to prepend to next mbuf). - */ - su.c[0] = *(char *)w; - } - - if (len) - puts("cksum: out of data"); - if (mlen == -1) { - /* The last mbuf has odd # of bytes. Follow the - standard (the odd byte is shifted left by 8 bits) */ - su.c[1] = 0; - sum += su.s; - } - REDUCE; - return (~sum & 0xffff); -} diff --git a/c/src/exec/libnetworking/netinet/in_pcb.c b/c/src/exec/libnetworking/netinet/in_pcb.c deleted file mode 100644 index 116f70eebf..0000000000 --- a/c/src/exec/libnetworking/netinet/in_pcb.c +++ /dev/null @@ -1,757 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1991, 1993, 1995 - * The Regents of the University of California. 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. 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. - * - * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/time.h> -#include <sys/proc.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/ip_var.h> - -struct in_addr zeroin_addr; - -static void in_pcbinshash __P((struct inpcb *)); -static void in_rtchange __P((struct inpcb *, int)); - -/* - * These configure the range of local port addresses assigned to - * "unspecified" outgoing connections/packets/whatever. - */ -static int ipport_lowfirstauto = IPPORT_RESERVED - 1; /* 1023 */ -static int ipport_lowlastauto = IPPORT_RESERVEDSTART; /* 600 */ -static int ipport_firstauto = IPPORT_RESERVED; /* 1024 */ -static int ipport_lastauto = IPPORT_USERRESERVED; /* 5000 */ -static int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* 40000 */ -static int ipport_hilastauto = IPPORT_HILASTAUTO; /* 44999 */ - -#define RANGECHK(var, min, max) \ - if ((var) < (min)) { (var) = (min); } \ - else if ((var) > (max)) { (var) = (max); } - -#if 0 -static int -sysctl_net_ipport_check SYSCTL_HANDLER_ARGS -{ - int error = sysctl_handle_int(oidp, - oidp->oid_arg1, oidp->oid_arg2, req); - if (!error) { - RANGECHK(ipport_lowfirstauto, 1, IPPORT_RESERVED - 1); - RANGECHK(ipport_lowlastauto, 1, IPPORT_RESERVED - 1); - RANGECHK(ipport_firstauto, IPPORT_RESERVED, USHRT_MAX); - RANGECHK(ipport_lastauto, IPPORT_RESERVED, USHRT_MAX); - RANGECHK(ipport_hifirstauto, IPPORT_RESERVED, USHRT_MAX); - RANGECHK(ipport_hilastauto, IPPORT_RESERVED, USHRT_MAX); - } - return error; -} -#endif - -#undef RANGECHK - -SYSCTL_NODE(_net_inet_ip, IPPROTO_IP, portrange, CTLFLAG_RW, 0, "IP Ports"); - -SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowfirst, CTLTYPE_INT|CTLFLAG_RW, - &ipport_lowfirstauto, 0, &sysctl_net_ipport_check, "I", ""); -SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowlast, CTLTYPE_INT|CTLFLAG_RW, - &ipport_lowlastauto, 0, &sysctl_net_ipport_check, "I", ""); -SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, first, CTLTYPE_INT|CTLFLAG_RW, - &ipport_firstauto, 0, &sysctl_net_ipport_check, "I", ""); -SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, last, CTLTYPE_INT|CTLFLAG_RW, - &ipport_lastauto, 0, &sysctl_net_ipport_check, "I", ""); -SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hifirst, CTLTYPE_INT|CTLFLAG_RW, - &ipport_hifirstauto, 0, &sysctl_net_ipport_check, "I", ""); -SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hilast, CTLTYPE_INT|CTLFLAG_RW, - &ipport_hilastauto, 0, &sysctl_net_ipport_check, "I", ""); - -int -in_pcballoc(so, pcbinfo) - struct socket *so; - struct inpcbinfo *pcbinfo; -{ - register struct inpcb *inp; - int s; - - MALLOC(inp, struct inpcb *, sizeof(*inp), M_PCB, M_NOWAIT); - if (inp == NULL) - return (ENOBUFS); - bzero((caddr_t)inp, sizeof(*inp)); - inp->inp_pcbinfo = pcbinfo; - inp->inp_socket = so; - s = splnet(); - LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list); - in_pcbinshash(inp); - splx(s); - so->so_pcb = (caddr_t)inp; - return (0); -} - -int -in_pcbbind(inp, nam) - register struct inpcb *inp; - struct mbuf *nam; -{ - register struct socket *so = inp->inp_socket; - unsigned short *lastport; - struct sockaddr_in *sin; - u_short lport = 0; - int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); - int error; - - if (in_ifaddr == 0) - return (EADDRNOTAVAIL); - if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY) - return (EINVAL); - if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && - ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || - (so->so_options & SO_ACCEPTCONN) == 0)) - wild = 1; - if (nam) { - sin = mtod(nam, struct sockaddr_in *); - if (nam->m_len != sizeof (*sin)) - return (EINVAL); -#ifdef notdef - /* - * We should check the family, but old programs - * incorrectly fail to initialize it. - */ - if (sin->sin_family != AF_INET) - return (EAFNOSUPPORT); -#endif - lport = sin->sin_port; - if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { - /* - * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; - * allow complete duplication of binding if - * SO_REUSEPORT is set, or if SO_REUSEADDR is set - * and a multicast address is bound on both - * new and duplicated sockets. - */ - if (so->so_options & SO_REUSEADDR) - reuseport = SO_REUSEADDR|SO_REUSEPORT; - } else if (sin->sin_addr.s_addr != INADDR_ANY) { - sin->sin_port = 0; /* yech... */ - if (ifa_ifwithaddr((struct sockaddr *)sin) == 0) - return (EADDRNOTAVAIL); - } - if (lport) { - struct inpcb *t; - - /* GROSS */ - if (ntohs(lport) < IPPORT_RESERVED && - (error = suser(p->p_ucred, &p->p_acflag))) - return (EACCES); - if (so->so_uid) { - t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr, - 0, sin->sin_addr, lport, - INPLOOKUP_WILDCARD); - if (t && (so->so_uid != t->inp_socket->so_uid)) - return (EADDRINUSE); - } - t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0, - sin->sin_addr, lport, wild); - if (t && (reuseport & t->inp_socket->so_options) == 0) - return (EADDRINUSE); - } - inp->inp_laddr = sin->sin_addr; - } - if (lport == 0) { - ushort first, last; - int count; - - inp->inp_flags |= INP_ANONPORT; - - if (inp->inp_flags & INP_HIGHPORT) { - first = ipport_hifirstauto; /* sysctl */ - last = ipport_hilastauto; - lastport = &inp->inp_pcbinfo->lasthi; - } else if (inp->inp_flags & INP_LOWPORT) { - if ((error = suser(p->p_ucred, &p->p_acflag))) - return (EACCES); - first = ipport_lowfirstauto; /* 1023 */ - last = ipport_lowlastauto; /* 600 */ - lastport = &inp->inp_pcbinfo->lastlow; - } else { - first = ipport_firstauto; /* sysctl */ - last = ipport_lastauto; - lastport = &inp->inp_pcbinfo->lastport; - } - /* - * Simple check to ensure all ports are not used up causing - * a deadlock here. - * - * We split the two cases (up and down) so that the direction - * is not being tested on each round of the loop. - */ - if (first > last) { - /* - * counting down - */ - count = first - last; - - do { - if (count-- <= 0) /* completely used? */ - return (EADDRNOTAVAIL); - --*lastport; - if (*lastport > first || *lastport < last) - *lastport = first; - lport = htons(*lastport); - } while (in_pcblookup(inp->inp_pcbinfo, - zeroin_addr, 0, inp->inp_laddr, lport, wild)); - } else { - /* - * counting up - */ - count = last - first; - - do { - if (count-- <= 0) /* completely used? */ - return (EADDRNOTAVAIL); - ++*lastport; - if (*lastport < first || *lastport > last) - *lastport = first; - lport = htons(*lastport); - } while (in_pcblookup(inp->inp_pcbinfo, - zeroin_addr, 0, inp->inp_laddr, lport, wild)); - } - } - inp->inp_lport = lport; - in_pcbrehash(inp); - return (0); -} - -/* - * Transform old in_pcbconnect() into an inner subroutine for new - * in_pcbconnect(): Do some validity-checking on the remote - * address (in mbuf 'nam') and then determine local host address - * (i.e., which interface) to use to access that remote host. - * - * This preserves definition of in_pcbconnect(), while supporting a - * slightly different version for T/TCP. (This is more than - * a bit of a kludge, but cleaning up the internal interfaces would - * have forced minor changes in every protocol). - */ - -int -in_pcbladdr(inp, nam, plocal_sin) - register struct inpcb *inp; - struct mbuf *nam; - struct sockaddr_in **plocal_sin; -{ - struct in_ifaddr *ia; - register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); - - if (nam->m_len != sizeof (*sin)) - return (EINVAL); - if (sin->sin_family != AF_INET) - return (EAFNOSUPPORT); - if (sin->sin_port == 0) - return (EADDRNOTAVAIL); - if (in_ifaddr) { - /* - * If the destination address is INADDR_ANY, - * use the primary local address. - * If the supplied address is INADDR_BROADCAST, - * and the primary interface supports broadcast, - * choose the broadcast address for that interface. - */ -#define satosin(sa) ((struct sockaddr_in *)(sa)) -#define sintosa(sin) ((struct sockaddr *)(sin)) -#define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) - if (sin->sin_addr.s_addr == INADDR_ANY) - sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr; - else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST && - (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST)) - sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr; - } - if (inp->inp_laddr.s_addr == INADDR_ANY) { - register struct route *ro; - - ia = (struct in_ifaddr *)0; - /* - * If route is known or can be allocated now, - * our src addr is taken from the i/f, else punt. - */ - ro = &inp->inp_route; - if (ro->ro_rt && - (satosin(&ro->ro_dst)->sin_addr.s_addr != - sin->sin_addr.s_addr || - inp->inp_socket->so_options & SO_DONTROUTE)) { - RTFREE(ro->ro_rt); - ro->ro_rt = (struct rtentry *)0; - } - if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ - (ro->ro_rt == (struct rtentry *)0 || - ro->ro_rt->rt_ifp == (struct ifnet *)0)) { - /* No route yet, so try to acquire one */ - ro->ro_dst.sa_family = AF_INET; - ro->ro_dst.sa_len = sizeof(struct sockaddr_in); - ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = - sin->sin_addr; - rtalloc(ro); - } - /* - * If we found a route, use the address - * corresponding to the outgoing interface - * unless it is the loopback (in case a route - * to our address on another net goes to loopback). - */ - if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) - ia = ifatoia(ro->ro_rt->rt_ifa); - if (ia == 0) { - u_short fport = sin->sin_port; - - sin->sin_port = 0; - ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin))); - if (ia == 0) - ia = ifatoia(ifa_ifwithnet(sintosa(sin))); - sin->sin_port = fport; - if (ia == 0) - ia = in_ifaddr; - if (ia == 0) - return (EADDRNOTAVAIL); - } - /* - * If the destination address is multicast and an outgoing - * interface has been set as a multicast option, use the - * address of that interface as our source address. - */ - if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) && - inp->inp_moptions != NULL) { - struct ip_moptions *imo; - struct ifnet *ifp; - - imo = inp->inp_moptions; - if (imo->imo_multicast_ifp != NULL) { - ifp = imo->imo_multicast_ifp; - for (ia = in_ifaddr; ia; ia = ia->ia_next) - if (ia->ia_ifp == ifp) - break; - if (ia == 0) - return (EADDRNOTAVAIL); - } - } - /* - * Don't do pcblookup call here; return interface in plocal_sin - * and exit to caller, that will do the lookup. - */ - *plocal_sin = &ia->ia_addr; - - } - return(0); -} - -/* - * Outer subroutine: - * Connect from a socket to a specified address. - * Both address and port must be specified in argument sin. - * If don't have a local address for this socket yet, - * then pick one. - */ -int -in_pcbconnect(inp, nam) - register struct inpcb *inp; - struct mbuf *nam; -{ - struct sockaddr_in *ifaddr; - register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); - int error; - - /* - * Call inner routine, to assign local interface address. - */ - if ((error = in_pcbladdr(inp, nam, &ifaddr))) - return(error); - - if (in_pcblookuphash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port, - inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr, - inp->inp_lport, 0) != NULL) - return (EADDRINUSE); - if (inp->inp_laddr.s_addr == INADDR_ANY) { - if (inp->inp_lport == 0) - (void)in_pcbbind(inp, (struct mbuf *)0); - inp->inp_laddr = ifaddr->sin_addr; - } - inp->inp_faddr = sin->sin_addr; - inp->inp_fport = sin->sin_port; - in_pcbrehash(inp); - return (0); -} - -void -in_pcbdisconnect(inp) - struct inpcb *inp; -{ - - inp->inp_faddr.s_addr = INADDR_ANY; - inp->inp_fport = 0; - in_pcbrehash(inp); - if (inp->inp_socket->so_state & SS_NOFDREF) - in_pcbdetach(inp); -} - -void -in_pcbdetach(inp) - struct inpcb *inp; -{ - struct socket *so = inp->inp_socket; - int s; - - so->so_pcb = 0; - sofree(so); - if (inp->inp_options) - (void)m_free(inp->inp_options); - if (inp->inp_route.ro_rt) - rtfree(inp->inp_route.ro_rt); - ip_freemoptions(inp->inp_moptions); - s = splnet(); - LIST_REMOVE(inp, inp_hash); - LIST_REMOVE(inp, inp_list); - splx(s); - FREE(inp, M_PCB); -} - -void -in_setsockaddr(inp, nam) - register struct inpcb *inp; - struct mbuf *nam; -{ - register struct sockaddr_in *sin; - - nam->m_len = sizeof (*sin); - sin = mtod(nam, struct sockaddr_in *); - bzero((caddr_t)sin, sizeof (*sin)); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(*sin); - sin->sin_port = inp->inp_lport; - sin->sin_addr = inp->inp_laddr; -} - -void -in_setpeeraddr(inp, nam) - struct inpcb *inp; - struct mbuf *nam; -{ - register struct sockaddr_in *sin; - - nam->m_len = sizeof (*sin); - sin = mtod(nam, struct sockaddr_in *); - bzero((caddr_t)sin, sizeof (*sin)); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(*sin); - sin->sin_port = inp->inp_fport; - sin->sin_addr = inp->inp_faddr; -} - -/* - * Pass some notification to all connections of a protocol - * associated with address dst. The local address and/or port numbers - * may be specified to limit the search. The "usual action" will be - * taken, depending on the ctlinput cmd. The caller must filter any - * cmds that are uninteresting (e.g., no error in the map). - * Call the protocol specific routine (if any) to report - * any errors for each matching socket. - * - * Must be called at splnet. - */ -void -in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify) - struct inpcbhead *head; - struct sockaddr *dst; - u_int fport_arg, lport_arg; - struct in_addr laddr; - int cmd; - void (*notify) __P((struct inpcb *, int)); -{ - register struct inpcb *inp, *oinp; - struct in_addr faddr; - u_short fport = fport_arg, lport = lport_arg; - int errnum, s; - - if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET) - return; - faddr = ((struct sockaddr_in *)dst)->sin_addr; - if (faddr.s_addr == INADDR_ANY) - return; - - /* - * Redirects go to all references to the destination, - * and use in_rtchange to invalidate the route cache. - * Dead host indications: notify all references to the destination. - * Otherwise, if we have knowledge of the local port and address, - * deliver only to that socket. - */ - if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { - fport = 0; - lport = 0; - laddr.s_addr = 0; - if (cmd != PRC_HOSTDEAD) - notify = in_rtchange; - } - errnum = inetctlerrmap[cmd]; - s = splnet(); - for (inp = head->lh_first; inp != NULL;) { - if (inp->inp_faddr.s_addr != faddr.s_addr || - inp->inp_socket == 0 || - (lport && inp->inp_lport != lport) || - (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) || - (fport && inp->inp_fport != fport)) { - inp = inp->inp_list.le_next; - continue; - } - oinp = inp; - inp = inp->inp_list.le_next; - if (notify) - (*notify)(oinp, errnum); - } - splx(s); -} - -/* - * Check for alternatives when higher level complains - * about service problems. For now, invalidate cached - * routing information. If the route was created dynamically - * (by a redirect), time to try a default gateway again. - */ -void -in_losing(inp) - struct inpcb *inp; -{ - register struct rtentry *rt; - struct rt_addrinfo info; - - if ((rt = inp->inp_route.ro_rt)) { - inp->inp_route.ro_rt = 0; - bzero((caddr_t)&info, sizeof(info)); - info.rti_info[RTAX_DST] = - (struct sockaddr *)&inp->inp_route.ro_dst; - info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; - info.rti_info[RTAX_NETMASK] = rt_mask(rt); - rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); - if (rt->rt_flags & RTF_DYNAMIC) - (void) rtrequest(RTM_DELETE, rt_key(rt), - rt->rt_gateway, rt_mask(rt), rt->rt_flags, - (struct rtentry **)0); - else - /* - * A new route can be allocated - * the next time output is attempted. - */ - rtfree(rt); - } -} - -/* - * After a routing change, flush old routing - * and allocate a (hopefully) better one. - */ -static void -in_rtchange(inp, errnum) - register struct inpcb *inp; - int errnum; -{ - if (inp->inp_route.ro_rt) { - rtfree(inp->inp_route.ro_rt); - inp->inp_route.ro_rt = 0; - /* - * A new route can be allocated the next time - * output is attempted. - */ - } -} - -struct inpcb * -in_pcblookup(pcbinfo, faddr, fport_arg, laddr, lport_arg, wild_okay) - struct inpcbinfo *pcbinfo; - struct in_addr faddr, laddr; - u_int fport_arg, lport_arg; - int wild_okay; -{ - register struct inpcb *inp, *match = NULL; - int matchwild = 3, wildcard; - u_short fport = fport_arg, lport = lport_arg; - int s; - - s = splnet(); - - for (inp = pcbinfo->listhead->lh_first; inp != NULL; inp = inp->inp_list.le_next) { - if (inp->inp_lport != lport) - continue; - wildcard = 0; - if (inp->inp_faddr.s_addr != INADDR_ANY) { - if (faddr.s_addr == INADDR_ANY) - wildcard++; - else if (inp->inp_faddr.s_addr != faddr.s_addr || - inp->inp_fport != fport) - continue; - } else { - if (faddr.s_addr != INADDR_ANY) - wildcard++; - } - if (inp->inp_laddr.s_addr != INADDR_ANY) { - if (laddr.s_addr == INADDR_ANY) - wildcard++; - else if (inp->inp_laddr.s_addr != laddr.s_addr) - continue; - } else { - if (laddr.s_addr != INADDR_ANY) - wildcard++; - } - if (wildcard && wild_okay == 0) - continue; - if (wildcard < matchwild) { - match = inp; - matchwild = wildcard; - if (matchwild == 0) { - break; - } - } - } - splx(s); - return (match); -} - -/* - * Lookup PCB in hash list. - */ -struct inpcb * -in_pcblookuphash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard) - struct inpcbinfo *pcbinfo; - struct in_addr faddr, laddr; - u_int fport_arg, lport_arg; - int wildcard; -{ - struct inpcbhead *head; - register struct inpcb *inp; - u_short fport = fport_arg, lport = lport_arg; - int s; - - s = splnet(); - /* - * First look for an exact match. - */ - head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)]; - for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { - if (inp->inp_faddr.s_addr == faddr.s_addr && - inp->inp_laddr.s_addr == laddr.s_addr && - inp->inp_fport == fport && - inp->inp_lport == lport) - goto found; - } - if (wildcard) { - struct inpcb *local_wild = NULL; - - head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)]; - for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { - if (inp->inp_faddr.s_addr == INADDR_ANY && - inp->inp_fport == 0 && inp->inp_lport == lport) { - if (inp->inp_laddr.s_addr == laddr.s_addr) - goto found; - else if (inp->inp_laddr.s_addr == INADDR_ANY) - local_wild = inp; - } - } - if (local_wild != NULL) { - inp = local_wild; - goto found; - } - } - splx(s); - return (NULL); - -found: - /* - * Move PCB to head of this hash chain so that it can be - * found more quickly in the future. - * XXX - this is a pessimization on machines with few - * concurrent connections. - */ - if (inp != head->lh_first) { - LIST_REMOVE(inp, inp_hash); - LIST_INSERT_HEAD(head, inp, inp_hash); - } - splx(s); - return (inp); -} - -/* - * Insert PCB into hash chain. Must be called at splnet. - */ -static void -in_pcbinshash(inp) - struct inpcb *inp; -{ - struct inpcbhead *head; - - head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr, - inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)]; - - LIST_INSERT_HEAD(head, inp, inp_hash); -} - -void -in_pcbrehash(inp) - struct inpcb *inp; -{ - struct inpcbhead *head; - int s; - - s = splnet(); - LIST_REMOVE(inp, inp_hash); - - head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr, - inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)]; - - LIST_INSERT_HEAD(head, inp, inp_hash); - splx(s); -} diff --git a/c/src/exec/libnetworking/netinet/in_pcb.h b/c/src/exec/libnetworking/netinet/in_pcb.h deleted file mode 100644 index 9390cfda6c..0000000000 --- a/c/src/exec/libnetworking/netinet/in_pcb.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1990, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)in_pcb.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_IN_PCB_H_ -#define _NETINET_IN_PCB_H_ - -#include <sys/queue.h> - -/* - * Common structure pcb for internet protocol implementation. - * Here are stored pointers to local and foreign host table - * entries, local and foreign socket numbers, and pointers - * up (to a socket structure) and down (to a protocol-specific) - * control block. - */ -LIST_HEAD(inpcbhead, inpcb); - -struct inpcb { - LIST_ENTRY(inpcb) inp_list; /* list for all PCBs of this proto */ - LIST_ENTRY(inpcb) inp_hash; /* hash list */ - struct inpcbinfo *inp_pcbinfo; /* PCB list info */ - struct in_addr inp_faddr; /* foreign host table entry */ - struct in_addr inp_laddr; /* local host table entry */ - u_short inp_fport; /* foreign port */ - u_short inp_lport; /* local port */ - caddr_t inp_ppcb; /* pointer to per-protocol pcb */ - struct socket *inp_socket; /* back pointer to socket */ - struct mbuf *inp_options; /* IP options */ - struct route inp_route; /* placeholder for routing entry */ - int inp_flags; /* generic IP/datagram flags */ - u_char inp_ip_tos; /* type of service proto */ - u_char inp_ip_ttl; /* time to live proto */ - u_char inp_ip_p; /* protocol proto */ - u_char pad[1]; /* alignment */ - struct ip_moptions *inp_moptions; /* IP multicast options */ -#if 0 /* Someday, perhaps... */ - struct ip inp_ip; /* header prototype; should have more */ -#endif -}; - -struct inpcbinfo { - struct inpcbhead *listhead; - struct inpcbhead *hashbase; - unsigned long hashmask; - unsigned short lastport; - unsigned short lastlow; - unsigned short lasthi; -}; - -#define INP_PCBHASH(faddr, lport, fport, mask) \ - (((faddr) ^ ((faddr) >> 16) ^ (lport) ^ (fport)) & (mask)) - -/* flags in inp_flags: */ -#define INP_RECVOPTS 0x01 /* receive incoming IP options */ -#define INP_RECVRETOPTS 0x02 /* receive IP options for reply */ -#define INP_RECVDSTADDR 0x04 /* receive IP dst address */ -#define INP_HDRINCL 0x08 /* user supplies entire IP header */ -#define INP_HIGHPORT 0x10 /* user wants "high" port binding */ -#define INP_LOWPORT 0x20 /* user wants "low" port binding */ -#define INP_ANONPORT 0x40 /* port chosen for user */ -#define INP_RECVIF 0x80 /* receive incoming interface */ -#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR|\ - INP_RECVIF) - -#define INPLOOKUP_WILDCARD 1 - -#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb) - -#ifdef KERNEL -void in_losing __P((struct inpcb *)); -int in_pcballoc __P((struct socket *, struct inpcbinfo *)); -int in_pcbbind __P((struct inpcb *, struct mbuf *)); -int in_pcbconnect __P((struct inpcb *, struct mbuf *)); -void in_pcbdetach __P((struct inpcb *)); -void in_pcbdisconnect __P((struct inpcb *)); -int in_pcbladdr __P((struct inpcb *, struct mbuf *, - struct sockaddr_in **)); -struct inpcb * - in_pcblookup __P((struct inpcbinfo *, - struct in_addr, u_int, struct in_addr, u_int, int)); -struct inpcb * - in_pcblookuphash __P((struct inpcbinfo *, - struct in_addr, u_int, struct in_addr, u_int, int)); -void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *, - u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int))); -void in_pcbrehash __P((struct inpcb *)); -void in_setpeeraddr __P((struct inpcb *, struct mbuf *)); -void in_setsockaddr __P((struct inpcb *, struct mbuf *)); -#endif - -#endif diff --git a/c/src/exec/libnetworking/netinet/in_proto.c b/c/src/exec/libnetworking/netinet/in_proto.c deleted file mode 100644 index 3fa845955e..0000000000 --- a/c/src/exec/libnetworking/netinet/in_proto.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)in_proto.c 8.2 (Berkeley) 2/9/95 - * $Id$ - */ - -#include "opt_tcpdebug.h" - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/domain.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/radix.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/ip_icmp.h> -#include <netinet/in_pcb.h> -#include <netinet/igmp_var.h> -#include <netinet/tcp.h> -#include <netinet/tcp_fsm.h> -#include <netinet/tcp_seq.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> -#include <netinet/tcpip.h> -#ifdef TCPDEBUG -#include <netinet/tcp_debug.h> -#endif -#include <netinet/udp.h> -#include <netinet/udp_var.h> -/* - * TCP/IP protocol family: IP, ICMP, UDP, TCP. - */ - -#ifdef IPXIP -#include <netipx/ipx.h> -#include <netipx/ipx_ip.h> -#endif - -#ifdef NSIP -#include <netns/ns.h> -#include <netns/ns_if.h> -#endif - -#ifdef TPIP -void tpip_input(), tpip_ctlinput(), tp_init(), tp_slowtimo(), tp_drain(); -int tp_ctloutput(), tp_usrreq(); -#endif - -#ifdef EON -void eoninput(), eonctlinput(), eonprotoinit(); -#endif /* EON */ - -extern struct domain inetdomain; - -struct protosw inetsw[] = { -{ 0, &inetdomain, 0, 0, - 0, 0, 0, 0, - 0, - ip_init, 0, ip_slowtimo, ip_drain -}, -{ SOCK_DGRAM, &inetdomain, IPPROTO_UDP, PR_ATOMIC|PR_ADDR, - udp_input, 0, udp_ctlinput, ip_ctloutput, - udp_usrreq, - udp_init -}, -{ SOCK_STREAM, &inetdomain, IPPROTO_TCP, - PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD, - tcp_input, 0, tcp_ctlinput, tcp_ctloutput, - 0, - tcp_init, tcp_fasttimo, tcp_slowtimo, tcp_drain, - &tcp_usrreqs -}, -{ SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR, - rip_input, 0, 0, rip_ctloutput, - rip_usrreq, - 0, 0, 0, 0, -}, -{ SOCK_RAW, &inetdomain, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR, - icmp_input, 0, 0, rip_ctloutput, - rip_usrreq -}, -{ SOCK_RAW, &inetdomain, IPPROTO_IGMP, PR_ATOMIC|PR_ADDR, - igmp_input, 0, 0, rip_ctloutput, - rip_usrreq, - igmp_init, igmp_fasttimo, igmp_slowtimo -}, -{ SOCK_RAW, &inetdomain, IPPROTO_RSVP, PR_ATOMIC|PR_ADDR, - rsvp_input, 0, 0, rip_ctloutput, - rip_usrreq, - 0, 0, 0, 0, -}, -{ SOCK_RAW, &inetdomain, IPPROTO_IPIP, PR_ATOMIC|PR_ADDR, - ipip_input, 0, 0, rip_ctloutput, - rip_usrreq, - 0, 0, 0, 0, -}, -#ifdef IPDIVERT -{ SOCK_RAW, &inetdomain, IPPROTO_DIVERT, PR_ATOMIC|PR_ADDR, - div_input, 0, 0, ip_ctloutput, - div_usrreq, - div_init, 0, 0, 0, -}, -#endif -#ifdef TPIP -{ SOCK_SEQPACKET,&inetdomain, IPPROTO_TP, PR_CONNREQUIRED|PR_WANTRCVD, - tpip_input, 0, tpip_ctlinput, tp_ctloutput, - tp_usrreq, - tp_init, 0, tp_slowtimo, tp_drain, -}, -#endif -/* EON (ISO CLNL over IP) */ -#ifdef EON -{ SOCK_RAW, &inetdomain, IPPROTO_EON, 0, - eoninput, 0, eonctlinput, 0, - 0, - eonprotoinit, 0, 0, 0, -}, -#endif -#ifdef IPXIP -{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR, - ipxip_input, 0, ipxip_ctlinput, 0, - rip_usrreq, - 0, 0, 0, 0, -}, -#endif -#ifdef NSIP -{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR, - idpip_input, 0, nsip_ctlinput, 0, - rip_usrreq, - 0, 0, 0, 0, -}, -#endif - /* raw wildcard */ -{ SOCK_RAW, &inetdomain, 0, PR_ATOMIC|PR_ADDR, - rip_input, 0, 0, rip_ctloutput, - rip_usrreq, - rip_init, 0, 0, 0, -}, -}; - -extern int in_inithead(void **, int); - -struct domain inetdomain = - { AF_INET, "internet", 0, 0, 0, - inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])], 0, - in_inithead, 32, sizeof(struct sockaddr_in) - }; - -DOMAIN_SET(inet); - -SYSCTL_NODE(_net, PF_INET, inet, CTLFLAG_RW, 0, - "Internet Family"); - -SYSCTL_NODE(_net_inet, IPPROTO_IP, ip, CTLFLAG_RW, 0, "IP"); -SYSCTL_NODE(_net_inet, IPPROTO_ICMP, icmp, CTLFLAG_RW, 0, "ICMP"); -SYSCTL_NODE(_net_inet, IPPROTO_UDP, udp, CTLFLAG_RW, 0, "UDP"); -SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp, CTLFLAG_RW, 0, "TCP"); -SYSCTL_NODE(_net_inet, IPPROTO_IGMP, igmp, CTLFLAG_RW, 0, "IGMP"); -#ifdef IPDIVERT -SYSCTL_NODE(_net_inet, IPPROTO_DIVERT, div, CTLFLAG_RW, 0, "DIVERT"); -#endif - diff --git a/c/src/exec/libnetworking/netinet/in_rmx.c b/c/src/exec/libnetworking/netinet/in_rmx.c deleted file mode 100644 index ba1793b3b4..0000000000 --- a/c/src/exec/libnetworking/netinet/in_rmx.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright 1994, 1995 Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that both the above copyright notice and this - * permission notice appear in all copies, that both the above - * copyright notice and this permission notice appear in all - * supporting documentation, and that the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. M.I.T. makes - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS - * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT - * SHALL M.I.T. 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. - * - * $Id$ - */ - -/* - * This code does two things necessary for the enhanced TCP metrics to - * function in a useful manner: - * 1) It marks all non-host routes as `cloning', thus ensuring that - * every actual reference to such a route actually gets turned - * into a reference to a host route to the specific destination - * requested. - * 2) When such routes lose all their references, it arranges for them - * to be deleted in some random collection of circumstances, so that - * a large quantity of stale routing data is not kept in kernel memory - * indefinitely. See in_rtqtimo() below for the exact mechanism. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/queue.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/mbuf.h> -#include <sys/syslog.h> - -#include <net/if.h> -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> - -#include <netinet/ip.h> -#include <netinet/ip_var.h> - -#include <netinet/tcp.h> -#include <netinet/tcp_seq.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> - -extern int in_inithead __P((void **head, int off)); - -#define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */ - -/* - * Do what we need to do when inserting a route. - */ -static struct radix_node * -in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, - struct radix_node *treenodes) -{ - struct rtentry *rt = (struct rtentry *)treenodes; - struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt); - struct radix_node *ret; - - /* - * For IP, all unicast non-host routes are automatically cloning. - */ - if(IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) - rt->rt_flags |= RTF_MULTICAST; - - if(!(rt->rt_flags & (RTF_HOST | RTF_CLONING | RTF_MULTICAST))) { - rt->rt_flags |= RTF_PRCLONING; - } - - /* - * A little bit of help for both IP output and input: - * For host routes, we make sure that RTF_BROADCAST - * is set for anything that looks like a broadcast address. - * This way, we can avoid an expensive call to in_broadcast() - * in ip_output() most of the time (because the route passed - * to ip_output() is almost always a host route). - * - * We also do the same for local addresses, with the thought - * that this might one day be used to speed up ip_input(). - * - * We also mark routes to multicast addresses as such, because - * it's easy to do and might be useful (but this is much more - * dubious since it's so easy to inspect the address). (This - * is done above.) - */ - if (rt->rt_flags & RTF_HOST) { - if (in_broadcast(sin->sin_addr, rt->rt_ifp)) { - rt->rt_flags |= RTF_BROADCAST; - } else { -#define satosin(sa) ((struct sockaddr_in *)sa) - if (satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr - == sin->sin_addr.s_addr) - rt->rt_flags |= RTF_LOCAL; -#undef satosin - } - } - - /* - * We also specify a send and receive pipe size for every - * route added, to help TCP a bit. TCP doesn't actually - * want a true pipe size, which would be prohibitive in memory - * costs and is hard to compute anyway; it simply uses these - * values to size its buffers. So, we fill them in with the - * same values that TCP would have used anyway, and allow the - * installing program or the link layer to override these values - * as it sees fit. This will hopefully allow TCP more - * opportunities to save its ssthresh value. - */ - if (!rt->rt_rmx.rmx_sendpipe && !(rt->rt_rmx.rmx_locks & RTV_SPIPE)) - rt->rt_rmx.rmx_sendpipe = tcp_sendspace; - - if (!rt->rt_rmx.rmx_recvpipe && !(rt->rt_rmx.rmx_locks & RTV_RPIPE)) - rt->rt_rmx.rmx_recvpipe = tcp_recvspace; - - if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU) - && rt->rt_ifp) - rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; - - ret = rn_addroute(v_arg, n_arg, head, treenodes); - if (ret == NULL && rt->rt_flags & RTF_HOST) { - struct rtentry *rt2; - /* - * We are trying to add a host route, but can't. - * Find out if it is because of an - * ARP entry and delete it if so. - */ - rt2 = rtalloc1((struct sockaddr *)sin, 0, - RTF_CLONING | RTF_PRCLONING); - if (rt2) { - if (rt2->rt_flags & RTF_LLINFO && - rt2->rt_flags & RTF_HOST && - rt2->rt_gateway && - rt2->rt_gateway->sa_family == AF_LINK) { - rtrequest(RTM_DELETE, - (struct sockaddr *)rt_key(rt2), - rt2->rt_gateway, - rt_mask(rt2), rt2->rt_flags, 0); - ret = rn_addroute(v_arg, n_arg, head, - treenodes); - } - RTFREE(rt2); - } - } - return ret; -} - -/* - * This code is the inverse of in_clsroute: on first reference, if we - * were managing the route, stop doing so and set the expiration timer - * back off again. - */ -static struct radix_node * -in_matroute(void *v_arg, struct radix_node_head *head) -{ - struct radix_node *rn = rn_match(v_arg, head); - struct rtentry *rt = (struct rtentry *)rn; - - if(rt && rt->rt_refcnt == 0) { /* this is first reference */ - if(rt->rt_flags & RTPRF_OURS) { - rt->rt_flags &= ~RTPRF_OURS; - rt->rt_rmx.rmx_expire = 0; - } - } - return rn; -} - -static int rtq_reallyold = 60*60; - /* one hour is ``really old'' */ -SYSCTL_INT(_net_inet_ip, IPCTL_RTEXPIRE, rtexpire, - CTLFLAG_RW, &rtq_reallyold , 0, ""); - -static int rtq_minreallyold = 10; - /* never automatically crank down to less */ -SYSCTL_INT(_net_inet_ip, IPCTL_RTMINEXPIRE, rtminexpire, - CTLFLAG_RW, &rtq_minreallyold , 0, ""); - -static int rtq_toomany = 128; - /* 128 cached routes is ``too many'' */ -SYSCTL_INT(_net_inet_ip, IPCTL_RTMAXCACHE, rtmaxcache, - CTLFLAG_RW, &rtq_toomany , 0, ""); - - -/* - * On last reference drop, mark the route as belong to us so that it can be - * timed out. - */ -static void -in_clsroute(struct radix_node *rn, struct radix_node_head *head) -{ - struct rtentry *rt = (struct rtentry *)rn; - - if(!(rt->rt_flags & RTF_UP)) - return; /* prophylactic measures */ - - if((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST) - return; - - if((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS)) - != RTF_WASCLONED) - return; - - /* - * As requested by David Greenman: - * If rtq_reallyold is 0, just delete the route without - * waiting for a timeout cycle to kill it. - */ - if(rtq_reallyold != 0) { - rt->rt_flags |= RTPRF_OURS; - rt->rt_rmx.rmx_expire = rtems_bsdnet_seconds_since_boot() + rtq_reallyold; - } else { - rtrequest(RTM_DELETE, - (struct sockaddr *)rt_key(rt), - rt->rt_gateway, rt_mask(rt), - rt->rt_flags, 0); - } -} - -struct rtqk_arg { - struct radix_node_head *rnh; - int draining; - int killed; - int found; - int updating; - time_t nextstop; -}; - -/* - * Get rid of old routes. When draining, this deletes everything, even when - * the timeout is not expired yet. When updating, this makes sure that - * nothing has a timeout longer than the current value of rtq_reallyold. - */ -static int -in_rtqkill(struct radix_node *rn, void *rock) -{ - struct rtqk_arg *ap = rock; - struct rtentry *rt = (struct rtentry *)rn; - int err; - - if(rt->rt_flags & RTPRF_OURS) { - ap->found++; - - if(ap->draining || rt->rt_rmx.rmx_expire <= rtems_bsdnet_seconds_since_boot()) { - if(rt->rt_refcnt > 0) - panic("rtqkill route really not free"); - - err = rtrequest(RTM_DELETE, - (struct sockaddr *)rt_key(rt), - rt->rt_gateway, rt_mask(rt), - rt->rt_flags, 0); - if(err) { - log(LOG_WARNING, "in_rtqkill: error %d\n", err); - } else { - ap->killed++; - } - } else { - if(ap->updating - && (rt->rt_rmx.rmx_expire - rtems_bsdnet_seconds_since_boot() - > rtq_reallyold)) { - rt->rt_rmx.rmx_expire = rtems_bsdnet_seconds_since_boot() - + rtq_reallyold; - } - ap->nextstop = lmin(ap->nextstop, - rt->rt_rmx.rmx_expire); - } - } - - return 0; -} - -#define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */ -static int rtq_timeout = RTQ_TIMEOUT; - -static void -in_rtqtimo(void *rock) -{ - struct radix_node_head *rnh = rock; - struct rtqk_arg arg; - struct timeval atv; - static time_t last_adjusted_timeout = 0; - int s; - - arg.found = arg.killed = 0; - arg.rnh = rnh; - arg.nextstop = rtems_bsdnet_seconds_since_boot() + rtq_timeout; - arg.draining = arg.updating = 0; - s = splnet(); - rnh->rnh_walktree(rnh, in_rtqkill, &arg); - splx(s); - - /* - * Attempt to be somewhat dynamic about this: - * If there are ``too many'' routes sitting around taking up space, - * then crank down the timeout, and see if we can't make some more - * go away. However, we make sure that we will never adjust more - * than once in rtq_timeout seconds, to keep from cranking down too - * hard. - */ - if((arg.found - arg.killed > rtq_toomany) - && (rtems_bsdnet_seconds_since_boot() - last_adjusted_timeout >= rtq_timeout) - && rtq_reallyold > rtq_minreallyold) { - rtq_reallyold = 2*rtq_reallyold / 3; - if(rtq_reallyold < rtq_minreallyold) { - rtq_reallyold = rtq_minreallyold; - } - - last_adjusted_timeout = rtems_bsdnet_seconds_since_boot(); -#ifdef DIAGNOSTIC - log(LOG_DEBUG, "in_rtqtimo: adjusted rtq_reallyold to %d\n", - rtq_reallyold); -#endif - arg.found = arg.killed = 0; - arg.updating = 1; - s = splnet(); - rnh->rnh_walktree(rnh, in_rtqkill, &arg); - splx(s); - } - - atv.tv_usec = 0; - atv.tv_sec = arg.nextstop; - timeout(in_rtqtimo, rock, hzto(&atv)); -} - -void -in_rtqdrain(void) -{ - struct radix_node_head *rnh = rt_tables[AF_INET]; - struct rtqk_arg arg; - int s; - arg.found = arg.killed = 0; - arg.rnh = rnh; - arg.nextstop = 0; - arg.draining = 1; - arg.updating = 0; - s = splnet(); - rnh->rnh_walktree(rnh, in_rtqkill, &arg); - splx(s); -} - -/* - * Initialize our routing tree. - */ -int -in_inithead(void **head, int off) -{ - struct radix_node_head *rnh; - - if(!rn_inithead(head, off)) - return 0; - - if(head != (void **)&rt_tables[AF_INET]) /* BOGUS! */ - return 1; /* only do this for the real routing table */ - - rnh = *head; - rnh->rnh_addaddr = in_addroute; - rnh->rnh_matchaddr = in_matroute; - rnh->rnh_close = in_clsroute; - in_rtqtimo(rnh); /* kick off timeout first time */ - return 1; -} - diff --git a/c/src/exec/libnetworking/netinet/in_systm.h b/c/src/exec/libnetworking/netinet/in_systm.h deleted file mode 100644 index d72e9b4665..0000000000 --- a/c/src/exec/libnetworking/netinet/in_systm.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)in_systm.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_IN_SYSTM_H_ -#define _NETINET_IN_SYSTM_H_ - -/* - * Miscellaneous internetwork - * definitions for kernel. - */ - -/* - * Network types. - * - * Internally the system keeps counters in the headers with the bytes - * swapped so that VAX instructions will work on them. It reverses - * the bytes before transmission at each protocol level. The n_ types - * represent the types with the bytes in ``high-ender'' order. - */ -typedef u_short n_short; /* short as received from the net */ -typedef u_long n_long; /* long as received from the net */ - -typedef u_long n_time; /* ms since 00:00 GMT, byte rev */ - -#ifdef KERNEL -n_time iptime __P((void)); -#endif - -#endif diff --git a/c/src/exec/libnetworking/netinet/in_var.h b/c/src/exec/libnetworking/netinet/in_var.h deleted file mode 100644 index e7a54d5e85..0000000000 --- a/c/src/exec/libnetworking/netinet/in_var.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 1985, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)in_var.h 8.2 (Berkeley) 1/9/95 - * $Id$ - */ - -#ifndef _NETINET_IN_VAR_H_ -#define _NETINET_IN_VAR_H_ - -#include <sys/queue.h> - -/* - * Interface address, Internet version. One of these structures - * is allocated for each interface with an Internet address. - * The ifaddr structure contains the protocol-independent part - * of the structure and is assumed to be first. - */ -struct in_ifaddr { - struct ifaddr ia_ifa; /* protocol-independent info */ -#define ia_ifp ia_ifa.ifa_ifp -#define ia_flags ia_ifa.ifa_flags - /* ia_{,sub}net{,mask} in host order */ - u_long ia_net; /* network number of interface */ - u_long ia_netmask; /* mask of net part */ - u_long ia_subnet; /* subnet number, including net */ - u_long ia_subnetmask; /* mask of subnet part */ - struct in_addr ia_netbroadcast; /* to recognize net broadcasts */ - struct in_ifaddr *ia_next; /* next in list of internet addresses */ - struct sockaddr_in ia_addr; /* reserve space for interface name */ - struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ -#define ia_broadaddr ia_dstaddr - struct sockaddr_in ia_sockmask; /* reserve space for general netmask */ - LIST_HEAD(in_multihead, in_multi) ia_multiaddrs; - /* list of multicast addresses */ -}; - -struct in_aliasreq { - char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - struct sockaddr_in ifra_addr; - struct sockaddr_in ifra_broadaddr; -#define ifra_dstaddr ifra_broadaddr - struct sockaddr_in ifra_mask; -}; -/* - * Given a pointer to an in_ifaddr (ifaddr), - * return a pointer to the addr as a sockaddr_in. - */ -#define IA_SIN(ia) (&(((struct in_ifaddr *)(ia))->ia_addr)) -#define IA_DSTSIN(ia) (&(((struct in_ifaddr *)(ia))->ia_dstaddr)) - -#define IN_LNAOF(in, ifa) \ - ((ntohl((in).s_addr) & ~((struct in_ifaddr *)(ifa)->ia_subnetmask)) - - -#ifdef KERNEL -extern struct in_ifaddr *in_ifaddr; -extern struct ifqueue ipintrq; /* ip packet input queue */ -extern struct in_addr zeroin_addr; -extern u_char inetctlerrmap[]; -extern int rtq_reallyold; /* XXX */ -extern int rtq_minreallyold; /* XXX */ -extern int rtq_toomany; /* XXX */ - -/* - * Macro for finding the interface (ifnet structure) corresponding to one - * of our IP addresses. - */ -#define INADDR_TO_IFP(addr, ifp) \ - /* struct in_addr addr; */ \ - /* struct ifnet *ifp; */ \ -{ \ - register struct in_ifaddr *ia; \ -\ - for (ia = in_ifaddr; \ - ia != NULL && ((ia->ia_ifp->if_flags & IFF_POINTOPOINT)? \ - IA_DSTSIN(ia):IA_SIN(ia))->sin_addr.s_addr != (addr).s_addr; \ - ia = ia->ia_next) \ - continue; \ - if (ia == NULL) \ - for (ia = in_ifaddr; \ - ia != NULL; \ - ia = ia->ia_next) \ - if (ia->ia_ifp->if_flags & IFF_POINTOPOINT && \ - IA_SIN(ia)->sin_addr.s_addr == (addr).s_addr) \ - break; \ - (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \ -} - -/* - * Macro for finding the internet address structure (in_ifaddr) corresponding - * to a given interface (ifnet structure). - */ -#define IFP_TO_IA(ifp, ia) \ - /* struct ifnet *ifp; */ \ - /* struct in_ifaddr *ia; */ \ -{ \ - for ((ia) = in_ifaddr; \ - (ia) != NULL && (ia)->ia_ifp != (ifp); \ - (ia) = (ia)->ia_next) \ - continue; \ -} -#endif - -/* - * This information should be part of the ifnet structure but we don't wish - * to change that - as it might break a number of things - */ - -struct router_info { - struct ifnet *rti_ifp; - int rti_type; /* type of router which is querier on this interface */ - int rti_time; /* # of slow timeouts since last old query */ - struct router_info *rti_next; -}; - -/* - * Internet multicast address structure. There is one of these for each IP - * multicast group to which this host belongs on a given network interface. - * They are kept in a linked list, rooted in the interface's in_ifaddr - * structure. - */ -struct in_multi { - LIST_ENTRY(in_multi) inm_entry; /* list glue */ - struct in_addr inm_addr; /* IP multicast address */ - struct ifnet *inm_ifp; /* back pointer to ifnet */ - struct in_ifaddr *inm_ia; /* back pointer to in_ifaddr */ - u_int inm_refcount; /* no. membership claims by sockets */ - u_int inm_timer; /* IGMP membership report timer */ - u_int inm_state; /* state of the membership */ - struct router_info *inm_rti; /* router info*/ -}; - -#ifdef KERNEL -/* - * Structure used by macros below to remember position when stepping through - * all of the in_multi records. - */ -struct in_multistep { - struct in_ifaddr *i_ia; - struct in_multi *i_inm; -}; - -/* - * Macro for looking up the in_multi record for a given IP multicast address - * on a given interface. If no matching record is found, "inm" returns NULL. - */ -#define IN_LOOKUP_MULTI(addr, ifp, inm) \ - /* struct in_addr addr; */ \ - /* struct ifnet *ifp; */ \ - /* struct in_multi *inm; */ \ -{ \ - register struct in_ifaddr *ia; \ -\ - IFP_TO_IA((ifp), ia); \ - if (ia == NULL) \ - (inm) = NULL; \ - else \ - for ((inm) = ia->ia_multiaddrs.lh_first; \ - (inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \ - (inm) = inm->inm_entry.le_next) \ - continue; \ -} - -/* - * Macro to step through all of the in_multi records, one at a time. - * The current position is remembered in "step", which the caller must - * provide. IN_FIRST_MULTI(), below, must be called to initialize "step" - * and get the first record. Both macros return a NULL "inm" when there - * are no remaining records. - */ -#define IN_NEXT_MULTI(step, inm) \ - /* struct in_multistep step; */ \ - /* struct in_multi *inm; */ \ -{ \ - if (((inm) = (step).i_inm) != NULL) \ - (step).i_inm = (inm)->inm_entry.le_next; \ - else \ - while ((step).i_ia != NULL) { \ - (inm) = (step).i_ia->ia_multiaddrs.lh_first; \ - (step).i_ia = (step).i_ia->ia_next; \ - if ((inm) != NULL) { \ - (step).i_inm = (inm)->inm_entry.le_next; \ - break; \ - } \ - } \ -} - -#define IN_FIRST_MULTI(step, inm) \ - /* struct in_multistep step; */ \ - /* struct in_multi *inm; */ \ -{ \ - (step).i_ia = in_ifaddr; \ - (step).i_inm = NULL; \ - IN_NEXT_MULTI((step), (inm)); \ -} - -struct in_multi *in_addmulti __P((struct in_addr *, struct ifnet *)); -void in_delmulti __P((struct in_multi *)); -int in_control __P((struct socket *, u_long, caddr_t, struct ifnet *)); -void in_rtqdrain __P((void)); -void ip_input __P((struct mbuf *)); - -#endif /* KERNEL */ - -#endif /* _NETINET_IN_VAR_H_ */ diff --git a/c/src/exec/libnetworking/netinet/ip.h b/c/src/exec/libnetworking/netinet/ip.h deleted file mode 100644 index e6be7d305d..0000000000 --- a/c/src/exec/libnetworking/netinet/ip.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)ip.h 8.2 (Berkeley) 6/1/94 - * $Id$ - */ - -#ifndef _NETINET_IP_H_ -#define _NETINET_IP_H_ - -/* - * Definitions for internet protocol version 4. - * Per RFC 791, September 1981. - */ -#define IPVERSION 4 - -/* - * Structure of an internet header, naked of options. - * - * We declare ip_len and ip_off to be short, rather than u_short - * pragmatically since otherwise unsigned comparisons can result - * against negative integers quite easily, and fail in subtle ways. - */ -struct ip { -#ifdef _IP_VHL - u_char ip_vhl; /* version << 4 | header length >> 2 */ -#else -#if BYTE_ORDER == LITTLE_ENDIAN - u_char ip_hl:4, /* header length */ - ip_v:4; /* version */ -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_char ip_v:4, /* version */ - ip_hl:4; /* header length */ -#endif -#endif /* not _IP_VHL */ - u_char ip_tos; /* type of service */ - u_short ip_len BYTE_PACK; /* total length */ - u_short ip_id BYTE_PACK; /* identification */ - u_short ip_off BYTE_PACK; /* fragment offset field */ -#define IP_RF 0x8000 /* reserved fragment flag */ -#define IP_DF 0x4000 /* dont fragment flag */ -#define IP_MF 0x2000 /* more fragments flag */ -#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ - u_char ip_ttl; /* time to live */ - u_char ip_p; /* protocol */ - u_short ip_sum BYTE_PACK; /* checksum */ - struct in_addr ip_src BYTE_PACK; /* source address */ - struct in_addr ip_dst BYTE_PACK; /* dest address */ -}; - -#ifdef _IP_VHL -#define IP_MAKE_VHL(v, hl) ((v) << 4 | (hl)) -#define IP_VHL_HL(vhl) ((vhl) & 0x0f) -#define IP_VHL_V(vhl) ((vhl) >> 4) -#define IP_VHL_BORING 0x45 -#endif - -#define IP_MAXPACKET 65535 /* maximum packet size */ - -/* - * Definitions for IP type of service (ip_tos) - */ -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 -#define IPTOS_MINCOST 0x02 - -/* - * Definitions for IP precedence (also in ip_tos) (hopefully unused) - */ -#define IPTOS_PREC_NETCONTROL 0xe0 -#define IPTOS_PREC_INTERNETCONTROL 0xc0 -#define IPTOS_PREC_CRITIC_ECP 0xa0 -#define IPTOS_PREC_FLASHOVERRIDE 0x80 -#define IPTOS_PREC_FLASH 0x60 -#define IPTOS_PREC_IMMEDIATE 0x40 -#define IPTOS_PREC_PRIORITY 0x20 -#define IPTOS_PREC_ROUTINE 0x00 - -/* - * Definitions for options. - */ -#define IPOPT_COPIED(o) ((o)&0x80) -#define IPOPT_CLASS(o) ((o)&0x60) -#define IPOPT_NUMBER(o) ((o)&0x1f) - -#define IPOPT_CONTROL 0x00 -#define IPOPT_RESERVED1 0x20 -#define IPOPT_DEBMEAS 0x40 -#define IPOPT_RESERVED2 0x60 - -#define IPOPT_EOL 0 /* end of option list */ -#define IPOPT_NOP 1 /* no operation */ - -#define IPOPT_RR 7 /* record packet route */ -#define IPOPT_TS 68 /* timestamp */ -#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ -#define IPOPT_LSRR 131 /* loose source route */ -#define IPOPT_SATID 136 /* satnet id */ -#define IPOPT_SSRR 137 /* strict source route */ -#define IPOPT_RA 148 /* router alert */ - -/* - * Offsets to fields in options other than EOL and NOP. - */ -#define IPOPT_OPTVAL 0 /* option ID */ -#define IPOPT_OLEN 1 /* option length */ -#define IPOPT_OFFSET 2 /* offset within option */ -#define IPOPT_MINOFF 4 /* min value of above */ - -/* - * Time stamp option structure. - */ -struct ip_timestamp { - u_char ipt_code; /* IPOPT_TS */ - u_char ipt_len; /* size of structure (variable) */ - u_char ipt_ptr; /* index of current entry */ -#if BYTE_ORDER == LITTLE_ENDIAN - u_char ipt_flg:4, /* flags, see below */ - ipt_oflw:4; /* overflow counter */ -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_char ipt_oflw:4, /* overflow counter */ - ipt_flg:4; /* flags, see below */ -#endif - union ipt_timestamp { - n_long ipt_time[1]; - struct ipt_ta { - struct in_addr ipt_addr; - n_long ipt_time; - } ipt_ta[1]; - } ipt_timestamp; -}; - -#include <machine/in_cksum.h> - -/* flag bits for ipt_flg */ -#define IPOPT_TS_TSONLY 0 /* timestamps only */ -#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ -#define IPOPT_TS_PRESPEC 3 /* specified modules only */ - -/* bits for security (not byte swapped) */ -#define IPOPT_SECUR_UNCLASS 0x0000 -#define IPOPT_SECUR_CONFID 0xf135 -#define IPOPT_SECUR_EFTO 0x789a -#define IPOPT_SECUR_MMMM 0xbc4d -#define IPOPT_SECUR_RESTR 0xaf13 -#define IPOPT_SECUR_SECRET 0xd788 -#define IPOPT_SECUR_TOPSECRET 0x6bc5 - -/* - * Internet implementation parameters. - */ -#define MAXTTL 255 /* maximum time to live (seconds) */ -#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ -#define IPFRAGTTL 60 /* time to live for frags, slowhz */ -#define IPTTLDEC 1 /* subtracted when forwarding */ - -#define IP_MSS 576 /* default maximum segment size */ - -#endif diff --git a/c/src/exec/libnetworking/netinet/ip_divert.c b/c/src/exec/libnetworking/netinet/ip_divert.c deleted file mode 100644 index 2955e811ad..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_divert.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. 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. 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. - * - * $Id$ - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/protosw.h> -#include <sys/socketvar.h> -#include <sys/errno.h> -#include <sys/systm.h> - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/ip_var.h> - -/* - * Divert sockets - */ - -/* - * Allocate enough space to hold a full IP packet - */ -#define DIVSNDQ (65536 + 100) -#define DIVRCVQ (65536 + 100) - -/* Global variables */ - -/* - * ip_input() and ip_output() set this secret value before calling us to - * let us know which divert port to divert a packet to; this is done so - * we can use the existing prototype for struct protosw's pr_input(). - * This is stored in host order. - */ -u_short ip_divert_port; - -/* - * We set this value to a non-zero port number when we want the call to - * ip_fw_chk() in ip_input() or ip_output() to ignore ``divert <port>'' - * chain entries. This is stored in host order. - */ -u_short ip_divert_ignore; - -/* Internal variables */ - -static struct inpcbhead divcb; -static struct inpcbinfo divcbinfo; - -static u_long div_sendspace = DIVSNDQ; /* XXX sysctl ? */ -static u_long div_recvspace = DIVRCVQ; /* XXX sysctl ? */ - -/* Optimization: have this preinitialized */ -static struct sockaddr_in divsrc = { sizeof(divsrc), AF_INET }; - -/* Internal functions */ - -static int div_output(struct socket *so, - struct mbuf *m, struct mbuf *addr, struct mbuf *control); - -/* - * Initialize divert connection block queue. - */ -void -div_init(void) -{ - LIST_INIT(&divcb); - divcbinfo.listhead = &divcb; - /* - * XXX We don't use the hash list for divert IP, but it's easier - * to allocate a one entry hash list than it is to check all - * over the place for hashbase == NULL. - */ - divcbinfo.hashbase = hashinit(1, M_PCB, &divcbinfo.hashmask); -} - -/* - * Setup generic address and protocol structures - * for div_input routine, then pass them along with - * mbuf chain. ip->ip_len is assumed to have had - * the header length (hlen) subtracted out already. - * We tell whether the packet was incoming or outgoing - * by seeing if hlen == 0, which is a hack. - */ -void -div_input(struct mbuf *m, int hlen) -{ - struct ip *ip; - struct inpcb *inp; - struct socket *sa; - - /* Sanity check */ - if (ip_divert_port == 0) - panic("div_input: port is 0"); - - /* Assure header */ - if (m->m_len < sizeof(struct ip) && - (m = m_pullup(m, sizeof(struct ip))) == 0) { - return; - } - ip = mtod(m, struct ip *); - - /* Record divert port */ - divsrc.sin_port = htons(ip_divert_port); - - /* Restore packet header fields */ - ip->ip_len += hlen; - HTONS(ip->ip_len); - HTONS(ip->ip_off); - - /* Record receive interface address, if any */ - divsrc.sin_addr.s_addr = 0; - if (hlen) { - struct ifaddr *ifa; - -#ifdef DIAGNOSTIC - /* Sanity check */ - if (!(m->m_flags & M_PKTHDR)) - panic("div_input: no pkt hdr"); -#endif - - /* More fields affected by ip_input() */ - HTONS(ip->ip_id); - - /* Find IP address for recieve interface */ - for (ifa = m->m_pkthdr.rcvif->if_addrlist; - ifa != NULL; ifa = ifa->ifa_next) { - if (ifa->ifa_addr == NULL) - continue; - if (ifa->ifa_addr->sa_family != AF_INET) - continue; - divsrc.sin_addr = - ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; - break; - } - } - - /* Put packet on socket queue, if any */ - sa = NULL; - for (inp = divcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { - if (inp->inp_lport == htons(ip_divert_port)) - sa = inp->inp_socket; - } - if (sa) { - if (sbappendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, - m, (struct mbuf *)0) == 0) - m_freem(m); - else - sorwakeup(sa); - } else { - m_freem(m); - ipstat.ips_noproto++; - ipstat.ips_delivered--; - } -} - -/* - * Deliver packet back into the IP processing machinery. - * - * If no address specified, or address is 0.0.0.0, send to ip_output(); - * otherwise, send to ip_input() and mark as having been received on - * the interface with that address. - * - * If no address specified, or dest port is 0, allow packet to divert - * back to this socket; otherwise, don't. - */ -static int -div_output(so, m, addr, control) - struct socket *so; - register struct mbuf *m; - struct mbuf *addr, *control; -{ - register struct inpcb *const inp = sotoinpcb(so); - register struct ip *const ip = mtod(m, struct ip *); - struct sockaddr_in *sin = NULL; - int error = 0; - - if (control) - m_freem(control); /* XXX */ - if (addr) - sin = mtod(addr, struct sockaddr_in *); - - /* Loopback avoidance option */ - ip_divert_ignore = ntohs(inp->inp_lport); - - /* Reinject packet into the system as incoming or outgoing */ - if (!sin || sin->sin_addr.s_addr == 0) { - /* Don't allow both user specified and setsockopt options, - and don't allow packet length sizes that will crash */ - if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options) || - ((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) { - error = EINVAL; - goto cantsend; - } - - /* Convert fields to host order for ip_output() */ - NTOHS(ip->ip_len); - NTOHS(ip->ip_off); - - /* Send packet to output processing */ - ipstat.ips_rawout++; /* XXX */ - error = ip_output(m, inp->inp_options, &inp->inp_route, - (so->so_options & SO_DONTROUTE) | - IP_ALLOWBROADCAST | IP_RAWOUTPUT, inp->inp_moptions); - } else { - struct ifaddr *ifa; - - /* Find receive interface with the given IP address */ - sin->sin_port = 0; - if ((ifa = ifa_ifwithaddr((struct sockaddr *) sin)) == 0) { - error = EADDRNOTAVAIL; - goto cantsend; - } - m->m_pkthdr.rcvif = ifa->ifa_ifp; - - /* Send packet to input processing */ - ip_input(m); - } - - /* Reset for next time (and other packets) */ - ip_divert_ignore = 0; - return error; - -cantsend: - ip_divert_ignore = 0; - m_freem(m); - return error; -} - -/*ARGSUSED*/ -int -div_usrreq(so, req, m, nam, control) - register struct socket *so; - int req; - struct mbuf *m, *nam, *control; -{ - register int error = 0; - register struct inpcb *inp = sotoinpcb(so); - int s; - - if (inp == NULL && req != PRU_ATTACH) { - error = EINVAL; - goto release; - } - switch (req) { - - case PRU_ATTACH: - if (inp) - panic("div_attach"); - if ((so->so_state & SS_PRIV) == 0) { - error = EACCES; - break; - } - s = splnet(); - error = in_pcballoc(so, &divcbinfo); - splx(s); - if (error) - break; - error = soreserve(so, div_sendspace, div_recvspace); - if (error) - break; - inp = (struct inpcb *)so->so_pcb; - inp->inp_ip_p = (int)nam; /* XXX */ - inp->inp_flags |= INP_HDRINCL; - /* The socket is always "connected" because - we always know "where" to send the packet */ - so->so_state |= SS_ISCONNECTED; - break; - - case PRU_DISCONNECT: - if ((so->so_state & SS_ISCONNECTED) == 0) { - error = ENOTCONN; - break; - } - /* FALLTHROUGH */ - case PRU_ABORT: - soisdisconnected(so); - /* FALLTHROUGH */ - case PRU_DETACH: - if (inp == 0) - panic("div_detach"); - in_pcbdetach(inp); - break; - - case PRU_BIND: - s = splnet(); - error = in_pcbbind(inp, nam); - splx(s); - break; - - /* - * Mark the connection as being incapable of further input. - */ - case PRU_SHUTDOWN: - socantsendmore(so); - break; - - case PRU_SEND: - /* Packet must have a header (but that's about it) */ - if (m->m_len < sizeof (struct ip) || - (m = m_pullup(m, sizeof (struct ip))) == 0) { - ipstat.ips_toosmall++; - error = EINVAL; - break; - } - - /* Send packet */ - error = div_output(so, m, nam, control); - m = NULL; - break; - - case PRU_SOCKADDR: - in_setsockaddr(inp, nam); - break; - - case PRU_SENSE: - /* - * stat: don't bother with a blocksize. - */ - return (0); - - /* - * Not supported. - */ - case PRU_CONNECT: - case PRU_CONNECT2: - case PRU_CONTROL: - case PRU_RCVOOB: - case PRU_RCVD: - case PRU_LISTEN: - case PRU_ACCEPT: - case PRU_SENDOOB: - case PRU_PEERADDR: - error = EOPNOTSUPP; - break; - - default: - panic("div_usrreq"); - } -release: - if (m) - m_freem(m); - return (error); -} diff --git a/c/src/exec/libnetworking/netinet/ip_fw.c b/c/src/exec/libnetworking/netinet/ip_fw.c deleted file mode 100644 index aeb09b0bbe..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_fw.c +++ /dev/null @@ -1,1069 +0,0 @@ -/* - * Copyright (c) 1996 Alex Nash - * Copyright (c) 1993 Daniel Boulet - * Copyright (c) 1994 Ugen J.S.Antsilevich - * - * Redistribution and use in source forms, with and without modification, - * are permitted provided that this entire comment appears intact. - * - * Redistribution in binary form may occur without any restrictions. - * Obviously, it would be nice if you gave credit where credit is due - * but requiring it would be too onerous. - * - * This software is provided ``AS IS'' without any warranties of any kind. - * - * $Id$ - */ - -/* - * Implement IP packet firewall - */ - -#ifndef IPFIREWALL_MODULE -#include "opt_ipfw.h" -#endif - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/queue.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <sys/sysctl.h> -#include <net/if.h> -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/ip_icmp.h> -#include <netinet/ip_fw.h> -#include <netinet/tcp.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> -#include <netinet/tcpip.h> -#include <netinet/udp.h> - -static int fw_debug = 1; -#ifdef IPFIREWALL_VERBOSE -static int fw_verbose = 1; -#else -static int fw_verbose = 0; -#endif -#ifdef IPFIREWALL_VERBOSE_LIMIT -static int fw_verbose_limit = IPFIREWALL_VERBOSE_LIMIT; -#else -static int fw_verbose_limit = 0; -#endif - -LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain; - -#ifdef SYSCTL_NODE -SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, &fw_debug, 0, ""); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose, CTLFLAG_RW, &fw_verbose, 0, ""); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, &fw_verbose_limit, 0, ""); -#endif - -#define dprintf(a) if (!fw_debug); else printf a - -#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\ - (ntohl(a.s_addr)>>16)&0xFF,\ - (ntohl(a.s_addr)>>8)&0xFF,\ - (ntohl(a.s_addr))&0xFF); - -#define dprint_ip(a) if (!fw_debug); else print_ip(a) - -static int add_entry __P((struct ip_fw_head *chainptr, struct ip_fw *frwl)); -static int del_entry __P((struct ip_fw_head *chainptr, u_short number)); -static int zero_entry __P((struct mbuf *m)); -static struct ip_fw *check_ipfw_struct __P((struct ip_fw *m)); -static struct ip_fw *check_ipfw_mbuf __P((struct mbuf *fw)); -static int ipopts_match __P((struct ip *ip, struct ip_fw *f)); -static int port_match __P((u_short *portptr, int nports, u_short port, - int range_flag)); -static int tcpflg_match __P((struct tcphdr *tcp, struct ip_fw *f)); -static int icmptype_match __P((struct icmp * icmp, struct ip_fw * f)); -static void ipfw_report __P((struct ip_fw *f, struct ip *ip, - struct ifnet *rif, struct ifnet *oif)); - -#ifdef IPFIREWALL_MODULE -static ip_fw_chk_t *old_chk_ptr; -static ip_fw_ctl_t *old_ctl_ptr; -#endif - -static int ip_fw_chk __P((struct ip **pip, int hlen, - struct ifnet *oif, int ignport, struct mbuf **m)); -static int ip_fw_ctl __P((int stage, struct mbuf **mm)); - -static char err_prefix[] = "ip_fw_ctl:"; - -/* - * Returns 1 if the port is matched by the vector, 0 otherwise - */ -static inline int -port_match(u_short *portptr, int nports, u_short port, int range_flag) -{ - if (!nports) - return 1; - if (range_flag) { - if (portptr[0] <= port && port <= portptr[1]) { - return 1; - } - nports -= 2; - portptr += 2; - } - while (nports-- > 0) { - if (*portptr++ == port) { - return 1; - } - } - return 0; -} - -static int -tcpflg_match(struct tcphdr *tcp, struct ip_fw *f) -{ - u_char flg_set, flg_clr; - - if ((f->fw_tcpf & IP_FW_TCPF_ESTAB) && - (tcp->th_flags & (IP_FW_TCPF_RST | IP_FW_TCPF_ACK))) - return 1; - - flg_set = tcp->th_flags & f->fw_tcpf; - flg_clr = tcp->th_flags & f->fw_tcpnf; - - if (flg_set != f->fw_tcpf) - return 0; - if (flg_clr) - return 0; - - return 1; -} - -static int -icmptype_match(struct icmp *icmp, struct ip_fw *f) -{ - int type; - - if (!(f->fw_flg & IP_FW_F_ICMPBIT)) - return(1); - - type = icmp->icmp_type; - - /* check for matching type in the bitmap */ - if (type < IP_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8 && - (f->fw_icmptypes[type / (sizeof(unsigned) * 8)] & - (1U << (type % (8 * sizeof(unsigned)))))) - return(1); - - return(0); /* no match */ -} - -static int -ipopts_match(struct ip *ip, struct ip_fw *f) -{ - register u_char *cp; - int opt, optlen, cnt; - u_char opts, nopts, nopts_sve; - - cp = (u_char *)(ip + 1); - cnt = (ip->ip_hl << 2) - sizeof (struct ip); - opts = f->fw_ipopt; - nopts = nopts_sve = f->fw_ipnopt; - - for (; cnt > 0; cnt -= optlen, cp += optlen) { - opt = cp[IPOPT_OPTVAL]; - if (opt == IPOPT_EOL) - break; - if (opt == IPOPT_NOP) - optlen = 1; - else { - optlen = cp[IPOPT_OLEN]; - if (optlen <= 0 || optlen > cnt) { - return 0; /*XXX*/ - } - } - switch (opt) { - - default: - break; - - case IPOPT_LSRR: - opts &= ~IP_FW_IPOPT_LSRR; - nopts &= ~IP_FW_IPOPT_LSRR; - break; - - case IPOPT_SSRR: - opts &= ~IP_FW_IPOPT_SSRR; - nopts &= ~IP_FW_IPOPT_SSRR; - break; - - case IPOPT_RR: - opts &= ~IP_FW_IPOPT_RR; - nopts &= ~IP_FW_IPOPT_RR; - break; - case IPOPT_TS: - opts &= ~IP_FW_IPOPT_TS; - nopts &= ~IP_FW_IPOPT_TS; - break; - } - if (opts == nopts) - break; - } - if (opts == 0 && nopts == nopts_sve) - return 1; - else - return 0; -} - -static inline int -iface_match(struct ifnet *ifp, union ip_fw_if *ifu, int byname) -{ - /* Check by name or by IP address */ - if (byname) { - /* Check unit number (-1 is wildcard) */ - if (ifu->fu_via_if.unit != -1 - && ifp->if_unit != ifu->fu_via_if.unit) - return(0); - /* Check name */ - if (strncmp(ifp->if_name, ifu->fu_via_if.name, FW_IFNLEN)) - return(0); - return(1); - } else if (ifu->fu_via_ip.s_addr != 0) { /* Zero == wildcard */ - struct ifaddr *ia; - - for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { - if (ia->ifa_addr == NULL) - continue; - if (ia->ifa_addr->sa_family != AF_INET) - continue; - if (ifu->fu_via_ip.s_addr != ((struct sockaddr_in *) - (ia->ifa_addr))->sin_addr.s_addr) - continue; - return(1); - } - return(0); - } - return(1); -} - -static void -ipfw_report(struct ip_fw *f, struct ip *ip, - struct ifnet *rif, struct ifnet *oif) -{ - static int counter; - struct tcphdr *const tcp = (struct tcphdr *) ((u_long *) ip+ ip->ip_hl); - struct udphdr *const udp = (struct udphdr *) ((u_long *) ip+ ip->ip_hl); - struct icmp *const icmp = (struct icmp *) ((u_long *) ip + ip->ip_hl); - int count; - - count = f ? f->fw_pcnt : ++counter; - if (fw_verbose_limit != 0 && count > fw_verbose_limit) - return; - - /* Print command name */ - printf("ipfw: %d ", f ? f->fw_number : -1); - if (!f) - printf("Refuse"); - else - switch (f->fw_flg & IP_FW_F_COMMAND) { - case IP_FW_F_DENY: - printf("Deny"); - break; - case IP_FW_F_REJECT: - if (f->fw_reject_code == IP_FW_REJECT_RST) - printf("Reset"); - else - printf("Unreach"); - break; - case IP_FW_F_ACCEPT: - printf("Accept"); - break; - case IP_FW_F_COUNT: - printf("Count"); - break; - case IP_FW_F_DIVERT: - printf("Divert %d", f->fw_divert_port); - break; - case IP_FW_F_TEE: - printf("Tee %d", f->fw_divert_port); - break; - case IP_FW_F_SKIPTO: - printf("SkipTo %d", f->fw_skipto_rule); - break; - default: - printf("UNKNOWN"); - break; - } - printf(" "); - - switch (ip->ip_p) { - case IPPROTO_TCP: - printf("TCP "); - print_ip(ip->ip_src); - if ((ip->ip_off & IP_OFFMASK) == 0) - printf(":%d ", ntohs(tcp->th_sport)); - else - printf(" "); - print_ip(ip->ip_dst); - if ((ip->ip_off & IP_OFFMASK) == 0) - printf(":%d", ntohs(tcp->th_dport)); - break; - case IPPROTO_UDP: - printf("UDP "); - print_ip(ip->ip_src); - if ((ip->ip_off & IP_OFFMASK) == 0) - printf(":%d ", ntohs(udp->uh_sport)); - else - printf(" "); - print_ip(ip->ip_dst); - if ((ip->ip_off & IP_OFFMASK) == 0) - printf(":%d", ntohs(udp->uh_dport)); - break; - case IPPROTO_ICMP: - printf("ICMP:%u.%u ", icmp->icmp_type, icmp->icmp_code); - print_ip(ip->ip_src); - printf(" "); - print_ip(ip->ip_dst); - break; - default: - printf("P:%d ", ip->ip_p); - print_ip(ip->ip_src); - printf(" "); - print_ip(ip->ip_dst); - break; - } - if (oif) - printf(" out via %s%d", oif->if_name, oif->if_unit); - else if (rif) - printf(" in via %s%d", rif->if_name, rif->if_unit); - if ((ip->ip_off & IP_OFFMASK)) - printf(" Fragment = %d",ip->ip_off & IP_OFFMASK); - printf("\n"); - if (fw_verbose_limit != 0 && count == fw_verbose_limit) - printf("ipfw: limit reached on rule #%d\n", - f ? f->fw_number : -1); -} - -/* - * Parameters: - * - * ip Pointer to packet header (struct ip *) - * hlen Packet header length - * oif Outgoing interface, or NULL if packet is incoming - * ignport Ignore all divert/tee rules to this port (if non-zero) - * *m The packet; we set to NULL when/if we nuke it. - * - * Return value: - * - * 0 The packet is to be accepted and routed normally OR - * the packet was denied/rejected and has been dropped; - * in the latter case, *m is equal to NULL upon return. - * port Divert the packet to port. - */ - -static int -ip_fw_chk(struct ip **pip, int hlen, - struct ifnet *oif, int ignport, struct mbuf **m) -{ - struct ip_fw_chain *chain; - struct ip_fw *rule = NULL; - struct ip *ip = *pip; - struct ifnet *const rif = (*m)->m_pkthdr.rcvif; - u_short offset = (ip->ip_off & IP_OFFMASK); - u_short src_port, dst_port; - - /* - * Go down the chain, looking for enlightment - */ - for (chain=ip_fw_chain.lh_first; chain; chain = chain->chain.le_next) { - register struct ip_fw *const f = chain->rule; - - /* Check direction inbound */ - if (!oif && !(f->fw_flg & IP_FW_F_IN)) - continue; - - /* Check direction outbound */ - if (oif && !(f->fw_flg & IP_FW_F_OUT)) - continue; - - /* Fragments */ - if ((f->fw_flg & IP_FW_F_FRAG) && !(ip->ip_off & IP_OFFMASK)) - continue; - - /* If src-addr doesn't match, not this rule. */ - if (((f->fw_flg & IP_FW_F_INVSRC) != 0) ^ ((ip->ip_src.s_addr - & f->fw_smsk.s_addr) != f->fw_src.s_addr)) - continue; - - /* If dest-addr doesn't match, not this rule. */ - if (((f->fw_flg & IP_FW_F_INVDST) != 0) ^ ((ip->ip_dst.s_addr - & f->fw_dmsk.s_addr) != f->fw_dst.s_addr)) - continue; - - /* Interface check */ - if ((f->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) { - struct ifnet *const iface = oif ? oif : rif; - - /* Backwards compatibility hack for "via" */ - if (!iface || !iface_match(iface, - &f->fw_in_if, f->fw_flg & IP_FW_F_OIFNAME)) - continue; - } else { - /* Check receive interface */ - if ((f->fw_flg & IP_FW_F_IIFACE) - && (!rif || !iface_match(rif, - &f->fw_in_if, f->fw_flg & IP_FW_F_IIFNAME))) - continue; - /* Check outgoing interface */ - if ((f->fw_flg & IP_FW_F_OIFACE) - && (!oif || !iface_match(oif, - &f->fw_out_if, f->fw_flg & IP_FW_F_OIFNAME))) - continue; - } - - /* Check IP options */ - if (f->fw_ipopt != f->fw_ipnopt && !ipopts_match(ip, f)) - continue; - - /* Check protocol; if wildcard, match */ - if (f->fw_prot == IPPROTO_IP) - goto got_match; - - /* If different, don't match */ - if (ip->ip_p != f->fw_prot) - continue; - -#define PULLUP_TO(len) do { \ - if ((*m)->m_len < (len) \ - && (*m = m_pullup(*m, (len))) == 0) { \ - goto bogusfrag; \ - } \ - *pip = ip = mtod(*m, struct ip *); \ - offset = (ip->ip_off & IP_OFFMASK); \ - } while (0) - - /* Protocol specific checks */ - switch (ip->ip_p) { - case IPPROTO_TCP: - { - struct tcphdr *tcp; - - if (offset == 1) /* cf. RFC 1858 */ - goto bogusfrag; - if (offset != 0) { - /* - * TCP flags and ports aren't available in this - * packet -- if this rule specified either one, - * we consider the rule a non-match. - */ - if (f->fw_nports != 0 || - f->fw_tcpf != f->fw_tcpnf) - continue; - - break; - } - PULLUP_TO(hlen + 14); - tcp = (struct tcphdr *) ((u_long *)ip + ip->ip_hl); - if (f->fw_tcpf != f->fw_tcpnf && !tcpflg_match(tcp, f)) - continue; - src_port = ntohs(tcp->th_sport); - dst_port = ntohs(tcp->th_dport); - goto check_ports; - } - - case IPPROTO_UDP: - { - struct udphdr *udp; - - if (offset != 0) { - /* - * Port specification is unavailable -- if this - * rule specifies a port, we consider the rule - * a non-match. - */ - if (f->fw_nports != 0) - continue; - - break; - } - PULLUP_TO(hlen + 4); - udp = (struct udphdr *) ((u_long *)ip + ip->ip_hl); - src_port = ntohs(udp->uh_sport); - dst_port = ntohs(udp->uh_dport); -check_ports: - if (!port_match(&f->fw_pts[0], - IP_FW_GETNSRCP(f), src_port, - f->fw_flg & IP_FW_F_SRNG)) - continue; - if (!port_match(&f->fw_pts[IP_FW_GETNSRCP(f)], - IP_FW_GETNDSTP(f), dst_port, - f->fw_flg & IP_FW_F_DRNG)) - continue; - break; - } - - case IPPROTO_ICMP: - { - struct icmp *icmp; - - if (offset != 0) /* Type isn't valid */ - break; - PULLUP_TO(hlen + 2); - icmp = (struct icmp *) ((u_long *)ip + ip->ip_hl); - if (!icmptype_match(icmp, f)) - continue; - break; - } -#undef PULLUP_TO - -bogusfrag: - if (fw_verbose) - ipfw_report(NULL, ip, rif, oif); - goto dropit; - } - -got_match: - /* Ignore divert/tee rule if socket port is "ignport" */ - switch (f->fw_flg & IP_FW_F_COMMAND) { - case IP_FW_F_DIVERT: - case IP_FW_F_TEE: - if (f->fw_divert_port == ignport) - continue; /* ignore this rule */ - break; - } - - /* Update statistics */ - f->fw_pcnt += 1; - f->fw_bcnt += ip->ip_len; - f->timestamp = rtems_bsdnet_seconds_since_boot(); - - /* Log to console if desired */ - if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose) - ipfw_report(f, ip, rif, oif); - - /* Take appropriate action */ - switch (f->fw_flg & IP_FW_F_COMMAND) { - case IP_FW_F_ACCEPT: - return(0); - case IP_FW_F_COUNT: - continue; - case IP_FW_F_DIVERT: - return(f->fw_divert_port); - case IP_FW_F_TEE: - /* - * XXX someday tee packet here, but beware that you - * can't use m_copym() or m_copypacket() because - * the divert input routine modifies the mbuf - * (and these routines only increment reference - * counts in the case of mbuf clusters), so need - * to write custom routine. - */ - continue; - case IP_FW_F_SKIPTO: -#ifdef DIAGNOSTIC - while (chain->chain.le_next - && chain->chain.le_next->rule->fw_number - < f->fw_skipto_rule) -#else - while (chain->chain.le_next->rule->fw_number - < f->fw_skipto_rule) -#endif - chain = chain->chain.le_next; - continue; - } - - /* Deny/reject this packet using this rule */ - rule = f; - break; - } - -#ifdef DIAGNOSTIC - /* Rule 65535 should always be there and should always match */ - if (!chain) - panic("ip_fw: chain"); -#endif - - /* - * At this point, we're going to drop the packet. - * Send a reject notice if all of the following are true: - * - * - The packet matched a reject rule - * - The packet is not an ICMP packet - * - The packet is not a multicast or broadcast packet - */ - if ((rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT - && ip->ip_p != IPPROTO_ICMP - && !((*m)->m_flags & (M_BCAST|M_MCAST)) - && !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { - switch (rule->fw_reject_code) { - case IP_FW_REJECT_RST: - { - struct tcphdr *const tcp = - (struct tcphdr *) ((u_long *)ip + ip->ip_hl); - struct tcpiphdr ti, *const tip = (struct tcpiphdr *) ip; - - if (offset != 0 || (tcp->th_flags & TH_RST)) - break; - ti.ti_i = *((struct ipovly *) ip); - ti.ti_t = *tcp; - bcopy(&ti, ip, sizeof(ti)); - NTOHL(tip->ti_seq); - NTOHL(tip->ti_ack); - tip->ti_len = ip->ip_len - hlen - (tip->ti_off << 2); - if (tcp->th_flags & TH_ACK) { - tcp_respond(NULL, tip, *m, - (tcp_seq)0, ntohl(tcp->th_ack), TH_RST); - } else { - if (tcp->th_flags & TH_SYN) - tip->ti_len++; - tcp_respond(NULL, tip, *m, tip->ti_seq - + tip->ti_len, (tcp_seq)0, TH_RST|TH_ACK); - } - *m = NULL; - break; - } - default: /* Send an ICMP unreachable using code */ - icmp_error(*m, ICMP_UNREACH, - rule->fw_reject_code, 0L, 0); - *m = NULL; - break; - } - } - -dropit: - /* - * Finally, drop the packet. - */ - if (*m) { - m_freem(*m); - *m = NULL; - } - return(0); -} - -static int -add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl) -{ - struct ip_fw *ftmp = 0; - struct ip_fw_chain *fwc = 0, *fcp, *fcpl = 0; - u_short nbr = 0; - int s; - - fwc = malloc(sizeof *fwc, M_IPFW, M_DONTWAIT); - ftmp = malloc(sizeof *ftmp, M_IPFW, M_DONTWAIT); - if (!fwc || !ftmp) { - dprintf(("%s malloc said no\n", err_prefix)); - if (fwc) free(fwc, M_IPFW); - if (ftmp) free(ftmp, M_IPFW); - return (ENOSPC); - } - - bcopy(frwl, ftmp, sizeof(struct ip_fw)); - ftmp->fw_in_if.fu_via_if.name[FW_IFNLEN - 1] = '\0'; - ftmp->fw_pcnt = 0L; - ftmp->fw_bcnt = 0L; - fwc->rule = ftmp; - - s = splnet(); - - if (!chainptr->lh_first) { - LIST_INSERT_HEAD(chainptr, fwc, chain); - splx(s); - return(0); - } else if (ftmp->fw_number == (u_short)-1) { - if (fwc) free(fwc, M_IPFW); - if (ftmp) free(ftmp, M_IPFW); - splx(s); - dprintf(("%s bad rule number\n", err_prefix)); - return (EINVAL); - } - - /* If entry number is 0, find highest numbered rule and add 100 */ - if (ftmp->fw_number == 0) { - for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) { - if (fcp->rule->fw_number != (u_short)-1) - nbr = fcp->rule->fw_number; - else - break; - } - if (nbr < (u_short)-1 - 100) - nbr += 100; - ftmp->fw_number = nbr; - } - - /* Got a valid number; now insert it, keeping the list ordered */ - for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) { - if (fcp->rule->fw_number > ftmp->fw_number) { - if (fcpl) { - LIST_INSERT_AFTER(fcpl, fwc, chain); - } else { - LIST_INSERT_HEAD(chainptr, fwc, chain); - } - break; - } else { - fcpl = fcp; - } - } - - splx(s); - return (0); -} - -static int -del_entry(struct ip_fw_head *chainptr, u_short number) -{ - struct ip_fw_chain *fcp; - int s; - - s = splnet(); - - fcp = chainptr->lh_first; - if (number != (u_short)-1) { - for (; fcp; fcp = fcp->chain.le_next) { - if (fcp->rule->fw_number == number) { - LIST_REMOVE(fcp, chain); - splx(s); - free(fcp->rule, M_IPFW); - free(fcp, M_IPFW); - return 0; - } - } - } - - splx(s); - return (EINVAL); -} - -static int -zero_entry(struct mbuf *m) -{ - struct ip_fw *frwl; - struct ip_fw_chain *fcp; - int s; - - if (m) { - if (m->m_len != sizeof(struct ip_fw)) - return(EINVAL); - frwl = mtod(m, struct ip_fw *); - } - else - frwl = NULL; - - /* - * It's possible to insert multiple chain entries with the - * same number, so we don't stop after finding the first - * match if zeroing a specific entry. - */ - s = splnet(); - for (fcp = ip_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next) - if (!frwl || frwl->fw_number == fcp->rule->fw_number) { - fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0; - fcp->rule->timestamp = 0; - } - splx(s); - - if (fw_verbose) { - if (frwl) - printf("ipfw: Entry %d cleared.\n", frwl->fw_number); - else - printf("ipfw: Accounting cleared.\n"); - } - - return(0); -} - -static struct ip_fw * -check_ipfw_mbuf(struct mbuf *m) -{ - /* Check length */ - if (m->m_len != sizeof(struct ip_fw)) { - dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len, - (int)sizeof(struct ip_fw))); - return (NULL); - } - return(check_ipfw_struct(mtod(m, struct ip_fw *))); -} - -static struct ip_fw * -check_ipfw_struct(struct ip_fw *frwl) -{ - /* Check for invalid flag bits */ - if ((frwl->fw_flg & ~IP_FW_F_MASK) != 0) { - dprintf(("%s undefined flag bits set (flags=%x)\n", - err_prefix, frwl->fw_flg)); - return (NULL); - } - /* Must apply to incoming or outgoing (or both) */ - if (!(frwl->fw_flg & (IP_FW_F_IN | IP_FW_F_OUT))) { - dprintf(("%s neither in nor out\n", err_prefix)); - return (NULL); - } - /* Empty interface name is no good */ - if (((frwl->fw_flg & IP_FW_F_IIFNAME) - && !*frwl->fw_in_if.fu_via_if.name) - || ((frwl->fw_flg & IP_FW_F_OIFNAME) - && !*frwl->fw_out_if.fu_via_if.name)) { - dprintf(("%s empty interface name\n", err_prefix)); - return (NULL); - } - /* Sanity check interface matching */ - if ((frwl->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) { - ; /* allow "via" backwards compatibility */ - } else if ((frwl->fw_flg & IP_FW_F_IN) - && (frwl->fw_flg & IP_FW_F_OIFACE)) { - dprintf(("%s outgoing interface check on incoming\n", - err_prefix)); - return (NULL); - } - /* Sanity check port ranges */ - if ((frwl->fw_flg & IP_FW_F_SRNG) && IP_FW_GETNSRCP(frwl) < 2) { - dprintf(("%s src range set but n_src_p=%d\n", - err_prefix, IP_FW_GETNSRCP(frwl))); - return (NULL); - } - if ((frwl->fw_flg & IP_FW_F_DRNG) && IP_FW_GETNDSTP(frwl) < 2) { - dprintf(("%s dst range set but n_dst_p=%d\n", - err_prefix, IP_FW_GETNDSTP(frwl))); - return (NULL); - } - if (IP_FW_GETNSRCP(frwl) + IP_FW_GETNDSTP(frwl) > IP_FW_MAX_PORTS) { - dprintf(("%s too many ports (%d+%d)\n", - err_prefix, IP_FW_GETNSRCP(frwl), IP_FW_GETNDSTP(frwl))); - return (NULL); - } - /* - * Protocols other than TCP/UDP don't use port range - */ - if ((frwl->fw_prot != IPPROTO_TCP) && - (frwl->fw_prot != IPPROTO_UDP) && - (IP_FW_GETNSRCP(frwl) || IP_FW_GETNDSTP(frwl))) { - dprintf(("%s port(s) specified for non TCP/UDP rule\n", - err_prefix)); - return(NULL); - } - - /* - * Rather than modify the entry to make such entries work, - * we reject this rule and require user level utilities - * to enforce whatever policy they deem appropriate. - */ - if ((frwl->fw_src.s_addr & (~frwl->fw_smsk.s_addr)) || - (frwl->fw_dst.s_addr & (~frwl->fw_dmsk.s_addr))) { - dprintf(("%s rule never matches\n", err_prefix)); - return(NULL); - } - - if ((frwl->fw_flg & IP_FW_F_FRAG) && - (frwl->fw_prot == IPPROTO_UDP || frwl->fw_prot == IPPROTO_TCP)) { - if (frwl->fw_nports) { - dprintf(("%s cannot mix 'frag' and ports\n", err_prefix)); - return(NULL); - } - if (frwl->fw_prot == IPPROTO_TCP && - frwl->fw_tcpf != frwl->fw_tcpnf) { - dprintf(("%s cannot mix 'frag' with TCP flags\n", err_prefix)); - return(NULL); - } - } - - /* Check command specific stuff */ - switch (frwl->fw_flg & IP_FW_F_COMMAND) - { - case IP_FW_F_REJECT: - if (frwl->fw_reject_code >= 0x100 - && !(frwl->fw_prot == IPPROTO_TCP - && frwl->fw_reject_code == IP_FW_REJECT_RST)) { - dprintf(("%s unknown reject code\n", err_prefix)); - return(NULL); - } - break; - case IP_FW_F_DIVERT: /* Diverting to port zero is invalid */ - case IP_FW_F_TEE: - if (frwl->fw_divert_port == 0) { - dprintf(("%s can't divert to port 0\n", err_prefix)); - return (NULL); - } - break; - case IP_FW_F_DENY: - case IP_FW_F_ACCEPT: - case IP_FW_F_COUNT: - case IP_FW_F_SKIPTO: - break; - default: - dprintf(("%s invalid command\n", err_prefix)); - return(NULL); - } - - return frwl; -} - -static int -ip_fw_ctl(int stage, struct mbuf **mm) -{ - int error; - struct mbuf *m; - - if (stage == IP_FW_GET) { - struct ip_fw_chain *fcp = ip_fw_chain.lh_first; - *mm = m = m_get(M_WAIT, MT_SOOPTS); - for (; fcp; fcp = fcp->chain.le_next) { - memcpy(m->m_data, fcp->rule, sizeof *(fcp->rule)); - m->m_len = sizeof *(fcp->rule); - m->m_next = m_get(M_WAIT, MT_SOOPTS); - m = m->m_next; - m->m_len = 0; - } - return (0); - } - m = *mm; - /* only allow get calls if secure mode > 2 */ - if (securelevel > 2) { - if (m) (void)m_free(m); - return(EPERM); - } - if (stage == IP_FW_FLUSH) { - while (ip_fw_chain.lh_first != NULL && - ip_fw_chain.lh_first->rule->fw_number != (u_short)-1) { - struct ip_fw_chain *fcp = ip_fw_chain.lh_first; - int s = splnet(); - LIST_REMOVE(ip_fw_chain.lh_first, chain); - splx(s); - free(fcp->rule, M_IPFW); - free(fcp, M_IPFW); - } - if (m) (void)m_free(m); - return (0); - } - if (stage == IP_FW_ZERO) { - error = zero_entry(m); - if (m) (void)m_free(m); - return (error); - } - if (m == NULL) { - printf("%s NULL mbuf ptr\n", err_prefix); - return (EINVAL); - } - - if (stage == IP_FW_ADD) { - struct ip_fw *frwl = check_ipfw_mbuf(m); - - if (!frwl) - error = EINVAL; - else - error = add_entry(&ip_fw_chain, frwl); - if (m) (void)m_free(m); - return error; - } - if (stage == IP_FW_DEL) { - if (m->m_len != sizeof(struct ip_fw)) { - dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len, - (int)sizeof(struct ip_fw))); - error = EINVAL; - } else if (mtod(m, struct ip_fw *)->fw_number == (u_short)-1) { - dprintf(("%s can't delete rule 65535\n", err_prefix)); - error = EINVAL; - } else - error = del_entry(&ip_fw_chain, - mtod(m, struct ip_fw *)->fw_number); - if (m) (void)m_free(m); - return error; - } - - dprintf(("%s unknown request %d\n", err_prefix, stage)); - if (m) (void)m_free(m); - return (EINVAL); -} - -void -ip_fw_init(void) -{ - struct ip_fw default_rule; - - ip_fw_chk_ptr = ip_fw_chk; - ip_fw_ctl_ptr = ip_fw_ctl; - LIST_INIT(&ip_fw_chain); - - bzero(&default_rule, sizeof default_rule); - default_rule.fw_prot = IPPROTO_IP; - default_rule.fw_number = (u_short)-1; -#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT - default_rule.fw_flg |= IP_FW_F_ACCEPT; -#else - default_rule.fw_flg |= IP_FW_F_DENY; -#endif - default_rule.fw_flg |= IP_FW_F_IN | IP_FW_F_OUT; - if (check_ipfw_struct(&default_rule) == NULL || - add_entry(&ip_fw_chain, &default_rule)) - panic(__FUNCTION__); - - printf("IP packet filtering initialized, " -#ifdef IPDIVERT - "divert enabled, "); -#else - "divert disabled, "); -#endif -#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT - printf("default to accept, "); -#endif -#ifndef IPFIREWALL_VERBOSE - printf("logging disabled\n"); -#else - if (fw_verbose_limit == 0) - printf("unlimited logging\n"); - else - printf("logging limited to %d packets/entry\n", - fw_verbose_limit); -#endif -} - -#ifdef IPFIREWALL_MODULE - -#include <sys/exec.h> -#include <sys/sysent.h> -#include <sys/lkm.h> - -MOD_MISC(ipfw); - -static int -ipfw_load(struct lkm_table *lkmtp, int cmd) -{ - int s=splnet(); - - old_chk_ptr = ip_fw_chk_ptr; - old_ctl_ptr = ip_fw_ctl_ptr; - - ip_fw_init(); - splx(s); - return 0; -} - -static int -ipfw_unload(struct lkm_table *lkmtp, int cmd) -{ - int s=splnet(); - - ip_fw_chk_ptr = old_chk_ptr; - ip_fw_ctl_ptr = old_ctl_ptr; - - while (ip_fw_chain.lh_first != NULL) { - struct ip_fw_chain *fcp = ip_fw_chain.lh_first; - LIST_REMOVE(ip_fw_chain.lh_first, chain); - free(fcp->rule, M_IPFW); - free(fcp, M_IPFW); - } - - splx(s); - printf("IP firewall unloaded\n"); - return 0; -} - -int -ipfw_mod(struct lkm_table *lkmtp, int cmd, int ver) -{ - DISPATCH(lkmtp, cmd, ver, ipfw_load, ipfw_unload, lkm_nullcmd); -} -#endif diff --git a/c/src/exec/libnetworking/netinet/ip_fw.h b/c/src/exec/libnetworking/netinet/ip_fw.h deleted file mode 100644 index cab7f4ac93..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_fw.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 1993 Daniel Boulet - * Copyright (c) 1994 Ugen J.S.Antsilevich - * - * Redistribution and use in source forms, with and without modification, - * are permitted provided that this entire comment appears intact. - * - * Redistribution in binary form may occur without any restrictions. - * Obviously, it would be nice if you gave credit where credit is due - * but requiring it would be too onerous. - * - * This software is provided ``AS IS'' without any warranties of any kind. - * - * $Id$ - */ - -#ifndef _IP_FW_H -#define _IP_FW_H - -#include <net/if.h> - -/* - * This union structure identifies an interface, either explicitly - * by name or implicitly by IP address. The flags IP_FW_F_IIFNAME - * and IP_FW_F_OIFNAME say how to interpret this structure. An - * interface unit number of -1 matches any unit number, while an - * IP address of 0.0.0.0 indicates matches any interface. - * - * The receive and transmit interfaces are only compared against the - * the packet if the corresponding bit (IP_FW_F_IIFACE or IP_FW_F_OIFACE) - * is set. Note some packets lack a receive or transmit interface - * (in which case the missing "interface" never matches). - */ - -union ip_fw_if { - struct in_addr fu_via_ip; /* Specified by IP address */ - struct { /* Specified by interface name */ -#define FW_IFNLEN IFNAMSIZ - char name[FW_IFNLEN]; - short unit; /* -1 means match any unit */ - } fu_via_if; -}; - -/* - * Format of an IP firewall descriptor - * - * fw_src, fw_dst, fw_smsk, fw_dmsk are always stored in network byte order. - * fw_flg and fw_n*p are stored in host byte order (of course). - * Port numbers are stored in HOST byte order. - * Warning: setsockopt() will fail if sizeof(struct ip_fw) > MLEN (108) - */ - -struct ip_fw { - u_long fw_pcnt,fw_bcnt; /* Packet and byte counters */ - struct in_addr fw_src, fw_dst; /* Source and destination IP addr */ - struct in_addr fw_smsk, fw_dmsk; /* Mask for src and dest IP addr */ - u_short fw_number; /* Rule number */ - u_short fw_flg; /* Flags word */ -#define IP_FW_MAX_PORTS 10 /* A reasonable maximum */ - u_short fw_pts[IP_FW_MAX_PORTS]; /* Array of port numbers to match */ - u_char fw_ipopt,fw_ipnopt; /* IP options set/unset */ - u_char fw_tcpf,fw_tcpnf; /* TCP flags set/unset */ -#define IP_FW_ICMPTYPES_DIM (32 / (sizeof(unsigned) * 8)) - unsigned fw_icmptypes[IP_FW_ICMPTYPES_DIM]; /* ICMP types bitmap */ - long timestamp; /* timestamp (tv_sec) of last match */ - union ip_fw_if fw_in_if, fw_out_if; /* Incoming and outgoing interfaces */ - union { - u_short fu_divert_port; /* Divert/tee port (options IPDIVERT) */ - u_short fu_skipto_rule; /* SKIPTO command rule number */ - u_short fu_reject_code; /* REJECT response code */ - } fw_un; - u_char fw_prot; /* IP protocol */ - u_char fw_nports; /* N'of src ports and # of dst ports */ - /* in ports array (dst ports follow */ - /* src ports; max of 10 ports in all; */ - /* count of 0 means match all ports) */ -}; - -#define IP_FW_GETNSRCP(rule) ((rule)->fw_nports & 0x0f) -#define IP_FW_SETNSRCP(rule, n) do { \ - (rule)->fw_nports &= ~0x0f; \ - (rule)->fw_nports |= (n); \ - } while (0) -#define IP_FW_GETNDSTP(rule) ((rule)->fw_nports >> 4) -#define IP_FW_SETNDSTP(rule, n) do { \ - (rule)->fw_nports &= ~0xf0; \ - (rule)->fw_nports |= (n) << 4;\ - } while (0) - -#define fw_divert_port fw_un.fu_divert_port -#define fw_skipto_rule fw_un.fu_skipto_rule -#define fw_reject_code fw_un.fu_reject_code - -struct ip_fw_chain { - LIST_ENTRY(ip_fw_chain) chain; - struct ip_fw *rule; -}; - -/* - * Values for "flags" field . - */ -#define IP_FW_F_IN 0x0001 /* Check inbound packets */ -#define IP_FW_F_OUT 0x0002 /* Check outbound packets */ -#define IP_FW_F_IIFACE 0x0004 /* Apply inbound interface test */ -#define IP_FW_F_OIFACE 0x0008 /* Apply outbound interface test */ - -#define IP_FW_F_COMMAND 0x0070 /* Mask for type of chain entry: */ -#define IP_FW_F_DENY 0x0000 /* This is a deny rule */ -#define IP_FW_F_REJECT 0x0010 /* Deny and send a response packet */ -#define IP_FW_F_ACCEPT 0x0020 /* This is an accept rule */ -#define IP_FW_F_COUNT 0x0030 /* This is a count rule */ -#define IP_FW_F_DIVERT 0x0040 /* This is a divert rule */ -#define IP_FW_F_TEE 0x0050 /* This is a tee rule */ -#define IP_FW_F_SKIPTO 0x0060 /* This is a skipto rule */ - -#define IP_FW_F_PRN 0x0080 /* Print if this rule matches */ - -#define IP_FW_F_SRNG 0x0100 /* The first two src ports are a min * - * and max range (stored in host byte * - * order). */ - -#define IP_FW_F_DRNG 0x0200 /* The first two dst ports are a min * - * and max range (stored in host byte * - * order). */ - -#define IP_FW_F_IIFNAME 0x0400 /* In interface by name/unit (not IP) */ -#define IP_FW_F_OIFNAME 0x0800 /* Out interface by name/unit (not IP) */ - -#define IP_FW_F_INVSRC 0x1000 /* Invert sense of src check */ -#define IP_FW_F_INVDST 0x2000 /* Invert sense of dst check */ - -#define IP_FW_F_FRAG 0x4000 /* Fragment */ - -#define IP_FW_F_ICMPBIT 0x8000 /* ICMP type bitmap is valid */ - -#define IP_FW_F_MASK 0xFFFF /* All possible flag bits mask */ - -/* - * For backwards compatibility with rules specifying "via iface" but - * not restricted to only "in" or "out" packets, we define this combination - * of bits to represent this configuration. - */ - -#define IF_FW_F_VIAHACK (IP_FW_F_IN|IP_FW_F_OUT|IP_FW_F_IIFACE|IP_FW_F_OIFACE) - -/* - * Definitions for REJECT response codes. - * Values less than 256 correspond to ICMP unreachable codes. - */ -#define IP_FW_REJECT_RST 0x0100 /* TCP packets: send RST */ - -/* - * Definitions for IP option names. - */ -#define IP_FW_IPOPT_LSRR 0x01 -#define IP_FW_IPOPT_SSRR 0x02 -#define IP_FW_IPOPT_RR 0x04 -#define IP_FW_IPOPT_TS 0x08 - -/* - * Definitions for TCP flags. - */ -#define IP_FW_TCPF_FIN TH_FIN -#define IP_FW_TCPF_SYN TH_SYN -#define IP_FW_TCPF_RST TH_RST -#define IP_FW_TCPF_PSH TH_PUSH -#define IP_FW_TCPF_ACK TH_ACK -#define IP_FW_TCPF_URG TH_URG -#define IP_FW_TCPF_ESTAB 0x40 - -/* - * Main firewall chains definitions and global var's definitions. - */ -#ifdef KERNEL - -/* - * Function definitions. - */ -void ip_fw_init(void); - -#endif /* KERNEL */ - -#endif /* _IP_FW_H */ diff --git a/c/src/exec/libnetworking/netinet/ip_icmp.c b/c/src/exec/libnetworking/netinet/ip_icmp.c deleted file mode 100644 index 44088ab713..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_icmp.c +++ /dev/null @@ -1,711 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/route.h> - -#define _IP_VHL -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#include <netinet/ip_icmp.h> -#include <netinet/ip_var.h> -#include <netinet/icmp_var.h> - -/* - * ICMP routines: error generation, receive packet processing, and - * routines to turnaround packets back to the originator, and - * host table maintenance routines. - */ - - struct icmpstat icmpstat; -SYSCTL_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RD, - &icmpstat, icmpstat, ""); - -static int icmpmaskrepl = 0; -SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW, - &icmpmaskrepl, 0, ""); - -static int icmpbmcastecho = 1; -SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, &icmpbmcastecho, - 0, ""); - -/* #define ICMPPRINTFS 1 */ -#ifdef ICMPPRINTFS -int icmpprintfs = 0; -#endif - -static void icmp_reflect __P((struct mbuf *)); -static void icmp_send __P((struct mbuf *, struct mbuf *)); -static int ip_next_mtu __P((int, int)); - -extern struct protosw inetsw[]; - -/* - * Generate an error packet of type error - * in response to bad packet ip. - */ -void -icmp_error(n, type, code, dest, destifp) - struct mbuf *n; - int type, code; - n_long dest; - struct ifnet *destifp; -{ - register struct ip *oip = mtod(n, struct ip *), *nip; - register unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2; - register struct icmp *icp; - register struct mbuf *m; - unsigned icmplen; - -#ifdef ICMPPRINTFS - if (icmpprintfs) - printf("icmp_error(%p, %x, %d)\n", oip, type, code); -#endif - if (type != ICMP_REDIRECT) - icmpstat.icps_error++; - /* - * Don't send error if not the first fragment of message. - * Don't error if the old packet protocol was ICMP - * error message, only known informational types. - */ - if (oip->ip_off &~ (IP_MF|IP_DF)) - goto freeit; - if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && - n->m_len >= oiplen + ICMP_MINLEN && - !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) { - icmpstat.icps_oldicmp++; - goto freeit; - } - /* Don't send error in response to a multicast or broadcast packet */ - if (n->m_flags & (M_BCAST|M_MCAST)) - goto freeit; - /* - * First, formulate icmp message - */ - m = m_gethdr(M_DONTWAIT, MT_HEADER); - if (m == NULL) - goto freeit; - icmplen = oiplen + min(8, oip->ip_len); - m->m_len = icmplen + ICMP_MINLEN; - MH_ALIGN(m, m->m_len); - icp = mtod(m, struct icmp *); - if ((u_int)type > ICMP_MAXTYPE) - panic("icmp_error"); - icmpstat.icps_outhist[type]++; - icp->icmp_type = type; - if (type == ICMP_REDIRECT) - icp->icmp_gwaddr.s_addr = dest; - else { - icp->icmp_void = 0; - /* - * The following assignments assume an overlay with the - * zeroed icmp_void field. - */ - if (type == ICMP_PARAMPROB) { - icp->icmp_pptr = code; - code = 0; - } else if (type == ICMP_UNREACH && - code == ICMP_UNREACH_NEEDFRAG && destifp) { - icp->icmp_nextmtu = htons(destifp->if_mtu); - } - } - - icp->icmp_code = code; - bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen); - nip = &icp->icmp_ip; - nip->ip_len = htons((u_short)(nip->ip_len + oiplen)); - - /* - * Now, copy old ip header (without options) - * in front of icmp message. - */ - if (m->m_data - sizeof(struct ip) < m->m_pktdat) - panic("icmp len"); - m->m_data -= sizeof(struct ip); - m->m_len += sizeof(struct ip); - m->m_pkthdr.len = m->m_len; - m->m_pkthdr.rcvif = n->m_pkthdr.rcvif; - nip = mtod(m, struct ip *); - bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip)); - nip->ip_len = m->m_len; - nip->ip_vhl = IP_VHL_BORING; - nip->ip_p = IPPROTO_ICMP; - nip->ip_tos = 0; - icmp_reflect(m); - -freeit: - m_freem(n); -} - -static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET }; -static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET }; -static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET }; - -/* - * Process a received ICMP message. - */ -void -icmp_input(m, hlen) - register struct mbuf *m; - int hlen; -{ - register struct icmp *icp; - register struct ip *ip = mtod(m, struct ip *); - int icmplen = ip->ip_len; - register int i; - struct in_ifaddr *ia; - void (*ctlfunc) __P((int, struct sockaddr *, void *)); - int code; - - /* - * Locate icmp structure in mbuf, and check - * that not corrupted and of at least minimum length. - */ -#ifdef ICMPPRINTFS - if (icmpprintfs) { - char buf[4 * sizeof "123"]; - strcpy(buf, inet_ntoa(ip->ip_src)); - printf("icmp_input from %s to %s, len %d\n", - buf, inet_ntoa(ip->ip_dst), icmplen); - } -#endif - if (icmplen < ICMP_MINLEN) { - icmpstat.icps_tooshort++; - goto freeit; - } - i = hlen + min(icmplen, ICMP_ADVLENMIN); - if (m->m_len < i && (m = m_pullup(m, i)) == 0) { - icmpstat.icps_tooshort++; - return; - } - ip = mtod(m, struct ip *); - m->m_len -= hlen; - m->m_data += hlen; - icp = mtod(m, struct icmp *); - if (in_cksum(m, icmplen)) { - icmpstat.icps_checksum++; - goto freeit; - } - m->m_len += hlen; - m->m_data -= hlen; - -#ifdef ICMPPRINTFS - if (icmpprintfs) - printf("icmp_input, type %d code %d\n", icp->icmp_type, - icp->icmp_code); -#endif - - /* - * Message type specific processing. - */ - if (icp->icmp_type > ICMP_MAXTYPE) - goto raw; - icmpstat.icps_inhist[icp->icmp_type]++; - code = icp->icmp_code; - switch (icp->icmp_type) { - - case ICMP_UNREACH: - switch (code) { - case ICMP_UNREACH_NET: - case ICMP_UNREACH_HOST: - case ICMP_UNREACH_PROTOCOL: - case ICMP_UNREACH_PORT: - case ICMP_UNREACH_SRCFAIL: - code += PRC_UNREACH_NET; - break; - - case ICMP_UNREACH_NEEDFRAG: - code = PRC_MSGSIZE; - break; - - case ICMP_UNREACH_NET_UNKNOWN: - case ICMP_UNREACH_NET_PROHIB: - case ICMP_UNREACH_TOSNET: - code = PRC_UNREACH_NET; - break; - - case ICMP_UNREACH_HOST_UNKNOWN: - case ICMP_UNREACH_ISOLATED: - case ICMP_UNREACH_HOST_PROHIB: - case ICMP_UNREACH_TOSHOST: - code = PRC_UNREACH_HOST; - break; - - case ICMP_UNREACH_FILTER_PROHIB: - case ICMP_UNREACH_HOST_PRECEDENCE: - case ICMP_UNREACH_PRECEDENCE_CUTOFF: - code = PRC_UNREACH_PORT; - break; - - default: - goto badcode; - } - goto deliver; - - case ICMP_TIMXCEED: - if (code > 1) - goto badcode; - code += PRC_TIMXCEED_INTRANS; - goto deliver; - - case ICMP_PARAMPROB: - if (code > 1) - goto badcode; - code = PRC_PARAMPROB; - goto deliver; - - case ICMP_SOURCEQUENCH: - if (code) - goto badcode; - code = PRC_QUENCH; - deliver: - /* - * Problem with datagram; advise higher level routines. - */ - if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || - IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) { - icmpstat.icps_badlen++; - goto freeit; - } - NTOHS(icp->icmp_ip.ip_len); - /* Discard ICMP's in response to multicast packets */ - if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr))) - goto badcode; -#ifdef ICMPPRINTFS - if (icmpprintfs) - printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); -#endif - icmpsrc.sin_addr = icp->icmp_ip.ip_dst; -#if 1 - /* - * MTU discovery: - * If we got a needfrag and there is a host route to the - * original destination, and the MTU is not locked, then - * set the MTU in the route to the suggested new value - * (if given) and then notify as usual. The ULPs will - * notice that the MTU has changed and adapt accordingly. - * If no new MTU was suggested, then we guess a new one - * less than the current value. If the new MTU is - * unreasonably small (arbitrarily set at 296), then - * we reset the MTU to the interface value and enable the - * lock bit, indicating that we are no longer doing MTU - * discovery. - */ - if (code == PRC_MSGSIZE) { - struct rtentry *rt; - int mtu; - - rt = rtalloc1((struct sockaddr *)&icmpsrc, 0, - RTF_CLONING | RTF_PRCLONING); - if (rt && (rt->rt_flags & RTF_HOST) - && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { - mtu = ntohs(icp->icmp_nextmtu); - if (!mtu) - mtu = ip_next_mtu(rt->rt_rmx.rmx_mtu, - 1); -#ifdef DEBUG_MTUDISC - printf("MTU for %s reduced to %d\n", - inet_ntoa(icmpsrc.sin_addr), mtu); -#endif - if (mtu < 296) { - /* rt->rt_rmx.rmx_mtu = - rt->rt_ifp->if_mtu; */ - rt->rt_rmx.rmx_locks |= RTV_MTU; - } else if (rt->rt_rmx.rmx_mtu > mtu) { - rt->rt_rmx.rmx_mtu = mtu; - } - } - if (rt) - RTFREE(rt); - } - -#endif - ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; - if (ctlfunc) - (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, - (void *)&icp->icmp_ip); - break; - - badcode: - icmpstat.icps_badcode++; - break; - - case ICMP_ECHO: - if (!icmpbmcastecho - && (m->m_flags & (M_MCAST | M_BCAST)) != 0 - && IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { - icmpstat.icps_bmcastecho++; - break; - } - icp->icmp_type = ICMP_ECHOREPLY; - goto reflect; - - case ICMP_TSTAMP: - if (!icmpbmcastecho - && (m->m_flags & (M_MCAST | M_BCAST)) != 0 - && IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { - icmpstat.icps_bmcasttstamp++; - break; - } - if (icmplen < ICMP_TSLEN) { - icmpstat.icps_badlen++; - break; - } - icp->icmp_type = ICMP_TSTAMPREPLY; - icp->icmp_rtime = iptime(); - icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ - goto reflect; - - case ICMP_MASKREQ: -#define satosin(sa) ((struct sockaddr_in *)(sa)) - if (icmpmaskrepl == 0) - break; - /* - * We are not able to respond with all ones broadcast - * unless we receive it over a point-to-point interface. - */ - if (icmplen < ICMP_MASKLEN) - break; - switch (ip->ip_dst.s_addr) { - - case INADDR_BROADCAST: - case INADDR_ANY: - icmpdst.sin_addr = ip->ip_src; - break; - - default: - icmpdst.sin_addr = ip->ip_dst; - } - ia = (struct in_ifaddr *)ifaof_ifpforaddr( - (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif); - if (ia == 0) - break; - if (ia->ia_ifp == 0) - break; - icp->icmp_type = ICMP_MASKREPLY; - icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr; - if (ip->ip_src.s_addr == 0) { - if (ia->ia_ifp->if_flags & IFF_BROADCAST) - ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr; - else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) - ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr; - } -reflect: - ip->ip_len += hlen; /* since ip_input deducts this */ - icmpstat.icps_reflect++; - icmpstat.icps_outhist[icp->icmp_type]++; - icmp_reflect(m); - return; - - case ICMP_REDIRECT: - if (code > 3) - goto badcode; - if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || - IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) { - icmpstat.icps_badlen++; - break; - } - /* - * Short circuit routing redirects to force - * immediate change in the kernel's routing - * tables. The message is also handed to anyone - * listening on a raw socket (e.g. the routing - * daemon for use in updating its tables). - */ - icmpgw.sin_addr = ip->ip_src; - icmpdst.sin_addr = icp->icmp_gwaddr; -#ifdef ICMPPRINTFS - if (icmpprintfs) { - char buf[4 * sizeof "123"]; - strcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst)); - - printf("redirect dst %s to %s\n", - buf, inet_ntoa(icp->icmp_gwaddr)); - } -#endif - icmpsrc.sin_addr = icp->icmp_ip.ip_dst; - rtredirect((struct sockaddr *)&icmpsrc, - (struct sockaddr *)&icmpdst, - (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, - (struct sockaddr *)&icmpgw, (struct rtentry **)0); - pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc); - break; - - /* - * No kernel processing for the following; - * just fall through to send to raw listener. - */ - case ICMP_ECHOREPLY: - case ICMP_ROUTERADVERT: - case ICMP_ROUTERSOLICIT: - case ICMP_TSTAMPREPLY: - case ICMP_IREQREPLY: - case ICMP_MASKREPLY: - default: - break; - } - -raw: - rip_input(m, hlen); - return; - -freeit: - m_freem(m); -} - -/* - * Reflect the ip packet back to the source - */ -static void -icmp_reflect(m) - struct mbuf *m; -{ - register struct ip *ip = mtod(m, struct ip *); - register struct in_ifaddr *ia; - struct in_addr t; - struct mbuf *opts = 0; - int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip); - - if (!in_canforward(ip->ip_src) && - ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) != - (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) { - m_freem(m); /* Bad return address */ - goto done; /* Ip_output() will check for broadcast */ - } - t = ip->ip_dst; - ip->ip_dst = ip->ip_src; - /* - * If the incoming packet was addressed directly to us, - * use dst as the src for the reply. Otherwise (broadcast - * or anonymous), use the address which corresponds - * to the incoming interface. - */ - for (ia = in_ifaddr; ia; ia = ia->ia_next) { - if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) - break; - if (ia->ia_ifp && (ia->ia_ifp->if_flags & IFF_BROADCAST) && - t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr) - break; - } - icmpdst.sin_addr = t; - if ((ia == (struct in_ifaddr *)0) && m->m_pkthdr.rcvif) - ia = (struct in_ifaddr *)ifaof_ifpforaddr( - (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif); - /* - * The following happens if the packet was not addressed to us, - * and was received on an interface with no IP address. - */ - if (ia == (struct in_ifaddr *)0) - ia = in_ifaddr; - t = IA_SIN(ia)->sin_addr; - ip->ip_src = t; - ip->ip_ttl = MAXTTL; - - if (optlen > 0) { - register u_char *cp; - int opt, cnt; - u_int len; - - /* - * Retrieve any source routing from the incoming packet; - * add on any record-route or timestamp options. - */ - cp = (u_char *) (ip + 1); - if ((opts = ip_srcroute()) == 0 && - (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { - opts->m_len = sizeof(struct in_addr); - mtod(opts, struct in_addr *)->s_addr = 0; - } - if (opts) { -#ifdef ICMPPRINTFS - if (icmpprintfs) - printf("icmp_reflect optlen %d rt %d => ", - optlen, opts->m_len); -#endif - for (cnt = optlen; cnt > 0; cnt -= len, cp += len) { - opt = cp[IPOPT_OPTVAL]; - if (opt == IPOPT_EOL) - break; - if (opt == IPOPT_NOP) - len = 1; - else { - len = cp[IPOPT_OLEN]; - if (len <= 0 || len > cnt) - break; - } - /* - * Should check for overflow, but it "can't happen" - */ - if (opt == IPOPT_RR || opt == IPOPT_TS || - opt == IPOPT_SECURITY) { - bcopy((caddr_t)cp, - mtod(opts, caddr_t) + opts->m_len, len); - opts->m_len += len; - } - } - /* Terminate & pad, if necessary */ - cnt = opts->m_len % 4; - if (cnt) { - for (; cnt < 4; cnt++) { - *(mtod(opts, caddr_t) + opts->m_len) = - IPOPT_EOL; - opts->m_len++; - } - } -#ifdef ICMPPRINTFS - if (icmpprintfs) - printf("%d\n", opts->m_len); -#endif - } - /* - * Now strip out original options by copying rest of first - * mbuf's data back, and adjust the IP length. - */ - ip->ip_len -= optlen; - ip->ip_vhl = IP_VHL_BORING; - m->m_len -= optlen; - if (m->m_flags & M_PKTHDR) - m->m_pkthdr.len -= optlen; - optlen += sizeof(struct ip); - bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1), - (unsigned)(m->m_len - sizeof(struct ip))); - } - m->m_flags &= ~(M_BCAST|M_MCAST); - icmp_send(m, opts); -done: - if (opts) - (void)m_free(opts); -} - -/* - * Send an icmp packet back to the ip level, - * after supplying a checksum. - */ -static void -icmp_send(m, opts) - register struct mbuf *m; - struct mbuf *opts; -{ - register struct ip *ip = mtod(m, struct ip *); - register int hlen; - register struct icmp *icp; - struct route ro; - - hlen = IP_VHL_HL(ip->ip_vhl) << 2; - m->m_data += hlen; - m->m_len -= hlen; - icp = mtod(m, struct icmp *); - icp->icmp_cksum = 0; - icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen); - m->m_data -= hlen; - m->m_len += hlen; -#ifdef ICMPPRINTFS - if (icmpprintfs) { - char buf[4 * sizeof "123"]; - strcpy(buf, inet_ntoa(ip->ip_dst)); - printf("icmp_send dst %s src %s\n", - buf, inet_ntoa(ip->ip_src)); - } -#endif - bzero(&ro, sizeof ro); - (void) ip_output(m, opts, &ro, 0, NULL); - if (ro.ro_rt) - RTFREE(ro.ro_rt); -} - -n_time -iptime() -{ - struct timeval atv; - u_long t; - - microtime(&atv); - t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000; - return (htonl(t)); -} - -#if 1 -/* - * Return the next larger or smaller MTU plateau (table from RFC 1191) - * given current value MTU. If DIR is less than zero, a larger plateau - * is returned; otherwise, a smaller value is returned. - */ -static int -ip_next_mtu(mtu, dir) - int mtu; - int dir; -{ - static int mtutab[] = { - 65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296, - 68, 0 - }; - int i; - - for (i = 0; i < (sizeof mtutab) / (sizeof mtutab[0]); i++) { - if (mtu >= mtutab[i]) - break; - } - - if (dir < 0) { - if (i == 0) { - return 0; - } else { - return mtutab[i - 1]; - } - } else { - if (mtutab[i] == 0) { - return 0; - } else if(mtu > mtutab[i]) { - return mtutab[i]; - } else { - return mtutab[i + 1]; - } - } -} -#endif diff --git a/c/src/exec/libnetworking/netinet/ip_icmp.h b/c/src/exec/libnetworking/netinet/ip_icmp.h deleted file mode 100644 index 9d07a682de..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_icmp.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_IP_ICMP_H_ -#define _NETINET_IP_ICMP_H_ - -/* - * Interface Control Message Protocol Definitions. - * Per RFC 792, September 1981. - */ - -/* - * Internal of an ICMP Router Advertisement - */ -struct icmp_ra_addr { - u_int32_t ira_addr; - u_int32_t ira_preference; -}; - -/* - * Structure of an icmp header. - */ -struct icmp { - u_char icmp_type; /* type of message, see below */ - u_char icmp_code; /* type sub code */ - u_short icmp_cksum; /* ones complement cksum of struct */ - union { - u_char ih_pptr; /* ICMP_PARAMPROB */ - struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ - struct ih_idseq { - n_short icd_id; - n_short icd_seq; - } ih_idseq; - int ih_void; - - /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ - struct ih_pmtu { - n_short ipm_void; - n_short ipm_nextmtu; - } ih_pmtu; - - struct ih_rtradv { - u_char irt_num_addrs; - u_char irt_wpa; - u_int16_t irt_lifetime; - } ih_rtradv; - } icmp_hun; -#define icmp_pptr icmp_hun.ih_pptr -#define icmp_gwaddr icmp_hun.ih_gwaddr -#define icmp_id icmp_hun.ih_idseq.icd_id -#define icmp_seq icmp_hun.ih_idseq.icd_seq -#define icmp_void icmp_hun.ih_void -#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void -#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu -#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs -#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa -#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime - union { - struct id_ts { - n_time its_otime; - n_time its_rtime; - n_time its_ttime; - } id_ts; - struct id_ip { - struct ip idi_ip; - /* options and then 64 bits of data */ - } id_ip; - struct icmp_ra_addr id_radv; - u_long id_mask; - char id_data[1]; - } icmp_dun; -#define icmp_otime icmp_dun.id_ts.its_otime -#define icmp_rtime icmp_dun.id_ts.its_rtime -#define icmp_ttime icmp_dun.id_ts.its_ttime -#define icmp_ip icmp_dun.id_ip.idi_ip -#define icmp_radv icmp_dun.id_radv -#define icmp_mask icmp_dun.id_mask -#define icmp_data icmp_dun.id_data -}; - -/* - * Lower bounds on packet lengths for various types. - * For the error advice packets must first insure that the - * packet is large enough to contain the returned ip header. - * Only then can we do the check to see if 64 bits of packet - * data have been returned, since we need to check the returned - * ip header length. - */ -#define ICMP_MINLEN 8 /* abs minimum */ -#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ -#define ICMP_MASKLEN 12 /* address mask */ -#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ -#ifndef _IP_VHL -#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) - /* N.B.: must separately check that ip_hl >= 5 */ -#else -#define ICMP_ADVLEN(p) (8 + (IP_VHL_HL((p)->icmp_ip.ip_vhl) << 2) + 8) - /* N.B.: must separately check that header length >= 5 */ -#endif - -/* - * Definition of type and code field values. - */ -#define ICMP_ECHOREPLY 0 /* echo reply */ -#define ICMP_UNREACH 3 /* dest unreachable, codes: */ -#define ICMP_UNREACH_NET 0 /* bad net */ -#define ICMP_UNREACH_HOST 1 /* bad host */ -#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ -#define ICMP_UNREACH_PORT 3 /* bad port */ -#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ -#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ -#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ -#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ -#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ -#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ -#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ -#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ -#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ -#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */ -#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */ -#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */ -#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ -#define ICMP_REDIRECT 5 /* shorter route, codes: */ -#define ICMP_REDIRECT_NET 0 /* for network */ -#define ICMP_REDIRECT_HOST 1 /* for host */ -#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ -#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ -#define ICMP_ECHO 8 /* echo service */ -#define ICMP_ROUTERADVERT 9 /* router advertisement */ -#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ -#define ICMP_TIMXCEED 11 /* time exceeded, code: */ -#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ -#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ -#define ICMP_PARAMPROB 12 /* ip header bad */ -#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ -#define ICMP_TSTAMP 13 /* timestamp request */ -#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ -#define ICMP_IREQ 15 /* information request */ -#define ICMP_IREQREPLY 16 /* information reply */ -#define ICMP_MASKREQ 17 /* address mask request */ -#define ICMP_MASKREPLY 18 /* address mask reply */ - -#define ICMP_MAXTYPE 18 - -#define ICMP_INFOTYPE(type) \ - ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ - (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ - (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ - (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ - (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) - -#ifdef KERNEL -void icmp_error __P((struct mbuf *, int, int, n_long, struct ifnet *)); -void icmp_input __P((struct mbuf *, int)); -#endif - -#endif diff --git a/c/src/exec/libnetworking/netinet/ip_input.c b/c/src/exec/libnetworking/netinet/ip_input.c deleted file mode 100644 index 238e10cf6b..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_input.c +++ /dev/null @@ -1,1488 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 - * $Id$ - * $ANA: ip_input.c,v 1.5 1996/09/18 14:34:59 wollman Exp $ - */ - -#define _IP_VHL - -#include "opt_ipfw.h" - -#include <stddef.h> - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/domain.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/errno.h> -#include <sys/time.h> -#include <sys/kernel.h> -#include <sys/syslog.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/if_dl.h> -#include <net/route.h> -#include <net/netisr.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/ip_var.h> -#include <netinet/ip_icmp.h> -#include <machine/in_cksum.h> - -#include <sys/socketvar.h> - -#ifdef IPFIREWALL -#include <netinet/ip_fw.h> -#endif - -int rsvp_on = 0; -static int ip_rsvp_on; -struct socket *ip_rsvpd; - -static int ipforwarding = 0; -SYSCTL_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW, - &ipforwarding, 0, ""); - -static int ipsendredirects = 1; /* XXX */ -SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_RW, - &ipsendredirects, 0, ""); - -int ip_defttl = IPDEFTTL; -SYSCTL_INT(_net_inet_ip, IPCTL_DEFTTL, ttl, CTLFLAG_RW, - &ip_defttl, 0, ""); - -static int ip_dosourceroute = 0; -SYSCTL_INT(_net_inet_ip, IPCTL_SOURCEROUTE, sourceroute, CTLFLAG_RW, - &ip_dosourceroute, 0, ""); - -static int ip_acceptsourceroute = 0; -SYSCTL_INT(_net_inet_ip, IPCTL_ACCEPTSOURCEROUTE, accept_sourceroute, - CTLFLAG_RW, &ip_acceptsourceroute, 0, ""); -#ifdef DIAGNOSTIC -static int ipprintfs = 0; -#endif - -extern struct domain inetdomain; -extern struct protosw inetsw[]; -u_char ip_protox[IPPROTO_MAX]; -static int ipqmaxlen = IFQ_MAXLEN; -struct in_ifaddr *in_ifaddr; /* first inet address */ -struct ifqueue ipintrq; -SYSCTL_INT(_net_inet_ip, IPCTL_INTRQMAXLEN, intr_queue_maxlen, CTLFLAG_RD, - &ipintrq.ifq_maxlen, 0, ""); -SYSCTL_INT(_net_inet_ip, IPCTL_INTRQDROPS, intr_queue_drops, CTLFLAG_RD, - &ipintrq.ifq_drops, 0, ""); - -struct ipstat ipstat; - -/* Packet reassembly stuff */ -#define IPREASS_NHASH_LOG2 6 -#define IPREASS_NHASH (1 << IPREASS_NHASH_LOG2) -#define IPREASS_HMASK (IPREASS_NHASH - 1) -#define IPREASS_HASH(x,y) \ - (((((x) & 0xF) | ((((x) >> 8) & 0xF) << 4)) ^ (y)) & IPREASS_HMASK) - -static struct ipq ipq[IPREASS_NHASH]; -static int nipq = 0; /* total # of reass queues */ -static int maxnipq; - -#ifdef IPCTL_DEFMTU -SYSCTL_INT(_net_inet_ip, IPCTL_DEFMTU, mtu, CTLFLAG_RW, - &ip_mtu, 0, ""); -#endif - -#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1 -#undef COMPAT_IPFW -#define COMPAT_IPFW 1 -#else -#undef COMPAT_IPFW -#endif - -#ifdef COMPAT_IPFW -/* Firewall hooks */ -ip_fw_chk_t *ip_fw_chk_ptr; -ip_fw_ctl_t *ip_fw_ctl_ptr; - -/* IP Network Address Translation (NAT) hooks */ -ip_nat_t *ip_nat_ptr; -ip_nat_ctl_t *ip_nat_ctl_ptr; -#endif - -/* - * We need to save the IP options in case a protocol wants to respond - * to an incoming packet over the same route if the packet got here - * using IP source routing. This allows connection establishment and - * maintenance when the remote end is on a network that is not known - * to us. - */ -static int ip_nhops = 0; -static struct ip_srcrt { - struct in_addr dst; /* final destination */ - char nop; /* one NOP to align */ - char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */ - struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)]; -} ip_srcrt; - -#ifdef IPDIVERT -/* - * Shared variable between ip_input() and ip_reass() to communicate - * about which packets, once assembled from fragments, get diverted, - * and to which port. - */ -static u_short frag_divert_port; -#endif - -static void save_rte __P((u_char *, struct in_addr)); -static void ip_deq __P((struct ipasfrag *)); -static int ip_dooptions __P((struct mbuf *)); -static void ip_enq __P((struct ipasfrag *, struct ipasfrag *)); -static void ip_forward __P((struct mbuf *, int)); -static void ip_freef __P((struct ipq *)); -static struct ip * - ip_reass __P((struct ipasfrag *, struct ipq *, struct ipq *)); -static struct in_ifaddr * - ip_rtaddr __P((struct in_addr)); -void ipintr __P((void)); -/* - * IP initialization: fill in IP protocol switch table. - * All protocols not implemented in kernel go to raw IP protocol handler. - */ -void -ip_init() -{ - register struct protosw *pr; - register int i; - - pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); - if (pr == 0) - panic("ip_init"); - for (i = 0; i < IPPROTO_MAX; i++) - ip_protox[i] = pr - inetsw; - for (pr = inetdomain.dom_protosw; - pr < inetdomain.dom_protoswNPROTOSW; pr++) - if (pr->pr_domain->dom_family == PF_INET && - pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) - ip_protox[pr->pr_protocol] = pr - inetsw; - - for (i = 0; i < IPREASS_NHASH; i++) - ipq[i].next = ipq[i].prev = &ipq[i]; - - maxnipq = nmbclusters/4; - - ip_id = rtems_bsdnet_seconds_since_boot() & 0xffff; - ipintrq.ifq_maxlen = ipqmaxlen; -#ifdef IPFIREWALL - ip_fw_init(); -#endif -#ifdef IPNAT - ip_nat_init(); -#endif - -} - -static struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; -static struct route ipforward_rt; - -/* - * Ip input routine. Checksum and byte swap header. If fragmented - * try to reassemble. Process options. Pass to next level. - */ -void -ip_input(struct mbuf *m) -{ - struct ip *ip; - struct ipq *fp; - struct in_ifaddr *ia; - int i, hlen; - u_short sum; - -#ifdef DIAGNOSTIC - if ((m->m_flags & M_PKTHDR) == 0) - panic("ip_input no HDR"); -#endif - /* - * If no IP addresses have been set yet but the interfaces - * are receiving, can't do anything with incoming packets yet. - */ - if (in_ifaddr == NULL) - goto bad; - ipstat.ips_total++; - - if (m->m_pkthdr.len < sizeof(struct ip)) - goto tooshort; - -#if defined(DIAGNOSTIC) && defined(ORIGINAL_FREEBSD_CODE) - if (m->m_len < sizeof(struct ip)) - panic("ipintr mbuf too short"); -#endif - - if (m->m_len < sizeof (struct ip) && - (m = m_pullup(m, sizeof (struct ip))) == 0) { - ipstat.ips_toosmall++; - return; - } - ip = mtod(m, struct ip *); - - if (IP_VHL_V(ip->ip_vhl) != IPVERSION) { - ipstat.ips_badvers++; - goto bad; - } - - hlen = IP_VHL_HL(ip->ip_vhl) << 2; - if (hlen < sizeof(struct ip)) { /* minimum header length */ - ipstat.ips_badhlen++; - goto bad; - } - if (hlen > m->m_len) { - if ((m = m_pullup(m, hlen)) == 0) { - ipstat.ips_badhlen++; - return; - } - ip = mtod(m, struct ip *); - } - if (hlen == sizeof(struct ip)) { - sum = in_cksum_hdr(ip); - } else { - sum = in_cksum(m, hlen); - } - if (sum) { - ipstat.ips_badsum++; - goto bad; - } - - /* - * Convert fields to host representation. - */ - NTOHS(ip->ip_len); - if (ip->ip_len < hlen) { - ipstat.ips_badlen++; - goto bad; - } - NTOHS(ip->ip_id); - NTOHS(ip->ip_off); - - /* - * Check that the amount of data in the buffers - * is as at least much as the IP header would have us expect. - * Trim mbufs if longer than we expect. - * Drop packet if shorter than we expect. - */ - if (m->m_pkthdr.len < ip->ip_len) { -tooshort: - ipstat.ips_tooshort++; - goto bad; - } - if (m->m_pkthdr.len > ip->ip_len) { - if (m->m_len == m->m_pkthdr.len) { - m->m_len = ip->ip_len; - m->m_pkthdr.len = ip->ip_len; - } else - m_adj(m, ip->ip_len - m->m_pkthdr.len); - } - /* - * IpHack's section. - * Right now when no processing on packet has done - * and it is still fresh out of network we do our black - * deals with it. - * - Firewall: deny/allow/divert - * - Xlate: translate packet's addr/port (NAT). - * - Wrap: fake packet's addr/port <unimpl.> - * - Encapsulate: put it in another IP and send out. <unimp.> - */ - -#ifdef COMPAT_IPFW - if (ip_fw_chk_ptr) { -#ifdef IPDIVERT - u_short port; - - port = (*ip_fw_chk_ptr)(&ip, hlen, NULL, ip_divert_ignore, &m); - ip_divert_ignore = 0; - if (port) { /* Divert packet */ - frag_divert_port = port; - goto ours; - } -#else - /* If ipfw says divert, we have to just drop packet */ - if ((*ip_fw_chk_ptr)(&ip, hlen, NULL, 0, &m)) { - m_freem(m); - m = NULL; - } -#endif - if (!m) - return; - } - - if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, m->m_pkthdr.rcvif, IP_NAT_IN)) - return; -#endif - - /* - * Process options and, if not destined for us, - * ship it on. ip_dooptions returns 1 when an - * error was detected (causing an icmp message - * to be sent and the original packet to be freed). - */ - ip_nhops = 0; /* for source routed packets */ - if (hlen > sizeof (struct ip) && ip_dooptions(m)) - return; - - /* greedy RSVP, snatches any PATH packet of the RSVP protocol and no - * matter if it is destined to another node, or whether it is - * a multicast one, RSVP wants it! and prevents it from being forwarded - * anywhere else. Also checks if the rsvp daemon is running before - * grabbing the packet. - */ - if (rsvp_on && ip->ip_p==IPPROTO_RSVP) - goto ours; - - /* - * Check our list of addresses, to see if the packet is for us. - */ - for (ia = in_ifaddr; ia; ia = ia->ia_next) { -#define satosin(sa) ((struct sockaddr_in *)(sa)) - - if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) - goto ours; -#ifdef BOOTP_COMPAT - if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY) - goto ours; -#endif - if (ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) { - if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == - ip->ip_dst.s_addr) - goto ours; - if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr) - goto ours; - } - } - if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { - struct in_multi *inm; - if (ip_mrouter) { - /* - * If we are acting as a multicast router, all - * incoming multicast packets are passed to the - * kernel-level multicast forwarding function. - * The packet is returned (relatively) intact; if - * ip_mforward() returns a non-zero value, the packet - * must be discarded, else it may be accepted below. - * - * (The IP ident field is put in the same byte order - * as expected when ip_mforward() is called from - * ip_output().) - */ - ip->ip_id = htons(ip->ip_id); - if (ip_mforward(ip, m->m_pkthdr.rcvif, m, 0) != 0) { - ipstat.ips_cantforward++; - m_freem(m); - return; - } - ip->ip_id = ntohs(ip->ip_id); - - /* - * The process-level routing demon needs to receive - * all multicast IGMP packets, whether or not this - * host belongs to their destination groups. - */ - if (ip->ip_p == IPPROTO_IGMP) - goto ours; - ipstat.ips_forward++; - } - /* - * See if we belong to the destination multicast group on the - * arrival interface. - */ - IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm); - if (inm == NULL) { - ipstat.ips_cantforward++; - m_freem(m); - return; - } - goto ours; - } - if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST) - goto ours; - if (ip->ip_dst.s_addr == INADDR_ANY) - goto ours; - - /* - * Not for us; forward if possible and desirable. - */ - if (ipforwarding == 0) { - ipstat.ips_cantforward++; - m_freem(m); - } else - ip_forward(m, 0); - return; - -ours: - - /* - * If offset or IP_MF are set, must reassemble. - * Otherwise, nothing need be done. - * (We could look in the reassembly queue to see - * if the packet was previously fragmented, - * but it's not worth the time; just let them time out.) - */ - if (ip->ip_off &~ (IP_DF | IP_RF)) { - if (m->m_flags & M_EXT) { /* XXX */ - if ((m = m_pullup(m, sizeof (struct ip))) == 0) { - ipstat.ips_toosmall++; -#ifdef IPDIVERT - frag_divert_port = 0; -#endif - return; - } - ip = mtod(m, struct ip *); - } - sum = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id); - /* - * Look for queue of fragments - * of this datagram. - */ - for (fp = ipq[sum].next; fp != &ipq[sum]; fp = fp->next) - if (ip->ip_id == fp->ipq_id && - ip->ip_src.s_addr == fp->ipq_src.s_addr && - ip->ip_dst.s_addr == fp->ipq_dst.s_addr && - ip->ip_p == fp->ipq_p) - goto found; - - fp = 0; - - /* check if there's a place for the new queue */ - if (nipq > maxnipq) { - /* - * drop something from the tail of the current queue - * before proceeding further - */ - if (ipq[sum].prev == &ipq[sum]) { /* gak */ - for (i = 0; i < IPREASS_NHASH; i++) { - if (ipq[i].prev != &ipq[i]) { - ip_freef(ipq[i].prev); - break; - } - } - } else - ip_freef(ipq[sum].prev); - } -found: - /* - * Adjust ip_len to not reflect header, - * set ip_mff if more fragments are expected, - * convert offset of this to bytes. - */ - ip->ip_len -= hlen; - ((struct ipasfrag *)ip)->ipf_mff &= ~1; - if (ip->ip_off & IP_MF) - ((struct ipasfrag *)ip)->ipf_mff |= 1; - ip->ip_off <<= 3; - - /* - * If datagram marked as having more fragments - * or if this is not the first fragment, - * attempt reassembly; if it succeeds, proceed. - */ - if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { - ipstat.ips_fragments++; - ip = ip_reass((struct ipasfrag *)ip, fp, &ipq[sum]); - if (ip == 0) - return; - ipstat.ips_reassembled++; - m = dtom(ip); -#ifdef IPDIVERT - if (frag_divert_port) { - ip->ip_len += hlen; - HTONS(ip->ip_len); - HTONS(ip->ip_off); - HTONS(ip->ip_id); - ip->ip_sum = 0; - ip->ip_sum = in_cksum_hdr(ip); - NTOHS(ip->ip_id); - NTOHS(ip->ip_off); - NTOHS(ip->ip_len); - ip->ip_len -= hlen; - } -#endif - } else - if (fp) - ip_freef(fp); - } else - ip->ip_len -= hlen; - -#ifdef IPDIVERT - /* - * Divert reassembled packets to the divert protocol if required - */ - if (frag_divert_port) { - ipstat.ips_delivered++; - ip_divert_port = frag_divert_port; - frag_divert_port = 0; - (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, hlen); - return; - } - - /* Don't let packets divert themselves */ - if (ip->ip_p == IPPROTO_DIVERT) { - ipstat.ips_noproto++; - goto bad; - } -#endif - - /* - * Switch out to protocol's input routine. - */ - ipstat.ips_delivered++; - (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen); - return; -bad: - m_freem(m); -} - -/* - * IP software interrupt routine - to go away sometime soon - */ -void -ipintr(void) -{ - int s; - struct mbuf *m; - - while(1) { - s = splimp(); - IF_DEQUEUE(&ipintrq, m); - splx(s); - if (m == 0) - return; - ip_input(m); - } -} - -NETISR_SET(NETISR_IP, ipintr); - -/* - * Take incoming datagram fragment and try to - * reassemble it into whole datagram. If a chain for - * reassembly of this datagram already exists, then it - * is given as fp; otherwise have to make a chain. - */ -static struct ip * -ip_reass(ip, fp, where) - register struct ipasfrag *ip; - register struct ipq *fp; - struct ipq *where; -{ - register struct mbuf *m = dtom(ip); - register struct ipasfrag *q; - struct mbuf *t; - int hlen = ip->ip_hl << 2; - int i, next; - - /* - * Presence of header sizes in mbufs - * would confuse code below. - */ - m->m_data += hlen; - m->m_len -= hlen; - - /* - * If first fragment to arrive, create a reassembly queue. - */ - if (fp == 0) { - if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL) - goto dropfrag; - fp = mtod(t, struct ipq *); - insque(fp, where); - nipq++; - fp->ipq_ttl = IPFRAGTTL; - fp->ipq_p = ip->ip_p; - fp->ipq_id = ip->ip_id; - fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp; - fp->ipq_src = ((struct ip *)ip)->ip_src; - fp->ipq_dst = ((struct ip *)ip)->ip_dst; -#ifdef IPDIVERT - fp->ipq_divert = 0; -#endif - q = (struct ipasfrag *)fp; - goto insert; - } - - /* - * Find a segment which begins after this one does. - */ - for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) - if (q->ip_off > ip->ip_off) - break; - - /* - * If there is a preceding segment, it may provide some of - * our data already. If so, drop the data from the incoming - * segment. If it provides all of our data, drop us. - */ - if (q->ipf_prev != (struct ipasfrag *)fp) { - i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off; - if (i > 0) { - if (i >= ip->ip_len) - goto dropfrag; - m_adj(dtom(ip), i); - ip->ip_off += i; - ip->ip_len -= i; - } - } - - /* - * While we overlap succeeding segments trim them or, - * if they are completely covered, dequeue them. - */ - while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { - struct mbuf *m0; - - i = (ip->ip_off + ip->ip_len) - q->ip_off; - if (i < q->ip_len) { - q->ip_len -= i; - q->ip_off += i; - m_adj(dtom(q), i); - break; - } - m0 = dtom(q); - q = q->ipf_next; - ip_deq(q->ipf_prev); - m_freem(m0); - } - -insert: - -#ifdef IPDIVERT - /* - * Any fragment diverting causes the whole packet to divert - */ - if (frag_divert_port != 0) - fp->ipq_divert = frag_divert_port; - frag_divert_port = 0; -#endif - - /* - * Stick new segment in its place; - * check for complete reassembly. - */ - ip_enq(ip, q->ipf_prev); - next = 0; - for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) { - if (q->ip_off != next) - return (0); - next += q->ip_len; - } - if (q->ipf_prev->ipf_mff & 1) - return (0); - - /* - * Reassembly is complete. Make sure the packet is a sane size. - */ - if (next + (IP_VHL_HL(((struct ip *)fp->ipq_next)->ip_vhl) << 2) - > IP_MAXPACKET) { - ipstat.ips_toolong++; - ip_freef(fp); - return (0); - } - - /* - * Concatenate fragments. - */ - q = fp->ipq_next; - m = dtom(q); - t = m->m_next; - m->m_next = 0; - m_cat(m, t); - q = q->ipf_next; - while (q != (struct ipasfrag *)fp) { - t = dtom(q); - q = q->ipf_next; - m_cat(m, t); - } - -#ifdef IPDIVERT - /* - * Record divert port for packet, if any - */ - frag_divert_port = fp->ipq_divert; -#endif - - /* - * Create header for new ip packet by - * modifying header of first packet; - * dequeue and discard fragment reassembly header. - * Make header visible. - */ - ip = fp->ipq_next; - ip->ip_len = next; - ip->ipf_mff &= ~1; - ((struct ip *)ip)->ip_src = fp->ipq_src; - ((struct ip *)ip)->ip_dst = fp->ipq_dst; - remque(fp); - nipq--; - (void) m_free(dtom(fp)); - m = dtom(ip); - m->m_len += (ip->ip_hl << 2); - m->m_data -= (ip->ip_hl << 2); - /* some debugging cruft by sklower, below, will go away soon */ - if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */ - register int plen = 0; - for (t = m; m; m = m->m_next) - plen += m->m_len; - t->m_pkthdr.len = plen; - } - return ((struct ip *)ip); - -dropfrag: - ipstat.ips_fragdropped++; - m_freem(m); - return (0); -} - -/* - * Free a fragment reassembly header and all - * associated datagrams. - */ -static void -ip_freef(fp) - struct ipq *fp; -{ - register struct ipasfrag *q, *p; - - for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) { - p = q->ipf_next; - ip_deq(q); - m_freem(dtom(q)); - } - remque(fp); - (void) m_free(dtom(fp)); - nipq--; -} - -/* - * Put an ip fragment on a reassembly chain. - * Like insque, but pointers in middle of structure. - */ -static void -ip_enq(p, prev) - register struct ipasfrag *p, *prev; -{ - - p->ipf_prev = prev; - p->ipf_next = prev->ipf_next; - prev->ipf_next->ipf_prev = p; - prev->ipf_next = p; -} - -/* - * To ip_enq as remque is to insque. - */ -static void -ip_deq(p) - register struct ipasfrag *p; -{ - - p->ipf_prev->ipf_next = p->ipf_next; - p->ipf_next->ipf_prev = p->ipf_prev; -} - -/* - * IP timer processing; - * if a timer expires on a reassembly - * queue, discard it. - */ -void -ip_slowtimo() -{ - register struct ipq *fp; - int s = splnet(); - int i; - - for (i = 0; i < IPREASS_NHASH; i++) { - fp = ipq[i].next; - if (fp == 0) - continue; - while (fp != &ipq[i]) { - --fp->ipq_ttl; - fp = fp->next; - if (fp->prev->ipq_ttl == 0) { - ipstat.ips_fragtimeout++; - ip_freef(fp->prev); - } - } - } - splx(s); -} - -/* - * Drain off all datagram fragments. - */ -void -ip_drain() -{ - int i; - - for (i = 0; i < IPREASS_NHASH; i++) { - while (ipq[i].next != &ipq[i]) { - ipstat.ips_fragdropped++; - ip_freef(ipq[i].next); - } - } - in_rtqdrain(); -} - -/* - * Do option processing on a datagram, - * possibly discarding it if bad options are encountered, - * or forwarding it if source-routed. - * Returns 1 if packet has been forwarded/freed, - * 0 if the packet should be processed further. - */ -static int -ip_dooptions(m) - struct mbuf *m; -{ - register struct ip *ip = mtod(m, struct ip *); - register u_char *cp; - register struct ip_timestamp *ipt; - register struct in_ifaddr *ia; - int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; - struct in_addr *sin, dst; - n_time ntime; - - dst = ip->ip_dst; - cp = (u_char *)(ip + 1); - cnt = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip); - for (; cnt > 0; cnt -= optlen, cp += optlen) { - opt = cp[IPOPT_OPTVAL]; - if (opt == IPOPT_EOL) - break; - if (opt == IPOPT_NOP) - optlen = 1; - else { - optlen = cp[IPOPT_OLEN]; - if (optlen <= 0 || optlen > cnt) { - code = &cp[IPOPT_OLEN] - (u_char *)ip; - goto bad; - } - } - switch (opt) { - - default: - break; - - /* - * Source routing with record. - * Find interface with current destination address. - * If none on this machine then drop if strictly routed, - * or do nothing if loosely routed. - * Record interface address and bring up next address - * component. If strictly routed make sure next - * address is on directly accessible net. - */ - case IPOPT_LSRR: - case IPOPT_SSRR: - if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { - code = &cp[IPOPT_OFFSET] - (u_char *)ip; - goto bad; - } - ipaddr.sin_addr = ip->ip_dst; - ia = (struct in_ifaddr *) - ifa_ifwithaddr((struct sockaddr *)&ipaddr); - if (ia == 0) { - if (opt == IPOPT_SSRR) { - type = ICMP_UNREACH; - code = ICMP_UNREACH_SRCFAIL; - goto bad; - } - if (!ip_dosourceroute) - goto nosourcerouting; - /* - * Loose routing, and not at next destination - * yet; nothing to do except forward. - */ - break; - } - off--; /* 0 origin */ - if (off > optlen - sizeof(struct in_addr)) { - /* - * End of source route. Should be for us. - */ - if (!ip_acceptsourceroute) - goto nosourcerouting; - save_rte(cp, ip->ip_src); - break; - } - - if (!ip_dosourceroute) { - char buf[4*sizeof "123"]; - -nosourcerouting: - strcpy(buf, inet_ntoa(ip->ip_dst)); - log(LOG_WARNING, - "attempted source route from %s to %s\n", - inet_ntoa(ip->ip_src), buf); - type = ICMP_UNREACH; - code = ICMP_UNREACH_SRCFAIL; - goto bad; - } - - /* - * locate outgoing interface - */ - (void)memcpy(&ipaddr.sin_addr, cp + off, - sizeof(ipaddr.sin_addr)); - - if (opt == IPOPT_SSRR) { -#define INA struct in_ifaddr * -#define SA struct sockaddr * - if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) - ia = (INA)ifa_ifwithnet((SA)&ipaddr); - } else - ia = ip_rtaddr(ipaddr.sin_addr); - if (ia == 0) { - type = ICMP_UNREACH; - code = ICMP_UNREACH_SRCFAIL; - goto bad; - } - ip->ip_dst = ipaddr.sin_addr; - (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr), - sizeof(struct in_addr)); - cp[IPOPT_OFFSET] += sizeof(struct in_addr); - /* - * Let ip_intr's mcast routing check handle mcast pkts - */ - forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr)); - break; - - case IPOPT_RR: - if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { - code = &cp[IPOPT_OFFSET] - (u_char *)ip; - goto bad; - } - /* - * If no space remains, ignore. - */ - off--; /* 0 origin */ - if (off > optlen - sizeof(struct in_addr)) - break; - (void)memcpy(&ipaddr.sin_addr, &ip->ip_dst, - sizeof(ipaddr.sin_addr)); - /* - * locate outgoing interface; if we're the destination, - * use the incoming interface (should be same). - */ - if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && - (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { - type = ICMP_UNREACH; - code = ICMP_UNREACH_HOST; - goto bad; - } - (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr), - sizeof(struct in_addr)); - cp[IPOPT_OFFSET] += sizeof(struct in_addr); - break; - - case IPOPT_TS: - code = cp - (u_char *)ip; - ipt = (struct ip_timestamp *)cp; - if (ipt->ipt_len < 5) - goto bad; - if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) { - if (++ipt->ipt_oflw == 0) - goto bad; - break; - } - sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); - switch (ipt->ipt_flg) { - - case IPOPT_TS_TSONLY: - break; - - case IPOPT_TS_TSANDADDR: - if (ipt->ipt_ptr + sizeof(n_time) + - sizeof(struct in_addr) > ipt->ipt_len) - goto bad; - ipaddr.sin_addr = dst; - ia = (INA)ifaof_ifpforaddr((SA)&ipaddr, - m->m_pkthdr.rcvif); - if (ia == 0) - continue; - (void)memcpy(sin, &IA_SIN(ia)->sin_addr, - sizeof(struct in_addr)); - ipt->ipt_ptr += sizeof(struct in_addr); - break; - - case IPOPT_TS_PRESPEC: - if (ipt->ipt_ptr + sizeof(n_time) + - sizeof(struct in_addr) > ipt->ipt_len) - goto bad; - (void)memcpy(&ipaddr.sin_addr, sin, - sizeof(struct in_addr)); - if (ifa_ifwithaddr((SA)&ipaddr) == 0) - continue; - ipt->ipt_ptr += sizeof(struct in_addr); - break; - - default: - goto bad; - } - ntime = iptime(); - (void)memcpy(cp + ipt->ipt_ptr - 1, &ntime, - sizeof(n_time)); - ipt->ipt_ptr += sizeof(n_time); - } - } - if (forward && ipforwarding) { - ip_forward(m, 1); - return (1); - } - return (0); -bad: - ip->ip_len -= IP_VHL_HL(ip->ip_vhl) << 2; /* XXX icmp_error adds in hdr length */ - icmp_error(m, type, code, 0, 0); - ipstat.ips_badoptions++; - return (1); -} - -/* - * Given address of next destination (final or next hop), - * return internet address info of interface to be used to get there. - */ -static struct in_ifaddr * -ip_rtaddr(dst) - struct in_addr dst; -{ - register struct sockaddr_in *sin; - - sin = (struct sockaddr_in *) &ipforward_rt.ro_dst; - - if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) { - if (ipforward_rt.ro_rt) { - RTFREE(ipforward_rt.ro_rt); - ipforward_rt.ro_rt = 0; - } - sin->sin_family = AF_INET; - sin->sin_len = sizeof(*sin); - sin->sin_addr = dst; - - rtalloc_ign(&ipforward_rt, RTF_PRCLONING); - } - if (ipforward_rt.ro_rt == 0) - return ((struct in_ifaddr *)0); - return ((struct in_ifaddr *) ipforward_rt.ro_rt->rt_ifa); -} - -/* - * Save incoming source route for use in replies, - * to be picked up later by ip_srcroute if the receiver is interested. - */ -void -save_rte(option, dst) - u_char *option; - struct in_addr dst; -{ - unsigned olen; - - olen = option[IPOPT_OLEN]; -#ifdef DIAGNOSTIC - if (ipprintfs) - printf("save_rte: olen %d\n", olen); -#endif - if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst))) - return; - bcopy(option, ip_srcrt.srcopt, olen); - ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); - ip_srcrt.dst = dst; -} - -/* - * Retrieve incoming source route for use in replies, - * in the same form used by setsockopt. - * The first hop is placed before the options, will be removed later. - */ -struct mbuf * -ip_srcroute() -{ - register struct in_addr *p, *q; - register struct mbuf *m; - - if (ip_nhops == 0) - return ((struct mbuf *)0); - m = m_get(M_DONTWAIT, MT_SOOPTS); - if (m == 0) - return ((struct mbuf *)0); - -#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) - - /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */ - m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) + - OPTSIZ; -#ifdef DIAGNOSTIC - if (ipprintfs) - printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len); -#endif - - /* - * First save first hop for return route - */ - p = &ip_srcrt.route[ip_nhops - 1]; - *(mtod(m, struct in_addr *)) = *p--; -#ifdef DIAGNOSTIC - if (ipprintfs) - printf(" hops %lx", ntohl(mtod(m, struct in_addr *)->s_addr)); -#endif - - /* - * Copy option fields and padding (nop) to mbuf. - */ - ip_srcrt.nop = IPOPT_NOP; - ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; - (void)memcpy(mtod(m, caddr_t) + sizeof(struct in_addr), - &ip_srcrt.nop, OPTSIZ); - q = (struct in_addr *)(mtod(m, caddr_t) + - sizeof(struct in_addr) + OPTSIZ); -#undef OPTSIZ - /* - * Record return path as an IP source route, - * reversing the path (pointers are now aligned). - */ - while (p >= ip_srcrt.route) { -#ifdef DIAGNOSTIC - if (ipprintfs) - printf(" %lx", ntohl(q->s_addr)); -#endif - *q++ = *p--; - } - /* - * Last hop goes to final destination. - */ - *q = ip_srcrt.dst; -#ifdef DIAGNOSTIC - if (ipprintfs) - printf(" %lx\n", ntohl(q->s_addr)); -#endif - return (m); -} - -/* - * Strip out IP options, at higher - * level protocol in the kernel. - * Second argument is buffer to which options - * will be moved, and return value is their length. - * XXX should be deleted; last arg currently ignored. - */ -void -ip_stripoptions(m, mopt) - register struct mbuf *m; - struct mbuf *mopt; -{ - register int i; - struct ip *ip = mtod(m, struct ip *); - register caddr_t opts; - int olen; - - olen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip); - opts = (caddr_t)(ip + 1); - i = m->m_len - (sizeof (struct ip) + olen); - bcopy(opts + olen, opts, (unsigned)i); - m->m_len -= olen; - if (m->m_flags & M_PKTHDR) - m->m_pkthdr.len -= olen; - ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2); -} - -u_char inetctlerrmap[PRC_NCMDS] = { - 0, 0, 0, 0, - 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, - EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, - EMSGSIZE, EHOSTUNREACH, 0, 0, - 0, 0, 0, 0, - ENOPROTOOPT -}; - -/* - * Forward a packet. If some error occurs return the sender - * an icmp packet. Note we can't always generate a meaningful - * icmp message because icmp doesn't have a large enough repertoire - * of codes and types. - * - * If not forwarding, just drop the packet. This could be confusing - * if ipforwarding was zero but some routing protocol was advancing - * us as a gateway to somewhere. However, we must let the routing - * protocol deal with that. - * - * The srcrt parameter indicates whether the packet is being forwarded - * via a source route. - */ -static void -ip_forward(m, srcrt) - struct mbuf *m; - int srcrt; -{ - register struct ip *ip = mtod(m, struct ip *); - register struct sockaddr_in *sin; - register struct rtentry *rt; - int error, type = 0, code = 0; - struct mbuf *mcopy; - n_long dest; - struct ifnet *destifp; - - dest = 0; -#ifdef DIAGNOSTIC - if (ipprintfs) - printf("forward: src %lx dst %lx ttl %x\n", - ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_ttl); -#endif - - - if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) { - ipstat.ips_cantforward++; - m_freem(m); - return; - } - HTONS(ip->ip_id); - if (ip->ip_ttl <= IPTTLDEC) { - icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); - return; - } - ip->ip_ttl -= IPTTLDEC; - - sin = (struct sockaddr_in *)&ipforward_rt.ro_dst; - if ((rt = ipforward_rt.ro_rt) == 0 || - ip->ip_dst.s_addr != sin->sin_addr.s_addr) { - if (ipforward_rt.ro_rt) { - RTFREE(ipforward_rt.ro_rt); - ipforward_rt.ro_rt = 0; - } - sin->sin_family = AF_INET; - sin->sin_len = sizeof(*sin); - sin->sin_addr = ip->ip_dst; - - rtalloc_ign(&ipforward_rt, RTF_PRCLONING); - if (ipforward_rt.ro_rt == 0) { - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); - return; - } - rt = ipforward_rt.ro_rt; - } - - /* - * Save at most 64 bytes of the packet in case - * we need to generate an ICMP message to the src. - */ - mcopy = m_copy(m, 0, imin((int)ip->ip_len, 64)); - - /* - * If forwarding packet using same interface that it came in on, - * perhaps should send a redirect to sender to shortcut a hop. - * Only send redirect if source is sending directly to us, - * and if packet was not source routed (or has any options). - * Also, don't send redirect if forwarding using a default route - * or a route modified by a redirect. - */ -#define satosin(sa) ((struct sockaddr_in *)(sa)) - if (rt->rt_ifp == m->m_pkthdr.rcvif && - (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && - satosin(rt_key(rt))->sin_addr.s_addr != 0 && - ipsendredirects && !srcrt) { -#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa)) - u_long src = ntohl(ip->ip_src.s_addr); - - if (RTA(rt) && - (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) { - if (rt->rt_flags & RTF_GATEWAY) - dest = satosin(rt->rt_gateway)->sin_addr.s_addr; - else - dest = ip->ip_dst.s_addr; - /* Router requirements says to only send host redirects */ - type = ICMP_REDIRECT; - code = ICMP_REDIRECT_HOST; -#ifdef DIAGNOSTIC - if (ipprintfs) - printf("redirect (%d) to %lx\n", code, (u_long)dest); -#endif - } - } - - error = ip_output(m, (struct mbuf *)0, &ipforward_rt, - IP_FORWARDING, 0); - if (error) - ipstat.ips_cantforward++; - else { - ipstat.ips_forward++; - if (type) - ipstat.ips_redirectsent++; - else { - if (mcopy) - m_freem(mcopy); - return; - } - } - if (mcopy == NULL) - return; - destifp = NULL; - - switch (error) { - - case 0: /* forwarded, but need redirect */ - /* type, code set above */ - break; - - case ENETUNREACH: /* shouldn't happen, checked above */ - case EHOSTUNREACH: - case ENETDOWN: - case EHOSTDOWN: - default: - type = ICMP_UNREACH; - code = ICMP_UNREACH_HOST; - break; - - case EMSGSIZE: - type = ICMP_UNREACH; - code = ICMP_UNREACH_NEEDFRAG; - if (ipforward_rt.ro_rt) - destifp = ipforward_rt.ro_rt->rt_ifp; - ipstat.ips_cantfrag++; - break; - - case ENOBUFS: - type = ICMP_SOURCEQUENCH; - code = 0; - break; - } - icmp_error(mcopy, type, code, dest, destifp); -} - -void -ip_savecontrol(inp, mp, ip, m) - register struct inpcb *inp; - register struct mbuf **mp; - register struct ip *ip; - register struct mbuf *m; -{ - if (inp->inp_socket->so_options & SO_TIMESTAMP) { - struct timeval tv; - - microtime(&tv); - *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), - SCM_TIMESTAMP, SOL_SOCKET); - if (*mp) - mp = &(*mp)->m_next; - } - if (inp->inp_flags & INP_RECVDSTADDR) { - *mp = sbcreatecontrol((caddr_t) &ip->ip_dst, - sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP); - if (*mp) - mp = &(*mp)->m_next; - } -#ifdef notyet - /* XXX - * Moving these out of udp_input() made them even more broken - * than they already were. - */ - /* options were tossed already */ - if (inp->inp_flags & INP_RECVOPTS) { - *mp = sbcreatecontrol((caddr_t) opts_deleted_above, - sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP); - if (*mp) - mp = &(*mp)->m_next; - } - /* ip_srcroute doesn't do what we want here, need to fix */ - if (inp->inp_flags & INP_RECVRETOPTS) { - *mp = sbcreatecontrol((caddr_t) ip_srcroute(), - sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP); - if (*mp) - mp = &(*mp)->m_next; - } -#endif - if (inp->inp_flags & INP_RECVIF) { - struct sockaddr_dl sdl; - - sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]); - sdl.sdl_family = AF_LINK; - sdl.sdl_index = m->m_pkthdr.rcvif ? - m->m_pkthdr.rcvif->if_index : 0; - sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0; - *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len, - IP_RECVIF, IPPROTO_IP); - if (*mp) - mp = &(*mp)->m_next; - } -} - -int -ip_rsvp_init(struct socket *so) -{ - if (so->so_type != SOCK_RAW || - so->so_proto->pr_protocol != IPPROTO_RSVP) - return EOPNOTSUPP; - - if (ip_rsvpd != NULL) - return EADDRINUSE; - - ip_rsvpd = so; - /* - * This may seem silly, but we need to be sure we don't over-increment - * the RSVP counter, in case something slips up. - */ - if (!ip_rsvp_on) { - ip_rsvp_on = 1; - rsvp_on++; - } - - return 0; -} - -int -ip_rsvp_done(void) -{ - ip_rsvpd = NULL; - /* - * This may seem silly, but we need to be sure we don't over-decrement - * the RSVP counter, in case something slips up. - */ - if (ip_rsvp_on) { - ip_rsvp_on = 0; - rsvp_on--; - } - return 0; -} diff --git a/c/src/exec/libnetworking/netinet/ip_mroute.c b/c/src/exec/libnetworking/netinet/ip_mroute.c deleted file mode 100644 index 662d695dfe..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_mroute.c +++ /dev/null @@ -1,2302 +0,0 @@ -/* - * IP multicast forwarding procedures - * - * Written by David Waitzman, BBN Labs, August 1988. - * Modified by Steve Deering, Stanford, February 1989. - * Modified by Mark J. Steiglitz, Stanford, May, 1991 - * Modified by Van Jacobson, LBL, January 1993 - * Modified by Ajit Thyagarajan, PARC, August 1993 - * Modified by Bill Fenner, PARC, April 1995 - * - * MROUTING Revision: 3.5 - * $Id$ - */ - -#include "opt_mrouting.h" - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/protosw.h> -#include <sys/errno.h> -#include <sys/time.h> -#include <sys/kernel.h> -#include <sys/ioctl.h> -#include <sys/syslog.h> -#include <net/if.h> -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/igmp.h> -#include <netinet/igmp_var.h> -#include <netinet/ip_mroute.h> -#include <netinet/udp.h> - -#ifndef NTOHL -#if BYTE_ORDER != BIG_ENDIAN -#define NTOHL(d) ((d) = ntohl((d))) -#define NTOHS(d) ((d) = ntohs((u_short)(d))) -#define HTONL(d) ((d) = htonl((d))) -#define HTONS(d) ((d) = htons((u_short)(d))) -#else -#define NTOHL(d) -#define NTOHS(d) -#define HTONL(d) -#define HTONS(d) -#endif -#endif - -#ifndef MROUTING -extern u_long _ip_mcast_src __P((int vifi)); -extern int _ip_mforward __P((struct ip *ip, struct ifnet *ifp, - struct mbuf *m, struct ip_moptions *imo)); -extern int _ip_mrouter_done __P((void)); -extern int _ip_mrouter_get __P((int cmd, struct socket *so, - struct mbuf **m)); -extern int _ip_mrouter_set __P((int cmd, struct socket *so, - struct mbuf *m)); -extern int _mrt_ioctl __P((int req, caddr_t data, struct proc *p)); - -/* - * Dummy routines and globals used when multicast routing is not compiled in. - */ - -struct socket *ip_mrouter = NULL; -/* static u_int ip_mrtproto = 0; */ -/* static struct mrtstat mrtstat; */ -u_int rsvpdebug = 0; - -int -_ip_mrouter_set(cmd, so, m) - int cmd; - struct socket *so; - struct mbuf *m; -{ - return(EOPNOTSUPP); -} - -int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = _ip_mrouter_set; - - -int -_ip_mrouter_get(cmd, so, m) - int cmd; - struct socket *so; - struct mbuf **m; -{ - return(EOPNOTSUPP); -} - -int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = _ip_mrouter_get; - -int -_ip_mrouter_done() -{ - return(0); -} - -int (*ip_mrouter_done)(void) = _ip_mrouter_done; - -int -_ip_mforward(ip, ifp, m, imo) - struct ip *ip; - struct ifnet *ifp; - struct mbuf *m; - struct ip_moptions *imo; -{ - return(0); -} - -int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, - struct ip_moptions *) = _ip_mforward; - -int -_mrt_ioctl(int req, caddr_t data, struct proc *p) -{ - return EOPNOTSUPP; -} - -int (*mrt_ioctl)(int, caddr_t, struct proc *) = _mrt_ioctl; - -void -rsvp_input(m, iphlen) /* XXX must fixup manually */ - struct mbuf *m; - int iphlen; -{ - /* Can still get packets with rsvp_on = 0 if there is a local member - * of the group to which the RSVP packet is addressed. But in this - * case we want to throw the packet away. - */ - if (!rsvp_on) { - m_freem(m); - return; - } - - if (ip_rsvpd != NULL) { - if (rsvpdebug) - printf("rsvp_input: Sending packet up old-style socket\n"); - rip_input(m, iphlen); - return; - } - /* Drop the packet */ - m_freem(m); -} - -void ipip_input(struct mbuf *m, int iphlen) { /* XXX must fixup manually */ - rip_input(m, iphlen); -} - -int (*legal_vif_num)(int) = 0; - -/* - * This should never be called, since IP_MULTICAST_VIF should fail, but - * just in case it does get called, the code a little lower in ip_output - * will assign the packet a local address. - */ -u_long -_ip_mcast_src(int vifi) { return INADDR_ANY; } -u_long (*ip_mcast_src)(int) = _ip_mcast_src; - -int -ip_rsvp_vif_init(so, m) - struct socket *so; - struct mbuf *m; -{ - return(EINVAL); -} - -int -ip_rsvp_vif_done(so, m) - struct socket *so; - struct mbuf *m; -{ - return(EINVAL); -} - -void -ip_rsvp_force_done(so) - struct socket *so; -{ - return; -} - -#else /* MROUTING */ - -#define M_HASCL(m) ((m)->m_flags & M_EXT) - -#define INSIZ sizeof(struct in_addr) -#define same(a1, a2) \ - (bcmp((caddr_t)(a1), (caddr_t)(a2), INSIZ) == 0) - -#define MT_MRTABLE MT_RTABLE /* since nothing else uses it */ - -/* - * Globals. All but ip_mrouter and ip_mrtproto could be static, - * except for netstat or debugging purposes. - */ -#ifndef MROUTE_LKM -struct socket *ip_mrouter = NULL; -struct mrtstat mrtstat; - -int ip_mrtproto = IGMP_DVMRP; /* for netstat only */ -#else /* MROUTE_LKM */ -extern void X_ipip_input __P((struct mbuf *m, int iphlen)); -extern struct mrtstat mrtstat; -static int ip_mrtproto; -#endif - -#define NO_RTE_FOUND 0x1 -#define RTE_FOUND 0x2 - -static struct mbuf *mfctable[MFCTBLSIZ]; -static u_char nexpire[MFCTBLSIZ]; -static struct vif viftable[MAXVIFS]; -static u_int mrtdebug = 0; /* debug level */ -#define DEBUG_MFC 0x02 -#define DEBUG_FORWARD 0x04 -#define DEBUG_EXPIRE 0x08 -#define DEBUG_XMIT 0x10 -static u_int tbfdebug = 0; /* tbf debug level */ -static u_int rsvpdebug = 0; /* rsvp debug level */ - -#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ -#define UPCALL_EXPIRE 6 /* number of timeouts */ - -/* - * Define the token bucket filter structures - * tbftable -> each vif has one of these for storing info - */ - -static struct tbf tbftable[MAXVIFS]; -#define TBF_REPROCESS (hz / 100) /* 100x / second */ - -/* - * 'Interfaces' associated with decapsulator (so we can tell - * packets that went through it from ones that get reflected - * by a broken gateway). These interfaces are never linked into - * the system ifnet list & no routes point to them. I.e., packets - * can't be sent this way. They only exist as a placeholder for - * multicast source verification. - */ -static struct ifnet multicast_decap_if[MAXVIFS]; - -#define ENCAP_TTL 64 -#define ENCAP_PROTO IPPROTO_IPIP /* 4 */ - -/* prototype IP hdr for encapsulated packets */ -static struct ip multicast_encap_iphdr = { -#if BYTE_ORDER == LITTLE_ENDIAN - sizeof(struct ip) >> 2, IPVERSION, -#else - IPVERSION, sizeof(struct ip) >> 2, -#endif - 0, /* tos */ - sizeof(struct ip), /* total length */ - 0, /* id */ - 0, /* frag offset */ - ENCAP_TTL, ENCAP_PROTO, - 0, /* checksum */ -}; - -/* - * Private variables. - */ -static vifi_t numvifs = 0; -static int have_encap_tunnel = 0; - -/* - * one-back cache used by ipip_input to locate a tunnel's vif - * given a datagram's src ip address. - */ -static u_long last_encap_src; -static struct vif *last_encap_vif; - -static u_long X_ip_mcast_src __P((int vifi)); -static int X_ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo)); -static int X_ip_mrouter_done __P((void)); -static int X_ip_mrouter_get __P((int cmd, struct socket *so, struct mbuf **m)); -static int X_ip_mrouter_set __P((int cmd, struct socket *so, struct mbuf *m)); -static int X_legal_vif_num __P((int vif)); -static int X_mrt_ioctl __P((int cmd, caddr_t data)); - -static int get_sg_cnt(struct sioc_sg_req *); -static int get_vif_cnt(struct sioc_vif_req *); -static int ip_mrouter_init(struct socket *, struct mbuf *); -static int add_vif(struct vifctl *); -static int del_vif(vifi_t *); -static int add_mfc(struct mfcctl *); -static int del_mfc(struct mfcctl *); -static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *); -static int get_version(struct mbuf *); -static int get_assert(struct mbuf *); -static int set_assert(int *); -static void expire_upcalls(void *); -static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, - vifi_t); -static void phyint_send(struct ip *, struct vif *, struct mbuf *); -static void encap_send(struct ip *, struct vif *, struct mbuf *); -static void tbf_control(struct vif *, struct mbuf *, struct ip *, u_long); -static void tbf_queue(struct vif *, struct mbuf *); -static void tbf_process_q(struct vif *); -static void tbf_reprocess_q(void *); -static int tbf_dq_sel(struct vif *, struct ip *); -static void tbf_send_packet(struct vif *, struct mbuf *); -static void tbf_update_tokens(struct vif *); -static int priority(struct vif *, struct ip *); -void multiencap_decap(struct mbuf *); - -/* - * whether or not special PIM assert processing is enabled. - */ -static int pim_assert; -/* - * Rate limit for assert notification messages, in usec - */ -#define ASSERT_MSG_TIME 3000000 - -/* - * Hash function for a source, group entry - */ -#define MFCHASH(a, g) MFCHASHMOD(((a) >> 20) ^ ((a) >> 10) ^ (a) ^ \ - ((g) >> 20) ^ ((g) >> 10) ^ (g)) - -/* - * Find a route for a given origin IP address and Multicast group address - * Type of service parameter to be added in the future!!! - */ - -#define MFCFIND(o, g, rt) { \ - register struct mbuf *_mb_rt = mfctable[MFCHASH(o,g)]; \ - register struct mfc *_rt = NULL; \ - rt = NULL; \ - ++mrtstat.mrts_mfc_lookups; \ - while (_mb_rt) { \ - _rt = mtod(_mb_rt, struct mfc *); \ - if ((_rt->mfc_origin.s_addr == o) && \ - (_rt->mfc_mcastgrp.s_addr == g) && \ - (_mb_rt->m_act == NULL)) { \ - rt = _rt; \ - break; \ - } \ - _mb_rt = _mb_rt->m_next; \ - } \ - if (rt == NULL) { \ - ++mrtstat.mrts_mfc_misses; \ - } \ -} - - -/* - * Macros to compute elapsed time efficiently - * Borrowed from Van Jacobson's scheduling code - */ -#define TV_DELTA(a, b, delta) { \ - register int xxs; \ - \ - delta = (a).tv_usec - (b).tv_usec; \ - if ((xxs = (a).tv_sec - (b).tv_sec)) { \ - switch (xxs) { \ - case 2: \ - delta += 1000000; \ - /* fall through */ \ - case 1: \ - delta += 1000000; \ - break; \ - default: \ - delta += (1000000 * xxs); \ - } \ - } \ -} - -#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \ - (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec) - -#ifdef UPCALL_TIMING -u_long upcall_data[51]; -static void collate(struct timeval *); -#endif /* UPCALL_TIMING */ - - -/* - * Handle MRT setsockopt commands to modify the multicast routing tables. - */ -static int -X_ip_mrouter_set(cmd, so, m) - int cmd; - struct socket *so; - struct mbuf *m; -{ - if (cmd != MRT_INIT && so != ip_mrouter) return EACCES; - - switch (cmd) { - case MRT_INIT: return ip_mrouter_init(so, m); - case MRT_DONE: return ip_mrouter_done(); - case MRT_ADD_VIF: return add_vif (mtod(m, struct vifctl *)); - case MRT_DEL_VIF: return del_vif (mtod(m, vifi_t *)); - case MRT_ADD_MFC: return add_mfc (mtod(m, struct mfcctl *)); - case MRT_DEL_MFC: return del_mfc (mtod(m, struct mfcctl *)); - case MRT_ASSERT: return set_assert(mtod(m, int *)); - default: return EOPNOTSUPP; - } -} - -#ifndef MROUTE_LKM -int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = X_ip_mrouter_set; -#endif - -/* - * Handle MRT getsockopt commands - */ -static int -X_ip_mrouter_get(cmd, so, m) - int cmd; - struct socket *so; - struct mbuf **m; -{ - struct mbuf *mb; - - if (so != ip_mrouter) return EACCES; - - *m = mb = m_get(M_WAIT, MT_SOOPTS); - - switch (cmd) { - case MRT_VERSION: return get_version(mb); - case MRT_ASSERT: return get_assert(mb); - default: return EOPNOTSUPP; - } -} - -#ifndef MROUTE_LKM -int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = X_ip_mrouter_get; -#endif - -/* - * Handle ioctl commands to obtain information from the cache - */ -static int -X_mrt_ioctl(cmd, data) - int cmd; - caddr_t data; -{ - int error = 0; - - switch (cmd) { - case (SIOCGETVIFCNT): - return (get_vif_cnt((struct sioc_vif_req *)data)); - break; - case (SIOCGETSGCNT): - return (get_sg_cnt((struct sioc_sg_req *)data)); - break; - default: - return (EINVAL); - break; - } - return error; -} - -#ifndef MROUTE_LKM -int (*mrt_ioctl)(int, caddr_t) = X_mrt_ioctl; -#endif - -/* - * returns the packet, byte, rpf-failure count for the source group provided - */ -static int -get_sg_cnt(req) - register struct sioc_sg_req *req; -{ - register struct mfc *rt; - int s; - - s = splnet(); - MFCFIND(req->src.s_addr, req->grp.s_addr, rt); - splx(s); - if (rt != NULL) { - req->pktcnt = rt->mfc_pkt_cnt; - req->bytecnt = rt->mfc_byte_cnt; - req->wrong_if = rt->mfc_wrong_if; - } else - req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff; - - return 0; -} - -/* - * returns the input and output packet and byte counts on the vif provided - */ -static int -get_vif_cnt(req) - register struct sioc_vif_req *req; -{ - register vifi_t vifi = req->vifi; - - if (vifi >= numvifs) return EINVAL; - - req->icount = viftable[vifi].v_pkt_in; - req->ocount = viftable[vifi].v_pkt_out; - req->ibytes = viftable[vifi].v_bytes_in; - req->obytes = viftable[vifi].v_bytes_out; - - return 0; -} - -/* - * Enable multicast routing - */ -static int -ip_mrouter_init(so, m) - struct socket *so; - struct mbuf *m; -{ - int *v; - - if (mrtdebug) - log(LOG_DEBUG,"ip_mrouter_init: so_type = %d, pr_protocol = %d\n", - so->so_type, so->so_proto->pr_protocol); - - if (so->so_type != SOCK_RAW || - so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP; - - if (!m || (m->m_len != sizeof(int *))) - return ENOPROTOOPT; - - v = mtod(m, int *); - if (*v != 1) - return ENOPROTOOPT; - - if (ip_mrouter != NULL) return EADDRINUSE; - - ip_mrouter = so; - - bzero((caddr_t)mfctable, sizeof(mfctable)); - bzero((caddr_t)nexpire, sizeof(nexpire)); - - pim_assert = 0; - - timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT); - - if (mrtdebug) - log(LOG_DEBUG, "ip_mrouter_init\n"); - - return 0; -} - -/* - * Disable multicast routing - */ -static int -X_ip_mrouter_done() -{ - vifi_t vifi; - int i; - struct ifnet *ifp; - struct ifreq ifr; - struct mbuf *mb_rt; - struct mbuf *m; - struct rtdetq *rte; - int s; - - s = splnet(); - - /* - * For each phyint in use, disable promiscuous reception of all IP - * multicasts. - */ - for (vifi = 0; vifi < numvifs; vifi++) { - if (viftable[vifi].v_lcl_addr.s_addr != 0 && - !(viftable[vifi].v_flags & VIFF_TUNNEL)) { - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr - = INADDR_ANY; - ifp = viftable[vifi].v_ifp; - (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); - } - } - bzero((caddr_t)tbftable, sizeof(tbftable)); - bzero((caddr_t)viftable, sizeof(viftable)); - numvifs = 0; - pim_assert = 0; - - untimeout(expire_upcalls, (caddr_t)NULL); - - /* - * Free all multicast forwarding cache entries. - */ - for (i = 0; i < MFCTBLSIZ; i++) { - mb_rt = mfctable[i]; - while (mb_rt) { - if (mb_rt->m_act != NULL) { - while (mb_rt->m_act) { - m = mb_rt->m_act; - mb_rt->m_act = m->m_act; - rte = mtod(m, struct rtdetq *); - m_freem(rte->m); - m_free(m); - } - } - mb_rt = m_free(mb_rt); - } - } - - bzero((caddr_t)mfctable, sizeof(mfctable)); - - /* - * Reset de-encapsulation cache - */ - last_encap_src = 0; - last_encap_vif = NULL; - have_encap_tunnel = 0; - - ip_mrouter = NULL; - - splx(s); - - if (mrtdebug) - log(LOG_DEBUG, "ip_mrouter_done\n"); - - return 0; -} - -#ifndef MROUTE_LKM -int (*ip_mrouter_done)(void) = X_ip_mrouter_done; -#endif - -static int -get_version(mb) - struct mbuf *mb; -{ - int *v; - - v = mtod(mb, int *); - - *v = 0x0305; /* XXX !!!! */ - mb->m_len = sizeof(int); - - return 0; -} - -/* - * Set PIM assert processing global - */ -static int -set_assert(i) - int *i; -{ - if ((*i != 1) && (*i != 0)) - return EINVAL; - - pim_assert = *i; - - return 0; -} - -/* - * Get PIM assert processing global - */ -static int -get_assert(m) - struct mbuf *m; -{ - int *i; - - i = mtod(m, int *); - - *i = pim_assert; - - return 0; -} - -/* - * Add a vif to the vif table - */ -static int -add_vif(vifcp) - register struct vifctl *vifcp; -{ - register struct vif *vifp = viftable + vifcp->vifc_vifi; - static struct sockaddr_in sin = {sizeof sin, AF_INET}; - struct ifaddr *ifa; - struct ifnet *ifp; - struct ifreq ifr; - int error, s; - struct tbf *v_tbf = tbftable + vifcp->vifc_vifi; - - if (vifcp->vifc_vifi >= MAXVIFS) return EINVAL; - if (vifp->v_lcl_addr.s_addr != 0) return EADDRINUSE; - - /* Find the interface with an address in AF_INET family */ - sin.sin_addr = vifcp->vifc_lcl_addr; - ifa = ifa_ifwithaddr((struct sockaddr *)&sin); - if (ifa == 0) return EADDRNOTAVAIL; - ifp = ifa->ifa_ifp; - - if (vifcp->vifc_flags & VIFF_TUNNEL) { - if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) { - /* - * An encapsulating tunnel is wanted. Tell ipip_input() to - * start paying attention to encapsulated packets. - */ - if (have_encap_tunnel == 0) { - have_encap_tunnel = 1; - for (s = 0; s < MAXVIFS; ++s) { - multicast_decap_if[s].if_name = "mdecap"; - multicast_decap_if[s].if_unit = s; - } - } - /* - * Set interface to fake encapsulator interface - */ - ifp = &multicast_decap_if[vifcp->vifc_vifi]; - /* - * Prepare cached route entry - */ - bzero(&vifp->v_route, sizeof(vifp->v_route)); - } else { - log(LOG_ERR, "source routed tunnels not supported\n"); - return EOPNOTSUPP; - } - } else { - /* Make sure the interface supports multicast */ - if ((ifp->if_flags & IFF_MULTICAST) == 0) - return EOPNOTSUPP; - - /* Enable promiscuous reception of all IP multicasts from the if */ - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; - s = splnet(); - error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); - splx(s); - if (error) - return error; - } - - s = splnet(); - /* define parameters for the tbf structure */ - vifp->v_tbf = v_tbf; - GET_TIME(vifp->v_tbf->tbf_last_pkt_t); - vifp->v_tbf->tbf_n_tok = 0; - vifp->v_tbf->tbf_q_len = 0; - vifp->v_tbf->tbf_max_q_len = MAXQSIZE; - vifp->v_tbf->tbf_q = vifp->v_tbf->tbf_t = NULL; - - vifp->v_flags = vifcp->vifc_flags; - vifp->v_threshold = vifcp->vifc_threshold; - vifp->v_lcl_addr = vifcp->vifc_lcl_addr; - vifp->v_rmt_addr = vifcp->vifc_rmt_addr; - vifp->v_ifp = ifp; - /* scaling up here allows division by 1024 in critical code */ - vifp->v_rate_limit= vifcp->vifc_rate_limit * 1024 / 1000; - vifp->v_rsvp_on = 0; - vifp->v_rsvpd = NULL; - /* initialize per vif pkt counters */ - vifp->v_pkt_in = 0; - vifp->v_pkt_out = 0; - vifp->v_bytes_in = 0; - vifp->v_bytes_out = 0; - splx(s); - - /* Adjust numvifs up if the vifi is higher than numvifs */ - if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1; - - if (mrtdebug) - log(LOG_DEBUG, "add_vif #%d, lcladdr %x, %s %x, thresh %x, rate %d\n", - vifcp->vifc_vifi, - ntohl(vifcp->vifc_lcl_addr.s_addr), - (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask", - ntohl(vifcp->vifc_rmt_addr.s_addr), - vifcp->vifc_threshold, - vifcp->vifc_rate_limit); - - return 0; -} - -/* - * Delete a vif from the vif table - */ -static int -del_vif(vifip) - vifi_t *vifip; -{ - register struct vif *vifp = viftable + *vifip; - register vifi_t vifi; - register struct mbuf *m; - struct ifnet *ifp; - struct ifreq ifr; - int s; - - if (*vifip >= numvifs) return EINVAL; - if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL; - - s = splnet(); - - if (!(vifp->v_flags & VIFF_TUNNEL)) { - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; - ifp = vifp->v_ifp; - (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); - } - - if (vifp == last_encap_vif) { - last_encap_vif = 0; - last_encap_src = 0; - } - - /* - * Free packets queued at the interface - */ - while (vifp->v_tbf->tbf_q) { - m = vifp->v_tbf->tbf_q; - vifp->v_tbf->tbf_q = m->m_act; - m_freem(m); - } - - bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf))); - bzero((caddr_t)vifp, sizeof (*vifp)); - - /* Adjust numvifs down */ - for (vifi = numvifs; vifi > 0; vifi--) - if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break; - numvifs = vifi; - - splx(s); - - if (mrtdebug) - log(LOG_DEBUG, "del_vif %d, numvifs %d\n", *vifip, numvifs); - - return 0; -} - -/* - * Add an mfc entry - */ -static int -add_mfc(mfccp) - struct mfcctl *mfccp; -{ - struct mfc *rt; - register struct mbuf *mb_rt; - u_long hash; - struct mbuf *mb_ntry; - struct rtdetq *rte; - register u_short nstl; - int s; - int i; - - MFCFIND(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr, rt); - - /* If an entry already exists, just update the fields */ - if (rt) { - if (mrtdebug & DEBUG_MFC) - log(LOG_DEBUG,"add_mfc update o %x g %x p %x\n", - ntohl(mfccp->mfcc_origin.s_addr), - ntohl(mfccp->mfcc_mcastgrp.s_addr), - mfccp->mfcc_parent); - - s = splnet(); - rt->mfc_parent = mfccp->mfcc_parent; - for (i = 0; i < numvifs; i++) - rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; - splx(s); - return 0; - } - - /* - * Find the entry for which the upcall was made and update - */ - s = splnet(); - hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr); - for (mb_rt = mfctable[hash], nstl = 0; mb_rt; mb_rt = mb_rt->m_next) { - - rt = mtod(mb_rt, struct mfc *); - if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && - (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) && - (mb_rt->m_act != NULL)) { - - if (nstl++) - log(LOG_ERR, "add_mfc %s o %x g %x p %x dbx %x\n", - "multiple kernel entries", - ntohl(mfccp->mfcc_origin.s_addr), - ntohl(mfccp->mfcc_mcastgrp.s_addr), - mfccp->mfcc_parent, mb_rt->m_act); - - if (mrtdebug & DEBUG_MFC) - log(LOG_DEBUG,"add_mfc o %x g %x p %x dbg %x\n", - ntohl(mfccp->mfcc_origin.s_addr), - ntohl(mfccp->mfcc_mcastgrp.s_addr), - mfccp->mfcc_parent, mb_rt->m_act); - - rt->mfc_origin = mfccp->mfcc_origin; - rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; - rt->mfc_parent = mfccp->mfcc_parent; - for (i = 0; i < numvifs; i++) - rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; - /* initialize pkt counters per src-grp */ - rt->mfc_pkt_cnt = 0; - rt->mfc_byte_cnt = 0; - rt->mfc_wrong_if = 0; - rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; - - rt->mfc_expire = 0; /* Don't clean this guy up */ - nexpire[hash]--; - - /* free packets Qed at the end of this entry */ - while (mb_rt->m_act) { - mb_ntry = mb_rt->m_act; - rte = mtod(mb_ntry, struct rtdetq *); -/* #ifdef RSVP_ISI */ - ip_mdq(rte->m, rte->ifp, rt, -1); -/* #endif */ - mb_rt->m_act = mb_ntry->m_act; - m_freem(rte->m); -#ifdef UPCALL_TIMING - collate(&(rte->t)); -#endif /* UPCALL_TIMING */ - m_free(mb_ntry); - } - } - } - - /* - * It is possible that an entry is being inserted without an upcall - */ - if (nstl == 0) { - if (mrtdebug & DEBUG_MFC) - log(LOG_DEBUG,"add_mfc no upcall h %d o %x g %x p %x\n", - hash, ntohl(mfccp->mfcc_origin.s_addr), - ntohl(mfccp->mfcc_mcastgrp.s_addr), - mfccp->mfcc_parent); - - for (mb_rt = mfctable[hash]; mb_rt; mb_rt = mb_rt->m_next) { - - rt = mtod(mb_rt, struct mfc *); - if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && - (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) { - - rt->mfc_origin = mfccp->mfcc_origin; - rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; - rt->mfc_parent = mfccp->mfcc_parent; - for (i = 0; i < numvifs; i++) - rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; - /* initialize pkt counters per src-grp */ - rt->mfc_pkt_cnt = 0; - rt->mfc_byte_cnt = 0; - rt->mfc_wrong_if = 0; - rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; - if (rt->mfc_expire) - nexpire[hash]--; - rt->mfc_expire = 0; - } - } - if (mb_rt == NULL) { - /* no upcall, so make a new entry */ - MGET(mb_rt, M_DONTWAIT, MT_MRTABLE); - if (mb_rt == NULL) { - splx(s); - return ENOBUFS; - } - - rt = mtod(mb_rt, struct mfc *); - - /* insert new entry at head of hash chain */ - rt->mfc_origin = mfccp->mfcc_origin; - rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; - rt->mfc_parent = mfccp->mfcc_parent; - for (i = 0; i < numvifs; i++) - rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; - /* initialize pkt counters per src-grp */ - rt->mfc_pkt_cnt = 0; - rt->mfc_byte_cnt = 0; - rt->mfc_wrong_if = 0; - rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; - rt->mfc_expire = 0; - - /* link into table */ - mb_rt->m_next = mfctable[hash]; - mfctable[hash] = mb_rt; - mb_rt->m_act = NULL; - } - } - splx(s); - return 0; -} - -#ifdef UPCALL_TIMING -/* - * collect delay statistics on the upcalls - */ -static void collate(t) -register struct timeval *t; -{ - register u_long d; - register struct timeval tp; - register u_long delta; - - GET_TIME(tp); - - if (TV_LT(*t, tp)) - { - TV_DELTA(tp, *t, delta); - - d = delta >> 10; - if (d > 50) - d = 50; - - ++upcall_data[d]; - } -} -#endif /* UPCALL_TIMING */ - -/* - * Delete an mfc entry - */ -static int -del_mfc(mfccp) - struct mfcctl *mfccp; -{ - struct in_addr origin; - struct in_addr mcastgrp; - struct mfc *rt; - struct mbuf *mb_rt; - struct mbuf **nptr; - u_long hash; - int s; - - origin = mfccp->mfcc_origin; - mcastgrp = mfccp->mfcc_mcastgrp; - hash = MFCHASH(origin.s_addr, mcastgrp.s_addr); - - if (mrtdebug & DEBUG_MFC) - log(LOG_DEBUG,"del_mfc orig %x mcastgrp %x\n", - ntohl(origin.s_addr), ntohl(mcastgrp.s_addr)); - - s = splnet(); - - nptr = &mfctable[hash]; - while ((mb_rt = *nptr) != NULL) { - rt = mtod(mb_rt, struct mfc *); - if (origin.s_addr == rt->mfc_origin.s_addr && - mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr && - mb_rt->m_act == NULL) - break; - - nptr = &mb_rt->m_next; - } - if (mb_rt == NULL) { - splx(s); - return EADDRNOTAVAIL; - } - - MFREE(mb_rt, *nptr); - - splx(s); - - return 0; -} - -/* - * Send a message to mrouted on the multicast routing socket - */ -static int -socket_send(s, mm, src) - struct socket *s; - struct mbuf *mm; - struct sockaddr_in *src; -{ - if (s) { - if (sbappendaddr(&s->so_rcv, - (struct sockaddr *)src, - mm, (struct mbuf *)0) != 0) { - sorwakeup(s); - return 0; - } - } - m_freem(mm); - return -1; -} - -/* - * IP multicast forwarding function. This function assumes that the packet - * pointed to by "ip" has arrived on (or is about to be sent to) the interface - * pointed to by "ifp", and the packet is to be relayed to other networks - * that have members of the packet's destination IP multicast group. - * - * The packet is returned unscathed to the caller, unless it is - * erroneous, in which case a non-zero return value tells the caller to - * discard it. - */ - -#define IP_HDR_LEN 20 /* # bytes of fixed IP header (excluding options) */ -#define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */ - -static int -X_ip_mforward(ip, ifp, m, imo) - register struct ip *ip; - struct ifnet *ifp; - struct mbuf *m; - struct ip_moptions *imo; -{ - register struct mfc *rt; - register u_char *ipoptions; - static struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET }; - static int srctun = 0; - register struct mbuf *mm; - int s; - vifi_t vifi; - struct vif *vifp; - - if (mrtdebug & DEBUG_FORWARD) - log(LOG_DEBUG, "ip_mforward: src %x, dst %x, ifp %x\n", - ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), ifp); - - if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 || - (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) { - /* - * Packet arrived via a physical interface or - * an encapsulated tunnel. - */ - } else { - /* - * Packet arrived through a source-route tunnel. - * Source-route tunnels are no longer supported. - */ - if ((srctun++ % 1000) == 0) - log(LOG_ERR, "ip_mforward: received source-routed packet from %x\n", - ntohl(ip->ip_src.s_addr)); - - return 1; - } - - if ((imo) && ((vifi = imo->imo_multicast_vif) < numvifs)) { - if (ip->ip_ttl < 255) - ip->ip_ttl++; /* compensate for -1 in *_send routines */ - if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { - vifp = viftable + vifi; - printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s%d)\n", - ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), vifi, - (vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "", - vifp->v_ifp->if_name, vifp->v_ifp->if_unit); - } - return (ip_mdq(m, ifp, NULL, vifi)); - } - if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { - printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n", - ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr)); - if(!imo) - printf("In fact, no options were specified at all\n"); - } - - /* - * Don't forward a packet with time-to-live of zero or one, - * or a packet destined to a local-only group. - */ - if (ip->ip_ttl <= 1 || - ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP) - return 0; - - /* - * Determine forwarding vifs from the forwarding cache table - */ - s = splnet(); - MFCFIND(ip->ip_src.s_addr, ip->ip_dst.s_addr, rt); - - /* Entry exists, so forward if necessary */ - if (rt != NULL) { - splx(s); - return (ip_mdq(m, ifp, rt, -1)); - } else { - /* - * If we don't have a route for packet's origin, - * Make a copy of the packet & - * send message to routing daemon - */ - - register struct mbuf *mb_rt; - register struct mbuf *mb_ntry; - register struct mbuf *mb0; - register struct rtdetq *rte; - register struct mbuf *rte_m; - register u_long hash; - register int npkts; - int hlen = ip->ip_hl << 2; -#ifdef UPCALL_TIMING - struct timeval tp; - - GET_TIME(tp); -#endif - - mrtstat.mrts_no_route++; - if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)) - log(LOG_DEBUG, "ip_mforward: no rte s %x g %x\n", - ntohl(ip->ip_src.s_addr), - ntohl(ip->ip_dst.s_addr)); - - /* - * Allocate mbufs early so that we don't do extra work if we are - * just going to fail anyway. Make sure to pullup the header so - * that other people can't step on it. - */ - MGET(mb_ntry, M_DONTWAIT, MT_DATA); - if (mb_ntry == NULL) { - splx(s); - return ENOBUFS; - } - mb0 = m_copy(m, 0, M_COPYALL); - if (mb0 && (M_HASCL(mb0) || mb0->m_len < hlen)) - mb0 = m_pullup(mb0, hlen); - if (mb0 == NULL) { - m_free(mb_ntry); - splx(s); - return ENOBUFS; - } - - /* is there an upcall waiting for this packet? */ - hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr); - for (mb_rt = mfctable[hash]; mb_rt; mb_rt = mb_rt->m_next) { - rt = mtod(mb_rt, struct mfc *); - if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) && - (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) && - (mb_rt->m_act != NULL)) - break; - } - - if (mb_rt == NULL) { - int i; - struct igmpmsg *im; - - /* no upcall, so make a new entry */ - MGET(mb_rt, M_DONTWAIT, MT_MRTABLE); - if (mb_rt == NULL) { - m_free(mb_ntry); - m_freem(mb0); - splx(s); - return ENOBUFS; - } - /* Make a copy of the header to send to the user level process */ - mm = m_copy(mb0, 0, hlen); - if (mm == NULL) { - m_free(mb_ntry); - m_freem(mb0); - m_free(mb_rt); - splx(s); - return ENOBUFS; - } - - /* - * Send message to routing daemon to install - * a route into the kernel table - */ - k_igmpsrc.sin_addr = ip->ip_src; - - im = mtod(mm, struct igmpmsg *); - im->im_msgtype = IGMPMSG_NOCACHE; - im->im_mbz = 0; - - mrtstat.mrts_upcalls++; - - if (socket_send(ip_mrouter, mm, &k_igmpsrc) < 0) { - log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n"); - ++mrtstat.mrts_upq_sockfull; - m_free(mb_ntry); - m_freem(mb0); - m_free(mb_rt); - splx(s); - return ENOBUFS; - } - - rt = mtod(mb_rt, struct mfc *); - - /* insert new entry at head of hash chain */ - rt->mfc_origin.s_addr = ip->ip_src.s_addr; - rt->mfc_mcastgrp.s_addr = ip->ip_dst.s_addr; - rt->mfc_expire = UPCALL_EXPIRE; - nexpire[hash]++; - for (i = 0; i < numvifs; i++) - rt->mfc_ttls[i] = 0; - rt->mfc_parent = -1; - - /* link into table */ - mb_rt->m_next = mfctable[hash]; - mfctable[hash] = mb_rt; - mb_rt->m_act = NULL; - - rte_m = mb_rt; - } else { - /* determine if q has overflowed */ - for (rte_m = mb_rt, npkts = 0; rte_m->m_act; rte_m = rte_m->m_act) - npkts++; - - if (npkts > MAX_UPQ) { - mrtstat.mrts_upq_ovflw++; - m_free(mb_ntry); - m_freem(mb0); - splx(s); - return 0; - } - } - - mb_ntry->m_act = NULL; - rte = mtod(mb_ntry, struct rtdetq *); - - rte->m = mb0; - rte->ifp = ifp; -#ifdef UPCALL_TIMING - rte->t = tp; -#endif - - /* Add this entry to the end of the queue */ - rte_m->m_act = mb_ntry; - - splx(s); - - return 0; - } -} - -#ifndef MROUTE_LKM -int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, - struct ip_moptions *) = X_ip_mforward; -#endif - -/* - * Clean up the cache entry if upcall is not serviced - */ -static void -expire_upcalls(void *unused) -{ - struct mbuf *mb_rt, *m, **nptr; - struct rtdetq *rte; - struct mfc *mfc; - int i; - int s; - - s = splnet(); - for (i = 0; i < MFCTBLSIZ; i++) { - if (nexpire[i] == 0) - continue; - nptr = &mfctable[i]; - for (mb_rt = *nptr; mb_rt != NULL; mb_rt = *nptr) { - mfc = mtod(mb_rt, struct mfc *); - - /* - * Skip real cache entries - * Make sure it wasn't marked to not expire (shouldn't happen) - * If it expires now - */ - if (mb_rt->m_act != NULL && - mfc->mfc_expire != 0 && - --mfc->mfc_expire == 0) { - if (mrtdebug & DEBUG_EXPIRE) - log(LOG_DEBUG, "expire_upcalls: expiring (%x %x)\n", - ntohl(mfc->mfc_origin.s_addr), - ntohl(mfc->mfc_mcastgrp.s_addr)); - /* - * drop all the packets - * free the mbuf with the pkt, if, timing info - */ - while (mb_rt->m_act) { - m = mb_rt->m_act; - mb_rt->m_act = m->m_act; - - rte = mtod(m, struct rtdetq *); - m_freem(rte->m); - m_free(m); - } - ++mrtstat.mrts_cache_cleanups; - nexpire[i]--; - - MFREE(mb_rt, *nptr); - } else { - nptr = &mb_rt->m_next; - } - } - } - splx(s); - timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT); -} - -/* - * Packet forwarding routine once entry in the cache is made - */ -static int -ip_mdq(m, ifp, rt, xmt_vif) - register struct mbuf *m; - register struct ifnet *ifp; - register struct mfc *rt; - register vifi_t xmt_vif; -{ - register struct ip *ip = mtod(m, struct ip *); - register vifi_t vifi; - register struct vif *vifp; - register int plen = ntohs(ip->ip_len); - -/* - * Macro to send packet on vif. Since RSVP packets don't get counted on - * input, they shouldn't get counted on output, so statistics keeping is - * seperate. - */ -#define MC_SEND(ip,vifp,m) { \ - if ((vifp)->v_flags & VIFF_TUNNEL) \ - encap_send((ip), (vifp), (m)); \ - else \ - phyint_send((ip), (vifp), (m)); \ -} - - /* - * If xmt_vif is not -1, send on only the requested vif. - * - * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.) - */ - if (xmt_vif < numvifs) { - MC_SEND(ip, viftable + xmt_vif, m); - return 1; - } - - /* - * Don't forward if it didn't arrive from the parent vif for its origin. - */ - vifi = rt->mfc_parent; - if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) { - /* came in the wrong interface */ - if (mrtdebug & DEBUG_FORWARD) - log(LOG_DEBUG, "wrong if: ifp %x vifi %d vififp %x\n", - ifp, vifi, viftable[vifi].v_ifp); - ++mrtstat.mrts_wrong_if; - ++rt->mfc_wrong_if; - /* - * If we are doing PIM assert processing, and we are forwarding - * packets on this interface, and it is a broadcast medium - * interface (and not a tunnel), send a message to the routing daemon. - */ - if (pim_assert && rt->mfc_ttls[vifi] && - (ifp->if_flags & IFF_BROADCAST) && - !(viftable[vifi].v_flags & VIFF_TUNNEL)) { - struct sockaddr_in k_igmpsrc; - struct mbuf *mm; - struct igmpmsg *im; - int hlen = ip->ip_hl << 2; - struct timeval now; - register u_long delta; - - GET_TIME(now); - - TV_DELTA(rt->mfc_last_assert, now, delta); - - if (delta > ASSERT_MSG_TIME) { - mm = m_copy(m, 0, hlen); - if (mm && (M_HASCL(mm) || mm->m_len < hlen)) - mm = m_pullup(mm, hlen); - if (mm == NULL) { - return ENOBUFS; - } - - rt->mfc_last_assert = now; - - im = mtod(mm, struct igmpmsg *); - im->im_msgtype = IGMPMSG_WRONGVIF; - im->im_mbz = 0; - im->im_vif = vifi; - - k_igmpsrc.sin_addr = im->im_src; - - socket_send(ip_mrouter, mm, &k_igmpsrc); - } - } - return 0; - } - - /* If I sourced this packet, it counts as output, else it was input. */ - if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) { - viftable[vifi].v_pkt_out++; - viftable[vifi].v_bytes_out += plen; - } else { - viftable[vifi].v_pkt_in++; - viftable[vifi].v_bytes_in += plen; - } - rt->mfc_pkt_cnt++; - rt->mfc_byte_cnt += plen; - - /* - * For each vif, decide if a copy of the packet should be forwarded. - * Forward if: - * - the ttl exceeds the vif's threshold - * - there are group members downstream on interface - */ - for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++) - if ((rt->mfc_ttls[vifi] > 0) && - (ip->ip_ttl > rt->mfc_ttls[vifi])) { - vifp->v_pkt_out++; - vifp->v_bytes_out += plen; - MC_SEND(ip, vifp, m); - } - - return 0; -} - -/* - * check if a vif number is legal/ok. This is used by ip_output, to export - * numvifs there, - */ -static int -X_legal_vif_num(vif) - int vif; -{ - if (vif >= 0 && vif < numvifs) - return(1); - else - return(0); -} - -#ifndef MROUTE_LKM -int (*legal_vif_num)(int) = X_legal_vif_num; -#endif - -/* - * Return the local address used by this vif - */ -static u_long -X_ip_mcast_src(vifi) - int vifi; -{ - if (vifi >= 0 && vifi < numvifs) - return viftable[vifi].v_lcl_addr.s_addr; - else - return INADDR_ANY; -} - -#ifndef MROUTE_LKM -u_long (*ip_mcast_src)(int) = X_ip_mcast_src; -#endif - -static void -phyint_send(ip, vifp, m) - struct ip *ip; - struct vif *vifp; - struct mbuf *m; -{ - register struct mbuf *mb_copy; - register int hlen = ip->ip_hl << 2; - - /* - * Make a new reference to the packet; make sure that - * the IP header is actually copied, not just referenced, - * so that ip_output() only scribbles on the copy. - */ - mb_copy = m_copy(m, 0, M_COPYALL); - if (mb_copy && (M_HASCL(mb_copy) || mb_copy->m_len < hlen)) - mb_copy = m_pullup(mb_copy, hlen); - if (mb_copy == NULL) - return; - - if (vifp->v_rate_limit <= 0) - tbf_send_packet(vifp, mb_copy); - else - tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len); -} - -static void -encap_send(ip, vifp, m) - register struct ip *ip; - register struct vif *vifp; - register struct mbuf *m; -{ - register struct mbuf *mb_copy; - register struct ip *ip_copy; - register int i, len = ip->ip_len; - - /* - * copy the old packet & pullup it's IP header into the - * new mbuf so we can modify it. Try to fill the new - * mbuf since if we don't the ethernet driver will. - */ - MGETHDR(mb_copy, M_DONTWAIT, MT_HEADER); - if (mb_copy == NULL) - return; - mb_copy->m_data += max_linkhdr; - mb_copy->m_len = sizeof(multicast_encap_iphdr); - - if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == NULL) { - m_freem(mb_copy); - return; - } - i = MHLEN - M_LEADINGSPACE(mb_copy); - if (i > len) - i = len; - mb_copy = m_pullup(mb_copy, i); - if (mb_copy == NULL) - return; - mb_copy->m_pkthdr.len = len + sizeof(multicast_encap_iphdr); - - /* - * fill in the encapsulating IP header. - */ - ip_copy = mtod(mb_copy, struct ip *); - *ip_copy = multicast_encap_iphdr; - ip_copy->ip_id = htons(ip_id++); - ip_copy->ip_len += len; - ip_copy->ip_src = vifp->v_lcl_addr; - ip_copy->ip_dst = vifp->v_rmt_addr; - - /* - * turn the encapsulated IP header back into a valid one. - */ - ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr)); - --ip->ip_ttl; - HTONS(ip->ip_len); - HTONS(ip->ip_off); - ip->ip_sum = 0; - mb_copy->m_data += sizeof(multicast_encap_iphdr); - ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2); - mb_copy->m_data -= sizeof(multicast_encap_iphdr); - - if (vifp->v_rate_limit <= 0) - tbf_send_packet(vifp, mb_copy); - else - tbf_control(vifp, mb_copy, ip, ip_copy->ip_len); -} - -/* - * De-encapsulate a packet and feed it back through ip input (this - * routine is called whenever IP gets a packet with proto type - * ENCAP_PROTO and a local destination address). - */ -void -#ifdef MROUTE_LKM -X_ipip_input(m, iphlen) -#else -ipip_input(m, iphlen) -#endif - register struct mbuf *m; - int iphlen; -{ - struct ifnet *ifp = m->m_pkthdr.rcvif; - register struct ip *ip = mtod(m, struct ip *); - register int hlen = ip->ip_hl << 2; - register int s; - register struct ifqueue *ifq; - register struct vif *vifp; - - if (!have_encap_tunnel) { - rip_input(m, iphlen); - return; - } - /* - * dump the packet if it's not to a multicast destination or if - * we don't have an encapsulating tunnel with the source. - * Note: This code assumes that the remote site IP address - * uniquely identifies the tunnel (i.e., that this site has - * at most one tunnel with the remote site). - */ - if (! IN_MULTICAST(ntohl(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr))) { - ++mrtstat.mrts_bad_tunnel; - m_freem(m); - return; - } - if (ip->ip_src.s_addr != last_encap_src) { - register struct vif *vife; - - vifp = viftable; - vife = vifp + numvifs; - last_encap_src = ip->ip_src.s_addr; - last_encap_vif = 0; - for ( ; vifp < vife; ++vifp) - if (vifp->v_rmt_addr.s_addr == ip->ip_src.s_addr) { - if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT)) - == VIFF_TUNNEL) - last_encap_vif = vifp; - break; - } - } - if ((vifp = last_encap_vif) == 0) { - last_encap_src = 0; - mrtstat.mrts_cant_tunnel++; /*XXX*/ - m_freem(m); - if (mrtdebug) - log(LOG_DEBUG, "ip_mforward: no tunnel with %x\n", - ntohl(ip->ip_src.s_addr)); - return; - } - ifp = vifp->v_ifp; - - if (hlen > IP_HDR_LEN) - ip_stripoptions(m, (struct mbuf *) 0); - m->m_data += IP_HDR_LEN; - m->m_len -= IP_HDR_LEN; - m->m_pkthdr.len -= IP_HDR_LEN; - m->m_pkthdr.rcvif = ifp; - - ifq = &ipintrq; - s = splimp(); - if (IF_QFULL(ifq)) { - IF_DROP(ifq); - m_freem(m); - } else { - IF_ENQUEUE(ifq, m); - /* - * normally we would need a "schednetisr(NETISR_IP)" - * here but we were called by ip_input and it is going - * to loop back & try to dequeue the packet we just - * queued as soon as we return so we avoid the - * unnecessary software interrrupt. - */ - } - splx(s); -} - -/* - * Token bucket filter module - */ - -static void -tbf_control(vifp, m, ip, p_len) - register struct vif *vifp; - register struct mbuf *m; - register struct ip *ip; - register u_long p_len; -{ - register struct tbf *t = vifp->v_tbf; - - if (p_len > MAX_BKT_SIZE) { - /* drop if packet is too large */ - mrtstat.mrts_pkt2large++; - m_freem(m); - return; - } - - tbf_update_tokens(vifp); - - /* if there are enough tokens, - * and the queue is empty, - * send this packet out - */ - - if (t->tbf_q_len == 0) { - /* queue empty, send packet if enough tokens */ - if (p_len <= t->tbf_n_tok) { - t->tbf_n_tok -= p_len; - tbf_send_packet(vifp, m); - } else { - /* queue packet and timeout till later */ - tbf_queue(vifp, m); - timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS); - } - } else if (t->tbf_q_len < t->tbf_max_q_len) { - /* finite queue length, so queue pkts and process queue */ - tbf_queue(vifp, m); - tbf_process_q(vifp); - } else { - /* queue length too much, try to dq and queue and process */ - if (!tbf_dq_sel(vifp, ip)) { - mrtstat.mrts_q_overflow++; - m_freem(m); - return; - } else { - tbf_queue(vifp, m); - tbf_process_q(vifp); - } - } - return; -} - -/* - * adds a packet to the queue at the interface - */ -static void -tbf_queue(vifp, m) - register struct vif *vifp; - register struct mbuf *m; -{ - register int s = splnet(); - register struct tbf *t = vifp->v_tbf; - - if (t->tbf_t == NULL) { - /* Queue was empty */ - t->tbf_q = m; - } else { - /* Insert at tail */ - t->tbf_t->m_act = m; - } - - /* Set new tail pointer */ - t->tbf_t = m; - -#ifdef DIAGNOSTIC - /* Make sure we didn't get fed a bogus mbuf */ - if (m->m_act) - panic("tbf_queue: m_act"); -#endif - m->m_act = NULL; - - t->tbf_q_len++; - - splx(s); -} - - -/* - * processes the queue at the interface - */ -static void -tbf_process_q(vifp) - register struct vif *vifp; -{ - register struct mbuf *m; - register int len; - register int s = splnet(); - register struct tbf *t = vifp->v_tbf; - - /* loop through the queue at the interface and send as many packets - * as possible - */ - while (t->tbf_q_len > 0) { - m = t->tbf_q; - - len = mtod(m, struct ip *)->ip_len; - - /* determine if the packet can be sent */ - if (len <= t->tbf_n_tok) { - /* if so, - * reduce no of tokens, dequeue the packet, - * send the packet. - */ - t->tbf_n_tok -= len; - - t->tbf_q = m->m_act; - if (--t->tbf_q_len == 0) - t->tbf_t = NULL; - - m->m_act = NULL; - tbf_send_packet(vifp, m); - - } else break; - } - splx(s); -} - -static void -tbf_reprocess_q(xvifp) - void *xvifp; -{ - register struct vif *vifp = xvifp; - if (ip_mrouter == NULL) - return; - - tbf_update_tokens(vifp); - - tbf_process_q(vifp); - - if (vifp->v_tbf->tbf_q_len) - timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS); -} - -/* function that will selectively discard a member of the queue - * based on the precedence value and the priority - */ -static int -tbf_dq_sel(vifp, ip) - register struct vif *vifp; - register struct ip *ip; -{ - register int s = splnet(); - register u_int p; - register struct mbuf *m, *last; - register struct mbuf **np; - register struct tbf *t = vifp->v_tbf; - - p = priority(vifp, ip); - - np = &t->tbf_q; - last = NULL; - while ((m = *np) != NULL) { - if (p > priority(vifp, mtod(m, struct ip *))) { - *np = m->m_act; - /* If we're removing the last packet, fix the tail pointer */ - if (m == t->tbf_t) - t->tbf_t = last; - m_freem(m); - /* it's impossible for the queue to be empty, but - * we check anyway. */ - if (--t->tbf_q_len == 0) - t->tbf_t = NULL; - splx(s); - mrtstat.mrts_drop_sel++; - return(1); - } - np = &m->m_act; - last = m; - } - splx(s); - return(0); -} - -static void -tbf_send_packet(vifp, m) - register struct vif *vifp; - register struct mbuf *m; -{ - struct ip_moptions imo; - int error; - static struct route ro; - int s = splnet(); - - if (vifp->v_flags & VIFF_TUNNEL) { - /* If tunnel options */ - ip_output(m, (struct mbuf *)0, &vifp->v_route, - IP_FORWARDING, (struct ip_moptions *)0); - } else { - imo.imo_multicast_ifp = vifp->v_ifp; - imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1; - imo.imo_multicast_loop = 1; - imo.imo_multicast_vif = -1; - - /* - * Re-entrancy should not be a problem here, because - * the packets that we send out and are looped back at us - * should get rejected because they appear to come from - * the loopback interface, thus preventing looping. - */ - error = ip_output(m, (struct mbuf *)0, &ro, - IP_FORWARDING, &imo); - - if (mrtdebug & DEBUG_XMIT) - log(LOG_DEBUG, "phyint_send on vif %d err %d\n", - vifp - viftable, error); - } - splx(s); -} - -/* determine the current time and then - * the elapsed time (between the last time and time now) - * in milliseconds & update the no. of tokens in the bucket - */ -static void -tbf_update_tokens(vifp) - register struct vif *vifp; -{ - struct timeval tp; - register u_long tm; - register int s = splnet(); - register struct tbf *t = vifp->v_tbf; - - GET_TIME(tp); - - TV_DELTA(tp, t->tbf_last_pkt_t, tm); - - /* - * This formula is actually - * "time in seconds" * "bytes/second". - * - * (tm / 1000000) * (v_rate_limit * 1000 * (1000/1024) / 8) - * - * The (1000/1024) was introduced in add_vif to optimize - * this divide into a shift. - */ - t->tbf_n_tok += tm * vifp->v_rate_limit / 1024 / 8; - t->tbf_last_pkt_t = tp; - - if (t->tbf_n_tok > MAX_BKT_SIZE) - t->tbf_n_tok = MAX_BKT_SIZE; - - splx(s); -} - -static int -priority(vifp, ip) - register struct vif *vifp; - register struct ip *ip; -{ - register int prio; - - /* temporary hack; may add general packet classifier some day */ - - /* - * The UDP port space is divided up into four priority ranges: - * [0, 16384) : unclassified - lowest priority - * [16384, 32768) : audio - highest priority - * [32768, 49152) : whiteboard - medium priority - * [49152, 65536) : video - low priority - */ - if (ip->ip_p == IPPROTO_UDP) { - struct udphdr *udp = (struct udphdr *)(((char *)ip) + (ip->ip_hl << 2)); - switch (ntohs(udp->uh_dport) & 0xc000) { - case 0x4000: - prio = 70; - break; - case 0x8000: - prio = 60; - break; - case 0xc000: - prio = 55; - break; - default: - prio = 50; - break; - } - if (tbfdebug > 1) - log(LOG_DEBUG, "port %x prio%d\n", ntohs(udp->uh_dport), prio); - } else { - prio = 50; - } - return prio; -} - -/* - * End of token bucket filter modifications - */ - -int -ip_rsvp_vif_init(so, m) - struct socket *so; - struct mbuf *m; -{ - int i; - register int s; - - if (rsvpdebug) - printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n", - so->so_type, so->so_proto->pr_protocol); - - if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) - return EOPNOTSUPP; - - /* Check mbuf. */ - if (m == NULL || m->m_len != sizeof(int)) { - return EINVAL; - } - i = *(mtod(m, int *)); - - if (rsvpdebug) - printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n",i,rsvp_on); - - s = splnet(); - - /* Check vif. */ - if (!legal_vif_num(i)) { - splx(s); - return EADDRNOTAVAIL; - } - - /* Check if socket is available. */ - if (viftable[i].v_rsvpd != NULL) { - splx(s); - return EADDRINUSE; - } - - viftable[i].v_rsvpd = so; - /* This may seem silly, but we need to be sure we don't over-increment - * the RSVP counter, in case something slips up. - */ - if (!viftable[i].v_rsvp_on) { - viftable[i].v_rsvp_on = 1; - rsvp_on++; - } - - splx(s); - return 0; -} - -int -ip_rsvp_vif_done(so, m) - struct socket *so; - struct mbuf *m; -{ - int i; - register int s; - - if (rsvpdebug) - printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n", - so->so_type, so->so_proto->pr_protocol); - - if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) - return EOPNOTSUPP; - - /* Check mbuf. */ - if (m == NULL || m->m_len != sizeof(int)) { - return EINVAL; - } - i = *(mtod(m, int *)); - - s = splnet(); - - /* Check vif. */ - if (!legal_vif_num(i)) { - splx(s); - return EADDRNOTAVAIL; - } - - if (rsvpdebug) - printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n", - viftable[i].v_rsvpd, so); - - viftable[i].v_rsvpd = NULL; - /* This may seem silly, but we need to be sure we don't over-decrement - * the RSVP counter, in case something slips up. - */ - if (viftable[i].v_rsvp_on) { - viftable[i].v_rsvp_on = 0; - rsvp_on--; - } - - splx(s); - return 0; -} - -void -ip_rsvp_force_done(so) - struct socket *so; -{ - int vifi; - register int s; - - /* Don't bother if it is not the right type of socket. */ - if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) - return; - - s = splnet(); - - /* The socket may be attached to more than one vif...this - * is perfectly legal. - */ - for (vifi = 0; vifi < numvifs; vifi++) { - if (viftable[vifi].v_rsvpd == so) { - viftable[vifi].v_rsvpd = NULL; - /* This may seem silly, but we need to be sure we don't - * over-decrement the RSVP counter, in case something slips up. - */ - if (viftable[vifi].v_rsvp_on) { - viftable[vifi].v_rsvp_on = 0; - rsvp_on--; - } - } - } - - splx(s); - return; -} - -void -rsvp_input(m, iphlen) - struct mbuf *m; - int iphlen; -{ - int vifi; - register struct ip *ip = mtod(m, struct ip *); - static struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET }; - register int s; - struct ifnet *ifp; - - if (rsvpdebug) - printf("rsvp_input: rsvp_on %d\n",rsvp_on); - - /* Can still get packets with rsvp_on = 0 if there is a local member - * of the group to which the RSVP packet is addressed. But in this - * case we want to throw the packet away. - */ - if (!rsvp_on) { - m_freem(m); - return; - } - - /* If the old-style non-vif-associated socket is set, then use - * it and ignore the new ones. - */ - if (ip_rsvpd != NULL) { - if (rsvpdebug) - printf("rsvp_input: Sending packet up old-style socket\n"); - rip_input(m, iphlen); - return; - } - - s = splnet(); - - if (rsvpdebug) - printf("rsvp_input: check vifs\n"); - -#ifdef DIAGNOSTIC - if (!(m->m_flags & M_PKTHDR)) - panic("rsvp_input no hdr"); -#endif - - ifp = m->m_pkthdr.rcvif; - /* Find which vif the packet arrived on. */ - for (vifi = 0; vifi < numvifs; vifi++) { - if (viftable[vifi].v_ifp == ifp) - break; - } - - if (vifi == numvifs) { - /* Can't find vif packet arrived on. Drop packet. */ - if (rsvpdebug) - printf("rsvp_input: Can't find vif for packet...dropping it.\n"); - m_freem(m); - splx(s); - return; - } - - if (rsvpdebug) - printf("rsvp_input: check socket\n"); - - if (viftable[vifi].v_rsvpd == NULL) { - /* drop packet, since there is no specific socket for this - * interface */ - if (rsvpdebug) - printf("rsvp_input: No socket defined for vif %d\n",vifi); - m_freem(m); - splx(s); - return; - } - rsvp_src.sin_addr = ip->ip_src; - - if (rsvpdebug && m) - printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n", - m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv))); - - if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) - if (rsvpdebug) - printf("rsvp_input: Failed to append to socket\n"); - else - if (rsvpdebug) - printf("rsvp_input: send packet up\n"); - - splx(s); -} - -#ifdef MROUTE_LKM -#include <sys/conf.h> -#include <sys/exec.h> -#include <sys/sysent.h> -#include <sys/lkm.h> - -MOD_MISC("ip_mroute_mod") - -static int -ip_mroute_mod_handle(struct lkm_table *lkmtp, int cmd) -{ - int i; - struct lkm_misc *args = lkmtp->private.lkm_misc; - int err = 0; - - switch(cmd) { - static int (*old_ip_mrouter_cmd)(); - static int (*old_ip_mrouter_done)(); - static int (*old_ip_mforward)(); - static int (*old_mrt_ioctl)(); - static void (*old_proto4_input)(); - static int (*old_legal_vif_num)(); - extern struct protosw inetsw[]; - - case LKM_E_LOAD: - if(lkmexists(lkmtp) || ip_mrtproto) - return(EEXIST); - old_ip_mrouter_cmd = ip_mrouter_cmd; - ip_mrouter_cmd = X_ip_mrouter_cmd; - old_ip_mrouter_done = ip_mrouter_done; - ip_mrouter_done = X_ip_mrouter_done; - old_ip_mforward = ip_mforward; - ip_mforward = X_ip_mforward; - old_mrt_ioctl = mrt_ioctl; - mrt_ioctl = X_mrt_ioctl; - old_proto4_input = inetsw[ip_protox[ENCAP_PROTO]].pr_input; - inetsw[ip_protox[ENCAP_PROTO]].pr_input = X_ipip_input; - old_legal_vif_num = legal_vif_num; - legal_vif_num = X_legal_vif_num; - ip_mrtproto = IGMP_DVMRP; - - printf("\nIP multicast routing loaded\n"); - break; - - case LKM_E_UNLOAD: - if (ip_mrouter) - return EINVAL; - - ip_mrouter_cmd = old_ip_mrouter_cmd; - ip_mrouter_done = old_ip_mrouter_done; - ip_mforward = old_ip_mforward; - mrt_ioctl = old_mrt_ioctl; - inetsw[ip_protox[ENCAP_PROTO]].pr_input = old_proto4_input; - legal_vif_num = old_legal_vif_num; - ip_mrtproto = 0; - break; - - default: - err = EINVAL; - break; - } - - return(err); -} - -int -ip_mroute_mod(struct lkm_table *lkmtp, int cmd, int ver) { - DISPATCH(lkmtp, cmd, ver, ip_mroute_mod_handle, ip_mroute_mod_handle, - nosys); -} - -#endif /* MROUTE_LKM */ -#endif /* MROUTING */ diff --git a/c/src/exec/libnetworking/netinet/ip_mroute.h b/c/src/exec/libnetworking/netinet/ip_mroute.h deleted file mode 100644 index 5ddd6799d2..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_mroute.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (c) 1989 Stephen Deering. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Stephen Deering of Stanford University. - * - * 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. - * - * @(#)ip_mroute.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_IP_MROUTE_H_ -#define _NETINET_IP_MROUTE_H_ - -/* - * Definitions for IP multicast forwarding. - * - * Written by David Waitzman, BBN Labs, August 1988. - * Modified by Steve Deering, Stanford, February 1989. - * Modified by Ajit Thyagarajan, PARC, August 1993. - * Modified by Ajit Thyagarajan, PARC, August 1994. - * - * MROUTING Revision: 3.3.1.3 - */ - - -/* - * Multicast Routing set/getsockopt commands. - */ -#define MRT_INIT 100 /* initialize forwarder */ -#define MRT_DONE 101 /* shut down forwarder */ -#define MRT_ADD_VIF 102 /* create virtual interface */ -#define MRT_DEL_VIF 103 /* delete virtual interface */ -#define MRT_ADD_MFC 104 /* insert forwarding cache entry */ -#define MRT_DEL_MFC 105 /* delete forwarding cache entry */ -#define MRT_VERSION 106 /* get kernel version number */ -#define MRT_ASSERT 107 /* enable PIM assert processing */ - - -#define GET_TIME(t) microtime(&t) - -/* - * Types and macros for handling bitmaps with one bit per virtual interface. - */ -#define MAXVIFS 32 -typedef u_long vifbitmap_t; -typedef u_short vifi_t; /* type of a vif index */ -#define ALL_VIFS (vifi_t)-1 - -#define VIFM_SET(n, m) ((m) |= (1 << (n))) -#define VIFM_CLR(n, m) ((m) &= ~(1 << (n))) -#define VIFM_ISSET(n, m) ((m) & (1 << (n))) -#define VIFM_CLRALL(m) ((m) = 0x00000000) -#define VIFM_COPY(mfrom, mto) ((mto) = (mfrom)) -#define VIFM_SAME(m1, m2) ((m1) == (m2)) - - -/* - * Argument structure for MRT_ADD_VIF. - * (MRT_DEL_VIF takes a single vifi_t argument.) - */ -struct vifctl { - vifi_t vifc_vifi; /* the index of the vif to be added */ - u_char vifc_flags; /* VIFF_ flags defined below */ - u_char vifc_threshold; /* min ttl required to forward on vif */ - u_int vifc_rate_limit; /* max rate */ - struct in_addr vifc_lcl_addr; /* local interface address */ - struct in_addr vifc_rmt_addr; /* remote address (tunnels only) */ -}; - -#define VIFF_TUNNEL 0x1 /* vif represents a tunnel end-point */ -#define VIFF_SRCRT 0x2 /* tunnel uses IP source routing */ - -/* - * Argument structure for MRT_ADD_MFC and MRT_DEL_MFC - * (mfcc_tos to be added at a future point) - */ -struct mfcctl { - struct in_addr mfcc_origin; /* ip origin of mcasts */ - struct in_addr mfcc_mcastgrp; /* multicast group associated*/ - vifi_t mfcc_parent; /* incoming vif */ - u_char mfcc_ttls[MAXVIFS]; /* forwarding ttls on vifs */ -}; - -/* - * The kernel's multicast routing statistics. - */ -struct mrtstat { - u_long mrts_mfc_lookups; /* # forw. cache hash table hits */ - u_long mrts_mfc_misses; /* # forw. cache hash table misses */ - u_long mrts_upcalls; /* # calls to mrouted */ - u_long mrts_no_route; /* no route for packet's origin */ - u_long mrts_bad_tunnel; /* malformed tunnel options */ - u_long mrts_cant_tunnel; /* no room for tunnel options */ - u_long mrts_wrong_if; /* arrived on wrong interface */ - u_long mrts_upq_ovflw; /* upcall Q overflow */ - u_long mrts_cache_cleanups; /* # entries with no upcalls */ - u_long mrts_drop_sel; /* pkts dropped selectively */ - u_long mrts_q_overflow; /* pkts dropped - Q overflow */ - u_long mrts_pkt2large; /* pkts dropped - size > BKT SIZE */ - u_long mrts_upq_sockfull; /* upcalls dropped - socket full */ -}; - -/* - * Argument structure used by mrouted to get src-grp pkt counts - */ -struct sioc_sg_req { - struct in_addr src; - struct in_addr grp; - u_long pktcnt; - u_long bytecnt; - u_long wrong_if; -}; - -/* - * Argument structure used by mrouted to get vif pkt counts - */ -struct sioc_vif_req { - vifi_t vifi; /* vif number */ - u_long icount; /* Input packet count on vif */ - u_long ocount; /* Output packet count on vif */ - u_long ibytes; /* Input byte count on vif */ - u_long obytes; /* Output byte count on vif */ -}; - - -/* - * The kernel's virtual-interface structure. - */ -struct vif { - u_char v_flags; /* VIFF_ flags defined above */ - u_char v_threshold; /* min ttl required to forward on vif*/ - u_int v_rate_limit; /* max rate */ - struct tbf *v_tbf; /* token bucket structure at intf. */ - struct in_addr v_lcl_addr; /* local interface address */ - struct in_addr v_rmt_addr; /* remote address (tunnels only) */ - struct ifnet *v_ifp; /* pointer to interface */ - u_long v_pkt_in; /* # pkts in on interface */ - u_long v_pkt_out; /* # pkts out on interface */ - u_long v_bytes_in; /* # bytes in on interface */ - u_long v_bytes_out; /* # bytes out on interface */ - struct route v_route; /* cached route if this is a tunnel */ - u_int v_rsvp_on; /* RSVP listening on this vif */ - struct socket *v_rsvpd; /* RSVP daemon socket */ -}; - -/* - * The kernel's multicast forwarding cache entry structure - * (A field for the type of service (mfc_tos) is to be added - * at a future point) - */ -struct mfc { - struct in_addr mfc_origin; /* IP origin of mcasts */ - struct in_addr mfc_mcastgrp; /* multicast group associated*/ - vifi_t mfc_parent; /* incoming vif */ - u_char mfc_ttls[MAXVIFS]; /* forwarding ttls on vifs */ - u_long mfc_pkt_cnt; /* pkt count for src-grp */ - u_long mfc_byte_cnt; /* byte count for src-grp */ - u_long mfc_wrong_if; /* wrong if for src-grp */ - int mfc_expire; /* time to clean entry up */ - struct timeval mfc_last_assert; /* last time I sent an assert*/ -}; - -/* - * Struct used to communicate from kernel to multicast router - * note the convenient similarity to an IP packet - */ -struct igmpmsg { - u_long unused1; - u_long unused2; - u_char im_msgtype; /* what type of message */ -#define IGMPMSG_NOCACHE 1 -#define IGMPMSG_WRONGVIF 2 - u_char im_mbz; /* must be zero */ - u_char im_vif; /* vif rec'd on */ - u_char unused3; - struct in_addr im_src, im_dst; -}; - -/* - * Argument structure used for pkt info. while upcall is made - */ -struct rtdetq { - struct mbuf *m; /* A copy of the packet */ - struct ifnet *ifp; /* Interface pkt came in on */ - vifi_t xmt_vif; /* Saved copy of imo_multicast_vif */ -#ifdef UPCALL_TIMING - struct timeval t; /* Timestamp */ -#endif /* UPCALL_TIMING */ -}; - -#define MFCTBLSIZ 256 -#if (MFCTBLSIZ & (MFCTBLSIZ - 1)) == 0 /* from sys:route.h */ -#define MFCHASHMOD(h) ((h) & (MFCTBLSIZ - 1)) -#else -#define MFCHASHMOD(h) ((h) % MFCTBLSIZ) -#endif - -#define MAX_UPQ 4 /* max. no of pkts in upcall Q */ - -/* - * Token Bucket filter code - */ -#define MAX_BKT_SIZE 10000 /* 10K bytes size */ -#define MAXQSIZE 10 /* max # of pkts in queue */ - -/* - * the token bucket filter at each vif - */ -struct tbf -{ - struct timeval tbf_last_pkt_t; /* arr. time of last pkt */ - u_long tbf_n_tok; /* no of tokens in bucket */ - u_long tbf_q_len; /* length of queue at this vif */ - u_long tbf_max_q_len; /* max. queue length */ - struct mbuf *tbf_q; /* Packet queue */ - struct mbuf *tbf_t; /* tail-insertion pointer */ -}; - -#ifdef KERNEL - -extern int (*ip_mrouter_set) __P((int, struct socket *, struct mbuf *)); -extern int (*ip_mrouter_get) __P((int, struct socket *, struct mbuf **)); -extern int (*ip_mrouter_done) __P((void)); -#ifdef MROUTING -extern int (*mrt_ioctl) __P((int, caddr_t)); -#else -extern int (*mrt_ioctl) __P((int, caddr_t, struct proc *)); -#endif - -#endif /* KERNEL */ - -#endif /* _NETINET_IP_MROUTE_H_ */ diff --git a/c/src/exec/libnetworking/netinet/ip_output.c b/c/src/exec/libnetworking/netinet/ip_output.c deleted file mode 100644 index 810f6c7479..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_output.c +++ /dev/null @@ -1,1307 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 - * $Id$ - */ - -#define _IP_VHL - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/errno.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/socketvar.h> - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/ip_var.h> - -#ifdef vax -#include <machine/mtpr.h> -#endif -#include <machine/in_cksum.h> - -#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1 -#undef COMPAT_IPFW -#define COMPAT_IPFW 1 -#else -#undef COMPAT_IPFW -#endif - -u_short ip_id; - -static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); -static void ip_mloopback - __P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int)); -static int ip_getmoptions - __P((int, struct ip_moptions *, struct mbuf **)); -static int ip_optcopy __P((struct ip *, struct ip *)); -static int ip_pcbopts __P((struct mbuf **, struct mbuf *)); -static int ip_setmoptions - __P((int, struct ip_moptions **, struct mbuf *)); - -extern struct protosw inetsw[]; - -/* - * IP output. The packet in mbuf chain m contains a skeletal IP - * header (with len, off, ttl, proto, tos, src, dst). - * The mbuf chain containing the packet will be freed. - * The mbuf opt, if present, will not be freed. - */ -int -ip_output(m0, opt, ro, flags, imo) - struct mbuf *m0; - struct mbuf *opt; - struct route *ro; - int flags; - struct ip_moptions *imo; -{ - struct ip *ip, *mhip; - struct ifnet *ifp; - struct mbuf *m = m0; - int hlen = sizeof (struct ip); - int len, off, error = 0; - struct sockaddr_in *dst; - struct in_ifaddr *ia; - int isbroadcast; - -#ifdef DIAGNOSTIC - if ((m->m_flags & M_PKTHDR) == 0) - panic("ip_output no HDR"); - if (!ro) - panic("ip_output no route, proto = %d", - mtod(m, struct ip *)->ip_p); -#endif - if (opt) { - m = ip_insertoptions(m, opt, &len); - hlen = len; - } - ip = mtod(m, struct ip *); - /* - * Fill in IP header. - */ - if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) { - ip->ip_vhl = IP_MAKE_VHL(IPVERSION, hlen >> 2); - ip->ip_off &= IP_DF; - ip->ip_id = htons(ip_id++); - ipstat.ips_localout++; - } else { - hlen = IP_VHL_HL(ip->ip_vhl) << 2; - } - - dst = (struct sockaddr_in *)&ro->ro_dst; - /* - * If there is a cached route, - * check that it is to the same destination - * and is still up. If not, free it and try again. - */ - if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || - dst->sin_addr.s_addr != ip->ip_dst.s_addr)) { - RTFREE(ro->ro_rt); - ro->ro_rt = (struct rtentry *)0; - } - if (ro->ro_rt == 0) { - dst->sin_family = AF_INET; - dst->sin_len = sizeof(*dst); - dst->sin_addr = ip->ip_dst; - } - /* - * If routing to interface only, - * short circuit routing lookup. - */ -#define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) -#define sintosa(sin) ((struct sockaddr *)(sin)) - if (flags & IP_ROUTETOIF) { - if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 && - (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) { - ipstat.ips_noroute++; - error = ENETUNREACH; - goto bad; - } - ifp = ia->ia_ifp; - ip->ip_ttl = 1; - isbroadcast = in_broadcast(dst->sin_addr, ifp); - } else { - /* - * If this is the case, we probably don't want to allocate - * a protocol-cloned route since we didn't get one from the - * ULP. This lets TCP do its thing, while not burdening - * forwarding or ICMP with the overhead of cloning a route. - * Of course, we still want to do any cloning requested by - * the link layer, as this is probably required in all cases - * for correct operation (as it is for ARP). - */ - if (ro->ro_rt == 0) - rtalloc_ign(ro, RTF_PRCLONING); - if (ro->ro_rt == 0) { - ipstat.ips_noroute++; - error = EHOSTUNREACH; - goto bad; - } - ia = ifatoia(ro->ro_rt->rt_ifa); - ifp = ro->ro_rt->rt_ifp; - ro->ro_rt->rt_use++; - if (ro->ro_rt->rt_flags & RTF_GATEWAY) - dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; - if (ro->ro_rt->rt_flags & RTF_HOST) - isbroadcast = (ro->ro_rt->rt_flags & RTF_BROADCAST); - else - isbroadcast = in_broadcast(dst->sin_addr, ifp); - } - if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { - struct in_multi *inm; - - m->m_flags |= M_MCAST; - /* - * IP destination address is multicast. Make sure "dst" - * still points to the address in "ro". (It may have been - * changed to point to a gateway address, above.) - */ - dst = (struct sockaddr_in *)&ro->ro_dst; - /* - * See if the caller provided any multicast options - */ - if (imo != NULL) { - ip->ip_ttl = imo->imo_multicast_ttl; - if (imo->imo_multicast_ifp != NULL) - ifp = imo->imo_multicast_ifp; - if (imo->imo_multicast_vif != -1) - ip->ip_src.s_addr = - ip_mcast_src(imo->imo_multicast_vif); - } else - ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL; - /* - * Confirm that the outgoing interface supports multicast. - */ - if ((imo == NULL) || (imo->imo_multicast_vif == -1)) { - if ((ifp->if_flags & IFF_MULTICAST) == 0) { - ipstat.ips_noroute++; - error = ENETUNREACH; - goto bad; - } - } - /* - * If source address not specified yet, use address - * of outgoing interface. - */ - if (ip->ip_src.s_addr == INADDR_ANY) { - register struct in_ifaddr *ia; - - for (ia = in_ifaddr; ia; ia = ia->ia_next) - if (ia->ia_ifp == ifp) { - ip->ip_src = IA_SIN(ia)->sin_addr; - break; - } - } - - IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm); - if (inm != NULL && - (imo == NULL || imo->imo_multicast_loop)) { - /* - * If we belong to the destination multicast group - * on the outgoing interface, and the caller did not - * forbid loopback, loop back a copy. - */ - ip_mloopback(ifp, m, dst, hlen); - } - else { - /* - * If we are acting as a multicast router, perform - * multicast forwarding as if the packet had just - * arrived on the interface to which we are about - * to send. The multicast forwarding function - * recursively calls this function, using the - * IP_FORWARDING flag to prevent infinite recursion. - * - * Multicasts that are looped back by ip_mloopback(), - * above, will be forwarded by the ip_input() routine, - * if necessary. - */ - if (ip_mrouter && (flags & IP_FORWARDING) == 0) { - /* - * Check if rsvp daemon is running. If not, don't - * set ip_moptions. This ensures that the packet - * is multicast and not just sent down one link - * as prescribed by rsvpd. - */ - if (!rsvp_on) - imo = NULL; - if (ip_mforward(ip, ifp, m, imo) != 0) { - m_freem(m); - goto done; - } - } - } - - /* - * Multicasts with a time-to-live of zero may be looped- - * back, above, but must not be transmitted on a network. - * Also, multicasts addressed to the loopback interface - * are not sent -- the above call to ip_mloopback() will - * loop back a copy if this host actually belongs to the - * destination group on the loopback interface. - */ - if (ip->ip_ttl == 0 || ifp->if_flags & IFF_LOOPBACK) { - m_freem(m); - goto done; - } - - goto sendit; - } -#ifndef notdef - /* - * If source address not specified yet, use address - * of outgoing interface. - */ - if (ip->ip_src.s_addr == INADDR_ANY) - ip->ip_src = IA_SIN(ia)->sin_addr; -#endif - /* - * Verify that we have any chance at all of being able to queue - * the packet or packet fragments - */ - if ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >= - ifp->if_snd.ifq_maxlen) { - error = ENOBUFS; - goto bad; - } - - /* - * Look for broadcast address and - * and verify user is allowed to send - * such a packet. - */ - if (isbroadcast) { - if ((ifp->if_flags & IFF_BROADCAST) == 0) { - error = EADDRNOTAVAIL; - goto bad; - } - if ((flags & IP_ALLOWBROADCAST) == 0) { - error = EACCES; - goto bad; - } - /* don't allow broadcast messages to be fragmented */ - if ((u_short)ip->ip_len > ifp->if_mtu) { - error = EMSGSIZE; - goto bad; - } - m->m_flags |= M_BCAST; - } else { - m->m_flags &= ~M_BCAST; - } - -sendit: - /* - * IpHack's section. - * - Xlate: translate packet's addr/port (NAT). - * - Firewall: deny/allow/etc. - * - Wrap: fake packet's addr/port <unimpl.> - * - Encapsulate: put it in another IP and send out. <unimp.> - */ - -#ifdef COMPAT_IPFW - if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, ifp, IP_NAT_OUT)) { - error = EACCES; - goto done; - } - - /* - * Check with the firewall... - */ - if (ip_fw_chk_ptr) { -#ifdef IPDIVERT - ip_divert_port = (*ip_fw_chk_ptr)(&ip, - hlen, ifp, ip_divert_ignore, &m); - ip_divert_ignore = 0; - if (ip_divert_port) { /* Divert packet */ - (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, 0); - goto done; - } -#else - /* If ipfw says divert, we have to just drop packet */ - if ((*ip_fw_chk_ptr)(&ip, hlen, ifp, 0, &m)) { - m_freem(m); - goto done; - } -#endif - if (!m) { - error = EACCES; - goto done; - } - } -#endif /* COMPAT_IPFW */ - - /* - * If small enough for interface, can just send directly. - */ - if ((u_short)ip->ip_len <= ifp->if_mtu) { - ip->ip_len = htons((u_short)ip->ip_len); - ip->ip_off = htons((u_short)ip->ip_off); - ip->ip_sum = 0; - if (ip->ip_vhl == IP_VHL_BORING) { - ip->ip_sum = in_cksum_hdr(ip); - } else { - ip->ip_sum = in_cksum(m, hlen); - } - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst, ro->ro_rt); - goto done; - } - /* - * Too large for interface; fragment if possible. - * Must be able to put at least 8 bytes per fragment. - */ - if (ip->ip_off & IP_DF) { - error = EMSGSIZE; - /* - * This case can happen if the user changed the MTU - * of an interface after enabling IP on it. Because - * most netifs don't keep track of routes pointing to - * them, there is no way for one to update all its - * routes when the MTU is changed. - */ - if ((ro->ro_rt->rt_flags & (RTF_UP | RTF_HOST)) - && !(ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU) - && (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)) { - ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu; - } - ipstat.ips_cantfrag++; - goto bad; - } - len = (ifp->if_mtu - hlen) &~ 7; - if (len < 8) { - error = EMSGSIZE; - goto bad; - } - - { - int mhlen, firstlen = len; - struct mbuf **mnext = &m->m_nextpkt; - - /* - * Loop through length of segment after first fragment, - * make new header and copy data of each part and link onto chain. - */ - m0 = m; - mhlen = sizeof (struct ip); - for (off = hlen + len; off < (u_short)ip->ip_len; off += len) { - MGETHDR(m, M_DONTWAIT, MT_HEADER); - if (m == 0) { - error = ENOBUFS; - ipstat.ips_odropped++; - goto sendorfree; - } - m->m_data += max_linkhdr; - mhip = mtod(m, struct ip *); - *mhip = *ip; - if (hlen > sizeof (struct ip)) { - mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); - mhip->ip_vhl = IP_MAKE_VHL(IPVERSION, mhlen >> 2); - } - m->m_len = mhlen; - mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); - if (ip->ip_off & IP_MF) - mhip->ip_off |= IP_MF; - if (off + len >= (u_short)ip->ip_len) - len = (u_short)ip->ip_len - off; - else - mhip->ip_off |= IP_MF; - mhip->ip_len = htons((u_short)(len + mhlen)); - m->m_next = m_copy(m0, off, len); - if (m->m_next == 0) { - (void) m_free(m); - error = ENOBUFS; /* ??? */ - ipstat.ips_odropped++; - goto sendorfree; - } - m->m_pkthdr.len = mhlen + len; - m->m_pkthdr.rcvif = (struct ifnet *)0; - mhip->ip_off = htons((u_short)mhip->ip_off); - mhip->ip_sum = 0; - if (mhip->ip_vhl == IP_VHL_BORING) { - mhip->ip_sum = in_cksum_hdr(mhip); - } else { - mhip->ip_sum = in_cksum(m, mhlen); - } - *mnext = m; - mnext = &m->m_nextpkt; - ipstat.ips_ofragments++; - } - /* - * Update first fragment by trimming what's been copied out - * and updating header, then send each fragment (in order). - */ - m = m0; - m_adj(m, hlen + firstlen - (u_short)ip->ip_len); - m->m_pkthdr.len = hlen + firstlen; - ip->ip_len = htons((u_short)m->m_pkthdr.len); - ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; - if (ip->ip_vhl == IP_VHL_BORING) { - ip->ip_sum = in_cksum_hdr(ip); - } else { - ip->ip_sum = in_cksum(m, hlen); - } -sendorfree: - for (m = m0; m; m = m0) { - m0 = m->m_nextpkt; - m->m_nextpkt = 0; - if (error == 0) - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst, ro->ro_rt); - else - m_freem(m); - } - - if (error == 0) - ipstat.ips_fragmented++; - } -done: - return (error); -bad: - m_freem(m0); - goto done; -} - -/* - * Insert IP options into preformed packet. - * Adjust IP destination as required for IP source routing, - * as indicated by a non-zero in_addr at the start of the options. - * - * XXX This routine assumes that the packet has no options in place. - */ -static struct mbuf * -ip_insertoptions(m, opt, phlen) - register struct mbuf *m; - struct mbuf *opt; - int *phlen; -{ - register struct ipoption *p = mtod(opt, struct ipoption *); - struct mbuf *n; - register struct ip *ip = mtod(m, struct ip *); - unsigned optlen; - - optlen = opt->m_len - sizeof(p->ipopt_dst); - if (optlen + (u_short)ip->ip_len > IP_MAXPACKET) - return (m); /* XXX should fail */ - if (p->ipopt_dst.s_addr) - ip->ip_dst = p->ipopt_dst; - if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) { - MGETHDR(n, M_DONTWAIT, MT_HEADER); - if (n == 0) - return (m); - n->m_pkthdr.len = m->m_pkthdr.len + optlen; - m->m_len -= sizeof(struct ip); - m->m_data += sizeof(struct ip); - n->m_next = m; - m = n; - m->m_len = optlen + sizeof(struct ip); - m->m_data += max_linkhdr; - (void)memcpy(mtod(m, void *), ip, sizeof(struct ip)); - } else { - m->m_data -= optlen; - m->m_len += optlen; - m->m_pkthdr.len += optlen; - ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip)); - } - ip = mtod(m, struct ip *); - bcopy(p->ipopt_list, ip + 1, optlen); - *phlen = sizeof(struct ip) + optlen; - ip->ip_vhl = IP_MAKE_VHL(IPVERSION, *phlen >> 2); - ip->ip_len += optlen; - return (m); -} - -/* - * Copy options from ip to jp, - * omitting those not copied during fragmentation. - */ -static int -ip_optcopy(ip, jp) - struct ip *ip, *jp; -{ - register u_char *cp, *dp; - int opt, optlen, cnt; - - cp = (u_char *)(ip + 1); - dp = (u_char *)(jp + 1); - cnt = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip); - for (; cnt > 0; cnt -= optlen, cp += optlen) { - opt = cp[0]; - if (opt == IPOPT_EOL) - break; - if (opt == IPOPT_NOP) { - /* Preserve for IP mcast tunnel's LSRR alignment. */ - *dp++ = IPOPT_NOP; - optlen = 1; - continue; - } else - optlen = cp[IPOPT_OLEN]; - /* bogus lengths should have been caught by ip_dooptions */ - if (optlen > cnt) - optlen = cnt; - if (IPOPT_COPIED(opt)) { - bcopy(cp, dp, optlen); - dp += optlen; - } - } - for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++) - *dp++ = IPOPT_EOL; - return (optlen); -} - -/* - * IP socket option processing. - */ -int -ip_ctloutput(op, so, level, optname, mp) - int op; - struct socket *so; - int level, optname; - struct mbuf **mp; -{ - register struct inpcb *inp = sotoinpcb(so); - register struct mbuf *m = *mp; - register int optval = 0; - int error = 0; - - if (level != IPPROTO_IP) { - error = EINVAL; - if (op == PRCO_SETOPT && *mp) - (void) m_free(*mp); - } else switch (op) { - - case PRCO_SETOPT: - switch (optname) { - case IP_OPTIONS: -#ifdef notyet - case IP_RETOPTS: - return (ip_pcbopts(optname, &inp->inp_options, m)); -#else - return (ip_pcbopts(&inp->inp_options, m)); -#endif - - case IP_TOS: - case IP_TTL: - case IP_RECVOPTS: - case IP_RECVRETOPTS: - case IP_RECVDSTADDR: - case IP_RECVIF: - if (m == 0 || m->m_len != sizeof(int)) - error = EINVAL; - else { - optval = *mtod(m, int *); - switch (optname) { - - case IP_TOS: - inp->inp_ip_tos = optval; - break; - - case IP_TTL: - inp->inp_ip_ttl = optval; - break; -#define OPTSET(bit) \ - if (optval) \ - inp->inp_flags |= bit; \ - else \ - inp->inp_flags &= ~bit; - - case IP_RECVOPTS: - OPTSET(INP_RECVOPTS); - break; - - case IP_RECVRETOPTS: - OPTSET(INP_RECVRETOPTS); - break; - - case IP_RECVDSTADDR: - OPTSET(INP_RECVDSTADDR); - break; - - case IP_RECVIF: - OPTSET(INP_RECVIF); - break; - } - } - break; -#undef OPTSET - - case IP_MULTICAST_IF: - case IP_MULTICAST_VIF: - case IP_MULTICAST_TTL: - case IP_MULTICAST_LOOP: - case IP_ADD_MEMBERSHIP: - case IP_DROP_MEMBERSHIP: - error = ip_setmoptions(optname, &inp->inp_moptions, m); - break; - - case IP_PORTRANGE: - if (m == 0 || m->m_len != sizeof(int)) - error = EINVAL; - else { - optval = *mtod(m, int *); - - switch (optval) { - - case IP_PORTRANGE_DEFAULT: - inp->inp_flags &= ~(INP_LOWPORT); - inp->inp_flags &= ~(INP_HIGHPORT); - break; - - case IP_PORTRANGE_HIGH: - inp->inp_flags &= ~(INP_LOWPORT); - inp->inp_flags |= INP_HIGHPORT; - break; - - case IP_PORTRANGE_LOW: - inp->inp_flags &= ~(INP_HIGHPORT); - inp->inp_flags |= INP_LOWPORT; - break; - - default: - error = EINVAL; - break; - } - } - break; - - default: - error = ENOPROTOOPT; - break; - } - if (m) - (void)m_free(m); - break; - - case PRCO_GETOPT: - switch (optname) { - case IP_OPTIONS: - case IP_RETOPTS: - *mp = m = m_get(M_WAIT, MT_SOOPTS); - if (inp->inp_options) { - m->m_len = inp->inp_options->m_len; - bcopy(mtod(inp->inp_options, void *), - mtod(m, void *), m->m_len); - } else - m->m_len = 0; - break; - - case IP_TOS: - case IP_TTL: - case IP_RECVOPTS: - case IP_RECVRETOPTS: - case IP_RECVDSTADDR: - case IP_RECVIF: - *mp = m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(int); - switch (optname) { - - case IP_TOS: - optval = inp->inp_ip_tos; - break; - - case IP_TTL: - optval = inp->inp_ip_ttl; - break; - -#define OPTBIT(bit) (inp->inp_flags & bit ? 1 : 0) - - case IP_RECVOPTS: - optval = OPTBIT(INP_RECVOPTS); - break; - - case IP_RECVRETOPTS: - optval = OPTBIT(INP_RECVRETOPTS); - break; - - case IP_RECVDSTADDR: - optval = OPTBIT(INP_RECVDSTADDR); - break; - - case IP_RECVIF: - optval = OPTBIT(INP_RECVIF); - break; - } - *mtod(m, int *) = optval; - break; - - case IP_MULTICAST_IF: - case IP_MULTICAST_VIF: - case IP_MULTICAST_TTL: - case IP_MULTICAST_LOOP: - case IP_ADD_MEMBERSHIP: - case IP_DROP_MEMBERSHIP: - error = ip_getmoptions(optname, inp->inp_moptions, mp); - break; - - case IP_PORTRANGE: - *mp = m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(int); - - if (inp->inp_flags & INP_HIGHPORT) - optval = IP_PORTRANGE_HIGH; - else if (inp->inp_flags & INP_LOWPORT) - optval = IP_PORTRANGE_LOW; - else - optval = 0; - - *mtod(m, int *) = optval; - break; - - default: - error = ENOPROTOOPT; - break; - } - break; - } - return (error); -} - -/* - * Set up IP options in pcb for insertion in output packets. - * Store in mbuf with pointer in pcbopt, adding pseudo-option - * with destination address if source routed. - */ -static int -#ifdef notyet -ip_pcbopts(optname, pcbopt, m) - int optname; -#else -ip_pcbopts(pcbopt, m) -#endif - struct mbuf **pcbopt; - register struct mbuf *m; -{ - register int cnt, optlen; - register u_char *cp; - u_char opt; - - /* turn off any old options */ - if (*pcbopt) - (void)m_free(*pcbopt); - *pcbopt = 0; - if (m == (struct mbuf *)0 || m->m_len == 0) { - /* - * Only turning off any previous options. - */ - if (m) - (void)m_free(m); - return (0); - } - -#ifndef vax - if (m->m_len % sizeof(long)) - goto bad; -#endif - /* - * IP first-hop destination address will be stored before - * actual options; move other options back - * and clear it when none present. - */ - if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN]) - goto bad; - cnt = m->m_len; - m->m_len += sizeof(struct in_addr); - cp = mtod(m, u_char *) + sizeof(struct in_addr); - ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt); - bzero(mtod(m, caddr_t), sizeof(struct in_addr)); - - for (; cnt > 0; cnt -= optlen, cp += optlen) { - opt = cp[IPOPT_OPTVAL]; - if (opt == IPOPT_EOL) - break; - if (opt == IPOPT_NOP) - optlen = 1; - else { - optlen = cp[IPOPT_OLEN]; - if (optlen <= IPOPT_OLEN || optlen > cnt) - goto bad; - } - switch (opt) { - - default: - break; - - case IPOPT_LSRR: - case IPOPT_SSRR: - /* - * user process specifies route as: - * ->A->B->C->D - * D must be our final destination (but we can't - * check that since we may not have connected yet). - * A is first hop destination, which doesn't appear in - * actual IP option, but is stored before the options. - */ - if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr)) - goto bad; - m->m_len -= sizeof(struct in_addr); - cnt -= sizeof(struct in_addr); - optlen -= sizeof(struct in_addr); - cp[IPOPT_OLEN] = optlen; - /* - * Move first hop before start of options. - */ - bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t), - sizeof(struct in_addr)); - /* - * Then copy rest of options back - * to close up the deleted entry. - */ - ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] + - sizeof(struct in_addr)), - (caddr_t)&cp[IPOPT_OFFSET+1], - (unsigned)cnt + sizeof(struct in_addr)); - break; - } - } - if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr)) - goto bad; - *pcbopt = m; - return (0); - -bad: - (void)m_free(m); - return (EINVAL); -} - -/* - * Set the IP multicast options in response to user setsockopt(). - */ -static int -ip_setmoptions(optname, imop, m) - int optname; - struct ip_moptions **imop; - struct mbuf *m; -{ - register int error = 0; - u_char loop; - register int i; - struct in_addr addr; - register struct ip_mreq *mreq; - register struct ifnet *ifp; - register struct ip_moptions *imo = *imop; - struct route ro; - register struct sockaddr_in *dst; - int s; - - if (imo == NULL) { - /* - * No multicast option buffer attached to the pcb; - * allocate one and initialize to default values. - */ - imo = (struct ip_moptions*)malloc(sizeof(*imo), M_IPMOPTS, - M_WAITOK); - - if (imo == NULL) - return (ENOBUFS); - *imop = imo; - imo->imo_multicast_ifp = NULL; - imo->imo_multicast_vif = -1; - imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; - imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; - imo->imo_num_memberships = 0; - } - - switch (optname) { - /* store an index number for the vif you wanna use in the send */ - case IP_MULTICAST_VIF: - if (!legal_vif_num) { - error = EOPNOTSUPP; - break; - } - if (m == NULL || m->m_len != sizeof(int)) { - error = EINVAL; - break; - } - i = *(mtod(m, int *)); - if (!legal_vif_num(i) && (i != -1)) { - error = EINVAL; - break; - } - imo->imo_multicast_vif = i; - break; - - case IP_MULTICAST_IF: - /* - * Select the interface for outgoing multicast packets. - */ - if (m == NULL || m->m_len != sizeof(struct in_addr)) { - error = EINVAL; - break; - } - addr = *(mtod(m, struct in_addr *)); - /* - * INADDR_ANY is used to remove a previous selection. - * When no interface is selected, a default one is - * chosen every time a multicast packet is sent. - */ - if (addr.s_addr == INADDR_ANY) { - imo->imo_multicast_ifp = NULL; - break; - } - /* - * The selected interface is identified by its local - * IP address. Find the interface and confirm that - * it supports multicasting. - */ - s = splimp(); - INADDR_TO_IFP(addr, ifp); - if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) { - splx(s); - error = EADDRNOTAVAIL; - break; - } - imo->imo_multicast_ifp = ifp; - splx(s); - break; - - case IP_MULTICAST_TTL: - /* - * Set the IP time-to-live for outgoing multicast packets. - */ - if (m == NULL || m->m_len != 1) { - error = EINVAL; - break; - } - imo->imo_multicast_ttl = *(mtod(m, u_char *)); - break; - - case IP_MULTICAST_LOOP: - /* - * Set the loopback flag for outgoing multicast packets. - * Must be zero or one. - */ - if (m == NULL || m->m_len != 1 || - (loop = *(mtod(m, u_char *))) > 1) { - error = EINVAL; - break; - } - imo->imo_multicast_loop = loop; - break; - - case IP_ADD_MEMBERSHIP: - /* - * Add a multicast group membership. - * Group must be a valid IP multicast address. - */ - if (m == NULL || m->m_len != sizeof(struct ip_mreq)) { - error = EINVAL; - break; - } - mreq = mtod(m, struct ip_mreq *); - if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) { - error = EINVAL; - break; - } - s = splimp(); - /* - * If no interface address was provided, use the interface of - * the route to the given multicast address. - */ - if (mreq->imr_interface.s_addr == INADDR_ANY) { - bzero((caddr_t)&ro, sizeof(ro)); - dst = (struct sockaddr_in *)&ro.ro_dst; - dst->sin_len = sizeof(*dst); - dst->sin_family = AF_INET; - dst->sin_addr = mreq->imr_multiaddr; - rtalloc(&ro); - if (ro.ro_rt == NULL) { - error = EADDRNOTAVAIL; - splx(s); - break; - } - ifp = ro.ro_rt->rt_ifp; - rtfree(ro.ro_rt); - } - else { - INADDR_TO_IFP(mreq->imr_interface, ifp); - } - - /* - * See if we found an interface, and confirm that it - * supports multicast. - */ - if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) { - error = EADDRNOTAVAIL; - splx(s); - break; - } - /* - * See if the membership already exists or if all the - * membership slots are full. - */ - for (i = 0; i < imo->imo_num_memberships; ++i) { - if (imo->imo_membership[i]->inm_ifp == ifp && - imo->imo_membership[i]->inm_addr.s_addr - == mreq->imr_multiaddr.s_addr) - break; - } - if (i < imo->imo_num_memberships) { - error = EADDRINUSE; - splx(s); - break; - } - if (i == IP_MAX_MEMBERSHIPS) { - error = ETOOMANYREFS; - splx(s); - break; - } - /* - * Everything looks good; add a new record to the multicast - * address list for the given interface. - */ - if ((imo->imo_membership[i] = - in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) { - error = ENOBUFS; - splx(s); - break; - } - ++imo->imo_num_memberships; - splx(s); - break; - - case IP_DROP_MEMBERSHIP: - /* - * Drop a multicast group membership. - * Group must be a valid IP multicast address. - */ - if (m == NULL || m->m_len != sizeof(struct ip_mreq)) { - error = EINVAL; - break; - } - mreq = mtod(m, struct ip_mreq *); - if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) { - error = EINVAL; - break; - } - - s = splimp(); - /* - * If an interface address was specified, get a pointer - * to its ifnet structure. - */ - if (mreq->imr_interface.s_addr == INADDR_ANY) - ifp = NULL; - else { - INADDR_TO_IFP(mreq->imr_interface, ifp); - if (ifp == NULL) { - error = EADDRNOTAVAIL; - splx(s); - break; - } - } - /* - * Find the membership in the membership array. - */ - for (i = 0; i < imo->imo_num_memberships; ++i) { - if ((ifp == NULL || - imo->imo_membership[i]->inm_ifp == ifp) && - imo->imo_membership[i]->inm_addr.s_addr == - mreq->imr_multiaddr.s_addr) - break; - } - if (i == imo->imo_num_memberships) { - error = EADDRNOTAVAIL; - splx(s); - break; - } - /* - * Give up the multicast address record to which the - * membership points. - */ - in_delmulti(imo->imo_membership[i]); - /* - * Remove the gap in the membership array. - */ - for (++i; i < imo->imo_num_memberships; ++i) - imo->imo_membership[i-1] = imo->imo_membership[i]; - --imo->imo_num_memberships; - splx(s); - break; - - default: - error = EOPNOTSUPP; - break; - } - - /* - * If all options have default values, no need to keep the mbuf. - */ - if (imo->imo_multicast_ifp == NULL && - imo->imo_multicast_vif == -1 && - imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL && - imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP && - imo->imo_num_memberships == 0) { - free(*imop, M_IPMOPTS); - *imop = NULL; - } - - return (error); -} - -/* - * Return the IP multicast options in response to user getsockopt(). - */ -static int -ip_getmoptions(optname, imo, mp) - int optname; - register struct ip_moptions *imo; - register struct mbuf **mp; -{ - u_char *ttl; - u_char *loop; - struct in_addr *addr; - struct in_ifaddr *ia; - - *mp = m_get(M_WAIT, MT_SOOPTS); - - switch (optname) { - - case IP_MULTICAST_VIF: - if (imo != NULL) - *(mtod(*mp, int *)) = imo->imo_multicast_vif; - else - *(mtod(*mp, int *)) = -1; - (*mp)->m_len = sizeof(int); - return(0); - - case IP_MULTICAST_IF: - addr = mtod(*mp, struct in_addr *); - (*mp)->m_len = sizeof(struct in_addr); - if (imo == NULL || imo->imo_multicast_ifp == NULL) - addr->s_addr = INADDR_ANY; - else { - IFP_TO_IA(imo->imo_multicast_ifp, ia); - addr->s_addr = (ia == NULL) ? INADDR_ANY - : IA_SIN(ia)->sin_addr.s_addr; - } - return (0); - - case IP_MULTICAST_TTL: - ttl = mtod(*mp, u_char *); - (*mp)->m_len = 1; - *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL - : imo->imo_multicast_ttl; - return (0); - - case IP_MULTICAST_LOOP: - loop = mtod(*mp, u_char *); - (*mp)->m_len = 1; - *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP - : imo->imo_multicast_loop; - return (0); - - default: - return (EOPNOTSUPP); - } -} - -/* - * Discard the IP multicast options. - */ -void -ip_freemoptions(imo) - register struct ip_moptions *imo; -{ - register int i; - - if (imo != NULL) { - for (i = 0; i < imo->imo_num_memberships; ++i) - in_delmulti(imo->imo_membership[i]); - free(imo, M_IPMOPTS); - } -} - -/* - * Routine called from ip_output() to loop back a copy of an IP multicast - * packet to the input queue of a specified interface. Note that this - * calls the output routine of the loopback "driver", but with an interface - * pointer that might NOT be a loopback interface -- evil, but easier than - * replicating that code here. - */ -static void -ip_mloopback(ifp, m, dst, hlen) - struct ifnet *ifp; - register struct mbuf *m; - register struct sockaddr_in *dst; - int hlen; -{ - register struct ip *ip; - struct mbuf *copym; - - copym = m_copy(m, 0, M_COPYALL); - if (copym != NULL && (copym->m_flags & M_EXT || copym->m_len < hlen)) - copym = m_pullup(copym, hlen); - if (copym != NULL) { - /* - * We don't bother to fragment if the IP length is greater - * than the interface's MTU. Can this possibly matter? - */ - ip = mtod(copym, struct ip *); - ip->ip_len = htons((u_short)ip->ip_len); - ip->ip_off = htons((u_short)ip->ip_off); - ip->ip_sum = 0; - if (ip->ip_vhl == IP_VHL_BORING) { - ip->ip_sum = in_cksum_hdr(ip); - } else { - ip->ip_sum = in_cksum(copym, hlen); - } - /* - * NB: - * It's not clear whether there are any lingering - * reentrancy problems in other areas which might - * be exposed by using ip_input directly (in - * particular, everything which modifies the packet - * in-place). Yet another option is using the - * protosw directly to deliver the looped back - * packet. For the moment, we'll err on the side - * of safety by continuing to abuse looutput(). - */ -#ifdef notdef - copym->m_pkthdr.rcvif = ifp; - ip_input(copym) -#else - (void) looutput(ifp, copym, (struct sockaddr *)dst, NULL); -#endif - } -} diff --git a/c/src/exec/libnetworking/netinet/ip_var.h b/c/src/exec/libnetworking/netinet/ip_var.h deleted file mode 100644 index 38e7896c4a..0000000000 --- a/c/src/exec/libnetworking/netinet/ip_var.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)ip_var.h 8.2 (Berkeley) 1/9/95 - * $Id$ - */ - -#ifndef _NETINET_IP_VAR_H_ -#define _NETINET_IP_VAR_H_ - -/* - * Overlay for ip header used by other protocols (tcp, udp). - */ -struct ipovly { - caddr_t ih_next BYTE_PACK; - caddr_t ih_prev BYTE_PACK; /* for protocol sequence q's */ - u_char ih_x1; /* (unused) */ - u_char ih_pr; /* protocol */ - u_short ih_len BYTE_PACK; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ -}; - -/* - * Ip reassembly queue structure. Each fragment - * being reassembled is attached to one of these structures. - * They are timed out after ipq_ttl drops to 0, and may also - * be reclaimed if memory becomes tight. - */ -struct ipq { - struct ipq *next,*prev; /* to other reass headers */ - u_char ipq_ttl; /* time for reass q to live */ - u_char ipq_p; /* protocol of this fragment */ - u_short ipq_id BYTE_PACK; /* sequence id for reassembly */ - struct ipasfrag *ipq_next,*ipq_prev; - /* to ip headers of fragments */ - struct in_addr ipq_src,ipq_dst; -#ifdef IPDIVERT - u_short ipq_divert BYTE_PACK; /* divert protocol port */ -#endif -}; - -/* - * Ip header, when holding a fragment. - * - * Note: ipf_next must be at same offset as ipq_next above - */ -struct ipasfrag { -#if BYTE_ORDER == LITTLE_ENDIAN - u_char ip_hl:4, - ip_v:4; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_char ip_v:4, - ip_hl:4; -#endif - u_char ipf_mff; /* XXX overlays ip_tos: use low bit - * to avoid destroying tos; - * copied from (ip_off&IP_MF) */ - u_short ip_len BYTE_PACK; - u_short ip_id BYTE_PACK; - u_short ip_off BYTE_PACK; - u_char ip_ttl; - u_char ip_p; - u_short ip_sum BYTE_PACK; - struct ipasfrag *ipf_next; /* next fragment */ - struct ipasfrag *ipf_prev; /* previous fragment */ -}; - -/* - * Structure stored in mbuf in inpcb.ip_options - * and passed to ip_output when ip options are in use. - * The actual length of the options (including ipopt_dst) - * is in m_len. - */ -#define MAX_IPOPTLEN 40 - -struct ipoption { - struct in_addr ipopt_dst; /* first-hop dst if source routed */ - char ipopt_list[MAX_IPOPTLEN]; /* options proper */ -}; - -/* - * Structure attached to inpcb.ip_moptions and - * passed to ip_output when IP multicast options are in use. - */ -struct ip_moptions { - struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */ - u_char imo_multicast_ttl; /* TTL for outgoing multicasts */ - u_char imo_multicast_loop; /* 1 => hear sends if a member */ - u_short imo_num_memberships; /* no. memberships this socket */ - struct in_multi *imo_membership[IP_MAX_MEMBERSHIPS]; - u_long imo_multicast_vif; /* vif num outgoing multicasts */ -}; - -struct ipstat { - u_long ips_total; /* total packets received */ - u_long ips_badsum; /* checksum bad */ - u_long ips_tooshort; /* packet too short */ - u_long ips_toosmall; /* not enough data */ - u_long ips_badhlen; /* ip header length < data size */ - u_long ips_badlen; /* ip length < ip header length */ - u_long ips_fragments; /* fragments received */ - u_long ips_fragdropped; /* frags dropped (dups, out of space) */ - u_long ips_fragtimeout; /* fragments timed out */ - u_long ips_forward; /* packets forwarded */ - u_long ips_cantforward; /* packets rcvd for unreachable dest */ - u_long ips_redirectsent; /* packets forwarded on same net */ - u_long ips_noproto; /* unknown or unsupported protocol */ - u_long ips_delivered; /* datagrams delivered to upper level*/ - u_long ips_localout; /* total ip packets generated here */ - u_long ips_odropped; /* lost packets due to nobufs, etc. */ - u_long ips_reassembled; /* total packets reassembled ok */ - u_long ips_fragmented; /* datagrams successfully fragmented */ - u_long ips_ofragments; /* output fragments created */ - u_long ips_cantfrag; /* don't fragment flag was set, etc. */ - u_long ips_badoptions; /* error in option processing */ - u_long ips_noroute; /* packets discarded due to no route */ - u_long ips_badvers; /* ip version != 4 */ - u_long ips_rawout; /* total raw ip packets generated */ - u_long ips_toolong; /* ip length > max ip packet size */ -}; - -#ifdef KERNEL -/* flags passed to ip_output as last parameter */ -#define IP_FORWARDING 0x1 /* most of ip header exists */ -#define IP_RAWOUTPUT 0x2 /* raw ip header exists */ -#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */ -#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ - -struct inpcb; -struct route; - -extern struct ipstat ipstat; -extern u_short ip_id; /* ip packet ctr, for ids */ -extern int ip_defttl; /* default IP ttl */ -extern u_char ip_protox[]; -extern struct socket *ip_rsvpd; /* reservation protocol daemon */ -extern struct socket *ip_mrouter; /* multicast routing daemon */ -extern int (*legal_vif_num) __P((int)); -extern u_long (*ip_mcast_src) __P((int)); -extern int rsvp_on; - -int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); -void ip_drain __P((void)); -void ip_freemoptions __P((struct ip_moptions *)); -void ip_init __P((void)); -extern int (*ip_mforward) __P((struct ip *, struct ifnet *, struct mbuf *, - struct ip_moptions *)); -int ip_output __P((struct mbuf *, - struct mbuf *, struct route *, int, struct ip_moptions *)); -void ip_savecontrol __P((struct inpcb *, struct mbuf **, struct ip *, - struct mbuf *)); -void ip_slowtimo __P((void)); -struct mbuf * - ip_srcroute __P((void)); -void ip_stripoptions __P((struct mbuf *, struct mbuf *)); -int rip_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); -void rip_init __P((void)); -void rip_input __P((struct mbuf *, int)); -int rip_output __P((struct mbuf *, struct socket *, u_long)); -int rip_usrreq __P((struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *)); -void ipip_input __P((struct mbuf *, int)); -void rsvp_input __P((struct mbuf *, int)); -int ip_rsvp_init __P((struct socket *)); -int ip_rsvp_done __P((void)); -int ip_rsvp_vif_init __P((struct socket *, struct mbuf *)); -int ip_rsvp_vif_done __P((struct socket *, struct mbuf *)); -void ip_rsvp_force_done __P((struct socket *)); - -#ifdef IPDIVERT -void div_init __P((void)); -void div_input __P((struct mbuf *, int)); -int div_usrreq __P((struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *)); -extern u_short ip_divert_port; -extern u_short ip_divert_ignore; -#endif /* IPDIVERT */ - -#endif /* KERNEL */ - -#endif /* _NETINET_IP_VAR_H_ */ diff --git a/c/src/exec/libnetworking/netinet/raw_ip.c b/c/src/exec/libnetworking/netinet/raw_ip.c deleted file mode 100644 index 44d58f1844..0000000000 --- a/c/src/exec/libnetworking/netinet/raw_ip.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/protosw.h> -#include <sys/socketvar.h> -#include <sys/errno.h> -#include <sys/systm.h> - -#include <net/if.h> -#include <net/route.h> - -#define _IP_VHL -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/ip_var.h> -#include <netinet/ip_mroute.h> - -#include <netinet/ip_fw.h> - -#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1 -#undef COMPAT_IPFW -#define COMPAT_IPFW 1 -#else -#undef COMPAT_IPFW -#endif - -static struct inpcbhead ripcb; -static struct inpcbinfo ripcbinfo; - -/* - * Nominal space allocated to a raw ip socket. - */ -#define RIPSNDQ 8192 -#define RIPRCVQ 8192 - -/* - * Raw interface to IP protocol. - */ - -/* - * Initialize raw connection block q. - */ -void -rip_init() -{ - LIST_INIT(&ripcb); - ripcbinfo.listhead = &ripcb; - /* - * XXX We don't use the hash list for raw IP, but it's easier - * to allocate a one entry hash list than it is to check all - * over the place for hashbase == NULL. - */ - ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask); -} - -static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; -/* - * Setup generic address and protocol structures - * for raw_input routine, then pass them along with - * mbuf chain. - */ -void -rip_input(m, iphlen) - struct mbuf *m; - int iphlen; -{ - register struct ip *ip = mtod(m, struct ip *); - register struct inpcb *inp; - struct inpcb *last = 0; - struct mbuf *opts = 0; - - ripsrc.sin_addr = ip->ip_src; - for (inp = ripcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { - if (inp->inp_ip_p && inp->inp_ip_p != ip->ip_p) - continue; - if (inp->inp_laddr.s_addr && - inp->inp_laddr.s_addr != ip->ip_dst.s_addr) - continue; - if (inp->inp_faddr.s_addr && - inp->inp_faddr.s_addr != ip->ip_src.s_addr) - continue; - if (last) { - struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); - if (n) { - if (last->inp_flags & INP_CONTROLOPTS || - last->inp_socket->so_options & SO_TIMESTAMP) - ip_savecontrol(last, &opts, ip, n); - if (sbappendaddr(&last->inp_socket->so_rcv, - (struct sockaddr *)&ripsrc, n, - opts) == 0) { - /* should notify about lost packet */ - m_freem(n); - if (opts) - m_freem(opts); - } else - sorwakeup(last->inp_socket); - opts = 0; - } - } - last = inp; - } - if (last) { - if (last->inp_flags & INP_CONTROLOPTS || - last->inp_socket->so_options & SO_TIMESTAMP) - ip_savecontrol(last, &opts, ip, m); - if (sbappendaddr(&last->inp_socket->so_rcv, - (struct sockaddr *)&ripsrc, m, opts) == 0) { - m_freem(m); - if (opts) - m_freem(opts); - } else - sorwakeup(last->inp_socket); - } else { - m_freem(m); - ipstat.ips_noproto++; - ipstat.ips_delivered--; - } -} - -/* - * Generate IP header and pass packet to ip_output. - * Tack on options user may have setup with control call. - */ -int -rip_output(m, so, dst) - register struct mbuf *m; - struct socket *so; - u_long dst; -{ - register struct ip *ip; - register struct inpcb *inp = sotoinpcb(so); - int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; - - /* - * If the user handed us a complete IP packet, use it. - * Otherwise, allocate an mbuf for a header and fill it in. - */ - if ((inp->inp_flags & INP_HDRINCL) == 0) { - if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) { - m_freem(m); - return(EMSGSIZE); - } - M_PREPEND(m, sizeof(struct ip), M_WAIT); - ip = mtod(m, struct ip *); - ip->ip_tos = 0; - ip->ip_off = 0; - ip->ip_p = inp->inp_ip_p; - ip->ip_len = m->m_pkthdr.len; - ip->ip_src = inp->inp_laddr; - ip->ip_dst.s_addr = dst; - ip->ip_ttl = MAXTTL; - } else { - if (m->m_pkthdr.len > IP_MAXPACKET) { - m_freem(m); - return(EMSGSIZE); - } - ip = mtod(m, struct ip *); - /* don't allow both user specified and setsockopt options, - and don't allow packet length sizes that will crash */ - if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2)) - && inp->inp_options) - || (ip->ip_len > m->m_pkthdr.len) - || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) { - m_freem(m); - return EINVAL; - } - if (ip->ip_id == 0) - ip->ip_id = htons(ip_id++); - /* XXX prevent ip_output from overwriting header fields */ - flags |= IP_RAWOUTPUT; - ipstat.ips_rawout++; - } - return (ip_output(m, inp->inp_options, &inp->inp_route, flags, - inp->inp_moptions)); -} - -/* - * Raw IP socket option processing. - */ -int -rip_ctloutput(op, so, level, optname, m) - int op; - struct socket *so; - int level, optname; - struct mbuf **m; -{ - register struct inpcb *inp = sotoinpcb(so); - register int error; - - if (level != IPPROTO_IP) { - if (op == PRCO_SETOPT && *m) - (void)m_free(*m); - return (EINVAL); - } - - switch (optname) { - - case IP_HDRINCL: - error = 0; - if (op == PRCO_SETOPT) { - if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int)) - error = EINVAL; - else if (*mtod(*m, int *)) - inp->inp_flags |= INP_HDRINCL; - else - inp->inp_flags &= ~INP_HDRINCL; - if (*m) - (void)m_free(*m); - } else { - *m = m_get(M_WAIT, MT_SOOPTS); - (*m)->m_len = sizeof (int); - *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL; - } - return (error); - -#ifdef COMPAT_IPFW - case IP_FW_GET: - if (ip_fw_ctl_ptr == NULL || op == PRCO_SETOPT) { - if (*m) (void)m_free(*m); - return(EINVAL); - } - return (*ip_fw_ctl_ptr)(optname, m); - - case IP_FW_ADD: - case IP_FW_DEL: - case IP_FW_FLUSH: - case IP_FW_ZERO: - if (ip_fw_ctl_ptr == NULL || op != PRCO_SETOPT) { - if (*m) (void)m_free(*m); - return(EINVAL); - } - return (*ip_fw_ctl_ptr)(optname, m); - - case IP_NAT: - if (ip_nat_ctl_ptr == NULL) { - if (*m) (void)m_free(*m); - return(EINVAL); - } - return (*ip_nat_ctl_ptr)(op, m); - -#endif - case IP_RSVP_ON: - return ip_rsvp_init(so); - break; - - case IP_RSVP_OFF: - return ip_rsvp_done(); - break; - - case IP_RSVP_VIF_ON: - return ip_rsvp_vif_init(so, *m); - - case IP_RSVP_VIF_OFF: - return ip_rsvp_vif_done(so, *m); - - case MRT_INIT: - case MRT_DONE: - case MRT_ADD_VIF: - case MRT_DEL_VIF: - case MRT_ADD_MFC: - case MRT_DEL_MFC: - case MRT_VERSION: - case MRT_ASSERT: - if (op == PRCO_SETOPT) { - error = ip_mrouter_set(optname, so, *m); - if (*m) - (void)m_free(*m); - } else if (op == PRCO_GETOPT) { - error = ip_mrouter_get(optname, so, m); - } else - error = EINVAL; - return (error); - } - return (ip_ctloutput(op, so, level, optname, m)); -} - -static u_long rip_sendspace = RIPSNDQ; /* XXX sysctl ? */ -static u_long rip_recvspace = RIPRCVQ; /* XXX sysctl ? */ - -/*ARGSUSED*/ -int -rip_usrreq(so, req, m, nam, control) - register struct socket *so; - int req; - struct mbuf *m, *nam, *control; -{ - register int error = 0; - register struct inpcb *inp = sotoinpcb(so); - int s; - - if (req == PRU_CONTROL) - return (in_control(so, (u_long)m, (caddr_t)nam, - (struct ifnet *)control)); - - switch (req) { - - case PRU_ATTACH: - if (inp) - panic("rip_attach"); - if ((so->so_state & SS_PRIV) == 0) { - error = EACCES; - break; - } - s = splnet(); - error = in_pcballoc(so, &ripcbinfo); - splx(s); - if (error) - break; - error = soreserve(so, rip_sendspace, rip_recvspace); - if (error) - break; - inp = (struct inpcb *)so->so_pcb; - inp->inp_ip_p = (int)nam; - break; - - case PRU_DISCONNECT: - if ((so->so_state & SS_ISCONNECTED) == 0) { - error = ENOTCONN; - break; - } - /* FALLTHROUGH */ - case PRU_ABORT: - soisdisconnected(so); - /* FALLTHROUGH */ - case PRU_DETACH: - if (inp == 0) - panic("rip_detach"); - if (so == ip_mrouter) - ip_mrouter_done(); - ip_rsvp_force_done(so); - if (so == ip_rsvpd) - ip_rsvp_done(); - in_pcbdetach(inp); - break; - - case PRU_BIND: - { - struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); - - if (nam->m_len != sizeof(*addr)) { - error = EINVAL; - break; - } - if ((ifnet == 0) || - ((addr->sin_family != AF_INET) && - (addr->sin_family != AF_IMPLINK)) || - (addr->sin_addr.s_addr && - ifa_ifwithaddr((struct sockaddr *)addr) == 0)) { - error = EADDRNOTAVAIL; - break; - } - inp->inp_laddr = addr->sin_addr; - break; - } - case PRU_CONNECT: - { - struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); - - if (nam->m_len != sizeof(*addr)) { - error = EINVAL; - break; - } - if (ifnet == 0) { - error = EADDRNOTAVAIL; - break; - } - if ((addr->sin_family != AF_INET) && - (addr->sin_family != AF_IMPLINK)) { - error = EAFNOSUPPORT; - break; - } - inp->inp_faddr = addr->sin_addr; - soisconnected(so); - break; - } - - case PRU_CONNECT2: - error = EOPNOTSUPP; - break; - - /* - * Mark the connection as being incapable of further input. - */ - case PRU_SHUTDOWN: - socantsendmore(so); - break; - - /* - * Ship a packet out. The appropriate raw output - * routine handles any massaging necessary. - */ - case PRU_SEND: - { - register u_long dst; - - if (so->so_state & SS_ISCONNECTED) { - if (nam) { - error = EISCONN; - break; - } - dst = inp->inp_faddr.s_addr; - } else { - if (nam == NULL) { - error = ENOTCONN; - break; - } - dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr; - } - error = rip_output(m, so, dst); - m = NULL; - break; - } - - case PRU_SENSE: - /* - * stat: don't bother with a blocksize. - */ - return (0); - - /* - * Not supported. - */ - case PRU_RCVOOB: - case PRU_RCVD: - case PRU_LISTEN: - case PRU_ACCEPT: - case PRU_SENDOOB: - error = EOPNOTSUPP; - break; - - case PRU_SOCKADDR: - in_setsockaddr(inp, nam); - break; - - case PRU_PEERADDR: - in_setpeeraddr(inp, nam); - break; - - default: - panic("rip_usrreq"); - } - if (m != NULL) - m_freem(m); - return (error); -} diff --git a/c/src/exec/libnetworking/netinet/tcp.h b/c/src/exec/libnetworking/netinet/tcp.h deleted file mode 100644 index 131d8011cf..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_TCP_H_ -#define _NETINET_TCP_H_ - -typedef u_long tcp_seq; -typedef u_long tcp_cc; /* connection count per rfc1644 */ - -/* - * TCP header. - * Per RFC 793, September, 1981. - */ -struct tcphdr { - u_short th_sport BYTE_PACK; /* source port */ - u_short th_dport BYTE_PACK; /* destination port */ - tcp_seq th_seq BYTE_PACK; /* sequence number */ - tcp_seq th_ack BYTE_PACK; /* acknowledgement number */ -#if BYTE_ORDER == LITTLE_ENDIAN - u_char th_x2:4, /* (unused) */ - th_off:4; /* data offset */ -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_char th_off:4, /* data offset */ - th_x2:4; /* (unused) */ -#endif - u_char th_flags; -#define TH_FIN 0x01 -#define TH_SYN 0x02 -#define TH_RST 0x04 -#define TH_PUSH 0x08 -#define TH_ACK 0x10 -#define TH_URG 0x20 -#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG) - - u_short th_win BYTE_PACK; /* window */ - u_short th_sum BYTE_PACK; /* checksum */ - u_short th_urp BYTE_PACK; /* urgent pointer */ -}; - -#define TCPOPT_EOL 0 -#define TCPOPT_NOP 1 -#define TCPOPT_MAXSEG 2 -#define TCPOLEN_MAXSEG 4 -#define TCPOPT_WINDOW 3 -#define TCPOLEN_WINDOW 3 -#define TCPOPT_SACK_PERMITTED 4 /* Experimental */ -#define TCPOLEN_SACK_PERMITTED 2 -#define TCPOPT_SACK 5 /* Experimental */ -#define TCPOPT_TIMESTAMP 8 -#define TCPOLEN_TIMESTAMP 10 -#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ -#define TCPOPT_TSTAMP_HDR \ - (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) - -#define TCPOPT_CC 11 /* CC options: RFC-1644 */ -#define TCPOPT_CCNEW 12 -#define TCPOPT_CCECHO 13 -#define TCPOLEN_CC 6 -#define TCPOLEN_CC_APPA (TCPOLEN_CC+2) -#define TCPOPT_CC_HDR(ccopt) \ - (TCPOPT_NOP<<24|TCPOPT_NOP<<16|(ccopt)<<8|TCPOLEN_CC) - -/* - * Default maximum segment size for TCP. - * With an IP MSS of 576, this is 536, - * but 512 is probably more convenient. - * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)). - */ -#define TCP_MSS 512 - -#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ -#define TTCP_CLIENT_SND_WND 4096 /* dflt send window for T/TCP client */ - -#define TCP_MAX_WINSHIFT 14 /* maximum window shift */ - -#define TCP_MAXHLEN (0xf<<2) /* max length of header in bytes */ -#define TCP_MAXOLEN (TCP_MAXHLEN - sizeof(struct tcphdr)) - /* max space left for options */ - -/* - * User-settable options (used with setsockopt). - */ -#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ -#define TCP_MAXSEG 0x02 /* set maximum segment size */ -#define TCP_NOPUSH 0x04 /* don't push last block of write */ -#define TCP_NOOPT 0x08 /* don't use TCP options */ - -#endif diff --git a/c/src/exec/libnetworking/netinet/tcp_debug.c b/c/src/exec/libnetworking/netinet/tcp_debug.c deleted file mode 100644 index 2f88ae658e..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_debug.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp_debug.c 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#include "opt_tcpdebug.h" - -#ifdef TCPDEBUG -/* load symbolic names */ -#define PRUREQUESTS -#define TCPSTATES -#define TCPTIMERS -#define TANAMES -#endif - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/protosw.h> -#include <sys/errno.h> - -#include <net/route.h> -#include <net/if.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#include <netinet/tcp_fsm.h> -#include <netinet/tcp_seq.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> -#include <netinet/tcpip.h> -#include <netinet/tcp_debug.h> - -#ifdef TCPDEBUG -static int tcpconsdebug = 0; /* set to 1 to enable prints */ -#endif - -static struct tcp_debug tcp_debug[TCP_NDEBUG]; -static int tcp_debx; - -/* - * Tcp debug routines - */ -void -tcp_trace(act, ostate, tp, ti, req) - short act, ostate; - struct tcpcb *tp; - struct tcpiphdr *ti; - int req; -{ -#ifdef TCPDEBUG - tcp_seq seq, ack; - int len, flags; -#endif - struct tcp_debug *td = &tcp_debug[tcp_debx++]; - - if (tcp_debx == TCP_NDEBUG) - tcp_debx = 0; - td->td_time = iptime(); - td->td_act = act; - td->td_ostate = ostate; - td->td_tcb = (caddr_t)tp; - if (tp) - td->td_cb = *tp; - else - bzero((caddr_t)&td->td_cb, sizeof (*tp)); - if (ti) - td->td_ti = *ti; - else - bzero((caddr_t)&td->td_ti, sizeof (*ti)); - td->td_req = req; -#ifdef TCPDEBUG - if (tcpconsdebug == 0) - return; - if (tp) - printf("%p %s:", tp, tcpstates[ostate]); - else - printf("???????? "); - printf("%s ", tanames[act]); - switch (act) { - - case TA_INPUT: - case TA_OUTPUT: - case TA_DROP: - if (ti == 0) - break; - seq = ti->ti_seq; - ack = ti->ti_ack; - len = ti->ti_len; - if (act == TA_OUTPUT) { - seq = ntohl(seq); - ack = ntohl(ack); - len = ntohs((u_short)len); - } - if (act == TA_OUTPUT) - len -= sizeof (struct tcphdr); - if (len) - printf("[%x..%x)", seq, seq+len); - else - printf("%x", seq); - printf("@%x, urp=%x", ack, ti->ti_urp); - flags = ti->ti_flags; - if (flags) { - char *cp = "<"; -#define pf(f) { \ - if (ti->ti_flags & TH_##f) { \ - printf("%s%s", cp, #f); \ - cp = ","; \ - } \ -} - pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG); - printf(">"); - } - break; - - case TA_USER: - printf("%s", prurequests[req&0xff]); - if ((req & 0xff) == PRU_SLOWTIMO) - printf("<%s>", tcptimers[req>>8]); - break; - } - if (tp) - printf(" -> %s", tcpstates[tp->t_state]); - /* print out internal state of tp !?! */ - printf("\n"); - if (tp == 0) - return; - printf("\trcv_(nxt,wnd,up) (%x,%x,%x) snd_(una,nxt,max) (%x,%x,%x)\n", - tp->rcv_nxt, tp->rcv_wnd, tp->rcv_up, tp->snd_una, tp->snd_nxt, - tp->snd_max); - printf("\tsnd_(wl1,wl2,wnd) (%x,%x,%x)\n", - tp->snd_wl1, tp->snd_wl2, tp->snd_wnd); -#endif /* TCPDEBUG */ -} diff --git a/c/src/exec/libnetworking/netinet/tcp_debug.h b/c/src/exec/libnetworking/netinet/tcp_debug.h deleted file mode 100644 index a33743b077..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_debug.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp_debug.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_TCP_DEBUG_H_ -#define _NETINET_TCP_DEBUG_H_ - -struct tcp_debug { - n_time td_time; - short td_act; - short td_ostate; - caddr_t td_tcb; - struct tcpiphdr td_ti; - short td_req; - struct tcpcb td_cb; -}; - -#define TA_INPUT 0 -#define TA_OUTPUT 1 -#define TA_USER 2 -#define TA_RESPOND 3 -#define TA_DROP 4 - -#ifdef TANAMES -static char *tanames[] = - { "input", "output", "user", "respond", "drop" }; -#endif - -#define TCP_NDEBUG 100 - -#ifndef KERNEL -/* XXX common variables for broken applications. */ -struct tcp_debug tcp_debug[TCP_NDEBUG]; -int tcp_debx; -#endif - -#endif /* !_NETINET_TCP_DEBUG_H_ */ diff --git a/c/src/exec/libnetworking/netinet/tcp_fsm.h b/c/src/exec/libnetworking/netinet/tcp_fsm.h deleted file mode 100644 index 3f2c12f54f..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_fsm.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp_fsm.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_TCP_FSM_H_ -#define _NETINET_TCP_FSM_H_ - -/* - * TCP FSM state definitions. - * Per RFC793, September, 1981. - */ - -#define TCP_NSTATES 11 - -#define TCPS_CLOSED 0 /* closed */ -#define TCPS_LISTEN 1 /* listening for connection */ -#define TCPS_SYN_SENT 2 /* active, have sent syn */ -#define TCPS_SYN_RECEIVED 3 /* have send and received syn */ -/* states < TCPS_ESTABLISHED are those where connections not established */ -#define TCPS_ESTABLISHED 4 /* established */ -#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ -/* states > TCPS_CLOSE_WAIT are those where user has closed */ -#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ -#define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ -#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ -/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ -#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ -#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ - -#define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) -#define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED) -#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT) - -#ifdef TCPOUTFLAGS -/* - * Flags used when sending segments in tcp_output. - * Basic flags (TH_RST,TH_ACK,TH_SYN,TH_FIN) are totally - * determined by state, with the proviso that TH_FIN is sent only - * if all data queued for output is included in the segment. - */ -static u_char tcp_outflags[TCP_NSTATES] = { - TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, - TH_ACK, TH_ACK, - TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, -}; -#endif - -#ifdef KPROF -int tcp_acounts[TCP_NSTATES][PRU_NREQ]; -#endif - -#ifdef TCPSTATES -char *tcpstates[] = { - "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", - "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", - "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", -}; -#endif - -#endif diff --git a/c/src/exec/libnetworking/netinet/tcp_input.c b/c/src/exec/libnetworking/netinet/tcp_input.c deleted file mode 100644 index 183b976f89..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_input.c +++ /dev/null @@ -1,2150 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995 - * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgment: - * 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. - * - * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95 - * $Id$ - */ - -#include "opt_tcpdebug.h" - -#ifndef TUBA_INCLUDE -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/errno.h> -#include <sys/syslog.h> - -#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */ - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#include <netinet/tcp_fsm.h> -#include <netinet/tcp_seq.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> -#include <netinet/tcpip.h> -#ifdef TCPDEBUG -#include <netinet/tcp_debug.h> -static struct tcpiphdr tcp_saveti; -#endif - -static int tcprexmtthresh = 3; -tcp_seq tcp_iss; -tcp_cc tcp_ccgen; - -struct tcpstat tcpstat; -SYSCTL_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, - CTLFLAG_RD, &tcpstat , tcpstat, ""); - -static int log_in_vain = 0; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_RW, - &log_in_vain, 0, ""); - -u_long tcp_now; -struct inpcbhead tcb; -struct inpcbinfo tcbinfo; - -static void tcp_dooptions __P((struct tcpcb *, - u_char *, int, struct tcpiphdr *, struct tcpopt *)); -static void tcp_pulloutofband __P((struct socket *, - struct tcpiphdr *, struct mbuf *)); -static int tcp_reass __P((struct tcpcb *, struct tcpiphdr *, struct mbuf *)); -static void tcp_xmit_timer __P((struct tcpcb *, int)); - -#endif /* TUBA_INCLUDE */ - -/* - * Insert segment ti into reassembly queue of tcp with - * control block tp. Return TH_FIN if reassembly now includes - * a segment with FIN. The macro form does the common case inline - * (segment is the next to be received on an established connection, - * and the queue is empty), avoiding linkage into and removal - * from the queue and repetition of various conversions. - * Set DELACK for segments received in order, but ack immediately - * when segments are out of order (so fast retransmit can work). - */ -#ifdef TCP_ACK_HACK -#define TCP_REASS(tp, ti, m, so, flags) { \ - if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (struct tcpiphdr *)(tp) && \ - (tp)->t_state == TCPS_ESTABLISHED) { \ - if (ti->ti_flags & TH_PUSH) \ - tp->t_flags |= TF_ACKNOW; \ - else \ - tp->t_flags |= TF_DELACK; \ - (tp)->rcv_nxt += (ti)->ti_len; \ - flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ - sbappend(&(so)->so_rcv, (m)); \ - sorwakeup(so); \ - } else { \ - (flags) = tcp_reass((tp), (ti), (m)); \ - tp->t_flags |= TF_ACKNOW; \ - } \ -} -#else -#define TCP_REASS(tp, ti, m, so, flags) { \ - if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (struct tcpiphdr *)(tp) && \ - (tp)->t_state == TCPS_ESTABLISHED) { \ - tp->t_flags |= TF_DELACK; \ - (tp)->rcv_nxt += (ti)->ti_len; \ - flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ - sbappend(&(so)->so_rcv, (m)); \ - sorwakeup(so); \ - } else { \ - (flags) = tcp_reass((tp), (ti), (m)); \ - tp->t_flags |= TF_ACKNOW; \ - } \ -} -#endif -#ifndef TUBA_INCLUDE - -static int -tcp_reass(tp, ti, m) - register struct tcpcb *tp; - register struct tcpiphdr *ti; - struct mbuf *m; -{ - register struct tcpiphdr *q; - struct socket *so = tp->t_inpcb->inp_socket; - int flags; - - /* - * Call with ti==0 after become established to - * force pre-ESTABLISHED data up to user socket. - */ - if (ti == 0) - goto present; - - /* - * Find a segment which begins after this one does. - */ - for (q = tp->seg_next; q != (struct tcpiphdr *)tp; - q = (struct tcpiphdr *)q->ti_next) - if (SEQ_GT(q->ti_seq, ti->ti_seq)) - break; - - /* - * If there is a preceding segment, it may provide some of - * our data already. If so, drop the data from the incoming - * segment. If it provides all of our data, drop us. - */ - if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { - register int i; - q = (struct tcpiphdr *)q->ti_prev; - /* conversion to int (in i) handles seq wraparound */ - i = q->ti_seq + q->ti_len - ti->ti_seq; - if (i > 0) { - if (i >= ti->ti_len) { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += ti->ti_len; - m_freem(m); - /* - * Try to present any queued data - * at the left window edge to the user. - * This is needed after the 3-WHS - * completes. - */ - goto present; /* ??? */ - } - m_adj(m, i); - ti->ti_len -= i; - ti->ti_seq += i; - } - q = (struct tcpiphdr *)(q->ti_next); - } - tcpstat.tcps_rcvoopack++; - tcpstat.tcps_rcvoobyte += ti->ti_len; - REASS_MBUF(ti) = m; /* XXX */ - - /* - * While we overlap succeeding segments trim them or, - * if they are completely covered, dequeue them. - */ - while (q != (struct tcpiphdr *)tp) { - register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; - if (i <= 0) - break; - if (i < q->ti_len) { - q->ti_seq += i; - q->ti_len -= i; - m_adj(REASS_MBUF(q), i); - break; - } - q = (struct tcpiphdr *)q->ti_next; - m = REASS_MBUF((struct tcpiphdr *)q->ti_prev); - remque(q->ti_prev); - m_freem(m); - } - - /* - * Stick new segment in its place. - */ - insque(ti, q->ti_prev); - -present: - /* - * Present data to user, advancing rcv_nxt through - * completed sequence space. - */ - if (!TCPS_HAVEESTABLISHED(tp->t_state)) - return (0); - ti = tp->seg_next; - if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) - return (0); - do { - tp->rcv_nxt += ti->ti_len; - flags = ti->ti_flags & TH_FIN; - remque(ti); - m = REASS_MBUF(ti); - ti = (struct tcpiphdr *)ti->ti_next; - if (so->so_state & SS_CANTRCVMORE) - m_freem(m); - else - sbappend(&so->so_rcv, m); - } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); - sorwakeup(so); - return (flags); -} - -/* - * TCP input routine, follows pages 65-76 of the - * protocol specification dated September, 1981 very closely. - */ -void -tcp_input(m, iphlen) - register struct mbuf *m; - int iphlen; -{ - register struct tcpiphdr *ti; - register struct inpcb *inp; - u_char *optp = NULL; - int optlen = 0; - int len, tlen, off; - register struct tcpcb *tp = 0; - register int tiflags; - struct socket *so = 0; - int todrop, acked, ourfinisacked, needoutput = 0; - struct in_addr laddr; - int dropsocket = 0; - int iss = 0; - u_long tiwin; - struct tcpopt to; /* options in this segment */ - struct rmxp_tao *taop; /* pointer to our TAO cache entry */ - struct rmxp_tao tao_noncached; /* in case there's no cached entry */ -#ifdef TCPDEBUG - short ostate = 0; -#endif - - bzero((char *)&to, sizeof(to)); - - tcpstat.tcps_rcvtotal++; - /* - * Get IP and TCP header together in first mbuf. - * Note: IP leaves IP header in first mbuf. - */ - ti = mtod(m, struct tcpiphdr *); - if (iphlen > sizeof (struct ip)) - ip_stripoptions(m, (struct mbuf *)0); - if (m->m_len < sizeof (struct tcpiphdr)) { - if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) { - tcpstat.tcps_rcvshort++; - return; - } - ti = mtod(m, struct tcpiphdr *); - } - - /* - * Checksum extended TCP header and data. - */ - tlen = ((struct ip *)ti)->ip_len; - len = sizeof (struct ip) + tlen; - ti->ti_next = ti->ti_prev = 0; - ti->ti_x1 = 0; - ti->ti_len = (u_short)tlen; - HTONS(ti->ti_len); - ti->ti_sum = in_cksum(m, len); - if (ti->ti_sum) { - tcpstat.tcps_rcvbadsum++; - goto drop; - } -#endif /* TUBA_INCLUDE */ - - /* - * Check that TCP offset makes sense, - * pull out TCP options and adjust length. XXX - */ - off = ti->ti_off << 2; - if (off < sizeof (struct tcphdr) || off > tlen) { - tcpstat.tcps_rcvbadoff++; - goto drop; - } - tlen -= off; - ti->ti_len = tlen; - if (off > sizeof (struct tcphdr)) { - if (m->m_len < sizeof(struct ip) + off) { - if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) { - tcpstat.tcps_rcvshort++; - return; - } - ti = mtod(m, struct tcpiphdr *); - } - optlen = off - sizeof (struct tcphdr); - optp = mtod(m, u_char *) + sizeof (struct tcpiphdr); - } - tiflags = ti->ti_flags; - - /* - * Convert TCP protocol specific fields to host format. - */ - NTOHL(ti->ti_seq); - NTOHL(ti->ti_ack); - NTOHS(ti->ti_win); - NTOHS(ti->ti_urp); - - /* - * Drop TCP, IP headers and TCP options. - */ - m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); - m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); - - /* - * Locate pcb for segment. - */ -findpcb: - inp = in_pcblookuphash(&tcbinfo, ti->ti_src, ti->ti_sport, - ti->ti_dst, ti->ti_dport, 1); - - /* - * If the state is CLOSED (i.e., TCB does not exist) then - * all data in the incoming segment is discarded. - * If the TCB exists but is in CLOSED state, it is embryonic, - * but should either do a listen or a connect soon. - */ - if (inp == NULL) { - if (log_in_vain && tiflags & TH_SYN) { - char buf[4*sizeof "123"]; - - strcpy(buf, inet_ntoa(ti->ti_dst)); - log(LOG_INFO, "Connection attempt to TCP %s:%d" - " from %s:%d\n", - buf, ntohs(ti->ti_dport), - inet_ntoa(ti->ti_src), ntohs(ti->ti_sport)); - } - goto dropwithreset; - } - tp = intotcpcb(inp); - if (tp == 0) - goto dropwithreset; - if (tp->t_state == TCPS_CLOSED) - goto drop; - - /* Unscale the window into a 32-bit value. */ - if ((tiflags & TH_SYN) == 0) - tiwin = ti->ti_win << tp->snd_scale; - else - tiwin = ti->ti_win; - - so = inp->inp_socket; - if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { -#ifdef TCPDEBUG - if (so->so_options & SO_DEBUG) { - ostate = tp->t_state; - tcp_saveti = *ti; - } -#endif - if (so->so_options & SO_ACCEPTCONN) { - register struct tcpcb *tp0 = tp; - struct socket *so2; - if ((tiflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) { - /* - * Note: dropwithreset makes sure we don't - * send a RST in response to a RST. - */ - if (tiflags & TH_ACK) { - tcpstat.tcps_badsyn++; - goto dropwithreset; - } - goto drop; - } - so2 = sonewconn(so, 0); - if (so2 == 0) { - tcpstat.tcps_listendrop++; - so2 = sodropablereq(so); - if (so2) { - tcp_drop(sototcpcb(so2), ETIMEDOUT); - so2 = sonewconn(so, 0); - } - if (!so2) - goto drop; - } - so = so2; - /* - * This is ugly, but .... - * - * Mark socket as temporary until we're - * committed to keeping it. The code at - * ``drop'' and ``dropwithreset'' check the - * flag dropsocket to see if the temporary - * socket created here should be discarded. - * We mark the socket as discardable until - * we're committed to it below in TCPS_LISTEN. - */ - dropsocket++; - inp = (struct inpcb *)so->so_pcb; - inp->inp_laddr = ti->ti_dst; - inp->inp_lport = ti->ti_dport; - in_pcbrehash(inp); -#if BSD>=43 - inp->inp_options = ip_srcroute(); -#endif - tp = intotcpcb(inp); - tp->t_state = TCPS_LISTEN; - tp->t_flags |= tp0->t_flags & (TF_NOPUSH|TF_NOOPT); - - /* Compute proper scaling value from buffer space */ - while (tp->request_r_scale < TCP_MAX_WINSHIFT && - TCP_MAXWIN << tp->request_r_scale < so->so_rcv.sb_hiwat) - tp->request_r_scale++; - } - } - - /* - * Segment received on connection. - * Reset idle time and keep-alive timer. - */ - tp->t_idle = 0; - if (TCPS_HAVEESTABLISHED(tp->t_state)) - tp->t_timer[TCPT_KEEP] = tcp_keepidle; - - /* - * Process options if not in LISTEN state, - * else do it below (after getting remote address). - */ - if (tp->t_state != TCPS_LISTEN) - tcp_dooptions(tp, optp, optlen, ti, &to); - - /* - * Header prediction: check for the two common cases - * of a uni-directional data xfer. If the packet has - * no control flags, is in-sequence, the window didn't - * change and we're not retransmitting, it's a - * candidate. If the length is zero and the ack moved - * forward, we're the sender side of the xfer. Just - * free the data acked & wake any higher level process - * that was blocked waiting for space. If the length - * is non-zero and the ack didn't move, we're the - * receiver side. If we're getting packets in-order - * (the reassembly queue is empty), add the data to - * the socket buffer and note that we need a delayed ack. - * Make sure that the hidden state-flags are also off. - * Since we check for TCPS_ESTABLISHED above, it can only - * be TH_NEEDSYN. - */ - if (tp->t_state == TCPS_ESTABLISHED && - (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK && - ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) && - ((to.to_flag & TOF_TS) == 0 || - TSTMP_GEQ(to.to_tsval, tp->ts_recent)) && - /* - * Using the CC option is compulsory if once started: - * the segment is OK if no T/TCP was negotiated or - * if the segment has a CC option equal to CCrecv - */ - ((tp->t_flags & (TF_REQ_CC|TF_RCVD_CC)) != (TF_REQ_CC|TF_RCVD_CC) || - ((to.to_flag & TOF_CC) != 0 && to.to_cc == tp->cc_recv)) && - ti->ti_seq == tp->rcv_nxt && - tiwin && tiwin == tp->snd_wnd && - tp->snd_nxt == tp->snd_max) { - - /* - * If last ACK falls within this segment's sequence numbers, - * record the timestamp. - * NOTE that the test is modified according to the latest - * proposal of the tcplw@cray.com list (Braden 1993/04/26). - */ - if ((to.to_flag & TOF_TS) != 0 && - SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)) { - tp->ts_recent_age = tcp_now; - tp->ts_recent = to.to_tsval; - } - - if (ti->ti_len == 0) { - if (SEQ_GT(ti->ti_ack, tp->snd_una) && - SEQ_LEQ(ti->ti_ack, tp->snd_max) && - tp->snd_cwnd >= tp->snd_wnd && - tp->t_dupacks < tcprexmtthresh) { - /* - * this is a pure ack for outstanding data. - */ - ++tcpstat.tcps_predack; - if ((to.to_flag & TOF_TS) != 0) - tcp_xmit_timer(tp, - tcp_now - to.to_tsecr + 1); - else if (tp->t_rtt && - SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, tp->t_rtt); - acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; - sbdrop(&so->so_snd, acked); - tp->snd_una = ti->ti_ack; - m_freem(m); - - /* - * If all outstanding data are acked, stop - * retransmit timer, otherwise restart timer - * using current (possibly backed-off) value. - * If process is waiting for space, - * wakeup/selwakeup/signal. If data - * are ready to send, let tcp_output - * decide between more output or persist. - */ - if (tp->snd_una == tp->snd_max) - tp->t_timer[TCPT_REXMT] = 0; - else if (tp->t_timer[TCPT_PERSIST] == 0) - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - - if (so->so_snd.sb_flags & SB_NOTIFY) - sowwakeup(so); - if (so->so_snd.sb_cc) - (void) tcp_output(tp); - return; - } - } else if (ti->ti_ack == tp->snd_una && - tp->seg_next == (struct tcpiphdr *)tp && - ti->ti_len <= sbspace(&so->so_rcv)) { - /* - * this is a pure, in-sequence data packet - * with nothing on the reassembly queue and - * we have enough buffer space to take it. - */ - ++tcpstat.tcps_preddat; - tp->rcv_nxt += ti->ti_len; - tcpstat.tcps_rcvpack++; - tcpstat.tcps_rcvbyte += ti->ti_len; - /* - * Add data to socket buffer. - */ - sbappend(&so->so_rcv, m); - sorwakeup(so); -#ifdef TCP_ACK_HACK - /* - * If this is a short packet, then ACK now - with Nagel - * congestion avoidance sender won't send more until - * he gets an ACK. - */ - if (tiflags & TH_PUSH) { - tp->t_flags |= TF_ACKNOW; - tcp_output(tp); - } else { - tp->t_flags |= TF_DELACK; - } -#else - tp->t_flags |= TF_DELACK; -#endif - return; - } - } - - /* - * Calculate amount of space in receive window, - * and then do TCP input processing. - * Receive window is amount of space in rcv queue, - * but not less than advertised window. - */ - { int win; - - win = sbspace(&so->so_rcv); - if (win < 0) - win = 0; - tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt)); - } - - switch (tp->t_state) { - - /* - * If the state is LISTEN then ignore segment if it contains an RST. - * If the segment contains an ACK then it is bad and send a RST. - * If it does not contain a SYN then it is not interesting; drop it. - * If it is from this socket, drop it, it must be forged. - * Don't bother responding if the destination was a broadcast. - * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial - * tp->iss, and send a segment: - * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK> - * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. - * Fill in remote peer address fields if not previously specified. - * Enter SYN_RECEIVED state, and process any other fields of this - * segment in this state. - */ - case TCPS_LISTEN: { - struct mbuf *am; - register struct sockaddr_in *sin; - - if (tiflags & TH_RST) - goto drop; - if (tiflags & TH_ACK) - goto dropwithreset; - if ((tiflags & TH_SYN) == 0) - goto drop; - if ((ti->ti_dport == ti->ti_sport) && - (ti->ti_dst.s_addr == ti->ti_src.s_addr)) - goto drop; - /* - * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN - * in_broadcast() should never return true on a received - * packet with M_BCAST not set. - */ - if (m->m_flags & (M_BCAST|M_MCAST) || - IN_MULTICAST(ntohl(ti->ti_dst.s_addr))) - goto drop; - am = m_get(M_DONTWAIT, MT_SONAME); /* XXX */ - if (am == NULL) - goto drop; - am->m_len = sizeof (struct sockaddr_in); - sin = mtod(am, struct sockaddr_in *); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(*sin); - sin->sin_addr = ti->ti_src; - sin->sin_port = ti->ti_sport; - bzero((caddr_t)sin->sin_zero, sizeof(sin->sin_zero)); - laddr = inp->inp_laddr; - if (inp->inp_laddr.s_addr == INADDR_ANY) - inp->inp_laddr = ti->ti_dst; - if (in_pcbconnect(inp, am)) { - inp->inp_laddr = laddr; - (void) m_free(am); - goto drop; - } - (void) m_free(am); - tp->t_template = tcp_template(tp); - if (tp->t_template == 0) { - tp = tcp_drop(tp, ENOBUFS); - dropsocket = 0; /* socket is already gone */ - goto drop; - } - if ((taop = tcp_gettaocache(inp)) == NULL) { - taop = &tao_noncached; - bzero(taop, sizeof(*taop)); - } - tcp_dooptions(tp, optp, optlen, ti, &to); - if (iss) - tp->iss = iss; - else - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/4; - tp->irs = ti->ti_seq; - tcp_sendseqinit(tp); - tcp_rcvseqinit(tp); - /* - * Initialization of the tcpcb for transaction; - * set SND.WND = SEG.WND, - * initialize CCsend and CCrecv. - */ - tp->snd_wnd = tiwin; /* initial send-window */ - tp->cc_send = CC_INC(tcp_ccgen); - tp->cc_recv = to.to_cc; - /* - * Perform TAO test on incoming CC (SEG.CC) option, if any. - * - compare SEG.CC against cached CC from the same host, - * if any. - * - if SEG.CC > chached value, SYN must be new and is accepted - * immediately: save new CC in the cache, mark the socket - * connected, enter ESTABLISHED state, turn on flag to - * send a SYN in the next segment. - * A virtual advertised window is set in rcv_adv to - * initialize SWS prevention. Then enter normal segment - * processing: drop SYN, process data and FIN. - * - otherwise do a normal 3-way handshake. - */ - if ((to.to_flag & TOF_CC) != 0) { - if (taop->tao_cc != 0 && CC_GT(to.to_cc, taop->tao_cc)) { - taop->tao_cc = to.to_cc; - tp->t_state = TCPS_ESTABLISHED; - - /* - * If there is a FIN, or if there is data and the - * connection is local, then delay SYN,ACK(SYN) in - * the hope of piggy-backing it on a response - * segment. Otherwise must send ACK now in case - * the other side is slow starting. - */ - if ((tiflags & TH_FIN) || (ti->ti_len != 0 && - in_localaddr(inp->inp_faddr))) - tp->t_flags |= (TF_DELACK | TF_NEEDSYN); - else - tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN); - - /* - * Limit the `virtual advertised window' to TCP_MAXWIN - * here. Even if we requested window scaling, it will - * become effective only later when our SYN is acked. - */ - tp->rcv_adv += min(tp->rcv_wnd, TCP_MAXWIN); - tcpstat.tcps_connects++; - soisconnected(so); - tp->t_timer[TCPT_KEEP] = tcp_keepinit; - dropsocket = 0; /* committed to socket */ - tcpstat.tcps_accepts++; - goto trimthenstep6; - } - /* else do standard 3-way handshake */ - } else { - /* - * No CC option, but maybe CC.NEW: - * invalidate cached value. - */ - taop->tao_cc = 0; - } - /* - * TAO test failed or there was no CC option, - * do a standard 3-way handshake. - */ - tp->t_flags |= TF_ACKNOW; - tp->t_state = TCPS_SYN_RECEIVED; - tp->t_timer[TCPT_KEEP] = tcp_keepinit; - dropsocket = 0; /* committed to socket */ - tcpstat.tcps_accepts++; - goto trimthenstep6; - } - - /* - * If the state is SYN_RECEIVED: - * if seg contains SYN/ACK, send a RST. - * if seg contains an ACK, but not for our SYN/ACK, send a RST. - */ - case TCPS_SYN_RECEIVED: - if (tiflags & TH_ACK) { - if (tiflags & TH_SYN) { - tcpstat.tcps_badsyn++; - goto dropwithreset; - } - if (SEQ_LEQ(ti->ti_ack, tp->snd_una) || - SEQ_GT(ti->ti_ack, tp->snd_max)) - goto dropwithreset; - } - break; - - /* - * If the state is SYN_SENT: - * if seg contains an ACK, but not for our SYN, drop the input. - * if seg contains a RST, then drop the connection. - * if seg does not contain SYN, then drop it. - * Otherwise this is an acceptable SYN segment - * initialize tp->rcv_nxt and tp->irs - * if seg contains ack then advance tp->snd_una - * if SYN has been acked change to ESTABLISHED else SYN_RCVD state - * arrange for segment to be acked (eventually) - * continue processing rest of data/controls, beginning with URG - */ - case TCPS_SYN_SENT: - if ((taop = tcp_gettaocache(inp)) == NULL) { - taop = &tao_noncached; - bzero(taop, sizeof(*taop)); - } - - if ((tiflags & TH_ACK) && - (SEQ_LEQ(ti->ti_ack, tp->iss) || - SEQ_GT(ti->ti_ack, tp->snd_max))) { - /* - * If we have a cached CCsent for the remote host, - * hence we haven't just crashed and restarted, - * do not send a RST. This may be a retransmission - * from the other side after our earlier ACK was lost. - * Our new SYN, when it arrives, will serve as the - * needed ACK. - */ - if (taop->tao_ccsent != 0) - goto drop; - else - goto dropwithreset; - } - if (tiflags & TH_RST) { - if (tiflags & TH_ACK) - tp = tcp_drop(tp, ECONNREFUSED); - goto drop; - } - if ((tiflags & TH_SYN) == 0) - goto drop; - tp->snd_wnd = ti->ti_win; /* initial send window */ - tp->cc_recv = to.to_cc; /* foreign CC */ - - tp->irs = ti->ti_seq; - tcp_rcvseqinit(tp); - if (tiflags & TH_ACK) { - /* - * Our SYN was acked. If segment contains CC.ECHO - * option, check it to make sure this segment really - * matches our SYN. If not, just drop it as old - * duplicate, but send an RST if we're still playing - * by the old rules. If no CC.ECHO option, make sure - * we don't get fooled into using T/TCP. - */ - if (to.to_flag & TOF_CCECHO) { - if (tp->cc_send != to.to_ccecho) { - if (taop->tao_ccsent != 0) - goto drop; - else - goto dropwithreset; - } - } else - tp->t_flags &= ~TF_RCVD_CC; - tcpstat.tcps_connects++; - soisconnected(so); - /* Do window scaling on this connection? */ - if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == - (TF_RCVD_SCALE|TF_REQ_SCALE)) { - tp->snd_scale = tp->requested_s_scale; - tp->rcv_scale = tp->request_r_scale; - } - /* Segment is acceptable, update cache if undefined. */ - if (taop->tao_ccsent == 0) - taop->tao_ccsent = to.to_ccecho; - - tp->rcv_adv += tp->rcv_wnd; - tp->snd_una++; /* SYN is acked */ - /* - * If there's data, delay ACK; if there's also a FIN - * ACKNOW will be turned on later. - */ - if (ti->ti_len != 0) - tp->t_flags |= TF_DELACK; - else - tp->t_flags |= TF_ACKNOW; - /* - * Received <SYN,ACK> in SYN_SENT[*] state. - * Transitions: - * SYN_SENT --> ESTABLISHED - * SYN_SENT* --> FIN_WAIT_1 - */ - if (tp->t_flags & TF_NEEDFIN) { - tp->t_state = TCPS_FIN_WAIT_1; - tp->t_flags &= ~TF_NEEDFIN; - tiflags &= ~TH_SYN; - } else { - tp->t_state = TCPS_ESTABLISHED; - tp->t_timer[TCPT_KEEP] = tcp_keepidle; - } - } else { - /* - * Received initial SYN in SYN-SENT[*] state => simul- - * taneous open. If segment contains CC option and there is - * a cached CC, apply TAO test; if it succeeds, connection is - * half-synchronized. Otherwise, do 3-way handshake: - * SYN-SENT -> SYN-RECEIVED - * SYN-SENT* -> SYN-RECEIVED* - * If there was no CC option, clear cached CC value. - */ - tp->t_flags |= TF_ACKNOW; - tp->t_timer[TCPT_REXMT] = 0; - if (to.to_flag & TOF_CC) { - if (taop->tao_cc != 0 && - CC_GT(to.to_cc, taop->tao_cc)) { - /* - * update cache and make transition: - * SYN-SENT -> ESTABLISHED* - * SYN-SENT* -> FIN-WAIT-1* - */ - taop->tao_cc = to.to_cc; - if (tp->t_flags & TF_NEEDFIN) { - tp->t_state = TCPS_FIN_WAIT_1; - tp->t_flags &= ~TF_NEEDFIN; - } else { - tp->t_state = TCPS_ESTABLISHED; - tp->t_timer[TCPT_KEEP] = tcp_keepidle; - } - tp->t_flags |= TF_NEEDSYN; - } else - tp->t_state = TCPS_SYN_RECEIVED; - } else { - /* CC.NEW or no option => invalidate cache */ - taop->tao_cc = 0; - tp->t_state = TCPS_SYN_RECEIVED; - } - } - -trimthenstep6: - /* - * Advance ti->ti_seq to correspond to first data byte. - * If data, trim to stay within window, - * dropping FIN if necessary. - */ - ti->ti_seq++; - if (ti->ti_len > tp->rcv_wnd) { - todrop = ti->ti_len - tp->rcv_wnd; - m_adj(m, -todrop); - ti->ti_len = tp->rcv_wnd; - tiflags &= ~TH_FIN; - tcpstat.tcps_rcvpackafterwin++; - tcpstat.tcps_rcvbyteafterwin += todrop; - } - tp->snd_wl1 = ti->ti_seq - 1; - tp->rcv_up = ti->ti_seq; - /* - * Client side of transaction: already sent SYN and data. - * If the remote host used T/TCP to validate the SYN, - * our data will be ACK'd; if so, enter normal data segment - * processing in the middle of step 5, ack processing. - * Otherwise, goto step 6. - */ - if (tiflags & TH_ACK) - goto process_ACK; - goto step6; - /* - * If the state is LAST_ACK or CLOSING or TIME_WAIT: - * if segment contains a SYN and CC [not CC.NEW] option: - * if state == TIME_WAIT and connection duration > MSL, - * drop packet and send RST; - * - * if SEG.CC > CCrecv then is new SYN, and can implicitly - * ack the FIN (and data) in retransmission queue. - * Complete close and delete TCPCB. Then reprocess - * segment, hoping to find new TCPCB in LISTEN state; - * - * else must be old SYN; drop it. - * else do normal processing. - */ - case TCPS_LAST_ACK: - case TCPS_CLOSING: - case TCPS_TIME_WAIT: - if ((tiflags & TH_SYN) && - (to.to_flag & TOF_CC) && tp->cc_recv != 0) { - if (tp->t_state == TCPS_TIME_WAIT && - tp->t_duration > TCPTV_MSL) - goto dropwithreset; - if (CC_GT(to.to_cc, tp->cc_recv)) { - tp = tcp_close(tp); - goto findpcb; - } - else - goto drop; - } - break; /* continue normal processing */ - } - - /* - * States other than LISTEN or SYN_SENT. - * First check timestamp, if present. - * Then check the connection count, if present. - * Then check that at least some bytes of segment are within - * receive window. If segment begins before rcv_nxt, - * drop leading data (and SYN); if nothing left, just ack. - * - * RFC 1323 PAWS: If we have a timestamp reply on this segment - * and it's less than ts_recent, drop it. - */ - if ((to.to_flag & TOF_TS) != 0 && (tiflags & TH_RST) == 0 && - tp->ts_recent && TSTMP_LT(to.to_tsval, tp->ts_recent)) { - - /* Check to see if ts_recent is over 24 days old. */ - if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) { - /* - * Invalidate ts_recent. If this segment updates - * ts_recent, the age will be reset later and ts_recent - * will get a valid value. If it does not, setting - * ts_recent to zero will at least satisfy the - * requirement that zero be placed in the timestamp - * echo reply when ts_recent isn't valid. The - * age isn't reset until we get a valid ts_recent - * because we don't want out-of-order segments to be - * dropped when ts_recent is old. - */ - tp->ts_recent = 0; - } else { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += ti->ti_len; - tcpstat.tcps_pawsdrop++; - goto dropafterack; - } - } - - /* - * T/TCP mechanism - * If T/TCP was negotiated and the segment doesn't have CC, - * or if it's CC is wrong then drop the segment. - * RST segments do not have to comply with this. - */ - if ((tp->t_flags & (TF_REQ_CC|TF_RCVD_CC)) == (TF_REQ_CC|TF_RCVD_CC) && - ((to.to_flag & TOF_CC) == 0 || tp->cc_recv != to.to_cc) && - (tiflags & TH_RST) == 0) - goto dropafterack; - - todrop = tp->rcv_nxt - ti->ti_seq; - if (todrop > 0) { - if (tiflags & TH_SYN) { - tiflags &= ~TH_SYN; - ti->ti_seq++; - if (ti->ti_urp > 1) - ti->ti_urp--; - else - tiflags &= ~TH_URG; - todrop--; - } - /* - * Following if statement from Stevens, vol. 2, p. 960. - */ - if (todrop > ti->ti_len - || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) { - /* - * Any valid FIN must be to the left of the window. - * At this point the FIN must be a duplicate or out - * of sequence; drop it. - */ - tiflags &= ~TH_FIN; - - /* - * Send an ACK to resynchronize and drop any data. - * But keep on processing for RST or ACK. - */ - tp->t_flags |= TF_ACKNOW; - todrop = ti->ti_len; - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += todrop; - } else { - tcpstat.tcps_rcvpartduppack++; - tcpstat.tcps_rcvpartdupbyte += todrop; - } - m_adj(m, todrop); - ti->ti_seq += todrop; - ti->ti_len -= todrop; - if (ti->ti_urp > todrop) - ti->ti_urp -= todrop; - else { - tiflags &= ~TH_URG; - ti->ti_urp = 0; - } - } - - /* - * If new data are received on a connection after the - * user processes are gone, then RST the other end. - */ - if ((so->so_state & SS_NOFDREF) && - tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { - tp = tcp_close(tp); - tcpstat.tcps_rcvafterclose++; - goto dropwithreset; - } - - /* - * If segment ends after window, drop trailing data - * (and PUSH and FIN); if nothing left, just ACK. - */ - todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); - if (todrop > 0) { - tcpstat.tcps_rcvpackafterwin++; - if (todrop >= ti->ti_len) { - tcpstat.tcps_rcvbyteafterwin += ti->ti_len; - /* - * If a new connection request is received - * while in TIME_WAIT, drop the old connection - * and start over if the sequence numbers - * are above the previous ones. - */ - if (tiflags & TH_SYN && - tp->t_state == TCPS_TIME_WAIT && - SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { - iss = tp->rcv_nxt + TCP_ISSINCR; - tp = tcp_close(tp); - goto findpcb; - } - /* - * If window is closed can only take segments at - * window edge, and have to drop data and PUSH from - * incoming segments. Continue processing, but - * remember to ack. Otherwise, drop segment - * and ack. - */ - if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { - tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_rcvwinprobe++; - } else - goto dropafterack; - } else - tcpstat.tcps_rcvbyteafterwin += todrop; - m_adj(m, -todrop); - ti->ti_len -= todrop; - tiflags &= ~(TH_PUSH|TH_FIN); - } - - /* - * If last ACK falls within this segment's sequence numbers, - * record its timestamp. - * NOTE that the test is modified according to the latest - * proposal of the tcplw@cray.com list (Braden 1993/04/26). - */ - if ((to.to_flag & TOF_TS) != 0 && - SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)) { - tp->ts_recent_age = tcp_now; - tp->ts_recent = to.to_tsval; - } - - /* - * If the RST bit is set examine the state: - * SYN_RECEIVED STATE: - * If passive open, return to LISTEN state. - * If active open, inform user that connection was refused. - * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: - * Inform user that connection was reset, and close tcb. - * CLOSING, LAST_ACK, TIME_WAIT STATES - * Close the tcb. - */ - if (tiflags&TH_RST) switch (tp->t_state) { - - case TCPS_SYN_RECEIVED: - so->so_error = ECONNREFUSED; - goto close; - - case TCPS_ESTABLISHED: - case TCPS_FIN_WAIT_1: - case TCPS_FIN_WAIT_2: - case TCPS_CLOSE_WAIT: - so->so_error = ECONNRESET; - close: - tp->t_state = TCPS_CLOSED; - tcpstat.tcps_drops++; - tp = tcp_close(tp); - goto drop; - - case TCPS_CLOSING: - case TCPS_LAST_ACK: - case TCPS_TIME_WAIT: - tp = tcp_close(tp); - goto drop; - } - - /* - * If a SYN is in the window, then this is an - * error and we send an RST and drop the connection. - */ - if (tiflags & TH_SYN) { - tp = tcp_drop(tp, ECONNRESET); - goto dropwithreset; - } - - /* - * If the ACK bit is off: if in SYN-RECEIVED state or SENDSYN - * flag is on (half-synchronized state), then queue data for - * later processing; else drop segment and return. - */ - if ((tiflags & TH_ACK) == 0) { - if (tp->t_state == TCPS_SYN_RECEIVED || - (tp->t_flags & TF_NEEDSYN)) - goto step6; - else - goto drop; - } - - /* - * Ack processing. - */ - switch (tp->t_state) { - - /* - * In SYN_RECEIVED state, the ack ACKs our SYN, so enter - * ESTABLISHED state and continue processing. - * The ACK was checked above. - */ - case TCPS_SYN_RECEIVED: - - tcpstat.tcps_connects++; - soisconnected(so); - /* Do window scaling? */ - if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == - (TF_RCVD_SCALE|TF_REQ_SCALE)) { - tp->snd_scale = tp->requested_s_scale; - tp->rcv_scale = tp->request_r_scale; - } - /* - * Upon successful completion of 3-way handshake, - * update cache.CC if it was undefined, pass any queued - * data to the user, and advance state appropriately. - */ - if ((taop = tcp_gettaocache(inp)) != NULL && - taop->tao_cc == 0) - taop->tao_cc = tp->cc_recv; - - /* - * Make transitions: - * SYN-RECEIVED -> ESTABLISHED - * SYN-RECEIVED* -> FIN-WAIT-1 - */ - if (tp->t_flags & TF_NEEDFIN) { - tp->t_state = TCPS_FIN_WAIT_1; - tp->t_flags &= ~TF_NEEDFIN; - } else { - tp->t_state = TCPS_ESTABLISHED; - tp->t_timer[TCPT_KEEP] = tcp_keepidle; - } - /* - * If segment contains data or ACK, will call tcp_reass() - * later; if not, do so now to pass queued data to user. - */ - if (ti->ti_len == 0 && (tiflags & TH_FIN) == 0) - (void) tcp_reass(tp, (struct tcpiphdr *)0, - (struct mbuf *)0); - tp->snd_wl1 = ti->ti_seq - 1; - /* fall into ... */ - - /* - * In ESTABLISHED state: drop duplicate ACKs; ACK out of range - * ACKs. If the ack is in the range - * tp->snd_una < ti->ti_ack <= tp->snd_max - * then advance tp->snd_una to ti->ti_ack and drop - * data from the retransmission queue. If this ACK reflects - * more up to date window information we update our window information. - */ - case TCPS_ESTABLISHED: - case TCPS_FIN_WAIT_1: - case TCPS_FIN_WAIT_2: - case TCPS_CLOSE_WAIT: - case TCPS_CLOSING: - case TCPS_LAST_ACK: - case TCPS_TIME_WAIT: - - if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { - if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { - tcpstat.tcps_rcvdupack++; - /* - * If we have outstanding data (other than - * a window probe), this is a completely - * duplicate ack (ie, window info didn't - * change), the ack is the biggest we've - * seen and we've seen exactly our rexmt - * threshhold of them, assume a packet - * has been dropped and retransmit it. - * Kludge snd_nxt & the congestion - * window so we send only this one - * packet. - * - * We know we're losing at the current - * window size so do congestion avoidance - * (set ssthresh to half the current window - * and pull our congestion window back to - * the new ssthresh). - * - * Dup acks mean that packets have left the - * network (they're now cached at the receiver) - * so bump cwnd by the amount in the receiver - * to keep a constant cwnd packets in the - * network. - */ - if (tp->t_timer[TCPT_REXMT] == 0 || - ti->ti_ack != tp->snd_una) - tp->t_dupacks = 0; - else if (++tp->t_dupacks == tcprexmtthresh) { - tcp_seq onxt = tp->snd_nxt; - u_int win = - min(tp->snd_wnd, tp->snd_cwnd) / 2 / - tp->t_maxseg; - - if (win < 2) - win = 2; - tp->snd_ssthresh = win * tp->t_maxseg; - tp->t_timer[TCPT_REXMT] = 0; - tp->t_rtt = 0; - tp->snd_nxt = ti->ti_ack; - tp->snd_cwnd = tp->t_maxseg; - (void) tcp_output(tp); - tp->snd_cwnd = tp->snd_ssthresh + - tp->t_maxseg * tp->t_dupacks; - if (SEQ_GT(onxt, tp->snd_nxt)) - tp->snd_nxt = onxt; - goto drop; - } else if (tp->t_dupacks > tcprexmtthresh) { - tp->snd_cwnd += tp->t_maxseg; - (void) tcp_output(tp); - goto drop; - } - } else - tp->t_dupacks = 0; - break; - } - /* - * If the congestion window was inflated to account - * for the other side's cached packets, retract it. - */ - if (tp->t_dupacks >= tcprexmtthresh && - tp->snd_cwnd > tp->snd_ssthresh) - tp->snd_cwnd = tp->snd_ssthresh; - tp->t_dupacks = 0; - if (SEQ_GT(ti->ti_ack, tp->snd_max)) { - tcpstat.tcps_rcvacktoomuch++; - goto dropafterack; - } - /* - * If we reach this point, ACK is not a duplicate, - * i.e., it ACKs something we sent. - */ - if (tp->t_flags & TF_NEEDSYN) { - /* - * T/TCP: Connection was half-synchronized, and our - * SYN has been ACK'd (so connection is now fully - * synchronized). Go to non-starred state, - * increment snd_una for ACK of SYN, and check if - * we can do window scaling. - */ - tp->t_flags &= ~TF_NEEDSYN; - tp->snd_una++; - /* Do window scaling? */ - if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == - (TF_RCVD_SCALE|TF_REQ_SCALE)) { - tp->snd_scale = tp->requested_s_scale; - tp->rcv_scale = tp->request_r_scale; - } - } - -process_ACK: - acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; - - /* - * If we have a timestamp reply, update smoothed - * round trip time. If no timestamp is present but - * transmit timer is running and timed sequence - * number was acked, update smoothed round trip time. - * Since we now have an rtt measurement, cancel the - * timer backoff (cf., Phil Karn's retransmit alg.). - * Recompute the initial retransmit timer. - */ - if (to.to_flag & TOF_TS) - tcp_xmit_timer(tp, tcp_now - to.to_tsecr + 1); - else if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp,tp->t_rtt); - - /* - * If all outstanding data is acked, stop retransmit - * timer and remember to restart (more output or persist). - * If there is more data to be acked, restart retransmit - * timer, using current (possibly backed-off) value. - */ - if (ti->ti_ack == tp->snd_max) { - tp->t_timer[TCPT_REXMT] = 0; - needoutput = 1; - } else if (tp->t_timer[TCPT_PERSIST] == 0) - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - - /* - * If no data (only SYN) was ACK'd, - * skip rest of ACK processing. - */ - if (acked == 0) - goto step6; - - /* - * When new data is acked, open the congestion window. - * If the window gives us less than ssthresh packets - * in flight, open exponentially (maxseg per packet). - * Otherwise open linearly: maxseg per window - * (maxseg^2 / cwnd per packet). - */ - { - register u_int cw = tp->snd_cwnd; - register u_int incr = tp->t_maxseg; - - if (cw > tp->snd_ssthresh) - incr = incr * incr / cw; - tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale); - } - if (acked > so->so_snd.sb_cc) { - tp->snd_wnd -= so->so_snd.sb_cc; - sbdrop(&so->so_snd, (int)so->so_snd.sb_cc); - ourfinisacked = 1; - } else { - sbdrop(&so->so_snd, acked); - tp->snd_wnd -= acked; - ourfinisacked = 0; - } - if (so->so_snd.sb_flags & SB_NOTIFY) - sowwakeup(so); - tp->snd_una = ti->ti_ack; - if (SEQ_LT(tp->snd_nxt, tp->snd_una)) - tp->snd_nxt = tp->snd_una; - - switch (tp->t_state) { - - /* - * In FIN_WAIT_1 STATE in addition to the processing - * for the ESTABLISHED state if our FIN is now acknowledged - * then enter FIN_WAIT_2. - */ - case TCPS_FIN_WAIT_1: - if (ourfinisacked) { - /* - * If we can't receive any more - * data, then closing user can proceed. - * Starting the timer is contrary to the - * specification, but if we don't get a FIN - * we'll hang forever. - */ - if (so->so_state & SS_CANTRCVMORE) { - soisdisconnected(so); - tp->t_timer[TCPT_2MSL] = tcp_maxidle; - } - tp->t_state = TCPS_FIN_WAIT_2; - } - break; - - /* - * In CLOSING STATE in addition to the processing for - * the ESTABLISHED state if the ACK acknowledges our FIN - * then enter the TIME-WAIT state, otherwise ignore - * the segment. - */ - case TCPS_CLOSING: - if (ourfinisacked) { - tp->t_state = TCPS_TIME_WAIT; - tcp_canceltimers(tp); - /* Shorten TIME_WAIT [RFC-1644, p.28] */ - if (tp->cc_recv != 0 && - tp->t_duration < TCPTV_MSL) - tp->t_timer[TCPT_2MSL] = - tp->t_rxtcur * TCPTV_TWTRUNC; - else - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - soisdisconnected(so); - } - break; - - /* - * In LAST_ACK, we may still be waiting for data to drain - * and/or to be acked, as well as for the ack of our FIN. - * If our FIN is now acknowledged, delete the TCB, - * enter the closed state and return. - */ - case TCPS_LAST_ACK: - if (ourfinisacked) { - tp = tcp_close(tp); - goto drop; - } - break; - - /* - * In TIME_WAIT state the only thing that should arrive - * is a retransmission of the remote FIN. Acknowledge - * it and restart the finack timer. - */ - case TCPS_TIME_WAIT: - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - goto dropafterack; - } - } - -step6: - /* - * Update window information. - * Don't look at window if no ACK: TAC's send garbage on first SYN. - */ - if ((tiflags & TH_ACK) && - (SEQ_LT(tp->snd_wl1, ti->ti_seq) || - (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) || - (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) { - /* keep track of pure window updates */ - if (ti->ti_len == 0 && - tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) - tcpstat.tcps_rcvwinupd++; - tp->snd_wnd = tiwin; - tp->snd_wl1 = ti->ti_seq; - tp->snd_wl2 = ti->ti_ack; - if (tp->snd_wnd > tp->max_sndwnd) - tp->max_sndwnd = tp->snd_wnd; - needoutput = 1; - } - - /* - * Process segments with URG. - */ - if ((tiflags & TH_URG) && ti->ti_urp && - TCPS_HAVERCVDFIN(tp->t_state) == 0) { - /* - * This is a kludge, but if we receive and accept - * random urgent pointers, we'll crash in - * soreceive. It's hard to imagine someone - * actually wanting to send this much urgent data. - */ - if (ti->ti_urp + so->so_rcv.sb_cc > sb_max) { - ti->ti_urp = 0; /* XXX */ - tiflags &= ~TH_URG; /* XXX */ - goto dodata; /* XXX */ - } - /* - * If this segment advances the known urgent pointer, - * then mark the data stream. This should not happen - * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since - * a FIN has been received from the remote side. - * In these states we ignore the URG. - * - * According to RFC961 (Assigned Protocols), - * the urgent pointer points to the last octet - * of urgent data. We continue, however, - * to consider it to indicate the first octet - * of data past the urgent section as the original - * spec states (in one of two places). - */ - if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) { - tp->rcv_up = ti->ti_seq + ti->ti_urp; - so->so_oobmark = so->so_rcv.sb_cc + - (tp->rcv_up - tp->rcv_nxt) - 1; - if (so->so_oobmark == 0) - so->so_state |= SS_RCVATMARK; - sohasoutofband(so); - tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA); - } - /* - * Remove out of band data so doesn't get presented to user. - * This can happen independent of advancing the URG pointer, - * but if two URG's are pending at once, some out-of-band - * data may creep in... ick. - */ - if (ti->ti_urp <= (u_long)ti->ti_len -#ifdef SO_OOBINLINE - && (so->so_options & SO_OOBINLINE) == 0 -#endif - ) - tcp_pulloutofband(so, ti, m); - } else - /* - * If no out of band data is expected, - * pull receive urgent pointer along - * with the receive window. - */ - if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) - tp->rcv_up = tp->rcv_nxt; -dodata: /* XXX */ - - /* - * Process the segment text, merging it into the TCP sequencing queue, - * and arranging for acknowledgment of receipt if necessary. - * This process logically involves adjusting tp->rcv_wnd as data - * is presented to the user (this happens in tcp_usrreq.c, - * case PRU_RCVD). If a FIN has already been received on this - * connection then we just ignore the text. - */ - if ((ti->ti_len || (tiflags&TH_FIN)) && - TCPS_HAVERCVDFIN(tp->t_state) == 0) { - TCP_REASS(tp, ti, m, so, tiflags); - /* - * Note the amount of data that peer has sent into - * our window, in order to estimate the sender's - * buffer size. - */ - len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt); - } else { - m_freem(m); - tiflags &= ~TH_FIN; - } - - /* - * If FIN is received ACK the FIN and let the user know - * that the connection is closing. - */ - if (tiflags & TH_FIN) { - if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { - socantrcvmore(so); - /* - * If connection is half-synchronized - * (ie NEEDSYN flag on) then delay ACK, - * so it may be piggybacked when SYN is sent. - * Otherwise, since we received a FIN then no - * more input can be expected, send ACK now. - */ - if (tp->t_flags & TF_NEEDSYN) - tp->t_flags |= TF_DELACK; - else - tp->t_flags |= TF_ACKNOW; - tp->rcv_nxt++; - } - switch (tp->t_state) { - - /* - * In SYN_RECEIVED and ESTABLISHED STATES - * enter the CLOSE_WAIT state. - */ - case TCPS_SYN_RECEIVED: - case TCPS_ESTABLISHED: - tp->t_state = TCPS_CLOSE_WAIT; - break; - - /* - * If still in FIN_WAIT_1 STATE FIN has not been acked so - * enter the CLOSING state. - */ - case TCPS_FIN_WAIT_1: - tp->t_state = TCPS_CLOSING; - break; - - /* - * In FIN_WAIT_2 state enter the TIME_WAIT state, - * starting the time-wait timer, turning off the other - * standard timers. - */ - case TCPS_FIN_WAIT_2: - tp->t_state = TCPS_TIME_WAIT; - tcp_canceltimers(tp); - /* Shorten TIME_WAIT [RFC-1644, p.28] */ - if (tp->cc_recv != 0 && - tp->t_duration < TCPTV_MSL) { - tp->t_timer[TCPT_2MSL] = - tp->t_rxtcur * TCPTV_TWTRUNC; - /* For transaction client, force ACK now. */ - tp->t_flags |= TF_ACKNOW; - } - else - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - soisdisconnected(so); - break; - - /* - * In TIME_WAIT state restart the 2 MSL time_wait timer. - */ - case TCPS_TIME_WAIT: - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - break; - } - } -#ifdef TCPDEBUG - if (so->so_options & SO_DEBUG) - tcp_trace(TA_INPUT, ostate, tp, &tcp_saveti, 0); -#endif - - /* - * Return any desired output. - */ - if (needoutput || (tp->t_flags & TF_ACKNOW)) - (void) tcp_output(tp); - return; - -dropafterack: - /* - * Generate an ACK dropping incoming segment if it occupies - * sequence space, where the ACK reflects our state. - */ - if (tiflags & TH_RST) - goto drop; -#ifdef TCPDEBUG - if (so->so_options & SO_DEBUG) - tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0); -#endif - m_freem(m); - tp->t_flags |= TF_ACKNOW; - (void) tcp_output(tp); - return; - -dropwithreset: - /* - * Generate a RST, dropping incoming segment. - * Make ACK acceptable to originator of segment. - * Don't bother to respond if destination was broadcast/multicast. - */ - if ((tiflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST) || - IN_MULTICAST(ntohl(ti->ti_dst.s_addr))) - goto drop; -#ifdef TCPDEBUG - if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) - tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0); -#endif - if (tiflags & TH_ACK) - tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); - else { - if (tiflags & TH_SYN) - ti->ti_len++; - tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, - TH_RST|TH_ACK); - } - /* destroy temporarily created socket */ - if (dropsocket) - (void) soabort(so); - return; - -drop: - /* - * Drop space held by incoming segment and return. - */ -#ifdef TCPDEBUG - if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) - tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0); -#endif - m_freem(m); - /* destroy temporarily created socket */ - if (dropsocket) - (void) soabort(so); - return; -#ifndef TUBA_INCLUDE -} - -static void -tcp_dooptions(tp, cp, cnt, ti, to) - struct tcpcb *tp; - u_char *cp; - int cnt; - struct tcpiphdr *ti; - struct tcpopt *to; -{ - u_short mss = 0; - int opt, optlen; - - for (; cnt > 0; cnt -= optlen, cp += optlen) { - opt = cp[0]; - if (opt == TCPOPT_EOL) - break; - if (opt == TCPOPT_NOP) - optlen = 1; - else { - optlen = cp[1]; - if (optlen <= 0) - break; - } - switch (opt) { - - default: - continue; - - case TCPOPT_MAXSEG: - if (optlen != TCPOLEN_MAXSEG) - continue; - if (!(ti->ti_flags & TH_SYN)) - continue; - bcopy((char *) cp + 2, (char *) &mss, sizeof(mss)); - NTOHS(mss); - break; - - case TCPOPT_WINDOW: - if (optlen != TCPOLEN_WINDOW) - continue; - if (!(ti->ti_flags & TH_SYN)) - continue; - tp->t_flags |= TF_RCVD_SCALE; - tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); - break; - - case TCPOPT_TIMESTAMP: - if (optlen != TCPOLEN_TIMESTAMP) - continue; - to->to_flag |= TOF_TS; - bcopy((char *)cp + 2, - (char *)&to->to_tsval, sizeof(to->to_tsval)); - NTOHL(to->to_tsval); - bcopy((char *)cp + 6, - (char *)&to->to_tsecr, sizeof(to->to_tsecr)); - NTOHL(to->to_tsecr); - - /* - * A timestamp received in a SYN makes - * it ok to send timestamp requests and replies. - */ - if (ti->ti_flags & TH_SYN) { - tp->t_flags |= TF_RCVD_TSTMP; - tp->ts_recent = to->to_tsval; - tp->ts_recent_age = tcp_now; - } - break; - case TCPOPT_CC: - if (optlen != TCPOLEN_CC) - continue; - to->to_flag |= TOF_CC; - bcopy((char *)cp + 2, - (char *)&to->to_cc, sizeof(to->to_cc)); - NTOHL(to->to_cc); - /* - * A CC or CC.new option received in a SYN makes - * it ok to send CC in subsequent segments. - */ - if (ti->ti_flags & TH_SYN) - tp->t_flags |= TF_RCVD_CC; - break; - case TCPOPT_CCNEW: - if (optlen != TCPOLEN_CC) - continue; - if (!(ti->ti_flags & TH_SYN)) - continue; - to->to_flag |= TOF_CCNEW; - bcopy((char *)cp + 2, - (char *)&to->to_cc, sizeof(to->to_cc)); - NTOHL(to->to_cc); - /* - * A CC or CC.new option received in a SYN makes - * it ok to send CC in subsequent segments. - */ - tp->t_flags |= TF_RCVD_CC; - break; - case TCPOPT_CCECHO: - if (optlen != TCPOLEN_CC) - continue; - if (!(ti->ti_flags & TH_SYN)) - continue; - to->to_flag |= TOF_CCECHO; - bcopy((char *)cp + 2, - (char *)&to->to_ccecho, sizeof(to->to_ccecho)); - NTOHL(to->to_ccecho); - break; - } - } - if (ti->ti_flags & TH_SYN) - tcp_mss(tp, mss); /* sets t_maxseg */ -} - -/* - * Pull out of band byte out of a segment so - * it doesn't appear in the user's data queue. - * It is still reflected in the segment length for - * sequencing purposes. - */ -static void -tcp_pulloutofband(so, ti, m) - struct socket *so; - struct tcpiphdr *ti; - register struct mbuf *m; -{ - int cnt = ti->ti_urp - 1; - - while (cnt >= 0) { - if (m->m_len > cnt) { - char *cp = mtod(m, caddr_t) + cnt; - struct tcpcb *tp = sototcpcb(so); - - tp->t_iobc = *cp; - tp->t_oobflags |= TCPOOB_HAVEDATA; - bcopy(cp+1, cp, (unsigned)(m->m_len - cnt - 1)); - m->m_len--; - return; - } - cnt -= m->m_len; - m = m->m_next; - if (m == 0) - break; - } - panic("tcp_pulloutofband"); -} - -/* - * Collect new round-trip time estimate - * and update averages and current timeout. - */ -static void -tcp_xmit_timer(tp, rtt) - register struct tcpcb *tp; - short rtt; -{ - register int delta; - - tcpstat.tcps_rttupdated++; - tp->t_rttupdated++; - if (tp->t_srtt != 0) { - /* - * srtt is stored as fixed point with 5 bits after the - * binary point (i.e., scaled by 8). The following magic - * is equivalent to the smoothing algorithm in rfc793 with - * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed - * point). Adjust rtt to origin 0. - */ - delta = ((rtt - 1) << TCP_DELTA_SHIFT) - - (tp->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT)); - - if ((tp->t_srtt += delta) <= 0) - tp->t_srtt = 1; - - /* - * We accumulate a smoothed rtt variance (actually, a - * smoothed mean difference), then set the retransmit - * timer to smoothed rtt + 4 times the smoothed variance. - * rttvar is stored as fixed point with 4 bits after the - * binary point (scaled by 16). The following is - * equivalent to rfc793 smoothing with an alpha of .75 - * (rttvar = rttvar*3/4 + |delta| / 4). This replaces - * rfc793's wired-in beta. - */ - if (delta < 0) - delta = -delta; - delta -= tp->t_rttvar >> (TCP_RTTVAR_SHIFT - TCP_DELTA_SHIFT); - if ((tp->t_rttvar += delta) <= 0) - tp->t_rttvar = 1; - } else { - /* - * No rtt measurement yet - use the unsmoothed rtt. - * Set the variance to half the rtt (so our first - * retransmit happens at 3*rtt). - */ - tp->t_srtt = rtt << TCP_RTT_SHIFT; - tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1); - } - tp->t_rtt = 0; - tp->t_rxtshift = 0; - - /* - * the retransmit should happen at rtt + 4 * rttvar. - * Because of the way we do the smoothing, srtt and rttvar - * will each average +1/2 tick of bias. When we compute - * the retransmit timer, we want 1/2 tick of rounding and - * 1 extra tick because of +-1/2 tick uncertainty in the - * firing of the timer. The bias will give us exactly the - * 1.5 tick we need. But, because the bias is - * statistical, we have to test that we don't drop below - * the minimum feasible timer (which is 2 ticks). - */ - TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), - max(tp->t_rttmin, rtt + 2), TCPTV_REXMTMAX); - - /* - * We received an ack for a packet that wasn't retransmitted; - * it is probably safe to discard any error indications we've - * received recently. This isn't quite right, but close enough - * for now (a route might have failed after we sent a segment, - * and the return path might not be symmetrical). - */ - tp->t_softerror = 0; -} - -/* - * Determine a reasonable value for maxseg size. - * If the route is known, check route for mtu. - * If none, use an mss that can be handled on the outgoing - * interface without forcing IP to fragment; if bigger than - * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES - * to utilize large mbufs. If no route is found, route has no mtu, - * or the destination isn't local, use a default, hopefully conservative - * size (usually 512 or the default IP max size, but no more than the mtu - * of the interface), as we can't discover anything about intervening - * gateways or networks. We also initialize the congestion/slow start - * window to be a single segment if the destination isn't local. - * While looking at the routing entry, we also initialize other path-dependent - * parameters from pre-set or cached values in the routing entry. - * - * Also take into account the space needed for options that we - * send regularly. Make maxseg shorter by that amount to assure - * that we can send maxseg amount of data even when the options - * are present. Store the upper limit of the length of options plus - * data in maxopd. - * - * NOTE that this routine is only called when we process an incoming - * segment, for outgoing segments only tcp_mssopt is called. - * - * In case of T/TCP, we call this routine during implicit connection - * setup as well (offer = -1), to initialize maxseg from the cached - * MSS of our peer. - */ -void -tcp_mss(tp, offer) - struct tcpcb *tp; - int offer; -{ - register struct rtentry *rt; - struct ifnet *ifp; - register int rtt, mss; - u_long bufsize; - struct inpcb *inp; - struct socket *so; - struct rmxp_tao *taop; - int origoffer = offer; - - inp = tp->t_inpcb; - if ((rt = tcp_rtlookup(inp)) == NULL) { - tp->t_maxopd = tp->t_maxseg = tcp_mssdflt; - return; - } - ifp = rt->rt_ifp; - so = inp->inp_socket; - - taop = rmx_taop(rt->rt_rmx); - /* - * Offer == -1 means that we didn't receive SYN yet, - * use cached value in that case; - */ - if (offer == -1) - offer = taop->tao_mssopt; - /* - * Offer == 0 means that there was no MSS on the SYN segment, - * in this case we use tcp_mssdflt. - */ - if (offer == 0) - offer = tcp_mssdflt; - else - /* - * Sanity check: make sure that maxopd will be large - * enough to allow some data on segments even is the - * all the option space is used (40bytes). Otherwise - * funny things may happen in tcp_output. - */ - offer = max(offer, 64); - taop->tao_mssopt = offer; - - /* - * While we're here, check if there's an initial rtt - * or rttvar. Convert from the route-table units - * to scaled multiples of the slow timeout timer. - */ - if (tp->t_srtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) { - /* - * XXX the lock bit for RTT indicates that the value - * is also a minimum value; this is subject to time. - */ - if (rt->rt_rmx.rmx_locks & RTV_RTT) - tp->t_rttmin = rtt / (RTM_RTTUNIT / PR_SLOWHZ); - tp->t_srtt = rtt / (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE)); - tcpstat.tcps_usedrtt++; - if (rt->rt_rmx.rmx_rttvar) { - tp->t_rttvar = rt->rt_rmx.rmx_rttvar / - (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE)); - tcpstat.tcps_usedrttvar++; - } else { - /* default variation is +- 1 rtt */ - tp->t_rttvar = - tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE; - } - TCPT_RANGESET(tp->t_rxtcur, - ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1, - tp->t_rttmin, TCPTV_REXMTMAX); - } - /* - * if there's an mtu associated with the route, use it - */ - if (rt->rt_rmx.rmx_mtu) - mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr); - else - { - mss = ifp->if_mtu - sizeof(struct tcpiphdr); - if (!in_localaddr(inp->inp_faddr)) - mss = min(mss, tcp_mssdflt); - } - mss = min(mss, offer); - /* - * maxopd stores the maximum length of data AND options - * in a segment; maxseg is the amount of data in a normal - * segment. We need to store this value (maxopd) apart - * from maxseg, because now every segment carries options - * and thus we normally have somewhat less data in segments. - */ - tp->t_maxopd = mss; - - /* - * In case of T/TCP, origoffer==-1 indicates, that no segments - * were received yet. In this case we just guess, otherwise - * we do the same as before T/TCP. - */ - if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && - (origoffer == -1 || - (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)) - mss -= TCPOLEN_TSTAMP_APPA; - if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC && - (origoffer == -1 || - (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC)) - mss -= TCPOLEN_CC_APPA; - -#if (MCLBYTES & (MCLBYTES - 1)) == 0 - if (mss > MCLBYTES) - mss &= ~(MCLBYTES-1); -#else - if (mss > MCLBYTES) - mss = mss / MCLBYTES * MCLBYTES; -#endif - /* - * If there's a pipesize, change the socket buffer - * to that size. Make the socket buffers an integral - * number of mss units; if the mss is larger than - * the socket buffer, decrease the mss. - */ -#ifdef RTV_SPIPE - if ((bufsize = rt->rt_rmx.rmx_sendpipe) == 0) -#endif - bufsize = so->so_snd.sb_hiwat; - if (bufsize < mss) - mss = bufsize; - else { - bufsize = roundup(bufsize, mss); - if (bufsize > sb_max) - bufsize = sb_max; - (void)sbreserve(&so->so_snd, bufsize); - } - tp->t_maxseg = mss; - -#ifdef RTV_RPIPE - if ((bufsize = rt->rt_rmx.rmx_recvpipe) == 0) -#endif - bufsize = so->so_rcv.sb_hiwat; - if (bufsize > mss) { - bufsize = roundup(bufsize, mss); - if (bufsize > sb_max) - bufsize = sb_max; - (void)sbreserve(&so->so_rcv, bufsize); - } - /* - * Don't force slow-start on local network. - */ - if (!in_localaddr(inp->inp_faddr)) - tp->snd_cwnd = mss; - - if (rt->rt_rmx.rmx_ssthresh) { - /* - * There's some sort of gateway or interface - * buffer limit on the path. Use this to set - * the slow start threshhold, but set the - * threshold to no less than 2*mss. - */ - tp->snd_ssthresh = max(2 * mss, rt->rt_rmx.rmx_ssthresh); - tcpstat.tcps_usedssthresh++; - } -} - -/* - * Determine the MSS option to send on an outgoing SYN. - */ -int -tcp_mssopt(tp) - struct tcpcb *tp; -{ - struct rtentry *rt; - - rt = tcp_rtlookup(tp->t_inpcb); - if (rt == NULL) - return tcp_mssdflt; - - return rt->rt_ifp->if_mtu - sizeof(struct tcpiphdr); -} -#endif /* TUBA_INCLUDE */ diff --git a/c/src/exec/libnetworking/netinet/tcp_output.c b/c/src/exec/libnetworking/netinet/tcp_output.c deleted file mode 100644 index cbb5218dce..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_output.c +++ /dev/null @@ -1,755 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp_output.c 8.4 (Berkeley) 5/24/95 - * $Id$ - */ - -#include "opt_tcpdebug.h" - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/errno.h> - -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#define TCPOUTFLAGS -#include <netinet/tcp_fsm.h> -#include <netinet/tcp_seq.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> -#include <netinet/tcpip.h> -#ifdef TCPDEBUG -#include <netinet/tcp_debug.h> -#endif - -#ifdef notyet -extern struct mbuf *m_copypack(); -#endif - - -/* - * Tcp output routine: figure out what should be sent and send it. - */ -int -tcp_output(tp) - register struct tcpcb *tp; -{ - register struct socket *so = tp->t_inpcb->inp_socket; - register long len, win; - int off, flags, error; - register struct mbuf *m; - register struct tcpiphdr *ti; - u_char opt[TCP_MAXOLEN]; - unsigned optlen, hdrlen; - int idle, sendalot; - struct rmxp_tao *taop; - struct rmxp_tao tao_noncached; - - /* - * Determine length of data that should be transmitted, - * and flags that will be used. - * If there is some data or critical controls (SYN, RST) - * to send, then transmit; otherwise, investigate further. - */ - idle = (tp->snd_max == tp->snd_una); - if (idle && tp->t_idle >= tp->t_rxtcur) - /* - * We have been idle for "a while" and no acks are - * expected to clock out any data we send -- - * slow start to get ack "clock" running again. - */ - tp->snd_cwnd = tp->t_maxseg; -again: - sendalot = 0; - off = tp->snd_nxt - tp->snd_una; - win = min(tp->snd_wnd, tp->snd_cwnd); - - flags = tcp_outflags[tp->t_state]; - /* - * Get standard flags, and add SYN or FIN if requested by 'hidden' - * state flags. - */ - if (tp->t_flags & TF_NEEDFIN) - flags |= TH_FIN; - if (tp->t_flags & TF_NEEDSYN) - flags |= TH_SYN; - - /* - * If in persist timeout with window of 0, send 1 byte. - * Otherwise, if window is small but nonzero - * and timer expired, we will send what we can - * and go to transmit state. - */ - if (tp->t_force) { - if (win == 0) { - /* - * If we still have some data to send, then - * clear the FIN bit. Usually this would - * happen below when it realizes that we - * aren't sending all the data. However, - * if we have exactly 1 byte of unset data, - * then it won't clear the FIN bit below, - * and if we are in persist state, we wind - * up sending the packet without recording - * that we sent the FIN bit. - * - * We can't just blindly clear the FIN bit, - * because if we don't have any more data - * to send then the probe will be the FIN - * itself. - */ - if (off < so->so_snd.sb_cc) - flags &= ~TH_FIN; - win = 1; - } else { - tp->t_timer[TCPT_PERSIST] = 0; - tp->t_rxtshift = 0; - } - } - - len = min(so->so_snd.sb_cc, win) - off; - - if ((taop = tcp_gettaocache(tp->t_inpcb)) == NULL) { - taop = &tao_noncached; - bzero(taop, sizeof(*taop)); - } - - /* - * Lop off SYN bit if it has already been sent. However, if this - * is SYN-SENT state and if segment contains data and if we don't - * know that foreign host supports TAO, suppress sending segment. - */ - if ((flags & TH_SYN) && SEQ_GT(tp->snd_nxt, tp->snd_una)) { - flags &= ~TH_SYN; - off--, len++; - if (len > 0 && tp->t_state == TCPS_SYN_SENT && - taop->tao_ccsent == 0) - return 0; - } - - /* - * Be careful not to send data and/or FIN on SYN segments - * in cases when no CC option will be sent. - * This measure is needed to prevent interoperability problems - * with not fully conformant TCP implementations. - */ - if ((flags & TH_SYN) && - ((tp->t_flags & TF_NOOPT) || !(tp->t_flags & TF_REQ_CC) || - ((flags & TH_ACK) && !(tp->t_flags & TF_RCVD_CC)))) { - len = 0; - flags &= ~TH_FIN; - } - - if (len < 0) { - /* - * If FIN has been sent but not acked, - * but we haven't been called to retransmit, - * len will be -1. Otherwise, window shrank - * after we sent into it. If window shrank to 0, - * cancel pending retransmit, pull snd_nxt back - * to (closed) window, and set the persist timer - * if it isn't already going. If the window didn't - * close completely, just wait for an ACK. - */ - len = 0; - if (win == 0) { - tp->t_timer[TCPT_REXMT] = 0; - tp->t_rxtshift = 0; - tp->snd_nxt = tp->snd_una; - if (tp->t_timer[TCPT_PERSIST] == 0) - tcp_setpersist(tp); - } - } - if (len > tp->t_maxseg) { - len = tp->t_maxseg; - sendalot = 1; - } - if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) - flags &= ~TH_FIN; - - win = sbspace(&so->so_rcv); - - /* - * Sender silly window avoidance. If connection is idle - * and can send all data, a maximum segment, - * at least a maximum default-size segment do it, - * or are forced, do it; otherwise don't bother. - * If peer's buffer is tiny, then send - * when window is at least half open. - * If retransmitting (possibly after persist timer forced us - * to send into a small window), then must resend. - */ - if (len) { - if (len == tp->t_maxseg) - goto send; - if ((idle || tp->t_flags & TF_NODELAY) && - (tp->t_flags & TF_NOPUSH) == 0 && - len + off >= so->so_snd.sb_cc) - goto send; - if (tp->t_force) - goto send; - if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) - goto send; - if (SEQ_LT(tp->snd_nxt, tp->snd_max)) - goto send; - } - - /* - * Compare available window to amount of window - * known to peer (as advertised window less - * next expected input). If the difference is at least two - * max size segments, or at least 50% of the maximum possible - * window, then want to send a window update to peer. - */ - if (win > 0) { - /* - * "adv" is the amount we can increase the window, - * taking into account that we are limited by - * TCP_MAXWIN << tp->rcv_scale. - */ - long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) - - (tp->rcv_adv - tp->rcv_nxt); - - if (adv >= (long) (2 * tp->t_maxseg)) - goto send; - if (2 * adv >= (long) so->so_rcv.sb_hiwat) - goto send; - } - - /* - * Send if we owe peer an ACK. - */ - if (tp->t_flags & TF_ACKNOW) - goto send; - if ((flags & TH_RST) || - ((flags & TH_SYN) && (tp->t_flags & TF_NEEDSYN) == 0)) - goto send; - if (SEQ_GT(tp->snd_up, tp->snd_una)) - goto send; - /* - * If our state indicates that FIN should be sent - * and we have not yet done so, or we're retransmitting the FIN, - * then we need to send. - */ - if (flags & TH_FIN && - ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) - goto send; - - /* - * TCP window updates are not reliable, rather a polling protocol - * using ``persist'' packets is used to insure receipt of window - * updates. The three ``states'' for the output side are: - * idle not doing retransmits or persists - * persisting to move a small or zero window - * (re)transmitting and thereby not persisting - * - * tp->t_timer[TCPT_PERSIST] - * is set when we are in persist state. - * tp->t_force - * is set when we are called to send a persist packet. - * tp->t_timer[TCPT_REXMT] - * is set when we are retransmitting - * The output side is idle when both timers are zero. - * - * If send window is too small, there is data to transmit, and no - * retransmit or persist is pending, then go to persist state. - * If nothing happens soon, send when timer expires: - * if window is nonzero, transmit what we can, - * otherwise force out a byte. - */ - if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && - tp->t_timer[TCPT_PERSIST] == 0) { - tp->t_rxtshift = 0; - tcp_setpersist(tp); - } - - /* - * No reason to send a segment, just return. - */ - return (0); - -send: - /* - * Before ESTABLISHED, force sending of initial options - * unless TCP set not to do any options. - * NOTE: we assume that the IP/TCP header plus TCP options - * always fit in a single mbuf, leaving room for a maximum - * link header, i.e. - * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN - */ - optlen = 0; - hdrlen = sizeof (struct tcpiphdr); - if (flags & TH_SYN) { - tp->snd_nxt = tp->iss; - if ((tp->t_flags & TF_NOOPT) == 0) { - u_short mss; - - opt[0] = TCPOPT_MAXSEG; - opt[1] = TCPOLEN_MAXSEG; - mss = htons((u_short) tcp_mssopt(tp)); - (void)memcpy(opt + 2, &mss, sizeof(mss)); - optlen = TCPOLEN_MAXSEG; - - if ((tp->t_flags & TF_REQ_SCALE) && - ((flags & TH_ACK) == 0 || - (tp->t_flags & TF_RCVD_SCALE))) { - *((u_long *) (opt + optlen)) = htonl( - TCPOPT_NOP << 24 | - TCPOPT_WINDOW << 16 | - TCPOLEN_WINDOW << 8 | - tp->request_r_scale); - optlen += 4; - } - } - } - - /* - * Send a timestamp and echo-reply if this is a SYN and our side - * wants to use timestamps (TF_REQ_TSTMP is set) or both our side - * and our peer have sent timestamps in our SYN's. - */ - if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && - (flags & TH_RST) == 0 && - ((flags & TH_ACK) == 0 || - (tp->t_flags & TF_RCVD_TSTMP))) { - u_long *lp = (u_long *)(opt + optlen); - - /* Form timestamp option as shown in appendix A of RFC 1323. */ - *lp++ = htonl(TCPOPT_TSTAMP_HDR); - *lp++ = htonl(tcp_now); - *lp = htonl(tp->ts_recent); - optlen += TCPOLEN_TSTAMP_APPA; - } - - /* - * Send `CC-family' options if our side wants to use them (TF_REQ_CC), - * options are allowed (!TF_NOOPT) and it's not a RST. - */ - if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC && - (flags & TH_RST) == 0) { - switch (flags & (TH_SYN|TH_ACK)) { - /* - * This is a normal ACK, send CC if we received CC before - * from our peer. - */ - case TH_ACK: - if (!(tp->t_flags & TF_RCVD_CC)) - break; - /*FALLTHROUGH*/ - - /* - * We can only get here in T/TCP's SYN_SENT* state, when - * we're a sending a non-SYN segment without waiting for - * the ACK of our SYN. A check above assures that we only - * do this if our peer understands T/TCP. - */ - case 0: - opt[optlen++] = TCPOPT_NOP; - opt[optlen++] = TCPOPT_NOP; - opt[optlen++] = TCPOPT_CC; - opt[optlen++] = TCPOLEN_CC; - *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send); - - optlen += 4; - break; - - /* - * This is our initial SYN, check whether we have to use - * CC or CC.new. - */ - case TH_SYN: - opt[optlen++] = TCPOPT_NOP; - opt[optlen++] = TCPOPT_NOP; - opt[optlen++] = tp->t_flags & TF_SENDCCNEW ? - TCPOPT_CCNEW : TCPOPT_CC; - opt[optlen++] = TCPOLEN_CC; - *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send); - optlen += 4; - break; - - /* - * This is a SYN,ACK; send CC and CC.echo if we received - * CC from our peer. - */ - case (TH_SYN|TH_ACK): - if (tp->t_flags & TF_RCVD_CC) { - opt[optlen++] = TCPOPT_NOP; - opt[optlen++] = TCPOPT_NOP; - opt[optlen++] = TCPOPT_CC; - opt[optlen++] = TCPOLEN_CC; - *(u_int32_t *)&opt[optlen] = - htonl(tp->cc_send); - optlen += 4; - opt[optlen++] = TCPOPT_NOP; - opt[optlen++] = TCPOPT_NOP; - opt[optlen++] = TCPOPT_CCECHO; - opt[optlen++] = TCPOLEN_CC; - *(u_int32_t *)&opt[optlen] = - htonl(tp->cc_recv); - optlen += 4; - } - break; - } - } - - hdrlen += optlen; - - /* - * Adjust data length if insertion of options will - * bump the packet length beyond the t_maxopd length. - * Clear the FIN bit because we cut off the tail of - * the segment. - */ - if (len + optlen > tp->t_maxopd) { - /* - * If there is still more to send, don't close the connection. - */ - flags &= ~TH_FIN; - len = tp->t_maxopd - optlen; - sendalot = 1; - } - -/*#ifdef DIAGNOSTIC*/ - if (max_linkhdr + hdrlen > MHLEN) - panic("tcphdr too big"); -/*#endif*/ - - /* - * Grab a header mbuf, attaching a copy of data to - * be transmitted, and initialize the header from - * the template for sends on this connection. - */ - if (len) { - if (tp->t_force && len == 1) - tcpstat.tcps_sndprobe++; - else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { - tcpstat.tcps_sndrexmitpack++; - tcpstat.tcps_sndrexmitbyte += len; - } else { - tcpstat.tcps_sndpack++; - tcpstat.tcps_sndbyte += len; - } -#ifdef notyet - if ((m = m_copypack(so->so_snd.sb_mb, off, - (int)len, max_linkhdr + hdrlen)) == 0) { - error = ENOBUFS; - goto out; - } - /* - * m_copypack left space for our hdr; use it. - */ - m->m_len += hdrlen; - m->m_data -= hdrlen; -#else - MGETHDR(m, M_DONTWAIT, MT_HEADER); - if (m == NULL) { - error = ENOBUFS; - goto out; - } - m->m_data += max_linkhdr; - m->m_len = hdrlen; - if (len <= MHLEN - hdrlen - max_linkhdr) { - m_copydata(so->so_snd.sb_mb, off, (int) len, - mtod(m, caddr_t) + hdrlen); - m->m_len += len; - } else { - m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len); - if (m->m_next == 0) { - (void) m_free(m); - error = ENOBUFS; - goto out; - } - } -#endif - /* - * If we're sending everything we've got, set PUSH. - * (This will keep happy those implementations which only - * give data to the user when a buffer fills or - * a PUSH comes in.) - */ - if (off + len == so->so_snd.sb_cc) - flags |= TH_PUSH; - } else { - if (tp->t_flags & TF_ACKNOW) - tcpstat.tcps_sndacks++; - else if (flags & (TH_SYN|TH_FIN|TH_RST)) - tcpstat.tcps_sndctrl++; - else if (SEQ_GT(tp->snd_up, tp->snd_una)) - tcpstat.tcps_sndurg++; - else - tcpstat.tcps_sndwinup++; - - MGETHDR(m, M_DONTWAIT, MT_HEADER); - if (m == NULL) { - error = ENOBUFS; - goto out; - } - m->m_data += max_linkhdr; - m->m_len = hdrlen; - } - m->m_pkthdr.rcvif = (struct ifnet *)0; - ti = mtod(m, struct tcpiphdr *); - if (tp->t_template == 0) - panic("tcp_output"); - (void)memcpy(ti, tp->t_template, sizeof (struct tcpiphdr)); - - /* - * Fill in fields, remembering maximum advertised - * window for use in delaying messages about window sizes. - * If resending a FIN, be sure not to use a new sequence number. - */ - if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && - tp->snd_nxt == tp->snd_max) - tp->snd_nxt--; - /* - * If we are doing retransmissions, then snd_nxt will - * not reflect the first unsent octet. For ACK only - * packets, we do not want the sequence number of the - * retransmitted packet, we want the sequence number - * of the next unsent octet. So, if there is no data - * (and no SYN or FIN), use snd_max instead of snd_nxt - * when filling in ti_seq. But if we are in persist - * state, snd_max might reflect one byte beyond the - * right edge of the window, so use snd_nxt in that - * case, since we know we aren't doing a retransmission. - * (retransmit and persist are mutually exclusive...) - */ - if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST]) - ti->ti_seq = htonl(tp->snd_nxt); - else - ti->ti_seq = htonl(tp->snd_max); - ti->ti_ack = htonl(tp->rcv_nxt); - if (optlen) { - bcopy(opt, ti + 1, optlen); - ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; - } - ti->ti_flags = flags; - /* - * Calculate receive window. Don't shrink window, - * but avoid silly window syndrome. - */ - if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg) - win = 0; - if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) - win = (long)(tp->rcv_adv - tp->rcv_nxt); - if (win > (long)TCP_MAXWIN << tp->rcv_scale) - win = (long)TCP_MAXWIN << tp->rcv_scale; - ti->ti_win = htons((u_short) (win>>tp->rcv_scale)); - if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { - ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt)); - ti->ti_flags |= TH_URG; - } else - /* - * If no urgent pointer to send, then we pull - * the urgent pointer to the left edge of the send window - * so that it doesn't drift into the send window on sequence - * number wraparound. - */ - tp->snd_up = tp->snd_una; /* drag it along */ - - /* - * Put TCP length in extended header, and then - * checksum extended header and data. - */ - if (len + optlen) - ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + - optlen + len)); - ti->ti_sum = in_cksum(m, (int)(hdrlen + len)); - - /* - * In transmit state, time the transmission and arrange for - * the retransmit. In persist state, just set snd_max. - */ - if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { - tcp_seq startseq = tp->snd_nxt; - - /* - * Advance snd_nxt over sequence space of this segment. - */ - if (flags & (TH_SYN|TH_FIN)) { - if (flags & TH_SYN) - tp->snd_nxt++; - if (flags & TH_FIN) { - tp->snd_nxt++; - tp->t_flags |= TF_SENTFIN; - } - } - tp->snd_nxt += len; - if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { - tp->snd_max = tp->snd_nxt; - /* - * Time this transmission if not a retransmission and - * not currently timing anything. - */ - if (tp->t_rtt == 0) { - tp->t_rtt = 1; - tp->t_rtseq = startseq; - tcpstat.tcps_segstimed++; - } - } - - /* - * Set retransmit timer if not currently set, - * and not doing an ack or a keep-alive probe. - * Initial value for retransmit timer is smoothed - * round-trip time + 2 * round-trip time variance. - * Initialize shift counter which is used for backoff - * of retransmit time. - */ - if (tp->t_timer[TCPT_REXMT] == 0 && - tp->snd_nxt != tp->snd_una) { - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - if (tp->t_timer[TCPT_PERSIST]) { - tp->t_timer[TCPT_PERSIST] = 0; - tp->t_rxtshift = 0; - } - } - } else - if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) - tp->snd_max = tp->snd_nxt + len; - -#ifdef TCPDEBUG - /* - * Trace. - */ - if (so->so_options & SO_DEBUG) - tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0); -#endif - - /* - * Fill in IP length and desired time to live and - * send to IP level. There should be a better way - * to handle ttl and tos; we could keep them in - * the template, but need a way to checksum without them. - */ - m->m_pkthdr.len = hdrlen + len; -#ifdef TUBA - if (tp->t_tuba_pcb) - error = tuba_output(m, tp); - else -#endif - { -#if 1 - struct rtentry *rt; -#endif - ((struct ip *)ti)->ip_len = m->m_pkthdr.len; - ((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip_ttl; /* XXX */ - ((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip_tos; /* XXX */ -#if 1 - /* - * See if we should do MTU discovery. We do it only if the following - * are true: - * 1) we have a valid route to the destination - * 2) the MTU is not locked (if it is, then discovery has been - * disabled) - */ - if ((rt = tp->t_inpcb->inp_route.ro_rt) - && rt->rt_flags & RTF_UP - && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { - ((struct ip *)ti)->ip_off |= IP_DF; - } -#endif - error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, - so->so_options & SO_DONTROUTE, 0); - } - if (error) { -out: - if (error == ENOBUFS) { - tcp_quench(tp->t_inpcb, 0); - return (0); - } -#if 1 - if (error == EMSGSIZE) { - /* - * ip_output() will have already fixed the route - * for us. tcp_mtudisc() will, as its last action, - * initiate retransmission, so it is important to - * not do so here. - */ - tcp_mtudisc(tp->t_inpcb, 0); - return 0; - } -#endif - if ((error == EHOSTUNREACH || error == ENETDOWN) - && TCPS_HAVERCVDSYN(tp->t_state)) { - tp->t_softerror = error; - return (0); - } - return (error); - } - tcpstat.tcps_sndtotal++; - - /* - * Data sent (as far as we can tell). - * If this advertises a larger window than any other segment, - * then remember the size of the advertised window. - * Any pending ACK has now been sent. - */ - if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) - tp->rcv_adv = tp->rcv_nxt + win; - tp->last_ack_sent = tp->rcv_nxt; - tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); - if (sendalot) - goto again; - return (0); -} - -void -tcp_setpersist(tp) - register struct tcpcb *tp; -{ - register int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; - - if (tp->t_timer[TCPT_REXMT]) - panic("tcp_output REXMT"); - /* - * Start/restart persistance timer. - */ - TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], - t * tcp_backoff[tp->t_rxtshift], - TCPTV_PERSMIN, TCPTV_PERSMAX); - if (tp->t_rxtshift < TCP_MAXRXTSHIFT) - tp->t_rxtshift++; -} diff --git a/c/src/exec/libnetworking/netinet/tcp_seq.h b/c/src/exec/libnetworking/netinet/tcp_seq.h deleted file mode 100644 index 8cccf199e1..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_seq.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993, 1995 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp_seq.h 8.3 (Berkeley) 6/21/95 - * $Id$ - */ - -#ifndef _NETINET_TCP_SEQ_H_ -#define _NETINET_TCP_SEQ_H_ -/* - * TCP sequence numbers are 32 bit integers operated - * on with modular arithmetic. These macros can be - * used to compare such integers. - */ -#define SEQ_LT(a,b) ((int)((a)-(b)) < 0) -#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) -#define SEQ_GT(a,b) ((int)((a)-(b)) > 0) -#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0) - -/* for modulo comparisons of timestamps */ -#define TSTMP_LT(a,b) ((int)((a)-(b)) < 0) -#define TSTMP_GEQ(a,b) ((int)((a)-(b)) >= 0) - -/* - * TCP connection counts are 32 bit integers operated - * on with modular arithmetic. These macros can be - * used to compare such integers. - */ -#define CC_LT(a,b) ((int)((a)-(b)) < 0) -#define CC_LEQ(a,b) ((int)((a)-(b)) <= 0) -#define CC_GT(a,b) ((int)((a)-(b)) > 0) -#define CC_GEQ(a,b) ((int)((a)-(b)) >= 0) - -/* Macro to increment a CC: skip 0 which has a special meaning */ -#define CC_INC(c) (++(c) == 0 ? ++(c) : (c)) - -/* - * Macros to initialize tcp sequence numbers for - * send and receive from initial send and receive - * sequence numbers. - */ -#define tcp_rcvseqinit(tp) \ - (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1 - -#define tcp_sendseqinit(tp) \ - (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \ - (tp)->iss - -#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ) - /* timestamp wrap-around time */ - -#ifdef KERNEL -extern tcp_cc tcp_ccgen; /* global connection count */ - -/* - * Increment for tcp_iss each second. - * This is designed to increment at the standard 250 KB/s, - * but with a random component averaging 128 KB. - * We also increment tcp_iss by a quarter of this amount - * each time we use the value for a new connection. - * If defined, the tcp_random18() macro should produce a - * number in the range [0-0x3ffff] that is hard to predict. - */ -#ifndef tcp_random18 -#define tcp_random18() ((random() >> 14) & 0x3ffff) -#endif -#define TCP_ISSINCR (122*1024 + tcp_random18()) - -extern tcp_seq tcp_iss; /* tcp initial send seq # */ -#else -#define TCP_ISSINCR (250*1024) /* increment for tcp_iss each second */ -#endif /* KERNEL */ -#endif /* _NETINET_TCP_SEQ_H_ */ diff --git a/c/src/exec/libnetworking/netinet/tcp_subr.c b/c/src/exec/libnetworking/netinet/tcp_subr.c deleted file mode 100644 index a9cde3fdf0..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_subr.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95 - * $Id$ - */ - -#include "opt_tcpdebug.h" - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/proc.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/protosw.h> -#include <sys/errno.h> - -#include <net/route.h> -#include <net/if.h> - -#define _IP_VHL -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/ip_var.h> -#include <netinet/ip_icmp.h> -#include <netinet/tcp.h> -#include <netinet/tcp_fsm.h> -#include <netinet/tcp_seq.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> -#include <netinet/tcpip.h> -#ifdef TCPDEBUG -#include <netinet/tcp_debug.h> -#endif - -int tcp_mssdflt = TCP_MSS; -SYSCTL_INT(_net_inet_tcp, TCPCTL_MSSDFLT, mssdflt, - CTLFLAG_RW, &tcp_mssdflt , 0, ""); - -static int tcp_do_rfc1323 = 1; -static int tcp_do_rfc1644 = 1; -#if !defined(__rtems__) -static int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ; -SYSCTL_INT(_net_inet_tcp, TCPCTL_RTTDFLT, rttdflt, - CTLFLAG_RW, &tcp_rttdflt , 0, ""); - -SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323, - CTLFLAG_RW, &tcp_do_rfc1323 , 0, ""); - -SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1644, rfc1644, - CTLFLAG_RW, &tcp_do_rfc1644 , 0, ""); -#endif - -static void tcp_cleartaocache(void); -static void tcp_notify __P((struct inpcb *, int)); - -/* - * Target size of TCP PCB hash table. Will be rounded down to a prime - * number. - */ -#ifndef TCBHASHSIZE -#define TCBHASHSIZE 128 -#endif - -/* - * Tcp initialization - */ -void -tcp_init() -{ - - tcp_iss = random(); /* wrong, but better than a constant */ - tcp_ccgen = 1; - tcp_cleartaocache(); - LIST_INIT(&tcb); - tcbinfo.listhead = &tcb; - tcbinfo.hashbase = hashinit(TCBHASHSIZE, M_PCB, &tcbinfo.hashmask); - if (max_protohdr < sizeof(struct tcpiphdr)) - max_protohdr = sizeof(struct tcpiphdr); - if (max_linkhdr + sizeof(struct tcpiphdr) > MHLEN) - panic("tcp_init"); -} - -/* - * Create template to be used to send tcp packets on a connection. - * Call after host entry created, allocates an mbuf and fills - * in a skeletal tcp/ip header, minimizing the amount of work - * necessary when the connection is used. - */ -struct tcpiphdr * -tcp_template(tp) - struct tcpcb *tp; -{ - register struct inpcb *inp = tp->t_inpcb; - register struct mbuf *m; - register struct tcpiphdr *n; - - if ((n = tp->t_template) == 0) { - m = m_get(M_DONTWAIT, MT_HEADER); - if (m == NULL) - return (0); - m->m_len = sizeof (struct tcpiphdr); - n = mtod(m, struct tcpiphdr *); - } - n->ti_next = n->ti_prev = 0; - n->ti_x1 = 0; - n->ti_pr = IPPROTO_TCP; - n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); - n->ti_src = inp->inp_laddr; - n->ti_dst = inp->inp_faddr; - n->ti_sport = inp->inp_lport; - n->ti_dport = inp->inp_fport; - n->ti_seq = 0; - n->ti_ack = 0; - n->ti_x2 = 0; - n->ti_off = 5; - n->ti_flags = 0; - n->ti_win = 0; - n->ti_sum = 0; - n->ti_urp = 0; - return (n); -} - -/* - * Send a single message to the TCP at address specified by - * the given TCP/IP header. If m == 0, then we make a copy - * of the tcpiphdr at ti and send directly to the addressed host. - * This is used to force keep alive messages out using the TCP - * template for a connection tp->t_template. If flags are given - * then we send a message back to the TCP which originated the - * segment ti, and discard the mbuf containing it and any other - * attached mbufs. - * - * In any case the ack and sequence number of the transmitted - * segment are as specified by the parameters. - * - * NOTE: If m != NULL, then ti must point to *inside* the mbuf. - */ -void -tcp_respond(tp, ti, m, ack, seq, flags) - struct tcpcb *tp; - register struct tcpiphdr *ti; - register struct mbuf *m; - tcp_seq ack, seq; - int flags; -{ - register int tlen; - int win = 0; - struct route *ro = 0; - struct route sro; - - if (tp) { - win = sbspace(&tp->t_inpcb->inp_socket->so_rcv); - ro = &tp->t_inpcb->inp_route; - } else { - ro = &sro; - bzero(ro, sizeof *ro); - } - if (m == 0) { - m = m_gethdr(M_DONTWAIT, MT_HEADER); - if (m == NULL) - return; -#ifdef TCP_COMPAT_42 - tlen = 1; -#else - tlen = 0; -#endif - m->m_data += max_linkhdr; - *mtod(m, struct tcpiphdr *) = *ti; - ti = mtod(m, struct tcpiphdr *); - flags = TH_ACK; - } else { - m_freem(m->m_next); - m->m_next = 0; - m->m_data = (caddr_t)ti; - m->m_len = sizeof (struct tcpiphdr); - tlen = 0; -#define xchg(a,b,type) { type t; t=a; a=b; b=t; } - xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long); - xchg(ti->ti_dport, ti->ti_sport, u_short); -#undef xchg - } - ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen)); - tlen += sizeof (struct tcpiphdr); - m->m_len = tlen; - m->m_pkthdr.len = tlen; - m->m_pkthdr.rcvif = (struct ifnet *) 0; - ti->ti_next = ti->ti_prev = 0; - ti->ti_x1 = 0; - ti->ti_seq = htonl(seq); - ti->ti_ack = htonl(ack); - ti->ti_x2 = 0; - ti->ti_off = sizeof (struct tcphdr) >> 2; - ti->ti_flags = flags; - if (tp) - ti->ti_win = htons((u_short) (win >> tp->rcv_scale)); - else - ti->ti_win = htons((u_short)win); - ti->ti_urp = 0; - ti->ti_sum = 0; - ti->ti_sum = in_cksum(m, tlen); - ((struct ip *)ti)->ip_len = tlen; - ((struct ip *)ti)->ip_ttl = ip_defttl; -#ifdef TCPDEBUG - if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) - tcp_trace(TA_OUTPUT, 0, tp, ti, 0); -#endif - (void) ip_output(m, NULL, ro, 0, NULL); - if (ro == &sro && ro->ro_rt) { - RTFREE(ro->ro_rt); - } -} - -/* - * Create a new TCP control block, making an - * empty reassembly queue and hooking it to the argument - * protocol control block. - */ -struct tcpcb * -tcp_newtcpcb(inp) - struct inpcb *inp; -{ - register struct tcpcb *tp; - - tp = malloc(sizeof(*tp), M_PCB, M_NOWAIT); - if (tp == NULL) - return ((struct tcpcb *)0); - bzero((char *) tp, sizeof(struct tcpcb)); - tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; - tp->t_maxseg = tp->t_maxopd = tcp_mssdflt; - - if (tcp_do_rfc1323) - tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP); - if (tcp_do_rfc1644) - tp->t_flags |= TF_REQ_CC; - tp->t_inpcb = inp; - /* - * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no - * rtt estimate. Set rttvar so that srtt + 4 * rttvar gives - * reasonable initial retransmit time. - */ - tp->t_srtt = TCPTV_SRTTBASE; - tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4; - tp->t_rttmin = TCPTV_MIN; - tp->t_rxtcur = TCPTV_RTOBASE; - tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; - tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; - inp->inp_ip_ttl = ip_defttl; - inp->inp_ppcb = (caddr_t)tp; - return (tp); -} - -/* - * Drop a TCP connection, reporting - * the specified error. If connection is synchronized, - * then send a RST to peer. - */ -struct tcpcb * -tcp_drop(tp, errnum) - register struct tcpcb *tp; - int errnum; -{ - struct socket *so = tp->t_inpcb->inp_socket; - - if (TCPS_HAVERCVDSYN(tp->t_state)) { - tp->t_state = TCPS_CLOSED; - (void) tcp_output(tp); - tcpstat.tcps_drops++; - } else - tcpstat.tcps_conndrops++; - if (errnum == ETIMEDOUT && tp->t_softerror) - errnum = tp->t_softerror; - so->so_error = errnum; - return (tcp_close(tp)); -} - -/* - * Close a TCP control block: - * discard all space held by the tcp - * discard internet protocol block - * wake up any sleepers - */ -struct tcpcb * -tcp_close(tp) - register struct tcpcb *tp; -{ - register struct tcpiphdr *t; - struct inpcb *inp = tp->t_inpcb; - struct socket *so = inp->inp_socket; - register struct mbuf *m; - register struct rtentry *rt; - - /* - * If we got enough samples through the srtt filter, - * save the rtt and rttvar in the routing entry. - * 'Enough' is arbitrarily defined as the 16 samples. - * 16 samples is enough for the srtt filter to converge - * to within 5% of the correct value; fewer samples and - * we could save a very bogus rtt. - * - * Don't update the default route's characteristics and don't - * update anything that the user "locked". - */ - if (tp->t_rttupdated >= 16 && - (rt = inp->inp_route.ro_rt) && - ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr != INADDR_ANY) { - register u_long i = 0; - - if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) { - i = tp->t_srtt * - (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE)); - if (rt->rt_rmx.rmx_rtt && i) - /* - * filter this update to half the old & half - * the new values, converting scale. - * See route.h and tcp_var.h for a - * description of the scaling constants. - */ - rt->rt_rmx.rmx_rtt = - (rt->rt_rmx.rmx_rtt + i) / 2; - else - rt->rt_rmx.rmx_rtt = i; - tcpstat.tcps_cachedrtt++; - } - if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) { - i = tp->t_rttvar * - (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE)); - if (rt->rt_rmx.rmx_rttvar && i) - rt->rt_rmx.rmx_rttvar = - (rt->rt_rmx.rmx_rttvar + i) / 2; - else - rt->rt_rmx.rmx_rttvar = i; - tcpstat.tcps_cachedrttvar++; - } - /* - * update the pipelimit (ssthresh) if it has been updated - * already or if a pipesize was specified & the threshhold - * got below half the pipesize. I.e., wait for bad news - * before we start updating, then update on both good - * and bad news. - */ - if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 && - ((i = tp->snd_ssthresh) != 0) && rt->rt_rmx.rmx_ssthresh) || - i < (rt->rt_rmx.rmx_sendpipe / 2)) { - /* - * convert the limit from user data bytes to - * packets then to packet data bytes. - */ - i = (i + tp->t_maxseg / 2) / tp->t_maxseg; - if (i < 2) - i = 2; - i *= (u_long)(tp->t_maxseg + sizeof (struct tcpiphdr)); - if (rt->rt_rmx.rmx_ssthresh) - rt->rt_rmx.rmx_ssthresh = - (rt->rt_rmx.rmx_ssthresh + i) / 2; - else - rt->rt_rmx.rmx_ssthresh = i; - tcpstat.tcps_cachedssthresh++; - } - } - /* free the reassembly queue, if any */ - t = tp->seg_next; - while (t != (struct tcpiphdr *)tp) { - t = (struct tcpiphdr *)t->ti_next; - m = REASS_MBUF((struct tcpiphdr *)t->ti_prev); - remque(t->ti_prev); - m_freem(m); - } - if (tp->t_template) - (void) m_free(dtom(tp->t_template)); - free(tp, M_PCB); - inp->inp_ppcb = 0; - soisdisconnected(so); - in_pcbdetach(inp); - tcpstat.tcps_closed++; - return ((struct tcpcb *)0); -} - -void -tcp_drain() -{ - -} - -/* - * Notify a tcp user of an asynchronous error; - * store error as soft error, but wake up user - * (for now, won't do anything until can select for soft error). - */ -static void -tcp_notify(inp, error) - struct inpcb *inp; - int error; -{ - register struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb; - register struct socket *so = inp->inp_socket; - - /* - * Ignore some errors if we are hooked up. - * If connection hasn't completed, has retransmitted several times, - * and receives a second error, give up now. This is better - * than waiting a long time to establish a connection that - * can never complete. - */ - if (tp->t_state == TCPS_ESTABLISHED && - (error == EHOSTUNREACH || error == ENETUNREACH || - error == EHOSTDOWN)) { - return; - } else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 && - tp->t_softerror) - so->so_error = error; - else - tp->t_softerror = error; - soconnwakeup (so); - sorwakeup(so); - sowwakeup(so); -} - -void -tcp_ctlinput(cmd, sa, vip) - int cmd; - struct sockaddr *sa; - void *vip; -{ - register struct ip *ip = vip; - register struct tcphdr *th; - void (*notify) __P((struct inpcb *, int)) = tcp_notify; - - if (cmd == PRC_QUENCH) - notify = tcp_quench; -#if 1 - else if (cmd == PRC_MSGSIZE) - notify = tcp_mtudisc; -#endif - else if (!PRC_IS_REDIRECT(cmd) && - ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)) - return; - if (ip) { - th = (struct tcphdr *)((caddr_t)ip - + (IP_VHL_HL(ip->ip_vhl) << 2)); - in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport, - cmd, notify); - } else - in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify); -} - -/* - * When a source quench is received, close congestion window - * to one segment. We will gradually open it again as we proceed. - */ -void -tcp_quench(inp, errnum) - struct inpcb *inp; - int errnum; -{ - struct tcpcb *tp = intotcpcb(inp); - - if (tp) - tp->snd_cwnd = tp->t_maxseg; -} - -#if 1 -/* - * When `need fragmentation' ICMP is received, update our idea of the MSS - * based on the new value in the route. Also nudge TCP to send something, - * since we know the packet we just sent was dropped. - * This duplicates some code in the tcp_mss() function in tcp_input.c. - */ -void -tcp_mtudisc(inp, errnum) - struct inpcb *inp; - int errnum; -{ - struct tcpcb *tp = intotcpcb(inp); - struct rtentry *rt; - struct rmxp_tao *taop; - struct socket *so = inp->inp_socket; - int offered; - int mss; - - if (tp) { - rt = tcp_rtlookup(inp); - if (!rt || !rt->rt_rmx.rmx_mtu) { - tp->t_maxopd = tp->t_maxseg = tcp_mssdflt; - return; - } - taop = rmx_taop(rt->rt_rmx); - offered = taop->tao_mssopt; - mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr); - if (offered) - mss = min(mss, offered); - /* - * XXX - The above conditional probably violates the TCP - * spec. The problem is that, since we don't know the - * other end's MSS, we are supposed to use a conservative - * default. But, if we do that, then MTU discovery will - * never actually take place, because the conservative - * default is much less than the MTUs typically seen - * on the Internet today. For the moment, we'll sweep - * this under the carpet. - * - * The conservative default might not actually be a problem - * if the only case this occurs is when sending an initial - * SYN with options and data to a host we've never talked - * to before. Then, they will reply with an MSS value which - * will get recorded and the new parameters should get - * recomputed. For Further Study. - */ - if (tp->t_maxopd <= mss) - return; - tp->t_maxopd = mss; - - if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && - (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP) - mss -= TCPOLEN_TSTAMP_APPA; - if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC && - (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC) - mss -= TCPOLEN_CC_APPA; -#if (MCLBYTES & (MCLBYTES - 1)) == 0 - if (mss > MCLBYTES) - mss &= ~(MCLBYTES-1); -#else - if (mss > MCLBYTES) - mss = mss / MCLBYTES * MCLBYTES; -#endif - if (so->so_snd.sb_hiwat < mss) - mss = so->so_snd.sb_hiwat; - - tp->t_maxseg = mss; - - tcpstat.tcps_mturesent++; - tp->t_rtt = 0; - tp->snd_nxt = tp->snd_una; - tcp_output(tp); - } -} -#endif - -/* - * Look-up the routing entry to the peer of this inpcb. If no route - * is found and it cannot be allocated the return NULL. This routine - * is called by TCP routines that access the rmx structure and by tcp_mss - * to get the interface MTU. - */ -struct rtentry * -tcp_rtlookup(inp) - struct inpcb *inp; -{ - struct route *ro; - struct rtentry *rt; - - ro = &inp->inp_route; - rt = ro->ro_rt; - if (rt == NULL || !(rt->rt_flags & RTF_UP)) { - /* No route yet, so try to acquire one */ - if (inp->inp_faddr.s_addr != INADDR_ANY) { - ro->ro_dst.sa_family = AF_INET; - ro->ro_dst.sa_len = sizeof(ro->ro_dst); - ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = - inp->inp_faddr; - rtalloc(ro); - rt = ro->ro_rt; - } - } - return rt; -} - -/* - * Return a pointer to the cached information about the remote host. - * The cached information is stored in the protocol specific part of - * the route metrics. - */ -struct rmxp_tao * -tcp_gettaocache(inp) - struct inpcb *inp; -{ - struct rtentry *rt = tcp_rtlookup(inp); - - /* Make sure this is a host route and is up. */ - if (rt == NULL || - (rt->rt_flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST)) - return NULL; - - return rmx_taop(rt->rt_rmx); -} - -/* - * Clear all the TAO cache entries, called from tcp_init. - * - * XXX - * This routine is just an empty one, because we assume that the routing - * routing tables are initialized at the same time when TCP, so there is - * nothing in the cache left over. - */ -static void -tcp_cleartaocache(void) -{ } diff --git a/c/src/exec/libnetworking/netinet/tcp_timer.c b/c/src/exec/libnetworking/netinet/tcp_timer.c deleted file mode 100644 index 04d3d604e2..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_timer.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95 - * $Id$ - */ - -#include "opt_tcpdebug.h" - -#ifndef TUBA_INCLUDE -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/protosw.h> -#include <sys/errno.h> - -#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */ - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#include <netinet/tcp_fsm.h> -#include <netinet/tcp_seq.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> -#include <netinet/tcpip.h> -#ifdef TCPDEBUG -#include <netinet/tcp_debug.h> -#endif - -int tcp_keepinit = TCPTV_KEEP_INIT; -SYSCTL_INT(_net_inet_tcp, TCPCTL_KEEPINIT, keepinit, - CTLFLAG_RW, &tcp_keepinit , 0, ""); - -int tcp_keepidle = TCPTV_KEEP_IDLE; -SYSCTL_INT(_net_inet_tcp, TCPCTL_KEEPIDLE, keepidle, - CTLFLAG_RW, &tcp_keepidle , 0, ""); - -static int tcp_keepintvl = TCPTV_KEEPINTVL; -SYSCTL_INT(_net_inet_tcp, TCPCTL_KEEPINTVL, keepintvl, - CTLFLAG_RW, &tcp_keepintvl , 0, ""); - -static int always_keepalive = 0; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, - CTLFLAG_RW, &always_keepalive , 0, ""); - -static int tcp_keepcnt = TCPTV_KEEPCNT; - /* max idle probes */ -static int tcp_maxpersistidle = TCPTV_KEEP_IDLE; - /* max idle time in persist */ -int tcp_maxidle; -#else /* TUBA_INCLUDE */ - -static int tcp_maxpersistidle; -#endif /* TUBA_INCLUDE */ - -/* - * Fast timeout routine for processing delayed acks - */ -void -tcp_fasttimo() -{ - register struct inpcb *inp; - register struct tcpcb *tp; - int s; - - s = splnet(); - - for (inp = tcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { - if ((tp = (struct tcpcb *)inp->inp_ppcb) && - (tp->t_flags & TF_DELACK)) { - tp->t_flags &= ~TF_DELACK; - tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_delack++; - (void) tcp_output(tp); - } - } - splx(s); -} - -/* - * Tcp protocol timeout routine called every 500 ms. - * Updates the timers in all active tcb's and - * causes finite state machine actions if timers expire. - */ -void -tcp_slowtimo() -{ - register struct inpcb *ip, *ipnxt; - register struct tcpcb *tp; - register int i; - int s; -#ifdef TCPDEBUG - int ostate; -#endif - - s = splnet(); - - tcp_maxidle = tcp_keepcnt * tcp_keepintvl; - - ip = tcb.lh_first; - if (ip == NULL) { - splx(s); - return; - } - /* - * Search through tcb's and update active timers. - */ - for (; ip != NULL; ip = ipnxt) { - ipnxt = ip->inp_list.le_next; - tp = intotcpcb(ip); - if (tp == 0 || tp->t_state == TCPS_LISTEN) - continue; - for (i = 0; i < TCPT_NTIMERS; i++) { - if (tp->t_timer[i] && --tp->t_timer[i] == 0) { -#ifdef TCPDEBUG - ostate = tp->t_state; -#endif - tp = tcp_timers(tp, i); - if (tp == NULL) - goto tpgone; -#ifdef TCPDEBUG - if (tp->t_inpcb->inp_socket->so_options - & SO_DEBUG) - tcp_trace(TA_USER, ostate, tp, - (struct tcpiphdr *)0, - PRU_SLOWTIMO); -#endif - } - } - tp->t_idle++; - tp->t_duration++; - if (tp->t_rtt) - tp->t_rtt++; -tpgone: - ; - } - tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ -#ifdef TCP_COMPAT_42 - if ((int)tcp_iss < 0) - tcp_iss = TCP_ISSINCR; /* XXX */ -#endif - tcp_now++; /* for timestamps */ - splx(s); -} -#ifndef TUBA_INCLUDE - -/* - * Cancel all timers for TCP tp. - */ -void -tcp_canceltimers(tp) - struct tcpcb *tp; -{ - register int i; - - for (i = 0; i < TCPT_NTIMERS; i++) - tp->t_timer[i] = 0; -} - -int tcp_backoff[TCP_MAXRXTSHIFT + 1] = - { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; - -static int tcp_totbackoff = 511; /* sum of tcp_backoff[] */ - -/* - * TCP timer processing. - */ -struct tcpcb * -tcp_timers(tp, timer) - register struct tcpcb *tp; - int timer; -{ - register int rexmt; - - switch (timer) { - - /* - * 2 MSL timeout in shutdown went off. If we're closed but - * still waiting for peer to close and connection has been idle - * too long, or if 2MSL time is up from TIME_WAIT, delete connection - * control block. Otherwise, check again in a bit. - */ - case TCPT_2MSL: - if (tp->t_state != TCPS_TIME_WAIT && - tp->t_idle <= tcp_maxidle) - tp->t_timer[TCPT_2MSL] = tcp_keepintvl; - else - tp = tcp_close(tp); - break; - - /* - * Retransmission timer went off. Message has not - * been acked within retransmit interval. Back off - * to a longer retransmit interval and retransmit one segment. - */ - case TCPT_REXMT: - if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { - tp->t_rxtshift = TCP_MAXRXTSHIFT; - tcpstat.tcps_timeoutdrop++; - tp = tcp_drop(tp, tp->t_softerror ? - tp->t_softerror : ETIMEDOUT); - break; - } - tcpstat.tcps_rexmttimeo++; - rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; - TCPT_RANGESET(tp->t_rxtcur, rexmt, - tp->t_rttmin, TCPTV_REXMTMAX); - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - /* - * If losing, let the lower level know and try for - * a better route. Also, if we backed off this far, - * our srtt estimate is probably bogus. Clobber it - * so we'll take the next rtt measurement as our srtt; - * move the current srtt into rttvar to keep the current - * retransmit times until then. - */ - if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) { - in_losing(tp->t_inpcb); - tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT); - tp->t_srtt = 0; - } - tp->snd_nxt = tp->snd_una; - /* - * Force a segment to be sent. - */ - tp->t_flags |= TF_ACKNOW; - /* - * If timing a segment in this window, stop the timer. - */ - tp->t_rtt = 0; - /* - * Close the congestion window down to one segment - * (we'll open it by one segment for each ack we get). - * Since we probably have a window's worth of unacked - * data accumulated, this "slow start" keeps us from - * dumping all that data as back-to-back packets (which - * might overwhelm an intermediate gateway). - * - * There are two phases to the opening: Initially we - * open by one mss on each ack. This makes the window - * size increase exponentially with time. If the - * window is larger than the path can handle, this - * exponential growth results in dropped packet(s) - * almost immediately. To get more time between - * drops but still "push" the network to take advantage - * of improving conditions, we switch from exponential - * to linear window opening at some threshhold size. - * For a threshhold, we use half the current window - * size, truncated to a multiple of the mss. - * - * (the minimum cwnd that will give us exponential - * growth is 2 mss. We don't allow the threshhold - * to go below this.) - */ - { - u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; - if (win < 2) - win = 2; - tp->snd_cwnd = tp->t_maxseg; - tp->snd_ssthresh = win * tp->t_maxseg; - tp->t_dupacks = 0; - } - (void) tcp_output(tp); - break; - - /* - * Persistance timer into zero window. - * Force a byte to be output, if possible. - */ - case TCPT_PERSIST: - tcpstat.tcps_persisttimeo++; - /* - * Hack: if the peer is dead/unreachable, we do not - * time out if the window is closed. After a full - * backoff, drop the connection if the idle time - * (no responses to probes) reaches the maximum - * backoff that we would use if retransmitting. - */ - if (tp->t_rxtshift == TCP_MAXRXTSHIFT) { - u_long maxidle = TCP_REXMTVAL(tp); - if (maxidle < tp->t_rttmin) - maxidle = tp->t_rttmin; - maxidle *= tcp_totbackoff; - if (tp->t_idle >= tcp_maxpersistidle || - tp->t_idle >= maxidle) { - tcpstat.tcps_persistdrop++; - tp = tcp_drop(tp, ETIMEDOUT); - break; - } - } - tcp_setpersist(tp); - tp->t_force = 1; - (void) tcp_output(tp); - tp->t_force = 0; - break; - - /* - * Keep-alive timer went off; send something - * or drop connection if idle for too long. - */ - case TCPT_KEEP: - tcpstat.tcps_keeptimeo++; - if (tp->t_state < TCPS_ESTABLISHED) - goto dropit; - if ((always_keepalive || - tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) && - tp->t_state <= TCPS_CLOSING) { - if (tp->t_idle >= tcp_keepidle + tcp_maxidle) - goto dropit; - /* - * Send a packet designed to force a response - * if the peer is up and reachable: - * either an ACK if the connection is still alive, - * or an RST if the peer has closed the connection - * due to timeout or reboot. - * Using sequence number tp->snd_una-1 - * causes the transmitted zero-length segment - * to lie outside the receive window; - * by the protocol spec, this requires the - * correspondent TCP to respond. - */ - tcpstat.tcps_keepprobe++; -#ifdef TCP_COMPAT_42 - /* - * The keepalive packet must have nonzero length - * to get a 4.2 host to respond. - */ - tcp_respond(tp, tp->t_template, (struct mbuf *)NULL, - tp->rcv_nxt - 1, tp->snd_una - 1, 0); -#else - tcp_respond(tp, tp->t_template, (struct mbuf *)NULL, - tp->rcv_nxt, tp->snd_una - 1, 0); -#endif - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; - } else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; - break; - dropit: - tcpstat.tcps_keepdrops++; - tp = tcp_drop(tp, ETIMEDOUT); - break; - } - return (tp); -} -#endif /* TUBA_INCLUDE */ diff --git a/c/src/exec/libnetworking/netinet/tcp_timer.h b/c/src/exec/libnetworking/netinet/tcp_timer.h deleted file mode 100644 index 38ffac4ee7..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_timer.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_TCP_TIMER_H_ -#define _NETINET_TCP_TIMER_H_ - -/* - * Definitions of the TCP timers. These timers are counted - * down PR_SLOWHZ times a second. - */ -#define TCPT_NTIMERS 4 - -#define TCPT_REXMT 0 /* retransmit */ -#define TCPT_PERSIST 1 /* retransmit persistence */ -#define TCPT_KEEP 2 /* keep alive */ -#define TCPT_2MSL 3 /* 2*msl quiet time timer */ - -/* - * The TCPT_REXMT timer is used to force retransmissions. - * The TCP has the TCPT_REXMT timer set whenever segments - * have been sent for which ACKs are expected but not yet - * received. If an ACK is received which advances tp->snd_una, - * then the retransmit timer is cleared (if there are no more - * outstanding segments) or reset to the base value (if there - * are more ACKs expected). Whenever the retransmit timer goes off, - * we retransmit one unacknowledged segment, and do a backoff - * on the retransmit timer. - * - * The TCPT_PERSIST timer is used to keep window size information - * flowing even if the window goes shut. If all previous transmissions - * have been acknowledged (so that there are no retransmissions in progress), - * and the window is too small to bother sending anything, then we start - * the TCPT_PERSIST timer. When it expires, if the window is nonzero, - * we go to transmit state. Otherwise, at intervals send a single byte - * into the peer's window to force him to update our window information. - * We do this at most as often as TCPT_PERSMIN time intervals, - * but no more frequently than the current estimate of round-trip - * packet time. The TCPT_PERSIST timer is cleared whenever we receive - * a window update from the peer. - * - * The TCPT_KEEP timer is used to keep connections alive. If an - * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time, - * but not yet established, then we drop the connection. Once the connection - * is established, if the connection is idle for TCPTV_KEEP_IDLE time - * (and keepalives have been enabled on the socket), we begin to probe - * the connection. We force the peer to send us a segment by sending: - * <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK> - * This segment is (deliberately) outside the window, and should elicit - * an ack segment in response from the peer. If, despite the TCPT_KEEP - * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE - * amount of time probing, then we drop the connection. - */ - -/* - * Time constants. - */ -#define TCPTV_MSL ( 30*PR_SLOWHZ) /* max seg lifetime (hah!) */ -#define TCPTV_SRTTBASE 0 /* base roundtrip time; - if 0, no idea yet */ -#define TCPTV_RTOBASE ( 3*PR_SLOWHZ) /* assumed RTO if no info */ -#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */ - -#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistence */ -#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */ - -#define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */ -#define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */ -#define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */ -#define TCPTV_KEEPCNT 8 /* max probes before drop */ - -#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */ -#define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) /* max allowable REXMT value */ - -#define TCPTV_TWTRUNC 8 /* RTO factor to truncate TW */ - -#define TCP_LINGERTIME 120 /* linger at most 2 minutes */ - -#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ - -#ifdef TCPTIMERS -static char *tcptimers[] = - { "REXMT", "PERSIST", "KEEP", "2MSL" }; -#endif - -/* - * Force a time value to be in a certain range. - */ -#define TCPT_RANGESET(tv, value, tvmin, tvmax) { \ - (tv) = (value); \ - if ((u_long)(tv) < (u_long)(tvmin)) \ - (tv) = (tvmin); \ - else if ((u_long)(tv) > (u_long)(tvmax)) \ - (tv) = (tvmax); \ -} - -#ifdef KERNEL -extern int tcp_keepinit; /* time to establish connection */ -extern int tcp_keepidle; /* time before keepalive probes begin */ -extern int tcp_keepintvl; /* time between keepalive probes */ -extern int tcp_maxidle; /* time to drop after starting probes */ -extern int tcp_ttl; /* time to live for TCP segs */ -extern int tcp_backoff[]; -#endif - -#endif diff --git a/c/src/exec/libnetworking/netinet/tcp_usrreq.c b/c/src/exec/libnetworking/netinet/tcp_usrreq.c deleted file mode 100644 index ecd9d95636..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_usrreq.c +++ /dev/null @@ -1,840 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. 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. 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. - * - * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94 - * $Id$ - */ - -#include "opt_tcpdebug.h" - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/protosw.h> -#include <sys/errno.h> -#include <sys/stat.h> - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#include <netinet/tcp_fsm.h> -#include <netinet/tcp_seq.h> -#include <netinet/tcp_timer.h> -#include <netinet/tcp_var.h> -#include <netinet/tcpip.h> -#ifdef TCPDEBUG -#include <netinet/tcp_debug.h> -#endif - -/* - * TCP protocol interface to socket abstraction. - */ -extern char *tcpstates[]; - -static int tcp_attach __P((struct socket *)); -static int tcp_connect __P((struct tcpcb *, struct mbuf *)); -static struct tcpcb * - tcp_disconnect __P((struct tcpcb *)); -static struct tcpcb * - tcp_usrclosed __P((struct tcpcb *)); - -#ifdef TCPDEBUG -#define TCPDEBUG0 int ostate -#define TCPDEBUG1() ostate = tp ? tp->t_state : 0 -#define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \ - tcp_trace(TA_USER, ostate, tp, 0, req) -#else -#define TCPDEBUG0 -#define TCPDEBUG1() -#define TCPDEBUG2(req) -#endif - -/* - * TCP attaches to socket via pru_attach(), reserving space, - * and an internet control block. - */ -static int -tcp_usr_attach(struct socket *so, int proto) -{ - int s = splnet(); - int error; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp = 0; - TCPDEBUG0; - - TCPDEBUG1(); - if (inp) { - error = EISCONN; - goto out; - } - - error = tcp_attach(so); - if (error) - goto out; - - if ((so->so_options & SO_LINGER) && so->so_linger == 0) - so->so_linger = TCP_LINGERTIME * hz; - tp = sototcpcb(so); -out: - TCPDEBUG2(PRU_ATTACH); - splx(s); - return error; -} - -/* - * pru_detach() detaches the TCP protocol from the socket. - * If the protocol state is non-embryonic, then can't - * do this directly: have to initiate a pru_disconnect(), - * which may finish later; embryonic TCB's can just - * be discarded here. - */ -static int -tcp_usr_detach(struct socket *so) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - TCPDEBUG0; - - if (inp == 0) { - splx(s); - return EINVAL; /* XXX */ - } - tp = intotcpcb(inp); - TCPDEBUG1(); - if (tp->t_state > TCPS_LISTEN) - tp = tcp_disconnect(tp); - else - tp = tcp_close(tp); - - TCPDEBUG2(PRU_DETACH); - splx(s); - return error; -} - -#define COMMON_START() TCPDEBUG0; \ - do { \ - if (inp == 0) { \ - splx(s); \ - return EINVAL; \ - } \ - tp = intotcpcb(inp); \ - TCPDEBUG1(); \ - } while(0) - -#define COMMON_END(req) out: TCPDEBUG2(req); splx(s); return error; goto out - - -/* - * Give the socket an address. - */ -static int -tcp_usr_bind(struct socket *so, struct mbuf *nam) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - struct sockaddr_in *sinp; - - COMMON_START(); - - /* - * Must check for multicast addresses and disallow binding - * to them. - */ - sinp = mtod(nam, struct sockaddr_in *); - if (sinp->sin_family == AF_INET && - IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { - error = EAFNOSUPPORT; - goto out; - } - error = in_pcbbind(inp, nam); - if (error) - goto out; - COMMON_END(PRU_BIND); - -} - -/* - * Prepare to accept connections. - */ -static int -tcp_usr_listen(struct socket *so) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - if (inp->inp_lport == 0) - error = in_pcbbind(inp, NULL); - if (error == 0) - tp->t_state = TCPS_LISTEN; - COMMON_END(PRU_LISTEN); -} - -/* - * Initiate connection to peer. - * Create a template for use in transmissions on this connection. - * Enter SYN_SENT state, and mark socket as connecting. - * Start keep-alive timer, and seed output sequence space. - * Send initial segment on connection. - */ -static int -tcp_usr_connect(struct socket *so, struct mbuf *nam) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - struct sockaddr_in *sinp; - - COMMON_START(); - - /* - * Must disallow TCP ``connections'' to multicast addresses. - */ - sinp = mtod(nam, struct sockaddr_in *); - if (sinp->sin_family == AF_INET - && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { - error = EAFNOSUPPORT; - goto out; - } - - if ((error = tcp_connect(tp, nam)) != 0) - goto out; - error = tcp_output(tp); - COMMON_END(PRU_CONNECT); -} - -/* - * Initiate disconnect from peer. - * If connection never passed embryonic stage, just drop; - * else if don't need to let data drain, then can just drop anyways, - * else have to begin TCP shutdown process: mark socket disconnecting, - * drain unread data, state switch to reflect user close, and - * send segment (e.g. FIN) to peer. Socket will be really disconnected - * when peer sends FIN and acks ours. - * - * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. - */ -static int -tcp_usr_disconnect(struct socket *so) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - tp = tcp_disconnect(tp); - COMMON_END(PRU_DISCONNECT); -} - -/* - * Accept a connection. Essentially all the work is - * done at higher levels; just return the address - * of the peer, storing through addr. - */ -static int -tcp_usr_accept(struct socket *so, struct mbuf *nam) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - in_setpeeraddr(inp, nam); - COMMON_END(PRU_ACCEPT); -} - -/* - * Mark the connection as being incapable of further output. - */ -static int -tcp_usr_shutdown(struct socket *so) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - socantsendmore(so); - tp = tcp_usrclosed(tp); - if (tp) - error = tcp_output(tp); - COMMON_END(PRU_SHUTDOWN); -} - -/* - * After a receive, possibly send window update to peer. - */ -static int -tcp_usr_rcvd(struct socket *so, int flags) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - tcp_output(tp); - COMMON_END(PRU_RCVD); -} - -/* - * Do a send by putting data in output queue and updating urgent - * marker if URG set. Possibly send more data. - */ -static int -tcp_usr_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam, - struct mbuf *control) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - if (control && control->m_len) { - m_freem(control); /* XXX shouldn't caller do this??? */ - if (m) - m_freem(m); - error = EINVAL; - goto out; - } - - if(!(flags & PRUS_OOB)) { - sbappend(&so->so_snd, m); - if (nam && tp->t_state < TCPS_SYN_SENT) { - /* - * Do implied connect if not yet connected, - * initialize window to default value, and - * initialize maxseg/maxopd using peer's cached - * MSS. - */ - error = tcp_connect(tp, nam); - if (error) - goto out; - tp->snd_wnd = TTCP_CLIENT_SND_WND; - tcp_mss(tp, -1); - } - - if (flags & PRUS_EOF) { - /* - * Close the send side of the connection after - * the data is sent. - */ - socantsendmore(so); - tp = tcp_usrclosed(tp); - } - if (tp != NULL) - error = tcp_output(tp); - } else { - if (sbspace(&so->so_snd) < -512) { - m_freem(m); - error = ENOBUFS; - goto out; - } - /* - * According to RFC961 (Assigned Protocols), - * the urgent pointer points to the last octet - * of urgent data. We continue, however, - * to consider it to indicate the first octet - * of data past the urgent section. - * Otherwise, snd_up should be one lower. - */ - sbappend(&so->so_snd, m); - if (nam && tp->t_state < TCPS_SYN_SENT) { - /* - * Do implied connect if not yet connected, - * initialize window to default value, and - * initialize maxseg/maxopd using peer's cached - * MSS. - */ - error = tcp_connect(tp, nam); - if (error) - goto out; - tp->snd_wnd = TTCP_CLIENT_SND_WND; - tcp_mss(tp, -1); - } - tp->snd_up = tp->snd_una + so->so_snd.sb_cc; - tp->t_force = 1; - error = tcp_output(tp); - tp->t_force = 0; - } - COMMON_END((flags & PRUS_OOB) ? PRU_SENDOOB : - ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND)); -} - -/* - * Abort the TCP. - */ -static int -tcp_usr_abort(struct socket *so) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - tp = tcp_drop(tp, ECONNABORTED); - COMMON_END(PRU_ABORT); -} - -/* - * Fill in st_bklsize for fstat() operations on a socket. - */ -static int -tcp_usr_sense(struct socket *so, struct stat *sb) -{ - int s = splnet(); - - sb->st_blksize = so->so_snd.sb_hiwat; - splx(s); - return 0; -} - -/* - * Receive out-of-band data. - */ -static int -tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - if ((so->so_oobmark == 0 && - (so->so_state & SS_RCVATMARK) == 0) || - so->so_options & SO_OOBINLINE || - tp->t_oobflags & TCPOOB_HADDATA) { - error = EINVAL; - goto out; - } - if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { - error = EWOULDBLOCK; - goto out; - } - m->m_len = 1; - *mtod(m, caddr_t) = tp->t_iobc; - if ((flags & MSG_PEEK) == 0) - tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); - COMMON_END(PRU_RCVOOB); -} - -static int -tcp_usr_sockaddr(struct socket *so, struct mbuf *nam) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - in_setsockaddr(inp, nam); - COMMON_END(PRU_SOCKADDR); -} - -static int -tcp_usr_peeraddr(struct socket *so, struct mbuf *nam) -{ - int s = splnet(); - int error = 0; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp; - - COMMON_START(); - in_setpeeraddr(inp, nam); - COMMON_END(PRU_PEERADDR); -} - -/* - * XXX - this should just be a call to in_control, but we need to get - * the types worked out. - */ -static int -tcp_usr_control(struct socket *so, int cmd, caddr_t arg, struct ifnet *ifp) -{ - return in_control(so, cmd, arg, ifp); -} - -/* xxx - should be const */ -struct pr_usrreqs tcp_usrreqs = { - tcp_usr_abort, tcp_usr_accept, tcp_usr_attach, tcp_usr_bind, - tcp_usr_connect, pru_connect2_notsupp, tcp_usr_control, tcp_usr_detach, - tcp_usr_disconnect, tcp_usr_listen, tcp_usr_peeraddr, tcp_usr_rcvd, - tcp_usr_rcvoob, tcp_usr_send, tcp_usr_sense, tcp_usr_shutdown, - tcp_usr_sockaddr -}; - -/* - * Common subroutine to open a TCP connection to remote host specified - * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local - * port number if needed. Call in_pcbladdr to do the routing and to choose - * a local host address (interface). If there is an existing incarnation - * of the same connection in TIME-WAIT state and if the remote host was - * sending CC options and if the connection duration was < MSL, then - * truncate the previous TIME-WAIT state and proceed. - * Initialize connection parameters and enter SYN-SENT state. - */ -static int -tcp_connect(tp, nam) - register struct tcpcb *tp; - struct mbuf *nam; -{ - struct inpcb *inp = tp->t_inpcb, *oinp; - struct socket *so = inp->inp_socket; - struct tcpcb *otp; - struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); - struct sockaddr_in *ifaddr; - int error; - struct rmxp_tao *taop; - struct rmxp_tao tao_noncached; - - if (inp->inp_lport == 0) { - error = in_pcbbind(inp, NULL); - if (error) - return error; - } - - /* - * Cannot simply call in_pcbconnect, because there might be an - * earlier incarnation of this same connection still in - * TIME_WAIT state, creating an ADDRINUSE error. - */ - error = in_pcbladdr(inp, nam, &ifaddr); - if (error) - return error; - oinp = in_pcblookuphash(inp->inp_pcbinfo, - sin->sin_addr, sin->sin_port, - inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr - : ifaddr->sin_addr, - inp->inp_lport, 0); - if (oinp) { - if (oinp != inp && (otp = intotcpcb(oinp)) != NULL && - otp->t_state == TCPS_TIME_WAIT && - otp->t_duration < TCPTV_MSL && - (otp->t_flags & TF_RCVD_CC)) - otp = tcp_close(otp); - else - return EADDRINUSE; - } - if (inp->inp_laddr.s_addr == INADDR_ANY) - inp->inp_laddr = ifaddr->sin_addr; - inp->inp_faddr = sin->sin_addr; - inp->inp_fport = sin->sin_port; - in_pcbrehash(inp); - - tp->t_template = tcp_template(tp); - if (tp->t_template == 0) { - in_pcbdisconnect(inp); - return ENOBUFS; - } - - /* Compute window scaling to request. */ - while (tp->request_r_scale < TCP_MAX_WINSHIFT && - (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) - tp->request_r_scale++; - - soisconnecting(so); - tcpstat.tcps_connattempt++; - tp->t_state = TCPS_SYN_SENT; - tp->t_timer[TCPT_KEEP] = tcp_keepinit; - tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; - tcp_sendseqinit(tp); - - /* - * Generate a CC value for this connection and - * check whether CC or CCnew should be used. - */ - if ((taop = tcp_gettaocache(tp->t_inpcb)) == NULL) { - taop = &tao_noncached; - bzero(taop, sizeof(*taop)); - } - - tp->cc_send = CC_INC(tcp_ccgen); - if (taop->tao_ccsent != 0 && - CC_GEQ(tp->cc_send, taop->tao_ccsent)) { - taop->tao_ccsent = tp->cc_send; - } else { - taop->tao_ccsent = 0; - tp->t_flags |= TF_SENDCCNEW; - } - - return 0; -} - -int -tcp_ctloutput(op, so, level, optname, mp) - int op; - struct socket *so; - int level, optname; - struct mbuf **mp; -{ - int error = 0, s; - struct inpcb *inp; - register struct tcpcb *tp; - register struct mbuf *m; - register int i; - - s = splnet(); - inp = sotoinpcb(so); - if (inp == NULL) { - splx(s); - if (op == PRCO_SETOPT && *mp) - (void) m_free(*mp); - return (ECONNRESET); - } - if (level != IPPROTO_TCP) { - error = ip_ctloutput(op, so, level, optname, mp); - splx(s); - return (error); - } - tp = intotcpcb(inp); - - switch (op) { - - case PRCO_SETOPT: - m = *mp; - switch (optname) { - - case TCP_NODELAY: - if (m == NULL || m->m_len < sizeof (int)) - error = EINVAL; - else if (*mtod(m, int *)) - tp->t_flags |= TF_NODELAY; - else - tp->t_flags &= ~TF_NODELAY; - break; - - case TCP_MAXSEG: - if (m && (i = *mtod(m, int *)) > 0 && i <= tp->t_maxseg) - tp->t_maxseg = i; - else - error = EINVAL; - break; - - case TCP_NOOPT: - if (m == NULL || m->m_len < sizeof (int)) - error = EINVAL; - else if (*mtod(m, int *)) - tp->t_flags |= TF_NOOPT; - else - tp->t_flags &= ~TF_NOOPT; - break; - - case TCP_NOPUSH: - if (m == NULL || m->m_len < sizeof (int)) - error = EINVAL; - else if (*mtod(m, int *)) - tp->t_flags |= TF_NOPUSH; - else - tp->t_flags &= ~TF_NOPUSH; - break; - - default: - error = ENOPROTOOPT; - break; - } - if (m) - (void) m_free(m); - break; - - case PRCO_GETOPT: - *mp = m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(int); - - switch (optname) { - case TCP_NODELAY: - *mtod(m, int *) = tp->t_flags & TF_NODELAY; - break; - case TCP_MAXSEG: - *mtod(m, int *) = tp->t_maxseg; - break; - case TCP_NOOPT: - *mtod(m, int *) = tp->t_flags & TF_NOOPT; - break; - case TCP_NOPUSH: - *mtod(m, int *) = tp->t_flags & TF_NOPUSH; - break; - default: - error = ENOPROTOOPT; - break; - } - break; - } - splx(s); - return (error); -} - -/* - * tcp_sendspace and tcp_recvspace are the default send and receive window - * sizes, respectively. These are obsolescent (this information should - * be set by the route). - */ -u_long tcp_sendspace = 1024*16; -SYSCTL_INT(_net_inet_tcp, TCPCTL_SENDSPACE, sendspace, - CTLFLAG_RW, &tcp_sendspace , 0, ""); -u_long tcp_recvspace = 1024*16; -SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, - CTLFLAG_RW, &tcp_recvspace , 0, ""); - -/* - * Attach TCP protocol to socket, allocating - * internet protocol control block, tcp control block, - * bufer space, and entering LISTEN state if to accept connections. - */ -static int -tcp_attach(so) - struct socket *so; -{ - register struct tcpcb *tp; - struct inpcb *inp; - int error; - - if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { - error = soreserve(so, tcp_sendspace, tcp_recvspace); - if (error) - return (error); - } - error = in_pcballoc(so, &tcbinfo); - if (error) - return (error); - inp = sotoinpcb(so); - tp = tcp_newtcpcb(inp); - if (tp == 0) { - int nofd = so->so_state & SS_NOFDREF; /* XXX */ - - so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ - in_pcbdetach(inp); - so->so_state |= nofd; - return (ENOBUFS); - } - tp->t_state = TCPS_CLOSED; - return (0); -} - -/* - * Initiate (or continue) disconnect. - * If embryonic state, just send reset (once). - * If in ``let data drain'' option and linger null, just drop. - * Otherwise (hard), mark socket disconnecting and drop - * current input data; switch states based on user close, and - * send segment to peer (with FIN). - */ -static struct tcpcb * -tcp_disconnect(tp) - register struct tcpcb *tp; -{ - struct socket *so = tp->t_inpcb->inp_socket; - - if (tp->t_state < TCPS_ESTABLISHED) - tp = tcp_close(tp); - else if ((so->so_options & SO_LINGER) && so->so_linger == 0) - tp = tcp_drop(tp, 0); - else { - soisdisconnecting(so); - sbflush(&so->so_rcv); - tp = tcp_usrclosed(tp); - if (tp) - (void) tcp_output(tp); - } - return (tp); -} - -/* - * User issued close, and wish to trail through shutdown states: - * if never received SYN, just forget it. If got a SYN from peer, - * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. - * If already got a FIN from peer, then almost done; go to LAST_ACK - * state. In all other cases, have already sent FIN to peer (e.g. - * after PRU_SHUTDOWN), and just have to play tedious game waiting - * for peer to send FIN or not respond to keep-alives, etc. - * We can let the user exit from the close as soon as the FIN is acked. - */ -static struct tcpcb * -tcp_usrclosed(tp) - register struct tcpcb *tp; -{ - - switch (tp->t_state) { - - case TCPS_CLOSED: - case TCPS_LISTEN: - tp->t_state = TCPS_CLOSED; - tp = tcp_close(tp); - break; - - case TCPS_SYN_SENT: - case TCPS_SYN_RECEIVED: - tp->t_flags |= TF_NEEDFIN; - break; - - case TCPS_ESTABLISHED: - tp->t_state = TCPS_FIN_WAIT_1; - break; - - case TCPS_CLOSE_WAIT: - tp->t_state = TCPS_LAST_ACK; - break; - } - if (tp && tp->t_state >= TCPS_FIN_WAIT_2) { - soisdisconnected(tp->t_inpcb->inp_socket); - /* To prevent the connection hanging in FIN_WAIT_2 forever. */ - if (tp->t_state == TCPS_FIN_WAIT_2) - tp->t_timer[TCPT_2MSL] = tcp_maxidle; - } - return (tp); -} - diff --git a/c/src/exec/libnetworking/netinet/tcp_var.h b/c/src/exec/libnetworking/netinet/tcp_var.h deleted file mode 100644 index 8e63a2cafe..0000000000 --- a/c/src/exec/libnetworking/netinet/tcp_var.h +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993, 1994, 1995 - * The Regents of the University of California. 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. 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. - * - * @(#)tcp_var.h 8.4 (Berkeley) 5/24/95 - * $Id$ - */ - -#ifndef _NETINET_TCP_VAR_H_ -#define _NETINET_TCP_VAR_H_ -/* - * Kernel variables for tcp. - */ - -/* - * Tcp control block, one per tcp; fields: - */ -struct tcpcb { - struct tcpiphdr *seg_next; /* sequencing queue */ - struct tcpiphdr *seg_prev; - int t_state; /* state of this connection */ - int t_timer[TCPT_NTIMERS]; /* tcp timers */ - int t_rxtshift; /* log(2) of rexmt exp. backoff */ - int t_rxtcur; /* current retransmit value */ - int t_dupacks; /* consecutive dup acks recd */ - u_int t_maxseg; /* maximum segment size */ - u_int t_maxopd; /* mss plus options */ - int t_force; /* 1 if forcing out a byte */ - u_int t_flags; -#define TF_ACKNOW 0x0001 /* ack peer immediately */ -#define TF_DELACK 0x0002 /* ack, but try to delay it */ -#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */ -#define TF_NOOPT 0x0008 /* don't use tcp options */ -#define TF_SENTFIN 0x0010 /* have sent FIN */ -#define TF_REQ_SCALE 0x0020 /* have/will request window scaling */ -#define TF_RCVD_SCALE 0x0040 /* other side has requested scaling */ -#define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */ -#define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */ -#define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */ -#define TF_NEEDSYN 0x0400 /* send SYN (implicit state) */ -#define TF_NEEDFIN 0x0800 /* send FIN (implicit state) */ -#define TF_NOPUSH 0x1000 /* don't push */ -#define TF_REQ_CC 0x2000 /* have/will request CC */ -#define TF_RCVD_CC 0x4000 /* a CC was received in SYN */ -#define TF_SENDCCNEW 0x8000 /* send CCnew instead of CC in SYN */ - - struct tcpiphdr *t_template; /* skeletal packet for transmit */ - struct inpcb *t_inpcb; /* back pointer to internet pcb */ -/* - * The following fields are used as in the protocol specification. - * See RFC783, Dec. 1981, page 21. - */ -/* send sequence variables */ - tcp_seq snd_una; /* send unacknowledged */ - tcp_seq snd_nxt; /* send next */ - tcp_seq snd_up; /* send urgent pointer */ - tcp_seq snd_wl1; /* window update seg seq number */ - tcp_seq snd_wl2; /* window update seg ack number */ - tcp_seq iss; /* initial send sequence number */ - u_long snd_wnd; /* send window */ -/* receive sequence variables */ - u_long rcv_wnd; /* receive window */ - tcp_seq rcv_nxt; /* receive next */ - tcp_seq rcv_up; /* receive urgent pointer */ - tcp_seq irs; /* initial receive sequence number */ -/* - * Additional variables for this implementation. - */ -/* receive variables */ - tcp_seq rcv_adv; /* advertised window */ -/* retransmit variables */ - tcp_seq snd_max; /* highest sequence number sent; - * used to recognize retransmits - */ -/* congestion control (for slow start, source quench, retransmit after loss) */ - u_long snd_cwnd; /* congestion-controlled window */ - u_long snd_ssthresh; /* snd_cwnd size threshold for - * for slow start exponential to - * linear switch - */ -/* - * transmit timing stuff. See below for scale of srtt and rttvar. - * "Variance" is actually smoothed difference. - */ - u_int t_idle; /* inactivity time */ - int t_rtt; /* round trip time */ - tcp_seq t_rtseq; /* sequence number being timed */ - int t_srtt; /* smoothed round-trip time */ - int t_rttvar; /* variance in round-trip time */ - u_int t_rttmin; /* minimum rtt allowed */ - u_long max_sndwnd; /* largest window peer has offered */ - -/* out-of-band data */ - char t_oobflags; /* have some */ - char t_iobc; /* input character */ -#define TCPOOB_HAVEDATA 0x01 -#define TCPOOB_HADDATA 0x02 - int t_softerror; /* possible error not yet reported */ - -/* RFC 1323 variables */ - u_char snd_scale; /* window scaling for send window */ - u_char rcv_scale; /* window scaling for recv window */ - u_char request_r_scale; /* pending window scaling */ - u_char requested_s_scale; - u_long ts_recent; /* timestamp echo data */ - u_long ts_recent_age; /* when last updated */ - tcp_seq last_ack_sent; -/* RFC 1644 variables */ - tcp_cc cc_send; /* send connection count */ - tcp_cc cc_recv; /* receive connection count */ - u_long t_duration; /* connection duration */ - -/* TUBA stuff */ - caddr_t t_tuba_pcb; /* next level down pcb for TCP over z */ -/* More RTT stuff */ - u_long t_rttupdated; /* number of times rtt sampled */ -}; - -/* - * Structure to hold TCP options that are only used during segment - * processing (in tcp_input), but not held in the tcpcb. - * It's basically used to reduce the number of parameters - * to tcp_dooptions. - */ -struct tcpopt { - u_long to_flag; /* which options are present */ -#define TOF_TS 0x0001 /* timestamp */ -#define TOF_CC 0x0002 /* CC and CCnew are exclusive */ -#define TOF_CCNEW 0x0004 -#define TOF_CCECHO 0x0008 - u_long to_tsval; - u_long to_tsecr; - tcp_cc to_cc; /* holds CC or CCnew */ - tcp_cc to_ccecho; -}; - -/* - * The TAO cache entry which is stored in the protocol family specific - * portion of the route metrics. - */ -struct rmxp_tao { - tcp_cc tao_cc; /* latest CC in valid SYN */ - tcp_cc tao_ccsent; /* latest CC sent to peer */ - u_short tao_mssopt; /* peer's cached MSS */ -#ifdef notyet - u_short tao_flags; /* cache status flags */ -#define TAOF_DONT 0x0001 /* peer doesn't understand rfc1644 */ -#define TAOF_OK 0x0002 /* peer does understand rfc1644 */ -#define TAOF_UNDEF 0 /* we don't know yet */ -#endif /* notyet */ -}; -#define rmx_taop(r) ((struct rmxp_tao *)(r).rmx_filler) - -#define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_ppcb) -#define sototcpcb(so) (intotcpcb(sotoinpcb(so))) - -/* - * The smoothed round-trip time and estimated variance - * are stored as fixed point numbers scaled by the values below. - * For convenience, these scales are also used in smoothing the average - * (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed). - * With these scales, srtt has 3 bits to the right of the binary point, - * and thus an "ALPHA" of 0.875. rttvar has 2 bits to the right of the - * binary point, and is smoothed with an ALPHA of 0.75. - */ -#define TCP_RTT_SCALE 32 /* multiplier for srtt; 3 bits frac. */ -#define TCP_RTT_SHIFT 5 /* shift for srtt; 3 bits frac. */ -#define TCP_RTTVAR_SCALE 16 /* multiplier for rttvar; 2 bits */ -#define TCP_RTTVAR_SHIFT 4 /* shift for rttvar; 2 bits */ -#define TCP_DELTA_SHIFT 2 /* see tcp_input.c */ - -/* - * The initial retransmission should happen at rtt + 4 * rttvar. - * Because of the way we do the smoothing, srtt and rttvar - * will each average +1/2 tick of bias. When we compute - * the retransmit timer, we want 1/2 tick of rounding and - * 1 extra tick because of +-1/2 tick uncertainty in the - * firing of the timer. The bias will give us exactly the - * 1.5 tick we need. But, because the bias is - * statistical, we have to test that we don't drop below - * the minimum feasible timer (which is 2 ticks). - * This version of the macro adapted from a paper by Lawrence - * Brakmo and Larry Peterson which outlines a problem caused - * by insufficient precision in the original implementation, - * which results in inappropriately large RTO values for very - * fast networks. - */ -#define TCP_REXMTVAL(tp) \ - ((((tp)->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT)) \ - + (tp)->t_rttvar) >> TCP_DELTA_SHIFT) - -/* XXX - * We want to avoid doing m_pullup on incoming packets but that - * means avoiding dtom on the tcp reassembly code. That in turn means - * keeping an mbuf pointer in the reassembly queue (since we might - * have a cluster). As a quick hack, the source & destination - * port numbers (which are no longer needed once we've located the - * tcpcb) are overlayed with an mbuf pointer. - */ -#define REASS_MBUF(ti) (*(struct mbuf **)&((ti)->ti_t)) - -/* - * TCP statistics. - * Many of these should be kept per connection, - * but that's inconvenient at the moment. - */ -struct tcpstat { - u_long tcps_connattempt; /* connections initiated */ - u_long tcps_accepts; /* connections accepted */ - u_long tcps_connects; /* connections established */ - u_long tcps_drops; /* connections dropped */ - u_long tcps_conndrops; /* embryonic connections dropped */ - u_long tcps_closed; /* conn. closed (includes drops) */ - u_long tcps_segstimed; /* segs where we tried to get rtt */ - u_long tcps_rttupdated; /* times we succeeded */ - u_long tcps_delack; /* delayed acks sent */ - u_long tcps_timeoutdrop; /* conn. dropped in rxmt timeout */ - u_long tcps_rexmttimeo; /* retransmit timeouts */ - u_long tcps_persisttimeo; /* persist timeouts */ - u_long tcps_keeptimeo; /* keepalive timeouts */ - u_long tcps_keepprobe; /* keepalive probes sent */ - u_long tcps_keepdrops; /* connections dropped in keepalive */ - - u_long tcps_sndtotal; /* total packets sent */ - u_long tcps_sndpack; /* data packets sent */ - u_long tcps_sndbyte; /* data bytes sent */ - u_long tcps_sndrexmitpack; /* data packets retransmitted */ - u_long tcps_sndrexmitbyte; /* data bytes retransmitted */ - u_long tcps_sndacks; /* ack-only packets sent */ - u_long tcps_sndprobe; /* window probes sent */ - u_long tcps_sndurg; /* packets sent with URG only */ - u_long tcps_sndwinup; /* window update-only packets sent */ - u_long tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */ - - u_long tcps_rcvtotal; /* total packets received */ - u_long tcps_rcvpack; /* packets received in sequence */ - u_long tcps_rcvbyte; /* bytes received in sequence */ - u_long tcps_rcvbadsum; /* packets received with ccksum errs */ - u_long tcps_rcvbadoff; /* packets received with bad offset */ - u_long tcps_rcvshort; /* packets received too short */ - u_long tcps_rcvduppack; /* duplicate-only packets received */ - u_long tcps_rcvdupbyte; /* duplicate-only bytes received */ - u_long tcps_rcvpartduppack; /* packets with some duplicate data */ - u_long tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ - u_long tcps_rcvoopack; /* out-of-order packets received */ - u_long tcps_rcvoobyte; /* out-of-order bytes received */ - u_long tcps_rcvpackafterwin; /* packets with data after window */ - u_long tcps_rcvbyteafterwin; /* bytes rcvd after window */ - u_long tcps_rcvafterclose; /* packets rcvd after "close" */ - u_long tcps_rcvwinprobe; /* rcvd window probe packets */ - u_long tcps_rcvdupack; /* rcvd duplicate acks */ - u_long tcps_rcvacktoomuch; /* rcvd acks for unsent data */ - u_long tcps_rcvackpack; /* rcvd ack packets */ - u_long tcps_rcvackbyte; /* bytes acked by rcvd acks */ - u_long tcps_rcvwinupd; /* rcvd window update packets */ - u_long tcps_pawsdrop; /* segments dropped due to PAWS */ - u_long tcps_predack; /* times hdr predict ok for acks */ - u_long tcps_preddat; /* times hdr predict ok for data pkts */ - u_long tcps_pcbcachemiss; - u_long tcps_cachedrtt; /* times cached RTT in route updated */ - u_long tcps_cachedrttvar; /* times cached rttvar updated */ - u_long tcps_cachedssthresh; /* times cached ssthresh updated */ - u_long tcps_usedrtt; /* times RTT initialized from route */ - u_long tcps_usedrttvar; /* times RTTVAR initialized from rt */ - u_long tcps_usedssthresh; /* times ssthresh initialized from rt*/ - u_long tcps_persistdrop; /* timeout in persist state */ - u_long tcps_badsyn; /* bogus SYN, e.g. premature ACK */ - u_long tcps_mturesent; /* resends due to MTU discovery */ - u_long tcps_listendrop; /* listen queue overflows */ -}; - -/* - * Names for TCP sysctl objects - */ -#define TCPCTL_DO_RFC1323 1 /* use RFC-1323 extensions */ -#define TCPCTL_DO_RFC1644 2 /* use RFC-1644 extensions */ -#define TCPCTL_MSSDFLT 3 /* MSS default */ -#define TCPCTL_STATS 4 /* statistics (read-only) */ -#define TCPCTL_RTTDFLT 5 /* default RTT estimate */ -#define TCPCTL_KEEPIDLE 6 /* keepalive idle timer */ -#define TCPCTL_KEEPINTVL 7 /* interval to send keepalives */ -#define TCPCTL_SENDSPACE 8 /* send buffer space */ -#define TCPCTL_RECVSPACE 9 /* receive buffer space */ -#define TCPCTL_KEEPINIT 10 /* receive buffer space */ -#define TCPCTL_MAXID 11 - -#define TCPCTL_NAMES { \ - { 0, 0 }, \ - { "rfc1323", CTLTYPE_INT }, \ - { "rfc1644", CTLTYPE_INT }, \ - { "mssdflt", CTLTYPE_INT }, \ - { "stats", CTLTYPE_STRUCT }, \ - { "rttdflt", CTLTYPE_INT }, \ - { "keepidle", CTLTYPE_INT }, \ - { "keepintvl", CTLTYPE_INT }, \ - { "sendspace", CTLTYPE_INT }, \ - { "recvspace", CTLTYPE_INT }, \ - { "keepinit", CTLTYPE_INT }, \ -} - -#ifdef KERNEL -extern struct inpcbhead tcb; /* head of queue of active tcpcb's */ -extern struct inpcbinfo tcbinfo; -extern struct tcpstat tcpstat; /* tcp statistics */ -extern int tcp_mssdflt; /* XXX */ -extern u_long tcp_now; /* for RFC 1323 timestamps */ - -void tcp_canceltimers __P((struct tcpcb *)); -struct tcpcb * - tcp_close __P((struct tcpcb *)); -void tcp_ctlinput __P((int, struct sockaddr *, void *)); -int tcp_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); -struct tcpcb * - tcp_drop __P((struct tcpcb *, int)); -void tcp_drain __P((void)); -void tcp_fasttimo __P((void)); -struct rmxp_tao * - tcp_gettaocache __P((struct inpcb *)); -void tcp_init __P((void)); -void tcp_input __P((struct mbuf *, int)); -void tcp_mss __P((struct tcpcb *, int)); -int tcp_mssopt __P((struct tcpcb *)); -void tcp_mtudisc __P((struct inpcb *, int)); -struct tcpcb * - tcp_newtcpcb __P((struct inpcb *)); -int tcp_output __P((struct tcpcb *)); -void tcp_quench __P((struct inpcb *, int)); -void tcp_respond __P((struct tcpcb *, - struct tcpiphdr *, struct mbuf *, u_long, u_long, int)); -struct rtentry * - tcp_rtlookup __P((struct inpcb *)); -void tcp_setpersist __P((struct tcpcb *)); -void tcp_slowtimo __P((void)); -struct tcpiphdr * - tcp_template __P((struct tcpcb *)); -struct tcpcb * - tcp_timers __P((struct tcpcb *, int)); -void tcp_trace __P((int, int, struct tcpcb *, struct tcpiphdr *, int)); - -extern struct pr_usrreqs tcp_usrreqs; -extern u_long tcp_sendspace; -extern u_long tcp_recvspace; - -#endif /* KERNEL */ - -#endif /* _NETINET_TCP_VAR_H_ */ diff --git a/c/src/exec/libnetworking/netinet/tcpip.h b/c/src/exec/libnetworking/netinet/tcpip.h deleted file mode 100644 index b8634bfd15..0000000000 --- a/c/src/exec/libnetworking/netinet/tcpip.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)tcpip.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_TCPIP_H_ -#define _NETINET_TCPIP_H_ - -/* - * Tcp+ip header, after ip options removed. - */ -struct tcpiphdr { - struct ipovly ti_i; /* overlaid ip structure */ - struct tcphdr ti_t; /* tcp header */ -}; -#ifdef notyet -/* - * Tcp+ip header, after ip options removed but including TCP options. - */ -struct full_tcpiphdr { - struct ipovly ti_i; /* overlaid ip structure */ - struct tcphdr ti_t; /* tcp header */ - char ti_o[TCP_MAXOLEN]; /* space for tcp options */ -}; -#endif /* notyet */ -#define ti_next ti_i.ih_next -#define ti_prev ti_i.ih_prev -#define ti_x1 ti_i.ih_x1 -#define ti_pr ti_i.ih_pr -#define ti_len ti_i.ih_len -#define ti_src ti_i.ih_src -#define ti_dst ti_i.ih_dst -#define ti_sport ti_t.th_sport -#define ti_dport ti_t.th_dport -#define ti_seq ti_t.th_seq -#define ti_ack ti_t.th_ack -#define ti_x2 ti_t.th_x2 -#define ti_off ti_t.th_off -#define ti_flags ti_t.th_flags -#define ti_win ti_t.th_win -#define ti_sum ti_t.th_sum -#define ti_urp ti_t.th_urp - -#endif diff --git a/c/src/exec/libnetworking/netinet/udp.h b/c/src/exec/libnetworking/netinet/udp.h deleted file mode 100644 index e73e1f4ddb..0000000000 --- a/c/src/exec/libnetworking/netinet/udp.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)udp.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_UDP_H_ -#define _NETINET_UDP_H_ - -/* - * Udp protocol header. - * Per RFC 768, September, 1981. - */ -struct udphdr { - u_short uh_sport; /* source port */ - u_short uh_dport; /* destination port */ - u_short uh_ulen; /* udp length */ - u_short uh_sum; /* udp checksum */ -}; - -#endif diff --git a/c/src/exec/libnetworking/netinet/udp_usrreq.c b/c/src/exec/libnetworking/netinet/udp_usrreq.c deleted file mode 100644 index 16c5fce2df..0000000000 --- a/c/src/exec/libnetworking/netinet/udp_usrreq.c +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 - * The Regents of the University of California. 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. 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. - * - * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 - * $Id$ - */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/errno.h> -#include <sys/stat.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/syslog.h> - -#include <net/if.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/in_var.h> -#include <netinet/ip_var.h> -#include <netinet/ip_icmp.h> -#include <netinet/udp.h> -#include <netinet/udp_var.h> - -/* - * UDP protocol implementation. - * Per RFC 768, August, 1980. - */ -#ifndef COMPAT_42 -static int udpcksum = 1; -#else -static int udpcksum = 0; /* XXX */ -#endif -SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW, - &udpcksum, 0, ""); - -static int log_in_vain = 0; -SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW, - &log_in_vain, 0, ""); - -static struct inpcbhead udb; /* from udp_var.h */ -static struct inpcbinfo udbinfo; - -#ifndef UDBHASHSIZE -#define UDBHASHSIZE 64 -#endif - - struct udpstat udpstat; /* from udp_var.h */ -SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD, - &udpstat, udpstat, ""); - -static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET }; - -static void udp_detach __P((struct inpcb *)); -static int udp_output __P((struct inpcb *, struct mbuf *, struct mbuf *, - struct mbuf *)); -static void udp_notify __P((struct inpcb *, int)); - -void -udp_init() -{ - LIST_INIT(&udb); - udbinfo.listhead = &udb; - udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask); -} - -void -udp_input(m, iphlen) - register struct mbuf *m; - int iphlen; -{ - register struct ip *ip; - register struct udphdr *uh; - register struct inpcb *inp; - struct mbuf *opts = 0; - int len; - struct ip save_ip; - - udpstat.udps_ipackets++; - - /* - * Strip IP options, if any; should skip this, - * make available to user, and use on returned packets, - * but we don't yet have a way to check the checksum - * with options still present. - */ - if (iphlen > sizeof (struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - iphlen = sizeof(struct ip); - } - - /* - * Get IP and UDP header together in first mbuf. - */ - ip = mtod(m, struct ip *); - if (m->m_len < iphlen + sizeof(struct udphdr)) { - if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) { - udpstat.udps_hdrops++; - return; - } - ip = mtod(m, struct ip *); - } - uh = (struct udphdr *)((caddr_t)ip + iphlen); - - /* - * Make mbuf data length reflect UDP length. - * If not enough data to reflect UDP length, drop. - */ - len = ntohs((u_short)uh->uh_ulen); - if (ip->ip_len != len) { - if (len > ip->ip_len || len < sizeof(struct udphdr)) { - udpstat.udps_badlen++; - goto bad; - } - m_adj(m, len - ip->ip_len); - /* ip->ip_len = len; */ - } - /* - * Save a copy of the IP header in case we want restore it - * for sending an ICMP error message in response. - */ - save_ip = *ip; - - /* - * Checksum extended UDP header and data. - */ - if (uh->uh_sum) { - ((struct ipovly *)ip)->ih_next = 0; - ((struct ipovly *)ip)->ih_prev = 0; - ((struct ipovly *)ip)->ih_x1 = 0; - ((struct ipovly *)ip)->ih_len = uh->uh_ulen; - uh->uh_sum = in_cksum(m, len + sizeof (struct ip)); - if (uh->uh_sum) { - udpstat.udps_badsum++; - m_freem(m); - return; - } - } - - if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || - in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { - struct inpcb *last; - /* - * Deliver a multicast or broadcast datagram to *all* sockets - * for which the local and remote addresses and ports match - * those of the incoming datagram. This allows more than - * one process to receive multi/broadcasts on the same port. - * (This really ought to be done for unicast datagrams as - * well, but that would cause problems with existing - * applications that open both address-specific sockets and - * a wildcard socket listening to the same port -- they would - * end up receiving duplicates of every unicast datagram. - * Those applications open the multiple sockets to overcome an - * inadequacy of the UDP socket interface, but for backwards - * compatibility we avoid the problem here rather than - * fixing the interface. Maybe 4.5BSD will remedy this?) - */ - - /* - * Construct sockaddr format source address. - */ - udp_in.sin_port = uh->uh_sport; - udp_in.sin_addr = ip->ip_src; - m->m_len -= sizeof (struct udpiphdr); - m->m_data += sizeof (struct udpiphdr); - /* - * Locate pcb(s) for datagram. - * (Algorithm copied from raw_intr().) - */ - last = NULL; - for (inp = udb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { - if (inp->inp_lport != uh->uh_dport) - continue; - if (inp->inp_laddr.s_addr != INADDR_ANY) { - if (inp->inp_laddr.s_addr != - ip->ip_dst.s_addr) - continue; - } - if (inp->inp_faddr.s_addr != INADDR_ANY) { - if (inp->inp_faddr.s_addr != - ip->ip_src.s_addr || - inp->inp_fport != uh->uh_sport) - continue; - } - - if (last != NULL) { - struct mbuf *n; - - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { - if (last->inp_flags & INP_CONTROLOPTS - || last->inp_socket->so_options & SO_TIMESTAMP) - ip_savecontrol(last, &opts, ip, n); - if (sbappendaddr(&last->inp_socket->so_rcv, - (struct sockaddr *)&udp_in, - n, opts) == 0) { - m_freem(n); - if (opts) - m_freem(opts); - udpstat.udps_fullsock++; - } else - sorwakeup(last->inp_socket); - opts = 0; - } - } - last = inp; - /* - * Don't look for additional matches if this one does - * not have either the SO_REUSEPORT or SO_REUSEADDR - * socket options set. This heuristic avoids searching - * through all pcbs in the common case of a non-shared - * port. It * assumes that an application will never - * clear these options after setting them. - */ - if (((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)) - break; - } - - if (last == NULL) { - /* - * No matching pcb found; discard datagram. - * (No need to send an ICMP Port Unreachable - * for a broadcast or multicast datgram.) - */ - udpstat.udps_noportbcast++; - goto bad; - } - if (last->inp_flags & INP_CONTROLOPTS - || last->inp_socket->so_options & SO_TIMESTAMP) - ip_savecontrol(last, &opts, ip, m); - if (sbappendaddr(&last->inp_socket->so_rcv, - (struct sockaddr *)&udp_in, - m, opts) == 0) { - udpstat.udps_fullsock++; - goto bad; - } - sorwakeup(last->inp_socket); - return; - } - /* - * Locate pcb for datagram. - */ - inp = in_pcblookuphash(&udbinfo, ip->ip_src, uh->uh_sport, - ip->ip_dst, uh->uh_dport, 1); - if (inp == NULL) { - if (log_in_vain) { - char buf[4*sizeof "123"]; - - strcpy(buf, inet_ntoa(ip->ip_dst)); - log(LOG_INFO, "Connection attempt to UDP %s:%d" - " from %s:%d\n", - buf, ntohs(uh->uh_dport), - inet_ntoa(ip->ip_src), ntohs(uh->uh_sport)); - } - udpstat.udps_noport++; - if (m->m_flags & (M_BCAST | M_MCAST)) { - udpstat.udps_noportbcast++; - goto bad; - } - *ip = save_ip; - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); - return; - } - - /* - * Construct sockaddr format source address. - * Stuff source address and datagram in user buffer. - */ - udp_in.sin_port = uh->uh_sport; - udp_in.sin_addr = ip->ip_src; - if (inp->inp_flags & INP_CONTROLOPTS - || inp->inp_socket->so_options & SO_TIMESTAMP) - ip_savecontrol(inp, &opts, ip, m); - iphlen += sizeof(struct udphdr); - m->m_len -= iphlen; - m->m_pkthdr.len -= iphlen; - m->m_data += iphlen; - if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, - m, opts) == 0) { - udpstat.udps_fullsock++; - goto bad; - } - sorwakeup(inp->inp_socket); - return; -bad: - m_freem(m); - if (opts) - m_freem(opts); -} - -/* - * Notify a udp user of an asynchronous error; - * just wake up so that he can collect error status. - */ -static void -udp_notify(inp, errnum) - register struct inpcb *inp; - int errnum; -{ - inp->inp_socket->so_error = errnum; - sorwakeup(inp->inp_socket); - sowwakeup(inp->inp_socket); -} - -void -udp_ctlinput(cmd, sa, vip) - int cmd; - struct sockaddr *sa; - void *vip; -{ - register struct ip *ip = vip; - register struct udphdr *uh; - - if (!PRC_IS_REDIRECT(cmd) && - ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0)) - return; - if (ip) { - uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); - in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport, - cmd, udp_notify); - } else - in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify); -} - -static int -udp_output(inp, m, addr, control) - register struct inpcb *inp; - register struct mbuf *m; - struct mbuf *addr, *control; -{ - register struct udpiphdr *ui; - register int len = m->m_pkthdr.len; - struct in_addr laddr; - int s = 0, error = 0; - - if (control) - m_freem(control); /* XXX */ - - if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) { - error = EMSGSIZE; - goto release; - } - - if (addr) { - laddr = inp->inp_laddr; - if (inp->inp_faddr.s_addr != INADDR_ANY) { - error = EISCONN; - goto release; - } - /* - * Must block input while temporarily connected. - */ - s = splnet(); - error = in_pcbconnect(inp, addr); - if (error) { - splx(s); - goto release; - } - } else { - if (inp->inp_faddr.s_addr == INADDR_ANY) { - error = ENOTCONN; - goto release; - } - } - /* - * Calculate data length and get a mbuf - * for UDP and IP headers. - */ - M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); - if (m == 0) { - error = ENOBUFS; - if (addr) - splx(s); - goto release; - } - - /* - * Fill in mbuf with extended UDP header - * and addresses and length put into network format. - */ - ui = mtod(m, struct udpiphdr *); - ui->ui_next = ui->ui_prev = 0; - ui->ui_x1 = 0; - ui->ui_pr = IPPROTO_UDP; - ui->ui_len = htons((u_short)len + sizeof (struct udphdr)); - ui->ui_src = inp->inp_laddr; - ui->ui_dst = inp->inp_faddr; - ui->ui_sport = inp->inp_lport; - ui->ui_dport = inp->inp_fport; - ui->ui_ulen = ui->ui_len; - - /* - * Stuff checksum and output datagram. - */ - ui->ui_sum = 0; - if (udpcksum) { - if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) - ui->ui_sum = 0xffff; - } - ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; - ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */ - ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */ - udpstat.udps_opackets++; - error = ip_output(m, inp->inp_options, &inp->inp_route, - inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), - inp->inp_moptions); - - if (addr) { - in_pcbdisconnect(inp); - inp->inp_laddr = laddr; - splx(s); - } - return (error); - -release: - m_freem(m); - return (error); -} - -static u_long udp_sendspace = 9216; /* really max datagram size */ - /* 40 1K datagrams */ -SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW, - &udp_sendspace, 0, ""); - -static u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); -SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW, - &udp_recvspace, 0, ""); - -/*ARGSUSED*/ -int -udp_usrreq(so, req, m, addr, control) - struct socket *so; - int req; - struct mbuf *m, *addr, *control; -{ - struct inpcb *inp = sotoinpcb(so); - int error = 0; - int s; - - if (req == PRU_CONTROL) - return (in_control(so, (u_long)m, (caddr_t)addr, - (struct ifnet *)control)); - if (inp == NULL && req != PRU_ATTACH) { - error = EINVAL; - goto release; - } - /* - * Note: need to block udp_input while changing - * the udp pcb queue and/or pcb addresses. - */ - switch (req) { - - case PRU_ATTACH: - if (inp != NULL) { - error = EINVAL; - break; - } - s = splnet(); - error = in_pcballoc(so, &udbinfo); - splx(s); - if (error) - break; - error = soreserve(so, udp_sendspace, udp_recvspace); - if (error) - break; - ((struct inpcb *) so->so_pcb)->inp_ip_ttl = ip_defttl; - break; - - case PRU_DETACH: - udp_detach(inp); - break; - - case PRU_BIND: - s = splnet(); - error = in_pcbbind(inp, addr); - splx(s); - break; - - case PRU_LISTEN: - error = EOPNOTSUPP; - break; - - case PRU_CONNECT: - if (inp->inp_faddr.s_addr != INADDR_ANY) { - error = EISCONN; - break; - } - s = splnet(); - error = in_pcbconnect(inp, addr); - splx(s); - if (error == 0) - soisconnected(so); - break; - - case PRU_CONNECT2: - error = EOPNOTSUPP; - break; - - case PRU_ACCEPT: - error = EOPNOTSUPP; - break; - - case PRU_DISCONNECT: - if (inp->inp_faddr.s_addr == INADDR_ANY) { - error = ENOTCONN; - break; - } - s = splnet(); - in_pcbdisconnect(inp); - inp->inp_laddr.s_addr = INADDR_ANY; - splx(s); - so->so_state &= ~SS_ISCONNECTED; /* XXX */ - break; - - case PRU_SHUTDOWN: - socantsendmore(so); - break; - - case PRU_SEND: - return (udp_output(inp, m, addr, control)); - - case PRU_ABORT: - soisdisconnected(so); - udp_detach(inp); - break; - - case PRU_SOCKADDR: - in_setsockaddr(inp, addr); - break; - - case PRU_PEERADDR: - in_setpeeraddr(inp, addr); - break; - - case PRU_SENSE: - /* - * stat: don't bother with a blocksize. - */ - return (0); - - case PRU_SENDOOB: - case PRU_FASTTIMO: - case PRU_SLOWTIMO: - case PRU_PROTORCV: - case PRU_PROTOSEND: - error = EOPNOTSUPP; - break; - - case PRU_RCVD: - case PRU_RCVOOB: - return (EOPNOTSUPP); /* do not free mbuf's */ - - default: - panic("udp_usrreq"); - } - -release: - if (control) { - printf("udp control data unexpectedly retained\n"); - m_freem(control); - } - if (m) - m_freem(m); - return (error); -} - -static void -udp_detach(inp) - struct inpcb *inp; -{ - int s = splnet(); - - in_pcbdetach(inp); - splx(s); -} diff --git a/c/src/exec/libnetworking/netinet/udp_var.h b/c/src/exec/libnetworking/netinet/udp_var.h deleted file mode 100644 index 90785b53de..0000000000 --- a/c/src/exec/libnetworking/netinet/udp_var.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1989, 1993 - * The Regents of the University of California. 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. 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. - * - * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 - * $Id$ - */ - -#ifndef _NETINET_UDP_VAR_H_ -#define _NETINET_UDP_VAR_H_ - -/* - * UDP kernel structures and variables. - */ -struct udpiphdr { - struct ipovly ui_i; /* overlaid ip structure */ - struct udphdr ui_u; /* udp header */ -}; -#define ui_next ui_i.ih_next -#define ui_prev ui_i.ih_prev -#define ui_x1 ui_i.ih_x1 -#define ui_pr ui_i.ih_pr -#define ui_len ui_i.ih_len -#define ui_src ui_i.ih_src -#define ui_dst ui_i.ih_dst -#define ui_sport ui_u.uh_sport -#define ui_dport ui_u.uh_dport -#define ui_ulen ui_u.uh_ulen -#define ui_sum ui_u.uh_sum - -struct udpstat { - /* input statistics: */ - u_long udps_ipackets; /* total input packets */ - u_long udps_hdrops; /* packet shorter than header */ - u_long udps_badsum; /* checksum error */ - u_long udps_badlen; /* data length larger than packet */ - u_long udps_noport; /* no socket on port */ - u_long udps_noportbcast; /* of above, arrived as broadcast */ - u_long udps_fullsock; /* not delivered, input socket full */ - u_long udpps_pcbcachemiss; /* input packets missing pcb cache */ - u_long udpps_pcbhashmiss; /* input packets not for hashed pcb */ - /* output statistics: */ - u_long udps_opackets; /* total output packets */ -}; - -/* - * Names for UDP sysctl objects - */ -#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ -#define UDPCTL_STATS 2 /* statistics (read-only) */ -#define UDPCTL_MAXDGRAM 3 /* max datagram size */ -#define UDPCTL_RECVSPACE 4 /* default receive buffer space */ -#define UDPCTL_MAXID 5 - -#define UDPCTL_NAMES { \ - { 0, 0 }, \ - { "checksum", CTLTYPE_INT }, \ - { "stats", CTLTYPE_STRUCT }, \ - { "maxdgram", CTLTYPE_INT }, \ - { "recvspace", CTLTYPE_INT }, \ -} - -#ifdef KERNEL -extern struct inpcbhead udb; -extern struct inpcbinfo udbinfo; -extern struct udpstat udpstat; - -void udp_ctlinput __P((int, struct sockaddr *, void *)); -void udp_init __P((void)); -void udp_input __P((struct mbuf *, int)); -int udp_usrreq __P((struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *)); -#endif - -#endif |