Newsgroups: comp.sources.unix From: argus@SEI.CMU.EDU Subject: v29i033: argus-1.5 - a generic IP network transaction auditing tool, Part03/06 References: <1.813909952.2078@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: argus@SEI.CMU.EDU Posting-Number: Volume 29, Issue 33 Archive-Name: argus-1.5/part03 #!/bin/sh # This is `part03' (part 3 of a multipart archive). # Do not concatenate these parts, unpack them in order with `/bin/sh'. # File `argus-1.5/common/addrtoname.c' is being continued... # touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo echo 'WARNING: not restoring timestamps. Consider getting and' echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # if test ! -r _sharseq.tmp; then echo 'Please unpack part 1 first!' exit 1 fi shar_sequence=`cat _sharseq.tmp` if test "$shar_sequence" != 3; then echo "Please unpack part $shar_sequence next!" exit 1 fi if test ! -f _sharnew.tmp; then echo 'x - still skipping argus-1.5/common/addrtoname.c' else echo 'x - continuing file argus-1.5/common/addrtoname.c' sed 's/^X//' << 'SHAR_EOF' >> 'argus-1.5/common/addrtoname.c' && X * Copyright (c) 1990, 1991, 1992, 1993, 1994 X * The Regents of the University of California. All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that: (1) source code distributions X * retain the above copyright notice and this paragraph in its entirety, (2) X * distributions including binary code include the above copyright notice and X * this paragraph in its entirety in the documentation or other materials X * provided with the distribution, and (3) all advertising materials mentioning X * features or use of this software display the following acknowledgement: X * ``This product includes software developed by the University of California, X * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of X * the University nor the names of its contributors may be used to endorse X * or promote products derived from this software without specific prior X * written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X * X * Internet, ethernet, port, and protocol string to address X * and address to string conversion routines X */ X#ifndef lint Xstatic char rcsid[] = X "@(#) $Header: /us/wcb/research/src/argus/argus-1.5/common/RCS/addrtoname.c,v 1.2 1995/04/24 19:36:49 wcb Exp $ (LBL)"; X#endif X X#include X#include X#include X X#include X X#include X#include X X#include X X#include X#include X#include X#include X#include X#include X#include X#ifdef __STDC__ X#include X#endif X#include X X#include "interface.h" X#include "addrtoname.h" X#include "llc.h" X Xstatic SIGRET nohostname(int); X#ifdef ETHER_SERVICE Xstruct ether_addr; Xextern int ether_ntohost(char *, struct ether_addr *); X#endif X X/* X * hash tables for whatever-to-name translations X */ X X#define HASHNAMESIZE 4096 X Xstruct hnamemem { X u_int32 addr; X char *name; X struct hnamemem *nxt; X}; X Xstruct hnamemem hnametable[HASHNAMESIZE]; Xstruct hnamemem tporttable[HASHNAMESIZE]; Xstruct hnamemem uporttable[HASHNAMESIZE]; Xstruct hnamemem eprototable[HASHNAMESIZE]; Xstruct hnamemem nnametable[HASHNAMESIZE]; Xstruct hnamemem llcsaptable[HASHNAMESIZE]; X Xstruct enamemem { X u_short e_addr0; X u_short e_addr1; X u_short e_addr2; X char *e_name; X u_char *e_nsap; /* used only for nsaptable[] */ X struct enamemem *e_nxt; X}; X Xstruct enamemem enametable[HASHNAMESIZE]; Xstruct enamemem nsaptable[HASHNAMESIZE]; X Xstruct protoidmem { X u_long p_oui; X u_short p_proto; X char *p_name; X struct protoidmem *p_nxt; X}; X Xstruct protoidmem protoidtable[HASHNAMESIZE]; X X/* X * A faster replacement for inet_ntoa(). X */ Xchar * Xintoa(u_int32 addr) X{ X char *cp; X u_int byte; X int n; X static char buf[sizeof(".xxx.xxx.xxx.xxx")]; X X NTOHL(addr); X cp = &buf[sizeof buf]; X *--cp = '\0'; X X n = 4; X do { X byte = addr & 0xff; X *--cp = byte % 10 + '0'; X byte /= 10; X if (byte > 0) { X *--cp = byte % 10 + '0'; X byte /= 10; X if (byte > 0) X *--cp = byte + '0'; X } X *--cp = '.'; X addr >>= 8; X } while (--n > 0); X X return cp + 1; X} X Xstatic u_int32 f_netmask; Xstatic u_int32 f_localnet; Xstatic u_int32 netmask; X X/* X * "getname" is written in this atrocious way to make sure we don't X * wait forever while trying to get hostnames from yp. X */ X#include X Xjmp_buf getname_env; X Xstatic SIGRET Xnohostname(int signo) X{ X longjmp(getname_env, 1); X} X X/* X * Return a name for the IP address pointed to by ap. This address X * is assumed to be in network byte order. X */ Xchar * Xgetname(u_char *ap) X{ X struct hostent *hp; X char *cp; X u_int32 addr; X static struct hnamemem *p; /* static for longjmp() */ X X#ifndef TCPDUMP_ALIGN X addr = *(const u_int32 *)ap; X#else X /* X * Deal with alignment. X */ X switch ((int)ap & 3) { X X case 0: X addr = *(u_int32 *)ap; X break; X X case 2: X#if BYTE_ORDER == LITTLE_ENDIAN X addr = ((u_int32)*(u_short *)(ap + 2) << 16) | X (u_int32)*(u_short *)ap; X#else X addr = ((u_int32)*(u_short *)ap << 16) | X (u_int32)*(u_short *)(ap + 2); X#endif X break; X X default: X#if BYTE_ORDER == LITTLE_ENDIAN X addr = ((u_int32)ap[0] << 24) | X ((u_int32)ap[1] << 16) | X ((u_int32)ap[2] << 8) | X (u_int32)ap[3]; X#else X addr = ((u_int32)ap[3] << 24) | X ((u_int32)ap[2] << 16) | X ((u_int32)ap[1] << 8) | X (u_int32)ap[0]; X#endif X break; X } X#endif X p = &hnametable[addr & (HASHNAMESIZE-1)]; X for (; p->nxt; p = p->nxt) { X if (p->addr == addr) X return (p->name); X } X p->addr = addr; X p->nxt = (struct hnamemem *)calloc(1, sizeof (*p)); X X /* X * Only print names when: X * (1) -n was not given. X * (2) Address is foreign and -f was given. If -f was not X * present, f_netmask and f_local are 0 and the second X * test will succeed. X * (3) The host portion is not 0 (i.e., a network address). X * (4) The host portion is not broadcast. X */ X if (!nflag && (addr & f_netmask) == f_localnet X && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) { X if (!setjmp(getname_env)) { X (void)signal(SIGALRM, nohostname); X (void)alarm(20); X hp = gethostbyaddr((char *)&addr, 4, AF_INET); X (void)alarm(0); X if (hp) { X char *dotp; X X p->name = savestr(hp->h_name); X if (Nflag) { X /* Remove domain qualifications */ X dotp = strchr(p->name, '.'); X if (dotp) X *dotp = 0; X } X return (p->name); X } X } X } X cp = intoa(addr); X p->name = savestr(cp); X return (p->name); X} X Xstatic char hex[] = "0123456789abcdef"; X X X/* Find the hash node that corresponds the ether address 'ep'. */ X Xstatic inline struct enamemem * Xlookup_emem(const u_char *ep) X{ X u_int i, j, k; X struct enamemem *tp; X X k = (ep[0] << 8) | ep[1]; X j = (ep[2] << 8) | ep[3]; X i = (ep[4] << 8) | ep[5]; X X tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; X while (tp->e_nxt) X if (tp->e_addr0 == i && X tp->e_addr1 == j && X tp->e_addr2 == k) X return tp; X else X tp = tp->e_nxt; X tp->e_addr0 = i; X tp->e_addr1 = j; X tp->e_addr2 = k; X tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); X X return tp; X} X X/* Find the hash node that corresponds the NSAP 'nsap'. */ X Xstatic inline struct enamemem * Xlookup_nsap(const u_char *nsap) X{ X u_int i, j, k; X int nlen = *nsap; X struct enamemem *tp; X const u_char *ensap = nsap + nlen - 6; X X if (nlen > 6) { X k = (ensap[0] << 8) | ensap[1]; X j = (ensap[2] << 8) | ensap[3]; X i = (ensap[4] << 8) | ensap[5]; X } X else X i = j = k = 0; X X tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)]; X while (tp->e_nxt) X if (tp->e_addr0 == i && X tp->e_addr1 == j && X tp->e_addr2 == k && X tp->e_nsap[0] == nlen && X bcmp((char *)&(nsap[1]), X (char *)&(tp->e_nsap[1]), nlen) == 0) X return tp; X else X tp = tp->e_nxt; X tp->e_addr0 = i; X tp->e_addr1 = j; X tp->e_addr2 = k; X tp->e_nsap = (u_char *) calloc(1, nlen + 1); X bcopy(nsap, tp->e_nsap, nlen + 1); X tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); X X return tp; X} X X/* Find the hash node that corresponds the protoid 'pi'. */ X Xstatic inline struct protoidmem * Xlookup_protoid(const u_char *pi) X{ X u_int i, j; X struct protoidmem *tp; X X /* 5 octets won't be aligned */ X i = (((pi[0] << 8) + pi[1]) << 8) + pi[2]; X j = (pi[3] << 8) + pi[4]; X /* XXX should be endian-insensitive, but do big-endian testing XXX */ X X tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)]; X while (tp->p_nxt) X if (tp->p_oui == i && tp->p_proto == j) X return tp; X else X tp = tp->p_nxt; X tp->p_oui = i; X tp->p_proto = j; X tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp)); X X return tp; X} X Xchar * Xetheraddr_string(u_char *ep) X{ X u_int i, j; X char *cp; X struct enamemem *tp; X X tp = lookup_emem(ep); X if (tp->e_name) X return (tp->e_name); X#ifdef ETHER_SERVICE X if (!nflag) { X char buf[128]; X if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) { X tp->e_name = savestr(buf); X return (tp->e_name); X } X } X#endif X tp->e_name = cp = (char *)malloc(sizeof("00:00:00:00:00:00")); X X if ((j = *ep >> 4) != 0) X *cp++ = hex[j]; X *cp++ = hex[*ep++ & 0xf]; X for (i = 5; (int)--i >= 0;) { X *cp++ = ':'; X if ((j = *ep >> 4) != 0) X *cp++ = hex[j]; X *cp++ = hex[*ep++ & 0xf]; X } X *cp = '\0'; X return (tp->e_name); X} X Xchar * Xetherproto_string(u_short port) X{ X char *cp; X struct hnamemem *tp; X u_long i = port; X X for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) X if (tp->addr == i) X return (tp->name); X X tp->name = cp = (char *)malloc(sizeof("0000")); X tp->addr = i; X tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); X X NTOHS(port); X *cp++ = hex[port >> 12 & 0xf]; X *cp++ = hex[port >> 8 & 0xf]; X *cp++ = hex[port >> 4 & 0xf]; X *cp++ = hex[port & 0xf]; X *cp++ = '\0'; X return (tp->name); X} X Xchar * Xprotoid_string(const u_char *pi) X{ X u_int i, j; X char *cp; X struct protoidmem *tp; X X tp = lookup_protoid(pi); X if (tp->p_name) X return tp->p_name; X X tp->p_name = cp = (char *)malloc(sizeof("00:00:00:00:00")); X X if ((j = *pi >> 4) != 0) X *cp++ = hex[j]; X *cp++ = hex[*pi++ & 0xf]; X for (i = 4; (int)--i >= 0;) { X *cp++ = ':'; X if ((j = *pi >> 4) != 0) X *cp++ = hex[j]; X *cp++ = hex[*pi++ & 0xf]; X } X *cp = '\0'; X return (tp->p_name); X} X Xchar * Xllcsap_string(u_char sap) X{ X char *cp; X struct hnamemem *tp; X u_long i = sap; X X for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) X if (tp->addr == i) X return (tp->name); X X tp->name = cp = (char *)malloc(sizeof("sap 00")); X tp->addr = i; X tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); X X (void)strcpy(cp, "sap "); X cp += strlen(cp); X *cp++ = hex[sap >> 4 & 0xf]; X *cp++ = hex[sap & 0xf]; X *cp++ = '\0'; X return (tp->name); X} X Xchar * Xisonsap_string(const u_char *nsap) X{ X u_int i, nlen = nsap[0]; X char *cp; X struct enamemem *tp; X X tp = lookup_nsap(nsap); X if (tp->e_name) X return tp->e_name; X X tp->e_name = cp = (char *)malloc(nlen * 2 + 2); X X nsap++; X *cp++ = '/'; X for (i = nlen; (int)--i >= 0;) { X *cp++ = hex[*nsap >> 4]; X *cp++ = hex[*nsap++ & 0xf]; X } X *cp = '\0'; X return (tp->e_name); X} X Xchar * Xtcpport_string(u_short port) X{ X struct hnamemem *tp; X u_long i = port; X X for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) X if (tp->addr == i) X return (tp->name); X X tp->name = (char *)malloc(sizeof("00000")); X tp->addr = i; X tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); X X (void)sprintf(tp->name, "%d", i); X return (tp->name); X} X Xchar * Xudpport_string(u_short port) X{ X struct hnamemem *tp; X u_long i = port; X X if (port) { X for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) X if (tp->addr == i) X return (tp->name); X X tp->name = (char *)malloc(sizeof("00000")); X tp->addr = i; X tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp)); X X (void)sprintf(tp->name, "%d", i); X X return (tp->name); X } else X return ("*"); X} X Xstatic void Xinit_servarray(void) X{ X struct servent *sv; X struct hnamemem *table; X int i; X X while ((sv = getservent()) != NULL) { X int port = ntohs(sv->s_port); X i = port & (HASHNAMESIZE-1); X if (strcmp(sv->s_proto, "tcp") == 0) X table = &tporttable[i]; X else if (strcmp(sv->s_proto, "udp") == 0) X table = &uporttable[i]; X else X continue; X X while (table->name) X table = table->nxt; X if (nflag) { X char buf[32]; X X (void)sprintf(buf, "%d", port); X table->name = savestr(buf); X } else X table->name = savestr(sv->s_name); X table->addr = port; X table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); X } X endservent(); X} X X/*XXX from libbpfc.a */ Xextern struct eproto { X char *s; X u_short p; X} eproto_db[]; X Xstatic void Xinit_eprotoarray(void) X{ X int i; X struct hnamemem *table; X X for (i = 0; eproto_db[i].s; i++) { X int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1); X table = &eprototable[j]; X while (table->name) X table = table->nxt; X table->name = eproto_db[i].s; X table->addr = ntohs(eproto_db[i].p); X table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); X } X} X X/* X * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet X * types. X */ Xstatic void Xinit_protoidarray(void) X{ X int i; X struct protoidmem *tp; X u_char protoid[5]; X X protoid[0] = 0; X protoid[1] = 0; X protoid[2] = 0; X for (i = 0; eproto_db[i].s; i++) { X u_short etype = htons(eproto_db[i].p); X bcopy((char *)&etype, (char *)&protoid[3], 2); X tp = lookup_protoid(protoid); X tp->p_name = savestr(eproto_db[i].s); X } X} X Xstatic struct etherlist { X u_char addr[6]; X char *name; X} etherlist[] = { X {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, X {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } X}; X X/* X * Initialize the ethers hash table. We take two different approaches X * depending on whether or not the system provides the ethers name X * service. If it does, we just wire in a few names at startup, X * and etheraddr_string() fills in the table on demand. If it doesn't, X * then we suck in the entire /etc/ethers file at startup. The idea X * is that parsing the local file will be fast, but spinning through X * all the ethers entries via NIS & next_etherent might be very slow. X * X * XXX pcap_next_etherent doesn't belong in the pcap interface, but X * since the pcap module already does name-to-address translation, X * it's already does most of the work for the ethernet address-to-name X * translation, so we just pcap_next_etherent as a convenience. X */ Xstatic void Xinit_etherarray(void) X{ X struct etherlist *el; X struct enamemem *tp; X#ifndef ETHER_SERVICE X struct pcap_etherent *ep; X FILE *fp; X X /* Suck in entire ethers file */ X fp = fopen(PCAP_ETHERS_FILE, "r"); X if (fp != NULL) { X while ((ep = pcap_next_etherent(fp)) != NULL) { X tp = lookup_emem(ep->addr); X tp->e_name = savestr(ep->name); X } X (void)fclose(fp); X } X#endif X X /* Hardwire some ethernet names */ X for (el = etherlist; el->name != NULL; ++el) { X#ifdef ETHER_SERVICE X /* Use yp/nis version of name if available */ X char wrk[256]; X if (ether_ntohost(wrk, (struct ether_addr *)el->addr) == 0) { X tp = lookup_emem(el->addr); X tp->e_name = savestr(wrk); X } X#else X /* install if not already present */ X tp = lookup_emem(el->addr); X if (tp->e_name == NULL) X tp->e_name = el->name; X#endif X X } X} X Xstatic struct token llcsap_db[] = { X { LLCSAP_NULL, "null" }, X { LLCSAP_8021B_I, "802.1b-gsap" }, X { LLCSAP_8021B_G, "802.1b-isap" }, X { LLCSAP_IP, "ip-sap" }, X { LLCSAP_PROWAYNM, "proway-nm" }, X { LLCSAP_8021D, "802.1d" }, X { LLCSAP_RS511, "eia-rs511" }, X { LLCSAP_ISO8208, "x.25/llc2" }, X { LLCSAP_PROWAY, "proway" }, X { LLCSAP_ISONS, "iso-clns" }, X { LLCSAP_GLOBAL, "global" }, X { 0, NULL } X}; X Xstatic void Xinit_llcsaparray(void) X{ X int i; X struct hnamemem *table; X X for (i = 0; llcsap_db[i].s != NULL; i++) { X table = &llcsaptable[llcsap_db[i].v]; X while (table->name) X table = table->nxt; X table->name = llcsap_db[i].s; X table->addr = llcsap_db[i].v; X table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); X } X} X X/* X * Initialize the address to name translation machinery. We map all X * non-local IP addresses to numeric addresses if fflag is true (i.e., X * to prevent blocking on the nameserver). localnet is the IP address X * of the local network. mask is its subnet mask. X */ Xvoid Xinit_addrtoname(int fflag, u_int32 localnet, u_int32 mask) X{ X netmask = mask; X if (fflag) { X f_localnet = localnet; X f_netmask = mask; X } X if (nflag) X /* X * Simplest way to suppress names. X */ X return; X X init_etherarray(); X init_servarray(); X init_eprotoarray(); X init_llcsaparray(); X init_protoidarray(); X} SHAR_EOF echo 'File argus-1.5/common/addrtoname.c is complete' && $shar_touch -am 0508141395 'argus-1.5/common/addrtoname.c' && chmod 0444 'argus-1.5/common/addrtoname.c' || echo 'restore of argus-1.5/common/addrtoname.c failed' shar_count="`wc -c < 'argus-1.5/common/addrtoname.c'`" test 15570 -eq "$shar_count" || echo "argus-1.5/common/addrtoname.c: original size 15570, current size $shar_count" rm -f _sharnew.tmp fi # ============= argus-1.5/common/argus_filter.c ============== if test -f 'argus-1.5/common/argus_filter.c' && test X"$1" != X"-c"; then echo 'x - skipping argus-1.5/common/argus_filter.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting argus-1.5/common/argus_filter.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'argus-1.5/common/argus_filter.c' && X/*- X * Copyright (c) 1990, 1991, 1992, 1993 X * The Regents of the University of California. All rights reserved. X * X * This code is derived from the Stanford/CMU enet packet filter, X * (net/enet.c) distributed as part of 4.3BSD, and code contributed X * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence X * Berkeley Laboratory. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * @(#)bpf.c 7.5 (Berkeley) 7/15/91 X * X * static char rcsid[] = X * "$Header: /usr/users/poepping/src/argus/argus-1.5/common/RCS/argus_filter.c,v 1.1 1995/02/08 21:03:27 poepping Exp $"; X */ X#if !(defined(lint) || defined(KERNEL)) Xstatic char rcsid[] = X "@(#) $Header: /usr/users/poepping/src/argus/argus-1.5/common/RCS/argus_filter.c,v 1.1 1995/02/08 21:03:27 poepping Exp $ (LBL)"; X#endif X X#include X#include X#include X#include X X#if defined(__alpha) Xtypedef int int32; Xtypedef u_int u_int32; X#else Xtypedef long int32; Xtypedef u_long u_int32; X#endif X X#ifdef sun X#include X#endif X X#if defined(sparc) || defined(mips) || defined(ibm032) || defined(__alpha) X#define BPF_ALIGN X#endif X X#ifndef BPF_ALIGN X#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) X#define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p)) X#else X#define EXTRACT_SHORT(p)\ X ((u_short)\ X ((u_short)*((u_char *)p+0)<<8|\ X (u_short)*((u_char *)p+1)<<0)) X#define EXTRACT_LONG(p)\ X ((u_int32)*((u_char *)p+0)<<24|\ X (u_int32)*((u_char *)p+1)<<16|\ X (u_int32)*((u_char *)p+2)<<8|\ X (u_int32)*((u_char *)p+3)<<0) X#endif X X#ifdef KERNEL X#include X#define MINDEX(m, k) \ X{ \ X register int len = m->m_len; \ X \ X while (k >= len) { \ X k -= len; \ X m = m->m_next; \ X if (m == 0) \ X return 0; \ X len = m->m_len; \ X } \ X} X Xstatic int Xm_xword(m, k, err) X register struct mbuf *m; X register int k, *err; X{ X register int len; X register u_char *cp, *np; X register struct mbuf *m0; X X len = m->m_len; X while (k >= len) { X k -= len; X m = m->m_next; X if (m == 0) X goto bad; X len = m->m_len; X } X cp = mtod(m, u_char *) + k; X if (len - k >= 4) { X *err = 0; X return EXTRACT_LONG(cp); X } X m0 = m->m_next; X if (m0 == 0 || m0->m_len + len - k < 4) X goto bad; X *err = 0; X np = mtod(m0, u_char *); X switch (len - k) { X X case 1: X return (cp[k] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; X X case 2: X return (cp[k] << 24) | (cp[k + 1] << 16) | (np[0] << 8) | X np[1]; X X default: X return (cp[k] << 24) | (cp[k + 1] << 16) | (cp[k + 2] << 8) | X np[0]; X } X bad: X *err = 1; X return 0; X} X Xstatic int Xm_xhalf(m, k, err) X register struct mbuf *m; X register int k, *err; X{ X register int len; X register u_char *cp; X register struct mbuf *m0; X X len = m->m_len; X while (k >= len) { X k -= len; X m = m->m_next; X if (m == 0) X goto bad; X len = m->m_len; X } X cp = mtod(m, u_char *) + k; X if (len - k >= 2) { X *err = 0; X return EXTRACT_SHORT(cp); X } X m0 = m->m_next; X if (m0 == 0) X goto bad; X *err = 0; X return (cp[k] << 8) | mtod(m0, u_char *)[0]; X bad: X *err = 1; X return 0; X} X#endif X X/* X * Execute the filter program starting at pc on the packet p X * wirelen is the length of the original packet X * buflen is the amount of data present X */ X Xu_int argus_filter_orig (); X Xu_int Xargus_filter (pc, p) Xstruct bpf_insn *pc; Xu_char *p; X{ X return argus_filter_orig (pc, p, 60, 60); X} X Xu_int Xargus_filter_orig (pc, p, wirelen, buflen) Xstruct bpf_insn *pc; Xu_char *p; Xint wirelen, buflen; X{ X register u_int32 A, X; X register int k; X int32 mem [BPF_MEMWORDS]; X X if (pc == 0) X /* X * No filter means accept all. X */ X return (u_int) -1; X#ifdef lint X A = 0; X X = 0; X#endif X --pc; X while (1) { X ++pc; X switch (pc->code) { X X default: X#ifdef KERNEL X return 0; X#else X abort(); X#endif X case BPF_RET|BPF_K: X return (u_int)pc->k; X X case BPF_RET|BPF_A: X return (u_int)A; X X case BPF_LD|BPF_W|BPF_ABS: X k = pc->k; X if (k + sizeof(int32) > buflen) { X#ifdef KERNEL X int merr; X X if (buflen != 0) X return 0; X A = m_xword((struct mbuf *)p, k, &merr); X if (merr != 0) X return 0; X continue; X#else X return 0; X#endif X } X A = EXTRACT_LONG(&p[k]); X continue; X X case BPF_LD|BPF_H|BPF_ABS: X k = pc->k; X if (k + sizeof(short) > buflen) { X#ifdef KERNEL X int merr; X X if (buflen != 0) X return 0; X A = m_xhalf((struct mbuf *)p, k, &merr); X continue; X#else X return 0; X#endif X } X A = EXTRACT_SHORT(&p[k]); X continue; X X case BPF_LD|BPF_B|BPF_ABS: X k = pc->k; X if (k >= buflen) { X#ifdef KERNEL X register struct mbuf *m; X X if (buflen != 0) X return 0; X m = (struct mbuf *)p; X MINDEX(m, k); X A = mtod(m, u_char *)[k]; X continue; X#else X return 0; X#endif X } X A = p[k]; X continue; X X case BPF_LD|BPF_W|BPF_LEN: X A = wirelen; X continue; X X case BPF_LDX|BPF_W|BPF_LEN: X X = wirelen; X continue; X X case BPF_LD|BPF_W|BPF_IND: X k = X + pc->k; X if (k + sizeof(int32) > buflen) { X#ifdef KERNEL X int merr; X X if (buflen != 0) X return 0; X A = m_xword((struct mbuf *)p, k, &merr); X if (merr != 0) X return 0; X continue; X#else X return 0; X#endif X } X A = EXTRACT_LONG(&p[k]); X continue; X X case BPF_LD|BPF_H|BPF_IND: X k = X + pc->k; X if (k + sizeof(short) > buflen) { X#ifdef KERNEL X int merr; X X if (buflen != 0) X return 0; X A = m_xhalf((struct mbuf *)p, k, &merr); X if (merr != 0) X return 0; X continue; X#else X return 0; X#endif X } X A = EXTRACT_SHORT(&p[k]); X continue; X X case BPF_LD|BPF_B|BPF_IND: X k = X + pc->k; X if (k >= buflen) { X#ifdef KERNEL X register struct mbuf *m; X X if (buflen != 0) X return 0; X m = (struct mbuf *)p; X MINDEX(m, k); X A = mtod(m, char *)[k]; X continue; X#else X return 0; X#endif X } X A = p[k]; X continue; X X case BPF_LDX|BPF_MSH|BPF_B: X k = pc->k; X if (k >= buflen) { X#ifdef KERNEL X register struct mbuf *m; X X if (buflen != 0) X return 0; X m = (struct mbuf *)p; X MINDEX(m, k); X X = (mtod(m, char *)[k] & 0xf) << 2; X continue; X#else X return 0; X#endif X } X X = (p[pc->k] & 0xf) << 2; X continue; X X case BPF_LD|BPF_IMM: X A = pc->k; X continue; X X case BPF_LDX|BPF_IMM: X X = pc->k; X continue; X X case BPF_LD|BPF_MEM: X A = mem[pc->k]; X continue; X X case BPF_LDX|BPF_MEM: X X = mem[pc->k]; X continue; X X case BPF_ST: X mem[pc->k] = A; X continue; X X case BPF_STX: X mem[pc->k] = X; X continue; X X case BPF_JMP|BPF_JA: X pc += pc->k; X continue; X X case BPF_JMP|BPF_JGT|BPF_K: X pc += (A > pc->k) ? pc->jt : pc->jf; X continue; X X case BPF_JMP|BPF_JGE|BPF_K: X pc += (A >= pc->k) ? pc->jt : pc->jf; X continue; X X case BPF_JMP|BPF_JEQ|BPF_K: X pc += (A == pc->k) ? pc->jt : pc->jf; X continue; X X case BPF_JMP|BPF_JSET|BPF_K: X pc += (A & pc->k) ? pc->jt : pc->jf; X continue; X X case BPF_JMP|BPF_JGT|BPF_X: X pc += (A > X) ? pc->jt : pc->jf; X continue; X X case BPF_JMP|BPF_JGE|BPF_X: X pc += (A >= X) ? pc->jt : pc->jf; X continue; X X case BPF_JMP|BPF_JEQ|BPF_X: X pc += (A == X) ? pc->jt : pc->jf; X continue; X X case BPF_JMP|BPF_JSET|BPF_X: X pc += (A & X) ? pc->jt : pc->jf; X continue; X X case BPF_ALU|BPF_ADD|BPF_X: X A += X; X continue; X X case BPF_ALU|BPF_SUB|BPF_X: X A -= X; X continue; X X case BPF_ALU|BPF_MUL|BPF_X: X A *= X; X continue; X X case BPF_ALU|BPF_DIV|BPF_X: X if (X == 0) X return 0; X A /= X; X continue; X X case BPF_ALU|BPF_AND|BPF_X: X A &= X; X continue; X X case BPF_ALU|BPF_OR|BPF_X: X A |= X; X continue; X X case BPF_ALU|BPF_LSH|BPF_X: X A <<= X; X continue; X X case BPF_ALU|BPF_RSH|BPF_X: X A >>= X; X continue; X X case BPF_ALU|BPF_ADD|BPF_K: X A += pc->k; X continue; X X case BPF_ALU|BPF_SUB|BPF_K: X A -= pc->k; X continue; X X case BPF_ALU|BPF_MUL|BPF_K: X A *= pc->k; X continue; X X case BPF_ALU|BPF_DIV|BPF_K: X A /= pc->k; X continue; X X case BPF_ALU|BPF_AND|BPF_K: X A &= pc->k; X continue; X X case BPF_ALU|BPF_OR|BPF_K: X A |= pc->k; X continue; X X case BPF_ALU|BPF_LSH|BPF_K: X A <<= pc->k; X continue; X X case BPF_ALU|BPF_RSH|BPF_K: X A >>= pc->k; X continue; X X case BPF_ALU|BPF_NEG: X A = -A; X continue; X X case BPF_MISC|BPF_TAX: X X = A; X continue; X X case BPF_MISC|BPF_TXA: X A = X; X continue; X } X } X} X X#ifdef KERNEL X/* X * Return true if the 'fcode' is a valid filter program. X * The constraints are that each jump be forward and to a valid X * code. The code must terminate with either an accept or reject. X * 'valid' is an array for use by the routine (it must be at least X * 'len' bytes long). X * X * The kernel needs to be able to verify an application's filter code. X * Otherwise, a bogus program could easily crash the system. X */ Xint Xbpf_validate(f, len) X struct bpf_insn *f; X int len; X{ X register int i; X register struct bpf_insn *p; X X for (i = 0; i < len; ++i) { X /* X * Check that that jumps are forward, and within X * the code block. X */ X p = &f[i]; X if (BPF_CLASS(p->code) == BPF_JMP) { X register int from = i + 1; X X if (BPF_OP(p->code) == BPF_JA) { X if (from + p->k >= len) X return 0; X } X else if (from + p->jt >= len || from + p->jf >= len) X return 0; X } X /* X * Check that memory operations use valid addresses. X */ X if ((BPF_CLASS(p->code) == BPF_ST || X (BPF_CLASS(p->code) == BPF_LD && X (p->code & 0xe0) == BPF_MEM)) && X (p->k >= BPF_MEMWORDS || p->k < 0)) X return 0; X /* X * Check for constant division by 0. X */ X if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) X return 0; X } X return BPF_CLASS(f[len - 1].code) == BPF_RET; X} X#endif SHAR_EOF $shar_touch -am 0508141395 'argus-1.5/common/argus_filter.c' && chmod 0444 'argus-1.5/common/argus_filter.c' || echo 'restore of argus-1.5/common/argus_filter.c failed' shar_count="`wc -c < 'argus-1.5/common/argus_filter.c'`" test 13053 -eq "$shar_count" || echo "argus-1.5/common/argus_filter.c: original size 13053, current size $shar_count" rm -f _sharnew.tmp fi # ============= argus-1.5/common/bpf_dump.c ============== if test -f 'argus-1.5/common/bpf_dump.c' && test X"$1" != X"-c"; then echo 'x - skipping argus-1.5/common/bpf_dump.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting argus-1.5/common/bpf_dump.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'argus-1.5/common/bpf_dump.c' && X/* X * Copyright (c) 1992, 1993, 1994 X * The Regents of the University of California. All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that: (1) source code distributions X * retain the above copyright notice and this paragraph in its entirety, (2) X * distributions including binary code include the above copyright notice and X * this paragraph in its entirety in the documentation or other materials X * provided with the distribution, and (3) all advertising materials mentioning X * features or use of this software display the following acknowledgement: X * ``This product includes software developed by the University of California, X * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of X * the University nor the names of its contributors may be used to endorse X * or promote products derived from this software without specific prior X * written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X#ifndef lint Xstatic char rcsid[] = X "@(#) $Header: /usr/users/poepping/src/argus/argus-1.5/common/RCS/bpf_dump.c,v 1.1 1995/02/08 21:03:27 poepping Exp $ (LBL)"; X#endif X X#include X#include X X#include X#include X X#include X Xextern void bpf_dump(struct bpf_program *, int); X Xvoid Xbpf_dump(struct bpf_program *p, int option) X{ X struct bpf_insn *insn; X int i; X int n = p->bf_len; X X insn = p->bf_insns; X if (option > 2) { X printf("%d\n", n); X for (i = 0; i < n; ++insn, ++i) { X printf("%lu %lu %lu %lu\n", insn->code, X insn->jt, insn->jf, insn->k); X } X return ; X } X if (option > 1) { X for (i = 0; i < n; ++insn, ++i) X printf("{ 0x%x, %d, %d, 0x%08x },\n", X insn->code, insn->jt, insn->jf, insn->k); X return; X } X for (i = 0; i < n; ++insn, ++i) { X#ifdef BDEBUG X extern int bids[]; X printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1); X#endif X puts(bpf_image(insn, i)); X } X} SHAR_EOF $shar_touch -am 0508141395 'argus-1.5/common/bpf_dump.c' && chmod 0444 'argus-1.5/common/bpf_dump.c' || echo 'restore of argus-1.5/common/bpf_dump.c failed' shar_count="`wc -c < 'argus-1.5/common/bpf_dump.c'`" test 2131 -eq "$shar_count" || echo "argus-1.5/common/bpf_dump.c: original size 2131, current size $shar_count" rm -f _sharnew.tmp fi # ============= argus-1.5/common/gencode.c ============== if test -f 'argus-1.5/common/gencode.c' && test X"$1" != X"-c"; then echo 'x - skipping argus-1.5/common/gencode.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting argus-1.5/common/gencode.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'argus-1.5/common/gencode.c' && X/* X * Copyright (c) 1990, 1991, 1992, 1993, 1994 X * The Regents of the University of California. All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that: (1) source code distributions X * retain the above copyright notice and this paragraph in its entirety, (2) X * distributions including binary code include the above copyright notice and X * this paragraph in its entirety in the documentation or other materials X * provided with the distribution, and (3) all advertising materials mentioning X * features or use of this software display the following acknowledgement: X * ``This product includes software developed by the University of California, X * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of X * the University nor the names of its contributors may be used to endorse X * or promote products derived from this software without specific prior X * written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X#ifndef lint Xstatic char rcsid[] = X "@(#) $Header: /usr/users/poepping/src/argus/argus-1.5/common/RCS/gencode.c,v 1.1 1995/02/08 21:03:27 poepping Exp $ (LBL)"; X#endif X X#include X#include X#include X X#include X#include X X#include X#include X X#include X#include X#include X#include X#include X#if __STDC__ X#include X#include X#else X#include X#endif X X#include X#include "gencode.h" X X#ifndef __GNUC__ X#define inline X#endif X X X#define JMP(c) ((c)|BPF_JMP|BPF_K) X Xstatic jmp_buf top_ctx; Xstatic pcap_t *bpf_pcap; X Xstatic u_int off_linktype = 0; Xstatic u_int off_nl = 0; X X X/* VARARGS */ Xvolatile void X#if __STDC__ || defined(SOLARIS) Xbpf_error(char *fmt, ...) X#else Xbpf_error(fmt, va_alist) X char *fmt; X va_dcl X#endif X{ X va_list ap; X X#if __STDC__ X va_start(ap, fmt); X#else X va_start(ap); X#endif X if (bpf_pcap != NULL) X (void)vsprintf(bpf_pcap->errbuf, fmt, ap); X va_end(ap); X longjmp(top_ctx, 1); X /* NOTREACHED */ X} X X Xstatic int alloc_reg(void); Xstatic void free_reg(int); X Xstatic struct block *root; X X/* X * We divy out chunks of memory rather than call malloc each time so X * we don't have to worry about leaking memory. It's probably X * not a big deal if all this memory was wasted but it this ever X * goes into a library that would probably not be a good idea. X */ X#define NCHUNKS 16 X#define CHUNK0SIZE 1024 Xstruct chunk { X u_int n_left; X void *m; X}; X Xstatic struct chunk chunks[NCHUNKS]; Xstatic int cur_chunk; X Xstatic void *newchunk(u_int); Xstatic void freechunks(void); Xstatic inline struct block *new_block(int); Xstatic inline struct slist *new_stmt(int); Xstatic struct block *gen_retblk(int); Xstatic inline void syntax(void); X Xstatic void backpatch(struct block *, struct block *); Xstatic void merge(struct block *, struct block *); Xstatic struct block *gen_cmp(u_int, u_int, u_long); Xstatic struct block *gen_mcmp(u_int, u_int, u_long, u_long); Xstatic struct block *gen_bcmp(u_int, u_int, u_char *); Xstatic struct block *gen_uncond(int); Xstatic inline struct block *gen_true(void); Xstatic inline struct block *gen_false(void); Xstatic struct block *gen_prototype(u_int); Xstatic struct block *gen_hostop(u_long, u_long, int, u_int, u_int, u_int); Xstatic struct block *gen_ehostop(u_char *, int); Xstatic struct block *gen_dnhostop(u_long, int, u_int); Xstatic struct block *gen_host(u_long, u_long, int, int); Xstatic struct block *gen_gateway(u_char *, u_long **, int, int); Xstatic struct block *gen_portatom(int, long); Xstruct block *gen_portop(int, int, int); Xstatic struct block *gen_port(int, u_int, int); Xstatic int lookup_proto(char *, int); Xstatic struct block *gen_proto(int, int, int); Xstatic u_long net_mask(u_long *); Xstatic u_long net_mask(u_long *); Xstatic struct slist *xfer_to_x(struct arth *); Xstatic struct slist *xfer_to_a(struct arth *); Xstatic struct block *gen_len(int, int); X Xstatic void * Xnewchunk(n) Xu_int n; X{ X struct chunk *cp; X int k, size; X X /* XXX Round up to nearest long. */ X n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1); X X cp = &chunks[cur_chunk]; X if (n > cp->n_left) { X ++cp, k = ++cur_chunk; X if (k >= NCHUNKS) X bpf_error("out of memory"); X size = CHUNK0SIZE << k; X cp->m = (void *)malloc(size); X memset((char *)cp->m, 0, size); X cp->n_left = size; X if (n > size) X bpf_error("out of memory"); X } X cp->n_left -= n; X return (void *)((char *)cp->m + cp->n_left); X} X Xstatic void Xfreechunks() X{ X int i; X X for (i = 0; i < NCHUNKS; ++i) X if (chunks[i].m) X free(chunks[i].m); X} X X/* X * A strdup whose allocations are freed after code generation is over. X */ Xchar * Xsdup(s) Xchar *s; X{ X int n = strlen(s) + 1; X char *cp = newchunk(n); X strcpy(cp, s); X return (cp); X} X Xstatic inline struct block * Xnew_block(code) Xint code; X{ X struct block *p; X X p = (struct block *)newchunk(sizeof(*p)); X p->s.code = code; X p->head = p; X X return p; X} X Xstatic inline struct slist * Xnew_stmt(code) Xint code; X{ X struct slist *p; X X p = (struct slist *)newchunk(sizeof(*p)); X p->s.code = code; X X return p; X} X Xstatic struct block * Xgen_retblk(v) Xint v; X{ X struct block *b = new_block(BPF_RET|BPF_K); X X b->s.k = v; X return b; X} X Xstatic inline void Xsyntax() X{ X bpf_error("syntax error in filter expression"); X} X Xstatic u_long netmask; Xstatic int snaplen; X X Xint Xpolicy_compile(p, program, buf, optimize, mask) Xpcap_t *p; Xstruct bpf_program *program; Xchar *buf; Xint optimize; Xu_long mask; X{ X extern int n_errors; X int len; X X bpf_pcap = p; X if (setjmp(top_ctx)) X return (-1); X X netmask = mask; X snaplen = 96; X X lex_init(buf ? buf : ""); X pcap_parse(); X X if (n_errors) X syntax(); X X if (root == NULL) X root = gen_retblk(snaplen); X X/* X if (optimize) { X bpf_optimize(&root); X if (root == NULL || X (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0)) X bpf_error("expression rejects all packets"); X } X*/ X X program->bf_insns = icode_to_fcode(root, &len); X program->bf_len = len; X X freechunks(); X return (0); X} X X/* X * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates X * which of the jt and jf fields has been resolved and which is a pointer X * back to another unresolved block (or nil). At least one of the fields X * in each block is already resolved. X */ Xstatic void Xbackpatch(list, target) Xstruct block *list, *target; X{ X struct block *next; X X while (list) { X if (!list->sense) { X next = JT(list); X JT(list) = target; X } else { X next = JF(list); X JF(list) = target; X } X list = next; X } X} X X/* X * Merge the lists in b0 and b1, using the 'sense' field to indicate X * which of jt and jf is the link. X */ Xstatic void Xmerge(b0, b1) Xstruct block *b0, *b1; X{ X register struct block **p = &b0; X X /* Find end of list. */ X while (*p) X p = !((*p)->sense) ? &JT(*p) : &JF(*p); X X /* Concatenate the lists. */ X *p = b1; X} X Xvoid Xfinish_parse(p) Xstruct block *p; X{ X backpatch(p, gen_retblk(snaplen)); X p->sense = !p->sense; X backpatch(p, gen_retblk(0)); X root = p->head; X} X Xvoid Xgen_and(b0, b1) Xstruct block *b0, *b1; X{ X if (b0 != b1) { X backpatch(b0, b1->head); X b0->sense = !b0->sense; X b1->sense = !b1->sense; X merge(b1, b0); X b1->sense = !b1->sense; X b1->head = b0->head; X } X} X Xvoid Xgen_or(b0, b1) Xstruct block *b0, *b1; X{ X if (b0 != b1) { X b0->sense = !b0->sense; X backpatch(b0, b1->head); X b0->sense = !b0->sense; X merge(b1, b0); X b1->head = b0->head; X } X} X Xvoid Xgen_not(b) Xstruct block *b; X{ X b->sense = !b->sense; X} X Xstatic struct block * Xgen_cmp(offset, size, v) Xu_int offset, size; Xu_long v; X{ X struct slist *s; X struct block *b; X X s = new_stmt(BPF_LD|BPF_ABS|size); X s->s.k = offset; X X b = new_block(JMP(BPF_JEQ)); X b->stmts = s; X b->s.k = v; X X return b; X} X Xstatic struct block * Xgen_mcmp(offset, size, v, mask) Xu_int offset, size; Xu_long v; Xu_long mask; X{ X struct block *b = gen_cmp(offset, size, v); X struct slist *s; X X if (mask != 0xffffffff) { X s = new_stmt(BPF_ALU|BPF_AND|BPF_K); X s->s.k = mask; X b->stmts->next = s; X } X return b; X} X Xstatic struct block * Xgen_bcmp(offset, size, v) Xu_int offset, size; Xu_char *v; X{ X struct block *b, *tmp; X X b = NULL; X while (size >= 4) { X u_char *p = &v[size - 4]; X u_long w = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; X tmp = gen_cmp(offset + size - 4, BPF_W, w); X if (b != NULL) X gen_and(b, tmp); X b = tmp; X size -= 4; X } X while (size >= 2) { X u_char *p = &v[size - 2]; X u_long w = (p[0] << 8) | p[1]; X tmp = gen_cmp(offset + size - 2, BPF_H, w); X if (b != NULL) X gen_and(b, tmp); X b = tmp; X size -= 2; X } X if (size > 0) { X tmp = gen_cmp(offset, BPF_B, (u_long)v[0]); X if (b != NULL) X gen_and(b, tmp); X b = tmp; X } X return b; X} X X X Xstatic struct block * Xgen_uncond(rsense) Xint rsense; X{ X struct block *b; X struct slist *s; X X s = new_stmt(BPF_LD|BPF_IMM); X s->s.k = !rsense; X b = new_block(JMP(BPF_JEQ)); X b->stmts = s; X X return b; X} X Xstatic inline struct block * Xgen_true() X{ X return gen_uncond(1); X} X Xstatic inline struct block * Xgen_false() X{ X return gen_uncond(0); X} X Xstatic struct block * Xgen_prototype(proto) Xunsigned int proto; X{ X struct block *b0, *b1; X X switch (proto) { X case IPPROTO: X case UDPPROTO: X case TCPPROTO: X case ICMPPROTO: X case ARPPROTO: X b0 = gen_mcmp(0, BPF_W, (u_long) proto, proto); X break; X X default: X b0 = gen_cmp(40, BPF_W, (u_long) proto); X break; X } X X return (b0); X} X X Xstatic struct block * Xgen_hostop(addr, mask, dir, proto, src_off, dst_off) Xu_long addr; Xu_long mask; Xint dir; Xu_int proto, src_off, dst_off; X{ X struct block *b0, *b1; X u_int offset; X X switch (dir) { X X case Q_SRC: X offset = src_off; X break; X X case Q_DST: X offset = dst_off; X break; X X case Q_AND: X b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); X b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); X gen_and(b0, b1); X return b1; X X case Q_OR: X case Q_DEFAULT: X b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); X b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); X gen_or(b0, b1); X return b1; X X default: X abort(); X } X b0 = gen_prototype(proto); X b1 = gen_mcmp(offset, BPF_W, (u_long)addr, mask); X gen_and(b0, b1); X return b1; X} X X Xstatic struct block * Xgen_ehostop(eaddr, dir) Xu_char *eaddr; Xint dir; X{ X struct block *b0, *b1; X X switch (dir) { X case Q_SRC: X return gen_bcmp (20, 6, eaddr); X X case Q_DST: X return gen_bcmp (26, 6, eaddr); X X case Q_AND: X b0 = gen_ehostop(eaddr, Q_SRC); X b1 = gen_ehostop(eaddr, Q_DST); X gen_and(b0, b1); X return b1; X X case Q_DEFAULT: X case Q_OR: X b0 = gen_ehostop(eaddr, Q_SRC); X b1 = gen_ehostop(eaddr, Q_DST); X gen_or(b0, b1); X return b1; X } X abort(); X /* NOTREACHED */ X} X X Xstatic struct block * Xgen_host(addr, mask, proto, dir) Xu_long addr; Xu_long mask; Xint proto; Xint dir; X{ X struct block *b0, *b1; X X switch (proto) { X X case Q_DEFAULT: X b0 = gen_host(addr, mask, Q_IP, dir); X b1 = gen_host(addr, mask, Q_ARP, dir); X gen_or(b1, b0); X return b0; X X case Q_IP: X return gen_hostop(addr, mask, dir, IPPROTO, 32, 36); X X case Q_ARP: X return gen_hostop(addr, mask, dir, ARPPROTO, 38, 48); X X case Q_TCP: X bpf_error("'tcp' modifier applied to host"); X X case Q_UDP: X bpf_error("'udp' modifier applied to host"); X X case Q_ICMP: X bpf_error("'icmp' modifier applied to host"); X X default: X abort(); X } X /* NOTREACHED */ X} X Xstatic struct block * Xgen_gateway(eaddr, alist, proto, dir) Xu_char *eaddr; Xu_long **alist; Xint proto; Xint dir; X{ X struct block *b0, *b1, *tmp; X X if (dir != 0) X bpf_error("direction applied to 'gateway'"); X X switch (proto) { X case Q_DEFAULT: X case Q_IP: X case Q_ARP: X case Q_RARP: X b0 = gen_ehostop(eaddr, Q_OR); X b1 = gen_host(**alist++, 0xffffffffL, proto, Q_OR); X while (*alist) { X tmp = gen_host(**alist++, 0xffffffffL, proto, Q_OR); X gen_or(b1, tmp); X b1 = tmp; X } X gen_not(b1); X gen_and(b0, b1); X return b1; X } X bpf_error("illegal modifier of 'gateway'"); X /* NOTREACHED */ X} X Xstruct block * Xgen_proto_abbrev(proto) Xint proto; X{ X struct block *b0, *b1; X X switch (proto) { X X case Q_TCP: X b0 = gen_prototype(IPPROTO); X b1 = gen_prototype(TCPPROTO); X gen_and(b0, b1); X break; X X case Q_UDP: X b0 = gen_prototype(IPPROTO); X b1 = gen_prototype(UDPPROTO); X gen_and(b0, b1); X break; X X case Q_ICMP: X b0 = gen_prototype(IPPROTO); X b1 = gen_prototype(ICMPPROTO); X gen_and(b0, b1); X break; X X case Q_IP: X b1 = gen_prototype(IPPROTO); X break; X X case Q_ARP: X b1 = gen_prototype(ARPPROTO); X break; X X case Q_LINK: X bpf_error("link layer applied in wrong context"); X X default: X abort(); X } X return b1; X} X Xstatic struct block * Xgen_portatom(off, v) Xint off; Xlong v; X{ X return gen_cmp(40 + off, BPF_H, (u_long)v); X} X Xstruct block * Xgen_portop(port, proto, dir) Xint port, proto, dir; X{ X struct block *b0, *b1, *tmp; X X /* ip proto 'proto' */ X b0 = gen_prototype(proto); X X switch (dir) { X case Q_SRC: X b1 = gen_portatom(0, (long)port); X break; X X case Q_DST: X b1 = gen_portatom(2, (long)port); X break; X X case Q_OR: X case Q_DEFAULT: X tmp = gen_portatom(0, (long)port); X b1 = gen_portatom(2, (long)port); X gen_or(tmp, b1); X break; X X case Q_AND: X tmp = gen_portatom(0, (long)port); X b1 = gen_portatom(2, (long)port); X gen_and(tmp, b1); X break; X X default: X abort(); X } X gen_and(b0, b1); X X return b1; X} X Xstatic struct block * Xgen_port(port, ip_proto, dir) Xint port; Xu_int ip_proto; Xint dir; X{ X struct block *b0, *b1, *tmp; X X /* ether proto ip */ X b0 = gen_prototype(IPPROTO); X X switch (ip_proto) { X case IPPROTO_TCP: X b1 = gen_portop(port, TCPPROTO, dir); X break; X X case IPPROTO_UDP: X b1 = gen_portop(port, UDPPROTO, dir); X break; X X case UDPPROTO: X case TCPPROTO: X b1 = gen_portop(port, ip_proto, dir); X break; X X case PROTO_UNDEF: X tmp = gen_portop(port, TCPPROTO, dir); X b1 = gen_portop(port, UDPPROTO, dir); X gen_or(tmp, b1); X break; X X default: X abort(); X } X gen_and(b0, b1); X return b1; X} X Xstatic int Xlookup_proto(name, proto) Xchar *name; Xint proto; X{ X int v = 0; X X switch (proto) { X case Q_DEFAULT: X case Q_IP: X v = pcap_nametoproto(name); X if (v == PROTO_UNDEF) X bpf_error("unknown ip proto '%s'", name); X break; X X case Q_LINK: X /* XXX should look up h/w protocol type based on linktype */ X v = pcap_nametoeproto(name); X if (v == PROTO_UNDEF) X bpf_error("unknown ether proto '%s'", name); X break; X X default: X v = PROTO_UNDEF; X break; X } X X return v; X} X Xstatic struct block * Xgen_proto(v, proto, dir) Xint v; Xint proto; Xint dir; X{ X struct block *b0, *b1; X X if (dir != Q_DEFAULT) X bpf_error("direction applied to 'proto'"); X X switch (proto) { X case Q_DEFAULT: X case Q_IP: X b0 = gen_prototype(IPPROTO); X b1 = gen_prototype(v); X gen_and(b0, b1); X b0 = gen_prototype(TCPPROTO); X gen_not(b0); X gen_and(b0, b1); X b0 = gen_prototype(UDPPROTO); X gen_not(b0); X gen_and(b0, b1); X b0 = gen_prototype(ICMPPROTO); X gen_not(b0); X gen_and(b0, b1); X return b1; X X case Q_ARP: X bpf_error("arp does not encapsulate another protocol"); X /* NOTREACHED */ X X case Q_RARP: X bpf_error("rarp does not encapsulate another protocol"); X /* NOTREACHED */ X X case Q_LINK: X return gen_prototype(v); X X case Q_UDP: X bpf_error("'udp proto' is bogus"); X /* NOTREACHED */ X X case Q_TCP: X bpf_error("'tcp proto' is bogus"); X /* NOTREACHED */ X X case Q_ICMP: X bpf_error("'icmp proto' is bogus"); X /* NOTREACHED */ X X default: X abort(); X /* NOTREACHED */ X } X /* NOTREACHED */ X} X X/* X * Left justify 'addr' and return its resulting network mask. X */ Xstatic u_long Xnet_mask(addr) Xu_long *addr; X{ X register u_long m = 0xffffffff; X X if (*addr) X while ((*addr & 0xff000000) == 0) X *addr <<= 8, m <<= 8; X X return m; X} X Xstruct block * Xgen_scode(name, q) Xchar *name; Xstruct qual q; X{ X int proto = q.proto; X int dir = q.dir; X u_char *eaddr; X u_long mask, addr, **alist; X struct block *b, *tmp; X int port, real_proto; X X switch (q.addr) { X X case Q_NET: X addr = pcap_nametonetaddr(name); X if (addr == 0) X bpf_error("unknown network '%s'", name); X mask = net_mask(&addr); X return gen_host(addr, mask, proto, dir); X X case Q_DEFAULT: X case Q_HOST: X if (proto == Q_LINK) { X eaddr = pcap_ether_hostton(name); X if (eaddr == NULL) X bpf_error("unknown ether host '%s'", name); X return gen_ehostop(eaddr, dir); X X } else if (proto == Q_DECNET) { X unsigned short dn_addr = __pcap_nametodnaddr(name); X /* X * I don't think DECNET hosts can be multihomed, so X * there is no need to build up a list of addresses X */ X return (gen_host(dn_addr, 0, proto, dir)); X } else { X alist = pcap_nametoaddr(name); X if (alist == NULL || *alist == NULL) X bpf_error("unknown host '%s'", name); X b = gen_host(**alist++, 0xffffffffL, proto, dir); X while (*alist) { X tmp = gen_host(**alist++, 0xffffffffL, X proto, dir); X gen_or(b, tmp); X b = tmp; X } X return b; X } X X case Q_PORT: X if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP) X bpf_error("illegal qualifier of 'port'"); X if (pcap_nametoport(name, &port, &real_proto) == 0) X bpf_error("unknown port '%s'", name); X if (proto == Q_UDP) { X if (real_proto == TCPPROTO) X bpf_error("port '%s' is tcp", name); X else X /* override PROTO_UNDEF */ X real_proto = UDPPROTO; X } X if (proto == Q_TCP) { X if (real_proto == UDPPROTO) X bpf_error("port '%s' is udp", name); X else X /* override PROTO_UNDEF */ X real_proto = TCPPROTO; X } X return gen_port(port, real_proto, dir); X X case Q_GATEWAY: X eaddr = pcap_ether_hostton(name); X if (eaddr == NULL) X bpf_error("unknown ether host: %s", name); X X alist = pcap_nametoaddr(name); X if (alist == NULL || *alist == NULL) X bpf_error("unknown host '%s'", name); X return gen_gateway(eaddr, alist, proto, dir); X X case Q_PROTO: X real_proto = lookup_proto(name, proto); X if (real_proto >= 0) X return gen_proto(real_proto, proto, dir); X else X bpf_error("unknown protocol: %s", name); X X case Q_UNDEF: X syntax(); X /* NOTREACHED */ X } X abort(); X /* NOTREACHED */ X} X Xstruct block * Xgen_ncode(v, q) Xu_long v; Xstruct qual q; X{ X u_long mask; X int proto = q.proto; X int dir = q.dir; X X switch (q.addr) { X X case Q_DEFAULT: X case Q_HOST: X case Q_NET: X if (proto == Q_LINK) { X bpf_error("illegal link layer address"); X } else { X mask = net_mask(&v); X return gen_host(v, mask, proto, dir); X } X X case Q_PORT: X if (proto == Q_UDP) X proto = UDPPROTO; X else if (proto == Q_TCP) X proto = TCPPROTO; X else if (proto == Q_DEFAULT) X proto = PROTO_UNDEF; X else X bpf_error("illegal qualifier of 'port'"); X X return gen_port((int)v, proto, dir); X X case Q_GATEWAY: X bpf_error("'gateway' requires a name"); X /* NOTREACHED */ X X case Q_PROTO: X return gen_proto((int)v, proto, dir); X X case Q_UNDEF: X syntax(); X /* NOTREACHED */ X X default: X abort(); X /* NOTREACHED */ X } X /* NOTREACHED */ X} X Xstruct block * Xgen_ecode(eaddr, q) Xu_char *eaddr; Xstruct qual q; X{ X if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) X return gen_ehostop(eaddr, (int)q.dir); X X bpf_error("ethernet address used in non-ether expression"); X /* NOTREACHED */ X} X Xvoid Xsappend(s0, s1) Xstruct slist *s0, *s1; X{ X /* X * This is definitely not the best way to do this, but the X * lists will rarely get long. X */ X while (s0->next) X s0 = s0->next; X s0->next = s1; X} X Xstatic struct slist * Xxfer_to_x(a) Xstruct arth *a; X{ X struct slist *s; X X s = new_stmt(BPF_LDX|BPF_MEM); X s->s.k = a->regno; X return s; X} X Xstatic struct slist * Xxfer_to_a(a) Xstruct arth *a; X{ X struct slist *s; X X s = new_stmt(BPF_LD|BPF_MEM); X s->s.k = a->regno; X return s; X} X Xstruct arth * Xgen_load(proto, index, size) Xint proto; Xstruct arth *index; Xint size; X{ X struct slist *s, *tmp; X struct block *b; X int regno = alloc_reg(); X X free_reg(index->regno); X switch (size) { X X default: X bpf_error("data size must be 1, 2, or 4"); X X case 1: X size = BPF_B; X break; X X case 2: X size = BPF_H; X break; X X case 4: X size = BPF_W; X break; X } X switch (proto) { X default: X bpf_error("unsupported index operation"); X X case Q_LINK: X s = xfer_to_x(index); X tmp = new_stmt(BPF_LD|BPF_IND|size); X sappend(s, tmp); X sappend(index->s, s); X break; X X case Q_IP: X case Q_ARP: X case Q_RARP: X s = xfer_to_x(index); X tmp = new_stmt(BPF_LD|BPF_IND|size); X tmp->s.k = off_nl; X sappend(s, tmp); X sappend(index->s, s); X X b = gen_proto_abbrev(proto); X if (index->b) X gen_and(index->b, b); X index->b = b; X break; X X case Q_TCP: X case Q_UDP: X case Q_ICMP: X s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); X s->s.k = off_nl; X sappend(s, xfer_to_a(index)); X sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); X sappend(s, new_stmt(BPF_MISC|BPF_TAX)); X sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size)); X tmp->s.k = off_nl; X sappend(index->s, s); X X b = gen_proto_abbrev(proto); X if (index->b) X gen_and(index->b, b); X index->b = b; X break; X } X index->regno = regno; X s = new_stmt(BPF_ST); X s->s.k = regno; X sappend(index->s, s); X X return index; X} X Xstruct block * Xgen_relation(code, a0, a1, reversed) Xint code; Xstruct arth *a0, *a1; Xint reversed; X{ X struct slist *s0, *s1, *s2; X struct block *b, *tmp; X X s0 = xfer_to_x(a1); X s1 = xfer_to_a(a0); X s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X); X b = new_block(JMP(code)); X if (reversed) X gen_not(b); X X sappend(s1, s2); X sappend(s0, s1); X sappend(a1->s, s0); X sappend(a0->s, a1->s); X X b->stmts = a0->s; X X free_reg(a0->regno); X free_reg(a1->regno); X X /* 'and' together protocol checks */ X if (a0->b) { X if (a1->b) { X gen_and(a0->b, tmp = a1->b); X } X else X tmp = a0->b; X } else X tmp = a1->b; X X if (tmp) X gen_and(tmp, b); X X return b; X} X Xstruct arth * Xgen_loadlen() X{ X int regno = alloc_reg(); X struct arth *a = (struct arth *)newchunk(sizeof(*a)); X struct slist *s; X X s = new_stmt(BPF_LD|BPF_LEN); X s->next = new_stmt(BPF_ST); X s->next->s.k = regno; X a->s = s; X a->regno = regno; X X return a; X} X Xstruct arth * Xgen_loadi(val) Xint val; X{ X struct arth *a; X struct slist *s; X int reg; X X a = (struct arth *)newchunk(sizeof(*a)); X X reg = alloc_reg(); X X s = new_stmt(BPF_LD|BPF_IMM); X s->s.k = val; X s->next = new_stmt(BPF_ST); X s->next->s.k = reg; X a->s = s; X a->regno = reg; X X return a; X} X Xstruct arth * Xgen_neg(a) Xstruct arth *a; X{ X struct slist *s; X X s = xfer_to_a(a); X sappend(a->s, s); X s = new_stmt(BPF_ALU|BPF_NEG); X s->s.k = 0; X sappend(a->s, s); X s = new_stmt(BPF_ST); X s->s.k = a->regno; X sappend(a->s, s); X X return a; X} X Xstruct arth * Xgen_arth(code, a0, a1) Xint code; Xstruct arth *a0, *a1; X{ X struct slist *s0, *s1, *s2; X X s0 = xfer_to_x(a1); X s1 = xfer_to_a(a0); X s2 = new_stmt(BPF_ALU|BPF_X|code); X X sappend(s1, s2); X sappend(s0, s1); X sappend(a1->s, s0); X sappend(a0->s, a1->s); X X free_reg(a1->regno); X X s0 = new_stmt(BPF_ST); X a0->regno = s0->s.k = alloc_reg(); X sappend(a0->s, s0); X X return a0; X} X X/* X * Here we handle simple allocation of the scratch registers. X * If too many registers are alloc'd, the allocator punts. X */ Xstatic int regused[BPF_MEMWORDS]; Xstatic int curreg; X X/* X * Return the next free register. X */ Xstatic int Xalloc_reg() X{ X int n = BPF_MEMWORDS; X X while (--n >= 0) { X if (regused[curreg]) X curreg = (curreg + 1) % BPF_MEMWORDS; X else { X regused[curreg] = 1; X return curreg; X } X } X bpf_error("too many registers needed to evaluate expression"); X /* NOTREACHED */ X} X X/* X * Return a register to the table so it can X * be used later. X */ Xstatic void Xfree_reg(n) X int n; X{ X regused[n] = 0; X} X Xstatic struct block * Xgen_len(jmp, n) X int jmp, n; X{ X struct slist *s; X struct block *b; X X s = new_stmt(BPF_LD|BPF_LEN); X s->next = new_stmt(BPF_ALU|BPF_SUB|BPF_K); X s->next->s.k = n; X b = new_block(JMP(jmp)); X b->stmts = s; X X return b; X} X Xstruct block * Xgen_greater(n) X int n; X{ X return gen_len(BPF_JGE, n); X} X Xstruct block * Xgen_less(n) X int n; X{ X struct block *b; X X b = gen_len(BPF_JGT, n); X gen_not(b); X X return b; X} X Xstruct block * Xgen_byteop(op, idx, val) Xint op, idx, val; X{ X struct block *b; X struct slist *s; X X switch (op) { X default: X abort(); X X case '=': X return gen_cmp((u_int)idx, BPF_B, (u_long)val); X X case '<': X b = gen_cmp((u_int)idx, BPF_B, (u_long)val); X b->s.code = JMP(BPF_JGE); X gen_not(b); X return b; X X case '>': X b = gen_cmp((u_int)idx, BPF_B, (u_long)val); X b->s.code = JMP(BPF_JGT); X return b; X X case '|': X s = new_stmt(BPF_ALU|BPF_OR|BPF_K); X break; X X case '&': X s = new_stmt(BPF_ALU|BPF_AND|BPF_K); X break; X } X s->s.k = val; X b = new_block(JMP(BPF_JEQ)); X b->stmts = s; X gen_not(b); X X return b; X} X Xstruct block * Xgen_broadcast(proto) Xint proto; X{ X u_long hostmask; X struct block *b0, *b1, *b2; X static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; X X switch (proto) { X X case Q_DEFAULT: X case Q_LINK: X return gen_ehostop(ebroadcast, Q_DST); X break; X X case Q_IP: X b0 = gen_prototype(IPPROTO); X hostmask = ~netmask; X b1 = gen_mcmp(off_nl + 16, BPF_W, (u_long)0, hostmask); X b2 = gen_mcmp(off_nl + 16, BPF_W, X (u_long)(~0 & hostmask), hostmask); X gen_or(b1, b2); X gen_and(b0, b2); X return b2; X } X bpf_error("only ether/ip broadcast filters supported"); X} X Xstruct block * Xgen_multicast(proto) X int proto; X{ X register struct block *b0, *b1; X register struct slist *s; X X switch (proto) { X X case Q_DEFAULT: X case Q_LINK: X s = new_stmt(BPF_LD|BPF_B|BPF_ABS); X s->s.k = 0; X b0 = new_block(JMP(BPF_JSET)); X b0->s.k = 1; X b0->stmts = s; X return b0; X break; X X case Q_IP: X b0 = gen_prototype(IPPROTO); X b1 = gen_cmp(off_nl + 16, BPF_B, (u_long)224); X b1->s.code = JMP(BPF_JGE); X gen_and(b0, b1); X return b1; X } X} X X/* X * generate command for inbound/outbound. It's here so we can X * make it link-type specific. 'dir' = 0 implies "inbound", X * = 1 implies "outbound". X */ Xstruct block * Xgen_inbound(dir) Xint dir; X{ X register struct block *b0; X X b0 = gen_relation(BPF_JEQ, X gen_load(Q_LINK, gen_loadi(0), 1), X gen_loadi(0), X dir); X return (b0); X} SHAR_EOF $shar_touch -am 0508141395 'argus-1.5/common/gencode.c' && chmod 0444 'argus-1.5/common/gencode.c' || echo 'restore of argus-1.5/common/gencode.c failed' shar_count="`wc -c < 'argus-1.5/common/gencode.c'`" test 28245 -eq "$shar_count" || echo "argus-1.5/common/gencode.c: original size 28245, current size $shar_count" rm -f _sharnew.tmp fi # ============= argus-1.5/common/util.c ============== if test -f 'argus-1.5/common/util.c' && test X"$1" != X"-c"; then echo 'x - skipping argus-1.5/common/util.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting argus-1.5/common/util.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'argus-1.5/common/util.c' && X/* X * Copyright (c) 1988-1990 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that: (1) source code distributions X * retain the above copyright notice and this paragraph in its entirety, (2) X * distributions including binary code include the above copyright notice and X * this paragraph in its entirety in the documentation or other materials X * provided with the distribution, and (3) all advertising materials mentioning X * features or use of this software display the following acknowledgement: X * ``This product includes software developed by the University of California, X * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of X * the University nor the names of its contributors may be used to endorse X * or promote products derived from this software without specific prior X * written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#ifndef lint Xstatic char rcsid[] = X "@(#) $Header: /usr/users/poepping/src/argus/argus-1.5/common/RCS/util.c,v 1.1 1995/02/08 21:03:27 poepping Exp $ (LBL)"; X#endif X X#include X#ifdef __STDC__ X#include X#endif X#include X#include X#include X#include X#include X#ifdef SOLARIS X#include X#endif X X X#include X#include X X/* Hex digit to integer. */ Xstatic inline int Xxdtoi(c) X{ X if (isdigit(c)) X return c - '0'; X else if (islower(c)) X return c - 'a' + 10; X else X return c - 'A' + 10; X} X X/* X * Convert string to integer. Just like atoi(), but checks for X * preceding 0x or 0 and uses hex or octal instead of decimal. X */ Xint Xstoi(s) X char *s; X{ X int base = 10; X int n = 0; X X if (*s == '0') { X if (s[1] == 'x' || s[1] == 'X') { X s += 2; X base = 16; X } X else { X base = 8; X s += 1; X } X } X while (*s) X n = n * base + xdtoi(*s++); X X return n; X} X X/* X * Print out a filename (or other ascii string). X * Return true if truncated. X */ Xint Xprintfn(s, ep) X register u_char *s, *ep; X{ X register u_char c; X X putchar('"'); X while (c = *s++) { X if (s > ep) { X putchar('"'); X return(1); X } X if (!isascii(c)) { X c = toascii(c); X putchar('M'); X putchar('-'); X } X if (!isprint(c)) { X c ^= 0x40; /* DEL to ?, others to alpha */ X putchar('^'); X } X putchar(c); X } X putchar('"'); X return(0); X} X X X#ifdef NOVFPRINTF X/* X * Stock 4.3 doesn't have vfprintf. X * This routine is due to Chris Torek. X */ Xvfprintf(f, fmt, args) X FILE *f; X char *fmt; X va_list args; X{ X int ret; X X if ((f->_flag & _IOWRT) == 0) { X if (f->_flag & _IORW) X f->_flag |= _IOWRT; X else X return EOF; X } X ret = _doprnt(fmt, args, f); X return ferror(f) ? EOF : ret; X} X#endif X X/* VARARGS */ Xvoid Xerror(va_alist) X va_dcl X{ X register char *cp; X va_list ap; X X (void)fprintf(stderr, "connect: "); X X va_start(ap); X cp = va_arg(ap, char *); X (void)vfprintf(stderr, cp, ap); X va_end(ap); X if (*cp) { X cp += strlen(cp); X if (cp[-1] != '\n') X (void)fputc('\n', stderr); X } X exit(1); X /* NOTREACHED */ X} X X/* VARARGS */ Xvoid Xwarning(va_alist) X va_dcl X{ X register char *cp; X va_list ap; X X (void)fprintf(stderr, "connect: warning: "); X X va_start(ap); X cp = va_arg(ap, char *); X (void)vfprintf(stderr, cp, ap); X va_end(ap); X if (*cp) { X cp += strlen(cp); X if (cp[-1] != '\n') X (void)fputc('\n', stderr); X } X} X X/* A replacement for strdup() that cuts down on malloc() overhead */ Xchar * Xsavestr(register const char *str) X{ X register u_int size; X register char *p; X static char *strptr = NULL; X static u_int strsize = 0; X X size = strlen(str) + 1; X if (size > strsize) { X strsize = 1024; X if (strsize < size) X strsize = size; X strptr = malloc(strsize); X if (strptr == NULL) X error("savestr: malloc"); X } X (void)strcpy(strptr, str); X p = strptr; X strptr += size; X strsize -= size; X return (p); X} X X X X/* X * Copy arg vector into a new buffer, concatenating arguments with spaces. X */ Xchar * Xcopy_argv(argv) Xregister char **argv; X{ X register char **p; X register int len = 0; X char *buf; X char *src, *dst; X X p = argv; X if (*p == 0) X return 0; X X while (*p) X len += strlen(*p++) + 1; X X buf = malloc (len); X X p = argv; X dst = buf; X while (src = *p++) { X while (*dst++ = *src++) X ; X dst[-1] = ' '; X } X dst[-1] = '\0'; X X return buf; X} X Xchar * Xread_infile(fname) X char *fname; X{ X struct stat buf; X int fd; X char *p; X X fd = open(fname, O_RDONLY); X if (fd < 0) X error("can't open '%s'", fname); X X if (fstat(fd, &buf) < 0) X error("can't state '%s'", fname); X X p = malloc((unsigned)buf.st_size); X if (read(fd, p, (int)buf.st_size) != buf.st_size) X error("problem reading '%s'", fname); X X return p; X} X X/* X * Left justify 'addr' and return its resulting network mask. X */ Xu_long Xnet_mask(addr) X u_long *addr; X{ X register u_long m = 0xffffffff; X X if (*addr) X while ((*addr & 0xff000000) == 0) X *addr <<= 8, m <<= 8; X X return m; X} X X#include X Xu_long Xipaddrtonetmask(addr) Xu_long addr; X{ X if (IN_CLASSA (addr)) return IN_CLASSA_NET; X if (IN_CLASSB (addr)) return IN_CLASSB_NET; X if (IN_CLASSC (addr)) return IN_CLASSC_NET; X else return 0; X} X X Xu_long Xgetnetnumber(addr) Xu_long addr; X{ X if (IN_CLASSA (addr)) return (addr >> 24 ); X if (IN_CLASSB (addr)) return (addr >> 16 ); X if (IN_CLASSC (addr)) return (addr >> 8 ); X else return 0; X} X X X X#ifdef SOLARIS Xbcopy (s1, s2, len) Xchar *s1, *s2; Xint len; X{ X memmove (s2, s1, len); X} X Xbcmp (s1, s2, len) Xchar *s1, *s2; Xint len; X{ X return (memcmp (s1, s2, len)); X} X Xbzero (s1, len) Xchar *s1; Xint len; X{ X memset (s1, 0, len); X} X#endif SHAR_EOF $shar_touch -am 0508141395 'argus-1.5/common/util.c' && chmod 0444 'argus-1.5/common/util.c' || echo 'restore of argus-1.5/common/util.c failed' shar_count="`wc -c < 'argus-1.5/common/util.c'`" test 6309 -eq "$shar_count" || echo "argus-1.5/common/util.c: original size 6309, current size $shar_count" rm -f _sharnew.tmp fi # ============= argus-1.5/common/argus_parse.c ============== if test -f 'argus-1.5/common/argus_parse.c' && test X"$1" != X"-c"; then echo 'x - skipping argus-1.5/common/argus_parse.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting argus-1.5/common/argus_parse.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'argus-1.5/common/argus_parse.c' && X X/* X * Copyright (c) 1993, 1994 Carnegie Mellon University. X * All rights reserved. X * X * Permission to use, copy, modify, and distribute this software and X * its documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appear in all copies and X * that both that copyright notice and this permission notice appear X * in supporting documentation, and that the name of CMU not be X * used in advertising or publicity pertaining to distribution of the X * software without specific, written prior permission. X * X * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL X * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X * X */ X X/* X * argus_parse - parse argus output. X * this module performs all the argus(1) related connection parsing, X * selects datum from a set of criteria, and then calls specific X * protocol dependant routines, depending on the selected datum. X * at the end of processing, argus_parse calls an application X * specific finish routine, argus_parse_complete(), and when X * connected to a remote data source, it supplies a periodic X * timeout routine; X * X * this module defines all things, except: X * X * (void) usage ((char *) argv[0]); X * this routine should print the standard usage message X * for the specific application. X * X * init (); this is the application specific init X * routine, which is called after all parsing X * initialization is done, prior to reading the X * first monitor(1) datum. X * X * (void) clientTimeout (); X * this routine is called every second, when X * argus_parse is connected to a remote data source. X * X * process_tcp ((struct writeStruct *) ptr); X * this routine should process tcp events; X * X * process_udp ((struct writeStruct *) ptr); X * this routine should process tcp events; X * X * process_icmp ((struct writeStruct *) ptr); X * this routine should process tcp events; X * X * process_ip ((struct writeStruct *) ptr); X * this routine should process tcp events; X * X * (void) argus_parse_complete (); X * this routine will be called after all the X * monitor data has been read. X * X * X * written by Carter Bullard X * Software Engineering Institute X * Carnegie Mellon Univeristy X * X */ X X#define MONITOR_PARSE X X X#include X#include X X#include X#include X#include X X#ifndef SOLARIS X#include X#endif X#include X#include X#include X X#include X#include X X#include X#include X#include X#include X X#include X#include X#include X#include X X#include X X#include X#include X#include X#include X X Xextern init (); Xextern void usage (); Xextern parse_arg (); Xextern process_tcp (); Xextern process_icmp (); Xextern process_udp (); Xextern process_ip (); Xextern char *copy_argv (); Xextern void argus_parse_complete (); Xextern char *appOptstring; X X X#include X#include X X Xstruct policyStruct *policy = NULL; Xchar *policyfile = NULL; Xchar *wfile = NULL; X Xstruct FILE_ENTRY *input_file_list = NULL; Xstruct IP_ENTRY *remote_host_list = NULL; X X#include X X#define MAXSTR 256 X#define MAXTIME 100000 X Xu_long localnet, netmask; X Xargus_parse_init (fd, read_mode) Xint fd; Xint read_mode; X{ X struct timeval now; X struct timezone tz; X char errbuf[256]; X char *device = NULL; X X if (gettimeofday(&now, &tz) < 0) X error("gettimeofday"); X thiszone = tz.tz_minuteswest * -60; X if (localtime ((time_t *)&now.tv_sec)->tm_isdst) X thiszone += 3600; X X if (device = pcap_lookupdev (errbuf)) X pcap_lookupnet(device, &localnet, &netmask, errbuf); X X init_addrtoname (0, localnet, netmask); X} X X X#include X Xchar *progname = NULL; Xchar cmdline[256]; X Xint portnum = 0; X Xmain (argc, argv) Xint argc; Xchar **argv; X{ X register int i, op; X register char *file = NULL; X struct bpf_program bpfcode; X struct FILE_ENTRY *ptr; X char *cmdbuf = NULL, *infile = NULL, *read_infile (); X pcap_t p; X extern char *optarg; X extern int optind, opterr; X X opterr = 0; X for (i = 0, *cmdline = '\0'; i < argc; i++) { X strcat (cmdline, argv[i]); X strcat (cmdline, " "); X } X if (strchr (argv[0], '/')) X argv[0] = strrchr(argv[0], '/') + 1; X progname = argv[0]; X while ((op = getopt (argc, argv, "bcC:d:EF:Ir:w:P:hnmMNOPRS:TWX")) != EOF) { X switch (op) { X case 'C': policyfile = optarg; break; X case 'd': debugflag = atoi (optarg); break; X case 'P': portnum = atoi (optarg); break; X case 'b': ++bflag; break; X case 'c': ++cflag; break; X case 't': ++tflag; break; X case 'E': ++Eflag; break; X case 'I': ++Iflag; break; X case 'R': ++Rflag; break; X case 'T': ++Tflag; break; X case 'u': ++uflag; break; X case 'm': ++mflag; break; X case 'M': ++Mflag; break; X case 'n': ++nflag; break; X case 'N': ++Normflag; break; X case 'W': ++Wflag; break; X case 'O': ++Oflag; break; X case 'X': ++Xflag; break; X case 'F': infile = optarg; break; X case 'w': X if ((wfile = optarg) == NULL) X if (!strcmp (argv[optind], "-")) { X wfile = "-"; X } X break; X case 'r': ++rflag; X if (optarg == NULL) optarg = "-"; X if (!(new_file_arg (optarg))) { X fprintf (stderr, "%s: error: file arg %s \n", *argv, optarg); X exit (1); X } X break; X case 'S': ++Sflag; X if (!(remote_host_arg (optarg))) { X fprintf (stderr, "%s: host %s unknown\n", *argv, optarg); X exit (1); X } X break; X X case 'h': X default: X usage (argv[0]); X /* NOTREACHED */ X } X } X X if (infile) X cmdbuf = read_infile (infile); X else X cmdbuf = copy_argv (&argv[optind]); X X bzero (&bpfcode, sizeof (bpfcode)); X if (policy_compile (&p, &bpfcode, cmdbuf, 1, netmask) < 0) { X fprintf (stderr, "%s: expression: %s\n", progname, p.errbuf); X exit (-1); X } X X if (bflag) { X bpf_dump(&bpfcode, bflag); X exit (0); X } X X if (readPolicy (&policy, policyfile)) { X if (Sflag) { X if (read_remote_connection (get_server_socket (remote_host_list), X &bpfcode)) X fprintf (stderr, "%s: connection failed\n", *argv); X } else X if (ptr = input_file_list) { X while (ptr) { X if (strcmp ((char *) ptr->str, "-")) { X if (read_connection (fopen (ptr->str, "r"), &bpfcode)) X perror ("fopen"); X } else X read_connection (stdin, &bpfcode); X ptr = ptr->nxt; X } X } else X read_connection (stdin, &bpfcode); X X argus_parse_complete (); X } X exit (0); X} X XreadPolicy (policy, file) Xstruct policyStruct **policy; Xchar *file; X{ X register int retn = 1, linenum = 0, parse; X register struct policyStruct *pol, *policyLast = NULL; X register FILE *fd; X char buffer [1024], *str; X X if (file) { X if (fd = fopen (file, "r")) { X while (fgets (buffer, 1024, fd)) { X linenum++; X if ((*buffer != '#') && (*buffer != '\n') && (*buffer != '!')) { X if (pol = (struct policyStruct *) calloc (1, X sizeof (struct policyStruct))) { X pol->str = strdup (buffer); X if (!(parsePolicy (pol, buffer))) { X free (pol->str); X free (pol); X str = parseerrorstr[parseerror]; X fprintf (stderr, "%s: parsing error: %s\n", X progname, file); X fprintf (stderr, "\tline number %d: %s\n", linenum, str); X retn = 0; X } X if (policyLast) { X policyLast->nxt = pol; X pol->prv = policyLast; X policyLast = pol; X } else X *policy = policyLast = pol; X } X } X } X fclose (fd); X } else { X retn = 0; X fprintf (stderr, "%s: error couldn't open %s\n", progname, file); X } X } X X return (retn); X} X X X#include X XparsePolicy (policy, buf) Xstruct policyStruct *policy; Xchar *buf; X{ X register int retn = 1, error = 0, i; X register char *ptr; X X if (strncmp (buf, "access", 6)) { X if (strstr (buf, "ip")) X if (strstr (buf, "source-route")) X policy->type = SSRCROUTE; X } else { X policy->type = ACCESSLIST; X for (i = 0; ((i < POLICYFIELDNUM) && !(error)); i++) { X if ((ptr = strtok (buf, " ")) && (*ptr != '\n')) { X switch (i) { X case POLICYSTRING: X if ((strcmp (ptr, POLICY_STRING))) error++; X break; X X case POLICYID: X if (!(policy->policyID = atoi (ptr))) error++; X break; X X case POLICYACTION: X if (!(strcmp (ptr, "permit"))) X policy->flags |= PERMIT; X else if (!(strcmp (ptr, "deny"))) X policy->flags |= DENY; X else error++; X break; X X case POLICYPROTO: X if (!(strcmp (ptr, "icmp"))) X policy->flags |= ICMP; X else if (!(strcmp (ptr, "tcp"))) X policy->flags |= TCP; X else if (!(strcmp (ptr, "udp"))) X policy->flags |= UDP; X else if (!(strcmp (ptr, "ip"))) X policy->flags |= IP; X else error++; X break; X X case POLICYDSTADDR: X policy->dst.addr = inet_addr (ptr); break; X case POLICYDSTMASK: X policy->dst.mask = inet_addr (ptr); break; X case POLICYSRCADDR: X policy->src.addr = inet_addr (ptr); break; X case POLICYSRCMASK: X policy->src.mask = inet_addr (ptr); break; X X case POLICYPORTACT: X if (!(strcmp (ptr, "eq"))) X policy->action |= EQ; X else if (!(strcmp (ptr, "lt"))) X policy->action |= LT; X else if (!(strcmp (ptr, "gt"))) X policy->action |= GT; X else if (!(strcmp (ptr, "neq"))) X policy->action |= NEQ; X else if (!(strncmp (ptr, "established",11))) X policy->action |= EST; X else error++; X break; X X case POLICYPORT: X if (!(policy->port = (u_short) atoi (ptr))) error++; X break; X X case POLICYNOTIFICATION: X break; X } X X buf = NULL; X } else X break; X } X } X X if (error) { X parseerror = i - 1; retn = 0; X } X X return (retn); X} X Xcheck_flags (ptr) Xstruct writeStruct *ptr; X{ X int retn = 0; X X if (Eflag|Mflag|Normflag|Oflag|Xflag|Rflag|Tflag|Wflag) { X if (Eflag && !retn) retn = ptr->status & CON_ESTABLISHED; X if (Mflag && !retn) retn = ptr->status & MULTIADDR; X if (Normflag && !retn) retn = ptr->status & NORMAL_CLOSE; X if (Oflag && !retn) retn = ptr->status & IPOPTIONMASK; X if (Xflag && !retn) retn = ptr->status & PKTS_RETRANS; X if (Rflag && !retn) retn = ptr->status & RESET; X if (Tflag && !retn) retn = ptr->status & TIMED_OUT; X if (Wflag && !retn) retn = ptr->status & X (SRC_WINDOW_SHUT|DST_WINDOW_SHUT); X } else X retn = 1; X X return (retn); X} X X Xcheck_policy (ptr, policy) Xstruct writeStruct *ptr; Xstruct policyStruct *policy; X{ X int retn = 1, i, policymatch = 0; X X if (policy) { X while (policy) { X if (retn = meets_policy_criteria (ptr, policy)) { X retn = do_notification (ptr, policy); X policymatch = 1; X break; X } X policy = policy->nxt; X } X } X X return (retn); X} X X Xmeets_policy_criteria (ptr, policy) Xstruct writeStruct *ptr; Xstruct policyStruct *policy; X{ X register int retn = 0, i = 0; X u_long saddr = 0, daddr = 0, addr = 0; X u_short sport = 0, dport = 0, port = 0; X X switch (policy->type) { X case SSRCROUTE: X if ((ptr->status & SSRCROUTE) || (ptr->status & LSRCROUTE)) X retn++; X break; X X case ACCESSLIST: X if ((ptr->status & ICMPPROTO) || (ptr->status & UDPPROTO) || X ((ptr->status & TCPPROTO) && !(ptr->status & REVERSE))) { X saddr = ptr->addr.src.s_addr; X daddr = ptr->addr.dst.s_addr; X sport = ((u_short *)&ptr->addr.port)[0]; X dport = ((u_short *)&ptr->addr.port)[1]; X port = dport; X } else { X saddr = ptr->addr.dst.s_addr; X daddr = ptr->addr.src.s_addr; X sport = ((u_short *)&ptr->addr.port)[1]; X dport = ((u_short *)&ptr->addr.port)[0]; X port = dport; X } X X for (i = 0, retn = 1; ((i < POLICYTESTCRITERIA) && retn); i++) { X retn = 0; X switch (i) { X case POLICYTESTPROTO: X switch (policy->flags & (UDP | TCP | ICMP | IP)) { X case UDP: if (ptr->status & UDPPROTO) retn++; break; X case TCP: if (ptr->status & TCPPROTO) retn++; break; X case ICMP: if (ptr->status & ICMPPROTO) retn++; break; X case IP: retn++; break; X } X break; X X case POLICYTESTSRC: X if ((saddr & ~policy->src.mask) == policy->src.addr) X retn++; X break; X case POLICYTESTDST: X if ((daddr & ~policy->dst.mask) == policy->dst.addr) X retn++; X break; X case POLICYTESTPORT: X switch (policy->action) { X case EQ: X if (port == policy->port) X retn++; break; X case LT: X if (port < policy->port) X retn++; break; X case GT: X if (port > policy->port) X retn++; break; X case NEQ: X if (port != policy->port) X retn++; break; X case EST: X if (!(ptr->status & SAW_SYN)) X retn++; break; X default: X retn++; break; X } X break; X } X } X } X X return (retn); X} X X Xdo_notification (ptr, policy) Xstruct writeStruct *ptr; Xstruct policyStruct *policy; X{ X register int retn = 1; X X if (policy) X if (policy->flags & PERMIT) { X if (debugflag > 1) X printf ("%s %s", "policy: permitted", policy->str); X else X retn = 0; X } else X if (debugflag) X printf ("%s %s", "policy: denyed", policy->str); X X return (retn); X} X X X Xstruct naddrmem *naddrtable [HASHNAMESIZE]; X Xstruct naddrmem { X struct naddrmem *nxt; X u_long addr; X u_short port; X}; X X Xchar *tag_string = "Argus Version "; Xextern u_long localaddr; Xint major_version = 0, minor_version = 0; X X Xhandle_argus_control (ptr) Xstruct writeStruct *ptr; X{ X} X Xhandle_datum (ptr, read_mode, bpfcode) Xstruct writeStruct *ptr; Xint read_mode; Xstruct bpf_program *bpfcode; X{ X int retn; X struct writeStruct buf; X struct bpf_insn *fcode = bpfcode->bf_insns; X X if (ptr->status & ARGUSCONTROL) X handle_argus_control (&ptr); X X else { X reformat_datum (ptr, &buf); X if (retn = check_flags (&buf)) { X if (retn = argus_filter (fcode, &buf)) { X if (retn = check_policy (&buf, policy)) { X if (wfile) { X writeNewLogfile (ptr); X X if (strcmp (wfile, "-")) X version_process (&buf, read_mode); X } else X version_process (&buf, read_mode); X } X } X } X } X} X X#define IPPROTOMASK (TCPPROTO | ICMPPROTO | UDPPROTO) X#define PROTOMASK (IPPROTO | ARPPROTO) X Xreformat_datum (ptr, buf) Xstruct writeStruct *ptr, *buf; X{ X u_long saddr, daddr; X u_short sport, dport; X struct writeStruct tmpbuf, *tmp = &tmpbuf; X X if (ptr && buf) { X bcopy (ptr, tmp, sizeof (struct writeStruct)); X if (tmp->status & REVERSE) { X bcopy (&ptr->etherdst, &tmp->ethersrc, 6); X bcopy (&ptr->ethersrc, &tmp->etherdst, 6); X bcopy (&ptr->addr.dst, &tmp->addr.src, 4); X bcopy (&ptr->addr.src, &tmp->addr.dst, 4); X sport = ((unsigned short *) &ptr->addr.port)[0]; X dport = ((unsigned short *) &ptr->addr.port)[1]; SHAR_EOF : || echo 'restore of argus-1.5/common/argus_parse.c failed' fi echo 'End of archive part 3' echo 'File argus-1.5/common/argus_parse.c is continued in part 4' echo 4 > _sharseq.tmp exit 0