libpcap-0.9.7/./0000755000026300017500000000000010651263467011432 5ustar mcrmcrlibpcap-0.9.7/./missing/0000755000026300017500000000000010245661231013071 5ustar mcrmcrlibpcap-0.9.7/./missing/snprintf.c0000644000026300017500000003143710034360447015111 0ustar mcrmcr/* * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * 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. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $Id: snprintf.c,v 1.1 2004/04/05 22:43:51 guy Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/missing/snprintf.c,v 1.1 2004/04/05 22:43:51 guy Exp $"; #endif #include #include #include #include #include #include #include enum format_flags { minus_flag = 1, plus_flag = 2, space_flag = 4, alternate_flag = 8, zero_flag = 16 }; /* * Common state */ struct state { unsigned char *str; unsigned char *s; unsigned char *theend; size_t sz; size_t max_sz; int (*append_char)(struct state *, unsigned char); int (*reserve)(struct state *, size_t); /* XXX - methods */ }; #ifndef HAVE_VSNPRINTF static int sn_reserve (struct state *state, size_t n) { return state->s + n > state->theend; } static int sn_append_char (struct state *state, unsigned char c) { if (sn_reserve (state, 1)) { return 1; } else { *state->s++ = c; return 0; } } #endif #if 0 static int as_reserve (struct state *state, size_t n) { if (state->s + n > state->theend) { int off = state->s - state->str; unsigned char *tmp; if (state->max_sz && state->sz >= state->max_sz) return 1; state->sz = max(state->sz * 2, state->sz + n); if (state->max_sz) state->sz = min(state->sz, state->max_sz); tmp = realloc (state->str, state->sz); if (tmp == NULL) return 1; state->str = tmp; state->s = state->str + off; state->theend = state->str + state->sz - 1; } return 0; } static int as_append_char (struct state *state, unsigned char c) { if(as_reserve (state, 1)) return 1; else { *state->s++ = c; return 0; } } #endif static int append_number(struct state *state, unsigned long num, unsigned base, char *rep, int width, int prec, int flags, int minusp) { int len = 0; int i; /* given precision, ignore zero flag */ if(prec != -1) flags &= ~zero_flag; else prec = 1; /* zero value with zero precision -> "" */ if(prec == 0 && num == 0) return 0; do{ if((*state->append_char)(state, rep[num % base])) return 1; len++; num /= base; }while(num); prec -= len; /* pad with prec zeros */ while(prec-- > 0){ if((*state->append_char)(state, '0')) return 1; len++; } /* add length of alternate prefix (added later) to len */ if(flags & alternate_flag && (base == 16 || base == 8)) len += base / 8; /* pad with zeros */ if(flags & zero_flag){ width -= len; if(minusp || (flags & space_flag) || (flags & plus_flag)) width--; while(width-- > 0){ if((*state->append_char)(state, '0')) return 1; len++; } } /* add alternate prefix */ if(flags & alternate_flag && (base == 16 || base == 8)){ if(base == 16) if((*state->append_char)(state, rep[10] + 23)) /* XXX */ return 1; if((*state->append_char)(state, '0')) return 1; } /* add sign */ if(minusp){ if((*state->append_char)(state, '-')) return 1; len++; } else if(flags & plus_flag) { if((*state->append_char)(state, '+')) return 1; len++; } else if(flags & space_flag) { if((*state->append_char)(state, ' ')) return 1; len++; } if(flags & minus_flag) /* swap before padding with spaces */ for(i = 0; i < len / 2; i++){ char c = state->s[-i-1]; state->s[-i-1] = state->s[-len+i]; state->s[-len+i] = c; } width -= len; while(width-- > 0){ if((*state->append_char)(state, ' ')) return 1; len++; } if(!(flags & minus_flag)) /* swap after padding with spaces */ for(i = 0; i < len / 2; i++){ char c = state->s[-i-1]; state->s[-i-1] = state->s[-len+i]; state->s[-len+i] = c; } return 0; } static int append_string (struct state *state, unsigned char *arg, int width, int prec, int flags) { if(prec != -1) width -= prec; else width -= strlen((char *)arg); if(!(flags & minus_flag)) while(width-- > 0) if((*state->append_char) (state, ' ')) return 1; if (prec != -1) { while (*arg && prec--) if ((*state->append_char) (state, *arg++)) return 1; } else { while (*arg) if ((*state->append_char) (state, *arg++)) return 1; } if(flags & minus_flag) while(width-- > 0) if((*state->append_char) (state, ' ')) return 1; return 0; } static int append_char(struct state *state, unsigned char arg, int width, int flags) { while(!(flags & minus_flag) && --width > 0) if((*state->append_char) (state, ' ')) return 1; if((*state->append_char) (state, arg)) return 1; while((flags & minus_flag) && --width > 0) if((*state->append_char) (state, ' ')) return 1; return 0; } /* * This can't be made into a function... */ #define PARSE_INT_FORMAT(res, arg, unsig) \ if (long_flag) \ res = (unsig long)va_arg(arg, unsig long); \ else if (short_flag) \ res = (unsig short)va_arg(arg, unsig int); \ else \ res = (unsig int)va_arg(arg, unsig int) /* * zyxprintf - return 0 or -1 */ static int xyzprintf (struct state *state, const char *char_format, va_list ap) { const unsigned char *format = (const unsigned char *)char_format; unsigned char c; while((c = *format++)) { if (c == '%') { int flags = 0; int width = 0; int prec = -1; int long_flag = 0; int short_flag = 0; /* flags */ while((c = *format++)){ if(c == '-') flags |= minus_flag; else if(c == '+') flags |= plus_flag; else if(c == ' ') flags |= space_flag; else if(c == '#') flags |= alternate_flag; else if(c == '0') flags |= zero_flag; else break; } if((flags & space_flag) && (flags & plus_flag)) flags ^= space_flag; if((flags & minus_flag) && (flags & zero_flag)) flags ^= zero_flag; /* width */ if (isdigit(c)) do { width = width * 10 + c - '0'; c = *format++; } while(isdigit(c)); else if(c == '*') { width = va_arg(ap, int); c = *format++; } /* precision */ if (c == '.') { prec = 0; c = *format++; if (isdigit(c)) do { prec = prec * 10 + c - '0'; c = *format++; } while(isdigit(c)); else if (c == '*') { prec = va_arg(ap, int); c = *format++; } } /* size */ if (c == 'h') { short_flag = 1; c = *format++; } else if (c == 'l') { long_flag = 1; c = *format++; } switch (c) { case 'c' : if(append_char(state, va_arg(ap, int), width, flags)) return -1; break; case 's' : if (append_string(state, va_arg(ap, unsigned char*), width, prec, flags)) return -1; break; case 'd' : case 'i' : { long arg; unsigned long num; int minusp = 0; PARSE_INT_FORMAT(arg, ap, signed); if (arg < 0) { minusp = 1; num = -arg; } else num = arg; if (append_number (state, num, 10, "0123456789", width, prec, flags, minusp)) return -1; break; } case 'u' : { unsigned long arg; PARSE_INT_FORMAT(arg, ap, unsigned); if (append_number (state, arg, 10, "0123456789", width, prec, flags, 0)) return -1; break; } case 'o' : { unsigned long arg; PARSE_INT_FORMAT(arg, ap, unsigned); if (append_number (state, arg, 010, "01234567", width, prec, flags, 0)) return -1; break; } case 'x' : { unsigned long arg; PARSE_INT_FORMAT(arg, ap, unsigned); if (append_number (state, arg, 0x10, "0123456789abcdef", width, prec, flags, 0)) return -1; break; } case 'X' :{ unsigned long arg; PARSE_INT_FORMAT(arg, ap, unsigned); if (append_number (state, arg, 0x10, "0123456789ABCDEF", width, prec, flags, 0)) return -1; break; } case 'p' : { unsigned long arg = (unsigned long)va_arg(ap, void*); if (append_number (state, arg, 0x10, "0123456789ABCDEF", width, prec, flags, 0)) return -1; break; } case 'n' : { int *arg = va_arg(ap, int*); *arg = state->s - state->str; break; } case '\0' : --format; /* FALLTHROUGH */ case '%' : if ((*state->append_char)(state, c)) return -1; break; default : if ( (*state->append_char)(state, '%') || (*state->append_char)(state, c)) return -1; break; } } else if ((*state->append_char) (state, c)) return -1; } return 0; } #ifndef HAVE_SNPRINTF int snprintf (char *str, size_t sz, const char *format, ...) { va_list args; int ret; va_start(args, format); ret = vsnprintf (str, sz, format, args); #ifdef PARANOIA { int ret2; char *tmp; tmp = malloc (sz); if (tmp == NULL) abort (); ret2 = vsprintf (tmp, format, args); if (ret != ret2 || strcmp(str, tmp)) abort (); free (tmp); } #endif va_end(args); return ret; } #endif #if 0 #ifndef HAVE_ASPRINTF int asprintf (char **ret, const char *format, ...) { va_list args; int val; va_start(args, format); val = vasprintf (ret, format, args); #ifdef PARANOIA { int ret2; char *tmp; tmp = malloc (val + 1); if (tmp == NULL) abort (); ret2 = vsprintf (tmp, format, args); if (val != ret2 || strcmp(*ret, tmp)) abort (); free (tmp); } #endif va_end(args); return val; } #endif #ifndef HAVE_ASNPRINTF int asnprintf (char **ret, size_t max_sz, const char *format, ...) { va_list args; int val; va_start(args, format); val = vasnprintf (ret, max_sz, format, args); #ifdef PARANOIA { int ret2; char *tmp; tmp = malloc (val + 1); if (tmp == NULL) abort (); ret2 = vsprintf (tmp, format, args); if (val != ret2 || strcmp(*ret, tmp)) abort (); free (tmp); } #endif va_end(args); return val; } #endif #ifndef HAVE_VASPRINTF int vasprintf (char **ret, const char *format, va_list args) { return vasnprintf (ret, 0, format, args); } #endif #ifndef HAVE_VASNPRINTF int vasnprintf (char **ret, size_t max_sz, const char *format, va_list args) { int st; size_t len; struct state state; state.max_sz = max_sz; state.sz = 1; state.str = malloc(state.sz); if (state.str == NULL) { *ret = NULL; return -1; } state.s = state.str; state.theend = state.s + state.sz - 1; state.append_char = as_append_char; state.reserve = as_reserve; st = xyzprintf (&state, format, args); if (st) { free (state.str); *ret = NULL; return -1; } else { char *tmp; *state.s = '\0'; len = state.s - state.str; tmp = realloc (state.str, len+1); if (tmp == NULL) { free (state.str); *ret = NULL; return -1; } *ret = tmp; return len; } } #endif #endif #ifndef HAVE_VSNPRINTF int vsnprintf (char *str, size_t sz, const char *format, va_list args) { struct state state; int ret; unsigned char *ustr = (unsigned char *)str; state.max_sz = 0; state.sz = sz; state.str = ustr; state.s = ustr; state.theend = ustr + sz - 1; state.append_char = sn_append_char; state.reserve = sn_reserve; ret = xyzprintf (&state, format, args); *state.s = '\0'; if (ret) return sz; else return state.s - state.str; } #endif libpcap-0.9.7/./missing/CVS/0000755000026300017500000000000010245661231013524 5ustar mcrmcrlibpcap-0.9.7/./missing/CVS/Entries0000644000026300017500000000007110245661231015056 0ustar mcrmcr/snprintf.c/1.1/Mon Apr 5 22:43:51 2004//Tlibpcap_0_9 D libpcap-0.9.7/./missing/CVS/Root0000644000026300017500000000004010245661231014364 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./missing/CVS/Repository0000644000026300017500000000002010245661231015616 0ustar mcrmcrlibpcap/missing libpcap-0.9.7/./missing/CVS/Tag0000644000026300017500000000001510245661231014156 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./pcap-dlpi.c0000644000026300017500000013523610504042141013436 0ustar mcrmcr/* * 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, and subsequently modified by * Guy Harris (guy@alum.mit.edu), Mark Pizzolato * , * and Mark C. Brown (mbrown@hp.com). */ /* * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX. * * Notes: * * - 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 when possible. * * - An older version of the HP-UX DLPI Programmer's Guide, which * I think was advertised as the 10.20 version, used to be available * at * * http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html * * but is no longer available; it can still be found at * * http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90093.pdf * * in PDF form. * * - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI * Programmer's Guide, which I think was once advertised as the * 11.00 version is available at * * http://docs.hp.com/en/B2355-90139/index.html * * - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide * is available at * * http://docs.hp.com/en/B2355-90871/index.html * * - All of the HP documents describe raw-mode services, which are * what we use if DL_HP_RAWDLS is defined. XXX - we use __hpux * in some places to test for HP-UX, but use DL_HP_RAWDLS in * other places; do we support any versions of HP-UX without * DL_HP_RAWDLS? */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.108.2.7 2006/04/04 05:33:02 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #ifdef HAVE_SYS_BUFMOD_H #include #endif #include #ifdef HAVE_SYS_DLPI_EXT_H #include #endif #ifdef HAVE_HPUX9 #include #endif #ifdef DL_HP_PPA_REQ #include #endif #include #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) #include #endif #ifdef HAVE_HPUX9 #include #endif #include #ifdef HAVE_HPUX9 #include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_LIMITS_H #include #else #define INT_MAX 2147483647 #endif #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #ifndef PCAP_DEV_PREFIX #ifdef _AIX #define PCAP_DEV_PREFIX "/dev/dlpi" #else #define PCAP_DEV_PREFIX "/dev" #endif #endif #define MAXDLBUF 8192 #ifdef HAVE_SYS_BUFMOD_H /* * Size of a bufmod chunk to pass upstream; that appears to be the biggest * value to which you can set it, and setting it to that value (which * is bigger than what appears to be the Solaris default of 8192) * reduces the number of packet drops. */ #define CHUNKSIZE 65536 /* * Size of the buffer to allocate for packet data we read; it must be * large enough to hold a chunk. */ #define PKTBUFSIZE CHUNKSIZE #else /* HAVE_SYS_BUFMOD_H */ /* * Size of the buffer to allocate for packet data we read; this is * what the value used to be - there's no particular reason why it * should be tied to MAXDLBUF, but we'll leave it as this for now. */ #define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32)) #endif /* Forwards */ static char *split_dname(char *, int *, char *); static int dl_doattach(int, int, char *); #ifdef DL_HP_RAWDLS static int dl_dohpuxbind(int, char *); #endif static int dlattachreq(int, bpf_u_int32, char *); static int dlbindreq(int, bpf_u_int32, char *); static int dlbindack(int, char *, char *, int *); static int dlpromisconreq(int, bpf_u_int32, char *); static int dlokack(int, const char *, char *, char *); static int dlinforeq(int, char *); static int dlinfoack(int, char *, char *); #ifdef DL_HP_RAWDLS static int dlrawdatareq(int, const u_char *, int); #endif static int recv_ack(int, int, const char *, char *, char *, int *); static char *dlstrerror(bpf_u_int32); static char *dlprim(bpf_u_int32); #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 static int pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps) { /* * "ps_recv" counts packets handed to the filter, not packets * that passed the filter. As filtering is done in userland, * this would not include packets dropped because we ran out * of buffer space; in order to make this more like other * platforms (Linux 2.4 and later, BSDs with BPF), where the * "packets received" count includes packets received but dropped * due to running out of buffer space, and to keep from confusing * applications that, for example, compute packet drop percentages, * we also make it count packets dropped by "bufmod" (otherwise we * might run the risk of the packet drop count being bigger than * the received-packet count). * * "ps_drop" counts packets dropped by "bufmod" because of * flow control requirements or resource exhaustion; it doesn't * count packets dropped by the interface driver, or packets * dropped upstream. As filtering is done in userland, it counts * packets regardless of whether they would've passed the filter. * * These statistics don't include packets not yet read from * the kernel by libpcap, but they may include packets not * yet read from libpcap by the application. */ *ps = p->md.stat; /* * Add in the drop count, as per the above comment. */ ps->ps_recv += ps->ps_drop; return (0); } /* XXX Needed by HP-UX (at least) */ static bpf_u_int32 ctlbuf[MAXDLBUF]; static struct strbuf ctl = { MAXDLBUF, 0, (char *)ctlbuf }; static int pcap_read_dlpi(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 = p->bufsize; data.len = 0; do { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates * that it has, and return -2 to * indicate that we were told to * break out of the loop. */ p->break_loop = 0; return (-2); } /* * XXX - check for the DLPI primitive, which * would be DL_HP_RAWDATA_IND on HP-UX * if we're in raw mode? */ if (getmsg(p->fd, &ctl, &data, &flags) < 0) { /* Don't choke when we get ptraced */ switch (errno) { case EINTR: cc = 0; continue; case EAGAIN: return (0); } strlcpy(p->errbuf, pcap_strerror(errno), sizeof(p->errbuf)); 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) { /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = bp; p->cc = ep - bp; return (n); } } #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.tv_sec = sbp->sbh_timestamp.tv_sec; pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec; #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); } static int pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) { int ret; #if defined(DLIOCRAW) ret = write(p->fd, buf, size); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } #elif defined(DL_HP_RAWDLS) if (p->send_fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: Output FD couldn't be opened"); return (-1); } ret = dlrawdatareq(p->send_fd, buf, size); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } /* * putmsg() returns either 0 or -1; it doesn't indicate how * many bytes were written (presumably they were all written * or none of them were written). OpenBSD's pcap_inject() * returns the number of bytes written, so, for API compatibility, * we return the number of bytes we were told to write. */ ret = size; #else /* no raw mode */ /* * XXX - this is a pain, because you might have to extract * the address from the packet and use it in a DL_UNITDATA_REQ * request. That would be dependent on the link-layer type. * * I also don't know what SAP you'd have to bind the descriptor * to, or whether you'd need separate "receive" and "send" FDs, * nor do I know whether you'd need different bindings for * D/I/X Ethernet and 802.3, or for {FDDI,Token Ring} plus * 802.2 and {FDDI,Token Ring} plus 802.2 plus SNAP. * * So, for now, we just return a "you can't send" indication, * and leave it up to somebody with a DLPI-based system lacking * both DLIOCRAW and DL_HP_RAWDLS to supply code to implement * packet transmission on that system. If they do, they should * send it to us - but should not send us code that assumes * Ethernet; if the code doesn't work on non-Ethernet interfaces, * it should check "p->linktype" and reject the send request if * it's anything other than DLT_EN10MB. */ strlcpy(p->errbuf, "send: Not supported on this version of this OS", PCAP_ERRBUF_SIZE); ret = -1; #endif /* raw mode */ return (ret); } #ifndef DL_IPATM #define DL_IPATM 0x12 /* ATM Classical IP interface */ #endif #ifdef HAVE_SOLARIS /* * For SunATM. */ #ifndef A_GET_UNITS #define A_GET_UNITS (('A'<<8)|118) #endif /* A_GET_UNITS */ #ifndef A_PROMISCON_REQ #define A_PROMISCON_REQ (('A'<<8)|121) #endif /* A_PROMISCON_REQ */ #endif /* HAVE_SOLARIS */ static void pcap_close_dlpi(pcap_t *p) { pcap_close_common(p); if (p->send_fd >= 0) close(p->send_fd); } pcap_t * pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { register char *cp; register pcap_t *p; int ppa; #ifdef HAVE_SOLARIS int isatm = 0; #endif register dl_info_ack_t *infop; #ifdef HAVE_SYS_BUFMOD_H bpf_u_int32 ss, chunksize; #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) { strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); return (NULL); } memset(p, 0, sizeof(*p)); p->fd = -1; /* indicate that it hasn't been opened yet */ p->send_fd = -1; #ifdef HAVE_DEV_DLPI /* ** Remove any "/dev/" on the front of the device. */ cp = strrchr(device, '/'); if (cp == NULL) strlcpy(dname, device, sizeof(dname)); else strlcpy(dname, cp + 1, sizeof(dname)); /* * Split the device name into a device type name and a unit number; * chop off the unit number, so "dname" is just a device type name. */ cp = split_dname(dname, &ppa, ebuf); if (cp == NULL) goto bad; *cp = '\0'; /* * Use "/dev/dlpi" as the device. * * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that * the "dl_mjr_num" field is for the "major number of interface * driver"; that's the major of "/dev/dlpi" on the system on * which I tried this, but there may be DLPI devices that * use a different driver, in which case we may need to * search "/dev" for the appropriate device with that major * device number, rather than hardwiring "/dev/dlpi". */ cp = "/dev/dlpi"; if ((p->fd = open(cp, O_RDWR)) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", cp, pcap_strerror(errno)); goto bad; } #ifdef DL_HP_RAWDLS /* * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and * receiving packets on the same descriptor - you need separate * descriptors for sending and receiving, bound to different SAPs. * * If the open fails, we just leave -1 in "p->send_fd" and reject * attempts to send packets, just as if, in pcap-bpf.c, we fail * to open the BPF device for reading and writing, we just try * to open it for reading only and, if that succeeds, just let * the send attempts fail. */ p->send_fd = open(cp, O_RDWR); #endif /* * Get a table of all PPAs for that device, and search that * table for the specified device type name and unit number. */ ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf); if (ppa < 0) goto bad; #else /* * If the device name begins with "/", assume it begins with * the pathname of the directory containing the device to open; * otherwise, concatenate the device directory name and the * device name. */ if (*device == '/') strlcpy(dname, device, sizeof(dname)); else snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, device); /* * Get the unit number, and a pointer to the end of the device * type name. */ cp = split_dname(dname, &ppa, ebuf); if (cp == NULL) goto bad; /* * Make a copy of the device pathname, and then remove the unit * number from the device pathname. */ strlcpy(dname2, dname, sizeof(dname)); *cp = '\0'; /* Try device without unit number */ if ((p->fd = open(dname, O_RDWR)) < 0) { if (errno != ENOENT) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, pcap_strerror(errno)); goto bad; } /* Try again with unit number */ if ((p->fd = open(dname2, O_RDWR)) < 0) { if (errno == ENOENT) { /* * We just report "No DLPI device found" * with the device name, so people don't * get confused and think, for example, * that if they can't capture on "lo0" * on Solaris the fix is to change libpcap * (or the application that uses it) to * look for something other than "/dev/lo0", * as the fix is to look for an operating * system other than Solaris - you just * *can't* capture on a loopback interface * on Solaris, the lack of a DLPI device * for the loopback interface is just a * symptom of that inability. */ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: No DLPI device found", device); } else { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%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; #ifdef HAVE_SOLARIS if (infop->dl_mac_type == DL_IPATM) isatm = 1; #endif if (infop->dl_provider_style == DL_STYLE2) { if (dl_doattach(p->fd, ppa, ebuf) < 0) goto bad; #ifdef DL_HP_RAWDLS if (p->send_fd >= 0) { if (dl_doattach(p->send_fd, ppa, ebuf) < 0) goto bad; } #endif } /* ** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally ** skip if using SINIX) */ #if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix) #ifdef _AIX /* ** AIX. ** According to IBM's AIX Support Line, the dl_sap value ** should not be less than 0x600 (1536) for standard Ethernet. ** However, we seem to get DL_BADADDR - "DLSAP addr in improper ** format or invalid" - errors if we use 1537 on the "tr0" ** device, which, given that its name starts with "tr" and that ** it's IBM, probably means a Token Ring device. (Perhaps we ** need to use 1537 on "/dev/dlpi/en" because that device is for ** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and ** it rejects invalid Ethernet types.) ** ** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea ** says that works on Token Ring (he says that 0 does *not* ** work; perhaps that's considered an invalid LLC SAP value - I ** assume the SAP value in a DLPI bind is an LLC SAP for network ** types that use 802.2 LLC). */ if ((dlbindreq(p->fd, 1537, ebuf) < 0 && dlbindreq(p->fd, 2, ebuf) < 0) || dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0) goto bad; #elif defined(DL_HP_RAWDLS) /* ** HP-UX 10.0x and 10.1x. */ if (dl_dohpuxbind(p->fd, ebuf) < 0) goto bad; if (p->send_fd >= 0) { /* ** XXX - if this fails, just close send_fd and ** set it to -1, so that you can't send but can ** still receive? */ if (dl_dohpuxbind(p->send_fd, ebuf) < 0) goto bad; } #else /* neither AIX nor HP-UX */ /* ** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other ** OS using DLPI. **/ if (dlbindreq(p->fd, 0, ebuf) < 0 || dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0) goto bad; #endif /* AIX vs. HP-UX vs. other */ #endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */ #ifdef HAVE_SOLARIS if (isatm) { /* ** Have to turn on some special ATM promiscuous mode ** for SunATM. ** Do *NOT* turn regular promiscuous mode on; it doesn't ** help, and may break things. */ if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "A_PROMISCON_REQ: %s", pcap_strerror(errno)); goto bad; } } else #endif if (promisc) { /* ** Enable promiscuous (not necessary on send FD) */ 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) (Not necessary on send FD) */ #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 promiscuity (when not in promiscuous mode ** when using HP-UX, when not doing SunATM on Solaris, and never ** under SINIX) (Not necessary on send FD) */ #ifndef sinix if ( #ifdef __hpux !promisc && #endif #ifdef HAVE_SOLARIS !isatm && #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 /* sinix */ /* ** HP-UX 9, and HP-UX 10.20 or later, must bind after setting ** promiscuous options. */ #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER) if (dl_dohpuxbind(p->fd, ebuf) < 0) goto bad; /* ** We don't set promiscuous mode on the send FD, but we'll defer ** binding it anyway, just to keep the HP-UX 9/10.20 or later ** code together. */ if (p->send_fd >= 0) { /* ** XXX - if this fails, just close send_fd and ** set it to -1, so that you can't send but can ** still receive? */ if (dl_dohpuxbind(p->send_fd, ebuf) < 0) goto bad; } #endif /* ** Determine link type ** XXX - get SAP length and address length as well, for use ** when sending packets. */ 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; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } break; case DL_FDDI: p->linktype = DLT_FDDI; p->offset = 3; break; case DL_TPR: /* * XXX - what about DL_TPB? Is that Token Bus? */ p->linktype = DLT_IEEE802; p->offset = 2; break; #ifdef HAVE_SOLARIS case DL_IPATM: p->linktype = DLT_SUNATM; p->offset = 0; /* works for LANE and LLC encapsulation */ break; #endif default: snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu", (unsigned long)infop->dl_mac_type); goto bad; } #ifdef DLIOCRAW /* ** This is a non standard SunOS hack to get the full raw link-layer ** header. */ if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s", pcap_strerror(errno)); goto bad; } } /* ** Set the chunk length. */ chunksize = CHUNKSIZE; if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize) != 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSCHUNKP: %s", pcap_strerror(errno)); goto bad; } #endif /* ** As the last operation flush the read side. */ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", pcap_strerror(errno)); goto bad; } /* Allocate data buffer */ p->bufsize = PKTBUFSIZE; p->buffer = (u_char *)malloc(p->bufsize + p->offset); if (p->buffer == NULL) { strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } /* * "p->fd" is an FD for a STREAMS device, so "select()" and * "poll()" should work on it. */ p->selectable_fd = p->fd; p->read_op = pcap_read_dlpi; p->inject_op = pcap_inject_dlpi; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented.*/ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_dlpi; p->close_op = pcap_close_dlpi; return (p); bad: if (p->fd >= 0) close(p->fd); if (p->send_fd >= 0) close(p->send_fd); /* * Get rid of any link-layer type list we allocated. */ if (p->dlt_list != NULL) free(p->dlt_list); free(p); return (NULL); } /* * Split a device name into a device type name and a unit number; * return the a pointer to the beginning of the unit number, which * is the end of the device type name, and set "*unitp" to the unit * number. * * Returns NULL on error, and fills "ebuf" with an error message. */ static char * split_dname(char *device, int *unitp, char *ebuf) { char *cp; char *eos; long unit; /* * Look for a number at the end of the device name string. */ cp = device + strlen(device) - 1; if (*cp < '0' || *cp > '9') { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", device); return (NULL); } /* Digits at end of string are unit number */ while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9') cp--; errno = 0; unit = strtol(cp, &eos, 10); if (*eos != '\0') { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); return (NULL); } if (errno == ERANGE || unit > INT_MAX) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large", device); return (NULL); } if (unit < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative", device); return (NULL); } *unitp = (int)unit; return (cp); } static int dl_doattach(int fd, int ppa, char *ebuf) { bpf_u_int32 buf[MAXDLBUF]; if (dlattachreq(fd, ppa, ebuf) < 0 || dlokack(fd, "attach", (char *)buf, ebuf) < 0) return (-1); return (0); } #ifdef DL_HP_RAWDLS static int dl_dohpuxbind(int fd, char *ebuf) { int hpsap; int uerror; bpf_u_int32 buf[MAXDLBUF]; /* * XXX - we start at 22 because we used to use only 22, but * that was just because that was the value used in some * sample code from HP. With what value *should* we start? * Does it matter, given that we're enabling SAP promiscuity * on the input FD? */ hpsap = 22; for (;;) { if (dlbindreq(fd, hpsap, ebuf) < 0) return (-1); if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0) break; /* * For any error other than a UNIX EBUSY, give up. */ if (uerror != EBUSY) { /* * dlbindack() has already filled in ebuf for * this error. */ return (-1); } /* * For EBUSY, try the next SAP value; that means that * somebody else is using that SAP. Clear ebuf so * that application doesn't report the "Device busy" * error as a warning. */ *ebuf = '\0'; hpsap++; if (hpsap > 100) { strlcpy(ebuf, "All SAPs from 22 through 100 are in use", PCAP_ERRBUF_SIZE); return (-1); } } return (0); } #endif int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { #ifdef HAVE_SOLARIS int fd; union { u_int nunits; char pad[516]; /* XXX - must be at least 513; is 516 in "atmgetunits" */ } buf; char baname[2+1+1]; u_int i; /* * We may have to do special magic to get ATM devices. */ if ((fd = open("/dev/ba", O_RDWR)) < 0) { /* * We couldn't open the "ba" device. * For now, just give up; perhaps we should * return an error if the problem is neither * a "that device doesn't exist" error (ENOENT, * ENXIO, etc.) or a "you're not allowed to do * that" error (EPERM, EACCES). */ return (0); } if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s", pcap_strerror(errno)); return (-1); } for (i = 0; i < buf.nunits; i++) { snprintf(baname, sizeof baname, "ba%u", i); if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0) return (-1); } #endif 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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "send_request: putmsg \"%s\": %s", what, pcap_strerror(errno)); return (-1); } return (0); } static int recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror) { union DL_primitives *dlp; struct strbuf ctl; int flags; /* * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR, * making that the only place where EBUSY is treated specially. */ if (uerror != NULL) *uerror = 0; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; flags = 0; if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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_SYSERR: if (uerror != NULL) *uerror = dlp->error_ack.dl_unix_errno; snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: UNIX error - %s", what, pcap_strerror(dlp->error_ack.dl_unix_errno)); break; default: snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", what, dlstrerror(dlp->error_ack.dl_errno)); break; } return (-1); default: snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Unexpected primitive ack %s", what, dlprim(dlp->dl_primitive)); return (-1); } if (ctl.len < size) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: Ack too small (%d < %d)", what, ctl.len, size); return (-1); } return (ctl.len); } static char * dlstrerror(bpf_u_int32 dl_errno) { static char errstring[6+2+8+1]; switch (dl_errno) { case DL_ACCESS: return ("Improper permissions for request"); case DL_BADADDR: return ("DLSAP addr in improper format or invalid"); case DL_BADCORR: return ("Seq number not from outstand DL_CONN_IND"); case DL_BADDATA: return ("User data exceeded provider limit"); case DL_BADPPA: #ifdef HAVE_DEV_DLPI /* * With a single "/dev/dlpi" device used for all * DLPI providers, PPAs have nothing to do with * unit numbers. */ return ("Specified PPA was invalid"); #else /* * We have separate devices for separate devices; * the PPA is just the unit number. */ return ("Specified PPA (device unit) was invalid"); #endif case DL_BADPRIM: return ("Primitive received not known by provider"); case DL_BADQOSPARAM: return ("QOS parameters contained invalid values"); case DL_BADQOSTYPE: return ("QOS structure type is unknown/unsupported"); case DL_BADSAP: return ("Bad LSAP selector"); case DL_BADTOKEN: return ("Token used not an active stream"); case DL_BOUND: return ("Attempted second bind with dl_max_conind"); case DL_INITFAILED: return ("Physical link initialization failed"); case DL_NOADDR: return ("Provider couldn't allocate alternate address"); case DL_NOTINIT: return ("Physical link not initialized"); case DL_OUTSTATE: return ("Primitive issued in improper state"); case DL_SYSERR: return ("UNIX system error occurred"); case DL_UNSUPPORTED: return ("Requested service not supplied by provider"); case DL_UNDELIVERABLE: return ("Previous data unit could not be delivered"); case DL_NOTSUPPORTED: return ("Primitive is known but not supported"); case DL_TOOMANY: return ("Limit exceeded"); case DL_NOTENAB: return ("Promiscuous mode not enabled"); case DL_BUSY: return ("Other streams for PPA in post-attached"); case DL_NOAUTO: return ("Automatic handling XID&TEST not supported"); case DL_NOXIDAUTO: return ("Automatic handling of XID not supported"); case DL_NOTESTAUTO: return ("Automatic handling of TEST not supported"); case DL_XIDAUTO: return ("Automatic handling of XID response"); case DL_TESTAUTO: return ("Automatic handling of TEST response"); case DL_PENDING: return ("Pending outstanding connect indications"); default: sprintf(errstring, "Error %02x", dl_errno); return (errstring); } } static char * dlprim(bpf_u_int32 prim) { static char primbuf[80]; switch (prim) { case DL_INFO_REQ: return ("DL_INFO_REQ"); case DL_INFO_ACK: return ("DL_INFO_ACK"); case DL_ATTACH_REQ: return ("DL_ATTACH_REQ"); case DL_DETACH_REQ: return ("DL_DETACH_REQ"); case DL_BIND_REQ: return ("DL_BIND_REQ"); case DL_BIND_ACK: return ("DL_BIND_ACK"); case DL_UNBIND_REQ: return ("DL_UNBIND_REQ"); case DL_OK_ACK: return ("DL_OK_ACK"); case DL_ERROR_ACK: return ("DL_ERROR_ACK"); case DL_SUBS_BIND_REQ: return ("DL_SUBS_BIND_REQ"); case DL_SUBS_BIND_ACK: return ("DL_SUBS_BIND_ACK"); case DL_UNITDATA_REQ: return ("DL_UNITDATA_REQ"); case DL_UNITDATA_IND: return ("DL_UNITDATA_IND"); case DL_UDERROR_IND: return ("DL_UDERROR_IND"); case DL_UDQOS_REQ: return ("DL_UDQOS_REQ"); case DL_CONNECT_REQ: return ("DL_CONNECT_REQ"); case DL_CONNECT_IND: return ("DL_CONNECT_IND"); case DL_CONNECT_RES: return ("DL_CONNECT_RES"); case DL_CONNECT_CON: return ("DL_CONNECT_CON"); case DL_TOKEN_REQ: return ("DL_TOKEN_REQ"); case DL_TOKEN_ACK: return ("DL_TOKEN_ACK"); case DL_DISCONNECT_REQ: return ("DL_DISCONNECT_REQ"); case DL_DISCONNECT_IND: return ("DL_DISCONNECT_IND"); case DL_RESET_REQ: return ("DL_RESET_REQ"); case DL_RESET_IND: return ("DL_RESET_IND"); case DL_RESET_RES: return ("DL_RESET_RES"); case DL_RESET_CON: return ("DL_RESET_CON"); default: (void) sprintf(primbuf, "unknown primitive 0x%x", prim); return (primbuf); } } 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; /* XXX - what if neither of these are defined? */ #if defined(DL_HP_RAWDLS) req.dl_max_conind = 1; /* XXX magic number */ req.dl_service_mode = DL_HP_RAWDLS; #elif defined(DL_CLDLS) req.dl_service_mode = DL_CLDLS; #endif req.dl_sap = sap; return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); } static int dlbindack(int fd, char *bufp, char *ebuf, int *uerror) { return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror)); } 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, NULL)); } 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, NULL)); } #ifdef DL_HP_RAWDLS /* * There's an ack *if* there's an error. */ static int dlrawdatareq(int fd, const u_char *datap, int datalen) { struct strbuf ctl, data; long buf[MAXDLBUF]; /* XXX - char? */ union DL_primitives *dlp; int dlen; dlp = (union DL_primitives*) buf; dlp->dl_primitive = DL_HP_RAWDATA_REQ; dlen = DL_HP_RAWDATA_REQ_SIZE; /* * HP's documentation doesn't appear to show us supplying any * address pointed to by the control part of the message. * I think that's what raw mode means - you just send the raw * packet, you don't specify where to send it to, as that's * implied by the destination address. */ ctl.maxlen = 0; ctl.len = dlen; ctl.buf = (void *)buf; data.maxlen = 0; data.len = datalen; data.buf = (void *)datap; return (putmsg(fd, &ctl, &data, 0)); } #endif /* DL_HP_RAWDLS */ #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((unsigned char)*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_REQ /* * Under HP-UX 10 and HP-UX 11, we can ask for the ppa */ /* * Determine ppa number that specifies ifname. * * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member, * the code that's used here is the old code for HP-UX 10.x. * * However, HP-UX 10.20, at least, appears to have such a member * in its "dl_hp_ppa_info_t" structure, so the new code is used. * The new code didn't work on an old 10.20 system on which Rick * Jones of HP tried it, but with later patches installed, it * worked - it appears that the older system had those members but * didn't put anything in them, so, if the search by name fails, we * do the old search. * * Rick suggests that making sure your system is "up on the latest * lancommon/DLPI/driver patches" is probably a good idea; it'd fix * that problem, as well as allowing libpcap to see packets sent * from the system on which the libpcap application is being run. * (On 10.20, in addition to getting the latest patches, you need * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB; * a posting to "comp.sys.hp.hpux" at * * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266 * * says that, to see the machine's outgoing traffic, you'd need to * apply the right patches to your system, and also set that variable * with: echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem * which could be put in, for example, "/sbin/init.d/lan". * * Setting the variable is not necessary on HP-UX 11.x. */ 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 *ipstart, *ip; register int i; char dname[100]; register u_long majdev; struct stat statbuf; dl_hp_ppa_req_t req; char buf[MAXDLBUF]; char *ppa_data_buf; dl_hp_ppa_ack_t *dlp; struct strbuf ctl; int flags; int ppa; 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) return (-1); ctl.maxlen = DL_HP_PPA_ACK_SIZE; ctl.len = 0; ctl.buf = (char *)buf; flags = 0; /* * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal * recv_ack will fail because it set the maxlen to MAXDLBUF (8192) * which is NOT big enough for a DL_HP_PPA_REQ. * * This causes libpcap applications to fail on a system with HP-APA * installed. * * To figure out how big the returned data is, we first call getmsg * to get the small head and peek at the head to get the actual data * length, and then issue another getmsg to get the actual PPA data. */ /* get the head first */ if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); return (-1); } dlp = (dl_hp_ppa_ack_t *)ctl.buf; if (dlp->dl_primitive != DL_HP_PPA_ACK) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", (bpf_u_int32)dlp->dl_primitive); return (-1); } if (ctl.len < DL_HP_PPA_ACK_SIZE) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %lu)", ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE); return (-1); } /* allocate buffer */ if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno)); return (-1); } ctl.maxlen = dlp->dl_length; ctl.len = 0; ctl.buf = (char *)ppa_data_buf; /* get the data */ if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); free(ppa_data_buf); return (-1); } if (ctl.len < dlp->dl_length) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %d)", ctl.len, dlp->dl_length); free(ppa_data_buf); return (-1); } ap = (dl_hp_ppa_ack_t *)buf; ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; ip = ipstart; #ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 /* * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1" * member that should, in theory, contain the part of the * name for the device that comes before the unit number, * and should also have a "dl_module_id_2" member that may * contain an alternate name (e.g., I think Ethernet devices * have both "lan", for "lanN", and "snap", for "snapN", with * the former being for Ethernet packets and the latter being * for 802.3/802.2 packets). * * Search for the device that has the specified name and * instance number. */ for (i = 0; i < ap->dl_count; i++) { if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 || strcmp((const char *)ip->dl_module_id_2, device) == 0) && ip->dl_instance_num == unit) break; ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); } #else /* * We don't have that member, so the search is impossible; make it * look as if the search failed. */ i = ap->dl_count; #endif if (i == ap->dl_count) { /* * Well, we didn't, or can't, find the device by name. * * HP-UX 10.20, whilst it has "dl_module_id_1" and * "dl_module_id_2" fields in the "dl_hp_ppa_info_t", * doesn't seem to fill them in unless the system is * at a reasonably up-to-date patch level. * * Older HP-UX 10.x systems might not have those fields * at all. * * Therefore, we'll search for the entry with the major * device number of a device with the name "/dev/", * if such a device exists, as the old code did. */ snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); if (stat(dname, &statbuf) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", dname, pcap_strerror(errno)); return (-1); } majdev = major(statbuf.st_rdev); ip = ipstart; 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 *)ipstart + ip->dl_next_offset); } } if (i == ap->dl_count) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "can't find /dev/dlpi PPA for %s%d", device, unit); return (-1); } if (ip->dl_hdw_state == HDW_DEAD) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s%d: hardware state: DOWN\n", device, unit); free(ppa_data_buf); return (-1); } ppa = ip->dl_ppa; free(ppa_data_buf); return (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) + 1]; cp = strrchr(ifname, '/'); if (cp != NULL) ifname = cp + 1; if (nlist(path_vmunix, &nl) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", path_vmunix); return (-1); } if (nl[NL_IFNET].n_value == 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "could't find %s kernel symbol", nl[NL_IFNET].n_name); return (-1); } kd = open("/dev/kmem", O_RDONLY); if (kd < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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(ifnet.if_name), ebuf) < 0) { (void)close(kd); return (-1); } if_name[sizeof(ifnet.if_name)] = '\0'; if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) return (ifnet.if_index); } snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", pcap_strerror(errno)); return (-1); } cc = read(fd, buf, len); if (cc < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", pcap_strerror(errno)); return (-1); } else if (cc != len) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, len); return (-1); } return (cc); } #endif libpcap-0.9.7/./README.Win320000644000026300017500000000424607524744700013220 0ustar mcrmcrUnder Win32, libpcap is integrated in the WinPcap packet capture system. WinPcap provides a framework that allows libpcap to capture the packets under Windows 95, Windows 98, Windows ME, Windows NT 4, Windows 2000 and Windows XP. WinPcap binaries and source code can be found at http://winpcap.polito.it: they include also a developer's pack with all the necessary to compile libpcap-based applications under Windows. How to compile libpcap with Visual Studio ----------------------------------------- In order to compile libpcap you will need: - version 6 (or higher) of Microsoft Visual Studio - The November 2001 (or later) edition of Microsoft Platform Software Development Kit (SDK), that contains some necessary includes for IPv6 support. You can download it from http://www.microsoft.com/sdk - the latest WinPcap sources from http://winpcap.polito.it/install The WinPcap source code already contains a recent (usually the latest stable) version of libpcap. If you need to compile a different one, simply download it from www.tcpdump.org and copy the sources in the winpcap\wpcap\libpcap folder of the WinPcap distribution. If you want to compile a libpcap source retrieved from the tcpdump.org CVS, you will have to create the scanner and the grammar by hand (with lex and yacc) or with the cygnus makefile, since The Visual Studio project is not able to build them. Open the project file winpcap\wpcap\prj\wpcap.dsw with Visual Studio and build wpcap.dll. wpcap.lib, the library file to link with the applications, will be generated in winpcap\wpcap\lib\. wpcap.dll will be generated in winpcap\wpcap\prj\release or winpcap\wpcap\prj\debug depending on the type of binary that is being created. How to compile libpcap with Cygnus ---------------------------------- To build wpcap.dll, cd to the directory WPCAP/PRJ of the WinPcap source code distribution and type "make". libwpcap.a, the library file to link with the applications, will be generated in winpcap\wpcap\lib\. wpcap.dll will be generated in winpcap\wpcap\prj. Remember, you CANNOT use the MSVC-generated .lib files with gcc, use libwpcap.a instead. "make install" installs wpcap.dll in the Windows system folder. libpcap-0.9.7/./libpcap-0.90000777000026300017500000000000010651262452015335 2../libpcap-0.9ustar mcrmcrlibpcap-0.9.7/./README.linux0000644000026300017500000000724007331052452013442 0ustar mcrmcrIn order for libpcap to be able to capture packets on a Linux system, the "packet" protocol must be supported by your kernel. If it is not, you may get error messages such as modprobe: can't locate module net-pf-17 in "/var/adm/messages", or may get messages such as socket: Address family not supported by protocol from applications using libpcap. You must configure the kernel with the CONFIG_PACKET option for this protocol; the following note is from the Linux "Configure.help" file for the 2.0[.x] kernel: Packet socket CONFIG_PACKET The Packet protocol is used by applications which communicate directly with network devices without an intermediate network protocol implemented in the kernel, e.g. tcpdump. If you want them to work, choose Y. This driver is also available as a module called af_packet.o ( = code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt; if you use modprobe or kmod, you may also want to add "alias net-pf-17 af_packet" to /etc/modules.conf. and the note for the 2.2[.x] kernel says: Packet socket CONFIG_PACKET The Packet protocol is used by applications which communicate directly with network devices without an intermediate network protocol implemented in the kernel, e.g. tcpdump. If you want them to work, choose Y. This driver is also available as a module called af_packet.o ( = code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. You will need to add 'alias net-pf-17 af_packet' to your /etc/conf.modules file for the module version to function automatically. If unsure, say Y. In addition, there is an option that, in 2.2 and later kernels, will allow packet capture filters specified to programs such as tcpdump to be executed in the kernel, so that packets that don't pass the filter won't be copied from the kernel to the program, rather than having all packets copied to the program and libpcap doing the filtering in user mode. Copying packets from the kernel to the program consumes a significant amount of CPU, so filtering in the kernel can reduce the overhead of capturing packets if a filter has been specified that discards a significant number of packets. (If no filter is specified, it makes no difference whether the filtering isn't performed in the kernel or isn't performed in user mode. :-)) The option for this is the CONFIG_FILTER option; the "Configure.help" file says: Socket filtering CONFIG_FILTER The Linux Socket Filter is derived from the Berkeley Packet Filter. If you say Y here, user-space programs can attach a filter to any socket and thereby tell the kernel that it should allow or disallow certain types of data to get through the socket. Linux Socket Filtering works on all socket types except TCP for now. See the text file linux/Documentation/networking/filter.txt for more information. If unsure, say N. Statistics: Statistics reported by pcap are platform specific. The statistics reported by pcap_stats on Linux are as follows: 2.2.x ===== ps_recv Number of packets that were accepted by the pcap filter ps_drops Always 0, this statistic is not gatherd on this platform 2.4.x ===== ps_rec Number of packets that were accepted by the pcap filter ps_drops Number of packets that had passed filtering but were not passed on to pcap due to things like buffer shortage, etc. This is useful because these are packets you are interested in but won't be reported by, for example, tcpdump output. libpcap-0.9.7/./fad-win32.c0000644000026300017500000001766310504042140013261 0ustar mcrmcr/* * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) * Copyright (c) 2005 - 2006 CACE Technologies, Davis (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. Neither the name of the Politecnico di Torino, CACE Technologies * nor the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.11.2.3 2006/02/22 17:09:32 gianluca Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include /* * Add an entry to the list of addresses for an interface. * "curdev" is the entry for that interface. */ static int add_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr, struct sockaddr *netmask, struct sockaddr *broadaddr, struct sockaddr *dstaddr, char *errbuf) { pcap_addr_t *curaddr, *prevaddr, *nextaddr; /* * Allocate the new entry and fill it in. */ curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t)); if (curaddr == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (-1); } curaddr->next = NULL; if (addr != NULL) { curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, sizeof(struct sockaddr_storage)); if (curaddr->addr == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); free(curaddr); return (-1); } } else curaddr->addr = NULL; if (netmask != NULL) { curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, sizeof(struct sockaddr_storage)); if (curaddr->netmask == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); free(curaddr); return (-1); } } else curaddr->netmask = NULL; if (broadaddr != NULL) { curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, sizeof(struct sockaddr_storage)); if (curaddr->broadaddr == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); free(curaddr); return (-1); } } else curaddr->broadaddr = NULL; if (dstaddr != NULL) { curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, sizeof(struct sockaddr_storage)); if (curaddr->dstaddr == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); free(curaddr); return (-1); } } else curaddr->dstaddr = NULL; /* * Find the end of the list of addresses. */ for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { nextaddr = prevaddr->next; if (nextaddr == NULL) { /* * This is the end of the list. */ break; } } if (prevaddr == NULL) { /* * The list was empty; this is the first member. */ curdev->addresses = curaddr; } else { /* * "prevaddr" is the last member of the list; append * this member to it. */ prevaddr->next = curaddr; } return (0); } static int pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc, char *errbuf) { pcap_if_t *curdev; npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; LONG if_addr_size; int res = 0; if_addr_size = MAX_NETWORK_ADDRESSES; /* * Add an entry for this interface, with no addresses. */ if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) { /* * Failure. */ return (-1); } /* * Get the list of addresses for the interface. */ if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) { /* * Failure. * * We don't return an error, because this can happen with * NdisWan interfaces, and we want to supply them even * if we can't supply their addresses. * * We return an entry with an empty address list. */ return (0); } /* * Now add the addresses. */ while (if_addr_size-- > 0) { /* * "curdev" is an entry for this interface; add an entry for * this address to its list of addresses. */ if(curdev == NULL) break; res = add_addr_to_list(curdev, (struct sockaddr *)&if_addrs[if_addr_size].IPAddress, (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask, (struct sockaddr *)&if_addrs[if_addr_size].Broadcast, NULL, errbuf); if (res == -1) { /* * Failure. */ break; } } return (res); } /* * Get a list of all interfaces that are up and that we can open. * Returns -1 on error, 0 otherwise. * The list, as returned through "alldevsp", may be null if no interfaces * were up and could be opened. * * Win32 implementation, based on WinPcap */ int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; int ret = 0; const char *desc; char *AdaptersName; ULONG NameLength; char *name; if (!PacketGetAdapterNames(NULL, &NameLength)) { DWORD last_error = GetLastError(); if (last_error != ERROR_INSUFFICIENT_BUFFER) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s", pcap_win32strerror()); return (-1); } } if (NameLength > 0) AdaptersName = (char*) malloc(NameLength); else { *alldevsp = NULL; return 0; } if (AdaptersName == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); return (-1); } if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s", pcap_win32strerror()); free(AdaptersName); return (-1); } /* * "PacketGetAdapterNames()" returned a list of * null-terminated ASCII interface name strings, * terminated by a null string, followed by a list * of null-terminated ASCII interface description * strings, terminated by a null string. * This means there are two ASCII nulls at the end * of the first list. * * Find the end of the first list; that's the * beginning of the second list. */ desc = &AdaptersName[0]; while (*desc != '\0' || *(desc + 1) != '\0') desc++; /* * Found it - "desc" points to the first of the two * nulls at the end of the list of names, so the * first byte of the list of descriptions is two bytes * after it. */ desc += 2; /* * Loop over the elements in the first list. */ name = &AdaptersName[0]; while (*name != '\0') { /* * Add an entry for this interface. */ if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) { /* * Failure. */ ret = -1; break; } name += strlen(name) + 1; desc += strlen(desc) + 1; } if (ret == -1) { /* * We had an error; free the list we've been constructing. */ if (devlist != NULL) { pcap_freealldevs(devlist); devlist = NULL; } } *alldevsp = devlist; free(AdaptersName); return (ret); } libpcap-0.9.7/./pcap-dos.c0000644000026300017500000010441110235744353013301 0ustar mcrmcr/* * This file is part of DOS-libpcap * Ported to DOS/DOSX by G. Vanem * * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode * network drivers. * * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1.2.1 2005/05/03 18:54:35 guy Exp $ (LBL) */ #include #include #include #include #include #include #include #if defined(USE_32BIT_DRIVERS) #include "msdos/pm_drvr/pmdrvr.h" #include "msdos/pm_drvr/pci.h" #include "msdos/pm_drvr/bios32.h" #include "msdos/pm_drvr/module.h" #include "msdos/pm_drvr/3c501.h" #include "msdos/pm_drvr/3c503.h" #include "msdos/pm_drvr/3c509.h" #include "msdos/pm_drvr/3c59x.h" #include "msdos/pm_drvr/3c515.h" #include "msdos/pm_drvr/3c90x.h" #include "msdos/pm_drvr/3c575_cb.h" #include "msdos/pm_drvr/ne.h" #include "msdos/pm_drvr/wd.h" #include "msdos/pm_drvr/accton.h" #include "msdos/pm_drvr/cs89x0.h" #include "msdos/pm_drvr/rtl8139.h" #include "msdos/pm_drvr/ne2k-pci.h" #endif #include "pcap.h" #include "pcap-dos.h" #include "pcap-int.h" #include "msdos/pktdrvr.h" #ifdef USE_NDIS2 #include "msdos/ndis2.h" #endif #include #include #include #include #include #include #if defined(USE_32BIT_DRIVERS) #define FLUSHK() do { _printk_safe = 1; _printk_flush(); } while (0) #define NDIS_NEXT_DEV &rtl8139_dev static char *rx_pool = NULL; static void init_32bit (void); static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool); static int pktq_check (struct rx_ringbuf *q); static int pktq_inc_out (struct rx_ringbuf *q); static int pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC; static void pktq_clear (struct rx_ringbuf *q) LOCKED_FUNC; static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) LOCKED_FUNC; static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q); #else #define FLUSHK() ((void)0) #define NDIS_NEXT_DEV NULL #endif /* * Internal variables/functions in Watt-32 */ extern WORD _pktdevclass; extern BOOL _eth_is_init; extern int _w32_dynamic_host; extern int _watt_do_exit; extern int _watt_is_init; extern int _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req; extern void (*_w32_usr_post_init) (void); extern void (*_w32_print_hook)(); extern void dbug_write (const char *); /* Watt-32 lib, pcdbug.c */ extern int pkt_get_mtu (void); static int ref_count = 0; static u_long mac_count = 0; static u_long filter_count = 0; static volatile BOOL exc_occured = 0; static struct device *handle_to_device [20]; static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data); static void pcap_close_dos (pcap_t *p); static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps); static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len); static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp); static int ndis_probe (struct device *dev); static int pkt_probe (struct device *dev); static void close_driver (void); static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf); static int first_init (const char *name, char *ebuf, int promisc); static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap, const u_char *buf); /* * These are the device we always support */ static struct device ndis_dev = { "ndis", "NDIS2 LanManager", 0, 0,0,0,0,0,0, NDIS_NEXT_DEV, /* NULL or a 32-bit device */ ndis_probe }; static struct device pkt_dev = { "pkt", "Packet-Driver", 0, 0,0,0,0,0,0, &ndis_dev, pkt_probe }; static struct device *get_device (int fd) { if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0])) return (NULL); return handle_to_device [fd-1]; } /* * Open MAC-driver with name 'device_name' for live capture of * network packets. */ pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc, int timeout_ms, char *errbuf) { struct pcap *pcap; if (snaplen < ETH_MIN) snaplen = ETH_MIN; if (snaplen > ETH_MAX) /* silently accept and truncate large MTUs */ snaplen = ETH_MAX; pcap = calloc (sizeof(*pcap), 1); if (!pcap) { strcpy (errbuf, "Not enough memory (pcap)"); return (NULL); } pcap->snapshot = max (ETH_MIN+8, snaplen); pcap->linktype = DLT_EN10MB; /* !! */ pcap->inter_packet_wait = timeout_ms; pcap->close_op = pcap_close_dos; pcap->read_op = pcap_read_dos; pcap->stats_op = pcap_stats_dos; pcap->inject_op = pcap_sendpacket_dos; pcap->setfilter_op = pcap_setfilter_dos; pcap->setdirection_op = NULL; /* Not implemented.*/ pcap->fd = ++ref_count; if (pcap->fd == 1) /* first time we're called */ { if (!init_watt32(pcap, device_name, errbuf) || !first_init(device_name, errbuf, promisc)) { free (pcap); return (NULL); } atexit (close_driver); } else if (stricmp(active_dev->name,device_name)) { snprintf (errbuf, PCAP_ERRBUF_SIZE, "Cannot use different devices simultaneously " "(`%s' vs. `%s')", active_dev->name, device_name); free (pcap); pcap = NULL; } handle_to_device [pcap->fd-1] = active_dev; return (pcap); } /* * Poll the receiver queue and call the pcap callback-handler * with the packet. */ static int pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) { struct pcap_pkthdr pcap; struct bpf_insn *fcode = p->fcode.bf_insns; struct timeval now, expiry; BYTE *rx_buf; int rx_len = 0; if (p->inter_packet_wait > 0) { gettimeofday2 (&now, NULL); expiry.tv_usec = now.tv_usec + 1000UL * p->inter_packet_wait; expiry.tv_sec = now.tv_sec; while (expiry.tv_usec >= 1000000L) { expiry.tv_usec -= 1000000L; expiry.tv_sec++; } } while (!exc_occured) { volatile struct device *dev; /* might be reset by sig_handler */ dev = get_device (p->fd); if (!dev) break; PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf); FLUSHK(); /* If driver has a zero-copy receive facility, peek at the queue, * filter it, do the callback and release the buffer. */ if (dev->peek_rx_buf) { PCAP_ASSERT (dev->release_rx_buf); rx_len = (*dev->peek_rx_buf) (&rx_buf); } else { BYTE buf [ETH_MAX+100]; /* add some margin */ rx_len = (*dev->copy_rx_buf) (buf, p->snapshot); rx_buf = buf; } if (rx_len > 0) /* got a packet */ { mac_count++; FLUSHK(); pcap.caplen = min (rx_len, p->snapshot); pcap.len = rx_len; if (callback && (!fcode || bpf_filter(fcode, rx_buf, pcap.len, pcap.caplen))) { filter_count++; /* Fix-me!! Should be time of arrival. Not time of * capture. */ gettimeofday2 (&pcap.ts, NULL); (*callback) (data, &pcap, rx_buf); } if (dev->release_rx_buf) (*dev->release_rx_buf) (rx_buf); if (pcap_pkt_debug > 0) { if (callback == watt32_recv_hook) dbug_write ("pcap_recv_hook\n"); else dbug_write ("pcap_read_op\n"); } FLUSHK(); return (1); } /* If not to wait for a packet or pcap_close() called from * e.g. SIGINT handler, exit loop now. */ if (p->inter_packet_wait <= 0 || (volatile int)p->fd <= 0) break; gettimeofday2 (&now, NULL); if (timercmp(&now, &expiry, >)) break; #ifndef DJGPP kbhit(); /* a real CPU hog */ #endif if (p->wait_proc) (*p->wait_proc)(); /* call yield func */ } if (rx_len < 0) /* receive error */ { p->md.stat.ps_drop++; #ifdef USE_32BIT_DRIVERS if (pcap_pkt_debug > 1) printk ("pkt-err %s\n", pktInfo.error); #endif return (-1); } return (0); } static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data) { int rc, num = 0; while (num <= cnt || (cnt < 0)) { if (p->fd <= 0) return (-1); rc = pcap_read_one (p, callback, data); if (rc > 0) num++; if (rc < 0) break; _w32_os_yield(); /* allow SIGINT generation, yield to Win95/NT */ } return (num); } /* * Return network statistics */ static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps) { struct net_device_stats *stats; struct device *dev = p ? get_device(p->fd) : NULL; if (!dev) { strcpy (p->errbuf, "illegal pcap handle"); return (-1); } if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL) { strcpy (p->errbuf, "device statistics not available"); return (-1); } FLUSHK(); p->md.stat.ps_recv = stats->rx_packets; p->md.stat.ps_drop += stats->rx_missed_errors; p->md.stat.ps_ifdrop = stats->rx_dropped + /* queue full */ stats->rx_errors; /* HW errors */ if (ps) *ps = p->md.stat; return (0); } /* * Return detailed network/device statistics. * May be called after 'dev->close' is called. */ int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se) { struct device *dev = p ? get_device (p->fd) : NULL; if (!dev || !dev->get_stats) { strlcpy (p->errbuf, "detailed device statistics not available", PCAP_ERRBUF_SIZE); return (-1); } if (!strnicmp(dev->name,"pkt",3)) { strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics", PCAP_ERRBUF_SIZE); return (-1); } memcpy (se, (*dev->get_stats)(dev), sizeof(*se)); return (0); } /* * Simply store the filter-code for the pcap_read_dos() callback * Some day the filter-code could be handed down to the active * device (pkt_rx1.s or 32-bit device interrupt handler). */ static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp) { if (!p) return (-1); p->fcode = *fp; return (0); } /* * Return # of packets received in pcap_read_dos() */ u_long pcap_mac_packets (void) { return (mac_count); } /* * Return # of packets passed through filter in pcap_read_dos() */ u_long pcap_filter_packets (void) { return (filter_count); } /* * Close pcap device. Not called for offline captures. */ static void pcap_close_dos (pcap_t *p) { if (p && !exc_occured) { if (pcap_stats(p,NULL) < 0) p->md.stat.ps_drop = 0; if (!get_device(p->fd)) return; handle_to_device [p->fd-1] = NULL; p->fd = 0; if (ref_count > 0) ref_count--; if (ref_count > 0) return; } close_driver(); } /* * Return the name of the 1st network interface, * or NULL if none can be found. */ char *pcap_lookupdev (char *ebuf) { struct device *dev; #ifdef USE_32BIT_DRIVERS init_32bit(); #endif for (dev = (struct device*)dev_base; dev; dev = dev->next) { PCAP_ASSERT (dev->probe); if ((*dev->probe)(dev)) { FLUSHK(); probed_dev = (struct device*) dev; /* remember last probed device */ return (char*) dev->name; } } if (ebuf) strcpy (ebuf, "No driver found"); return (NULL); } /* * Gets localnet & netmask from Watt-32. */ int pcap_lookupnet (const char *device, bpf_u_int32 *localnet, bpf_u_int32 *netmask, char *errbuf) { if (!_watt_is_init) { strcpy (errbuf, "pcap_open_offline() or pcap_open_live() must be " "called first"); return (-1); } *netmask = _w32_sin_mask; *localnet = my_ip_addr & *netmask; if (*localnet == 0) { if (IN_CLASSA(*netmask)) *localnet = IN_CLASSA_NET; else if (IN_CLASSB(*netmask)) *localnet = IN_CLASSB_NET; else if (IN_CLASSC(*netmask)) *localnet = IN_CLASSC_NET; else { sprintf (errbuf, "inet class for 0x%lx unknown", *netmask); return (-1); } } ARGSUSED (device); return (0); } /* * Get a list of all interfaces that are present and that we probe okay. * Returns -1 on error, 0 otherwise. * The list, as returned through "alldevsp", may be null if no interfaces * were up and could be opened. */ int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf) { struct device *dev; struct sockaddr_ll sa_ll_1, sa_ll_2; struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; pcap_if_t *devlist = NULL; int ret = 0; size_t addr_size = sizeof(struct sockaddr_ll); for (dev = (struct device*)dev_base; dev; dev = dev->next) { PCAP_ASSERT (dev->probe); if (!(*dev->probe)(dev)) continue; PCAP_ASSERT (dev->close); /* set by probe routine */ FLUSHK(); (*dev->close) (dev); memset (&sa_ll_1, 0, sizeof(sa_ll_1)); memset (&sa_ll_2, 0, sizeof(sa_ll_2)); sa_ll_1.sll_family = AF_PACKET; sa_ll_2.sll_family = AF_PACKET; addr = (struct sockaddr*) &sa_ll_1; netmask = (struct sockaddr*) &sa_ll_1; dstaddr = (struct sockaddr*) &sa_ll_1; broadaddr = (struct sockaddr*) &sa_ll_2; memset (&sa_ll_2.sll_addr, 0xFF, sizeof(sa_ll_2.sll_addr)); if (pcap_add_if(&devlist, dev->name, dev->flags, dev->long_name, errbuf) < 0) { ret = -1; break; } if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size, netmask, addr_size, broadaddr, addr_size, dstaddr, addr_size, errbuf) < 0) { ret = -1; break; } } if (devlist && ret < 0) { pcap_freealldevs (devlist); devlist = NULL; } else if (!devlist) strcpy (errbuf, "No drivers found"); *alldevsp = devlist; return (ret); } /* * pcap_assert() is mainly used for debugging */ void pcap_assert (const char *what, const char *file, unsigned line) { FLUSHK(); fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n", file, line, what); close_driver(); _exit (-1); } /* * For pcap_offline_read(): wait and yield between printing packets * to simulate the pace packets where actually recorded. */ void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait) { if (p) { p->wait_proc = yield; p->inter_packet_wait = wait; } } /* * Initialise a named network device. */ static struct device * open_driver (const char *dev_name, char *ebuf, int promisc) { struct device *dev; for (dev = (struct device*)dev_base; dev; dev = dev->next) { PCAP_ASSERT (dev->name); if (strcmp (dev_name,dev->name)) continue; if (!probed_dev) /* user didn't call pcap_lookupdev() first */ { PCAP_ASSERT (dev->probe); if (!(*dev->probe)(dev)) /* call the xx_probe() function */ { sprintf (ebuf, "failed to detect device `%s'", dev_name); return (NULL); } probed_dev = dev; /* device is probed okay and may be used */ } else if (dev != probed_dev) { goto not_probed; } FLUSHK(); /* Select what traffic to receive */ if (promisc) dev->flags |= (IFF_ALLMULTI | IFF_PROMISC); else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC); PCAP_ASSERT (dev->open); if (!(*dev->open)(dev)) { sprintf (ebuf, "failed to activate device `%s'", dev_name); if (pktInfo.error && !strncmp(dev->name,"pkt",3)) { strcat (ebuf, ": "); strcat (ebuf, pktInfo.error); } return (NULL); } /* Some devices need this to operate in promiscous mode */ if (promisc && dev->set_multicast_list) (*dev->set_multicast_list) (dev); active_dev = dev; /* remember our active device */ break; } /* 'dev_name' not matched in 'dev_base' list. */ if (!dev) { sprintf (ebuf, "device `%s' not supported", dev_name); return (NULL); } not_probed: if (!probed_dev) { sprintf (ebuf, "device `%s' not probed", dev_name); return (NULL); } return (dev); } /* * Deinitialise MAC driver. * Set receive mode back to default mode. */ static void close_driver (void) { /* !!todo: loop over all 'handle_to_device[]' ? */ struct device *dev = active_dev; if (dev && dev->close) { (*dev->close) (dev); FLUSHK(); } active_dev = NULL; #ifdef USE_32BIT_DRIVERS if (rx_pool) { k_free (rx_pool); rx_pool = NULL; } if (dev) pcibios_exit(); #endif } #ifdef __DJGPP__ static void setup_signals (void (*handler)(int)) { signal (SIGSEGV,handler); signal (SIGILL, handler); signal (SIGFPE, handler); } static void exc_handler (int sig) { #ifdef USE_32BIT_DRIVERS if (active_dev->irq > 0) /* excludes IRQ 0 */ { disable_irq (active_dev->irq); irq_eoi_cmd (active_dev->irq); _printk_safe = 1; } #endif switch (sig) { case SIGSEGV: fputs ("Catching SIGSEGV.\n", stderr); break; case SIGILL: fputs ("Catching SIGILL.\n", stderr); break; case SIGFPE: _fpreset(); fputs ("Catching SIGFPE.\n", stderr); break; default: fprintf (stderr, "Catching signal %d.\n", sig); } exc_occured = 1; pcap_close_dos (NULL); } #endif /* __DJGPP__ */ /* * Open the pcap device for the first client calling pcap_open_live() */ static int first_init (const char *name, char *ebuf, int promisc) { struct device *dev; #ifdef USE_32BIT_DRIVERS rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE); if (!rx_pool) { strcpy (ebuf, "Not enough memory (Rx pool)"); return (0); } #endif #ifdef __DJGPP__ setup_signals (exc_handler); #endif #ifdef USE_32BIT_DRIVERS init_32bit(); #endif dev = open_driver (name, ebuf, promisc); if (!dev) { #ifdef USE_32BIT_DRIVERS k_free (rx_pool); rx_pool = NULL; #endif #ifdef __DJGPP__ setup_signals (SIG_DFL); #endif return (0); } #ifdef USE_32BIT_DRIVERS /* * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf' * set in it's probe handler), initialise near-memory ring-buffer for * the 32-bit device. */ if (dev->copy_rx_buf == NULL) { dev->get_rx_buf = get_rxbuf; dev->peek_rx_buf = peek_rxbuf; dev->release_rx_buf = release_rxbuf; pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool); } #endif return (1); } #ifdef USE_32BIT_DRIVERS static void init_32bit (void) { static int init_pci = 0; if (!_printk_file) _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */ if (!init_pci) (void)pci_init(); /* init BIOS32+PCI interface */ init_pci = 1; } #endif /* * Hook functions for using Watt-32 together with pcap */ static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */ static WORD etype; static pcap_t pcap_save; static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap, const u_char *buf) { /* Fix me: assumes Ethernet II only */ struct ether_header *ep = (struct ether_header*) buf; memcpy (rxbuf, buf, pcap->caplen); etype = ep->ether_type; ARGSUSED (dummy); } #if (WATTCP_VER >= 0x0224) /* * This function is used by Watt-32 to poll for a packet. * i.e. it's set to bypass _eth_arrived() */ static void *pcap_recv_hook (WORD *type) { int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL); if (len < 0) return (NULL); *type = etype; return (void*) &rxbuf; } /* * This function is called by Watt-32 (via _eth_xmit_hook). * If dbug_init() was called, we should trace packets sent. */ static int pcap_xmit_hook (const void *buf, unsigned len) { int rc = 0; if (pcap_pkt_debug > 0) dbug_write ("pcap_xmit_hook: "); if (active_dev && active_dev->xmit) if ((*active_dev->xmit) (active_dev, buf, len) > 0) rc = len; if (pcap_pkt_debug > 0) dbug_write (rc ? "ok\n" : "fail\n"); return (rc); } #endif static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len) { struct device *dev = p ? get_device(p->fd) : NULL; if (!dev || !dev->xmit) return (-1); return (*dev->xmit) (dev, buf, len); } /* * This function is called by Watt-32 in tcp_post_init(). * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc. */ static void (*prev_post_hook) (void); static void pcap_init_hook (void) { _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0; _w32__do_mask_req = 0; _w32_dynamic_host = 0; if (prev_post_hook) (*prev_post_hook)(); } /* * Supress PRINT message from Watt-32's sock_init() */ static void null_print (void) {} /* * To use features of Watt-32 (netdb functions and socket etc.) * we must call sock_init(). But we set various hooks to prevent * using normal PKTDRVR functions in pcpkt.c. This should hopefully * make Watt-32 and pcap co-operate. */ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf) { char *env; int rc, MTU, has_ip_addr; int using_pktdrv = 1; /* If user called sock_init() first, we need to reinit in * order to open debug/trace-file properly */ if (_watt_is_init) sock_exit(); env = getenv ("PCAP_DEBUG"); if (env && atoi(env) > 0 && pcap_pkt_debug < 0) /* if not already set */ { dbug_init(); pcap_pkt_debug = atoi (env); } _watt_do_exit = 0; /* prevent sock_init() calling exit() */ prev_post_hook = _w32_usr_post_init; _w32_usr_post_init = pcap_init_hook; _w32_print_hook = null_print; if (dev_name && strncmp(dev_name,"pkt",3)) using_pktdrv = FALSE; rc = sock_init(); has_ip_addr = (rc != 8); /* IP-address assignment failed */ /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we * just pretend Watt-32 is initialised okay. * * !! fix-me: The Watt-32 config isn't done if no pktdrvr * was found. In that case my_ip_addr + sin_mask * have default values. Should be taken from another * ini-file/environment in any case (ref. tcpdump.ini) */ _watt_is_init = 1; if (!using_pktdrv || !has_ip_addr) /* for now .... */ { static const char myip[] = "192.168.0.1"; static const char mask[] = "255.255.255.0"; printf ("Just guessing, using IP %s and netmask %s\n", myip, mask); my_ip_addr = aton (myip); _w32_sin_mask = aton (mask); } else if (rc && using_pktdrv) { sprintf (err_buf, "sock_init() failed, code %d", rc); return (0); } /* Set recv-hook for peeking in _eth_arrived(). */ #if (WATTCP_VER >= 0x0224) _eth_recv_hook = pcap_recv_hook; _eth_xmit_hook = pcap_xmit_hook; #endif /* Free the pkt-drvr handle allocated in pkt_init(). * The above hooks should thus use the handle reopened in open_driver() */ if (using_pktdrv) { _eth_release(); /* _eth_is_init = 1; */ /* hack to get Rx/Tx-hooks in Watt-32 working */ } memcpy (&pcap_save, pcap, sizeof(pcap_save)); MTU = pkt_get_mtu(); pcap_save.fcode.bf_insns = NULL; pcap_save.linktype = _eth_get_hwtype (NULL, NULL); pcap_save.snapshot = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */ #if 1 /* prevent use of resolve() and resolve_ip() */ last_nameserver = 0; #endif return (1); } int EISA_bus = 0; /* Where is natural place for this? */ /* * Application config hooks to set various driver parameters. */ static struct config_table debug_tab[] = { { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug }, { "PKT.VECTOR", ARG_ATOX_W, NULL }, { "NDIS.DEBUG", ARG_ATOI, NULL }, #ifdef USE_32BIT_DRIVERS { "3C503.DEBUG", ARG_ATOI, &ei_debug }, { "3C503.IO_BASE", ARG_ATOX_W, &el2_dev.base_addr }, { "3C503.MEMORY", ARG_ATOX_W, &el2_dev.mem_start }, { "3C503.IRQ", ARG_ATOI, &el2_dev.irq }, { "3C505.DEBUG", ARG_ATOI, NULL }, { "3C505.BASE", ARG_ATOX_W, NULL }, { "3C507.DEBUG", ARG_ATOI, NULL }, { "3C509.DEBUG", ARG_ATOI, &el3_debug }, { "3C509.ILOOP", ARG_ATOI, &el3_max_loop }, { "3C529.DEBUG", ARG_ATOI, NULL }, { "3C575.DEBUG", ARG_ATOI, &debug_3c575 }, { "3C59X.DEBUG", ARG_ATOI, &vortex_debug }, { "3C59X.IFACE0", ARG_ATOI, &vortex_options[0] }, { "3C59X.IFACE1", ARG_ATOI, &vortex_options[1] }, { "3C59X.IFACE2", ARG_ATOI, &vortex_options[2] }, { "3C59X.IFACE3", ARG_ATOI, &vortex_options[3] }, { "3C90X.DEBUG", ARG_ATOX_W, &tc90xbc_debug }, { "ACCT.DEBUG", ARG_ATOI, ðpk_debug }, { "CS89.DEBUG", ARG_ATOI, &cs89_debug }, { "RTL8139.DEBUG", ARG_ATOI, &rtl8139_debug }, /* { "RTL8139.FDUPLEX", ARG_ATOI, &rtl8139_options }, */ { "SMC.DEBUG", ARG_ATOI, &ei_debug }, /* { "E100.DEBUG", ARG_ATOI, &e100_debug }, */ { "PCI.DEBUG", ARG_ATOI, &pci_debug }, { "BIOS32.DEBUG", ARG_ATOI, &bios32_debug }, { "IRQ.DEBUG", ARG_ATOI, &irq_debug }, { "TIMER.IRQ", ARG_ATOI, &timer_irq }, #endif { NULL } }; /* * pcap_config_hook() is an extension to application's config * handling. Uses Watt-32's config-table function. */ int pcap_config_hook (const char *name, const char *value) { return parse_config_table (debug_tab, NULL, name, value); } /* * Linked list of supported devices */ struct device *active_dev = NULL; /* the device we have opened */ struct device *probed_dev = NULL; /* the device we have probed */ const struct device *dev_base = &pkt_dev; /* list of network devices */ /* * PKTDRVR device functions */ int pcap_pkt_debug = -1; static void pkt_close (struct device *dev) { BOOL okay = PktExitDriver(); if (pcap_pkt_debug > 1) fprintf (stderr, "pkt_close(): %d\n", okay); if (dev->priv) free (dev->priv); dev->priv = NULL; } static int pkt_open (struct device *dev) { PKT_RX_MODE mode; if (dev->flags & IFF_PROMISC) mode = PDRX_ALL_PACKETS; else mode = PDRX_BROADCAST; if (!PktInitDriver(mode)) return (0); PktResetStatistics (pktInfo.handle); PktQueueBusy (FALSE); return (1); } static int pkt_xmit (struct device *dev, const void *buf, int len) { struct net_device_stats *stats = (struct net_device_stats*) dev->priv; if (pcap_pkt_debug > 0) dbug_write ("pcap_xmit\n"); if (!PktTransmit(buf,len)) { stats->tx_errors++; return (0); } return (len); } static void *pkt_stats (struct device *dev) { struct net_device_stats *stats = (struct net_device_stats*) dev->priv; if (!stats || !PktSessStatistics(pktInfo.handle)) return (NULL); stats->rx_packets = pktStat.inPackets; stats->rx_errors = pktStat.lost; stats->rx_missed_errors = PktRxDropped(); return (stats); } static int pkt_probe (struct device *dev) { if (!PktSearchDriver()) return (0); dev->open = pkt_open; dev->xmit = pkt_xmit; dev->close = pkt_close; dev->get_stats = pkt_stats; dev->copy_rx_buf = PktReceive; /* farmem peek and copy routine */ dev->get_rx_buf = NULL; dev->peek_rx_buf = NULL; dev->release_rx_buf = NULL; dev->priv = calloc (sizeof(struct net_device_stats), 1); if (!dev->priv) return (0); return (1); } /* * NDIS device functions */ static void ndis_close (struct device *dev) { #ifdef USE_NDIS2 NdisShutdown(); #endif ARGSUSED (dev); } static int ndis_open (struct device *dev) { int promis = (dev->flags & IFF_PROMISC); #ifdef USE_NDIS2 if (!NdisInit(promis)) return (0); return (1); #else ARGSUSED (promis); return (0); #endif } static void *ndis_stats (struct device *dev) { static struct net_device_stats stats; /* to-do */ ARGSUSED (dev); return (&stats); } static int ndis_probe (struct device *dev) { #ifdef USE_NDIS2 if (!NdisOpen()) return (0); #endif dev->open = ndis_open; dev->xmit = NULL; dev->close = ndis_close; dev->get_stats = ndis_stats; dev->copy_rx_buf = NULL; /* to-do */ dev->get_rx_buf = NULL; /* upcall is from rmode driver */ dev->peek_rx_buf = NULL; dev->release_rx_buf = NULL; return (0); } /* * Search & probe for supported 32-bit (pmode) pcap devices */ #if defined(USE_32BIT_DRIVERS) struct device el2_dev LOCKED_VAR = { "3c503", "EtherLink II", 0, 0,0,0,0,0,0, NULL, el2_probe }; struct device el3_dev LOCKED_VAR = { "3c509", "EtherLink III", 0, 0,0,0,0,0,0, &el2_dev, el3_probe }; struct device tc515_dev LOCKED_VAR = { "3c515", "EtherLink PCI", 0, 0,0,0,0,0,0, &el3_dev, tc515_probe }; struct device tc59_dev LOCKED_VAR = { "3c59x", "EtherLink PCI", 0, 0,0,0,0,0,0, &tc515_dev, tc59x_probe }; struct device tc90xbc_dev LOCKED_VAR = { "3c90x", "EtherLink 90X", 0, 0,0,0,0,0,0, &tc59_dev, tc90xbc_probe }; struct device wd_dev LOCKED_VAR = { "wd", "Westen Digital", 0, 0,0,0,0,0,0, &tc90xbc_dev, wd_probe }; struct device ne_dev LOCKED_VAR = { "ne", "NEx000", 0, 0,0,0,0,0,0, &wd_dev, ne_probe }; struct device acct_dev LOCKED_VAR = { "acct", "Accton EtherPocket", 0, 0,0,0,0,0,0, &ne_dev, ethpk_probe }; struct device cs89_dev LOCKED_VAR = { "cs89", "Crystal Semiconductor", 0, 0,0,0,0,0,0, &acct_dev, cs89x0_probe }; struct device rtl8139_dev LOCKED_VAR = { "rtl8139", "RealTek PCI", 0, 0,0,0,0,0,0, &cs89_dev, rtl8139_probe /* dev->probe routine */ }; /* * Dequeue routine is called by polling. * NOTE: the queue-element is not copied, only a pointer is * returned at '*buf' */ int peek_rxbuf (BYTE **buf) { struct rx_elem *tail, *head; PCAP_ASSERT (pktq_check (&active_dev->queue)); DISABLE(); tail = pktq_out_elem (&active_dev->queue); head = pktq_in_elem (&active_dev->queue); ENABLE(); if (head != tail) { PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2); *buf = &tail->data[0]; return (tail->size); } *buf = NULL; return (0); } /* * Release buffer we peeked at above. */ int release_rxbuf (BYTE *buf) { #ifndef NDEBUG struct rx_elem *tail = pktq_out_elem (&active_dev->queue); PCAP_ASSERT (&tail->data[0] == buf); #else ARGSUSED (buf); #endif pktq_inc_out (&active_dev->queue); return (1); } /* * get_rxbuf() routine (in locked code) is called from IRQ handler * to request a buffer. Interrupts are disabled and we have a 32kB stack. */ BYTE *get_rxbuf (int len) { int idx; if (len < ETH_MIN || len > ETH_MAX) return (NULL); idx = pktq_in_index (&active_dev->queue); #ifdef DEBUG { static int fan_idx LOCKED_VAR = 0; writew ("-\\|/"[fan_idx++] | (15 << 8), /* white on black colour */ 0xB8000 + 2*79); /* upper-right corner, 80-col colour screen */ fan_idx &= 3; } /* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */ #endif if (idx != active_dev->queue.out_index) { struct rx_elem *head = pktq_in_elem (&active_dev->queue); head->size = len; active_dev->queue.in_index = idx; return (&head->data[0]); } /* !!to-do: drop 25% of the oldest element */ pktq_clear (&active_dev->queue); return (NULL); } /* * Simple ring-buffer queue handler for reception of packets * from network driver. */ #define PKTQ_MARKER 0xDEADBEEF static int pktq_check (struct rx_ringbuf *q) { #ifndef NDEBUG int i; char *buf; #endif if (!q || !q->num_elem || !q->buf_start) return (0); #ifndef NDEBUG buf = q->buf_start; for (i = 0; i < q->num_elem; i++) { buf += q->elem_size; if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER) return (0); } #endif return (1); } static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool) { int i; q->elem_size = size; q->num_elem = num; q->buf_start = pool; q->in_index = 0; q->out_index = 0; PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD)); PCAP_ASSERT (num); PCAP_ASSERT (pool); for (i = 0; i < num; i++) { #if 0 struct rx_elem *elem = (struct rx_elem*) pool; /* assert dword aligned elements */ PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0); #endif pool += size; *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER; } return (1); } /* * Increment the queue 'out_index' (tail). * Check for wraps. */ static int pktq_inc_out (struct rx_ringbuf *q) { q->out_index++; if (q->out_index >= q->num_elem) q->out_index = 0; return (q->out_index); } /* * Return the queue's next 'in_index' (head). * Check for wraps. */ static int pktq_in_index (struct rx_ringbuf *q) { volatile int index = q->in_index + 1; if (index >= q->num_elem) index = 0; return (index); } /* * Return the queue's head-buffer. */ static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) { return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index)); } /* * Return the queue's tail-buffer. */ static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q) { return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index)); } /* * Clear the queue ring-buffer by setting head=tail. */ static void pktq_clear (struct rx_ringbuf *q) { q->in_index = q->out_index; } /* * Symbols that must be linkable for "gcc -O0" */ #undef __IOPORT_H #undef __DMA_H #define extern #define __inline__ #include "msdos/pm_drvr/ioport.h" #include "msdos/pm_drvr/dma.h" #endif /* USE_32BIT_DRIVERS */ libpcap-0.9.7/./gencode.c0000644000026300017500000051604210644760047013210 0ustar mcrmcr/*#define CHASE_CHAIN*/ /* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.52 2007/06/22 06:43:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #include #include #endif /* WIN32 */ /* * XXX - why was this included even on UNIX? */ #ifdef __MINGW32__ #include "IP6_misc.h" #endif #ifndef WIN32 #ifdef __NetBSD__ #include #endif #include #endif /* WIN32 */ #include #include #include #include #include #ifdef MSDOS #include "pcap-dos.h" #endif #include "pcap-int.h" #include "ethertype.h" #include "nlpid.h" #include "llc.h" #include "gencode.h" #include "atmuni31.h" #include "sunatmpos.h" #include "ppp.h" #include "sll.h" #include "arcnet.h" #include "pf.h" #ifndef offsetof #define offsetof(s, e) ((size_t)&((s *)0)->e) #endif #ifdef INET6 #ifndef WIN32 #include /* for "struct addrinfo" */ #endif /* WIN32 */ #endif /*INET6*/ #include #define ETHERMTU 1500 #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #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; #ifdef WIN32 /* Hack for updating VLAN, MPLS, and PPPoE offsets. */ static u_int orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1; #else static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U; #endif /* XXX */ #ifdef PCAP_FDDIPAD static int pcap_fddipad; #endif /* VARARGS */ void bpf_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (bpf_pcap != NULL) (void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE, fmt, ap); va_end(ap); longjmp(top_ctx, 1); /* NOTREACHED */ } static void init_linktype(pcap_t *); static int alloc_reg(void); static void free_reg(int); static struct block *root; /* * Value passed to gen_load_a() to indicate what the offset argument * is relative to. */ enum e_offrel { OR_PACKET, /* relative to the beginning of the packet */ OR_LINK, /* relative to the link-layer header */ OR_NET, /* relative to the network-layer header */ OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ }; /* * 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 if this ever * goes into a library that would probably not be a good idea. * * XXX - this *is* in a library.... */ #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(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32, bpf_u_int32); static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *); static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32); static struct slist *gen_load_llrel(u_int, u_int); static struct slist *gen_load_a(enum e_offrel, u_int, u_int); static struct slist *gen_loadx_iphdrlen(void); static struct block *gen_uncond(int); static inline struct block *gen_true(void); static inline struct block *gen_false(void); static struct block *gen_ether_linktype(int); static struct block *gen_linux_sll_linktype(int); static void insert_radiotap_load_llprefixlen(struct block *); static void insert_ppi_load_llprefixlen(struct block *); static void insert_load_llprefixlen(struct block *); static struct slist *gen_llprefixlen(void); static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); static struct block *gen_llc_linktype(int); static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); #ifdef INET6 static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); #endif static struct block *gen_ahostop(const u_char *, int); static struct block *gen_ehostop(const u_char *, int); static struct block *gen_fhostop(const u_char *, int); static struct block *gen_thostop(const u_char *, int); static struct block *gen_wlanhostop(const u_char *, int); static struct block *gen_ipfchostop(const u_char *, int); static struct block *gen_dnhostop(bpf_u_int32, int); static struct block *gen_mpls_linktype(int); static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int); #ifdef INET6 static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int); #endif #ifndef INET6 static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int); #endif static struct block *gen_ipfrag(void); static struct block *gen_portatom(int, bpf_int32); static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32); #ifdef INET6 static struct block *gen_portatom6(int, bpf_int32); static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32); #endif struct block *gen_portop(int, int, int); static struct block *gen_port(int, int, int); struct block *gen_portrangeop(int, int, int, int); static struct block *gen_portrange(int, int, int, int); #ifdef INET6 struct block *gen_portop6(int, int, int); static struct block *gen_port6(int, int, int); struct block *gen_portrangeop6(int, int, int, int); static struct block *gen_portrange6(int, int, int, int); #endif static int lookup_proto(const char *, int); static struct block *gen_protochain(int, int, 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_mac_multicast(int); static struct block *gen_len(int, int); static struct block *gen_ppi_dlt_check(void); static struct block *gen_msg_abbrev(int type); static void * newchunk(n) u_int n; { struct chunk *cp; int k; size_t size; #ifndef __NetBSD__ /* XXX Round up to nearest long. */ n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1); #else /* XXX Round up to structure boundary. */ n = ALIGN(n); #endif 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); if (cp->m == NULL) bpf_error("out of memory"); 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); strlcpy(cp, s, n); 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; int no_optimize; int pcap_compile(pcap_t *p, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) { extern int n_errors; const char * volatile xbuf = buf; int len; no_optimize = 0; n_errors = 0; root = NULL; bpf_pcap = p; if (setjmp(top_ctx)) { lex_cleanup(); freechunks(); return (-1); } netmask = mask; snaplen = pcap_snapshot(p); if (snaplen == 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snaplen of 0 rejects all packets"); return -1; } lex_init(xbuf ? xbuf : ""); init_linktype(p); (void)pcap_parse(); if (n_errors) syntax(); if (root == NULL) root = gen_retblk(snaplen); if (optimize && !no_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; lex_cleanup(); freechunks(); return (0); } /* * entry point for using the compiler with no pcap open * pass in all the stuff that is needed explicitly instead. */ int pcap_compile_nopcap(int snaplen_arg, int linktype_arg, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) { pcap_t *p; int ret; p = pcap_open_dead(linktype_arg, snaplen_arg); if (p == NULL) return (-1); ret = pcap_compile(p, program, buf, optimize, mask); pcap_close(p); return (ret); } /* * Clean up a "struct bpf_program" by freeing all the memory allocated * in it. */ void pcap_freecode(struct bpf_program *program) { program->bf_len = 0; if (program->bf_insns != NULL) { free((char *)program->bf_insns); program->bf_insns = NULL; } } /* * 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; { struct block *ppi_dlt_check; ppi_dlt_check = gen_ppi_dlt_check(); if (ppi_dlt_check != NULL) { gen_and(ppi_dlt_check, p); } backpatch(p, gen_retblk(snaplen)); p->sense = !p->sense; backpatch(p, gen_retblk(0)); root = p->head; /* * Insert before the statements of the first (root) block any * statements needed to load the lengths of any variable-length * headers into registers. * * XXX - a fancier strategy would be to insert those before the * statements of all blocks that use those lengths and that * have no predecessors that use them, so that we only compute * the lengths if we need them. There might be even better * approaches than that. However, as we're currently only * handling variable-length radiotap headers, and as all * filtering expressions other than raw link[M:N] tests * require the length of that header, doing more for that * header length isn't really worth the effort. */ insert_load_llprefixlen(root); } 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(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v); } static struct block * gen_cmp_gt(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v); } static struct block * gen_cmp_ge(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v); } static struct block * gen_cmp_lt(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v); } static struct block * gen_cmp_le(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v); } static struct block * gen_mcmp(offrel, offset, size, v, mask) enum e_offrel offrel; u_int offset, size; bpf_int32 v; bpf_u_int32 mask; { return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v); } static struct block * gen_bcmp(offrel, offset, size, v) enum e_offrel offrel; 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(offrel, 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(offrel, offset + size - 2, BPF_H, w); if (b != NULL) gen_and(b, tmp); b = tmp; size -= 2; } if (size > 0) { tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]); if (b != NULL) gen_and(b, tmp); b = tmp; } return b; } /* * AND the field of size "size" at offset "offset" relative to the header * specified by "offrel" with "mask", and compare it with the value "v" * with the test specified by "jtype"; if "reverse" is true, the test * should test the opposite of "jtype". */ static struct block * gen_ncmp(offrel, offset, size, mask, jtype, reverse, v) enum e_offrel offrel; bpf_int32 v; bpf_u_int32 offset, size, mask, jtype; int reverse; { struct slist *s, *s2; struct block *b; s = gen_load_a(offrel, offset, size); if (mask != 0xffffffff) { s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); s2->s.k = mask; sappend(s, s2); } b = new_block(JMP(jtype)); b->stmts = s; b->s.k = v; if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE)) gen_not(b); return b; } /* * Various code constructs need to know the layout of the data link * layer. These variables give the necessary offsets from the beginning * of the packet data. * * If the link layer has variable_length headers, the offsets are offsets * from the end of the link-link-layer header, and "reg_ll_size" is * the register number for a register containing the length of the * link-layer header. Otherwise, "reg_ll_size" is -1. */ static int reg_ll_size; /* * This is the offset of the beginning of the link-layer header from * the beginning of the raw packet data. * * It's usually 0, except for 802.11 with a fixed-length radio header. * (For 802.11 with a variable-length radio header, we have to generate * code to compute that offset; off_ll is 0 in that case.) */ static u_int off_ll; /* * This is the offset of the beginning of the MAC-layer header. * It's usually 0, except for ATM LANE, where it's the offset, relative * to the beginning of the raw packet data, of the Ethernet header. */ static u_int off_mac; /* * "off_linktype" is the offset to information in the link-layer header * giving the packet type. This offset is relative to the beginning * of the link-layer header (i.e., it doesn't include off_ll). * * For Ethernet, it's the offset of the Ethernet type field. * * For link-layer types that always use 802.2 headers, it's the * offset of the LLC header. * * For PPP, it's the offset of the PPP type field. * * For Cisco HDLC, it's the offset of the CHDLC type field. * * For BSD loopback, it's the offset of the AF_ value. * * For Linux cooked sockets, it's the offset of the type field. * * It's set to -1 for no encapsulation, in which case, IP is assumed. */ static u_int off_linktype; /* * TRUE if the link layer includes an ATM pseudo-header. */ static int is_atm = 0; /* * TRUE if "lane" appeared in the filter; it causes us to generate * code that assumes LANE rather than LLC-encapsulated traffic in SunATM. */ static int is_lane = 0; /* * These are offsets for the ATM pseudo-header. */ static u_int off_vpi; static u_int off_vci; static u_int off_proto; /* * These are offsets for the MTP2 fields. */ static u_int off_li; /* * These are offsets for the MTP3 fields. */ static u_int off_sio; static u_int off_opc; static u_int off_dpc; static u_int off_sls; /* * This is the offset of the first byte after the ATM pseudo_header, * or -1 if there is no ATM pseudo-header. */ static u_int off_payload; /* * These are offsets to the beginning of the network-layer header. * They are relative to the beginning of the link-layer header (i.e., * they don't include off_ll). * * If the link layer never uses 802.2 LLC: * * "off_nl" and "off_nl_nosnap" are the same. * * If the link layer always uses 802.2 LLC: * * "off_nl" is the offset if there's a SNAP header following * the 802.2 header; * * "off_nl_nosnap" is the offset if there's no SNAP header. * * If the link layer is Ethernet: * * "off_nl" is the offset if the packet is an Ethernet II packet * (we assume no 802.3+802.2+SNAP); * * "off_nl_nosnap" is the offset if the packet is an 802.3 packet * with an 802.2 header following it. */ static u_int off_nl; static u_int off_nl_nosnap; static int linktype; static void init_linktype(p) pcap_t *p; { linktype = pcap_datalink(p); #ifdef PCAP_FDDIPAD pcap_fddipad = p->fddipad; #endif /* * Assume it's not raw ATM with a pseudo-header, for now. */ off_mac = 0; is_atm = 0; is_lane = 0; off_vpi = -1; off_vci = -1; off_proto = -1; off_payload = -1; /* * And assume we're not doing SS7. */ off_li = -1; off_sio = -1; off_opc = -1; off_dpc = -1; off_sls = -1; /* * Also assume it's not 802.11 with a fixed-length radio header. */ off_ll = 0; orig_linktype = -1; orig_nl = -1; label_stack_depth = 0; reg_ll_size = -1; switch (linktype) { case DLT_ARCNET: off_linktype = 2; off_nl = 6; /* XXX in reality, variable! */ off_nl_nosnap = 6; /* no 802.2 LLC */ return; case DLT_ARCNET_LINUX: off_linktype = 4; off_nl = 8; /* XXX in reality, variable! */ off_nl_nosnap = 8; /* no 802.2 LLC */ return; case DLT_EN10MB: off_linktype = 12; off_nl = 14; /* Ethernet II */ off_nl_nosnap = 17; /* 802.3+802.2 */ 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; off_nl_nosnap = 16; /* no 802.2 LLC */ 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; off_nl_nosnap = 24; /* no 802.2 LLC */ return; case DLT_NULL: case DLT_LOOP: off_linktype = 0; off_nl = 4; off_nl_nosnap = 4; /* no 802.2 LLC */ return; case DLT_ENC: off_linktype = 0; off_nl = 12; off_nl_nosnap = 12; /* no 802.2 LLC */ return; case DLT_PPP: case DLT_PPP_PPPD: case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ off_linktype = 2; off_nl = 4; off_nl_nosnap = 4; /* no 802.2 LLC */ return; case DLT_PPP_ETHER: /* * This does no include the Ethernet header, and * only covers session state. */ off_linktype = 6; off_nl = 8; off_nl_nosnap = 8; /* no 802.2 LLC */ return; case DLT_PPP_BSDOS: off_linktype = 5; off_nl = 24; off_nl_nosnap = 24; /* no 802.2 LLC */ return; case DLT_FDDI: /* * FDDI doesn't really have a link-level type field. * We set "off_linktype" to the offset of the LLC header. * * To check for Ethernet types, we assume that SSAP = SNAP * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? */ off_linktype = 13; #ifdef PCAP_FDDIPAD off_linktype += pcap_fddipad; #endif off_nl = 21; /* FDDI+802.2+SNAP */ off_nl_nosnap = 16; /* FDDI+802.2 */ #ifdef PCAP_FDDIPAD off_nl += pcap_fddipad; off_nl_nosnap += pcap_fddipad; #endif return; case DLT_IEEE802: /* * Token Ring doesn't really have a link-level type field. * We set "off_linktype" to the offset of the LLC header. * * To check for Ethernet types, we assume that SSAP = SNAP * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? * * XXX - the header is actually variable-length. * Some various Linux patched versions gave 38 * as "off_linktype" and 40 as "off_nl"; however, * if a token ring packet has *no* routing * information, i.e. is not source-routed, the correct * values are 20 and 22, as they are in the vanilla code. * * A packet is source-routed iff the uppermost bit * of the first byte of the source address, at an * offset of 8, has the uppermost bit set. If the * packet is source-routed, the total number of bytes * of routing information is 2 plus bits 0x1F00 of * the 16-bit value at an offset of 14 (shifted right * 8 - figure out which byte that is). */ off_linktype = 14; off_nl = 22; /* Token Ring+802.2+SNAP */ off_nl_nosnap = 17; /* Token Ring+802.2 */ return; case DLT_IEEE802_11: /* * 802.11 doesn't really have a link-level type field. * We set "off_linktype" to the offset of the LLC header. * * To check for Ethernet types, we assume that SSAP = SNAP * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? * * XXX - the header is actually variable-length. We * assume a 24-byte link-layer header, as appears in * data frames in networks with no bridges. If the * fromds and tods 802.11 header bits are both set, * it's actually supposed to be 30 bytes. */ off_linktype = 24; off_nl = 32; /* 802.11+802.2+SNAP */ off_nl_nosnap = 27; /* 802.11+802.2 */ return; case DLT_PRISM_HEADER: /* * Same as 802.11, but with an additional header before * the 802.11 header, containing a bunch of additional * information including radio-level information. * * The header is 144 bytes long. * * XXX - same variable-length header problem; at least * the Prism header is fixed-length. */ off_ll = 144; off_linktype = 24; off_nl = 32; /* Prism+802.11+802.2+SNAP */ off_nl_nosnap = 27; /* Prism+802.11+802.2 */ return; case DLT_IEEE802_11_RADIO_AVS: /* * Same as 802.11, but with an additional header before * the 802.11 header, containing a bunch of additional * information including radio-level information. * * The header is 64 bytes long, at least in its * current incarnation. * * XXX - same variable-length header problem, only * more so; this header is also variable-length, * with the length being the 32-bit big-endian * number at an offset of 4 from the beginning * of the radio header. We should handle that the * same way we handle the length at the beginning * of the radiotap header. * * XXX - in Linux, do any drivers that supply an AVS * header supply a link-layer type other than * ARPHRD_IEEE80211_PRISM? If so, we should map that * to DLT_IEEE802_11_RADIO_AVS; if not, or if there are * any drivers that supply an AVS header but supply * an ARPHRD value of ARPHRD_IEEE80211_PRISM, we'll * have to check the header in the generated code to * determine whether it's Prism or AVS. */ off_ll = 64; off_linktype = 24; off_nl = 32; /* Radio+802.11+802.2+SNAP */ off_nl_nosnap = 27; /* Radio+802.11+802.2 */ return; /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ case DLT_PPI: case DLT_IEEE802_11_RADIO: /* * Same as 802.11, but with an additional header before * the 802.11 header, containing a bunch of additional * information including radio-level information. * * The radiotap header is variable length, and we * generate code to compute its length and store it * in a register. These offsets are relative to the * beginning of the 802.11 header. */ off_linktype = 24; off_nl = 32; /* 802.11+802.2+SNAP */ off_nl_nosnap = 27; /* 802.11+802.2 */ return; case DLT_ATM_RFC1483: case DLT_ATM_CLIP: /* Linux ATM defines this */ /* * assume routed, non-ISO PDUs * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00) * * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS, * or PPP with the PPP NLPID (e.g., PPPoA)? The * latter would presumably be treated the way PPPoE * should be, so you can do "pppoe and udp port 2049" * or "pppoa and tcp port 80" and have it check for * PPPo{A,E} and a PPP protocol of IP and.... */ off_linktype = 0; off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; case DLT_SUNATM: /* * Full Frontal ATM; you get AALn PDUs with an ATM * pseudo-header. */ is_atm = 1; off_vpi = SUNATM_VPI_POS; off_vci = SUNATM_VCI_POS; off_proto = PROTO_POS; off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */ off_payload = SUNATM_PKT_BEGIN_POS; off_linktype = off_payload; off_nl = off_payload+8; /* 802.2+SNAP */ off_nl_nosnap = off_payload+3; /* 802.2 */ return; case DLT_RAW: off_linktype = -1; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_LINUX_SLL: /* fake header for Linux cooked socket */ off_linktype = 14; off_nl = 16; off_nl_nosnap = 16; /* no 802.2 LLC */ return; case DLT_LTALK: /* * LocalTalk does have a 1-byte type field in the LLAP header, * but really it just indicates whether there is a "short" or * "long" DDP packet following. */ off_linktype = -1; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_IP_OVER_FC: /* * RFC 2625 IP-over-Fibre-Channel doesn't really have a * link-level type field. We set "off_linktype" to the * offset of the LLC header. * * To check for Ethernet types, we assume that SSAP = SNAP * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? RFC * 2625 says SNAP should be used. */ off_linktype = 16; off_nl = 24; /* IPFC+802.2+SNAP */ off_nl_nosnap = 19; /* IPFC+802.2 */ return; case DLT_FRELAY: /* * XXX - we should set this to handle SNAP-encapsulated * frames (NLPID of 0x80). */ off_linktype = -1; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; /* * the only BPF-interesting FRF.16 frames are non-control frames; * Frame Relay has a variable length link-layer * so lets start with offset 4 for now and increments later on (FIXME); */ case DLT_MFR: off_linktype = -1; off_nl = 4; off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */ return; case DLT_APPLE_IP_OVER_IEEE1394: off_linktype = 16; off_nl = 18; off_nl_nosnap = 18; /* no 802.2 LLC */ return; case DLT_LINUX_IRDA: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_DOCSIS: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_SYMANTEC_FIREWALL: off_linktype = 6; off_nl = 44; /* Ethernet II */ off_nl_nosnap = 44; /* XXX - what does it do with 802.3 packets? */ return; case DLT_PFLOG: off_linktype = 0; /* XXX read this from pf.h? */ off_nl = PFLOG_HDRLEN; off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */ return; case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_PPP: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_FRELAY: off_linktype = 4; off_nl = 4; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_ATM1: off_linktype = 4; /* in reality variable between 4-8 */ off_nl = 4; off_nl_nosnap = 14; return; case DLT_JUNIPER_ATM2: off_linktype = 8; /* in reality variable between 8-12 */ off_nl = 8; off_nl_nosnap = 18; return; /* frames captured on a Juniper PPPoE service PIC * contain raw ethernet frames */ case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_ETHER: off_linktype = 16; off_nl = 18; /* Ethernet II */ off_nl_nosnap = 21; /* 802.3+802.2 */ return; case DLT_JUNIPER_PPPOE_ATM: off_linktype = 4; off_nl = 6; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_GGSN: off_linktype = 6; off_nl = 12; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_ES: off_linktype = 6; off_nl = -1; /* not really a network layer but raw IP adresses */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_MONITOR: off_linktype = 12; off_nl = 12; /* raw IP/IP6 header */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_SERVICES: off_linktype = 12; off_nl = -1; /* L3 proto location dep. on cookie type */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_VP: off_linktype = 18; off_nl = -1; off_nl_nosnap = -1; return; case DLT_MTP2: off_li = 2; off_sio = 3; off_opc = 4; off_dpc = 4; off_sls = 7; off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_MTP2_WITH_PHDR: off_li = 6; off_sio = 7; off_opc = 8; off_dpc = 8; off_sls = 11; off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; #ifdef DLT_PFSYNC case DLT_PFSYNC: off_linktype = -1; off_nl = 4; off_nl_nosnap = 4; return; #endif case DLT_LINUX_LAPD: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_USB: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_BLUETOOTH_HCI_H4: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ } /* * Load a value relative to the beginning of the link-layer header. * The link-layer header doesn't necessarily begin at the beginning * of the packet data; there might be a variable-length prefix containing * radio information. */ static struct slist * gen_load_llrel(offset, size) u_int offset, size; { struct slist *s, *s2; s = gen_llprefixlen(); /* * If "s" is non-null, it has code to arrange that the X register * contains the length of the prefix preceding the link-layer * header. * * Otherwise, the length of the prefix preceding the link-layer * header is "off_ll". */ if (s != NULL) { /* * There's a variable-length prefix preceding the * link-layer header. "s" points to a list of statements * that put the length of that prefix into the X register. * do an indirect load, to use the X register as an offset. */ s2 = new_stmt(BPF_LD|BPF_IND|size); s2->s.k = offset; sappend(s, s2); } else { /* * There is no variable-length header preceding the * link-layer header; add in off_ll, which, if there's * a fixed-length header preceding the link-layer header, * is the length of that header. */ s = new_stmt(BPF_LD|BPF_ABS|size); s->s.k = offset + off_ll; } return s; } /* * Load a value relative to the beginning of the specified header. */ static struct slist * gen_load_a(offrel, offset, size) enum e_offrel offrel; u_int offset, size; { struct slist *s, *s2; switch (offrel) { case OR_PACKET: s = new_stmt(BPF_LD|BPF_ABS|size); s->s.k = offset; break; case OR_LINK: s = gen_load_llrel(offset, size); break; case OR_NET: s = gen_load_llrel(off_nl + offset, size); break; case OR_NET_NOSNAP: s = gen_load_llrel(off_nl_nosnap + offset, size); break; case OR_TRAN_IPV4: /* * Load the X register with the length of the IPv4 header * (plus the offset of the link-layer header, if it's * preceded by a variable-length header such as a radio * header), in bytes. */ s = gen_loadx_iphdrlen(); /* * Load the item at {offset of the link-layer header} + * {offset, relative to the start of the link-layer * header, of the IPv4 header} + {length of the IPv4 header} + * {specified offset}. * * (If the link-layer is variable-length, it's included * in the value in the X register, and off_ll is 0.) */ s2 = new_stmt(BPF_LD|BPF_IND|size); s2->s.k = off_ll + off_nl + offset; sappend(s, s2); break; case OR_TRAN_IPV6: s = gen_load_llrel(off_nl + 40 + offset, size); break; default: abort(); return NULL; } return s; } /* * Generate code to load into the X register the sum of the length of * the IPv4 header and any variable-length header preceding the link-layer * header. */ static struct slist * gen_loadx_iphdrlen() { struct slist *s, *s2; s = gen_llprefixlen(); if (s != NULL) { /* * There's a variable-length prefix preceding the * link-layer header. "s" points to a list of statements * that put the length of that prefix into the X register. * The 4*([k]&0xf) addressing mode can't be used, as we * don't have a constant offset, so we have to load the * value in question into the A register and add to it * the value from the X register. */ s2 = new_stmt(BPF_LD|BPF_IND|BPF_B); s2->s.k = off_nl; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); s2->s.k = 0xf; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); s2->s.k = 2; sappend(s, s2); /* * The A register now contains the length of the * IP header. We need to add to it the length * of the prefix preceding the link-layer * header, which is still in the X register, and * move the result into the X register. */ sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else { /* * There is no variable-length header preceding the * link-layer header; add in off_ll, which, if there's * a fixed-length header preceding the link-layer header, * is the length of that header. */ s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s->s.k = off_ll + off_nl; } return s; } 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); } /* * Byte-swap a 32-bit number. * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on * big-endian platforms.) */ #define SWAPLONG(y) \ ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) /* * Generate code to match a particular packet type. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the type/length field or to check the type/length field for * a value <= ETHERMTU to see whether it's a type field and then do * the appropriate test. */ static struct block * gen_ether_linktype(proto) register int proto; { struct block *b0, *b1; switch (proto) { case LLCSAP_ISONS: case LLCSAP_IP: case LLCSAP_NETBEUI: /* * OSI protocols and NetBEUI always use 802.2 encapsulation, * so we check the DSAP and SSAP. * * LLCSAP_IP checks for IP-over-802.2, rather * than IP-over-Ethernet or IP-over-SNAP. * * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32) ((proto << 8) | proto)); gen_and(b0, b1); return b1; case LLCSAP_IPX: /* * Check for; * * Ethernet_II frames, which are Ethernet * frames with a frame type of ETHERTYPE_IPX; * * Ethernet_802.3 frames, which are 802.3 * frames (i.e., the type/length field is * a length field, <= ETHERMTU, rather than * a type field) with the first two bytes * after the Ethernet/802.3 header being * 0xFFFF; * * Ethernet_802.2 frames, which are 802.3 * frames with an 802.2 LLC header and * with the IPX LSAP as the DSAP in the LLC * header; * * Ethernet_SNAP frames, which are 802.3 * frames with an LLC header and a SNAP * header and with an OUI of 0x000000 * (encapsulated Ethernet) and a protocol * ID of ETHERTYPE_IPX in the SNAP header. * * XXX - should we generate the same code both * for tests for LLCSAP_IPX and for ETHERTYPE_IPX? */ /* * This generates code to check both for the * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3. */ b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32)0xFFFF); gen_or(b0, b1); /* * Now we add code to check for SNAP frames with * ETHERTYPE_IPX, i.e. Ethernet_SNAP. */ b0 = gen_snap(0x000000, ETHERTYPE_IPX, 14); gen_or(b0, b1); /* * Now we generate code to check for 802.3 * frames in general. */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); /* * Now add the check for 802.3 frames before the * check for Ethernet_802.2 and Ethernet_802.3, * as those checks should only be done on 802.3 * frames, not on Ethernet frames. */ gen_and(b0, b1); /* * Now add the check for Ethernet_II frames, and * do that before checking for the other frame * types. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)ETHERTYPE_IPX); gen_or(b0, b1); return b1; case ETHERTYPE_ATALK: case ETHERTYPE_AARP: /* * EtherTalk (AppleTalk protocols on Ethernet link * layer) may use 802.2 encapsulation. */ /* * Check for 802.2 encapsulation (EtherTalk phase 2?); * we check for an Ethernet type field less than * 1500, which means it's an 802.3 length field. */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); /* * 802.2-encapsulated ETHERTYPE_ATALK packets are * SNAP packets with an organization code of * 0x080007 (Apple, for Appletalk) and a protocol * type of ETHERTYPE_ATALK (Appletalk). * * 802.2-encapsulated ETHERTYPE_AARP packets are * SNAP packets with an organization code of * 0x000000 (encapsulated Ethernet) and a protocol * type of ETHERTYPE_AARP (Appletalk ARP). */ if (proto == ETHERTYPE_ATALK) b1 = gen_snap(0x080007, ETHERTYPE_ATALK, 14); else /* proto == ETHERTYPE_AARP */ b1 = gen_snap(0x000000, ETHERTYPE_AARP, 14); gen_and(b0, b1); /* * Check for Ethernet encapsulation (Ethertalk * phase 1?); we just check for the Ethernet * protocol type. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); gen_or(b0, b1); return b1; default: if (proto <= ETHERMTU) { /* * This is an LLC SAP value, so the frames * that match would be 802.2 frames. * Check that the frame is an 802.2 frame * (i.e., that the length/type field is * a length field, <= ETHERMTU) and * then check the DSAP. */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)proto); gen_and(b0, b1); return b1; } else { /* * This is an Ethernet type, so compare * the length/type field with it (if * the frame is an 802.2 frame, the length * field will be <= ETHERMTU, and, as * "proto" is > ETHERMTU, this test * will fail and the frame won't match, * which is what we want). */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } } } /* * Generate code to match a particular packet type. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the type field or to check the type field for the special * LINUX_SLL_P_802_2 value and then do the appropriate test. */ static struct block * gen_linux_sll_linktype(proto) register int proto; { struct block *b0, *b1; switch (proto) { case LLCSAP_ISONS: case LLCSAP_IP: case LLCSAP_NETBEUI: /* * OSI protocols and NetBEUI always use 802.2 encapsulation, * so we check the DSAP and SSAP. * * LLCSAP_IP checks for IP-over-802.2, rather * than IP-over-Ethernet or IP-over-SNAP. * * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32) ((proto << 8) | proto)); gen_and(b0, b1); return b1; case LLCSAP_IPX: /* * Ethernet_II frames, which are Ethernet * frames with a frame type of ETHERTYPE_IPX; * * Ethernet_802.3 frames, which have a frame * type of LINUX_SLL_P_802_3; * * Ethernet_802.2 frames, which are 802.3 * frames with an 802.2 LLC header (i.e, have * a frame type of LINUX_SLL_P_802_2) and * with the IPX LSAP as the DSAP in the LLC * header; * * Ethernet_SNAP frames, which are 802.3 * frames with an LLC header and a SNAP * header and with an OUI of 0x000000 * (encapsulated Ethernet) and a protocol * ID of ETHERTYPE_IPX in the SNAP header. * * First, do the checks on LINUX_SLL_P_802_2 * frames; generate the check for either * Ethernet_802.2 or Ethernet_SNAP frames, and * then put a check for LINUX_SLL_P_802_2 frames * before it. */ b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX); b1 = gen_snap(0x000000, ETHERTYPE_IPX, off_linktype + 2); gen_or(b0, b1); b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); gen_and(b0, b1); /* * Now check for 802.3 frames and OR that with * the previous test. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3); gen_or(b0, b1); /* * Now add the check for Ethernet_II frames, and * do that before checking for the other frame * types. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)ETHERTYPE_IPX); gen_or(b0, b1); return b1; case ETHERTYPE_ATALK: case ETHERTYPE_AARP: /* * EtherTalk (AppleTalk protocols on Ethernet link * layer) may use 802.2 encapsulation. */ /* * Check for 802.2 encapsulation (EtherTalk phase 2?); * we check for the 802.2 protocol type in the * "Ethernet type" field. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); /* * 802.2-encapsulated ETHERTYPE_ATALK packets are * SNAP packets with an organization code of * 0x080007 (Apple, for Appletalk) and a protocol * type of ETHERTYPE_ATALK (Appletalk). * * 802.2-encapsulated ETHERTYPE_AARP packets are * SNAP packets with an organization code of * 0x000000 (encapsulated Ethernet) and a protocol * type of ETHERTYPE_AARP (Appletalk ARP). */ if (proto == ETHERTYPE_ATALK) b1 = gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype + 2); else /* proto == ETHERTYPE_AARP */ b1 = gen_snap(0x000000, ETHERTYPE_AARP, off_linktype + 2); gen_and(b0, b1); /* * Check for Ethernet encapsulation (Ethertalk * phase 1?); we just check for the Ethernet * protocol type. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); gen_or(b0, b1); return b1; default: if (proto <= ETHERMTU) { /* * This is an LLC SAP value, so the frames * that match would be 802.2 frames. * Check for the 802.2 protocol type * in the "Ethernet type" field, and * then check the DSAP. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)proto); gen_and(b0, b1); return b1; } else { /* * This is an Ethernet type, so compare * the length/type field with it (if * the frame is an 802.2 frame, the length * field will be <= ETHERMTU, and, as * "proto" is > ETHERMTU, this test * will fail and the frame won't match, * which is what we want). */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } } } static void insert_radiotap_load_llprefixlen(b) struct block *b; { struct slist *s1, *s2; /* * Prepend to the statements in this block code to load the * length of the radiotap header into the register assigned * to hold that length, if one has been assigned. */ if (reg_ll_size != -1) { /* * The 2 bytes at offsets of 2 and 3 from the beginning * of the radiotap header are the length of the radiotap * header; unfortunately, it's little-endian, so we have * to load it a byte at a time and construct the value. */ /* * Load the high-order byte, at an offset of 3, shift it * left a byte, and put the result in the X register. */ s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS); s1->s.k = 3; s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); sappend(s1, s2); s2->s.k = 8; s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Load the next byte, at an offset of 2, and OR the * value from the X register into it. */ s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS); sappend(s1, s2); s2->s.k = 2; s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X); sappend(s1, s2); /* * Now allocate a register to hold that value and store * it. */ s2 = new_stmt(BPF_ST); s2->s.k = reg_ll_size; sappend(s1, s2); /* * Now move it into the X register. */ s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Now append all the existing statements in this * block to these statements. */ sappend(s1, b->stmts); b->stmts = s1; } } /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ static void insert_ppi_load_llprefixlen(b) struct block *b; { struct slist *s1, *s2; /* * Prepend to the statements in this block code to load the * length of the radiotap header into the register assigned * to hold that length, if one has been assigned. */ if (reg_ll_size != -1) { /* * The 2 bytes at offsets of 2 and 3 from the beginning * of the radiotap header are the length of the radiotap * header; unfortunately, it's little-endian, so we have * to load it a byte at a time and construct the value. */ /* * Load the high-order byte, at an offset of 3, shift it * left a byte, and put the result in the X register. */ s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS); s1->s.k = 3; s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); sappend(s1, s2); s2->s.k = 8; s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Load the next byte, at an offset of 2, and OR the * value from the X register into it. */ s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS); sappend(s1, s2); s2->s.k = 2; s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X); sappend(s1, s2); /* * Now allocate a register to hold that value and store * it. */ s2 = new_stmt(BPF_ST); s2->s.k = reg_ll_size; sappend(s1, s2); /* * Now move it into the X register. */ s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Now append all the existing statements in this * block to these statements. */ sappend(s1, b->stmts); b->stmts = s1; } } static struct block * gen_ppi_dlt_check(void) { struct slist *s_load_dlt; struct block *b; if (linktype == DLT_PPI) { /* Create the statements that check for the DLT */ s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS); s_load_dlt->s.k = 4; b = new_block(JMP(BPF_JEQ)); b->stmts = s_load_dlt; b->s.k = SWAPLONG(DLT_IEEE802_11); } else { b = NULL; } return b; } static void insert_load_llprefixlen(b) struct block *b; { switch (linktype) { /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ case DLT_PPI: insert_ppi_load_llprefixlen(b); break; case DLT_IEEE802_11_RADIO: insert_radiotap_load_llprefixlen(b); break; } } static struct slist * gen_radiotap_llprefixlen(void) { struct slist *s; if (reg_ll_size == -1) { /* * We haven't yet assigned a register for the length * of the radiotap header; allocate one. */ reg_ll_size = alloc_reg(); } /* * Load the register containing the radiotap length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_ll_size; return s; } /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ static struct slist * gen_ppi_llprefixlen(void) { struct slist *s; if (reg_ll_size == -1) { /* * We haven't yet assigned a register for the length * of the radiotap header; allocate one. */ reg_ll_size = alloc_reg(); } /* * Load the register containing the radiotap length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_ll_size; return s; } /* * Generate code to compute the link-layer header length, if necessary, * putting it into the X register, and to return either a pointer to a * "struct slist" for the list of statements in that code, or NULL if * no code is necessary. */ static struct slist * gen_llprefixlen(void) { switch (linktype) { case DLT_PPI: return gen_ppi_llprefixlen(); case DLT_IEEE802_11_RADIO: return gen_radiotap_llprefixlen(); default: return NULL; } } /* * Generate code to match a particular packet type by matching the * link-layer type field or fields in the 802.2 LLC header. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. */ static struct block * gen_linktype(proto) register int proto; { struct block *b0, *b1, *b2; /* are we checking MPLS-encapsulated packets? */ if (label_stack_depth > 0) { switch (proto) { case ETHERTYPE_IP: case PPP_IP: /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IP); case ETHERTYPE_IPV6: case PPP_IPV6: /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IPV6); default: bpf_error("unsupported protocol over mpls"); /* NOTREACHED */ } } switch (linktype) { case DLT_EN10MB: return gen_ether_linktype(proto); /*NOTREACHED*/ break; case DLT_C_HDLC: switch (proto) { case LLCSAP_ISONS: proto = (proto << 8 | LLCSAP_ISONS); /* fall through */ default: return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); /*NOTREACHED*/ break; } break; case DLT_PPI: case DLT_FDDI: case DLT_IEEE802: case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: case DLT_ATM_RFC1483: case DLT_ATM_CLIP: case DLT_IP_OVER_FC: return gen_llc_linktype(proto); /*NOTREACHED*/ break; case DLT_SUNATM: /* * If "is_lane" is set, check for a LANE-encapsulated * version of this protocol, otherwise check for an * LLC-encapsulated version of this protocol. * * We assume LANE means Ethernet, not Token Ring. */ if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b0); /* * Now generate an Ethernet test. */ b1 = gen_ether_linktype(proto); gen_and(b0, b1); return b1; } else { /* * Check for LLC encapsulation and then check the * protocol. */ b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); b1 = gen_llc_linktype(proto); gen_and(b0, b1); return b1; } /*NOTREACHED*/ break; case DLT_LINUX_SLL: return gen_linux_sll_linktype(proto); /*NOTREACHED*/ break; case DLT_SLIP: case DLT_SLIP_BSDOS: case DLT_RAW: /* * These types don't provide any type field; packets * are always IPv4 or IPv6. * * XXX - for IPv4, check for a version number of 4, and, * for IPv6, check for a version number of 6? */ switch (proto) { case ETHERTYPE_IP: /* Check for a version number of 4. */ return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0); #ifdef INET6 case ETHERTYPE_IPV6: /* Check for a version number of 6. */ return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0); #endif default: return gen_false(); /* always false */ } /*NOTREACHED*/ break; case DLT_PPP: case DLT_PPP_PPPD: case DLT_PPP_SERIAL: case DLT_PPP_ETHER: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ switch (proto) { case ETHERTYPE_IP: proto = PPP_IP; break; #ifdef INET6 case ETHERTYPE_IPV6: proto = PPP_IPV6; break; #endif case ETHERTYPE_DN: proto = PPP_DECNET; break; case ETHERTYPE_ATALK: proto = PPP_APPLE; break; case ETHERTYPE_NS: proto = PPP_NS; break; case LLCSAP_ISONS: proto = PPP_OSI; break; case LLCSAP_8021D: /* * I'm assuming the "Bridging PDU"s that go * over PPP are Spanning Tree Protocol * Bridging PDUs. */ proto = PPP_BRPDU; break; case LLCSAP_IPX: proto = PPP_IPX; break; } break; case DLT_PPP_BSDOS: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ switch (proto) { case ETHERTYPE_IP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC); gen_or(b0, b1); b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC); gen_or(b1, b0); return b0; #ifdef INET6 case ETHERTYPE_IPV6: proto = PPP_IPV6; /* more to go? */ break; #endif case ETHERTYPE_DN: proto = PPP_DECNET; break; case ETHERTYPE_ATALK: proto = PPP_APPLE; break; case ETHERTYPE_NS: proto = PPP_NS; break; case LLCSAP_ISONS: proto = PPP_OSI; break; case LLCSAP_8021D: /* * I'm assuming the "Bridging PDU"s that go * over PPP are Spanning Tree Protocol * Bridging PDUs. */ proto = PPP_BRPDU; break; case LLCSAP_IPX: proto = PPP_IPX; break; } break; case DLT_NULL: case DLT_LOOP: case DLT_ENC: /* * For DLT_NULL, the link-layer header is a 32-bit * word containing an AF_ value in *host* byte order, * and for DLT_ENC, the link-layer header begins * with a 32-bit work containing an AF_ value in * host byte order. * * In addition, if we're reading a saved capture file, * the host byte order in the capture may not be the * same as the host byte order on this machine. * * For DLT_LOOP, the link-layer header is a 32-bit * word containing an AF_ value in *network* byte order. * * XXX - AF_ values may, unfortunately, be platform- * dependent; for example, FreeBSD's AF_INET6 is 24 * whilst NetBSD's and OpenBSD's is 26. * * This means that, when reading a capture file, just * checking for our AF_INET6 value won't work if the * capture file came from another OS. */ switch (proto) { case ETHERTYPE_IP: proto = AF_INET; break; #ifdef INET6 case ETHERTYPE_IPV6: proto = AF_INET6; break; #endif default: /* * Not a type on which we support filtering. * XXX - support those that have AF_ values * #defined on this platform, at least? */ return gen_false(); } if (linktype == DLT_NULL || linktype == DLT_ENC) { /* * The AF_ value is in host byte order, but * the BPF interpreter will convert it to * network byte order. * * If this is a save file, and it's from a * machine with the opposite byte order to * ours, we byte-swap the AF_ value. * * Then we run it through "htonl()", and * generate code to compare against the result. */ if (bpf_pcap->sf.rfile != NULL && bpf_pcap->sf.swapped) proto = SWAPLONG(proto); proto = htonl(proto); } return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto)); case DLT_PFLOG: /* * af field is host byte order in contrast to the rest of * the packet. */ if (proto == ETHERTYPE_IP) return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET)); #ifdef INET6 else if (proto == ETHERTYPE_IPV6) return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET6)); #endif /* INET6 */ else return gen_false(); /*NOTREACHED*/ break; case DLT_ARCNET: case DLT_ARCNET_LINUX: /* * XXX should we check for first fragment if the protocol * uses PHDS? */ switch (proto) { default: return gen_false(); #ifdef INET6 case ETHERTYPE_IPV6: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_INET6)); #endif /* INET6 */ case ETHERTYPE_IP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_ARP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_REVARP: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_REVARP)); case ETHERTYPE_ATALK: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ATALK)); } /*NOTREACHED*/ break; case DLT_LTALK: switch (proto) { case ETHERTYPE_ATALK: return gen_true(); default: return gen_false(); } /*NOTREACHED*/ break; case DLT_FRELAY: /* * XXX - assumes a 2-byte Frame Relay header with * DLCI and flags. What if the address is longer? */ switch (proto) { case ETHERTYPE_IP: /* * Check for the special NLPID for IP. */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc); #ifdef INET6 case ETHERTYPE_IPV6: /* * Check for the special NLPID for IPv6. */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e); #endif case LLCSAP_ISONS: /* * Check for several OSI protocols. * * Frame Relay packets typically have an OSI * NLPID at the beginning; we check for each * of them. * * What we check for is the NLPID and a frame * control field of UI, i.e. 0x03 followed * by the NLPID. */ b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP); b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS); b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS); gen_or(b1, b2); gen_or(b0, b2); return b2; default: return gen_false(); } /*NOTREACHED*/ break; case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: case DLT_JUNIPER_ATM2: case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_PPPOE_ATM: case DLT_JUNIPER_GGSN: case DLT_JUNIPER_ES: case DLT_JUNIPER_MONITOR: case DLT_JUNIPER_SERVICES: case DLT_JUNIPER_ETHER: case DLT_JUNIPER_PPP: case DLT_JUNIPER_FRELAY: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_VP: /* just lets verify the magic number for now - * on ATM we may have up to 6 different encapsulations on the wire * and need a lot of heuristics to figure out that the payload * might be; * * FIXME encapsulation specific BPF_ filters */ return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ case DLT_LINUX_IRDA: bpf_error("IrDA link-layer type filtering not implemented"); case DLT_DOCSIS: bpf_error("DOCSIS link-layer type filtering not implemented"); case DLT_LINUX_LAPD: bpf_error("LAPD link-layer type filtering not implemented"); } /* * All the types that have no encapsulation should either be * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if * all packets are IP packets, or should be handled in some * special case, if none of them are (if some are and some * aren't, the lack of encapsulation is a problem, as we'd * have to find some other way of determining the packet type). * * Therefore, if "off_linktype" is -1, there's an error. */ if (off_linktype == (u_int)-1) abort(); /* * Any type not handled above should always have an Ethernet * type at an offset of "off_linktype". (PPP is partially * handled above - the protocol type is mapped from the * Ethernet and LLC types we use internally to the corresponding * PPP type - but the PPP type is always specified by a value * at "off_linktype", so we don't have to do the code generation * above.) */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } /* * Check for an LLC SNAP packet with a given organization code and * protocol type; we check the entire contents of the 802.2 LLC and * snap headers, checking for DSAP and SSAP of SNAP and a control * field of 0x03 in the LLC header, and for the specified organization * code and protocol type in the SNAP header. */ static struct block * gen_snap(orgcode, ptype, offset) bpf_u_int32 orgcode; bpf_u_int32 ptype; u_int offset; { u_char snapblock[8]; snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */ snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */ snapblock[2] = 0x03; /* control = UI */ snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */ snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */ snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */ snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */ snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */ return gen_bcmp(OR_LINK, offset, 8, snapblock); } /* * Generate code to match a particular packet type, for link-layer types * using 802.2 LLC headers. * * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the DSAP or both DSAP and LSAP or to check the OUI and * protocol ID in a SNAP header. */ static struct block * gen_llc_linktype(proto) int proto; { /* * XXX - handle token-ring variable-length header. */ switch (proto) { case LLCSAP_IP: case LLCSAP_ISONS: case LLCSAP_NETBEUI: /* * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_u_int32) ((proto << 8) | proto)); case LLCSAP_IPX: /* * XXX - are there ever SNAP frames for IPX on * non-Ethernet 802.x networks? */ return gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)LLCSAP_IPX); case ETHERTYPE_ATALK: /* * 802.2-encapsulated ETHERTYPE_ATALK packets are * SNAP packets with an organization code of * 0x080007 (Apple, for Appletalk) and a protocol * type of ETHERTYPE_ATALK (Appletalk). * * XXX - check for an organization code of * encapsulated Ethernet as well? */ return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype); default: /* * XXX - we don't have to check for IPX 802.3 * here, but should we check for the IPX Ethertype? */ if (proto <= ETHERMTU) { /* * This is an LLC SAP value, so check * the DSAP. */ return gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)proto); } else { /* * This is an Ethernet type; we assume that it's * unlikely that it'll appear in the right place * at random, and therefore check only the * location that would hold the Ethernet type * in a SNAP frame with an organization code of * 0x000000 (encapsulated Ethernet). * * XXX - if we were to check for the SNAP DSAP and * LSAP, as per XXX, and were also to check for an * organization code of 0x000000 (encapsulated * Ethernet), we'd do * * return gen_snap(0x000000, proto, * off_linktype); * * here; for now, we don't, as per the above. * I don't know whether it's worth the extra CPU * time to do the right check or not. */ return gen_cmp(OR_LINK, off_linktype+6, BPF_H, (bpf_int32)proto); } } } 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(OR_NET, offset, BPF_W, (bpf_int32)addr, mask); gen_and(b0, b1); return b1; } #ifdef INET6 static struct block * gen_hostop6(addr, mask, dir, proto, src_off, dst_off) struct in6_addr *addr; struct in6_addr *mask; int dir, proto; u_int src_off, dst_off; { struct block *b0, *b1; u_int offset; u_int32_t *a, *m; switch (dir) { case Q_SRC: offset = src_off; break; case Q_DST: offset = dst_off; break; case Q_AND: b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); gen_and(b0, b1); return b1; case Q_OR: case Q_DEFAULT: b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); gen_or(b0, b1); return b1; default: abort(); } /* this order is important */ a = (u_int32_t *)addr; m = (u_int32_t *)mask; b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); gen_and(b0, b1); b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); gen_and(b0, b1); b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0])); gen_and(b0, b1); b0 = gen_linktype(proto); gen_and(b0, b1); return b1; } #endif /*INET6*/ 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(OR_LINK, off_mac + 6, 6, eaddr); case Q_DST: return gen_bcmp(OR_LINK, off_mac + 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(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr); #else return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr); #endif case Q_DST: #ifdef PCAP_FDDIPAD return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr); #else return gen_bcmp(OR_LINK, 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 */ } /* * Like gen_ehostop, but for DLT_IEEE802 (Token Ring) */ static struct block * gen_thostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1; switch (dir) { case Q_SRC: return gen_bcmp(OR_LINK, 8, 6, eaddr); case Q_DST: return gen_bcmp(OR_LINK, 2, 6, eaddr); case Q_AND: b0 = gen_thostop(eaddr, Q_SRC); b1 = gen_thostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_thostop(eaddr, Q_SRC); b1 = gen_thostop(eaddr, Q_DST); gen_or(b0, b1); return b1; } abort(); /* NOTREACHED */ } /* * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) */ static struct block * gen_wlanhostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1, *b2; register struct slist *s; switch (dir) { case Q_SRC: /* * Oh, yuk. * * For control frames, there is no SA. * * For management frames, SA is at an * offset of 10 from the beginning of * the packet. * * For data frames, SA is at an offset * of 10 from the beginning of the packet * if From DS is clear, at an offset of * 16 from the beginning of the packet * if From DS is set and To DS is clear, * and an offset of 24 from the beginning * of the packet if From DS is set and To DS * is set. */ /* * Generate the tests to be done for data frames * with From DS set. * * First, check for To DS set, i.e. check "link[1] & 0x01". */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; /* * If To DS is set, the SA is at 24. */ b0 = gen_bcmp(OR_LINK, 24, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; gen_not(b2); /* * If To DS is not set, the SA is at 16. */ b1 = gen_bcmp(OR_LINK, 16, 6, eaddr); gen_and(b2, b1); /* * Now OR together the last two checks. That gives * the complete set of checks for data frames with * From DS set. */ gen_or(b1, b0); /* * Now check for From DS being set, and AND that with * the ORed-together checks. */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x02; /* From DS */ b1->stmts = s; gen_and(b1, b0); /* * Now check for data frames with From DS not set. */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x02; /* From DS */ b2->stmts = s; gen_not(b2); /* * If From DS isn't set, the SA is at 10. */ b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); /* * Now OR together the checks for data frames with * From DS not set and for data frames with From DS * set; that gives the checks done for data frames. */ gen_or(b1, b0); /* * Now check for a data frame. * I.e, check "link[0] & 0x08". */ gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the checks done for data frames. */ gen_and(b1, b0); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "!(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; gen_not(b2); /* * For management frames, the SA is at 10. */ b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); /* * OR that with the checks done for data frames. * That gives the checks done for management and * data frames. */ gen_or(b1, b0); /* * If the low-order bit of the type value is 1, * this is either a control frame or a frame * with a reserved type, and thus not a * frame with an SA. * * I.e., check "!(link[0] & 0x04)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); /* * AND that with the checks for data and management * frames. */ gen_and(b1, b0); return b0; case Q_DST: /* * Oh, yuk. * * For control frames, there is no DA. * * For management frames, DA is at an * offset of 4 from the beginning of * the packet. * * For data frames, DA is at an offset * of 4 from the beginning of the packet * if To DS is clear and at an offset of * 16 from the beginning of the packet * if To DS is set. */ /* * Generate the tests to be done for data frames. * * First, check for To DS set, i.e. "link[1] & 0x01". */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; /* * If To DS is set, the DA is at 16. */ b0 = gen_bcmp(OR_LINK, 16, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; gen_not(b2); /* * If To DS is not set, the DA is at 4. */ b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); gen_and(b2, b1); /* * Now OR together the last two checks. That gives * the complete set of checks for data frames. */ gen_or(b1, b0); /* * Now check for a data frame. * I.e, check "link[0] & 0x08". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the checks done for data frames. */ gen_and(b1, b0); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "!(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; gen_not(b2); /* * For management frames, the DA is at 4. */ b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); gen_and(b2, b1); /* * OR that with the checks done for data frames. * That gives the checks done for management and * data frames. */ gen_or(b1, b0); /* * If the low-order bit of the type value is 1, * this is either a control frame or a frame * with a reserved type, and thus not a * frame with an SA. * * I.e., check "!(link[0] & 0x04)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); /* * AND that with the checks for data and management * frames. */ gen_and(b1, b0); return b0; case Q_AND: b0 = gen_wlanhostop(eaddr, Q_SRC); b1 = gen_wlanhostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_wlanhostop(eaddr, Q_SRC); b1 = gen_wlanhostop(eaddr, Q_DST); gen_or(b0, b1); return b1; } abort(); /* NOTREACHED */ } /* * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel. * (We assume that the addresses are IEEE 48-bit MAC addresses, * as the RFC states.) */ static struct block * gen_ipfchostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1; switch (dir) { case Q_SRC: return gen_bcmp(OR_LINK, 10, 6, eaddr); case Q_DST: return gen_bcmp(OR_LINK, 2, 6, eaddr); case Q_AND: b0 = gen_ipfchostop(eaddr, Q_SRC); b1 = gen_ipfchostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_ipfchostop(eaddr, Q_SRC); b1 = gen_ipfchostop(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) bpf_u_int32 addr; int dir; { 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); b1 = gen_dnhostop(addr, Q_DST); 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); b1 = gen_dnhostop(addr, Q_DST); gen_or(b0, b1); return b1; case Q_ISO: bpf_error("ISO host filtering not implemented"); default: abort(); } b0 = gen_linktype(ETHERTYPE_DN); /* Check for pad = 1, long header case */ tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF)); b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b1); /* Check for pad = 0, long header case */ tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7); b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 1, short header case */ tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF)); b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 0, short header case */ tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7); b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Combine with test for linktype */ gen_and(b0, b1); return b1; } /* * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets; * test the bottom-of-stack bit, and then check the version number * field in the IP header. */ static struct block * gen_mpls_linktype(proto) int proto; { struct block *b0, *b1; switch (proto) { case Q_IP: /* match the bottom-of-stack bit */ b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01); /* match the IPv4 version number */ b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x40, 0xf0); gen_and(b0, b1); return b1; case Q_IPV6: /* match the bottom-of-stack bit */ b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01); /* match the IPv4 version number */ b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0); gen_and(b0, b1); return b1; default: abort(); } } static struct block * gen_host(addr, mask, proto, dir, type) bpf_u_int32 addr; bpf_u_int32 mask; int proto; int dir; int type; { struct block *b0, *b1; const char *typestr; if (type == Q_NET) typestr = "net"; else typestr = "host"; switch (proto) { case Q_DEFAULT: b0 = gen_host(addr, mask, Q_IP, dir, type); /* * Only check for non-IPv4 addresses if we're not * checking MPLS-encapsulated packets. */ if (label_stack_depth == 0) { b1 = gen_host(addr, mask, Q_ARP, dir, type); gen_or(b0, b1); b0 = gen_host(addr, mask, Q_RARP, dir, type); gen_or(b1, b0); } return b0; case Q_IP: return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16); case Q_RARP: return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24); case Q_ARP: return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24); case Q_TCP: bpf_error("'tcp' modifier applied to %s", typestr); case Q_SCTP: bpf_error("'sctp' modifier applied to %s", typestr); case Q_UDP: bpf_error("'udp' modifier applied to %s", typestr); case Q_ICMP: bpf_error("'icmp' modifier applied to %s", typestr); case Q_IGMP: bpf_error("'igmp' modifier applied to %s", typestr); case Q_IGRP: bpf_error("'igrp' modifier applied to %s", typestr); case Q_PIM: bpf_error("'pim' modifier applied to %s", typestr); case Q_VRRP: bpf_error("'vrrp' modifier applied to %s", typestr); case Q_ATALK: bpf_error("ATALK host filtering not implemented"); case Q_AARP: bpf_error("AARP host filtering not implemented"); case Q_DECNET: return gen_dnhostop(addr, dir); 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"); #ifdef INET6 case Q_IPV6: bpf_error("'ip6' modifier applied to ip host"); case Q_ICMPV6: bpf_error("'icmp6' modifier applied to %s", typestr); #endif /* INET6 */ case Q_AH: bpf_error("'ah' modifier applied to %s", typestr); case Q_ESP: bpf_error("'esp' modifier applied to %s", typestr); case Q_ISO: bpf_error("ISO host filtering not implemented"); case Q_ESIS: bpf_error("'esis' modifier applied to %s", typestr); case Q_ISIS: bpf_error("'isis' modifier applied to %s", typestr); case Q_CLNP: bpf_error("'clnp' modifier applied to %s", typestr); case Q_STP: bpf_error("'stp' modifier applied to %s", typestr); case Q_IPX: bpf_error("IPX host filtering not implemented"); case Q_NETBEUI: bpf_error("'netbeui' modifier applied to %s", typestr); case Q_RADIO: bpf_error("'radio' modifier applied to %s", typestr); default: abort(); } /* NOTREACHED */ } #ifdef INET6 static struct block * gen_host6(addr, mask, proto, dir, type) struct in6_addr *addr; struct in6_addr *mask; int proto; int dir; int type; { const char *typestr; if (type == Q_NET) typestr = "net"; else typestr = "host"; switch (proto) { case Q_DEFAULT: return gen_host6(addr, mask, Q_IPV6, dir, type); case Q_IP: bpf_error("'ip' modifier applied to ip6 %s", typestr); case Q_RARP: bpf_error("'rarp' modifier applied to ip6 %s", typestr); case Q_ARP: bpf_error("'arp' modifier applied to ip6 %s", typestr); case Q_SCTP: bpf_error("'sctp' modifier applied to %s", typestr); case Q_TCP: bpf_error("'tcp' modifier applied to %s", typestr); case Q_UDP: bpf_error("'udp' modifier applied to %s", typestr); case Q_ICMP: bpf_error("'icmp' modifier applied to %s", typestr); case Q_IGMP: bpf_error("'igmp' modifier applied to %s", typestr); case Q_IGRP: bpf_error("'igrp' modifier applied to %s", typestr); case Q_PIM: bpf_error("'pim' modifier applied to %s", typestr); case Q_VRRP: bpf_error("'vrrp' modifier applied to %s", typestr); case Q_ATALK: bpf_error("ATALK host filtering not implemented"); case Q_AARP: bpf_error("AARP host filtering not implemented"); case Q_DECNET: bpf_error("'decnet' modifier applied to ip6 %s", typestr); 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"); case Q_IPV6: return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24); case Q_ICMPV6: bpf_error("'icmp6' modifier applied to %s", typestr); case Q_AH: bpf_error("'ah' modifier applied to %s", typestr); case Q_ESP: bpf_error("'esp' modifier applied to %s", typestr); case Q_ISO: bpf_error("ISO host filtering not implemented"); case Q_ESIS: bpf_error("'esis' modifier applied to %s", typestr); case Q_ISIS: bpf_error("'isis' modifier applied to %s", typestr); case Q_CLNP: bpf_error("'clnp' modifier applied to %s", typestr); case Q_STP: bpf_error("'stp' modifier applied to %s", typestr); case Q_IPX: bpf_error("IPX host filtering not implemented"); case Q_NETBEUI: bpf_error("'netbeui' modifier applied to %s", typestr); case Q_RADIO: bpf_error("'radio' modifier applied to %s", typestr); default: abort(); } /* NOTREACHED */ } #endif /*INET6*/ #ifndef INET6 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: switch (linktype) { case DLT_EN10MB: b0 = gen_ehostop(eaddr, Q_OR); break; case DLT_FDDI: b0 = gen_fhostop(eaddr, Q_OR); break; case DLT_IEEE802: b0 = gen_thostop(eaddr, Q_OR); break; case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_PPI: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: b0 = gen_wlanhostop(eaddr, Q_OR); break; case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b1); /* * Now check the MAC address. */ b0 = gen_ehostop(eaddr, Q_OR); gen_and(b1, b0); } break; case DLT_IP_OVER_FC: b0 = gen_ipfchostop(eaddr, Q_OR); break; default: bpf_error( "'gateway' supported only on ethernet/FDDI/token ring/802.11/Fibre Channel"); } b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST); while (*alist) { tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST); gen_or(b1, tmp); b1 = tmp; } gen_not(b1); gen_and(b0, b1); return b1; } bpf_error("illegal modifier of 'gateway'"); /* NOTREACHED */ } #endif struct block * gen_proto_abbrev(proto) int proto; { struct block *b0; struct block *b1; switch (proto) { case Q_SCTP: b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; case Q_TCP: b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; case Q_UDP: b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; case Q_ICMP: b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_IGMP #define IPPROTO_IGMP 2 #endif case Q_IGMP: b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_IGRP #define IPPROTO_IGRP 9 #endif case Q_IGRP: b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_PIM #define IPPROTO_PIM 103 #endif case Q_PIM: b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; #ifndef IPPROTO_VRRP #define IPPROTO_VRRP 112 #endif case Q_VRRP: b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT); 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_AARP: b1 = gen_linktype(ETHERTYPE_AARP); 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; #ifdef INET6 case Q_IPV6: b1 = gen_linktype(ETHERTYPE_IPV6); break; #ifndef IPPROTO_ICMPV6 #define IPPROTO_ICMPV6 58 #endif case Q_ICMPV6: b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT); break; #endif /* INET6 */ #ifndef IPPROTO_AH #define IPPROTO_AH 51 #endif case Q_AH: b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; #ifndef IPPROTO_ESP #define IPPROTO_ESP 50 #endif case Q_ESP: b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; case Q_ISO: b1 = gen_linktype(LLCSAP_ISONS); break; case Q_ESIS: b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS: b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */ b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_LSP: b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_SNP: b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_CSNP: b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_PSNP: b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_CLNP: b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); break; case Q_STP: b1 = gen_linktype(LLCSAP_8021D); break; case Q_IPX: b1 = gen_linktype(LLCSAP_IPX); break; case Q_NETBEUI: b1 = gen_linktype(LLCSAP_NETBEUI); break; case Q_RADIO: bpf_error("'radio' is not a valid protocol type"); default: abort(); } return b1; } static struct block * gen_ipfrag() { struct slist *s; struct block *b; /* not ip frag */ s = gen_load_a(OR_NET, 6, BPF_H); b = new_block(JMP(BPF_JSET)); b->s.k = 0x1fff; b->stmts = s; gen_not(b); return b; } /* * Generate a comparison to a port value in the transport-layer header * at the specified offset from the beginning of that header. * * XXX - this handles a variable-length prefix preceding the link-layer * header, such as the radiotap or AVS radio prefix, but doesn't handle * variable-length link-layer headers (such as Token Ring or 802.11 * headers). */ static struct block * gen_portatom(off, v) int off; bpf_int32 v; { return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v); } #ifdef INET6 static struct block * gen_portatom6(off, v) int off; bpf_int32 v; { return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v); } #endif/*INET6*/ struct block * gen_portop(port, proto, dir) int port, proto, dir; { struct block *b0, *b1, *tmp; /* ip proto 'proto' */ tmp = gen_cmp(OR_NET, 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 * * For FDDI, RFC 1188 says that SNAP encapsulation is used, * not LLC encapsulation with LLCSAP_IP. * * For IEEE 802 networks - which includes 802.5 token ring * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042 * says that SNAP encapsulation is used, not LLC encapsulation * with LLCSAP_IP. * * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and * RFC 2225 say that SNAP encapsulation is used, not LLC * encapsulation with LLCSAP_IP. * * So we always check for ETHERTYPE_IP. */ b0 = gen_linktype(ETHERTYPE_IP); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: 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); tmp = gen_portop(port, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } #ifdef INET6 struct block * gen_portop6(port, proto, dir) int port, proto, dir; { struct block *b0, *b1, *tmp; /* ip6 proto 'proto' */ b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); switch (dir) { case Q_SRC: b1 = gen_portatom6(0, (bpf_int32)port); break; case Q_DST: b1 = gen_portatom6(2, (bpf_int32)port); break; case Q_OR: case Q_DEFAULT: tmp = gen_portatom6(0, (bpf_int32)port); b1 = gen_portatom6(2, (bpf_int32)port); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portatom6(0, (bpf_int32)port); b1 = gen_portatom6(2, (bpf_int32)port); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_port6(port, ip_proto, dir) int port; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* link proto ip6 */ b0 = gen_linktype(ETHERTYPE_IPV6); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portop6(port, ip_proto, dir); break; case PROTO_UNDEF: tmp = gen_portop6(port, IPPROTO_TCP, dir); b1 = gen_portop6(port, IPPROTO_UDP, dir); gen_or(tmp, b1); tmp = gen_portop6(port, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } #endif /* INET6 */ /* gen_portrange code */ static struct block * gen_portrangeatom(off, v1, v2) int off; bpf_int32 v1, v2; { struct block *b1, *b2; if (v1 > v2) { /* * Reverse the order of the ports, so v1 is the lower one. */ bpf_int32 vtemp; vtemp = v1; v1 = v2; v2 = vtemp; } b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1); b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2); gen_and(b1, b2); return b2; } struct block * gen_portrangeop(port1, port2, proto, dir) int port1, port2; int proto; int dir; { struct block *b0, *b1, *tmp; /* ip proto 'proto' */ tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); b0 = gen_ipfrag(); gen_and(tmp, b0); switch (dir) { case Q_SRC: b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); break; case Q_DST: b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); break; case Q_OR: case Q_DEFAULT: tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_portrange(port1, port2, ip_proto, dir) int port1, port2; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* link proto ip */ b0 = gen_linktype(ETHERTYPE_IP); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portrangeop(port1, port2, ip_proto, dir); break; case PROTO_UNDEF: tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir); b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir); gen_or(tmp, b1); tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } #ifdef INET6 static struct block * gen_portrangeatom6(off, v1, v2) int off; bpf_int32 v1, v2; { struct block *b1, *b2; if (v1 > v2) { /* * Reverse the order of the ports, so v1 is the lower one. */ bpf_int32 vtemp; vtemp = v1; v1 = v2; v2 = vtemp; } b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1); b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2); gen_and(b1, b2); return b2; } struct block * gen_portrangeop6(port1, port2, proto, dir) int port1, port2; int proto; int dir; { struct block *b0, *b1, *tmp; /* ip6 proto 'proto' */ b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); switch (dir) { case Q_SRC: b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); break; case Q_DST: b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); break; case Q_OR: case Q_DEFAULT: tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_portrange6(port1, port2, ip_proto, dir) int port1, port2; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* link proto ip6 */ b0 = gen_linktype(ETHERTYPE_IPV6); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portrangeop6(port1, port2, ip_proto, dir); break; case PROTO_UNDEF: tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir); b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir); gen_or(tmp, b1); tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } #endif /* INET6 */ static int lookup_proto(name, proto) register const char *name; register int proto; { register int v; switch (proto) { case Q_DEFAULT: case Q_IP: case Q_IPV6: 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) { v = pcap_nametollc(name); if (v == PROTO_UNDEF) bpf_error("unknown ether proto '%s'", name); } break; case Q_ISO: if (strcmp(name, "esis") == 0) v = ISO9542_ESIS; else if (strcmp(name, "isis") == 0) v = ISO10589_ISIS; else if (strcmp(name, "clnp") == 0) v = ISO8473_CLNP; else bpf_error("unknown osi proto '%s'", name); break; default: v = PROTO_UNDEF; break; } return v; } #if 0 struct stmt * gen_joinsp(s, n) struct stmt **s; int n; { return NULL; } #endif static struct block * gen_protochain(v, proto, dir) int v; int proto; int dir; { #ifdef NO_PROTOCHAIN return gen_proto(v, proto, dir); #else struct block *b0, *b; struct slist *s[100]; int fix2, fix3, fix4, fix5; int ahcheck, again, end; int i, max; int reg2 = alloc_reg(); memset(s, 0, sizeof(s)); fix2 = fix3 = fix4 = fix5 = 0; switch (proto) { case Q_IP: case Q_IPV6: break; case Q_DEFAULT: b0 = gen_protochain(v, Q_IP, dir); b = gen_protochain(v, Q_IPV6, dir); gen_or(b0, b); return b; default: bpf_error("bad protocol applied for 'protochain'"); /*NOTREACHED*/ } /* * We don't handle variable-length radiotap here headers yet. * We might want to add BPF instructions to do the protochain * work, to simplify that and, on platforms that have a BPF * interpreter with the new instructions, let the filtering * be done in the kernel. (We already require a modified BPF * engine to do the protochain stuff, to support backward * branches, and backward branch support is unlikely to appear * in kernel BPF engines.) */ if (linktype == DLT_IEEE802_11_RADIO) bpf_error("'protochain' not supported with radiotap headers"); if (linktype == DLT_PPI) bpf_error("'protochain' not supported with PPI headers"); no_optimize = 1; /*this code is not compatible with optimzer yet */ /* * s[0] is a dummy entry to protect other BPF insn from damage * by s[fix] = foo with uninitialized variable "fix". It is somewhat * hard to find interdependency made by jump table fixup. */ i = 0; s[i] = new_stmt(0); /*dummy*/ i++; switch (proto) { case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); /* A = ip->ip_p */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); s[i]->s.k = off_ll + off_nl + 9; i++; /* X = ip->ip_hl << 2 */ s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s[i]->s.k = off_ll + off_nl; i++; break; #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); /* A = ip6->ip_nxt */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); s[i]->s.k = off_ll + off_nl + 6; i++; /* X = sizeof(struct ip6_hdr) */ s[i] = new_stmt(BPF_LDX|BPF_IMM); s[i]->s.k = 40; i++; break; #endif default: bpf_error("unsupported proto to gen_protochain"); /*NOTREACHED*/ } /* again: if (A == v) goto end; else fall through; */ again = i; s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.k = v; s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ fix5 = i; i++; #ifndef IPPROTO_NONE #define IPPROTO_NONE 59 #endif /* if (A == IPPROTO_NONE) goto end */ s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_NONE; s[fix5]->s.jf = s[i]; fix2 = i; i++; #ifdef INET6 if (proto == Q_IPV6) { int v6start, v6end, v6advance, j; v6start = i; /* if (A == IPPROTO_HOPOPTS) goto v6advance */ s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_HOPOPTS; s[fix2]->s.jf = s[i]; i++; /* if (A == IPPROTO_DSTOPTS) goto v6advance */ s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_DSTOPTS; i++; /* if (A == IPPROTO_ROUTING) goto v6advance */ s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_ROUTING; i++; /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */ s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*later*/ s[i]->s.k = IPPROTO_FRAGMENT; fix3 = i; v6end = i; i++; /* v6advance: */ v6advance = i; /* * in short, * A = P[X]; * X = X + (P[X + 1] + 1) * 8; */ /* A = X */ s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_ll + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); s[i]->s.k = reg2; i++; /* A = X */ s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 1; i++; /* X = A */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = P[X + packet head]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_ll + off_nl; i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 1; i++; /* A *= 8 */ s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); s[i]->s.k = 8; i++; /* X = A; */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = MEM[reg2] */ s[i] = new_stmt(BPF_LD|BPF_MEM); s[i]->s.k = reg2; i++; /* goto again; (must use BPF_JA for backward jump) */ s[i] = new_stmt(BPF_JMP|BPF_JA); s[i]->s.k = again - i - 1; s[i - 1]->s.jf = s[i]; i++; /* fixup */ for (j = v6start; j <= v6end; j++) s[j]->s.jt = s[v6advance]; } else #endif { /* nop */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 0; s[fix2]->s.jf = s[i]; i++; } /* ahcheck: */ ahcheck = i; /* if (A == IPPROTO_AH) then fall through; else goto end; */ s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*later*/ s[i]->s.k = IPPROTO_AH; if (fix3) s[fix3]->s.jf = s[ahcheck]; fix4 = i; i++; /* * in short, * A = P[X]; * X = X + (P[X + 1] + 2) * 4; */ /* A = X */ s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A = P[X + packet head]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_ll + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); s[i]->s.k = reg2; i++; /* A = X */ s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 1; i++; /* X = A */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_ll + off_nl; i++; /* A += 2 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 2; i++; /* A *= 4 */ s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); s[i]->s.k = 4; i++; /* X = A; */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = MEM[reg2] */ s[i] = new_stmt(BPF_LD|BPF_MEM); s[i]->s.k = reg2; i++; /* goto again; (must use BPF_JA for backward jump) */ s[i] = new_stmt(BPF_JMP|BPF_JA); s[i]->s.k = again - i - 1; i++; /* end: nop */ end = i; s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 0; s[fix2]->s.jt = s[end]; s[fix4]->s.jf = s[end]; s[fix5]->s.jt = s[end]; i++; /* * make slist chain */ max = i; for (i = 0; i < max - 1; i++) s[i]->next = s[i + 1]; s[max - 1]->next = NULL; /* * emit final check */ b = new_block(JMP(BPF_JEQ)); b->stmts = s[1]; /*remember, s[0] is dummy*/ b->s.k = v; free_reg(reg2); gen_and(b0, b); return b; #endif } /* * Generate code that checks whether the packet is a packet for protocol * and whether the type field in that protocol's header has * the value , e.g. if is Q_IP, it checks whether it's an * IP packet and checks the protocol number in the IP header against . * * If is Q_DEFAULT, i.e. just "proto" was specified, it checks * against Q_IP and Q_IPV6. */ 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: #ifdef INET6 b0 = gen_proto(v, Q_IP, dir); b1 = gen_proto(v, Q_IPV6, dir); gen_or(b0, b1); return b1; #else /*FALLTHROUGH*/ #endif case Q_IP: /* * For FDDI, RFC 1188 says that SNAP encapsulation is used, * not LLC encapsulation with LLCSAP_IP. * * For IEEE 802 networks - which includes 802.5 token ring * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042 * says that SNAP encapsulation is used, not LLC encapsulation * with LLCSAP_IP. * * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and * RFC 2225 say that SNAP encapsulation is used, not LLC * encapsulation with LLCSAP_IP. * * So we always check for ETHERTYPE_IP. */ b0 = gen_linktype(ETHERTYPE_IP); #ifndef CHASE_CHAIN b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v); #else b1 = gen_protochain(v, Q_IP); #endif gen_and(b0, b1); return b1; case Q_ISO: switch (linktype) { case DLT_FRELAY: /* * Frame Relay packets typically have an OSI * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)" * generates code to check for all the OSI * NLPIDs, so calling it and then adding a check * for the particular NLPID for which we're * looking is bogus, as we can just check for * the NLPID. * * What we check for is the NLPID and a frame * control field value of UI, i.e. 0x03 followed * by the NLPID. * * XXX - assumes a 2-byte Frame Relay header with * DLCI and flags. What if the address is longer? * * XXX - what about SNAP-encapsulated frames? */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v); /*NOTREACHED*/ break; case DLT_C_HDLC: /* * Cisco uses an Ethertype lookalike - for OSI, * it's 0xfefe. */ b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS); /* OSI in C-HDLC is stuffed with a fudge byte */ b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v); gen_and(b0, b1); return b1; default: b0 = gen_linktype(LLCSAP_ISONS); b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v); gen_and(b0, b1); return b1; } case Q_ISIS: b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); /* * 4 is the offset of the PDU type relative to the IS-IS * header. */ b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)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_SCTP: bpf_error("'sctp 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 */ case Q_PIM: bpf_error("'pim proto' is bogus"); /* NOTREACHED */ case Q_VRRP: bpf_error("'vrrp proto' is bogus"); /* NOTREACHED */ #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); #ifndef CHASE_CHAIN b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v); #else b1 = gen_protochain(v, Q_IPV6); #endif gen_and(b0, b1); return b1; case Q_ICMPV6: bpf_error("'icmp6 proto' is bogus"); #endif /* INET6 */ case Q_AH: bpf_error("'ah proto' is bogus"); case Q_ESP: bpf_error("'ah proto' is bogus"); case Q_STP: bpf_error("'stp proto' is bogus"); case Q_IPX: bpf_error("'ipx proto' is bogus"); case Q_NETBEUI: bpf_error("'netbeui proto' is bogus"); case Q_RADIO: bpf_error("'radio proto' is bogus"); 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; #ifndef INET6 bpf_u_int32 **alist; #else int tproto6; struct sockaddr_in *sin4; struct sockaddr_in6 *sin6; struct addrinfo *res, *res0; struct in6_addr mask128; #endif /*INET6*/ struct block *b, *tmp; int port, real_proto; int port1, port2; 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, q.addr); 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); b = gen_ehostop(eaddr, dir); free(eaddr); return b; case DLT_FDDI: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown FDDI host '%s'", name); b = gen_fhostop(eaddr, dir); free(eaddr); return b; case DLT_IEEE802: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown token ring host '%s'", name); b = gen_thostop(eaddr, dir); free(eaddr); return b; case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: case DLT_PPI: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown 802.11 host '%s'", name); b = gen_wlanhostop(eaddr, dir); free(eaddr); return b; case DLT_IP_OVER_FC: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown Fibre Channel host '%s'", name); b = gen_ipfchostop(eaddr, dir); free(eaddr); return b; case DLT_SUNATM: if (!is_lane) break; /* * Check that the packet doesn't begin * with an LE Control marker. (We've * already generated a test for LANE.) */ tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(tmp); eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown ether host '%s'", name); b = gen_ehostop(eaddr, dir); gen_and(tmp, b); free(eaddr); return b; } bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name"); } 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, q.addr)); } else { #ifndef INET6 alist = pcap_nametoaddr(name); if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); tproto = proto; if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT) tproto = Q_IP; b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr); while (*alist) { tmp = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr); gen_or(b, tmp); b = tmp; } return b; #else memset(&mask128, 0xff, sizeof(mask128)); res0 = res = pcap_nametoaddrinfo(name); if (res == NULL) bpf_error("unknown host '%s'", name); b = tmp = NULL; tproto = tproto6 = proto; if (off_linktype == -1 && tproto == Q_DEFAULT) { tproto = Q_IP; tproto6 = Q_IPV6; } for (res = res0; res; res = res->ai_next) { switch (res->ai_family) { case AF_INET: if (tproto == Q_IPV6) continue; sin4 = (struct sockaddr_in *) res->ai_addr; tmp = gen_host(ntohl(sin4->sin_addr.s_addr), 0xffffffff, tproto, dir, q.addr); break; case AF_INET6: if (tproto6 == Q_IP) continue; sin6 = (struct sockaddr_in6 *) res->ai_addr; tmp = gen_host6(&sin6->sin6_addr, &mask128, tproto6, dir, q.addr); break; default: continue; } if (b) gen_or(b, tmp); b = tmp; } freeaddrinfo(res0); if (b == NULL) { bpf_error("unknown host '%s'%s", name, (proto == Q_DEFAULT) ? "" : " for specified address family"); } return b; #endif /*INET6*/ } case Q_PORT: if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) 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 if (real_proto == IPPROTO_SCTP) bpf_error("port '%s' is sctp", 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 if (real_proto == IPPROTO_SCTP) bpf_error("port '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } if (proto == Q_SCTP) { if (real_proto == IPPROTO_UDP) bpf_error("port '%s' is udp", name); else if (real_proto == IPPROTO_TCP) bpf_error("port '%s' is tcp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_SCTP; } #ifndef INET6 return gen_port(port, real_proto, dir); #else b = gen_port(port, real_proto, dir); gen_or(gen_port6(port, real_proto, dir), b); return b; #endif /* INET6 */ case Q_PORTRANGE: if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) bpf_error("illegal qualifier of 'portrange'"); if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0) bpf_error("unknown port in range '%s'", name); if (proto == Q_UDP) { if (real_proto == IPPROTO_TCP) bpf_error("port in range '%s' is tcp", name); else if (real_proto == IPPROTO_SCTP) bpf_error("port in range '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_UDP; } if (proto == Q_TCP) { if (real_proto == IPPROTO_UDP) bpf_error("port in range '%s' is udp", name); else if (real_proto == IPPROTO_SCTP) bpf_error("port in range '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } if (proto == Q_SCTP) { if (real_proto == IPPROTO_UDP) bpf_error("port in range '%s' is udp", name); else if (real_proto == IPPROTO_TCP) bpf_error("port in range '%s' is tcp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_SCTP; } #ifndef INET6 return gen_portrange(port1, port2, real_proto, dir); #else b = gen_portrange(port1, port2, real_proto, dir); gen_or(gen_portrange6(port1, port2, real_proto, dir), b); return b; #endif /* INET6 */ case Q_GATEWAY: #ifndef INET6 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); b = gen_gateway(eaddr, alist, proto, dir); free(eaddr); return b; #else bpf_error("'gateway' not supported in this configuration"); #endif /*INET6*/ 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_PROTOCHAIN: real_proto = lookup_proto(name, proto); if (real_proto >= 0) return gen_protochain(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"); if (masklen == 0) { /* * X << 32 is not guaranteed by C to be 0; it's * undefined. */ m = 0; } else 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, q.addr); default: bpf_error("Mask syntax for networks only"); /* NOTREACHED */ } /* NOTREACHED */ return NULL; } 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, q.addr); 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, q.addr); } case Q_PORT: if (proto == Q_UDP) proto = IPPROTO_UDP; else if (proto == Q_TCP) proto = IPPROTO_TCP; else if (proto == Q_SCTP) proto = IPPROTO_SCTP; else if (proto == Q_DEFAULT) proto = PROTO_UNDEF; else bpf_error("illegal qualifier of 'port'"); #ifndef INET6 return gen_port((int)v, proto, dir); #else { struct block *b; b = gen_port((int)v, proto, dir); gen_or(gen_port6((int)v, proto, dir), b); return b; } #endif /* INET6 */ case Q_PORTRANGE: if (proto == Q_UDP) proto = IPPROTO_UDP; else if (proto == Q_TCP) proto = IPPROTO_TCP; else if (proto == Q_SCTP) proto = IPPROTO_SCTP; else if (proto == Q_DEFAULT) proto = PROTO_UNDEF; else bpf_error("illegal qualifier of 'portrange'"); #ifndef INET6 return gen_portrange((int)v, (int)v, proto, dir); #else { struct block *b; b = gen_portrange((int)v, (int)v, proto, dir); gen_or(gen_portrange6((int)v, (int)v, proto, dir), b); return b; } #endif /* INET6 */ case Q_GATEWAY: bpf_error("'gateway' requires a name"); /* NOTREACHED */ case Q_PROTO: return gen_proto((int)v, proto, dir); case Q_PROTOCHAIN: return gen_protochain((int)v, proto, dir); case Q_UNDEF: syntax(); /* NOTREACHED */ default: abort(); /* NOTREACHED */ } /* NOTREACHED */ } #ifdef INET6 struct block * gen_mcode6(s1, s2, masklen, q) register const char *s1, *s2; register int masklen; struct qual q; { struct addrinfo *res; struct in6_addr *addr; struct in6_addr mask; struct block *b; u_int32_t *a, *m; if (s2) bpf_error("no mask %s supported", s2); res = pcap_nametoaddrinfo(s1); if (!res) bpf_error("invalid ip6 address %s", s1); if (res->ai_next) bpf_error("%s resolved to multiple address", s1); addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; if (sizeof(mask) * 8 < masklen) bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8)); memset(&mask, 0, sizeof(mask)); memset(&mask, 0xff, masklen / 8); if (masklen % 8) { mask.s6_addr[masklen / 8] = (0xff << (8 - masklen % 8)) & 0xff; } a = (u_int32_t *)addr; m = (u_int32_t *)&mask; if ((a[0] & ~m[0]) || (a[1] & ~m[1]) || (a[2] & ~m[2]) || (a[3] & ~m[3])) { bpf_error("non-network bits set in \"%s/%d\"", s1, masklen); } switch (q.addr) { case Q_DEFAULT: case Q_HOST: if (masklen != 128) bpf_error("Mask syntax for networks only"); /* FALLTHROUGH */ case Q_NET: b = gen_host6(addr, &mask, q.proto, q.dir, q.addr); freeaddrinfo(res); return b; default: bpf_error("invalid qualifier against IPv6 address"); /* NOTREACHED */ } return NULL; } #endif /*INET6*/ struct block * gen_ecode(eaddr, q) register const u_char *eaddr; struct qual q; { struct block *b, *tmp; if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { switch (linktype) { case DLT_EN10MB: return gen_ehostop(eaddr, (int)q.dir); case DLT_FDDI: return gen_fhostop(eaddr, (int)q.dir); case DLT_IEEE802: return gen_thostop(eaddr, (int)q.dir); case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: case DLT_PPI: return gen_wlanhostop(eaddr, (int)q.dir); case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(tmp); /* * Now check the MAC address. */ b = gen_ehostop(eaddr, (int)q.dir); gen_and(tmp, b); return b; } break; case DLT_IP_OVER_FC: return gen_ipfchostop(eaddr, (int)q.dir); default: bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); break; } } bpf_error("ethernet address used in non-ether expression"); /* NOTREACHED */ return NULL; } 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; } /* * Modify "index" to use the value stored into its register as an * offset relative to the beginning of the header for the protocol * "proto", and allocate a register and put an item "size" bytes long * (1, 2, or 4) at that offset into that register, making it the register * for "index". */ struct arth * gen_load(proto, inst, size) int proto; struct arth *inst; int size; { struct slist *s, *tmp; struct block *b; int regno = alloc_reg(); free_reg(inst->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_RADIO: /* * The offset is relative to the beginning of the packet * data, if we have a radio header. (If we don't, this * is an error.) */ if (linktype != DLT_IEEE802_11_RADIO_AVS && linktype != DLT_IEEE802_11_RADIO && linktype != DLT_PRISM_HEADER) bpf_error("radio information not present in capture"); /* * Load into the X register the offset computed into the * register specifed by "index". */ s = xfer_to_x(inst); /* * Load the item at that offset. */ tmp = new_stmt(BPF_LD|BPF_IND|size); sappend(s, tmp); sappend(inst->s, s); break; case Q_LINK: /* * The offset is relative to the beginning of * the link-layer header. * * XXX - what about ATM LANE? Should the index be * relative to the beginning of the AAL5 frame, so * that 0 refers to the beginning of the LE Control * field, or relative to the beginning of the LAN * frame, so that 0 refers, for Ethernet LANE, to * the beginning of the destination address? */ s = gen_llprefixlen(); /* * If "s" is non-null, it has code to arrange that the * X register contains the length of the prefix preceding * the link-layer header. Add to it the offset computed * into the register specified by "index", and move that * into the X register. Otherwise, just load into the X * register the offset computed into the register specifed * by "index". */ if (s != NULL) { sappend(s, xfer_to_a(inst)); sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else s = xfer_to_x(inst); /* * Load the item at the sum of the offset we've put in the * X register and the offset of the start of the link * layer header (which is 0 if the radio header is * variable-length; that header length is what we put * into the X register and then added to the index). */ tmp = new_stmt(BPF_LD|BPF_IND|size); tmp->s.k = off_ll; sappend(s, tmp); sappend(inst->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: #ifdef INET6 case Q_IPV6: #endif /* * The offset is relative to the beginning of * the network-layer header. * XXX - are there any cases where we want * off_nl_nosnap? */ s = gen_llprefixlen(); /* * If "s" is non-null, it has code to arrange that the * X register contains the length of the prefix preceding * the link-layer header. Add to it the offset computed * into the register specified by "index", and move that * into the X register. Otherwise, just load into the X * register the offset computed into the register specifed * by "index". */ if (s != NULL) { sappend(s, xfer_to_a(inst)); sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else s = xfer_to_x(inst); /* * Load the item at the sum of the offset we've put in the * X register, the offset of the start of the network * layer header, and the offset of the start of the link * layer header (which is 0 if the radio header is * variable-length; that header length is what we put * into the X register and then added to the index). */ tmp = new_stmt(BPF_LD|BPF_IND|size); tmp->s.k = off_ll + off_nl; sappend(s, tmp); sappend(inst->s, s); /* * Do the computation only if the packet contains * the protocol in question. */ b = gen_proto_abbrev(proto); if (inst->b) gen_and(inst->b, b); inst->b = b; break; case Q_SCTP: case Q_TCP: case Q_UDP: case Q_ICMP: case Q_IGMP: case Q_IGRP: case Q_PIM: case Q_VRRP: /* * The offset is relative to the beginning of * the transport-layer header. * * Load the X register with the length of the IPv4 header * (plus the offset of the link-layer header, if it's * a variable-length header), in bytes. * * XXX - are there any cases where we want * off_nl_nosnap? * XXX - we should, if we're built with * IPv6 support, generate code to load either * IPv4, IPv6, or both, as appropriate. */ s = gen_loadx_iphdrlen(); /* * The X register now contains the sum of the length * of any variable-length header preceding the link-layer * header and the length of the network-layer header. * Load into the A register the offset relative to * the beginning of the transport layer header, * add the X register to that, move that to the * X register, and load with an offset from the * X register equal to the offset of the network * layer header relative to the beginning of * the link-layer header plus the length of any * fixed-length header preceding the link-layer * header. */ sappend(s, xfer_to_a(inst)); 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_ll + off_nl; sappend(inst->s, s); /* * Do the computation only if the packet contains * the protocol in question - which is true only * if this is an IP datagram and is the first or * only fragment of that datagram. */ gen_and(gen_proto_abbrev(proto), b = gen_ipfrag()); if (inst->b) gen_and(inst->b, b); #ifdef INET6 gen_and(gen_proto_abbrev(Q_IP), b); #endif inst->b = b; break; #ifdef INET6 case Q_ICMPV6: bpf_error("IPv6 upper-layer protocol is not supported by proto[x]"); /*NOTREACHED*/ #endif } inst->regno = regno; s = new_stmt(BPF_ST); s->s.k = regno; sappend(inst->s, s); return inst; } 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); if (code == BPF_JEQ) { s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X); b = new_block(JMP(code)); sappend(s1, s2); } else b = new_block(BPF_JMP|code|BPF_X); if (reversed) gen_not(b); 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(a0->regno); 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 0; } /* * 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); } /* * Actually, this is less than or equal. */ struct block * gen_less(n) int n; { struct block *b; b = gen_len(BPF_JGT, n); gen_not(b); return b; } /* * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to * the beginning of the link-layer header. * XXX - that means you can't test values in the radiotap header, but * as that header is difficult if not impossible to parse generally * without a loop, that might not be a severe problem. A new keyword * "radio" could be added for that, although what you'd really want * would be a way of testing particular radio header values, which * would generate code appropriate to the radio header in question. */ 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(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); case '<': b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); return b; case '>': b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); 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; } static u_char abroadcast[] = { 0x0 }; 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: switch (linktype) { case DLT_ARCNET: case DLT_ARCNET_LINUX: return gen_ahostop(abroadcast, Q_DST); case DLT_EN10MB: return gen_ehostop(ebroadcast, Q_DST); case DLT_FDDI: return gen_fhostop(ebroadcast, Q_DST); case DLT_IEEE802: return gen_thostop(ebroadcast, Q_DST); case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: case DLT_PRISM_HEADER: return gen_wlanhostop(ebroadcast, Q_DST); case DLT_IP_OVER_FC: return gen_ipfchostop(ebroadcast, Q_DST); case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b1); /* * Now check the MAC address. */ b0 = gen_ehostop(ebroadcast, Q_DST); gen_and(b1, b0); return b0; } break; default: bpf_error("not a broadcast link"); } break; case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); hostmask = ~netmask; b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask); b2 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)(~0 & hostmask), hostmask); gen_or(b1, b2); gen_and(b0, b2); return b2; } bpf_error("only link-layer/IP broadcast filters supported"); /* NOTREACHED */ return NULL; } /* * Generate code to test the low-order bit of a MAC address (that's * the bottom bit of the *first* byte). */ static struct block * gen_mac_multicast(offset) int offset; { register struct block *b0; register struct slist *s; /* link[offset] & 1 != 0 */ s = gen_load_a(OR_LINK, offset, BPF_B); b0 = new_block(JMP(BPF_JSET)); b0->s.k = 1; b0->stmts = s; return b0; } struct block * gen_multicast(proto) int proto; { register struct block *b0, *b1, *b2; register struct slist *s; switch (proto) { case Q_DEFAULT: case Q_LINK: switch (linktype) { case DLT_ARCNET: case DLT_ARCNET_LINUX: /* all ARCnet multicasts use the same address */ return gen_ahostop(abroadcast, Q_DST); case DLT_EN10MB: /* ether[0] & 1 != 0 */ return gen_mac_multicast(0); case DLT_FDDI: /* * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX * * XXX - was that referring to bit-order issues? */ /* fddi[1] & 1 != 0 */ return gen_mac_multicast(1); case DLT_IEEE802: /* tr[2] & 1 != 0 */ return gen_mac_multicast(2); case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_PPI: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: /* * Oh, yuk. * * For control frames, there is no DA. * * For management frames, DA is at an * offset of 4 from the beginning of * the packet. * * For data frames, DA is at an offset * of 4 from the beginning of the packet * if To DS is clear and at an offset of * 16 from the beginning of the packet * if To DS is set. */ /* * Generate the tests to be done for data frames. * * First, check for To DS set, i.e. "link[1] & 0x01". */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; /* * If To DS is set, the DA is at 16. */ b0 = gen_mac_multicast(16); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; gen_not(b2); /* * If To DS is not set, the DA is at 4. */ b1 = gen_mac_multicast(4); gen_and(b2, b1); /* * Now OR together the last two checks. That gives * the complete set of checks for data frames. */ gen_or(b1, b0); /* * Now check for a data frame. * I.e, check "link[0] & 0x08". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the checks done for data frames. */ gen_and(b1, b0); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "!(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; gen_not(b2); /* * For management frames, the DA is at 4. */ b1 = gen_mac_multicast(4); gen_and(b2, b1); /* * OR that with the checks done for data frames. * That gives the checks done for management and * data frames. */ gen_or(b1, b0); /* * If the low-order bit of the type value is 1, * this is either a control frame or a frame * with a reserved type, and thus not a * frame with an SA. * * I.e., check "!(link[0] & 0x04)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); /* * AND that with the checks for data and management * frames. */ gen_and(b1, b0); return b0; case DLT_IP_OVER_FC: b0 = gen_mac_multicast(2); return b0; case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b1); /* ether[off_mac] & 1 != 0 */ b0 = gen_mac_multicast(off_mac); gen_and(b1, b0); return b0; } break; default: break; } /* Link not known to support multicasts */ break; case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224); gen_and(b0, b1); return b1; #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255); gen_and(b0, b1); return b1; #endif /* INET6 */ } bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel"); /* NOTREACHED */ return NULL; } /* * 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; /* * Only some data link types support inbound/outbound qualifiers. */ switch (linktype) { case DLT_SLIP: b0 = gen_relation(BPF_JEQ, gen_load(Q_LINK, gen_loadi(0), 1), gen_loadi(0), dir); break; case DLT_LINUX_SLL: if (dir) { /* * Match packets sent by this machine. */ b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING); } else { /* * Match packets sent to this machine. * (No broadcast or multicast packets, or * packets sent to some other machine and * received promiscuously.) * * XXX - packets sent to other machines probably * shouldn't be matched, but what about broadcast * or multicast packets we received? */ b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST); } break; case DLT_PFLOG: b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B, (bpf_int32)((dir == 0) ? PF_IN : PF_OUT)); break; case DLT_PPP_PPPD: if (dir) { /* match outgoing packets */ b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT); } else { /* match incoming packets */ b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN); } break; case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: case DLT_JUNIPER_ATM2: case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_PPPOE_ATM: case DLT_JUNIPER_GGSN: case DLT_JUNIPER_ES: case DLT_JUNIPER_MONITOR: case DLT_JUNIPER_SERVICES: case DLT_JUNIPER_ETHER: case DLT_JUNIPER_PPP: case DLT_JUNIPER_FRELAY: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_VP: /* juniper flags (including direction) are stored * the byte after the 3-byte magic number */ if (dir) { /* match outgoing packets */ b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01); } else { /* match incoming packets */ b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01); } break; default: bpf_error("inbound/outbound not supported on linktype %d", linktype); b0 = NULL; /* NOTREACHED */ } return (b0); } /* PF firewall log matched interface */ struct block * gen_pf_ifname(const char *ifname) { struct block *b0; u_int len, off; if (linktype == DLT_PFLOG) { len = sizeof(((struct pfloghdr *)0)->ifname); off = offsetof(struct pfloghdr, ifname); } else { bpf_error("ifname not supported on linktype 0x%x", linktype); /* NOTREACHED */ } if (strlen(ifname) >= len) { bpf_error("ifname interface names can only be %d characters", len-1); /* NOTREACHED */ } b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname); return (b0); } /* PF firewall log ruleset name */ struct block * gen_pf_ruleset(char *ruleset) { struct block *b0; if (linktype != DLT_PFLOG) { bpf_error("ruleset not supported on linktype 0x%x", linktype); /* NOTREACHED */ } if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) { bpf_error("ruleset names can only be %ld characters", (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1)); /* NOTREACHED */ } b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset), strlen(ruleset), (const u_char *)ruleset); return (b0); } /* PF firewall log rule number */ struct block * gen_pf_rnr(int rnr) { struct block *b0; if (linktype == DLT_PFLOG) { b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W, (bpf_int32)rnr); } else { bpf_error("rnr not supported on linktype 0x%x", linktype); /* NOTREACHED */ } return (b0); } /* PF firewall log sub-rule number */ struct block * gen_pf_srnr(int srnr) { struct block *b0; if (linktype != DLT_PFLOG) { bpf_error("srnr not supported on linktype 0x%x", linktype); /* NOTREACHED */ } b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W, (bpf_int32)srnr); return (b0); } /* PF firewall log reason code */ struct block * gen_pf_reason(int reason) { struct block *b0; if (linktype == DLT_PFLOG) { b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B, (bpf_int32)reason); } else { bpf_error("reason not supported on linktype 0x%x", linktype); /* NOTREACHED */ } return (b0); } /* PF firewall log action */ struct block * gen_pf_action(int action) { struct block *b0; if (linktype == DLT_PFLOG) { b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B, (bpf_int32)action); } else { bpf_error("action not supported on linktype 0x%x", linktype); /* NOTREACHED */ } return (b0); } struct block * gen_acode(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_ARCNET || linktype == DLT_ARCNET_LINUX) return gen_ahostop(eaddr, (int)q.dir); } bpf_error("ARCnet address used in non-arc expression"); /* NOTREACHED */ return NULL; } static struct block * gen_ahostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1; switch (dir) { /* src comes first, different from Ethernet */ case Q_SRC: return gen_bcmp(OR_LINK, 0, 1, eaddr); case Q_DST: return gen_bcmp(OR_LINK, 1, 1, eaddr); case Q_AND: b0 = gen_ahostop(eaddr, Q_SRC); b1 = gen_ahostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_ahostop(eaddr, Q_SRC); b1 = gen_ahostop(eaddr, Q_DST); gen_or(b0, b1); return b1; } abort(); /* NOTREACHED */ } /* * support IEEE 802.1Q VLAN trunk over ethernet */ struct block * gen_vlan(vlan_num) int vlan_num; { struct block *b0, *b1; /* can't check for VLAN-encapsulated packets inside MPLS */ if (label_stack_depth > 0) bpf_error("no VLAN match after MPLS"); /* * Change the offsets to point to the type and data fields within * the VLAN packet. Just increment the offsets, so that we * can support a hierarchy, e.g. "vlan 300 && vlan 200" to * capture VLAN 200 encapsulated within VLAN 100. * * XXX - this is a bit of a kludge. If we were to split the * compiler into a parser that parses an expression and * generates an expression tree, and a code generator that * takes an expression tree (which could come from our * parser or from some other parser) and generates BPF code, * we could perhaps make the offsets parameters of routines * and, in the handler for an "AND" node, pass to subnodes * other than the VLAN node the adjusted offsets. * * This would mean that "vlan" would, instead of changing the * behavior of *all* tests after it, change only the behavior * of tests ANDed with it. That would change the documented * semantics of "vlan", which might break some expressions. * However, it would mean that "(vlan and ip) or ip" would check * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than * checking only for VLAN-encapsulated IP, so that could still * be considered worth doing; it wouldn't break expressions * that are of the form "vlan and ..." or "vlan N and ...", * which I suspect are the most common expressions involving * "vlan". "vlan or ..." doesn't necessarily do what the user * would really want, now, as all the "or ..." tests would * be done assuming a VLAN, even though the "or" could be viewed * as meaning "or, if this isn't a VLAN packet...". */ orig_linktype = off_linktype; /* save original values */ orig_nl = off_nl; switch (linktype) { case DLT_EN10MB: off_linktype += 4; off_nl_nosnap += 4; off_nl += 4; break; default: bpf_error("no VLAN support for data link type %d", linktype); /*NOTREACHED*/ } /* check for VLAN */ b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q); /* If a specific VLAN is requested, check VLAN id */ if (vlan_num >= 0) { b1 = gen_mcmp(OR_LINK, orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff); gen_and(b0, b1); b0 = b1; } return (b0); } /* * support for MPLS */ struct block * gen_mpls(label_num) int label_num; { struct block *b0,*b1; /* * Change the offsets to point to the type and data fields within * the MPLS packet. Just increment the offsets, so that we * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to * capture packets with an outer label of 100000 and an inner * label of 1024. * * XXX - this is a bit of a kludge. See comments in gen_vlan(). */ orig_nl = off_nl; if (label_stack_depth > 0) { /* just match the bottom-of-stack bit clear */ b0 = gen_mcmp(OR_LINK, orig_nl-2, BPF_B, 0, 0x01); } else { /* * Indicate that we're checking MPLS-encapsulated headers, * to make sure higher level code generators don't try to * match against IP-related protocols such as Q_ARP, Q_RARP * etc. */ switch (linktype) { case DLT_C_HDLC: /* fall through */ case DLT_EN10MB: b0 = gen_linktype(ETHERTYPE_MPLS); break; case DLT_PPP: b0 = gen_linktype(PPP_MPLS_UCAST); break; /* FIXME add other DLT_s ... * for Frame-Relay/and ATM this may get messy due to SNAP headers * leave it for now */ default: bpf_error("no MPLS support for data link type %d", linktype); b0 = NULL; /*NOTREACHED*/ break; } } /* If a specific MPLS label is requested, check it */ if (label_num >= 0) { label_num = label_num << 12; /* label is shifted 12 bits on the wire */ b1 = gen_mcmp(OR_LINK, orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */ gen_and(b0, b1); b0 = b1; } off_nl_nosnap += 4; off_nl += 4; label_stack_depth++; return (b0); } /* * Support PPPOE discovery and session. */ struct block * gen_pppoed() { /* check for PPPoE discovery */ return gen_linktype((bpf_int32)ETHERTYPE_PPPOED); } struct block * gen_pppoes() { struct block *b0; /* * Test against the PPPoE session link-layer type. */ b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES); /* * Change the offsets to point to the type and data fields within * the PPP packet. * * XXX - this is a bit of a kludge. If we were to split the * compiler into a parser that parses an expression and * generates an expression tree, and a code generator that * takes an expression tree (which could come from our * parser or from some other parser) and generates BPF code, * we could perhaps make the offsets parameters of routines * and, in the handler for an "AND" node, pass to subnodes * other than the PPPoE node the adjusted offsets. * * This would mean that "pppoes" would, instead of changing the * behavior of *all* tests after it, change only the behavior * of tests ANDed with it. That would change the documented * semantics of "pppoes", which might break some expressions. * However, it would mean that "(pppoes and ip) or ip" would check * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than * checking only for VLAN-encapsulated IP, so that could still * be considered worth doing; it wouldn't break expressions * that are of the form "pppoes and ..." which I suspect are the * most common expressions involving "pppoes". "pppoes or ..." * doesn't necessarily do what the user would really want, now, * as all the "or ..." tests would be done assuming PPPoE, even * though the "or" could be viewed as meaning "or, if this isn't * a PPPoE packet...". */ orig_linktype = off_linktype; /* save original values */ orig_nl = off_nl; /* * The "network-layer" protocol is PPPoE, which has a 6-byte * PPPoE header, followed by PPP payload, so we set the * offsets to the network layer offset plus 6 bytes for * the PPPoE header plus the values appropriate for PPP when * encapsulated in Ethernet (which means there's no HDLC * encapsulation). */ off_linktype = orig_nl + 6; off_nl = orig_nl + 6 + 2; off_nl_nosnap = orig_nl + 6 + 2; /* * Set the link-layer type to PPP, as all subsequent tests will * be on the encapsulated PPP header. */ linktype = DLT_PPP; return b0; } struct block * gen_atmfield_code(atmfield, jvalue, jtype, reverse) int atmfield; bpf_int32 jvalue; bpf_u_int32 jtype; int reverse; { struct block *b0; switch (atmfield) { case A_VPI: if (!is_atm) bpf_error("'vpi' supported only on raw ATM"); if (off_vpi == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; case A_VCI: if (!is_atm) bpf_error("'vci' supported only on raw ATM"); if (off_vci == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype, reverse, jvalue); break; case A_PROTOTYPE: if (off_proto == (u_int)-1) abort(); /* XXX - this isn't on FreeBSD */ b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype, reverse, jvalue); break; case A_MSGTYPE: if (off_payload == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; case A_CALLREFTYPE: if (!is_atm) bpf_error("'callref' supported only on raw ATM"); if (off_proto == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; default: abort(); } return b0; } struct block * gen_atmtype_abbrev(type) int type; { struct block *b0, *b1; switch (type) { case A_METAC: /* Get all packets in Meta signalling Circuit */ if (!is_atm) bpf_error("'metac' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0); gen_and(b0, b1); break; case A_BCC: /* Get all packets in Broadcast Circuit*/ if (!is_atm) bpf_error("'bcc' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0); gen_and(b0, b1); break; case A_OAMF4SC: /* Get all cells in Segment OAM F4 circuit*/ if (!is_atm) bpf_error("'oam4sc' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); gen_and(b0, b1); break; case A_OAMF4EC: /* Get all cells in End-to-End OAM F4 Circuit*/ if (!is_atm) bpf_error("'oam4ec' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); gen_and(b0, b1); break; case A_SC: /* Get all packets in connection Signalling Circuit */ if (!is_atm) bpf_error("'sc' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0); gen_and(b0, b1); break; case A_ILMIC: /* Get all packets in ILMI Circuit */ if (!is_atm) bpf_error("'ilmic' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0); gen_and(b0, b1); break; case A_LANE: /* Get all LANE packets */ if (!is_atm) bpf_error("'lane' supported only on raw ATM"); b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0); /* * Arrange that all subsequent tests assume LANE * rather than LLC-encapsulated packets, and set * the offsets appropriately for LANE-encapsulated * Ethernet. * * "off_mac" is the offset of the Ethernet header, * which is 2 bytes past the ATM pseudo-header * (skipping the pseudo-header and 2-byte LE Client * field). The other offsets are Ethernet offsets * relative to "off_mac". */ is_lane = 1; off_mac = off_payload + 2; /* MAC header */ off_linktype = off_mac + 12; off_nl = off_mac + 14; /* Ethernet II */ off_nl_nosnap = off_mac + 17; /* 802.3+802.2 */ break; case A_LLC: /* Get all LLC-encapsulated packets */ if (!is_atm) bpf_error("'llc' supported only on raw ATM"); b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); is_lane = 0; break; default: abort(); } return b1; } /* * Filtering for MTP2 messages based on li value * FISU, length is null * LSSU, length is 1 or 2 * MSU, length is 3 or more */ struct block * gen_mtp2type_abbrev(type) int type; { struct block *b0, *b1; switch (type) { case M_FISU: if ( (linktype != DLT_MTP2) && (linktype != DLT_MTP2_WITH_PHDR) ) bpf_error("'fisu' supported only on MTP2"); /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */ b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0); break; case M_LSSU: if ( (linktype != DLT_MTP2) && (linktype != DLT_MTP2_WITH_PHDR) ) bpf_error("'lssu' supported only on MTP2"); b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2); b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0); gen_and(b1, b0); break; case M_MSU: if ( (linktype != DLT_MTP2) && (linktype != DLT_MTP2_WITH_PHDR) ) bpf_error("'msu' supported only on MTP2"); b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2); break; default: abort(); } return b0; } struct block * gen_mtp3field_code(mtp3field, jvalue, jtype, reverse) int mtp3field; bpf_u_int32 jvalue; bpf_u_int32 jtype; int reverse; { struct block *b0; bpf_u_int32 val1 , val2 , val3; switch (mtp3field) { case M_SIO: if (off_sio == (u_int)-1) bpf_error("'sio' supported only on SS7"); /* sio coded on 1 byte so max value 255 */ if(jvalue > 255) bpf_error("sio value %u too big; max value = 255", jvalue); b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff, (u_int)jtype, reverse, (u_int)jvalue); break; case M_OPC: if (off_opc == (u_int)-1) bpf_error("'opc' supported only on SS7"); /* opc coded on 14 bits so max value 16383 */ if (jvalue > 16383) bpf_error("opc value %u too big; max value = 16383", jvalue); /* the following instructions are made to convert jvalue * to the form used to write opc in an ss7 message*/ val1 = jvalue & 0x00003c00; val1 = val1 >>10; val2 = jvalue & 0x000003fc; val2 = val2 <<6; val3 = jvalue & 0x00000003; val3 = val3 <<22; jvalue = val1 + val2 + val3; b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f, (u_int)jtype, reverse, (u_int)jvalue); break; case M_DPC: if (off_dpc == (u_int)-1) bpf_error("'dpc' supported only on SS7"); /* dpc coded on 14 bits so max value 16383 */ if (jvalue > 16383) bpf_error("dpc value %u too big; max value = 16383", jvalue); /* the following instructions are made to convert jvalue * to the forme used to write dpc in an ss7 message*/ val1 = jvalue & 0x000000ff; val1 = val1 << 24; val2 = jvalue & 0x00003f00; val2 = val2 << 8; jvalue = val1 + val2; b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000, (u_int)jtype, reverse, (u_int)jvalue); break; case M_SLS: if (off_sls == (u_int)-1) bpf_error("'sls' supported only on SS7"); /* sls coded on 4 bits so max value 15 */ if (jvalue > 15) bpf_error("sls value %u too big; max value = 15", jvalue); /* the following instruction is made to convert jvalue * to the forme used to write sls in an ss7 message*/ jvalue = jvalue << 4; b0 = gen_ncmp(OR_PACKET, off_sls, BPF_B, 0xf0, (u_int)jtype,reverse, (u_int)jvalue); break; default: abort(); } return b0; } static struct block * gen_msg_abbrev(type) int type; { struct block *b1; /* * Q.2931 signalling protocol messages for handling virtual circuits * establishment and teardown */ switch (type) { case A_SETUP: b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0); break; case A_CALLPROCEED: b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0); break; case A_CONNECT: b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0); break; case A_CONNECTACK: b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0); break; case A_RELEASE: b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0); break; case A_RELEASE_DONE: b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0); break; default: abort(); } return b1; } struct block * gen_atmmulti_abbrev(type) int type; { struct block *b0, *b1; switch (type) { case A_OAM: if (!is_atm) bpf_error("'oam' supported only on raw ATM"); b1 = gen_atmmulti_abbrev(A_OAMF4); break; case A_OAMF4: if (!is_atm) bpf_error("'oamf4' supported only on raw ATM"); /* OAM F4 type */ b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); gen_or(b0, b1); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); gen_and(b0, b1); break; case A_CONNECTMSG: /* * Get Q.2931 signalling messages for switched * virtual connection */ if (!is_atm) bpf_error("'connectmsg' supported only on raw ATM"); b0 = gen_msg_abbrev(A_SETUP); b1 = gen_msg_abbrev(A_CALLPROCEED); gen_or(b0, b1); b0 = gen_msg_abbrev(A_CONNECT); gen_or(b0, b1); b0 = gen_msg_abbrev(A_CONNECTACK); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE_DONE); gen_or(b0, b1); b0 = gen_atmtype_abbrev(A_SC); gen_and(b0, b1); break; case A_METACONNECT: if (!is_atm) bpf_error("'metaconnect' supported only on raw ATM"); b0 = gen_msg_abbrev(A_SETUP); b1 = gen_msg_abbrev(A_CALLPROCEED); gen_or(b0, b1); b0 = gen_msg_abbrev(A_CONNECT); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE_DONE); gen_or(b0, b1); b0 = gen_atmtype_abbrev(A_METAC); gen_and(b0, b1); break; default: abort(); } return b1; } libpcap-0.9.7/./Win32/0000755000026300017500000000000010245661225012325 5ustar mcrmcrlibpcap-0.9.7/./Win32/CVS/0000755000026300017500000000000010245661233012757 5ustar mcrmcrlibpcap-0.9.7/./Win32/CVS/Entries0000644000026300017500000000004210245661233014307 0ustar mcrmcrD/Include//// D/Prj//// D/Src//// libpcap-0.9.7/./Win32/CVS/Root0000644000026300017500000000004010245661223013616 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./Win32/CVS/Repository0000644000026300017500000000001610245661223015055 0ustar mcrmcrlibpcap/Win32 libpcap-0.9.7/./Win32/CVS/Tag0000644000026300017500000000001510245661223013410 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./Win32/Include/0000755000026300017500000000000010504042141013674 5ustar mcrmcrlibpcap-0.9.7/./Win32/Include/sockstorage.h0000644000026300017500000000334007522171102016377 0ustar mcrmcr/* * Copyright (C) 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. */ struct sockaddr_storage { #ifdef HAVE_SOCKADDR_SA_LEN u_int8_t __ss_len; u_int8_t __ss_family; u_int8_t fill[126]; #else u_int8_t __ss_family; u_int8_t fill[127]; #endif /* HAVE_SOCKADDR_SA_LEN */ }; libpcap-0.9.7/./Win32/Include/ip6_misc.h0000644000026300017500000001276310504042141015567 0ustar mcrmcr/* * Copyright (c) 1993, 1994, 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. * * @(#) $Header: /tcpdump/master/libpcap/Win32/Include/ip6_misc.h,v 1.4.2.1 2006/01/22 18:13:47 gianluca Exp $ (LBL) */ /* * This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows */ #include #ifndef __MINGW32__ #include #endif /* __MINGW32__ */ #ifndef __MINGW32__ #define IN_MULTICAST(a) IN_CLASSD(a) #endif #define IN_EXPERIMENTAL(a) ((((u_int32_t) (a)) & 0xf0000000) == 0xf0000000) #define IN_LOOPBACKNET 127 #ifdef __MINGW32__ /* IPv6 address */ struct in6_addr { union { u_int8_t u6_addr8[16]; u_int16_t u6_addr16[8]; u_int32_t u6_addr32[4]; } in6_u; #define s6_addr in6_u.u6_addr8 #define s6_addr16 in6_u.u6_addr16 #define s6_addr32 in6_u.u6_addr32 #define s6_addr64 in6_u.u6_addr64 }; #define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } #define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } #endif /* __MINGW32__ */ #if (defined WIN32) || (defined __MINGW32__) typedef unsigned short sa_family_t; #endif #ifdef __MINGW32__ #define __SOCKADDR_COMMON(sa_prefix) \ sa_family_t sa_prefix##family /* Ditto, for IPv6. */ struct sockaddr_in6 { __SOCKADDR_COMMON (sin6_); u_int16_t sin6_port; /* Transport layer port # */ u_int32_t sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ }; #define IN6_IS_ADDR_V4MAPPED(a) \ ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \ (((u_int32_t *) (a))[2] == htonl (0xffff))) #define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff) #define IN6_IS_ADDR_LINKLOCAL(a) \ ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000)) #define IN6_IS_ADDR_LOOPBACK(a) \ (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \ ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1)) #endif /* __MINGW32__ */ #define ip6_vfc ip6_ctlun.ip6_un2_vfc #define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow #define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen #define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt #define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim #define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim #define nd_rd_type nd_rd_hdr.icmp6_type #define nd_rd_code nd_rd_hdr.icmp6_code #define nd_rd_cksum nd_rd_hdr.icmp6_cksum #define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] /* * IPV6 extension headers */ #define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ #define IPPROTO_IPV6 41 /* IPv6 header. */ #define IPPROTO_ROUTING 43 /* IPv6 routing header */ #define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ #define IPPROTO_ESP 50 /* encapsulating security payload */ #define IPPROTO_AH 51 /* authentication header */ #define IPPROTO_ICMPV6 58 /* ICMPv6 */ #define IPPROTO_NONE 59 /* IPv6 no next header */ #define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ #define IPPROTO_PIM 103 /* Protocol Independent Multicast. */ #define IPV6_RTHDR_TYPE_0 0 /* Option types and related macros */ #define IP6OPT_PAD1 0x00 /* 00 0 00000 */ #define IP6OPT_PADN 0x01 /* 00 0 00001 */ #define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ #define IP6OPT_JUMBO_LEN 6 #define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 */ #define IP6OPT_RTALERT_LEN 4 #define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ #define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ #define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ #define IP6OPT_MINLEN 2 #define IP6OPT_BINDING_UPDATE 0xc6 /* 11 0 00110 */ #define IP6OPT_BINDING_ACK 0x07 /* 00 0 00111 */ #define IP6OPT_BINDING_REQ 0x08 /* 00 0 01000 */ #define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */ #define IP6OPT_EID 0x8a /* 10 0 01010 */ #define IP6OPT_TYPE(o) ((o) & 0xC0) #define IP6OPT_TYPE_SKIP 0x00 #define IP6OPT_TYPE_DISCARD 0x40 #define IP6OPT_TYPE_FORCEICMP 0x80 #define IP6OPT_TYPE_ICMP 0xC0 #define IP6OPT_MUTABLE 0x20 #ifdef __MINGW32__ #ifndef EAI_ADDRFAMILY struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ size_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; #endif #endif /* __MINGW32__ */ libpcap-0.9.7/./Win32/Include/bittypes.h0000644000026300017500000000744510236222331015725 0ustar mcrmcr/* * Copyright (C) 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _BITTYPES_H #define _BITTYPES_H #ifndef HAVE_U_INT8_T #if SIZEOF_CHAR == 1 typedef unsigned char u_int8_t; typedef signed char int8_t; #elif SIZEOF_INT == 1 typedef unsigned int u_int8_t; typedef signed int int8_t; #else /* XXX */ #error "there's no appropriate type for u_int8_t" #endif #define HAVE_U_INT8_T 1 #define HAVE_INT8_T 1 #endif /* HAVE_U_INT8_T */ #ifndef HAVE_U_INT16_T #if SIZEOF_SHORT == 2 typedef unsigned short u_int16_t; typedef signed short int16_t; #elif SIZEOF_INT == 2 typedef unsigned int u_int16_t; typedef signed int int16_t; #elif SIZEOF_CHAR == 2 typedef unsigned char u_int16_t; typedef signed char int16_t; #else /* XXX */ #error "there's no appropriate type for u_int16_t" #endif #define HAVE_U_INT16_T 1 #define HAVE_INT16_T 1 #endif /* HAVE_U_INT16_T */ #ifndef HAVE_U_INT32_T #if SIZEOF_INT == 4 typedef unsigned int u_int32_t; typedef signed int int32_t; #elif SIZEOF_LONG == 4 typedef unsigned long u_int32_t; typedef signed long int32_t; #elif SIZEOF_SHORT == 4 typedef unsigned short u_int32_t; typedef signed short int32_t; #else /* XXX */ #error "there's no appropriate type for u_int32_t" #endif #define HAVE_U_INT32_T 1 #define HAVE_INT32_T 1 #endif /* HAVE_U_INT32_T */ #ifndef HAVE_U_INT64_T #if SIZEOF_LONG_LONG == 8 typedef unsigned long long u_int64_t; #elif defined(_MSC_EXTENSIONS) typedef unsigned _int64 u_int64_t; #elif SIZEOF_INT == 8 typedef unsigned int u_int64_t; #elif SIZEOF_LONG == 8 typedef unsigned long u_int64_t; #elif SIZEOF_SHORT == 8 typedef unsigned short u_int64_t; #else /* XXX */ #error "there's no appropriate type for u_int64_t" #endif #endif /* HAVE_U_INT64_T */ #ifndef PRId64 #ifdef _MSC_EXTENSIONS #define PRId64 "I64d" #else /* _MSC_EXTENSIONS */ #define PRId64 "lld" #endif /* _MSC_EXTENSIONS */ #endif /* PRId64 */ #ifndef PRIo64 #ifdef _MSC_EXTENSIONS #define PRIo64 "I64o" #else /* _MSC_EXTENSIONS */ #define PRIo64 "llo" #endif /* _MSC_EXTENSIONS */ #endif /* PRIo64 */ #ifndef PRIx64 #ifdef _MSC_EXTENSIONS #define PRIx64 "I64x" #else /* _MSC_EXTENSIONS */ #define PRIx64 "llx" #endif /* _MSC_EXTENSIONS */ #endif /* PRIx64 */ #ifndef PRIu64 #ifdef _MSC_EXTENSIONS #define PRIu64 "I64u" #else /* _MSC_EXTENSIONS */ #define PRIu64 "llu" #endif /* _MSC_EXTENSIONS */ #endif /* PRIu64 */ #endif /* _BITTYPES_H */ libpcap-0.9.7/./Win32/Include/inetprivate.h0000644000026300017500000000547107660722207016427 0ustar mcrmcr/* * Copyright (c) 1999 - 2003 * NetGroup, Politecnico di Torino (Italy) * 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. Neither the name of the Politecnico di Torino nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * */ #include #include #include #include #include #include #include #include extern void _sethtent(int f); extern void _endhtent(void); extern struct hostent *_gethtent(void); extern struct hostent *_gethtbyname(const char *name); extern struct hostent *_gethtbyaddr(const char *addr, int len, int type); extern int _validuser(FILE *hostf, const char *rhost, const char *luser, const char *ruser, int baselen); extern int _checkhost(const char *rhost, const char *lhost, int len); #if 0 extern void putlong(u_long l, u_char *msgp); extern void putshort(u_short l, u_char *msgp); extern u_int32_t _getlong(register const u_char *msgp); extern u_int16_t _getshort(register const u_char *msgp); extern void p_query(char *msg); extern void fp_query(char *msg, FILE *file); extern char *p_cdname(char *cp, char *msg, FILE *file); extern char *p_rr(char *cp, char *msg, FILE *file); extern char *p_type(int type); extern char * p_class(int class); extern char *p_time(u_long value); #endif extern char * hostalias(const char *name); extern void sethostfile(char *name); extern void _res_close (void); extern void ruserpass(const char *host, char **aname, char **apass); libpcap-0.9.7/./Win32/Include/cdecl_ext.h0000644000026300017500000000340307522171102016005 0ustar mcrmcr/* * Copyright (C) 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 HAVE_PORTABLE_PROTOTYPE #if defined(__STDC__) || defined(__cplusplus) #define __P(protos) protos /* full-blown ANSI C */ #else #define __P(protos) () /* traditional C preprocessor */ #endif #endif /* !HAVE_PORTABLE_PROTOTYPE */ libpcap-0.9.7/./Win32/Include/net/0000755000026300017500000000000010245661224014475 5ustar mcrmcrlibpcap-0.9.7/./Win32/Include/net/paths.h0000644000026300017500000000723107522171104015765 0ustar mcrmcr/* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)paths.h 5.15 (Berkeley) 5/29/91 */ #ifndef _PATHS_H_ #define _PATHS_H_ #if 0 #define __PATH_ETC_INET "/usr/etc/inet" #else #define __PATH_ETC_INET "/etc" #endif /* Default search path. */ #define _PATH_DEFPATH "/usr/local/bin:/usr/bin:/bin:." #define _PATH_DEFPATH_ROOT "/sbin:/bin:/usr/sbin:/usr/bin" #define _PATH_BSHELL "/bin/sh" #define _PATH_CONSOLE "/dev/console" #define _PATH_CSHELL "/bin/csh" #define _PATH_DEVDB "/var/run/dev.db" #define _PATH_DEVNULL "/dev/null" #define _PATH_DRUM "/dev/drum" #define _PATH_HEQUIV __PATH_ETC_INET"/hosts.equiv" #define _PATH_KMEM "/dev/kmem" #define _PATH_MAILDIR "/var/spool/mail" #define _PATH_MAN "/usr/man" #define _PATH_MEM "/dev/mem" #define _PATH_LOGIN "/bin/login" #define _PATH_NOLOGIN "/etc/nologin" #define _PATH_SENDMAIL "/usr/sbin/sendmail" #define _PATH_SHELLS "/etc/shells" #define _PATH_TTY "/dev/tty" #define _PATH_UNIX "/vmlinux" #define _PATH_VI "/usr/bin/vi" /* Provide trailing slash, since mostly used for building pathnames. */ #define _PATH_DEV "/dev/" #define _PATH_TMP "/tmp/" #define _PATH_VARRUN "/var/run/" #define _PATH_VARTMP "/var/tmp/" #define _PATH_KLOG "/proc/kmsg" #define _PATH_LOGCONF __PATH_ETC_INET"/syslog.conf" #if 0 #define _PATH_LOGPID __PATH_ETC_INET"/syslog.pid" #else #define _PATH_LOGPID "/var/run/syslog.pid" #endif #define _PATH_LOG "/dev/log" #define _PATH_CONSOLE "/dev/console" #if 0 #define _PATH_UTMP "/var/adm/utmp" #define _PATH_WTMP "/var/adm/wtmp" #define _PATH_LASTLOG "/var/adm/lastlog" #else #define _PATH_UTMP "/var/run/utmp" #define _PATH_WTMP "/var/log/wtmp" #define _PATH_LASTLOG "/var/log/lastlog" #endif #define _PATH_LOCALE "/usr/lib/locale" #define _PATH_RWHODIR "/var/spool/rwho" #if _MIT_POSIX_THREADS /* For the MIT pthreads */ #define _PATH_PTY "/dev/" #define _PATH_TZDIR "/usr/lib/zoneinfo" #define _PATH_TZFILE "/usr/lib/zoneinfo/localtime" #endif #endif /* !_PATHS_H_ */ libpcap-0.9.7/./Win32/Include/net/netdb.h0000644000026300017500000001426607522171104015750 0ustar mcrmcr/*- * Copyright (c) 1980, 1983, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)netdb.h 8.1 (Berkeley) 6/2/93 * netdb.h,v 1.4 1995/08/14 04:05:04 hjl Exp * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ #ifndef _NETDB_H_ #define _NETDB_H_ #if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT) #include #include #endif #include #include #define _PATH_HEQUIV __PATH_ETC_INET"/hosts.equiv" #define _PATH_HOSTS __PATH_ETC_INET"/hosts" #define _PATH_NETWORKS __PATH_ETC_INET"/networks" #define _PATH_PROTOCOLS __PATH_ETC_INET"/protocols" #define _PATH_SERVICES __PATH_ETC_INET"/services" #define _PATH_RESCONF __PATH_ETC_INET"/resolv.conf" #define _PATH_RPC __PATH_ETC_INET"/rpc" struct rpcent { char *r_name; /* name of server for this rpc program */ char **r_aliases; /* alias list */ int r_number; /* rpc program number */ }; #ifndef WIN32 #if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT) #define __NETDB_MAXALIASES 35 #define __NETDB_MAXADDRS 35 /* * Error return codes from gethostbyname() and gethostbyaddr() * (left in extern int h_errno). */ #define h_errno (*__h_errno_location ()) #else extern int h_errno; #endif #endif #define NETDB_INTERNAL -1 /* see errno */ #define NETDB_SUCCESS 0 /* no problem */ //#include void endhostent (void); void endnetent (void); void endprotoent (void); void endservent (void); void endrpcent (void); struct hostent *gethostent (void); struct netent *getnetbyaddr (long, int); /* u_long? */ struct netent *getnetbyname (const char *); struct netent *getnetent (void); struct protoent *getprotoent (void); struct servent *getservent (void); struct rpcent *getrpcent (void); struct rpcent *getrpcbyname (const char *); struct rpcent *getrpcbynumber (int); void herror (const char *); void sethostent (int); /* void sethostfile (const char *); */ void setnetent (int); void setprotoent (int); void setservent (int); void setrpcent (int); #if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT) struct hostent *gethostbyaddr_r (const char *__addr, int __length, int __type, struct hostent *__result, char *__buffer, int __buflen, int *__h_errnop); struct hostent *gethostbyname_r (const char * __name, struct hostent *__result, char *__buffer, int __buflen, int *__h_errnop); struct hostent *gethostent_r (struct hostent *__result, char *__buffer, int __buflen, int *__h_errnop); struct netent *getnetbyaddr_r (long __net, int __type, struct netent *__result, char *__buffer, int __buflen); struct netent *getnetbyname_r (const char * __name, struct netent *__result, char *__buffer, int __buflen); struct netent *getnetent_r (struct netent *__result, char *__buffer, int __buflen); struct protoent *getprotobyname_r (const char * __name, struct protoent *__result, char *__buffer, int __buflen); struct protoent *getprotobynumber_r (int __proto, struct protoent *__result, char *__buffer, int __buflen); struct protoent *getprotoent_r (struct protoent *__result, char *__buffer, int __buflen); struct servent *getservbyname_r (const char * __name, const char *__proto, struct servent *__result, char *__buffer, int __buflen); struct servent *getservbyport_r (int __port, const char *__proto, struct servent *__result, char *__buffer, int __buflen); struct servent *getservent_r (struct servent *__result, char *__buffer, int __buflen); int *__h_errno_location (void); #endif #endif /* !_NETDB_H_ */ libpcap-0.9.7/./Win32/Include/net/CVS/0000755000026300017500000000000010245661224015130 5ustar mcrmcrlibpcap-0.9.7/./Win32/Include/net/CVS/Entries0000644000026300017500000000023310245661224016462 0ustar mcrmcr/if.h/1.1/Thu Aug 1 08:33:07 2002//Tlibpcap_0_9 /netdb.h/1.1/Thu Aug 1 08:33:08 2002//Tlibpcap_0_9 /paths.h/1.1/Thu Aug 1 08:33:08 2002//Tlibpcap_0_9 D libpcap-0.9.7/./Win32/Include/net/CVS/Root0000644000026300017500000000004010245661223015767 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./Win32/Include/net/CVS/Repository0000644000026300017500000000003210245661223017224 0ustar mcrmcrlibpcap/Win32/Include/net libpcap-0.9.7/./Win32/Include/net/CVS/Tag0000644000026300017500000000001510245661224015562 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./Win32/Include/net/if.h0000644000026300017500000002110007522171103015232 0ustar mcrmcr/* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if.h 8.1 (Berkeley) 6/10/93 * $FreeBSD: src/sys/net/if.h,v 1.49.2.1 1999/08/29 16:28:15 peter Exp $ */ #ifndef _NET_IF_H_ #define _NET_IF_H_ /* * does not depend on on most other systems. This * helps userland compatability. (struct timeval ifi_lastchange) */ #ifndef KERNEL #include #endif /* * Structure describing information about an interface * which may be of interest to management entities. */ struct if_data { /* generic interface information */ u_char ifi_type; /* ethernet, tokenring, etc */ u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */ u_char ifi_addrlen; /* media address length */ u_char ifi_hdrlen; /* media header length */ u_char ifi_recvquota; /* polling quota for receive intrs */ u_char ifi_xmitquota; /* polling quota for xmit intrs */ u_long ifi_mtu; /* maximum transmission unit */ u_long ifi_metric; /* routing metric (external only) */ u_long ifi_baudrate; /* linespeed */ /* volatile statistics */ u_long ifi_ipackets; /* packets received on interface */ u_long ifi_ierrors; /* input errors on interface */ u_long ifi_opackets; /* packets sent on interface */ u_long ifi_oerrors; /* output errors on interface */ u_long ifi_collisions; /* collisions on csma interfaces */ u_long ifi_ibytes; /* total number of octets received */ u_long ifi_obytes; /* total number of octets sent */ u_long ifi_imcasts; /* packets received via multicast */ u_long ifi_omcasts; /* packets sent via multicast */ u_long ifi_iqdrops; /* dropped on input, this interface */ u_long ifi_noproto; /* destined for unsupported protocol */ u_long ifi_recvtiming; /* usec spent receiving when timing */ u_long ifi_xmittiming; /* usec spent xmitting when timing */ struct timeval ifi_lastchange; /* time of last administrative change */ }; /* ws2tcpip.h has interface flags: IFF_* */ #if 0 #define IFF_UP 0x1 /* interface is up */ #define IFF_BROADCAST 0x2 /* broadcast address valid */ #define IFF_DEBUG 0x4 /* turn on debugging */ #define IFF_LOOPBACK 0x8 /* is a loopback net */ #define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */ /*#define IFF_NOTRAILERS 0x20 * obsolete: avoid use of trailers */ #define IFF_RUNNING 0x40 /* resources allocated */ #define IFF_NOARP 0x80 /* no address resolution protocol */ #define IFF_PROMISC 0x100 /* receive all packets */ #define IFF_ALLMULTI 0x200 /* receive all multicast packets */ #define IFF_OACTIVE 0x400 /* transmission in progress */ #define IFF_SIMPLEX 0x800 /* can't hear own transmissions */ #define IFF_LINK0 0x1000 /* per link layer defined bit */ #define IFF_LINK1 0x2000 /* per link layer defined bit */ #define IFF_LINK2 0x4000 /* per link layer defined bit */ #define IFF_ALTPHYS IFF_LINK2 /* use alternate physical connection */ #define IFF_MULTICAST 0x8000 /* supports multicast */ #endif /* 0 */ /* flags set internally only: */ #define IFF_CANTCHANGE \ (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\ IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI) #define IFQ_MAXLEN 50 #define IFNET_SLOWHZ 1 /* granularity is 1 second */ /* * Message format for use in obtaining information about interfaces * from getkerninfo and the routing socket */ struct if_msghdr { u_short ifm_msglen; /* to skip over non-understood messages */ u_char ifm_version; /* future binary compatability */ u_char ifm_type; /* message type */ int ifm_addrs; /* like rtm_addrs */ int ifm_flags; /* value of if_flags */ u_short ifm_index; /* index for associated ifp */ struct if_data ifm_data;/* statistics and other data about if */ }; /* * Message format for use in obtaining information about interface addresses * from getkerninfo and the routing socket */ struct ifa_msghdr { u_short ifam_msglen; /* to skip over non-understood messages */ u_char ifam_version; /* future binary compatability */ u_char ifam_type; /* message type */ int ifam_addrs; /* like rtm_addrs */ int ifam_flags; /* value of ifa_flags */ u_short ifam_index; /* index for associated ifp */ int ifam_metric; /* value of ifa_metric */ }; /* * Message format for use in obtaining information about multicast addresses * from the routing socket */ struct ifma_msghdr { u_short ifmam_msglen; /* to skip over non-understood messages */ u_char ifmam_version; /* future binary compatability */ u_char ifmam_type; /* message type */ int ifmam_addrs; /* like rtm_addrs */ int ifmam_flags; /* value of ifa_flags */ u_short ifmam_index; /* index for associated ifp */ }; /* * Interface request structure used for socket * ioctl's. All interface ioctl's must have parameter * definitions which begin with ifr_name. The * remainder may be interface specific. */ struct ifreq { #define IFNAMSIZ 16 char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ union { struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; short ifru_flags; int ifru_metric; int ifru_mtu; int ifru_phys; int ifru_media; caddr_t ifru_data; } ifr_ifru; #define ifr_addr ifr_ifru.ifru_addr /* address */ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ #define ifr_flags ifr_ifru.ifru_flags /* flags */ #define ifr_metric ifr_ifru.ifru_metric /* metric */ #define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ #define ifr_phys ifr_ifru.ifru_phys /* physical wire */ #define ifr_media ifr_ifru.ifru_media /* physical media */ #define ifr_data ifr_ifru.ifru_data /* for use by interface */ }; #define _SIZEOF_ADDR_IFREQ(ifr) \ ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \ (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ (ifr).ifr_addr.sa_len) : sizeof(struct ifreq)) struct ifaliasreq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr ifra_addr; struct sockaddr ifra_broadaddr; struct sockaddr ifra_mask; }; struct ifmediareq { char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */ int ifm_current; /* current media options */ int ifm_mask; /* don't care mask */ int ifm_status; /* media status */ int ifm_active; /* active options */ int ifm_count; /* # entries in ifm_ulist array */ int *ifm_ulist; /* media words */ }; /* * Structure used in SIOCGIFCONF request. * Used to retrieve interface configuration * for machine (useful for programs which * must know all networks accessible). */ struct ifconf { int ifc_len; /* size of associated buffer */ union { caddr_t ifcu_buf; struct ifreq *ifcu_req; } ifc_ifcu; #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ #define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */ }; #ifdef KERNEL #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_IFADDR); MALLOC_DECLARE(M_IFMADDR); #endif #endif /* XXX - this should go away soon */ #ifdef KERNEL #include #endif #endif /* !_NET_IF_H_ */ libpcap-0.9.7/./Win32/Include/addrinfo.h0000644000026300017500000001120607522171101015640 0ustar mcrmcr/* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $Id: addrinfo.h,v 1.1 2002/08/01 08:33:05 risso Exp $ */ #ifndef HAVE_ADDRINFO /* * Error return codes from getaddrinfo() */ #define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ #define EAI_AGAIN 2 /* temporary failure in name resolution */ #define EAI_BADFLAGS 3 /* invalid value for ai_flags */ #define EAI_FAIL 4 /* non-recoverable failure in name resolution */ #define EAI_FAMILY 5 /* ai_family not supported */ #define EAI_MEMORY 6 /* memory allocation failure */ #define EAI_NODATA 7 /* no address associated with hostname */ #define EAI_NONAME 8 /* hostname nor servname provided, or not known */ #define EAI_SERVICE 9 /* servname not supported for ai_socktype */ #define EAI_SOCKTYPE 10 /* ai_socktype not supported */ #define EAI_SYSTEM 11 /* system error returned in errno */ #define EAI_BADHINTS 12 #define EAI_PROTOCOL 13 #define EAI_MAX 14 /* internal error */ #define NETDB_INTERNAL -1 /* see errno */ /* * Flag values for getaddrinfo() */ #define AI_PASSIVE 0x00000001 /* get address to use bind() */ #define AI_CANONNAME 0x00000002 /* fill ai_canonname */ #define AI_NUMERICHOST 0x00000004 /* prevent name resolution */ /* valid flags for addrinfo */ #define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST) #define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */ #define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */ #define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */ #define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */ /* special recommended flags for getipnodebyname */ #define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG) struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ size_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; extern void freeaddrinfo (struct addrinfo *); extern void freehostent (struct hostent *); extern char *gai_strerror (int); extern int getaddrinfo (const char *, const char *, const struct addrinfo *, struct addrinfo **); extern int getnameinfo (const struct sockaddr *, size_t, char *, size_t, char *, size_t, int); extern struct hostent *getipnodebyaddr (const void *, size_t, int, int *); extern struct hostent *getipnodebyname (const char *, int, int, int *); extern int inet_pton (int, const char *, void *); extern const char *inet_ntop (int, const void *, char *, size_t); #endif /* HAVE_ADDRINFO */ /* * Constants for getnameinfo() */ #ifndef NI_MAXHOST #define NI_MAXHOST 1025 #endif #ifndef NI_MAXSERV #define NI_MAXSERV 32 #endif /* * Flag values for getnameinfo() */ #ifndef NI_NOFQDN #define NI_NOFQDN 0x00000001 #endif #ifndef NI_NUMERICHOST #define NI_NUMERICHOST 0x00000002 #endif #ifndef NI_NAMEREQD #define NI_NAMEREQD 0x00000004 #endif #ifndef NI_NUMERICSERV #define NI_NUMERICSERV 0x00000008 #endif #ifndef NI_DGRAM #define NI_DGRAM 0x00000010 #endif libpcap-0.9.7/./Win32/Include/CVS/0000755000026300017500000000000010504042141014327 5ustar mcrmcrlibpcap-0.9.7/./Win32/Include/CVS/Entries0000644000026300017500000000064110504042141015664 0ustar mcrmcr/Gnuc.h/1.1/Thu Aug 1 08:33:05 2002//Tlibpcap_0_9 /addrinfo.h/1.1/Thu Aug 1 08:33:05 2002//Tlibpcap_0_9 /bittypes.h/1.1.4.1/Wed May 4 19:39:05 2005//Tlibpcap_0_9 /cdecl_ext.h/1.1/Thu Aug 1 08:33:06 2002//Tlibpcap_0_9 /inetprivate.h/1.2/Thu May 15 14:30:31 2003//Tlibpcap_0_9 /sockstorage.h/1.1/Thu Aug 1 08:33:06 2002//Tlibpcap_0_9 D/arpa//// D/net//// /ip6_misc.h/1.4.2.1/Tue Sep 19 19:26:25 2006//Tlibpcap_0_9 libpcap-0.9.7/./Win32/Include/CVS/Root0000644000026300017500000000004010245661223015201 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./Win32/Include/CVS/Repository0000644000026300017500000000002610245661223016441 0ustar mcrmcrlibpcap/Win32/Include libpcap-0.9.7/./Win32/Include/CVS/Tag0000644000026300017500000000001510245661223014773 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./Win32/Include/arpa/0000755000026300017500000000000010245661223014631 5ustar mcrmcrlibpcap-0.9.7/./Win32/Include/arpa/nameser.h0000644000026300017500000003052607522171103016437 0ustar mcrmcr/* * ++Copyright++ 1983, 1989, 1993 * - * Copyright (c) 1983, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ /* * @(#)nameser.h 8.1 (Berkeley) 6/2/93 * nameser.h,v 1.2 1995/05/06 14:23:54 hjl Exp */ #ifndef _NAMESER_H_ #define _NAMESER_H_ #ifndef WIN32 #include #if (!defined(BSD)) || (BSD < 199306) # include #else # include #endif #include #else #include #define __LITTLE_ENDIAN 1 #define __BYTE_ORDER __LITTLE_ENDIAN #endif /* * revision information. this is the release date in YYYYMMDD format. * it can change every day so the right thing to do with it is use it * in preprocessor commands such as "#if (__BIND > 19931104)". do not * compare for equality; rather, use it to determine whether your resolver * is new enough to contain a certain feature. */ #define __BIND 19940417 /* interface version stamp */ /* * Define constants based on rfc883 */ #define PACKETSZ 512 /* maximum packet size */ #define MAXDNAME 256 /* maximum domain name */ #define MAXCDNAME 255 /* maximum compressed domain name */ #define MAXLABEL 63 /* maximum length of domain label */ #define HFIXEDSZ 12 /* #/bytes of fixed data in header */ #define QFIXEDSZ 4 /* #/bytes of fixed data in query */ #define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ #define INT32SZ 4 /* for systems without 32-bit ints */ #define INT16SZ 2 /* for systems without 16-bit ints */ #define INADDRSZ 4 /* for sizeof(struct inaddr) != 4 */ /* * Internet nameserver port number */ #define NAMESERVER_PORT 53 /* * Currently defined opcodes */ #define QUERY 0x0 /* standard query */ #define IQUERY 0x1 /* inverse query */ #define STATUS 0x2 /* nameserver status query */ /*#define xxx 0x3 *//* 0x3 reserved */ #define NS_NOTIFY_OP 0x4 /* notify secondary of SOA change */ #ifdef ALLOW_UPDATES /* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */ # define UPDATEA 0x9 /* add resource record */ # define UPDATED 0xa /* delete a specific resource record */ # define UPDATEDA 0xb /* delete all named resource record */ # define UPDATEM 0xc /* modify a specific resource record */ # define UPDATEMA 0xd /* modify all named resource record */ # define ZONEINIT 0xe /* initial zone transfer */ # define ZONEREF 0xf /* incremental zone referesh */ #endif /* * Currently defined response codes */ #ifdef HAVE_ADDRINFO #define NOERROR 0 /* no error */ #endif /* HAVE_ADDRINFO */ #define FORMERR 1 /* format error */ #define SERVFAIL 2 /* server failure */ #define NXDOMAIN 3 /* non existent domain */ #define NOTIMP 4 /* not implemented */ #define REFUSED 5 /* query refused */ #ifdef ALLOW_UPDATES /* non standard */ # define NOCHANGE 0xf /* update failed to change db */ #endif /* * Type values for resources and queries */ #define T_A 1 /* host address */ #define T_NS 2 /* authoritative server */ #define T_MD 3 /* mail destination */ #define T_MF 4 /* mail forwarder */ #define T_CNAME 5 /* canonical name */ #define T_SOA 6 /* start of authority zone */ #define T_MB 7 /* mailbox domain name */ #define T_MG 8 /* mail group member */ #define T_MR 9 /* mail rename name */ #define T_NULL 10 /* null resource record */ #define T_WKS 11 /* well known service */ #define T_PTR 12 /* domain name pointer */ #define T_HINFO 13 /* host information */ #define T_MINFO 14 /* mailbox information */ #define T_MX 15 /* mail routing information */ #define T_TXT 16 /* text strings */ #define T_RP 17 /* responsible person */ #define T_AFSDB 18 /* AFS cell database */ #define T_X25 19 /* X_25 calling address */ #define T_ISDN 20 /* ISDN calling address */ #define T_RT 21 /* router */ #define T_NSAP 22 /* NSAP address */ #define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */ #define T_SIG 24 /* security signature */ #define T_KEY 25 /* security key */ #define T_PX 26 /* X.400 mail mapping */ #define T_GPOS 27 /* geographical position (withdrawn) */ #define T_AAAA 28 /* IP6 Address */ #define T_LOC 29 /* Location Information */ /* non standard */ #define T_UINFO 100 /* user (finger) information */ #define T_UID 101 /* user ID */ #define T_GID 102 /* group ID */ #define T_UNSPEC 103 /* Unspecified format (binary data) */ /* Query type values which do not appear in resource records */ #define T_AXFR 252 /* transfer zone of authority */ #define T_MAILB 253 /* transfer mailbox records */ #define T_MAILA 254 /* transfer mail agent records */ #define T_ANY 255 /* wildcard match */ /* * Values for class field */ #define C_IN 1 /* the arpa internet */ #define C_CHAOS 3 /* for chaos net (MIT) */ #define C_HS 4 /* for Hesiod name server (MIT) (XXX) */ /* Query class values which do not appear in resource records */ #define C_ANY 255 /* wildcard match */ /* * Status return codes for T_UNSPEC conversion routines */ #define CONV_SUCCESS 0 #define CONV_OVERFLOW (-1) #define CONV_BADFMT (-2) #define CONV_BADCKSUM (-3) #define CONV_BADBUFLEN (-4) #ifndef __BYTE_ORDER #if (BSD >= 199103) # include #else #ifdef linux # include #else #define __LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ #define __BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ #define __PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ #if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ defined(__alpha__) || defined(__alpha) #define __BYTE_ORDER __LITTLE_ENDIAN #endif #if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ defined(apollo) || defined(__convex__) || defined(_CRAY) || \ defined(__hppa) || defined(__hp9000) || \ defined(__hp9000s300) || defined(__hp9000s700) || \ defined (BIT_ZERO_ON_LEFT) || defined(m68k) #define __BYTE_ORDER __BIG_ENDIAN #endif #endif /* linux */ #endif /* BSD */ #endif /* __BYTE_ORDER */ #if !defined(__BYTE_ORDER) || \ (__BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN && \ __BYTE_ORDER != __PDP_ENDIAN) /* you must determine what the correct bit order is for * your compiler - the next line is an intentional error * which will force your compiles to bomb until you fix * the above macros. */ error "Undefined or invalid __BYTE_ORDER"; #endif /* * Structure for query header. The order of the fields is machine- and * compiler-dependent, depending on the byte/bit order and the layout * of bit fields. We use bit fields only in int variables, as this * is all ANSI requires. This requires a somewhat confusing rearrangement. */ typedef struct { unsigned id :16; /* query identification number */ #if __BYTE_ORDER == __BIG_ENDIAN /* fields in third byte */ unsigned qr: 1; /* response flag */ unsigned opcode: 4; /* purpose of message */ unsigned aa: 1; /* authoritive answer */ unsigned tc: 1; /* truncated message */ unsigned rd: 1; /* recursion desired */ /* fields in fourth byte */ unsigned ra: 1; /* recursion available */ unsigned pr: 1; /* primary server req'd (!standard) */ unsigned unused :2; /* unused bits (MBZ as of 4.9.3a3) */ unsigned rcode :4; /* response code */ #endif #if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN /* fields in third byte */ unsigned rd :1; /* recursion desired */ unsigned tc :1; /* truncated message */ unsigned aa :1; /* authoritive answer */ unsigned opcode :4; /* purpose of message */ unsigned qr :1; /* response flag */ /* fields in fourth byte */ unsigned rcode :4; /* response code */ unsigned unused :2; /* unused bits (MBZ as of 4.9.3a3) */ unsigned pr :1; /* primary server req'd (!standard) */ unsigned ra :1; /* recursion available */ #endif /* remaining bytes */ unsigned qdcount :16; /* number of question entries */ unsigned ancount :16; /* number of answer entries */ unsigned nscount :16; /* number of authority entries */ unsigned arcount :16; /* number of resource entries */ } HEADER; /* * Defines for handling compressed domain names */ #define INDIR_MASK 0xc0 /* * Structure for passing resource records around. */ struct rrec { int16_t r_zone; /* zone number */ int16_t r_class; /* class number */ int16_t r_type; /* type number */ u_int32_t r_ttl; /* time to live */ int r_size; /* size of data area */ char *r_data; /* pointer to data */ }; //extern u_int16_t _getshort __P((const u_char *)); //extern u_int32_t _getlong __P((const u_char *)); /* * Inline versions of get/put short/long. Pointer is advanced. * * These macros demonstrate the property of C whereby it can be * portable or it can be elegant but rarely both. */ #define GETSHORT(s, cp) { \ register u_char *t_cp = (u_char *)(cp); \ (s) = ((u_int16_t)t_cp[0] << 8) \ | ((u_int16_t)t_cp[1]) \ ; \ (cp) += INT16SZ; \ } #define GETLONG(l, cp) { \ register u_char *t_cp = (u_char *)(cp); \ (l) = ((u_int32_t)t_cp[0] << 24) \ | ((u_int32_t)t_cp[1] << 16) \ | ((u_int32_t)t_cp[2] << 8) \ | ((u_int32_t)t_cp[3]) \ ; \ (cp) += INT32SZ; \ } #define PUTSHORT(s, cp) { \ register u_int16_t t_s = (u_int16_t)(s); \ register u_char *t_cp = (u_char *)(cp); \ *t_cp++ = t_s >> 8; \ *t_cp = t_s; \ (cp) += INT16SZ; \ } #define PUTLONG(l, cp) { \ register u_int32_t t_l = (u_int32_t)(l); \ register u_char *t_cp = (u_char *)(cp); \ *t_cp++ = t_l >> 24; \ *t_cp++ = t_l >> 16; \ *t_cp++ = t_l >> 8; \ *t_cp = t_l; \ (cp) += INT32SZ; \ } #endif /* !_NAMESER_H_ */ libpcap-0.9.7/./Win32/Include/arpa/CVS/0000755000026300017500000000000010245661223015264 5ustar mcrmcrlibpcap-0.9.7/./Win32/Include/arpa/CVS/Entries0000644000026300017500000000007010245661223016615 0ustar mcrmcr/nameser.h/1.1/Thu Aug 1 08:33:07 2002//Tlibpcap_0_9 D libpcap-0.9.7/./Win32/Include/arpa/CVS/Root0000644000026300017500000000004010245661223016124 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./Win32/Include/arpa/CVS/Repository0000644000026300017500000000003310245661223017362 0ustar mcrmcrlibpcap/Win32/Include/arpa libpcap-0.9.7/./Win32/Include/arpa/CVS/Tag0000644000026300017500000000001510245661223015716 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./Win32/Include/Gnuc.h0000644000026300017500000000141707522171101014751 0ustar mcrmcr/* @(#) $Header: /tcpdump/master/libpcap/Win32/Include/Gnuc.h,v 1.1 2002/08/01 08:33:05 risso Exp $ (LBL) */ /* Define __P() macro, if necessary */ #ifndef __P #if __STDC__ #define __P(protos) protos #else #define __P(protos) () #endif #endif /* inline foo */ #ifndef __cplusplus #ifdef __GNUC__ #define inline __inline #else #define inline #endif #endif /* * Handle new and old "dead" routine prototypes * * For example: * * __dead void foo(void) __attribute__((volatile)); * */ #ifdef __GNUC__ #ifndef __dead #define __dead volatile #endif #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) #ifndef __attribute__ #define __attribute__(args) #endif #endif #else #ifndef __dead #define __dead #endif #ifndef __attribute__ #define __attribute__(args) #endif #endif libpcap-0.9.7/./Win32/Src/0000755000026300017500000000000010504042141013040 5ustar mcrmcrlibpcap-0.9.7/./Win32/Src/ffs.c0000644000026300017500000000420107522171104013767 0ustar mcrmcr/*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)ffs.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include /* * ffs -- vax ffs instruction */ int ffs(mask) register int mask; { register int bit; if (mask == 0) return(0); for (bit = 1; !(mask & 1); bit++) mask >>= 1; return(bit); } libpcap-0.9.7/./Win32/Src/inet_net.c0000644000026300017500000000622307522171106015026 0ustar mcrmcr/* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include "inetprivate.h" /* * Internet network address interpretation routine. * The library routines call this routine to interpret * network numbers. */ u_int32_t inet_network(const char *cp) { register u_long val, base, n; register char c; u_long parts[4], *pp = parts; register int i; again: /* * Collect number up to ``.''. * Values are specified as for C: * 0x=hex, 0=octal, other=decimal. */ val = 0; base = 10; /* * The 4.4BSD version of this file also accepts 'x__' as a hexa * number. I don't think this is correct. -- Uli */ if (*cp == '0') { if (*++cp == 'x' || *cp == 'X') base = 16, cp++; else base = 8; } while ((c = *cp)) { if (isdigit(c)) { val = (val * base) + (c - '0'); cp++; continue; } if (base == 16 && isxdigit(c)) { val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); cp++; continue; } break; } if (*cp == '.') { if (pp >= parts + 4) return (INADDR_NONE); *pp++ = val, cp++; goto again; } if (*cp && !isspace(*cp)) return (INADDR_NONE); *pp++ = val; n = pp - parts; if (n > 4) return (INADDR_NONE); for (val = 0, i = 0; i < (int)n; i++) { val <<= 8; val |= parts[i] & 0xff; } return (val); } libpcap-0.9.7/./Win32/Src/getnetbynm.c0000644000026300017500000000253207522171105015373 0ustar mcrmcr/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getnetbyname.c 5.5 (Berkeley) 6/27/88"; #endif /* LIBC_SCCS and not lint */ #include "inetprivate.h" extern int _net_stayopen; struct netent * getnetbyname(const char *name) { register struct netent *p; register char **cp; setnetent(_net_stayopen); while (p = getnetent()) { if (strcmp(p->n_name, name) == 0) break; for (cp = p->n_aliases; *cp != 0; cp++) if (strcmp(*cp, name) == 0) goto found; } found: if (!_net_stayopen) endnetent(); return (p); } libpcap-0.9.7/./Win32/Src/CVS/0000755000026300017500000000000010504042141013473 5ustar mcrmcrlibpcap-0.9.7/./Win32/Src/CVS/Entries0000644000026300017500000000106310504042141015027 0ustar mcrmcr/ffs.c/1.1/Thu Aug 1 08:33:08 2002//Tlibpcap_0_9 /getaddrinfo.c/1.2/Sat Nov 15 23:24:06 2003//Tlibpcap_0_9 /getnetbynm.c/1.1/Thu Aug 1 08:33:09 2002//Tlibpcap_0_9 /getnetent.c/1.1/Thu Aug 1 08:33:09 2002//Tlibpcap_0_9 /getopt.c/1.1/Thu Aug 1 08:33:09 2002//Tlibpcap_0_9 /getservent.c/1.1/Thu Aug 1 08:33:10 2002//Tlibpcap_0_9 /inet_aton.c/1.2/Sat Nov 15 23:24:06 2003//Tlibpcap_0_9 /inet_net.c/1.1/Thu Aug 1 08:33:10 2002//Tlibpcap_0_9 /inet_pton.c/1.2/Sat Nov 15 23:24:06 2003//Tlibpcap_0_9 /gai_strerror.c/1.1.2.1/Sun Jan 22 18:14:17 2006//Tlibpcap_0_9 D libpcap-0.9.7/./Win32/Src/CVS/Root0000644000026300017500000000004010245661225014347 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./Win32/Src/CVS/Repository0000644000026300017500000000002210245661225015603 0ustar mcrmcrlibpcap/Win32/Src libpcap-0.9.7/./Win32/Src/CVS/Tag0000644000026300017500000000001510245661225014141 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./Win32/Src/inet_aton.c0000644000026300017500000000465107755532626015224 0ustar mcrmcr/* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * 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 Kungliga Tekniska * Högskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $Id: inet_aton.c,v 1.2 2003/11/15 23:24:06 guy Exp $ */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/Win32/Src/inet_aton.c,v 1.2 2003/11/15 23:24:06 guy Exp $"; #endif #include #include /* Minimal implementation of inet_aton. * Cannot distinguish between failure and a local broadcast address. */ #ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif int inet_aton(const char *cp, struct in_addr *addr) { addr->s_addr = inet_addr(cp); return (addr->s_addr == INADDR_NONE) ? 0 : 1; } libpcap-0.9.7/./Win32/Src/getopt.c0000644000026300017500000000753307522171105014527 0ustar mcrmcr/* * Copyright (c) 1987, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; #endif /* LIBC_SCCS and not lint */ #include #include #include int opterr = 1, /* if error message should be printed */ optind = 1, /* index into parent argv vector */ optopt, /* character checked for validity */ optreset; /* reset getopt */ char *optarg; /* argument associated with option */ #define BADCH (int)'?' #define BADARG (int)':' #define EMSG "" /* * getopt -- * Parse argc/argv argument vector. */ int getopt(nargc, nargv, ostr) int nargc; char * const *nargv; const char *ostr; { #ifdef WIN32 char *__progname="windump"; #else extern char *__progname; #endif static char *place = EMSG; /* option letter processing */ char *oli; /* option letter list index */ if (optreset || !*place) { /* update scanning pointer */ optreset = 0; if (optind >= nargc || *(place = nargv[optind]) != '-') { place = EMSG; return (-1); } if (place[1] && *++place == '-') { /* found "--" */ ++optind; place = EMSG; return (-1); } } /* option letter okay? */ if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr, optopt))) { /* * if the user didn't specify '-' as an option, * assume it means -1. */ if (optopt == (int)'-') return (-1); if (!*place) ++optind; if (opterr && *ostr != ':') (void)fprintf(stderr, "%s: illegal option -- %c\n", __progname, optopt); return (BADCH); } if (*++oli != ':') { /* don't need argument */ optarg = NULL; if (!*place) ++optind; } else { /* need an argument */ if (*place) /* no white space */ optarg = place; else if (nargc <= ++optind) { /* no arg */ place = EMSG; if (*ostr == ':') return (BADARG); if (opterr) (void)fprintf(stderr, "%s: option requires an argument -- %c\n", __progname, optopt); return (BADCH); } else /* white space */ optarg = nargv[optind]; place = EMSG; ++optind; } return (optopt); /* dump back option letter */ } libpcap-0.9.7/./Win32/Src/gai_strerror.c0000644000026300017500000000554410364745571015743 0ustar mcrmcr/* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. */ /* #include __FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/net/gai_strerror.c,v 1.1 2005/04/06 12:45:51 ume Exp $"); */ #ifdef WIN32 #include #else #include #endif /* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) are obsoleted, but left */ /* for backward compatibility with userland code prior to 2553bis-02 */ static char *ai_errlist[] = { "Success", /* 0 */ "Address family for hostname not supported", /* 1 */ "Temporary failure in name resolution", /* EAI_AGAIN */ "Invalid value for ai_flags", /* EAI_BADFLAGS */ "Non-recoverable failure in name resolution", /* EAI_FAIL */ "ai_family not supported", /* EAI_FAMILY */ "Memory allocation failure", /* EAI_MEMORY */ "No address associated with hostname", /* 7 */ "hostname nor servname provided, or not known", /* EAI_NONAME */ "servname not supported for ai_socktype", /* EAI_SERVICE */ "ai_socktype not supported", /* EAI_SOCKTYPE */ "System error returned in errno", /* EAI_SYSTEM */ "Invalid value for hints", /* EAI_BADHINTS */ "Resolved protocol is unknown" /* EAI_PROTOCOL */ }; #ifndef EAI_MAX #define EAI_MAX (sizeof(ai_errlist)/sizeof(ai_errlist[0])) #endif char * WSAAPI gai_strerrorA(int ecode) { if (ecode >= 0 && ecode < EAI_MAX) return ai_errlist[ecode]; return "Unknown error"; } libpcap-0.9.7/./Win32/Src/getnetent.c0000644000026300017500000000473307522171105015221 0ustar mcrmcr/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getnetent.c 5.5 (Berkeley) 6/27/88"; #endif /* LIBC_SCCS and not lint */ #include "inetprivate.h" #define MAXALIASES 35 static char NETDB[] = _PATH_NETWORKS; static FILE *netf = NULL; static char line[BUFSIZ+1]; static struct netent net; static char *net_aliases[MAXALIASES]; static char *any(char *, char *); int _net_stayopen; extern u_int32_t inet_network(const char *cp); void setnetent(f) int f; { if (netf == NULL) netf = fopen(NETDB, "r" ); else rewind(netf); _net_stayopen |= f; } void endnetent() { if (netf) { fclose(netf); netf = NULL; } _net_stayopen = 0; } struct netent * getnetent() { char *p; register char *cp, **q; if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL) return (NULL); again: p = fgets(line, BUFSIZ, netf); if (p == NULL) return (NULL); if (*p == '#') goto again; cp = any(p, "#\n"); if (cp == NULL) goto again; *cp = '\0'; net.n_name = p; cp = any(p, " \t"); if (cp == NULL) goto again; *cp++ = '\0'; while (*cp == ' ' || *cp == '\t') cp++; p = any(cp, " \t"); if (p != NULL) *p++ = '\0'; net.n_net = inet_network(cp); net.n_addrtype = AF_INET; q = net.n_aliases = net_aliases; if (p != NULL) cp = p; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (q < &net_aliases[MAXALIASES - 1]) *q++ = cp; cp = any(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; return (&net); } static char * any(cp, match) register char *cp; char *match; { register char *mp, c; while (c = *cp) { for (mp = match; *mp; mp++) if (*mp == c) return (cp); cp++; } return ((char *)0); } libpcap-0.9.7/./Win32/Src/getaddrinfo.c0000644000026300017500000006147507755532626015541 0ustar mcrmcr/* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. */ /* * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. * * Issues to be discussed: * - Thread safe-ness must be checked. * - Return values. There are nonstandard return values defined and used * in the source code. This is because RFC2553 is silent about which error * code must be returned for which situation. * Note: * - We use getipnodebyname() just for thread-safeness. There's no intent * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to * getipnodebyname(). * - The code filters out AFs that are not supported by the kernel, * when globbing NULL hostname (to loopback, or wildcard). Is it the right * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG * in ai_flags? */ #ifdef HAVE_CONFIG_H #include #endif #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/Win32/Src/getaddrinfo.c,v 1.2 2003/11/15 23:24:06 guy Exp $"; #endif #include #if 0 #include #endif #ifndef __MINGW32__ #include #endif #include #include #include #include #include #include #ifndef HAVE_PORTABLE_PROTOTYPE #include "cdecl_ext.h" #endif #ifndef HAVE_U_INT32_T #include "bittypes.h" #endif #ifndef HAVE_SOCKADDR_STORAGE #ifndef __MINGW32__ #include "sockstorage.h" #endif #endif #ifdef NEED_ADDRINFO_H #include "addrinfo.h" #ifdef WIN32 #include "IP6_misc.h" #endif #endif #if defined(__KAME__) && defined(INET6) # define FAITH #endif #define SUCCESS 0 #define ANY 0 #define YES 1 #define NO 0 #ifdef FAITH static int translate = NO; static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT; #endif static const char in_addrany[] = { 0, 0, 0, 0 }; static const char in6_addrany[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const char in_loopback[] = { 127, 0, 0, 1 }; static const char in6_loopback[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; struct sockinet { u_char si_len; u_char si_family; u_short si_port; u_int32_t si_scope_id; }; static const struct afd { int a_af; int a_addrlen; int a_socklen; int a_off; const char *a_addrany; const char *a_loopback; int a_scoped; } afdl [] = { #ifdef INET6 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), offsetof(struct sockaddr_in6, sin6_addr), in6_addrany, in6_loopback, 1}, #endif {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), offsetof(struct sockaddr_in, sin_addr), in_addrany, in_loopback, 0}, {0, 0, 0, 0, NULL, NULL, 0}, }; struct explore { int e_af; int e_socktype; int e_protocol; const char *e_protostr; int e_wild; #define WILD_AF(ex) ((ex)->e_wild & 0x01) #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) }; static const struct explore explore[] = { #if 0 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, #endif #ifdef INET6 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, #endif { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, { -1, 0, 0, NULL, 0 }, }; #ifdef INET6 #define PTON_MAX 16 #else #define PTON_MAX 4 #endif static int str_isnumber __P((const char *)); static int explore_fqdn __P((const struct addrinfo *, const char *, const char *, struct addrinfo **)); static int explore_null __P((const struct addrinfo *, const char *, const char *, struct addrinfo **)); static int explore_numeric __P((const struct addrinfo *, const char *, const char *, struct addrinfo **)); static int explore_numeric_scope __P((const struct addrinfo *, const char *, const char *, struct addrinfo **)); static int get_name __P((const char *, const struct afd *, struct addrinfo **, char *, const struct addrinfo *, const char *)); static int get_canonname __P((const struct addrinfo *, struct addrinfo *, const char *)); static struct addrinfo *get_ai __P((const struct addrinfo *, const struct afd *, const char *)); static int get_portmatch __P((const struct addrinfo *, const char *)); static int get_port __P((struct addrinfo *, const char *, int)); static const struct afd *find_afd __P((int)); static char *ai_errlist[] = { "Success", "Address family for hostname not supported", /* EAI_ADDRFAMILY */ "Temporary failure in name resolution", /* EAI_AGAIN */ "Invalid value for ai_flags", /* EAI_BADFLAGS */ "Non-recoverable failure in name resolution", /* EAI_FAIL */ "ai_family not supported", /* EAI_FAMILY */ "Memory allocation failure", /* EAI_MEMORY */ "No address associated with hostname", /* EAI_NODATA */ "hostname nor servname provided, or not known", /* EAI_NONAME */ "servname not supported for ai_socktype", /* EAI_SERVICE */ "ai_socktype not supported", /* EAI_SOCKTYPE */ "System error returned in errno", /* EAI_SYSTEM */ "Invalid value for hints", /* EAI_BADHINTS */ "Resolved protocol is unknown", /* EAI_PROTOCOL */ "Unknown error", /* EAI_MAX */ }; /* XXX macros that make external reference is BAD. */ #define GET_AI(ai, afd, addr) \ do { \ /* external reference: pai, error, and label free */ \ (ai) = get_ai(pai, (afd), (addr)); \ if ((ai) == NULL) { \ error = EAI_MEMORY; \ goto free; \ } \ } while (0) #define GET_PORT(ai, serv) \ do { \ /* external reference: error and label free */ \ error = get_port((ai), (serv), 0); \ if (error != 0) \ goto free; \ } while (0) #define GET_CANONNAME(ai, str) \ do { \ /* external reference: pai, error and label free */ \ error = get_canonname(pai, (ai), (str)); \ if (error != 0) \ goto free; \ } while (0) #define ERR(err) \ do { \ /* external reference: error, and label bad */ \ error = (err); \ goto bad; \ } while (0) #define MATCH_FAMILY(x, y, w) \ ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) #define MATCH(x, y, w) \ ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY))) char * gai_strerror(ecode) int ecode; { if (ecode < 0 || ecode > EAI_MAX) ecode = EAI_MAX; return ai_errlist[ecode]; } void freeaddrinfo(ai) struct addrinfo *ai; { struct addrinfo *next; do { next = ai->ai_next; if (ai->ai_canonname) free(ai->ai_canonname); /* no need to free(ai->ai_addr) */ free(ai); } while ((ai = next) != NULL); } static int str_isnumber(p) const char *p; { char *q = (char *)p; while (*q) { if (! isdigit(*q)) return NO; q++; } return YES; } int getaddrinfo(hostname, servname, hints, res) const char *hostname, *servname; const struct addrinfo *hints; struct addrinfo **res; { struct addrinfo sentinel; struct addrinfo *cur; int error = 0; struct addrinfo ai; struct addrinfo ai0; struct addrinfo *pai; const struct afd *afd; const struct explore *ex; #ifdef FAITH static int firsttime = 1; if (firsttime) { /* translator hack */ char *q = getenv("GAI"); if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1) translate = YES; firsttime = 0; } #endif sentinel.ai_next = NULL; cur = &sentinel; pai = &ai; pai->ai_flags = 0; pai->ai_family = PF_UNSPEC; pai->ai_socktype = ANY; pai->ai_protocol = ANY; pai->ai_addrlen = 0; pai->ai_canonname = NULL; pai->ai_addr = NULL; pai->ai_next = NULL; if (hostname == NULL && servname == NULL) return EAI_NONAME; if (hints) { /* error check for hints */ if (hints->ai_addrlen || hints->ai_canonname || hints->ai_addr || hints->ai_next) ERR(EAI_BADHINTS); /* xxx */ if (hints->ai_flags & ~AI_MASK) ERR(EAI_BADFLAGS); switch (hints->ai_family) { case PF_UNSPEC: case PF_INET: #ifdef INET6 case PF_INET6: #endif break; default: ERR(EAI_FAMILY); } memcpy(pai, hints, sizeof(*pai)); /* * if both socktype/protocol are specified, check if they * are meaningful combination. */ if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { for (ex = explore; ex->e_af >= 0; ex++) { if (pai->ai_family != ex->e_af) continue; if (ex->e_socktype == ANY) continue; if (ex->e_protocol == ANY) continue; if (pai->ai_socktype == ex->e_socktype && pai->ai_protocol != ex->e_protocol) { ERR(EAI_BADHINTS); } } } } /* * check for special cases. (1) numeric servname is disallowed if * socktype/protocol are left unspecified. (2) servname is disallowed * for raw and other inet{,6} sockets. */ if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) #ifdef PF_INET6 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) #endif ) { ai0 = *pai; if (pai->ai_family == PF_UNSPEC) { #ifdef PF_INET6 pai->ai_family = PF_INET6; #else pai->ai_family = PF_INET; #endif } error = get_portmatch(pai, servname); if (error) ERR(error); *pai = ai0; } ai0 = *pai; /* NULL hostname, or numeric hostname */ for (ex = explore; ex->e_af >= 0; ex++) { *pai = ai0; if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) continue; if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) continue; if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) continue; if (pai->ai_family == PF_UNSPEC) pai->ai_family = ex->e_af; if (pai->ai_socktype == ANY && ex->e_socktype != ANY) pai->ai_socktype = ex->e_socktype; if (pai->ai_protocol == ANY && ex->e_protocol != ANY) pai->ai_protocol = ex->e_protocol; if (hostname == NULL) error = explore_null(pai, hostname, servname, &cur->ai_next); else error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next); if (error) goto free; while (cur && cur->ai_next) cur = cur->ai_next; } /* * XXX * If numreic representation of AF1 can be interpreted as FQDN * representation of AF2, we need to think again about the code below. */ if (sentinel.ai_next) goto good; if (pai->ai_flags & AI_NUMERICHOST) ERR(EAI_NONAME); if (hostname == NULL) ERR(EAI_NONAME); /* * hostname as alphabetical name. * we would like to prefer AF_INET6 than AF_INET, so we'll make a * outer loop by AFs. */ for (afd = afdl; afd->a_af; afd++) { *pai = ai0; if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1)) continue; for (ex = explore; ex->e_af >= 0; ex++) { *pai = ai0; if (pai->ai_family == PF_UNSPEC) pai->ai_family = afd->a_af; if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) continue; if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) { continue; } if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) { continue; } if (pai->ai_family == PF_UNSPEC) pai->ai_family = ex->e_af; if (pai->ai_socktype == ANY && ex->e_socktype != ANY) pai->ai_socktype = ex->e_socktype; if (pai->ai_protocol == ANY && ex->e_protocol != ANY) pai->ai_protocol = ex->e_protocol; error = explore_fqdn(pai, hostname, servname, &cur->ai_next); while (cur && cur->ai_next) cur = cur->ai_next; } } /* XXX */ if (sentinel.ai_next) error = 0; if (error) goto free; if (error == 0) { if (sentinel.ai_next) { good: *res = sentinel.ai_next; return SUCCESS; } else error = EAI_FAIL; } free: bad: if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); *res = NULL; return error; } /* * FQDN hostname, DNS lookup */ static int explore_fqdn(pai, hostname, servname, res) const struct addrinfo *pai; const char *hostname; const char *servname; struct addrinfo **res; { struct hostent *hp; int h_error; int af; char **aplist = NULL, *apbuf = NULL; char *ap; struct addrinfo sentinel, *cur; int i; #ifndef USE_GETIPNODEBY int naddrs; #endif const struct afd *afd; int error; *res = NULL; sentinel.ai_next = NULL; cur = &sentinel; /* * Do not filter unsupported AFs here. We need to honor content of * databases (/etc/hosts, DNS and others). Otherwise we cannot * replace gethostbyname() by getaddrinfo(). */ /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) return 0; afd = find_afd(pai->ai_family); /* * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG) * rather than hardcoding it. we may need to add AI_ADDRCONFIG * handling code by ourselves in case we don't have getipnodebyname(). */ #ifdef USE_GETIPNODEBY hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error); #else #ifdef HAVE_GETHOSTBYNAME2 hp = gethostbyname2(hostname, pai->ai_family); #else if (pai->ai_family != AF_INET) return 0; hp = gethostbyname(hostname); #ifdef HAVE_H_ERRNO h_error = h_errno; #else h_error = EINVAL; #endif #endif /*HAVE_GETHOSTBYNAME2*/ #endif /*USE_GETIPNODEBY*/ if (hp == NULL) { switch (h_error) { case HOST_NOT_FOUND: case NO_DATA: error = EAI_NODATA; break; case TRY_AGAIN: error = EAI_AGAIN; break; case NO_RECOVERY: case NETDB_INTERNAL: default: error = EAI_FAIL; break; } } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || (hp->h_addr_list[0] == NULL)) { #ifdef USE_GETIPNODEBY freehostent(hp); #endif hp = NULL; error = EAI_FAIL; } if (hp == NULL) goto free; #ifdef USE_GETIPNODEBY aplist = hp->h_addr_list; #else /* * hp will be overwritten if we use gethostbyname2(). * always deep copy for simplification. */ for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++) ; naddrs++; aplist = (char **)malloc(sizeof(aplist[0]) * naddrs); apbuf = (char *)malloc(hp->h_length * naddrs); if (aplist == NULL || apbuf == NULL) { error = EAI_MEMORY; goto free; } memset(aplist, 0, sizeof(aplist[0]) * naddrs); for (i = 0; i < naddrs; i++) { if (hp->h_addr_list[i] == NULL) { aplist[i] = NULL; continue; } memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i], hp->h_length); aplist[i] = &apbuf[i * hp->h_length]; } #endif for (i = 0; aplist[i] != NULL; i++) { af = hp->h_addrtype; ap = aplist[i]; #ifdef AF_INET6 if (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { af = AF_INET; ap = ap + sizeof(struct in6_addr) - sizeof(struct in_addr); } #endif if (af != pai->ai_family) continue; if ((pai->ai_flags & AI_CANONNAME) == 0) { GET_AI(cur->ai_next, afd, ap); GET_PORT(cur->ai_next, servname); } else { /* * if AI_CANONNAME and if reverse lookup * fail, return ai anyway to pacify * calling application. * * XXX getaddrinfo() is a name->address * translation function, and it looks * strange that we do addr->name * translation here. */ get_name(ap, afd, &cur->ai_next, ap, pai, servname); } while (cur && cur->ai_next) cur = cur->ai_next; } *res = sentinel.ai_next; return 0; free: #ifdef USE_GETIPNODEBY if (hp) freehostent(hp); #endif if (aplist) free(aplist); if (apbuf) free(apbuf); if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); return error; } /* * hostname == NULL. * passive socket -> anyaddr (0.0.0.0 or ::) * non-passive socket -> localhost (127.0.0.1 or ::1) */ static int explore_null(pai, hostname, servname, res) const struct addrinfo *pai; const char *hostname; const char *servname; struct addrinfo **res; { int s; const struct afd *afd; struct addrinfo *cur; struct addrinfo sentinel; int error; *res = NULL; sentinel.ai_next = NULL; cur = &sentinel; /* * filter out AFs that are not supported by the kernel * XXX errno? */ s = socket(pai->ai_family, SOCK_DGRAM, 0); if (s < 0) { if (errno != EMFILE) return 0; } else close(s); /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) return 0; afd = find_afd(pai->ai_family); if (pai->ai_flags & AI_PASSIVE) { GET_AI(cur->ai_next, afd, afd->a_addrany); /* xxx meaningless? * GET_CANONNAME(cur->ai_next, "anyaddr"); */ GET_PORT(cur->ai_next, servname); } else { GET_AI(cur->ai_next, afd, afd->a_loopback); /* xxx meaningless? * GET_CANONNAME(cur->ai_next, "localhost"); */ GET_PORT(cur->ai_next, servname); } cur = cur->ai_next; *res = sentinel.ai_next; return 0; free: if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); return error; } /* * numeric hostname */ static int explore_numeric(pai, hostname, servname, res) const struct addrinfo *pai; const char *hostname; const char *servname; struct addrinfo **res; { const struct afd *afd; struct addrinfo *cur; struct addrinfo sentinel; int error; char pton[PTON_MAX]; int flags; *res = NULL; sentinel.ai_next = NULL; cur = &sentinel; /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) return 0; afd = find_afd(pai->ai_family); flags = pai->ai_flags; if (inet_pton(afd->a_af, hostname, pton) == 1) { u_int32_t v4a; #ifdef INET6 u_char pfx; #endif switch (afd->a_af) { case AF_INET: v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr); if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) flags &= ~AI_CANONNAME; v4a >>= IN_CLASSA_NSHIFT; if (v4a == 0 || v4a == IN_LOOPBACKNET) flags &= ~AI_CANONNAME; break; #ifdef INET6 case AF_INET6: pfx = ((struct in6_addr *)pton)->s6_addr[0]; if (pfx == 0 || pfx == 0xfe || pfx == 0xff) flags &= ~AI_CANONNAME; break; #endif } if (pai->ai_family == afd->a_af || pai->ai_family == PF_UNSPEC /*?*/) { if ((flags & AI_CANONNAME) == 0) { GET_AI(cur->ai_next, afd, pton); GET_PORT(cur->ai_next, servname); } else { /* * if AI_CANONNAME and if reverse lookup * fail, return ai anyway to pacify * calling application. * * XXX getaddrinfo() is a name->address * translation function, and it looks * strange that we do addr->name * translation here. */ get_name(pton, afd, &cur->ai_next, pton, pai, servname); } while (cur && cur->ai_next) cur = cur->ai_next; } else ERR(EAI_FAMILY); /*xxx*/ } *res = sentinel.ai_next; return 0; free: bad: if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); return error; } /* * numeric hostname with scope */ static int explore_numeric_scope(pai, hostname, servname, res) const struct addrinfo *pai; const char *hostname; const char *servname; struct addrinfo **res; { #ifndef SCOPE_DELIMITER return explore_numeric(pai, hostname, servname, res); #else const struct afd *afd; struct addrinfo *cur; int error; char *cp, *hostname2 = NULL; int scope; struct sockaddr_in6 *sin6; /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) return 0; afd = find_afd(pai->ai_family); if (!afd->a_scoped) return explore_numeric(pai, hostname, servname, res); cp = strchr(hostname, SCOPE_DELIMITER); if (cp == NULL) return explore_numeric(pai, hostname, servname, res); /* * Handle special case of */ hostname2 = strdup(hostname); if (hostname2 == NULL) return EAI_MEMORY; /* terminate at the delimiter */ hostname2[cp - hostname] = '\0'; cp++; switch (pai->ai_family) { #ifdef INET6 case AF_INET6: scope = if_nametoindex(cp); if (scope == 0) { free(hostname2); return (EAI_NONAME); } break; #endif } error = explore_numeric(pai, hostname2, servname, res); if (error == 0) { for (cur = *res; cur; cur = cur->ai_next) { if (cur->ai_family != AF_INET6) continue; sin6 = (struct sockaddr_in6 *)cur->ai_addr; if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) sin6->sin6_scope_id = scope; } } free(hostname2); return error; #endif } static int get_name(addr, afd, res, numaddr, pai, servname) const char *addr; const struct afd *afd; struct addrinfo **res; char *numaddr; const struct addrinfo *pai; const char *servname; { struct hostent *hp = NULL; struct addrinfo *cur = NULL; int error = 0; char *ap = NULL, *cn = NULL; #ifdef USE_GETIPNODEBY int h_error; hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error); #else hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); #endif if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { #ifdef USE_GETIPNODEBY GET_AI(cur, afd, hp->h_addr_list[0]); GET_PORT(cur, servname); GET_CANONNAME(cur, hp->h_name); #else /* hp will be damaged if we use gethostbyaddr() */ if ((ap = (char *)malloc(hp->h_length)) == NULL) { error = EAI_MEMORY; goto free; } memcpy(ap, hp->h_addr_list[0], hp->h_length); if ((cn = strdup(hp->h_name)) == NULL) { error = EAI_MEMORY; goto free; } GET_AI(cur, afd, ap); GET_PORT(cur, servname); GET_CANONNAME(cur, cn); free(ap); ap = NULL; free(cn); cn = NULL; #endif } else { GET_AI(cur, afd, numaddr); GET_PORT(cur, servname); } #ifdef USE_GETIPNODEBY if (hp) freehostent(hp); #endif *res = cur; return SUCCESS; free: if (cur) freeaddrinfo(cur); if (ap) free(ap); if (cn) free(cn); #ifdef USE_GETIPNODEBY if (hp) freehostent(hp); #endif *res = NULL; return error; } static int get_canonname(pai, ai, str) const struct addrinfo *pai; struct addrinfo *ai; const char *str; { if ((pai->ai_flags & AI_CANONNAME) != 0) { ai->ai_canonname = (char *)malloc(strlen(str) + 1); if (ai->ai_canonname == NULL) return EAI_MEMORY; strcpy(ai->ai_canonname, str); } return 0; } static struct addrinfo * get_ai(pai, afd, addr) const struct addrinfo *pai; const struct afd *afd; const char *addr; { char *p; struct addrinfo *ai; ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + (afd->a_socklen)); if (ai == NULL) return NULL; memcpy(ai, pai, sizeof(struct addrinfo)); ai->ai_addr = (struct sockaddr *)(ai + 1); memset(ai->ai_addr, 0, afd->a_socklen); #ifdef HAVE_SOCKADDR_SA_LEN ai->ai_addr->sa_len = afd->a_socklen; #endif ai->ai_addrlen = afd->a_socklen; ai->ai_addr->sa_family = ai->ai_family = afd->a_af; p = (char *)(ai->ai_addr); memcpy(p + afd->a_off, addr, afd->a_addrlen); return ai; } static int get_portmatch(ai, servname) const struct addrinfo *ai; const char *servname; { /* get_port does not touch first argument. when matchonly == 1. */ return get_port((struct addrinfo *)ai, servname, 1); } static int get_port(ai, servname, matchonly) struct addrinfo *ai; const char *servname; int matchonly; { const char *proto; struct servent *sp; int port; int allownumeric; if (servname == NULL) return 0; switch (ai->ai_family) { case AF_INET: #ifdef AF_INET6 case AF_INET6: #endif break; default: return 0; } switch (ai->ai_socktype) { case SOCK_RAW: return EAI_SERVICE; case SOCK_DGRAM: case SOCK_STREAM: allownumeric = 1; break; case ANY: allownumeric = 0; break; default: return EAI_SOCKTYPE; } if (str_isnumber(servname)) { if (!allownumeric) return EAI_SERVICE; port = htons(atoi(servname)); if (port < 0 || port > 65535) return EAI_SERVICE; } else { switch (ai->ai_socktype) { case SOCK_DGRAM: proto = "udp"; break; case SOCK_STREAM: proto = "tcp"; break; default: proto = NULL; break; } if ((sp = getservbyname(servname, proto)) == NULL) return EAI_SERVICE; port = sp->s_port; } if (!matchonly) { switch (ai->ai_family) { case AF_INET: ((struct sockaddr_in *)ai->ai_addr)->sin_port = port; break; #ifdef INET6 case AF_INET6: ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port; break; #endif } } return 0; } static const struct afd * find_afd(af) int af; { const struct afd *afd; if (af == PF_UNSPEC) return NULL; for (afd = afdl; afd->a_af; afd++) { if (afd->a_af == af) return afd; } return NULL; } libpcap-0.9.7/./Win32/Src/getservent.c0000644000026300017500000000662107522171106015411 0ustar mcrmcr/* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #define MAXALIASES 35 static char SERVDB[] = _PATH_SERVICES; static FILE *servf = NULL; static char line[BUFSIZ+1]; static struct servent serv; static char *serv_aliases[MAXALIASES]; int _serv_stayopen; void setservent(f) int f; { if (servf == NULL) servf = fopen(SERVDB, "r" ); else rewind(servf); _serv_stayopen |= f; } void endservent() { if (servf) { fclose(servf); servf = NULL; } _serv_stayopen = 0; } struct servent * getservent() { char *p; register char *cp, **q; if (servf == NULL && (servf = fopen(SERVDB, "r" )) == NULL) return (NULL); again: if ((p = fgets(line, BUFSIZ, servf)) == NULL) return (NULL); if (*p == '#') goto again; cp = strpbrk(p, "#\n"); if (cp == NULL) goto again; *cp = '\0'; serv.s_name = p; p = strpbrk(p, " \t"); if (p == NULL) goto again; *p++ = '\0'; while (*p == ' ' || *p == '\t') p++; cp = strpbrk(p, ",/"); if (cp == NULL) goto again; *cp++ = '\0'; serv.s_port = htons((u_short)atoi(p)); serv.s_proto = cp; q = serv.s_aliases = serv_aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (q < &serv_aliases[MAXALIASES - 1]) *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; return (&serv); } libpcap-0.9.7/./Win32/Src/inet_pton.c0000644000026300017500000000471407755532626015243 0ustar mcrmcr/* * Copyright (c) 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * 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 Kungliga Tekniska * Högskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $Id: inet_pton.c,v 1.2 2003/11/15 23:24:06 guy Exp $ */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/Win32/Src/inet_pton.c,v 1.2 2003/11/15 23:24:06 guy Exp $"; #endif #include #ifdef WIN32 #ifndef EAFNOSUPPORT #define EAFNOSUPPORT 97 /* not present in errno.h provided with VC */ #endif #endif #ifdef __MINGW32__ int* _errno(); #define errno (*_errno()) #endif /* __MINGW32__ */ #include int inet_pton(int af, const char *src, void *dst) { if (af != AF_INET) { errno = EAFNOSUPPORT; return -1; } return inet_aton (src, dst); } libpcap-0.9.7/./Win32/Prj/0000755000026300017500000000000010245661224013057 5ustar mcrmcrlibpcap-0.9.7/./Win32/Prj/libpcap.dsp0000644000026300017500000001103210005741141015165 0ustar mcrmcr# Microsoft Developer Studio Project File - Name="libpcap" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Static Library" 0x0104 CFG=libpcap - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "libpcap.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "libpcap.mak" CFG="libpcap - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "libpcap - Win32 Release" (based on "Win32 (x86) Static Library") !MESSAGE "libpcap - Win32 Debug" (based on "Win32 (x86) Static Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "libpcap - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../lbl/" /I "../../bpf/" /I "../include/" /I "../../../../common" /I "../../../../dag/include" /I "../../../../dag/drv/windows" /D "NDEBUG" /D "YY_NEVER_INTERACTIVE" /D yylval=pcap_lval /D "_USRDLL" /D "LIBPCAP_EXPORTS" /D "HAVE_STRERROR" /D "__STDC__" /D "INET6" /D "_WINDOWS" /D "_MBCS" /D SIZEOF_CHAR=1 /D SIZEOF_SHORT=2 /D SIZEOF_INT=4 /D "HAVE_ADDRINFO" /D "WIN32" /D _U_= /D "HAVE_SNPRINTF" /D "HAVE_VSNPRINTF" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo !ELSEIF "$(CFG)" == "libpcap - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../lbl/" /I "../../bpf/" /I "../include/" /I "../../../../common" /I "../../../../dag/include" /I "../../../../dag/drv/windows" /D "_DEBUG" /D "YY_NEVER_INTERACTIVE" /D yylval=pcap_lval /D "_USRDLL" /D "LIBPCAP_EXPORTS" /D "HAVE_STRERROR" /D "__STDC__" /D "INET6" /D "_WINDOWS" /D "_MBCS" /D SIZEOF_CHAR=1 /D SIZEOF_SHORT=2 /D SIZEOF_INT=4 /D "HAVE_ADDRINFO" /D "WIN32" /D _U_= /D "HAVE_SNPRINTF" /D "HAVE_VSNPRINTF" /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo !ENDIF # Begin Target # Name "libpcap - Win32 Release" # Name "libpcap - Win32 Debug" # Begin Source File SOURCE=..\..\bpf_dump.c # End Source File # Begin Source File SOURCE=..\..\bpf\net\bpf_filter.c # End Source File # Begin Source File SOURCE=..\..\bpf_image.c # End Source File # Begin Source File SOURCE=..\..\etherent.c # End Source File # Begin Source File SOURCE="..\..\fad-win32.c" # End Source File # Begin Source File SOURCE=..\Src\ffs.c # End Source File # Begin Source File SOURCE=..\..\gencode.c # End Source File # Begin Source File SOURCE=..\Src\getnetbynm.c # End Source File # Begin Source File SOURCE=..\Src\getnetent.c # End Source File # Begin Source File SOURCE=..\Src\getservent.c # End Source File # Begin Source File SOURCE=..\..\grammar.c # End Source File # Begin Source File SOURCE=..\..\inet.c # End Source File # Begin Source File SOURCE=..\Src\inet_aton.c # End Source File # Begin Source File SOURCE=..\Src\inet_net.c # End Source File # Begin Source File SOURCE=..\Src\inet_pton.c # End Source File # Begin Source File SOURCE=..\..\nametoaddr.c # End Source File # Begin Source File SOURCE=..\..\optimize.c # End Source File # Begin Source File SOURCE="..\..\Pcap-win32.c" # End Source File # Begin Source File SOURCE=..\..\pcap.c # End Source File # Begin Source File SOURCE=..\..\savefile.c # End Source File # Begin Source File SOURCE=..\..\scanner.c # End Source File # End Target # End Project libpcap-0.9.7/./Win32/Prj/CVS/0000755000026300017500000000000010245661224013512 5ustar mcrmcrlibpcap-0.9.7/./Win32/Prj/CVS/Entries0000644000026300017500000000016210245661224015045 0ustar mcrmcr/libpcap.dsp/1.5/Wed Jan 28 14:08:33 2004//Tlibpcap_0_9 /libpcap.dsw/1.1/Fri Aug 9 13:54:19 2002//Tlibpcap_0_9 D libpcap-0.9.7/./Win32/Prj/CVS/Root0000644000026300017500000000004010245661224014352 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./Win32/Prj/CVS/Repository0000644000026300017500000000002210245661224015606 0ustar mcrmcrlibpcap/Win32/Prj libpcap-0.9.7/./Win32/Prj/CVS/Tag0000644000026300017500000000001510245661224014144 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./Win32/Prj/libpcap.dsw0000644000026300017500000000077607524744613015234 0ustar mcrmcrMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "libpcap"=".\libpcap.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### libpcap-0.9.7/./LICENSE0000644000026300017500000000155107170444400012427 0ustar mcrmcrLicense: BSD Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of the authors 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. libpcap-0.9.7/./nlpid.h0000644000026300017500000000340507573764336012725 0ustar mcrmcr/* * Copyright (c) 1996 * Juniper Networks, Inc. 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. The name of Juniper Networks 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 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#) $Header: /tcpdump/master/libpcap/nlpid.h,v 1.2 2002/12/06 00:01:34 hannes Exp $ (Juniper) */ /* Types missing from some systems */ /* * Network layer prototocol identifiers */ #ifndef ISO8473_CLNP #define ISO8473_CLNP 0x81 #endif #ifndef ISO9542_ESIS #define ISO9542_ESIS 0x82 #endif #ifndef ISO9542X25_ESIS #define ISO9542X25_ESIS 0x8a #endif #ifndef ISO10589_ISIS #define ISO10589_ISIS 0x83 #endif /* * this does not really belong in the nlpid.h file * however we need it for generating nice * IS-IS related BPF filters */ #define ISIS_L1_LAN_IIH 15 #define ISIS_L2_LAN_IIH 16 #define ISIS_PTP_IIH 17 #define ISIS_L1_LSP 18 #define ISIS_L2_LSP 20 #define ISIS_L1_CSNP 24 #define ISIS_L2_CSNP 25 #define ISIS_L1_PSNP 26 #define ISIS_L2_PSNP 27 #ifndef ISO8878A_CONS #define ISO8878A_CONS 0x84 #endif #ifndef ISO10747_IDRP #define ISO10747_IDRP 0x85 #endif libpcap-0.9.7/./pcap-int.h0000644000026300017500000002507610643174160013320 0ustar mcrmcr/* * 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: /tcpdump/master/libpcap/pcap-int.h,v 1.68.2.11 2007/06/22 06:43:58 guy Exp $ (LBL) */ #ifndef pcap_int_h #define pcap_int_h #ifdef __cplusplus extern "C" { #endif #include #ifdef WIN32 #include #endif /* WIN32 */ #ifdef MSDOS #include #include #endif /* * Swap byte ordering of unsigned long long timestamp on a big endian * machine. */ #define SWAPLL(ull) ((ull & 0xff00000000000000LL) >> 56) | \ ((ull & 0x00ff000000000000LL) >> 40) | \ ((ull & 0x0000ff0000000000LL) >> 24) | \ ((ull & 0x000000ff00000000LL) >> 8) | \ ((ull & 0x00000000ff000000LL) << 8) | \ ((ull & 0x0000000000ff0000LL) << 24) | \ ((ull & 0x000000000000ff00LL) << 40) | \ ((ull & 0x00000000000000ffLL) << 56) /* * Savefile */ typedef enum { NOT_SWAPPED, SWAPPED, MAYBE_SWAPPED } swapped_type_t; struct pcap_sf { FILE *rfile; int swapped; int hdrsize; swapped_type_t lengths_swapped; int version_major; int version_minor; u_char *base; }; struct pcap_md { struct pcap_stat stat; /*XXX*/ int use_bpf; /* using kernel filter */ 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 */ char *device; /* device name */ #ifdef linux int sock_packet; /* using Linux 2.0 compatible interface */ int timeout; /* timeout specified to pcap_open_live */ int clear_promisc; /* must clear promiscuous mode when we close */ int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ int ifindex; /* interface index of device we're bound to */ int lo_ifindex; /* interface index of the loopback device */ struct pcap *next; /* list of open promiscuous sock_packet pcaps */ u_int packets_read; /* count of packets read with recvfrom() */ #endif #ifdef HAVE_DAG_API #ifdef HAVE_DAG_STREAMS_API u_char *dag_mem_bottom; /* DAG card current memory bottom pointer */ u_char *dag_mem_top; /* DAG card current memory top pointer */ #else void *dag_mem_base; /* DAG card memory base address */ u_int dag_mem_bottom; /* DAG card current memory bottom offset */ u_int dag_mem_top; /* DAG card current memory top offset */ #endif /* HAVE_DAG_STREAMS_API */ int dag_fcs_bits; /* Number of checksum bits from link layer */ int dag_offset_flags; /* Flags to pass to dag_offset(). */ int dag_stream; /* DAG stream number */ int dag_timeout; /* timeout specified to pcap_open_live. * Same as in linux above, introduce * generally? */ #endif /* HAVE_DAG_API */ }; /* * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H * Tru64 UNIX, and some versions of NetBSD pad FDDI packets to make everything * line up on a nice boundary. */ #ifdef __NetBSD__ #include /* needed to declare __NetBSD_Version__ */ #endif #if defined(ultrix) || defined(__osf__) || (defined(__NetBSD__) && __NetBSD_Version__ > 106000000) #define PCAP_FDDIPAD 3 #endif struct pcap { #ifdef WIN32 ADAPTER *adapter; LPPACKET Packet; int timeout; int nonblock; #else int fd; int selectable_fd; int send_fd; #endif /* WIN32 */ int snapshot; int linktype; int tzoff; /* timezone offset */ int offset; /* offset for proper alignment */ int break_loop; /* flag set to force break from packet-reading loop */ #ifdef PCAP_FDDIPAD int fddipad; #endif #ifdef MSDOS int inter_packet_wait; /* offline: wait between packets */ void (*wait_proc)(void); /* call proc while waiting */ #endif 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; /* We're accepting only packets in this direction/these directions. */ pcap_direction_t direction; /* * Methods. */ int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *); int (*inject_op)(pcap_t *, const void *, size_t); int (*setfilter_op)(pcap_t *, struct bpf_program *); int (*setdirection_op)(pcap_t *, pcap_direction_t); int (*set_datalink_op)(pcap_t *, int); int (*getnonblock_op)(pcap_t *, char *); int (*setnonblock_op)(pcap_t *, int, char *); int (*stats_op)(pcap_t *, struct pcap_stat *); void (*close_op)(pcap_t *); /* * Placeholder for filter code if bpf not in kernel. */ struct bpf_program fcode; char errbuf[PCAP_ERRBUF_SIZE + 1]; int dlt_count; u_int *dlt_list; struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */ }; /* * This is a timeval as stored in a savefile. * It has to use the same types everywhere, independent of the actual * `struct timeval'; `struct timeval' has 32-bit tv_sec values on some * platforms and 64-bit tv_sec values on other platforms, and writing * out native `struct timeval' values would mean files could only be * read on systems with the same tv_sec size as the system on which * the file was written. */ struct pcap_timeval { bpf_int32 tv_sec; /* seconds */ bpf_int32 tv_usec; /* microseconds */ }; /* * This is a `pcap_pkthdr' as actually stored in a savefile. * * Do not change the format of this structure, in any way (this includes * changes that only affect the length of fields in this structure), * and do not make the time stamp anything other than seconds and * microseconds (e.g., seconds and nanoseconds). Instead: * * introduce a new structure for the new format; * * send mail to "tcpdump-workers@tcpdump.org", requesting a new * magic number for your new capture file format, and, when * you get the new magic number, put it in "savefile.c"; * * use that magic number for save files with the changed record * header; * * make the code in "savefile.c" capable of reading files with * the old record header as well as files with the new record header * (using the magic number to determine the header format). * * Then supply the changes to "patches@tcpdump.org", so that future * versions of libpcap and programs that use it (such as tcpdump) will * be able to read your new capture file format. */ struct pcap_sf_pkthdr { struct pcap_timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }; /* * How a `pcap_pkthdr' is actually stored in savefiles written * by some patched versions of libpcap (e.g. the ones in Red * Hat Linux 6.1 and 6.2). * * Do not change the format of this structure, in any way (this includes * changes that only affect the length of fields in this structure). * Instead, introduce a new structure, as per the above. */ struct pcap_sf_patched_pkthdr { struct pcap_timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ int index; unsigned short protocol; unsigned char pkt_type; }; 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 *); #ifndef HAVE_STRLCPY #define strlcpy(x, y, z) \ (strncpy((x), (y), (z)), \ ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \ strlen((y))) #endif #include #if !defined(HAVE_SNPRINTF) #define snprintf pcap_snprintf extern int snprintf (char *, size_t, const char *, ...); #endif #if !defined(HAVE_VSNPRINTF) #define vsnprintf pcap_vsnprintf extern int vsnprintf (char *, size_t, const char *, va_list ap); #endif /* * Routines that most pcap implementations can use for non-blocking mode. */ #if !defined(WIN32) && !defined(MSDOS) int pcap_getnonblock_fd(pcap_t *, char *); int pcap_setnonblock_fd(pcap_t *p, int, char *); #endif void pcap_close_common(pcap_t *); /* * Internal interfaces for "pcap_findalldevs()". * * "pcap_platform_finddevs()" is a platform-dependent routine to * add devices not found by the "standard" mechanisms (SIOCGIFCONF, * "getifaddrs()", etc.. * * "pcap_add_if()" adds an interface to the list of interfaces. */ int pcap_platform_finddevs(pcap_if_t **, char *); int add_addr_to_iflist(pcap_if_t **, const char *, u_int, struct sockaddr *, size_t, struct sockaddr *, size_t, struct sockaddr *, size_t, struct sockaddr *, size_t, char *); int pcap_add_if(pcap_if_t **, const char *, u_int, const char *, char *); struct sockaddr *dup_sockaddr(struct sockaddr *, size_t); int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int, const char *, char *); #ifdef WIN32 char *pcap_win32strerror(void); #endif int install_bpf_program(pcap_t *, struct bpf_program *); int pcap_strcasecmp(const char *, const char *); #ifdef __cplusplus } #endif #endif libpcap-0.9.7/./pcap-nit.c0000644000026300017500000002143210235744355013311 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.57.2.1 2005/05/03 18:54:37 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcap-int.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 *); static int pcap_stats_nit(pcap_t *p, struct pcap_stat *ps) { /* * "ps_recv" counts packets handed to the filter, not packets * that passed the filter. As filtering is done in userland, * this does not include packets dropped because we ran out * of buffer space. * * "ps_drop" presumably counts packets dropped by the socket * because of flow control requirements or resource exhaustion; * it doesn't count packets dropped by the interface driver. * As filtering is done in userland, it counts packets regardless * of whether they would've passed the filter. * * These statistics don't include packets not yet read from the * kernel by libpcap or packets not yet read from libpcap by the * application. */ *ps = p->md.stat; return (0); } static int pcap_read_nit(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); snprintf(p->errbuf, sizeof(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) { /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->cc = ep - bp; p->bp = bp; return (n); } } 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: snprintf(p->errbuf, sizeof(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 pcap_inject_nit(pcap_t *p, const void *buf, size_t size) { struct sockaddr sa; int ret; memset(&sa, 0, sizeof(sa)); strncpy(sa.sa_data, device, sizeof(sa.sa_data)); ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa)); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } static int nit_setflags(int fd, int promisc, int to_ms, char *ebuf) { struct nit_ioc nioc; memset(&nioc, 0, 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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s", pcap_strerror(errno)); return (-1); } return (0); } static void pcap_close_nit(pcap_t *p) { pcap_close_common(p); if (p->device != NULL) free(p->device); } pcap_t * pcap_open_live(const 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) { strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); return (NULL); } if (snaplen < 96) /* * NIT requires a snapshot length of at least 96. */ snaplen = 96; memset(p, 0, sizeof(*p)); p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); if (fd < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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))) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } /* * We need the device name in order to send packets. */ p->device = strdup(device); if (p->device == NULL) { strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); free(p->buffer); goto bad; } /* * "p->fd" is a socket, so "select()" should work on it. */ p->selectable_fd = p->fd; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } p->read_op = pcap_read_nit; p->inject_op = pcap_inject_nit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_nit; p->close_op = pcap_close_nit; return (p); bad: if (fd >= 0) close(fd); free(p); return (NULL); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } libpcap-0.9.7/./pcap.c0000644000026300017500000006225410643174161012523 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88.2.17 2007/06/22 06:43:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #include #endif /* WIN32 */ #include #include #include #if !defined(_MSC_VER) && !defined(__BORLANDC__) #include #endif #include #include #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #ifdef MSDOS #include "pcap-dos.h" #endif #include "pcap-int.h" #ifdef HAVE_DAG_API #include #include #endif int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { return p->read_op(p, cnt, callback, user); } /* * XXX - is this necessary? */ int pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { return p->read_op(p, cnt, callback, user); } int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { register int n; for (;;) { if (p->sf.rfile != NULL) { /* * 0 means EOF, so don't loop if we get 0. */ n = pcap_offline_read(p, cnt, callback, user); } else { /* * XXX keep reading until we get something * (or an error occurs) */ do { n = p->read_op(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); } struct pkt_for_fakecallback { struct pcap_pkthdr *hdr; const u_char **pkt; }; static void pcap_fakecallback(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt) { struct pkt_for_fakecallback *sp = (struct pkt_for_fakecallback *)userData; *sp->hdr = *h; *sp->pkt = pkt; } int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data) { struct pkt_for_fakecallback s; s.hdr = &p->pcap_header; s.pkt = pkt_data; /* Saves a pointer to the packet headers */ *pkt_header= &p->pcap_header; if (p->sf.rfile != NULL) { int status; /* We are on an offline capture */ status = pcap_offline_read(p, 1, pcap_fakecallback, (u_char *)&s); /* * Return codes for pcap_offline_read() are: * - 0: EOF * - -1: error * - >1: OK * The first one ('0') conflicts with the return code of * 0 from pcap_read() meaning "no packets arrived before * the timeout expired", so we map it to -2 so you can * distinguish between an EOF from a savefile and a * "no packets arrived before the timeout expired, try * again" from a live capture. */ if (status == 0) return (-2); else return (status); } /* * Return codes for pcap_read() are: * - 0: timeout * - -1: error * - -2: loop was broken out of with pcap_breakloop() * - >1: OK * The first one ('0') conflicts with the return code of 0 from * pcap_offline_read() meaning "end of file". */ return (p->read_op(p, 1, pcap_fakecallback, (u_char *)&s)); } /* * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate. */ void pcap_breakloop(pcap_t *p) { p->break_loop = 1; } int pcap_datalink(pcap_t *p) { return (p->linktype); } int pcap_list_datalinks(pcap_t *p, int **dlt_buffer) { if (p->dlt_count == 0) { /* * We couldn't fetch the list of DLTs, which means * this platform doesn't support changing the * DLT for an interface. Return a list of DLTs * containing only the DLT this device supports. */ *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer)); if (*dlt_buffer == NULL) { (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (-1); } **dlt_buffer = p->linktype; return (1); } else { *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer) * p->dlt_count); if (*dlt_buffer == NULL) { (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (-1); } (void)memcpy(*dlt_buffer, p->dlt_list, sizeof(**dlt_buffer) * p->dlt_count); return (p->dlt_count); } } int pcap_set_datalink(pcap_t *p, int dlt) { int i; const char *dlt_name; if (p->dlt_count == 0 || p->set_datalink_op == NULL) { /* * We couldn't fetch the list of DLTs, or we don't * have a "set datalink" operation, which means * this platform doesn't support changing the * DLT for an interface. Check whether the new * DLT is the one this interface supports. */ if (p->linktype != dlt) goto unsupported; /* * It is, so there's nothing we need to do here. */ return (0); } for (i = 0; i < p->dlt_count; i++) if (p->dlt_list[i] == dlt) break; if (i >= p->dlt_count) goto unsupported; if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB && dlt == DLT_DOCSIS) { /* * This is presumably an Ethernet device, as the first * link-layer type it offers is DLT_EN10MB, and the only * other type it offers is DLT_DOCSIS. That means that * we can't tell the driver to supply DOCSIS link-layer * headers - we're just pretending that's what we're * getting, as, presumably, we're capturing on a dedicated * link to a Cisco Cable Modem Termination System, and * it's putting raw DOCSIS frames on the wire inside low-level * Ethernet framing. */ p->linktype = dlt; return (0); } if (p->set_datalink_op(p, dlt) == -1) return (-1); p->linktype = dlt; return (0); unsupported: dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name != NULL) { (void) snprintf(p->errbuf, sizeof(p->errbuf), "%s is not one of the DLTs supported by this device", dlt_name); } else { (void) snprintf(p->errbuf, sizeof(p->errbuf), "DLT %d is not one of the DLTs supported by this device", dlt); } return (-1); } struct dlt_choice { const char *name; const char *description; int dlt; }; #define DLT_CHOICE(code, description) { #code, description, code } #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 } static struct dlt_choice dlt_choices[] = { DLT_CHOICE(DLT_NULL, "BSD loopback"), DLT_CHOICE(DLT_EN10MB, "Ethernet"), DLT_CHOICE(DLT_IEEE802, "Token ring"), DLT_CHOICE(DLT_ARCNET, "ARCNET"), DLT_CHOICE(DLT_SLIP, "SLIP"), DLT_CHOICE(DLT_PPP, "PPP"), DLT_CHOICE(DLT_FDDI, "FDDI"), DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"), DLT_CHOICE(DLT_RAW, "Raw IP"), DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"), DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"), DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"), DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"), DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"), DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"), DLT_CHOICE(DLT_IEEE802_11, "802.11"), DLT_CHOICE(DLT_FRELAY, "Frame Relay"), DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"), DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"), DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"), DLT_CHOICE(DLT_LTALK, "Localtalk"), DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"), DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"), DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"), DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"), DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus BSD radio information header"), DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"), DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"), DLT_CHOICE(DLT_DOCSIS, "DOCSIS"), DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"), DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"), DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"), DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"), DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"), DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"), DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"), DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"), DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"), DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"), DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"), DLT_CHOICE(DLT_GPF_T, "GPF-T"), DLT_CHOICE(DLT_GPF_F, "GPF-F"), DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"), DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"), DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"), DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"), DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"), DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"), DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"), DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"), DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"), DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"), DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"), DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"), DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"), DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"), DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"), DLT_CHOICE(DLT_MTP2, "SS7 MTP2"), DLT_CHOICE(DLT_A429, "Arinc 429"), DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"), DLT_CHOICE(DLT_USB, "USB"), DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"), DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"), DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"), DLT_CHOICE_SENTINEL }; /* * This array is designed for mapping upper and lower case letter * together for a case independent comparison. The mappings are * based upon ascii character sequences. */ static const u_char charmap[] = { (u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003', (u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007', (u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013', (u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017', (u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023', (u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027', (u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033', (u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037', (u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043', (u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047', (u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053', (u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057', (u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063', (u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067', (u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073', (u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077', (u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143', (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147', (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153', (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157', (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163', (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167', (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133', (u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137', (u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143', (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147', (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153', (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157', (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163', (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167', (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173', (u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177', (u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203', (u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207', (u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213', (u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217', (u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223', (u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227', (u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233', (u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237', (u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243', (u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247', (u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253', (u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257', (u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263', (u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267', (u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273', (u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277', (u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343', (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347', (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353', (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357', (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363', (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367', (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333', (u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337', (u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343', (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347', (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353', (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357', (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363', (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367', (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373', (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377', }; int pcap_strcasecmp(const char *s1, const char *s2) { register const u_char *cm = charmap, *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; while (cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return(0); return (cm[*us1] - cm[*--us2]); } int pcap_datalink_name_to_val(const char *name) { int i; for (i = 0; dlt_choices[i].name != NULL; i++) { if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1, name) == 0) return (dlt_choices[i].dlt); } return (-1); } const char * pcap_datalink_val_to_name(int dlt) { int i; for (i = 0; dlt_choices[i].name != NULL; i++) { if (dlt_choices[i].dlt == dlt) return (dlt_choices[i].name + sizeof("DLT_") - 1); } return (NULL); } const char * pcap_datalink_val_to_description(int dlt) { int i; for (i = 0; dlt_choices[i].name != NULL; i++) { if (dlt_choices[i].dlt == dlt) return (dlt_choices[i].description); } return (NULL); } int pcap_snapshot(pcap_t *p) { return (p->snapshot); } int pcap_is_swapped(pcap_t *p) { return (p->sf.swapped); } int pcap_major_version(pcap_t *p) { return (p->sf.version_major); } int pcap_minor_version(pcap_t *p) { return (p->sf.version_minor); } FILE * pcap_file(pcap_t *p) { return (p->sf.rfile); } int pcap_fileno(pcap_t *p) { #ifndef WIN32 return (p->fd); #else if (p->adapter != NULL) return ((int)(DWORD)p->adapter->hFile); else return (-1); #endif } #if !defined(WIN32) && !defined(MSDOS) int pcap_get_selectable_fd(pcap_t *p) { return (p->selectable_fd); } #endif 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); } int pcap_getnonblock(pcap_t *p, char *errbuf) { return p->getnonblock_op(p, errbuf); } /* * Get the current non-blocking mode setting, under the assumption that * it's just the standard POSIX non-blocking flag. * * We don't look at "p->nonblock", in case somebody tweaked the FD * directly. */ #if !defined(WIN32) && !defined(MSDOS) int pcap_getnonblock_fd(pcap_t *p, char *errbuf) { int fdflags; fdflags = fcntl(p->fd, F_GETFL, 0); if (fdflags == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", pcap_strerror(errno)); return (-1); } if (fdflags & O_NONBLOCK) return (1); else return (0); } #endif int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) { return p->setnonblock_op(p, nonblock, errbuf); } #if !defined(WIN32) && !defined(MSDOS) /* * Set non-blocking mode, under the assumption that it's just the * standard POSIX non-blocking flag. (This can be called by the * per-platform non-blocking-mode routine if that routine also * needs to do some additional work.) */ int pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf) { int fdflags; fdflags = fcntl(p->fd, F_GETFL, 0); if (fdflags == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", pcap_strerror(errno)); return (-1); } if (nonblock) fdflags |= O_NONBLOCK; else fdflags &= ~O_NONBLOCK; if (fcntl(p->fd, F_SETFL, fdflags) == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", pcap_strerror(errno)); return (-1); } return (0); } #endif #ifdef WIN32 /* * Generate a string for the last Win32-specific error (i.e. an error generated when * calling a Win32 API). * For errors occurred during standard C calls, we still use pcap_strerror() */ char * pcap_win32strerror(void) { DWORD error; static char errbuf[PCAP_ERRBUF_SIZE+1]; int errlen; char *p; error = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, PCAP_ERRBUF_SIZE, NULL); /* * "FormatMessage()" "helpfully" sticks CR/LF at the end of the * message. Get rid of it. */ errlen = strlen(errbuf); if (errlen >= 2) { errbuf[errlen - 1] = '\0'; errbuf[errlen - 2] = '\0'; } p = strchr(errbuf, '\0'); snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error); return (errbuf); } #endif /* * Not all systems have strerror(). */ const 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)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); return(ebuf); #endif } int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { return p->setfilter_op(p, fp); } /* * Set direction flag, which controls whether we accept only incoming * packets, only outgoing packets, or both. * Note that, depending on the platform, some or all direction arguments * might not be supported. */ int pcap_setdirection(pcap_t *p, pcap_direction_t d) { if (p->setdirection_op == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Setting direction is not implemented on this platform"); return -1; } else return p->setdirection_op(p, d); } int pcap_stats(pcap_t *p, struct pcap_stat *ps) { return p->stats_op(p, ps); } static int pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Statistics aren't available from a pcap_open_dead pcap_t"); return (-1); } void pcap_close_common(pcap_t *p) { if (p->buffer != NULL) free(p->buffer); #if !defined(WIN32) && !defined(MSDOS) if (p->fd >= 0) close(p->fd); #endif } static void pcap_close_dead(pcap_t *p _U_) { /* Nothing to do. */ } pcap_t * pcap_open_dead(int linktype, int snaplen) { pcap_t *p; p = malloc(sizeof(*p)); if (p == NULL) return NULL; memset (p, 0, sizeof(*p)); p->snapshot = snaplen; p->linktype = linktype; p->stats_op = pcap_stats_dead; p->close_op = pcap_close_dead; return p; } /* * API compatible with WinPcap's "send a packet" routine - returns -1 * on error, 0 otherwise. * * XXX - what if we get a short write? */ int pcap_sendpacket(pcap_t *p, const u_char *buf, int size) { if (p->inject_op(p, buf, size) == -1) return (-1); return (0); } /* * API compatible with OpenBSD's "send a packet" routine - returns -1 on * error, number of bytes written otherwise. */ int pcap_inject(pcap_t *p, const void *buf, size_t size) { return (p->inject_op(p, buf, size)); } void pcap_close(pcap_t *p) { p->close_op(p); if (p->dlt_list != NULL) free(p->dlt_list); pcap_freecode(&p->fcode); free(p); } /* * We make the version string static, and return a pointer to it, rather * than exporting the version string directly. On at least some UNIXes, * if you import data from a shared library into an program, the data is * bound into the program binary, so if the string in the version of the * library with which the program was linked isn't the same as the * string in the version of the library with which the program is being * run, various undesirable things may happen (warnings, the string * being the one from the version of the library with which the program * was linked, or even weirder things, such as the string being the one * from the library but being truncated). */ #ifdef HAVE_VERSION_H #include "version.h" #else static const char pcap_version_string[] = "libpcap version 0.9.7"; #endif #ifdef WIN32 /* * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap * version numbers when building WinPcap. (It'd be nice to do so for * the packet.dll version number as well.) */ static const char wpcap_version_string[] = "4.0"; static const char pcap_version_string_fmt[] = "WinPcap version %s, based on %s"; static const char pcap_version_string_packet_dll_fmt[] = "WinPcap version %s (packet.dll version %s), based on %s"; static char *full_pcap_version_string; const char * pcap_lib_version(void) { char *packet_version_string; size_t full_pcap_version_string_len; if (full_pcap_version_string == NULL) { /* * Generate the version string. */ packet_version_string = PacketGetVersion(); if (strcmp(wpcap_version_string, packet_version_string) == 0) { /* * WinPcap version string and packet.dll version * string are the same; just report the WinPcap * version. */ full_pcap_version_string_len = (sizeof pcap_version_string_fmt - 4) + strlen(wpcap_version_string) + strlen(pcap_version_string); full_pcap_version_string = malloc(full_pcap_version_string_len); sprintf(full_pcap_version_string, pcap_version_string_fmt, wpcap_version_string, pcap_version_string); } else { /* * WinPcap version string and packet.dll version * string are different; that shouldn't be the * case (the two libraries should come from the * same version of WinPcap), so we report both * versions. */ full_pcap_version_string_len = (sizeof pcap_version_string_packet_dll_fmt - 6) + strlen(wpcap_version_string) + strlen(packet_version_string) + strlen(pcap_version_string); full_pcap_version_string = malloc(full_pcap_version_string_len); sprintf(full_pcap_version_string, pcap_version_string_packet_dll_fmt, wpcap_version_string, packet_version_string, pcap_version_string); } } return (full_pcap_version_string); } #elif defined(MSDOS) static char *full_pcap_version_string; const char * pcap_lib_version (void) { char *packet_version_string; size_t full_pcap_version_string_len; static char dospfx[] = "DOS-"; if (full_pcap_version_string == NULL) { /* * Generate the version string. */ full_pcap_version_string_len = sizeof dospfx + strlen(pcap_version_string); full_pcap_version_string = malloc(full_pcap_version_string_len); strcpy(full_pcap_version_string, dospfx); strcat(full_pcap_version_string, pcap_version_string); } return (full_pcap_version_string); } #else /* UN*X */ const char * pcap_lib_version(void) { return (pcap_version_string); } #endif libpcap-0.9.7/./config.h.in0000644000026300017500000001136310643174157013457 0ustar mcrmcr/* config.h.in. Generated from configure.in by autoheader. */ /* Long story short: aclocal.m4 depends on autoconf 2.13 * implementation details wrt "const"; newer versions * have different implementation details so for now we * put "const" here. This may cause duplicate definitions * in config.h but that should be OK since they're the same. */ #undef const /* Enable optimizer debugging */ #undef BDEBUG /* define if you have a cloning BPF device */ #undef HAVE_CLONING_BPF /* define if you have the DAG API */ #undef HAVE_DAG_API /* define if you have dag_get_erf_types() */ #undef HAVE_DAG_GET_ERF_TYPES /* define if you have streams capable DAG API */ #undef HAVE_DAG_STREAMS_API /* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you don't. */ #undef HAVE_DECL_ETHER_HOSTTON /* define if you have a /dev/dlpi */ #undef HAVE_DEV_DLPI /* Define to 1 if you have the `ether_hostton' function. */ #undef HAVE_ETHER_HOSTTON /* on HP-UX 10.20 or later */ #undef HAVE_HPUX10_20_OR_LATER /* on HP-UX 9.x */ #undef HAVE_HPUX9 /* if ppa_info_t_dl_module_id exists */ #undef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_ETHER_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IF_ETHER_H /* if there's an os_proto.h */ #undef HAVE_OS_PROTO_H /* Define to 1 if you have the header file. */ #undef HAVE_PATHS_H /* define if you have a /proc/net/dev */ #undef HAVE_PROC_NET_DEV /* define if you have a Septel API */ #undef HAVE_SEPTEL_API /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* if struct sockaddr has sa_len */ #undef HAVE_SOCKADDR_SA_LEN /* if struct sockaddr_storage exists */ #undef HAVE_SOCKADDR_STORAGE /* On solaris */ #undef HAVE_SOLARIS /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY /* Define to 1 if the system has the type `struct ether_addr'. */ #undef HAVE_STRUCT_ETHER_ADDR /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BUFMOD_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_DLPI_EXT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCCOM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* if if_packet.h has tpacket_stats defined */ #undef HAVE_TPACKET_STATS /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* define if version.h is generated in the build procedure */ #undef HAVE_VERSION_H /* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF /* define if your compiler has __attribute__ */ #undef HAVE___ATTRIBUTE__ /* IPv6 */ #undef INET6 /* if unaligned access fails */ #undef LBL_ALIGN /* Define to 1 if netinet/ether.h declares `ether_hostton' */ #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON /* Define to 1 if netinet/if_ether.h declares `ether_hostton' */ #undef NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /* do not use protochain */ #undef NO_PROTOCHAIN /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* /dev/dlpi directory */ #undef PCAP_DEV_PREFIX /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Enable parser debugging */ #undef YYDEBUG /* needed on HP-UX */ #undef _HPUX_SOURCE /* define on AIX to get certain functions */ #undef _SUN /* Define as token for inline if inlining supported */ #undef inline /* on sinix */ #undef sinix /* if we have u_int16_t */ #undef u_int16_t /* if we have u_int32_t */ #undef u_int32_t /* if we have u_int8_t */ #undef u_int8_t libpcap-0.9.7/./.cvsignore0000644000026300017500000000020407630037550013421 0ustar mcrmcrconfig.log config.cache config.status config.h .devel stamp-h stamp-h.in Makefile scanner.c grammar.c tokdefs.h version.c version.h libpcap-0.9.7/./CHANGES~0000644000026300017500000004124010633321703012610 0ustar mcrmcr@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.59.2.10 2007/04/23 21:22:17 ken Exp $ (LBL) Wed. April 25, 2007. ken@xelerance.com. Summary for 0.9.6 libpcap release Put the public libpcap headers into a pcap subdirectory in both the source directory and the target include directory, and have include files at the top-level directory to include those headers, for backwards compatibility. Add Bluetooth support Add USB capturing support on Linux Add support for the binary USB sniffing interface in Linux Add support for new FreeBSD BIOCSDIRECTION ioctl Add additional filter operations for 802.11 frame types Add support for filtering on MTP2 frame types Propagate some changes from the main branch, so the x.9 branch has all the DLT_ and LINKTYPE_ values that the main branch does Reserved a DLT_ and SAVEFILE_ value for PPI (Per Packet Info) encapsulated packets Add LINKTYPE_ for IEEE 802.15.4, with address fields padded as done by Linux drivers Add LINKTYPE_ value corresponding to DLT_IEEE802_16_MAC_CPS. Add DLT for IEEE 802.16 (WiMAX) MAC Common Part Sublayer Add DLT for Bluetooth HCI UART transport layer When building a shared library, build with "-fPIC" on Linux to support x86_64 Link with "$(CC) -shared" rather than "ld -shared" when building a ".so" shared library Add support for autoconf 2.60 Fixes to discard unread packets when changing filters Changes to handle name changes in the DAG library resulting from switching to libtool. Add support for new DAG ERF types. Add an explicit "-ldag" when building the shared library, so the DAG library dependency is explicit. Mac OSX fixes for dealing with "wlt" devices Fixes in add_or_find_if() & pcap_findalldevs() to optimize generating device lists Fixed a bug in pcap_open_live(). The return value of PacketSetHwFilter was not checked. Tue. September 19, 2006. ken@xelerance.com. Summary for 0.9.5 libpcap release Support for LAPD frames with vISDN Support for ERF on channelized T1/E1 cards via DAG API Fix capitalization that caused issues crossc compiling on Linux Better failure detection on PacketGetAdapterNames() Fixes for MPLS packet generation (link layer) OP_PACKET now matches the beginning of the packet, instead of beginning+link-layer Add DLT/LINKTYPE for carrying FRF.16 Multi-link Frame Relay Fix allocation of buffer for list of link-layer types Added a new DLT and LINKTYPE value for ARINC 653 Interpartition Communcation Messages Fixed a typo in a DLT value: it should start with DLT_ and not LINKTYPE_ Redefined DLT_CAN20B and LINKTYPE_CAN20B as #190 (as this is the right value for CAN). Added definition for DLT_A429 and LINKTYPE_A429 as #184. Added a new DLT and LINKTYPE value for CAN v2.0B frames. Add support for DLT_JUNIPER_VP. Don't double-count received packets on Linux systems that support the PACKET_STATISTICS getsockopt() argument on PF_PACKET sockets. Add support for DLT_IEEE802_11 and DLT_IEEE802_11_RADIO link layers in Windows Add support to build libpcap.lib and wpcap.dll under Cygnus and MingW32. Mon. September 5, 2005. ken@xelerance.com. Summary for 0.9.4 libpcap release Support for radiotap on Linux (Mike Kershaw) Fixes for HP-UX Support for additional Juniper link-layer types Fixes for filters on MPLS-encapsulated packets "vlan" filter fixed "pppoed" and "pppoes" filters added; the latter modifies later parts of the filter expression to look at the PPP headers and headers in the PPP payload Tue. July 5, 2005. ken@xelerance.com. Summary for 0.9.3 libpcap release Fixes for compiling on nearly every platform, including improved 64bit support MSDOS Support Add support for sending packets OpenBSD pf format support IrDA capture (Linux only) Tue. March 30, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.3 release Fixed minor problem in gencode.c that would appear on 64-bit platforms. Version number is now sane. Mon. March 29, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.2 release updates for autoconf 2.5 fixes for ppp interfaces for freebsd 4.1 pcap gencode can generate code for 802.11, IEEE1394, and pflog. Wed. November 12, 2003. mcr@sandelman.ottawa.on.ca. Summary for 0.8 release added pcap_findalldevs() Win32 patches from NetGroup, Politecnico di Torino (Italy) OpenBSD pf, DLT_PFLOG added Many changes to ATM support. lookup pcap_lookupnet() Added DLT_ARCNET_LINUX, DLT_ENC, DLT_IEEE802_11_RADIO, DLT_SUNATM, DLT_IP_OVER_FC, DLT_FRELAY, others. Sigh. More AIX wonderfulness. Document updates. Changes to API: pcap_next_ex(), pcap_breakloop(), pcap_dump_flush(), pcap_list_datalinks(), pcap_set_datalink(), pcap_lib_version(), pcap_datalink_val_to_name(), pcap_datalink_name_to_val(), new error returns. Tuesday, February 25, 2003. fenner@research.att.com. 0.7.2 release Support link types that use 802.2 always, never, and sometimes. Don't decrease the size of the BPF buffer from the default. Support frame relay. Handle 32-bit timestamps in DLPI, and pass the right buffer size. Handle Linux systems with modern kernel but without SOL_PACKET in the userland headers. Linux support for ARPHRD_RAWHDLC. Handle 32-bit timestamps in snoop. Support eg (Octane/O2xxx/O3xxx Gigabit) devices. Add new reserved DLT types. Monday October 23, 2001. mcr@sandelman.ottawa.on.ca. Summary for 0.7 release Added pcap_findalldevs() call to get list of interfaces in a MI way. pcap_stats() has been documented as to what its counters mean on each platform. Tuesday January 9, 2001. guy@alum.mit.edu. Summary for 0.6 release New Linux libpcap implementation, which, in 2.2 and later kernels, uses PF_PACKET sockets and supports kernel packet filtering (if compiled into the kernel), and supports the "any" device for capturing on all interfaces. Cleans up promiscuous mode better on pre-2.2 kernels, and has various other fixes (handles 2.4 ARPHRD_IEEE802_TR, handles ISDN devices better, doesn't show duplicate packets on loopback interface, etc.). Fixed HP-UX libpcap implementation to correctly get the PPA for an interface, to allow interfaces to be opened by interface name. libpcap savefiles have system-independent link-layer type values in the header, rather than sometimes platform-dependent DLT_ values, to make it easier to exchange capture files between different OSes. Non-standard capture files produced by some Linux tcpdumps, e.g. the one from Red Hat Linux 6.2 and later, can now be read. Updated autoconf stock files. Filter expressions can filter on VLAN IDs and various OSI protocols, and work on Token Ring (with non-source-routed packets). "pcap_open_dead()" added to allow compiling filter expressions to pcap code without opening a capture device or capture file. Header files fixed to allow use in C++ programs. Removed dependancy on native headers for packet layout. Removed Linux specific headers that were shipped. Security fixes: Strcpy replaced with strlcpy, sprintf replaced with snprintf. Fixed bug that could cause subsequent "pcap_compile()"s to fail erroneously after one compile failed. Assorted other bug fixes. README.aix and README.linux files added to describe platform-specific issues. "getifaddrs()" rather than SIOCGIFCONF used, if available. v0.5 Sat Jun 10 11:09:15 PDT 2000 itojun@iijlab.net - Brought in KAME IPv6/IPsec bpf compiler. - Fixes for NetBSD. - Support added for OpenBSD DLT_LOOP and BSD/OS DLT_C_HDLC (Cisco HDLC), and changes to work around different BSDs having different DLT_ types with the same numeric value. Assar Westerlund - Building outside the source code tree fixed. - Changed to write out time stamps with 32-bit seconds and microseconds fields, regardless of whether those fields are 32 bits or 64 bits in the OS's native "struct timeval". - Changed "pcap_lookupdev()" to dynamically grow the buffer into which the list of interfaces is read as necessary in order to hold the entire list. Greg Troxel - Added a new "pcap_compile_nopcap()", which lets you compile a filter expression into a BPF program without having an open live capture or capture file. v0.4 Sat Jul 25 12:40:09 PDT 1998 - Fix endian problem with DLT_NULL devices. From FreeBSD via Bill Fenner (fenner@parc.xerox.com) - Fix alignment problem with FDDI under DLPI. This was causing core dumps under Solaris. - Added configure options to disable flex and bison. Resulted from a bug report by barnett@grymoire.crd.ge.com (Bruce Barnett). Also added options to disable gcc and to force a particular packet capture type. - Added support for Fore ATM interfaces (qaa and fa) under IRIX. Thanks to John Hawkinson (jhawk@mit.edu) - Change Linux PPP and SLIP to use DLT_RAW since the kernel does not supply any "link layer" data. - Change Linux to use SIOCGIFHWADDR ioctl to determine link layer type. Thanks to Thomas Sailer (sailer@ife.ee.ethz.ch) - Change IRIX PPP to use DLT_RAW since the kernel does not supply any "link layer" data. - Modified to support the new BSD/OS 2.1 PPP and SLIP link layer header formats. - Added some new SGI snoop interface types. Thanks to Steve Alexander (sca@refugee.engr.sgi.com) - Fixes for HP-UX 10.20 (which is similar to HP-UX 9). Thanks to Richard Allen (ra@hp.is) and Steinar Haug (sthaug@nethelp.no) - Fddi supports broadcast as reported by Jeff Macdonald (jeff@iacnet.com). Also correct ieee802 and arcnet. - Determine Linux pcap buffer size at run time or else it might not be big enough for some interface types (e.g. FDDI). Thanks to Jes Sorensen (Jes.Sorensen@cern.ch) - Fix some linux alignment problems. - Document promisc argument to pcap_open_live(). Reported by Ian Marsh (ianm@sics.se) - Support Metricom radio packets under Linux. Thanks to Kevin Lai (laik@gunpowder.stanford.edu) - Bind to interface name under Linux to avoid packets from multiple interfaces on multi-homed hosts. Thanks to Kevin Lai (laik@gunpowder.stanford.edu) - Change L_SET to SEEK_SET for HP-UX. Thanks to Roland Roberts (rroberts@muller.com) - Fixed an uninitialized memory reference found by Kent Vander Velden (graphix@iastate.edu) - Fixed lex pattern for IDs to allow leading digits. As reported by Theo de Raadt (deraadt@cvs.openbsd.org) - Fixed Linux include file problems when using GNU libc. - Ifdef ARPHRD_FDDI since not all versions of the Linux kernel have it. Reported reported by Eric Jacksch (jacksch@tenebris.ca) - Fixed bug in pcap_dispatch() that kept it from returning on packet timeouts. - Changed ISLOOPBACK() macro when IFF_LOOPBACK isn't available to check for "lo" followed by an eos or digit (newer versions of Linux apparently call the loopback "lo" instead of "lo0"). - Fixed Linux networking include files to use ints instead of longs to avoid problems with 64 bit longs on the alpha. Thanks to Cristian Gafton (gafton@redhat.com) v0.3 Sat Nov 30 20:56:27 PST 1996 - Added Linux support. - Fixed savefile bugs. - Solaris x86 fix from Tim Rylance (t.rylance@elsevier.nl) - Add support for bpf kernel port filters. - Remove duplicate atalk protocol table entry. Thanks to Christian Hopps (chopps@water.emich.edu) - Fixed pcap_lookupdev() to ignore nonexistent devices. This was reported to happen under BSD/OS by David Vincenzetti (vince@cryptonet.it) - Avoid solaris compiler warnings. Thanks to Bruce Barnett (barnett@grymoire.crd.ge.com) v0.2.1 Sun Jul 14 03:02:26 PDT 1996 - Fixes for HP-UX 10. Thanks in part to to Thomas Wolfram (wolf@prz.tu-berlin.de) and Rick Jones (raj@hpisrdq.cup.hp.com) - Added support for SINIX. Thanks to Andrej Borsenkow (borsenkow.msk@sni.de) - Fixes for AIX (although this system is not yet supported). Thanks to John Hawkinson (jhawk@mit.edu) - Use autoconf's idea of the top level directory in install targets. Thanks to John Hawkinson. - Add missing autoconf packet capture result message. Thanks to Bill Fenner (fenner@parc.xerox.com) - Fixed padding problems in the pf module. - Fixed some more alignment problems on the alpha. - Added explicit netmask support. Thanks to Steve Nuchia (steve@research.oknet.com) - Fixed to handle raw ip addresses such as 0.0.0.1 without "left justifing" - Add "sca" keyword (for DEC cluster services) as suggested by Terry Kennedy (terry@spcvxa.spc.edu) - Add "atalk" keyword as suggested by John Hawkinson. - Add "igrp" keyword. - Fixed HID definition in grammar.y to be a string, not a value. - Use $CC when checking gcc version. Thanks to Carl Lindberg (carl_lindberg@blacksmith.com) - Removed obsolete reference to pcap_immediate() from the man page. Michael Stolarchuk (mts@terminator.rs.itd.umich.edu) - DLT_NULL has a 4 byte family header. Thanks to Jeffrey Honig (jch@bsdi.com) v0.2 Sun Jun 23 02:28:42 PDT 1996 - Add support for HP-UX. Resulted from code contributed by Tom Murray (tmurray@hpindck.cup.hp.com) and Philippe-Andri Prindeville (philipp@res.enst.fr) - Update INSTALL with a reminder to install include files. Thanks to Mark Andrews (mandrews@aw.sgi.com) - Fix bpf compiler alignment bug on the alpha. - Use autoconf to detect architectures that can't handle misaligned accesses. - Added loopback support for snoop. Resulted from report Steve Alexander (sca@engr.sgi.com) v0.1 Fri Apr 28 18:11:03 PDT 1995 - Fixed compiler and optimizer bugs. The BPF filter engine uses unsigned comparison operators, while the code generator and optimizer assumed signed semantics in several places. Thanks to Charlie Slater (cslater@imatek.com) for pointing this out. - Removed FDDI ifdef's, they aren't really needed. Resulted from report by Gary Veum (veum@boa.gsfc.nasa.gov). - Add pcap-null.c which allows offline use of libpcap on systems that don't support live package capture. This feature resulting from a request from Jan van Oorschot (j.p.m.voorschot@et.tudelft.nl). - Make bpf_compile() reentrant. Fix thanks to Pascal Hennequin (Pascal.Hennequin@hugo.int-evry.fr). - Port to GNU autoconf. - Fix pcap-dlpi.c to work with isdn. Resulted from report by Flemming Johansen (fsj@csd.cri.dk). - Handle multi-digit interface unit numbers (aka ppa's) under dlpi. Resulted from report by Daniel Ehrlich (ehrlich@cse.psu.edu). - Fix pcap-dlpi.c to work in non-promiscuous mode. Resulted from report by Jeff Murphy (jcmurphy@acsu.buffalo.edu). - Add support for "long jumps". Thanks to Jeffrey Mogul (mogul@pa.dec.com). - Fix minor problems when compiling with BDEBUG as noticed by Scott Bertilson (scott@unet.umn.edu). - Declare sys_errlist "const char *const" to avoid problems under FreeBSD. Resulted from report by jher@eden.com. v0.0.6 Fri Apr 28 04:07:13 PDT 1995 - Add missing variable declaration missing from 0.0.6 v0.0.5 Fri Apr 28 00:22:21 PDT 1995 - Workaround for problems when pcap_read() returns 0 due to the timeout expiring. v0.0.4 Thu Apr 20 20:41:48 PDT 1995 - Change configuration to not use gcc v2 flags with gcc v1. - Fixed a bug in pcap_next(); if pcap_dispatch() returns 0, pcap_next() should also return 0. Thanks to Richard Stevens (rstevens@noao.edu). - Fixed configure to test for snoop before dlpi to avoid problems under IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com). - Hack around deficiency in Ultrix's make. - Fix two bugs related to the Solaris pre-5.3.2 bufmod bug; handle savefiles that have more than snapshot bytes of data in them (so we can read old savefiles) and avoid writing such files. - Added checkioctl which is used with gcc to check that the "fixincludes" script has been run. v0.0.3 Tue Oct 18 18:13:46 PDT 1994 - Fixed configure to test for snoop before dlpi to avoid problems under IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com). v0.0.2 Wed Oct 12 20:56:37 PDT 1994 - Implement timeout in the dlpi pcap_open_live(). Thanks to Richard Stevens. - Determine pcap link type from dlpi media type. Resulted from report by Mahesh Jethanandani (mahesh@npix.com). v0.0.1 Fri Jun 24 14:50:57 PDT 1994 - Fixed bug in nit_setflags() in pcap-snit.c. The streams ioctl timeout wasn't being initialized sometimes resulting in an "NIOCSFLAGS: Invalid argument" error under OSF/1. Reported by Matt Day (mday@artisoft.com) and Danny Mitzel (dmitzel@whitney.hitc.com). - Turn on FDDI support by default. v0.0 Mon Jun 20 19:20:16 PDT 1994 - Initial release. - Fixed bug with greater/less keywords, reported by Mark Andrews (mandrews@alias.com). - Fix bug where '|' was defined as BPF_AND instead of BPF_OR, reported by Elan Amir (elan@leeb.cs.berkeley.edu). - Machines with little-endian byte ordering are supported thanks to Jeff Mogul. - Add hack for version 2.3 savefiles which don't have caplen and len swapped thanks to Vern Paxson. - Added "&&" and "||" aliases for "and" and "or" thanks to Vern Paxson. - Added length, inbound and outbound keywords. libpcap-0.9.7/./bpf_image.c0000644000026300017500000001156010633321703013476 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.26.2.1 2007/06/11 09:52:04 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif char * bpf_image(p, n) struct bpf_insn *p; int n; { int v; const 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)snprintf(operand, sizeof operand, fmt, v); (void)snprintf(image, sizeof 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; } libpcap-0.9.7/./gencode.h0000644000026300017500000002270210633321703013176 0ustar mcrmcr/* * 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: /tcpdump/master/libpcap/gencode.h,v 1.60.2.11 2007/06/11 09:52:04 guy Exp $ (LBL) */ /* * ATM support: * * Copyright (c) 1997 Yen Yen Lim and North Dakota State University * 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 Yen Yen Lim and * North Dakota State University * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 HAVE___ATTRIBUTE__ #define __attribute__(x) #endif /* HAVE___ATTRIBUTE__ */ /* Address qualifiers. */ #define Q_HOST 1 #define Q_NET 2 #define Q_PORT 3 #define Q_GATEWAY 4 #define Q_PROTO 5 #define Q_PROTOCHAIN 6 #define Q_PORTRANGE 7 /* Protocol qualifiers. */ #define Q_LINK 1 #define Q_IP 2 #define Q_ARP 3 #define Q_RARP 4 #define Q_SCTP 5 #define Q_TCP 6 #define Q_UDP 7 #define Q_ICMP 8 #define Q_IGMP 9 #define Q_IGRP 10 #define Q_ATALK 11 #define Q_DECNET 12 #define Q_LAT 13 #define Q_SCA 14 #define Q_MOPRC 15 #define Q_MOPDL 16 #define Q_IPV6 17 #define Q_ICMPV6 18 #define Q_AH 19 #define Q_ESP 20 #define Q_PIM 21 #define Q_VRRP 22 #define Q_AARP 23 #define Q_ISO 24 #define Q_ESIS 25 #define Q_ISIS 26 #define Q_CLNP 27 #define Q_STP 28 #define Q_IPX 29 #define Q_NETBEUI 30 /* IS-IS Levels */ #define Q_ISIS_L1 31 #define Q_ISIS_L2 32 /* PDU types */ #define Q_ISIS_IIH 33 #define Q_ISIS_LAN_IIH 34 #define Q_ISIS_PTP_IIH 35 #define Q_ISIS_SNP 36 #define Q_ISIS_CSNP 37 #define Q_ISIS_PSNP 38 #define Q_ISIS_LSP 39 #define Q_RADIO 40 /* 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 /* ATM types */ #define A_METAC 22 /* Meta signalling Circuit */ #define A_BCC 23 /* Broadcast Circuit */ #define A_OAMF4SC 24 /* Segment OAM F4 Circuit */ #define A_OAMF4EC 25 /* End-to-End OAM F4 Circuit */ #define A_SC 26 /* Signalling Circuit*/ #define A_ILMIC 27 /* ILMI Circuit */ #define A_OAM 28 /* OAM cells : F4 only */ #define A_OAMF4 29 /* OAM F4 cells: Segment + End-to-end */ #define A_LANE 30 /* LANE traffic */ #define A_LLC 31 /* LLC-encapsulated traffic */ /* Based on Q.2931 signalling protocol */ #define A_SETUP 41 /* Setup message */ #define A_CALLPROCEED 42 /* Call proceeding message */ #define A_CONNECT 43 /* Connect message */ #define A_CONNECTACK 44 /* Connect Ack message */ #define A_RELEASE 45 /* Release message */ #define A_RELEASE_DONE 46 /* Release message */ /* ATM field types */ #define A_VPI 51 #define A_VCI 52 #define A_PROTOTYPE 53 #define A_MSGTYPE 54 #define A_CALLREFTYPE 55 #define A_CONNECTMSG 70 /* returns Q.2931 signalling messages for establishing and destroying switched virtual connection */ #define A_METACONNECT 71 /* returns Q.2931 signalling messages for establishing and destroying predefined virtual circuits, such as broadcast circuit, oamf4 segment circuit, oamf4 end-to-end circuits, ILMI circuits or connection signalling circuit. */ /* MTP2 types */ #define M_FISU 22 /* FISU */ #define M_LSSU 23 /* LSSU */ #define M_MSU 24 /* MSU */ /* MTP3 field types */ #define M_SIO 1 #define M_OPC 2 #define M_DPC 3 #define M_SLS 4 struct slist; struct stmt { int code; struct slist *jt; /*only for relative jump in block*/ struct slist *jf; /*only for relative jump in block*/ 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_acode(const u_char *, struct qual); struct block *gen_mcode(const char *, const char *, int, struct qual); #ifdef INET6 struct block *gen_mcode6(const char *, const char *, int, struct qual); #endif 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); struct block *gen_vlan(int); struct block *gen_mpls(int); struct block *gen_pppoed(void); struct block *gen_pppoes(void); struct block *gen_atmfield_code(int atmfield, bpf_int32 jvalue, bpf_u_int32 jtype, int reverse); struct block *gen_atmtype_abbrev(int type); struct block *gen_atmmulti_abbrev(int type); struct block *gen_mtp2type_abbrev(int type); struct block *gen_mtp3field_code(int mtp3field, bpf_u_int32 jvalue, bpf_u_int32 jtype, int reverse); struct block *gen_pf_ifname(const char *); struct block *gen_pf_rnr(int); struct block *gen_pf_srnr(int); struct block *gen_pf_ruleset(char *); struct block *gen_pf_reason(int); struct block *gen_pf_action(int); struct block *gen_pf_dir(int); void bpf_optimize(struct block **); void bpf_error(const char *, ...) __attribute__((noreturn, format (printf, 1, 2))); 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(const char *); void lex_cleanup(void); void sappend(struct slist *, struct slist *); /* XXX */ #define JT(b) ((b)->et.succ) #define JF(b) ((b)->ef.succ) extern int no_optimize; libpcap-0.9.7/./grammar.y0000644000026300017500000003116610633321703013245 0ustar mcrmcr%{ /* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.86.2.8 2007/06/11 09:52:04 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #include #include #endif /* WIN32 */ #include #ifndef WIN32 #if __STDC__ struct mbuf; struct rtentry; #endif #include #endif /* WIN32 */ #include #include "pcap-int.h" #include "gencode.h" #include "pf.h" #include #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(const char *msg) { ++n_errors; bpf_error("%s", msg); /* NOTREACHED */ } #ifndef YYBISON int yyparse(void); int 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; int atmfieldtype; int mtp3fieldtype; struct block *b; } blk; struct block *rblk; } %type expr id nid pid term rterm qid %type head %type pqual dqual aqual ndaqual %type arth narth %type byteop pname pnum relop irelop %type and or paren not null prog %type other pfvar %type atmtype atmmultitype %type atmfield %type atmfieldvalue atmvalue atmlistvalue %type mtp2type %type mtp3field %type mtp3fieldvalue mtp3value mtp3listvalue %token DST SRC HOST GATEWAY %token NET NETMASK PORT PORTRANGE LESS GREATER PROTO PROTOCHAIN CBYTE %token ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP %token ATALK AARP DECNET LAT SCA MOPRC MOPDL %token TK_BROADCAST TK_MULTICAST %token NUM INBOUND OUTBOUND %token PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION %token LINK %token GEQ LEQ NEQ %token ID EID HID HID6 AID %token LSH RSH %token LEN %token IPV6 ICMPV6 AH ESP %token VLAN MPLS %token PPPOED PPPOES %token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP %token STP %token IPX %token NETBEUI %token LANE LLC METAC BCC SC ILMIC OAMF4EC OAMF4SC %token OAM OAMF4 CONNECTMSG METACONNECT %token VPI VCI %token RADIO %token FISU LSSU MSU %token SIO OPC DPC SLS %type ID %type EID %type AID %type HID HID6 %type NUM action reason %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 { $$ = $0; } ; or: OR { $$ = $0; } ; id: nid | pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1, $$.q = $0.q); } | paren pid ')' { $$ = $2; } ; nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } | HID '/' NUM { $$.b = gen_mcode($1, NULL, $3, $$.q = $0.q); } | HID NETMASK HID { $$.b = gen_mcode($1, $3, 0, $$.q = $0.q); } | HID { /* Decide how to parse HID based on proto */ $$.q = $0.q; $$.b = gen_ncode($1, 0, $$.q); } | HID6 '/' NUM { #ifdef INET6 $$.b = gen_mcode6($1, NULL, $3, $$.q = $0.q); #else bpf_error("'ip6addr/prefixlen' not supported " "in this configuration"); #endif /*INET6*/ } | HID6 { #ifdef INET6 $$.b = gen_mcode6($1, 0, 128, $$.q = $0.q); #else bpf_error("'ip6addr' not supported " "in this configuration"); #endif /*INET6*/ } | EID { $$.b = gen_ecode($1, $$.q = $0.q); /* * $1 was allocated by "pcap_ether_aton()", * so we must free it now that we're done * with it. */ free($1); } | AID { $$.b = gen_acode($1, $$.q = $0.q); /* * $1 was allocated by "pcap_ether_aton()", * so we must free it now that we're done * with it. */ free($1); } | not id { gen_not($2.b); $$ = $2; } ; not: '!' { $$ = $0; } ; paren: '(' { $$ = $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 = $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 PROTOCHAIN { QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); } | 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; } | atmtype { $$.b = gen_atmtype_abbrev($1); $$.q = qerr; } | atmmultitype { $$.b = gen_atmmulti_abbrev($1); $$.q = qerr; } | atmfield atmvalue { $$.b = $2.b; $$.q = qerr; } | mtp2type { $$.b = gen_mtp2type_abbrev($1); $$.q = qerr; } | mtp3field mtp3value { $$.b = $2.b; $$.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; } | PORTRANGE { $$ = Q_PORTRANGE; } ; /* non-directional address type qualifiers */ ndaqual: GATEWAY { $$ = Q_GATEWAY; } ; pname: LINK { $$ = Q_LINK; } | IP { $$ = Q_IP; } | ARP { $$ = Q_ARP; } | RARP { $$ = Q_RARP; } | SCTP { $$ = Q_SCTP; } | TCP { $$ = Q_TCP; } | UDP { $$ = Q_UDP; } | ICMP { $$ = Q_ICMP; } | IGMP { $$ = Q_IGMP; } | IGRP { $$ = Q_IGRP; } | PIM { $$ = Q_PIM; } | VRRP { $$ = Q_VRRP; } | ATALK { $$ = Q_ATALK; } | AARP { $$ = Q_AARP; } | DECNET { $$ = Q_DECNET; } | LAT { $$ = Q_LAT; } | SCA { $$ = Q_SCA; } | MOPDL { $$ = Q_MOPDL; } | MOPRC { $$ = Q_MOPRC; } | IPV6 { $$ = Q_IPV6; } | ICMPV6 { $$ = Q_ICMPV6; } | AH { $$ = Q_AH; } | ESP { $$ = Q_ESP; } | ISO { $$ = Q_ISO; } | ESIS { $$ = Q_ESIS; } | ISIS { $$ = Q_ISIS; } | L1 { $$ = Q_ISIS_L1; } | L2 { $$ = Q_ISIS_L2; } | IIH { $$ = Q_ISIS_IIH; } | LSP { $$ = Q_ISIS_LSP; } | SNP { $$ = Q_ISIS_SNP; } | PSNP { $$ = Q_ISIS_PSNP; } | CSNP { $$ = Q_ISIS_CSNP; } | CLNP { $$ = Q_CLNP; } | STP { $$ = Q_STP; } | IPX { $$ = Q_IPX; } | NETBEUI { $$ = Q_NETBEUI; } | RADIO { $$ = Q_RADIO; } ; other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | pqual TK_MULTICAST { $$ = gen_multicast($1); } | LESS NUM { $$ = gen_less($2); } | GREATER NUM { $$ = gen_greater($2); } | CBYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); } | INBOUND { $$ = gen_inbound(0); } | OUTBOUND { $$ = gen_inbound(1); } | VLAN pnum { $$ = gen_vlan($2); } | VLAN { $$ = gen_vlan(-1); } | MPLS pnum { $$ = gen_mpls($2); } | MPLS { $$ = gen_mpls(-1); } | PPPOED { $$ = gen_pppoed(); } | PPPOES { $$ = gen_pppoes(); } | pfvar { $$ = $1; } ; pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); } | PF_RSET ID { $$ = gen_pf_ruleset($2); } | PF_RNR NUM { $$ = gen_pf_rnr($2); } | PF_SRNR NUM { $$ = gen_pf_srnr($2); } | PF_REASON reason { $$ = gen_pf_reason($2); } | PF_ACTION action { $$ = gen_pf_action($2); } ; reason: NUM { $$ = $1; } | ID { const char *reasons[] = PFRES_NAMES; int i; for (i = 0; reasons[i]; i++) { if (pcap_strcasecmp($1, reasons[i]) == 0) { $$ = i; break; } } if (reasons[i] == NULL) bpf_error("unknown PF reason"); } ; action: ID { if (pcap_strcasecmp($1, "pass") == 0 || pcap_strcasecmp($1, "accept") == 0) $$ = PF_PASS; else if (pcap_strcasecmp($1, "drop") == 0 || pcap_strcasecmp($1, "block") == 0) $$ = PF_DROP; else bpf_error("unknown PF action"); } ; 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; } ; atmtype: LANE { $$ = A_LANE; } | LLC { $$ = A_LLC; } | METAC { $$ = A_METAC; } | BCC { $$ = A_BCC; } | OAMF4EC { $$ = A_OAMF4EC; } | OAMF4SC { $$ = A_OAMF4SC; } | SC { $$ = A_SC; } | ILMIC { $$ = A_ILMIC; } ; atmmultitype: OAM { $$ = A_OAM; } | OAMF4 { $$ = A_OAMF4; } | CONNECTMSG { $$ = A_CONNECTMSG; } | METACONNECT { $$ = A_METACONNECT; } ; /* ATM field types quantifier */ atmfield: VPI { $$.atmfieldtype = A_VPI; } | VCI { $$.atmfieldtype = A_VCI; } ; atmvalue: atmfieldvalue | relop NUM { $$.b = gen_atmfield_code($0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0); } | irelop NUM { $$.b = gen_atmfield_code($0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1); } | paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; } ; atmfieldvalue: NUM { $$.atmfieldtype = $0.atmfieldtype; if ($$.atmfieldtype == A_VPI || $$.atmfieldtype == A_VCI) $$.b = gen_atmfield_code($$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0); } ; atmlistvalue: atmfieldvalue | atmlistvalue or atmfieldvalue { gen_or($1.b, $3.b); $$ = $3; } ; /* MTP2 types quantifier */ mtp2type: FISU { $$ = M_FISU; } | LSSU { $$ = M_LSSU; } | MSU { $$ = M_MSU; } ; /* MTP3 field types quantifier */ mtp3field: SIO { $$.mtp3fieldtype = M_SIO; } | OPC { $$.mtp3fieldtype = M_OPC; } | DPC { $$.mtp3fieldtype = M_DPC; } | SLS { $$.mtp3fieldtype = M_SLS; } ; mtp3value: mtp3fieldvalue | relop NUM { $$.b = gen_mtp3field_code($0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); } | irelop NUM { $$.b = gen_mtp3field_code($0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1); } | paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; } ; mtp3fieldvalue: NUM { $$.mtp3fieldtype = $0.mtp3fieldtype; if ($$.mtp3fieldtype == M_SIO || $$.mtp3fieldtype == M_OPC || $$.mtp3fieldtype == M_DPC || $$.mtp3fieldtype == M_SLS ) $$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0); } ; mtp3listvalue: mtp3fieldvalue | mtp3listvalue or mtp3fieldvalue { gen_or($1.b, $3.b); $$ = $3; } ; %% libpcap-0.9.7/./.#CHANGES.1.590000644000026300017500000003222710245661351013140 0ustar mcrmcr@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.59 2004/03/30 14:42:50 mcr Exp $ (LBL) Tue. May 27, 2005. mcr@sandelman.ottawa.on.ca. Summary for 0.9.1 release Numerous fixes for Tue. March 30, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.3 release Fixed minor problem in gencode.c that would appear on 64-bit platforms. Version number is now sane. Mon. March 29, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.2 release updates for autoconf 2.5 fixes for ppp interfaces for freebsd 4.1 pcap gencode can generate code for 802.11, IEEE1394, and pflog. Wed. November 12, 2003. mcr@sandelman.ottawa.on.ca. Summary for 0.8 release added pcap_findalldevs() Win32 patches from NetGroup, Politecnico di Torino (Italy) OpenBSD pf, DLT_PFLOG added Many changes to ATM support. lookup pcap_lookupnet() Added DLT_ARCNET_LINUX, DLT_ENC, DLT_IEEE802_11_RADIO, DLT_SUNATM, DLT_IP_OVER_FC, DLT_FRELAY, others. Sigh. More AIX wonderfulness. Document updates. Changes to API: pcap_next_ex(), pcap_breakloop(), pcap_dump_flush(), pcap_list_datalinks(), pcap_set_datalink(), pcap_lib_version(), pcap_datalink_val_to_name(), pcap_datalink_name_to_val(), new error returns. Tuesday, February 25, 2003. fenner@research.att.com. 0.7.2 release Support link types that use 802.2 always, never, and sometimes. Don't decrease the size of the BPF buffer from the default. Support frame relay. Handle 32-bit timestamps in DLPI, and pass the right buffer size. Handle Linux systems with modern kernel but without SOL_PACKET in the userland headers. Linux support for ARPHRD_RAWHDLC. Handle 32-bit timestamps in snoop. Support eg (Octane/O2xxx/O3xxx Gigabit) devices. Add new reserved DLT types. Monday October 23, 2001. mcr@sandelman.ottawa.on.ca. Summary for 0.7 release Added pcap_findalldevs() call to get list of interfaces in a MI way. pcap_stats() has been documented as to what its counters mean on each platform. Tuesday January 9, 2001. guy@alum.mit.edu. Summary for 0.6 release New Linux libpcap implementation, which, in 2.2 and later kernels, uses PF_PACKET sockets and supports kernel packet filtering (if compiled into the kernel), and supports the "any" device for capturing on all interfaces. Cleans up promiscuous mode better on pre-2.2 kernels, and has various other fixes (handles 2.4 ARPHRD_IEEE802_TR, handles ISDN devices better, doesn't show duplicate packets on loopback interface, etc.). Fixed HP-UX libpcap implementation to correctly get the PPA for an interface, to allow interfaces to be opened by interface name. libpcap savefiles have system-independent link-layer type values in the header, rather than sometimes platform-dependent DLT_ values, to make it easier to exchange capture files between different OSes. Non-standard capture files produced by some Linux tcpdumps, e.g. the one from Red Hat Linux 6.2 and later, can now be read. Updated autoconf stock files. Filter expressions can filter on VLAN IDs and various OSI protocols, and work on Token Ring (with non-source-routed packets). "pcap_open_dead()" added to allow compiling filter expressions to pcap code without opening a capture device or capture file. Header files fixed to allow use in C++ programs. Removed dependancy on native headers for packet layout. Removed Linux specific headers that were shipped. Security fixes: Strcpy replaced with strlcpy, sprintf replaced with snprintf. Fixed bug that could cause subsequent "pcap_compile()"s to fail erroneously after one compile failed. Assorted other bug fixes. README.aix and README.linux files added to describe platform-specific issues. "getifaddrs()" rather than SIOCGIFCONF used, if available. v0.5 Sat Jun 10 11:09:15 PDT 2000 itojun@iijlab.net - Brought in KAME IPv6/IPsec bpf compiler. - Fixes for NetBSD. - Support added for OpenBSD DLT_LOOP and BSD/OS DLT_C_HDLC (Cisco HDLC), and changes to work around different BSDs having different DLT_ types with the same numeric value. Assar Westerlund - Building outside the source code tree fixed. - Changed to write out time stamps with 32-bit seconds and microseconds fields, regardless of whether those fields are 32 bits or 64 bits in the OS's native "struct timeval". - Changed "pcap_lookupdev()" to dynamically grow the buffer into which the list of interfaces is read as necessary in order to hold the entire list. Greg Troxel - Added a new "pcap_compile_nopcap()", which lets you compile a filter expression into a BPF program without having an open live capture or capture file. v0.4 Sat Jul 25 12:40:09 PDT 1998 - Fix endian problem with DLT_NULL devices. From FreeBSD via Bill Fenner (fenner@parc.xerox.com) - Fix alignment problem with FDDI under DLPI. This was causing core dumps under Solaris. - Added configure options to disable flex and bison. Resulted from a bug report by barnett@grymoire.crd.ge.com (Bruce Barnett). Also added options to disable gcc and to force a particular packet capture type. - Added support for Fore ATM interfaces (qaa and fa) under IRIX. Thanks to John Hawkinson (jhawk@mit.edu) - Change Linux PPP and SLIP to use DLT_RAW since the kernel does not supply any "link layer" data. - Change Linux to use SIOCGIFHWADDR ioctl to determine link layer type. Thanks to Thomas Sailer (sailer@ife.ee.ethz.ch) - Change IRIX PPP to use DLT_RAW since the kernel does not supply any "link layer" data. - Modified to support the new BSD/OS 2.1 PPP and SLIP link layer header formats. - Added some new SGI snoop interface types. Thanks to Steve Alexander (sca@refugee.engr.sgi.com) - Fixes for HP-UX 10.20 (which is similar to HP-UX 9). Thanks to Richard Allen (ra@hp.is) and Steinar Haug (sthaug@nethelp.no) - Fddi supports broadcast as reported by Jeff Macdonald (jeff@iacnet.com). Also correct ieee802 and arcnet. - Determine Linux pcap buffer size at run time or else it might not be big enough for some interface types (e.g. FDDI). Thanks to Jes Sorensen (Jes.Sorensen@cern.ch) - Fix some linux alignment problems. - Document promisc argument to pcap_open_live(). Reported by Ian Marsh (ianm@sics.se) - Support Metricom radio packets under Linux. Thanks to Kevin Lai (laik@gunpowder.stanford.edu) - Bind to interface name under Linux to avoid packets from multiple interfaces on multi-homed hosts. Thanks to Kevin Lai (laik@gunpowder.stanford.edu) - Change L_SET to SEEK_SET for HP-UX. Thanks to Roland Roberts (rroberts@muller.com) - Fixed an uninitialized memory reference found by Kent Vander Velden (graphix@iastate.edu) - Fixed lex pattern for IDs to allow leading digits. As reported by Theo de Raadt (deraadt@cvs.openbsd.org) - Fixed Linux include file problems when using GNU libc. - Ifdef ARPHRD_FDDI since not all versions of the Linux kernel have it. Reported reported by Eric Jacksch (jacksch@tenebris.ca) - Fixed bug in pcap_dispatch() that kept it from returning on packet timeouts. - Changed ISLOOPBACK() macro when IFF_LOOPBACK isn't available to check for "lo" followed by an eos or digit (newer versions of Linux apparently call the loopback "lo" instead of "lo0"). - Fixed Linux networking include files to use ints instead of longs to avoid problems with 64 bit longs on the alpha. Thanks to Cristian Gafton (gafton@redhat.com) v0.3 Sat Nov 30 20:56:27 PST 1996 - Added Linux support. - Fixed savefile bugs. - Solaris x86 fix from Tim Rylance (t.rylance@elsevier.nl) - Add support for bpf kernel port filters. - Remove duplicate atalk protocol table entry. Thanks to Christian Hopps (chopps@water.emich.edu) - Fixed pcap_lookupdev() to ignore nonexistent devices. This was reported to happen under BSD/OS by David Vincenzetti (vince@cryptonet.it) - Avoid solaris compiler warnings. Thanks to Bruce Barnett (barnett@grymoire.crd.ge.com) v0.2.1 Sun Jul 14 03:02:26 PDT 1996 - Fixes for HP-UX 10. Thanks in part to to Thomas Wolfram (wolf@prz.tu-berlin.de) and Rick Jones (raj@hpisrdq.cup.hp.com) - Added support for SINIX. Thanks to Andrej Borsenkow (borsenkow.msk@sni.de) - Fixes for AIX (although this system is not yet supported). Thanks to John Hawkinson (jhawk@mit.edu) - Use autoconf's idea of the top level directory in install targets. Thanks to John Hawkinson. - Add missing autoconf packet capture result message. Thanks to Bill Fenner (fenner@parc.xerox.com) - Fixed padding problems in the pf module. - Fixed some more alignment problems on the alpha. - Added explicit netmask support. Thanks to Steve Nuchia (steve@research.oknet.com) - Fixed to handle raw ip addresses such as 0.0.0.1 without "left justifing" - Add "sca" keyword (for DEC cluster services) as suggested by Terry Kennedy (terry@spcvxa.spc.edu) - Add "atalk" keyword as suggested by John Hawkinson. - Add "igrp" keyword. - Fixed HID definition in grammar.y to be a string, not a value. - Use $CC when checking gcc version. Thanks to Carl Lindberg (carl_lindberg@blacksmith.com) - Removed obsolete reference to pcap_immediate() from the man page. Michael Stolarchuk (mts@terminator.rs.itd.umich.edu) - DLT_NULL has a 4 byte family header. Thanks to Jeffrey Honig (jch@bsdi.com) v0.2 Sun Jun 23 02:28:42 PDT 1996 - Add support for HP-UX. Resulted from code contributed by Tom Murray (tmurray@hpindck.cup.hp.com) and Philippe-Andri Prindeville (philipp@res.enst.fr) - Update INSTALL with a reminder to install include files. Thanks to Mark Andrews (mandrews@aw.sgi.com) - Fix bpf compiler alignment bug on the alpha. - Use autoconf to detect architectures that can't handle misaligned accesses. - Added loopback support for snoop. Resulted from report Steve Alexander (sca@engr.sgi.com) v0.1 Fri Apr 28 18:11:03 PDT 1995 - Fixed compiler and optimizer bugs. The BPF filter engine uses unsigned comparison operators, while the code generator and optimizer assumed signed semantics in several places. Thanks to Charlie Slater (cslater@imatek.com) for pointing this out. - Removed FDDI ifdef's, they aren't really needed. Resulted from report by Gary Veum (veum@boa.gsfc.nasa.gov). - Add pcap-null.c which allows offline use of libpcap on systems that don't support live package capture. This feature resulting from a request from Jan van Oorschot (j.p.m.voorschot@et.tudelft.nl). - Make bpf_compile() reentrant. Fix thanks to Pascal Hennequin (Pascal.Hennequin@hugo.int-evry.fr). - Port to GNU autoconf. - Fix pcap-dlpi.c to work with isdn. Resulted from report by Flemming Johansen (fsj@csd.cri.dk). - Handle multi-digit interface unit numbers (aka ppa's) under dlpi. Resulted from report by Daniel Ehrlich (ehrlich@cse.psu.edu). - Fix pcap-dlpi.c to work in non-promiscuous mode. Resulted from report by Jeff Murphy (jcmurphy@acsu.buffalo.edu). - Add support for "long jumps". Thanks to Jeffrey Mogul (mogul@pa.dec.com). - Fix minor problems when compiling with BDEBUG as noticed by Scott Bertilson (scott@unet.umn.edu). - Declare sys_errlist "const char *const" to avoid problems under FreeBSD. Resulted from report by jher@eden.com. v0.0.6 Fri Apr 28 04:07:13 PDT 1995 - Add missing variable declaration missing from 0.0.6 v0.0.5 Fri Apr 28 00:22:21 PDT 1995 - Workaround for problems when pcap_read() returns 0 due to the timeout expiring. v0.0.4 Thu Apr 20 20:41:48 PDT 1995 - Change configuration to not use gcc v2 flags with gcc v1. - Fixed a bug in pcap_next(); if pcap_dispatch() returns 0, pcap_next() should also return 0. Thanks to Richard Stevens (rstevens@noao.edu). - Fixed configure to test for snoop before dlpi to avoid problems under IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com). - Hack around deficiency in Ultrix's make. - Fix two bugs related to the Solaris pre-5.3.2 bufmod bug; handle savefiles that have more than snapshot bytes of data in them (so we can read old savefiles) and avoid writing such files. - Added checkioctl which is used with gcc to check that the "fixincludes" script has been run. v0.0.3 Tue Oct 18 18:13:46 PDT 1994 - Fixed configure to test for snoop before dlpi to avoid problems under IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com). v0.0.2 Wed Oct 12 20:56:37 PDT 1994 - Implement timeout in the dlpi pcap_open_live(). Thanks to Richard Stevens. - Determine pcap link type from dlpi media type. Resulted from report by Mahesh Jethanandani (mahesh@npix.com). v0.0.1 Fri Jun 24 14:50:57 PDT 1994 - Fixed bug in nit_setflags() in pcap-snit.c. The streams ioctl timeout wasn't being initialized sometimes resulting in an "NIOCSFLAGS: Invalid argument" error under OSF/1. Reported by Matt Day (mday@artisoft.com) and Danny Mitzel (dmitzel@whitney.hitc.com). - Turn on FDDI support by default. v0.0 Mon Jun 20 19:20:16 PDT 1994 - Initial release. - Fixed bug with greater/less keywords, reported by Mark Andrews (mandrews@alias.com). - Fix bug where '|' was defined as BPF_AND instead of BPF_OR, reported by Elan Amir (elan@leeb.cs.berkeley.edu). - Machines with little-endian byte ordering are supported thanks to Jeff Mogul. - Add hack for version 2.3 savefiles which don't have caplen and len swapped thanks to Vern Paxson. - Added "&&" and "||" aliases for "and" and "or" thanks to Vern Paxson. - Added length, inbound and outbound keywords. libpcap-0.9.7/./config.sub0000755000026300017500000007413407756336233013432 0ustar mcrmcr#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. timestamp='2003-11-03' # 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. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # 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. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; 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 nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) 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 | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb 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/'` ;; -udk*) 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 ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; 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. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # 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*86 | x86_64) 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. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | msp430-* \ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; 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 | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; 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 ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-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 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; 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 ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; 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 ;; necv70) basic_machine=v70-nec os=-sysv ;; 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 ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nv1) basic_machine=nv1-cray os=-unicosmp ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; 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 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-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/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; 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=-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 ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; 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 ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; 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. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) 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 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -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* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -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|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -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*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; 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 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-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 ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # 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 ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libpcap-0.9.7/./bpf/0000755000026300017500000000000010245661226012173 5ustar mcrmcrlibpcap-0.9.7/./bpf/net/0000755000026300017500000000000010245661226012761 5ustar mcrmcrlibpcap-0.9.7/./bpf/net/bpf_filter.c0000644000026300017500000002722407755532627015266 0ustar mcrmcr/*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)bpf.c 7.5 (Berkeley) 7/15/91 */ #if !(defined(lint) || defined(KERNEL) || defined(_KERNEL)) static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.44 2003/11/15 23:24:07 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #include #include #include #define SOLARIS (defined(sun) && (defined(__SVR4) || defined(__svr4__))) #if defined(__hpux) || SOLARIS # include # include # define mbuf msgb # define m_next b_cont # define MLEN(m) ((m)->b_wptr - (m)->b_rptr) # define mtod(m,t) ((t)(m)->b_rptr) #else # define MLEN(m) ((m)->m_len) #endif #endif /* WIN32 */ #include #if !defined(KERNEL) && !defined(_KERNEL) #include #endif #define int32 bpf_int32 #define u_int32 bpf_u_int32 #ifndef LBL_ALIGN /* * XXX - IA-64? If not, this probably won't work on Win64 IA-64 * systems, unless LBL_ALIGN is defined elsewhere for them. * XXX - SuperH? If not, this probably won't work on WinCE SuperH * systems, unless LBL_ALIGN is defined elsewhere for them. */ #if defined(sparc) || defined(__sparc__) || defined(mips) || \ defined(ibm032) || defined(__alpha) || defined(__hpux) || \ defined(__arm__) #define LBL_ALIGN #endif #endif #ifndef LBL_ALIGN #ifndef WIN32 #include #endif #define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) #define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p)) #else #define EXTRACT_SHORT(p)\ ((u_short)\ ((u_short)*((u_char *)p+0)<<8|\ (u_short)*((u_char *)p+1)<<0)) #define EXTRACT_LONG(p)\ ((u_int32)*((u_char *)p+0)<<24|\ (u_int32)*((u_char *)p+1)<<16|\ (u_int32)*((u_char *)p+2)<<8|\ (u_int32)*((u_char *)p+3)<<0) #endif #if defined(KERNEL) || defined(_KERNEL) # if !defined(__hpux) && !SOLARIS #include # endif #define MINDEX(len, _m, _k) \ { \ len = MLEN(m); \ while ((_k) >= len) { \ (_k) -= len; \ (_m) = (_m)->m_next; \ if ((_m) == 0) \ return 0; \ len = MLEN(m); \ } \ } static int m_xword(m, k, err) register struct mbuf *m; register int k, *err; { register int len; register u_char *cp, *np; register struct mbuf *m0; MINDEX(len, m, k); cp = mtod(m, u_char *) + k; if (len - k >= 4) { *err = 0; return EXTRACT_LONG(cp); } m0 = m->m_next; if (m0 == 0 || MLEN(m0) + len - k < 4) goto bad; *err = 0; np = mtod(m0, u_char *); switch (len - k) { case 1: return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; case 2: return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1]; default: return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0]; } bad: *err = 1; return 0; } static int m_xhalf(m, k, err) register struct mbuf *m; register int k, *err; { register int len; register u_char *cp; register struct mbuf *m0; MINDEX(len, m, k); cp = mtod(m, u_char *) + k; if (len - k >= 2) { *err = 0; return EXTRACT_SHORT(cp); } m0 = m->m_next; if (m0 == 0) goto bad; *err = 0; return (cp[0] << 8) | mtod(m0, u_char *)[0]; bad: *err = 1; return 0; } #endif /* * Execute the filter program starting at pc on the packet p * wirelen is the length of the original packet * buflen is the amount of data present * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0, * in all other cases, p is a pointer to a buffer and buflen is its size. */ u_int bpf_filter(pc, p, wirelen, buflen) register struct bpf_insn *pc; register u_char *p; u_int wirelen; register u_int buflen; { register u_int32 A, X; register int k; int32 mem[BPF_MEMWORDS]; #if defined(KERNEL) || defined(_KERNEL) struct mbuf *m, *n; int merr, len; if (buflen == 0) { m = (struct mbuf *)p; p = mtod(m, u_char *); buflen = MLEN(m); } else m = NULL; #endif if (pc == 0) /* * No filter means accept all. */ return (u_int)-1; A = 0; X = 0; --pc; while (1) { ++pc; switch (pc->code) { default: #if defined(KERNEL) || defined(_KERNEL) return 0; #else abort(); #endif case BPF_RET|BPF_K: return (u_int)pc->k; case BPF_RET|BPF_A: return (u_int)A; case BPF_LD|BPF_W|BPF_ABS: k = pc->k; if (k + sizeof(int32) > buflen) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; A = m_xword(m, k, &merr); if (merr != 0) return 0; continue; #else return 0; #endif } A = EXTRACT_LONG(&p[k]); continue; case BPF_LD|BPF_H|BPF_ABS: k = pc->k; if (k + sizeof(short) > buflen) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; A = m_xhalf(m, k, &merr); if (merr != 0) return 0; continue; #else return 0; #endif } A = EXTRACT_SHORT(&p[k]); continue; case BPF_LD|BPF_B|BPF_ABS: k = pc->k; if (k >= buflen) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; n = m; MINDEX(len, n, k); A = mtod(n, u_char *)[k]; continue; #else return 0; #endif } A = p[k]; continue; case BPF_LD|BPF_W|BPF_LEN: A = wirelen; continue; case BPF_LDX|BPF_W|BPF_LEN: X = wirelen; continue; case BPF_LD|BPF_W|BPF_IND: k = X + pc->k; if (k + sizeof(int32) > buflen) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; A = m_xword(m, k, &merr); if (merr != 0) return 0; continue; #else return 0; #endif } A = EXTRACT_LONG(&p[k]); continue; case BPF_LD|BPF_H|BPF_IND: k = X + pc->k; if (k + sizeof(short) > buflen) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; A = m_xhalf(m, k, &merr); if (merr != 0) return 0; continue; #else return 0; #endif } A = EXTRACT_SHORT(&p[k]); continue; case BPF_LD|BPF_B|BPF_IND: k = X + pc->k; if (k >= buflen) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; n = m; MINDEX(len, n, k); A = mtod(n, u_char *)[k]; continue; #else return 0; #endif } A = p[k]; continue; case BPF_LDX|BPF_MSH|BPF_B: k = pc->k; if (k >= buflen) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; n = m; MINDEX(len, n, k); X = (mtod(n, char *)[k] & 0xf) << 2; continue; #else return 0; #endif } X = (p[pc->k] & 0xf) << 2; continue; case BPF_LD|BPF_IMM: A = pc->k; continue; case BPF_LDX|BPF_IMM: X = pc->k; continue; case BPF_LD|BPF_MEM: A = mem[pc->k]; continue; case BPF_LDX|BPF_MEM: X = mem[pc->k]; continue; case BPF_ST: mem[pc->k] = A; continue; case BPF_STX: mem[pc->k] = X; continue; case BPF_JMP|BPF_JA: pc += pc->k; continue; case BPF_JMP|BPF_JGT|BPF_K: pc += (A > pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGE|BPF_K: pc += (A >= pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JEQ|BPF_K: pc += (A == pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JSET|BPF_K: pc += (A & pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGT|BPF_X: pc += (A > X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGE|BPF_X: pc += (A >= X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JEQ|BPF_X: pc += (A == X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JSET|BPF_X: pc += (A & X) ? pc->jt : pc->jf; continue; case BPF_ALU|BPF_ADD|BPF_X: A += X; continue; case BPF_ALU|BPF_SUB|BPF_X: A -= X; continue; case BPF_ALU|BPF_MUL|BPF_X: A *= X; continue; case BPF_ALU|BPF_DIV|BPF_X: if (X == 0) return 0; A /= X; continue; case BPF_ALU|BPF_AND|BPF_X: A &= X; continue; case BPF_ALU|BPF_OR|BPF_X: A |= X; continue; case BPF_ALU|BPF_LSH|BPF_X: A <<= X; continue; case BPF_ALU|BPF_RSH|BPF_X: A >>= X; continue; case BPF_ALU|BPF_ADD|BPF_K: A += pc->k; continue; case BPF_ALU|BPF_SUB|BPF_K: A -= pc->k; continue; case BPF_ALU|BPF_MUL|BPF_K: A *= pc->k; continue; case BPF_ALU|BPF_DIV|BPF_K: A /= pc->k; continue; case BPF_ALU|BPF_AND|BPF_K: A &= pc->k; continue; case BPF_ALU|BPF_OR|BPF_K: A |= pc->k; continue; case BPF_ALU|BPF_LSH|BPF_K: A <<= pc->k; continue; case BPF_ALU|BPF_RSH|BPF_K: A >>= pc->k; continue; case BPF_ALU|BPF_NEG: A = -A; continue; case BPF_MISC|BPF_TAX: X = A; continue; case BPF_MISC|BPF_TXA: A = X; continue; } } } /* * Return true if the 'fcode' is a valid filter program. * The constraints are that each jump be forward and to a valid * code. The code must terminate with either an accept or reject. * 'valid' is an array for use by the routine (it must be at least * 'len' bytes long). * * The kernel needs to be able to verify an application's filter code. * Otherwise, a bogus program could easily crash the system. */ int bpf_validate(f, len) struct bpf_insn *f; int len; { register int i; register struct bpf_insn *p; for (i = 0; i < len; ++i) { /* * Check that that jumps are forward, and within * the code block. */ p = &f[i]; if (BPF_CLASS(p->code) == BPF_JMP) { register int from = i + 1; if (BPF_OP(p->code) == BPF_JA) { if (from + p->k >= (unsigned)len) return 0; } else if (from + p->jt >= len || from + p->jf >= len) return 0; } /* * Check that memory operations use valid addresses. */ if ((BPF_CLASS(p->code) == BPF_ST || (BPF_CLASS(p->code) == BPF_LD && (p->code & 0xe0) == BPF_MEM)) && (p->k >= BPF_MEMWORDS || p->k < 0)) return 0; /* * Check for constant division by 0. */ if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) return 0; } return BPF_CLASS(f[len - 1].code) == BPF_RET; } libpcap-0.9.7/./bpf/net/CVS/0000755000026300017500000000000010245661226013414 5ustar mcrmcrlibpcap-0.9.7/./bpf/net/CVS/Entries0000644000026300017500000000007410245661226014751 0ustar mcrmcr/bpf_filter.c/1.44/Sat Nov 15 23:24:07 2003//Tlibpcap_0_9 D libpcap-0.9.7/./bpf/net/CVS/Root0000644000026300017500000000004010245661226014254 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./bpf/net/CVS/Repository0000644000026300017500000000002010245661226015506 0ustar mcrmcrlibpcap/bpf/net libpcap-0.9.7/./bpf/net/CVS/Tag0000644000026300017500000000001510245661226014046 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./bpf/CVS/0000755000026300017500000000000010245661233012624 5ustar mcrmcrlibpcap-0.9.7/./bpf/CVS/Entries0000644000026300017500000000001210245661233014151 0ustar mcrmcrD/net//// libpcap-0.9.7/./bpf/CVS/Root0000644000026300017500000000004010245661226013466 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./bpf/CVS/Repository0000644000026300017500000000001410245661226014723 0ustar mcrmcrlibpcap/bpf libpcap-0.9.7/./bpf/CVS/Tag0000644000026300017500000000001510245661226013260 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./scanner.l0000644000026300017500000002424110633321704013230 0ustar mcrmcr%{ /* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.99.2.9 2007/06/11 09:52:05 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "pcap-int.h" #include "gencode.h" #ifdef INET6 #ifdef WIN32 #include #ifdef __MINGW32__ #include "IP6_misc.h" #endif #else /* WIN32 */ #include /* for "struct sockaddr" in "struct addrinfo" */ #include /* for "struct addrinfo" */ #endif /* WIN32 */ /* Workaround for AIX 4.3 */ #if !defined(AI_NUMERICHOST) #define AI_NUMERICHOST 0x04 #endif #endif /*INET6*/ #include #include "tokdefs.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 static YY_BUFFER_STATE in_buffer; #else static char *in_buffer; #undef getc #define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++) #endif #define yylval pcap_lval extern YYSTYPE yylval; %} N ([0-9]+|(0X|0x)[0-9A-Fa-f]+) B ([0-9A-Fa-f][0-9A-Fa-f]?) W ([0-9A-Fa-f][0-9A-Fa-f]?[0-9A-Fa-f]?[0-9A-Fa-f]?) %a 18400 %o 21500 %e 7600 %k 4550 %p 27600 %n 2000 V680 {W}:{W}:{W}:{W}:{W}:{W}:{W}:{W} V670 ::{W}:{W}:{W}:{W}:{W}:{W}:{W} V671 {W}::{W}:{W}:{W}:{W}:{W}:{W} V672 {W}:{W}::{W}:{W}:{W}:{W}:{W} V673 {W}:{W}:{W}::{W}:{W}:{W}:{W} V674 {W}:{W}:{W}:{W}::{W}:{W}:{W} V675 {W}:{W}:{W}:{W}:{W}::{W}:{W} V676 {W}:{W}:{W}:{W}:{W}:{W}::{W} V677 {W}:{W}:{W}:{W}:{W}:{W}:{W}:: V660 ::{W}:{W}:{W}:{W}:{W}:{W} V661 {W}::{W}:{W}:{W}:{W}:{W} V662 {W}:{W}::{W}:{W}:{W}:{W} V663 {W}:{W}:{W}::{W}:{W}:{W} V664 {W}:{W}:{W}:{W}::{W}:{W} V665 {W}:{W}:{W}:{W}:{W}::{W} V666 {W}:{W}:{W}:{W}:{W}:{W}:: V650 ::{W}:{W}:{W}:{W}:{W} V651 {W}::{W}:{W}:{W}:{W} V652 {W}:{W}::{W}:{W}:{W} V653 {W}:{W}:{W}::{W}:{W} V654 {W}:{W}:{W}:{W}::{W} V655 {W}:{W}:{W}:{W}:{W}:: V640 ::{W}:{W}:{W}:{W} V641 {W}::{W}:{W}:{W} V642 {W}:{W}::{W}:{W} V643 {W}:{W}:{W}::{W} V644 {W}:{W}:{W}:{W}:: V630 ::{W}:{W}:{W} V631 {W}::{W}:{W} V632 {W}:{W}::{W} V633 {W}:{W}:{W}:: V620 ::{W}:{W} V621 {W}::{W} V622 {W}:{W}:: V610 ::{W} V611 {W}:: V600 :: V6604 {W}:{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6504 ::{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6514 {W}::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6524 {W}:{W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6534 {W}:{W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N} V6544 {W}:{W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N} V6554 {W}:{W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N} V6404 ::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6414 {W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6424 {W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N} V6434 {W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N} V6444 {W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N} V6304 ::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} V6314 {W}::{W}:{W}:{N}\.{N}\.{N}\.{N} V6324 {W}:{W}::{W}:{N}\.{N}\.{N}\.{N} V6334 {W}:{W}:{W}::{N}\.{N}\.{N}\.{N} V6204 ::{W}:{W}:{N}\.{N}\.{N}\.{N} V6214 {W}::{W}:{N}\.{N}\.{N}\.{N} V6224 {W}:{W}::{N}\.{N}\.{N}\.{N} V6104 ::{W}:{N}\.{N}\.{N}\.{N} V6114 {W}::{N}\.{N}\.{N}\.{N} V6004 ::{N}\.{N}\.{N}\.{N} V6 ({V680}|{V670}|{V671}|{V672}|{V673}|{V674}|{V675}|{V676}|{V677}|{V660}|{V661}|{V662}|{V663}|{V664}|{V665}|{V666}|{V650}|{V651}|{V652}|{V653}|{V654}|{V655}|{V640}|{V641}|{V642}|{V643}|{V644}|{V630}|{V631}|{V632}|{V633}|{V620}|{V621}|{V622}|{V610}|{V611}|{V600}|{V6604}|{V6504}|{V6514}|{V6524}|{V6534}|{V6544}|{V6554}|{V6404}|{V6414}|{V6424}|{V6434}|{V6444}|{V6304}|{V6314}|{V6324}|{V6334}|{V6204}|{V6214}|{V6224}|{V6104}|{V6114}|{V6004}) %% dst return DST; src return SRC; link|ether|ppp|slip return LINK; fddi|tr|wlan return LINK; arp return ARP; rarp return RARP; ip return IP; sctp return SCTP; tcp return TCP; udp return UDP; icmp return ICMP; igmp return IGMP; igrp return IGRP; pim return PIM; vrrp return VRRP; radio return RADIO; ip6 { #ifdef INET6 return IPV6; #else bpf_error("%s not supported", yytext); #endif } icmp6 { #ifdef INET6 return ICMPV6; #else bpf_error("%s not supported", yytext); #endif } ah return AH; esp return ESP; atalk return ATALK; aarp return AARP; decnet return DECNET; lat return LAT; sca return SCA; moprc return MOPRC; mopdl return MOPDL; iso return ISO; esis return ESIS; es-is return ESIS; isis return ISIS; is-is return ISIS; l1 return L1; l2 return L2; iih return IIH; lsp return LSP; snp return SNP; csnp return CSNP; psnp return PSNP; clnp return CLNP; stp return STP; ipx return IPX; netbeui return NETBEUI; host return HOST; net return NET; mask return NETMASK; port return PORT; portrange return PORTRANGE; proto return PROTO; protochain { #ifdef NO_PROTOCHAIN bpf_error("%s not supported", yytext); #else return PROTOCHAIN; #endif } gateway return GATEWAY; less return LESS; greater return GREATER; byte return CBYTE; 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; vlan return VLAN; mpls return MPLS; pppoed return PPPOED; pppoes return PPPOES; lane return LANE; llc return LLC; metac return METAC; bcc return BCC; oam return OAM; oamf4 return OAMF4; oamf4ec return OAMF4EC; oamf4sc return OAMF4SC; sc return SC; ilmic return ILMIC; vpi return VPI; vci return VCI; connectmsg return CONNECTMSG; metaconnect return METACONNECT; on|ifname return PF_IFNAME; rset|ruleset return PF_RSET; rnr|rulenum return PF_RNR; srnr|subrulenum return PF_SRNR; reason return PF_REASON; action return PF_ACTION; fisu return FISU; lssu return LSSU; lsu return LSSU; msu return MSU; sio return SIO; opc return OPC; dpc return DPC; sls return SLS; [ \r\n\t] ; [+\-*/:\[\]!<>()&|=] return yytext[0]; ">=" return GEQ; "<=" return LEQ; "!=" return NEQ; "==" return '='; "<<" return LSH; ">>" return RSH; ${B} { yylval.e = pcap_ether_aton(((char *)yytext)+1); return AID; } {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; } {V6} { #ifdef INET6 struct addrinfo hints, *res; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_flags = AI_NUMERICHOST; if (getaddrinfo(yytext, NULL, &hints, &res)) bpf_error("bogus IPv6 address %s", yytext); else { yylval.s = sdup((char *)yytext); return HID6; } #else bpf_error("IPv6 address %s not supported", yytext); #endif /*INET6*/ } {B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); } icmptype { yylval.i = 0; return NUM; } icmpcode { yylval.i = 1; return NUM; } icmp-echoreply { yylval.i = 0; return NUM; } icmp-unreach { yylval.i = 3; return NUM; } icmp-sourcequench { yylval.i = 4; return NUM; } icmp-redirect { yylval.i = 5; return NUM; } icmp-echo { yylval.i = 8; return NUM; } icmp-routeradvert { yylval.i = 9; return NUM; } icmp-routersolicit { yylval.i = 10; return NUM; } icmp-timxceed { yylval.i = 11; return NUM; } icmp-paramprob { yylval.i = 12; return NUM; } icmp-tstamp { yylval.i = 13; return NUM; } icmp-tstampreply { yylval.i = 14; return NUM; } icmp-ireq { yylval.i = 15; return NUM; } icmp-ireqreply { yylval.i = 16; return NUM; } icmp-maskreq { yylval.i = 17; return NUM; } icmp-maskreply { yylval.i = 18; return NUM; } tcpflags { yylval.i = 13; return NUM; } tcp-fin { yylval.i = 0x01; return NUM; } tcp-syn { yylval.i = 0x02; return NUM; } tcp-rst { yylval.i = 0x04; return NUM; } tcp-push { yylval.i = 0x08; return NUM; } tcp-ack { yylval.i = 0x10; return NUM; } tcp-urg { yylval.i = 0x20; return NUM; } [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!<>()&|=]+ { bpf_error("illegal token: %s", yytext); } . { bpf_error("illegal char '%c'", *yytext); } %% void lex_init(buf) const char *buf; { #ifdef FLEX_SCANNER in_buffer = yy_scan_string(buf); #else in_buffer = buf; #endif } /* * Do any cleanup necessary after parsing. */ void lex_cleanup() { #ifdef FLEX_SCANNER if (in_buffer != NULL) yy_delete_buffer(in_buffer); in_buffer = NULL; #endif } /* * Also define a yywrap. Note that if we're using flex, it will * define a macro to map this identifier to pcap_wrap. */ int 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; } libpcap-0.9.7/./README.septel0000644000026300017500000000377510255632546013617 0ustar mcrmcrThe following instructions apply if you have a Linux platform and want libpcap to support the Septel range of passive network monitoring cards from Intel (http://www.intel.com) 1) Install and build the Septel software distribution by following the instructions supplied with that package. 2) Configure libcap. To allow the 'configure' script to locate the Septel software distribution use the '--with-septel' option: ./configure --with-septel=DIR where DIR is the root of the Septel software distribution, for example /var/src/septel. By default (if you write only ./configure --with-septel) it takes ./../septel as argument for DIR. If the Septel software is correctly detected 'configure' will report: checking whether we have Septel API... yes If 'configure' reports that there is no Septel API, the directory may have been incorrectly specified or the Septel software was not built before configuring libpcap. See also the libpcap INSTALL.txt file for further libpcap configuration options. Building libpcap at this stage will include support for both the native packet capture stream and for capturing from Septel cards. To build libpcap with only Septel support specify the capture type as 'septel' when configuring libpcap: ./configure --with-septel=DIR --with-pcap=septel Applications built with libpcap configured in this way will only detect Septel cards and will not capture from the native OS packet stream. Note: As mentioned in pcap-septel.c we should first edit the system.txt file to change the user part example (UPE) module id to 0xdd instead of 0x2d for technical reason. So this change in system.txt is crutial and things will go wrong if it's not done. System.txt along with config.txt are configuration files that are edited by the user before running the gctload program that uses these files for initialising modules and configuring parameters. ---------------------------------------------------------------------- for more information please contact me : gil_hoyek@hotmail.com libpcap-0.9.7/./fad-getad.c0000644000026300017500000002033710226265301013402 0ustar mcrmcr/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.10.2.1 2005/04/10 18:04:49 hannes Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #ifdef AF_PACKET # include #endif /* * This is fun. * * In older BSD systems, socket addresses were fixed-length, and * "sizeof (struct sockaddr)" gave the size of the structure. * All addresses fit within a "struct sockaddr". * * In newer BSD systems, the socket address is variable-length, and * there's an "sa_len" field giving the length of the structure; * this allows socket addresses to be longer than 2 bytes of family * and 14 bytes of data. * * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553 * variant of the old BSD scheme (with "struct sockaddr_storage" rather * than "struct sockaddr"), and some use the new BSD scheme. * * Some versions of GNU libc use neither scheme, but has an "SA_LEN()" * macro that determines the size based on the address family. Other * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553 * but not in the final version). On the latter systems, we explicitly * check the AF_ type to determine the length; we assume that on * all those systems we have "struct sockaddr_storage". */ #ifndef SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN #define SA_LEN(addr) ((addr)->sa_len) #else /* HAVE_SOCKADDR_SA_LEN */ #ifdef HAVE_SOCKADDR_STORAGE static size_t get_sa_len(struct sockaddr *addr) { switch (addr->sa_family) { #ifdef AF_INET case AF_INET: return (sizeof (struct sockaddr_in)); #endif #ifdef AF_INET6 case AF_INET6: return (sizeof (struct sockaddr_in6)); #endif #ifdef AF_PACKET case AF_PACKET: return (sizeof (struct sockaddr_ll)); #endif default: return (sizeof (struct sockaddr)); } } #define SA_LEN(addr) (get_sa_len(addr)) #else /* HAVE_SOCKADDR_STORAGE */ #define SA_LEN(addr) (sizeof (struct sockaddr)) #endif /* HAVE_SOCKADDR_STORAGE */ #endif /* HAVE_SOCKADDR_SA_LEN */ #endif /* SA_LEN */ /* * Get a list of all interfaces that are up and that we can open. * Returns -1 on error, 0 otherwise. * The list, as returned through "alldevsp", may be null if no interfaces * were up and could be opened. * * This is the implementation used on platforms that have "getifaddrs()". */ int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; struct ifaddrs *ifap, *ifa; struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; size_t addr_size, broadaddr_size, dstaddr_size; int ret = 0; char *p, *q; /* * Get the list of interface addresses. * * Note: this won't return information about interfaces * with no addresses; are there any such interfaces * that would be capable of receiving packets? * (Interfaces incapable of receiving packets aren't * very interesting from libpcap's point of view.) * * LAN interfaces will probably have link-layer * addresses; I don't know whether all implementations * of "getifaddrs()" now, or in the future, will return * those. */ if (getifaddrs(&ifap) != 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "getifaddrs: %s", pcap_strerror(errno)); return (-1); } for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { /* * Is this interface up? */ if (!(ifa->ifa_flags & IFF_UP)) { /* * No, so don't add it to the list. */ continue; } /* * "ifa_addr" was apparently null on at least one * interface on some system. * * "ifa_broadaddr" may be non-null even on * non-broadcast interfaces, and was null on * at least one OpenBSD 3.4 system on at least * one interface with IFF_BROADCAST set. * * "ifa_dstaddr" was, on at least one FreeBSD 4.1 * system, non-null on a non-point-to-point * interface. * * Therefore, we supply the address and netmask only * if "ifa_addr" is non-null (if there's no address, * there's obviously no netmask), and supply the * broadcast and destination addresses if the appropriate * flag is set *and* the appropriate "ifa_" entry doesn't * evaluate to a null pointer. */ if (ifa->ifa_addr != NULL) { addr = ifa->ifa_addr; addr_size = SA_LEN(addr); netmask = ifa->ifa_netmask; } else { addr = NULL; addr_size = 0; netmask = NULL; } if (ifa->ifa_flags & IFF_BROADCAST && ifa->ifa_broadaddr != NULL) { broadaddr = ifa->ifa_broadaddr; broadaddr_size = SA_LEN(broadaddr); } else { broadaddr = NULL; broadaddr_size = 0; } if (ifa->ifa_flags & IFF_POINTOPOINT && ifa->ifa_dstaddr != NULL) { dstaddr = ifa->ifa_dstaddr; dstaddr_size = SA_LEN(ifa->ifa_dstaddr); } else { dstaddr = NULL; dstaddr_size = 0; } /* * If this entry has a colon followed by a number at * the end, we assume it's a logical interface. Those * are just the way you assign multiple IP addresses to * a real interface on Linux, so an entry for a logical * interface should be treated like the entry for the * real interface; we do that by stripping off the ":" * and the number. * * XXX - should we do this only on Linux? */ p = strchr(ifa->ifa_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ q = p + 1; while (isdigit((unsigned char)*q)) q++; if (*q == '\0') { /* * All digits after the ":" until the end. * Strip off the ":" and everything after * it. */ *p = '\0'; } } /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifa->ifa_name, ifa->ifa_flags, addr, addr_size, netmask, addr_size, broadaddr, broadaddr_size, dstaddr, dstaddr_size, errbuf) < 0) { ret = -1; break; } } freeifaddrs(ifap); if (ret != -1) { /* * We haven't had any errors yet; do any platform-specific * operations to add devices. */ if (pcap_platform_finddevs(&devlist, errbuf) < 0) ret = -1; } if (ret == -1) { /* * We had an error; free the list we've been constructing. */ if (devlist != NULL) { pcap_freealldevs(devlist); devlist = NULL; } } *alldevsp = devlist; return (ret); } libpcap-0.9.7/./packaging/0000755000026300017500000000000010504042141013333 5ustar mcrmcrlibpcap-0.9.7/./packaging/pcap.spec0000644000026300017500000000323110504042141015131 0ustar mcrmcr%define prefix /usr %define version 0.9.4 Summary: packet capture library Name: libpcap Version: %version Release: 1 Group: Development/Libraries Copyright: BSD Source: libpcap-0.9.4.tar.gz BuildRoot: /tmp/%{name}-buildroot URL: http://www.tcpdump.org %description Packet-capture library LIBPCAP 0.9.4 Now maintained by "The Tcpdump Group" See http://www.tcpdump.org Please send inquiries/comments/reports to tcpdump-workers@tcpdump.org %prep %setup %post ldconfig %build CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%prefix make %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT/usr/{lib,include} mkdir -p $RPM_BUILD_ROOT/usr/share/man mkdir -p $RPM_BUILD_ROOT/usr/include/net mkdir -p $RPM_BUILD_ROOT/usr/man/man3 make install DESTDIR=$RPM_BUILD_ROOT mandir=/usr/share/man cd $RPM_BUILD_ROOT/usr/lib V1=`echo 0.9.4 | sed 's/\\.[^\.]*$//g'` V2=`echo 0.9.4 | sed 's/\\.[^\.]*\.[^\.]*$//g'` ln -sf libpcap.so.0.9.4 libpcap.so.$V1 if test "$V2" -ne "$V1"; then ln -sf libpcap.so.$V1 libpcap.so.$V2 ln -sf libpcap.so.$V2 libpcap.so else ln -sf libpcap.so.$V1 libpcap.so fi #install -m 755 -o root libpcap.a $RPM_BUILD_ROOT/usr/lib #install -m 644 -o root pcap.3 $RPM_BUILD_ROOT/usr/man/man3 #install -m 644 -o root pcap.h $RPM_BUILD_ROOT/usr/include #install -m 644 -o root pcap-bpf.h $RPM_BUILD_ROOT/usr/include/net #install -m 644 -o root pcap-namedb.h $RPM_BUILD_ROOT/usr/include %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc LICENSE CHANGES INSTALL.txt README.linux TODO VERSION CREDITS packaging/pcap.spec /usr/lib/libpcap.a /usr/share/man/man3/* /usr/include/pcap.h /usr/include/pcap-bpf.h /usr/include/pcap-namedb.h /usr/lib/libpcap.so* libpcap-0.9.7/./packaging/CVS/0000755000026300017500000000000010504042141013766 5ustar mcrmcrlibpcap-0.9.7/./packaging/CVS/Entries0000644000026300017500000000016510504042141015324 0ustar mcrmcr/pcap.spec.in/1.1/Sun Nov 30 04:45:14 2003//Tlibpcap_0_9 /pcap.spec/1.4.2.1/Tue Sep 19 19:26:25 2006//Tlibpcap_0_9 D libpcap-0.9.7/./packaging/CVS/Root0000644000026300017500000000004010245661233014641 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./packaging/CVS/Repository0000644000026300017500000000002210245661233016075 0ustar mcrmcrlibpcap/packaging libpcap-0.9.7/./packaging/CVS/Tag0000644000026300017500000000001510245661233014433 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./packaging/pcap.spec.in0000644000026300017500000000324607762272732015573 0ustar mcrmcr%define prefix /usr %define version @VERSION@ Summary: packet capture library Name: libpcap Version: %version Release: 1 Group: Development/Libraries Copyright: BSD Source: @NAME@.tar.gz BuildRoot: /tmp/%{name}-buildroot URL: http://www.tcpdump.org %description Packet-capture library LIBPCAP @VERSION@ Now maintained by "The Tcpdump Group" See http://www.tcpdump.org Please send inquiries/comments/reports to tcpdump-workers@tcpdump.org %prep %setup %post ldconfig %build CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%prefix make %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT/usr/{lib,include} mkdir -p $RPM_BUILD_ROOT/usr/share/man mkdir -p $RPM_BUILD_ROOT/usr/include/net mkdir -p $RPM_BUILD_ROOT/usr/man/man3 make install DESTDIR=$RPM_BUILD_ROOT mandir=/usr/share/man cd $RPM_BUILD_ROOT/usr/lib V1=`echo @VERSION@ | sed 's/\\.[^\.]*$//g'` V2=`echo @VERSION@ | sed 's/\\.[^\.]*\.[^\.]*$//g'` ln -sf libpcap.so.@VERSION@ libpcap.so.$V1 if test "$V2" -ne "$V1"; then ln -sf libpcap.so.$V1 libpcap.so.$V2 ln -sf libpcap.so.$V2 libpcap.so else ln -sf libpcap.so.$V1 libpcap.so fi #install -m 755 -o root libpcap.a $RPM_BUILD_ROOT/usr/lib #install -m 644 -o root pcap.3 $RPM_BUILD_ROOT/usr/man/man3 #install -m 644 -o root pcap.h $RPM_BUILD_ROOT/usr/include #install -m 644 -o root pcap-bpf.h $RPM_BUILD_ROOT/usr/include/net #install -m 644 -o root pcap-namedb.h $RPM_BUILD_ROOT/usr/include %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc LICENSE CHANGES INSTALL.txt README.linux TODO VERSION CREDITS packaging/pcap.spec /usr/lib/libpcap.a /usr/share/man/man3/* /usr/include/pcap.h /usr/include/pcap-bpf.h /usr/include/pcap-namedb.h /usr/lib/libpcap.so* libpcap-0.9.7/./pcap.h0000644000026300017500000002540110633321704012515 0ustar mcrmcr/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * 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: /tcpdump/master/libpcap/pcap.h,v 1.52.2.7 2007/06/11 09:52:05 guy Exp $ (LBL) */ #ifndef lib_pcap_h #define lib_pcap_h #if defined(WIN32) #include #elif defined(MSDOS) #include #include /* u_int, u_char etc. */ #else /* UN*X */ #include #include #endif /* WIN32/MSDOS/UN*X */ #ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H #include #endif #include #ifdef __cplusplus extern "C" { #endif #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; typedef struct pcap_if pcap_if_t; typedef struct pcap_addr pcap_addr_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. * * Do not change the layout of this structure, in any way (this includes * changes that only affect the length of fields in this structure). * * Also, do not change the interpretation of any of the members of this * structure, in any way (this includes using values other than * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" * field). * * Instead: * * introduce a new structure for the new format, if the layout * of the structure changed; * * send mail to "tcpdump-workers@tcpdump.org", requesting a new * magic number for your new capture file format, and, when * you get the new magic number, put it in "savefile.c"; * * use that magic number for save files with the changed file * header; * * make the code in "savefile.c" capable of reading files with * the old file header as well as files with the new file header * (using the magic number to determine the header format). * * Then supply the changes to "patches@tcpdump.org", so that future * versions of libpcap and programs that use it (such as tcpdump) will * be able to read your new capture file format. */ 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 (LINKTYPE_*) */ }; typedef enum { PCAP_D_INOUT = 0, PCAP_D_IN, PCAP_D_OUT } pcap_direction_t; /* * Generic per-packet information, as supplied by libpcap. * * The time stamp can and should be a "struct timeval", regardless of * whether your system supports 32-bit tv_sec in "struct timeval", * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit * and 64-bit applications. The on-disk format of savefiles uses 32-bit * tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit * and 64-bit versions of libpcap, even if they're on the same platform, * should supply the appropriate version of "struct timeval", even if * that's not what the underlying packet capture mechanism supplies. */ 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 */ #ifdef WIN32 u_int bs_capt; /* number of packets that reach the application */ #endif /* WIN32 */ }; #ifdef MSDOS /* * As returned by the pcap_stats_ex() */ struct pcap_stat_ex { u_long rx_packets; /* total packets received */ u_long tx_packets; /* total packets transmitted */ u_long rx_bytes; /* total bytes received */ u_long tx_bytes; /* total bytes transmitted */ u_long rx_errors; /* bad packets received */ u_long tx_errors; /* packet transmit problems */ u_long rx_dropped; /* no space in Rx buffers */ u_long tx_dropped; /* no space available for Tx */ u_long multicast; /* multicast packets received */ u_long collisions; /* detailed rx_errors: */ u_long rx_length_errors; u_long rx_over_errors; /* receiver ring buff overflow */ u_long rx_crc_errors; /* recv'd pkt with crc error */ u_long rx_frame_errors; /* recv'd frame alignment error */ u_long rx_fifo_errors; /* recv'r fifo overrun */ u_long rx_missed_errors; /* recv'r missed packet */ /* detailed tx_errors */ u_long tx_aborted_errors; u_long tx_carrier_errors; u_long tx_fifo_errors; u_long tx_heartbeat_errors; u_long tx_window_errors; }; #endif /* * Item in a list of interfaces. */ struct pcap_if { struct pcap_if *next; char *name; /* name to hand to "pcap_open_live()" */ char *description; /* textual description of interface, or NULL */ struct pcap_addr *addresses; bpf_u_int32 flags; /* PCAP_IF_ interface flags */ }; #define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ /* * Representation of an interface address. */ struct pcap_addr { struct pcap_addr *next; struct sockaddr *addr; /* address */ struct sockaddr *netmask; /* netmask for that address */ struct sockaddr *broadaddr; /* broadcast address for that address */ struct sockaddr *dstaddr; /* P2P destination address for that address */ }; typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *); char *pcap_lookupdev(char *); int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); pcap_t *pcap_open_live(const char *, int, int, int, char *); pcap_t *pcap_open_dead(int, int); pcap_t *pcap_open_offline(const char *, char *); pcap_t *pcap_fopen_offline(FILE *, 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_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **); void pcap_breakloop(pcap_t *); int pcap_stats(pcap_t *, struct pcap_stat *); int pcap_setfilter(pcap_t *, struct bpf_program *); int pcap_setdirection(pcap_t *, pcap_direction_t); int pcap_getnonblock(pcap_t *, char *); int pcap_setnonblock(pcap_t *, int, char *); void pcap_perror(pcap_t *, char *); int pcap_inject(pcap_t *, const void *, size_t); int pcap_sendpacket(pcap_t *, const u_char *, int); const char *pcap_strerror(int); char *pcap_geterr(pcap_t *); int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32); int pcap_compile_nopcap(int, int, struct bpf_program *, const char *, int, bpf_u_int32); void pcap_freecode(struct bpf_program *); int pcap_datalink(pcap_t *); int pcap_list_datalinks(pcap_t *, int **); int pcap_set_datalink(pcap_t *, int); int pcap_datalink_name_to_val(const char *); const char *pcap_datalink_val_to_name(int); const char *pcap_datalink_val_to_description(int); 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 *); pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp); FILE *pcap_dump_file(pcap_dumper_t *); long pcap_dump_ftell(pcap_dumper_t *); int pcap_dump_flush(pcap_dumper_t *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); int pcap_findalldevs(pcap_if_t **, char *); void pcap_freealldevs(pcap_if_t *); const char *pcap_lib_version(void); /* XXX this guy lives in the bpf tree */ u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); int bpf_validate(struct bpf_insn *f, int len); char *bpf_image(struct bpf_insn *, int); void bpf_dump(struct bpf_program *, int); #if defined(WIN32) /* * Win32 definitions */ int pcap_setbuff(pcap_t *p, int dim); int pcap_setmode(pcap_t *p, int mode); int pcap_setmintocopy(pcap_t *p, int size); #ifdef WPCAP /* Include file with the wpcap-specific extensions */ #include #endif /* WPCAP */ #define MODE_CAPT 0 #define MODE_STAT 1 #define MODE_MON 2 #elif defined(MSDOS) /* * MS-DOS definitions */ int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *); void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait); u_long pcap_mac_packets (void); #else /* UN*X */ /* * UN*X definitions */ int pcap_get_selectable_fd(pcap_t *); #endif /* WIN32/MSDOS/UN*X */ #ifdef __cplusplus } #endif #endif libpcap-0.9.7/./pcap-nit.h0000644000026300017500000000171206777230340013315 0ustar mcrmcr/* * 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: /tcpdump/master/libpcap/pcap-nit.h,v 1.2.1.1 1999/10/07 23:46:40 mcr Exp $ (LBL) */ libpcap-0.9.7/./wlan_filtering.patch0000644000026300017500000002460110634331527015454 0ustar mcrmcr--- gencode.c.cvs 2007-06-14 13:54:12.000000000 -0700 +++ gencode.c 2007-06-14 13:56:27.531250000 -0700 @@ -24,6 +24,8 @@ "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.51 2007/06/14 20:54:12 gianluca Exp $ (LBL)"; #endif +#define ENABLE_WLAN_FILTERING_PATCH + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -144,7 +146,8 @@ OR_NET, /* relative to the network-layer header */ OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ - OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ + OR_TRAN_IPV6, /* relative to the transport-layer header, with IPv6 network layer */ + OR_LINK_AFTER_WIRELESS_HDR /* After the 802.11 variable length header */ }; /* @@ -199,6 +202,7 @@ static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); static struct block *gen_llc_linktype(int); +static struct block *gen_802_11_llc_linktype(int); static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); #ifdef INET6 static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); @@ -242,6 +246,7 @@ static struct slist *xfer_to_a(struct arth *); static struct block *gen_mac_multicast(int); static struct block *gen_len(int, int); +static struct block *gen_check_802_11_data_frame(); static struct block *gen_ppi_dlt_check(); static struct block *gen_msg_abbrev(int type); @@ -1345,6 +1350,138 @@ return s; } +/* + * Load a value relative to the beginning of the link-layer header after the 802.11 + * header, i.e. LLC_SNAP. + * The link-layer header doesn't necessarily begin at the beginning + * of the packet data; there might be a variable-length prefix containing + * radio information. + */ +static struct slist * +gen_load_ll_after_802_11_rel(offset, size) + u_int offset, size; +{ + struct slist *s, *s_load_fc; + struct slist *sjset_qos; + struct slist *s_load; + struct slist *s_ld_a_2; + struct slist *s_add_a_x; + struct slist *s_a_to_x; + struct slist *sjset_data_frame_1; + struct slist *sjset_data_frame_2; + struct slist *s_load_x_0; + + /* + * This code is not compatible with the optimizer, as + * we are generating jmp instructions within a normal + * slist of instructions + * + */ + no_optimize = 1; + + s = gen_llprefixlen(); + + /* + * If "s" is non-null, it has code to arrange that the X register + * contains the length of the prefix preceding the link-layer + * header. + * + * Otherwise, the length of the prefix preceding the link-layer + * header is "off_ll". + */ + if (s != NULL) { + /* + * There's a variable-length prefix preceding the + * link-layer header. "s" points to a list of statements + * that put the length of that prefix into the X register. + * do an indirect load, to use the X register as an offset. + */ + + /* + * Load the Frame Control field + */ + s_load_fc = new_stmt(BPF_LD|BPF_IND|BPF_B); + s_load_fc->s.k = 0; + } else { + /* + * There is no variable-length header preceding the + * link-layer header; add in off_ll, which, if there's + * a fixed-length header preceding the link-layer header, + * is the length of that header. + */ + + /* + * We need to load the Frame control directly, and + * then load X with a fake 0, i.e. the length of the + * non-existing prepended header + */ + + /* + * TODO GV: I'm not sure if 0 is the right constant in this + * case. If the link layer has a fixed length prepended header, + * that should be the value that we put here + */ + + /* Load 0 into X */ + s_load_x_0 = new_stmt(BPF_LDX|BPF_IMM); + s_load_x_0->s.k = 0; + + /* + * TODO GV: I'm not sure if 0 is the right constant in this + * case. If the link layer has a fixed length prepended header, + * that should be the value that we put here + */ + + /* + * load the Frame Control with absolute access + */ + s_load_fc = new_stmt(BPF_LD|BPF_ABS|BPF_B); + s_load_fc->s.k = 0; + s = s_load_x_0; + } + + /* + * Generate the common instructions to check if it's a data frame + * and if so compute the 802.11 header length + */ + sjset_data_frame_1 = new_stmt(JMP(BPF_JSET)); // b3 should be 1 + sjset_data_frame_1->s.k = 0x8; + + sjset_data_frame_2 = new_stmt(JMP(BPF_JSET)); // b2 should be 0 + sjset_data_frame_2->s.k = 0x04; + + sjset_qos = new_stmt(JMP(BPF_JSET)); + sjset_qos->s.k = 0x80; //QOS bit + + s_ld_a_2 = new_stmt(BPF_LD|BPF_IMM); + s_ld_a_2->s.k = 2; + + s_add_a_x = new_stmt(BPF_ALU|BPF_ADD|BPF_X); + s_a_to_x = new_stmt(BPF_MISC|BPF_TAX); + + s_load = new_stmt(BPF_LD|BPF_IND|size); + s_load->s.k = offset; + + sjset_data_frame_1->s.jt = sjset_data_frame_2; + sjset_data_frame_1->s.jf = s_load; + + sjset_data_frame_2->s.jt = s_load; + sjset_data_frame_2->s.jf = sjset_qos; + + sjset_qos->s.jt = s_ld_a_2; + sjset_qos->s.jf = s_load; + + sappend(s, s_load_fc); + sappend(s_load_fc, sjset_data_frame_1); + sappend(sjset_data_frame_1, sjset_data_frame_2); + sappend(sjset_data_frame_2, sjset_qos); + sappend(sjset_qos, s_ld_a_2); + sappend(s_ld_a_2, s_add_a_x); + sappend(s_add_a_x,s_a_to_x); + sappend(s_a_to_x, s_load); + + return s; +} /* * Load a value relative to the beginning of the specified header. @@ -1367,6 +1504,22 @@ s = gen_load_llrel(offset, size); break; +#ifdef ENABLE_WLAN_FILTERING_PATCH + + case OR_LINK_AFTER_WIRELESS_HDR: + if (linktype != DLT_IEEE802_11_RADIO + && linktype != DLT_PPI + && linktype != DLT_IEEE802_11 + && linktype != DLT_PRISM_HEADER + && linktype != DLT_IEEE802_11_RADIO_AVS) + { + abort(); + return NULL; + } + s = gen_load_ll_after_802_11_rel(offset + 24, size); + break; +#endif /* ENABLE_WLAN_FILTERING_PATCH */ + case OR_NET: s = gen_load_llrel(off_nl + offset, size); break; @@ -2163,11 +2316,17 @@ break; case DLT_PPI: + case DLT_IEEE802_11_RADIO: + case DLT_IEEE802_11: +#ifdef ENABLE_WLAN_FILTERING_PATCH + return gen_802_11_llc_linktype(proto); + /*NOTREACHED*/ + break; +#endif /* ENABLE_WLAN_FILTERING_PATCH */ + case DLT_FDDI: case DLT_IEEE802: - case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: - case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: case DLT_ATM_RFC1483: case DLT_ATM_CLIP: @@ -2711,6 +2870,113 @@ } } +/* + * Generate code to match a particular packet type, for link-layer types + * using 802.2 LLC headers. + * + * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used + * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. + * + * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP + * value, if <= ETHERMTU. We use that to determine whether to + * match the DSAP or both DSAP and LSAP or to check the OUI and + * protocol ID in a SNAP header. + */ +static struct block * +gen_802_11_llc_linktype(proto) + int proto; +{ + struct block *b_check_data_frame; + struct block *b_check_linktype; + + b_check_data_frame = gen_check_802_11_data_frame(); + + /* + * XXX - generate the code that discards non data frames + */ + switch (proto) { + + case LLCSAP_IP: + case LLCSAP_ISONS: + case LLCSAP_NETBEUI: + /* + * XXX - should we check both the DSAP and the + * SSAP, like this, or should we check just the + * DSAP, as we do for other types <= ETHERMTU + * (i.e., other SAP values)? + */ + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_H, (bpf_u_int32) + ((proto << 8) | proto)); + break; + + case LLCSAP_IPX: + /* + * XXX - are there ever SNAP frames for IPX on + * non-Ethernet 802.x networks? + */ + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_B, + (bpf_int32)LLCSAP_IPX); + + break; + +#if 0 + case ETHERTYPE_ATALK: + /* + * 802.2-encapsulated ETHERTYPE_ATALK packets are + * SNAP packets with an organization code of + * 0x080007 (Apple, for Appletalk) and a protocol + * type of ETHERTYPE_ATALK (Appletalk). + * + * XXX - check for an organization code of + * encapsulated Ethernet as well? + */ + return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype); +#endif + default: + /* + * XXX - we don't have to check for IPX 802.3 + * here, but should we check for the IPX Ethertype? + */ + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so check + * the DSAP. + */ + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_B, + (bpf_int32)proto); + } else { + /* + * This is an Ethernet type; we assume that it's + * unlikely that it'll appear in the right place + * at random, and therefore check only the + * location that would hold the Ethernet type + * in a SNAP frame with an organization code of + * 0x000000 (encapsulated Ethernet). + * + * XXX - if we were to check for the SNAP DSAP and + * LSAP, as per XXX, and were also to check for an + * organization code of 0x000000 (encapsulated + * Ethernet), we'd do + * + * return gen_snap(0x000000, proto, + * off_linktype); + * + * here; for now, we don't, as per the above. + * I don't know whether it's worth the extra CPU + * time to do the right check or not. + */ + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0+6, BPF_H, + (bpf_int32)proto); + } + } + + gen_and(b_check_data_frame, b_check_linktype); + return b_check_linktype; + +} + + + static struct block * gen_hostop(addr, mask, dir, proto, src_off, dst_off) bpf_u_int32 addr; @@ -2925,6 +3191,17 @@ register struct block *b0, *b1, *b2; register struct slist *s; +#ifdef ENABLE_WLAN_FILTERING_PATCH + /* + * TODO GV 20070613 + * We need to disable the optimizer because the optimizer is buggy + * and wipes out some LD instructions generated by the below + * code to validate the Frame Control bits + * + */ + no_optimize = 1; +#endif /* ENABLE_WLAN_FILTERING_PATCH */ + switch (dir) { case Q_SRC: /* @@ -4713,6 +4990,32 @@ #endif } +static struct block * +gen_check_802_11_data_frame() +{ + struct slist *s; + struct block *b0, *b1; + /* + * Now check for a data frame. + * I.e, check "link[0] & 0x08". + */ + s = gen_load_a(OR_LINK, 0, BPF_B); + b0 = new_block(JMP(BPF_JSET)); + b0->s.k = 0x08; + b0->stmts = s; + + s = gen_load_a(OR_LINK, 0, BPF_B); + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x04; + b1->stmts = s; + gen_not(b1); + + + gen_and(b1, b0); + + return b0; +} + /* * Generate code that checks whether the packet is a packet for protocol libpcap-0.9.7/./pcap-dag.c0000644000026300017500000006341010643174160013246 0ustar mcrmcr/* * pcap-dag.c: Packet capture interface for Endace DAG card. * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible. This code is compiled in several different ways depending on * whether DAG_ONLY and HAVE_DAG_API are defined. If HAVE_DAG_API is not * defined it should not get compiled in, otherwise if DAG_ONLY is defined then * the 'dag_' function calls are renamed to 'pcap_' equivalents. If DAG_ONLY * is not defined then nothing is altered - the dag_ functions will be * called as required from their pcap-linux/bpf equivalents. * * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) * Modifications: Jesper Peterson * Koryn Grant * Stephen Donnelly */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21.2.7 2007/06/22 06:43:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* optionally get BSD define */ #include #include #include #include "pcap-int.h" #include #include #include #include #include #include struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include #include "dagnew.h" #include "dagapi.h" #define ATM_CELL_SIZE 52 #define ATM_HDR_SIZE 4 /* * A header containing additional MTP information. */ #define MTP2_SENT_OFFSET 0 /* 1 byte */ #define MTP2_ANNEX_A_USED_OFFSET 1 /* 1 byte */ #define MTP2_LINK_NUMBER_OFFSET 2 /* 2 bytes */ #define MTP2_HDR_LEN 4 /* length of the header */ #define MTP2_ANNEX_A_NOT_USED 0 #define MTP2_ANNEX_A_USED 1 #define MTP2_ANNEX_A_USED_UNKNOWN 2 /* SunATM pseudo header */ struct sunatm_hdr { unsigned char flags; /* destination and traffic type */ unsigned char vpi; /* VPI */ unsigned short vci; /* VCI */ }; typedef struct pcap_dag_node { struct pcap_dag_node *next; pcap_t *p; pid_t pid; } pcap_dag_node_t; static pcap_dag_node_t *pcap_dags = NULL; static int atexit_handler_installed = 0; static const unsigned short endian_test_word = 0x0100; #define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word)) #ifdef DAG_ONLY /* This code is required when compiling for a DAG device only. */ #include "pcap-dag.h" /* Replace dag function names with pcap equivalent. */ #define dag_open_live pcap_open_live #define dag_platform_finddevs pcap_platform_finddevs #endif /* DAG_ONLY */ #define MAX_DAG_PACKET 65536 static unsigned char TempPkt[MAX_DAG_PACKET]; static int dag_setfilter(pcap_t *p, struct bpf_program *fp); static int dag_stats(pcap_t *p, struct pcap_stat *ps); static int dag_set_datalink(pcap_t *p, int dlt); static int dag_get_datalink(pcap_t *p); static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf); static void delete_pcap_dag(pcap_t *p) { pcap_dag_node_t *curr = NULL, *prev = NULL; for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) { /* empty */ } if (curr != NULL && curr->p == p) { if (prev != NULL) { prev->next = curr->next; } else { pcap_dags = curr->next; } } } /* * Performs a graceful shutdown of the DAG card, frees dynamic memory held * in the pcap_t structure, and closes the file descriptor for the DAG card. */ static void dag_platform_close(pcap_t *p) { if (p != NULL) { #ifdef HAVE_DAG_STREAMS_API if(dag_stop_stream(p->fd, p->md.dag_stream) < 0) fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); if(dag_detach_stream(p->fd, p->md.dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else if(dag_stop(p->fd) < 0) fprintf(stderr,"dag_stop: %s\n", strerror(errno)); #endif /* HAVE_DAG_STREAMS_API */ if(dag_close(p->fd) < 0) fprintf(stderr,"dag_close: %s\n", strerror(errno)); } delete_pcap_dag(p); /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */ } static void atexit_handler(void) { while (pcap_dags != NULL) { if (pcap_dags->pid == getpid()) { dag_platform_close(pcap_dags->p); } else { delete_pcap_dag(pcap_dags->p); } } } static int new_pcap_dag(pcap_t *p) { pcap_dag_node_t *node = NULL; if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) { return -1; } if (!atexit_handler_installed) { atexit(atexit_handler); atexit_handler_installed = 1; } node->next = pcap_dags; node->p = p; node->pid = getpid(); pcap_dags = node; return 0; } /* * Read at most max_packets from the capture stream and call the callback * for each of them. Returns the number of packets handled, -1 if an * error occured, or -2 if we were told to break out of the loop. */ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { unsigned int processed = 0; int flags = p->md.dag_offset_flags; unsigned int nonblocking = flags & DAGF_NONBLOCK; /* Get the next bufferful of packets (if necessary). */ while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } #ifdef HAVE_DAG_STREAMS_API /* dag_advance_stream() will block (unless nonblock is called) * until 64kB of data has accumulated. * If to_ms is set, it will timeout before 64kB has accumulated. * We wait for 64kB because processing a few packets at a time * can cause problems at high packet rates (>200kpps) due * to inefficiencies. * This does mean if to_ms is not specified the capture may 'hang' * for long periods if the data rate is extremely slow (<64kB/sec) * If non-block is specified it will return immediately. The user * is then responsible for efficiency. */ p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom)); #else /* dag_offset does not support timeouts */ p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags); #endif /* HAVE_DAG_STREAMS_API */ if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) { /* Pcap is configured to process only available packets, and there aren't any, return immediately. */ return 0; } if(!nonblocking && p->md.dag_timeout && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) { /* Blocking mode, but timeout set and no data has arrived, return anyway.*/ return 0; } } /* Process the packets. */ while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) { unsigned short packet_len = 0; int caplen = 0; struct pcap_pkthdr pcap_header; #ifdef HAVE_DAG_STREAMS_API dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom); #else dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom); #endif /* HAVE_DAG_STREAMS_API */ u_char *dp = ((u_char *)header) + dag_record_size; unsigned short rlen; /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } rlen = ntohs(header->rlen); if (rlen < dag_record_size) { strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE); return -1; } p->md.dag_mem_bottom += rlen; switch(header->type) { case TYPE_ATM: #ifdef TYPE_AAL5 case TYPE_AAL5: if (header->type == TYPE_AAL5) { packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size; } #endif #ifdef TYPE_MC_ATM case TYPE_MC_ATM: if (header->type == TYPE_MC_ATM) { caplen = packet_len = ATM_CELL_SIZE; dp+=4; } #endif #ifdef TYPE_MC_AAL5 case TYPE_MC_AAL5: if (header->type == TYPE_MC_AAL5) { packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size - 4; dp+=4; } #endif if (header->type == TYPE_ATM) { caplen = packet_len = ATM_CELL_SIZE; } if (p->linktype == DLT_SUNATM) { struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp; unsigned long rawatm; rawatm = ntohl(*((unsigned long *)dp)); sunatm->vci = htons((rawatm >> 4) & 0xffff); sunatm->vpi = (rawatm >> 20) & 0x00ff; sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 : ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : ((dp[ATM_HDR_SIZE] == 0xaa && dp[ATM_HDR_SIZE+1] == 0xaa && dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1))); } else { packet_len -= ATM_HDR_SIZE; caplen -= ATM_HDR_SIZE; dp += ATM_HDR_SIZE; } break; #ifdef TYPE_DSM_COLOR_ETH case TYPE_DSM_COLOR_ETH: #endif #ifdef TYPE_COLOR_ETH case TYPE_COLOR_ETH: #endif case TYPE_ETH: packet_len = ntohs(header->wlen); packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 2; if (caplen > packet_len) { caplen = packet_len; } dp += 2; break; #ifdef TYPE_DSM_COLOR_HDLC_POS case TYPE_DSM_COLOR_HDLC_POS: #endif #ifdef TYPE_COLOR_HDLC_POS case TYPE_COLOR_HDLC_POS: #endif case TYPE_HDLC_POS: packet_len = ntohs(header->wlen); packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size; if (caplen > packet_len) { caplen = packet_len; } break; #ifdef TYPE_COLOR_MC_HDLC_POS case TYPE_COLOR_MC_HDLC_POS: #endif #ifdef TYPE_MC_HDLC case TYPE_MC_HDLC: packet_len = ntohs(header->wlen); packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 4; if (caplen > packet_len) { caplen = packet_len; } /* jump the MC_HDLC_HEADER */ dp += 4; if (p->linktype == DLT_MTP2_WITH_PHDR) { /* Add the MTP2 Pseudo Header */ caplen += MTP2_HDR_LEN; packet_len += MTP2_HDR_LEN; TempPkt[MTP2_SENT_OFFSET] = 0; TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN; *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01); *(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff); memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen); dp = TempPkt; } break; #endif default: /* Unhandled ERF type. * Ignore rather than generating error */ continue; } if (caplen > p->snapshot) caplen = p->snapshot; /* Count lost packets. */ switch(header->type) { #ifdef TYPE_COLOR_HDLC_POS /* in this type the color value overwrites the lctr */ case TYPE_COLOR_HDLC_POS: break; #endif #ifdef TYPE_COLOR_ETH /* in this type the color value overwrites the lctr */ case TYPE_COLOR_ETH: break; #endif #ifdef TYPE_DSM_COLOR_HDLC_POS /* in this type the color value overwrites the lctr */ case TYPE_DSM_COLOR_HDLC_POS: break; #endif #ifdef TYPE_DSM_COLOR_ETH /* in this type the color value overwrites the lctr */ case TYPE_DSM_COLOR_ETH: break; #endif #ifdef TYPE_COLOR_MC_HDLC_POS case TYPE_COLOR_MC_HDLC_POS: break; #endif default: if (header->lctr) { if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) { p->md.stat.ps_drop = UINT_MAX; } else { p->md.stat.ps_drop += ntohs(header->lctr); } } } /* Run the packet filter if there is one. */ if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { /* convert between timestamp formats */ register unsigned long long ts; if (IS_BIGENDIAN()) { ts = SWAPLL(header->ts); } else { ts = header->ts; } pcap_header.ts.tv_sec = ts >> 32; ts = (ts & 0xffffffffULL) * 1000000; ts += 0x80000000; /* rounding */ pcap_header.ts.tv_usec = ts >> 32; if (pcap_header.ts.tv_usec >= 1000000) { pcap_header.ts.tv_usec -= 1000000; pcap_header.ts.tv_sec++; } /* Fill in our own header data */ pcap_header.caplen = caplen; pcap_header.len = packet_len; /* Count the packet. */ p->md.stat.ps_recv++; /* Call the user supplied callback function */ callback(user, &pcap_header, dp); /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */ processed++; if (processed == cnt) { /* Reached the user-specified limit. */ return cnt; } } } return processed; } static int dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_) { strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards", PCAP_ERRBUF_SIZE); return (-1); } /* * Get a handle for a live capture from the given DAG device. Passing a NULL * device will result in a failure. The promisc flag is ignored because DAG * cards are always promiscuous. The to_ms parameter is also ignored as it is * not supported in hardware. * * snaplen is now also ignored, until we get per-stream slen support. Set * slen with approprite DAG tool BEFORE pcap_open_live(). * * See also pcap(3). */ pcap_t * dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { char conf[30]; /* dag configure string */ pcap_t *handle; char *s; int n; daginf_t* daginf; char * newDev = NULL; #ifdef HAVE_DAG_STREAMS_API uint32_t mindata; struct timeval maxwait; struct timeval poll; #endif if (device == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno)); return NULL; } /* Allocate a handle for this session. */ handle = malloc(sizeof(*handle)); if (handle == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno)); return NULL; } /* Initialize some components of the pcap structure. */ memset(handle, 0, sizeof(*handle)); #ifdef HAVE_DAG_STREAMS_API newDev = (char *)malloc(strlen(device) + 16); if (newDev == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno)); goto fail; } /* Parse input name to get dag device and stream number if provided */ if (dag_parse_name(device, newDev, strlen(device) + 16, &handle->md.dag_stream) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno)); goto fail; } device = newDev; if (handle->md.dag_stream%2) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n"); goto fail; } #else if (strncmp(device, "/dev/", 5) != 0) { newDev = (char *)malloc(strlen(device) + 5); if (newDev == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno)); goto fail; } strcpy(newDev, "/dev/"); strcat(newDev, device); device = newDev; } #endif /* HAVE_DAG_STREAMS_API */ /* setup device parameters */ if((handle->fd = dag_open((char *)device)) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno)); goto fail; } #ifdef HAVE_DAG_STREAMS_API /* Open requested stream. Can fail if already locked or on error */ if (dag_attach_stream(handle->fd, handle->md.dag_stream, 0, 0) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno)); goto failclose; } /* Set up default poll parameters for stream * Can be overridden by pcap_set_nonblock() */ if (dag_get_stream_poll(handle->fd, handle->md.dag_stream, &mindata, &maxwait, &poll) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } /* Amount of data to collect in Bytes before calling callbacks. * Important for efficiency, but can introduce latency * at low packet rates if to_ms not set! */ mindata = 65536; /* Obey to_ms if supplied. This is a good idea! * Recommend 10-100ms. Calls will time out even if no data arrived. */ maxwait.tv_sec = to_ms/1000; maxwait.tv_usec = (to_ms%1000) * 1000; if (dag_set_stream_poll(handle->fd, handle->md.dag_stream, mindata, &maxwait, &poll) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } #else if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); goto failclose; } #endif /* HAVE_DAG_STREAMS_API */ /* XXX Not calling dag_configure() to set slen; this is unsafe in * multi-stream environments as the gpp config is global. * Once the firmware provides 'per-stream slen' this can be supported * again via the Config API without side-effects */ #if 0 /* set the card snap length to the specified snaplen parameter */ /* This is a really bad idea, as different cards have different * valid slen ranges. Should fix in Config API. */ if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) { snaplen = MAX_DAG_SNAPLEN; } else if (snaplen < MIN_DAG_SNAPLEN) { snaplen = MIN_DAG_SNAPLEN; } /* snap len has to be a multiple of 4 */ snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3); if(dag_configure(handle->fd, conf) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno)); goto faildetach; } #endif #ifdef HAVE_DAG_STREAMS_API if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno)); goto faildetach; } #else if(dag_start(handle->fd) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno)); goto failclose; } #endif /* HAVE_DAG_STREAMS_API */ /* * Important! You have to ensure bottom is properly * initialized to zero on startup, it won't give you * a compiler warning if you make this mistake! */ handle->md.dag_mem_bottom = 0; handle->md.dag_mem_top = 0; handle->md.dag_fcs_bits = 32; /* Query the card first for special cases. */ daginf = dag_info(handle->fd); if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) { /* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */ handle->md.dag_fcs_bits = 0; } /* Then allow an environment variable to override. */ if ((s = getenv("ERF_FCS_BITS")) != NULL) { if ((n = atoi(s)) == 0 || n == 16|| n == 32) { handle->md.dag_fcs_bits = n; } else { snprintf(ebuf, PCAP_ERRBUF_SIZE, "pcap_open_live %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n); goto failstop; } } handle->snapshot = snaplen; handle->md.dag_timeout = to_ms; handle->linktype = -1; if (dag_get_datalink(handle) < 0) { strcpy(ebuf, handle->errbuf); goto failstop; } handle->bufsize = 0; if (new_pcap_dag(handle) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno)); goto failstop; } /* * "select()" and "poll()" don't work on DAG device descriptors. */ handle->selectable_fd = -1; if (newDev != NULL) { free((char *)newDev); } handle->read_op = dag_read; handle->inject_op = dag_inject; handle->setfilter_op = dag_setfilter; handle->setdirection_op = NULL; /* Not implemented.*/ handle->set_datalink_op = dag_set_datalink; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = dag_setnonblock; handle->stats_op = dag_stats; handle->close_op = dag_platform_close; handle->md.stat.ps_drop = 0; handle->md.stat.ps_recv = 0; return handle; #ifdef HAVE_DAG_STREAMS_API failstop: if (handle != NULL) { if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0) fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); } faildetach: if (handle != NULL) { if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); } #else failstop: if (handle != NULL) { if (dag_stop(p->fd) < 0) fprintf(stderr,"dag_stop: %s\n", strerror(errno)); } #endif /* HAVE_DAG_STREAMS_API */ failclose: if (handle != NULL) { if (dag_close(handle->fd) < 0) fprintf(stderr,"dag_close: %s\n", strerror(errno)); } if (handle != NULL) delete_pcap_dag(handle); fail: if (newDev != NULL) { free((char *)newDev); } if (handle != NULL) { /* * Get rid of any link-layer type list we allocated. */ if (handle->dlt_list != NULL) { free(handle->dlt_list); } free(handle); } return NULL; } static int dag_stats(pcap_t *p, struct pcap_stat *ps) { /* This needs to be filled out correctly. Hopefully a dagapi call will provide all necessary information. */ /*p->md.stat.ps_recv = 0;*/ /*p->md.stat.ps_drop = 0;*/ *ps = p->md.stat; return 0; } /* * Simply submit all possible dag names as candidates. * pcap_add_if() internally tests each candidate with pcap_open_live(), * so any non-existent devices are dropped. * For 2.5 try all rx stream names as well. */ int dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf) { char name[12]; /* XXX - pick a size */ int ret = 0; int c; /* Try all the DAGs 0-9 */ for (c = 0; c < 9; c++) { snprintf(name, 12, "dag%d", c); if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { /* * Failure. */ ret = -1; } #ifdef HAVE_DAG_STREAMS_API { int stream; for(stream=0;stream<16;stream+=2) { snprintf(name, 10, "dag%d:%d", c, stream); if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { /* * Failure. */ ret = -1; } } } #endif /* HAVE_DAG_STREAMS_API */ } return (ret); } /* * Installs the given bpf filter program in the given pcap structure. There is * no attempt to store the filter in kernel memory as that is not supported * with DAG cards. */ static int dag_setfilter(pcap_t *p, struct bpf_program *fp) { if (!p) return -1; if (!fp) { strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf)); return -1; } /* Make our private copy of the filter */ if (install_bpf_program(p, fp) < 0) return -1; p->md.use_bpf = 0; return (0); } static int dag_set_datalink(pcap_t *p, int dlt) { p->linktype = dlt; return (0); } static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) { /* * Set non-blocking mode on the FD. * XXX - is that necessary? If not, don't bother calling it, * and have a "dag_getnonblock()" function that looks at * "p->md.dag_offset_flags". */ if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0) return (-1); #ifdef HAVE_DAG_STREAMS_API { uint32_t mindata; struct timeval maxwait; struct timeval poll; if (dag_get_stream_poll(p->fd, p->md.dag_stream, &mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); return -1; } /* Amount of data to collect in Bytes before calling callbacks. * Important for efficiency, but can introduce latency * at low packet rates if to_ms not set! */ if(nonblock) mindata = 0; else mindata = 65536; if (dag_set_stream_poll(p->fd, p->md.dag_stream, mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); return -1; } } #endif /* HAVE_DAG_STREAMS_API */ if (nonblock) { p->md.dag_offset_flags |= DAGF_NONBLOCK; } else { p->md.dag_offset_flags &= ~DAGF_NONBLOCK; } return (0); } static int dag_get_datalink(pcap_t *p) { int index=0; uint8_t types[255]; memset(types, 0, 255); if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) { (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (-1); } p->linktype = 0; #ifdef HAVE_DAG_GET_ERF_TYPES /* Get list of possible ERF types for this card */ if (dag_get_erf_types(p->fd, types, 255) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno)); return (-1); } while (types[index]) { #else /* Check the type through a dagapi call. */ types[index] = dag_linktype(p->fd); { #endif switch(types[index]) { case TYPE_HDLC_POS: #ifdef TYPE_COLOR_HDLC_POS case TYPE_COLOR_HDLC_POS: #endif #ifdef TYPE_DSM_COLOR_HDLC_POS case TYPE_DSM_COLOR_HDLC_POS: #endif if (p->dlt_list != NULL) { p->dlt_list[index++] = DLT_CHDLC; p->dlt_list[index++] = DLT_PPP_SERIAL; p->dlt_list[index++] = DLT_FRELAY; } if(!p->linktype) p->linktype = DLT_CHDLC; break; case TYPE_ETH: #ifdef TYPE_COLOR_ETH case TYPE_COLOR_ETH: #endif #ifdef TYPE_DSM_COLOR_ETH case TYPE_DSM_COLOR_ETH: #endif /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ if (p->dlt_list != NULL) { p->dlt_list[index++] = DLT_EN10MB; p->dlt_list[index++] = DLT_DOCSIS; } if(!p->linktype) p->linktype = DLT_EN10MB; break; case TYPE_ATM: #ifdef TYPE_AAL5 case TYPE_AAL5: #endif #ifdef TYPE_MC_ATM case TYPE_MC_ATM: #endif #ifdef TYPE_MC_AAL5 case TYPE_MC_AAL5: #endif if (p->dlt_list != NULL) { p->dlt_list[index++] = DLT_ATM_RFC1483; p->dlt_list[index++] = DLT_SUNATM; } if(!p->linktype) p->linktype = DLT_ATM_RFC1483; break; #ifdef TYPE_COLOR_MC_HDLC_POS case TYPE_COLOR_MC_HDLC_POS: #endif #ifdef TYPE_MC_HDLC case TYPE_MC_HDLC: if (p->dlt_list != NULL) { p->dlt_list[index++] = DLT_CHDLC; p->dlt_list[index++] = DLT_PPP_SERIAL; p->dlt_list[index++] = DLT_FRELAY; p->dlt_list[index++] = DLT_MTP2; p->dlt_list[index++] = DLT_MTP2_WITH_PHDR; } if(!p->linktype) p->linktype = DLT_CHDLC; break; #endif case TYPE_LEGACY: if(!p->linktype) p->linktype = DLT_NULL; break; default: snprintf(p->errbuf, sizeof(p->errbuf), "unknown DAG linktype %d", types[index]); return (-1); } /* switch */ } p->dlt_count = index; return p->linktype; } libpcap-0.9.7/./net0000777000026300017500000000000010651263465013553 2./bpf/netustar mcrmcrlibpcap-0.9.7/./CHANGES0000644000026300017500000004271310651261624012425 0ustar mcrmcr@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.59.2.11 2007/07/24 02:27:32 mcr Exp $ (LBL) Wed. July 23, 2007. mcr@xelerance.com. Summary for 0.9.7 libpcap release FIXED version file to be 0.9.7 instead of 0.9.5. added flags/configuration for cloning bpf device. added DLT_MTP2_WITH_PHDR support (PPI) "fix" the "memory leak" in icode_to_fcode() -- documentation bug Various link-layer types, with a pseudo-header, for SITA http://www.sita.aero/ introduces support for the DAG ERF type TYPE_COLOR_MC_HDLC_POS. Basic BPF filtering support for DLT_MTP2_WITH_PHDR is also added. check for IPv4 and IPv6, even for DLT_RAW add support for DLT_JUNIPER_ISM Pick up changes from NetBSD: many from tron, christos, drochner Allocate DLT_ for 802.15.4 without any header munging, for Mikko Saarnivala. Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header Wed. April 25, 2007. ken@xelerance.com. Summary for 0.9.6 libpcap release Put the public libpcap headers into a pcap subdirectory in both the source directory and the target include directory, and have include files at the top-level directory to include those headers, for backwards compatibility. Add Bluetooth support Add USB capturing support on Linux Add support for the binary USB sniffing interface in Linux Add support for new FreeBSD BIOCSDIRECTION ioctl Add additional filter operations for 802.11 frame types Add support for filtering on MTP2 frame types Propagate some changes from the main branch, so the x.9 branch has all the DLT_ and LINKTYPE_ values that the main branch does Reserved a DLT_ and SAVEFILE_ value for PPI (Per Packet Info) encapsulated packets Add LINKTYPE_ for IEEE 802.15.4, with address fields padded as done by Linux drivers Add LINKTYPE_ value corresponding to DLT_IEEE802_16_MAC_CPS. Add DLT for IEEE 802.16 (WiMAX) MAC Common Part Sublayer Add DLT for Bluetooth HCI UART transport layer When building a shared library, build with "-fPIC" on Linux to support x86_64 Link with "$(CC) -shared" rather than "ld -shared" when building a ".so" shared library Add support for autoconf 2.60 Fixes to discard unread packets when changing filters Changes to handle name changes in the DAG library resulting from switching to libtool. Add support for new DAG ERF types. Add an explicit "-ldag" when building the shared library, so the DAG library dependency is explicit. Mac OSX fixes for dealing with "wlt" devices Fixes in add_or_find_if() & pcap_findalldevs() to optimize generating device lists Fixed a bug in pcap_open_live(). The return value of PacketSetHwFilter was not checked. Tue. September 19, 2006. ken@xelerance.com. Summary for 0.9.5 libpcap release Support for LAPD frames with vISDN Support for ERF on channelized T1/E1 cards via DAG API Fix capitalization that caused issues crossc compiling on Linux Better failure detection on PacketGetAdapterNames() Fixes for MPLS packet generation (link layer) OP_PACKET now matches the beginning of the packet, instead of beginning+link-layer Add DLT/LINKTYPE for carrying FRF.16 Multi-link Frame Relay Fix allocation of buffer for list of link-layer types Added a new DLT and LINKTYPE value for ARINC 653 Interpartition Communcation Messages Fixed a typo in a DLT value: it should start with DLT_ and not LINKTYPE_ Redefined DLT_CAN20B and LINKTYPE_CAN20B as #190 (as this is the right value for CAN). Added definition for DLT_A429 and LINKTYPE_A429 as #184. Added a new DLT and LINKTYPE value for CAN v2.0B frames. Add support for DLT_JUNIPER_VP. Don't double-count received packets on Linux systems that support the PACKET_STATISTICS getsockopt() argument on PF_PACKET sockets. Add support for DLT_IEEE802_11 and DLT_IEEE802_11_RADIO link layers in Windows Add support to build libpcap.lib and wpcap.dll under Cygnus and MingW32. Mon. September 5, 2005. ken@xelerance.com. Summary for 0.9.4 libpcap release Support for radiotap on Linux (Mike Kershaw) Fixes for HP-UX Support for additional Juniper link-layer types Fixes for filters on MPLS-encapsulated packets "vlan" filter fixed "pppoed" and "pppoes" filters added; the latter modifies later parts of the filter expression to look at the PPP headers and headers in the PPP payload Tue. July 5, 2005. ken@xelerance.com. Summary for 0.9.3 libpcap release Fixes for compiling on nearly every platform, including improved 64bit support MSDOS Support Add support for sending packets OpenBSD pf format support IrDA capture (Linux only) Tue. March 30, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.3 release Fixed minor problem in gencode.c that would appear on 64-bit platforms. Version number is now sane. Mon. March 29, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.2 release updates for autoconf 2.5 fixes for ppp interfaces for freebsd 4.1 pcap gencode can generate code for 802.11, IEEE1394, and pflog. Wed. November 12, 2003. mcr@sandelman.ottawa.on.ca. Summary for 0.8 release added pcap_findalldevs() Win32 patches from NetGroup, Politecnico di Torino (Italy) OpenBSD pf, DLT_PFLOG added Many changes to ATM support. lookup pcap_lookupnet() Added DLT_ARCNET_LINUX, DLT_ENC, DLT_IEEE802_11_RADIO, DLT_SUNATM, DLT_IP_OVER_FC, DLT_FRELAY, others. Sigh. More AIX wonderfulness. Document updates. Changes to API: pcap_next_ex(), pcap_breakloop(), pcap_dump_flush(), pcap_list_datalinks(), pcap_set_datalink(), pcap_lib_version(), pcap_datalink_val_to_name(), pcap_datalink_name_to_val(), new error returns. Tuesday, February 25, 2003. fenner@research.att.com. 0.7.2 release Support link types that use 802.2 always, never, and sometimes. Don't decrease the size of the BPF buffer from the default. Support frame relay. Handle 32-bit timestamps in DLPI, and pass the right buffer size. Handle Linux systems with modern kernel but without SOL_PACKET in the userland headers. Linux support for ARPHRD_RAWHDLC. Handle 32-bit timestamps in snoop. Support eg (Octane/O2xxx/O3xxx Gigabit) devices. Add new reserved DLT types. Monday October 23, 2001. mcr@sandelman.ottawa.on.ca. Summary for 0.7 release Added pcap_findalldevs() call to get list of interfaces in a MI way. pcap_stats() has been documented as to what its counters mean on each platform. Tuesday January 9, 2001. guy@alum.mit.edu. Summary for 0.6 release New Linux libpcap implementation, which, in 2.2 and later kernels, uses PF_PACKET sockets and supports kernel packet filtering (if compiled into the kernel), and supports the "any" device for capturing on all interfaces. Cleans up promiscuous mode better on pre-2.2 kernels, and has various other fixes (handles 2.4 ARPHRD_IEEE802_TR, handles ISDN devices better, doesn't show duplicate packets on loopback interface, etc.). Fixed HP-UX libpcap implementation to correctly get the PPA for an interface, to allow interfaces to be opened by interface name. libpcap savefiles have system-independent link-layer type values in the header, rather than sometimes platform-dependent DLT_ values, to make it easier to exchange capture files between different OSes. Non-standard capture files produced by some Linux tcpdumps, e.g. the one from Red Hat Linux 6.2 and later, can now be read. Updated autoconf stock files. Filter expressions can filter on VLAN IDs and various OSI protocols, and work on Token Ring (with non-source-routed packets). "pcap_open_dead()" added to allow compiling filter expressions to pcap code without opening a capture device or capture file. Header files fixed to allow use in C++ programs. Removed dependancy on native headers for packet layout. Removed Linux specific headers that were shipped. Security fixes: Strcpy replaced with strlcpy, sprintf replaced with snprintf. Fixed bug that could cause subsequent "pcap_compile()"s to fail erroneously after one compile failed. Assorted other bug fixes. README.aix and README.linux files added to describe platform-specific issues. "getifaddrs()" rather than SIOCGIFCONF used, if available. v0.5 Sat Jun 10 11:09:15 PDT 2000 itojun@iijlab.net - Brought in KAME IPv6/IPsec bpf compiler. - Fixes for NetBSD. - Support added for OpenBSD DLT_LOOP and BSD/OS DLT_C_HDLC (Cisco HDLC), and changes to work around different BSDs having different DLT_ types with the same numeric value. Assar Westerlund - Building outside the source code tree fixed. - Changed to write out time stamps with 32-bit seconds and microseconds fields, regardless of whether those fields are 32 bits or 64 bits in the OS's native "struct timeval". - Changed "pcap_lookupdev()" to dynamically grow the buffer into which the list of interfaces is read as necessary in order to hold the entire list. Greg Troxel - Added a new "pcap_compile_nopcap()", which lets you compile a filter expression into a BPF program without having an open live capture or capture file. v0.4 Sat Jul 25 12:40:09 PDT 1998 - Fix endian problem with DLT_NULL devices. From FreeBSD via Bill Fenner (fenner@parc.xerox.com) - Fix alignment problem with FDDI under DLPI. This was causing core dumps under Solaris. - Added configure options to disable flex and bison. Resulted from a bug report by barnett@grymoire.crd.ge.com (Bruce Barnett). Also added options to disable gcc and to force a particular packet capture type. - Added support for Fore ATM interfaces (qaa and fa) under IRIX. Thanks to John Hawkinson (jhawk@mit.edu) - Change Linux PPP and SLIP to use DLT_RAW since the kernel does not supply any "link layer" data. - Change Linux to use SIOCGIFHWADDR ioctl to determine link layer type. Thanks to Thomas Sailer (sailer@ife.ee.ethz.ch) - Change IRIX PPP to use DLT_RAW since the kernel does not supply any "link layer" data. - Modified to support the new BSD/OS 2.1 PPP and SLIP link layer header formats. - Added some new SGI snoop interface types. Thanks to Steve Alexander (sca@refugee.engr.sgi.com) - Fixes for HP-UX 10.20 (which is similar to HP-UX 9). Thanks to Richard Allen (ra@hp.is) and Steinar Haug (sthaug@nethelp.no) - Fddi supports broadcast as reported by Jeff Macdonald (jeff@iacnet.com). Also correct ieee802 and arcnet. - Determine Linux pcap buffer size at run time or else it might not be big enough for some interface types (e.g. FDDI). Thanks to Jes Sorensen (Jes.Sorensen@cern.ch) - Fix some linux alignment problems. - Document promisc argument to pcap_open_live(). Reported by Ian Marsh (ianm@sics.se) - Support Metricom radio packets under Linux. Thanks to Kevin Lai (laik@gunpowder.stanford.edu) - Bind to interface name under Linux to avoid packets from multiple interfaces on multi-homed hosts. Thanks to Kevin Lai (laik@gunpowder.stanford.edu) - Change L_SET to SEEK_SET for HP-UX. Thanks to Roland Roberts (rroberts@muller.com) - Fixed an uninitialized memory reference found by Kent Vander Velden (graphix@iastate.edu) - Fixed lex pattern for IDs to allow leading digits. As reported by Theo de Raadt (deraadt@cvs.openbsd.org) - Fixed Linux include file problems when using GNU libc. - Ifdef ARPHRD_FDDI since not all versions of the Linux kernel have it. Reported reported by Eric Jacksch (jacksch@tenebris.ca) - Fixed bug in pcap_dispatch() that kept it from returning on packet timeouts. - Changed ISLOOPBACK() macro when IFF_LOOPBACK isn't available to check for "lo" followed by an eos or digit (newer versions of Linux apparently call the loopback "lo" instead of "lo0"). - Fixed Linux networking include files to use ints instead of longs to avoid problems with 64 bit longs on the alpha. Thanks to Cristian Gafton (gafton@redhat.com) v0.3 Sat Nov 30 20:56:27 PST 1996 - Added Linux support. - Fixed savefile bugs. - Solaris x86 fix from Tim Rylance (t.rylance@elsevier.nl) - Add support for bpf kernel port filters. - Remove duplicate atalk protocol table entry. Thanks to Christian Hopps (chopps@water.emich.edu) - Fixed pcap_lookupdev() to ignore nonexistent devices. This was reported to happen under BSD/OS by David Vincenzetti (vince@cryptonet.it) - Avoid solaris compiler warnings. Thanks to Bruce Barnett (barnett@grymoire.crd.ge.com) v0.2.1 Sun Jul 14 03:02:26 PDT 1996 - Fixes for HP-UX 10. Thanks in part to to Thomas Wolfram (wolf@prz.tu-berlin.de) and Rick Jones (raj@hpisrdq.cup.hp.com) - Added support for SINIX. Thanks to Andrej Borsenkow (borsenkow.msk@sni.de) - Fixes for AIX (although this system is not yet supported). Thanks to John Hawkinson (jhawk@mit.edu) - Use autoconf's idea of the top level directory in install targets. Thanks to John Hawkinson. - Add missing autoconf packet capture result message. Thanks to Bill Fenner (fenner@parc.xerox.com) - Fixed padding problems in the pf module. - Fixed some more alignment problems on the alpha. - Added explicit netmask support. Thanks to Steve Nuchia (steve@research.oknet.com) - Fixed to handle raw ip addresses such as 0.0.0.1 without "left justifing" - Add "sca" keyword (for DEC cluster services) as suggested by Terry Kennedy (terry@spcvxa.spc.edu) - Add "atalk" keyword as suggested by John Hawkinson. - Add "igrp" keyword. - Fixed HID definition in grammar.y to be a string, not a value. - Use $CC when checking gcc version. Thanks to Carl Lindberg (carl_lindberg@blacksmith.com) - Removed obsolete reference to pcap_immediate() from the man page. Michael Stolarchuk (mts@terminator.rs.itd.umich.edu) - DLT_NULL has a 4 byte family header. Thanks to Jeffrey Honig (jch@bsdi.com) v0.2 Sun Jun 23 02:28:42 PDT 1996 - Add support for HP-UX. Resulted from code contributed by Tom Murray (tmurray@hpindck.cup.hp.com) and Philippe-Andri Prindeville (philipp@res.enst.fr) - Update INSTALL with a reminder to install include files. Thanks to Mark Andrews (mandrews@aw.sgi.com) - Fix bpf compiler alignment bug on the alpha. - Use autoconf to detect architectures that can't handle misaligned accesses. - Added loopback support for snoop. Resulted from report Steve Alexander (sca@engr.sgi.com) v0.1 Fri Apr 28 18:11:03 PDT 1995 - Fixed compiler and optimizer bugs. The BPF filter engine uses unsigned comparison operators, while the code generator and optimizer assumed signed semantics in several places. Thanks to Charlie Slater (cslater@imatek.com) for pointing this out. - Removed FDDI ifdef's, they aren't really needed. Resulted from report by Gary Veum (veum@boa.gsfc.nasa.gov). - Add pcap-null.c which allows offline use of libpcap on systems that don't support live package capture. This feature resulting from a request from Jan van Oorschot (j.p.m.voorschot@et.tudelft.nl). - Make bpf_compile() reentrant. Fix thanks to Pascal Hennequin (Pascal.Hennequin@hugo.int-evry.fr). - Port to GNU autoconf. - Fix pcap-dlpi.c to work with isdn. Resulted from report by Flemming Johansen (fsj@csd.cri.dk). - Handle multi-digit interface unit numbers (aka ppa's) under dlpi. Resulted from report by Daniel Ehrlich (ehrlich@cse.psu.edu). - Fix pcap-dlpi.c to work in non-promiscuous mode. Resulted from report by Jeff Murphy (jcmurphy@acsu.buffalo.edu). - Add support for "long jumps". Thanks to Jeffrey Mogul (mogul@pa.dec.com). - Fix minor problems when compiling with BDEBUG as noticed by Scott Bertilson (scott@unet.umn.edu). - Declare sys_errlist "const char *const" to avoid problems under FreeBSD. Resulted from report by jher@eden.com. v0.0.6 Fri Apr 28 04:07:13 PDT 1995 - Add missing variable declaration missing from 0.0.6 v0.0.5 Fri Apr 28 00:22:21 PDT 1995 - Workaround for problems when pcap_read() returns 0 due to the timeout expiring. v0.0.4 Thu Apr 20 20:41:48 PDT 1995 - Change configuration to not use gcc v2 flags with gcc v1. - Fixed a bug in pcap_next(); if pcap_dispatch() returns 0, pcap_next() should also return 0. Thanks to Richard Stevens (rstevens@noao.edu). - Fixed configure to test for snoop before dlpi to avoid problems under IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com). - Hack around deficiency in Ultrix's make. - Fix two bugs related to the Solaris pre-5.3.2 bufmod bug; handle savefiles that have more than snapshot bytes of data in them (so we can read old savefiles) and avoid writing such files. - Added checkioctl which is used with gcc to check that the "fixincludes" script has been run. v0.0.3 Tue Oct 18 18:13:46 PDT 1994 - Fixed configure to test for snoop before dlpi to avoid problems under IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com). v0.0.2 Wed Oct 12 20:56:37 PDT 1994 - Implement timeout in the dlpi pcap_open_live(). Thanks to Richard Stevens. - Determine pcap link type from dlpi media type. Resulted from report by Mahesh Jethanandani (mahesh@npix.com). v0.0.1 Fri Jun 24 14:50:57 PDT 1994 - Fixed bug in nit_setflags() in pcap-snit.c. The streams ioctl timeout wasn't being initialized sometimes resulting in an "NIOCSFLAGS: Invalid argument" error under OSF/1. Reported by Matt Day (mday@artisoft.com) and Danny Mitzel (dmitzel@whitney.hitc.com). - Turn on FDDI support by default. v0.0 Mon Jun 20 19:20:16 PDT 1994 - Initial release. - Fixed bug with greater/less keywords, reported by Mark Andrews (mandrews@alias.com). - Fix bug where '|' was defined as BPF_AND instead of BPF_OR, reported by Elan Amir (elan@leeb.cs.berkeley.edu). - Machines with little-endian byte ordering are supported thanks to Jeff Mogul. - Add hack for version 2.3 savefiles which don't have caplen and len swapped thanks to Vern Paxson. - Added "&&" and "||" aliases for "and" and "or" thanks to Vern Paxson. - Added length, inbound and outbound keywords. libpcap-0.9.7/./Makefile.in0000644000026300017500000001631410651262543013476 0ustar mcrmcr# Copyright (c) 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: /tcpdump/master/libpcap/Makefile.in,v 1.99.2.2 2007/07/24 02:35:15 mcr Exp $ (LBL) # # Various configurable paths (remember to edit Makefile.in, not Makefile) # # Top level hierarchy prefix = @prefix@ exec_prefix = @exec_prefix@ # Pathname of directory to install the include files includedir = @includedir@ # Pathname of directory to install the library libdir = @libdir@ # Pathname of directory to install the man page mandir = @mandir@ # VPATH srcdir = @srcdir@ VPATH = @srcdir@ # # You shouldn't need to edit anything below. # CC = @CC@ CCOPT = @V_CCOPT@ INCLS = -I. @V_INCLS@ DEFS = @DEFS@ @V_DEFS@ LIBS = @V_LIBS@ DAGLIBS = @DAGLIBS@ DYEXT = @DYEXT@ PROG=libpcap # Standard CFLAGS CFLAGS = $(CCOPT) $(INCLS) $(DEFS) INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ RANLIB = @RANLIB@ # # Flex and bison allow you to specify the prefixes of the global symbols # used by the generated parser. This allows programs to use lex/yacc # and link against libpcap. If you don't have flex or bison, get them. # LEX = @V_LEX@ YACC = @V_YACC@ # Explicitly define compilation rule since SunOS 4's make doesn't like gcc. # Also, gcc does not remove the .o before forking 'as', which can be a # problem if you don't own the file but can write to the directory. .c.o: @rm -f $@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c PSRC = pcap-@V_PCAP@.c FSRC = fad-@V_FINDALLDEVS@.c SSRC = @SSRC@ CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \ etherent.c savefile.c bpf_filter.c bpf_image.c bpf_dump.c GENSRC = scanner.c grammar.c version.c LIBOBJS = @LIBOBJS@ SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC) # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS) HDR = pcap.h pcap-int.h pcap-namedb.h pcap-nit.h pcap-pf.h \ ethertype.h gencode.h gnuc.h GENHDR = \ tokdefs.h version.h TAGHDR = \ pcap-bpf.h TAGFILES = \ $(SRC) $(HDR) $(TAGHDR) CLEANFILES = $(OBJ) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c all: libpcap.a libpcap.a: $(OBJ) @rm -f $@ ar rc $@ $(OBJ) $(LIBS) $(RANLIB) $@ shared: libpcap.$(DYEXT) # # XXX - this works with GNU ld, but won't necessarily work with native # ld on, for example, various SVR4-flavored platforms, or Digital UNIX. # libpcap.so: $(OBJ) @rm -f $@ $(CC) -shared -o $@.`cat VERSION` $(OBJ) $(DAGLIBS) # the following rule succeeds, but the result is untested. libpcap.dylib: $(OBJ) rm -f libpcap*.dylib $(CC) -dynamiclib -undefined error -o libpcap.`cat VERSION`.dylib $(OBJ) \ -install_name $(libdir)/libpcap.0.dylib -compatibility_version `cat VERSION` \ -current_version `cat VERSION` scanner.c: $(srcdir)/scanner.l @rm -f $@ $(LEX) -t $< > $$$$.$@; mv $$$$.$@ $@ scanner.o: scanner.c tokdefs.h $(CC) $(CFLAGS) -c scanner.c pcap.o: version.h tokdefs.h: grammar.c grammar.c: $(srcdir)/grammar.y @rm -f grammar.c tokdefs.h $(YACC) -d $< mv y.tab.c grammar.c mv y.tab.h tokdefs.h grammar.o: grammar.c @rm -f $@ $(CC) $(CFLAGS) -Dyylval=pcap_lval -c grammar.c version.o: version.c $(CC) $(CFLAGS) -c version.c snprintf.o: $(srcdir)/missing/snprintf.c $(CC) $(CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c version.c: $(srcdir)/VERSION @rm -f $@ sed -e 's/.*/char pcap_version[] = "&";/' $(srcdir)/VERSION > $@ # # NOTE: this really is supposed to be static; importing a string # from a shared library does not work very well on many # versions of UNIX (Solaris, Linux, and the BSDs, for example), # so we make the version string static and return it from # a function, which does work. # version.h: $(srcdir)/VERSION @rm -f $@ sed -e 's/.*/static const char pcap_version_string[] = "libpcap version &";/' $(srcdir)/VERSION > $@ bpf_filter.c: $(srcdir)/bpf/net/bpf_filter.c rm -f bpf_filter.c ln -s $(srcdir)/bpf/net/bpf_filter.c bpf_filter.c bpf_filter.o: bpf_filter.c $(CC) $(CFLAGS) -c bpf_filter.c install: libpcap.a [ -d $(DESTDIR)$(libdir) ] || \ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir)) $(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a $(RANLIB) $(DESTDIR)$(libdir)/libpcap.a [ -d $(DESTDIR)$(includedir) ] || \ (mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir)) $(INSTALL_DATA) $(srcdir)/pcap.h $(DESTDIR)$(includedir)/pcap.h $(INSTALL_DATA) $(srcdir)/pcap-bpf.h \ $(DESTDIR)$(includedir)/pcap-bpf.h $(INSTALL_DATA) $(srcdir)/pcap-namedb.h \ $(DESTDIR)$(includedir)/pcap-namedb.h [ -d $(DESTDIR)$(mandir)/man3 ] || \ (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3) $(INSTALL_DATA) $(srcdir)/pcap.3 \ $(DESTDIR)$(mandir)/man3/pcap.3 install-shared: install-shared-$(DYEXT) install-shared-so: libpcap.so $(INSTALL_PROGRAM) libpcap.so.`cat VERSION` $(DESTDIR)$(libdir)/libpcap.so.`cat VERSION` install-shared-dylib: libpcap.dylib $(INSTALL_PROGRAM) libpcap.`cat VERSION`.dylib $(DESTDIR)$(libdir)/libpcap.`cat VERSION`.dylib VER=`cat VERSION`; cd $(DESTDIR)$(libdir) && ln -sf libpcap.$$VER.dylib libpcap.0.dylib; ln -sf libpcap.0.dylib libpcap.dylib uninstall: rm -f $(DESTDIR)$(libdir)/libpcap.a rm -f $(DESTDIR)$(includedir)/pcap.h rm -f $(DESTDIR)$(includedir)/pcap-bpf.h rm -f $(DESTDIR)$(includedir)/pcap-namedb.h rm -f $(DESTDIR)$(mandir)/man3/pcap.3 clean: rm -f $(CLEANFILES) libpcap*.dylib libpcap.so* distclean: clean rm -f Makefile config.cache config.log config.status \ config.h gnuc.h os-proto.h bpf_filter.c stamp-h stamp-h.in rm -rf autom4te.cache tags: $(TAGFILES) ctags -wtd $(TAGFILES) packaging/pcap.spec: packaging/pcap.spec.in VERSION RPMVERSION=`cat VERSION | sed s/-.*//g`; \ sed -e s/@VERSION@/$$RPMVERSION/ -e s/@NAME@/libpcap-`cat VERSION`/ $< > $@ releasetar: @cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \ list="" ; make distclean; cd ..; mkdir -p n; cd n; ln -s ../$$dir $$name; \ tar -c -z -f $$name.tar.gz $$name/. ; depend: $(GENSRC) $(GENHDR) bpf_filter.c ./mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC) Makefile: Makefile.in config.status ./config.status @echo your Makefile was out of date, now run $(MAKE) again exit 1 libpcap-0.9.7/./lbl/0000755000026300017500000000000010245661230012170 5ustar mcrmcrlibpcap-0.9.7/./lbl/os-sunos4.h0000644000026300017500000001417506777230341014235 0ustar mcrmcr/* * Copyright (c) 1989, 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. * * @(#) $Header: /tcpdump/master/libpcap/lbl/os-sunos4.h,v 1.32.1.1 1999/10/07 23:46:41 mcr Exp $ (LBL) */ /* Prototypes missing in SunOS 4 */ #ifdef FILE int _filbuf(FILE *); int _flsbuf(u_char, FILE *); int fclose(FILE *); int fflush(FILE *); int fgetc(FILE *); int fprintf(FILE *, const char *, ...); int fputc(int, FILE *); int fputs(const char *, FILE *); u_int fread(void *, u_int, u_int, FILE *); int fseek(FILE *, long, int); u_int fwrite(const void *, u_int, u_int, FILE *); int pclose(FILE *); void rewind(FILE *); void setbuf(FILE *, char *); int setlinebuf(FILE *); int ungetc(int, FILE *); int vfprintf(FILE *, const char *, ...); int vprintf(const char *, ...); #endif #if __GNUC__ <= 1 int read(int, char *, u_int); int write(int, char *, u_int); #endif long a64l(const char *); #ifdef __STDC__ struct sockaddr; #endif int accept(int, struct sockaddr *, int *); int bind(int, struct sockaddr *, int); int bcmp(const void *, const void *, u_int); void bcopy(const void *, void *, u_int); void bzero(void *, int); int chroot(const char *); int close(int); void closelog(void); int connect(int, struct sockaddr *, int); char *crypt(const char *, const char *); int daemon(int, int); int fchmod(int, int); int fchown(int, int, int); void endgrent(void); void endpwent(void); void endservent(void); #ifdef __STDC__ struct ether_addr; #endif struct ether_addr *ether_aton(const char *); int flock(int, int); #ifdef __STDC__ struct stat; #endif int fstat(int, struct stat *); #ifdef __STDC__ struct statfs; #endif int fstatfs(int, struct statfs *); int fsync(int); #ifdef __STDC__ struct timeb; #endif int ftime(struct timeb *); int ftruncate(int, off_t); int getdtablesize(void); long gethostid(void); int gethostname(char *, int); int getopt(int, char * const *, const char *); int getpagesize(void); char *getpass(char *); int getpeername(int, struct sockaddr *, int *); int getpriority(int, int); #ifdef __STDC__ struct rlimit; #endif int getrlimit(int, struct rlimit *); int getsockname(int, struct sockaddr *, int *); int getsockopt(int, int, int, char *, int *); #ifdef __STDC__ struct timeval; struct timezone; #endif int gettimeofday(struct timeval *, struct timezone *); char *getusershell(void); char *getwd(char *); int initgroups(const char *, int); int ioctl(int, int, caddr_t); int iruserok(u_long, int, char *, char *); int isatty(int); int killpg(int, int); int listen(int, int); #ifdef __STDC__ struct utmp; #endif void login(struct utmp *); int logout(const char *); off_t lseek(int, off_t, int); int lstat(const char *, struct stat *); int mkstemp(char *); char *mktemp(char *); int munmap(caddr_t, int); void openlog(const char *, int, int); void perror(const char *); int printf(const char *, ...); int puts(const char *); long random(void); int readlink(const char *, char *, int); #ifdef __STDC__ struct iovec; #endif int readv(int, struct iovec *, int); int recv(int, char *, u_int, int); int recvfrom(int, char *, u_int, int, struct sockaddr *, int *); int rename(const char *, const char *); int rcmd(char **, u_short, char *, char *, char *, int *); int rresvport(int *); int send(int, char *, u_int, int); int sendto(int, char *, u_int, int, struct sockaddr *, int); int setenv(const char *, const char *, int); int seteuid(int); int setpriority(int, int, int); int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); int setpgrp(int, int); void setpwent(void); int setrlimit(int, struct rlimit *); void setservent(int); int setsockopt(int, int, int, char *, int); int shutdown(int, int); int sigblock(int); void (*signal (int, void (*) (int))) (int); int sigpause(int); int sigsetmask(int); #ifdef __STDC__ struct sigvec; #endif int sigvec(int, struct sigvec *, struct sigvec*); int snprintf(char *, size_t, const char *, ...); int socket(int, int, int); int socketpair(int, int, int, int *); int symlink(const char *, const char *); void srandom(int); int sscanf(char *, const char *, ...); int stat(const char *, struct stat *); int statfs(char *, struct statfs *); char *strerror(int); int strcasecmp(const char *, const char *); #ifdef __STDC__ struct tm; #endif int strftime(char *, int, char *, struct tm *); int strncasecmp(const char *, const char *, int); long strtol(const char *, char **, int); void sync(void); void syslog(int, const char *, ...); int system(const char *); long tell(int); time_t time(time_t *); char *timezone(int, int); int tolower(int); int toupper(int); int truncate(char *, off_t); void unsetenv(const char *); int vfork(void); int vsprintf(char *, const char *, ...); int writev(int, struct iovec *, int); #ifdef __STDC__ struct rusage; #endif int utimes(const char *, struct timeval *); #if __GNUC__ <= 1 int wait(int *); pid_t wait3(int *, int, struct rusage *); #endif /* Ugly signal hacking */ #ifdef SIG_ERR #undef SIG_ERR #define SIG_ERR (void (*)(int))-1 #undef SIG_DFL #define SIG_DFL (void (*)(int))0 #undef SIG_IGN #define SIG_IGN (void (*)(int))1 #ifdef KERNEL #undef SIG_CATCH #define SIG_CATCH (void (*)(int))2 #endif #undef SIG_HOLD #define SIG_HOLD (void (*)(int))3 #endif libpcap-0.9.7/./lbl/os-osf5.h0000644000026300017500000000307607522375537013662 0ustar mcrmcr/* * 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. * * @(#) $Header: /tcpdump/master/libpcap/lbl/os-osf5.h,v 1.2 2002/08/02 03:24:15 guy Exp $ (LBL) */ /* * Prototypes missing in Tru64 UNIX 5.x * XXX - "snprintf()" and "vsnprintf()" aren't missing, but you have to * #define the right value to get them defined by . */ int snprintf(char *, size_t, const char *, ...); int vsnprintf(char *, size_t, const char *, va_list); int pfopen(char *, int); libpcap-0.9.7/./lbl/os-osf4.h0000644000026300017500000000266707220640105013643 0ustar mcrmcr/* * 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. * * @(#) $Header: /tcpdump/master/libpcap/lbl/os-osf4.h,v 1.2 2000/12/22 11:51:33 guy Exp $ (LBL) */ /* Prototypes missing in Digital UNIX 4.x */ int snprintf(char *, size_t, const char *, ...); int vsnprintf(char *, size_t, const char *, va_list); int pfopen(char *, int); libpcap-0.9.7/./lbl/CVS/0000755000026300017500000000000010245661230012623 5ustar mcrmcrlibpcap-0.9.7/./lbl/CVS/Entries0000644000026300017500000000062210245661230014157 0ustar mcrmcr/os-aix4.h/1.1/Sat Jun 1 09:37:40 2002//Tlibpcap_0_9 /os-hpux11.h/1.1/Sat Jun 1 09:37:41 2002//Tlibpcap_0_9 /os-osf4.h/1.2/Fri Dec 22 11:51:33 2000//Tlibpcap_0_9 /os-osf5.h/1.2/Fri Aug 2 03:24:15 2002//Tlibpcap_0_9 /os-solaris2.h/1.19/Wed Oct 11 04:02:52 2000//Tlibpcap_0_9 /os-sunos4.h/1.32.1.1/Thu Oct 7 23:46:41 1999//Tlibpcap_0_9 /os-ultrix4.h/1.19.1.1/Thu Oct 7 23:46:41 1999//Tlibpcap_0_9 D libpcap-0.9.7/./lbl/CVS/Root0000644000026300017500000000004010245661227013471 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./lbl/CVS/Repository0000644000026300017500000000001410245661227014726 0ustar mcrmcrlibpcap/lbl libpcap-0.9.7/./lbl/CVS/Tag0000644000026300017500000000001510245661230013255 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./lbl/os-ultrix4.h0000644000026300017500000000335706777230341014415 0ustar mcrmcr/* * 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. * * @(#) $Header: /tcpdump/master/libpcap/lbl/os-ultrix4.h,v 1.19.1.1 1999/10/07 23:46:41 mcr Exp $ (LBL) */ /* Prototypes missing in Ultrix 4 */ int bcmp(const char *, const char *, u_int); void bcopy(const void *, void *, u_int); void bzero(void *, u_int); void endservent(void); int getopt(int, char * const *, const char *); #ifdef __STDC__ struct timeval; struct timezone; #endif int gettimeofday(struct timeval *, struct timezone *); int ioctl(int, int, caddr_t); int pfopen(char *, int); int setlinebuf(FILE *); int socket(int, int, int); int strcasecmp(const char *, const char *); libpcap-0.9.7/./lbl/os-hpux11.h0000644000026300017500000000247107476112745014130 0ustar mcrmcr/* * 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. * * @(#) $Header: /tcpdump/master/libpcap/lbl/os-hpux11.h,v 1.1 2002/06/01 09:37:41 guy Exp $ */ /* Prototypes missing in HP-UX 11.x */ int ffs(int i); libpcap-0.9.7/./lbl/os-solaris2.h0000644000026300017500000000257007170763154014535 0ustar mcrmcr/* * 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. * * @(#) $Header: /tcpdump/master/libpcap/lbl/os-solaris2.h,v 1.19 2000/10/11 04:02:52 guy Exp $ (LBL) */ /* Prototypes missing in SunOS 5 */ char *strerror(int); int snprintf(char *, size_t, const char *, ...); libpcap-0.9.7/./lbl/os-aix4.h0000644000026300017500000000246407476112744013650 0ustar mcrmcr/* * 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. * * @(#) $Header: /tcpdump/master/libpcap/lbl/os-aix4.h,v 1.1 2002/06/01 09:37:40 guy Exp $ */ /* Prototypes missing in AIX 4.x */ int ffs(int i); libpcap-0.9.7/./nametoaddr.c0000644000026300017500000002417710633321703013713 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.77.2.4 2007/06/11 09:52:05 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #include #include /* concession to AIX */ #include #include #include #endif /* WIN32 */ /* * XXX - why was this included even on UNIX? */ #ifdef __MINGW32__ #include "IP6_misc.h" #endif #ifndef WIN32 #ifdef HAVE_ETHER_HOSTTON /* * XXX - do we need any of this if doesn't declare * ether_hostton()? */ #ifdef HAVE_NETINET_IF_ETHER_H struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include /* for "struct ifnet" in "struct arpcom" on Solaris */ #include #endif /* HAVE_NETINET_IF_ETHER_H */ #ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON #include #endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */ #endif /* HAVE_ETHER_HOSTTON */ #include #include #endif /* WIN32 */ #include #include #include #include #include #include "pcap-int.h" #include "gencode.h" #include #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; } #ifdef INET6 struct addrinfo * pcap_nametoaddrinfo(const char *name) { struct addrinfo hints, *res; int error; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; /*not really*/ hints.ai_protocol = IPPROTO_TCP; /*not really*/ error = getaddrinfo(name, NULL, &hints, &res); if (error) return NULL; else return res; } #endif /*INET6*/ /* * Convert net name to internet address. * Return 0 upon failure. */ bpf_u_int32 pcap_nametonetaddr(const char *name) { #ifndef WIN32 struct netent *np; if ((np = getnetbyname(name)) != NULL) return np->n_net; else return 0; #else /* * There's no "getnetbyname()" on Windows. */ return 0; #endif } /* * Convert a port name to its port and protocol numbers. * We assume only TCP or UDP. * Return 0 upon failure. */ int pcap_nametoport(const char *name, int *port, int *proto) { struct servent *sp; int tcp_port = -1; int udp_port = -1; /* * 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. */ sp = getservbyname(name, "tcp"); if (sp != NULL) tcp_port = ntohs(sp->s_port); sp = getservbyname(name, "udp"); if (sp != NULL) udp_port = ntohs(sp->s_port); if (tcp_port >= 0) { *port = tcp_port; *proto = IPPROTO_TCP; if (udp_port >= 0) { if (udp_port == tcp_port) *proto = PROTO_UNDEF; #ifdef notdef else /* Can't handle ambiguous names that refer to different port numbers. */ warning("ambiguous port %s in /etc/services", name); #endif } return 1; } if (udp_port >= 0) { *port = udp_port; *proto = IPPROTO_UDP; 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; } /* * Convert a string in the form PPP-PPP, where correspond to ports, to * a starting and ending port in a port range. * Return 0 on failure. */ int pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto) { u_int p1, p2; char *off, *cpy; int save_proto; if (sscanf(name, "%d-%d", &p1, &p2) != 2) { if ((cpy = strdup(name)) == NULL) return 0; if ((off = strchr(cpy, '-')) == NULL) { free(cpy); return 0; } *off = '\0'; if (pcap_nametoport(cpy, port1, proto) == 0) { free(cpy); return 0; } save_proto = *proto; if (pcap_nametoport(off + 1, port2, proto) == 0) { free(cpy); return 0; } if (*proto != save_proto) *proto = PROTO_UNDEF; } else { *port1 = p1; *port2 = p2; *proto = PROTO_UNDEF; } return 1; } int 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 { const 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 }, #ifdef INET6 { "ip6", ETHERTYPE_IPV6 }, #endif { "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 } }; int 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; } #include "llc.h" /* Static data base of LLC values. */ static struct eproto llc_db[] = { { "iso", LLCSAP_ISONS }, { "stp", LLCSAP_8021D }, { "ipx", LLCSAP_IPX }, { "netbeui", LLCSAP_NETBEUI }, { (char *)0, 0 } }; int pcap_nametollc(const char *s) { struct eproto *p = llc_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; } int __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 */ } int __pcap_atodn(const char *s, bpf_u_int32 *addr) { #define AREASHIFT 10 #define AREAMASK 0176000 #define NODEMASK 01777 u_int node, area; if (sscanf(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((unsigned char)*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 int 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 #if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON #ifndef HAVE_STRUCT_ETHER_ADDR struct ether_addr { unsigned char ether_addr_octet[6]; }; #endif extern int ether_hostton(const 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(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); return(0); #endif } libpcap-0.9.7/./ppp.h0000644000026300017500000000532510202214163012364 0ustar mcrmcr/* @(#) $Header: /tcpdump/master/libpcap/ppp.h,v 1.12 2005/02/08 19:52:19 guy 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 */ #define PPP_PPPD_IN 0x00 /* non-standard for DLT_PPP_PPPD */ #define PPP_PPPD_OUT 0x01 /* non-standard for DLT_PPP_PPPD */ /* 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_IPV6 0x0057 /* Internet Protocol version 6 */ #define PPP_HELLO 0x0201 /* 802.1d Hello Packets */ #define PPP_LUXCOM 0x0231 /* Luxcom */ #define PPP_SNS 0x0233 /* Sigma Network Systems */ #define PPP_MPLS_UCAST 0x0281 /* rfc 3032 */ #define PPP_MPLS_MCAST 0x0283 /* rfc 3022 */ #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_IPV6CP 0x8057 /* IPv6 Control Protocol */ #define PPP_MPLSCP 0x8281 /* rfc 3022 */ #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 */ libpcap-0.9.7/./README.dag0000644000026300017500000001154010504042140013021 0ustar mcrmcr The following instructions apply if you have a Linux or FreeBSD platform and want libpcap to support the DAG range of passive network monitoring cards from Endace (http://www.endace.com, see below for further contact details). 1) Install and build the DAG software distribution by following the instructions supplied with that package. Current Endace customers can download the DAG software distibution from https://www.endace.com 2) Configure libcap. To allow the 'configure' script to locate the DAG software distribution use the '--with-dag' option: ./configure --with-dag=DIR Where DIR is the root of the DAG software distribution, for example /var/src/dag. If the DAG software is correctly detected 'configure' will report: checking whether we have DAG API... yes If 'configure' reports that there is no DAG API, the directory may have been incorrectly specified or the DAG software was not built before configuring libpcap. See also the libpcap INSTALL.txt file for further libpcap configuration options. Building libpcap at this stage will include support for both the native packet capture stream (linux or bpf) and for capturing from DAG cards. To build libpcap with only DAG support specify the capture type as 'dag' when configuring libpcap: ./configure --with-dag=DIR --with-pcap=dag Applications built with libpcap configured in this way will only detect DAG cards and will not capture from the native OS packet stream. ---------------------------------------------------------------------- Libpcap when built for DAG cards against dag-2.5.1 or later releases: Timeouts are supported. pcap_dispatch() will return after to_ms milliseconds regardless of how many packets are received. If to_ms is zero pcap_dispatch() will block waiting for data indefinitely. pcap_dispatch() will block on and process a minimum of 64kB of data (before filtering) for efficiency. This can introduce high latencies on quiet interfaces unless a timeout value is set. The timeout expiring will override the 64kB minimum causing pcap_dispatch() to process any available data and return. pcap_setnonblock is supported. When nonblock is set, pcap_dispatch() will check once for available data, process any data available up to count, then return immediately. pcap_findalldevs() is supported, e.g. dag0, dag1... Some DAG cards can provide more than one 'stream' of received data. This can be data from different physical ports, or separated by filtering or load balancing mechanisms. Receive streams have even numbers, e.g. dag0:0, dag0:2 etc. Specifying transmit streams for capture is not supported. pcap_setfilter() is supported, BPF programs run in userspace. pcap_setdirection() is not supported. Only received traffic is captured. DAG cards normally do not have IP or link layer addresses assigned as they are used to passively monitor links. pcap_breakloop() is supported. pcap_datalink() and pcap_list_datalinks() are supported. The DAG card does not attempt to set the correct datalink type automatically where more than one type is possible. pcap_stats() is supported. ps_drop is the number of packets dropped due to RX stream buffer overflow, this count is before filters are applied (it will include packets that would have been dropped by the filter). The RX stream buffer size is user configurable outside libpcap, typically 16-512MB. pcap_get_selectable_fd() is not supported, as DAG cards do not support poll/select methods. pcap_inject() and pcap_sendpacket() are not supported. Some DAG cards now support capturing to multiple virtual interfaces, called streams. Capture streams have even numbers. These are available via libpcap as separate interfaces, e.g. dag0:0, dag0:2, dag0:4 etc. dag0:0 is the same as dag0. These are visible via pcap_findalldevs(). libpcap now does NOT set the card's hardware snaplen (slen). This must now be set using the appropriate DAG coniguration program, e.g. dagthree, dagfour, dagsix, dagconfig. This is because the snaplen is currently shared between all of the streams. In future this may change if per-stream slen is implemented. DAG cards by default capture entire packets including the L2 CRC/FCS. If the card is not configured to discard the CRC/FCS, this can confuse applications that use libpcap if they're not prepared for packets to have an FCS. Libpcap now reads the environment variable ERF_FCS_BITS to determine how many bits of CRC/FCS to strip from the end of the captured frame. This defaults to 32 for use with Ethernet. If the card is configured to strip the CRC/FCS, then set ERF_FCS_BITS=0. If used with a HDLC/PoS/PPP/Frame Relay link with 16 bit CRC/FCS, then set ERF_FCS_BITS=16. ---------------------------------------------------------------------- Please submit bug reports via . Please also visit our Web site at: http://www.endace.com/ For more information about Endace DAG cards contact . libpcap-0.9.7/./TODO0000644000026300017500000000302710633321703012110 0ustar mcrmcr TODO list for libpcap ======================= Important stuff (to be done before the next release) --------------- General - configure should not be in the CVS. Most open source projects have an autogen.sh script to run autoconf etc. after checkout. I think we should stick to the standard. - The source files should be better documented. There is no official design guideline for what is done where. There should be a common coding style (okay, you can guess that by looking at the code) and a guide for what needs to be documented. Less urgent items ----------------- - Better documentation and cleanup of the interface. I am seeing a few problems at the first glance which needs fixing: + pcap_lookupnet makes little to no sense with protocols != IPv4 + not very well suited for interactive programs (think ethereal). There should be a way for the application to get a file descriptor which it has to monitor and a callback in pcap which has to be called on activity (XXX - "pcap_fileno()" handles the first part, although "select()" and "poll()" don't work on BPF devices on most BSDs, and you can call "pcap_dispatch()" as the dispatch routine after putting the descriptor into non-blocking mode) + too many functions. There are a lot of functions for everything which violates the KISS principle. Why do we need pcap_strerror, pcap_perror and pcap_geterr? + the manpage has a brief description of each function but where is the big picture? Seems like you need to buy UNP for that... libpcap-0.9.7/./mkdep0000755000026300017500000000445606777230340012467 0ustar mcrmcr#!/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 fi if [ ! -w $MAKE ]; then echo "mkdep: no writeable file \"$MAKE\"" exit 1 fi 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 libpcap-0.9.7/./acconfig.h0000644000026300017500000000045707374045231013355 0ustar mcrmcr/* Long story short: aclocal.m4 depends on autoconf 2.13 * implementation details wrt "const"; newer versions * have different implementation details so for now we * put "const" here. This may cause duplicate definitions * in config.h but that should be OK since they're the same. */ #undef const libpcap-0.9.7/./pcap-dag.h0000644000026300017500000000113310264535366013255 0ustar mcrmcr/* * pcap-dag.c: Packet capture interface for Endace DAG card. * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible. This code is only needed when compiling in the DAG card code * at the same time as another type of device. * * Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) * * @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.3.4.1 2005/07/07 06:56:04 guy Exp $ (LBL) */ pcap_t *dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf); int dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf); libpcap-0.9.7/./pcap-snoop.c0000644000026300017500000002737710235744356013674 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.54.2.1 2005/05/03 18:54:38 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif static int pcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; register struct snoopheader *sh; register u_int datalen; register u_int caplen; register u_char *cp; again: /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return -2 to indicate that we were * told to break out of the loop. */ p->break_loop = 0; return (-2); } 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 */ } snprintf(p->errbuf, sizeof(p->errbuf), "read: %s", pcap_strerror(errno)); return (-1); } sh = (struct snoopheader *)p->buffer; datalen = sh->snoop_packetlen; /* * XXX - Sigh, snoop_packetlen is a 16 bit quantity. If we * got a short length, but read a full sized snoop pakcet, * assume we overflowed and add back the 64K... */ if (cc == (p->snapshot + sizeof(struct snoopheader)) && (datalen < p->snapshot)) datalen += (64 * 1024); caplen = (datalen < p->snapshot) ? datalen : p->snapshot; cp = (u_char *)(sh + 1) + p->offset; /* XXX */ /* * XXX unfortunately snoop loopback isn't exactly like * BSD's. The address family is encoded in the first 2 * bytes rather than the first 4 bytes! Luckily the last * two snoop loopback bytes are zeroed. */ if (p->linktype == DLT_NULL && *((short *)(cp + 2)) == 0) { u_int *uip = (u_int *)cp; *uip >>= 16; } 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.tv_sec = sh->snoop_timestamp.tv_sec; h.ts.tv_usec = sh->snoop_timestamp.tv_usec; h.len = datalen; h.caplen = caplen; (*callback)(user, &h, cp); return (1); } return (0); } static int pcap_inject_snoop(pcap_t *p, const void *buf, size_t size) { int ret; /* * XXX - libnet overwrites the source address with what I * presume is the interface's address; is that required? */ ret = write(p->fd, buf, size); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } static int pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps) { register struct rawstats *rs; struct rawstats rawstats; rs = &rawstats; memset(rs, 0, sizeof(*rs)); if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "SIOCRAWSTATS: %s", pcap_strerror(errno)); return (-1); } /* * "ifdrops" are those dropped by the network interface * due to resource shortages or hardware errors. * * "sbdrops" are those dropped due to socket buffer limits. * * As filter is done in userland, "sbdrops" counts packets * regardless of whether they would've passed the filter. * * XXX - does this count *all* Snoop or Drain sockets, * rather than just this socket? If not, why does it have * both Snoop and Drain statistics? */ 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_recv" counts only packets that passed the filter. * As filtering is done in userland, this does not include * packets dropped because we ran out of buffer space. */ *ps = p->md.stat; return (0); } /* XXX can't disable promiscuous */ pcap_t * pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { int fd; struct sockaddr_raw sr; struct snoopfilter sf; u_int v; int ll_hdrlen; int snooplen; pcap_t *p; struct ifreq ifr; p = (pcap_t *)malloc(sizeof(*p)); if (p == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } memset(p, 0, sizeof(*p)); fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP); if (fd < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop socket: %s", pcap_strerror(errno)); goto bad; } p->fd = fd; memset(&sr, 0, 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))) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop bind: %s", pcap_strerror(errno)); goto bad; } memset(&sf, 0, sizeof(sf)); if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s", pcap_strerror(errno)); goto bad; } v = 64 * 1024; (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v)); /* * 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("eg", device, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */ 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 || strncmp("cip", device, 3) == 0 || strncmp("el", device, 2) == 0) { p->linktype = DLT_EN10MB; p->offset = RAW_HDRPAD(sizeof(struct ether_header)); ll_hdrlen = sizeof(struct ether_header); /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). * * XXX - are there any sorts of "fake Ethernet" that have * Ethernet link-layer headers but that *shouldn't offer * DLT_DOCSIS as a Cisco CMTS won't put traffic onto it * or get traffic bridged onto it? "el" is for ATM LANE * Ethernet devices, so that might be the case for them; * the same applies for "qaa" classical IP devices. If * "fa" devices are for FORE SPANS, that'd apply to them * as well; what are "cip" devices - some other ATM * Classical IP devices? */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } } 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? */ ll_hdrlen = 13; } else if (strncmp("ppp", device, 3) == 0) { p->linktype = DLT_RAW; ll_hdrlen = 0; /* DLT_RAW meaning "no PPP header, just the IP packet"? */ } else if (strncmp("qfa", device, 3) == 0) { p->linktype = DLT_IP_OVER_FC; ll_hdrlen = 24; } else if (strncmp("pl", device, 2) == 0) { p->linktype = DLT_RAW; ll_hdrlen = 0; /* Cray UNICOS/mp pseudo link */ } else if (strncmp("lo", device, 2) == 0) { p->linktype = DLT_NULL; ll_hdrlen = 4; } else { snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop: unknown physical layer type"); goto bad; } #ifdef SIOCGIFMTU /* * XXX - IRIX appears to give you an error if you try to set the * capture length to be greater than the MTU, so let's try to get * the MTU first and, if that succeeds, trim the snap length * to be no greater than the MTU. */ (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s", pcap_strerror(errno)); goto bad; } /* * OK, we got it. * * XXX - some versions of IRIX 6.5 define "ifr_mtu" and have an * "ifru_metric" member of the "ifr_ifru" union in an "ifreq" * structure, others don't. * * I've no idea what's going on, so, if "ifr_mtu" isn't defined, * we define it as "ifr_metric", as using that field appears to * work on the versions that lack "ifr_mtu" (and, on those that * don't lack it, "ifru_metric" and "ifru_mtu" are both "int" * members of the "ifr_ifru" union, which suggests that they * may be interchangeable in this case). */ #ifndef ifr_mtu #define ifr_mtu ifr_metric #endif if (snaplen > ifr.ifr_mtu + ll_hdrlen) snaplen = ifr.ifr_mtu + ll_hdrlen; #endif /* * The argument to SIOCSNOOPLEN is the number of link-layer * payload bytes to capture - it doesn't count link-layer * header bytes. */ snooplen = snaplen - ll_hdrlen; if (snooplen < 0) snooplen = 0; if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s", pcap_strerror(errno)); goto bad; } p->snapshot = snaplen; v = 1; if (ioctl(fd, SIOCSNOOPING, &v) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s", pcap_strerror(errno)); goto bad; } p->bufsize = 4096; /* XXX */ p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } /* * "p->fd" is a socket, so "select()" should work on it. */ p->selectable_fd = p->fd; p->read_op = pcap_read_snoop; p->inject_op = pcap_inject_snoop; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_snoop; p->close_op = pcap_close_common; return (p); bad: (void)close(fd); /* * Get rid of any link-layer type list we allocated. */ if (p->dlt_list != NULL) free(p->dlt_list); free(p); return (NULL); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } libpcap-0.9.7/./fad-null.c0000644000026300017500000000522607755532616013313 0ustar mcrmcr/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/fad-null.c,v 1.2 2003/11/15 23:23:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* * Get a list of all interfaces that are up and that we can open. * Returns -1 on error, 0 otherwise. * The list, as returned through "alldevsp", may be null if no interfaces * were up and could be opened. * * This is the implementation used on platforms that have no support for * packet capture. */ int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) { /* * Succeed, but don't return any interfaces; we return only those * we can open, and we can't open any if there's no support * for packet capture. */ *alldevsp = NULL; return (0); } libpcap-0.9.7/./README.hpux0000644000026300017500000002011010172070254013253 0ustar mcrmcrFor HP-UX 11i (11.11) and later, there are no known issues with promiscuous mode under HP-UX. If you are using a earlier version of HP-UX and cannot upgrade, please continue reading. HP-UX patches to fix packet capture problems Note that packet-capture programs such as tcpdump may, on HP-UX, not be able to see packets sent from the machine on which they're running. Some articles on groups.google.com discussing this are: http://groups.google.com/groups?selm=82ld3v%2480i%241%40mamenchi.zrz.TU-Berlin.DE which says: Newsgroups: comp.sys.hp.hpux Subject: Re: Did someone made tcpdump working on 10.20 ? Date: 12/08/1999 From: Lutz Jaenicke In article <82ks5i$5vc$1@news1.dti.ne.jp>, mtsat wrote: >Hello, > >I downloaded and compiled tcpdump3.4 a couple of week ago. I tried to use >it, but I can only see incoming data, never outgoing. >Someone (raj) explained me that a patch was missing, and that this patch >must me "patched" (poked) in order to see outbound data in promiscuous mode. >Many things to do .... So the question is : did someone has already this >"ready to use" PHNE_**** patch ? Two things: 1. You do need a late "LAN products cumulative patch" (e.g. PHNE_18173 for s700/10.20). 2. You must use echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem You can insert this e.g. into /sbin/init.d/lan Best regards, Lutz and http://groups.google.com/groups?selm=88cf4t%24p03%241%40web1.cup.hp.com which says: Newsgroups: comp.sys.hp.hpux Subject: Re: tcpdump only shows incoming packets Date: 02/15/2000 From: Rick Jones Harald Skotnes wrote: > I am running HPUX 11.0 on a C200 hanging on a 100Mb switch. I have > compiled libpcap-0.4 an tcpdump-3.4 and it seems to work. But at a > closer look I only get to see the incoming packets not the > outgoing. I have tried tcpflow-0.12 which also uses libpcap and the > same thing happens. Could someone please give me a hint on how to > get this right? Search/Read the archives ?-) What you are seeing is expected, un-patched, behaviour for an HP-UX system. On 11.00, you need to install the latest lancommon/DLPI patches, and then the latest driver patch for the interface(s) in use. At that point, a miracle happens and you should start seeing outbound traffic. [That article also mentions the patch that appears below.] and http://groups.google.com/groups?selm=38AA973E.96BE7DF7%40cc.uit.no which says: Newsgroups: comp.sys.hp.hpux Subject: Re: tcpdump only shows incoming packets Date: 02/16/2000 From: Harald Skotnes Rick Jones wrote: ... > What you are seeing is expected, un-patched, behaviour for an HP-UX > system. On 11.00, you need to install the latest lancommon/DLPI > patches, and then the latest driver patch for the interface(s) in > use. At that point, a miracle happens and you should start seeing > outbound traffic. Thanks a lot. I have this problem on several machines running HPUX 10.20 and 11.00. The machines where patched up before y2k so did not know what to think. Anyway I have now installed PHNE_19766, PHNE_19826, PHNE_20008, PHNE_20735 on the C200 and now I can see the outbound traffic too. Thanks again. (although those patches may not be the ones to install - there may be later patches). And another message to tcpdump-workers@tcpdump.org, from Rick Jones: Date: Mon, 29 Apr 2002 15:59:55 -0700 From: Rick Jones To: tcpdump-workers@tcpdump.org Subject: Re: [tcpdump-workers] I Can't Capture the Outbound Traffic ... http://itrc.hp.com/ would be one place to start in a search for the most up-to-date patches for DLPI and the lan driver(s) used on your system (I cannot guess because 9000/800 is too generic - one hs to use the "model" command these days and/or an ioscan command (see manpage) to guess what the drivers (btlan[3456], gelan, etc) might be involved in addition to DLPI. Another option is to upgrade to 11i as outbound promiscuous mode support is there in the base OS, no patches required. Another posting: http://groups.google.com/groups?selm=7d6gvn%24b3%241%40ocean.cup.hp.com indicates that you need to install the optional STREAMS product to do captures on HP-UX 9.x: Newsgroups: comp.sys.hp.hpux Subject: Re: tcpdump HP/UX 9.x Date: 03/22/1999 From: Rick Jones Dave Barr (barr@cis.ohio-state.edu) wrote: : Has anyone ported tcpdump (or something similar) to HP/UX 9.x? I'm reasonably confident that any port of tcpdump to 9.X would require the (then optional) STREAMS product. This would bring DLPI, which is what one uses to access interfaces in promiscuous mode. I'm not sure that HP even sells the 9.X STREAMS product any longer, since HP-UX 9.X is off the pricelist (well, maybe 9.10 for the old 68K devices). Your best bet is to be up on 10.20 or better if that is at all possible. If your hardware is supported by it, I'd go with HP-UX 11. If you want to see the system's own outbound traffic, you'll never get that functionality on 9.X, but it might happen at some point for 10.20 and 11.X. rick jones (as per other messages cited here, the ability to see the system's own outbound traffic did happen). Rick Jones reports that HP-UX 11i needs no patches for outbound promiscuous mode support. An additional note, from Jost Martin, for HP-UX 10.20: Q: How do I get ethereral on HPUX to capture the _outgoing_ packets of an interface A: You need to get PHNE_20892,PHNE_20725 and PHCO_10947 (or newer, this is as of 4.4.00) and its dependencies. Then you can enable the feature as descibed below: Patch Name: PHNE_20892 Patch Description: s700 10.20 PCI 100Base-T cumulative patch To trace the outbound packets, please do the following to turn on a global promiscuous switch before running the promiscuous applications like snoop or tcpdump: adb -w /stand/vmunix /dev/mem lanc_outbound_promisc_flag/W 1 (adb will echo the result showing that the flag has been changed) $quit (Thanks for this part to HP-support, Ratingen) The attached hack does this and some security-related stuff (thanks to hildeb@www.stahl.bau.tu-bs.de (Ralf Hildebrandt) who posted the security-part some time ago) <> (Don't switch IP-forwarding off, if you need it !) Install the hack as /sbin/init.d/hacl_ip_stack (adjust permissions !) and make a sequencing-symlink /sbin/rc2.d/S350hack_ip_stack pointing to this script. Now all this is done on every reboot. According to Rick Jones, the global promiscuous switch also has to be turned on for HP-UX 11.00, but not for 11i - and, in fact, the switch doesn't even exist on 11i. Here's the "hack_ip_stack" script: -----------------------------------Cut Here------------------------------------- #!/sbin/sh # # nettune: hack kernel parms for safety OKAY=0 ERROR=-1 # /usr/contrib/bin fuer nettune auf Pfad PATH=/sbin:/usr/sbin:/usr/bin:/usr/contrib/bin export PATH ########## # main # ########## case $1 in start_msg) print "Tune IP-Stack for security" exit $OKAY ;; stop_msg) print "This action is not applicable" exit $OKAY ;; stop) exit $OKAY ;; start) ;; # fall through *) print "USAGE: $0 {start_msg | stop_msg | start | stop}" >&2 exit $ERROR ;; esac ########### # start # ########### # # tcp-Sequence-Numbers nicht mehr inkrementieren sondern random # Syn-Flood-Protection an # ip_forwarding aus # Source-Routing aus # Ausgehende Packets an ethereal/tcpdump etc. /usr/contrib/bin/nettune -s tcp_random_seq 2 || exit $ERROR /usr/contrib/bin/nettune -s hp_syn_protect 1 || exit $ERROR /usr/contrib/bin/nettune -s ip_forwarding 0 || exit $ERROR echo 'ip_block_source_routed/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem || exit $ERROR echo 'lanc_outbound_promisc_flag/W 1' | adb -w /stand/vmunix /dev/mem || exit $ERROR exit $OKAY -----------------------------------Cut Here------------------------------------- libpcap-0.9.7/./gencode.c.rej0000644000026300017500000003130610644760047013762 0ustar mcrmcr*************** *** 24,29 **** "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.51 2007/06/14 20:54:12 gianluca Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif --- 24,31 ---- "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.51 2007/06/14 20:54:12 gianluca Exp $ (LBL)"; #endif + #define ENABLE_WLAN_FILTERING_PATCH + #ifdef HAVE_CONFIG_H #include "config.h" #endif *************** *** 144,150 **** OR_NET, /* relative to the network-layer header */ OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ - OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ }; /* --- 146,153 ---- OR_NET, /* relative to the network-layer header */ OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ + OR_TRAN_IPV6, /* relative to the transport-layer header, with IPv6 network layer */ + OR_LINK_AFTER_WIRELESS_HDR /* After the 802.11 variable length header */ }; /* *************** *** 199,204 **** static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); static struct block *gen_llc_linktype(int); static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); #ifdef INET6 static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); --- 202,208 ---- static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); static struct block *gen_llc_linktype(int); + static struct block *gen_802_11_llc_linktype(int); static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); #ifdef INET6 static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); *************** *** 242,247 **** static struct slist *xfer_to_a(struct arth *); static struct block *gen_mac_multicast(int); static struct block *gen_len(int, int); static struct block *gen_ppi_dlt_check(); static struct block *gen_msg_abbrev(int type); --- 246,252 ---- static struct slist *xfer_to_a(struct arth *); static struct block *gen_mac_multicast(int); static struct block *gen_len(int, int); + static struct block *gen_check_802_11_data_frame(); static struct block *gen_ppi_dlt_check(); static struct block *gen_msg_abbrev(int type); *************** *** 1345,1350 **** return s; } /* * Load a value relative to the beginning of the specified header. --- 1350,1487 ---- return s; } + /* + * Load a value relative to the beginning of the link-layer header after the 802.11 + * header, i.e. LLC_SNAP. + * The link-layer header doesn't necessarily begin at the beginning + * of the packet data; there might be a variable-length prefix containing + * radio information. + */ + static struct slist * + gen_load_ll_after_802_11_rel(offset, size) + u_int offset, size; + { + struct slist *s, *s_load_fc; + struct slist *sjset_qos; + struct slist *s_load; + struct slist *s_ld_a_2; + struct slist *s_add_a_x; + struct slist *s_a_to_x; + struct slist *sjset_data_frame_1; + struct slist *sjset_data_frame_2; + struct slist *s_load_x_0; + + /* + * This code is not compatible with the optimizer, as + * we are generating jmp instructions within a normal + * slist of instructions + * + */ + no_optimize = 1; + + s = gen_llprefixlen(); + + /* + * If "s" is non-null, it has code to arrange that the X register + * contains the length of the prefix preceding the link-layer + * header. + * + * Otherwise, the length of the prefix preceding the link-layer + * header is "off_ll". + */ + if (s != NULL) { + /* + * There's a variable-length prefix preceding the + * link-layer header. "s" points to a list of statements + * that put the length of that prefix into the X register. + * do an indirect load, to use the X register as an offset. + */ + + /* + * Load the Frame Control field + */ + s_load_fc = new_stmt(BPF_LD|BPF_IND|BPF_B); + s_load_fc->s.k = 0; + } else { + /* + * There is no variable-length header preceding the + * link-layer header; add in off_ll, which, if there's + * a fixed-length header preceding the link-layer header, + * is the length of that header. + */ + + /* + * We need to load the Frame control directly, and + * then load X with a fake 0, i.e. the length of the + * non-existing prepended header + */ + + /* + * TODO GV: I'm not sure if 0 is the right constant in this + * case. If the link layer has a fixed length prepended header, + * that should be the value that we put here + */ + + /* Load 0 into X */ + s_load_x_0 = new_stmt(BPF_LDX|BPF_IMM); + s_load_x_0->s.k = 0; + + /* + * TODO GV: I'm not sure if 0 is the right constant in this + * case. If the link layer has a fixed length prepended header, + * that should be the value that we put here + */ + + /* + * load the Frame Control with absolute access + */ + s_load_fc = new_stmt(BPF_LD|BPF_ABS|BPF_B); + s_load_fc->s.k = 0; + s = s_load_x_0; + } + + /* + * Generate the common instructions to check if it's a data frame + * and if so compute the 802.11 header length + */ + sjset_data_frame_1 = new_stmt(JMP(BPF_JSET)); // b3 should be 1 + sjset_data_frame_1->s.k = 0x8; + + sjset_data_frame_2 = new_stmt(JMP(BPF_JSET)); // b2 should be 0 + sjset_data_frame_2->s.k = 0x04; + + sjset_qos = new_stmt(JMP(BPF_JSET)); + sjset_qos->s.k = 0x80; //QOS bit + + s_ld_a_2 = new_stmt(BPF_LD|BPF_IMM); + s_ld_a_2->s.k = 2; + + s_add_a_x = new_stmt(BPF_ALU|BPF_ADD|BPF_X); + s_a_to_x = new_stmt(BPF_MISC|BPF_TAX); + + s_load = new_stmt(BPF_LD|BPF_IND|size); + s_load->s.k = offset; + + sjset_data_frame_1->s.jt = sjset_data_frame_2; + sjset_data_frame_1->s.jf = s_load; + + sjset_data_frame_2->s.jt = s_load; + sjset_data_frame_2->s.jf = sjset_qos; + + sjset_qos->s.jt = s_ld_a_2; + sjset_qos->s.jf = s_load; + + sappend(s, s_load_fc); + sappend(s_load_fc, sjset_data_frame_1); + sappend(sjset_data_frame_1, sjset_data_frame_2); + sappend(sjset_data_frame_2, sjset_qos); + sappend(sjset_qos, s_ld_a_2); + sappend(s_ld_a_2, s_add_a_x); + sappend(s_add_a_x,s_a_to_x); + sappend(s_a_to_x, s_load); + + return s; + } /* * Load a value relative to the beginning of the specified header. *************** *** 1367,1372 **** s = gen_load_llrel(offset, size); break; case OR_NET: s = gen_load_llrel(off_nl + offset, size); break; --- 1504,1525 ---- s = gen_load_llrel(offset, size); break; + #ifdef ENABLE_WLAN_FILTERING_PATCH + + case OR_LINK_AFTER_WIRELESS_HDR: + if (linktype != DLT_IEEE802_11_RADIO + && linktype != DLT_PPI + && linktype != DLT_IEEE802_11 + && linktype != DLT_PRISM_HEADER + && linktype != DLT_IEEE802_11_RADIO_AVS) + { + abort(); + return NULL; + } + s = gen_load_ll_after_802_11_rel(offset + 24, size); + break; + #endif /* ENABLE_WLAN_FILTERING_PATCH */ + case OR_NET: s = gen_load_llrel(off_nl + offset, size); break; *************** *** 2163,2173 **** break; case DLT_PPI: case DLT_FDDI: case DLT_IEEE802: - case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: - case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: case DLT_ATM_RFC1483: case DLT_ATM_CLIP: --- 2316,2332 ---- break; case DLT_PPI: + case DLT_IEEE802_11_RADIO: + case DLT_IEEE802_11: + #ifdef ENABLE_WLAN_FILTERING_PATCH + return gen_802_11_llc_linktype(proto); + /*NOTREACHED*/ + break; + #endif /* ENABLE_WLAN_FILTERING_PATCH */ + case DLT_FDDI: case DLT_IEEE802: case DLT_IEEE802_11_RADIO_AVS: case DLT_PRISM_HEADER: case DLT_ATM_RFC1483: case DLT_ATM_CLIP: *************** *** 2711,2716 **** } } static struct block * gen_hostop(addr, mask, dir, proto, src_off, dst_off) bpf_u_int32 addr; --- 2870,2982 ---- } } + /* + * Generate code to match a particular packet type, for link-layer types + * using 802.2 LLC headers. + * + * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used + * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. + * + * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP + * value, if <= ETHERMTU. We use that to determine whether to + * match the DSAP or both DSAP and LSAP or to check the OUI and + * protocol ID in a SNAP header. + */ + static struct block * + gen_802_11_llc_linktype(proto) + int proto; + { + struct block *b_check_data_frame; + struct block *b_check_linktype; + + b_check_data_frame = gen_check_802_11_data_frame(); + + /* + * XXX - generate the code that discards non data frames + */ + switch (proto) { + + case LLCSAP_IP: + case LLCSAP_ISONS: + case LLCSAP_NETBEUI: + /* + * XXX - should we check both the DSAP and the + * SSAP, like this, or should we check just the + * DSAP, as we do for other types <= ETHERMTU + * (i.e., other SAP values)? + */ + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_H, (bpf_u_int32) + ((proto << 8) | proto)); + break; + + case LLCSAP_IPX: + /* + * XXX - are there ever SNAP frames for IPX on + * non-Ethernet 802.x networks? + */ + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_B, + (bpf_int32)LLCSAP_IPX); + + break; + + #if 0 + case ETHERTYPE_ATALK: + /* + * 802.2-encapsulated ETHERTYPE_ATALK packets are + * SNAP packets with an organization code of + * 0x080007 (Apple, for Appletalk) and a protocol + * type of ETHERTYPE_ATALK (Appletalk). + * + * XXX - check for an organization code of + * encapsulated Ethernet as well? + */ + return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype); + #endif + default: + /* + * XXX - we don't have to check for IPX 802.3 + * here, but should we check for the IPX Ethertype? + */ + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so check + * the DSAP. + */ + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_B, + (bpf_int32)proto); + } else { + /* + * This is an Ethernet type; we assume that it's + * unlikely that it'll appear in the right place + * at random, and therefore check only the + * location that would hold the Ethernet type + * in a SNAP frame with an organization code of + * 0x000000 (encapsulated Ethernet). + * + * XXX - if we were to check for the SNAP DSAP and + * LSAP, as per XXX, and were also to check for an + * organization code of 0x000000 (encapsulated + * Ethernet), we'd do + * + * return gen_snap(0x000000, proto, + * off_linktype); + * + * here; for now, we don't, as per the above. + * I don't know whether it's worth the extra CPU + * time to do the right check or not. + */ + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0+6, BPF_H, + (bpf_int32)proto); + } + } + + gen_and(b_check_data_frame, b_check_linktype); + return b_check_linktype; + + } + + + static struct block * gen_hostop(addr, mask, dir, proto, src_off, dst_off) bpf_u_int32 addr; *************** *** 2925,2930 **** register struct block *b0, *b1, *b2; register struct slist *s; switch (dir) { case Q_SRC: /* --- 3191,3207 ---- register struct block *b0, *b1, *b2; register struct slist *s; + #ifdef ENABLE_WLAN_FILTERING_PATCH + /* + * TODO GV 20070613 + * We need to disable the optimizer because the optimizer is buggy + * and wipes out some LD instructions generated by the below + * code to validate the Frame Control bits + * + */ + no_optimize = 1; + #endif /* ENABLE_WLAN_FILTERING_PATCH */ + switch (dir) { case Q_SRC: /* *************** *** 4713,4718 **** #endif } /* * Generate code that checks whether the packet is a packet for protocol --- 4990,5021 ---- #endif } + static struct block * + gen_check_802_11_data_frame() + { + struct slist *s; + struct block *b0, *b1; + /* + * Now check for a data frame. + * I.e, check "link[0] & 0x08". + */ + s = gen_load_a(OR_LINK, 0, BPF_B); + b0 = new_block(JMP(BPF_JSET)); + b0->s.k = 0x08; + b0->stmts = s; + + s = gen_load_a(OR_LINK, 0, BPF_B); + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x04; + b1->stmts = s; + gen_not(b1); + + + gen_and(b1, b0); + + return b0; + } + /* * Generate code that checks whether the packet is a packet for protocol libpcap-0.9.7/./etherent.c0000644000026300017500000000643207755532615013426 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.22 2003/11/15 23:23:57 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "pcap-int.h" #include #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; do 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); } libpcap-0.9.7/./pcap-namedb.h0000644000026300017500000000654210231104140013731 0ustar mcrmcr/* * Copyright (c) 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 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: /tcpdump/master/libpcap/pcap-namedb.h,v 1.10.2.1 2005/04/19 04:26:08 guy Exp $ (LBL) */ #ifndef lib_pcap_namedb_h #define lib_pcap_namedb_h #ifdef __cplusplus extern "C" { #endif /* * As returned by the pcap_next_etherent() * XXX this stuff doesn't belong in this interface, but this * library already must do name to address translation, so * on systems that don't have support for /etc/ethers, we * export these hooks since they'll */ struct pcap_etherent { u_char addr[6]; char name[122]; }; #ifndef PCAP_ETHERS_FILE #define PCAP_ETHERS_FILE "/etc/ethers" #endif struct pcap_etherent *pcap_next_etherent(FILE *); u_char *pcap_ether_hostton(const char*); u_char *pcap_ether_aton(const char *); bpf_u_int32 **pcap_nametoaddr(const char *); #ifdef INET6 struct addrinfo *pcap_nametoaddrinfo(const char *); #endif bpf_u_int32 pcap_nametonetaddr(const char *); int pcap_nametoport(const char *, int *, int *); int pcap_nametoportrange(const char *, int *, int *, int *); int pcap_nametoproto(const char *); int pcap_nametoeproto(const char *); int pcap_nametollc(const char *); /* * If a protocol is unknown, PROTO_UNDEF is returned. * Also, pcap_nametoport() returns the protocol along with the port number. * If there are ambiguous entried in /etc/services (i.e. domain * can be either tcp or udp) PROTO_UNDEF is returned. */ #define PROTO_UNDEF -1 /* XXX move these to pcap-int.h? */ int __pcap_atodn(const char *, bpf_u_int32 *); int __pcap_atoin(const char *, bpf_u_int32 *); u_short __pcap_nametodnaddr(const char *); #ifdef __cplusplus } #endif #endif libpcap-0.9.7/./sll.h0000644000026300017500000001257407501426660012402 0ustar mcrmcr/*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) $Header: /tcpdump/master/libpcap/sll.h,v 1.7 2002/06/11 17:04:48 itojun Exp $ (LBL) */ /* * For captures on Linux cooked sockets, we construct a fake header * that includes: * * a 2-byte "packet type" which is one of: * * LINUX_SLL_HOST packet was sent to us * LINUX_SLL_BROADCAST packet was broadcast * LINUX_SLL_MULTICAST packet was multicast * LINUX_SLL_OTHERHOST packet was sent to somebody else * LINUX_SLL_OUTGOING packet was sent *by* us; * * a 2-byte Ethernet protocol field; * * a 2-byte link-layer type; * * a 2-byte link-layer address length; * * an 8-byte source link-layer address, whose actual length is * specified by the previous value. * * All fields except for the link-layer address are in network byte order. * * DO NOT change the layout of this structure, or change any of the * LINUX_SLL_ values below. If you must change the link-layer header * for a "cooked" Linux capture, introduce a new DLT_ type (ask * "tcpdump-workers@tcpdump.org" for one, so that you don't give it a * value that collides with a value already being used), and use the * new header in captures of that type, so that programs that can * handle DLT_LINUX_SLL captures will continue to handle them correctly * without any change, and so that capture files with different headers * can be told apart and programs that read them can dissect the * packets in them. */ /* * A DLT_LINUX_SLL fake link-layer header. */ #define SLL_HDR_LEN 16 /* total header length */ #define SLL_ADDRLEN 8 /* length of address field */ struct sll_header { u_int16_t sll_pkttype; /* packet type */ u_int16_t sll_hatype; /* link-layer address type */ u_int16_t sll_halen; /* link-layer address length */ u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */ u_int16_t sll_protocol; /* protocol */ }; /* * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the * PACKET_ values on Linux, but are defined here so that they're * available even on systems other than Linux, and so that they * don't change even if the PACKET_ values change. */ #define LINUX_SLL_HOST 0 #define LINUX_SLL_BROADCAST 1 #define LINUX_SLL_MULTICAST 2 #define LINUX_SLL_OTHERHOST 3 #define LINUX_SLL_OUTGOING 4 /* * The LINUX_SLL_ values for "sll_protocol"; these correspond to the * ETH_P_ values on Linux, but are defined here so that they're * available even on systems other than Linux. We assume, for now, * that the ETH_P_ values won't change in Linux; if they do, then: * * if we don't translate them in "pcap-linux.c", capture files * won't necessarily be readable if captured on a system that * defines ETH_P_ values that don't match these values; * * if we do translate them in "pcap-linux.c", that makes life * unpleasant for the BPF code generator, as the values you test * for in the kernel aren't the values that you test for when * reading a capture file, so the fixup code run on BPF programs * handed to the kernel ends up having to do more work. * * Add other values here as necessary, for handling packet types that * might show up on non-Ethernet, non-802.x networks. (Not all the ones * in the Linux "if_ether.h" will, I suspect, actually show up in * captures.) */ #define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */ #define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */ libpcap-0.9.7/./aclocal.m40000644000026300017500000006116310231620421013256 0ustar mcrmcrdnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.85.2.1 2005/04/21 03:42:09 guy Exp $ (LBL) dnl dnl Copyright (c) 1995, 1996, 1997, 1998 dnl The Regents of the University of California. All rights reserved. dnl 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 dnl LBL autoconf macros dnl dnl 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 dnl usage: dnl dnl AC_LBL_C_INIT(copt, incls) dnl dnl results: dnl dnl $1 (copt set) dnl $2 (incls set) dnl CC dnl LDFLAGS dnl ac_cv_lbl_gcc_vers dnl LBL_CFLAGS dnl 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 ], [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 ], [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,1,[needed on HP-UX]) ;; *) 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 ], [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 ]) # # Try compiling a sample of the type of code that appears in # gencode.c with "inline", "__inline__", and "__inline". # # Autoconf's AC_C_INLINE, at least in autoconf 2.13, isn't good enough, # as it just tests whether a function returning "int" can be inlined; # at least some versions of HP's C compiler can inline that, but can't # inline a function that returns a struct pointer. # # Make sure we use the V_CCOPT flags, because some of those might # disable inlining. # AC_DEFUN(AC_LBL_C_INLINE, [AC_MSG_CHECKING(for inline) save_CFLAGS="$CFLAGS" CFLAGS="$V_CCOPT" AC_CACHE_VAL(ac_cv_lbl_inline, [ ac_cv_lbl_inline="" ac_lbl_cc_inline=no for ac_lbl_inline in inline __inline__ __inline do AC_TRY_COMPILE( [#define inline $ac_lbl_inline static inline struct iltest *foo(void); struct iltest { int iltest1; int iltest2; }; static inline struct iltest * foo() { static struct iltest xxx; return &xxx; }],,ac_lbl_cc_inline=yes,) if test "$ac_lbl_cc_inline" = yes ; then break; fi done if test "$ac_lbl_cc_inline" = yes ; then ac_cv_lbl_inline=$ac_lbl_inline fi]) CFLAGS="$save_CFLAGS" if test ! -z "$ac_cv_lbl_inline" ; then AC_MSG_RESULT($ac_cv_lbl_inline) else AC_MSG_RESULT(no) fi AC_DEFINE_UNQUOTED(inline, $ac_cv_lbl_inline, [Define as token for inline if inlining supported])]) dnl 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 dnl usage: dnl dnl AC_LBL_LIBPCAP(pcapdep, incls) dnl dnl results: dnl dnl $1 (pcapdep set) dnl $2 (incls appended) dnl LIBS dnl LBL_LIBS dnl 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 dnl Define RETSIGTYPE and RETSIGVAL dnl dnl usage: dnl dnl AC_LBL_TYPE_SIGNAL dnl dnl results: dnl dnl RETSIGTYPE (defined) dnl RETSIGVAL (defined) dnl 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,[],[return value of signal handlers]) else AC_DEFINE(RETSIGVAL,(0),[return value of signal handlers]) fi case "$target_os" in irix*) AC_DEFINE(_BSD_SIGNALS,1,[get BSD semantics on Irix]) ;; *) dnl prefer sigset() to sigaction() AC_CHECK_FUNCS(sigset) if test $ac_cv_func_sigset = no ; then AC_CHECK_FUNCS(sigaction) fi ;; esac]) dnl dnl If using gcc, make sure we have ANSI ioctl definitions dnl dnl usage: dnl dnl AC_LBL_FIXINCLUDES dnl 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 # include # include # ifdef HAVE_SYS_IOCCOM_H # include # 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 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 dnl usage: dnl dnl AC_LBL_LEX_AND_YACC(lex, yacc, yyprefix) dnl dnl results: dnl dnl $1 (lex set) dnl $2 (yacc appended) dnl $3 (optional flex and bison -P prefix) dnl 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 dnl Checks to see if union wait is used with WEXITSTATUS() dnl dnl usage: dnl dnl AC_LBL_UNION_WAIT dnl dnl results: dnl dnl DECLWAITSTATUS (defined) dnl 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 # include ], [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,[type for wait]) else AC_DEFINE(DECLWAITSTATUS,int,[type for wait]) fi]) dnl dnl Checks to see if the sockaddr struct has the 4.4 BSD sa_len member dnl dnl usage: dnl dnl AC_LBL_SOCKADDR_SA_LEN dnl dnl results: dnl dnl HAVE_SOCKADDR_SA_LEN (defined) dnl 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 # include ], [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,1,[if struct sockaddr has sa_len]) fi]) dnl dnl Checks to see if there's a sockaddr_storage structure dnl dnl usage: dnl dnl AC_LBL_SOCKADDR_STORAGE dnl dnl results: dnl dnl HAVE_SOCKADDR_STORAGE (defined) dnl AC_DEFUN(AC_LBL_SOCKADDR_STORAGE, [AC_MSG_CHECKING(if sockaddr_storage struct exists) AC_CACHE_VAL(ac_cv_lbl_has_sockaddr_storage, AC_TRY_COMPILE([ # include # include ], [u_int i = sizeof (struct sockaddr_storage)], ac_cv_lbl_has_sockaddr_storage=yes, ac_cv_lbl_has_sockaddr_storage=no)) AC_MSG_RESULT($ac_cv_lbl_has_sockaddr_storage) if test $ac_cv_lbl_has_sockaddr_storage = yes ; then AC_DEFINE(HAVE_SOCKADDR_STORAGE,1,[if struct sockaddr_storage exists]) fi]) dnl dnl Checks to see if the dl_hp_ppa_info_t struct has the HP-UX 11.00 dnl dl_module_id_1 member dnl dnl usage: dnl dnl AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1 dnl dnl results: dnl dnl HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 (defined) dnl dnl NOTE: any compile failure means we conclude that it doesn't have dnl that member, so if we don't have DLPI, don't have a dnl header, or have one that doesn't declare a dl_hp_ppa_info_t type, dnl we conclude it doesn't have that member (which is OK, as either we dnl won't be using code that would use that member, or we wouldn't dnl compile in any case). dnl AC_DEFUN(AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1, [AC_MSG_CHECKING(if dl_hp_ppa_info_t struct has dl_module_id_1 member) AC_CACHE_VAL(ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1, AC_TRY_COMPILE([ # include # include # include ], [u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1)], ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes, ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=no)) AC_MSG_RESULT($ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1) if test $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1 = yes ; then AC_DEFINE(HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1,1,[if ppa_info_t_dl_module_id exists]) fi]) dnl dnl Checks to see if -R is used dnl dnl usage: dnl dnl AC_LBL_HAVE_RUN_PATH dnl dnl results: dnl dnl ac_cv_lbl_have_run_path (yes or no) dnl 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 fi rm -f conftest*]) AC_MSG_RESULT($ac_cv_lbl_have_run_path) ]) dnl dnl Due to the stupid way it's implemented, AC_CHECK_TYPE is nearly useless. dnl dnl usage: dnl dnl AC_LBL_CHECK_TYPE dnl dnl results: dnl dnl int32_t (defined) dnl u_int32_t (defined) dnl 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 # if STDC_HEADERS # include # include # 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, [if we have $1]) fi]) dnl dnl Checks to see if unaligned memory accesses fail dnl dnl usage: dnl dnl AC_LBL_UNALIGNED_ACCESS dnl dnl results: dnl dnl LBL_ALIGN (DEFINED) dnl AC_DEFUN(AC_LBL_UNALIGNED_ACCESS, [AC_MSG_CHECKING(if unaligned accesses fail) AC_CACHE_VAL(ac_cv_lbl_unaligned_fail, [case "$host_cpu" in # # These are CPU types where: # # the CPU faults on an unaligned access, but at least some # OSes that support that CPU catch the fault and simulate # the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) - # the simulation is slow, so we don't want to use it; # # the CPU, I infer (from the old # # XXX: should also check that they don't do weird things (like on arm) # # comment) doesn't fault on unaligned accesses, but doesn't # do a normal unaligned fetch, either (e.g., presumably, ARM); # # for whatever reason, the test program doesn't work # (this has been claimed to be the case for several of those # CPUs - I don't know what the problem is; the problem # was reported as "the test program dumps core" for SuperH, # but that's what the test program is *supposed* to do - # it dumps core before it writes anything, so the test # for an empty output file should find an empty output # file and conclude that unaligned accesses don't work). # # This run-time test won't work if you're cross-compiling, so # in order to support cross-compiling for a particular CPU, # we have to wire in the list of CPU types anyway, as far as # I know, so perhaps we should just have a set of CPUs on # which we know it doesn't work, a set of CPUs on which we # know it does work, and have the script just fail on other # cpu types and update it when such a failure occurs. # alpha*|arm*|hp*|mips*|sh*|sparc*|ia64|nv1) ac_cv_lbl_unaligned_fail=yes ;; *) cat >conftest.c < # include # include 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); } EOF ${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,1,[if unaligned access fails]) fi]) dnl 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 dnl usage: dnl dnl AC_LBL_DEVEL(copt) dnl dnl results: dnl dnl $1 (copt appended) dnl HAVE_OS_PROTO_H (defined) dnl os-proto.h (symlinked) dnl 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,1,[if there's an os_proto.h]) else AC_MSG_WARN(can't find $name) fi fi]) dnl dnl Improved version of AC_CHECK_LIB dnl dnl Thanks to John Hawkinson (jhawk@mit.edu) dnl dnl usage: dnl dnl AC_LBL_CHECK_LIB(LIBRARY, FUNCTION [, ACTION-IF-FOUND [, dnl ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]]) dnl dnl results: dnl dnl LIBS dnl 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 fi ]) dnl dnl AC_LBL_LIBRARY_NET dnl 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 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 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 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). dnl AC_DEFUN(AC_LBL_LIBRARY_NET, [ # Most operating systems have gethostbyname() in the default searched # libraries (i.e. libc): # Some OSes (eg. Solaris) place it in libnsl # Some strange OSes (SINIX) have it in libsocket: AC_SEARCH_LIBS(gethostbyname, nsl socket resolv) # Unfortunately libsocket sometimes depends on libnsl and # AC_SEARCH_LIBS isn't up to the task of handling dependencies like this. if test "$ac_cv_search_gethostbyname" = "no" then AC_CHECK_LIB(socket, gethostbyname, LIBS="-lsocket -lnsl $LIBS", , -lnsl) fi AC_SEARCH_LIBS(socket, socket, , AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , -lnsl)) # DLPI needs putmsg under HPUX so test for -lstr while we're at it AC_SEARCH_LIBS(putmsg, str) ]) dnl dnl Test for __attribute__ dnl AC_DEFUN(AC_C___ATTRIBUTE__, [ AC_MSG_CHECKING(for __attribute__) AC_CACHE_VAL(ac_cv___attribute__, [ AC_COMPILE_IFELSE( AC_LANG_SOURCE([[ #include static void foo(void) __attribute__ ((noreturn)); static void foo(void) { exit(1); } int main(int argc, char **argv) { foo(); } ]]), ac_cv___attribute__=yes, ac_cv___attribute__=no)]) if test "$ac_cv___attribute__" = "yes"; then AC_DEFINE(HAVE___ATTRIBUTE__, 1, [define if your compiler has __attribute__]) V_DEFS="$V_DEFS -D_U_=\"__attribute__((unused))\"" else V_DEFS="$V_DEFS -D_U_=\"\"" fi AC_MSG_RESULT($ac_cv___attribute__) ]) dnl dnl Checks to see if tpacket_stats is defined in linux/if_packet.h dnl If so then pcap-linux.c can use this to report proper statistics. dnl dnl -Scott Barron dnl AC_DEFUN(AC_LBL_TPACKET_STATS, [AC_MSG_CHECKING(if if_packet.h has tpacket_stats defined) AC_CACHE_VAL(ac_cv_lbl_tpacket_stats, AC_TRY_COMPILE([ # include ], [struct tpacket_stats stats], ac_cv_lbl_tpacket_stats=yes, ac_cv_lbl_tpacket_stats=no)) AC_MSG_RESULT($ac_cv_lbl_tpacket_stats) if test $ac_cv_lbl_tpacket_stats = yes; then AC_DEFINE(HAVE_TPACKET_STATS,1,[if if_packet.h has tpacket_stats defined]) fi]) libpcap-0.9.7/./doc/0000755000026300017500000000000010245661227012172 5ustar mcrmcrlibpcap-0.9.7/./doc/pcap.html0000644000026300017500000016212410034340422013774 0ustar mcrmcr PCAP New Generation Dump File Format
 TOC 
Network Working GroupL. Degioanni
Internet-DraftF. Risso
Expires: August 30, 2004Politecnico di Torino
 March 2004

PCAP New Generation Dump File Format

pcap

Status of this Memo

This document is an Internet-Draft and is in full conformance with all provisions of Section 10 of RFC2026.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

The list of Internet-Draft Shadow Directories can be accessed at http://www.ietf.org/shadow.html.

This Internet-Draft will expire on August 30, 2004.

Copyright Notice

Copyright (C) The Internet Society (2004). All Rights Reserved.

Abstract

This document describes a format to dump captured packets on a file. This format is extensible and it is currently proposed for implementation in the libpcap/WinPcap packet capture library.



Table of Contents

1.  Objectives
2.  General File Structure
2.1  General Block Structure
2.2  Block Types
2.3  Block Hierarchy and Precedence
2.4  Data format
3.  Block Definition
3.1  Section Header Block (mandatory)
3.2  Interface Description Block (mandatory)
3.3  Packet Block (optional)
3.4  Simple Packet Block (optional)
3.5  Name Resolution Block (optional)
3.6  Interface Statistics Block (optional)
4.  Options
5.  Experimental Blocks (deserved to a further investigation)
5.1  Other Packet Blocks (experimental)
5.2  Compression Block (experimental)
5.3  Encryption Block (experimental)
5.4  Fixed Length Block (experimental)
5.5  Directory Block (experimental)
5.6  Traffic Statistics and Monitoring Blocks (experimental)
5.7  Event/Security Block (experimental)
6.  Conclusions
7.  Most important open issues
§  Intellectual Property and Copyright Statements




 TOC 

1. Objectives

The problem of exchanging packet traces becomes more and more critical every day; unfortunately, no standard solutions exist for this task right now. One of the most accepted packet interchange formats is the one defined by libpcap, which is rather old and does not fit for some of the nowadays applications especially in terms of extensibility.

This document proposes a new format for dumping packet traces. The following goals are being pursued:

  • Extensibility: aside of some common functionalities, third parties should be able to enrich the information embedded in the file with proprietary extensions, which will be ignored by tools that are not able to understand them.
  • Portability: a capture trace must contain all the information needed to read data independently from network, hardware and operating system of the machine that made the capture.
  • Merge/Append data: it should be possible to add data at the end of a given file, and the resulting file must still be readable.


 TOC 

2. General File Structure

2.1 General Block Structure

A capture file is organized in blocks, that are appended one to another to form the file. All the blocks share a common format, which is shown in Figure 1.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          Block Type                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Block Total Length                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                          Block Body                           /
   /          /* variable length, aligned to 32 bits */            /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Block Total Length                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 Basic block structure. 

The fields have the following meaning:

  • Block Type (32 bits): unique value that identifies the block. Values whose Most Significant Bit (MSB) is equal to 1 are reserved for local use. They allow to save private data to the file and to extend the file format.
  • Block Total Length: total size of this block, in bytes. For instance, a block that does not have a body has a length of 12 bytes.
  • Block Body: content of the block.
  • Block Total Length: total size of this block, in bytes. This field is duplicated for permitting backward file navigation.

This structure, shared among all blocks, makes easy to process a file and to skip unneeded or unknown blocks. Blocks can be nested one inside the others (NOTE: needed?). Some of the blocks are mandatory, i.e. a dump file is not valid if they are not present, other are optional.

The structure of the blocks allows to define other blocks if needed. A parser that does non understand them can simply ignore their content.

2.2 Block Types

The currently defined blocks are the following:

  1. Section Header Block: it defines the most important characteristics of the capture file.
  2. Interface Description Block: it defines the most important characteristics of the interface(s) used for capturing traffic.
  3. Packet Block: it contains a single captured packet, or a portion of it.
  4. Simple Packet Block: it contains a single captured packet, or a portion of it, with only a minimal set of information about it.
  5. Name Resolution Block: it defines the mapping from numeric addresses present in the packet dump and the canonical name counterpart.
  6. Capture Statistics Block: it defines how to store some statistical data (e.g. packet dropped, etc) which can be useful to undestand the conditions in which the capture has been made.
  7. Compression Marker Block: TODO
  8. Encryption Marker Block: TODO
  9. Fixed Length Marker Block: TODO

The following blocks instead are considered interesting but the authors believe that they deserve more in-depth discussion before being defined:

  1. Further Packet Blocks
  2. Directory Block
  3. Traffic Statistics and Monitoring Blocks
  4. Alert and Security Blocks

TODO Currently standardized Block Type codes are specified in Appendix 1.

2.3 Block Hierarchy and Precedence

The file must begin with a Section Header Block. However, more than one Section Header Block can be present on the dump, each one covering the data following it till the next one (or the end of file). A Section includes the data delimited by two Section Header Blocks (or by a Section Header Block and the end of the file), including the first Section Header Block.

In case an application cannot read a Section because of different version number, it must skip everything until the next Section Header Block. Note that, in order to properly skip the blocks until the next section, all blocks must have the fields Type and Length at the beginning. This is a mandatory requirement that must be maintained in future versions of the block format.

Figure 2 shows two valid files: the first has a typical configuration, with a single Section Header that covers the whole file. The second one contains three headers, and is normally the result of file concatenation. An application that understands only version 1.0 of the file format skips the intermediate section and restart processing the packets after the third Section Header.



   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | SHB v1.0  |                      Data                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   Typical configuration with a single Section Header Block 


   |--   1st Section   --|--   2nd Section   --|--  3rd Section  --|
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | SHB v1.0  |  Data   | SHB V1.1  |  Data   | SHB V1.0  |  Data |  
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   Configuration with three different Section Header Blocks
 File structure example: the Section Header Block. 

NOTE: TO BE COMPLETED with some examples of other blocks

2.4 Data format

Data contained in each section will always be saved according to the characteristics (little endian / big endian) of the dumping machine. This refers to all fields that are saved as numbers and that span over two or more bytes.

The approach of having each section saved in the native format of the generating host is more efficient because it avoids translation of data when reading / writing on the host itself, which is the most common case when generating/processing capture dumps.

TODO Probably we have to specify something more here. Is what we're saying enough to avoid any kind of ambiguity?.



 TOC 

3. Block Definition

This section details the format of the body of the blocks currently defined.

3.1 Section Header Block (mandatory)

The Section Header Block is mandatory. It identifies the beginning of a section of the capture dump file. Its format is shown in Figure 3.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                            Magic                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              Major            |             Minor             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               / 
   /                      Options (variable)                       / 
   /                                                               / 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 Section Header Block format. 

The meaning of the fields is:

  • Magic: magic number, whose value is the hexadecimal number 0x1A2B3C4D. This number can be used to distinguish section that have been saved on little-endian machines from the one saved on big-endian machines.
  • Major: number of the current mayor version of the format. Current value is 1.
  • Minor: number of the current minor version of the format. Current value is 0.
  • Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present.

Aside form the options defined in Section 4, the following options are valid within this block:

Name Code Length Description
Hardware 2 variable An ascii string containing the description of the hardware used to create this section.
Operating System 3 variable An ascii string containing the name of the operating system used to create this section.
User Application 3 variable An ascii string containing the name of the application used to create this section.

The Section Header Block does not contain data but it rather identifies a list of blocks (interfaces, packets) that are logically correlated. This block does not contain any reference to the size of the section it is currently delimiting, therefore the reader cannot skip a whole section at once. In case a section must be skipped, the user has to repeatedly skip all the blocks contained within it; this makes the parsing of the file slower but it permits to append several capture dumps at the same file.

3.2 Interface Description Block (mandatory)

The Interface Description Block is mandatory. This block is needed to specify the characteristics of the network interface on which the capture has been made. In order to properly associate the captured data to the corresponding interface, the Interface Description Block must be defined before any other block that uses it; therefore, this block is usually placed immediately after the Section Header Block.

An Interface Description Block is valid only inside the section which it belongs to. The structure of a Interface Description Block is shown in Figure 4.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Interface ID         |           LinkType            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                            SnapLen                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               / 
   /                      Options (variable)                       / 
   /                                                               / 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 Interface Description Block format. 

The meaning of the fields is:

  • Interface ID: a progressive number that identifies uniquely any interface inside current section. Two Interface Description Blocks can have the same Interface ID only if they are in different sections of the file. The Interface ID is referenced by the packet blocks.
  • LinkType: a value that defines the link layer type of this interface.
  • SnapLen: maximum number of bytes dumped from each packet. The portion of each packet that exceeds this value will not be stored in the file.
  • Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present.

In addition to the options defined in Section 4, the following options are valid within this block:

Name Code Length Description
if_name 2 Variable Name of the device used to capture data.
if_IPv4addr 3 8 Interface network address and netmask.
if_IPv6addr 4 17 Interface network address and prefix length (stored in the last byte).
if_MACaddr 5 6 Interface Hardware MAC address (48 bits).
if_EUIaddr 6 8 Interface Hardware EUI address (64 bits), if available.
if_speed 7 8 Interface speed (in bps).
if_tsaccur 8 1 Precision of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as a negative power of 10 (e.g. 6 means microsecond accuracy). If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a precision of 10^-6 is assumed.
if_tzone 9 4 Time zone for GMT support (TODO: specify better).
if_flags 10 4 Interface flags. (TODO: specify better. Possible flags: promiscuous, inbound/outbound, traffic filtered during capture).
if_filter 11 variable The filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO).
if_opersystem 12 variable An ascii string containing the name of the operating system of the machine that hosts this interface. This can be different from the same information that can be contained by the Section Header Block (Section 3.1) because the capture can have been done on a remote machine.

3.3 Packet Block (optional)

A Packet Block is the standard container for storing the packets coming from the network. The Packet Block is optional because packets can be stored either by means of this block or the Simple Packet Block, which can be used to speed up dump generation. The format of a packet block is shown in Figure 5.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Interface ID          |          Drops Count          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Timestamp (High)                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Timestamp (Low)                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Captured Len                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          Packet Len                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   |                          Packet Data                          |
   |                                                               |
   |              /* variable length, byte-aligned */              |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               / 
   /                      Options (variable)                       / 
   /                                                               / 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 Packet Block format. 

The Packet Block has the following fields:

  • Interface ID: Specifies the interface this packet comes from, and corresponds to the ID of one of the Interface Description Blocks present in this section of the file (see Figure 4).
  • Drops Count: a local drop counter. It specified the number of packets lost (by the interface and the operating system) between this packet and the preceding one. The value xFFFF (in hexadecimal) is reserved for those systems in which this information is not available.
  • Timestamp (High): the most significative part of the timestamp. in standard Unix format, i.e. from 1/1/1970.
  • Timestamp (Low): the less significative part of the timestamp. The way to interpret this field is specified by the 'ts_accur' option (see Figure 4) of the Interface Description block referenced by this packet. If the Interface Description block does not contain a 'ts_accur' option, then this field is expressed in microseconds.
  • Captured Len: number of bytes captured from the packet (i.e. the length of the Packet Data field). It will be the minimum value among the actual Packet Length and the snapshot length (defined in Figure 4).
  • Packet Len: actual length of the packet when it was transmitted on the network. Can be different from Captured Len if the user wants only a snapshot of the packet.
  • Packet Data: the data coming from the network, including link-layer headers. The length of this field is Captured Len. The format of the link-layer headers depends on the LinkType field specified in the Interface Description Block (see Section 3.2) and it is specified in Appendix XXX (TODO).
  • Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present.

3.4 Simple Packet Block (optional)

The Simple Packet Block is a lightweight container for storing the packets coming from the network. Its presence is optional.

A Simple Packet Block is similar to a Packet Block (see Section 3.3), but it is smaller, simpler to process and contains only a minimal set of information. This block is preferred to the standard Packet Block when performance or space occupation are critical factors, such as in sustained traffic dump applications. A capture file can contain both Packet Blocks and Simple Packet Blocks: for example, a capture tool could switch from Packet Blocks to Simple Packet Blocks when the hardware resources become critical.

The Simple Packet Block does not contain the Interface ID field. Therefore, it must be assumed that all the Simple Packet Blocks have been captured on the interface previously specified in the Interface Description Block.

Figure 6 shows the format of the Simple Packet Block.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          Packet Len                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   |                          Packet Data                          |
   |                                                               |
   |              /* variable length, byte-aligned */              |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 Simple Packet Block format. 

The Packet Block has the following fields:

  • Packet Len: actual length of the packet when it was transmitted on the network. Can be different from captured len if the packet has been truncated.
  • Packet data: the data coming from the network, including link-layers headers. The length of this field can be derived from the field Block Total Length, present in the Block Header.

The Simple Packet Block does not contain the timestamp because this is one of the most costly operations on PCs. Additionally, there are applications that do not require it; e.g. an Intrusion Detection System is interested in packets, not in their timestamp.

The Simple Packet Block is very efficient in term of disk space: a snapshot of length 100 bytes requires only 16 bytes of overhead, which corresponds to an efficiency of more than 86%.

3.5 Name Resolution Block (optional)

The Name Resolution Block is used to support the correlation of numeric addresses (present in the captured packets) and their corresponding canonical names and it is optional. Having the literal names saved in the file, this prevents the need of a name resolution in a delayed time, when the association between names and addresses can be different from the one in use at capture time. Moreover, The Name Resolution Block avoids the need of issuing a lot of DNS requests every time the trace capture is opened, and allows to have name resolution also when reading the capture with a machine not connected to the network.

The format of the Name Resolution Block is shown in Figure 7.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      Record Type              |         Record Length         | 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Record Value                            |
   |              /* variable length, byte-aligned */              |
   |               + + + + + + + + + + + + + + + + + + + + + + + + +
   |               |               |               |               |
   +-+-+-+-+-+-+-+-+ + + + + + + + + + + + + + + + + + + + + + + + +
             . . . other records . . .
   |  Record Type == end_of_recs   |  Record Length == 00          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               / 
   /                      Options (variable)                       / 
   /                                                               / 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 Name Resolution Block format. 

A Name Resolution Block is a zero-terminated list of records (in the TLV format), each of which contains an association between a network address and a name. There are three possible types of records:

Name Code Length Description
end_of_recs 0 0 End of records
ip4_rec 1 Variable Specifies an IPv4 address (contained in the first 4 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address.
ip6_rec 1 Variable Specifies an IPv6 address (contained in the first 16 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address.

After the list or Name Resolution Records, optionally, a list of options (formatted according to the rules defined in Section 4) can be present.

A Name Resolution Block is normally placed at the beginning of the file, but no assumptions can be taken about its position. Name Resolution Blocks can be added in a second time by tools that process the file, like network analyzers.

In addiction to the options defined in Section 4, the following options are valid within this block:

Name Code Length Description
ns_dnsname 2 Variable An ascii string containing the name of the machine (DNS server) used to perform the name resolution.

3.6 Interface Statistics Block (optional)

The Interface Statistics Block contains the capture statistics for a given interface and it is optional. The statistics are referred to the interface defined in the current Section identified by the Interface ID field.

The format of the Interface Statistics Block is shown in Figure 8.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         IfRecv                                |
   |                          (high + low)                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         IfDrop                                |
   |                          (high + low)                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         FilterAccept                          |
   |                          (high + low)                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         OSDrop                                |
   |                          (high + low)                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         UsrDelivered                          |
   |                          (high + low)                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Interface ID         |           Reserved            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               / 
   /                      Options (variable)                       / 
   /                                                               / 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 Interface Statistics Block format. 

The fields have the following meaning:

  • IfRecv: number of packets received from the interface during the capture. This number is reported as a 64 bits value, in which the most significat bits are located in the first four bytes of the field.
  • IfDrop: number of packets dropped by the interface during the capture due to lack of resources.
  • FilterAccept: number of packets accepeted by filter during current capture.
  • OSDrop: number of packets dropped by the operating system during the capture.
  • UsrDelivered: number of packets delivered to the user. UsrDelivered can be different from the value 'FilterAccept - OSDropped' because some packets could still lay in the OS buffers when the capture ended.
  • Interface ID: reference to an Interface Description Block.
  • Reserved: Reserved to future use.
  • Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present.

In addiction to the options defined in Section 4, the following options are valid within this block:

Name Code Length Description
isb_starttime 2 8 Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds.
isb_endtime 3 8 Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds.


 TOC 

4. Options

Almost all blocks have the possibility to embed optional fields. Optional fields can be used to insert some information that may be useful when reading data, but that it is not really needed for packet processing. Therefore, each tool can be either read the content of the optional fields (if any), or skip them at once.

Skipping all the optional fields at once is straightforward because most of the blocks have a fixed length, therefore the field Block Length (present in the General Block Structure, see Section 2.1) can be used to skip everything till the next block.

Options are a list of Type - Length - Value fields, each one containing a single value:

  • Option Type (2 bytes): it contains the code that specifies the type of the current TLV record. Option types whose Most Significant Bit is equal to one are reserved for local use; therefore, there is no guarantee that the code used is unique among all capture files (generated by other applications). In case of vendor-specific extensions that have to be identified uniquely, vendors must request an Option Code whose MSB is equal to zero.
  • Option Length (2 bytes): it contains the length of the following 'Option Value' field.
  • Option Value (variable length): it contains the value of the given option. The length of this field as been specified by the Option Length field.

Options may be repeated several times (e.g. an interface that has several IP addresses associated to it). The option list is terminated by a special code which is the 'End of Option'.

The format of the optional fields is shown in Figure 9.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      Option Code              |         Option Length         | 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Option Value                            |
   |              /* variable length, byte-aligned */              |
   |               + + + + + + + + + + + + + + + + + + + + + + + + +
   |               /               /               /               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               /
   /                 . . . other options . . .                     /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Option Code == opt_endofopt  |  Option Length == 0          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 Options format. 

The following codes can always be present in any optional field:

Name Code Length Description
opt_endofopt 0 0 End of options: it is used to delimit the end of the optional fields. This block cannot be repeated within a given list of options.
opt_comment 1 variable Comment: it is an ascii string containing a comment that is associated to the current block.


 TOC 

5. Experimental Blocks (deserved to a further investigation)

5.1 Other Packet Blocks (experimental)

Can some other packet blocks (besides the two described in the previous paragraphs) be useful?

5.2 Compression Block (experimental)

The Compression Block is optional. A file can contain an arbitrary number of these blocks. A Compression Block, as the name says, is used to store compressed data. Its format is shown in Figure 10.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Compr. Type  |                                               |
   +-+-+-+-+-+-+-+-+                                               |
   |                                                               |
   |                       Compressed Data                         |
   |                                                               |
   |              /* variable length, byte-aligned */              |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 Compression Block format. 

The fields have the following meaning:

  • Compression Type: specifies the compression algorithm. Possible values for this field are 0 (uncompressed), 1 (Lempel Ziv), 2 (Gzip), other?? Probably some kind of dumb and fast compression algorithm could be effective with some types of traffic (for example web), but which?
  • Compressed Data: data of this block. Once decompressed, it is made of other blocks.

5.3 Encryption Block (experimental)

The Encryption Block is optional. A file can contain an arbitrary number of these blocks. An Encryption Block is used to sotre encrypted data. Its format is shown in Figure 11.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Encr. Type  |                                               |
   +-+-+-+-+-+-+-+-+                                               |
   |                                                               |
   |                       Compressed Data                         |
   |                                                               |
   |              /* variable length, byte-aligned */              |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 Encryption Block format. 

The fields have the following meaning:

  • Compression Type: specifies the encryption algorithm. Possible values for this field are ??? NOTE: this block should probably contain other fields, depending on the encryption algorithm. To be define precisely.
  • Encrypted Data: data of this block. Once decripted, it consists of other blocks.

5.4 Fixed Length Block (experimental)

The Fixed Length Block is optional. A file can contain an arbitrary number of these blocks. A Fixed Length Block can be used to optimize the access to the file. Its format is shown in Figure 12. A Fixed Length Block stores records with constant size. It contains a set of Blocks (normally Packet Blocks or Simple Packet Blocks), of wihich it specifies the size. Knowing this size a priori helps to scan the file and to load some portions of it without truncating a block, and is particularly useful with cell-based networks like ATM.



    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Cell Size            |                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
   |                                                               |
   |                        Fixed Size Data                        |
   |                                                               |
   |              /* variable length, byte-aligned */              |
   |                                                               |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 Fixed Length Block format. 

The fields have the following meaning:

  • Cell size: the size of the blocks contained in the data field.
  • Fixed Size Data: data of this block.

5.5 Directory Block (experimental)

If present, this block contains the following information:

  • number of indexed packets (N)
  • table with position and length of any indexed packet (N entries)

A directory block must be followed by at least N packets, otherwise it must be considered invalid. It can be used to efficiently load portions of the file to memory and to support operations on memory mapped files. This block can be added by tools like network analyzers as a consequence of file processing.

5.6 Traffic Statistics and Monitoring Blocks (experimental)

One or more blocks could be defined to contain network statistics or traffic monitoring information. They could be use to store data collected from RMON or Netflow probes, or from other network monitoring tools.

5.7 Event/Security Block (experimental)

This block could be used to store events. Events could contain generic information (for example network load over 50%, server down...) or security alerts. An event could be:

  • skipped, if the application doesn't know how to do with it
  • processed independently by the packets. In other words, the applications skips the packets and processes only the alerts
  • processed in relation to packets: for example, a security tool could load only the packets of the file that are near a security alert; a monitorg tool could skip the packets captured while the server was down.


 TOC 

6. Conclusions

The file format proposed in this document should be very versatile and satisfy a wide range of applications. In the simplest case, it can contain a raw dump of the network data, made of a series of Simple Packet Blocks. In the most complex case, it can be used as a repository for heterogeneous information. In every case, the file remains easy to parse and an application can always skip the data it is not interested in; at the same time, different applications can share the file, and each of them can benfit of the information produced by the others. Two or more files can be concatenated obtaining another valid file.



 TOC 

7. Most important open issues

  • Data, in the file, must be byte or word aligned? Currently, the structure of this document is not consistent with respect to this point.


 TOC 

Intellectual Property Statement

Full Copyright Statement

Acknowledgment

libpcap-0.9.7/./doc/pcap.xml0000644000026300017500000012262010034340422013625 0ustar mcrmcr PCAP New Generation Dump File Format Politecnico di Torino
Corso Duca degli Abruzzi, 24 Torino 10129 Italy +39 011 564 7008 loris.degioanni@polito.it http://netgroup.polito.it/loris/
Politecnico di Torino
Corso Duca degli Abruzzi, 24 Torino 10129 Italy +39 011 564 7008 fulvio.risso@polito.it http://netgroup.polito.it/fulvio.risso/
General Internet-Draft Libpcap, dump file format This document describes a format to dump captured packets on a file. This format is extensible and it is currently proposed for implementation in the libpcap/WinPcap packet capture library.
The problem of exchanging packet traces becomes more and more critical every day; unfortunately, no standard solutions exist for this task right now. One of the most accepted packet interchange formats is the one defined by libpcap, which is rather old and does not fit for some of the nowadays applications especially in terms of extensibility. This document proposes a new format for dumping packet traces. The following goals are being pursued: Extensibility: aside of some common functionalities, third parties should be able to enrich the information embedded in the file with proprietary extensions, which will be ignored by tools that are not able to understand them. Portability: a capture trace must contain all the information needed to read data independently from network, hardware and operating system of the machine that made the capture. Merge/Append data: it should be possible to add data at the end of a given file, and the resulting file must still be readable.
A capture file is organized in blocks, that are appended one to another to form the file. All the blocks share a common format, which is shown in .
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Block Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Block Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Block Body / / /* variable length, aligned to 32 bits */ / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Block Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The fields have the following meaning: Block Type (32 bits): unique value that identifies the block. Values whose Most Significant Bit (MSB) is equal to 1 are reserved for local use. They allow to save private data to the file and to extend the file format. Block Total Length: total size of this block, in bytes. For instance, a block that does not have a body has a length of 12 bytes. Block Body: content of the block. Block Total Length: total size of this block, in bytes. This field is duplicated for permitting backward file navigation. This structure, shared among all blocks, makes easy to process a file and to skip unneeded or unknown blocks. Blocks can be nested one inside the others (NOTE: needed?). Some of the blocks are mandatory, i.e. a dump file is not valid if they are not present, other are optional. The structure of the blocks allows to define other blocks if needed. A parser that does non understand them can simply ignore their content.
The currently defined blocks are the following: Section Header Block: it defines the most important characteristics of the capture file. Interface Description Block: it defines the most important characteristics of the interface(s) used for capturing traffic. Packet Block: it contains a single captured packet, or a portion of it. Simple Packet Block: it contains a single captured packet, or a portion of it, with only a minimal set of information about it. Name Resolution Block: it defines the mapping from numeric addresses present in the packet dump and the canonical name counterpart. Capture Statistics Block: it defines how to store some statistical data (e.g. packet dropped, etc) which can be useful to undestand the conditions in which the capture has been made. Compression Marker Block: TODO Encryption Marker Block: TODO Fixed Length Marker Block: TODO The following blocks instead are considered interesting but the authors believe that they deserve more in-depth discussion before being defined: Further Packet Blocks Directory Block Traffic Statistics and Monitoring Blocks Alert and Security Blocks TODO Currently standardized Block Type codes are specified in Appendix 1.
The file must begin with a Section Header Block. However, more than one Section Header Block can be present on the dump, each one covering the data following it till the next one (or the end of file). A Section includes the data delimited by two Section Header Blocks (or by a Section Header Block and the end of the file), including the first Section Header Block. In case an application cannot read a Section because of different version number, it must skip everything until the next Section Header Block. Note that, in order to properly skip the blocks until the next section, all blocks must have the fields Type and Length at the beginning. This is a mandatory requirement that must be maintained in future versions of the block format. shows two valid files: the first has a typical configuration, with a single Section Header that covers the whole file. The second one contains three headers, and is normally the result of file concatenation. An application that understands only version 1.0 of the file format skips the intermediate section and restart processing the packets after the third Section Header.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SHB v1.0 | Data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Typical configuration with a single Section Header Block |-- 1st Section --|-- 2nd Section --|-- 3rd Section --| | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SHB v1.0 | Data | SHB V1.1 | Data | SHB V1.0 | Data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Configuration with three different Section Header Blocks
NOTE: TO BE COMPLETED with some examples of other blocks
Data contained in each section will always be saved according to the characteristics (little endian / big endian) of the dumping machine. This refers to all fields that are saved as numbers and that span over two or more bytes. The approach of having each section saved in the native format of the generating host is more efficient because it avoids translation of data when reading / writing on the host itself, which is the most common case when generating/processing capture dumps. TODO Probably we have to specify something more here. Is what we're saying enough to avoid any kind of ambiguity?.
This section details the format of the body of the blocks currently defined.
The Section Header Block is mandatory. It identifies the beginning of a section of the capture dump file. Its format is shown in .
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Magic | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Major | Minor | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The meaning of the fields is: Magic: magic number, whose value is the hexadecimal number 0x1A2B3C4D. This number can be used to distinguish section that have been saved on little-endian machines from the one saved on big-endian machines. Major: number of the current mayor version of the format. Current value is 1. Minor: number of the current minor version of the format. Current value is 0. Options: optionally, a list of options (formatted according to the rules defined in ) can be present. Aside form the options defined in , the following options are valid within this block: Name Code Length Description Hardware 2 variable An ascii string containing the description of the hardware used to create this section. Operating System 3 variable An ascii string containing the name of the operating system used to create this section. User Application 3 variable An ascii string containing the name of the application used to create this section. The Section Header Block does not contain data but it rather identifies a list of blocks (interfaces, packets) that are logically correlated. This block does not contain any reference to the size of the section it is currently delimiting, therefore the reader cannot skip a whole section at once. In case a section must be skipped, the user has to repeatedly skip all the blocks contained within it; this makes the parsing of the file slower but it permits to append several capture dumps at the same file.
The Interface Description Block is mandatory. This block is needed to specify the characteristics of the network interface on which the capture has been made. In order to properly associate the captured data to the corresponding interface, the Interface Description Block must be defined before any other block that uses it; therefore, this block is usually placed immediately after the Section Header Block. An Interface Description Block is valid only inside the section which it belongs to. The structure of a Interface Description Block is shown in .
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Interface ID | LinkType | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SnapLen | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The meaning of the fields is: Interface ID: a progressive number that identifies uniquely any interface inside current section. Two Interface Description Blocks can have the same Interface ID only if they are in different sections of the file. The Interface ID is referenced by the packet blocks. LinkType: a value that defines the link layer type of this interface. SnapLen: maximum number of bytes dumped from each packet. The portion of each packet that exceeds this value will not be stored in the file. Options: optionally, a list of options (formatted according to the rules defined in ) can be present. In addition to the options defined in , the following options are valid within this block: Name Code Length Description if_name 2 Variable Name of the device used to capture data. if_IPv4addr 3 8 Interface network address and netmask. if_IPv6addr 4 17 Interface network address and prefix length (stored in the last byte). if_MACaddr 5 6 Interface Hardware MAC address (48 bits). if_EUIaddr 6 8 Interface Hardware EUI address (64 bits), if available. if_speed 7 8 Interface speed (in bps). if_tsaccur 8 1 Precision of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as a negative power of 10 (e.g. 6 means microsecond accuracy). If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a precision of 10^-6 is assumed. if_tzone 9 4 Time zone for GMT support (TODO: specify better). if_flags 10 4 Interface flags. (TODO: specify better. Possible flags: promiscuous, inbound/outbound, traffic filtered during capture). if_filter 11 variable The filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO). if_opersystem 12 variable An ascii string containing the name of the operating system of the machine that hosts this interface. This can be different from the same information that can be contained by the Section Header Block () because the capture can have been done on a remote machine.
A Packet Block is the standard container for storing the packets coming from the network. The Packet Block is optional because packets can be stored either by means of this block or the Simple Packet Block, which can be used to speed up dump generation. The format of a packet block is shown in .
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Interface ID | Drops Count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Timestamp (High) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Timestamp (Low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Captured Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Packet Data | | | | /* variable length, byte-aligned */ | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The Packet Block has the following fields: Interface ID: Specifies the interface this packet comes from, and corresponds to the ID of one of the Interface Description Blocks present in this section of the file (see ). Drops Count: a local drop counter. It specified the number of packets lost (by the interface and the operating system) between this packet and the preceding one. The value xFFFF (in hexadecimal) is reserved for those systems in which this information is not available. Timestamp (High): the most significative part of the timestamp. in standard Unix format, i.e. from 1/1/1970. Timestamp (Low): the less significative part of the timestamp. The way to interpret this field is specified by the 'ts_accur' option (see ) of the Interface Description block referenced by this packet. If the Interface Description block does not contain a 'ts_accur' option, then this field is expressed in microseconds. Captured Len: number of bytes captured from the packet (i.e. the length of the Packet Data field). It will be the minimum value among the actual Packet Length and the snapshot length (defined in ). Packet Len: actual length of the packet when it was transmitted on the network. Can be different from Captured Len if the user wants only a snapshot of the packet. Packet Data: the data coming from the network, including link-layer headers. The length of this field is Captured Len. The format of the link-layer headers depends on the LinkType field specified in the Interface Description Block (see ) and it is specified in Appendix XXX (TODO). Options: optionally, a list of options (formatted according to the rules defined in ) can be present.
The Simple Packet Block is a lightweight container for storing the packets coming from the network. Its presence is optional. A Simple Packet Block is similar to a Packet Block (see ), but it is smaller, simpler to process and contains only a minimal set of information. This block is preferred to the standard Packet Block when performance or space occupation are critical factors, such as in sustained traffic dump applications. A capture file can contain both Packet Blocks and Simple Packet Blocks: for example, a capture tool could switch from Packet Blocks to Simple Packet Blocks when the hardware resources become critical. The Simple Packet Block does not contain the Interface ID field. Therefore, it must be assumed that all the Simple Packet Blocks have been captured on the interface previously specified in the Interface Description Block. shows the format of the Simple Packet Block.
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Packet Data | | | | /* variable length, byte-aligned */ | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The Packet Block has the following fields: Packet Len: actual length of the packet when it was transmitted on the network. Can be different from captured len if the packet has been truncated. Packet data: the data coming from the network, including link-layers headers. The length of this field can be derived from the field Block Total Length, present in the Block Header. The Simple Packet Block does not contain the timestamp because this is one of the most costly operations on PCs. Additionally, there are applications that do not require it; e.g. an Intrusion Detection System is interested in packets, not in their timestamp. The Simple Packet Block is very efficient in term of disk space: a snapshot of length 100 bytes requires only 16 bytes of overhead, which corresponds to an efficiency of more than 86%.
The Name Resolution Block is used to support the correlation of numeric addresses (present in the captured packets) and their corresponding canonical names and it is optional. Having the literal names saved in the file, this prevents the need of a name resolution in a delayed time, when the association between names and addresses can be different from the one in use at capture time. Moreover, The Name Resolution Block avoids the need of issuing a lot of DNS requests every time the trace capture is opened, and allows to have name resolution also when reading the capture with a machine not connected to the network. The format of the Name Resolution Block is shown in .
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Record Type | Record Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Record Value | | /* variable length, byte-aligned */ | | + + + + + + + + + + + + + + + + + + + + + + + + + | | | | | +-+-+-+-+-+-+-+-+ + + + + + + + + + + + + + + + + + + + + + + + + . . . other records . . . | Record Type == end_of_recs | Record Length == 00 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
A Name Resolution Block is a zero-terminated list of records (in the TLV format), each of which contains an association between a network address and a name. There are three possible types of records: Name Code Length Description end_of_recs 0 0 End of records ip4_rec 1 Variable Specifies an IPv4 address (contained in the first 4 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address. ip6_rec 1 Variable Specifies an IPv6 address (contained in the first 16 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address. After the list or Name Resolution Records, optionally, a list of options (formatted according to the rules defined in ) can be present. A Name Resolution Block is normally placed at the beginning of the file, but no assumptions can be taken about its position. Name Resolution Blocks can be added in a second time by tools that process the file, like network analyzers. In addiction to the options defined in , the following options are valid within this block: Name Code Length Description ns_dnsname 2 Variable An ascii string containing the name of the machine (DNS server) used to perform the name resolution.
The Interface Statistics Block contains the capture statistics for a given interface and it is optional. The statistics are referred to the interface defined in the current Section identified by the Interface ID field. The format of the Interface Statistics Block is shown in .
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | IfRecv | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | IfDrop | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | FilterAccept | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | OSDrop | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | UsrDelivered | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Interface ID | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The fields have the following meaning: IfRecv: number of packets received from the interface during the capture. This number is reported as a 64 bits value, in which the most significat bits are located in the first four bytes of the field. IfDrop: number of packets dropped by the interface during the capture due to lack of resources. FilterAccept: number of packets accepeted by filter during current capture. OSDrop: number of packets dropped by the operating system during the capture. UsrDelivered: number of packets delivered to the user. UsrDelivered can be different from the value 'FilterAccept - OSDropped' because some packets could still lay in the OS buffers when the capture ended. Interface ID: reference to an Interface Description Block. Reserved: Reserved to future use. Options: optionally, a list of options (formatted according to the rules defined in ) can be present. In addiction to the options defined in , the following options are valid within this block: Name Code Length Description isb_starttime 2 8 Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds. isb_endtime 3 8 Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds.
Almost all blocks have the possibility to embed optional fields. Optional fields can be used to insert some information that may be useful when reading data, but that it is not really needed for packet processing. Therefore, each tool can be either read the content of the optional fields (if any), or skip them at once. Skipping all the optional fields at once is straightforward because most of the blocks have a fixed length, therefore the field Block Length (present in the General Block Structure, see ) can be used to skip everything till the next block. Options are a list of Type - Length - Value fields, each one containing a single value: Option Type (2 bytes): it contains the code that specifies the type of the current TLV record. Option types whose Most Significant Bit is equal to one are reserved for local use; therefore, there is no guarantee that the code used is unique among all capture files (generated by other applications). In case of vendor-specific extensions that have to be identified uniquely, vendors must request an Option Code whose MSB is equal to zero. Option Length (2 bytes): it contains the length of the following 'Option Value' field. Option Value (variable length): it contains the value of the given option. The length of this field as been specified by the Option Length field. Options may be repeated several times (e.g. an interface that has several IP addresses associated to it). The option list is terminated by a special code which is the 'End of Option'. The format of the optional fields is shown in .
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Option Code | Option Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Option Value | | /* variable length, byte-aligned */ | | + + + + + + + + + + + + + + + + + + + + + + + + + | / / / | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / . . . other options . . . / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Option Code == opt_endofopt | Option Length == 0 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The following codes can always be present in any optional field: Name Code Length Description opt_endofopt 0 0 End of options: it is used to delimit the end of the optional fields. This block cannot be repeated within a given list of options. opt_comment 1 variable Comment: it is an ascii string containing a comment that is associated to the current block.
Can some other packet blocks (besides the two described in the previous paragraphs) be useful?
The Compression Block is optional. A file can contain an arbitrary number of these blocks. A Compression Block, as the name says, is used to store compressed data. Its format is shown in .
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Compr. Type | | +-+-+-+-+-+-+-+-+ | | | | Compressed Data | | | | /* variable length, byte-aligned */ | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The fields have the following meaning: Compression Type: specifies the compression algorithm. Possible values for this field are 0 (uncompressed), 1 (Lempel Ziv), 2 (Gzip), other?? Probably some kind of dumb and fast compression algorithm could be effective with some types of traffic (for example web), but which? Compressed Data: data of this block. Once decompressed, it is made of other blocks.
The Encryption Block is optional. A file can contain an arbitrary number of these blocks. An Encryption Block is used to sotre encrypted data. Its format is shown in .
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Encr. Type | | +-+-+-+-+-+-+-+-+ | | | | Compressed Data | | | | /* variable length, byte-aligned */ | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The fields have the following meaning: Compression Type: specifies the encryption algorithm. Possible values for this field are ??? NOTE: this block should probably contain other fields, depending on the encryption algorithm. To be define precisely. Encrypted Data: data of this block. Once decripted, it consists of other blocks.
The Fixed Length Block is optional. A file can contain an arbitrary number of these blocks. A Fixed Length Block can be used to optimize the access to the file. Its format is shown in . A Fixed Length Block stores records with constant size. It contains a set of Blocks (normally Packet Blocks or Simple Packet Blocks), of wihich it specifies the size. Knowing this size a priori helps to scan the file and to load some portions of it without truncating a block, and is particularly useful with cell-based networks like ATM.
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cell Size | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | | Fixed Size Data | | | | /* variable length, byte-aligned */ | | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The fields have the following meaning: Cell size: the size of the blocks contained in the data field. Fixed Size Data: data of this block.
If present, this block contains the following information: number of indexed packets (N) table with position and length of any indexed packet (N entries) A directory block must be followed by at least N packets, otherwise it must be considered invalid. It can be used to efficiently load portions of the file to memory and to support operations on memory mapped files. This block can be added by tools like network analyzers as a consequence of file processing.
One or more blocks could be defined to contain network statistics or traffic monitoring information. They could be use to store data collected from RMON or Netflow probes, or from other network monitoring tools.
This block could be used to store events. Events could contain generic information (for example network load over 50%, server down...) or security alerts. An event could be: skipped, if the application doesn't know how to do with it processed independently by the packets. In other words, the applications skips the packets and processes only the alerts processed in relation to packets: for example, a security tool could load only the packets of the file that are near a security alert; a monitorg tool could skip the packets captured while the server was down.
The file format proposed in this document should be very versatile and satisfy a wide range of applications. In the simplest case, it can contain a raw dump of the network data, made of a series of Simple Packet Blocks. In the most complex case, it can be used as a repository for heterogeneous information. In every case, the file remains easy to parse and an application can always skip the data it is not interested in; at the same time, different applications can share the file, and each of them can benfit of the information produced by the others. Two or more files can be concatenated obtaining another valid file.
Data, in the file, must be byte or word aligned? Currently, the structure of this document is not consistent with respect to this point.
libpcap-0.9.7/./doc/pcap.txt0000644000026300017500000017626010034340422013655 0ustar mcrmcr Network Working Group L. Degioanni Internet-Draft F. Risso Expires: August 30, 2004 Politecnico di Torino March 2004 PCAP New Generation Dump File Format pcap Status of this Memo This document is an Internet-Draft and is in full conformance with all provisions of Section 10 of RFC2026. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." The list of current Internet-Drafts can be accessed at http:// www.ietf.org/ietf/1id-abstracts.txt. The list of Internet-Draft Shadow Directories can be accessed at http://www.ietf.org/shadow.html. This Internet-Draft will expire on August 30, 2004. Copyright Notice Copyright (C) The Internet Society (2004). All Rights Reserved. Abstract This document describes a format to dump captured packets on a file. This format is extensible and it is currently proposed for implementation in the libpcap/WinPcap packet capture library. Degioanni & Risso Expires August 30, 2004 [Page 1] Internet-Draft PCAP New Generation Dump File Format March 2004 Table of Contents 1. Objectives . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2. General File Structure . . . . . . . . . . . . . . . . . . . . 4 2.1 General Block Structure . . . . . . . . . . . . . . . . . . . 4 2.2 Block Types . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.3 Block Hierarchy and Precedence . . . . . . . . . . . . . . . . 5 2.4 Data format . . . . . . . . . . . . . . . . . . . . . . . . . 6 3. Block Definition . . . . . . . . . . . . . . . . . . . . . . . 8 3.1 Section Header Block (mandatory) . . . . . . . . . . . . . . . 8 3.2 Interface Description Block (mandatory) . . . . . . . . . . . 9 3.3 Packet Block (optional) . . . . . . . . . . . . . . . . . . . 13 3.4 Simple Packet Block (optional) . . . . . . . . . . . . . . . . 15 3.5 Name Resolution Block (optional) . . . . . . . . . . . . . . . 16 3.6 Interface Statistics Block (optional) . . . . . . . . . . . . 18 4. Options . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5. Experimental Blocks (deserved to a further investigation) . . 23 5.1 Other Packet Blocks (experimental) . . . . . . . . . . . . . . 23 5.2 Compression Block (experimental) . . . . . . . . . . . . . . . 23 5.3 Encryption Block (experimental) . . . . . . . . . . . . . . . 23 5.4 Fixed Length Block (experimental) . . . . . . . . . . . . . . 24 5.5 Directory Block (experimental) . . . . . . . . . . . . . . . . 25 5.6 Traffic Statistics and Monitoring Blocks (experimental) . . . 25 5.7 Event/Security Block (experimental) . . . . . . . . . . . . . 25 6. Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . 27 7. Most important open issues . . . . . . . . . . . . . . . . . . 28 Intellectual Property and Copyright Statements . . . . . . . . 29 Degioanni & Risso Expires August 30, 2004 [Page 2] Internet-Draft PCAP New Generation Dump File Format March 2004 1. Objectives The problem of exchanging packet traces becomes more and more critical every day; unfortunately, no standard solutions exist for this task right now. One of the most accepted packet interchange formats is the one defined by libpcap, which is rather old and does not fit for some of the nowadays applications especially in terms of extensibility. This document proposes a new format for dumping packet traces. The following goals are being pursued: o Extensibility: aside of some common functionalities, third parties should be able to enrich the information embedded in the file with proprietary extensions, which will be ignored by tools that are not able to understand them. o Portability: a capture trace must contain all the information needed to read data independently from network, hardware and operating system of the machine that made the capture. o Merge/Append data: it should be possible to add data at the end of a given file, and the resulting file must still be readable. Degioanni & Risso Expires August 30, 2004 [Page 3] Internet-Draft PCAP New Generation Dump File Format March 2004 2. General File Structure 2.1 General Block Structure A capture file is organized in blocks, that are appended one to another to form the file. All the blocks share a common format, which is shown in Figure 1. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Block Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Block Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / Block Body / / /* variable length, aligned to 32 bits */ / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Block Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 1: Basic block structure. The fields have the following meaning: o Block Type (32 bits): unique value that identifies the block. Values whose Most Significant Bit (MSB) is equal to 1 are reserved for local use. They allow to save private data to the file and to extend the file format. o Block Total Length: total size of this block, in bytes. For instance, a block that does not have a body has a length of 12 bytes. o Block Body: content of the block. o Block Total Length: total size of this block, in bytes. This field is duplicated for permitting backward file navigation. This structure, shared among all blocks, makes easy to process a file and to skip unneeded or unknown blocks. Blocks can be nested one inside the others (NOTE: needed?). Some of the blocks are mandatory, i.e. a dump file is not valid if they are not present, other are optional. The structure of the blocks allows to define other blocks if needed. A parser that does non understand them can simply ignore their content. Degioanni & Risso Expires August 30, 2004 [Page 4] Internet-Draft PCAP New Generation Dump File Format March 2004 2.2 Block Types The currently defined blocks are the following: 1. Section Header Block: it defines the most important characteristics of the capture file. 2. Interface Description Block: it defines the most important characteristics of the interface(s) used for capturing traffic. 3. Packet Block: it contains a single captured packet, or a portion of it. 4. Simple Packet Block: it contains a single captured packet, or a portion of it, with only a minimal set of information about it. 5. Name Resolution Block: it defines the mapping from numeric addresses present in the packet dump and the canonical name counterpart. 6. Capture Statistics Block: it defines how to store some statistical data (e.g. packet dropped, etc) which can be useful to undestand the conditions in which the capture has been made. 7. Compression Marker Block: TODO 8. Encryption Marker Block: TODO 9. Fixed Length Marker Block: TODO The following blocks instead are considered interesting but the authors believe that they deserve more in-depth discussion before being defined: 1. Further Packet Blocks 2. Directory Block 3. Traffic Statistics and Monitoring Blocks 4. Alert and Security Blocks TODO Currently standardized Block Type codes are specified in Appendix 1. 2.3 Block Hierarchy and Precedence The file must begin with a Section Header Block. However, more than Degioanni & Risso Expires August 30, 2004 [Page 5] Internet-Draft PCAP New Generation Dump File Format March 2004 one Section Header Block can be present on the dump, each one covering the data following it till the next one (or the end of file). A Section includes the data delimited by two Section Header Blocks (or by a Section Header Block and the end of the file), including the first Section Header Block. In case an application cannot read a Section because of different version number, it must skip everything until the next Section Header Block. Note that, in order to properly skip the blocks until the next section, all blocks must have the fields Type and Length at the beginning. This is a mandatory requirement that must be maintained in future versions of the block format. Figure 2 shows two valid files: the first has a typical configuration, with a single Section Header that covers the whole file. The second one contains three headers, and is normally the result of file concatenation. An application that understands only version 1.0 of the file format skips the intermediate section and restart processing the packets after the third Section Header. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SHB v1.0 | Data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Typical configuration with a single Section Header Block |-- 1st Section --|-- 2nd Section --|-- 3rd Section --| | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SHB v1.0 | Data | SHB V1.1 | Data | SHB V1.0 | Data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Configuration with three different Section Header Blocks Figure 2: File structure example: the Section Header Block. NOTE: TO BE COMPLETED with some examples of other blocks 2.4 Data format Data contained in each section will always be saved according to the characteristics (little endian / big endian) of the dumping machine. This refers to all fields that are saved as numbers and that span over two or more bytes. The approach of having each section saved in the native format of the generating host is more efficient because it avoids translation of data when reading / writing on the host itself, which is the most common case when generating/processing capture dumps. Degioanni & Risso Expires August 30, 2004 [Page 6] Internet-Draft PCAP New Generation Dump File Format March 2004 TODO Probably we have to specify something more here. Is what we're saying enough to avoid any kind of ambiguity?. Degioanni & Risso Expires August 30, 2004 [Page 7] Internet-Draft PCAP New Generation Dump File Format March 2004 3. Block Definition This section details the format of the body of the blocks currently defined. 3.1 Section Header Block (mandatory) The Section Header Block is mandatory. It identifies the beginning of a section of the capture dump file. Its format is shown in Figure 3. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Magic | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Major | Minor | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 3: Section Header Block format. The meaning of the fields is: o Magic: magic number, whose value is the hexadecimal number 0x1A2B3C4D. This number can be used to distinguish section that have been saved on little-endian machines from the one saved on big-endian machines. o Major: number of the current mayor version of the format. Current value is 1. o Minor: number of the current minor version of the format. Current value is 0. o Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present. Aside form the options defined in Section 4, the following options are valid within this block: +----------------+----------------+----------------+----------------+ | Name | Code | Length | Description | +----------------+----------------+----------------+----------------+ | Hardware | 2 | variable | An ascii | | | | | string | Degioanni & Risso Expires August 30, 2004 [Page 8] Internet-Draft PCAP New Generation Dump File Format March 2004 | | | | containing the | | | | | description of | | | | | the hardware | | | | | used to create | | | | | this section. | | | | | | | Operating | 3 | variable | An ascii | | System | | | string | | | | | containing the | | | | | name of the | | | | | operating | | | | | system used to | | | | | create this | | | | | section. | | | | | | | User | 3 | variable | An ascii | | Application | | | string | | | | | containing the | | | | | name of the | | | | | application | | | | | used to create | | | | | this section. | +----------------+----------------+----------------+----------------+ Table 1 The Section Header Block does not contain data but it rather identifies a list of blocks (interfaces, packets) that are logically correlated. This block does not contain any reference to the size of the section it is currently delimiting, therefore the reader cannot skip a whole section at once. In case a section must be skipped, the user has to repeatedly skip all the blocks contained within it; this makes the parsing of the file slower but it permits to append several capture dumps at the same file. 3.2 Interface Description Block (mandatory) The Interface Description Block is mandatory. This block is needed to specify the characteristics of the network interface on which the capture has been made. In order to properly associate the captured data to the corresponding interface, the Interface Description Block must be defined before any other block that uses it; therefore, this block is usually placed immediately after the Section Header Block. An Interface Description Block is valid only inside the section which it belongs to. The structure of a Interface Description Block is shown in Figure 4. Degioanni & Risso Expires August 30, 2004 [Page 9] Internet-Draft PCAP New Generation Dump File Format March 2004 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Interface ID | LinkType | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SnapLen | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 4: Interface Description Block format. The meaning of the fields is: o Interface ID: a progressive number that identifies uniquely any interface inside current section. Two Interface Description Blocks can have the same Interface ID only if they are in different sections of the file. The Interface ID is referenced by the packet blocks. o LinkType: a value that defines the link layer type of this interface. o SnapLen: maximum number of bytes dumped from each packet. The portion of each packet that exceeds this value will not be stored in the file. o Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present. In addition to the options defined in Section 4, the following options are valid within this block: +----------------+----------------+----------------+----------------+ | Name | Code | Length | Description | +----------------+----------------+----------------+----------------+ | if_name | 2 | Variable | Name of the | | | | | device used to | | | | | capture data. | | | | | | | if_IPv4addr | 3 | 8 | Interface | | | | | network | | | | | address and | | | | | netmask. | | | | | | | if_IPv6addr | 4 | 17 | Interface | Degioanni & Risso Expires August 30, 2004 [Page 10] Internet-Draft PCAP New Generation Dump File Format March 2004 | | | | network | | | | | address and | | | | | prefix length | | | | | (stored in the | | | | | last byte). | | | | | | | if_MACaddr | 5 | 6 | Interface | | | | | Hardware MAC | | | | | address (48 | | | | | bits). | | | | | | | if_EUIaddr | 6 | 8 | Interface | | | | | Hardware EUI | | | | | address (64 | | | | | bits), if | | | | | available. | | | | | | | if_speed | 7 | 8 | Interface | | | | | speed (in | | | | | bps). | | | | | | | if_tsaccur | 8 | 1 | Precision of | | | | | timestamps. If | | | | | the Most | | | | | Significant | | | | | Bit is equal | | | | | to zero, the | | | | | remaining bits | | | | | indicates the | | | | | accuracy as as | | | | | a negative | | | | | power of 10 | | | | | (e.g. 6 means | | | | | microsecond | | | | | accuracy). If | | | | | the Most | | | | | Significant | | | | | Bit is equal | | | | | to zero, the | | | | | remaining bits | | | | | indicates the | | | | | accuracy as as | | | | | negative power | | | | | of 2 (e.g. 10 | | | | | means 1/1024 | | | | | of second). If | | | | | this option is | | | | | not present, a | Degioanni & Risso Expires August 30, 2004 [Page 11] Internet-Draft PCAP New Generation Dump File Format March 2004 | | | | precision of | | | | | 10^-6 is | | | | | assumed. | | | | | | | if_tzone | 9 | 4 | Time zone for | | | | | GMT support | | | | | (TODO: specify | | | | | better). | | | | | | | if_flags | 10 | 4 | Interface | | | | | flags. (TODO: | | | | | specify | | | | | better. | | | | | Possible | | | | | flags: | | | | | promiscuous, | | | | | inbound/outbou | | | | | nd, traffic | | | | | filtered | | | | | during | | | | | capture). | | | | | | | if_filter | 11 | variable | The filter | | | | | (e.g. "capture | | | | | only TCP | | | | | traffic") used | | | | | to capture | | | | | traffic. The | | | | | first byte of | | | | | the Option | | | | | Data keeps a | | | | | code of the | | | | | filter used | | | | | (e.g. if this | | | | | is a libpcap | | | | | string, or BPF | | | | | bytecode, and | | | | | more). More | | | | | details about | | | | | this format | | | | | will be | | | | | presented in | | | | | Appendix XXX | | | | | (TODO). | | | | | | | if_opersystem | 12 | variable | An ascii | | | | | string | | | | | containing the | Degioanni & Risso Expires August 30, 2004 [Page 12] Internet-Draft PCAP New Generation Dump File Format March 2004 | | | | name of the | | | | | operating | | | | | system of the | | | | | machine that | | | | | hosts this | | | | | interface. | | | | | This can be | | | | | different from | | | | | the same | | | | | information | | | | | that can be | | | | | contained by | | | | | the Section | | | | | Header Block | | | | | (Section 3.1) | | | | | because the | | | | | capture can | | | | | have been done | | | | | on a remote | | | | | machine. | +----------------+----------------+----------------+----------------+ Table 2 3.3 Packet Block (optional) A Packet Block is the standard container for storing the packets coming from the network. The Packet Block is optional because packets can be stored either by means of this block or the Simple Packet Block, which can be used to speed up dump generation. The format of a packet block is shown in Figure 5. Degioanni & Risso Expires August 30, 2004 [Page 13] Internet-Draft PCAP New Generation Dump File Format March 2004 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Interface ID | Drops Count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Timestamp (High) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Timestamp (Low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Captured Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Packet Data | | | | /* variable length, byte-aligned */ | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 5: Packet Block format. The Packet Block has the following fields: o Interface ID: Specifies the interface this packet comes from, and corresponds to the ID of one of the Interface Description Blocks present in this section of the file (see Figure 4). o Drops Count: a local drop counter. It specified the number of packets lost (by the interface and the operating system) between this packet and the preceding one. The value xFFFF (in hexadecimal) is reserved for those systems in which this information is not available. o Timestamp (High): the most significative part of the timestamp. in standard Unix format, i.e. from 1/1/1970. o Timestamp (Low): the less significative part of the timestamp. The way to interpret this field is specified by the 'ts_accur' option (see Figure 4) of the Interface Description block referenced by this packet. If the Interface Description block does not contain a 'ts_accur' option, then this field is expressed in microseconds. o Captured Len: number of bytes captured from the packet (i.e. the Degioanni & Risso Expires August 30, 2004 [Page 14] Internet-Draft PCAP New Generation Dump File Format March 2004 length of the Packet Data field). It will be the minimum value among the actual Packet Length and the snapshot length (defined in Figure 4). o Packet Len: actual length of the packet when it was transmitted on the network. Can be different from Captured Len if the user wants only a snapshot of the packet. o Packet Data: the data coming from the network, including link-layer headers. The length of this field is Captured Len. The format of the link-layer headers depends on the LinkType field specified in the Interface Description Block (see Section 3.2) and it is specified in Appendix XXX (TODO). o Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present. 3.4 Simple Packet Block (optional) The Simple Packet Block is a lightweight container for storing the packets coming from the network. Its presence is optional. A Simple Packet Block is similar to a Packet Block (see Section 3.3), but it is smaller, simpler to process and contains only a minimal set of information. This block is preferred to the standard Packet Block when performance or space occupation are critical factors, such as in sustained traffic dump applications. A capture file can contain both Packet Blocks and Simple Packet Blocks: for example, a capture tool could switch from Packet Blocks to Simple Packet Blocks when the hardware resources become critical. The Simple Packet Block does not contain the Interface ID field. Therefore, it must be assumed that all the Simple Packet Blocks have been captured on the interface previously specified in the Interface Description Block. Figure 6 shows the format of the Simple Packet Block. Degioanni & Risso Expires August 30, 2004 [Page 15] Internet-Draft PCAP New Generation Dump File Format March 2004 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Packet Data | | | | /* variable length, byte-aligned */ | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 6: Simple Packet Block format. The Packet Block has the following fields: o Packet Len: actual length of the packet when it was transmitted on the network. Can be different from captured len if the packet has been truncated. o Packet data: the data coming from the network, including link-layers headers. The length of this field can be derived from the field Block Total Length, present in the Block Header. The Simple Packet Block does not contain the timestamp because this is one of the most costly operations on PCs. Additionally, there are applications that do not require it; e.g. an Intrusion Detection System is interested in packets, not in their timestamp. The Simple Packet Block is very efficient in term of disk space: a snapshot of length 100 bytes requires only 16 bytes of overhead, which corresponds to an efficiency of more than 86%. 3.5 Name Resolution Block (optional) The Name Resolution Block is used to support the correlation of numeric addresses (present in the captured packets) and their corresponding canonical names and it is optional. Having the literal names saved in the file, this prevents the need of a name resolution in a delayed time, when the association between names and addresses can be different from the one in use at capture time. Moreover, The Name Resolution Block avoids the need of issuing a lot of DNS requests every time the trace capture is opened, and allows to have name resolution also when reading the capture with a machine not connected to the network. The format of the Name Resolution Block is shown in Figure 7. Degioanni & Risso Expires August 30, 2004 [Page 16] Internet-Draft PCAP New Generation Dump File Format March 2004 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Record Type | Record Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Record Value | | /* variable length, byte-aligned */ | | + + + + + + + + + + + + + + + + + + + + + + + + + | | | | | +-+-+-+-+-+-+-+-+ + + + + + + + + + + + + + + + + + + + + + + + + . . . other records . . . | Record Type == end_of_recs | Record Length == 00 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 7: Name Resolution Block format. A Name Resolution Block is a zero-terminated list of records (in the TLV format), each of which contains an association between a network address and a name. There are three possible types of records: +----------------+----------------+----------------+----------------+ | Name | Code | Length | Description | +----------------+----------------+----------------+----------------+ | end_of_recs | 0 | 0 | End of records | | | | | | | ip4_rec | 1 | Variable | Specifies an | | | | | IPv4 address | | | | | (contained in | | | | | the first 4 | | | | | bytes), | | | | | followed by | | | | | one or more | | | | | zero-terminate | | | | | d strings | | | | | containing the | | | | | DNS entries | | | | | for that | | | | | address. | | | | | | | ip6_rec | 1 | Variable | Specifies an | | | | | IPv6 address | | | | | (contained in | | | | | the first 16 | | | | | bytes), | Degioanni & Risso Expires August 30, 2004 [Page 17] Internet-Draft PCAP New Generation Dump File Format March 2004 | | | | followed by | | | | | one or more | | | | | zero-terminate | | | | | d strings | | | | | containing the | | | | | DNS entries | | | | | for that | | | | | address. | +----------------+----------------+----------------+----------------+ Table 3 After the list or Name Resolution Records, optionally, a list of options (formatted according to the rules defined in Section 4) can be present. A Name Resolution Block is normally placed at the beginning of the file, but no assumptions can be taken about its position. Name Resolution Blocks can be added in a second time by tools that process the file, like network analyzers. In addiction to the options defined in Section 4, the following options are valid within this block: +----------------+----------------+----------------+----------------+ | Name | Code | Length | Description | +----------------+----------------+----------------+----------------+ | ns_dnsname | 2 | Variable | An ascii | | | | | string | | | | | containing the | | | | | name of the | | | | | machine (DNS | | | | | server) used | | | | | to perform the | | | | | name | | | | | resolution. | +----------------+----------------+----------------+----------------+ 3.6 Interface Statistics Block (optional) The Interface Statistics Block contains the capture statistics for a given interface and it is optional. The statistics are referred to the interface defined in the current Section identified by the Interface ID field. The format of the Interface Statistics Block is shown in Figure 8. Degioanni & Risso Expires August 30, 2004 [Page 18] Internet-Draft PCAP New Generation Dump File Format March 2004 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | IfRecv | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | IfDrop | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | FilterAccept | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | OSDrop | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | UsrDelivered | | (high + low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Interface ID | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Options (variable) / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 8: Interface Statistics Block format. The fields have the following meaning: o IfRecv: number of packets received from the interface during the capture. This number is reported as a 64 bits value, in which the most significat bits are located in the first four bytes of the field. o IfDrop: number of packets dropped by the interface during the capture due to lack of resources. o FilterAccept: number of packets accepeted by filter during current capture. o OSDrop: number of packets dropped by the operating system during the capture. o UsrDelivered: number of packets delivered to the user. UsrDelivered can be different from the value 'FilterAccept - OSDropped' because some packets could still lay in the OS buffers when the capture ended. Degioanni & Risso Expires August 30, 2004 [Page 19] Internet-Draft PCAP New Generation Dump File Format March 2004 o Interface ID: reference to an Interface Description Block. o Reserved: Reserved to future use. o Options: optionally, a list of options (formatted according to the rules defined in Section 4) can be present. In addiction to the options defined in Section 4, the following options are valid within this block: +----------------+----------------+----------------+----------------+ | Name | Code | Length | Description | +----------------+----------------+----------------+----------------+ | isb_starttime | 2 | 8 | Time in which | | | | | the capture | | | | | started; time | | | | | will be stored | | | | | in two blocks | | | | | of four bytes | | | | | each, | | | | | containing the | | | | | timestamp in | | | | | seconds and | | | | | nanoseconds. | | | | | | | isb_endtime | 3 | 8 | Time in which | | | | | the capture | | | | | started; time | | | | | will be stored | | | | | in two blocks | | | | | of four bytes | | | | | each, | | | | | containing the | | | | | timestamp in | | | | | seconds and | | | | | nanoseconds. | +----------------+----------------+----------------+----------------+ Degioanni & Risso Expires August 30, 2004 [Page 20] Internet-Draft PCAP New Generation Dump File Format March 2004 4. Options Almost all blocks have the possibility to embed optional fields. Optional fields can be used to insert some information that may be useful when reading data, but that it is not really needed for packet processing. Therefore, each tool can be either read the content of the optional fields (if any), or skip them at once. Skipping all the optional fields at once is straightforward because most of the blocks have a fixed length, therefore the field Block Length (present in the General Block Structure, see Section 2.1) can be used to skip everything till the next block. Options are a list of Type - Length - Value fields, each one containing a single value: o Option Type (2 bytes): it contains the code that specifies the type of the current TLV record. Option types whose Most Significant Bit is equal to one are reserved for local use; therefore, there is no guarantee that the code used is unique among all capture files (generated by other applications). In case of vendor-specific extensions that have to be identified uniquely, vendors must request an Option Code whose MSB is equal to zero. o Option Length (2 bytes): it contains the length of the following 'Option Value' field. o Option Value (variable length): it contains the value of the given option. The length of this field as been specified by the Option Length field. Options may be repeated several times (e.g. an interface that has several IP addresses associated to it). The option list is terminated by a special code which is the 'End of Option'. The format of the optional fields is shown in Figure 9. Degioanni & Risso Expires August 30, 2004 [Page 21] Internet-Draft PCAP New Generation Dump File Format March 2004 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Option Code | Option Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Option Value | | /* variable length, byte-aligned */ | | + + + + + + + + + + + + + + + + + + + + + + + + + | / / / | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / . . . other options . . . / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Option Code == opt_endofopt | Option Length == 0 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 9: Options format. The following codes can always be present in any optional field: +----------------+----------------+----------------+----------------+ | Name | Code | Length | Description | +----------------+----------------+----------------+----------------+ | opt_endofopt | 0 | 0 | End of | | | | | options: it is | | | | | used to | | | | | delimit the | | | | | end of the | | | | | optional | | | | | fields. This | | | | | block cannot | | | | | be repeated | | | | | within a given | | | | | list of | | | | | options. | | | | | | | opt_comment | 1 | variable | Comment: it is | | | | | an ascii | | | | | string | | | | | containing a | | | | | comment that | | | | | is associated | | | | | to the current | | | | | block. | +----------------+----------------+----------------+----------------+ Degioanni & Risso Expires August 30, 2004 [Page 22] Internet-Draft PCAP New Generation Dump File Format March 2004 5. Experimental Blocks (deserved to a further investigation) 5.1 Other Packet Blocks (experimental) Can some other packet blocks (besides the two described in the previous paragraphs) be useful? 5.2 Compression Block (experimental) The Compression Block is optional. A file can contain an arbitrary number of these blocks. A Compression Block, as the name says, is used to store compressed data. Its format is shown in Figure 10. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Compr. Type | | +-+-+-+-+-+-+-+-+ | | | | Compressed Data | | | | /* variable length, byte-aligned */ | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 10: Compression Block format. The fields have the following meaning: o Compression Type: specifies the compression algorithm. Possible values for this field are 0 (uncompressed), 1 (Lempel Ziv), 2 (Gzip), other?? Probably some kind of dumb and fast compression algorithm could be effective with some types of traffic (for example web), but which? o Compressed Data: data of this block. Once decompressed, it is made of other blocks. 5.3 Encryption Block (experimental) The Encryption Block is optional. A file can contain an arbitrary number of these blocks. An Encryption Block is used to sotre encrypted data. Its format is shown in Figure 11. Degioanni & Risso Expires August 30, 2004 [Page 23] Internet-Draft PCAP New Generation Dump File Format March 2004 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Encr. Type | | +-+-+-+-+-+-+-+-+ | | | | Compressed Data | | | | /* variable length, byte-aligned */ | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 11: Encryption Block format. The fields have the following meaning: o Compression Type: specifies the encryption algorithm. Possible values for this field are ??? NOTE: this block should probably contain other fields, depending on the encryption algorithm. To be define precisely. o Encrypted Data: data of this block. Once decripted, it consists of other blocks. 5.4 Fixed Length Block (experimental) The Fixed Length Block is optional. A file can contain an arbitrary number of these blocks. A Fixed Length Block can be used to optimize the access to the file. Its format is shown in Figure 12. A Fixed Length Block stores records with constant size. It contains a set of Blocks (normally Packet Blocks or Simple Packet Blocks), of wihich it specifies the size. Knowing this size a priori helps to scan the file and to load some portions of it without truncating a block, and is particularly useful with cell-based networks like ATM. Degioanni & Risso Expires August 30, 2004 [Page 24] Internet-Draft PCAP New Generation Dump File Format March 2004 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cell Size | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | | Fixed Size Data | | | | /* variable length, byte-aligned */ | | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 12: Fixed Length Block format. The fields have the following meaning: o Cell size: the size of the blocks contained in the data field. o Fixed Size Data: data of this block. 5.5 Directory Block (experimental) If present, this block contains the following information: o number of indexed packets (N) o table with position and length of any indexed packet (N entries) A directory block must be followed by at least N packets, otherwise it must be considered invalid. It can be used to efficiently load portions of the file to memory and to support operations on memory mapped files. This block can be added by tools like network analyzers as a consequence of file processing. 5.6 Traffic Statistics and Monitoring Blocks (experimental) One or more blocks could be defined to contain network statistics or traffic monitoring information. They could be use to store data collected from RMON or Netflow probes, or from other network monitoring tools. 5.7 Event/Security Block (experimental) This block could be used to store events. Events could contain generic information (for example network load over 50%, server down...) or security alerts. An event could be: Degioanni & Risso Expires August 30, 2004 [Page 25] Internet-Draft PCAP New Generation Dump File Format March 2004 o skipped, if the application doesn't know how to do with it o processed independently by the packets. In other words, the applications skips the packets and processes only the alerts o processed in relation to packets: for example, a security tool could load only the packets of the file that are near a security alert; a monitorg tool could skip the packets captured while the server was down. Degioanni & Risso Expires August 30, 2004 [Page 26] Internet-Draft PCAP New Generation Dump File Format March 2004 6. Conclusions The file format proposed in this document should be very versatile and satisfy a wide range of applications. In the simplest case, it can contain a raw dump of the network data, made of a series of Simple Packet Blocks. In the most complex case, it can be used as a repository for heterogeneous information. In every case, the file remains easy to parse and an application can always skip the data it is not interested in; at the same time, different applications can share the file, and each of them can benfit of the information produced by the others. Two or more files can be concatenated obtaining another valid file. Degioanni & Risso Expires August 30, 2004 [Page 27] Internet-Draft PCAP New Generation Dump File Format March 2004 7. Most important open issues o Data, in the file, must be byte or word aligned? Currently, the structure of this document is not consistent with respect to this point. Degioanni & Risso Expires August 30, 2004 [Page 28] Internet-Draft PCAP New Generation Dump File Format March 2004 Intellectual Property Statement The IETF takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on the IETF's procedures with respect to rights in standards-track and standards-related documentation can be found in BCP-11. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification can be obtained from the IETF Secretariat. The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to practice this standard. Please address the information to the IETF Executive Director. Full Copyright Statement Copyright (C) The Internet Society (2004). All Rights Reserved. This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English. The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assignees. This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION Degioanni & Risso Expires August 30, 2004 [Page 29] Internet-Draft PCAP New Generation Dump File Format March 2004 HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Acknowledgment Funding for the RFC Editor function is currently provided by the Internet Society. Degioanni & Risso Expires August 30, 2004 [Page 30] libpcap-0.9.7/./doc/CVS/0000755000026300017500000000000010245661227012625 5ustar mcrmcrlibpcap-0.9.7/./doc/CVS/Entries0000644000026300017500000000024210245661227014157 0ustar mcrmcr/pcap.html/1.1/Mon Apr 5 20:26:58 2004//Tlibpcap_0_9 /pcap.txt/1.1/Mon Apr 5 20:26:58 2004//Tlibpcap_0_9 /pcap.xml/1.1/Mon Apr 5 20:26:58 2004//Tlibpcap_0_9 D libpcap-0.9.7/./doc/CVS/Root0000644000026300017500000000004010245661227013465 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./doc/CVS/Repository0000644000026300017500000000001410245661227014722 0ustar mcrmcrlibpcap/doc libpcap-0.9.7/./doc/CVS/Tag0000644000026300017500000000001510245661227013257 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./pcap-dos.h0000644000026300017500000001546210160767672013323 0ustar mcrmcr/* * Internal details for libpcap on DOS. * 32-bit targets: djgpp, Pharlap or DOS4GW. * * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.h,v 1.1 2004/12/18 08:52:10 guy Exp $ (LBL) */ #ifndef __PCAP_DOS_H #define __PCAP_DOS_H #ifdef __DJGPP__ #include /* simple non-conio kbhit */ #else #include #endif typedef int BOOL; typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef BYTE ETHER[6]; #define ETH_ALEN sizeof(ETHER) /* Ether address length */ #define ETH_HLEN (2*ETH_ALEN+2) /* Ether header length */ #define ETH_MTU 1500 #define ETH_MIN 60 #define ETH_MAX (ETH_MTU+ETH_HLEN) #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define PHARLAP 1 #define DJGPP 2 #define DOS4GW 4 #ifdef __DJGPP__ #undef DOSX #define DOSX DJGPP #endif #ifdef __WATCOMC__ #undef DOSX #define DOSX DOS4GW #endif #ifdef __HIGHC__ #include #undef DOSX #define DOSX PHARLAP #define inline #else typedef unsigned int UINT; #endif #if defined(__GNUC__) || defined(__HIGHC__) typedef unsigned long long uint64; typedef unsigned long long QWORD; #endif #if defined(__WATCOMC__) typedef unsigned __int64 uint64; typedef unsigned __int64 QWORD; #endif #define ARGSUSED(x) (void) x #if defined (__SMALL__) || defined(__LARGE__) #define DOSX 0 #elif !defined(DOSX) #error DOSX not defined; 1 = PharLap, 2 = djgpp, 4 = DOS4GW #endif #ifdef __HIGHC__ #define min(a,b) _min(a,b) #define max(a,b) _max(a,b) #endif #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef max #define max(a,b) ((a) < (b) ? (b) : (a)) #endif #if !defined(_U_) && defined(__GNUC__) #define _U_ __attribute__((unused)) #endif #ifndef _U_ #define _U_ #endif #if defined(USE_32BIT_DRIVERS) #include "msdos/pm_drvr/lock.h" #ifndef RECEIVE_QUEUE_SIZE #define RECEIVE_QUEUE_SIZE 60 #endif #ifndef RECEIVE_BUF_SIZE #define RECEIVE_BUF_SIZE (ETH_MAX+20) #endif extern struct device el2_dev LOCKED_VAR; /* 3Com EtherLink II */ extern struct device el3_dev LOCKED_VAR; /* EtherLink III */ extern struct device tc59_dev LOCKED_VAR; /* 3Com Vortex Card (?) */ extern struct device tc515_dev LOCKED_VAR; extern struct device tc90x_dev LOCKED_VAR; extern struct device tc90bcx_dev LOCKED_VAR; extern struct device wd_dev LOCKED_VAR; extern struct device ne_dev LOCKED_VAR; extern struct device acct_dev LOCKED_VAR; extern struct device cs89_dev LOCKED_VAR; extern struct device rtl8139_dev LOCKED_VAR; struct rx_ringbuf { volatile int in_index; /* queue index head */ int out_index; /* queue index tail */ int elem_size; /* size of each element */ int num_elem; /* number of elements */ char *buf_start; /* start of buffer pool */ }; struct rx_elem { DWORD size; /* size copied to this element */ BYTE data[ETH_MAX+10]; /* add some margin. data[0] should be */ }; /* dword aligned */ extern BYTE *get_rxbuf (int len) LOCKED_FUNC; extern int peek_rxbuf (BYTE **buf); extern int release_rxbuf (BYTE *buf); #else #define LOCKED_VAR #define LOCKED_FUNC struct device { const char *name; const char *long_name; DWORD base_addr; /* device I/O address */ int irq; /* device IRQ number */ int dma; /* DMA channel */ DWORD mem_start; /* shared mem start */ DWORD mem_end; /* shared mem end */ DWORD rmem_start; /* shmem "recv" start */ DWORD rmem_end; /* shared "recv" end */ struct device *next; /* next device in list */ /* interface service routines */ int (*probe)(struct device *dev); int (*open) (struct device *dev); void (*close)(struct device *dev); int (*xmit) (struct device *dev, const void *buf, int len); void *(*get_stats)(struct device *dev); void (*set_multicast_list)(struct device *dev); /* driver-to-pcap receive buffer routines */ int (*copy_rx_buf) (BYTE *buf, int max); /* rx-copy (pktdrvr only) */ BYTE *(*get_rx_buf) (int len); /* rx-buf fetch/enqueue */ int (*peek_rx_buf) (BYTE **buf); /* rx-non-copy at queue */ int (*release_rx_buf) (BYTE *buf); /* release after peek */ WORD flags; /* Low-level status flags. */ void *priv; /* private data */ }; /* * Network device statistics */ typedef struct net_device_stats { DWORD rx_packets; /* total packets received */ DWORD tx_packets; /* total packets transmitted */ DWORD rx_bytes; /* total bytes received */ DWORD tx_bytes; /* total bytes transmitted */ DWORD rx_errors; /* bad packets received */ DWORD tx_errors; /* packet transmit problems */ DWORD rx_dropped; /* no space in Rx buffers */ DWORD tx_dropped; /* no space available for Tx */ DWORD multicast; /* multicast packets received */ /* detailed rx_errors: */ DWORD rx_length_errors; DWORD rx_over_errors; /* recv'r overrun error */ DWORD rx_osize_errors; /* recv'r over-size error */ DWORD rx_crc_errors; /* recv'd pkt with crc error */ DWORD rx_frame_errors; /* recv'd frame alignment error */ DWORD rx_fifo_errors; /* recv'r fifo overrun */ DWORD rx_missed_errors; /* recv'r missed packet */ /* detailed tx_errors */ DWORD tx_aborted_errors; DWORD tx_carrier_errors; DWORD tx_fifo_errors; DWORD tx_heartbeat_errors; DWORD tx_window_errors; DWORD tx_collisions; DWORD tx_jabbers; } NET_STATS; #endif extern struct device *active_dev LOCKED_VAR; extern const struct device *dev_base LOCKED_VAR; extern struct device *probed_dev; extern int pcap_pkt_debug; extern void _w32_os_yield (void); /* Watt-32's misc.c */ #ifdef NDEBUG #define PCAP_ASSERT(x) ((void)0) #else void pcap_assert (const char *what, const char *file, unsigned line); #define PCAP_ASSERT(x) do { \ if (!(x)) \ pcap_assert (#x, __FILE__, __LINE__); \ } while (0) #endif #endif /* __PCAP_DOS_H */ libpcap-0.9.7/./.#Makefile.in.1.99.2.10000644000026300017500000002035210651261565014515 0ustar mcrmcr# Copyright (c) 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: /tcpdump/master/libpcap/Makefile.in,v 1.99.2.1 2006/09/25 18:06:00 guy Exp $ (LBL) # # Various configurable paths (remember to edit Makefile.in, not Makefile) # # Top level hierarchy prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ # Pathname of directory to install the include files includedir = @includedir@ # Pathname of directory to install the library libdir = @libdir@ # Pathname of directory to install the man page mandir = @mandir@ # VPATH srcdir = @srcdir@ VPATH = @srcdir@ # # You shouldn't need to edit anything below. # CC = @CC@ CCOPT = @V_CCOPT@ INCLS = -I. @V_INCLS@ DEFS = @DEFS@ @V_DEFS@ LIBS = @V_LIBS@ DAGLIBS = @DAGLIBS@ DYEXT = @DYEXT@ # Standard CFLAGS CFLAGS = $(CCOPT) $(INCLS) $(DEFS) INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ RANLIB = @RANLIB@ # # Flex and bison allow you to specify the prefixes of the global symbols # used by the generated parser. This allows programs to use lex/yacc # and link against libpcap. If you don't have flex or bison, get them. # LEX = @V_LEX@ YACC = @V_YACC@ # Explicitly define compilation rule since SunOS 4's make doesn't like gcc. # Also, gcc does not remove the .o before forking 'as', which can be a # problem if you don't own the file but can write to the directory. .c.o: @rm -f $@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ FSRC = fad-@V_FINDALLDEVS@.c SSRC = @SSRC@ CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \ etherent.c savefile.c bpf_filter.c bpf_image.c bpf_dump.c GENSRC = scanner.c grammar.c version.c LIBOBJS = @LIBOBJS@ SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC) # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS) HDR = pcap.h pcap-int.h pcap-namedb.h pcap-nit.h pcap-pf.h \ ethertype.h gencode.h gnuc.h GENHDR = \ tokdefs.h version.h TAGHDR = \ pcap-bpf.h TAGFILES = \ $(SRC) $(HDR) $(TAGHDR) CLEANFILES = $(OBJ) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c all: libpcap.a libpcap.a: $(OBJ) @rm -f $@ ar rc $@ $(OBJ) $(LIBS) $(RANLIB) $@ shared: libpcap.$(DYEXT) # # XXX - this works with GNU ld, but won't necessarily work with native # ld on, for example, various SVR4-flavored platforms, or Digital UNIX. # libpcap.so: $(OBJ) @rm -f $@ $(CC) -shared -o $@.`cat VERSION` $(OBJ) $(DAGLIBS) # the following rule succeeds, but the result is untested. libpcap.dylib: $(OBJ) rm -f libpcap*.dylib $(CC) -dynamiclib -undefined error -o libpcap.`cat VERSION`.dylib $(OBJ) \ -install_name $(libdir)/libpcap.0.dylib -compatibility_version `cat VERSION` \ -current_version `cat VERSION` scanner.c: $(srcdir)/scanner.l @rm -f $@ $(LEX) -t $< > $$$$.$@; mv $$$$.$@ $@ scanner.o: scanner.c tokdefs.h $(CC) $(CFLAGS) -c scanner.c pcap.o: version.h tokdefs.h: grammar.c grammar.c: $(srcdir)/grammar.y @rm -f grammar.c tokdefs.h $(YACC) -d $< mv y.tab.c grammar.c mv y.tab.h tokdefs.h grammar.o: grammar.c @rm -f $@ $(CC) $(CFLAGS) -Dyylval=pcap_lval -c grammar.c version.o: version.c $(CC) $(CFLAGS) -c version.c snprintf.o: $(srcdir)/missing/snprintf.c $(CC) $(CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c version.c: $(srcdir)/VERSION @rm -f $@ sed -e 's/.*/char pcap_version[] = "&";/' $(srcdir)/VERSION > $@ # # NOTE: this really is supposed to be static; importing a string # from a shared library does not work very well on many # versions of UNIX (Solaris, Linux, and the BSDs, for example), # so we make the version string static and return it from # a function, which does work. # version.h: $(srcdir)/VERSION @rm -f $@ sed -e 's/.*/static const char pcap_version_string[] = "libpcap version &";/' $(srcdir)/VERSION > $@ bpf_filter.c: $(srcdir)/bpf/net/bpf_filter.c rm -f bpf_filter.c ln -s $(srcdir)/bpf/net/bpf_filter.c bpf_filter.c bpf_filter.o: bpf_filter.c $(CC) $(CFLAGS) -c bpf_filter.c # # Test programs - not built by default, and not installed. # filtertest: filtertest.c libpcap.a $(CC) $(CFLAGS) -I. -L. -o filtertest filtertest.c libpcap.a findalldevstest: findalldevstest.c libpcap.a $(CC) $(CFLAGS) -I. -L. -o findalldevstest findalldevstest.c libpcap.a install: libpcap.a [ -d $(DESTDIR)$(libdir) ] || \ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir)) $(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a $(RANLIB) $(DESTDIR)$(libdir)/libpcap.a [ -d $(DESTDIR)$(includedir) ] || \ (mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir)) [ -d $(DESTDIR)$(includedir)/pcap ] || \ (mkdir -p $(DESTDIR)$(includedir)/pcap; chmod 755 $(DESTDIR)$(includedir)/pcap) $(INSTALL_DATA) $(srcdir)/pcap/pcap.h \ $(DESTDIR)$(includedir)/pcap/pcap.h $(INSTALL_DATA) $(srcdir)/pcap/bpf.h \ $(DESTDIR)$(includedir)/pcap/bpf.h $(INSTALL_DATA) $(srcdir)/pcap/namedb.h \ $(DESTDIR)$(includedir)/pcap/namedb.h $(INSTALL_DATA) $(srcdir)/pcap/sll.h \ $(DESTDIR)$(includedir)/pcap/sll.h $(INSTALL_DATA) $(srcdir)/pcap/usb.h \ $(DESTDIR)$(includedir)/pcap/usb.h $(INSTALL_DATA) $(srcdir)/pcap.h $(DESTDIR)$(includedir)/pcap.h $(INSTALL_DATA) $(srcdir)/pcap-bpf.h \ $(DESTDIR)$(includedir)/pcap-bpf.h $(INSTALL_DATA) $(srcdir)/pcap-namedb.h \ $(DESTDIR)$(includedir)/pcap-namedb.h [ -d $(DESTDIR)$(mandir)/man3 ] || \ (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3) $(INSTALL_DATA) $(srcdir)/pcap.3 \ $(DESTDIR)$(mandir)/man3/pcap.3 install-shared: install-shared-$(DYEXT) install-shared-so: libpcap.so $(INSTALL_PROGRAM) libpcap.so.`cat VERSION` $(DESTDIR)$(libdir)/libpcap.so.`cat VERSION` install-shared-dylib: libpcap.dylib $(INSTALL_PROGRAM) libpcap.`cat VERSION`.dylib $(DESTDIR)$(libdir)/libpcap.`cat VERSION`.dylib VER=`cat VERSION`; cd $(DESTDIR)$(libdir) && ln -sf libpcap.$$VER.dylib libpcap.0.dylib; ln -sf libpcap.0.dylib libpcap.dylib uninstall: rm -f $(DESTDIR)$(libdir)/libpcap.a rm -f $(DESTDIR)$(includedir)/pcap/pcap.h rm -f $(DESTDIR)$(includedir)/pcap/bpf.h rm -f $(DESTDIR)$(includedir)/pcap/namedb.h rm -f $(DESTDIR)$(includedir)/pcap/sll.h rm -f $(DESTDIR)$(includedir)/pcap/usb.h -rmdir $(DESTDIR)$(includedir)/pcap rm -f $(DESTDIR)$(includedir)/pcap.h rm -f $(DESTDIR)$(includedir)/pcap-bpf.h rm -f $(DESTDIR)$(includedir)/pcap-namedb.h rm -f $(DESTDIR)$(mandir)/man3/pcap.3 clean: rm -f $(CLEANFILES) libpcap*.dylib libpcap.so* distclean: clean rm -f Makefile config.cache config.log config.status \ config.h gnuc.h os-proto.h bpf_filter.c stamp-h stamp-h.in rm -rf autom4te.cache tags: $(TAGFILES) ctags -wtd $(TAGFILES) packaging/pcap.spec: packaging/pcap.spec.in VERSION RPMVERSION=`cat VERSION | sed s/-.*//g`; \ sed -e s/@VERSION@/$$RPMVERSION/ -e s/@NAME@/libpcap-`cat VERSION`/ $< > $@ releasetar: @cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \ list="" ; make distclean; \ cd ..; tar -c -z -f $name.tar.gz $dir ; depend: $(GENSRC) $(GENHDR) bpf_filter.c ./mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC) Makefile: Makefile.in config.status ./config.status @echo your Makefile was out of date, now run $(MAKE) again exit 1 libpcap-0.9.7/./pcap-null.c0000644000026300017500000000347207755532623013503 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.21 2003/11/15 23:24:03 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* optionally get BSD define */ #include #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_t * pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { (void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE); return (NULL); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } libpcap-0.9.7/./pcap-bpf.c0000644000026300017500000007412310643174160013265 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.86.2.12 2007/06/15 17:57:27 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* optionally get BSD define */ #include #include #include #include #include #include #include #ifdef _AIX /* * Make "pcap.h" not include "pcap-bpf.h"; we are going to include the * native OS version, as we need "struct bpf_config" from it. */ #define PCAP_DONT_INCLUDE_PCAP_BPF_H #include /* * Prevent bpf.h from redefining the DLT_ values to their * IFT_ values, as we're going to return the standard libpcap * values, not IBM's non-standard IFT_ values. */ #undef _AIX #include #define _AIX #include /* for IFT_ values */ #include #include #include #include #ifdef __64BIT__ #define domakedev makedev64 #define getmajor major64 #define bpf_hdr bpf_hdr32 #else /* __64BIT__ */ #define domakedev makedev #define getmajor major #endif /* __64BIT__ */ #define BPF_NAME "bpf" #define BPF_MINORS 4 #define DRIVER_PATH "/usr/lib/drivers" #define BPF_NODE "/dev/bpf" static int bpfloadedflag = 0; static int odmlockid = 0; #else /* _AIX */ #include #endif /* _AIX */ #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_DAG_API #include "pcap-dag.h" #endif /* HAVE_DAG_API */ #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #include "gencode.h" /* for "no_optimize" */ static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp); static int pcap_setdirection_bpf(pcap_t *, pcap_direction_t); static int pcap_set_datalink_bpf(pcap_t *p, int dlt); static int pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps) { struct bpf_stat s; /* * "ps_recv" counts packets handed to the filter, not packets * that passed the filter. This includes packets later dropped * because we ran out of buffer space. * * "ps_drop" counts packets dropped inside the BPF device * because we ran out of buffer space. It doesn't count * packets dropped by the interface driver. It counts * only packets that passed the filter. * * Both statistics include packets not yet read from the kernel * by libpcap, and thus not yet seen by the application. */ if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s", pcap_strerror(errno)); return (-1); } ps->ps_recv = s.bs_recv; ps->ps_drop = s.bs_drop; return (0); } static int pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; int n = 0; register u_char *bp, *ep; u_char *datap; struct bpf_insn *fcode; #ifdef PCAP_FDDIPAD register int pad; #endif fcode = p->md.use_bpf ? NULL : p->fcode.bf_insns; again: /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return -2 to indicate that we were * told to break out of the loop. */ p->break_loop = 0; return (-2); } 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; #ifdef _AIX case EFAULT: /* * Sigh. More AIX wonderfulness. * * For some unknown reason the uiomove() * operation in the bpf kernel extension * used to copy the buffer into user * space sometimes returns EFAULT. I have * no idea why this is the case given that * a kernel debugger shows the user buffer * is correct. This problem appears to * be mostly mitigated by the memset of * the buffer before it is first used. * Very strange.... Shaun Clowes * * In any case this means that we shouldn't * treat EFAULT as a fatal error; as we * don't have an API for returning * a "some packets were dropped since * the last packet you saw" indication, * we just ignore EFAULT and keep reading. */ goto again; #endif 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 } snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "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; #ifdef PCAP_FDDIPAD pad = p->fddipad; #endif while (bp < ep) { register int caplen, hdrlen; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = bp; p->cc = ep - bp; return (n); } } caplen = bhp->bh_caplen; hdrlen = bhp->bh_hdrlen; datap = bp + hdrlen; /* * Short-circuit evaluation: if using BPF filter * in kernel, no need to do it now. * #ifdef PCAP_FDDIPAD * Note: the filter code was generated assuming * that p->fddipad was the amount of padding * before the header, as that's what's required * in the kernel, so we run the filter before * skipping that padding. #endif */ if (fcode == NULL || bpf_filter(fcode, datap, bhp->bh_datalen, caplen)) { struct pcap_pkthdr pkthdr; pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec; #ifdef _AIX /* * AIX's BPF returns seconds/nanoseconds time * stamps, not seconds/microseconds time stamps. */ pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec/1000; #else pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec; #endif #ifdef PCAP_FDDIPAD if (caplen > pad) pkthdr.caplen = caplen - pad; else pkthdr.caplen = 0; if (bhp->bh_datalen > pad) pkthdr.len = bhp->bh_datalen - pad; else pkthdr.len = 0; datap += pad; #else pkthdr.caplen = caplen; pkthdr.len = bhp->bh_datalen; #endif (*callback)(user, &pkthdr, datap); bp += BPF_WORDALIGN(caplen + hdrlen); if (++n >= cnt && cnt > 0) { p->bp = bp; p->cc = ep - bp; return (n); } } else { /* * Skip this packet. */ bp += BPF_WORDALIGN(caplen + hdrlen); } } #undef bhp p->cc = 0; return (n); } static int pcap_inject_bpf(pcap_t *p, const void *buf, size_t size) { int ret; ret = write(p->fd, buf, size); #ifdef __APPLE__ if (ret == -1 && errno == EAFNOSUPPORT) { /* * In Mac OS X, there's a bug wherein setting the * BIOCSHDRCMPLT flag causes writes to fail; see, * for example: * * http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/BIOCSHDRCMPLT-10.3.3.patch * * So, if, on OS X, we get EAFNOSUPPORT from the write, we * assume it's due to that bug, and turn off that flag * and try again. If we succeed, it either means that * somebody applied the fix from that URL, or other patches * for that bug from * * http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/ * * and are running a Darwin kernel with those fixes, or * that Apple fixed the problem in some OS X release. */ u_int spoof_eth_src = 0; if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: can't turn off BIOCSHDRCMPLT: %s", pcap_strerror(errno)); return (-1); } /* * Now try the write again. */ ret = write(p->fd, buf, size); } #endif /* __APPLE__ */ if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } #ifdef _AIX static int bpf_odminit(char *errbuf) { char *errstr; if (odm_initialize() == -1) { if (odm_err_msg(odmerrno, &errstr) == -1) errstr = "Unknown error"; snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_initialize failed: %s", errstr); return (-1); } if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) { if (odm_err_msg(odmerrno, &errstr) == -1) errstr = "Unknown error"; snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s", errstr); return (-1); } return (0); } static int bpf_odmcleanup(char *errbuf) { char *errstr; if (odm_unlock(odmlockid) == -1) { if (odm_err_msg(odmerrno, &errstr) == -1) errstr = "Unknown error"; snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_unlock failed: %s", errstr); return (-1); } if (odm_terminate() == -1) { if (odm_err_msg(odmerrno, &errstr) == -1) errstr = "Unknown error"; snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: odm_terminate failed: %s", errstr); return (-1); } return (0); } static int bpf_load(char *errbuf) { long major; int *minors; int numminors, i, rc; char buf[1024]; struct stat sbuf; struct bpf_config cfg_bpf; struct cfg_load cfg_ld; struct cfg_kmod cfg_km; /* * This is very very close to what happens in the real implementation * but I've fixed some (unlikely) bug situations. */ if (bpfloadedflag) return (0); if (bpf_odminit(errbuf) != 0) return (-1); major = genmajor(BPF_NAME); if (major == -1) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: genmajor failed: %s", pcap_strerror(errno)); return (-1); } minors = getminor(major, &numminors, BPF_NAME); if (!minors) { minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1); if (!minors) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: genminor failed: %s", pcap_strerror(errno)); return (-1); } } if (bpf_odmcleanup(errbuf)) return (-1); rc = stat(BPF_NODE "0", &sbuf); if (rc == -1 && errno != ENOENT) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: can't stat %s: %s", BPF_NODE "0", pcap_strerror(errno)); return (-1); } if (rc == -1 || getmajor(sbuf.st_rdev) != major) { for (i = 0; i < BPF_MINORS; i++) { sprintf(buf, "%s%d", BPF_NODE, i); unlink(buf); if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: can't mknod %s: %s", buf, pcap_strerror(errno)); return (-1); } } } /* Check if the driver is loaded */ memset(&cfg_ld, 0x0, sizeof(cfg_ld)); cfg_ld.path = buf; sprintf(cfg_ld.path, "%s/%s", DRIVER_PATH, BPF_NAME); if ((sysconfig(SYS_QUERYLOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) || (cfg_ld.kmid == 0)) { /* Driver isn't loaded, load it now */ if (sysconfig(SYS_SINGLELOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: could not load driver: %s", strerror(errno)); return (-1); } } /* Configure the driver */ cfg_km.cmd = CFG_INIT; cfg_km.kmid = cfg_ld.kmid; cfg_km.mdilen = sizeof(cfg_bpf); cfg_km.mdiptr = (void *)&cfg_bpf; for (i = 0; i < BPF_MINORS; i++) { cfg_bpf.devno = domakedev(major, i); if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bpf_load: could not configure driver: %s", strerror(errno)); return (-1); } } bpfloadedflag = 1; return (0); } #endif static inline int bpf_open(pcap_t *p, char *errbuf) { int fd; #ifdef HAVE_CLONING_BPF static const char device[] = "/dev/bpf"; #else int n = 0; char device[sizeof "/dev/bpf0000000000"]; #endif #ifdef _AIX /* * Load the bpf driver, if it isn't already loaded, * and create the BPF device entries, if they don't * already exist. */ if (bpf_load(errbuf) == -1) return (-1); #endif #ifdef HAVE_CLONING_BPF if ((fd = open(device, O_RDWR)) == -1 && (errno != EACCES || (fd = open(device, O_RDONLY)) == -1)) snprintf(errbuf, PCAP_ERRBUF_SIZE, "(cannot open device) %s: %s", device, pcap_strerror(errno)); #else /* * Go through all the minors and find one that isn't in use. */ do { (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++); /* * Initially try a read/write open (to allow the inject * method to work). If that fails due to permission * issues, fall back to read-only. This allows a * non-root user to be granted specific access to pcap * capabilities via file permissions. * * XXX - we should have an API that has a flag that * controls whether to open read-only or read-write, * so that denial of permission to send (or inability * to send, if sending packets isn't supported on * the device in question) can be indicated at open * time. */ fd = open(device, O_RDWR); if (fd == -1 && errno == EACCES) fd = open(device, O_RDONLY); } while (fd < 0 && errno == EBUSY); /* * XXX better message for all minors used */ if (fd < 0) snprintf(errbuf, PCAP_ERRBUF_SIZE, "(no devices found) %s: %s", device, pcap_strerror(errno)); #endif return (fd); } /* * We include the OS's , not our "pcap-bpf.h", so we probably * don't get DLT_DOCSIS defined. */ #ifndef DLT_DOCSIS #define DLT_DOCSIS 143 #endif pcap_t * pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { int fd; struct ifreq ifr; struct bpf_version bv; #ifdef BIOCGDLTLIST struct bpf_dltlist bdl; #endif #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) u_int spoof_eth_src = 1; #endif u_int v; pcap_t *p; struct bpf_insn total_insn; struct bpf_program total_prog; struct utsname osinfo; #ifdef HAVE_DAG_API if (strstr(device, "dag")) { return dag_open_live(device, snaplen, promisc, to_ms, ebuf); } #endif /* HAVE_DAG_API */ #ifdef BIOCGDLTLIST memset(&bdl, 0, sizeof(bdl)); #endif p = (pcap_t *)malloc(sizeof(*p)); if (p == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } memset(p, 0, 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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s", pcap_strerror(errno)); goto bad; } if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "kernel bpf filter out of date"); goto bad; } /* * Try finding a good size for the buffer; 32768 may be too * big, so keep cutting it in half until we find a size * that works, or run out of sizes to try. If the default * is larger, don't make it smaller. * * XXX - there should be a user-accessible hook to set the * initial buffer size. */ if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) || v < 32768) v = 32768; for ( ; v != 0; v >>= 1) { /* 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) break; /* that size worked; we're done */ if (errno != ENOBUFS) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s", device, pcap_strerror(errno)); goto bad; } } if (v == 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSBLEN: %s: No buffer size worked", device); goto bad; } /* Get the data link layer type. */ if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s", pcap_strerror(errno)); goto bad; } #ifdef _AIX /* * AIX's BPF returns IFF_ types, not DLT_ types, in BIOCGDLT. */ switch (v) { case IFT_ETHER: case IFT_ISO88023: v = DLT_EN10MB; break; case IFT_FDDI: v = DLT_FDDI; break; case IFT_ISO88025: v = DLT_IEEE802; break; case IFT_LOOP: v = DLT_NULL; break; default: /* * We don't know what to map this to yet. */ snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown interface type %u", v); goto bad; } #endif #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; case 11: /*DLT_FR*/ v = DLT_FRELAY; break; case 12: /*DLT_C_HDLC*/ v = DLT_CHDLC; break; } #endif #ifdef PCAP_FDDIPAD if (v == DLT_FDDI) p->fddipad = PCAP_FDDIPAD; else p->fddipad = 0; #endif p->linktype = v; #ifdef BIOCGDLTLIST /* * We know the default link type -- now determine all the DLTs * this interface supports. If this fails with EINVAL, it's * not fatal; we just don't get to use the feature later. */ if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) == 0) { u_int i; int is_ethernet; bdl.bfl_list = (u_int *) malloc(sizeof(u_int) * (bdl.bfl_len + 1)); if (bdl.bfl_list == NULL) { (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) < 0) { (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLTLIST: %s", pcap_strerror(errno)); free(bdl.bfl_list); goto bad; } /* * OK, for real Ethernet devices, add DLT_DOCSIS to the * list, so that an application can let you choose it, * in case you're capturing DOCSIS traffic that a Cisco * Cable Modem Termination System is putting out onto * an Ethernet (it doesn't put an Ethernet header onto * the wire, it puts raw DOCSIS frames out on the wire * inside the low-level Ethernet framing). * * A "real Ethernet device" is defined here as a device * that has a link-layer type of DLT_EN10MB and that has * no alternate link-layer types; that's done to exclude * 802.11 interfaces (which might or might not be the * right thing to do, but I suspect it is - Ethernet <-> * 802.11 bridges would probably badly mishandle frames * that don't have Ethernet headers). */ if (p->linktype == DLT_EN10MB) { is_ethernet = 1; for (i = 0; i < bdl.bfl_len; i++) { if (bdl.bfl_list[i] != DLT_EN10MB) { is_ethernet = 0; break; } } if (is_ethernet) { /* * We reserved one more slot at the end of * the list. */ bdl.bfl_list[bdl.bfl_len] = DLT_DOCSIS; bdl.bfl_len++; } } p->dlt_count = bdl.bfl_len; p->dlt_list = bdl.bfl_list; } else { if (errno != EINVAL) { (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLTLIST: %s", pcap_strerror(errno)); goto bad; } } #endif /* * If this is an Ethernet device, and we don't have a DLT_ list, * give it a list with DLT_EN10MB and DLT_DOCSIS. (That'd give * 802.11 interfaces DLT_DOCSIS, which isn't the right thing to * do, but there's not much we can do about that without finding * some other way of determining whether it's an Ethernet or 802.11 * device.) */ if (p->linktype == DLT_EN10MB && p->dlt_count == 0) { p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } } #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) /* * Do a BIOCSHDRCMPLT, if defined, to turn that flag on, so * the link-layer source address isn't forcibly overwritten. * (Should we ignore errors? Should we do this only if * we're open for writing?) * * XXX - I seem to remember some packet-sending bug in some * BSDs - check CVS log for "bpf.c"? */ if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSHDRCMPLT: %s", pcap_strerror(errno)); goto bad; } #endif /* set timeout */ if (to_ms != 0) { /* * XXX - is this seconds/nanoseconds in AIX? * (Treating it as such doesn't fix the timeout * problem described below.) */ 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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); goto bad; } } #ifdef _AIX #ifdef BIOCIMMEDIATE /* * Darren Reed notes that * * On AIX (4.2 at least), if BIOCIMMEDIATE is not set, the * timeout appears to be ignored and it waits until the buffer * is filled before returning. The result of not having it * set is almost worse than useless if your BPF filter * is reducing things to only a few packets (i.e. one every * second or so). * * so we turn BIOCIMMEDIATE mode on if this is AIX. * * We don't turn it on for other platforms, as that means we * get woken up for every packet, which may not be what we want; * in the Winter 1993 USENIX paper on BPF, they say: * * Since a process might want to look at every packet on a * network and the time between packets can be only a few * microseconds, it is not possible to do a read system call * per packet and BPF must collect the data from several * packets and return it as a unit when the monitoring * application does a read. * * which I infer is the reason for the timeout - it means we * wait that amount of time, in the hopes that more packets * will arrive and we'll get them all with one read. * * Setting BIOCIMMEDIATE mode on FreeBSD (and probably other * BSDs) causes the timeout to be ignored. * * On the other hand, some platforms (e.g., Linux) don't support * timeouts, they just hand stuff to you as soon as it arrives; * if that doesn't cause a problem on those platforms, it may * be OK to have BIOCIMMEDIATE mode on BSD as well. * * (Note, though, that applications may depend on the read * completing, even if no packets have arrived, when the timeout * expires, e.g. GUI applications that have to check for input * while waiting for packets to arrive; a non-zero timeout * prevents "select()" from working right on FreeBSD and * possibly other BSDs, as the timer doesn't start until a * "read()" is done, so the timer isn't in effect if the * application is blocked on a "select()", and the "select()" * doesn't get woken up for a BPF device until the buffer * fills up.) */ v = 1; if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s", pcap_strerror(errno)); goto bad; } #endif /* BIOCIMMEDIATE */ #endif /* _AIX */ if (promisc) { /* set promiscuous mode, okay if it fails */ if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s", pcap_strerror(errno)); } } if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s", pcap_strerror(errno)); goto bad; } p->bufsize = v; p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } #ifdef _AIX /* For some strange reason this seems to prevent the EFAULT * problems we have experienced from AIX BPF. */ memset(p->buffer, 0x0, p->bufsize); #endif /* * If there's no filter program installed, there's * no indication to the kernel of what the snapshot * length should be, so no snapshotting is done. * * Therefore, when we open the device, we install * an "accept everything" filter with the specified * snapshot length. */ total_insn.code = (u_short)(BPF_RET | BPF_K); total_insn.jt = 0; total_insn.jf = 0; total_insn.k = snaplen; total_prog.bf_len = 1; total_prog.bf_insns = &total_insn; if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", pcap_strerror(errno)); goto bad; } /* * On most BPF platforms, either you can do a "select()" or * "poll()" on a BPF file descriptor and it works correctly, * or you can do it and it will return "readable" if the * hold buffer is full but not if the timeout expires *and* * a non-blocking read will, if the hold buffer is empty * but the store buffer isn't empty, rotate the buffers * and return what packets are available. * * In the latter case, the fact that a non-blocking read * will give you the available packets means you can work * around the failure of "select()" and "poll()" to wake up * and return "readable" when the timeout expires by using * the timeout as the "select()" or "poll()" timeout, putting * the BPF descriptor into non-blocking mode, and read from * it regardless of whether "select()" reports it as readable * or not. * * However, in FreeBSD 4.3 and 4.4, "select()" and "poll()" * won't wake up and return "readable" if the timer expires * and non-blocking reads return EWOULDBLOCK if the hold * buffer is empty, even if the store buffer is non-empty. * * This means the workaround in question won't work. * * Therefore, on FreeBSD 4.3 and 4.4, we set "p->selectable_fd" * to -1, which means "sorry, you can't use 'select()' or 'poll()' * here". On all other BPF platforms, we set it to the FD for * the BPF device; in NetBSD, OpenBSD, and Darwin, a non-blocking * read will, if the hold buffer is empty and the store buffer * isn't empty, rotate the buffers and return what packets are * there (and in sufficiently recent versions of OpenBSD * "select()" and "poll()" should work correctly). * * XXX - what about AIX? */ p->selectable_fd = p->fd; /* assume select() works until we know otherwise */ if (uname(&osinfo) == 0) { /* * We can check what OS this is. */ if (strcmp(osinfo.sysname, "FreeBSD") == 0) { if (strncmp(osinfo.release, "4.3-", 4) == 0 || strncmp(osinfo.release, "4.4-", 4) == 0) p->selectable_fd = -1; } } p->read_op = pcap_read_bpf; p->inject_op = pcap_inject_bpf; p->setfilter_op = pcap_setfilter_bpf; p->setdirection_op = pcap_setdirection_bpf; p->set_datalink_op = pcap_set_datalink_bpf; p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_bpf; p->close_op = pcap_close_common; return (p); bad: (void)close(fd); if (p->dlt_list != NULL) free(p->dlt_list); free(p); return (NULL); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { #ifdef HAVE_DAG_API if (dag_platform_finddevs(alldevsp, errbuf) < 0) return (-1); #endif /* HAVE_DAG_API */ return (0); } static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp) { /* * It looks that BPF code generated by gen_protochain() is not * compatible with some of kernel BPF code (for example BSD/OS 3.1). * Take a safer side for now. */ if (no_optimize) { /* * XXX - what if we already have a filter in the kernel? */ if (install_bpf_program(p, fp) < 0) return (-1); p->md.use_bpf = 0; /* filtering in userland */ return (0); } /* * Free any user-mode filter we might happen to have installed. */ pcap_freecode(&p->fcode); /* * Try to install the kernel filter. */ if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", pcap_strerror(errno)); return (-1); } p->md.use_bpf = 1; /* filtering in the kernel */ /* * Discard any previously-received packets, as they might have * passed whatever filter was formerly in effect, but might * not pass this filter (BIOCSETF discards packets buffered * in the kernel, so you can lose packets in any case). */ p->cc = 0; return (0); } /* * Set direction flag: Which packets do we accept on a forwarding * single device? IN, OUT or both? */ static int pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d) { #if defined(BIOCSDIRECTION) u_int direction; direction = (d == PCAP_D_IN) ? BPF_D_IN : ((d == PCAP_D_OUT) ? BPF_D_OUT : BPF_D_INOUT); if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) { (void) snprintf(p->errbuf, sizeof(p->errbuf), "Cannot set direction to %s: %s", (d == PCAP_D_IN) ? "PCAP_D_IN" : ((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"), strerror(errno)); return (-1); } return (0); #elif defined(BIOCSSEESENT) u_int seesent; /* * We don't support PCAP_D_OUT. */ if (d == PCAP_D_OUT) { snprintf(p->errbuf, sizeof(p->errbuf), "Setting direction to PCAP_D_OUT is not supported on BPF"); return -1; } seesent = (d == PCAP_D_INOUT); if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) { (void) snprintf(p->errbuf, sizeof(p->errbuf), "Cannot set direction to %s: %s", (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN", strerror(errno)); return (-1); } return (0); #else (void) snprintf(p->errbuf, sizeof(p->errbuf), "This system doesn't support BIOCSSEESENT, so the direction can't be set"); return (-1); #endif } static int pcap_set_datalink_bpf(pcap_t *p, int dlt) { #ifdef BIOCSDLT if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) { (void) snprintf(p->errbuf, sizeof(p->errbuf), "Cannot set DLT %d: %s", dlt, strerror(errno)); return (-1); } #endif return (0); } libpcap-0.9.7/./fad-glifc.c0000644000026300017500000002444010231053270013375 0ustar mcrmcr/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.5.2.1 2005/04/19 00:54:16 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #ifdef HAVE_SYS_SOCKIO_H #include #endif #include /* concession to AIX */ struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif /* * Get a list of all interfaces that are up and that we can open. * Returns -1 on error, 0 otherwise. * The list, as returned through "alldevsp", may be null if no interfaces * were up and could be opened. * * This is the implementation used on platforms that have SIOCLGIFCONF * but don't have "getifaddrs()". (Solaris 8 and later; we use * SIOCLGIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.) */ int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; register int fd4, fd6, fd; register struct lifreq *ifrp, *ifend; struct lifnum ifn; struct lifconf ifc; char *buf = NULL; unsigned buf_size; #ifdef HAVE_SOLARIS char *p, *q; #endif struct lifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; struct sockaddr *netmask, *broadaddr, *dstaddr; int ret = 0; /* * Create a socket from which to fetch the list of interfaces, * and from which to fetch IPv4 information. */ fd4 = socket(AF_INET, SOCK_DGRAM, 0); if (fd4 < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); return (-1); } /* * Create a socket from which to fetch IPv6 information. */ fd6 = socket(AF_INET6, SOCK_DGRAM, 0); if (fd6 < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); (void)close(fd4); return (-1); } /* * How many entries will SIOCGLIFCONF return? */ ifn.lifn_family = AF_UNSPEC; ifn.lifn_flags = 0; ifn.lifn_count = 0; if (ioctl(fd4, SIOCGLIFNUM, (char *)&ifn) < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFNUM: %s", pcap_strerror(errno)); (void)close(fd6); (void)close(fd4); return (-1); } /* * Allocate a buffer for those entries. */ buf_size = ifn.lifn_count * sizeof (struct lifreq); buf = malloc(buf_size); if (buf == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); (void)close(fd6); (void)close(fd4); return (-1); } /* * Get the entries. */ ifc.lifc_len = buf_size; ifc.lifc_buf = buf; ifc.lifc_family = AF_UNSPEC; ifc.lifc_flags = 0; memset(buf, 0, buf_size); if (ioctl(fd4, SIOCGLIFCONF, (char *)&ifc) < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFCONF: %s", pcap_strerror(errno)); (void)close(fd6); (void)close(fd4); free(buf); return (-1); } /* * Loop over the entries. */ ifrp = (struct lifreq *)buf; ifend = (struct lifreq *)(buf + ifc.lifc_len); for (; ifrp < ifend; ifrp++) { /* * IPv6 or not? */ if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6) fd = fd6; else fd = fd4; /* * Skip entries that begin with "dummy". * XXX - what are these? Is this Linux-specific? * Are there platforms on which we shouldn't do this? */ if (strncmp(ifrp->lifr_name, "dummy", 5) == 0) continue; #ifdef HAVE_SOLARIS /* * Skip entries that have a ":" followed by a number * at the end - those are Solaris virtual interfaces * on which you can't capture. */ p = strchr(ifrp->lifr_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ while (isdigit((unsigned char)*p)) p++; if (*p == '\0') { /* * All digits after the ":" until the end. */ continue; } } #endif /* * Get the flags for this interface, and skip it if it's * not up. */ strncpy(ifrflags.lifr_name, ifrp->lifr_name, sizeof(ifrflags.lifr_name)); if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) { if (errno == ENXIO) continue; (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFFLAGS: %.*s: %s", (int)sizeof(ifrflags.lifr_name), ifrflags.lifr_name, pcap_strerror(errno)); ret = -1; break; } if (!(ifrflags.lifr_flags & IFF_UP)) continue; /* * Get the netmask for this address on this interface. */ strncpy(ifrnetmask.lifr_name, ifrp->lifr_name, sizeof(ifrnetmask.lifr_name)); memcpy(&ifrnetmask.lifr_addr, &ifrp->lifr_addr, sizeof(ifrnetmask.lifr_addr)); if (ioctl(fd, SIOCGLIFNETMASK, (char *)&ifrnetmask) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ netmask = NULL; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFNETMASK: %.*s: %s", (int)sizeof(ifrnetmask.lifr_name), ifrnetmask.lifr_name, pcap_strerror(errno)); ret = -1; break; } } else netmask = (struct sockaddr *)&ifrnetmask.lifr_addr; /* * Get the broadcast address for this address on this * interface (if any). */ if (ifrflags.lifr_flags & IFF_BROADCAST) { strncpy(ifrbroadaddr.lifr_name, ifrp->lifr_name, sizeof(ifrbroadaddr.lifr_name)); memcpy(&ifrbroadaddr.lifr_addr, &ifrp->lifr_addr, sizeof(ifrbroadaddr.lifr_addr)); if (ioctl(fd, SIOCGLIFBRDADDR, (char *)&ifrbroadaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ broadaddr = NULL; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFBRDADDR: %.*s: %s", (int)sizeof(ifrbroadaddr.lifr_name), ifrbroadaddr.lifr_name, pcap_strerror(errno)); ret = -1; break; } } else broadaddr = (struct sockaddr *)&ifrbroadaddr.lifr_broadaddr; } else { /* * Not a broadcast interface, so no broadcast * address. */ broadaddr = NULL; } /* * Get the destination address for this address on this * interface (if any). */ if (ifrflags.lifr_flags & IFF_POINTOPOINT) { strncpy(ifrdstaddr.lifr_name, ifrp->lifr_name, sizeof(ifrdstaddr.lifr_name)); memcpy(&ifrdstaddr.lifr_addr, &ifrp->lifr_addr, sizeof(ifrdstaddr.lifr_addr)); if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&ifrdstaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ dstaddr = NULL; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGLIFDSTADDR: %.*s: %s", (int)sizeof(ifrdstaddr.lifr_name), ifrdstaddr.lifr_name, pcap_strerror(errno)); ret = -1; break; } } else dstaddr = (struct sockaddr *)&ifrdstaddr.lifr_dstaddr; } else dstaddr = NULL; #ifdef HAVE_SOLARIS /* * If this entry has a colon followed by a number at * the end, it's a logical interface. Those are just * the way you assign multiple IP addresses to a real * interface, so an entry for a logical interface should * be treated like the entry for the real interface; * we do that by stripping off the ":" and the number. */ p = strchr(ifrp->lifr_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ q = p + 1; while (isdigit((unsigned char)*q)) q++; if (*q == '\0') { /* * All digits after the ":" until the end. * Strip off the ":" and everything after * it. */ *p = '\0'; } } #endif /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifrp->lifr_name, ifrflags.lifr_flags, (struct sockaddr *)&ifrp->lifr_addr, sizeof (struct sockaddr_storage), netmask, sizeof (struct sockaddr_storage), broadaddr, sizeof (struct sockaddr_storage), dstaddr, sizeof (struct sockaddr_storage), errbuf) < 0) { ret = -1; break; } } free(buf); (void)close(fd6); (void)close(fd4); if (ret != -1) { /* * We haven't had any errors yet; do any platform-specific * operations to add devices. */ if (pcap_platform_finddevs(&devlist, errbuf) < 0) ret = -1; } if (ret == -1) { /* * We had an error; free the list we've been constructing. */ if (devlist != NULL) { pcap_freealldevs(devlist); devlist = NULL; } } *alldevsp = devlist; return (ret); } libpcap-0.9.7/./FILES0000644000026300017500000000341310262571366012216 0ustar mcrmcrCHANGES ChmodBPF/ChmodBPF ChmodBPF/StartupParameters.plist CREDITS FILES INSTALL.txt LICENSE Makefile.in README README.aix README.dag README.hpux README.linux README.macosx README.septel README.tru64 README.Win32 SUNOS4/nit_if.o.sparc SUNOS4/nit_if.o.sun3 SUNOS4/nit_if.o.sun4c.4.0.3c TODO VERSION acconfig.h aclocal.m4 arcnet.h atmuni31.h bpf/net/bpf_filter.c bpf_dump.c bpf_image.c config.guess config.h.in config.sub configure configure.in etherent.c ethertype.h fad-getad.c fad-gifc.c fad-glifc.c fad-null.c fad-win32.c gencode.c gencode.h grammar.y inet.c install-sh lbl/os-aix4.h lbl/os-hpux11.h lbl/os-osf4.h lbl/os-osf5.h lbl/os-solaris2.h lbl/os-sunos4.h lbl/os-ultrix4.h llc.h missing/snprintf.c mkdep msdos/bin2c.c msdos/common.dj msdos/makefile msdos/makefile.dj msdos/makefile.wc msdos/ndis2.c msdos/ndis2.h msdos/ndis_0.asm msdos/pkt_rx0.asm msdos/pkt_rx1.s msdos/pktdrvr.c msdos/pktdrvr.h msdos/readme.dos nametoaddr.c nlpid.h optimize.c packaging/pcap.spec packaging/pcap.spec.in pcap-bpf.c pcap-bpf.h pcap-dag.c pcap-dag.h pcap-dlpi.c pcap-dos.c pcap-dos.h pcap-enet.c pcap-int.h pcap-linux.c pcap-namedb.h pcap-nit.c pcap-nit.h pcap-null.c pcap-pf.c pcap-pf.h pcap-septel.c pcap-septel.h pcap-stdinc.h pcap-snit.c pcap-snoop.c pcap-win32.c pcap.3 pcap.c pcap.h pf.h ppp.h savefile.c scanner.l sll.h sunatmpos.h Win32/Include/Gnuc.h Win32/Include/addrinfo.h Win32/Include/bittypes.h Win32/Include/cdecl_ext.h Win32/Include/inetprivate.h Win32/Include/ip6_misc.h Win32/Include/sockstorage.h Win32/Include/arpa/nameser.h Win32/Include/net/if.h Win32/Include/net/netdb.h Win32/Include/net/paths.h Win32/Src/ffs.c Win32/Src/getaddrinfo.c Win32/Src/getnetbynm.c Win32/Src/getnetent.c Win32/Src/getopt.c Win32/Src/getservent.c Win32/Src/inet_aton.c Win32/Src/inet_net.c Win32/Src/inet_pton.c libpcap-0.9.7/./pcap.30000644000026300017500000010650210633321704012432 0ustar mcrmcr.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.64.2.11 2007/06/11 09:52:05 guy Exp $ .\" .\" 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 "27 February 2004" .SH NAME pcap \- Packet Capture library .SH SYNOPSIS .nf .ft B #include .ft .LP .nf .ft B char errbuf[PCAP_ERRBUF_SIZE]; .ft .LP .ft B pcap_t *pcap_open_live(const char *device, int snaplen, .ti +8 int promisc, int to_ms, char *errbuf) pcap_t *pcap_open_dead(int linktype, int snaplen) pcap_t *pcap_open_offline(const char *fname, char *errbuf) pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf) pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname) pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp) .ft .LP .ft B int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf); int pcap_getnonblock(pcap_t *p, char *errbuf); .ft .LP .ft B int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) void pcap_freealldevs(pcap_if_t *alldevs) char *pcap_lookupdev(char *errbuf) int pcap_lookupnet(const char *device, bpf_u_int32 *netp, .ti +8 bpf_u_int32 *maskp, char *errbuf) .ft .LP .ft B typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h, .ti +8 const u_char *bytes); .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 .LP .ft B int pcap_compile(pcap_t *p, struct bpf_program *fp, .ti +8 const char *str, int optimize, bpf_u_int32 netmask) int pcap_setfilter(pcap_t *p, struct bpf_program *fp) void pcap_freecode(struct bpf_program *) int pcap_setdirection(pcap_t *p, pcap_direction_t d) .ft .LP .ft B const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h) int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, .ti +8 const u_char **pkt_data) .ft .LP .ft B void pcap_breakloop(pcap_t *) .ft .LP .ft B int pcap_inject(pcap_t *p, const void *buf, size_t size) int pcap_sendpacket(pcap_t *p, const u_char *buf, int size) .ft .LP .ft B int pcap_datalink(pcap_t *p) int pcap_list_datalinks(pcap_t *p, int **dlt_buf); int pcap_set_datalink(pcap_t *p, int dlt); int pcap_datalink_name_to_val(const char *name); const char *pcap_datalink_val_to_name(int dlt); const char *pcap_datalink_val_to_description(int dlt); 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) int pcap_get_selectable_fd(pcap_t *p); void pcap_perror(pcap_t *p, char *prefix) char *pcap_geterr(pcap_t *p) const char *pcap_strerror(int error) const char *pcap_lib_version(void) .ft .LP .ft B void pcap_close(pcap_t *p) int pcap_dump_flush(pcap_dumper_t *p) long pcap_dump_ftell(pcap_dumper_t *p) FILE *pcap_dump_file(pcap_dumper_t *p) void pcap_dump_close(pcap_dumper_t *p) .ft .fi .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. .PP .SH ROUTINES NOTE: .I errbuf in .BR pcap_open_live() , .BR pcap_open_dead() , .BR pcap_open_offline() , .BR pcap_fopen_offline() , .BR pcap_setnonblock() , .BR pcap_getnonblock() , .BR pcap_findalldevs() , .BR pcap_lookupdev() , and .B pcap_lookupnet() is assumed to be able to hold at least .B PCAP_ERRBUF_SIZE chars. .PP .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; on Linux systems with 2.2 or later kernels, a .I device argument of "any" or .B NULL can be used to capture packets from all interfaces. .I snaplen specifies the maximum number of bytes to capture. If this value is less than the size of a packet that is captured, only the first .I snaplen bytes of that packet will be captured and provided as packet data. A value of 65535 should be sufficient, on most if not all networks, to capture all the data available from the packet. .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.) For now, this doesn't work on the "any" device; if an argument of "any" or NULL is supplied, the .I promisc flag is ignored. .I to_ms specifies the read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it wait for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored. A zero value for .IR to_ms , on platforms that support a read timeout, will cause a read to wait forever to allow enough packets to arrive, with no timeout. .I errbuf is used to return error or warning text. It will be set to error text when .B pcap_open_live() fails and returns .BR NULL . .I errbuf may also be set to warning text when .B pcap_open_live() succeds; to detect this case the caller should store a zero-length string in .I errbuf before calling .B pcap_open_live() and display the warning to the user if .I errbuf is no longer a zero-length string. .PP .B pcap_open_dead() is used for creating a .B pcap_t structure to use when calling the other functions in libpcap. It is typically used when just using libpcap for compiling BPF code. .PP .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) and .BR tcpslice(1) . The name "-" in a synonym for .BR stdin . Alternatively, you may call .B pcap_fopen_offline() to read dumped data from an existing open stream .IR fp . Note that on Windows, that stream should be opened in binary mode. .I errbuf is used to return error text and is only set when .B pcap_open_offline() or .B pcap_fopen_offline() fails and returns .BR NULL . .PP .B pcap_dump_open() is called to open a ``savefile'' for writing. The name "-" in a synonym for .BR stdout . .B NULL is returned on failure. .I p is a .I pcap struct as returned by .B pcap_open_offline() or .BR pcap_open_live() . .I fname specifies the name of the file to open. Alternatively, you may call .B pcap_dump_fopen() to write data to an existing open stream .IR fp . Note that on Windows, that stream should be opened in binary mode. If .B NULL is returned, .B pcap_geterr() can be used to get the error text. .PP .PP .B pcap_setnonblock() puts a capture descriptor, opened with .BR pcap_open_live() , into ``non-blocking'' mode, or takes it out of ``non-blocking'' mode, depending on whether the .I nonblock argument is non-zero or zero. It has no effect on ``savefiles''. If there is an error, \-1 is returned and .I errbuf is filled in with an appropriate error message; otherwise, 0 is returned. In ``non-blocking'' mode, an attempt to read from the capture descriptor with .B pcap_dispatch() will, if no packets are currently available to be read, return 0 immediately rather than blocking waiting for packets to arrive. .B pcap_loop() and .B pcap_next() will not work in ``non-blocking'' mode. .PP .B pcap_getnonblock() returns the current ``non-blocking'' state of the capture descriptor; it always returns 0 on ``savefiles''. If there is an error, \-1 is returned and .I errbuf is filled in with an appropriate error message. .PP .B pcap_findalldevs() constructs a list of network devices that can be opened with .BR pcap_open_live() . (Note that there may be network devices that cannot be opened with .BR pcap_open_live() by the process calling .BR pcap_findalldevs() , because, for example, that process might not have sufficient privileges to open them for capturing; if so, those devices will not appear on the list.) .I alldevsp is set to point to the first element of the list; each element of the list is of type .BR pcap_if_t , and has the following members: .RS .TP .B next if not .BR NULL , a pointer to the next element in the list; .B NULL for the last element of the list .TP .B name a pointer to a string giving a name for the device to pass to .B pcap_open_live() .TP .B description if not .BR NULL , a pointer to a string giving a human-readable description of the device .TP .B addresses a pointer to the first element of a list of addresses for the interface .TP .B flags interface flags: .RS .TP .B PCAP_IF_LOOPBACK set if the interface is a loopback interface .RE .RE .PP Each element of the list of addresses is of type .BR pcap_addr_t , and has the following members: .RS .TP .B next if not .BR NULL , a pointer to the next element in the list; .B NULL for the last element of the list .TP .B addr a pointer to a .B "struct sockaddr" containing an address .TP .B netmask if not .BR NULL , a pointer to a .B "struct sockaddr" that contains the netmask corresponding to the address pointed to by .B addr .TP .B broadaddr if not .BR NULL , a pointer to a .B "struct sockaddr" that contains the broadcast address corresponding to the address pointed to by .BR addr ; may be null if the interface doesn't support broadcasts .TP .B dstaddr if not .BR NULL , a pointer to a .B "struct sockaddr" that contains the destination address corresponding to the address pointed to by .BR addr ; may be null if the interface isn't a point-to-point interface .RE .PP Note that not all the addresses in the list of addresses are necessarily IPv4 or IPv6 addresses - you must check the .B sa_family member of the .B "struct sockaddr" before interpreting the contents of the address. .PP .B \-1 is returned on failure, in which case .B errbuf is filled in with an appropriate error message; .B 0 is returned on success. .PP .B pcap_freealldevs() is used to free a list allocated by .BR pcap_findalldevs() . .PP .B pcap_lookupdev() returns a pointer to a network device suitable for use with .B pcap_open_live() and .BR pcap_lookupnet() . If there is an error, .B NULL is returned and .I errbuf is filled in with an appropriate error message. .PP .B pcap_lookupnet() is used to determine the network number and mask associated with the network device .BR device . Both .I netp and .I maskp are .I bpf_u_int32 pointers. A return of \-1 indicates an error in which case .I errbuf is filled in with an appropriate error message. .PP .B pcap_dispatch() is used to collect and process packets. .I cnt specifies the maximum number of packets to process before returning. This is not a minimum number; when reading a live capture, only one bufferful of packets is read at a time, so fewer than .I cnt packets may be processed. A .I cnt of \-1 processes all the packets received in one buffer when reading a live capture, or all the packets in the file when reading a ``savefile''. .I callback specifies a routine to be called with three arguments: a .I u_char pointer which is passed in from .BR pcap_dispatch() , a .I const struct pcap_pkthdr pointer to a structure with the following members: .RS .TP .B ts a .I struct timeval containing the time when the packet was captured .TP .B caplen a .I bpf_u_int32 giving the number of bytes of the packet that are available from the capture .TP .B len a .I bpf_u_int32 giving the length of the packet, in bytes (which might be more than the number of bytes available from the capture, if the length of the packet is larger than the maximum number of bytes to capture) .RE .PP and a .I const u_char pointer to the first .B caplen (as given in the .I struct pcap_pkthdr a pointer to which is passed to the callback routine) bytes of data from the packet (which won't necessarily be the entire packet; to capture the entire packet, you will have to provide a value for .I snaplen in your call to .B pcap_open_live() that is sufficiently large to get all of the packet's data - a value of 65535 should be sufficient on most if not all networks). .PP The number of packets read is returned. 0 is returned if no packets were read from a live capture (if, for example, they were discarded because they didn't pass the packet filter, or if, on platforms that support a read timeout that starts before any packets arrive, the timeout expires before any packets arrive, or if the file descriptor for the capture device is in non-blocking mode and no packets were available to be read) or if no more packets are available in a ``savefile.'' A return of \-1 indicates an error in which case .B pcap_perror() or .B pcap_geterr() may be used to display the error text. A return of \-2 indicates that the loop terminated due to a call to .B pcap_breakloop() before any packets were processed. .ft B If your application uses pcap_breakloop(), make sure that you explicitly check for \-1 and \-2, rather than just checking for a return value < 0. .ft R .PP .BR NOTE : when reading a live capture, .B pcap_dispatch() will not necessarily return when the read times out; on some platforms, the read timeout isn't supported, and, on other platforms, the timer doesn't start until at least one packet arrives. This means that the read timeout should .B NOT be used in, for example, an interactive application, to allow the packet capture loop to ``poll'' for user input periodically, as there's no guarantee that .B pcap_dispatch() will return after the timeout expires. .PP .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). \-1 is returned on an error; 0 is returned if .I cnt is exhausted; \-2 is returned if the loop terminated due to a call to .B pcap_breakloop() before any packets were processed. .ft B If your application uses pcap_breakloop(), make sure that you explicitly check for \-1 and \-2, rather than just checking for a return value < 0. .ft R .PP .B pcap_next() reads the next packet (by calling .B pcap_dispatch() with a .I cnt of 1) and returns a .I u_char pointer to the data in that packet. (The .I pcap_pkthdr struct for that packet is not supplied.) .B NULL is returned if an error occured, or if no packets were read from a live capture (if, for example, they were discarded because they didn't pass the packet filter, or if, on platforms that support a read timeout that starts before any packets arrive, the timeout expires before any packets arrive, or if the file descriptor for the capture device is in non-blocking mode and no packets were available to be read), or if no more packets are available in a ``savefile.'' Unfortunately, there is no way to determine whether an error occured or not. .PP .B pcap_next_ex() reads the next packet and returns a success/failure indication: .RS .TP 1 the packet was read without problems .TP 0 packets are being read from a live capture, and the timeout expired .TP \-1 an error occurred while reading the packet .TP \-2 packets are being read from a ``savefile'', and there are no more packets to read from the savefile. .RE .PP If the packet was read without problems, the pointer pointed to by the .I pkt_header argument is set to point to the .I pcap_pkthdr struct for the packet, and the pointer pointed to by the .I pkt_data argument is set to point to the data in the packet. .PP .B pcap_breakloop() sets a flag that will force .B pcap_dispatch() or .B pcap_loop() to return rather than looping; they will return the number of packets that have been processed so far, or \-2 if no packets have been processed so far. .PP This routine is safe to use inside a signal handler on UNIX or a console control handler on Windows, as it merely sets a flag that is checked within the loop. .PP The flag is checked in loops reading packets from the OS - a signal by itself will not necessarily terminate those loops - as well as in loops processing a set of packets returned by the OS. .ft B Note that if you are catching signals on UNIX systems that support restarting system calls after a signal, and calling pcap_breakloop() in the signal handler, you must specify, when catching those signals, that system calls should NOT be restarted by that signal. Otherwise, if the signal interrupted a call reading packets in a live capture, when your signal handler returns after calling pcap_breakloop(), the call will be restarted, and the loop will not terminate until more packets arrive and the call completes. .PP Note also that, in a multi-threaded application, if one thread is blocked in .BR pcap_dispatch() , .BR pcap_loop() , .BR pcap_next() , or .BR pcap_next_ex() , a call to .B pcap_breakloop() in a different thread will not unblock that thread; you will need to use whatever mechanism the OS provides for breaking a thread out of blocking calls in order to unblock the thread, such as thread cancellation in systems that support POSIX threads. .ft R .PP Note that .B pcap_next() will, on some platforms, loop reading packets from the OS; that loop will not necessarily be terminated by a signal, so .B pcap_breakloop() should be used to terminate packet processing even if .B pcap_next() is being used. .PP .B pcap_breakloop() does not guarantee that no further packets will be processed by .B pcap_dispatch() or .B pcap_loop() after it is called; at most one more packet might be processed. .PP If \-2 is returned from .B pcap_dispatch() or .BR pcap_loop() , the flag is cleared, so a subsequent call will resume reading packets. If a positive number is returned, the flag is not cleared, so a subsequent call will return \-2 and clear the flag. .PP .B pcap_inject() sends a raw packet through the network interface; .I buf points to the data of the packet, including the link-layer header, and .I size is the number of bytes in the packet. It returns the number of bytes written on success. A return of \-1 indicates an error in which case .B pcap_perror() or .B pcap_geterr() may be used to display the error text. Note that, even if you successfully open the network interface, you might not have permission to send packets on it, or it might not support sending packets; as .I pcap_open_live() doesn't have a flag to indicate whether to open for capturing, sending, or capturing and sending, you cannot request an open that supports sending and be notified at open time whether sending will be possible. Note also that some devices might not support sending packets. .PP Note that, on some platforms, the link-layer header of the packet that's sent might not be the same as the link-layer header of the packet supplied to .BR pcap_inject() , as the source link-layer address, if the header contains such an address, might be changed to be the address assigned to the interface on which the packet it sent, if the platform doesn't support sending completely raw and unchanged packets. Even worse, some drivers on some platforms might change the link-layer type field to whatever value libpcap used when attaching to the device, even on platforms that .I do nominally support sending completely raw and unchanged packets. .PP .B pcap_sendpacket() is like .BR pcap_inject() , but it returns 0 on success and \-1 on failure. .RB ( pcap_inject() comes from OpenBSD; .B pcap_sendpacket() comes from WinPcap. Both are provided for compatibility.) .PP .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 .B pcap_dispatch() or .BR pcap_loop() . If called directly, the .I user parameter is of type .I pcap_dumper_t as returned by .BR pcap_dump_open() . .PP .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 IPv4 netmask of the network on which packets are being captured; it is used only when checking for IPv4 broadcast addresses in the filter program. If the netmask of the network on which packets are being captured isn't known to the program, or if packets are being captured on the Linux "any" pseudo-interface that can capture on more than one network, a value of 0 can be supplied; tests for IPv4 broadcast addreses won't be done correctly, but all other tests in the filter program will be OK. A return of \-1 indicates an error in which case .BR pcap_geterr() may be used to display the error text. .PP .B pcap_compile_nopcap() is similar to .B pcap_compile() except that instead of passing a pcap structure, one passes the snaplen and linktype explicitly. It is intended to be used for compiling filters for direct BPF usage, without necessarily having called .BR pcap_open() . A return of \-1 indicates an error; the error text is unavailable. .RB ( pcap_compile_nopcap() is a wrapper around .BR pcap_open_dead() , .BR pcap_compile() , and .BR pcap_close() ; the latter three routines can be used directly in order to get the error text for a compilation error.) .B .PP .B pcap_setfilter() is used to specify a filter program. .I fp is a pointer to a .I bpf_program struct, usually the result of a call to .BR pcap_compile() . .B \-1 is returned on failure, in which case .BR pcap_geterr() may be used to display the error text; .B 0 is returned on success. .PP .B pcap_freecode() is used to free up allocated memory pointed to by a .I bpf_program struct generated by .B pcap_compile() when that BPF program is no longer needed, for example after it has been made the filter program for a pcap structure by a call to .BR pcap_setfilter() . .PP .B pcap_setdirection() is used to specify a direction that packets will be captured. .I pcap_direction_t is one of the constants .BR PCAP_D_IN , .B PCAP_D_OUT or .BR PCAP_D_INOUT . .B PCAP_D_IN will only capture packets received by the device, .B PCAP_D_OUT will only capture packets sent by the device and .B PCAP_D_INOUT will capture packets received by or sent by the device. .B PCAP_D_INOUT is the default setting if this function is not called. This isn't necessarily supported on all platforms; some platforms might return an error, and some other platforms might not support .BR PCAP_D_OUT . This operation is not supported if a ``savefile'' is being read. .B \-1 is returned on failure, .B 0 is returned on success. .PP .B pcap_datalink() returns the link layer type; link layer types it can return include: .PP .RS 5 .TP 5 .B DLT_NULL BSD loopback encapsulation; the link layer header is a 4-byte field, in .I host byte order, containing a PF_ value from .B socket.h for the network-layer protocol of the packet. .IP Note that ``host byte order'' is the byte order of the machine on which the packets are captured, and the PF_ values are for the OS of the machine on which the packets are captured; if a live capture is being done, ``host byte order'' is the byte order of the machine capturing the packets, and the PF_ values are those of the OS of the machine capturing the packets, but if a ``savefile'' is being read, the byte order and PF_ values are .I not necessarily those of the machine reading the capture file. .TP 5 .B DLT_EN10MB Ethernet (10Mb, 100Mb, 1000Mb, and up) .TP 5 .B DLT_IEEE802 IEEE 802.5 Token Ring .TP 5 .B DLT_ARCNET ARCNET .TP 5 .B DLT_SLIP SLIP; the link layer header contains, in order: .RS 10 .LP a 1-byte flag, which is 0 for packets received by the machine and 1 for packets sent by the machine; .LP a 1-byte field, the upper 4 bits of which indicate the type of packet, as per RFC 1144: .RS 5 .TP 5 0x40 an unmodified IP datagram (TYPE_IP); .TP 5 0x70 an uncompressed-TCP IP datagram (UNCOMPRESSED_TCP), with that byte being the first byte of the raw IP header on the wire, containing the connection number in the protocol field; .TP 5 0x80 a compressed-TCP IP datagram (COMPRESSED_TCP), with that byte being the first byte of the compressed TCP/IP datagram header; .RE .LP for UNCOMPRESSED_TCP, the rest of the modified IP header, and for COMPRESSED_TCP, the compressed TCP/IP datagram header; .RE .RS 5 .LP for a total of 16 bytes; the uncompressed IP datagram follows the header. .RE .TP 5 .B DLT_PPP PPP; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like framing, with the PPP header following those two bytes, otherwise it's PPP without framing, and the packet begins with the PPP header. .TP 5 .B DLT_FDDI FDDI .TP 5 .B DLT_ATM_RFC1483 RFC 1483 LLC/SNAP-encapsulated ATM; the packet begins with an IEEE 802.2 LLC header. .TP 5 .B DLT_RAW raw IP; the packet begins with an IP header. .TP 5 .B DLT_PPP_SERIAL PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547; the first byte will be 0xFF for PPP in HDLC-like framing, and will be 0x0F or 0x8F for Cisco PPP with HDLC framing. .TP 5 .B DLT_PPP_ETHER PPPoE; the packet begins with a PPPoE header, as per RFC 2516. .TP 5 .B DLT_C_HDLC Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547. .TP 5 .B DLT_IEEE802_11 IEEE 802.11 wireless LAN .TP 5 .B DLT_FRELAY Frame Relay .TP 5 .B DLT_LOOP OpenBSD loopback encapsulation; the link layer header is a 4-byte field, in .I network byte order, containing a PF_ value from OpenBSD's .B socket.h for the network-layer protocol of the packet. .IP Note that, if a ``savefile'' is being read, those PF_ values are .I not necessarily those of the machine reading the capture file. .TP 5 .B DLT_LINUX_SLL Linux "cooked" capture encapsulation; the link layer header contains, in order: .RS 10 .LP a 2-byte "packet type", in network byte order, which is one of: .RS 5 .TP 5 0 packet was sent to us by somebody else .TP 5 1 packet was broadcast by somebody else .TP 5 2 packet was multicast, but not broadcast, by somebody else .TP 5 3 packet was sent by somebody else to somebody else .TP 5 4 packet was sent by us .RE .LP a 2-byte field, in network byte order, containing a Linux ARPHRD_ value for the link layer device type; .LP a 2-byte field, in network byte order, containing the length of the link layer address of the sender of the packet (which could be 0); .LP an 8-byte field containing that number of bytes of the link layer header (if there are more than 8 bytes, only the first 8 are present); .LP a 2-byte field containing an Ethernet protocol type, in network byte order, or containing 1 for Novell 802.3 frames without an 802.2 LLC header or 4 for frames beginning with an 802.2 LLC header. .RE .TP 5 .B DLT_LTALK Apple LocalTalk; the packet begins with an AppleTalk LLAP header. .TP 5 .B DLT_PFLOG OpenBSD pflog; the link layer header contains, in order: .RS 10 .LP a 1-byte header length, in host byte order; .LP a 4-byte PF_ value, in host byte order; .LP a 2-byte action code, in network byte order, which is one of: .RS 5 .TP 5 0 passed .TP 5 1 dropped .TP 5 2 scrubbed .RE .LP a 2-byte reason code, in network byte order, which is one of: .RS 5 .TP 5 0 match .TP 5 1 bad offset .TP 5 2 fragment .TP 5 3 short .TP 5 4 normalize .TP 5 5 memory .RE .LP a 16-character interface name; .LP a 16-character ruleset name (only meaningful if subrule is set); .LP a 4-byte rule number, in network byte order; .LP a 4-byte subrule number, in network byte order; .LP a 1-byte direction, in network byte order, which is one of: .RS 5 .TP 5 0 incoming or outgoing .TP 5 1 incoming .TP 5 2 outgoing .RE .RE .TP 5 .B DLT_PRISM_HEADER Prism monitor mode information followed by an 802.11 header. .TP 5 .B DLT_IP_OVER_FC RFC 2625 IP-over-Fibre Channel, with the link-layer header being the Network_Header as described in that RFC. .TP 5 .B DLT_SUNATM SunATM devices; the link layer header contains, in order: .RS 10 .LP a 1-byte flag field, containing a direction flag in the uppermost bit, which is set for packets transmitted by the machine and clear for packets received by the machine, and a 4-byte traffic type in the low-order 4 bits, which is one of: .RS 5 .TP 5 0 raw traffic .TP 5 1 LANE traffic .TP 5 2 LLC-encapsulated traffic .TP 5 3 MARS traffic .TP 5 4 IFMP traffic .TP 5 5 ILMI traffic .TP 5 6 Q.2931 traffic .RE .LP a 1-byte VPI value; .LP a 2-byte VCI field, in network byte order. .RE .TP 5 .B DLT_IEEE802_11_RADIO link-layer information followed by an 802.11 header - see http://www.shaftnet.org/~pizza/software/capturefrm.txt for a description of the link-layer information. .TP 5 .B DLT_ARCNET_LINUX ARCNET, with no exception frames, reassembled packets rather than raw frames, and an extra 16-bit offset field between the destination host and type bytes. .TP 5 .B DLT_LINUX_IRDA Linux-IrDA packets, with a .B DLT_LINUX_SLL header followed by the IrLAP header. .TP 5 .B DLT_LINUX_LAPD LAPD (Q.921) frames, with a .B DLT_LINUX_SLL header captured via vISDN. .RE .PP .B pcap_list_datalinks() is used to get a list of the supported data link types of the interface associated with the pcap descriptor. .B pcap_list_datalinks() allocates an array to hold the list and sets .IR *dlt_buf . The caller is responsible for freeing the array. .B \-1 is returned on failure; otherwise, the number of data link types in the array is returned. .PP .B pcap_set_datalink() is used to set the current data link type of the pcap descriptor to the type specified by .IR dlt . .B \-1 is returned on failure. .PP .B pcap_datalink_name_to_val() translates a data link type name, which is a .B DLT_ name with the .B DLT_ removed, to the corresponding data link type value. The translation is case-insensitive. .B \-1 is returned on failure. .PP .B pcap_datalink_val_to_name() translates a data link type value to the corresponding data link type name. NULL is returned on failure. .PP .B pcap_datalink_val_to_description() translates a data link type value to a short description of that data link type. NULL is returned on failure. .PP .B pcap_snapshot() returns the snapshot length specified when .B pcap_open_live() was called. .PP .B pcap_is_swapped() returns true if the current ``savefile'' uses a different byte order than the current system. .PP .B pcap_major_version() returns the major number of the file format of the savefile; .B pcap_minor_version() returns the minor number of the file format of the savefile. The version number is stored in the header of the savefile. .PP .B pcap_file() returns the standard I/O stream of the ``savefile,'' if a ``savefile'' was opened with .BR pcap_open_offline() , or NULL, if a network device was opened with .BR pcap_open_live() . .PP .B pcap_stats() returns 0 and fills in the .B pcap_stat structure pointed to by its second argument. The values represent packet statistics from the start of the run to the time of the call. If there is an error or the underlying packet capture doesn't support packet statistics, \-1 is returned and the error text can be obtained with .B pcap_perror() or .BR pcap_geterr() . .B pcap_stats() is supported only on live captures, not on ``savefiles''; no statistics are stored in ``savefiles'', so no statistics are available when reading from a ``savefile''. .PP .B pcap_fileno() returns the file descriptor number from which captured packets are read, if a network device was opened with .BR pcap_open_live() , or \-1, if a ``savefile'' was opened with .BR pcap_open_offline() . .PP .B pcap_get_selectable_fd() returns, on UNIX, a file descriptor number for a file descriptor on which one can do a .B select() or .B poll() to wait for it to be possible to read packets without blocking, if such a descriptor exists, or \-1, if no such descriptor exists. Some network devices opened with .B pcap_open_live() do not support .B select() or .B poll() (for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace DAG devices), so \-1 is returned for those devices. .PP Note that on most versions of most BSDs (including Mac OS X) .B select() and .B poll() do not work correctly on BPF devices; .B pcap_get_selectable_fd() will return a file descriptor on most of those versions (the exceptions being FreeBSD 4.3 and 4.4), a simple .B select() or .B poll() will not return even after a timeout specified in .B pcap_open_live() expires. To work around this, an application that uses .B select() or .B poll() to wait for packets to arrive must put the .B pcap_t in non-blocking mode, and must arrange that the .B select() or .B poll() have a timeout less than or equal to the timeout specified in .BR pcap_open_live() , and must try to read packets after that timeout expires, regardless of whether .B select() or .B poll() indicated that the file descriptor for the .B pcap_t is ready to be read or not. (That workaround will not work in FreeBSD 4.3 and later; however, in FreeBSD 4.6 and later, .B select() and .B poll() work correctly on BPF devices, so the workaround isn't necessary, although it does no harm.) .PP .B pcap_get_selectable_fd() is not available on Windows. .PP .B pcap_perror() prints the text of the last pcap library error on .BR stderr , prefixed by .IR prefix . .PP .B pcap_geterr() returns the error text pertaining to the last pcap library error. .BR NOTE : the pointer it returns will no longer point to a valid error message string after the .B pcap_t passed to it is closed; you must use or copy the string before closing the .BR pcap_t . .PP .B pcap_strerror() is provided in case .BR strerror (1) isn't available. .PP .B pcap_lib_version() returns a pointer to a string giving information about the version of the libpcap library being used; note that it contains more information than just a version number. .PP .B pcap_close() closes the files associated with .I p and deallocates resources. .PP .B pcap_dump_file() returns the standard I/O stream of the ``savefile'' opened by .BR pcap_dump_open(). .PP .B pcap_dump_flush() flushes the output buffer to the ``savefile,'' so that any packets written with .B pcap_dump() but not yet written to the ``savefile'' will be written. .B \-1 is returned on error, 0 on success. .PP .B pcap_dump_ftell() returns the current file position for the ``savefile'', representing the number of bytes written by .B pcap_dump_open() and .BR pcap_dump() . .B \-1 is returned on error. .PP .B pcap_dump_close() closes the ``savefile.'' .PP .SH SEE ALSO tcpdump(1), tcpslice(1) .SH AUTHORS The original authors are: .LP Van Jacobson, Craig Leres and Steven McCanne, all of the Lawrence Berkeley National Laboratory, University of California, Berkeley, CA. .LP The current version is available from "The Tcpdump Group"'s Web site at .LP .RS .I http://www.tcpdump.org/ .RE .SH BUGS Please send problems, bugs, questions, desirable enhancements, etc. to: .LP .RS tcpdump-workers@tcpdump.org .RE .LP Please send source code contributions, etc. to: .LP .RS patches@tcpdump.org .RE libpcap-0.9.7/./README0000644000026300017500000000733010132635464012307 0ustar mcrmcr@(#) $Header: /tcpdump/master/libpcap/README,v 1.30 2004/10/12 02:02:28 guy Exp $ (LBL) LIBPCAP 0.9 Now maintained by "The Tcpdump Group" See www.tcpdump.org Please send inquiries/comments/reports to tcpdump-workers@tcpdump.org Anonymous CVS is available via: cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master login (password "anoncvs") cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout libpcap Version 0.9 of LIBPCAP can be retrieved with the CVS tag "libpcap_0_9rel1": cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_0_9rel1 libpcap Please send patches against the master copy to patches@tcpdump.org. formerly from Lawrence Berkeley National Laboratory Network Research Group ftp://ftp.ee.lbl.gov/libpcap.tar.Z (0.4) This directory contains source code for libpcap, a system-independent interface for user-level packet capture. libpcap provides a portable framework for low-level network monitoring. Applications include network statistics collection, security monitoring, network debugging, etc. Since almost every system vendor provides a different interface for packet capture, and since we've developed several tools that require this functionality, we've created this system-independent API to ease in porting and to alleviate the need for several system-dependent packet capture modules in each application. Note well: this interface is new and is likely to change. For some platforms there are README.{system} files that discuss issues with the OS's interface for packet capture on those platforms, such as how to enable support for that interface in the OS, if it's not built in by default. The libpcap interface supports a filtering mechanism based on the architecture in the BSD packet filter. BPF is described in the 1993 Winter Usenix paper ``The BSD Packet Filter: A New Architecture for User-level Packet Capture''. A compressed PostScript version can be found at ftp://ftp.ee.lbl.gov/papers/bpf-usenix93.ps.Z or http://www.tcpdump.org/papers/bpf-usenix93.ps.Z and a gzipped version can be found at http://www.tcpdump.org/papers/bpf-usenix93.ps.gz A PDF version can be found at http://www.tcpdump.org/papers/bpf-usenix93.pdf Although most packet capture interfaces support in-kernel filtering, libpcap utilizes in-kernel filtering only for the BPF interface. On systems that don't have BPF, all packets are read into user-space and the BPF filters are evaluated in the libpcap library, incurring added overhead (especially, for selective filters). Ideally, libpcap would translate BPF filters into a filter program that is compatible with the underlying kernel subsystem, but this is not yet implemented. BPF is standard in 4.4BSD, BSD/OS, NetBSD, FreeBSD, and OpenBSD. DEC OSF/1/Digital UNIX/Tru64 UNIX uses the packetfilter interface but has been extended to accept BPF filters (which libpcap utilizes). Also, you can add BPF filter support to Ultrix using the kernel source and/or object patches available in: ftp://gatekeeper.dec.com/pub/DEC/net/bpfext42.tar.Z. Linux, in the 2.2 kernel and later kernels, has a "Socket Filter" mechanism that accepts BPF filters; see the README.linux file for information on configuring that option. Problems, bugs, questions, desirable enhancements, etc. should be sent to the address "tcpdump-workers@tcpdump.org". Bugs, support requests, and feature requests may also be submitted on the SourceForge site for libpcap at http://sourceforge.net/projects/libpcap/ Source code contributions, etc. should be sent to the email address "patches@tcpdump.org", or submitted as patches on the SourceForge site for libpcap. Current versions can be found at www.tcpdump.org, or the SourceForge site for libpcap. - The TCPdump team libpcap-0.9.7/./CVS/0000755000026300017500000000000010651262543012057 5ustar mcrmcrlibpcap-0.9.7/./CVS/Entries0000644000026300017500000001102710651262543013414 0ustar mcrmcr/.cvsignore/1.4/Sat Mar 1 05:04:40 2003//Tlibpcap_0_9 /LICENSE/1.1/Mon Oct 9 22:38:56 2000//Tlibpcap_0_9 /README/1.30/Tue Oct 12 02:02:28 2004//Tlibpcap_0_9 /README.Win32/1.1/Fri Aug 9 13:55:12 2002//Tlibpcap_0_9 /README.aix/1.5/Thu Apr 17 06:32:37 2003//Tlibpcap_0_9 /README.hpux/1.4/Sat Jan 15 01:23:56 2005//Tlibpcap_0_9 /README.linux/1.2/Sun Jul 29 18:25:46 2001//Tlibpcap_0_9 /README.macosx/1.1/Mon Oct 18 09:51:02 2004//Tlibpcap_0_9 /README.tru64/1.1/Wed Jan 24 06:52:53 2001//Tlibpcap_0_9 /acconfig.h/1.3/Mon Nov 12 22:18:01 2001//Tlibpcap_0_9 /aclocal.m4/1.85.2.1/Thu Apr 21 03:42:09 2005//Tlibpcap_0_9 /arcnet.h/1.2/Tue Apr 24 02:17:52 2001//Tlibpcap_0_9 /atmuni31.h/1.1/Thu Jul 11 09:06:32 2002//Tlibpcap_0_9 /bpf_dump.c/1.14/Sat Nov 15 23:23:57 2003//Tlibpcap_0_9 /config.guess/1.5/Tue Nov 18 06:30:50 2003//Tlibpcap_0_9 /config.sub/1.5/Tue Nov 18 06:30:51 2003//Tlibpcap_0_9 /etherent.c/1.22/Sat Nov 15 23:23:57 2003//Tlibpcap_0_9 /fad-getad.c/1.10.2.1/Sun Apr 10 18:04:49 2005//Tlibpcap_0_9 /fad-glifc.c/1.5.2.1/Tue Apr 19 00:54:16 2005//Tlibpcap_0_9 /fad-null.c/1.2/Sat Nov 15 23:23:58 2003//Tlibpcap_0_9 /install-sh/1.1.1.1/Thu Oct 7 23:46:40 1999//Tlibpcap_0_9 /llc.h/1.2/Sun Jan 28 09:44:50 2001//Tlibpcap_0_9 /mkdep/1.1.1.1/Thu Oct 7 23:46:40 1999//Tlibpcap_0_9 /nlpid.h/1.2/Fri Dec 6 00:01:34 2002//Tlibpcap_0_9 /pcap-dos.c/1.1.2.1/Tue May 3 18:54:35 2005//Tlibpcap_0_9 /pcap-dos.h/1.1/Sat Dec 18 08:52:10 2004//Tlibpcap_0_9 /pcap-enet.c/1.8/Sat Nov 15 23:24:02 2003//Tlibpcap_0_9 /pcap-namedb.h/1.10.2.1/Tue Apr 19 04:26:08 2005//Tlibpcap_0_9 /pcap-nit.c/1.57.2.1/Tue May 3 18:54:37 2005//Tlibpcap_0_9 /pcap-nit.h/1.2.1.1/Thu Oct 7 23:46:40 1999//Tlibpcap_0_9 /pcap-null.c/1.21/Sat Nov 15 23:24:03 2003//Tlibpcap_0_9 /pcap-pf.c/1.91.2.2/Tue May 3 18:54:37 2005//Tlibpcap_0_9 /pcap-pf.h/1.2.1.1/Thu Oct 7 23:46:40 1999//Tlibpcap_0_9 /pcap-snit.c/1.72.2.1/Tue May 3 18:54:38 2005//Tlibpcap_0_9 /pcap-snoop.c/1.54.2.1/Tue May 3 18:54:38 2005//Tlibpcap_0_9 /pcap1.h/1.2/Tue Mar 30 14:42:50 2004//Tlibpcap_0_9 /pf.h/1.3/Fri Apr 2 06:33:30 2004//Tlibpcap_0_9 /ppp.h/1.12/Tue Feb 8 19:52:19 2005//Tlibpcap_0_9 /sll.h/1.7/Tue Jun 11 17:04:48 2002//Tlibpcap_0_9 /sunatmpos.h/1.1/Thu Jul 11 09:06:47 2002//Tlibpcap_0_9 D/ChmodBPF//// D/SUNOS4//// D/Win32//// D/bpf//// D/doc//// D/lbl//// D/missing//// D/msdos//// D/packaging//// /FILES/1.33.2.2/Tue Jul 5 20:52:06 2005//Tlibpcap_0_9 /INSTALL.txt/1.12.2.1/Tue Jul 5 20:52:06 2005//Tlibpcap_0_9 /README.septel/1.1.2.1/Mon Jun 20 21:30:14 2005//Tlibpcap_0_9 /fad-gifc.c/1.8.2.2/Tue Jul 5 20:52:08 2005//Tlibpcap_0_9 /pcap-septel.c/1.1.2.2/Tue Jun 21 01:03:23 2005//Tlibpcap_0_9 /pcap-septel.h/1.1.2.1/Mon Jun 20 21:30:19 2005//Tlibpcap_0_9 /pcap-dag.h/1.3.4.1/Mon Jul 11 18:31:18 2005//Tlibpcap_0_9 /ethertype.h/1.13.2.1/Sun Oct 2 21:52:00 2005//Tlibpcap_0_9 /pcap-stdinc.h/1.7.4.1/Sun Oct 2 21:52:03 2005//Tlibpcap_0_9 /README.dag/1.1.4.2/Tue Sep 19 19:26:24 2006//Tlibpcap_0_9 /fad-win32.c/1.11.2.3/Tue Sep 19 19:26:24 2006//Tlibpcap_0_9 /pcap-dlpi.c/1.108.2.7/Tue Sep 19 19:26:25 2006//Tlibpcap_0_9 /CREDITS/1.77.2.11/Mon Jun 11 19:34:27 2007//Tlibpcap_0_9 /TODO/1.3.6.1/Mon Jun 11 19:34:27 2007//Tlibpcap_0_9 /bpf_image.c/1.26.2.1/Mon Jun 11 19:34:27 2007//Tlibpcap_0_9 /gencode.h/1.60.2.11/Mon Jun 11 19:34:27 2007//Tlibpcap_0_9 /grammar.y/1.86.2.8/Mon Jun 11 19:34:27 2007//Tlibpcap_0_9 /inet.c/1.66.2.6/Mon Jun 11 19:34:27 2007//Tlibpcap_0_9 /nametoaddr.c/1.77.2.4/Mon Jun 11 19:34:27 2007//Tlibpcap_0_9 /pcap-linux.c/1.110.2.14/Mon Jun 11 19:34:28 2007//Tlibpcap_0_9 /pcap.3/1.64.2.11/Mon Jun 11 19:34:28 2007//Tlibpcap_0_9 /pcap.h/1.52.2.7/Mon Jun 11 19:34:28 2007//Tlibpcap_0_9 /scanner.l/1.99.2.9/Mon Jun 11 19:34:28 2007//Tlibpcap_0_9 /VERSION/1.7.2.5/Thu Jul 5 13:55:59 2007//Tlibpcap_0_9 /config.h.in/1.17.2.7/Thu Jul 5 13:55:59 2007//Tlibpcap_0_9 /configure/1.60.2.14/Thu Jul 5 13:56:00 2007//Tlibpcap_0_9 /configure.in/1.120.2.12/Thu Jul 5 13:56:00 2007//Tlibpcap_0_9 /pcap-bpf.c/1.86.2.12/Thu Jul 5 13:56:00 2007//Tlibpcap_0_9 /pcap-dag.c/1.21.2.7/Thu Jul 5 13:56:00 2007//Tlibpcap_0_9 /pcap-int.h/1.68.2.11/Thu Jul 5 13:56:00 2007//Tlibpcap_0_9 /pcap-win32.c/1.25.2.7/Thu Jul 5 13:56:01 2007//Tlibpcap_0_9 /pcap.c/1.88.2.17/Thu Jul 5 13:56:01 2007//Tlibpcap_0_9 /gencode.c/1.221.2.52/Tue Jul 10 19:38:15 2007//Tlibpcap_0_9 /optimize.c/1.85.2.2/Mon Jul 23 22:29:05 2007//Tlibpcap_0_9 /pcap-bpf.h/1.34.2.20/Mon Jul 23 22:29:05 2007//Tlibpcap_0_9 /savefile.c/1.126.2.27/Mon Jul 23 22:29:05 2007//Tlibpcap_0_9 /CHANGES/1.59.2.11/Tue Jul 24 02:27:32 2007//Tlibpcap_0_9 /Makefile.in/1.99.2.2/Tue Jul 24 02:35:15 2007//Tlibpcap_0_9 libpcap-0.9.7/./CVS/Root0000644000026300017500000000004010245661215012715 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./CVS/Repository0000644000026300017500000000001010245661215014146 0ustar mcrmcrlibpcap libpcap-0.9.7/./CVS/Tag0000644000026300017500000000001510245661221012504 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./sunatmpos.h0000644000026300017500000000427207513245247013640 0ustar mcrmcr/* * Copyright (c) 1997 Yen Yen Lim and North Dakota State University * 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 Yen Yen Lim and North Dakota State University * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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: /tcpdump/master/libpcap/sunatmpos.h,v 1.1 2002/07/11 09:06:47 guy Exp $ (LBL) */ /* SunATM header for ATM packet */ #define SUNATM_DIR_POS 0 #define SUNATM_VPI_POS 1 #define SUNATM_VCI_POS 2 #define SUNATM_PKT_BEGIN_POS 4 /* Start of ATM packet */ /* Protocol type values in the bottom for bits of the byte at SUNATM_DIR_POS. */ #define PT_LANE 0x01 /* LANE */ #define PT_LLC 0x02 /* LLC encapsulation */ #define PT_ILMI 0x05 /* ILMI */ #define PT_QSAAL 0x06 /* Q.SAAL */ libpcap-0.9.7/./llc.h0000644000026300017500000000403507234765022012354 0ustar mcrmcr/* * Copyright (c) 1993, 1994, 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. * * @(#) $Header: /tcpdump/master/libpcap/llc.h,v 1.2 2001/01/28 09:44:50 guy Exp $ (LBL) */ /* * 802.2 LLC SAP values. */ #ifndef LLCSAP_NULL #define LLCSAP_NULL 0x00 #endif #ifndef LLCSAP_GLOBAL #define LLCSAP_GLOBAL 0xff #endif #ifndef LLCSAP_8021B #define LLCSAP_8021B_I 0x02 #endif #ifndef LLCSAP_8021B #define LLCSAP_8021B_G 0x03 #endif #ifndef LLCSAP_IP #define LLCSAP_IP 0x06 #endif #ifndef LLCSAP_PROWAYNM #define LLCSAP_PROWAYNM 0x0e #endif #ifndef LLCSAP_8021D #define LLCSAP_8021D 0x42 #endif #ifndef LLCSAP_RS511 #define LLCSAP_RS511 0x4e #endif #ifndef LLCSAP_ISO8208 #define LLCSAP_ISO8208 0x7e #endif #ifndef LLCSAP_PROWAY #define LLCSAP_PROWAY 0x8e #endif #ifndef LLCSAP_SNAP #define LLCSAP_SNAP 0xaa #endif #ifndef LLCSAP_IPX #define LLCSAP_IPX 0xe0 #endif #ifndef LLCSAP_NETBEUI #define LLCSAP_NETBEUI 0xf0 #endif #ifndef LLCSAP_ISONS #define LLCSAP_ISONS 0xfe #endif libpcap-0.9.7/./CREDITS0000644000026300017500000000767110633321703012451 0ustar mcrmcrThis file lists people who have contributed to libpcap: The current maintainers: Bill Fenner Fulvio Risso Guy Harris Hannes Gredler Jun-ichiro itojun Hagino Michael Richardson Additional people who have contributed patches: Alan Bawden Alexey Kuznetsov Albert Chin Andrew Brown Antti Kantee Arkadiusz Miskiewicz Armando L. Caro Jr. Assar Westerlund Brian Ginsbach Charles M. Hannum Chris G. Demetriou Chris Lightfoot Chris Pepper Daniele Orlandi Darren Reed David Kaelbling David Young Dean Gaudet Don Ebright Dug Song Eric Anderson Erik de Castro Lopo Florent Drouin Franz Schaefer Gianluca Varenni Gilbert Hoyek Gisle Vanem Graeme Hewson Greg Stark Greg Troxel Guillaume Pelat Hyung Sik Yoon Igor Khristophorov Jan-Philip Velders Jason R. Thorpe Javier Achirica Jean Tourrilhes Jefferson Ogata Jesper Peterson John Bankier Jon Lindgren Juergen Schoenwaelder Jung-uk Kim Kazushi Sugyo Klaus Klein Koryn Grant Krzysztof Halasa Lorenzo Cavallaro Loris Degioanni Love Hörnquist-Åstrand Maciej W. Rozycki Marcus Felipe Pereira Mark C. Brown Mark Pizzolato Martin Husemann Matthew Luckie Mike Kershaw Mike Wiacek Monroe Williams Nicolas Dade Octavian Cerna Olaf Kirch Ollie Wild Onno van der Linden Patrick Marie Paul Mundt Pavel Kankovsky Pawel Pokrywka Peter Fales Peter Jeremy Phil Wood Rafal Maszkowski Rick Jones Scott Barron Scott Gifford Sebastian Krahmer Shaun Clowes Solomon Peachy Stefan Hudson Stephen Donnelly Takashi Yamamoto Tanaka Shin-ya Tony Li Torsten Landschoff Uns Lider Uwe Girlich Xianjie Zhang Yen Yen Lim Yoann Vandoorselaere The original LBL crew: Steve McCanne Craig Leres Van Jacobson libpcap-0.9.7/./pf.h0000644000026300017500000000520510033204472012173 0ustar mcrmcr/* * Copyright (c) 2001 Daniel Hartmeier * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - 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. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 * COPYRIGHT HOLDERS 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: /tcpdump/master/libpcap/pf.h,v 1.3 2004/04/02 06:33:30 guy Exp $ (LBL) */ /* from $OpenBSD: pfvar.h,v 1.170 2003/08/22 21:50:34 david Exp $ */ enum { PF_INOUT=0, PF_IN=1, PF_OUT=2 }; enum { PF_PASS=0, PF_DROP=1, PF_SCRUB=2, PF_NAT=3, PF_NONAT=4, PF_BINAT=5, PF_NOBINAT=6, PF_RDR=7, PF_NORDR=8, PF_SYNPROXY_DROP=9 }; /* Reasons code for passing/dropping a packet */ #define PFRES_MATCH 0 /* Explicit match of a rule */ #define PFRES_BADOFF 1 /* Bad offset for pull_hdr */ #define PFRES_FRAG 2 /* Dropping following fragment */ #define PFRES_SHORT 3 /* Dropping short packet */ #define PFRES_NORM 4 /* Dropping by normalizer */ #define PFRES_MEMORY 5 /* Dropped due to lacking mem */ #define PFRES_MAX 6 /* total+1 */ #define PFRES_NAMES { \ "match", \ "bad-offset", \ "fragment", \ "short", \ "normalize", \ "memory", \ NULL \ } #define PF_RULESET_NAME_SIZE 16 /* from $OpenBSD: if_pflog.h,v 1.9 2003/07/15 20:27:27 dhartmei Exp $ */ #ifndef IFNAMSIZ #define IFNAMSIZ 16 #endif struct pfloghdr { u_int8_t length; u_int8_t af; u_int8_t action; u_int8_t reason; char ifname[IFNAMSIZ]; char ruleset[PF_RULESET_NAME_SIZE]; u_int32_t rulenr; u_int32_t subrulenr; u_int8_t dir; u_int8_t pad[3]; }; #define PFLOG_HDRLEN sizeof(struct pfloghdr) libpcap-0.9.7/./inet.c0000644000026300017500000004706310633321703012533 0ustar mcrmcr/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.66.2.6 2007/06/11 09:52:04 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #include #ifndef MSDOS #include #endif #include #include #ifdef HAVE_SYS_SOCKIO_H #include #endif struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include #include #endif /* WIN32 */ #include #include #include #include #include #include #if !defined(WIN32) && !defined(__BORLANDC__) #include #endif /* !WIN32 && !__BORLANDC__ */ #ifdef HAVE_LIMITS_H #include #else #define INT_MAX 2147483647 #endif #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif /* Not all systems have IFF_LOOPBACK */ #ifdef IFF_LOOPBACK #define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK) #else #define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \ (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0')) #endif struct sockaddr * dup_sockaddr(struct sockaddr *sa, size_t sa_length) { struct sockaddr *newsa; if ((newsa = malloc(sa_length)) == NULL) return (NULL); return (memcpy(newsa, sa, sa_length)); } static int get_instance(const char *name) { const char *cp, *endcp; int n; if (strcmp(name, "any") == 0) { /* * Give the "any" device an artificially high instance * number, so it shows up after all other non-loopback * interfaces. */ return INT_MAX; } endcp = name + strlen(name); for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp) continue; if (isdigit((unsigned char)*cp)) n = atoi(cp); else n = 0; return (n); } int add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name, u_int flags, const char *description, char *errbuf) { pcap_t *p; pcap_if_t *curdev, *prevdev, *nextdev; int this_instance; /* * Is there already an entry in the list for this interface? */ for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) { if (strcmp(name, curdev->name) == 0) break; /* yes, we found it */ } if (curdev == NULL) { /* * No, we didn't find it. * * Can we open this interface for live capture? * * We do this check so that interfaces that are * supplied by the interface enumeration mechanism * we're using but that don't support packet capture * aren't included in the list. Loopback interfaces * on Solaris are an example of this; we don't just * omit loopback interfaces on all platforms because * you *can* capture on loopback interfaces on some * OSes. * * On OS X, we don't do this check if the device * name begins with "wlt"; at least some versions * of OS X offer monitor mode capturing by having * a separate "monitor mode" device for each wireless * adapter, rather than by implementing the ioctls * that {Free,Net,Open,DragonFly}BSD provide. * Opening that device puts the adapter into monitor * mode, which, at least for some adapters, causes * them to deassociate from the network with which * they're associated. * * Instead, we try to open the corresponding "en" * device (so that we don't end up with, for users * without sufficient privilege to open capture * devices, a list of adapters that only includes * the wlt devices). */ #ifdef __APPLE__ if (strncmp(name, "wlt", 3) == 0) { char *en_name; size_t en_name_len; /* * Try to allocate a buffer for the "en" * device's name. */ en_name_len = strlen(name) - 1; en_name = malloc(en_name_len + 1); if (en_name == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (-1); } strcpy(en_name, "en"); strcat(en_name, name + 3); p = pcap_open_live(en_name, 68, 0, 0, errbuf); free(en_name); } else #endif /* __APPLE */ p = pcap_open_live(name, 68, 0, 0, errbuf); if (p == NULL) { /* * No. Don't bother including it. * Don't treat this as an error, though. */ *curdev_ret = NULL; return (0); } pcap_close(p); /* * Yes, we can open it. * Allocate a new entry. */ curdev = malloc(sizeof(pcap_if_t)); if (curdev == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (-1); } /* * Fill in the entry. */ curdev->next = NULL; curdev->name = strdup(name); if (curdev->name == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); free(curdev); return (-1); } if (description != NULL) { /* * We have a description for this interface. */ curdev->description = strdup(description); if (curdev->description == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); free(curdev->name); free(curdev); return (-1); } } else { /* * We don't. */ curdev->description = NULL; } curdev->addresses = NULL; /* list starts out as empty */ curdev->flags = 0; if (ISLOOPBACK(name, flags)) curdev->flags |= PCAP_IF_LOOPBACK; /* * Add it to the list, in the appropriate location. * First, get the instance number of this interface. */ this_instance = get_instance(name); /* * Now look for the last interface with an instance number * less than or equal to the new interface's instance * number - except that non-loopback interfaces are * arbitrarily treated as having interface numbers less * than those of loopback interfaces, so the loopback * interfaces are put at the end of the list. * * We start with "prevdev" being NULL, meaning we're before * the first element in the list. */ prevdev = NULL; for (;;) { /* * Get the interface after this one. */ if (prevdev == NULL) { /* * The next element is the first element. */ nextdev = *alldevs; } else nextdev = prevdev->next; /* * Are we at the end of the list? */ if (nextdev == NULL) { /* * Yes - we have to put the new entry * after "prevdev". */ break; } /* * Is the new interface a non-loopback interface * and the next interface a loopback interface? */ if (!(curdev->flags & PCAP_IF_LOOPBACK) && (nextdev->flags & PCAP_IF_LOOPBACK)) { /* * Yes, we should put the new entry * before "nextdev", i.e. after "prevdev". */ break; } /* * Is the new interface's instance number less * than the next interface's instance number, * and is it the case that the new interface is a * non-loopback interface or the next interface is * a loopback interface? * * (The goal of both loopback tests is to make * sure that we never put a loopback interface * before any non-loopback interface and that we * always put a non-loopback interface before all * loopback interfaces.) */ if (this_instance < get_instance(nextdev->name) && (!(curdev->flags & PCAP_IF_LOOPBACK) || (nextdev->flags & PCAP_IF_LOOPBACK))) { /* * Yes - we should put the new entry * before "nextdev", i.e. after "prevdev". */ break; } prevdev = nextdev; } /* * Insert before "nextdev". */ curdev->next = nextdev; /* * Insert after "prevdev" - unless "prevdev" is null, * in which case this is the first interface. */ if (prevdev == NULL) { /* * This is the first interface. Pass back a * pointer to it, and put "curdev" before * "nextdev". */ *alldevs = curdev; } else prevdev->next = curdev; } *curdev_ret = curdev; return (0); } int add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, struct sockaddr *addr, size_t addr_size, struct sockaddr *netmask, size_t netmask_size, struct sockaddr *broadaddr, size_t broadaddr_size, struct sockaddr *dstaddr, size_t dstaddr_size, char *errbuf) { pcap_if_t *curdev; pcap_addr_t *curaddr, *prevaddr, *nextaddr; if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) { /* * Error - give up. */ return (-1); } if (curdev == NULL) { /* * Device wasn't added because it can't be opened. * Not a fatal error. */ return (0); } /* * "curdev" is an entry for this interface; add an entry for this * address to its list of addresses. * * Allocate the new entry and fill it in. */ curaddr = malloc(sizeof(pcap_addr_t)); if (curaddr == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (-1); } curaddr->next = NULL; if (addr != NULL) { curaddr->addr = dup_sockaddr(addr, addr_size); if (curaddr->addr == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); free(curaddr); return (-1); } } else curaddr->addr = NULL; if (netmask != NULL) { curaddr->netmask = dup_sockaddr(netmask, netmask_size); if (curaddr->netmask == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); if (curaddr->addr != NULL) free(curaddr->addr); free(curaddr); return (-1); } } else curaddr->netmask = NULL; if (broadaddr != NULL) { curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size); if (curaddr->broadaddr == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); if (curaddr->netmask != NULL) free(curaddr->netmask); if (curaddr->addr != NULL) free(curaddr->addr); free(curaddr); return (-1); } } else curaddr->broadaddr = NULL; if (dstaddr != NULL) { curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size); if (curaddr->dstaddr == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); if (curaddr->broadaddr != NULL) free(curaddr->broadaddr); if (curaddr->netmask != NULL) free(curaddr->netmask); if (curaddr->addr != NULL) free(curaddr->addr); free(curaddr); return (-1); } } else curaddr->dstaddr = NULL; /* * Find the end of the list of addresses. */ for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { nextaddr = prevaddr->next; if (nextaddr == NULL) { /* * This is the end of the list. */ break; } } if (prevaddr == NULL) { /* * The list was empty; this is the first member. */ curdev->addresses = curaddr; } else { /* * "prevaddr" is the last member of the list; append * this member to it. */ prevaddr->next = curaddr; } return (0); } int pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags, const char *description, char *errbuf) { pcap_if_t *curdev; return (add_or_find_if(&curdev, devlist, name, flags, description, errbuf)); } /* * Free a list of interfaces. */ void pcap_freealldevs(pcap_if_t *alldevs) { pcap_if_t *curdev, *nextdev; pcap_addr_t *curaddr, *nextaddr; for (curdev = alldevs; curdev != NULL; curdev = nextdev) { nextdev = curdev->next; /* * Free all addresses. */ for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) { nextaddr = curaddr->next; if (curaddr->addr) free(curaddr->addr); if (curaddr->netmask) free(curaddr->netmask); if (curaddr->broadaddr) free(curaddr->broadaddr); if (curaddr->dstaddr) free(curaddr->dstaddr); free(curaddr); } /* * Free the name string. */ free(curdev->name); /* * Free the description string, if any. */ if (curdev->description != NULL) free(curdev->description); /* * Free the interface. */ free(curdev); } } #if !defined(WIN32) && !defined(MSDOS) /* * 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; { pcap_if_t *alldevs; /* for old BSD systems, including bsdi3 */ #ifndef IF_NAMESIZE #define IF_NAMESIZE IFNAMSIZ #endif static char device[IF_NAMESIZE + 1]; char *ret; if (pcap_findalldevs(&alldevs, errbuf) == -1) return (NULL); if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) { /* * There are no devices on the list, or the first device * on the list is a loopback device, which means there * are no non-loopback devices on the list. This means * we can't return any device. * * XXX - why not return a loopback device? If we can't * capture on it, it won't be on the list, and if it's * on the list, there aren't any non-loopback devices, * so why not just supply it as the default device? */ (void)strlcpy(errbuf, "no suitable device found", PCAP_ERRBUF_SIZE); ret = NULL; } else { /* * Return the name of the first device on the list. */ (void)strlcpy(device, alldevs->name, sizeof(device)); ret = device; } pcap_freealldevs(alldevs); return (ret); } int pcap_lookupnet(device, netp, maskp, errbuf) register const char *device; register bpf_u_int32 *netp, *maskp; register char *errbuf; { register int fd; register struct sockaddr_in *sin4; struct ifreq ifr; /* * The pseudo-device "any" listens on all interfaces and therefore * has the network address and -mask "0.0.0.0" therefore catching * all traffic. Using NULL for the interface is the same as "any". */ if (!device || strcmp(device, "any") == 0 #ifdef HAVE_DAG_API || strstr(device, "dag") != NULL #endif #ifdef HAVE_SEPTEL_API || strstr(device, "septel") != NULL #endif ) { *netp = *maskp = 0; return 0; } fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "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) { if (errno == EADDRNOTAVAIL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: no IPv4 address assigned", device); } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFADDR: %s: %s", device, pcap_strerror(errno)); } (void)close(fd); return (-1); } sin4 = (struct sockaddr_in *)&ifr.ifr_addr; *netp = sin4->sin_addr.s_addr; if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); (void)close(fd); return (-1); } (void)close(fd); *maskp = sin4->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)snprintf(errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%x unknown", *netp); return (-1); } } *netp &= *maskp; return (0); } #elif defined(WIN32) /* * 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; { DWORD dwVersion; DWORD dwWindowsMajorVersion; dwVersion = GetVersion(); /* get the OS version */ dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { /* * Windows 95, 98, ME. */ ULONG NameLength = 8192; static char AdaptersName[8192]; if (PacketGetAdapterNames(AdaptersName,&NameLength) ) return (AdaptersName); else return NULL; } else { /* * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility */ ULONG NameLength = 8192; static WCHAR AdaptersName[8192]; char *tAstr; WCHAR *tUstr; WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR)); int NAdapts = 0; if(TAdaptersName == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure"); return NULL; } if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) ) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s", pcap_win32strerror()); free(TAdaptersName); return NULL; } tAstr = (char*)TAdaptersName; tUstr = (WCHAR*)AdaptersName; /* * Convert and copy the device names */ while(sscanf(tAstr, "%S", tUstr) > 0) { tAstr += strlen(tAstr) + 1; tUstr += wcslen(tUstr) + 1; NAdapts ++; } tAstr++; *tUstr = 0; tUstr++; /* * Copy the descriptions */ while(NAdapts--) { strcpy((char*)tUstr, tAstr); (char*)tUstr += strlen(tAstr) + 1;; tAstr += strlen(tAstr) + 1; } free(TAdaptersName); return (char *)(AdaptersName); } } int pcap_lookupnet(device, netp, maskp, errbuf) register const char *device; register bpf_u_int32 *netp, *maskp; register char *errbuf; { /* * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo() * in order to skip non IPv4 (i.e. IPv6 addresses) */ npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; LONG if_addr_size = 1; struct sockaddr_in *t_addr; unsigned int i; if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) { *netp = *maskp = 0; return (0); } for(i=0; isin_addr.S_un.S_addr; t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask); *maskp = t_addr->sin_addr.S_un.S_addr; *netp &= *maskp; return (0); } } *netp = *maskp = 0; return (0); } #endif /* !WIN32 && !MSDOS */ libpcap-0.9.7/./configure0000755000026300017500000073513510643174160013347 0ustar mcrmcr#! /bin/sh # From configure.in Revision: 1.120.2.12 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59. # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="pcap.c" # Factoring default headers for most tests. ac_includes_default="\ #include #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os SHLICC2 CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP LIBOBJS V_LEX V_YACC RANLIB ac_ct_RANLIB V_CCOPT V_DEFS V_INCLS V_LIBS V_PCAP V_FINDALLDEVS V_RANLIB SSRC DYEXT DAGLIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. 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' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # 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_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$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 ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) 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 | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$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 | -n) 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=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } 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 "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # 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_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP # # Report the --help message. # if test "$ac_init_help" = "long"; then # 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 <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-protochain disable \"protochain\" insn --enable-ipv6 build IPv6-capable version --enable-optimizer-dbg build optimizer debugging code --enable-yydebug build parser debugging code Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --without-gcc don't use gcc --with-pcap=TYPE use packet capture TYPE --with-dag[=DIR] include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present) --with-dag-includes=DIR Endace DAG include directory --with-dag-libraries=DIR Endace DAG library directory --with-septel[=DIR] include Septel support (located in directory DIR, if supplied). default=yes, on Linux, if present --without-flex don't use flex --without-bison don't use bison Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # 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 # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # 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 fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu 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 elif test -f $ac_dir/shtool; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} { (exit 1); exit 1; }; } fi ac_config_guess="$SHELL $ac_aux_dir/config.guess" ac_config_sub="$SHELL $ac_aux_dir/config.sub" ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # Make sure we can run config.sub. $ac_config_sub sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 echo "$as_me: error: cannot run $ac_config_sub" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking build system type" >&5 echo $ECHO_N "checking build system type... $ECHO_C" >&6 if test "${ac_cv_build+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_build_alias=$build_alias test -z "$ac_cv_build_alias" && ac_cv_build_alias=`$ac_config_guess` test -z "$ac_cv_build_alias" && { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_build" >&5 echo "${ECHO_T}$ac_cv_build" >&6 build=$ac_cv_build build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$as_me:$LINENO: checking host system type" >&5 echo $ECHO_N "checking host system type... $ECHO_C" >&6 if test "${ac_cv_host+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_host_alias=$host_alias test -z "$ac_cv_host_alias" && ac_cv_host_alias=$ac_cv_build_alias ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6 host=$ac_cv_host host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$as_me:$LINENO: checking target system type" >&5 echo $ECHO_N "checking target system type... $ECHO_C" >&6 if test "${ac_cv_target+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_target_alias=$target_alias test "x$ac_cv_target_alias" = "x" && ac_cv_target_alias=$ac_cv_host_alias ac_cv_target=`$ac_config_sub $ac_cv_target_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_target" >&5 echo "${ECHO_T}$ac_cv_target" >&6 target=$ac_cv_target target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- # Check whether --with-gcc or --without-gcc was given. if test "${with_gcc+set}" = set; then withval="$with_gcc" fi; 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 "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_SHLICC2+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$SHLICC2"; then ac_cv_prog_SHLICC2="$SHLICC2" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_SHLICC2="yes" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_SHLICC2" && ac_cv_prog_SHLICC2="no" fi fi SHLICC2=$ac_cv_prog_SHLICC2 if test -n "$SHLICC2"; then echo "$as_me:$LINENO: result: $SHLICC2" >&5 echo "${ECHO_T}$SHLICC2" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi 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_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi 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 "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done 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 $# != 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 ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version

The list of current Internet-Drafts can be accessed at http://www.ietf.org/ietf/1id-abstracts.txt.

&5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$GCC" = yes ; then if test "$SHLICC2" = yes ; then ac_cv_lbl_gcc_vers=2 V_CCOPT="-O2" else echo "$as_me:$LINENO: checking gcc version" >&5 echo $ECHO_N "checking gcc version... $ECHO_C" >&6 if test "${ac_cv_lbl_gcc_vers+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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/\..*//'` fi echo "$as_me:$LINENO: result: $ac_cv_lbl_gcc_vers" >&5 echo "${ECHO_T}$ac_cv_lbl_gcc_vers" >&6 if test $ac_cv_lbl_gcc_vers -gt 1 ; then V_CCOPT="-O2" fi fi else echo "$as_me:$LINENO: checking that $CC handles ansi prototypes" >&5 echo $ECHO_N "checking that $CC handles ansi prototypes... $ECHO_C" >&6 if test "${ac_cv_lbl_cc_ansi_prototypes+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { int frob(int, char *) ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_cc_ansi_prototypes=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_cc_ansi_prototypes=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_cc_ansi_prototypes" >&5 echo "${ECHO_T}$ac_cv_lbl_cc_ansi_prototypes" >&6 if test $ac_cv_lbl_cc_ansi_prototypes = no ; then case "$target_os" in hpux*) echo "$as_me:$LINENO: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5 echo $ECHO_N "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)... $ECHO_C" >&6 savedcflags="$CFLAGS" CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS" if test "${ac_cv_lbl_cc_hpux_cc_aa+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { int frob(int, char *) ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_cc_hpux_cc_aa=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_cc_hpux_cc_aa=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_cc_hpux_cc_aa" >&5 echo "${ECHO_T}$ac_cv_lbl_cc_hpux_cc_aa" >&6 if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then { { echo "$as_me:$LINENO: error: see the INSTALL doc for more info" >&5 echo "$as_me: error: see the INSTALL doc for more info" >&2;} { (exit 1); exit 1; }; } fi CFLAGS="$savedcflags" V_CCOPT="-Aa $V_CCOPT" cat >>confdefs.h <<\_ACEOF #define _HPUX_SOURCE 1 _ACEOF ;; *) { { echo "$as_me:$LINENO: error: see the INSTALL doc for more info" >&5 echo "$as_me: error: see the INSTALL doc for more info" >&2;} { (exit 1); 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 "$as_me:$LINENO: checking that Ultrix $CC hacks const in prototypes" >&5 echo $ECHO_N "checking that Ultrix $CC hacks const in prototypes... $ECHO_C" >&6 if test "${ac_cv_lbl_cc_const_proto+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { struct a { int b; }; void c(const struct a *) ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_cc_const_proto=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_cc_const_proto=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_cc_const_proto" >&5 echo "${ECHO_T}$ac_cv_lbl_cc_const_proto" >&6 if test $ac_cv_lbl_cc_const_proto = no ; then cat >>confdefs.h <<\_ACEOF #define const _ACEOF fi ;; esac fi echo "$as_me:$LINENO: checking for inline" >&5 echo $ECHO_N "checking for inline... $ECHO_C" >&6 save_CFLAGS="$CFLAGS" CFLAGS="$V_CCOPT" if test "${ac_cv_lbl_inline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_lbl_inline="" ac_lbl_cc_inline=no for ac_lbl_inline in inline __inline__ __inline do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define inline $ac_lbl_inline static inline struct iltest *foo(void); struct iltest { int iltest1; int iltest2; }; static inline struct iltest * foo() { static struct iltest xxx; return &xxx; } int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lbl_cc_inline=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test "$ac_lbl_cc_inline" = yes ; then break; fi done if test "$ac_lbl_cc_inline" = yes ; then ac_cv_lbl_inline=$ac_lbl_inline fi fi CFLAGS="$save_CFLAGS" if test ! -z "$ac_cv_lbl_inline" ; then echo "$as_me:$LINENO: result: $ac_cv_lbl_inline" >&5 echo "${ECHO_T}$ac_cv_lbl_inline" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi cat >>confdefs.h <<_ACEOF #define inline $ac_cv_lbl_inline _ACEOF echo "$as_me:$LINENO: checking for __attribute__" >&5 echo $ECHO_N "checking for __attribute__... $ECHO_C" >&6 if test "${ac_cv___attribute__+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include static void foo(void) __attribute__ ((noreturn)); static void foo(void) { exit(1); } int main(int argc, char **argv) { foo(); } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv___attribute__=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv___attribute__=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "$ac_cv___attribute__" = "yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE___ATTRIBUTE__ 1 _ACEOF V_DEFS="$V_DEFS -D_U_=\"__attribute__((unused))\"" else V_DEFS="$V_DEFS -D_U_=\"\"" fi echo "$as_me:$LINENO: result: $ac_cv___attribute__" >&5 echo "${ECHO_T}$ac_cv___attribute__" >&6 echo "$as_me:$LINENO: checking for u_int8_t using $CC" >&5 echo $ECHO_N "checking for u_int8_t using $CC... $ECHO_C" >&6 if test "${ac_cv_lbl_have_u_int8_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include "confdefs.h" # include # if STDC_HEADERS # include # include # endif int main () { u_int8_t i ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_have_u_int8_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_have_u_int8_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_have_u_int8_t" >&5 echo "${ECHO_T}$ac_cv_lbl_have_u_int8_t" >&6 if test $ac_cv_lbl_have_u_int8_t = no ; then cat >>confdefs.h <<\_ACEOF #define u_int8_t u_char _ACEOF fi echo "$as_me:$LINENO: checking for u_int16_t using $CC" >&5 echo $ECHO_N "checking for u_int16_t using $CC... $ECHO_C" >&6 if test "${ac_cv_lbl_have_u_int16_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include "confdefs.h" # include # if STDC_HEADERS # include # include # endif int main () { u_int16_t i ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_have_u_int16_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_have_u_int16_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_have_u_int16_t" >&5 echo "${ECHO_T}$ac_cv_lbl_have_u_int16_t" >&6 if test $ac_cv_lbl_have_u_int16_t = no ; then cat >>confdefs.h <<\_ACEOF #define u_int16_t u_short _ACEOF fi echo "$as_me:$LINENO: checking for u_int32_t using $CC" >&5 echo $ECHO_N "checking for u_int32_t using $CC... $ECHO_C" >&6 if test "${ac_cv_lbl_have_u_int32_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include "confdefs.h" # include # if STDC_HEADERS # include # include # endif int main () { u_int32_t i ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_have_u_int32_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_have_u_int32_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_have_u_int32_t" >&5 echo "${ECHO_T}$ac_cv_lbl_have_u_int32_t" >&6 if test $ac_cv_lbl_have_u_int32_t = no ; then cat >>confdefs.h <<\_ACEOF #define u_int32_t u_int _ACEOF fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/ioccom.h sys/sockio.h limits.h paths.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in netinet/if_ether.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_netinet_if_ether_h" != yes; then # # The simple test didn't work. # Do we need to include first? # Unset ac_cv_header_netinet_if_ether_h so we don't # treat the previous failure as a cached value and # suppress the next test. # { echo "$as_me:$LINENO: Rechecking with some additional includes" >&5 echo "$as_me: Rechecking with some additional includes" >&6;} unset ac_cv_header_netinet_if_ether_h for ac_header in netinet/if_ether.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include struct mbuf; struct rtentry; #include #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi if test "$GCC" = yes ; then echo "$as_me:$LINENO: checking for ANSI ioctl definitions" >&5 echo $ECHO_N "checking for ANSI ioctl definitions... $ECHO_C" >&6 if test "${ac_cv_lbl_gcc_fixincludes+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* * This generates a "duplicate case value" when fixincludes * has not be run. */ # include # include # include # ifdef HAVE_SYS_IOCCOM_H # include # endif int main () { switch (0) { case _IO('A', 1):; case _IO('B', 1):; } ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_gcc_fixincludes=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_gcc_fixincludes=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_gcc_fixincludes" >&5 echo "${ECHO_T}$ac_cv_lbl_gcc_fixincludes" >&6 if test $ac_cv_lbl_gcc_fixincludes = no ; then # Don't cache failure unset ac_cv_lbl_gcc_fixincludes { { echo "$as_me:$LINENO: error: see the INSTALL for more info" >&5 echo "$as_me: error: see the INSTALL for more info" >&2;} { (exit 1); exit 1; }; } fi fi for ac_func in strerror strlcpy do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* 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 (); /* 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 char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done needsnprintf=no for ac_func in vsnprintf snprintf do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* 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 (); /* 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 char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else needsnprintf=yes fi done if test $needsnprintf = yes; then case $LIBOBJS in "snprintf.$ac_objext" | \ *" snprintf.$ac_objext" | \ "snprintf.$ac_objext "* | \ *" snprintf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" ;; esac fi # # Do this before checking for ether_hostton(), as it's a # "gethostbyname() -ish function". # # Most operating systems have gethostbyname() in the default searched # libraries (i.e. libc): # Some OSes (eg. Solaris) place it in libnsl # Some strange OSes (SINIX) have it in libsocket: echo "$as_me:$LINENO: checking for library containing gethostbyname" >&5 echo $ECHO_N "checking for library containing gethostbyname... $ECHO_C" >&6 if test "${ac_cv_search_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_gethostbyname=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostbyname (); int main () { gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_gethostbyname="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_gethostbyname" = no; then for ac_lib in nsl socket resolv; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostbyname (); int main () { gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_gethostbyname="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_search_gethostbyname" >&6 if test "$ac_cv_search_gethostbyname" != no; then test "$ac_cv_search_gethostbyname" = "none required" || LIBS="$ac_cv_search_gethostbyname $LIBS" fi # Unfortunately libsocket sometimes depends on libnsl and # AC_SEARCH_LIBS isn't up to the task of handling dependencies like this. if test "$ac_cv_search_gethostbyname" = "no" then echo "$as_me:$LINENO: checking for gethostbyname in -lsocket" >&5 echo $ECHO_N "checking for gethostbyname in -lsocket... $ECHO_C" >&6 if test "${ac_cv_lib_socket_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket -lnsl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostbyname (); int main () { gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_socket_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_gethostbyname=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_socket_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_socket_gethostbyname" >&6 if test $ac_cv_lib_socket_gethostbyname = yes; then LIBS="-lsocket -lnsl $LIBS" fi fi echo "$as_me:$LINENO: checking for library containing socket" >&5 echo $ECHO_N "checking for library containing socket... $ECHO_C" >&6 if test "${ac_cv_search_socket+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_socket=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char socket (); int main () { socket (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_socket="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_socket" = no; then for ac_lib in socket; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char socket (); int main () { socket (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_socket="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_socket" >&5 echo "${ECHO_T}$ac_cv_search_socket" >&6 if test "$ac_cv_search_socket" != no; then test "$ac_cv_search_socket" = "none required" || LIBS="$ac_cv_search_socket $LIBS" else echo "$as_me:$LINENO: checking for socket in -lsocket" >&5 echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6 if test "${ac_cv_lib_socket_socket+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket -lnsl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char socket (); int main () { socket (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_socket_socket=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_socket=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5 echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6 if test $ac_cv_lib_socket_socket = yes; then LIBS="-lsocket -lnsl $LIBS" fi fi # DLPI needs putmsg under HPUX so test for -lstr while we're at it echo "$as_me:$LINENO: checking for library containing putmsg" >&5 echo $ECHO_N "checking for library containing putmsg... $ECHO_C" >&6 if test "${ac_cv_search_putmsg+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_putmsg=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char putmsg (); int main () { putmsg (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_putmsg="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_putmsg" = no; then for ac_lib in str; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char putmsg (); int main () { putmsg (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_putmsg="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_putmsg" >&5 echo "${ECHO_T}$ac_cv_search_putmsg" >&6 if test "$ac_cv_search_putmsg" != no; then test "$ac_cv_search_putmsg" = "none required" || LIBS="$ac_cv_search_putmsg $LIBS" fi # # You are in a twisty little maze of UN*Xes, all different. # Some might not have ether_hostton(). # Some might have it, but not declare it in any header file. # Some might have it, but declare it in . # Some might have it, but declare it in # (And some might have it but document it as something declared in # , although appears to work.) # # Before you is a C compiler. # for ac_func in ether_hostton do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* 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 (); /* 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 char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_func_ether_hostton" = yes; then # # OK, we have ether_hostton(). Do we have ? # if test "$ac_cv_header_netinet_if_ether_h" = yes; then # # Yes. Does it declare ether_hostton()? # echo "$as_me:$LINENO: checking whether ether_hostton is declared" >&5 echo $ECHO_N "checking whether ether_hostton is declared... $ECHO_C" >&6 if test "${ac_cv_have_decl_ether_hostton+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include struct mbuf; struct rtentry; #include #include int main () { #ifndef ether_hostton char *p = (char *) ether_hostton; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_have_decl_ether_hostton=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_ether_hostton=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_have_decl_ether_hostton" >&5 echo "${ECHO_T}$ac_cv_have_decl_ether_hostton" >&6 if test $ac_cv_have_decl_ether_hostton = yes; then cat >>confdefs.h <<\_ACEOF #define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON _ACEOF fi fi # # Did that succeed? # if test "$ac_cv_have_decl_ether_hostton" != yes; then # # No, how about , as on Linux? # for ac_header in netinet/ether.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_netinet_ether_h" = yes; then # # We have it - does it declare ether_hostton()? # Unset ac_cv_have_decl_ether_hostton so we don't # treat the previous failure as a cached value and # suppress the next test. # unset ac_cv_have_decl_ether_hostton echo "$as_me:$LINENO: checking whether ether_hostton is declared" >&5 echo $ECHO_N "checking whether ether_hostton is declared... $ECHO_C" >&6 if test "${ac_cv_have_decl_ether_hostton+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { #ifndef ether_hostton char *p = (char *) ether_hostton; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_have_decl_ether_hostton=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_ether_hostton=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_have_decl_ether_hostton" >&5 echo "${ECHO_T}$ac_cv_have_decl_ether_hostton" >&6 if test $ac_cv_have_decl_ether_hostton = yes; then cat >>confdefs.h <<\_ACEOF #define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON _ACEOF fi fi fi # # Is ether_hostton() declared? # if test "$ac_cv_have_decl_ether_hostton" != yes; then # # No, we'll have to declare it ourselves. # Do we have "struct ether_addr"? # echo "$as_me:$LINENO: checking for struct ether_addr" >&5 echo $ECHO_N "checking for struct ether_addr... $ECHO_C" >&6 if test "${ac_cv_type_struct_ether_addr+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include struct mbuf; struct rtentry; #include #include int main () { if ((struct ether_addr *) 0) return 0; if (sizeof (struct ether_addr)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_struct_ether_addr=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_struct_ether_addr=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_struct_ether_addr" >&5 echo "${ECHO_T}$ac_cv_type_struct_ether_addr" >&6 if test $ac_cv_type_struct_ether_addr = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_ETHER_ADDR 1 _ACEOF fi cat >>confdefs.h <<\_ACEOF #define HAVE_DECL_ETHER_HOSTTON 0 _ACEOF else cat >>confdefs.h <<\_ACEOF #define HAVE_DECL_ETHER_HOSTTON 1 _ACEOF fi fi echo "$as_me:$LINENO: checking if --disable-protochain option is specified" >&5 echo $ECHO_N "checking if --disable-protochain option is specified... $ECHO_C" >&6 # Check whether --enable-protochain or --disable-protochain was given. if test "${enable_protochain+set}" = set; then enableval="$enable_protochain" fi; case "x$enable_protochain" in xyes) enable_protochain=enabled ;; xno) enable_protochain=disabled ;; x) enable_protochain=enabled ;; esac if test "$enable_protochain" = "disabled"; then cat >>confdefs.h <<\_ACEOF #define NO_PROTOCHAIN 1 _ACEOF fi echo "$as_me:$LINENO: result: ${enable_protochain}" >&5 echo "${ECHO_T}${enable_protochain}" >&6 if test -z "$with_pcap" && test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: pcap type not determined when cross-compiling; use --with-pcap=..." >&5 echo "$as_me: error: pcap type not determined when cross-compiling; use --with-pcap=..." >&2;} { (exit 1); exit 1; }; } fi # Check whether --with-pcap or --without-pcap was given. if test "${with_pcap+set}" = set; then withval="$with_pcap" fi; echo "$as_me:$LINENO: checking packet capture type" >&5 echo $ECHO_N "checking packet capture type... $ECHO_C" >&6 if test ! -z "$with_pcap" ; then V_PCAP="$withval" elif test -r /dev/bpf ; then # # Cloning BPF device. # V_PCAP=bpf cat >>confdefs.h <<\_ACEOF #define HAVE_CLONING_BPF 1 _ACEOF 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/linux/socket.h ; then V_PCAP=linux elif test -r /usr/include/net/raw.h ; then V_PCAP=snoop elif test -r /usr/include/odmi.h ; then # # On AIX, the BPF devices might not yet be present - they're # created the first time libpcap runs after booting. # We check for odmi.h instead. # V_PCAP=bpf elif test -r /usr/include/sys/dlpi.h ; then V_PCAP=dlpi 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 fi echo "$as_me:$LINENO: result: $V_PCAP" >&5 echo "${ECHO_T}$V_PCAP" >&6 if test "$V_PCAP" = null then # # We can't capture, so we can't open any capture # devices, so we won't return any interfaces. # V_FINDALLDEVS=null else echo "$as_me:$LINENO: checking for getifaddrs" >&5 echo $ECHO_N "checking for getifaddrs... $ECHO_C" >&6 if test "${ac_cv_func_getifaddrs+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define getifaddrs to an innocuous variant, in case declares getifaddrs. For example, HP-UX 11i declares gettimeofday. */ #define getifaddrs innocuous_getifaddrs /* System header to define __stub macros and hopefully few prototypes, which can conflict with char getifaddrs (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef getifaddrs /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char getifaddrs (); /* 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_getifaddrs) || defined (__stub___getifaddrs) choke me #else char (*f) () = getifaddrs; #endif #ifdef __cplusplus } #endif int main () { return f != getifaddrs; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_getifaddrs=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_getifaddrs=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_getifaddrs" >&5 echo "${ECHO_T}$ac_cv_func_getifaddrs" >&6 if test $ac_cv_func_getifaddrs = yes; then # # We have "getifaddrs()"; make sure we have # as well, just in case some platform is really weird. # if test "${ac_cv_header_ifaddrs_h+set}" = set; then echo "$as_me:$LINENO: checking for ifaddrs.h" >&5 echo $ECHO_N "checking for ifaddrs.h... $ECHO_C" >&6 if test "${ac_cv_header_ifaddrs_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_ifaddrs_h" >&5 echo "${ECHO_T}$ac_cv_header_ifaddrs_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking ifaddrs.h usability" >&5 echo $ECHO_N "checking ifaddrs.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking ifaddrs.h presence" >&5 echo $ECHO_N "checking ifaddrs.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: ifaddrs.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: ifaddrs.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: ifaddrs.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: ifaddrs.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: ifaddrs.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: ifaddrs.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: ifaddrs.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: ifaddrs.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: ifaddrs.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: ifaddrs.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: ifaddrs.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: ifaddrs.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: ifaddrs.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: ifaddrs.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for ifaddrs.h" >&5 echo $ECHO_N "checking for ifaddrs.h... $ECHO_C" >&6 if test "${ac_cv_header_ifaddrs_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_ifaddrs_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_ifaddrs_h" >&5 echo "${ECHO_T}$ac_cv_header_ifaddrs_h" >&6 fi if test $ac_cv_header_ifaddrs_h = yes; then # # We have the header, so we use "getifaddrs()" to # get the list of interfaces. # V_FINDALLDEVS=getad else # # We don't have the header - give up. # XXX - we could also fall back on some other # mechanism, but, for now, this'll catch this # problem so that we can at least try to figure # out something to do on systems with "getifaddrs()" # but without "ifaddrs.h", if there is something # we can do on those systems. # { { echo "$as_me:$LINENO: error: Your system has getifaddrs() but doesn't have a usable ." >&5 echo "$as_me: error: Your system has getifaddrs() but doesn't have a usable ." >&2;} { (exit 1); exit 1; }; } fi else # # Well, we don't have "getifaddrs()", so we have to use # some other mechanism; determine what that mechanism is. # # The first thing we use is the type of capture mechanism, # which is somewhat of a proxy for the OS we're using. # case "$V_PCAP" in dlpi) # # This might be Solaris 8 or later, with # SIOCGLIFCONF, or it might be some other OS # or some older version of Solaris, with # just SIOCGIFCONF. # echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5 echo $ECHO_N "checking whether we have SIOCGLIFCONF... $ECHO_C" >&6 if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include #include int main () { ioctl(0, SIOCGLIFCONF, (char *)0); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_have_siocglifconf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_have_siocglifconf=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_have_siocglifconf" >&5 echo "${ECHO_T}$ac_cv_lbl_have_siocglifconf" >&6 if test $ac_cv_lbl_have_siocglifconf = yes ; then V_FINDALLDEVS=glifc else V_FINDALLDEVS=gifc fi ;; *) # # Assume we just have SIOCGIFCONF. # (XXX - on at least later Linux kernels, there's # another mechanism, and we should be using that # instead.) # V_FINDALLDEVS=gifc ;; esac fi fi echo "$as_me:$LINENO: checking if --enable-ipv6 option is specified" >&5 echo $ECHO_N "checking if --enable-ipv6 option is specified... $ECHO_C" >&6 # Check whether --enable-ipv6 or --disable-ipv6 was given. if test "${enable_ipv6+set}" = set; then enableval="$enable_ipv6" fi; if test "$enable_ipv6" = "yes"; then cat >>confdefs.h <<\_ACEOF #define INET6 1 _ACEOF fi echo "$as_me:$LINENO: result: ${enable_ipv6-no}" >&5 echo "${ECHO_T}${enable_ipv6-no}" >&6 echo "$as_me:$LINENO: checking whether to build optimizer debugging code" >&5 echo $ECHO_N "checking whether to build optimizer debugging code... $ECHO_C" >&6 # Check whether --enable-optimizer-dbg or --disable-optimizer-dbg was given. if test "${enable_optimizer_dbg+set}" = set; then enableval="$enable_optimizer_dbg" fi; if test "$enable_optimizer_dbg" = "yes"; then cat >>confdefs.h <<\_ACEOF #define BDEBUG 1 _ACEOF fi echo "$as_me:$LINENO: result: ${enable_optimizer_dbg-no}" >&5 echo "${ECHO_T}${enable_optimizer_dbg-no}" >&6 echo "$as_me:$LINENO: checking whether to build parser debugging code" >&5 echo $ECHO_N "checking whether to build parser debugging code... $ECHO_C" >&6 # Check whether --enable-yydebug or --disable-yydebug was given. if test "${enable_yydebug+set}" = set; then enableval="$enable_yydebug" fi; if test "$enable_yydebug" = "yes"; then cat >>confdefs.h <<\_ACEOF #define YYDEBUG 1 _ACEOF fi echo "$as_me:$LINENO: result: ${enable_yydebug-no}" >&5 echo "${ECHO_T}${enable_yydebug-no}" >&6 case "$V_PCAP" in dlpi) for ac_header in sys/bufmod.h sys/dlpi_ext.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking for /dev/dlpi device" >&5 echo $ECHO_N "checking for /dev/dlpi device... $ECHO_C" >&6 if test -c /dev/dlpi ; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define HAVE_DEV_DLPI 1 _ACEOF else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 dir="/dev/dlpi" echo "$as_me:$LINENO: checking for $dir directory" >&5 echo $ECHO_N "checking for $dir directory... $ECHO_C" >&6 if test -d $dir ; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<_ACEOF #define PCAP_DEV_PREFIX "$dir" _ACEOF else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; linux) echo "$as_me:$LINENO: checking Linux kernel version" >&5 echo $ECHO_N "checking Linux kernel version... $ECHO_C" >&6 if test "$cross_compiling" = yes; then if test "${ac_cv_linux_vers+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_linux_vers=unknown fi else if test "${ac_cv_linux_vers+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_linux_vers=`uname -r 2>&1 | \ sed -n -e '$s/.* //' -e '$s/\..*//p'` fi fi echo "$as_me:$LINENO: result: $ac_cv_linux_vers" >&5 echo "${ECHO_T}$ac_cv_linux_vers" >&6 if test $ac_cv_linux_vers = unknown ; then { { echo "$as_me:$LINENO: error: cannot determine linux version when cross-compiling" >&5 echo "$as_me: error: cannot determine linux version when cross-compiling" >&2;} { (exit 1); exit 1; }; } fi if test $ac_cv_linux_vers -lt 2 ; then { { echo "$as_me:$LINENO: error: version 2 or higher required; see the INSTALL doc for more info" >&5 echo "$as_me: error: version 2 or higher required; see the INSTALL doc for more info" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: checking if if_packet.h has tpacket_stats defined" >&5 echo $ECHO_N "checking if if_packet.h has tpacket_stats defined... $ECHO_C" >&6 if test "${ac_cv_lbl_tpacket_stats+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include int main () { struct tpacket_stats stats ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_tpacket_stats=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_tpacket_stats=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_tpacket_stats" >&5 echo "${ECHO_T}$ac_cv_lbl_tpacket_stats" >&6 if test $ac_cv_lbl_tpacket_stats = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_TPACKET_STATS 1 _ACEOF fi ;; dag) V_DEFS="$V_DEFS -DDAG_ONLY" ;; septel) V_DEFS="$V_DEFS -DSEPTEL_ONLY" ;; null) { echo "$as_me:$LINENO: WARNING: cannot determine packet capture interface" >&5 echo "$as_me: WARNING: cannot determine packet capture interface" >&2;} { echo "$as_me:$LINENO: WARNING: (see the INSTALL doc for more info)" >&5 echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;} ;; esac echo "$as_me:$LINENO: checking whether we have /proc/net/dev" >&5 echo $ECHO_N "checking whether we have /proc/net/dev... $ECHO_C" >&6 if test -r /proc/net/dev ; then ac_cv_lbl_proc_net_dev=yes else ac_cv_lbl_proc_net_dev=no fi if test $ac_cv_lbl_proc_net_dev = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_PROC_NET_DEV 1 _ACEOF fi echo "$as_me:$LINENO: result: $ac_cv_lbl_proc_net_dev" >&5 echo "${ECHO_T}$ac_cv_lbl_proc_net_dev" >&6 # Check for Endace DAG card support. # Check whether --with-dag or --without-dag was given. if test "${with_dag+set}" = set; then withval="$with_dag" if test "$withval" = no then # User doesn't want DAG support. want_dag=no elif test "$withval" = yes then # User wants DAG support but hasn't specified a directory. want_dag=yes else # User wants DAG support and has specified a directory, so use the provided value. want_dag=yes dag_root=$withval fi else # # Use DAG API if present, otherwise don't # want_dag=ifpresent fi; # Check whether --with-dag-includes or --without-dag-includes was given. if test "${with_dag_includes+set}" = set; then withval="$with_dag_includes" # User wants DAG support and has specified a header directory, so use the provided value. want_dag=yes dag_include_dir=$withval fi; # Check whether --with-dag-libraries or --without-dag-libraries was given. if test "${with_dag_libraries+set}" = set; then withval="$with_dag_libraries" # User wants DAG support and has specified a library directory, so use the provided value. want_dag=yes dag_lib_dir=$withval fi; case "$V_PCAP" in linux|bpf|dag) # # We support the DAG API if we're on Linux or BSD, or if we're # building a DAG-only libpcap. # ;; *) # # If the user explicitly requested DAG, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_dag = yes; then { { echo "$as_me:$LINENO: error: DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" >&5 echo "$as_me: error: DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" >&2;} { (exit 1); exit 1; }; } elif test $want_dag = yes; then want_dag=no fi ;; esac ac_cv_lbl_dag_api=no if test "$want_dag" != no; then echo "$as_me:$LINENO: checking whether we have DAG API headers" >&5 echo $ECHO_N "checking whether we have DAG API headers... $ECHO_C" >&6 # If necessary, set default paths for DAG API headers and libraries. if test -z "$dag_root"; then dag_root=/usr/local fi if test -z "$dag_include_dir"; then dag_include_dir="$dag_root/include" fi if test -z "$dag_lib_dir"; then dag_lib_dir="$dag_root/lib" fi if test -z "$dag_tools_dir"; then dag_tools_dir="$dag_root/tools" fi if test -r $dag_include_dir/dagapi.h; then ac_cv_lbl_dag_api=yes fi echo "$as_me:$LINENO: result: $ac_cv_lbl_dag_api ($dag_include_dir)" >&5 echo "${ECHO_T}$ac_cv_lbl_dag_api ($dag_include_dir)" >&6 fi if test $ac_cv_lbl_dag_api = yes; then echo "$as_me:$LINENO: checking dagapi.o" >&5 echo $ECHO_N "checking dagapi.o... $ECHO_C" >&6 dagapi_obj=no if test -r $dag_tools_dir/dagapi.o; then # 2.4.x. dagapi_obj=$dag_tools_dir/dagapi.o elif test -r $dag_lib_dir/dagapi.o; then # 2.5.x. dagapi_obj=$dag_lib_dir/dagapi.o elif test -r $dag_lib_dir/libdag.a; then # 2.5.x. ar x $dag_lib_dir/libdag.a dagapi.o if test -r ./dagapi.o; then dagapi_obj=./dagapi.o else ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o if test -r ./libdag_la-dagapi.o; then dagapi_obj=./libdag_la-dagapi.o fi fi fi if test $dagapi_obj = no; then echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&5 echo "${ECHO_T}no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&6 ac_cv_lbl_dag_api=no else echo "$as_me:$LINENO: result: yes ($dagapi_obj)" >&5 echo "${ECHO_T}yes ($dagapi_obj)" >&6 fi fi if test $ac_cv_lbl_dag_api = yes; then echo "$as_me:$LINENO: checking dagopts.o" >&5 echo $ECHO_N "checking dagopts.o... $ECHO_C" >&6 dagopts_obj=no if test -r $dag_tools_dir/dagopts.o; then # 2.4.x. dagopts_obj=$dag_tools_dir/dagopts.o elif test -r $dag_lib_dir/dagopts.o; then # 2.5.x. dagopts_obj=$dag_lib_dir/dagopts.o elif test -r $dag_lib_dir/libdag.a; then # 2.5.x. ar x $dag_lib_dir/libdag.a dagopts.o if test -r ./dagopts.o; then dagopts_obj=./dagopts.o else ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o if test -r ./libdag_la-dagopts.o; then dagopts_obj=./libdag_la-dagopts.o fi fi fi if test $dagopts_obj = no; then echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&5 echo "${ECHO_T}no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&6 ac_cv_lbl_dag_api=no else echo "$as_me:$LINENO: result: yes ($dagopts_obj)" >&5 echo "${ECHO_T}yes ($dagopts_obj)" >&6 fi fi if test $ac_cv_lbl_dag_api = yes; then # Under 2.5.x only we need to add dagreg.o. if test -r $dag_include_dir/dagreg.h; then echo "$as_me:$LINENO: checking dagreg.o" >&5 echo $ECHO_N "checking dagreg.o... $ECHO_C" >&6 dagreg_obj=no if test -r $dag_lib_dir/dagreg.o; then # Object file is ready and waiting. dagreg_obj=$dag_lib_dir/dagreg.o elif test -r $dag_lib_dir/libdag.a; then # Extract from libdag.a. ar x $dag_lib_dir/libdag.a dagreg.o if test -r ./dagreg.o; then dagreg_obj=./dagreg.o else ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o if test -r ./libdag_la-dagreg.o; then dagreg_obj=./libdag_la-dagreg.o fi fi fi if test $dagreg_obj = no; then echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_lib_dir/libdag.a)" >&5 echo "${ECHO_T}no (checked $dag_lib_dir $dag_lib_dir/libdag.a)" >&6 ac_cv_lbl_dag_api=no else echo "$as_me:$LINENO: result: yes ($dagreg_obj)" >&5 echo "${ECHO_T}yes ($dagreg_obj)" >&6 fi fi fi if test $ac_cv_lbl_dag_api = yes; then V_INCLS="$V_INCLS -I$dag_include_dir" V_LIBS="$V_LIBS $dagapi_obj $dagopts_obj $dagreg_obj" if test $V_PCAP != dag ; then SSRC="pcap-dag.c" fi # See if we can find a general version string. # Don't need to save and restore LIBS to prevent -ldag being # included if there's a found-action (arg 3). saved_ldflags=$LDFLAGS LDFLAGS="-L$dag_lib_dir" echo "$as_me:$LINENO: checking for dag_attach_stream in -ldag" >&5 echo $ECHO_N "checking for dag_attach_stream in -ldag... $ECHO_C" >&6 if test "${ac_cv_lib_dag_dag_attach_stream+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldag $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dag_attach_stream (); int main () { dag_attach_stream (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dag_dag_attach_stream=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dag_dag_attach_stream=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dag_dag_attach_stream" >&5 echo "${ECHO_T}$ac_cv_lib_dag_dag_attach_stream" >&6 if test $ac_cv_lib_dag_dag_attach_stream = yes; then dag_version="2.5.x" else dag_version="2.4.x" fi echo "$as_me:$LINENO: checking for dag_get_erf_types in -ldag" >&5 echo $ECHO_N "checking for dag_get_erf_types in -ldag... $ECHO_C" >&6 if test "${ac_cv_lib_dag_dag_get_erf_types+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldag $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dag_get_erf_types (); int main () { dag_get_erf_types (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dag_dag_get_erf_types=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dag_dag_get_erf_types=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dag_dag_get_erf_types" >&5 echo "${ECHO_T}$ac_cv_lib_dag_dag_get_erf_types" >&6 if test $ac_cv_lib_dag_dag_get_erf_types = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_DAG_GET_ERF_TYPES 1 _ACEOF fi LDFLAGS=$saved_ldflags if test "$dag_version" = 2.5.x; then cat >>confdefs.h <<\_ACEOF #define HAVE_DAG_STREAMS_API 1 _ACEOF DAGLIBS="-ldag" fi # See if we can find a specific version string. echo "$as_me:$LINENO: checking the DAG API version" >&5 echo $ECHO_N "checking the DAG API version... $ECHO_C" >&6 if test -r "$dag_root/VERSION"; then dag_version="`cat $dag_root/VERSION`" fi echo "$as_me:$LINENO: result: $dag_version" >&5 echo "${ECHO_T}$dag_version" >&6 cat >>confdefs.h <<\_ACEOF #define HAVE_DAG_API 1 _ACEOF fi if test $ac_cv_lbl_dag_api = no; then if test "$want_dag" = yes; then # User wanted DAG support but we couldn't find it. { { echo "$as_me:$LINENO: error: DAG API requested, but not found at $dag_root: use --without-dag" >&5 echo "$as_me: error: DAG API requested, but not found at $dag_root: use --without-dag" >&2;} { (exit 1); exit 1; }; } fi if test "$V_PCAP" = dag; then # User requested "dag" capture type but the DAG API wasn't # found. { { echo "$as_me:$LINENO: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&5 echo "$as_me: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&2;} { (exit 1); exit 1; }; } fi fi # Check whether --with-septel or --without-septel was given. if test "${with_septel+set}" = set; then withval="$with_septel" if test "$withval" = no then want_septel=no elif test "$withval" = yes then want_septel=yes septel_root= else want_septel=yes septel_root=$withval fi else # # Use Septel API if present, otherwise don't # want_septel=ifpresent septel_root=./../septel fi; ac_cv_lbl_septel_api=no case "$V_PCAP" in linux|septel) # # We support the Septel API if we're on Linux, or if we're building # a Septel-only libpcap. # ;; *) # # If the user explicitly requested Septel, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_septel = yes; then { { echo "$as_me:$LINENO: error: Septel support only available with 'linux' and 'septel' packet capture types" >&5 echo "$as_me: error: Septel support only available with 'linux' and 'septel' packet capture types" >&2;} { (exit 1); exit 1; }; } elif test $want_septel = yes; then want_septel=no fi ;; esac if test "$with_septel" != no; then echo "$as_me:$LINENO: checking whether we have Septel API" >&5 echo $ECHO_N "checking whether we have Septel API... $ECHO_C" >&6 if test -z "$septel_root"; then septel_root=$srcdir/../septel fi septel_tools_dir="$septel_root" septel_include_dir="$septel_root/INC" DEF="-DHAVE_SEPTEL_API" ac_cv_lbl_septel_api=no if test -r "$septel_include_dir/msg.h"; then V_INCLS="$V_INCLS -I$septel_include_dir" V_DEFS="$V_DEFS $DEF" V_LIBS="$V_LIBS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o " if test "$V_PCAP" != septel ; then SSRC="pcap-septel.c" fi ac_cv_lbl_septel_api=yes fi echo "$as_me:$LINENO: result: $ac_cv_lbl_septel_api" >&5 echo "${ECHO_T}$ac_cv_lbl_septel_api" >&6 if test $ac_cv_lbl_septel_api = no; then if test "$want_septel" = yes; then { { echo "$as_me:$LINENO: error: Septel API not found under directory $septel_root; use --without-septel" >&5 echo "$as_me: error: Septel API not found under directory $septel_root; use --without-septel" >&2;} { (exit 1); exit 1; }; } fi else cat >>confdefs.h <<\_ACEOF #define HAVE_SEPTEL_API 1 _ACEOF fi fi if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then { { echo "$as_me:$LINENO: error: Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" >&5 echo "$as_me: error: Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" >&2;} { (exit 1); exit 1; }; } fi # Check whether --with-flex or --without-flex was given. if test "${with_flex+set}" = set; then withval="$with_flex" fi; # Check whether --with-bison or --without-bison was given. if test "${with_bison+set}" = set; then withval="$with_bison" fi; if test "$with_flex" = no ; then V_LEX=lex else for ac_prog in flex do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_V_LEX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$V_LEX"; then ac_cv_prog_V_LEX="$V_LEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_V_LEX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi V_LEX=$ac_cv_prog_V_LEX if test -n "$V_LEX"; then echo "$as_me:$LINENO: result: $V_LEX" >&5 echo "${ECHO_T}$V_LEX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi 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 "$as_me:$LINENO: checking for flex 2.4 or higher" >&5 echo $ECHO_N "checking for flex 2.4 or higher... $ECHO_C" >&6 if test "${ac_cv_lbl_flex_v24+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if flex -V >/dev/null 2>&1; then ac_cv_lbl_flex_v24=yes else ac_cv_lbl_flex_v24=no fi fi echo "$as_me:$LINENO: result: $ac_cv_lbl_flex_v24" >&5 echo "${ECHO_T}$ac_cv_lbl_flex_v24" >&6 if test $ac_cv_lbl_flex_v24 = no ; then s="2.4 or higher required" { echo "$as_me:$LINENO: WARNING: ignoring obsolete flex executable ($s)" >&5 echo "$as_me: WARNING: ignoring obsolete flex executable ($s)" >&2;} V_LEX=lex fi fi if test "$with_bison" = no ; then V_YACC=yacc else for ac_prog in bison do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_V_YACC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$V_YACC"; then ac_cv_prog_V_YACC="$V_YACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_V_YACC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi V_YACC=$ac_cv_prog_V_YACC if test -n "$V_YACC"; then echo "$as_me:$LINENO: result: $V_YACC" >&5 echo "${ECHO_T}$V_YACC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi 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 "$as_me:$LINENO: WARNING: don't have both flex and bison; reverting to lex/yacc" >&5 echo "$as_me: WARNING: don't have both flex and bison; reverting to lex/yacc" >&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 if test "$V_LEX" = lex ; then # Some versions of lex can't handle the definitions section of scanner.l . # Try lexing it and complain if it can't deal. echo "$as_me:$LINENO: checking for capable lex" >&5 echo $ECHO_N "checking for capable lex... $ECHO_C" >&6 if test "${tcpdump_cv_capable_lex+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if lex -t scanner.l > /dev/null 2>&1; then tcpdump_cv_capable_lex=yes else tcpdump_cv_capable_lex=insufficient fi fi echo "$as_me:$LINENO: result: $tcpdump_cv_capable_lex" >&5 echo "${ECHO_T}$tcpdump_cv_capable_lex" >&6 if test $tcpdump_cv_capable_lex = insufficient ; then { { echo "$as_me:$LINENO: error: Your operating system's lex is insufficient to compile libpcap. flex is a lex replacement that has many advantages, including being able to compile libpcap. For more information, see http://www.gnu.org/software/flex/flex.html ." >&5 echo "$as_me: error: Your operating system's lex is insufficient to compile libpcap. flex is a lex replacement that has many advantages, including being able to compile libpcap. For more information, see http://www.gnu.org/software/flex/flex.html ." >&2;} { (exit 1); exit 1; }; } fi fi DYEXT="so" case "$host_os" in aix*) cat >>confdefs.h <<\_ACEOF #define _SUN 1 _ACEOF ;; hpux9*) cat >>confdefs.h <<\_ACEOF #define HAVE_HPUX9 1 _ACEOF ;; hpux10.0*) ;; hpux10.1*) ;; hpux*) cat >>confdefs.h <<\_ACEOF #define HAVE_HPUX10_20_OR_LATER 1 _ACEOF ;; sinix*) echo "$as_me:$LINENO: checking if SINIX compiler defines sinix" >&5 echo $ECHO_N "checking if SINIX compiler defines sinix... $ECHO_C" >&6 if test "${ac_cv_cc_sinix_defined+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i = sinix; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_cc_sinix_defined=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_cc_sinix_defined=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_cc_sinix_defined" >&5 echo "${ECHO_T}$ac_cv_cc_sinix_defined" >&6 if test $ac_cv_cc_sinix_defined = no ; then cat >>confdefs.h <<\_ACEOF #define sinix 1 _ACEOF fi ;; solaris*) cat >>confdefs.h <<\_ACEOF #define HAVE_SOLARIS 1 _ACEOF ;; darwin*) DYEXT="dylib" V_CCOPT="$V_CCOPT -fno-common" ;; linux*) V_CCOPT="$V_CCOPT -fPIC" ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RANLIB=$ac_ct_RANLIB else RANLIB="$ac_cv_prog_RANLIB" fi 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 <<\_ACEOF #define HAVE_OS_PROTO_H 1 _ACEOF else { echo "$as_me:$LINENO: WARNING: can't find $name" >&5 echo "$as_me: WARNING: can't find $name" >&2;} fi fi echo "$as_me:$LINENO: checking if sockaddr struct has sa_len member" >&5 echo $ECHO_N "checking if sockaddr struct has sa_len member... $ECHO_C" >&6 if test "${ac_cv_lbl_sockaddr_has_sa_len+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include # include int main () { u_int i = sizeof(((struct sockaddr *)0)->sa_len) ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_sockaddr_has_sa_len=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_sockaddr_has_sa_len=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_sockaddr_has_sa_len" >&5 echo "${ECHO_T}$ac_cv_lbl_sockaddr_has_sa_len" >&6 if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then cat >>confdefs.h <<\_ACEOF #define HAVE_SOCKADDR_SA_LEN 1 _ACEOF fi echo "$as_me:$LINENO: checking if sockaddr_storage struct exists" >&5 echo $ECHO_N "checking if sockaddr_storage struct exists... $ECHO_C" >&6 if test "${ac_cv_lbl_has_sockaddr_storage+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include # include int main () { u_int i = sizeof (struct sockaddr_storage) ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_has_sockaddr_storage=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_has_sockaddr_storage=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_has_sockaddr_storage" >&5 echo "${ECHO_T}$ac_cv_lbl_has_sockaddr_storage" >&6 if test $ac_cv_lbl_has_sockaddr_storage = yes ; then cat >>confdefs.h <<\_ACEOF #define HAVE_SOCKADDR_STORAGE 1 _ACEOF fi echo "$as_me:$LINENO: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5 echo $ECHO_N "checking if dl_hp_ppa_info_t struct has dl_module_id_1 member... $ECHO_C" >&6 if test "${ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # include # include # include int main () { u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1) ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&5 echo "${ECHO_T}$ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&6 if test $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1 = yes ; then cat >>confdefs.h <<\_ACEOF #define HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 1 _ACEOF fi echo "$as_me:$LINENO: checking if unaligned accesses fail" >&5 echo $ECHO_N "checking if unaligned accesses fail... $ECHO_C" >&6 if test "${ac_cv_lbl_unaligned_fail+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case "$host_cpu" in # # These are CPU types where: # # the CPU faults on an unaligned access, but at least some # OSes that support that CPU catch the fault and simulate # the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) - # the simulation is slow, so we don't want to use it; # # the CPU, I infer (from the old # # XXX: should also check that they don't do weird things (like on arm) # # comment) doesn't fault on unaligned accesses, but doesn't # do a normal unaligned fetch, either (e.g., presumably, ARM); # # for whatever reason, the test program doesn't work # (this has been claimed to be the case for several of those # CPUs - I don't know what the problem is; the problem # was reported as "the test program dumps core" for SuperH, # but that's what the test program is *supposed* to do - # it dumps core before it writes anything, so the test # for an empty output file should find an empty output # file and conclude that unaligned accesses don't work). # # This run-time test won't work if you're cross-compiling, so # in order to support cross-compiling for a particular CPU, # we have to wire in the list of CPU types anyway, as far as # I know, so perhaps we should just have a set of CPUs on # which we know it doesn't work, a set of CPUs on which we # know it does work, and have the script just fail on other # cpu types and update it when such a failure occurs. # alpha*|arm*|hp*|mips*|sh*|sparc*|ia64|nv1) ac_cv_lbl_unaligned_fail=yes ;; *) cat >conftest.c < # include # include 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); } EOF ${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 fi echo "$as_me:$LINENO: result: $ac_cv_lbl_unaligned_fail" >&5 echo "${ECHO_T}$ac_cv_lbl_unaligned_fail" >&6 if test $ac_cv_lbl_unaligned_fail = yes ; then cat >>confdefs.h <<\_ACEOF #define LBL_ALIGN 1 _ACEOF fi # # Makefile.in includes rules to generate version.h, so we assume # that it will be generated if autoconf is used. # cat >>confdefs.h <<\_ACEOF #define HAVE_VERSION_H 1 _ACEOF rm -f net ln -s ${srcdir}/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 # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi 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 fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&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_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' ac_config_headers="$ac_config_headers config.h" ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # 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, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # 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 | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by $as_me, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir INSTALL="$INSTALL" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@build@,$build,;t t s,@build_cpu@,$build_cpu,;t t s,@build_vendor@,$build_vendor,;t t s,@build_os@,$build_os,;t t s,@host@,$host,;t t s,@host_cpu@,$host_cpu,;t t s,@host_vendor@,$host_vendor,;t t s,@host_os@,$host_os,;t t s,@target@,$target,;t t s,@target_cpu@,$target_cpu,;t t s,@target_vendor@,$target_vendor,;t t s,@target_os@,$target_os,;t t s,@SHLICC2@,$SHLICC2,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@V_LEX@,$V_LEX,;t t s,@V_YACC@,$V_YACC,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@V_CCOPT@,$V_CCOPT,;t t s,@V_DEFS@,$V_DEFS,;t t s,@V_INCLS@,$V_INCLS,;t t s,@V_LIBS@,$V_LIBS,;t t s,@V_PCAP@,$V_PCAP,;t t s,@V_FINDALLDEVS@,$V_FINDALLDEVS,;t t s,@V_RANLIB@,$V_RANLIB,;t t s,@SSRC@,$SSRC,;t t s,@DYEXT@,$DYEXT,;t t s,@DAGLIBS@,$DAGLIBS,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # 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_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # 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" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t s,@INSTALL@,$ac_INSTALL,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_HEADER section. # # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } # Do quote $f, to prevent DOS paths from being IFS'd. echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF # Transform confdefs.h into two sed scripts, `conftest.defines' and # `conftest.undefs', that substitutes the proper values into # config.h.in to produce config.h. The first handles `#define' # templates, and the second `#undef' templates. # And first: Protect against being on the right side of a sed subst in # config.status. Protect against being in an unquoted here document # in config.status. rm -f conftest.defines conftest.undefs # Using a here document instead of a string reduces the quoting nightmare. # Putting comments in sed scripts is not portable. # # `end' is used to avoid that the second main sed command (meant for # 0-ary CPP macros) applies to n-ary macro definitions. # See the Autoconf documentation for `clear'. cat >confdef2sed.sed <<\_ACEOF s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times # the same #defines, which is useless. Nevertheless, we may not want to # sort them, since we want the *last* AC-DEFINE to be honored. uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.defines >/dev/null do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/defines.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #undef templates' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.undefs >/dev/null do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#undef' echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/undefs.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail rm -f conftest.undefs mv conftest.tail conftest.undefs done rm -f conftest.undefs cat >>$CONFIG_STATUS <<\_ACEOF # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then echo "/* Generated by configure. */" >$tmp/config.h else echo "/* $ac_file. Generated by configure. */" >$tmp/config.h fi cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } rm -f $ac_file mv $tmp/config.h $ac_file fi else cat $tmp/config.h rm -f $tmp/config.h fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi if test -f .devel ; then make depend fi exit 0 libpcap-0.9.7/./pcap1.h0000644000026300017500000002250110032303552012566 0ustar mcrmcr/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * 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: /tcpdump/master/libpcap/pcap1.h,v 1.2 2004/03/30 14:42:50 mcr Exp $ (LBL) */ #ifndef lib_pcap_h #define lib_pcap_h #ifdef WIN32 #include #else /* WIN32 */ #include #include #endif /* WIN32 */ #ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H #include #endif #include #ifdef __cplusplus extern "C" { #endif #define PCAP_VERSION_MAJOR 3 #define PCAP_VERSION_MINOR 0 #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; typedef struct pcap_if pcap_if_t; typedef struct pcap_addr pcap_addr_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. * * Do not change the layout of this structure, in any way (this includes * changes that only affect the length of fields in this structure). * * Also, do not change the interpretation of any of the members of this * structure, in any way (this includes using values other than * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" * field). * * Instead: * * introduce a new structure for the new format, if the layout * of the structure changed; * * send mail to "tcpdump-workers@tcpdump.org", requesting a new * magic number for your new capture file format, and, when * you get the new magic number, put it in "savefile.c"; * * use that magic number for save files with the changed file * header; * * make the code in "savefile.c" capable of reading files with * the old file header as well as files with the new file header * (using the magic number to determine the header format). * * Then supply the changes to "patches@tcpdump.org", so that future * versions of libpcap and programs that use it (such as tcpdump) will * be able to read your new capture file format. */ enum pcap1_info_types { PCAP_DATACAPTURE, PCAP_TIMESTAMP, PCAP_WALLTIME, PCAP_TIMESKEW, PCAP_PROBEPLACE, /* aka direction */ PCAP_COMMENT, /* comment */ }; struct pcap1_info_container { bpf_u_int32 info_len; /* in bytes */ bpf_u_int32 info_type; /* enum pcap1_info_types */ unsigned char info_data[0]; }; struct pcap1_info_timestamp { struct pcap1_info_container pic; bpf_u_int32 nanoseconds; /* 10^-9 of seconds */ bpf_u_int32 seconds; /* seconds since Unix epoch - GMT */ bpf_u_int16 macroseconds; /* 16 bits more of MSB of time */ bpf_u_int16 sigfigs; /* accuracy of timestamps - LSB bits */ }; struct pcap1_info_packet { struct pcap1_info_container pic; bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ bpf_u_int32 ifIndex; /* abstracted interface index */ unsigned char packet_data[0]; }; enum pcap1_probe { INBOUND =1, OUTBOUND =2, FORWARD =3, PREENCAP =4, POSTDECAP=5, }; struct pcap1_info_probe { struct pcap1_info_container pic; bpf_u_int32 probeloc; /* enum pcap1_probe */ unsigned char probe_desc[0]; }; struct pcap1_info_comment { struct pcap1_info_container pic; unsigned char comment[0]; }; struct pcap1_packet_header { bpf_u_int32 magic; u_short version_major; u_short version_minor; bpf_u_int32 block_len; struct pcap1_info_container pics[0]; }; /* * Each packet in the dump file is prepended with this generic header. * This gets around the problem of different headers for different * packet interfaces. */ /* * 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 */ #ifdef WIN32 u_int bs_capt; /* number of packets that reach the application */ #endif /* WIN32 */ }; /* * Item in a list of interfaces. */ struct pcap_if { struct pcap_if *next; char *name; /* name to hand to "pcap_open_live()" */ char *description; /* textual description of interface, or NULL */ struct pcap_addr *addresses; bpf_u_int32 flags; /* PCAP_IF_ interface flags */ }; #define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ /* * Representation of an interface address. */ struct pcap_addr { struct pcap_addr *next; struct sockaddr *addr; /* address */ struct sockaddr *netmask; /* netmask for that address */ struct sockaddr *broadaddr; /* broadcast address for that address */ struct sockaddr *dstaddr; /* P2P destination address for that address */ }; typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *); char *pcap_lookupdev(char *); int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); pcap_t *pcap_open_live(const char *, int, int, int, char *); pcap_t *pcap_open_dead(int, int); 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_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **); void pcap_breakloop(pcap_t *); int pcap_stats(pcap_t *, struct pcap_stat *); int pcap_setfilter(pcap_t *, struct bpf_program *); int pcap_getnonblock(pcap_t *, char *); int pcap_setnonblock(pcap_t *, int, char *); 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); int pcap_compile_nopcap(int, int, struct bpf_program *, char *, int, bpf_u_int32); void pcap_freecode(struct bpf_program *); int pcap_datalink(pcap_t *); int pcap_list_datalinks(pcap_t *, int **); int pcap_set_datalink(pcap_t *, int); int pcap_datalink_name_to_val(const char *); const char *pcap_datalink_val_to_name(int); const char *pcap_datalink_val_to_description(int); 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 *); int pcap_dump_flush(pcap_dumper_t *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); FILE *pcap_dump_file(pcap_dumper_t *); int pcap_findalldevs(pcap_if_t **, char *); void pcap_freealldevs(pcap_if_t *); const char *pcap_lib_version(void); /* XXX this guy lives in the bpf tree */ u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); int bpf_validate(struct bpf_insn *f, int len); char *bpf_image(struct bpf_insn *, int); void bpf_dump(struct bpf_program *, int); #ifdef WIN32 /* * Win32 definitions */ int pcap_setbuff(pcap_t *p, int dim); int pcap_setmode(pcap_t *p, int mode); int pcap_sendpacket(pcap_t *p, u_char *buf, int size); int pcap_setmintocopy(pcap_t *p, int size); #ifdef WPCAP /* Include file with the wpcap-specific extensions */ #include #endif #define MODE_CAPT 0 #define MODE_STAT 1 #else /* * UN*X definitions */ int pcap_get_selectable_fd(pcap_t *); #endif /* WIN32 */ #ifdef __cplusplus } #endif #endif libpcap-0.9.7/./pcap-bpf.h0000644000026300017500000006077110651225661013300 0ustar mcrmcr/*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)bpf.h 7.1 (Berkeley) 5/7/91 * * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.34.2.20 2007/07/19 06:20:53 guy Exp $ (LBL) */ /* * This is libpcap's cut-down version of bpf.h; it includes only * the stuff needed for the code generator and the userland BPF * interpreter, and the libpcap APIs for setting filters, etc.. * * "pcap-bpf.c" will include the native OS version, as it deals with * the OS's BPF implementation. * * XXX - should this all just be moved to "pcap.h"? */ #ifndef BPF_MAJOR_VERSION #ifdef __cplusplus extern "C" { #endif /* BSD style release date */ #define BPF_RELEASE 199606 #ifdef MSDOS /* must be 32-bit */ typedef long bpf_int32; typedef unsigned long bpf_u_int32; #else typedef int bpf_int32; typedef u_int bpf_u_int32; #endif /* * Alignment macros. BPF_WORDALIGN rounds up to the next * even multiple of BPF_ALIGNMENT. */ #ifndef __NetBSD__ #define BPF_ALIGNMENT sizeof(bpf_int32) #else #define BPF_ALIGNMENT sizeof(long) #endif #define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) #define BPF_MAXINSNS 512 #define BPF_MAXBUFSIZE 0x8000 #define BPF_MINBUFSIZE 32 /* * Structure for "pcap_compile()", "pcap_setfilter()", etc.. */ struct bpf_program { u_int bf_len; struct bpf_insn *bf_insns; }; /* * Struct return by BIOCVERSION. This represents the version number of * the filter language described by the instruction encodings below. * bpf understands a program iff kernel_major == filter_major && * kernel_minor >= filter_minor, that is, if the value returned by the * running kernel has the same major number and a minor number equal * equal to or less than the filter being downloaded. Otherwise, the * results are undefined, meaning an error may be returned or packets * may be accepted haphazardly. * It has nothing to do with the source code version. */ struct bpf_version { u_short bv_major; u_short bv_minor; }; /* Current version number of filter architecture. */ #define BPF_MAJOR_VERSION 1 #define BPF_MINOR_VERSION 1 /* * Data-link level type codes. * * Do *NOT* add new values to this list without asking * "tcpdump-workers@tcpdump.org" for a value. Otherwise, you run the * risk of using a value that's already being used for some other purpose, * and of having tools that read libpcap-format captures not being able * to handle captures with your new DLT_ value, with no hope that they * will ever be changed to do so (as that would destroy their ability * to read captures using that value for that other purpose). */ /* * These are the types that are the same on all platforms, and that * have been defined by for ages. */ #define DLT_NULL 0 /* BSD loopback encapsulation */ #define DLT_EN10MB 1 /* Ethernet (10Mb) */ #define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ #define DLT_AX25 3 /* Amateur Radio AX.25 */ #define DLT_PRONET 4 /* Proteon ProNET Token Ring */ #define DLT_CHAOS 5 /* Chaos */ #define DLT_IEEE802 6 /* IEEE 802 Networks */ #define DLT_ARCNET 7 /* ARCNET, with BSD-style header */ #define DLT_SLIP 8 /* Serial Line IP */ #define DLT_PPP 9 /* Point-to-point Protocol */ #define DLT_FDDI 10 /* FDDI */ /* * These are types that are different on some platforms, and that * have been defined by for ages. We use #ifdefs to * detect the BSDs that define them differently from the traditional * libpcap * * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS, * but I don't know what the right #define is for BSD/OS. */ #define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */ #ifdef __OpenBSD__ #define DLT_RAW 14 /* raw IP */ #else #define DLT_RAW 12 /* raw IP */ #endif /* * Given that the only OS that currently generates BSD/OS SLIP or PPP * is, well, BSD/OS, arguably everybody should have chosen its values * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they * didn't. So it goes. */ #if defined(__NetBSD__) || defined(__FreeBSD__) #ifndef DLT_SLIP_BSDOS #define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ #define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ #endif #else #define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ #define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ #endif /* * 17 is used for DLT_OLD_PFLOG in OpenBSD; * OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below. * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else. */ #define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ /* * Apparently Redback uses this for its SmartEdge 400/800. I hope * nobody else decided to use it, too. */ #define DLT_REDBACK_SMARTEDGE 32 /* * These values are defined by NetBSD; other platforms should refrain from * using them for other purposes, so that NetBSD savefiles with link * types of 50 or 51 can be read as this type on all platforms. */ #define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ #define DLT_PPP_ETHER 51 /* PPP over Ethernet */ /* * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses * a link-layer type of 99 for the tcpdump it supplies. The link-layer * header has 6 bytes of unknown data, something that appears to be an * Ethernet type, and 36 bytes that appear to be 0 in at least one capture * I've seen. */ #define DLT_SYMANTEC_FIREWALL 99 /* * Values between 100 and 103 are used in capture file headers as * link-layer types corresponding to DLT_ types that differ * between platforms; don't use those values for new DLT_ new types. */ /* * This value was defined by libpcap 0.5; platforms that have defined * it with a different value should define it here with that value - * a link type of 104 in a save file will be mapped to DLT_C_HDLC, * whatever value that happens to be, so programs will correctly * handle files with that link type regardless of the value of * DLT_C_HDLC. * * The name DLT_C_HDLC was used by BSD/OS; we use that name for source * compatibility with programs written for BSD/OS. * * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, * for source compatibility with programs written for libpcap 0.5. */ #define DLT_C_HDLC 104 /* Cisco HDLC */ #define DLT_CHDLC DLT_C_HDLC #define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ /* * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, * except when it isn't. (I.e., sometimes it's just raw IP, and * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, * so that we don't have to worry about the link-layer header.) */ /* * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides * with other values. * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header * (DLCI, etc.). */ #define DLT_FRELAY 107 /* * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except * that the AF_ type in the link-layer header is in network byte order. * * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so * we don't use 12 for it in OSes other than OpenBSD. */ #ifdef __OpenBSD__ #define DLT_LOOP 12 #else #define DLT_LOOP 108 #endif /* * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other * than OpenBSD. */ #ifdef __OpenBSD__ #define DLT_ENC 13 #else #define DLT_ENC 109 #endif /* * Values between 110 and 112 are reserved for use in capture file headers * as link-layer types corresponding to DLT_ types that might differ * between platforms; don't use those values for new DLT_ types * other than the corresponding DLT_ types. */ /* * This is for Linux cooked sockets. */ #define DLT_LINUX_SLL 113 /* * Apple LocalTalk hardware. */ #define DLT_LTALK 114 /* * Acorn Econet. */ #define DLT_ECONET 115 /* * Reserved for use with OpenBSD ipfilter. */ #define DLT_IPFILTER 116 /* * OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023 * in SuSE 6.3, so we can't use 17 for it in capture-file headers. * * XXX: is there a conflict with DLT_PFSYNC 18 as well? */ #ifdef __OpenBSD__ #define DLT_OLD_PFLOG 17 #define DLT_PFSYNC 18 #endif #define DLT_PFLOG 117 /* * Registered for Cisco-internal use. */ #define DLT_CISCO_IOS 118 /* * For 802.11 cards using the Prism II chips, with a link-layer * header including Prism monitor mode information plus an 802.11 * header. */ #define DLT_PRISM_HEADER 119 /* * Reserved for Aironet 802.11 cards, with an Aironet link-layer header * (see Doug Ambrisko's FreeBSD patches). */ #define DLT_AIRONET_HEADER 120 /* * Reserved for Siemens HiPath HDLC. */ #define DLT_HHDLC 121 /* * This is for RFC 2625 IP-over-Fibre Channel. * * This is not for use with raw Fibre Channel, where the link-layer * header starts with a Fibre Channel frame header; it's for IP-over-FC, * where the link-layer header starts with an RFC 2625 Network_Header * field. */ #define DLT_IP_OVER_FC 122 /* * This is for Full Frontal ATM on Solaris with SunATM, with a * pseudo-header followed by an AALn PDU. * * There may be other forms of Full Frontal ATM on other OSes, * with different pseudo-headers. * * If ATM software returns a pseudo-header with VPI/VCI information * (and, ideally, packet type information, e.g. signalling, ILMI, * LANE, LLC-multiplexed traffic, etc.), it should not use * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump * and the like don't have to infer the presence or absence of a * pseudo-header and the form of the pseudo-header. */ #define DLT_SUNATM 123 /* Solaris+SunATM */ /* * Reserved as per request from Kent Dahlgren * for private use. */ #define DLT_RIO 124 /* RapidIO */ #define DLT_PCI_EXP 125 /* PCI Express */ #define DLT_AURORA 126 /* Xilinx Aurora link layer */ /* * Header for 802.11 plus a number of bits of link-layer information * including radio information, used by some recent BSD drivers as * well as the madwifi Atheros driver for Linux. */ #define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */ /* * Reserved for the TZSP encapsulation, as per request from * Chris Waters * TZSP is a generic encapsulation for any other link type, * which includes a means to include meta-information * with the packet, e.g. signal strength and channel * for 802.11 packets. */ #define DLT_TZSP 128 /* Tazmen Sniffer Protocol */ /* * BSD's ARCNET headers have the source host, destination host, * and type at the beginning of the packet; that's what's handed * up to userland via BPF. * * Linux's ARCNET headers, however, have a 2-byte offset field * between the host IDs and the type; that's what's handed up * to userland via PF_PACKET sockets. * * We therefore have to have separate DLT_ values for them. */ #define DLT_ARCNET_LINUX 129 /* ARCNET */ /* * Juniper-private data link types, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, etc.. */ #define DLT_JUNIPER_MLPPP 130 #define DLT_JUNIPER_MLFR 131 #define DLT_JUNIPER_ES 132 #define DLT_JUNIPER_GGSN 133 #define DLT_JUNIPER_MFR 134 #define DLT_JUNIPER_ATM2 135 #define DLT_JUNIPER_SERVICES 136 #define DLT_JUNIPER_ATM1 137 /* * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund * . The header that's presented is an Ethernet-like * header: * * #define FIREWIRE_EUI64_LEN 8 * struct firewire_header { * u_char firewire_dhost[FIREWIRE_EUI64_LEN]; * u_char firewire_shost[FIREWIRE_EUI64_LEN]; * u_short firewire_type; * }; * * with "firewire_type" being an Ethernet type value, rather than, * for example, raw GASP frames being handed up. */ #define DLT_APPLE_IP_OVER_IEEE1394 138 /* * Various SS7 encapsulations, as per a request from Jeff Morriss * and subsequent discussions. */ #define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */ #define DLT_MTP2 140 /* MTP2, without pseudo-header */ #define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */ #define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */ /* * DOCSIS MAC frames. */ #define DLT_DOCSIS 143 /* * Linux-IrDA packets. Protocol defined at http://www.irda.org. * Those packets include IrLAP headers and above (IrLMP...), but * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy * framing can be handled by the hardware and depend on the bitrate. * This is exactly the format you would get capturing on a Linux-IrDA * interface (irdaX), but not on a raw serial port. * Note the capture is done in "Linux-cooked" mode, so each packet include * a fake packet header (struct sll_header). This is because IrDA packet * decoding is dependant on the direction of the packet (incomming or * outgoing). * When/if other platform implement IrDA capture, we may revisit the * issue and define a real DLT_IRDA... * Jean II */ #define DLT_LINUX_IRDA 144 /* * Reserved for IBM SP switch and IBM Next Federation switch. */ #define DLT_IBM_SP 145 #define DLT_IBM_SN 146 /* * Reserved for private use. If you have some link-layer header type * that you want to use within your organization, with the capture files * using that link-layer header type not ever be sent outside your * organization, you can use these values. * * No libpcap release will use these for any purpose, nor will any * tcpdump release use them, either. * * Do *NOT* use these in capture files that you expect anybody not using * your private versions of capture-file-reading tools to read; in * particular, do *NOT* use them in products, otherwise you may find that * people won't be able to use tcpdump, or snort, or Ethereal, or... to * read capture files from your firewall/intrusion detection/traffic * monitoring/etc. appliance, or whatever product uses that DLT_ value, * and you may also find that the developers of those applications will * not accept patches to let them read those files. * * Also, do not use them if somebody might send you a capture using them * for *their* private type and tools using them for *your* private type * would have to read them. * * Instead, ask "tcpdump-workers@tcpdump.org" for a new DLT_ value, * as per the comment above, and use the type you're given. */ #define DLT_USER0 147 #define DLT_USER1 148 #define DLT_USER2 149 #define DLT_USER3 150 #define DLT_USER4 151 #define DLT_USER5 152 #define DLT_USER6 153 #define DLT_USER7 154 #define DLT_USER8 155 #define DLT_USER9 156 #define DLT_USER10 157 #define DLT_USER11 158 #define DLT_USER12 159 #define DLT_USER13 160 #define DLT_USER14 161 #define DLT_USER15 162 /* * For future use with 802.11 captures - defined by AbsoluteValue * Systems to store a number of bits of link-layer information * including radio information: * * http://www.shaftnet.org/~pizza/software/capturefrm.txt * * but it might be used by some non-AVS drivers now or in the * future. */ #define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */ /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, etc.. */ #define DLT_JUNIPER_MONITOR 164 /* * Reserved for BACnet MS/TP. */ #define DLT_BACNET_MS_TP 165 /* * Another PPP variant as per request from Karsten Keil . * * This is used in some OSes to allow a kernel socket filter to distinguish * between incoming and outgoing packets, on a socket intended to * supply pppd with outgoing packets so it can do dial-on-demand and * hangup-on-lack-of-demand; incoming packets are filtered out so they * don't cause pppd to hold the connection up (you don't want random * input packets such as port scans, packets from old lost connections, * etc. to force the connection to stay up). * * The first byte of the PPP header (0xff03) is modified to accomodate * the direction - 0x00 = IN, 0x01 = OUT. */ #define DLT_PPP_PPPD 166 /* * Names for backwards compatibility with older versions of some PPP * software; new software should use DLT_PPP_PPPD. */ #define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD #define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, cookies, etc.. */ #define DLT_JUNIPER_PPPOE 167 #define DLT_JUNIPER_PPPOE_ATM 168 #define DLT_GPRS_LLC 169 /* GPRS LLC */ #define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */ #define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */ /* * Requested by Oolan Zimmer for use in Gcom's T1/E1 line * monitoring equipment. */ #define DLT_GCOM_T1E1 172 #define DLT_GCOM_SERIAL 173 /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_ is used * for internal communication to Physical Interface Cards (PIC) */ #define DLT_JUNIPER_PIC_PEER 174 /* * Link types requested by Gregor Maier of Endace * Measurement Systems. They add an ERF header (see * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of * the link-layer header. */ #define DLT_ERF_ETH 175 /* Ethernet */ #define DLT_ERF_POS 176 /* Packet-over-SONET */ /* * Requested by Daniele Orlandi for raw LAPD * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header * includes additional information before the LAPD header, so it's * not necessarily a generic LAPD header. */ #define DLT_LINUX_LAPD 177 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ are used for prepending meta-information * like interface index, interface name * before standard Ethernet, PPP, Frelay & C-HDLC Frames */ #define DLT_JUNIPER_ETHER 178 #define DLT_JUNIPER_PPP 179 #define DLT_JUNIPER_FRELAY 180 #define DLT_JUNIPER_CHDLC 181 /* * Multi Link Frame Relay (FRF.16) */ #define DLT_MFR 182 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * voice Adapter Card (PIC) */ #define DLT_JUNIPER_VP 183 /* * Arinc 429 frames. * DLT_ requested by Gianluca Varenni . * Every frame contains a 32bit A429 label. * More documentation on Arinc 429 can be found at * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf */ #define DLT_A429 184 /* * Arinc 653 Interpartition Communication messages. * DLT_ requested by Gianluca Varenni . * Please refer to the A653-1 standard for more information. */ #define DLT_A653_ICM 185 /* * USB packets, beginning with a USB setup header; requested by * Paolo Abeni . */ #define DLT_USB 186 /* * Bluetooth HCI UART transport layer (part H:4); requested by * Paolo Abeni. */ #define DLT_BLUETOOTH_HCI_H4 187 /* * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz * . */ #define DLT_IEEE802_16_MAC_CPS 188 /* * USB packets, beginning with a Linux USB header; requested by * Paolo Abeni . */ #define DLT_USB_LINUX 189 /* * Controller Area Network (CAN) v. 2.0B packets. * DLT_ requested by Gianluca Varenni . * Used to dump CAN packets coming from a CAN Vector board. * More documentation on the CAN v2.0B frames can be found at * http://www.can-cia.org/downloads/?269 */ #define DLT_CAN20B 190 /* * IEEE 802.15.4, with address fields padded, as is done by Linux * drivers; requested by Juergen Schimmer. */ #define DLT_IEEE802_15_4_LINUX 191 /* * Per Packet Information encapsulated packets. * DLT_ requested by Gianluca Varenni . */ #define DLT_PPI 192 /* * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header; * requested by Charles Clancy. */ #define DLT_IEEE802_16_MAC_CPS_RADIO 193 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * integrated service module (ISM). */ #define DLT_JUNIPER_ISM 194 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing); requested by Mikko Saarnivala . */ #define DLT_IEEE802_15_4 195 /* * Various link-layer types, with a pseudo-header, for SITA * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com). */ #define DLT_SITA 196 /* * The instruction encodings. */ /* instruction classes */ #define BPF_CLASS(code) ((code) & 0x07) #define BPF_LD 0x00 #define BPF_LDX 0x01 #define BPF_ST 0x02 #define BPF_STX 0x03 #define BPF_ALU 0x04 #define BPF_JMP 0x05 #define BPF_RET 0x06 #define BPF_MISC 0x07 /* ld/ldx fields */ #define BPF_SIZE(code) ((code) & 0x18) #define BPF_W 0x00 #define BPF_H 0x08 #define BPF_B 0x10 #define BPF_MODE(code) ((code) & 0xe0) #define BPF_IMM 0x00 #define BPF_ABS 0x20 #define BPF_IND 0x40 #define BPF_MEM 0x60 #define BPF_LEN 0x80 #define BPF_MSH 0xa0 /* alu/jmp fields */ #define BPF_OP(code) ((code) & 0xf0) #define BPF_ADD 0x00 #define BPF_SUB 0x10 #define BPF_MUL 0x20 #define BPF_DIV 0x30 #define BPF_OR 0x40 #define BPF_AND 0x50 #define BPF_LSH 0x60 #define BPF_RSH 0x70 #define BPF_NEG 0x80 #define BPF_JA 0x00 #define BPF_JEQ 0x10 #define BPF_JGT 0x20 #define BPF_JGE 0x30 #define BPF_JSET 0x40 #define BPF_SRC(code) ((code) & 0x08) #define BPF_K 0x00 #define BPF_X 0x08 /* ret - BPF_K and BPF_X also apply */ #define BPF_RVAL(code) ((code) & 0x18) #define BPF_A 0x10 /* misc */ #define BPF_MISCOP(code) ((code) & 0xf8) #define BPF_TAX 0x00 #define BPF_TXA 0x80 /* * The instruction data structure. */ struct bpf_insn { u_short code; u_char jt; u_char jf; bpf_int32 k; }; /* * Macros for insn array initializers. */ #define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } #define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } #if __STDC__ || defined(__cplusplus) extern int bpf_validate(struct bpf_insn *, int); extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); #else extern int bpf_validate(); extern u_int bpf_filter(); #endif /* * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). */ #define BPF_MEMWORDS 16 #ifdef __cplusplus } #endif #endif libpcap-0.9.7/./ethertype.h0000644000026300017500000000670510320053200013573 0ustar mcrmcr/* * 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: /tcpdump/master/libpcap/ethertype.h,v 1.13.2.1 2005/09/05 09:08:03 guy Exp $ (LBL) */ /* * Ethernet types. * * We wrap the declarations with #ifdef, so that if a file includes * , which may declare some of these, we don't * get a bunch of complaints from the C compiler about redefinitions * of these values. * * We declare all of them here so that no file has to include * if all it needs are ETHERTYPE_ values. */ #ifndef ETHERTYPE_PUP #define ETHERTYPE_PUP 0x0200 /* PUP protocol */ #endif #ifndef ETHERTYPE_IP #define ETHERTYPE_IP 0x0800 /* IP protocol */ #endif #ifndef ETHERTYPE_ARP #define ETHERTYPE_ARP 0x0806 /* Addr. resolution protocol */ #endif #ifndef ETHERTYPE_REVARP #define ETHERTYPE_REVARP 0x8035 /* reverse Addr. resolution protocol */ #endif #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_8021Q #define ETHERTYPE_8021Q 0x8100 #endif #ifndef ETHERTYPE_IPX #define ETHERTYPE_IPX 0x8137 #endif #ifndef ETHERTYPE_IPV6 #define ETHERTYPE_IPV6 0x86dd #endif #ifndef ETHERTYPE_MPLS #define ETHERTYPE_MPLS 0x8847 #endif #ifndef ETHERTYPE_MPLS_MULTI #define ETHERTYPE_MPLS_MULTI 0x8848 #endif #ifndef ETHERTYPE_PPPOED #define ETHERTYPE_PPPOED 0x8863 #endif #ifndef ETHERTYPE_PPPOES #define ETHERTYPE_PPPOES 0x8864 #endif #ifndef ETHERTYPE_LOOPBACK #define ETHERTYPE_LOOPBACK 0x9000 #endif libpcap-0.9.7/./gencode.c.orig0000644000026300017500000051604210643174160014141 0ustar mcrmcr/*#define CHASE_CHAIN*/ /* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.52 2007/06/22 06:43:58 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #else /* WIN32 */ #include #include #endif /* WIN32 */ /* * XXX - why was this included even on UNIX? */ #ifdef __MINGW32__ #include "IP6_misc.h" #endif #ifndef WIN32 #ifdef __NetBSD__ #include #endif #include #endif /* WIN32 */ #include #include #include #include #include #ifdef MSDOS #include "pcap-dos.h" #endif #include "pcap-int.h" #include "ethertype.h" #include "nlpid.h" #include "llc.h" #include "gencode.h" #include "atmuni31.h" #include "sunatmpos.h" #include "ppp.h" #include "sll.h" #include "arcnet.h" #include "pf.h" #ifndef offsetof #define offsetof(s, e) ((size_t)&((s *)0)->e) #endif #ifdef INET6 #ifndef WIN32 #include /* for "struct addrinfo" */ #endif /* WIN32 */ #endif /*INET6*/ #include #define ETHERMTU 1500 #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #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; #ifdef WIN32 /* Hack for updating VLAN, MPLS, and PPPoE offsets. */ static u_int orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1; #else static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U; #endif /* XXX */ #ifdef PCAP_FDDIPAD static int pcap_fddipad; #endif /* VARARGS */ void bpf_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (bpf_pcap != NULL) (void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE, fmt, ap); va_end(ap); longjmp(top_ctx, 1); /* NOTREACHED */ } static void init_linktype(pcap_t *); static int alloc_reg(void); static void free_reg(int); static struct block *root; /* * Value passed to gen_load_a() to indicate what the offset argument * is relative to. */ enum e_offrel { OR_PACKET, /* relative to the beginning of the packet */ OR_LINK, /* relative to the link-layer header */ OR_NET, /* relative to the network-layer header */ OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ }; /* * 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 if this ever * goes into a library that would probably not be a good idea. * * XXX - this *is* in a library.... */ #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(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32); static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32, bpf_u_int32); static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *); static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32); static struct slist *gen_load_llrel(u_int, u_int); static struct slist *gen_load_a(enum e_offrel, u_int, u_int); static struct slist *gen_loadx_iphdrlen(void); static struct block *gen_uncond(int); static inline struct block *gen_true(void); static inline struct block *gen_false(void); static struct block *gen_ether_linktype(int); static struct block *gen_linux_sll_linktype(int); static void insert_radiotap_load_llprefixlen(struct block *); static void insert_ppi_load_llprefixlen(struct block *); static void insert_load_llprefixlen(struct block *); static struct slist *gen_llprefixlen(void); static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); static struct block *gen_llc_linktype(int); static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); #ifdef INET6 static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); #endif static struct block *gen_ahostop(const u_char *, int); static struct block *gen_ehostop(const u_char *, int); static struct block *gen_fhostop(const u_char *, int); static struct block *gen_thostop(const u_char *, int); static struct block *gen_wlanhostop(const u_char *, int); static struct block *gen_ipfchostop(const u_char *, int); static struct block *gen_dnhostop(bpf_u_int32, int); static struct block *gen_mpls_linktype(int); static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int); #ifdef INET6 static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int); #endif #ifndef INET6 static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int); #endif static struct block *gen_ipfrag(void); static struct block *gen_portatom(int, bpf_int32); static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32); #ifdef INET6 static struct block *gen_portatom6(int, bpf_int32); static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32); #endif struct block *gen_portop(int, int, int); static struct block *gen_port(int, int, int); struct block *gen_portrangeop(int, int, int, int); static struct block *gen_portrange(int, int, int, int); #ifdef INET6 struct block *gen_portop6(int, int, int); static struct block *gen_port6(int, int, int); struct block *gen_portrangeop6(int, int, int, int); static struct block *gen_portrange6(int, int, int, int); #endif static int lookup_proto(const char *, int); static struct block *gen_protochain(int, int, 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_mac_multicast(int); static struct block *gen_len(int, int); static struct block *gen_ppi_dlt_check(void); static struct block *gen_msg_abbrev(int type); static void * newchunk(n) u_int n; { struct chunk *cp; int k; size_t size; #ifndef __NetBSD__ /* XXX Round up to nearest long. */ n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1); #else /* XXX Round up to structure boundary. */ n = ALIGN(n); #endif 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); if (cp->m == NULL) bpf_error("out of memory"); 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); strlcpy(cp, s, n); 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; int no_optimize; int pcap_compile(pcap_t *p, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) { extern int n_errors; const char * volatile xbuf = buf; int len; no_optimize = 0; n_errors = 0; root = NULL; bpf_pcap = p; if (setjmp(top_ctx)) { lex_cleanup(); freechunks(); return (-1); } netmask = mask; snaplen = pcap_snapshot(p); if (snaplen == 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snaplen of 0 rejects all packets"); return -1; } lex_init(xbuf ? xbuf : ""); init_linktype(p); (void)pcap_parse(); if (n_errors) syntax(); if (root == NULL) root = gen_retblk(snaplen); if (optimize && !no_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; lex_cleanup(); freechunks(); return (0); } /* * entry point for using the compiler with no pcap open * pass in all the stuff that is needed explicitly instead. */ int pcap_compile_nopcap(int snaplen_arg, int linktype_arg, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) { pcap_t *p; int ret; p = pcap_open_dead(linktype_arg, snaplen_arg); if (p == NULL) return (-1); ret = pcap_compile(p, program, buf, optimize, mask); pcap_close(p); return (ret); } /* * Clean up a "struct bpf_program" by freeing all the memory allocated * in it. */ void pcap_freecode(struct bpf_program *program) { program->bf_len = 0; if (program->bf_insns != NULL) { free((char *)program->bf_insns); program->bf_insns = NULL; } } /* * 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; { struct block *ppi_dlt_check; ppi_dlt_check = gen_ppi_dlt_check(); if (ppi_dlt_check != NULL) { gen_and(ppi_dlt_check, p); } backpatch(p, gen_retblk(snaplen)); p->sense = !p->sense; backpatch(p, gen_retblk(0)); root = p->head; /* * Insert before the statements of the first (root) block any * statements needed to load the lengths of any variable-length * headers into registers. * * XXX - a fancier strategy would be to insert those before the * statements of all blocks that use those lengths and that * have no predecessors that use them, so that we only compute * the lengths if we need them. There might be even better * approaches than that. However, as we're currently only * handling variable-length radiotap headers, and as all * filtering expressions other than raw link[M:N] tests * require the length of that header, doing more for that * header length isn't really worth the effort. */ insert_load_llprefixlen(root); } 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(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v); } static struct block * gen_cmp_gt(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v); } static struct block * gen_cmp_ge(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v); } static struct block * gen_cmp_lt(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v); } static struct block * gen_cmp_le(offrel, offset, size, v) enum e_offrel offrel; u_int offset, size; bpf_int32 v; { return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v); } static struct block * gen_mcmp(offrel, offset, size, v, mask) enum e_offrel offrel; u_int offset, size; bpf_int32 v; bpf_u_int32 mask; { return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v); } static struct block * gen_bcmp(offrel, offset, size, v) enum e_offrel offrel; 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(offrel, 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(offrel, offset + size - 2, BPF_H, w); if (b != NULL) gen_and(b, tmp); b = tmp; size -= 2; } if (size > 0) { tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]); if (b != NULL) gen_and(b, tmp); b = tmp; } return b; } /* * AND the field of size "size" at offset "offset" relative to the header * specified by "offrel" with "mask", and compare it with the value "v" * with the test specified by "jtype"; if "reverse" is true, the test * should test the opposite of "jtype". */ static struct block * gen_ncmp(offrel, offset, size, mask, jtype, reverse, v) enum e_offrel offrel; bpf_int32 v; bpf_u_int32 offset, size, mask, jtype; int reverse; { struct slist *s, *s2; struct block *b; s = gen_load_a(offrel, offset, size); if (mask != 0xffffffff) { s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); s2->s.k = mask; sappend(s, s2); } b = new_block(JMP(jtype)); b->stmts = s; b->s.k = v; if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE)) gen_not(b); return b; } /* * Various code constructs need to know the layout of the data link * layer. These variables give the necessary offsets from the beginning * of the packet data. * * If the link layer has variable_length headers, the offsets are offsets * from the end of the link-link-layer header, and "reg_ll_size" is * the register number for a register containing the length of the * link-layer header. Otherwise, "reg_ll_size" is -1. */ static int reg_ll_size; /* * This is the offset of the beginning of the link-layer header from * the beginning of the raw packet data. * * It's usually 0, except for 802.11 with a fixed-length radio header. * (For 802.11 with a variable-length radio header, we have to generate * code to compute that offset; off_ll is 0 in that case.) */ static u_int off_ll; /* * This is the offset of the beginning of the MAC-layer header. * It's usually 0, except for ATM LANE, where it's the offset, relative * to the beginning of the raw packet data, of the Ethernet header. */ static u_int off_mac; /* * "off_linktype" is the offset to information in the link-layer header * giving the packet type. This offset is relative to the beginning * of the link-layer header (i.e., it doesn't include off_ll). * * For Ethernet, it's the offset of the Ethernet type field. * * For link-layer types that always use 802.2 headers, it's the * offset of the LLC header. * * For PPP, it's the offset of the PPP type field. * * For Cisco HDLC, it's the offset of the CHDLC type field. * * For BSD loopback, it's the offset of the AF_ value. * * For Linux cooked sockets, it's the offset of the type field. * * It's set to -1 for no encapsulation, in which case, IP is assumed. */ static u_int off_linktype; /* * TRUE if the link layer includes an ATM pseudo-header. */ static int is_atm = 0; /* * TRUE if "lane" appeared in the filter; it causes us to generate * code that assumes LANE rather than LLC-encapsulated traffic in SunATM. */ static int is_lane = 0; /* * These are offsets for the ATM pseudo-header. */ static u_int off_vpi; static u_int off_vci; static u_int off_proto; /* * These are offsets for the MTP2 fields. */ static u_int off_li; /* * These are offsets for the MTP3 fields. */ static u_int off_sio; static u_int off_opc; static u_int off_dpc; static u_int off_sls; /* * This is the offset of the first byte after the ATM pseudo_header, * or -1 if there is no ATM pseudo-header. */ static u_int off_payload; /* * These are offsets to the beginning of the network-layer header. * They are relative to the beginning of the link-layer header (i.e., * they don't include off_ll). * * If the link layer never uses 802.2 LLC: * * "off_nl" and "off_nl_nosnap" are the same. * * If the link layer always uses 802.2 LLC: * * "off_nl" is the offset if there's a SNAP header following * the 802.2 header; * * "off_nl_nosnap" is the offset if there's no SNAP header. * * If the link layer is Ethernet: * * "off_nl" is the offset if the packet is an Ethernet II packet * (we assume no 802.3+802.2+SNAP); * * "off_nl_nosnap" is the offset if the packet is an 802.3 packet * with an 802.2 header following it. */ static u_int off_nl; static u_int off_nl_nosnap; static int linktype; static void init_linktype(p) pcap_t *p; { linktype = pcap_datalink(p); #ifdef PCAP_FDDIPAD pcap_fddipad = p->fddipad; #endif /* * Assume it's not raw ATM with a pseudo-header, for now. */ off_mac = 0; is_atm = 0; is_lane = 0; off_vpi = -1; off_vci = -1; off_proto = -1; off_payload = -1; /* * And assume we're not doing SS7. */ off_li = -1; off_sio = -1; off_opc = -1; off_dpc = -1; off_sls = -1; /* * Also assume it's not 802.11 with a fixed-length radio header. */ off_ll = 0; orig_linktype = -1; orig_nl = -1; label_stack_depth = 0; reg_ll_size = -1; switch (linktype) { case DLT_ARCNET: off_linktype = 2; off_nl = 6; /* XXX in reality, variable! */ off_nl_nosnap = 6; /* no 802.2 LLC */ return; case DLT_ARCNET_LINUX: off_linktype = 4; off_nl = 8; /* XXX in reality, variable! */ off_nl_nosnap = 8; /* no 802.2 LLC */ return; case DLT_EN10MB: off_linktype = 12; off_nl = 14; /* Ethernet II */ off_nl_nosnap = 17; /* 802.3+802.2 */ 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; off_nl_nosnap = 16; /* no 802.2 LLC */ 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; off_nl_nosnap = 24; /* no 802.2 LLC */ return; case DLT_NULL: case DLT_LOOP: off_linktype = 0; off_nl = 4; off_nl_nosnap = 4; /* no 802.2 LLC */ return; case DLT_ENC: off_linktype = 0; off_nl = 12; off_nl_nosnap = 12; /* no 802.2 LLC */ return; case DLT_PPP: case DLT_PPP_PPPD: case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ off_linktype = 2; off_nl = 4; off_nl_nosnap = 4; /* no 802.2 LLC */ return; case DLT_PPP_ETHER: /* * This does no include the Ethernet header, and * only covers session state. */ off_linktype = 6; off_nl = 8; off_nl_nosnap = 8; /* no 802.2 LLC */ return; case DLT_PPP_BSDOS: off_linktype = 5; off_nl = 24; off_nl_nosnap = 24; /* no 802.2 LLC */ return; case DLT_FDDI: /* * FDDI doesn't really have a link-level type field. * We set "off_linktype" to the offset of the LLC header. * * To check for Ethernet types, we assume that SSAP = SNAP * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? */ off_linktype = 13; #ifdef PCAP_FDDIPAD off_linktype += pcap_fddipad; #endif off_nl = 21; /* FDDI+802.2+SNAP */ off_nl_nosnap = 16; /* FDDI+802.2 */ #ifdef PCAP_FDDIPAD off_nl += pcap_fddipad; off_nl_nosnap += pcap_fddipad; #endif return; case DLT_IEEE802: /* * Token Ring doesn't really have a link-level type field. * We set "off_linktype" to the offset of the LLC header. * * To check for Ethernet types, we assume that SSAP = SNAP * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? * * XXX - the header is actually variable-length. * Some various Linux patched versions gave 38 * as "off_linktype" and 40 as "off_nl"; however, * if a token ring packet has *no* routing * information, i.e. is not source-routed, the correct * values are 20 and 22, as they are in the vanilla code. * * A packet is source-routed iff the uppermost bit * of the first byte of the source address, at an * offset of 8, has the uppermost bit set. If the * packet is source-routed, the total number of bytes * of routing information is 2 plus bits 0x1F00 of * the 16-bit value at an offset of 14 (shifted right * 8 - figure out which byte that is). */ off_linktype = 14; off_nl = 22; /* Token Ring+802.2+SNAP */ off_nl_nosnap = 17; /* Token Ring+802.2 */ return; case DLT_IEEE802_11: /* * 802.11 doesn't really have a link-level type field. * We set "off_linktype" to the offset of the LLC header. * * To check for Ethernet types, we assume that SSAP = SNAP * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? * * XXX - the header is actually variable-length. We * assume a 24-byte link-layer header, as appears in * data frames in networks with no bridges. If the * fromds and tods 802.11 header bits are both set, * it's actually supposed to be 30 bytes. */ off_linktype = 24; off_nl = 32; /* 802.11+802.2+SNAP */ off_nl_nosnap = 27; /* 802.11+802.2 */ return; case DLT_PRISM_HEADER: /* * Same as 802.11, but with an additional header before * the 802.11 header, containing a bunch of additional * information including radio-level information. * * The header is 144 bytes long. * * XXX - same variable-length header problem; at least * the Prism header is fixed-length. */ off_ll = 144; off_linktype = 24; off_nl = 32; /* Prism+802.11+802.2+SNAP */ off_nl_nosnap = 27; /* Prism+802.11+802.2 */ return; case DLT_IEEE802_11_RADIO_AVS: /* * Same as 802.11, but with an additional header before * the 802.11 header, containing a bunch of additional * information including radio-level information. * * The header is 64 bytes long, at least in its * current incarnation. * * XXX - same variable-length header problem, only * more so; this header is also variable-length, * with the length being the 32-bit big-endian * number at an offset of 4 from the beginning * of the radio header. We should handle that the * same way we handle the length at the beginning * of the radiotap header. * * XXX - in Linux, do any drivers that supply an AVS * header supply a link-layer type other than * ARPHRD_IEEE80211_PRISM? If so, we should map that * to DLT_IEEE802_11_RADIO_AVS; if not, or if there are * any drivers that supply an AVS header but supply * an ARPHRD value of ARPHRD_IEEE80211_PRISM, we'll * have to check the header in the generated code to * determine whether it's Prism or AVS. */ off_ll = 64; off_linktype = 24; off_nl = 32; /* Radio+802.11+802.2+SNAP */ off_nl_nosnap = 27; /* Radio+802.11+802.2 */ return; /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ case DLT_PPI: case DLT_IEEE802_11_RADIO: /* * Same as 802.11, but with an additional header before * the 802.11 header, containing a bunch of additional * information including radio-level information. * * The radiotap header is variable length, and we * generate code to compute its length and store it * in a register. These offsets are relative to the * beginning of the 802.11 header. */ off_linktype = 24; off_nl = 32; /* 802.11+802.2+SNAP */ off_nl_nosnap = 27; /* 802.11+802.2 */ return; case DLT_ATM_RFC1483: case DLT_ATM_CLIP: /* Linux ATM defines this */ /* * assume routed, non-ISO PDUs * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00) * * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS, * or PPP with the PPP NLPID (e.g., PPPoA)? The * latter would presumably be treated the way PPPoE * should be, so you can do "pppoe and udp port 2049" * or "pppoa and tcp port 80" and have it check for * PPPo{A,E} and a PPP protocol of IP and.... */ off_linktype = 0; off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; case DLT_SUNATM: /* * Full Frontal ATM; you get AALn PDUs with an ATM * pseudo-header. */ is_atm = 1; off_vpi = SUNATM_VPI_POS; off_vci = SUNATM_VCI_POS; off_proto = PROTO_POS; off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */ off_payload = SUNATM_PKT_BEGIN_POS; off_linktype = off_payload; off_nl = off_payload+8; /* 802.2+SNAP */ off_nl_nosnap = off_payload+3; /* 802.2 */ return; case DLT_RAW: off_linktype = -1; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_LINUX_SLL: /* fake header for Linux cooked socket */ off_linktype = 14; off_nl = 16; off_nl_nosnap = 16; /* no 802.2 LLC */ return; case DLT_LTALK: /* * LocalTalk does have a 1-byte type field in the LLAP header, * but really it just indicates whether there is a "short" or * "long" DDP packet following. */ off_linktype = -1; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_IP_OVER_FC: /* * RFC 2625 IP-over-Fibre-Channel doesn't really have a * link-level type field. We set "off_linktype" to the * offset of the LLC header. * * To check for Ethernet types, we assume that SSAP = SNAP * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? RFC * 2625 says SNAP should be used. */ off_linktype = 16; off_nl = 24; /* IPFC+802.2+SNAP */ off_nl_nosnap = 19; /* IPFC+802.2 */ return; case DLT_FRELAY: /* * XXX - we should set this to handle SNAP-encapsulated * frames (NLPID of 0x80). */ off_linktype = -1; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; /* * the only BPF-interesting FRF.16 frames are non-control frames; * Frame Relay has a variable length link-layer * so lets start with offset 4 for now and increments later on (FIXME); */ case DLT_MFR: off_linktype = -1; off_nl = 4; off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */ return; case DLT_APPLE_IP_OVER_IEEE1394: off_linktype = 16; off_nl = 18; off_nl_nosnap = 18; /* no 802.2 LLC */ return; case DLT_LINUX_IRDA: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_DOCSIS: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_SYMANTEC_FIREWALL: off_linktype = 6; off_nl = 44; /* Ethernet II */ off_nl_nosnap = 44; /* XXX - what does it do with 802.3 packets? */ return; case DLT_PFLOG: off_linktype = 0; /* XXX read this from pf.h? */ off_nl = PFLOG_HDRLEN; off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */ return; case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_PPP: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_FRELAY: off_linktype = 4; off_nl = 4; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_ATM1: off_linktype = 4; /* in reality variable between 4-8 */ off_nl = 4; off_nl_nosnap = 14; return; case DLT_JUNIPER_ATM2: off_linktype = 8; /* in reality variable between 8-12 */ off_nl = 8; off_nl_nosnap = 18; return; /* frames captured on a Juniper PPPoE service PIC * contain raw ethernet frames */ case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_ETHER: off_linktype = 16; off_nl = 18; /* Ethernet II */ off_nl_nosnap = 21; /* 802.3+802.2 */ return; case DLT_JUNIPER_PPPOE_ATM: off_linktype = 4; off_nl = 6; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_GGSN: off_linktype = 6; off_nl = 12; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_ES: off_linktype = 6; off_nl = -1; /* not really a network layer but raw IP adresses */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_MONITOR: off_linktype = 12; off_nl = 12; /* raw IP/IP6 header */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_SERVICES: off_linktype = 12; off_nl = -1; /* L3 proto location dep. on cookie type */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_VP: off_linktype = 18; off_nl = -1; off_nl_nosnap = -1; return; case DLT_MTP2: off_li = 2; off_sio = 3; off_opc = 4; off_dpc = 4; off_sls = 7; off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_MTP2_WITH_PHDR: off_li = 6; off_sio = 7; off_opc = 8; off_dpc = 8; off_sls = 11; off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; #ifdef DLT_PFSYNC case DLT_PFSYNC: off_linktype = -1; off_nl = 4; off_nl_nosnap = 4; return; #endif case DLT_LINUX_LAPD: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_USB: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; case DLT_BLUETOOTH_HCI_H4: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ } /* * Load a value relative to the beginning of the link-layer header. * The link-layer header doesn't necessarily begin at the beginning * of the packet data; there might be a variable-length prefix containing * radio information. */ static struct slist * gen_load_llrel(offset, size) u_int offset, size; { struct slist *s, *s2; s = gen_llprefixlen(); /* * If "s" is non-null, it has code to arrange that the X register * contains the length of the prefix preceding the link-layer * header. * * Otherwise, the length of the prefix preceding the link-layer * header is "off_ll". */ if (s != NULL) { /* * There's a variable-length prefix preceding the * link-layer header. "s" points to a list of statements * that put the length of that prefix into the X register. * do an indirect load, to use the X register as an offset. */ s2 = new_stmt(BPF_LD|BPF_IND|size); s2->s.k = offset; sappend(s, s2); } else { /* * There is no variable-length header preceding the * link-layer header; add in off_ll, which, if there's * a fixed-length header preceding the link-layer header, * is the length of that header. */ s = new_stmt(BPF_LD|BPF_ABS|size); s->s.k = offset + off_ll; } return s; } /* * Load a value relative to the beginning of the specified header. */ static struct slist * gen_load_a(offrel, offset, size) enum e_offrel offrel; u_int offset, size; { struct slist *s, *s2; switch (offrel) { case OR_PACKET: s = new_stmt(BPF_LD|BPF_ABS|size); s->s.k = offset; break; case OR_LINK: s = gen_load_llrel(offset, size); break; case OR_NET: s = gen_load_llrel(off_nl + offset, size); break; case OR_NET_NOSNAP: s = gen_load_llrel(off_nl_nosnap + offset, size); break; case OR_TRAN_IPV4: /* * Load the X register with the length of the IPv4 header * (plus the offset of the link-layer header, if it's * preceded by a variable-length header such as a radio * header), in bytes. */ s = gen_loadx_iphdrlen(); /* * Load the item at {offset of the link-layer header} + * {offset, relative to the start of the link-layer * header, of the IPv4 header} + {length of the IPv4 header} + * {specified offset}. * * (If the link-layer is variable-length, it's included * in the value in the X register, and off_ll is 0.) */ s2 = new_stmt(BPF_LD|BPF_IND|size); s2->s.k = off_ll + off_nl + offset; sappend(s, s2); break; case OR_TRAN_IPV6: s = gen_load_llrel(off_nl + 40 + offset, size); break; default: abort(); return NULL; } return s; } /* * Generate code to load into the X register the sum of the length of * the IPv4 header and any variable-length header preceding the link-layer * header. */ static struct slist * gen_loadx_iphdrlen() { struct slist *s, *s2; s = gen_llprefixlen(); if (s != NULL) { /* * There's a variable-length prefix preceding the * link-layer header. "s" points to a list of statements * that put the length of that prefix into the X register. * The 4*([k]&0xf) addressing mode can't be used, as we * don't have a constant offset, so we have to load the * value in question into the A register and add to it * the value from the X register. */ s2 = new_stmt(BPF_LD|BPF_IND|BPF_B); s2->s.k = off_nl; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); s2->s.k = 0xf; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); s2->s.k = 2; sappend(s, s2); /* * The A register now contains the length of the * IP header. We need to add to it the length * of the prefix preceding the link-layer * header, which is still in the X register, and * move the result into the X register. */ sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else { /* * There is no variable-length header preceding the * link-layer header; add in off_ll, which, if there's * a fixed-length header preceding the link-layer header, * is the length of that header. */ s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s->s.k = off_ll + off_nl; } return s; } 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); } /* * Byte-swap a 32-bit number. * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on * big-endian platforms.) */ #define SWAPLONG(y) \ ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) /* * Generate code to match a particular packet type. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the type/length field or to check the type/length field for * a value <= ETHERMTU to see whether it's a type field and then do * the appropriate test. */ static struct block * gen_ether_linktype(proto) register int proto; { struct block *b0, *b1; switch (proto) { case LLCSAP_ISONS: case LLCSAP_IP: case LLCSAP_NETBEUI: /* * OSI protocols and NetBEUI always use 802.2 encapsulation, * so we check the DSAP and SSAP. * * LLCSAP_IP checks for IP-over-802.2, rather * than IP-over-Ethernet or IP-over-SNAP. * * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32) ((proto << 8) | proto)); gen_and(b0, b1); return b1; case LLCSAP_IPX: /* * Check for; * * Ethernet_II frames, which are Ethernet * frames with a frame type of ETHERTYPE_IPX; * * Ethernet_802.3 frames, which are 802.3 * frames (i.e., the type/length field is * a length field, <= ETHERMTU, rather than * a type field) with the first two bytes * after the Ethernet/802.3 header being * 0xFFFF; * * Ethernet_802.2 frames, which are 802.3 * frames with an 802.2 LLC header and * with the IPX LSAP as the DSAP in the LLC * header; * * Ethernet_SNAP frames, which are 802.3 * frames with an LLC header and a SNAP * header and with an OUI of 0x000000 * (encapsulated Ethernet) and a protocol * ID of ETHERTYPE_IPX in the SNAP header. * * XXX - should we generate the same code both * for tests for LLCSAP_IPX and for ETHERTYPE_IPX? */ /* * This generates code to check both for the * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3. */ b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32)0xFFFF); gen_or(b0, b1); /* * Now we add code to check for SNAP frames with * ETHERTYPE_IPX, i.e. Ethernet_SNAP. */ b0 = gen_snap(0x000000, ETHERTYPE_IPX, 14); gen_or(b0, b1); /* * Now we generate code to check for 802.3 * frames in general. */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); /* * Now add the check for 802.3 frames before the * check for Ethernet_802.2 and Ethernet_802.3, * as those checks should only be done on 802.3 * frames, not on Ethernet frames. */ gen_and(b0, b1); /* * Now add the check for Ethernet_II frames, and * do that before checking for the other frame * types. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)ETHERTYPE_IPX); gen_or(b0, b1); return b1; case ETHERTYPE_ATALK: case ETHERTYPE_AARP: /* * EtherTalk (AppleTalk protocols on Ethernet link * layer) may use 802.2 encapsulation. */ /* * Check for 802.2 encapsulation (EtherTalk phase 2?); * we check for an Ethernet type field less than * 1500, which means it's an 802.3 length field. */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); /* * 802.2-encapsulated ETHERTYPE_ATALK packets are * SNAP packets with an organization code of * 0x080007 (Apple, for Appletalk) and a protocol * type of ETHERTYPE_ATALK (Appletalk). * * 802.2-encapsulated ETHERTYPE_AARP packets are * SNAP packets with an organization code of * 0x000000 (encapsulated Ethernet) and a protocol * type of ETHERTYPE_AARP (Appletalk ARP). */ if (proto == ETHERTYPE_ATALK) b1 = gen_snap(0x080007, ETHERTYPE_ATALK, 14); else /* proto == ETHERTYPE_AARP */ b1 = gen_snap(0x000000, ETHERTYPE_AARP, 14); gen_and(b0, b1); /* * Check for Ethernet encapsulation (Ethertalk * phase 1?); we just check for the Ethernet * protocol type. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); gen_or(b0, b1); return b1; default: if (proto <= ETHERMTU) { /* * This is an LLC SAP value, so the frames * that match would be 802.2 frames. * Check that the frame is an 802.2 frame * (i.e., that the length/type field is * a length field, <= ETHERMTU) and * then check the DSAP. */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)proto); gen_and(b0, b1); return b1; } else { /* * This is an Ethernet type, so compare * the length/type field with it (if * the frame is an 802.2 frame, the length * field will be <= ETHERMTU, and, as * "proto" is > ETHERMTU, this test * will fail and the frame won't match, * which is what we want). */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } } } /* * Generate code to match a particular packet type. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the type field or to check the type field for the special * LINUX_SLL_P_802_2 value and then do the appropriate test. */ static struct block * gen_linux_sll_linktype(proto) register int proto; { struct block *b0, *b1; switch (proto) { case LLCSAP_ISONS: case LLCSAP_IP: case LLCSAP_NETBEUI: /* * OSI protocols and NetBEUI always use 802.2 encapsulation, * so we check the DSAP and SSAP. * * LLCSAP_IP checks for IP-over-802.2, rather * than IP-over-Ethernet or IP-over-SNAP. * * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32) ((proto << 8) | proto)); gen_and(b0, b1); return b1; case LLCSAP_IPX: /* * Ethernet_II frames, which are Ethernet * frames with a frame type of ETHERTYPE_IPX; * * Ethernet_802.3 frames, which have a frame * type of LINUX_SLL_P_802_3; * * Ethernet_802.2 frames, which are 802.3 * frames with an 802.2 LLC header (i.e, have * a frame type of LINUX_SLL_P_802_2) and * with the IPX LSAP as the DSAP in the LLC * header; * * Ethernet_SNAP frames, which are 802.3 * frames with an LLC header and a SNAP * header and with an OUI of 0x000000 * (encapsulated Ethernet) and a protocol * ID of ETHERTYPE_IPX in the SNAP header. * * First, do the checks on LINUX_SLL_P_802_2 * frames; generate the check for either * Ethernet_802.2 or Ethernet_SNAP frames, and * then put a check for LINUX_SLL_P_802_2 frames * before it. */ b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX); b1 = gen_snap(0x000000, ETHERTYPE_IPX, off_linktype + 2); gen_or(b0, b1); b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); gen_and(b0, b1); /* * Now check for 802.3 frames and OR that with * the previous test. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3); gen_or(b0, b1); /* * Now add the check for Ethernet_II frames, and * do that before checking for the other frame * types. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)ETHERTYPE_IPX); gen_or(b0, b1); return b1; case ETHERTYPE_ATALK: case ETHERTYPE_AARP: /* * EtherTalk (AppleTalk protocols on Ethernet link * layer) may use 802.2 encapsulation. */ /* * Check for 802.2 encapsulation (EtherTalk phase 2?); * we check for the 802.2 protocol type in the * "Ethernet type" field. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); /* * 802.2-encapsulated ETHERTYPE_ATALK packets are * SNAP packets with an organization code of * 0x080007 (Apple, for Appletalk) and a protocol * type of ETHERTYPE_ATALK (Appletalk). * * 802.2-encapsulated ETHERTYPE_AARP packets are * SNAP packets with an organization code of * 0x000000 (encapsulated Ethernet) and a protocol * type of ETHERTYPE_AARP (Appletalk ARP). */ if (proto == ETHERTYPE_ATALK) b1 = gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype + 2); else /* proto == ETHERTYPE_AARP */ b1 = gen_snap(0x000000, ETHERTYPE_AARP, off_linktype + 2); gen_and(b0, b1); /* * Check for Ethernet encapsulation (Ethertalk * phase 1?); we just check for the Ethernet * protocol type. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); gen_or(b0, b1); return b1; default: if (proto <= ETHERMTU) { /* * This is an LLC SAP value, so the frames * that match would be 802.2 frames. * Check for the 802.2 protocol type * in the "Ethernet type" field, and * then check the DSAP. */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)proto); gen_and(b0, b1); return b1; } else { /* * This is an Ethernet type, so compare * the length/type field with it (if * the frame is an 802.2 frame, the length * field will be <= ETHERMTU, and, as * "proto" is > ETHERMTU, this test * will fail and the frame won't match, * which is what we want). */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } } } static void insert_radiotap_load_llprefixlen(b) struct block *b; { struct slist *s1, *s2; /* * Prepend to the statements in this block code to load the * length of the radiotap header into the register assigned * to hold that length, if one has been assigned. */ if (reg_ll_size != -1) { /* * The 2 bytes at offsets of 2 and 3 from the beginning * of the radiotap header are the length of the radiotap * header; unfortunately, it's little-endian, so we have * to load it a byte at a time and construct the value. */ /* * Load the high-order byte, at an offset of 3, shift it * left a byte, and put the result in the X register. */ s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS); s1->s.k = 3; s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); sappend(s1, s2); s2->s.k = 8; s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Load the next byte, at an offset of 2, and OR the * value from the X register into it. */ s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS); sappend(s1, s2); s2->s.k = 2; s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X); sappend(s1, s2); /* * Now allocate a register to hold that value and store * it. */ s2 = new_stmt(BPF_ST); s2->s.k = reg_ll_size; sappend(s1, s2); /* * Now move it into the X register. */ s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Now append all the existing statements in this * block to these statements. */ sappend(s1, b->stmts); b->stmts = s1; } } /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ static void insert_ppi_load_llprefixlen(b) struct block *b; { struct slist *s1, *s2; /* * Prepend to the statements in this block code to load the * length of the radiotap header into the register assigned * to hold that length, if one has been assigned. */ if (reg_ll_size != -1) { /* * The 2 bytes at offsets of 2 and 3 from the beginning * of the radiotap header are the length of the radiotap * header; unfortunately, it's little-endian, so we have * to load it a byte at a time and construct the value. */ /* * Load the high-order byte, at an offset of 3, shift it * left a byte, and put the result in the X register. */ s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS); s1->s.k = 3; s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); sappend(s1, s2); s2->s.k = 8; s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Load the next byte, at an offset of 2, and OR the * value from the X register into it. */ s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS); sappend(s1, s2); s2->s.k = 2; s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X); sappend(s1, s2); /* * Now allocate a register to hold that value and store * it. */ s2 = new_stmt(BPF_ST); s2->s.k = reg_ll_size; sappend(s1, s2); /* * Now move it into the X register. */ s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Now append all the existing statements in this * block to these statements. */ sappend(s1, b->stmts); b->stmts = s1; } } static struct block * gen_ppi_dlt_check(void) { struct slist *s_load_dlt; struct block *b; if (linktype == DLT_PPI) { /* Create the statements that check for the DLT */ s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS); s_load_dlt->s.k = 4; b = new_block(JMP(BPF_JEQ)); b->stmts = s_load_dlt; b->s.k = SWAPLONG(DLT_IEEE802_11); } else { b = NULL; } return b; } static void insert_load_llprefixlen(b) struct block *b; { switch (linktype) { /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ case DLT_PPI: insert_ppi_load_llprefixlen(b); break; case DLT_IEEE802_11_RADIO: insert_radiotap_load_llprefixlen(b); break; } } static struct slist * gen_radiotap_llprefixlen(void) { struct slist *s; if (reg_ll_size == -1) { /* * We haven't yet assigned a register for the length * of the radiotap header; allocate one. */ reg_ll_size = alloc_reg(); } /* * Load the register containing the radiotap length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_ll_size; return s; } /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ static struct slist * gen_ppi_llprefixlen(void) { struct slist *s; if (reg_ll_size == -1) { /* * We haven't yet assigned a register for the length * of the radiotap header; allocate one. */ reg_ll_size = alloc_reg(); } /* * Load the register containing the radiotap length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_ll_size; return s; } /* * Generate code to compute the link-layer header length, if necessary, * putting it into the X register, and to return either a pointer to a * "struct slist" for the list of statements in that code, or NULL if * no code is necessary. */ static struct slist * gen_llprefixlen(void) { switch (linktype) { case DLT_PPI: return gen_ppi_llprefixlen(); case DLT_IEEE802_11_RADIO: return gen_radiotap_llprefixlen(); default: return NULL; } } /* * Generate code to match a particular packet type by matching the * link-layer type field or fields in the 802.2 LLC header. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. */ static struct block * gen_linktype(proto) register int proto; { struct block *b0, *b1, *b2; /* are we checking MPLS-encapsulated packets? */ if (label_stack_depth > 0) { switch (proto) { case ETHERTYPE_IP: case PPP_IP: /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IP); case ETHERTYPE_IPV6: case PPP_IPV6: /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IPV6); default: bpf_error("unsupported protocol over mpls"); /* NOTREACHED */ } } switch (linktype) { case DLT_EN10MB: return gen_ether_linktype(proto); /*NOTREACHED*/ break; case DLT_C_HDLC: switch (proto) { case LLCSAP_ISONS: proto = (proto << 8 | LLCSAP_ISONS); /* fall through */ default: return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); /*NOTREACHED*/ break; } break; case DLT_PPI: case DLT_FDDI: case DLT_IEEE802: case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: case DLT_ATM_RFC1483: case DLT_ATM_CLIP: case DLT_IP_OVER_FC: return gen_llc_linktype(proto); /*NOTREACHED*/ break; case DLT_SUNATM: /* * If "is_lane" is set, check for a LANE-encapsulated * version of this protocol, otherwise check for an * LLC-encapsulated version of this protocol. * * We assume LANE means Ethernet, not Token Ring. */ if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b0); /* * Now generate an Ethernet test. */ b1 = gen_ether_linktype(proto); gen_and(b0, b1); return b1; } else { /* * Check for LLC encapsulation and then check the * protocol. */ b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); b1 = gen_llc_linktype(proto); gen_and(b0, b1); return b1; } /*NOTREACHED*/ break; case DLT_LINUX_SLL: return gen_linux_sll_linktype(proto); /*NOTREACHED*/ break; case DLT_SLIP: case DLT_SLIP_BSDOS: case DLT_RAW: /* * These types don't provide any type field; packets * are always IPv4 or IPv6. * * XXX - for IPv4, check for a version number of 4, and, * for IPv6, check for a version number of 6? */ switch (proto) { case ETHERTYPE_IP: /* Check for a version number of 4. */ return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0); #ifdef INET6 case ETHERTYPE_IPV6: /* Check for a version number of 6. */ return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0); #endif default: return gen_false(); /* always false */ } /*NOTREACHED*/ break; case DLT_PPP: case DLT_PPP_PPPD: case DLT_PPP_SERIAL: case DLT_PPP_ETHER: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ switch (proto) { case ETHERTYPE_IP: proto = PPP_IP; break; #ifdef INET6 case ETHERTYPE_IPV6: proto = PPP_IPV6; break; #endif case ETHERTYPE_DN: proto = PPP_DECNET; break; case ETHERTYPE_ATALK: proto = PPP_APPLE; break; case ETHERTYPE_NS: proto = PPP_NS; break; case LLCSAP_ISONS: proto = PPP_OSI; break; case LLCSAP_8021D: /* * I'm assuming the "Bridging PDU"s that go * over PPP are Spanning Tree Protocol * Bridging PDUs. */ proto = PPP_BRPDU; break; case LLCSAP_IPX: proto = PPP_IPX; break; } break; case DLT_PPP_BSDOS: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ switch (proto) { case ETHERTYPE_IP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC); gen_or(b0, b1); b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC); gen_or(b1, b0); return b0; #ifdef INET6 case ETHERTYPE_IPV6: proto = PPP_IPV6; /* more to go? */ break; #endif case ETHERTYPE_DN: proto = PPP_DECNET; break; case ETHERTYPE_ATALK: proto = PPP_APPLE; break; case ETHERTYPE_NS: proto = PPP_NS; break; case LLCSAP_ISONS: proto = PPP_OSI; break; case LLCSAP_8021D: /* * I'm assuming the "Bridging PDU"s that go * over PPP are Spanning Tree Protocol * Bridging PDUs. */ proto = PPP_BRPDU; break; case LLCSAP_IPX: proto = PPP_IPX; break; } break; case DLT_NULL: case DLT_LOOP: case DLT_ENC: /* * For DLT_NULL, the link-layer header is a 32-bit * word containing an AF_ value in *host* byte order, * and for DLT_ENC, the link-layer header begins * with a 32-bit work containing an AF_ value in * host byte order. * * In addition, if we're reading a saved capture file, * the host byte order in the capture may not be the * same as the host byte order on this machine. * * For DLT_LOOP, the link-layer header is a 32-bit * word containing an AF_ value in *network* byte order. * * XXX - AF_ values may, unfortunately, be platform- * dependent; for example, FreeBSD's AF_INET6 is 24 * whilst NetBSD's and OpenBSD's is 26. * * This means that, when reading a capture file, just * checking for our AF_INET6 value won't work if the * capture file came from another OS. */ switch (proto) { case ETHERTYPE_IP: proto = AF_INET; break; #ifdef INET6 case ETHERTYPE_IPV6: proto = AF_INET6; break; #endif default: /* * Not a type on which we support filtering. * XXX - support those that have AF_ values * #defined on this platform, at least? */ return gen_false(); } if (linktype == DLT_NULL || linktype == DLT_ENC) { /* * The AF_ value is in host byte order, but * the BPF interpreter will convert it to * network byte order. * * If this is a save file, and it's from a * machine with the opposite byte order to * ours, we byte-swap the AF_ value. * * Then we run it through "htonl()", and * generate code to compare against the result. */ if (bpf_pcap->sf.rfile != NULL && bpf_pcap->sf.swapped) proto = SWAPLONG(proto); proto = htonl(proto); } return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto)); case DLT_PFLOG: /* * af field is host byte order in contrast to the rest of * the packet. */ if (proto == ETHERTYPE_IP) return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET)); #ifdef INET6 else if (proto == ETHERTYPE_IPV6) return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET6)); #endif /* INET6 */ else return gen_false(); /*NOTREACHED*/ break; case DLT_ARCNET: case DLT_ARCNET_LINUX: /* * XXX should we check for first fragment if the protocol * uses PHDS? */ switch (proto) { default: return gen_false(); #ifdef INET6 case ETHERTYPE_IPV6: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_INET6)); #endif /* INET6 */ case ETHERTYPE_IP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_ARP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_REVARP: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_REVARP)); case ETHERTYPE_ATALK: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ATALK)); } /*NOTREACHED*/ break; case DLT_LTALK: switch (proto) { case ETHERTYPE_ATALK: return gen_true(); default: return gen_false(); } /*NOTREACHED*/ break; case DLT_FRELAY: /* * XXX - assumes a 2-byte Frame Relay header with * DLCI and flags. What if the address is longer? */ switch (proto) { case ETHERTYPE_IP: /* * Check for the special NLPID for IP. */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc); #ifdef INET6 case ETHERTYPE_IPV6: /* * Check for the special NLPID for IPv6. */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e); #endif case LLCSAP_ISONS: /* * Check for several OSI protocols. * * Frame Relay packets typically have an OSI * NLPID at the beginning; we check for each * of them. * * What we check for is the NLPID and a frame * control field of UI, i.e. 0x03 followed * by the NLPID. */ b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP); b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS); b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS); gen_or(b1, b2); gen_or(b0, b2); return b2; default: return gen_false(); } /*NOTREACHED*/ break; case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: case DLT_JUNIPER_ATM2: case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_PPPOE_ATM: case DLT_JUNIPER_GGSN: case DLT_JUNIPER_ES: case DLT_JUNIPER_MONITOR: case DLT_JUNIPER_SERVICES: case DLT_JUNIPER_ETHER: case DLT_JUNIPER_PPP: case DLT_JUNIPER_FRELAY: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_VP: /* just lets verify the magic number for now - * on ATM we may have up to 6 different encapsulations on the wire * and need a lot of heuristics to figure out that the payload * might be; * * FIXME encapsulation specific BPF_ filters */ return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ case DLT_LINUX_IRDA: bpf_error("IrDA link-layer type filtering not implemented"); case DLT_DOCSIS: bpf_error("DOCSIS link-layer type filtering not implemented"); case DLT_LINUX_LAPD: bpf_error("LAPD link-layer type filtering not implemented"); } /* * All the types that have no encapsulation should either be * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if * all packets are IP packets, or should be handled in some * special case, if none of them are (if some are and some * aren't, the lack of encapsulation is a problem, as we'd * have to find some other way of determining the packet type). * * Therefore, if "off_linktype" is -1, there's an error. */ if (off_linktype == (u_int)-1) abort(); /* * Any type not handled above should always have an Ethernet * type at an offset of "off_linktype". (PPP is partially * handled above - the protocol type is mapped from the * Ethernet and LLC types we use internally to the corresponding * PPP type - but the PPP type is always specified by a value * at "off_linktype", so we don't have to do the code generation * above.) */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } /* * Check for an LLC SNAP packet with a given organization code and * protocol type; we check the entire contents of the 802.2 LLC and * snap headers, checking for DSAP and SSAP of SNAP and a control * field of 0x03 in the LLC header, and for the specified organization * code and protocol type in the SNAP header. */ static struct block * gen_snap(orgcode, ptype, offset) bpf_u_int32 orgcode; bpf_u_int32 ptype; u_int offset; { u_char snapblock[8]; snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */ snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */ snapblock[2] = 0x03; /* control = UI */ snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */ snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */ snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */ snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */ snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */ return gen_bcmp(OR_LINK, offset, 8, snapblock); } /* * Generate code to match a particular packet type, for link-layer types * using 802.2 LLC headers. * * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the DSAP or both DSAP and LSAP or to check the OUI and * protocol ID in a SNAP header. */ static struct block * gen_llc_linktype(proto) int proto; { /* * XXX - handle token-ring variable-length header. */ switch (proto) { case LLCSAP_IP: case LLCSAP_ISONS: case LLCSAP_NETBEUI: /* * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_u_int32) ((proto << 8) | proto)); case LLCSAP_IPX: /* * XXX - are there ever SNAP frames for IPX on * non-Ethernet 802.x networks? */ return gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)LLCSAP_IPX); case ETHERTYPE_ATALK: /* * 802.2-encapsulated ETHERTYPE_ATALK packets are * SNAP packets with an organization code of * 0x080007 (Apple, for Appletalk) and a protocol * type of ETHERTYPE_ATALK (Appletalk). * * XXX - check for an organization code of * encapsulated Ethernet as well? */ return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype); default: /* * XXX - we don't have to check for IPX 802.3 * here, but should we check for the IPX Ethertype? */ if (proto <= ETHERMTU) { /* * This is an LLC SAP value, so check * the DSAP. */ return gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)proto); } else { /* * This is an Ethernet type; we assume that it's * unlikely that it'll appear in the right place * at random, and therefore check only the * location that would hold the Ethernet type * in a SNAP frame with an organization code of * 0x000000 (encapsulated Ethernet). * * XXX - if we were to check for the SNAP DSAP and * LSAP, as per XXX, and were also to check for an * organization code of 0x000000 (encapsulated * Ethernet), we'd do * * return gen_snap(0x000000, proto, * off_linktype); * * here; for now, we don't, as per the above. * I don't know whether it's worth the extra CPU * time to do the right check or not. */ return gen_cmp(OR_LINK, off_linktype+6, BPF_H, (bpf_int32)proto); } } } 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(OR_NET, offset, BPF_W, (bpf_int32)addr, mask); gen_and(b0, b1); return b1; } #ifdef INET6 static struct block * gen_hostop6(addr, mask, dir, proto, src_off, dst_off) struct in6_addr *addr; struct in6_addr *mask; int dir, proto; u_int src_off, dst_off; { struct block *b0, *b1; u_int offset; u_int32_t *a, *m; switch (dir) { case Q_SRC: offset = src_off; break; case Q_DST: offset = dst_off; break; case Q_AND: b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); gen_and(b0, b1); return b1; case Q_OR: case Q_DEFAULT: b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); gen_or(b0, b1); return b1; default: abort(); } /* this order is important */ a = (u_int32_t *)addr; m = (u_int32_t *)mask; b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); gen_and(b0, b1); b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); gen_and(b0, b1); b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0])); gen_and(b0, b1); b0 = gen_linktype(proto); gen_and(b0, b1); return b1; } #endif /*INET6*/ 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(OR_LINK, off_mac + 6, 6, eaddr); case Q_DST: return gen_bcmp(OR_LINK, off_mac + 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(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr); #else return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr); #endif case Q_DST: #ifdef PCAP_FDDIPAD return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr); #else return gen_bcmp(OR_LINK, 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 */ } /* * Like gen_ehostop, but for DLT_IEEE802 (Token Ring) */ static struct block * gen_thostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1; switch (dir) { case Q_SRC: return gen_bcmp(OR_LINK, 8, 6, eaddr); case Q_DST: return gen_bcmp(OR_LINK, 2, 6, eaddr); case Q_AND: b0 = gen_thostop(eaddr, Q_SRC); b1 = gen_thostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_thostop(eaddr, Q_SRC); b1 = gen_thostop(eaddr, Q_DST); gen_or(b0, b1); return b1; } abort(); /* NOTREACHED */ } /* * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) */ static struct block * gen_wlanhostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1, *b2; register struct slist *s; switch (dir) { case Q_SRC: /* * Oh, yuk. * * For control frames, there is no SA. * * For management frames, SA is at an * offset of 10 from the beginning of * the packet. * * For data frames, SA is at an offset * of 10 from the beginning of the packet * if From DS is clear, at an offset of * 16 from the beginning of the packet * if From DS is set and To DS is clear, * and an offset of 24 from the beginning * of the packet if From DS is set and To DS * is set. */ /* * Generate the tests to be done for data frames * with From DS set. * * First, check for To DS set, i.e. check "link[1] & 0x01". */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; /* * If To DS is set, the SA is at 24. */ b0 = gen_bcmp(OR_LINK, 24, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; gen_not(b2); /* * If To DS is not set, the SA is at 16. */ b1 = gen_bcmp(OR_LINK, 16, 6, eaddr); gen_and(b2, b1); /* * Now OR together the last two checks. That gives * the complete set of checks for data frames with * From DS set. */ gen_or(b1, b0); /* * Now check for From DS being set, and AND that with * the ORed-together checks. */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x02; /* From DS */ b1->stmts = s; gen_and(b1, b0); /* * Now check for data frames with From DS not set. */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x02; /* From DS */ b2->stmts = s; gen_not(b2); /* * If From DS isn't set, the SA is at 10. */ b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); /* * Now OR together the checks for data frames with * From DS not set and for data frames with From DS * set; that gives the checks done for data frames. */ gen_or(b1, b0); /* * Now check for a data frame. * I.e, check "link[0] & 0x08". */ gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the checks done for data frames. */ gen_and(b1, b0); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "!(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; gen_not(b2); /* * For management frames, the SA is at 10. */ b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); gen_and(b2, b1); /* * OR that with the checks done for data frames. * That gives the checks done for management and * data frames. */ gen_or(b1, b0); /* * If the low-order bit of the type value is 1, * this is either a control frame or a frame * with a reserved type, and thus not a * frame with an SA. * * I.e., check "!(link[0] & 0x04)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); /* * AND that with the checks for data and management * frames. */ gen_and(b1, b0); return b0; case Q_DST: /* * Oh, yuk. * * For control frames, there is no DA. * * For management frames, DA is at an * offset of 4 from the beginning of * the packet. * * For data frames, DA is at an offset * of 4 from the beginning of the packet * if To DS is clear and at an offset of * 16 from the beginning of the packet * if To DS is set. */ /* * Generate the tests to be done for data frames. * * First, check for To DS set, i.e. "link[1] & 0x01". */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; /* * If To DS is set, the DA is at 16. */ b0 = gen_bcmp(OR_LINK, 16, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; gen_not(b2); /* * If To DS is not set, the DA is at 4. */ b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); gen_and(b2, b1); /* * Now OR together the last two checks. That gives * the complete set of checks for data frames. */ gen_or(b1, b0); /* * Now check for a data frame. * I.e, check "link[0] & 0x08". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the checks done for data frames. */ gen_and(b1, b0); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "!(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; gen_not(b2); /* * For management frames, the DA is at 4. */ b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); gen_and(b2, b1); /* * OR that with the checks done for data frames. * That gives the checks done for management and * data frames. */ gen_or(b1, b0); /* * If the low-order bit of the type value is 1, * this is either a control frame or a frame * with a reserved type, and thus not a * frame with an SA. * * I.e., check "!(link[0] & 0x04)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); /* * AND that with the checks for data and management * frames. */ gen_and(b1, b0); return b0; case Q_AND: b0 = gen_wlanhostop(eaddr, Q_SRC); b1 = gen_wlanhostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_wlanhostop(eaddr, Q_SRC); b1 = gen_wlanhostop(eaddr, Q_DST); gen_or(b0, b1); return b1; } abort(); /* NOTREACHED */ } /* * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel. * (We assume that the addresses are IEEE 48-bit MAC addresses, * as the RFC states.) */ static struct block * gen_ipfchostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1; switch (dir) { case Q_SRC: return gen_bcmp(OR_LINK, 10, 6, eaddr); case Q_DST: return gen_bcmp(OR_LINK, 2, 6, eaddr); case Q_AND: b0 = gen_ipfchostop(eaddr, Q_SRC); b1 = gen_ipfchostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_ipfchostop(eaddr, Q_SRC); b1 = gen_ipfchostop(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) bpf_u_int32 addr; int dir; { 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); b1 = gen_dnhostop(addr, Q_DST); 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); b1 = gen_dnhostop(addr, Q_DST); gen_or(b0, b1); return b1; case Q_ISO: bpf_error("ISO host filtering not implemented"); default: abort(); } b0 = gen_linktype(ETHERTYPE_DN); /* Check for pad = 1, long header case */ tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF)); b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b1); /* Check for pad = 0, long header case */ tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7); b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 1, short header case */ tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF)); b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 0, short header case */ tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7); b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Combine with test for linktype */ gen_and(b0, b1); return b1; } /* * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets; * test the bottom-of-stack bit, and then check the version number * field in the IP header. */ static struct block * gen_mpls_linktype(proto) int proto; { struct block *b0, *b1; switch (proto) { case Q_IP: /* match the bottom-of-stack bit */ b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01); /* match the IPv4 version number */ b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x40, 0xf0); gen_and(b0, b1); return b1; case Q_IPV6: /* match the bottom-of-stack bit */ b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01); /* match the IPv4 version number */ b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0); gen_and(b0, b1); return b1; default: abort(); } } static struct block * gen_host(addr, mask, proto, dir, type) bpf_u_int32 addr; bpf_u_int32 mask; int proto; int dir; int type; { struct block *b0, *b1; const char *typestr; if (type == Q_NET) typestr = "net"; else typestr = "host"; switch (proto) { case Q_DEFAULT: b0 = gen_host(addr, mask, Q_IP, dir, type); /* * Only check for non-IPv4 addresses if we're not * checking MPLS-encapsulated packets. */ if (label_stack_depth == 0) { b1 = gen_host(addr, mask, Q_ARP, dir, type); gen_or(b0, b1); b0 = gen_host(addr, mask, Q_RARP, dir, type); gen_or(b1, b0); } return b0; case Q_IP: return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16); case Q_RARP: return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24); case Q_ARP: return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24); case Q_TCP: bpf_error("'tcp' modifier applied to %s", typestr); case Q_SCTP: bpf_error("'sctp' modifier applied to %s", typestr); case Q_UDP: bpf_error("'udp' modifier applied to %s", typestr); case Q_ICMP: bpf_error("'icmp' modifier applied to %s", typestr); case Q_IGMP: bpf_error("'igmp' modifier applied to %s", typestr); case Q_IGRP: bpf_error("'igrp' modifier applied to %s", typestr); case Q_PIM: bpf_error("'pim' modifier applied to %s", typestr); case Q_VRRP: bpf_error("'vrrp' modifier applied to %s", typestr); case Q_ATALK: bpf_error("ATALK host filtering not implemented"); case Q_AARP: bpf_error("AARP host filtering not implemented"); case Q_DECNET: return gen_dnhostop(addr, dir); 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"); #ifdef INET6 case Q_IPV6: bpf_error("'ip6' modifier applied to ip host"); case Q_ICMPV6: bpf_error("'icmp6' modifier applied to %s", typestr); #endif /* INET6 */ case Q_AH: bpf_error("'ah' modifier applied to %s", typestr); case Q_ESP: bpf_error("'esp' modifier applied to %s", typestr); case Q_ISO: bpf_error("ISO host filtering not implemented"); case Q_ESIS: bpf_error("'esis' modifier applied to %s", typestr); case Q_ISIS: bpf_error("'isis' modifier applied to %s", typestr); case Q_CLNP: bpf_error("'clnp' modifier applied to %s", typestr); case Q_STP: bpf_error("'stp' modifier applied to %s", typestr); case Q_IPX: bpf_error("IPX host filtering not implemented"); case Q_NETBEUI: bpf_error("'netbeui' modifier applied to %s", typestr); case Q_RADIO: bpf_error("'radio' modifier applied to %s", typestr); default: abort(); } /* NOTREACHED */ } #ifdef INET6 static struct block * gen_host6(addr, mask, proto, dir, type) struct in6_addr *addr; struct in6_addr *mask; int proto; int dir; int type; { const char *typestr; if (type == Q_NET) typestr = "net"; else typestr = "host"; switch (proto) { case Q_DEFAULT: return gen_host6(addr, mask, Q_IPV6, dir, type); case Q_IP: bpf_error("'ip' modifier applied to ip6 %s", typestr); case Q_RARP: bpf_error("'rarp' modifier applied to ip6 %s", typestr); case Q_ARP: bpf_error("'arp' modifier applied to ip6 %s", typestr); case Q_SCTP: bpf_error("'sctp' modifier applied to %s", typestr); case Q_TCP: bpf_error("'tcp' modifier applied to %s", typestr); case Q_UDP: bpf_error("'udp' modifier applied to %s", typestr); case Q_ICMP: bpf_error("'icmp' modifier applied to %s", typestr); case Q_IGMP: bpf_error("'igmp' modifier applied to %s", typestr); case Q_IGRP: bpf_error("'igrp' modifier applied to %s", typestr); case Q_PIM: bpf_error("'pim' modifier applied to %s", typestr); case Q_VRRP: bpf_error("'vrrp' modifier applied to %s", typestr); case Q_ATALK: bpf_error("ATALK host filtering not implemented"); case Q_AARP: bpf_error("AARP host filtering not implemented"); case Q_DECNET: bpf_error("'decnet' modifier applied to ip6 %s", typestr); 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"); case Q_IPV6: return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24); case Q_ICMPV6: bpf_error("'icmp6' modifier applied to %s", typestr); case Q_AH: bpf_error("'ah' modifier applied to %s", typestr); case Q_ESP: bpf_error("'esp' modifier applied to %s", typestr); case Q_ISO: bpf_error("ISO host filtering not implemented"); case Q_ESIS: bpf_error("'esis' modifier applied to %s", typestr); case Q_ISIS: bpf_error("'isis' modifier applied to %s", typestr); case Q_CLNP: bpf_error("'clnp' modifier applied to %s", typestr); case Q_STP: bpf_error("'stp' modifier applied to %s", typestr); case Q_IPX: bpf_error("IPX host filtering not implemented"); case Q_NETBEUI: bpf_error("'netbeui' modifier applied to %s", typestr); case Q_RADIO: bpf_error("'radio' modifier applied to %s", typestr); default: abort(); } /* NOTREACHED */ } #endif /*INET6*/ #ifndef INET6 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: switch (linktype) { case DLT_EN10MB: b0 = gen_ehostop(eaddr, Q_OR); break; case DLT_FDDI: b0 = gen_fhostop(eaddr, Q_OR); break; case DLT_IEEE802: b0 = gen_thostop(eaddr, Q_OR); break; case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_PPI: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: b0 = gen_wlanhostop(eaddr, Q_OR); break; case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b1); /* * Now check the MAC address. */ b0 = gen_ehostop(eaddr, Q_OR); gen_and(b1, b0); } break; case DLT_IP_OVER_FC: b0 = gen_ipfchostop(eaddr, Q_OR); break; default: bpf_error( "'gateway' supported only on ethernet/FDDI/token ring/802.11/Fibre Channel"); } b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST); while (*alist) { tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST); gen_or(b1, tmp); b1 = tmp; } gen_not(b1); gen_and(b0, b1); return b1; } bpf_error("illegal modifier of 'gateway'"); /* NOTREACHED */ } #endif struct block * gen_proto_abbrev(proto) int proto; { struct block *b0; struct block *b1; switch (proto) { case Q_SCTP: b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; case Q_TCP: b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; case Q_UDP: b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; case Q_ICMP: b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_IGMP #define IPPROTO_IGMP 2 #endif case Q_IGMP: b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_IGRP #define IPPROTO_IGRP 9 #endif case Q_IGRP: b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_PIM #define IPPROTO_PIM 103 #endif case Q_PIM: b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; #ifndef IPPROTO_VRRP #define IPPROTO_VRRP 112 #endif case Q_VRRP: b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT); 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_AARP: b1 = gen_linktype(ETHERTYPE_AARP); 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; #ifdef INET6 case Q_IPV6: b1 = gen_linktype(ETHERTYPE_IPV6); break; #ifndef IPPROTO_ICMPV6 #define IPPROTO_ICMPV6 58 #endif case Q_ICMPV6: b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT); break; #endif /* INET6 */ #ifndef IPPROTO_AH #define IPPROTO_AH 51 #endif case Q_AH: b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; #ifndef IPPROTO_ESP #define IPPROTO_ESP 50 #endif case Q_ESP: b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT); #ifdef INET6 b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT); gen_or(b0, b1); #endif break; case Q_ISO: b1 = gen_linktype(LLCSAP_ISONS); break; case Q_ESIS: b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS: b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */ b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_LSP: b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_SNP: b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_CSNP: b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_PSNP: b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_CLNP: b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); break; case Q_STP: b1 = gen_linktype(LLCSAP_8021D); break; case Q_IPX: b1 = gen_linktype(LLCSAP_IPX); break; case Q_NETBEUI: b1 = gen_linktype(LLCSAP_NETBEUI); break; case Q_RADIO: bpf_error("'radio' is not a valid protocol type"); default: abort(); } return b1; } static struct block * gen_ipfrag() { struct slist *s; struct block *b; /* not ip frag */ s = gen_load_a(OR_NET, 6, BPF_H); b = new_block(JMP(BPF_JSET)); b->s.k = 0x1fff; b->stmts = s; gen_not(b); return b; } /* * Generate a comparison to a port value in the transport-layer header * at the specified offset from the beginning of that header. * * XXX - this handles a variable-length prefix preceding the link-layer * header, such as the radiotap or AVS radio prefix, but doesn't handle * variable-length link-layer headers (such as Token Ring or 802.11 * headers). */ static struct block * gen_portatom(off, v) int off; bpf_int32 v; { return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v); } #ifdef INET6 static struct block * gen_portatom6(off, v) int off; bpf_int32 v; { return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v); } #endif/*INET6*/ struct block * gen_portop(port, proto, dir) int port, proto, dir; { struct block *b0, *b1, *tmp; /* ip proto 'proto' */ tmp = gen_cmp(OR_NET, 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 * * For FDDI, RFC 1188 says that SNAP encapsulation is used, * not LLC encapsulation with LLCSAP_IP. * * For IEEE 802 networks - which includes 802.5 token ring * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042 * says that SNAP encapsulation is used, not LLC encapsulation * with LLCSAP_IP. * * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and * RFC 2225 say that SNAP encapsulation is used, not LLC * encapsulation with LLCSAP_IP. * * So we always check for ETHERTYPE_IP. */ b0 = gen_linktype(ETHERTYPE_IP); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: 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); tmp = gen_portop(port, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } #ifdef INET6 struct block * gen_portop6(port, proto, dir) int port, proto, dir; { struct block *b0, *b1, *tmp; /* ip6 proto 'proto' */ b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); switch (dir) { case Q_SRC: b1 = gen_portatom6(0, (bpf_int32)port); break; case Q_DST: b1 = gen_portatom6(2, (bpf_int32)port); break; case Q_OR: case Q_DEFAULT: tmp = gen_portatom6(0, (bpf_int32)port); b1 = gen_portatom6(2, (bpf_int32)port); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portatom6(0, (bpf_int32)port); b1 = gen_portatom6(2, (bpf_int32)port); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_port6(port, ip_proto, dir) int port; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* link proto ip6 */ b0 = gen_linktype(ETHERTYPE_IPV6); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portop6(port, ip_proto, dir); break; case PROTO_UNDEF: tmp = gen_portop6(port, IPPROTO_TCP, dir); b1 = gen_portop6(port, IPPROTO_UDP, dir); gen_or(tmp, b1); tmp = gen_portop6(port, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } #endif /* INET6 */ /* gen_portrange code */ static struct block * gen_portrangeatom(off, v1, v2) int off; bpf_int32 v1, v2; { struct block *b1, *b2; if (v1 > v2) { /* * Reverse the order of the ports, so v1 is the lower one. */ bpf_int32 vtemp; vtemp = v1; v1 = v2; v2 = vtemp; } b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1); b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2); gen_and(b1, b2); return b2; } struct block * gen_portrangeop(port1, port2, proto, dir) int port1, port2; int proto; int dir; { struct block *b0, *b1, *tmp; /* ip proto 'proto' */ tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); b0 = gen_ipfrag(); gen_and(tmp, b0); switch (dir) { case Q_SRC: b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); break; case Q_DST: b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); break; case Q_OR: case Q_DEFAULT: tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_portrange(port1, port2, ip_proto, dir) int port1, port2; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* link proto ip */ b0 = gen_linktype(ETHERTYPE_IP); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portrangeop(port1, port2, ip_proto, dir); break; case PROTO_UNDEF: tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir); b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir); gen_or(tmp, b1); tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } #ifdef INET6 static struct block * gen_portrangeatom6(off, v1, v2) int off; bpf_int32 v1, v2; { struct block *b1, *b2; if (v1 > v2) { /* * Reverse the order of the ports, so v1 is the lower one. */ bpf_int32 vtemp; vtemp = v1; v1 = v2; v2 = vtemp; } b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1); b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2); gen_and(b1, b2); return b2; } struct block * gen_portrangeop6(port1, port2, proto, dir) int port1, port2; int proto; int dir; { struct block *b0, *b1, *tmp; /* ip6 proto 'proto' */ b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); switch (dir) { case Q_SRC: b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); break; case Q_DST: b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); break; case Q_OR: case Q_DEFAULT: tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); gen_or(tmp, b1); break; case Q_AND: tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2); b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2); gen_and(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } static struct block * gen_portrange6(port1, port2, ip_proto, dir) int port1, port2; int ip_proto; int dir; { struct block *b0, *b1, *tmp; /* link proto ip6 */ b0 = gen_linktype(ETHERTYPE_IPV6); switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: b1 = gen_portrangeop6(port1, port2, ip_proto, dir); break; case PROTO_UNDEF: tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir); b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir); gen_or(tmp, b1); tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir); gen_or(tmp, b1); break; default: abort(); } gen_and(b0, b1); return b1; } #endif /* INET6 */ static int lookup_proto(name, proto) register const char *name; register int proto; { register int v; switch (proto) { case Q_DEFAULT: case Q_IP: case Q_IPV6: 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) { v = pcap_nametollc(name); if (v == PROTO_UNDEF) bpf_error("unknown ether proto '%s'", name); } break; case Q_ISO: if (strcmp(name, "esis") == 0) v = ISO9542_ESIS; else if (strcmp(name, "isis") == 0) v = ISO10589_ISIS; else if (strcmp(name, "clnp") == 0) v = ISO8473_CLNP; else bpf_error("unknown osi proto '%s'", name); break; default: v = PROTO_UNDEF; break; } return v; } #if 0 struct stmt * gen_joinsp(s, n) struct stmt **s; int n; { return NULL; } #endif static struct block * gen_protochain(v, proto, dir) int v; int proto; int dir; { #ifdef NO_PROTOCHAIN return gen_proto(v, proto, dir); #else struct block *b0, *b; struct slist *s[100]; int fix2, fix3, fix4, fix5; int ahcheck, again, end; int i, max; int reg2 = alloc_reg(); memset(s, 0, sizeof(s)); fix2 = fix3 = fix4 = fix5 = 0; switch (proto) { case Q_IP: case Q_IPV6: break; case Q_DEFAULT: b0 = gen_protochain(v, Q_IP, dir); b = gen_protochain(v, Q_IPV6, dir); gen_or(b0, b); return b; default: bpf_error("bad protocol applied for 'protochain'"); /*NOTREACHED*/ } /* * We don't handle variable-length radiotap here headers yet. * We might want to add BPF instructions to do the protochain * work, to simplify that and, on platforms that have a BPF * interpreter with the new instructions, let the filtering * be done in the kernel. (We already require a modified BPF * engine to do the protochain stuff, to support backward * branches, and backward branch support is unlikely to appear * in kernel BPF engines.) */ if (linktype == DLT_IEEE802_11_RADIO) bpf_error("'protochain' not supported with radiotap headers"); if (linktype == DLT_PPI) bpf_error("'protochain' not supported with PPI headers"); no_optimize = 1; /*this code is not compatible with optimzer yet */ /* * s[0] is a dummy entry to protect other BPF insn from damage * by s[fix] = foo with uninitialized variable "fix". It is somewhat * hard to find interdependency made by jump table fixup. */ i = 0; s[i] = new_stmt(0); /*dummy*/ i++; switch (proto) { case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); /* A = ip->ip_p */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); s[i]->s.k = off_ll + off_nl + 9; i++; /* X = ip->ip_hl << 2 */ s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s[i]->s.k = off_ll + off_nl; i++; break; #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); /* A = ip6->ip_nxt */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); s[i]->s.k = off_ll + off_nl + 6; i++; /* X = sizeof(struct ip6_hdr) */ s[i] = new_stmt(BPF_LDX|BPF_IMM); s[i]->s.k = 40; i++; break; #endif default: bpf_error("unsupported proto to gen_protochain"); /*NOTREACHED*/ } /* again: if (A == v) goto end; else fall through; */ again = i; s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.k = v; s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ fix5 = i; i++; #ifndef IPPROTO_NONE #define IPPROTO_NONE 59 #endif /* if (A == IPPROTO_NONE) goto end */ s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_NONE; s[fix5]->s.jf = s[i]; fix2 = i; i++; #ifdef INET6 if (proto == Q_IPV6) { int v6start, v6end, v6advance, j; v6start = i; /* if (A == IPPROTO_HOPOPTS) goto v6advance */ s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_HOPOPTS; s[fix2]->s.jf = s[i]; i++; /* if (A == IPPROTO_DSTOPTS) goto v6advance */ s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_DSTOPTS; i++; /* if (A == IPPROTO_ROUTING) goto v6advance */ s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*update in next stmt*/ s[i]->s.k = IPPROTO_ROUTING; i++; /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */ s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*later*/ s[i]->s.k = IPPROTO_FRAGMENT; fix3 = i; v6end = i; i++; /* v6advance: */ v6advance = i; /* * in short, * A = P[X]; * X = X + (P[X + 1] + 1) * 8; */ /* A = X */ s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_ll + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); s[i]->s.k = reg2; i++; /* A = X */ s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 1; i++; /* X = A */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = P[X + packet head]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_ll + off_nl; i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 1; i++; /* A *= 8 */ s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); s[i]->s.k = 8; i++; /* X = A; */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = MEM[reg2] */ s[i] = new_stmt(BPF_LD|BPF_MEM); s[i]->s.k = reg2; i++; /* goto again; (must use BPF_JA for backward jump) */ s[i] = new_stmt(BPF_JMP|BPF_JA); s[i]->s.k = again - i - 1; s[i - 1]->s.jf = s[i]; i++; /* fixup */ for (j = v6start; j <= v6end; j++) s[j]->s.jt = s[v6advance]; } else #endif { /* nop */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 0; s[fix2]->s.jf = s[i]; i++; } /* ahcheck: */ ahcheck = i; /* if (A == IPPROTO_AH) then fall through; else goto end; */ s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); s[i]->s.jt = NULL; /*later*/ s[i]->s.jf = NULL; /*later*/ s[i]->s.k = IPPROTO_AH; if (fix3) s[fix3]->s.jf = s[ahcheck]; fix4 = i; i++; /* * in short, * A = P[X]; * X = X + (P[X + 1] + 2) * 4; */ /* A = X */ s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A = P[X + packet head]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_ll + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); s[i]->s.k = reg2; i++; /* A = X */ s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 1; i++; /* X = A */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_ll + off_nl; i++; /* A += 2 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 2; i++; /* A *= 4 */ s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); s[i]->s.k = 4; i++; /* X = A; */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; /* A = MEM[reg2] */ s[i] = new_stmt(BPF_LD|BPF_MEM); s[i]->s.k = reg2; i++; /* goto again; (must use BPF_JA for backward jump) */ s[i] = new_stmt(BPF_JMP|BPF_JA); s[i]->s.k = again - i - 1; i++; /* end: nop */ end = i; s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); s[i]->s.k = 0; s[fix2]->s.jt = s[end]; s[fix4]->s.jf = s[end]; s[fix5]->s.jt = s[end]; i++; /* * make slist chain */ max = i; for (i = 0; i < max - 1; i++) s[i]->next = s[i + 1]; s[max - 1]->next = NULL; /* * emit final check */ b = new_block(JMP(BPF_JEQ)); b->stmts = s[1]; /*remember, s[0] is dummy*/ b->s.k = v; free_reg(reg2); gen_and(b0, b); return b; #endif } /* * Generate code that checks whether the packet is a packet for protocol * and whether the type field in that protocol's header has * the value , e.g. if is Q_IP, it checks whether it's an * IP packet and checks the protocol number in the IP header against . * * If is Q_DEFAULT, i.e. just "proto" was specified, it checks * against Q_IP and Q_IPV6. */ 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: #ifdef INET6 b0 = gen_proto(v, Q_IP, dir); b1 = gen_proto(v, Q_IPV6, dir); gen_or(b0, b1); return b1; #else /*FALLTHROUGH*/ #endif case Q_IP: /* * For FDDI, RFC 1188 says that SNAP encapsulation is used, * not LLC encapsulation with LLCSAP_IP. * * For IEEE 802 networks - which includes 802.5 token ring * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042 * says that SNAP encapsulation is used, not LLC encapsulation * with LLCSAP_IP. * * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and * RFC 2225 say that SNAP encapsulation is used, not LLC * encapsulation with LLCSAP_IP. * * So we always check for ETHERTYPE_IP. */ b0 = gen_linktype(ETHERTYPE_IP); #ifndef CHASE_CHAIN b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v); #else b1 = gen_protochain(v, Q_IP); #endif gen_and(b0, b1); return b1; case Q_ISO: switch (linktype) { case DLT_FRELAY: /* * Frame Relay packets typically have an OSI * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)" * generates code to check for all the OSI * NLPIDs, so calling it and then adding a check * for the particular NLPID for which we're * looking is bogus, as we can just check for * the NLPID. * * What we check for is the NLPID and a frame * control field value of UI, i.e. 0x03 followed * by the NLPID. * * XXX - assumes a 2-byte Frame Relay header with * DLCI and flags. What if the address is longer? * * XXX - what about SNAP-encapsulated frames? */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v); /*NOTREACHED*/ break; case DLT_C_HDLC: /* * Cisco uses an Ethertype lookalike - for OSI, * it's 0xfefe. */ b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS); /* OSI in C-HDLC is stuffed with a fudge byte */ b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v); gen_and(b0, b1); return b1; default: b0 = gen_linktype(LLCSAP_ISONS); b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v); gen_and(b0, b1); return b1; } case Q_ISIS: b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); /* * 4 is the offset of the PDU type relative to the IS-IS * header. */ b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)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_SCTP: bpf_error("'sctp 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 */ case Q_PIM: bpf_error("'pim proto' is bogus"); /* NOTREACHED */ case Q_VRRP: bpf_error("'vrrp proto' is bogus"); /* NOTREACHED */ #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); #ifndef CHASE_CHAIN b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v); #else b1 = gen_protochain(v, Q_IPV6); #endif gen_and(b0, b1); return b1; case Q_ICMPV6: bpf_error("'icmp6 proto' is bogus"); #endif /* INET6 */ case Q_AH: bpf_error("'ah proto' is bogus"); case Q_ESP: bpf_error("'ah proto' is bogus"); case Q_STP: bpf_error("'stp proto' is bogus"); case Q_IPX: bpf_error("'ipx proto' is bogus"); case Q_NETBEUI: bpf_error("'netbeui proto' is bogus"); case Q_RADIO: bpf_error("'radio proto' is bogus"); 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; #ifndef INET6 bpf_u_int32 **alist; #else int tproto6; struct sockaddr_in *sin4; struct sockaddr_in6 *sin6; struct addrinfo *res, *res0; struct in6_addr mask128; #endif /*INET6*/ struct block *b, *tmp; int port, real_proto; int port1, port2; 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, q.addr); 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); b = gen_ehostop(eaddr, dir); free(eaddr); return b; case DLT_FDDI: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown FDDI host '%s'", name); b = gen_fhostop(eaddr, dir); free(eaddr); return b; case DLT_IEEE802: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown token ring host '%s'", name); b = gen_thostop(eaddr, dir); free(eaddr); return b; case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: case DLT_PPI: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown 802.11 host '%s'", name); b = gen_wlanhostop(eaddr, dir); free(eaddr); return b; case DLT_IP_OVER_FC: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown Fibre Channel host '%s'", name); b = gen_ipfchostop(eaddr, dir); free(eaddr); return b; case DLT_SUNATM: if (!is_lane) break; /* * Check that the packet doesn't begin * with an LE Control marker. (We've * already generated a test for LANE.) */ tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(tmp); eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown ether host '%s'", name); b = gen_ehostop(eaddr, dir); gen_and(tmp, b); free(eaddr); return b; } bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name"); } 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, q.addr)); } else { #ifndef INET6 alist = pcap_nametoaddr(name); if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); tproto = proto; if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT) tproto = Q_IP; b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr); while (*alist) { tmp = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr); gen_or(b, tmp); b = tmp; } return b; #else memset(&mask128, 0xff, sizeof(mask128)); res0 = res = pcap_nametoaddrinfo(name); if (res == NULL) bpf_error("unknown host '%s'", name); b = tmp = NULL; tproto = tproto6 = proto; if (off_linktype == -1 && tproto == Q_DEFAULT) { tproto = Q_IP; tproto6 = Q_IPV6; } for (res = res0; res; res = res->ai_next) { switch (res->ai_family) { case AF_INET: if (tproto == Q_IPV6) continue; sin4 = (struct sockaddr_in *) res->ai_addr; tmp = gen_host(ntohl(sin4->sin_addr.s_addr), 0xffffffff, tproto, dir, q.addr); break; case AF_INET6: if (tproto6 == Q_IP) continue; sin6 = (struct sockaddr_in6 *) res->ai_addr; tmp = gen_host6(&sin6->sin6_addr, &mask128, tproto6, dir, q.addr); break; default: continue; } if (b) gen_or(b, tmp); b = tmp; } freeaddrinfo(res0); if (b == NULL) { bpf_error("unknown host '%s'%s", name, (proto == Q_DEFAULT) ? "" : " for specified address family"); } return b; #endif /*INET6*/ } case Q_PORT: if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) 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 if (real_proto == IPPROTO_SCTP) bpf_error("port '%s' is sctp", 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 if (real_proto == IPPROTO_SCTP) bpf_error("port '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } if (proto == Q_SCTP) { if (real_proto == IPPROTO_UDP) bpf_error("port '%s' is udp", name); else if (real_proto == IPPROTO_TCP) bpf_error("port '%s' is tcp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_SCTP; } #ifndef INET6 return gen_port(port, real_proto, dir); #else b = gen_port(port, real_proto, dir); gen_or(gen_port6(port, real_proto, dir), b); return b; #endif /* INET6 */ case Q_PORTRANGE: if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) bpf_error("illegal qualifier of 'portrange'"); if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0) bpf_error("unknown port in range '%s'", name); if (proto == Q_UDP) { if (real_proto == IPPROTO_TCP) bpf_error("port in range '%s' is tcp", name); else if (real_proto == IPPROTO_SCTP) bpf_error("port in range '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_UDP; } if (proto == Q_TCP) { if (real_proto == IPPROTO_UDP) bpf_error("port in range '%s' is udp", name); else if (real_proto == IPPROTO_SCTP) bpf_error("port in range '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } if (proto == Q_SCTP) { if (real_proto == IPPROTO_UDP) bpf_error("port in range '%s' is udp", name); else if (real_proto == IPPROTO_TCP) bpf_error("port in range '%s' is tcp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_SCTP; } #ifndef INET6 return gen_portrange(port1, port2, real_proto, dir); #else b = gen_portrange(port1, port2, real_proto, dir); gen_or(gen_portrange6(port1, port2, real_proto, dir), b); return b; #endif /* INET6 */ case Q_GATEWAY: #ifndef INET6 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); b = gen_gateway(eaddr, alist, proto, dir); free(eaddr); return b; #else bpf_error("'gateway' not supported in this configuration"); #endif /*INET6*/ 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_PROTOCHAIN: real_proto = lookup_proto(name, proto); if (real_proto >= 0) return gen_protochain(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"); if (masklen == 0) { /* * X << 32 is not guaranteed by C to be 0; it's * undefined. */ m = 0; } else 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, q.addr); default: bpf_error("Mask syntax for networks only"); /* NOTREACHED */ } /* NOTREACHED */ return NULL; } 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, q.addr); 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, q.addr); } case Q_PORT: if (proto == Q_UDP) proto = IPPROTO_UDP; else if (proto == Q_TCP) proto = IPPROTO_TCP; else if (proto == Q_SCTP) proto = IPPROTO_SCTP; else if (proto == Q_DEFAULT) proto = PROTO_UNDEF; else bpf_error("illegal qualifier of 'port'"); #ifndef INET6 return gen_port((int)v, proto, dir); #else { struct block *b; b = gen_port((int)v, proto, dir); gen_or(gen_port6((int)v, proto, dir), b); return b; } #endif /* INET6 */ case Q_PORTRANGE: if (proto == Q_UDP) proto = IPPROTO_UDP; else if (proto == Q_TCP) proto = IPPROTO_TCP; else if (proto == Q_SCTP) proto = IPPROTO_SCTP; else if (proto == Q_DEFAULT) proto = PROTO_UNDEF; else bpf_error("illegal qualifier of 'portrange'"); #ifndef INET6 return gen_portrange((int)v, (int)v, proto, dir); #else { struct block *b; b = gen_portrange((int)v, (int)v, proto, dir); gen_or(gen_portrange6((int)v, (int)v, proto, dir), b); return b; } #endif /* INET6 */ case Q_GATEWAY: bpf_error("'gateway' requires a name"); /* NOTREACHED */ case Q_PROTO: return gen_proto((int)v, proto, dir); case Q_PROTOCHAIN: return gen_protochain((int)v, proto, dir); case Q_UNDEF: syntax(); /* NOTREACHED */ default: abort(); /* NOTREACHED */ } /* NOTREACHED */ } #ifdef INET6 struct block * gen_mcode6(s1, s2, masklen, q) register const char *s1, *s2; register int masklen; struct qual q; { struct addrinfo *res; struct in6_addr *addr; struct in6_addr mask; struct block *b; u_int32_t *a, *m; if (s2) bpf_error("no mask %s supported", s2); res = pcap_nametoaddrinfo(s1); if (!res) bpf_error("invalid ip6 address %s", s1); if (res->ai_next) bpf_error("%s resolved to multiple address", s1); addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; if (sizeof(mask) * 8 < masklen) bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8)); memset(&mask, 0, sizeof(mask)); memset(&mask, 0xff, masklen / 8); if (masklen % 8) { mask.s6_addr[masklen / 8] = (0xff << (8 - masklen % 8)) & 0xff; } a = (u_int32_t *)addr; m = (u_int32_t *)&mask; if ((a[0] & ~m[0]) || (a[1] & ~m[1]) || (a[2] & ~m[2]) || (a[3] & ~m[3])) { bpf_error("non-network bits set in \"%s/%d\"", s1, masklen); } switch (q.addr) { case Q_DEFAULT: case Q_HOST: if (masklen != 128) bpf_error("Mask syntax for networks only"); /* FALLTHROUGH */ case Q_NET: b = gen_host6(addr, &mask, q.proto, q.dir, q.addr); freeaddrinfo(res); return b; default: bpf_error("invalid qualifier against IPv6 address"); /* NOTREACHED */ } return NULL; } #endif /*INET6*/ struct block * gen_ecode(eaddr, q) register const u_char *eaddr; struct qual q; { struct block *b, *tmp; if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { switch (linktype) { case DLT_EN10MB: return gen_ehostop(eaddr, (int)q.dir); case DLT_FDDI: return gen_fhostop(eaddr, (int)q.dir); case DLT_IEEE802: return gen_thostop(eaddr, (int)q.dir); case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: case DLT_PPI: return gen_wlanhostop(eaddr, (int)q.dir); case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(tmp); /* * Now check the MAC address. */ b = gen_ehostop(eaddr, (int)q.dir); gen_and(tmp, b); return b; } break; case DLT_IP_OVER_FC: return gen_ipfchostop(eaddr, (int)q.dir); default: bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); break; } } bpf_error("ethernet address used in non-ether expression"); /* NOTREACHED */ return NULL; } 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; } /* * Modify "index" to use the value stored into its register as an * offset relative to the beginning of the header for the protocol * "proto", and allocate a register and put an item "size" bytes long * (1, 2, or 4) at that offset into that register, making it the register * for "index". */ struct arth * gen_load(proto, inst, size) int proto; struct arth *inst; int size; { struct slist *s, *tmp; struct block *b; int regno = alloc_reg(); free_reg(inst->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_RADIO: /* * The offset is relative to the beginning of the packet * data, if we have a radio header. (If we don't, this * is an error.) */ if (linktype != DLT_IEEE802_11_RADIO_AVS && linktype != DLT_IEEE802_11_RADIO && linktype != DLT_PRISM_HEADER) bpf_error("radio information not present in capture"); /* * Load into the X register the offset computed into the * register specifed by "index". */ s = xfer_to_x(inst); /* * Load the item at that offset. */ tmp = new_stmt(BPF_LD|BPF_IND|size); sappend(s, tmp); sappend(inst->s, s); break; case Q_LINK: /* * The offset is relative to the beginning of * the link-layer header. * * XXX - what about ATM LANE? Should the index be * relative to the beginning of the AAL5 frame, so * that 0 refers to the beginning of the LE Control * field, or relative to the beginning of the LAN * frame, so that 0 refers, for Ethernet LANE, to * the beginning of the destination address? */ s = gen_llprefixlen(); /* * If "s" is non-null, it has code to arrange that the * X register contains the length of the prefix preceding * the link-layer header. Add to it the offset computed * into the register specified by "index", and move that * into the X register. Otherwise, just load into the X * register the offset computed into the register specifed * by "index". */ if (s != NULL) { sappend(s, xfer_to_a(inst)); sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else s = xfer_to_x(inst); /* * Load the item at the sum of the offset we've put in the * X register and the offset of the start of the link * layer header (which is 0 if the radio header is * variable-length; that header length is what we put * into the X register and then added to the index). */ tmp = new_stmt(BPF_LD|BPF_IND|size); tmp->s.k = off_ll; sappend(s, tmp); sappend(inst->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: #ifdef INET6 case Q_IPV6: #endif /* * The offset is relative to the beginning of * the network-layer header. * XXX - are there any cases where we want * off_nl_nosnap? */ s = gen_llprefixlen(); /* * If "s" is non-null, it has code to arrange that the * X register contains the length of the prefix preceding * the link-layer header. Add to it the offset computed * into the register specified by "index", and move that * into the X register. Otherwise, just load into the X * register the offset computed into the register specifed * by "index". */ if (s != NULL) { sappend(s, xfer_to_a(inst)); sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else s = xfer_to_x(inst); /* * Load the item at the sum of the offset we've put in the * X register, the offset of the start of the network * layer header, and the offset of the start of the link * layer header (which is 0 if the radio header is * variable-length; that header length is what we put * into the X register and then added to the index). */ tmp = new_stmt(BPF_LD|BPF_IND|size); tmp->s.k = off_ll + off_nl; sappend(s, tmp); sappend(inst->s, s); /* * Do the computation only if the packet contains * the protocol in question. */ b = gen_proto_abbrev(proto); if (inst->b) gen_and(inst->b, b); inst->b = b; break; case Q_SCTP: case Q_TCP: case Q_UDP: case Q_ICMP: case Q_IGMP: case Q_IGRP: case Q_PIM: case Q_VRRP: /* * The offset is relative to the beginning of * the transport-layer header. * * Load the X register with the length of the IPv4 header * (plus the offset of the link-layer header, if it's * a variable-length header), in bytes. * * XXX - are there any cases where we want * off_nl_nosnap? * XXX - we should, if we're built with * IPv6 support, generate code to load either * IPv4, IPv6, or both, as appropriate. */ s = gen_loadx_iphdrlen(); /* * The X register now contains the sum of the length * of any variable-length header preceding the link-layer * header and the length of the network-layer header. * Load into the A register the offset relative to * the beginning of the transport layer header, * add the X register to that, move that to the * X register, and load with an offset from the * X register equal to the offset of the network * layer header relative to the beginning of * the link-layer header plus the length of any * fixed-length header preceding the link-layer * header. */ sappend(s, xfer_to_a(inst)); 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_ll + off_nl; sappend(inst->s, s); /* * Do the computation only if the packet contains * the protocol in question - which is true only * if this is an IP datagram and is the first or * only fragment of that datagram. */ gen_and(gen_proto_abbrev(proto), b = gen_ipfrag()); if (inst->b) gen_and(inst->b, b); #ifdef INET6 gen_and(gen_proto_abbrev(Q_IP), b); #endif inst->b = b; break; #ifdef INET6 case Q_ICMPV6: bpf_error("IPv6 upper-layer protocol is not supported by proto[x]"); /*NOTREACHED*/ #endif } inst->regno = regno; s = new_stmt(BPF_ST); s->s.k = regno; sappend(inst->s, s); return inst; } 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); if (code == BPF_JEQ) { s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X); b = new_block(JMP(code)); sappend(s1, s2); } else b = new_block(BPF_JMP|code|BPF_X); if (reversed) gen_not(b); 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(a0->regno); 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 0; } /* * 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); } /* * Actually, this is less than or equal. */ struct block * gen_less(n) int n; { struct block *b; b = gen_len(BPF_JGT, n); gen_not(b); return b; } /* * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to * the beginning of the link-layer header. * XXX - that means you can't test values in the radiotap header, but * as that header is difficult if not impossible to parse generally * without a loop, that might not be a severe problem. A new keyword * "radio" could be added for that, although what you'd really want * would be a way of testing particular radio header values, which * would generate code appropriate to the radio header in question. */ 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(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); case '<': b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); return b; case '>': b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); 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; } static u_char abroadcast[] = { 0x0 }; 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: switch (linktype) { case DLT_ARCNET: case DLT_ARCNET_LINUX: return gen_ahostop(abroadcast, Q_DST); case DLT_EN10MB: return gen_ehostop(ebroadcast, Q_DST); case DLT_FDDI: return gen_fhostop(ebroadcast, Q_DST); case DLT_IEEE802: return gen_thostop(ebroadcast, Q_DST); case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PPI: case DLT_PRISM_HEADER: return gen_wlanhostop(ebroadcast, Q_DST); case DLT_IP_OVER_FC: return gen_ipfchostop(ebroadcast, Q_DST); case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b1); /* * Now check the MAC address. */ b0 = gen_ehostop(ebroadcast, Q_DST); gen_and(b1, b0); return b0; } break; default: bpf_error("not a broadcast link"); } break; case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); hostmask = ~netmask; b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask); b2 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)(~0 & hostmask), hostmask); gen_or(b1, b2); gen_and(b0, b2); return b2; } bpf_error("only link-layer/IP broadcast filters supported"); /* NOTREACHED */ return NULL; } /* * Generate code to test the low-order bit of a MAC address (that's * the bottom bit of the *first* byte). */ static struct block * gen_mac_multicast(offset) int offset; { register struct block *b0; register struct slist *s; /* link[offset] & 1 != 0 */ s = gen_load_a(OR_LINK, offset, BPF_B); b0 = new_block(JMP(BPF_JSET)); b0->s.k = 1; b0->stmts = s; return b0; } struct block * gen_multicast(proto) int proto; { register struct block *b0, *b1, *b2; register struct slist *s; switch (proto) { case Q_DEFAULT: case Q_LINK: switch (linktype) { case DLT_ARCNET: case DLT_ARCNET_LINUX: /* all ARCnet multicasts use the same address */ return gen_ahostop(abroadcast, Q_DST); case DLT_EN10MB: /* ether[0] & 1 != 0 */ return gen_mac_multicast(0); case DLT_FDDI: /* * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX * * XXX - was that referring to bit-order issues? */ /* fddi[1] & 1 != 0 */ return gen_mac_multicast(1); case DLT_IEEE802: /* tr[2] & 1 != 0 */ return gen_mac_multicast(2); case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_PPI: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: /* * Oh, yuk. * * For control frames, there is no DA. * * For management frames, DA is at an * offset of 4 from the beginning of * the packet. * * For data frames, DA is at an offset * of 4 from the beginning of the packet * if To DS is clear and at an offset of * 16 from the beginning of the packet * if To DS is set. */ /* * Generate the tests to be done for data frames. * * First, check for To DS set, i.e. "link[1] & 0x01". */ s = gen_load_a(OR_LINK, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; /* * If To DS is set, the DA is at 16. */ b0 = gen_mac_multicast(16); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ s = gen_load_a(OR_LINK, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; gen_not(b2); /* * If To DS is not set, the DA is at 4. */ b1 = gen_mac_multicast(4); gen_and(b2, b1); /* * Now OR together the last two checks. That gives * the complete set of checks for data frames. */ gen_or(b1, b0); /* * Now check for a data frame. * I.e, check "link[0] & 0x08". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; /* * AND that with the checks done for data frames. */ gen_and(b1, b0); /* * If the high-order bit of the type value is 0, this * is a management frame. * I.e, check "!(link[0] & 0x08)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; gen_not(b2); /* * For management frames, the DA is at 4. */ b1 = gen_mac_multicast(4); gen_and(b2, b1); /* * OR that with the checks done for data frames. * That gives the checks done for management and * data frames. */ gen_or(b1, b0); /* * If the low-order bit of the type value is 1, * this is either a control frame or a frame * with a reserved type, and thus not a * frame with an SA. * * I.e., check "!(link[0] & 0x04)". */ s = gen_load_a(OR_LINK, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; gen_not(b1); /* * AND that with the checks for data and management * frames. */ gen_and(b1, b0); return b0; case DLT_IP_OVER_FC: b0 = gen_mac_multicast(2); return b0; case DLT_SUNATM: if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b1); /* ether[off_mac] & 1 != 0 */ b0 = gen_mac_multicast(off_mac); gen_and(b1, b0); return b0; } break; default: break; } /* Link not known to support multicasts */ break; case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224); gen_and(b0, b1); return b1; #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255); gen_and(b0, b1); return b1; #endif /* INET6 */ } bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel"); /* NOTREACHED */ return NULL; } /* * 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; /* * Only some data link types support inbound/outbound qualifiers. */ switch (linktype) { case DLT_SLIP: b0 = gen_relation(BPF_JEQ, gen_load(Q_LINK, gen_loadi(0), 1), gen_loadi(0), dir); break; case DLT_LINUX_SLL: if (dir) { /* * Match packets sent by this machine. */ b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING); } else { /* * Match packets sent to this machine. * (No broadcast or multicast packets, or * packets sent to some other machine and * received promiscuously.) * * XXX - packets sent to other machines probably * shouldn't be matched, but what about broadcast * or multicast packets we received? */ b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST); } break; case DLT_PFLOG: b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B, (bpf_int32)((dir == 0) ? PF_IN : PF_OUT)); break; case DLT_PPP_PPPD: if (dir) { /* match outgoing packets */ b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT); } else { /* match incoming packets */ b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN); } break; case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: case DLT_JUNIPER_ATM2: case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_PPPOE_ATM: case DLT_JUNIPER_GGSN: case DLT_JUNIPER_ES: case DLT_JUNIPER_MONITOR: case DLT_JUNIPER_SERVICES: case DLT_JUNIPER_ETHER: case DLT_JUNIPER_PPP: case DLT_JUNIPER_FRELAY: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_VP: /* juniper flags (including direction) are stored * the byte after the 3-byte magic number */ if (dir) { /* match outgoing packets */ b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01); } else { /* match incoming packets */ b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01); } break; default: bpf_error("inbound/outbound not supported on linktype %d", linktype); b0 = NULL; /* NOTREACHED */ } return (b0); } /* PF firewall log matched interface */ struct block * gen_pf_ifname(const char *ifname) { struct block *b0; u_int len, off; if (linktype == DLT_PFLOG) { len = sizeof(((struct pfloghdr *)0)->ifname); off = offsetof(struct pfloghdr, ifname); } else { bpf_error("ifname not supported on linktype 0x%x", linktype); /* NOTREACHED */ } if (strlen(ifname) >= len) { bpf_error("ifname interface names can only be %d characters", len-1); /* NOTREACHED */ } b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname); return (b0); } /* PF firewall log ruleset name */ struct block * gen_pf_ruleset(char *ruleset) { struct block *b0; if (linktype != DLT_PFLOG) { bpf_error("ruleset not supported on linktype 0x%x", linktype); /* NOTREACHED */ } if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) { bpf_error("ruleset names can only be %ld characters", (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1)); /* NOTREACHED */ } b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset), strlen(ruleset), (const u_char *)ruleset); return (b0); } /* PF firewall log rule number */ struct block * gen_pf_rnr(int rnr) { struct block *b0; if (linktype == DLT_PFLOG) { b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W, (bpf_int32)rnr); } else { bpf_error("rnr not supported on linktype 0x%x", linktype); /* NOTREACHED */ } return (b0); } /* PF firewall log sub-rule number */ struct block * gen_pf_srnr(int srnr) { struct block *b0; if (linktype != DLT_PFLOG) { bpf_error("srnr not supported on linktype 0x%x", linktype); /* NOTREACHED */ } b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W, (bpf_int32)srnr); return (b0); } /* PF firewall log reason code */ struct block * gen_pf_reason(int reason) { struct block *b0; if (linktype == DLT_PFLOG) { b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B, (bpf_int32)reason); } else { bpf_error("reason not supported on linktype 0x%x", linktype); /* NOTREACHED */ } return (b0); } /* PF firewall log action */ struct block * gen_pf_action(int action) { struct block *b0; if (linktype == DLT_PFLOG) { b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B, (bpf_int32)action); } else { bpf_error("action not supported on linktype 0x%x", linktype); /* NOTREACHED */ } return (b0); } struct block * gen_acode(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_ARCNET || linktype == DLT_ARCNET_LINUX) return gen_ahostop(eaddr, (int)q.dir); } bpf_error("ARCnet address used in non-arc expression"); /* NOTREACHED */ return NULL; } static struct block * gen_ahostop(eaddr, dir) register const u_char *eaddr; register int dir; { register struct block *b0, *b1; switch (dir) { /* src comes first, different from Ethernet */ case Q_SRC: return gen_bcmp(OR_LINK, 0, 1, eaddr); case Q_DST: return gen_bcmp(OR_LINK, 1, 1, eaddr); case Q_AND: b0 = gen_ahostop(eaddr, Q_SRC); b1 = gen_ahostop(eaddr, Q_DST); gen_and(b0, b1); return b1; case Q_DEFAULT: case Q_OR: b0 = gen_ahostop(eaddr, Q_SRC); b1 = gen_ahostop(eaddr, Q_DST); gen_or(b0, b1); return b1; } abort(); /* NOTREACHED */ } /* * support IEEE 802.1Q VLAN trunk over ethernet */ struct block * gen_vlan(vlan_num) int vlan_num; { struct block *b0, *b1; /* can't check for VLAN-encapsulated packets inside MPLS */ if (label_stack_depth > 0) bpf_error("no VLAN match after MPLS"); /* * Change the offsets to point to the type and data fields within * the VLAN packet. Just increment the offsets, so that we * can support a hierarchy, e.g. "vlan 300 && vlan 200" to * capture VLAN 200 encapsulated within VLAN 100. * * XXX - this is a bit of a kludge. If we were to split the * compiler into a parser that parses an expression and * generates an expression tree, and a code generator that * takes an expression tree (which could come from our * parser or from some other parser) and generates BPF code, * we could perhaps make the offsets parameters of routines * and, in the handler for an "AND" node, pass to subnodes * other than the VLAN node the adjusted offsets. * * This would mean that "vlan" would, instead of changing the * behavior of *all* tests after it, change only the behavior * of tests ANDed with it. That would change the documented * semantics of "vlan", which might break some expressions. * However, it would mean that "(vlan and ip) or ip" would check * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than * checking only for VLAN-encapsulated IP, so that could still * be considered worth doing; it wouldn't break expressions * that are of the form "vlan and ..." or "vlan N and ...", * which I suspect are the most common expressions involving * "vlan". "vlan or ..." doesn't necessarily do what the user * would really want, now, as all the "or ..." tests would * be done assuming a VLAN, even though the "or" could be viewed * as meaning "or, if this isn't a VLAN packet...". */ orig_linktype = off_linktype; /* save original values */ orig_nl = off_nl; switch (linktype) { case DLT_EN10MB: off_linktype += 4; off_nl_nosnap += 4; off_nl += 4; break; default: bpf_error("no VLAN support for data link type %d", linktype); /*NOTREACHED*/ } /* check for VLAN */ b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q); /* If a specific VLAN is requested, check VLAN id */ if (vlan_num >= 0) { b1 = gen_mcmp(OR_LINK, orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff); gen_and(b0, b1); b0 = b1; } return (b0); } /* * support for MPLS */ struct block * gen_mpls(label_num) int label_num; { struct block *b0,*b1; /* * Change the offsets to point to the type and data fields within * the MPLS packet. Just increment the offsets, so that we * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to * capture packets with an outer label of 100000 and an inner * label of 1024. * * XXX - this is a bit of a kludge. See comments in gen_vlan(). */ orig_nl = off_nl; if (label_stack_depth > 0) { /* just match the bottom-of-stack bit clear */ b0 = gen_mcmp(OR_LINK, orig_nl-2, BPF_B, 0, 0x01); } else { /* * Indicate that we're checking MPLS-encapsulated headers, * to make sure higher level code generators don't try to * match against IP-related protocols such as Q_ARP, Q_RARP * etc. */ switch (linktype) { case DLT_C_HDLC: /* fall through */ case DLT_EN10MB: b0 = gen_linktype(ETHERTYPE_MPLS); break; case DLT_PPP: b0 = gen_linktype(PPP_MPLS_UCAST); break; /* FIXME add other DLT_s ... * for Frame-Relay/and ATM this may get messy due to SNAP headers * leave it for now */ default: bpf_error("no MPLS support for data link type %d", linktype); b0 = NULL; /*NOTREACHED*/ break; } } /* If a specific MPLS label is requested, check it */ if (label_num >= 0) { label_num = label_num << 12; /* label is shifted 12 bits on the wire */ b1 = gen_mcmp(OR_LINK, orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */ gen_and(b0, b1); b0 = b1; } off_nl_nosnap += 4; off_nl += 4; label_stack_depth++; return (b0); } /* * Support PPPOE discovery and session. */ struct block * gen_pppoed() { /* check for PPPoE discovery */ return gen_linktype((bpf_int32)ETHERTYPE_PPPOED); } struct block * gen_pppoes() { struct block *b0; /* * Test against the PPPoE session link-layer type. */ b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES); /* * Change the offsets to point to the type and data fields within * the PPP packet. * * XXX - this is a bit of a kludge. If we were to split the * compiler into a parser that parses an expression and * generates an expression tree, and a code generator that * takes an expression tree (which could come from our * parser or from some other parser) and generates BPF code, * we could perhaps make the offsets parameters of routines * and, in the handler for an "AND" node, pass to subnodes * other than the PPPoE node the adjusted offsets. * * This would mean that "pppoes" would, instead of changing the * behavior of *all* tests after it, change only the behavior * of tests ANDed with it. That would change the documented * semantics of "pppoes", which might break some expressions. * However, it would mean that "(pppoes and ip) or ip" would check * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than * checking only for VLAN-encapsulated IP, so that could still * be considered worth doing; it wouldn't break expressions * that are of the form "pppoes and ..." which I suspect are the * most common expressions involving "pppoes". "pppoes or ..." * doesn't necessarily do what the user would really want, now, * as all the "or ..." tests would be done assuming PPPoE, even * though the "or" could be viewed as meaning "or, if this isn't * a PPPoE packet...". */ orig_linktype = off_linktype; /* save original values */ orig_nl = off_nl; /* * The "network-layer" protocol is PPPoE, which has a 6-byte * PPPoE header, followed by PPP payload, so we set the * offsets to the network layer offset plus 6 bytes for * the PPPoE header plus the values appropriate for PPP when * encapsulated in Ethernet (which means there's no HDLC * encapsulation). */ off_linktype = orig_nl + 6; off_nl = orig_nl + 6 + 2; off_nl_nosnap = orig_nl + 6 + 2; /* * Set the link-layer type to PPP, as all subsequent tests will * be on the encapsulated PPP header. */ linktype = DLT_PPP; return b0; } struct block * gen_atmfield_code(atmfield, jvalue, jtype, reverse) int atmfield; bpf_int32 jvalue; bpf_u_int32 jtype; int reverse; { struct block *b0; switch (atmfield) { case A_VPI: if (!is_atm) bpf_error("'vpi' supported only on raw ATM"); if (off_vpi == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; case A_VCI: if (!is_atm) bpf_error("'vci' supported only on raw ATM"); if (off_vci == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype, reverse, jvalue); break; case A_PROTOTYPE: if (off_proto == (u_int)-1) abort(); /* XXX - this isn't on FreeBSD */ b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype, reverse, jvalue); break; case A_MSGTYPE: if (off_payload == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; case A_CALLREFTYPE: if (!is_atm) bpf_error("'callref' supported only on raw ATM"); if (off_proto == (u_int)-1) abort(); b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; default: abort(); } return b0; } struct block * gen_atmtype_abbrev(type) int type; { struct block *b0, *b1; switch (type) { case A_METAC: /* Get all packets in Meta signalling Circuit */ if (!is_atm) bpf_error("'metac' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0); gen_and(b0, b1); break; case A_BCC: /* Get all packets in Broadcast Circuit*/ if (!is_atm) bpf_error("'bcc' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0); gen_and(b0, b1); break; case A_OAMF4SC: /* Get all cells in Segment OAM F4 circuit*/ if (!is_atm) bpf_error("'oam4sc' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); gen_and(b0, b1); break; case A_OAMF4EC: /* Get all cells in End-to-End OAM F4 Circuit*/ if (!is_atm) bpf_error("'oam4ec' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); gen_and(b0, b1); break; case A_SC: /* Get all packets in connection Signalling Circuit */ if (!is_atm) bpf_error("'sc' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0); gen_and(b0, b1); break; case A_ILMIC: /* Get all packets in ILMI Circuit */ if (!is_atm) bpf_error("'ilmic' supported only on raw ATM"); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0); gen_and(b0, b1); break; case A_LANE: /* Get all LANE packets */ if (!is_atm) bpf_error("'lane' supported only on raw ATM"); b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0); /* * Arrange that all subsequent tests assume LANE * rather than LLC-encapsulated packets, and set * the offsets appropriately for LANE-encapsulated * Ethernet. * * "off_mac" is the offset of the Ethernet header, * which is 2 bytes past the ATM pseudo-header * (skipping the pseudo-header and 2-byte LE Client * field). The other offsets are Ethernet offsets * relative to "off_mac". */ is_lane = 1; off_mac = off_payload + 2; /* MAC header */ off_linktype = off_mac + 12; off_nl = off_mac + 14; /* Ethernet II */ off_nl_nosnap = off_mac + 17; /* 802.3+802.2 */ break; case A_LLC: /* Get all LLC-encapsulated packets */ if (!is_atm) bpf_error("'llc' supported only on raw ATM"); b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); is_lane = 0; break; default: abort(); } return b1; } /* * Filtering for MTP2 messages based on li value * FISU, length is null * LSSU, length is 1 or 2 * MSU, length is 3 or more */ struct block * gen_mtp2type_abbrev(type) int type; { struct block *b0, *b1; switch (type) { case M_FISU: if ( (linktype != DLT_MTP2) && (linktype != DLT_MTP2_WITH_PHDR) ) bpf_error("'fisu' supported only on MTP2"); /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */ b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0); break; case M_LSSU: if ( (linktype != DLT_MTP2) && (linktype != DLT_MTP2_WITH_PHDR) ) bpf_error("'lssu' supported only on MTP2"); b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2); b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0); gen_and(b1, b0); break; case M_MSU: if ( (linktype != DLT_MTP2) && (linktype != DLT_MTP2_WITH_PHDR) ) bpf_error("'msu' supported only on MTP2"); b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2); break; default: abort(); } return b0; } struct block * gen_mtp3field_code(mtp3field, jvalue, jtype, reverse) int mtp3field; bpf_u_int32 jvalue; bpf_u_int32 jtype; int reverse; { struct block *b0; bpf_u_int32 val1 , val2 , val3; switch (mtp3field) { case M_SIO: if (off_sio == (u_int)-1) bpf_error("'sio' supported only on SS7"); /* sio coded on 1 byte so max value 255 */ if(jvalue > 255) bpf_error("sio value %u too big; max value = 255", jvalue); b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff, (u_int)jtype, reverse, (u_int)jvalue); break; case M_OPC: if (off_opc == (u_int)-1) bpf_error("'opc' supported only on SS7"); /* opc coded on 14 bits so max value 16383 */ if (jvalue > 16383) bpf_error("opc value %u too big; max value = 16383", jvalue); /* the following instructions are made to convert jvalue * to the form used to write opc in an ss7 message*/ val1 = jvalue & 0x00003c00; val1 = val1 >>10; val2 = jvalue & 0x000003fc; val2 = val2 <<6; val3 = jvalue & 0x00000003; val3 = val3 <<22; jvalue = val1 + val2 + val3; b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f, (u_int)jtype, reverse, (u_int)jvalue); break; case M_DPC: if (off_dpc == (u_int)-1) bpf_error("'dpc' supported only on SS7"); /* dpc coded on 14 bits so max value 16383 */ if (jvalue > 16383) bpf_error("dpc value %u too big; max value = 16383", jvalue); /* the following instructions are made to convert jvalue * to the forme used to write dpc in an ss7 message*/ val1 = jvalue & 0x000000ff; val1 = val1 << 24; val2 = jvalue & 0x00003f00; val2 = val2 << 8; jvalue = val1 + val2; b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000, (u_int)jtype, reverse, (u_int)jvalue); break; case M_SLS: if (off_sls == (u_int)-1) bpf_error("'sls' supported only on SS7"); /* sls coded on 4 bits so max value 15 */ if (jvalue > 15) bpf_error("sls value %u too big; max value = 15", jvalue); /* the following instruction is made to convert jvalue * to the forme used to write sls in an ss7 message*/ jvalue = jvalue << 4; b0 = gen_ncmp(OR_PACKET, off_sls, BPF_B, 0xf0, (u_int)jtype,reverse, (u_int)jvalue); break; default: abort(); } return b0; } static struct block * gen_msg_abbrev(type) int type; { struct block *b1; /* * Q.2931 signalling protocol messages for handling virtual circuits * establishment and teardown */ switch (type) { case A_SETUP: b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0); break; case A_CALLPROCEED: b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0); break; case A_CONNECT: b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0); break; case A_CONNECTACK: b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0); break; case A_RELEASE: b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0); break; case A_RELEASE_DONE: b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0); break; default: abort(); } return b1; } struct block * gen_atmmulti_abbrev(type) int type; { struct block *b0, *b1; switch (type) { case A_OAM: if (!is_atm) bpf_error("'oam' supported only on raw ATM"); b1 = gen_atmmulti_abbrev(A_OAMF4); break; case A_OAMF4: if (!is_atm) bpf_error("'oamf4' supported only on raw ATM"); /* OAM F4 type */ b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); gen_or(b0, b1); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); gen_and(b0, b1); break; case A_CONNECTMSG: /* * Get Q.2931 signalling messages for switched * virtual connection */ if (!is_atm) bpf_error("'connectmsg' supported only on raw ATM"); b0 = gen_msg_abbrev(A_SETUP); b1 = gen_msg_abbrev(A_CALLPROCEED); gen_or(b0, b1); b0 = gen_msg_abbrev(A_CONNECT); gen_or(b0, b1); b0 = gen_msg_abbrev(A_CONNECTACK); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE_DONE); gen_or(b0, b1); b0 = gen_atmtype_abbrev(A_SC); gen_and(b0, b1); break; case A_METACONNECT: if (!is_atm) bpf_error("'metaconnect' supported only on raw ATM"); b0 = gen_msg_abbrev(A_SETUP); b1 = gen_msg_abbrev(A_CALLPROCEED); gen_or(b0, b1); b0 = gen_msg_abbrev(A_CONNECT); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE); gen_or(b0, b1); b0 = gen_msg_abbrev(A_RELEASE_DONE); gen_or(b0, b1); b0 = gen_atmtype_abbrev(A_METAC); gen_and(b0, b1); break; default: abort(); } return b1; } libpcap-0.9.7/./savefile.c0000644000026300017500000012366210651225661013400 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.126.2.27 2007/07/19 06:20:53 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif /* * Standard libpcap format. */ #define TCPDUMP_MAGIC 0xa1b2c3d4 /* * Alexey Kuznetzov's modified libpcap format. */ #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34 /* * Reserved for Francisco Mesquita * for another modified format. */ #define FMESQUITA_TCPDUMP_MAGIC 0xa1b234cd /* * Navtel Communcations' format, with nanosecond timestamps, * as per a request from Dumas Hwang . */ #define NAVTEL_TCPDUMP_MAGIC 0xa12b3c4d /* * Normal libpcap format, except for seconds/nanoseconds timestamps, * as per a request by Ulf Lamping */ #define NSEC_TCPDUMP_MAGIC 0xa1b23c4d /* * 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 bytes of packet data are written out in the order in * which they were received, so multi-byte fields in packets are not * written in host byte order, they're written in whatever order the * sending machine put them in. * * 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 */ /* * Setting O_BINARY on DOS/Windows is a bit tricky */ #if defined(WIN32) #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY) #elif defined(MSDOS) #if defined(__HIGHC__) #define SET_BINMODE(f) setmode(f, O_BINARY) #else #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) #endif #endif /* * We don't write DLT_* values to the capture file header, because * they're not the same on all platforms. * * Unfortunately, the various flavors of BSD have not always used the same * numerical values for the same data types, and various patches to * libpcap for non-BSD OSes have added their own DLT_* codes for link * layer encapsulation types seen on those OSes, and those codes have had, * in some cases, values that were also used, on other platforms, for other * link layer encapsulation types. * * This means that capture files of a type whose numerical DLT_* code * means different things on different BSDs, or with different versions * of libpcap, can't always be read on systems other than those like * the one running on the machine on which the capture was made. * * Instead, we define here a set of LINKTYPE_* codes, and map DLT_* codes * to LINKTYPE_* codes when writing a savefile header, and map LINKTYPE_* * codes to DLT_* codes when reading a savefile header. * * For those DLT_* codes that have, as far as we know, the same values on * all platforms (DLT_NULL through DLT_FDDI), we define LINKTYPE_xxx as * DLT_xxx; that way, captures of those types can still be read by * versions of libpcap that map LINKTYPE_* values to DLT_* values, and * captures of those types written by versions of libpcap that map DLT_ * values to LINKTYPE_ values can still be read by older versions * of libpcap. * * The other LINKTYPE_* codes are given values starting at 100, in the * hopes that no DLT_* code will be given one of those values. * * In order to ensure that a given LINKTYPE_* code's value will refer to * the same encapsulation type on all platforms, you should not allocate * a new LINKTYPE_* value without consulting "tcpdump-workers@tcpdump.org". * The tcpdump developers will allocate a value for you, and will not * subsequently allocate it to anybody else; that value will be added to * the "pcap.h" in the tcpdump.org CVS repository, so that a future * libpcap release will include it. * * You should, if possible, also contribute patches to libpcap and tcpdump * to handle the new encapsulation type, so that they can also be checked * into the tcpdump.org CVS repository and so that they will appear in * future libpcap and tcpdump releases. * * Do *NOT* assume that any values after the largest value in this file * are available; you might not have the most up-to-date version of this * file, and new values after that one might have been assigned. Also, * do *NOT* use any values below 100 - those might already have been * taken by one (or more!) organizations. */ #define LINKTYPE_NULL DLT_NULL #define LINKTYPE_ETHERNET DLT_EN10MB /* also for 100Mb and up */ #define LINKTYPE_EXP_ETHERNET DLT_EN3MB /* 3Mb experimental Ethernet */ #define LINKTYPE_AX25 DLT_AX25 #define LINKTYPE_PRONET DLT_PRONET #define LINKTYPE_CHAOS DLT_CHAOS #define LINKTYPE_TOKEN_RING DLT_IEEE802 /* DLT_IEEE802 is used for Token Ring */ #define LINKTYPE_ARCNET DLT_ARCNET /* BSD-style headers */ #define LINKTYPE_SLIP DLT_SLIP #define LINKTYPE_PPP DLT_PPP #define LINKTYPE_FDDI DLT_FDDI /* * LINKTYPE_PPP is for use when there might, or might not, be an RFC 1662 * PPP in HDLC-like framing header (with 0xff 0x03 before the PPP protocol * field) at the beginning of the packet. * * This is for use when there is always such a header; the address field * might be 0xff, for regular PPP, or it might be an address field for Cisco * point-to-point with HDLC framing as per section 4.3.1 of RFC 1547 ("Cisco * HDLC"). This is, for example, what you get with NetBSD's DLT_PPP_SERIAL. * * We give it the same value as NetBSD's DLT_PPP_SERIAL, in the hopes that * nobody else will choose a DLT_ value of 50, and so that DLT_PPP_SERIAL * captures will be written out with a link type that NetBSD's tcpdump * can read. */ #define LINKTYPE_PPP_HDLC 50 /* PPP in HDLC-like framing */ #define LINKTYPE_PPP_ETHER 51 /* NetBSD PPP-over-Ethernet */ #define LINKTYPE_SYMANTEC_FIREWALL 99 /* Symantec Enterprise Firewall */ #define LINKTYPE_ATM_RFC1483 100 /* LLC/SNAP-encapsulated ATM */ #define LINKTYPE_RAW 101 /* raw IP */ #define LINKTYPE_SLIP_BSDOS 102 /* BSD/OS SLIP BPF header */ #define LINKTYPE_PPP_BSDOS 103 /* BSD/OS PPP BPF header */ #define LINKTYPE_C_HDLC 104 /* Cisco HDLC */ #define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 (wireless) */ #define LINKTYPE_ATM_CLIP 106 /* Linux Classical IP over ATM */ #define LINKTYPE_FRELAY 107 /* Frame Relay */ #define LINKTYPE_LOOP 108 /* OpenBSD loopback */ #define LINKTYPE_ENC 109 /* OpenBSD IPSEC enc */ /* * These three types are reserved for future use. */ #define LINKTYPE_LANE8023 110 /* ATM LANE + 802.3 */ #define LINKTYPE_HIPPI 111 /* NetBSD HIPPI */ #define LINKTYPE_HDLC 112 /* NetBSD HDLC framing */ #define LINKTYPE_LINUX_SLL 113 /* Linux cooked socket capture */ #define LINKTYPE_LTALK 114 /* Apple LocalTalk hardware */ #define LINKTYPE_ECONET 115 /* Acorn Econet */ /* * Reserved for use with OpenBSD ipfilter. */ #define LINKTYPE_IPFILTER 116 #define LINKTYPE_PFLOG 117 /* OpenBSD DLT_PFLOG */ #define LINKTYPE_CISCO_IOS 118 /* For Cisco-internal use */ #define LINKTYPE_PRISM_HEADER 119 /* 802.11+Prism II monitor mode */ #define LINKTYPE_AIRONET_HEADER 120 /* FreeBSD Aironet driver stuff */ /* * Reserved for Siemens HiPath HDLC. */ #define LINKTYPE_HHDLC 121 #define LINKTYPE_IP_OVER_FC 122 /* RFC 2625 IP-over-Fibre Channel */ #define LINKTYPE_SUNATM 123 /* Solaris+SunATM */ /* * Reserved as per request from Kent Dahlgren * for private use. */ #define LINKTYPE_RIO 124 /* RapidIO */ #define LINKTYPE_PCI_EXP 125 /* PCI Express */ #define LINKTYPE_AURORA 126 /* Xilinx Aurora link layer */ #define LINKTYPE_IEEE802_11_RADIO 127 /* 802.11 plus BSD radio header */ /* * Reserved for the TZSP encapsulation, as per request from * Chris Waters * TZSP is a generic encapsulation for any other link type, * which includes a means to include meta-information * with the packet, e.g. signal strength and channel * for 802.11 packets. */ #define LINKTYPE_TZSP 128 /* Tazmen Sniffer Protocol */ #define LINKTYPE_ARCNET_LINUX 129 /* Linux-style headers */ /* * Juniper-private data link types, as per request from * Hannes Gredler . The corresponding * DLT_s are used for passing on chassis-internal * metainformation such as QOS profiles, etc.. */ #define LINKTYPE_JUNIPER_MLPPP 130 #define LINKTYPE_JUNIPER_MLFR 131 #define LINKTYPE_JUNIPER_ES 132 #define LINKTYPE_JUNIPER_GGSN 133 #define LINKTYPE_JUNIPER_MFR 134 #define LINKTYPE_JUNIPER_ATM2 135 #define LINKTYPE_JUNIPER_SERVICES 136 #define LINKTYPE_JUNIPER_ATM1 137 #define LINKTYPE_APPLE_IP_OVER_IEEE1394 138 /* Apple IP-over-IEEE 1394 cooked header */ #define LINKTYPE_MTP2_WITH_PHDR 139 #define LINKTYPE_MTP2 140 #define LINKTYPE_MTP3 141 #define LINKTYPE_SCCP 142 #define LINKTYPE_DOCSIS 143 /* DOCSIS MAC frames */ #define LINKTYPE_LINUX_IRDA 144 /* Linux-IrDA */ /* * Reserved for IBM SP switch and IBM Next Federation switch. */ #define LINKTYPE_IBM_SP 145 #define LINKTYPE_IBM_SN 146 /* * Reserved for private use. If you have some link-layer header type * that you want to use within your organization, with the capture files * using that link-layer header type not ever be sent outside your * organization, you can use these values. * * No libpcap release will use these for any purpose, nor will any * tcpdump release use them, either. * * Do *NOT* use these in capture files that you expect anybody not using * your private versions of capture-file-reading tools to read; in * particular, do *NOT* use them in products, otherwise you may find that * people won't be able to use tcpdump, or snort, or Ethereal, or... to * read capture files from your firewall/intrusion detection/traffic * monitoring/etc. appliance, or whatever product uses that LINKTYPE_ value, * and you may also find that the developers of those applications will * not accept patches to let them read those files. * * Also, do not use them if somebody might send you a capture using them * for *their* private type and tools using them for *your* private type * would have to read them. * * Instead, in those cases, ask "tcpdump-workers@tcpdump.org" for a new DLT_ * and LINKTYPE_ value, as per the comment in pcap-bpf.h, and use the type * you're given. */ #define LINKTYPE_USER0 147 #define LINKTYPE_USER1 148 #define LINKTYPE_USER2 149 #define LINKTYPE_USER3 150 #define LINKTYPE_USER4 151 #define LINKTYPE_USER5 152 #define LINKTYPE_USER6 153 #define LINKTYPE_USER7 154 #define LINKTYPE_USER8 155 #define LINKTYPE_USER9 156 #define LINKTYPE_USER10 157 #define LINKTYPE_USER11 158 #define LINKTYPE_USER12 159 #define LINKTYPE_USER13 160 #define LINKTYPE_USER14 161 #define LINKTYPE_USER15 162 /* * For future use with 802.11 captures - defined by AbsoluteValue * Systems to store a number of bits of link-layer information * including radio information: * * http://www.shaftnet.org/~pizza/software/capturefrm.txt * * but could and arguably should also be used by non-AVS Linux * 802.11 drivers; that may happen in the future. */ #define LINKTYPE_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */ /* * Juniper-private data link type, as per request from * Hannes Gredler . The corresponding * DLT_s are used for passing on chassis-internal * metainformation such as QOS profiles, etc.. */ #define LINKTYPE_JUNIPER_MONITOR 164 /* * Reserved for BACnet MS/TP. */ #define LINKTYPE_BACNET_MS_TP 165 /* * Another PPP variant as per request from Karsten Keil . * * This is used in some OSes to allow a kernel socket filter to distinguish * between incoming and outgoing packets, on a socket intended to * supply pppd with outgoing packets so it can do dial-on-demand and * hangup-on-lack-of-demand; incoming packets are filtered out so they * don't cause pppd to hold the connection up (you don't want random * input packets such as port scans, packets from old lost connections, * etc. to force the connection to stay up). * * The first byte of the PPP header (0xff03) is modified to accomodate * the direction - 0x00 = IN, 0x01 = OUT. */ #define LINKTYPE_PPP_PPPD 166 /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, cookies, etc.. */ #define LINKTYPE_JUNIPER_PPPOE 167 #define LINKTYPE_JUNIPER_PPPOE_ATM 168 #define LINKTYPE_GPRS_LLC 169 /* GPRS LLC */ #define LINKTYPE_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */ #define LINKTYPE_GPF_F 171 /* GPF-T (ITU-T G.7041/Y.1303) */ /* * Requested by Oolan Zimmer for use in Gcom's T1/E1 line * monitoring equipment. */ #define LINKTYPE_GCOM_T1E1 172 #define LINKTYPE_GCOM_SERIAL 173 /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_ is used * for internal communication to Physical Interface Cards (PIC) */ #define LINKTYPE_JUNIPER_PIC_PEER 174 /* * Link types requested by Gregor Maier of Endace * Measurement Systems. They add an ERF header (see * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of * the link-layer header. */ #define LINKTYPE_ERF_ETH 175 /* Ethernet */ #define LINKTYPE_ERF_POS 176 /* Packet-over-SONET */ /* * Requested by Daniele Orlandi for raw LAPD * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header * includes additional information before the LAPD header, so it's * not necessarily a generic LAPD header. */ #define LINKTYPE_LINUX_LAPD 177 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The Link Types are used for prepending meta-information * like interface index, interface name * before standard Ethernet, PPP, Frelay & C-HDLC Frames */ #define LINKTYPE_JUNIPER_ETHER 178 #define LINKTYPE_JUNIPER_PPP 179 #define LINKTYPE_JUNIPER_FRELAY 180 #define LINKTYPE_JUNIPER_CHDLC 181 /* * Multi Link Frame Relay (FRF.16) */ #define LINKTYPE_MFR 182 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * voice Adapter Card (PIC) */ #define LINKTYPE_JUNIPER_VP 183 /* * Arinc 429 frames. * DLT_ requested by Gianluca Varenni . * Every frame contains a 32bit A429 label. * More documentation on Arinc 429 can be found at * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf */ #define LINKTYPE_A429 184 /* * Arinc 653 Interpartition Communication messages. * DLT_ requested by Gianluca Varenni . * Please refer to the A653-1 standard for more information. */ #define LINKTYPE_A653_ICM 185 /* * USB packets, beginning with a USB setup header; requested by * Paolo Abeni . */ #define LINKTYPE_USB 186 /* * Bluetooth HCI UART transport layer (part H:4); requested by * Paolo Abeni. */ #define LINKTYPE_BLUETOOTH_HCI_H4 187 /* * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz * . */ #define LINKTYPE_IEEE802_16_MAC_CPS 188 /* * USB packets, beginning with a Linux USB header; requested by * Paolo Abeni . */ #define LINKTYPE_USB_LINUX 189 /* * Controller Area Network (CAN) v. 2.0B packets. * DLT_ requested by Gianluca Varenni . * Used to dump CAN packets coming from a CAN Vector board. * More documentation on the CAN v2.0B frames can be found at * http://www.can-cia.org/downloads/?269 */ #define LINKTYPE_CAN20B 190 /* * IEEE 802.15.4, with address fields padded, as is done by Linux * drivers; requested by Juergen Schimmer. */ #define LINKTYPE_IEEE802_15_4_LINUX 191 /* * Per Packet Information encapsulated packets. * LINKTYPE_ requested by Gianluca Varenni . */ #define LINKTYPE_PPI 192 /* * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header; * requested by Charles Clancy. */ #define LINKTYPE_IEEE802_16_MAC_CPS_RADIO 193 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * integrated service module (ISM). */ #define LINKTYPE_JUNIPER_ISM 194 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing); requested by Mikko Saarnivala . */ #define LINKTYPE_IEEE802_15_4 195 /* * Various link-layer types, with a pseudo-header, for SITA * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com). */ #define LINKTYPE_SITA 196 static struct linktype_map { int dlt; int linktype; } map[] = { /* * These DLT_* codes have LINKTYPE_* codes with values identical * to the values of the corresponding DLT_* code. */ { DLT_NULL, LINKTYPE_NULL }, { DLT_EN10MB, LINKTYPE_ETHERNET }, { DLT_EN3MB, LINKTYPE_EXP_ETHERNET }, { DLT_AX25, LINKTYPE_AX25 }, { DLT_PRONET, LINKTYPE_PRONET }, { DLT_CHAOS, LINKTYPE_CHAOS }, { DLT_IEEE802, LINKTYPE_TOKEN_RING }, { DLT_ARCNET, LINKTYPE_ARCNET }, { DLT_SLIP, LINKTYPE_SLIP }, { DLT_PPP, LINKTYPE_PPP }, { DLT_FDDI, LINKTYPE_FDDI }, /* * These DLT_* codes have different values on different * platforms; we map them to LINKTYPE_* codes that * have values that should never be equal to any DLT_* * code. */ #ifdef DLT_FR /* BSD/OS Frame Relay */ { DLT_FR, LINKTYPE_FRELAY }, #endif { DLT_SYMANTEC_FIREWALL, LINKTYPE_SYMANTEC_FIREWALL }, { DLT_ATM_RFC1483, LINKTYPE_ATM_RFC1483 }, { DLT_RAW, LINKTYPE_RAW }, { DLT_SLIP_BSDOS, LINKTYPE_SLIP_BSDOS }, { DLT_PPP_BSDOS, LINKTYPE_PPP_BSDOS }, /* BSD/OS Cisco HDLC */ { DLT_C_HDLC, LINKTYPE_C_HDLC }, /* * These DLT_* codes are not on all platforms, but, so far, * there don't appear to be any platforms that define * other codes with those values; we map them to * different LINKTYPE_* values anyway, just in case. */ /* Linux ATM Classical IP */ { DLT_ATM_CLIP, LINKTYPE_ATM_CLIP }, /* NetBSD sync/async serial PPP (or Cisco HDLC) */ { DLT_PPP_SERIAL, LINKTYPE_PPP_HDLC }, /* NetBSD PPP over Ethernet */ { DLT_PPP_ETHER, LINKTYPE_PPP_ETHER }, /* IEEE 802.11 wireless */ { DLT_IEEE802_11, LINKTYPE_IEEE802_11 }, /* Frame Relay */ { DLT_FRELAY, LINKTYPE_FRELAY }, /* OpenBSD loopback */ { DLT_LOOP, LINKTYPE_LOOP }, /* Linux cooked socket capture */ { DLT_LINUX_SLL, LINKTYPE_LINUX_SLL }, /* Apple LocalTalk hardware */ { DLT_LTALK, LINKTYPE_LTALK }, /* Acorn Econet */ { DLT_ECONET, LINKTYPE_ECONET }, /* OpenBSD DLT_PFLOG */ { DLT_PFLOG, LINKTYPE_PFLOG }, /* For Cisco-internal use */ { DLT_CISCO_IOS, LINKTYPE_CISCO_IOS }, /* Prism II monitor-mode header plus 802.11 header */ { DLT_PRISM_HEADER, LINKTYPE_PRISM_HEADER }, /* FreeBSD Aironet driver stuff */ { DLT_AIRONET_HEADER, LINKTYPE_AIRONET_HEADER }, /* Siemens HiPath HDLC */ { DLT_HHDLC, LINKTYPE_HHDLC }, /* RFC 2625 IP-over-Fibre Channel */ { DLT_IP_OVER_FC, LINKTYPE_IP_OVER_FC }, /* Solaris+SunATM */ { DLT_SUNATM, LINKTYPE_SUNATM }, /* RapidIO */ { DLT_RIO, LINKTYPE_RIO }, /* PCI Express */ { DLT_PCI_EXP, LINKTYPE_PCI_EXP }, /* Xilinx Aurora link layer */ { DLT_AURORA, LINKTYPE_AURORA }, /* 802.11 plus BSD radio header */ { DLT_IEEE802_11_RADIO, LINKTYPE_IEEE802_11_RADIO }, /* Tazmen Sniffer Protocol */ { DLT_TZSP, LINKTYPE_TZSP }, /* Arcnet with Linux-style link-layer headers */ { DLT_ARCNET_LINUX, LINKTYPE_ARCNET_LINUX }, /* Juniper-internal chassis encapsulation */ { DLT_JUNIPER_MLPPP, LINKTYPE_JUNIPER_MLPPP }, { DLT_JUNIPER_MLFR, LINKTYPE_JUNIPER_MLFR }, { DLT_JUNIPER_ES, LINKTYPE_JUNIPER_ES }, { DLT_JUNIPER_GGSN, LINKTYPE_JUNIPER_GGSN }, { DLT_JUNIPER_MFR, LINKTYPE_JUNIPER_MFR }, { DLT_JUNIPER_ATM2, LINKTYPE_JUNIPER_ATM2 }, { DLT_JUNIPER_SERVICES, LINKTYPE_JUNIPER_SERVICES }, { DLT_JUNIPER_ATM1, LINKTYPE_JUNIPER_ATM1 }, /* Apple IP-over-IEEE 1394 cooked header */ { DLT_APPLE_IP_OVER_IEEE1394, LINKTYPE_APPLE_IP_OVER_IEEE1394 }, /* SS7 */ { DLT_MTP2_WITH_PHDR, LINKTYPE_MTP2_WITH_PHDR }, { DLT_MTP2, LINKTYPE_MTP2 }, { DLT_MTP3, LINKTYPE_MTP3 }, { DLT_SCCP, LINKTYPE_SCCP }, /* DOCSIS MAC frames */ { DLT_DOCSIS, LINKTYPE_DOCSIS }, /* IrDA IrLAP packets + Linux-cooked header */ { DLT_LINUX_IRDA, LINKTYPE_LINUX_IRDA }, /* IBM SP and Next Federation switches */ { DLT_IBM_SP, LINKTYPE_IBM_SP }, { DLT_IBM_SN, LINKTYPE_IBM_SN }, /* 802.11 plus AVS radio header */ { DLT_IEEE802_11_RADIO_AVS, LINKTYPE_IEEE802_11_RADIO_AVS }, /* * Any platform that defines additional DLT_* codes should: * * request a LINKTYPE_* code and value from tcpdump.org, * as per the above; * * add, in their version of libpcap, an entry to map * those DLT_* codes to the corresponding LINKTYPE_* * code; * * redefine, in their "net/bpf.h", any DLT_* values * that collide with the values used by their additional * DLT_* codes, to remove those collisions (but without * making them collide with any of the LINKTYPE_* * values equal to 50 or above; they should also avoid * defining DLT_* values that collide with those * LINKTYPE_* values, either). */ /* Juniper-internal chassis encapsulation */ { DLT_JUNIPER_MONITOR, LINKTYPE_JUNIPER_MONITOR }, /* BACnet MS/TP */ { DLT_BACNET_MS_TP, LINKTYPE_BACNET_MS_TP }, /* PPP for pppd, with direction flag in the PPP header */ { DLT_PPP_PPPD, LINKTYPE_PPP_PPPD}, /* Juniper-internal chassis encapsulation */ { DLT_JUNIPER_PPPOE, LINKTYPE_JUNIPER_PPPOE }, { DLT_JUNIPER_PPPOE_ATM,LINKTYPE_JUNIPER_PPPOE_ATM }, /* GPRS LLC */ { DLT_GPRS_LLC, LINKTYPE_GPRS_LLC }, /* Transparent Generic Framing Procedure (ITU-T G.7041/Y.1303) */ { DLT_GPF_T, LINKTYPE_GPF_T }, /* Framed Generic Framing Procedure (ITU-T G.7041/Y.1303) */ { DLT_GPF_F, LINKTYPE_GPF_F }, { DLT_GCOM_T1E1, LINKTYPE_GCOM_T1E1 }, { DLT_GCOM_SERIAL, LINKTYPE_GCOM_SERIAL }, /* Juniper-internal chassis encapsulation */ { DLT_JUNIPER_PIC_PEER, LINKTYPE_JUNIPER_PIC_PEER }, /* Endace types */ { DLT_ERF_ETH, LINKTYPE_ERF_ETH }, { DLT_ERF_POS, LINKTYPE_ERF_POS }, /* viSDN LAPD */ { DLT_LINUX_LAPD, LINKTYPE_LINUX_LAPD }, /* Juniper meta-information before Ether, PPP, Frame Relay, C-HDLC Frames */ { DLT_JUNIPER_ETHER, LINKTYPE_JUNIPER_ETHER }, { DLT_JUNIPER_PPP, LINKTYPE_JUNIPER_PPP }, { DLT_JUNIPER_FRELAY, LINKTYPE_JUNIPER_FRELAY }, { DLT_JUNIPER_CHDLC, LINKTYPE_JUNIPER_CHDLC }, /* Multi Link Frame Relay (FRF.16) */ { DLT_MFR, LINKTYPE_MFR }, /* Juniper Voice PIC */ { DLT_JUNIPER_VP, LINKTYPE_JUNIPER_VP }, /* Controller Area Network (CAN) v2.0B */ { DLT_A429, LINKTYPE_A429 }, /* Arinc 653 Interpartition Communication messages */ { DLT_A653_ICM, LINKTYPE_A653_ICM }, /* USB */ { DLT_USB, LINKTYPE_USB }, /* Bluetooth HCI UART transport layer */ { DLT_BLUETOOTH_HCI_H4, LINKTYPE_BLUETOOTH_HCI_H4 }, /* IEEE 802.16 MAC Common Part Sublayer */ { DLT_IEEE802_16_MAC_CPS, LINKTYPE_IEEE802_16_MAC_CPS }, /* USB with Linux header */ { DLT_USB_LINUX, LINKTYPE_USB_LINUX }, /* Controller Area Network (CAN) v2.0B */ { DLT_CAN20B, LINKTYPE_CAN20B }, /* IEEE 802.15.4 with address fields padded */ { DLT_IEEE802_15_4_LINUX, LINKTYPE_IEEE802_15_4_LINUX }, /* Per Packet Information encapsulated packets */ { DLT_PPI, LINKTYPE_PPI }, /* IEEE 802.16 MAC Common Part Sublayer plus radiotap header */ { DLT_IEEE802_16_MAC_CPS_RADIO, LINKTYPE_IEEE802_16_MAC_CPS_RADIO }, /* Juniper Voice ISM */ { DLT_JUNIPER_ISM, LINKTYPE_JUNIPER_ISM }, /* IEEE 802.15.4 exactly as it appears in the spec */ { DLT_IEEE802_15_4, LINKTYPE_IEEE802_15_4 }, /* Various link-layer types for SITA */ { DLT_SITA, LINKTYPE_SITA }, { -1, -1 } }; static int dlt_to_linktype(int dlt) { int i; for (i = 0; map[i].dlt != -1; i++) { if (map[i].dlt == dlt) return (map[i].linktype); } /* * If we don't have a mapping for this DLT_ code, return an * error; that means that the table above needs to have an * entry added. */ return (-1); } static int linktype_to_dlt(int linktype) { int i; for (i = 0; map[i].linktype != -1; i++) { if (map[i].linktype == linktype) return (map[i].dlt); } /* * If we don't have an entry for this link type, return * the link type value; it may be a DLT_ value from an * older version of libpcap. */ return linktype; } 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); } static int sf_getnonblock(pcap_t *p, char *errbuf) { /* * This is a savefile, not a live capture file, so never say * it's in non-blocking mode. */ return (0); } static int sf_setnonblock(pcap_t *p, int nonblock, char *errbuf) { /* * This is a savefile, not a live capture file, so ignore * requests to put it in non-blocking mode. */ return (0); } static int sf_stats(pcap_t *p, struct pcap_stat *ps) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Statistics aren't available from savefiles"); return (-1); } static int sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) { strlcpy(p->errbuf, "Sending packets isn't supported on savefiles", PCAP_ERRBUF_SIZE); return (-1); } /* * Set direction flag: Which packets do we accept on a forwarding * single device? IN, OUT or both? */ static int sf_setdirection(pcap_t *p, pcap_direction_t d) { snprintf(p->errbuf, sizeof(p->errbuf), "Setting direction is not supported on savefiles"); return (-1); } static void sf_close(pcap_t *p) { if (p->sf.rfile != stdin) (void)fclose(p->sf.rfile); if (p->sf.base != NULL) free(p->sf.base); } pcap_t * pcap_open_offline(const char *fname, char *errbuf) { FILE *fp; pcap_t *p; if (fname[0] == '-' && fname[1] == '\0') { fp = stdin; #if defined(WIN32) || defined(MSDOS) /* * We're reading from the standard input, so put it in binary * mode, as savefiles are binary files. */ SET_BINMODE(fp); #endif } else { #if !defined(WIN32) && !defined(MSDOS) fp = fopen(fname, "r"); #else fp = fopen(fname, "rb"); #endif if (fp == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, pcap_strerror(errno)); return (NULL); } } p = pcap_fopen_offline(fp, errbuf); if (p == NULL) { if (fp != stdin) fclose(fp); } return (p); } pcap_t * pcap_fopen_offline(FILE *fp, char *errbuf) { register pcap_t *p; struct pcap_file_header hdr; size_t amt_read; bpf_u_int32 magic; int linklen; p = (pcap_t *)malloc(sizeof(*p)); if (p == NULL) { strlcpy(errbuf, "out of swap", PCAP_ERRBUF_SIZE); return (NULL); } memset((char *)p, 0, sizeof(*p)); amt_read = fread((char *)&hdr, 1, sizeof(hdr), fp); if (amt_read != sizeof(hdr)) { if (ferror(fp)) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", pcap_strerror(errno)); } else { snprintf(errbuf, PCAP_ERRBUF_SIZE, "truncated dump file; tried to read %lu file header bytes, only got %lu", (unsigned long)sizeof(hdr), (unsigned long)amt_read); } goto bad; } magic = hdr.magic; if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) { magic = SWAPLONG(magic); if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bad dump file format"); goto bad; } p->sf.swapped = 1; swap_hdr(&hdr); } if (magic == KUZNETZOV_TCPDUMP_MAGIC) { /* * XXX - the patch that's in some versions of libpcap * changes the packet header but not the magic number, * and some other versions with this magic number have * some extra debugging information in the packet header; * we'd have to use some hacks^H^H^H^H^Hheuristics to * detect those variants. * * Ethereal does that, but it does so by trying to read * the first two packets of the file with each of the * record header formats. That currently means it seeks * backwards and retries the reads, which doesn't work * on pipes. We want to be able to read from a pipe, so * that strategy won't work; we'd have to buffer some * data ourselves and read from that buffer in order to * make that work. */ p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr); } else p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr); if (hdr.version_major < PCAP_VERSION_MAJOR) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "archaic file format"); goto bad; } p->tzoff = hdr.thiszone; p->snapshot = hdr.snaplen; p->linktype = linktype_to_dlt(hdr.linktype); if (magic == KUZNETZOV_TCPDUMP_MAGIC && p->linktype == DLT_EN10MB) { /* * This capture might have been done in raw mode or cooked * mode. * * If it was done in cooked mode, p->snapshot was passed * to recvfrom() as the buffer size, meaning that the * most packet data that would be copied would be * p->snapshot. However, a faked Ethernet header would * then have been added to it, so the most data that would * be in a packet in the file would be p->snapshot + 14. * * We can't easily tell whether the capture was done in * raw mode or cooked mode, so we'll assume it was * cooked mode, and add 14 to the snapshot length. That * means that, for a raw capture, the snapshot length will * be misleading if you use it to figure out why a capture * doesn't have all the packet data, but there's not much * we can do to avoid that. */ p->snapshot += 14; } p->sf.rfile = fp; #ifndef WIN32 p->bufsize = hdr.snaplen; #else /* Allocate the space for pcap_pkthdr as well. It will be used by pcap_read_ex */ p->bufsize = hdr.snaplen+sizeof(struct pcap_pkthdr); #endif /* 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; } if (p->bufsize < 0) p->bufsize = BPF_MAXBUFSIZE; p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT); if (p->sf.base == NULL) { strlcpy(errbuf, "out of swap", PCAP_ERRBUF_SIZE); goto bad; } 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 /* Padding only needed for live capture fcode */ p->fddipad = 0; #endif /* * 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. * * In addition, DG/UX tcpdump writes out files with a version * number of 543.0, and with the caplen and len fields in the * pre-2.3 order. */ switch (hdr.version_major) { case 2: if (hdr.version_minor < 3) p->sf.lengths_swapped = SWAPPED; else if (hdr.version_minor == 3) p->sf.lengths_swapped = MAYBE_SWAPPED; else p->sf.lengths_swapped = NOT_SWAPPED; break; case 543: p->sf.lengths_swapped = SWAPPED; break; default: p->sf.lengths_swapped = NOT_SWAPPED; break; } #if !defined(WIN32) && !defined(MSDOS) /* * You can do "select()" and "poll()" on plain files on most * platforms, and should be able to do so on pipes. * * You can't do "select()" on anything other than sockets in * Windows, so, on Win32 systems, we don't have "selectable_fd". */ p->selectable_fd = fileno(fp); #endif p->read_op = pcap_offline_read; p->inject_op = sf_inject; p->setfilter_op = install_bpf_program; p->setdirection_op = sf_setdirection; p->set_datalink_op = NULL; /* we don't support munging link-layer headers */ p->getnonblock_op = sf_getnonblock; p->setnonblock_op = sf_setnonblock; p->stats_op = sf_stats; p->close_op = sf_close; 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, u_int buflen) { struct pcap_sf_patched_pkthdr sf_hdr; FILE *fp = p->sf.rfile; size_t amt_read; bpf_u_int32 t; /* * Read the packet header; the structure we use as a buffer * is the longer structure for files generated by the patched * libpcap, but if the file has the magic number for an * unpatched libpcap we only read as many bytes as the regular * header has. */ amt_read = fread(&sf_hdr, 1, p->sf.hdrsize, fp); if (amt_read != p->sf.hdrsize) { if (ferror(fp)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", pcap_strerror(errno)); return (-1); } else { if (amt_read != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "truncated dump file; tried to read %d header bytes, only got %lu", p->sf.hdrsize, (unsigned long)amt_read); return (-1); } /* EOF */ return (1); } } if (p->sf.swapped) { /* these were written in opposite byte order */ hdr->caplen = SWAPLONG(sf_hdr.caplen); hdr->len = SWAPLONG(sf_hdr.len); hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec); hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec); } else { hdr->caplen = sf_hdr.caplen; hdr->len = sf_hdr.len; hdr->ts.tv_sec = sf_hdr.ts.tv_sec; hdr->ts.tv_usec = sf_hdr.ts.tv_usec; } /* Swap the caplen and len fields, if necessary. */ switch (p->sf.lengths_swapped) { case NOT_SWAPPED: break; case MAYBE_SWAPPED: if (hdr->caplen <= hdr->len) { /* * The captured length is <= the actual length, * so presumably they weren't swapped. */ break; } /* FALLTHROUGH */ case SWAPPED: t = hdr->caplen; hdr->caplen = hdr->len; hdr->len = t; break; } 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 size_t tsize = 0; if (hdr->caplen > 65535) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "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; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BUFMOD hack malloc"); return (-1); } } amt_read = fread((char *)tp, 1, hdr->caplen, fp); if (amt_read != hdr->caplen) { if (ferror(fp)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", pcap_strerror(errno)); } else { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "truncated dump file; tried to read %u captured bytes, only got %lu", hdr->caplen, (unsigned long)amt_read); } 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 */ amt_read = fread((char *)buf, 1, hdr->caplen, fp); if (amt_read != hdr->caplen) { if (ferror(fp)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", pcap_strerror(errno)); } else { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "truncated dump file; tried to read %u captured bytes, only got %lu", hdr->caplen, (unsigned long)amt_read); } 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. */ int pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { struct bpf_insn *fcode; int status = 0; int n = 0; while (status == 0) { struct pcap_pkthdr h; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else return (n); } status = sf_next_packet(p, &h, p->buffer, p->bufsize); if (status) { if (status == 1) return (0); return (status); } if ((fcode = p->fcode.bf_insns) == 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; struct pcap_sf_pkthdr sf_hdr; f = (FILE *)user; sf_hdr.ts.tv_sec = h->ts.tv_sec; sf_hdr.ts.tv_usec = h->ts.tv_usec; sf_hdr.caplen = h->caplen; sf_hdr.len = h->len; /* XXX we should check the return status */ (void)fwrite(&sf_hdr, sizeof(sf_hdr), 1, f); (void)fwrite(sp, h->caplen, 1, f); } static pcap_dumper_t * pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname) { #if defined(WIN32) || defined(MSDOS) /* * If we're writing to the standard output, put it in binary * mode, as savefiles are binary files. * * Otherwise, we turn off buffering. * XXX - why? And why not on the standard output? */ if (f == stdout) SET_BINMODE(f); else setbuf(f, NULL); #endif if (sf_write_header(f, linktype, p->tzoff, p->snapshot) == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s", fname, pcap_strerror(errno)); if (f != stdout) (void)fclose(f); return (NULL); } return ((pcap_dumper_t *)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; int linktype; linktype = dlt_to_linktype(p->linktype); if (linktype == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: link-layer type %d isn't supported in savefiles", fname, linktype); return (NULL); } if (fname[0] == '-' && fname[1] == '\0') { f = stdout; fname = "standard output"; } else { #if !defined(WIN32) && !defined(MSDOS) f = fopen(fname, "w"); #else f = fopen(fname, "wb"); #endif if (f == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, pcap_strerror(errno)); return (NULL); } } return (pcap_setup_dump(p, linktype, f, fname)); } /* * Initialize so that sf_write() will output to the given stream. */ pcap_dumper_t * pcap_dump_fopen(pcap_t *p, FILE *f) { int linktype; linktype = dlt_to_linktype(p->linktype); if (linktype == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "stream: link-layer type %d isn't supported in savefiles", linktype); return (NULL); } return (pcap_setup_dump(p, linktype, f, "stream")); } FILE * pcap_dump_file(pcap_dumper_t *p) { return ((FILE *)p); } long pcap_dump_ftell(pcap_dumper_t *p) { return (ftell((FILE *)p)); } int pcap_dump_flush(pcap_dumper_t *p) { if (fflush((FILE *)p) == EOF) return (-1); else return (0); } 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); } libpcap-0.9.7/./pcap-stdinc.h0000644000026300017500000000426210320053203013766 0ustar mcrmcr/* * Copyright (c) 2002 - 2003 * NetGroup, Politecnico di Torino (Italy) * 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. Neither the name of the Politecnico di Torino nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * */ #define SIZEOF_CHAR 1 #define SIZEOF_SHORT 2 #define SIZEOF_INT 4 #ifndef _MSC_EXTENSIONS #define SIZEOF_LONG_LONG 8 #endif /* * Avoids a compiler warning in case this was already defined * (someone defined _WINSOCKAPI_ when including 'windows.h', in order * to prevent it from including 'winsock.h') */ #ifdef _WINSOCKAPI_ #undef _WINSOCKAPI_ #endif #include #include #include "bittypes.h" #include #include #ifndef __MINGW32__ #include "IP6_misc.h" #endif #define caddr_t char* #define snprintf _snprintf #define vsnprintf _vsnprintf #define inline __inline libpcap-0.9.7/./pcap-enet.c0000644000026300017500000001161007755532622013454 0ustar mcrmcr/* * Stanford Enetfilter subroutines for tcpdump * * Based on the MERIT NNstat etherifrt.c and the Ultrix pcap-pf.c * subroutines. * * Rayan Zachariassen, CA*Net */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.8 2003/11/15 23:24:02 guy Exp $"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #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); } int 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); } libpcap-0.9.7/./ChmodBPF/0000755000026300017500000000000010245661222013002 5ustar mcrmcrlibpcap-0.9.7/./ChmodBPF/StartupParameters.plist0000644000026300017500000000017610134711007017543 0ustar mcrmcr{ Description = "Change BPF permissions"; Provides = ("Non-root permission to capture or send raw packets"); } libpcap-0.9.7/./ChmodBPF/CVS/0000755000026300017500000000000010245661222013435 5ustar mcrmcrlibpcap-0.9.7/./ChmodBPF/CVS/Entries0000644000026300017500000000017310245661222014772 0ustar mcrmcr/ChmodBPF/1.1/Mon Oct 18 09:51:03 2004//Tlibpcap_0_9 /StartupParameters.plist/1.1/Mon Oct 18 09:51:03 2004//Tlibpcap_0_9 D libpcap-0.9.7/./ChmodBPF/CVS/Root0000644000026300017500000000004010245661221014274 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./ChmodBPF/CVS/Repository0000644000026300017500000000002110245661221015527 0ustar mcrmcrlibpcap/ChmodBPF libpcap-0.9.7/./ChmodBPF/CVS/Tag0000644000026300017500000000001510245661222014067 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./ChmodBPF/ChmodBPF0000755000026300017500000000160410134711007014305 0ustar mcrmcr#! /bin/sh . /etc/rc.common StartService () { # # Unfortunately, Mac OS X's devfs is based on the old FreeBSD # one, not the current one, so there's no way to configure it # to create BPF devices with particular owners or groups. # This startup item will make it owned by the admin group, # with permissions rw-rw----, so that anybody in the admin # group can use programs that capture or send raw packets. # # Change this as appropriate for your site, e.g. to make # it owned by a particular user without changing the permissions, # so only that user and the super-user can capture or send raw # packets, or give it the permissions rw-r-----, so that # only the super-user can send raw packets but anybody in the # admin group can capture packets. # chgrp admin /dev/bpf* chmod g+rw /dev/bpf* } StopService () { return 0; } RestartService () { StartService; } RunService "$1" libpcap-0.9.7/./pcap-win32.c0000644000026300017500000004560610643174161013465 0ustar mcrmcr/* * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) * Copyright (c) 2005 - 2007 CACE Technologies, Davis (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. Neither the name of the Politecnico di Torino, CACE Technologies * nor the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.25.2.7 2007/06/14 22:07:14 gianluca Exp $ (LBL)"; #endif #include #include #include #ifdef HAVE_DAG_API #include #include #endif /* HAVE_DAG_API */ #ifdef __MINGW32__ int* _errno(); #define errno (*_errno()) #endif /* __MINGW32__ */ static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *); static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *); static int pcap_getnonblock_win32(pcap_t *, char *); static int pcap_setnonblock_win32(pcap_t *, int, char *); #define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/ #define SIZE_BUF 1000000 /* Equivalent to ntohs(), but a lot faster under Windows */ #define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8) /* * Header that the WinPcap driver associates to the packets. * Once was in bpf.h */ struct bpf_hdr { struct timeval bh_tstamp; /* time stamp */ bpf_u_int32 bh_caplen; /* length of captured portion */ bpf_u_int32 bh_datalen; /* original length of packet */ u_short bh_hdrlen; /* length of bpf header (this struct plus alignment padding) */ }; /* Start winsock */ int wsockinit() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return -1; } return 0; } static int pcap_stats_win32(pcap_t *p, struct pcap_stat *ps) { if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror()); return -1; } return 0; } static int pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; int n = 0; register u_char *bp, *ep; cc = p->cc; if (p->cc == 0) { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return -2 to indicate that we were * told to break out of the loop. */ p->break_loop = 0; return (-2); } /* capture the packets */ if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); return (-1); } cc = p->Packet->ulBytesReceived; bp = p->Packet->Buffer; } else bp = p->bp; /* * Loop through each packet. */ #define bhp ((struct bpf_hdr *)bp) ep = bp + cc; while (1) { register int caplen, hdrlen; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = bp; p->cc = ep - bp; return (n); } } if (bp >= ep) break; 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); } #ifdef HAVE_DAG_API static int pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { u_char *dp = NULL; int packet_len = 0, caplen = 0; struct pcap_pkthdr pcap_header; u_char *endofbuf; int n = 0; dag_record_t *header; unsigned erf_record_len; ULONGLONG ts; int cc; unsigned swt; unsigned dfp = p->adapter->DagFastProcess; cc = p->cc; if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */ { /* Get new packets from the network */ if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); return (-1); } cc = p->Packet->ulBytesReceived; if(cc == 0) /* The timeout has expired but we no packets arrived */ return 0; header = (dag_record_t*)p->adapter->DagBuffer; } else header = (dag_record_t*)p->bp; endofbuf = (char*)header + cc; /* * Cycle through the packets */ do { erf_record_len = SWAPS(header->rlen); if((char*)header + erf_record_len > endofbuf) break; /* Increase the number of captured packets */ p->md.stat.ps_recv++; /* Find the beginning of the packet */ dp = ((u_char *)header) + dag_record_size; /* Determine actual packet len */ switch(header->type) { case TYPE_ATM: packet_len = ATM_SNAPLEN; caplen = ATM_SNAPLEN; dp += 4; break; case TYPE_ETH: swt = SWAPS(header->wlen); packet_len = swt - (p->md.dag_fcs_bits); caplen = erf_record_len - dag_record_size - 2; if (caplen > packet_len) { caplen = packet_len; } dp += 2; break; case TYPE_HDLC_POS: swt = SWAPS(header->wlen); packet_len = swt - (p->md.dag_fcs_bits); caplen = erf_record_len - dag_record_size; if (caplen > packet_len) { caplen = packet_len; } break; } if(caplen > p->snapshot) caplen = p->snapshot; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = (char*)header; p->cc = endofbuf - (char*)header; return (n); } } if(!dfp) { /* convert between timestamp formats */ ts = header->ts; pcap_header.ts.tv_sec = (int)(ts >> 32); ts = (ts & 0xffffffffi64) * 1000000; ts += 0x80000000; /* rounding */ pcap_header.ts.tv_usec = (int)(ts >> 32); if (pcap_header.ts.tv_usec >= 1000000) { pcap_header.ts.tv_usec -= 1000000; pcap_header.ts.tv_sec++; } } /* No underlaying filtering system. We need to filter on our own */ if (p->fcode.bf_insns) { if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0) { /* Move to next packet */ header = (dag_record_t*)((char*)header + erf_record_len); continue; } } /* Fill the header for the user suppplied callback function */ pcap_header.caplen = caplen; pcap_header.len = packet_len; /* Call the callback function */ (*callback)(user, &pcap_header, dp); /* Move to next packet */ header = (dag_record_t*)((char*)header + erf_record_len); /* Stop if the number of packets requested by user has been reached*/ if (++n >= cnt && cnt > 0) { p->bp = (char*)header; p->cc = endofbuf - (char*)header; return (n); } } while((u_char*)header < endofbuf); return 1; } #endif /* HAVE_DAG_API */ /* Send a packet to the network */ static int pcap_inject_win32(pcap_t *p, const void *buf, size_t size){ LPPACKET PacketToSend; PacketToSend=PacketAllocatePacket(); if (PacketToSend == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed"); return -1; } PacketInitPacket(PacketToSend,(PVOID)buf,size); if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed"); PacketFreePacket(PacketToSend); return -1; } PacketFreePacket(PacketToSend); /* * We assume it all got sent if "PacketSendPacket()" succeeded. * "pcap_inject()" is expected to return the number of bytes * sent. */ return size; } static void pcap_close_win32(pcap_t *p) { pcap_close_common(p); if (p->adapter != NULL) { PacketCloseAdapter(p->adapter); p->adapter = NULL; } if (p->Packet) { PacketFreePacket(p->Packet); p->Packet = NULL; } } pcap_t * pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { register pcap_t *p; NetType type; /* Init WinSock */ wsockinit(); p = (pcap_t *)malloc(sizeof(*p)); if (p == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } memset(p, 0, sizeof(*p)); p->adapter=NULL; p->adapter = PacketOpenAdapter((char*)device); if (p->adapter == NULL) { free(p); /* Adapter detected but we are not able to open it. Return failure. */ snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror()); return NULL; } /*get network type*/ if(PacketGetNetType (p->adapter,&type) == FALSE) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); goto bad; } /*Set the linktype*/ switch (type.LinkType) { case NdisMediumWan: p->linktype = DLT_EN10MB; break; case NdisMedium802_3: p->linktype = DLT_EN10MB; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } break; case NdisMediumFddi: p->linktype = DLT_FDDI; break; case NdisMedium802_5: p->linktype = DLT_IEEE802; break; case NdisMediumArcnetRaw: p->linktype = DLT_ARCNET; break; case NdisMediumArcnet878_2: p->linktype = DLT_ARCNET; break; case NdisMediumAtm: p->linktype = DLT_ATM_RFC1483; break; case NdisMediumCHDLC: p->linktype = DLT_CHDLC; break; case NdisMediumPPPSerial: p->linktype = DLT_PPP_SERIAL; break; case NdisMediumNull: p->linktype = DLT_NULL; break; case NdisMediumBare80211: p->linktype = DLT_IEEE802_11; break; case NdisMediumRadio80211: p->linktype = DLT_IEEE802_11_RADIO; break; case NdisMediumPpi: p->linktype = DLT_PPI; break; default: p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/ break; } /* Set promiscuous mode */ if (promisc) { if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode"); goto bad; } } else { if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode"); goto bad; } } /* Set the buffer size */ p->bufsize = PcapBufSize; /* Store the timeout. Used by pcap_setnonblock() */ p->timeout= to_ms; /* allocate Packet structure used during the capture */ if((p->Packet = PacketAllocatePacket())==NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure"); goto bad; } if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD)) { /* * Traditional Adapter */ p->buffer = (u_char *)malloc(PcapBufSize); if (p->buffer == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); p->snapshot = snaplen; /* allocate the standard buffer in the driver */ if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE) { snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n"); goto bad; } /* tell the driver to copy the buffer only if it contains at least 16K */ if(PacketSetMinToCopy(p->adapter,16000)==FALSE) { snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror()); goto bad; } } else #ifdef HAVE_DAG_API { /* * Dag Card */ LONG status; HKEY dagkey; DWORD lptype; DWORD lpcbdata; int postype = 0; char keyname[512]; snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s", "SYSTEM\\CurrentControlSet\\Services\\DAG", strstr(_strlwr((char*)device), "dag")); do { status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey); if(status != ERROR_SUCCESS) break; status = RegQueryValueEx(dagkey, "PosType", NULL, &lptype, (char*)&postype, &lpcbdata); if(status != ERROR_SUCCESS) { postype = 0; } RegCloseKey(dagkey); } while(FALSE); p->snapshot = PacketSetSnapLen(p->adapter, snaplen); /* Set the length of the FCS associated to any packet. This value * will be subtracted to the packet length */ p->md.dag_fcs_bits = p->adapter->DagFcsLen; } #else goto bad; #endif /* HAVE_DAG_API */ PacketSetReadTimeout(p->adapter, to_ms); #ifdef HAVE_DAG_API if(p->adapter->Flags & INFO_FLAG_DAG_CARD) { /* install dag specific handlers for read and setfilter */ p->read_op = pcap_read_win32_dag; p->setfilter_op = pcap_setfilter_win32_dag; } else { #endif /* HAVE_DAG_API */ /* install traditional npf handlers for read and setfilter */ p->read_op = pcap_read_win32_npf; p->setfilter_op = pcap_setfilter_win32_npf; #ifdef HAVE_DAG_API } #endif /* HAVE_DAG_API */ p->setdirection_op = NULL; /* Not implemented. */ /* XXX - can this be implemented on some versions of Windows? */ p->inject_op = pcap_inject_win32; p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_win32; p->setnonblock_op = pcap_setnonblock_win32; p->stats_op = pcap_stats_win32; p->close_op = pcap_close_win32; return (p); bad: if (p->adapter) PacketCloseAdapter(p->adapter); if (p->buffer != NULL) free(p->buffer); if(p->Packet) PacketFreePacket(p->Packet); /* * Get rid of any link-layer type list we allocated. */ if (p->dlt_list != NULL) free(p->dlt_list); free(p); return (NULL); } static int pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp) { if(PacketSetBpf(p->adapter,fp)==FALSE){ /* * Kernel filter not installed. * XXX - fall back on userland filtering, as is done * on other platforms? */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror()); return (-1); } /* * Discard any previously-received packets, as they might have * passed whatever filter was formerly in effect, but might * not pass this filter (BIOCSETF discards packets buffered * in the kernel, so you can lose packets in any case). */ p->cc = 0; return (0); } /* * We filter at user level, since the kernel driver does't process the packets */ static int pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) { if(!fp) { strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf)); return -1; } /* Install a user level filter */ if (install_bpf_program(p, fp) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "setfilter, unable to install the filter: %s", pcap_strerror(errno)); return -1; } p->md.use_bpf = 0; return (0); } static int pcap_getnonblock_win32(pcap_t *p, char *errbuf) { /* * XXX - if there were a PacketGetReadTimeout() call, we * would use it, and return 1 if the timeout is -1 * and 0 otherwise. */ return (p->nonblock); } static int pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf) { int newtimeout; if (nonblock) { /* * Set the read timeout to -1 for non-blocking mode. */ newtimeout = -1; } else { /* * Restore the timeout set when the device was opened. * (Note that this may be -1, in which case we're not * really leaving non-blocking mode.) */ newtimeout = p->timeout; } if (!PacketSetReadTimeout(p->adapter, newtimeout)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketSetReadTimeout: %s", pcap_win32strerror()); return (-1); } p->nonblock = (newtimeout == -1); return (0); } /* Set the driver working mode */ int pcap_setmode(pcap_t *p, int mode){ if (p->adapter==NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file"); return -1; } if(PacketSetMode(p->adapter,mode)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized"); return -1; } return 0; } /* Set the dimension of the kernel-level capture buffer */ int pcap_setbuff(pcap_t *p, int dim) { if (p->adapter==NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file"); return -1; } if(PacketSetBuff(p->adapter,dim)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); return -1; } return 0; } /*set the minimum amount of data that will release a read call*/ int pcap_setmintocopy(pcap_t *p, int size) { if (p->adapter==NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture"); return -1; } if(PacketSetMinToCopy(p->adapter, size)==FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size"); return -1; } return 0; } libpcap-0.9.7/./README.macosx0000644000026300017500000000436410134711006013571 0ustar mcrmcrAs with other systems using BPF, Mac OS X allows users with read access to the BPF devices to capture packets with libpcap and allows users with write access to the BPF devices to send packets with libpcap. On some systems that use BPF, the BPF devices live on the root file system, and the permissions and/or ownership on those devices can be changed to give users other than root permission to read or write those devices. On newer versions of FreeBSD, the BPF devices live on devfs, and devfs can be configured to set the permissions and/or ownership of those devices to give users other than root permission to read or write those devices. On Mac OS X, the BPF devices live on devfs, but the OS X version of devfs is based on an older (non-default) FreeBSD devfs, and that version of devfs cannot be configured to set the permissions and/or ownership of those devices. Therefore, we supply a "startup item" for OS X that will change the ownership of the BPF devices so that the "admin" group owns them, and will change the permission of the BPF devices to rw-rw----, so that all users in the "admin" group - i.e., all users with "Allow user to administer this computer" turned on - have both read and write access to them. The startup item is in the ChmodBPF directory in the source tree. A /Library/StartupItems directory should be created if it doesn't already exist, and the ChmodBPF directory should be copied to the /Library/StartupItems directory (copy the entire directory, so that there's a /Library/StartupItems/ChmodBPF directory, containing all the files in the source tree's ChmodBPF directory; don't copy the individual items in that directory to /Library/StartupItems). If you want to give a particular user permission to access the BPF devices, rather than giving all administrative users permission to access them, you can have the ChmodBPF/ChmodBPF script change the ownership of /dev/bpf* without changing the permissions. If you want to give a particular user permission to read and write the BPF devices and give the administrative users permission to read but not write the BPF devices, you can have the script change the owner to that user, the group to "admin", and the permissions to rw-r-----. Other possibilities are left as an exercise for the reader. libpcap-0.9.7/./arcnet.h0000644000026300017500000000472007271161120013045 0ustar mcrmcr/* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) $Id: arcnet.h,v 1.2 2001/04/24 02:17:52 guy Exp $ (LBL) * * from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp */ /* RFC 1051 */ #define ARCTYPE_IP_OLD 240 /* IP protocol */ #define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ /* RFC 1201 */ #define ARCTYPE_IP 212 /* IP protocol */ #define ARCTYPE_ARP 213 /* address resolution protocol */ #define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ #define ARCTYPE_ATALK 221 /* Appletalk */ #define ARCTYPE_BANIAN 247 /* Banyan Vines */ #define ARCTYPE_IPX 250 /* Novell IPX */ #define ARCTYPE_INET6 0xc4 /* IPng */ #define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */ libpcap-0.9.7/./optimize.c0000644000026300017500000014037310651225661013440 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.85.2.2 2007/07/15 19:55:04 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "pcap-int.h" #include "gencode.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #ifdef BDEBUG extern int dflag; #endif #if defined(MSDOS) && !defined(__DJGPP__) extern int _w32_ffs (int mask); #define ffs _w32_ffs #endif /* * Represents a deleted instruction. */ #define NOP -1 /* * Register numbers for use-def values. * 0 through BPF_MEMWORDS-1 represent the corresponding scratch memory * location. A_ATOM is the accumulator and X_ATOM is the index * register. */ #define A_ATOM BPF_MEMWORDS #define X_ATOM (BPF_MEMWORDS+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 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; } /* * Compute the sets of registers used, defined, and killed by 'b'. * * "Used" means that a statement in 'b' uses the register before any * statement in 'b' defines it, i.e. it uses the value left in * that register by a predecessor block of this block. * "Defined" means that a statement in 'b' defines it. * "Killed" means that a statement in 'b' defines it before any * statement in 'b' uses it, i.e. it kills the value left in that * register by a predecessor block of this block. */ 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 (BPF_CLASS(b->s.code) == BPF_JMP) { /* * XXX - what about RET? */ atom = atomuse(&b->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(); } } 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 *)hashtbl, 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_u_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; for (/*empty*/; /*empty*/; s = next) { /* * Skip over nops. */ s = this_op(s); if (s == 0) break; /* nothing left in the block */ /* * Find the next real instruction after that one * (skipping nops). */ next = this_op(s->next); if (next == 0) break; /* no next instruction */ 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)) continue; /* * Check that the instruction following the ldi * is an addx, or it's an ldxms with an addx * following it (with 0 or more nops between the * ldxms and addx). */ 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)) continue; /* * Check that a tax follows that (with 0 or more * nops between them). */ tax = this_op(add->next); if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX)) continue; /* * Check that an ild follows that (with 0 or more * nops between them). */ ild = this_op(tax->next); if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD || BPF_MODE(ild->s.code) != BPF_IND) continue; /* * 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] * * XXX We need to check that X is not * subsequently used, because we want to change * what'll be in it after this sequence. * * We know we can eliminate the accumulator * modifications earlier in the sequence since * it is defined by the last stmt of this sequence * (i.e., the last statement of the sequence loads * a value into the accumulator, so we can eliminate * earlier operations on the accumulator). */ ild->s.k += s->s.k; s->s.code = NOP; add->s.code = NOP; tax->s.code = NOP; done = 0; } } /* * If the comparison at the end of a block is an equality * comparison against a constant, and nobody uses the value * we leave in the A register at the end of a block, and * the operation preceding the comparison is an arithmetic * operation, we can sometime optimize it away. */ if (b->s.code == (BPF_JMP|BPF_JEQ|BPF_K) && !ATOMELEM(b->out_use, A_ATOM)) { /* * We can optimize away certain subtractions of the * X register. */ if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) { val = b->val[X_ATOM]; if (vmap[val].is_const) { /* * 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: * * sub x -> nop * jeq #y jeq #(x+y) */ b->s.k += vmap[val].const_val; last->s.code = NOP; done = 0; } else if (b->s.k == 0) { /* * If the X register isn't a constant, * and the comparison in the test is * against 0, we can compare with the * X register, instead: * * sub x -> nop * jeq #0 jeq x */ last->s.code = NOP; b->s.code = BPF_JMP|BPF_JEQ|BPF_X; done = 0; } } /* * Likewise, a constant subtract can be simplified: * * sub #x -> nop * jeq #y -> jeq #(x+y) */ else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) { last->s.code = NOP; b->s.k += last->s.k; done = 0; } /* * And, similarly, a constant AND can be simplified * if we're testing against 0, i.e.: * * and #k nop * jeq #0 -> jset #k */ else if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) && 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); } } /* * jset #0 -> never * jset #ffffffff -> always */ if (b->s.code == (BPF_JMP|BPF_K|BPF_JSET)) { if (b->s.k == 0) JT(b) = JF(b); if (b->s.k == 0xffffffff) JF(b) = JT(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) { /* don't optimize away "sub #0" * as it may be needed later to * fixup the generated math code */ if (op == BPF_ADD || 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, etc. */ if (alter && vmap[val[A_ATOM]].is_const && vmap[val[A_ATOM]].const_val == 0) { if (op == BPF_ADD || op == BPF_OR) { 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 || op == BPF_LSH || op == BPF_RSH) { 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, xval; #if 0 for (s = b->stmts; s && s->next; s = s->next) if (BPF_CLASS(s->s.code) == BPF_JMP) { do_stmts = 0; break; } #endif /* * Initialize the atom values. */ p = b->in_edges; if (p == 0) { /* * We have no predecessors, so everything is undefined * upon entry to this block. */ memset((char *)b->val, 0, sizeof(b->val)); } else { /* * Inherit values from our predecessors. * * First, get the values from the predecessor along the * first edge leading to this node. */ memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val)); /* * Now look at all the other nodes leading to this node. * If, for the predecessor along that edge, a register * has a different value from the one we have (i.e., * control paths are merging, and the merging paths * assign different values to that register), give the * register the undefined value of 0. */ 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]; xval = b->val[X_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 or index register with a * value that is already there, or if this block is a return, * eliminate all the statements. * * XXX - what if it does a store? * * XXX - why does it matter whether we use anything from this * block? If the accumulator or index register doesn't change * its value, isn't that OK even if we use that value? * * XXX - if we load the accumulator with a different value, * and the block ends with a conditional branch, we obviously * can't eliminate it, as the branch depends on that value. * For the index register, the conditional branch only depends * on the index register value if the test is against the index * register value rather than a constant; if nothing uses the * value we put into the index register, and we're not testing * against the index register's value, and there aren't any * other problems that would keep us from eliminating this * block, can we eliminate it? */ if (do_stmts && ((b->out_use == 0 && aval != 0 && b->val[A_ATOM] == aval && xval != 0 && b->val[X_ATOM] == xval) || 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 of the branch instructions 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. * * I.e., if we came down the true branch, and the branch * was an equality comparison with a constant, we know the * accumulator contains that constant. If we came down * the false branch, or the comparison wasn't with a * constant, we don't know what was in the accumulator. * * 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; find_inedges(root); 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); } } find_inedges(root); 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) { printf("opt_loop(root, %d) begin\n", do_stmts); opt_dump(root); } #endif do { done = 1; find_levels(root); find_dom(root); find_closure(root); find_ud(root); find_edom(root); opt_blks(root, do_stmts); #ifdef BDEBUG if (dflag > 1) { printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, done); 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); #ifdef BDEBUG if (dflag > 1) { printf("after intern_blocks()\n"); opt_dump(root); } #endif opt_root(rootp); #ifdef BDEBUG if (dflag > 1) { printf("after opt_root()\n"); opt_dump(root); } #endif 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 done1; /* don't shadow global */ top: done1 = 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) { done1 = 0; JT(p) = JT(p)->link; } if (JF(p)->link) { done1 = 0; JF(p) = JF(p)->link; } } if (!done1) 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. * * Note that "stmts" means "instructions", and that this includes * * side-effect statements in 'p' (slength(p->stmts)); * * statements in the true branch from 'p' (count_stmts(JT(p))); * * statements in the false branch from 'p' (count_stmts(JF(p))); * * the conditional jump itself (1); * * an extra long jump if the true branch requires it (p->longjt); * * an extra long jump if the false branch requires it (p->longjf). */ 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 + p->longjt + p->longjf; } /* * 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)); if (blocks == NULL) bpf_error("malloc"); unMarkAll(); n_blocks = 0; number_blks_r(root); n_edges = 2 * n_blocks; edges = (struct edge **)malloc(n_edges * sizeof(*edges)); if (edges == NULL) bpf_error("malloc"); /* * The number of levels is bounded by the number of nodes. */ levels = (struct block **)malloc(n_blocks * sizeof(*levels)); if (levels == NULL) bpf_error("malloc"); 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)); if (space == NULL) bpf_error("malloc"); 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(*vnode_base)); if (vmap == NULL || vnode_base == NULL) bpf_error("malloc"); } /* * 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 */ struct slist **offset = NULL; 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; /* generate offset[] for convenience */ if (slen) { offset = (struct slist **)calloc(slen, sizeof(struct slist *)); if (!offset) { bpf_error("not enough core"); /*NOTREACHED*/ } } src = p->stmts; for (off = 0; off < slen && src; off++) { #if 0 printf("off=%d src=%x\n", off, src); #endif offset[off] = src; src = src->next; } off = 0; 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; /* fill block-local relative jump */ if (BPF_CLASS(src->s.code) != BPF_JMP || src->s.code == (BPF_JMP|BPF_JA)) { #if 0 if (src->s.jt || src->s.jf) { bpf_error("illegal jmp destination"); /*NOTREACHED*/ } #endif goto filled; } if (off == slen - 2) /*???*/ goto filled; { int i; int jt, jf; const char *ljerr = "%s for block-local relative jump: off=%d"; #if 0 printf("code=%x off=%d %x %x\n", src->s.code, off, src->s.jt, src->s.jf); #endif if (!src->s.jt || !src->s.jf) { bpf_error(ljerr, "no jmp destination", off); /*NOTREACHED*/ } jt = jf = 0; for (i = 0; i < slen; i++) { if (offset[i] == src->s.jt) { if (jt) { bpf_error(ljerr, "multiple matches", off); /*NOTREACHED*/ } dst->jt = i - off - 1; jt++; } if (offset[i] == src->s.jf) { if (jf) { bpf_error(ljerr, "multiple matches", off); /*NOTREACHED*/ } dst->jf = i - off - 1; jf++; } } if (!jt || !jf) { bpf_error(ljerr, "no destination found", off); /*NOTREACHED*/ } } filled: ++dst; ++off; } if (offset) free(offset); #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. * * This routine does *NOT* leak the memory pointed to by fp. It *must * not* do free(fp) before returning fp; doing so would make no sense, * as the BPF array pointed to by the return value of icode_to_fcode() * must be valid - it's being returned for use in a bpf_program structure. * * If it appears that icode_to_fcode() is leaking, the problem is that * the program using pcap_compile() is failing to free the memory in * the BPF program when it's done - the leak is in the program, not in * the routine that happens to be allocating the memory. (By analogy, if * a program calls fopen() without ever calling fclose() on the FILE *, * it will leak the FILE structure; the leak is not in fopen(), it's in * the program.) Change the program to use pcap_freecode() when it's * done with the filter program. See the pcap man page. */ struct bpf_insn * icode_to_fcode(root, lenp) struct block *root; int *lenp; { int n; struct bpf_insn *fp; /* * Loop doing convert_code_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); if (fp == NULL) bpf_error("malloc"); memset((char *)fp, 0, sizeof(*fp) * n); fstart = fp; ftail = fp + n; unMarkAll(); if (convert_code_r(root)) break; free(fp); } return fp; } /* * Make a copy of a BPF program and put it in the "fcode" member of * a "pcap_t". * * If we fail to allocate memory for the copy, fill in the "errbuf" * member of the "pcap_t" with an error message, and return -1; * otherwise, return 0. */ int install_bpf_program(pcap_t *p, struct bpf_program *fp) { size_t prog_size; /* * Free up any already installed program. */ pcap_freecode(&p->fcode); prog_size = sizeof(*fp->bf_insns) * fp->bf_len; p->fcode.bf_len = fp->bf_len; p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size); if (p->fcode.bf_insns == NULL) { snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (-1); } memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size); return (0); } #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 libpcap-0.9.7/./pcap-pf.h0000644000026300017500000000171106777230340013127 0ustar mcrmcr/* * 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: /tcpdump/master/libpcap/pcap-pf.h,v 1.2.1.1 1999/10/07 23:46:40 mcr Exp $ (LBL) */ libpcap-0.9.7/./SUNOS4/0000755000026300017500000000000010245661223012414 5ustar mcrmcrlibpcap-0.9.7/./SUNOS4/nit_if.o.sparc0000644000026300017500000001213406777230341015164 0ustar mcrmcr ð¸¸X`ã¿ ³.`€¦à€³>`²`ú@¶ €"€ €¦áÔ`€¦À &€ €¦á²ú@¶à€2¿ÿùÔ`€¦á2€0’ – ¶?ÿ€^Ö(4Ѐ"€€Y¶?ÿ¶`ÿ²àú@€"€!’ à`€¦À6€ â`’ @ ¸€2€è ¦ ¶?ÿ€Dæ(4Ѐ¦À4€²¤ ¶?ÿ€=ä(4Ðú@€"€’ à`€¦À6¿ÿóâ`’ @ ¸€"¿ÿé¦ è ’ ¨ è' ú  ø'`ì@ì'@ú&@ð'`ú& ú& 8À'`À'`ö'`À'`@À'` ²€€î`´ ô-à ú` . 0Ð7@’c€Ò7`  ”¢àÔ7` Ö`’–àÖ&` Â@Â@ŸÀ@Ð Çà‘èã¿  $@’ ö úà Ðà€Š "€ €"€’ @¸`ú€"€ €€§@"€€¸ú€2¿ÿû€§@€2€ÔÀ@ ÔÀÔ'À& @ÐàÇà‘è ã¿ Ò`Ò ` € €H€¢`€!€¢`€€¢`†€BÐ` Ð €Š "€ Ú` ’ @ú` Ö@– àý– àÿÖ/@Ú` Ú @€‹`€0’@€.’@-€)ú` Ð`¶`€€!ä ä   €€ê@€€@û¸€2€îà @€”î6à Ð ’Ð Â 0ŸÀ@@€@Çà‘è ã¿ ú ö`  øÀ’`€§ €0’a €§ 2€ Ð` €2€  Ò`” ‚Ô*` – 9Ö&à’@€!’`€§ €F ’`€§ €‚ ’`€§ €+0’`€§ €o0’`€§ €²0’a €§ "€ ú` Ø`š ‚Ú+ ’@² Çà‘èÔ`Ô  Â`4ŸÀ@’Ð&àÞà€"€ä`à`¢ ‚¿ÿíâ, ¦ æ,  ¨ ¿ÿèè&à Ð`’ @Ð ¸€2€ø'` î` ‚Ð-à ’ ¿ÿÚÒ&àÔ`– Ö*  ¿ÿÕÀ&à ô`¸ ô  ô€€Ž "€è`àà€"€â`€ ¸ €Œ`2€€Ð` @’ ¸€"€î`ä`¦ ‚æ,  ¿ÿ¹ø&à€ "€ î`Ð` @’ €"€î`ê`¬ ‚ì-` ¿ÿ«Ð&à´ ® ÿðî'`Ô`𠔀Ô'`Ø`Ú+ ¿ÿ À&à Þ`¨ Þà ú`ª º`ú#Àæ`è,à ¿ÿ•ê&à ì`ì  ì€ì'`Ò`€ "€ Ø`Ô`€¢ :€Ø`– Ö'`Ø`š Ú+ À&à ’ @ ¶€"¿ÿ}’Þ`€"€º%Üú`€§`d4€€§a€¸ 4€¸ ¸ âठä,` ôà ¦ 0æ6€’@‘/`Ð6  ‘/`@’Ð6  èਠè&à@’¿ÿZ’ì`” ì  ú`– ú%€Ò`Ô*` ¿ÿOÖ&à ã¿ ø €"€€Ò €¢@2€øÔ  € €Ö €Šà"€ ø@Ð €2€ €Ø ˜ Ø' ø€2¿ÿëÒ €€ è ’”@®€"€ Þ €"€”º €"€‘º €úžà€ŒÞ' €¤@2€ú@ä  €€æ`€Œà"€ ú@@Ð`€2€ €Ð` Ð'`ú@€2¿ÿëâ` €"€à Ô`€¢€2€ Ô`@ª€2€à Ö`–à€ Ö'`’@cª€2€è`Ú`š`Ú'`à €Œ "€J ⠶ €Œ`"€ä ¶ ä €Œ "€æ ¶àæ €Œà"€’ ¶à’ @¶€2€Ôà@Ð  €4Ð' – Ö*  Ø €‹ "€ Ð ìàžààÀÞàà% Þ% äठä&àÐ €Š "€ Ø ìàÒ Ò%€Ôà” Ô&àØ €‹ "€ ’ìàÚ Þ š@Ú%€âà¢`â&à’@®Â ’Â` Â@Â@Ð ŸÀ@Ð ¸€¿ÿq®º Çà‘èã¿ ú €"€ø ´& €§@(€ø ºø ’ ¸@¸ ¹7 ¹/ @´€2€ê €´ À-` ì ì ¬%€ì& ì&  ÐÒ @Ô ð Ô €”€€ Ô& Ö ”’ @Ø ˜Ø& Çà‘èã¿ @Çà‘è 㿘€¸¿ü€À'¿üÖ Ò Ô –"À  ’@˜ º€2€ ú'Ô¿ü€ €@пü@€° 𠸀2¿ÿçÖ ð¿üÇàè@(#)nit_if.c 1.24 88/02/09 Copyr 1987 Sun Micro껀.àsnitsnit_close nonexistent instance ˆ ‹| ˆŒ ‹´†ÿÿÿL†ÿÿþäx†ÿÿþˆô&†ÿÿþ  ˆ ˆ$†ÿÿýÜ, ˆ0 ‹p …t%†ÿÿýŒx …ˆ†ÿÿýxà&†ÿÿý 6†ÿÿüðˆ†ÿÿüx¸†ÿÿüHÈ5†ÿÿü846†ÿÿûÌ´6†ÿÿûL *†ÿÿúਆÿÿúXä†ÿÿú°†ÿÿùP9†ÿÿøè(9†ÿÿøØD6†ÿÿø¼€ ˆ„ ‹Ä †ÿÿø<| †ÿÿ÷„È#†ÿÿ÷8 l†ÿÿö” „5†ÿÿö| ¸ˆ ¼‹ 8†ÿÿõÈ À†ÿÿõ@ †ÿÿõ ,†ÿÿôÔ L†ÿÿô´ € H „ H Œ †ÿÿôt ´ †ÿÿôL ¼5†ÿÿôD4 €HLìT \˜p x 0| L ì" €.Ø: F LR 0^hqzƒŒ€•Ÿ@©°¶¿ÆÐ×Ýãíõü˜ #.6=AI \\ck H~@Š”œ§° ¹Ä hÏ|ÚÞæîòû ð$_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_hz_dupmsg_cp_mblks_to_mbufs_panic_flushq_free_mbuffed_mblk_domainname_zombproc_ifunit_procNPROC_allproc_avenrun_snit_open_snit_info_snit_intr_qs_m_want_mbstat_tz_freemsg_qreply_etherbroadcastaddr_sccsid.mullibpcap-0.9.7/./SUNOS4/nit_if.o.sun30000644000026300017500000001025306777230341014744 0ustar mcrmcr €¸¬H@NVÿìH×<€ ®f.~(|` ¾­m R‡(M*TJfð ‡fFüšxpÿ`ìJ®gpÿ`à~.(|`¾­m¾­n üšxpÿ`º(M*TJfàHxHx N¹PO&@J‹f ü šxpÿ`r Ó«*k +K*”(+n n!M n!M8B­B­+GB­B­ HxHxN¹PO&@J€g: k| $k 4¼05|»€ 5|.à rÓ«HS n/( h P PNPO Lî<€ÿìN^NuNVÿìH×<*nHxHm$N¹PO(m$l ,gJŠg B§HRN¹PO-|ÿü`·Ìg-Kÿü nÿü&PJ‹fîJ‹fHy N¹XO nÿü ”B­/,N¹XOpLî<ÿìN^NuNVÿì n hp( J€g r°grr°gX €†fö n h gHx/.N¹PO n h ý n h g¼/. /.N¹PO`´/. /.N¹öPO`  n -h ÿü-hÿø .ÿüT€-@ÿìJ®ÿøgr nÿø hJ( fd nÿüJPf\/.ÿøN¹ XO-@ÿôf /. N¹`H nÿì1h n h-h ÿð/.ÿü/.ÿô/.ÿð nÿð h.NOï /. N¹` /. N¹XOpN^NuNVÿÜH×<À n*h n (h .  €€pg €À i f–J­ fŽ n h|‚ ~9)G/. /.N¹PO`Â&m n h$h HR/HS k2NOï )@J¬fv n h| ~ )G `l n h$h HxHRN¹PO&@J‹f n h|‚ ~)G`4+K n h| B¬ ` n h h -Pÿü| .ÿÿg@Jlg|` -fHx/- N¹PO,J†g2 n h|‚ )F` -gB§/- N¹PO,fÎ~ðÏ­.ÿÿ~À‡­ n h| B¬ `~ n h h -~À‡ € n h| ~)G `P n h h +PJ­g ­d~+G n h| B¬ HxHxN¹PO-@ÿügJ­g -` <Ü-@ÿø ®dÿønp` ®ÿønp`p-@ÿô nÿü h| nÿü&h 6¼0 .ÿøë€L.ÿô7@ .ÿøç€L.ÿô7@ nÿü~ߨ/.ÿü/.N¹PO`p n h h ­ n h| ~)G `J  €€pgþ( €€pgþè €€ pgý €Àpgþ¦ €Àpg¨ €À i gýb n h|‚ /. /.N¹POpLî<ÀÿÜN^NuNVÿàH×<ÀB®ÿü&y`4 + °®f( nJ¨ g +~À‡g/+N¹XOJ€f R«&SJ‹fÈJ‹gÐ.+//. /.N¹HOï *@Jf¨R«`¨Jg $S`4 * °®f( nJ¨ g *g/*N¹XOJ€f Rª$RJŠfÈJŠgB¾ªfHUN¹XO(@JŒf,Rª`&/*/. /.N¹HOï (@JŒfRª`.* +|À†gî| +gP† +gX† +gX†Hx/N¹PO-@ÿüfHUN¹XOR«`¼ nÿü h| +g$ nÿü-hÿøAù"nÿø#h" nÿüP¨ +g nÿü-hÿø nÿø « nÿüX¨ +g$ nÿü-hÿø n (Ш nÿø € nÿüX¨HU/.ÿüN¹PO*nÿüHU k/( k h P PNPO&J*LJ‹fþ^pLî<ÀÿàN^NuNVÿìH×0à*n..,-J‡g z…¼€cž…,*Ú­V…äåHx/N¹PO(@J€fp`R lB( l (…)@)@ /-/,/N¹Oï -ѬJ†o/,/B§/. N¹Ý¬ Lî0àÿìN^NuNV/.N¹XOpN^NuNVÿðH×8B®ÿüIîÿü&n`NB§ +« //+ / HzÿÀN¹Oï*@Jf J®ÿüg /.ÿüN¹XOHSN¹XOp`((M&kJ‹f® .ÿüLî8ÿðN^Nu@(#)nit_if.c 1.24 88/02/09 Copyr 1987 Sun Micro 0껀.à4 ° ° ¾ Úsnit_close nonexistent instancesnitPTP„$Pâ$PJ,Pl8PtP”@š.P°7P,P4PH@Ž@ 7PÞ7Pê#PJP¬P 8PT8Pö$PŠP P,PVP€@ÆPè"P@Z$Pj#Pœ-P5P‚$P¸PÚ6Pø7P 2P L%P V#P2@F@J@R@Z@n@v@z@  €&* Ú6=F O^kHw@‹— ª³4¿Ó öÞ °êòú î#.€7>F@RYajr{ö‹ ¾— ª°¸¾ÅÂÏÖßéñü _cp_mblks_to_mbufs_sccsid_lbolt_qs_snit_winit_nproc_whichqs_avenrun_domainnamelen_hostnamelen_snit_cpmsg_rawintrq_hostname_tz_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_hz_snit_ioctl_snit_rinit_mclfree_freeproc_proc_flushq_time_panic_snit_put_ifnet_allproc_zombproc_mbstat_snit_intr_linkb_m_cpytoc_freeb_ifpromisclibpcap-0.9.7/./SUNOS4/CVS/0000755000026300017500000000000010245661223013047 5ustar mcrmcrlibpcap-0.9.7/./SUNOS4/CVS/Entries0000644000026300017500000000031610245661223014403 0ustar mcrmcr/nit_if.o.sparc/1.1.1.1/Thu Oct 7 23:46:41 1999/-ko/Tlibpcap_0_9 /nit_if.o.sun3/1.1.1.1/Thu Oct 7 23:46:41 1999/-ko/Tlibpcap_0_9 /nit_if.o.sun4c.4.0.3c/1.1.1.1/Thu Oct 7 23:46:41 1999/-ko/Tlibpcap_0_9 D libpcap-0.9.7/./SUNOS4/CVS/Root0000644000026300017500000000004010245661222013706 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./SUNOS4/CVS/Repository0000644000026300017500000000001710245661222015146 0ustar mcrmcrlibpcap/SUNOS4 libpcap-0.9.7/./SUNOS4/CVS/Tag0000644000026300017500000000001510245661223013501 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./SUNOS4/nit_if.o.sun4c.4.0.3c0000644000026300017500000001225306777230341015716 0ustar mcrmcr ðÄL`ã¿ ³.`€¦à€³>`²`ú@¶ €"€ €¦áÔ`€¦À &€ €¦á²ú@¶à€2¿ÿùÔ`€¦á2€"’ – ¶?ÿ€SÖ(4Ѐ"€€N¶?ÿ¶`ÿ²àú@€"€’ à`€¦À&€’ â`€¦À4€²¤ ¶?ÿ€<ä(4Ðú@€2¿ÿóà`’ @ ¸€2€è ¦ ¶?ÿ€-æ(4Ð’ ¨ è' ú  ø'`ì@ì'@ú&@ð'`ú& ú& 8À'`À'`ö'`À'`@À'` ²€€î`´ ô-à ú` . 0Ð7@’c€Ò7`  ”¢àÔ7` Ö`’–àÖ&` Â@Â@ŸÀ@Ð Çà‘èã¿  $@’ ö úà Ðà€Š "€ €"€’ @¸`ú€"€ €€§@"€€¸ú€2¿ÿû€§@€2€ÔÀ@ ÔÀÔ'À& @ÐàÇà‘è ã¿ Ò`Ò ` € €H€¢`€!€¢`€€¢`†€BÐ` Ð €Š "€ Ú` ’ @ú` Ö@– àý– àÿÖ/@Ú` Ú @€‹`€0’@€.’@-€)ú` Ð`¶`€€!ä ä   €€ê@€€@¸€2€îà @€”î6à Ð ’Ð Â 0ŸÀ@@€@Çà‘è ã¿ ú ö`  øÀ’`€§ €0’a €§ 2€½ Ð` €2€¹ Ò`” ‚Ô*` – 9Ö&à’@€ÎÔ`Ô  Â`4ŸÀ@’Ð&àÞà€"€ä`à`¢ ‚€»â, ¦ æ,  ¨ €¶è&à Ð`’ @Ð ¸€2€ø'` î` ‚Ð-à ’ €¨Ò&àÔ`– Ö*  €£À&à ô`¸ ô  ô€€Ž "€è`àà€"€â`€ ¸ €Œ`2€€Ð` @’ ¸€"€î`ä`¦ ‚æ,  €‡ø&à€ "€ î`Ð` @’ €"€î`ê`¬ ‚ì-` €yÐ&à´ ® ÿðî'`Ô`𠔀Ô'`Ø`Ú+ €nÀ&à Þ`¨ Þà ú`ª º`ú#Àæ`è,à €cê&à ì`ì  ì€ì'`Ò`€ "€ Ø`Ô`€¢ :€Ø`– Ö'`Ø`š Ú+ À&à ’ @ ¶€"€K’Þ`€"€º%Üú`€§`d4€€§a€¸ 4€¸ ¸ âठä,` ôà ¦ 0æ6€’@‘/`Ð6  ‘/`@’Ð6  èਠè&à@’€(’ì`” ì  ú`– ú%€Ò`Ô*` €Ö&à ’`€§ ¿ÿx ’`€§ ¿ÿ´ ’`€§ ¿ÿ]0’`€§ ¿ÿ¡0’`€§ ¿ÿä0’a €§ "¿ÿ=ú` Ø`š ‚Ú+ ’@² Çà‘èã¿ ø €"€€Ò €¢@2€øÔ  € €Ö €Šà"€ ø@Ð €2€ €Ø ˜ Ø' ø€2¿ÿëÒ €€¬è ’”@©¬€2€€Þ žà€ŸÞ' ?ÿÜ#ÿÿ¦€™¤€"€—º ú€"€€Ò` €¢@2€ú@Ô  € €Ö`€Šà"€ ú@@Ð`€2€ €Ø`˜ Ø'`ú@€2¿ÿëÒ` €"€Ô Þ`€£À2€ Ô`@ª€2€Ô à`  € à'`’@iª€2€è`Ð` Ð'`Ô €Š "€PÂ Ö ¶ €Šà"€Ø ¶ Ø €‹ "€Ú ¶àÚ €‹`"€’ ¶à’ @¶€2€âà@Þ žà€:Þ'  Ð,` Ò €Š`"€Ø îà–àØÀÖàØ%àÖ%àÞÀÐàž ÀŸ3à Ð%àÔà” Ô&àØ €‹ "€ â îàÚ Ú%ÀÞàžàÞ&àâ €Œ`"€ ’îàРҠ Ð%ÀÖà–àÖ&à’@¬Â ’Â` Â@Â@Ð ŸÀ@Ð ¸€¿ÿk¬º Çà‘èã¿ ú €"€ø ´& €§@(€ø ºø ’ ¸@¸ ¹7 ¹/ @´€2€ê €´ À-` ì ì ¬%€ì& ì&  ÐÒ @Ô ð Ô €”€€ Ô& Ö ”’ @Ø ˜Ø& Çà‘èã¿ @Çà‘è 㿘€¸¿ü€À'¿üÖ Ò Ô –"À  ’@˜ º€2€ ú'Ô¿ü€ €@пü@€° 𠸀2¿ÿçÖ ð¿üÇàè@(#) $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껀.àsnitsnit_close nonexistent instance ˆ ‹| ˆŒ ‹ä†ÿÿÿL†ÿÿþ´È&†ÿÿþ8ä ˆð ˆø†ÿÿþ ˆ ‹D ÍH%†ÿÿý¸L Í\†ÿÿý¤´&†ÿÿýLä7†ÿÿý\†ÿÿü¤Œ†ÿÿütœ6†ÿÿüd7†ÿÿûøp+†ÿÿûø†ÿÿû4†ÿÿú̆ÿÿúh:†ÿÿù˜x:†ÿÿùˆ”7†ÿÿùl<7†ÿÿøÄT ˆX ‹˜ †ÿÿøhh †ÿÿ÷˜´#†ÿÿ÷L X†ÿÿö¨ p6†ÿÿö ¤ˆ ¨‹ <†ÿÿõÄ Ä†ÿÿõ< †ÿÿôü 0†ÿÿôÐ P†ÿÿô° „ L ˆ L †ÿÿôp ¸ †ÿÿôH À6†ÿÿô@€ È”˜À  l¨l¼ lÄ |È ˜ À" „.¬: lF ˜R |^hqzƒŒ€•Ÿ@©°¶¿ÆÐ×Ýãíõül #.6=AI `\ck ðr L…@‘›£®· ÀË ´ÖPáåíõù  8&+_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_hz_dupmsg_cp_mblks_to_mbufs_panic_flushq_rcsid_free_mbuffed_mblk_domainname_zombproc_ifunit_procNPROC_allproc_avenrun_snit_open_snit_info_snit_intr_qs_m_want_mbstat_tz_freemsg_qreply_etherbroadcastaddr_sccsid.mullibpcap-0.9.7/./README.aix0000644000026300017500000000533307647445205013101 0ustar mcrmcrUsing BPF: (1) AIX 4.x's version of BPF is undocumented and somewhat unstandard; the current BPF support code includes changes that should work around that; it appears to compile and work on at least one AIX 4.3.3 machine. Note that the BPF driver and the "/dev/bpf" devices might not exist on your machine; AIX's tcpdump loads the driver and creates the devices if they don't already exist. Our libpcap should do the same, and the configure script should detect that it's on an AIX system and choose BPF even if the devices aren't there. (2) If libpcap doesn't compile on your machine when configured to use BPF, or if the workarounds fail to make it work correctly, you should send to tcpdump-workers@tcpdump.org a detailed bug report (if the compile fails, send us the compile error messages; if it compiles but fails to work correctly, send us as detailed as possible a description of the symptoms, including indications of the network link-layer type being wrong or time stamps being wrong). If you fix the problems yourself, please send to patches@tcpdump.org a patch, so we can incorporate them into the next release. If you don't fix the problems yourself, you can, as a workaround, make libpcap use DLPI instead of BPF. This can be done by specifying the flag: --with-pcap=dlpi to the "configure" script for libpcap. If you use DLPI: (1) It is a good idea to have the latest version of the DLPI driver on your system, since certain versions may be buggy and cause your AIX system to crash. DLPI is included in the fileset bos.rte.tty. I found that the DLPI driver that came with AIX 4.3.2 was buggy, and had to upgrade to bos.rte.tty 4.3.2.4: lslpp -l bos.rte.tty bos.rte.tty 4.3.2.4 COMMITTED Base TTY Support and Commands Updates for AIX filesets can be obtained from: ftp://service.software.ibm.com/aix/fixes/ These updates can be installed with the smit program. (2) After compiling libpcap, you need to make sure that the DLPI driver is loaded. Type: strload -q -d dlpi If the result is: dlpi: yes then the DLPI driver is loaded correctly. If it is: dlpi: no Then you need to type: strload -f /etc/dlpi.conf Check again with strload -q -d dlpi that the dlpi driver is loaded. Alternatively, you can uncomment the lines for DLPI in /etc/pse.conf and reboot the machine; this way DLPI will always be loaded when you boot your system. (3) There appears to be a problem in the DLPI code in some versions of AIX, causing a warning about DL_PROMISC_MULTI failing; this might be responsible for DLPI not being able to capture outgoing packets. libpcap-0.9.7/./pcap-septel.h0000644000026300017500000000107510255632553014017 0ustar mcrmcr/* * pcap-septel.c: Packet capture interface for Intel Septel card * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible. This code is only needed when compiling in the Intel/Septel * card code at the same time as another type of device. * * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY * (+961 3 485343); * * @(#) $Header: /tcpdump/master/libpcap/pcap-septel.h,v 1.1.2.1 2005/06/20 21:30:19 guy Exp $ */ pcap_t *septel_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf); libpcap-0.9.7/./fad-gifc.c0000644000026300017500000004051110262571370013230 0ustar mcrmcr/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.8.2.2 2005/06/29 06:43:31 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #ifdef HAVE_SYS_SOCKIO_H #include #endif #include /* concession to AIX */ struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include #include #include #include #include #include #include #include #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif /* * This is fun. * * In older BSD systems, socket addresses were fixed-length, and * "sizeof (struct sockaddr)" gave the size of the structure. * All addresses fit within a "struct sockaddr". * * In newer BSD systems, the socket address is variable-length, and * there's an "sa_len" field giving the length of the structure; * this allows socket addresses to be longer than 2 bytes of family * and 14 bytes of data. * * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553 * variant of the old BSD scheme (with "struct sockaddr_storage" rather * than "struct sockaddr"), and some use the new BSD scheme. * * Some versions of GNU libc use neither scheme, but has an "SA_LEN()" * macro that determines the size based on the address family. Other * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553 * but not in the final version). * * We assume that a UNIX that doesn't have "getifaddrs()" and doesn't have * SIOCGLIFCONF, but has SIOCGIFCONF, uses "struct sockaddr" for the * address in an entry returned by SIOCGIFCONF. */ #ifndef SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN #define SA_LEN(addr) ((addr)->sa_len) #else /* HAVE_SOCKADDR_SA_LEN */ #define SA_LEN(addr) (sizeof (struct sockaddr)) #endif /* HAVE_SOCKADDR_SA_LEN */ #endif /* SA_LEN */ /* * This is also fun. * * There is no ioctl that returns the amount of space required for all * the data that SIOCGIFCONF could return, and if a buffer is supplied * that's not large enough for all the data SIOCGIFCONF could return, * on at least some platforms it just returns the data that'd fit with * no indication that there wasn't enough room for all the data, much * less an indication of how much more room is required. * * The only way to ensure that we got all the data is to pass a buffer * large enough that the amount of space in the buffer *not* filled in * is greater than the largest possible entry. * * We assume that's "sizeof(ifreq.ifr_name)" plus 255, under the assumption * that no address is more than 255 bytes (on systems where the "sa_len" * field in a "struct sockaddr" is 1 byte, e.g. newer BSDs, that's the * case, and addresses are unlikely to be bigger than that in any case). */ #define MAX_SA_LEN 255 #ifdef HAVE_PROC_NET_DEV /* * Get from "/proc/net/dev" all interfaces listed there; if they're * already in the list of interfaces we have, that won't add another * instance, but if they're not, that'll add them. * * We don't bother getting any addresses for them; it appears you can't * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and, * although some other types of addresses can be fetched with SIOCGIFADDR, * we don't bother with them for now. * * We also don't fail if we couldn't open "/proc/net/dev"; we just leave * the list of interfaces as is. */ static int scan_proc_net_dev(pcap_if_t **devlistp, int fd, char *errbuf) { FILE *proc_net_f; char linebuf[512]; int linenum; unsigned char *p; char name[512]; /* XXX - pick a size */ char *q, *saveq; struct ifreq ifrflags; int ret = 0; proc_net_f = fopen("/proc/net/dev", "r"); if (proc_net_f == NULL) return (0); for (linenum = 1; fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) { /* * Skip the first two lines - they're headers. */ if (linenum <= 2) continue; p = &linebuf[0]; /* * Skip leading white space. */ while (*p != '\0' && isspace(*p)) p++; if (*p == '\0' || *p == '\n') continue; /* blank line */ /* * Get the interface name. */ q = &name[0]; while (*p != '\0' && !isspace(*p)) { if (*p == ':') { /* * This could be the separator between a * name and an alias number, or it could be * the separator between a name with no * alias number and the next field. * * If there's a colon after digits, it * separates the name and the alias number, * otherwise it separates the name and the * next field. */ saveq = q; while (isdigit(*p)) *q++ = *p++; if (*p != ':') { /* * That was the next field, * not the alias number. */ q = saveq; } break; } else *q++ = *p++; } *q = '\0'; /* * Get the flags for this interface, and skip it if * it's not up. */ strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name)); if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { if (errno == ENXIO) continue; (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFFLAGS: %.*s: %s", (int)sizeof(ifrflags.ifr_name), ifrflags.ifr_name, pcap_strerror(errno)); ret = -1; break; } if (!(ifrflags.ifr_flags & IFF_UP)) continue; /* * Add an entry for this interface, with no addresses. */ if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL, errbuf) == -1) { /* * Failure. */ ret = -1; break; } } if (ret != -1) { /* * Well, we didn't fail for any other reason; did we * fail due to an error reading the file? */ if (ferror(proc_net_f)) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading /proc/net/dev: %s", pcap_strerror(errno)); ret = -1; } } (void)fclose(proc_net_f); return (ret); } #endif /* HAVE_PROC_NET_DEV */ /* * Get a list of all interfaces that are up and that we can open. * Returns -1 on error, 0 otherwise. * The list, as returned through "alldevsp", may be null if no interfaces * were up and could be opened. * * This is the implementation used on platforms that have SIOCGIFCONF but * don't have any other mechanism for getting a list of interfaces. * * XXX - or platforms that have other, better mechanisms but for which * we don't yet have code to use that mechanism; I think there's a better * way on Linux, for example. */ int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; register int fd; register struct ifreq *ifrp, *ifend, *ifnext; int n; struct ifconf ifc; char *buf = NULL; unsigned buf_size; #if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER) char *p, *q; #endif struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; struct sockaddr *netmask, *broadaddr, *dstaddr; size_t netmask_size, broadaddr_size, dstaddr_size; int ret = 0; /* * Create a socket from which to fetch the list of interfaces. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); return (-1); } /* * Start with an 8K buffer, and keep growing the buffer until * we have more than "sizeof(ifrp->ifr_name) + MAX_SA_LEN" * bytes left over in the buffer or we fail to get the * interface list for some reason other than EINVAL (which is * presumed here to mean "buffer is too small"). */ buf_size = 8192; for (;;) { buf = malloc(buf_size); if (buf == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); (void)close(fd); return (-1); } ifc.ifc_len = buf_size; ifc.ifc_buf = buf; memset(buf, 0, buf_size); if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 && errno != EINVAL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFCONF: %s", pcap_strerror(errno)); (void)close(fd); free(buf); return (-1); } if (ifc.ifc_len < buf_size && (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN) break; free(buf); buf_size *= 2; } ifrp = (struct ifreq *)buf; ifend = (struct ifreq *)(buf + ifc.ifc_len); for (; ifrp < ifend; ifrp = ifnext) { /* * XXX - what if this isn't an IPv4 address? Can * we still get the netmask, etc. with ioctls on * an IPv4 socket? * * The answer is probably platform-dependent, and * if the answer is "no" on more than one platform, * the way you work around it is probably platform- * dependent as well. */ n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name); if (n < sizeof(*ifrp)) ifnext = ifrp + 1; else ifnext = (struct ifreq *)((char *)ifrp + n); /* * XXX - The 32-bit compatibility layer for Linux on IA-64 * is slightly broken. It correctly converts the structures * to and from kernel land from 64 bit to 32 bit but * doesn't update ifc.ifc_len, leaving it larger than the * amount really used. This means we read off the end * of the buffer and encounter an interface with an * "empty" name. Since this is highly unlikely to ever * occur in a valid case we can just finish looking for * interfaces if we see an empty name. */ if (!(*ifrp->ifr_name)) break; /* * Skip entries that begin with "dummy". * XXX - what are these? Is this Linux-specific? * Are there platforms on which we shouldn't do this? */ if (strncmp(ifrp->ifr_name, "dummy", 5) == 0) continue; /* * Get the flags for this interface, and skip it if it's * not up. */ strncpy(ifrflags.ifr_name, ifrp->ifr_name, sizeof(ifrflags.ifr_name)); if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { if (errno == ENXIO) continue; (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFFLAGS: %.*s: %s", (int)sizeof(ifrflags.ifr_name), ifrflags.ifr_name, pcap_strerror(errno)); ret = -1; break; } if (!(ifrflags.ifr_flags & IFF_UP)) continue; /* * Get the netmask for this address on this interface. */ strncpy(ifrnetmask.ifr_name, ifrp->ifr_name, sizeof(ifrnetmask.ifr_name)); memcpy(&ifrnetmask.ifr_addr, &ifrp->ifr_addr, sizeof(ifrnetmask.ifr_addr)); if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifrnetmask) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ netmask = NULL; netmask_size = 0; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFNETMASK: %.*s: %s", (int)sizeof(ifrnetmask.ifr_name), ifrnetmask.ifr_name, pcap_strerror(errno)); ret = -1; break; } } else { netmask = &ifrnetmask.ifr_addr; netmask_size = SA_LEN(netmask); } /* * Get the broadcast address for this address on this * interface (if any). */ if (ifrflags.ifr_flags & IFF_BROADCAST) { strncpy(ifrbroadaddr.ifr_name, ifrp->ifr_name, sizeof(ifrbroadaddr.ifr_name)); memcpy(&ifrbroadaddr.ifr_addr, &ifrp->ifr_addr, sizeof(ifrbroadaddr.ifr_addr)); if (ioctl(fd, SIOCGIFBRDADDR, (char *)&ifrbroadaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ broadaddr = NULL; broadaddr_size = 0; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFBRDADDR: %.*s: %s", (int)sizeof(ifrbroadaddr.ifr_name), ifrbroadaddr.ifr_name, pcap_strerror(errno)); ret = -1; break; } } else { broadaddr = &ifrbroadaddr.ifr_broadaddr; broadaddr_size = SA_LEN(broadaddr); } } else { /* * Not a broadcast interface, so no broadcast * address. */ broadaddr = NULL; broadaddr_size = 0; } /* * Get the destination address for this address on this * interface (if any). */ if (ifrflags.ifr_flags & IFF_POINTOPOINT) { strncpy(ifrdstaddr.ifr_name, ifrp->ifr_name, sizeof(ifrdstaddr.ifr_name)); memcpy(&ifrdstaddr.ifr_addr, &ifrp->ifr_addr, sizeof(ifrdstaddr.ifr_addr)); if (ioctl(fd, SIOCGIFDSTADDR, (char *)&ifrdstaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ dstaddr = NULL; dstaddr_size = 0; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFDSTADDR: %.*s: %s", (int)sizeof(ifrdstaddr.ifr_name), ifrdstaddr.ifr_name, pcap_strerror(errno)); ret = -1; break; } } else { dstaddr = &ifrdstaddr.ifr_dstaddr; dstaddr_size = SA_LEN(dstaddr); } } else { /* * Not a point-to-point interface, so no destination * address. */ dstaddr = NULL; dstaddr_size = 0; } #if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER) /* * If this entry has a colon followed by a number at * the end, it's a logical interface. Those are just * the way you assign multiple IP addresses to a real * interface, so an entry for a logical interface should * be treated like the entry for the real interface; * we do that by stripping off the ":" and the number. */ p = strchr(ifrp->ifr_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ q = p + 1; while (isdigit((unsigned char)*q)) q++; if (*q == '\0') { /* * All digits after the ":" until the end. * Strip off the ":" and everything after * it. */ *p = '\0'; } } #endif /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifrp->ifr_name, ifrflags.ifr_flags, &ifrp->ifr_addr, SA_LEN(&ifrp->ifr_addr), netmask, netmask_size, broadaddr, broadaddr_size, dstaddr, dstaddr_size, errbuf) < 0) { ret = -1; break; } } free(buf); #ifdef HAVE_PROC_NET_DEV if (ret != -1) { /* * We haven't had any errors yet; now read "/proc/net/dev", * and add to the list of interfaces all interfaces listed * there that we don't already have, because, on Linux, * SIOCGIFCONF reports only interfaces with IPv4 addresses, * so you need to read "/proc/net/dev" to get the names of * the rest of the interfaces. */ ret = scan_proc_net_dev(&devlist, fd, errbuf); } #endif (void)close(fd); if (ret != -1) { /* * We haven't had any errors yet; do any platform-specific * operations to add devices. */ if (pcap_platform_finddevs(&devlist, errbuf) < 0) ret = -1; } if (ret == -1) { /* * We had an error; free the list we've been constructing. */ if (devlist != NULL) { pcap_freealldevs(devlist); devlist = NULL; } } *alldevsp = devlist; return (ret); } libpcap-0.9.7/./atmuni31.h0000644000026300017500000000770507513245230013244 0ustar mcrmcr/* * Copyright (c) 1997 Yen Yen Lim and North Dakota State University * 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 Yen Yen Lim and North Dakota State University * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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: /tcpdump/master/libpcap/atmuni31.h,v 1.1 2002/07/11 09:06:32 guy Exp $ (LBL) */ /* Based on UNI3.1 standard by ATM Forum */ /* ATM traffic types based on VPI=0 and (the following VCI */ #define PPC 0x05 /* Point-to-point signal msg */ #define BCC 0x02 /* Broadcast signal msg */ #define OAMF4SC 0x03 /* Segment OAM F4 flow cell */ #define OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */ #define METAC 0x01 /* Meta signal msg */ #define ILMIC 0x10 /* ILMI msg */ /* Q.2931 signalling messages */ #define CALL_PROCEED 0x02 /* call proceeding */ #define CONNECT 0x07 /* connect */ #define CONNECT_ACK 0x0f /* connect_ack */ #define SETUP 0x05 /* setup */ #define RELEASE 0x4d /* release */ #define RELEASE_DONE 0x5a /* release_done */ #define RESTART 0x46 /* restart */ #define RESTART_ACK 0x4e /* restart ack */ #define STATUS 0x7d /* status */ #define STATUS_ENQ 0x75 /* status ack */ #define ADD_PARTY 0x80 /* add party */ #define ADD_PARTY_ACK 0x81 /* add party ack */ #define ADD_PARTY_REJ 0x82 /* add party rej */ #define DROP_PARTY 0x83 /* drop party */ #define DROP_PARTY_ACK 0x84 /* drop party ack */ /* Information Element Parameters in the signalling messages */ #define CAUSE 0x08 /* cause */ #define ENDPT_REF 0x54 /* endpoint reference */ #define AAL_PARA 0x58 /* ATM adaptation layer parameters */ #define TRAFF_DESCRIP 0x59 /* atm traffic descriptors */ #define CONNECT_ID 0x5a /* connection identifier */ #define QOS_PARA 0x5c /* quality of service parameters */ #define B_HIGHER 0x5d /* broadband higher layer information */ #define B_BEARER 0x5e /* broadband bearer capability */ #define B_LOWER 0x5f /* broadband lower information */ #define CALLING_PARTY 0x6c /* calling party number */ #define CALLED_PARTY 0x70 /* called party nmber */ #define Q2931 0x09 /* Q.2931 signalling general messages format */ #define PROTO_POS 0 /* offset of protocol discriminator */ #define CALL_REF_POS 2 /* offset of call reference value */ #define MSG_TYPE_POS 5 /* offset of message type */ #define MSG_LEN_POS 7 /* offset of mesage length */ #define IE_BEGIN_POS 9 /* offset of first information element */ /* format of signalling messages */ #define TYPE_POS 0 #define LEN_POS 2 #define FIELD_BEGIN_POS 4 libpcap-0.9.7/./msdos/0000755000026300017500000000000010651260473012551 5ustar mcrmcrlibpcap-0.9.7/./msdos/ndis_0.asm0000644000026300017500000001047610160767675014452 0ustar mcrmcrPAGE 60,132 NAME NDIS_0 ifdef DOSX .386 _TEXT SEGMENT PUBLIC DWORD USE16 'CODE' _TEXT ENDS _DATA SEGMENT PUBLIC DWORD USE16 'CODE' _DATA ENDS _TEXT32 SEGMENT PUBLIC BYTE USE32 'CODE' _TEXT32 ENDS CB_DSEG EQU ; DOSX is tiny-model D_SEG EQU <_TEXT SEGMENT> D_END EQU <_TEXT ENDS> ASSUME CS:_TEXT,DS:_TEXT PUSHREGS equ POPREGS equ PUBPROC macro name align 4 public @&name @&name label near endm else .286 _TEXT SEGMENT PUBLIC DWORD 'CODE' _TEXT ENDS _DATA SEGMENT PUBLIC DWORD 'DATA' _DATA ENDS CB_DSEG EQU ; 16bit is small/large model D_SEG EQU <_DATA SEGMENT> D_END EQU <_DATA ENDS> ASSUME CS:_TEXT,DS:_DATA PUSHREGS equ POPREGS equ PUBPROC macro name public _&name _&name label far endm endif ;------------------------------------------- D_SEG D_END _TEXT SEGMENT EXTRN _NdisSystemRequest : near EXTRN _NdisRequestConfirm : near EXTRN _NdisTransmitConfirm : near EXTRN _NdisReceiveLookahead : near EXTRN _NdisIndicationComplete : near EXTRN _NdisReceiveChain : near EXTRN _NdisStatusProc : near EXTRN _NdisAllocStack : near EXTRN _NdisFreeStack : near ; ; *ALL* interrupt threads come through this macro. ; CALLBACK macro callbackProc, argsSize pushf PUSHREGS ;; Save the registers push es push ds mov ax,CB_DSEG ;; Load DS mov ds,ax call _NdisAllocStack ;; Get and install a stack. mov bx,ss ;; Save off the old stack in other regs mov cx,sp mov ss,dx ;; Install the new one mov sp,ax push bx ;; Save the old one on to the new stack push cx sub sp,&argsSize ;; Allocate space for arguments on the stack mov ax,ss ;; Set up the destination for the move mov es,ax mov di,sp mov ds,bx ;; Set up the source for the move. mov si,cx add si,4+6+32 mov cx,&argsSize ;; Move the arguments to the stack. shr cx,1 cld rep movsw mov ax,CB_DSEG ;; Set my data segment again. mov ds,ax call &callbackProc ;; Call the real callback. pop di ;; Pop off the old stack pop si mov bx,ss ;; Save off the current allocated stack. mov cx,sp mov ss,si ;; Restore the old stack mov sp,di push ax ;; Save the return code push bx ;; Free the stack. Push the pointer to it push cx call _NdisFreeStack add sp,4 pop ax ;; Get the return code back add di,32 ;; Get a pointer to ax on the stack mov word ptr ss:[di],ax pop ds pop es POPREGS popf endm ; ; Define all of the callbacks for the NDIS procs. ; PUBPROC systemRequestGlue CALLBACK _NdisSystemRequest,14 RETF PUBPROC requestConfirmGlue CALLBACK _NdisRequestConfirm,12 RETF PUBPROC transmitConfirmGlue CALLBACK _NdisTransmitConfirm,10 RETF PUBPROC receiveLookaheadGlue CALLBACK _NdisReceiveLookahead,16 RETF PUBPROC indicationCompleteGlue CALLBACK _NdisIndicationComplete,4 RETF PUBPROC receiveChainGlue CALLBACK _NdisReceiveChain,16 RETF PUBPROC statusGlue CALLBACK _NdisStatusProc,12 RETF ; ; int FAR NdisGetLinkage (int handle, char *data, int size); ; ifdef DOSX PUBPROC NdisGetLinkage push ebx mov ebx, [esp+8] ; device handle mov eax, 4402h ; IOCTRL read function mov edx, [esp+12] ; DS:EDX -> result data mov ecx, [esp+16] ; ECX = length int 21h pop ebx jc @fail xor eax, eax @fail: ret else PUBPROC NdisGetLinkage enter 0, 0 mov bx, [bp+6] mov ax, 4402h mov dx, [bp+8] mov cx, [bp+12] int 21h jc @fail xor ax, ax @fail: leave retf endif ENDS END libpcap-0.9.7/./msdos/pktdrvr.h0000644000026300017500000001261710160767676014441 0ustar mcrmcr#ifndef __PKTDRVR_H #define __PKTDRVR_H #define PUBLIC #define LOCAL static #define RX_BUF_SIZE ETH_MTU /* buffer size variables. NB !! */ #define TX_BUF_SIZE ETH_MTU /* must be same as in pkt_rx*.* */ #ifdef __HIGHC__ #pragma Off(Align_members) #else #pragma pack(1) #endif typedef enum { /* Packet-driver classes */ PD_ETHER = 1, PD_PRONET10 = 2, PD_IEEE8025 = 3, PD_OMNINET = 4, PD_APPLETALK = 5, PD_SLIP = 6, PD_STARTLAN = 7, PD_ARCNET = 8, PD_AX25 = 9, PD_KISS = 10, PD_IEEE8023_2 = 11, PD_FDDI8022 = 12, PD_X25 = 13, PD_LANstar = 14, PD_PPP = 18 } PKT_CLASS; typedef enum { /* Packet-driver receive modes */ PDRX_OFF = 1, /* turn off receiver */ PDRX_DIRECT, /* receive only to this interface */ PDRX_BROADCAST, /* DIRECT + broadcast packets */ PDRX_MULTICAST1, /* BROADCAST + limited multicast */ PDRX_MULTICAST2, /* BROADCAST + all multicast */ PDRX_ALL_PACKETS, /* receive all packets on network */ } PKT_RX_MODE; typedef struct { char type[8]; char len; } PKT_FRAME; typedef struct { BYTE class; /* = 1 for DEC/Interl/Xerox Ethernet */ BYTE number; /* = 0 for single LAN adapter */ WORD type; /* = 13 for 3C523 */ BYTE funcs; /* Basic/Extended/HiPerf functions */ WORD intr; /* user interrupt vector number */ WORD handle; /* Handle associated with session */ BYTE name [15]; /* Name of adapter interface,ie.3C523*/ BOOL quiet; /* (don't) print errors to stdout */ const char *error; /* address of error string */ BYTE majVer; /* Major driver implementation ver. */ BYTE minVer; /* Minor driver implementation ver. */ BYTE dummyLen; /* length of following data */ WORD MAClength; /* HiPerformance data, N/A */ WORD MTU; /* HiPerformance data, N/A */ WORD multicast; /* HiPerformance data, N/A */ WORD rcvrBuffers; /* valid for */ WORD UMTbufs; /* High Performance drivers only */ WORD postEOIintr; /* Usage ?? */ } PKT_INFO; #define PKT_PARAM_SIZE 14 /* members majVer - postEOIintr */ typedef struct { DWORD inPackets; /* # of packets received */ DWORD outPackets; /* # of packets transmitted */ DWORD inBytes; /* # of bytes received */ DWORD outBytes; /* # of bytes transmitted */ DWORD inErrors; /* # of reception errors */ DWORD outErrors; /* # of transmission errors */ DWORD lost; /* # of packets lost (RX) */ } PKT_STAT; typedef struct { ETHER destin; ETHER source; WORD proto; BYTE data [TX_BUF_SIZE]; } TX_ELEMENT; typedef struct { WORD firstCount; /* # of bytes on 1st */ WORD secondCount; /* and 2nd upcall */ WORD handle; /* instance that upcalled */ ETHER destin; /* E-net destination address */ ETHER source; /* E-net source address */ WORD proto; /* protocol number */ BYTE data [RX_BUF_SIZE]; } RX_ELEMENT; #ifdef __HIGHC__ #pragma pop(Align_members) #else #pragma pack() #endif /* * Prototypes for publics */ #ifdef __cplusplus extern "C" { #endif extern PKT_STAT pktStat; /* statistics for packets */ extern PKT_INFO pktInfo; /* packet-driver information */ extern PKT_RX_MODE receiveMode; extern ETHER myAddress, ethBroadcast; extern BOOL PktInitDriver (PKT_RX_MODE mode); extern BOOL PktExitDriver (void); extern const char *PktGetErrorStr (int errNum); extern const char *PktGetClassName (WORD class); extern const char *PktRXmodeStr (PKT_RX_MODE mode); extern BOOL PktSearchDriver (void); extern int PktReceive (BYTE *buf, int max); extern BOOL PktTransmit (const void *eth, int len); extern DWORD PktRxDropped (void); extern BOOL PktReleaseHandle (WORD handle); extern BOOL PktTerminHandle (WORD handle); extern BOOL PktResetInterface (WORD handle); extern BOOL PktSetReceiverMode(PKT_RX_MODE mode); extern BOOL PktGetReceiverMode(PKT_RX_MODE *mode); extern BOOL PktGetStatistics (WORD handle); extern BOOL PktSessStatistics (WORD handle); extern BOOL PktResetStatistics(WORD handle); extern BOOL PktGetAddress (ETHER *addr); extern BOOL PktSetAddress (const ETHER *addr); extern BOOL PktGetDriverInfo (void); extern BOOL PktGetDriverParam (void); extern void PktQueueBusy (BOOL busy); extern WORD PktBuffersUsed (void); #ifdef __cplusplus } #endif #endif /* __PKTDRVR_H */ libpcap-0.9.7/./msdos/pkt_rx0.asm0000644000026300017500000001422410160767675014660 0ustar mcrmcrPAGE 60,132 NAME PKT_RX ifdef ??version ; using TASM masm jumps endif PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf, _pktTemp PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd ; ; these sizes MUST be equal to the sizes in PKTDRVR.H ; RX_BUF_SIZE = 1500 ; max message size on Ethernet TX_BUF_SIZE = 1500 ifdef DOSX .386 NUM_RX_BUF = 32 ; # of RX element buffers _TEXT SEGMENT PUBLIC DWORD USE16 'CODE' _TEXT ENDS _DATA SEGMENT PUBLIC DWORD USE16 'CODE' _DATA ENDS D_SEG EQU <_TEXT SEGMENT> D_END EQU <_TEXT ENDS> ASSUME CS:_TEXT,DS:_TEXT else .286 NUM_RX_BUF = 10 _TEXT SEGMENT PUBLIC DWORD 'CODE' _TEXT ENDS _DATA SEGMENT PUBLIC DWORD 'DATA' _DATA ENDS D_SEG EQU <_DATA SEGMENT> D_END EQU <_DATA ENDS> ASSUME CS:_TEXT,DS:_DATA endif ;------------------------------------------- D_SEG RX_ELEMENT STRUC firstCount dw 0 ; # of bytes on 1st call secondCount dw 0 ; # of bytes on 2nd call handle dw 0 ; handle for upcall destinAdr db 6 dup (0) ; packet destination address sourceAdr db 6 dup (0) ; packet source address protocol dw 0 ; packet protocol number rxBuffer db RX_BUF_SIZE dup (0) ; RX buffer ENDS align 4 _rxOutOfs dw offset _pktRxBuf ; ring buffer offsets _rxInOfs dw offset _pktRxBuf ; into _pktRxBuf _pktDrop dw 0,0 ; packet drop counter _pktTemp db 20 dup (0) ; temp work area _pktTxBuf db (TX_BUF_SIZE+14) dup (0) ; TX buffer _pktRxBuf RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures LAST_OFS = offset $ screenSeg dw 0B800h newInOffset dw 0 fanChars db '-\|/' fanIndex dw 0 D_END _TEXT SEGMENT SHOW_RX MACRO push es push bx mov bx, screenSeg mov es, bx ;; r-mode segment of colour screen mov di, 158 ;; upper right corner - 1 mov bx, fanIndex mov al, fanChars[bx] ;; get write char mov ah, 15 ;; and white colour stosw ;; write to screen at ES:EDI inc fanIndex ;; update next index and fanIndex, 3 pop bx pop es ENDM ;------------------------------------------------------------------------ ; ; This macro return ES:DI to tail of Rx queue ENQUEUE MACRO LOCAL @noWrap mov ax, _rxInOfs ;; DI = current in-offset add ax, SIZE RX_ELEMENT ;; point to next _pktRxBuf buffer cmp ax, LAST_OFS ;; pointing past last ? jb @noWrap ;; no - jump lea ax, _pktRxBuf ;; yes, point to 1st buffer align 4 @noWrap: cmp ax, _rxOutOfs ;; in-ofs = out-ofs ? je @dump ;; yes, queue is full mov di, _rxInOfs ;; ES:DI -> buffer at queue input mov newInOffset, ax ;; remember new input offset ;; NOTE. rxInOfs is updated after the packet has been copied ;; to ES:DI (= DS:SI on 2nd call) by the packet driver ENDM ;------------------------------------------------------------------------ ; ; This routine gets called by the packet driver twice: ; 1st time (AX=0) it requests an address where to put the packet ; ; 2nd time (AX=1) the packet has been copied to this location (DS:SI) ; BX has client handle (stored in RX_ELEMENT.handle). ; CX has # of bytes in packet on both call. They should be equal. ; ; A test for equality is done by putting CX in _pktRxBuf [n].firstCount ; and _pktRxBuf[n].secondCount, and CL on first call in ; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive" ; (PKTDRVR.C) ; ;--------------------------------------------------------------------- _PktReceiver: pushf cli ; no distraction wanted ! push ds push bx ifdef DOSX mov bx, cs else mov bx, SEG _DATA endif mov ds, bx mov es, bx ; ES = DS = CS or seg _DATA pop bx ; restore handle cmp ax, 0 ; first call? (AX=0) jne @post ; AX=1: second call, do post process ifdef DEBUG SHOW_RX ; show that a packet is received endif cmp cx, RX_BUF_SIZE+14 ; size OK ? ja @skip ; no, packet to large for us ENQUEUE ; ES:DI -> _pktRxBuf[n] mov [di].firstCount, cx ; remember the first count. mov [di].handle, bx ; remember the handle. add di, 6 ; ES:DI -> _pktRxBuf[n].destinAdr pop ds popf retf ; far return to driver with ES:DI align 4 @dump: inc _pktDrop[0] ; discard the packet on 1st call adc _pktDrop[2], 0 ; increment packets lost @skip: xor di, di ; return ES:DI = NIL pointer xor ax, ax mov es, ax pop ds popf retf align 4 @post: or si, si ; DS:SI->_pktRxBuf[n][n].destinAdr jz @discard ; make sure we don't use NULL-pointer sub si, 6 ; DS:SI -> _pktRxBuf[n].destinAdr ; ; push si ; push [si].firstCount ; call bpf_filter_match ; run the filter here some day? ; add sp, 4 ; cmp ax, 0 ; je @discard mov [si].secondCount, cx mov ax, newInOffset mov _rxInOfs, ax ; update _pktRxBuf input offset align 4 @discard:pop ds popf retf _pktRxEnd db 0 ; marker for end of r-mode code/data _TEXT ENDS END libpcap-0.9.7/./msdos/makefile.wc0000644000026300017500000000763710160767675014711 0ustar mcrmcr# # Watcom Makefile for dos-libpcap. # # Specify MODEL = `3r' or `3s' # Specify TARGET = `pharlap' or `dos4g' # # Use this makefile from the libpcap root directory. # E.g. like this: # # c:\net\pcap> wmake -f msdos\makefile.wc # MODEL = 3s TARGET = dos4g OBJDIR = msdos\$(TARGET).w$(MODEL) LIB = $(OBJDIR)\pcap.lib .EXTENSIONS: .l .y DEFS = -dDEBUG -dNDIS_DEBUG -d_U_= -dHAVE_LIMITS_H -dHAVE_STRERROR & -dHAVE_SNPRINTF -dHAVE_VSNPRINTF CC = wcc386.exe ASM = wasm.exe -$(MODEL) $(DEFS) -dDOSX -dDOS4GW -zq -bt=dos -fr=nul -d3 -s OBJS = $(OBJDIR)\grammar.obj $(OBJDIR)\scanner.obj $(OBJDIR)\pcap.obj & $(OBJDIR)\bpf_filt.obj $(OBJDIR)\bpf_imag.obj $(OBJDIR)\bpf_dump.obj & $(OBJDIR)\etherent.obj $(OBJDIR)\gencode.obj $(OBJDIR)\nametoad.obj & $(OBJDIR)\pcap-dos.obj $(OBJDIR)\pktdrvr.obj $(OBJDIR)\optimize.obj & $(OBJDIR)\savefile.obj $(OBJDIR)\inet.obj $(OBJDIR)\ndis2.obj CFLAGS = $(DEFS) $(YYDEFS) -I. -I$(%watt_root)\inc -I.\msdos\pm_drvr & -$(MODEL) -mf -zff -zgf -zq -bt=dos -fr=nul -w6 -fpi & -oilrtf -zm TEMPBIN = tmp.bin all: $(OBJDIR) $(OBJDIR)\pcap.lib $(OBJDIR): - mkdir $(OBJDIR) $(OBJDIR)\pcap.lib: $(OBJS) wlib.arg wlib -q -b -c $(OBJDIR)\pcap.lib @wlib.arg wlib.arg: msdos\makefile.wc %create $^@ for %f in ($(OBJS)) do %append $^@ +- %f $(OBJDIR)\pktdrvr.obj: msdos\pkt_stub.inc msdos\pktdrvr.c gnuc.h & pcap-dos.h pcap-int.h pcap.h msdos\pktdrvr.h *$(CC) $(CFLAGS) msdos\pktdrvr.c -fo=$@ $(OBJDIR)\ndis2.obj: msdos\ndis2.c *$(CC) $(CFLAGS) msdos\ndis2.c -fo=$@ .ERASE .c{$(OBJDIR)}.obj: *$(CC) $(CFLAGS) $[@ -fo=$@ grammar.c tokdefs.h: grammar.y bison --name-prefix=pcap_ --yacc --defines $[@ - @del grammar.c - @del tokdefs.h ren y_tab.c grammar.c ren y_tab.h tokdefs.h scanner.c: scanner.l flex -Ppcap_ -7 -o$@ $[@ msdos\pkt_stub.inc: bin2c.exe msdos\pkt_rx1.S nasm -fbin -dDEBUG -o $(TEMPBIN) -lmsdos\pkt_rx1.lst msdos\pkt_rx1.S bin2c.exe $(TEMPBIN) > $@ @del $(TEMPBIN) bin2c.exe: msdos\bin2c.c wcl $[@ clean realclean vclean: .SYMBOLIC for %f in (dos4g.w3r dos4g.w3s pharlap.w3r pharlap.w3s) do & @del %f\*.obj @del grammar.c @del tokdefs.h @del scanner.c @del bin2c.exe @del bin2c.obj @del msdos\pkt_stub.inc @echo Cleaned # # dependencies # $(OBJDIR)\bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h $(OBJDIR)\bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h $(OBJDIR)\bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h $(OBJDIR)\etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-nam.h $(OBJDIR)\optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h $(OBJDIR)\savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h $(OBJDIR)\pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h $(OBJDIR)\inet.obj: inet.c pcap-int.h pcap.h pcap-bpf.h $(OBJDIR)\grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h & pf.h pcap-nam.h $(OBJDIR)\scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h & pcap-nam.h tokdefs.h $(OBJDIR)\gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h & ethertyp.h nlpid.h llc.h gencode.h atmuni31.h sunatmpo.h ppp.h sll.h & arcnet.h pf.h pcap-nam.h $(OBJDIR)\nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h & pcap-nam.h ethertyp.h $(OBJDIR)\pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h & msdos\pktdrvr.h $(OBJDIR)\pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h & pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc $(OBJDIR)\ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h & msdos\ndis2.h libpcap-0.9.7/./msdos/makefile0000644000026300017500000001205210160767674014263 0ustar mcrmcr# # Makefile for dos-libpcap. NB. This makefile requires a Borland # compatible make tool. # # Targets: # Borland C 4.0+ (DOS large model) # Metaware HighC 3.3+ (PharLap 386|DosX) # .AUTODEPEND .SWAP !if "$(WATT_ROOT)" == "" !error Environment variable "WATT_ROOT" not set. !endif WATT_INC = $(WATT_ROOT)\inc DEFS = -DMSDOS -DDEBUG -DNDIS_DEBUG -D_U_= -Dinline= \ -DHAVE_STRERROR -DHAVE_LIMITS_H ASM = tasm.exe -t -l -mx -m2 -DDEBUG SOURCE = grammar.c scanner.c bpf_filt.c bpf_imag.c bpf_dump.c \ etherent.c gencode.c nametoad.c pcap-dos.c optimize.c \ savefile.c pcap.c inet.c msdos\ndis2.c msdos\pktdrvr.c \ missing\snprintf.c BORLAND_OBJ = $(SOURCE:.c=.obj) msdos\pkt_rx0.obj msdos\ndis_0.obj HIGHC_OBJ = $(SOURCE:.c=.o32) msdos\pkt_rx0.o32 all: @echo Usage: make pcap_bc.lib or pcap_hc.lib pcap_bc.lib: bcc.arg $(BORLAND_OBJ) pcap_bc pcap_hc.lib: hc386.arg $(HIGHC_OBJ) 386lib $< @&&| -nowarn -nobackup -twocase -replace $(HIGHC_OBJ) | pcap_bc: $(BORLAND_OBJ) @tlib pcap_bc.lib /C @&&| -+$(**:.obj=-+) | .c.obj: bcc.exe @bcc.arg -o$*.obj $*.c .c.o32: hc386.exe @hc386.arg -o $*.o32 $*.c .asm.obj: $(ASM) $*.asm, $*.obj .asm.o32: $(ASM) -DDOSX=1 $*.asm, $*.o32 scanner.c: scanner.l flex -Ppcap_ -7 -oscanner.c scanner.l grammar.c tokdefs.h: grammar.y bison --name-prefix=pcap_ --yacc --defines grammar.y - @del grammar.c - @del tokdefs.h ren y_tab.c grammar.c ren y_tab.h tokdefs.h bcc.arg: msdos\Makefile @copy &&| $(DEFS) -ml -c -v -3 -O2 -po -RT- -w- -I$(WATT_INC) -I. -I.\msdos\pm_drvr -H=$(TEMP)\bcc.sym | $< hc386.arg: msdos\Makefile @copy &&| # -DUSE_32BIT_DRIVERS $(DEFS) -DDOSX=1 -w3 -c -g -O5 -I$(WATT_INC) -I. -I.\msdos\pm_drvr -Hsuffix=.o32 -Hnocopyr -Hpragma=Offwarn(491,553,572) -Hon=Recognize_library # make memcpy/strlen etc. inline -Hoff=Behaved # turn off some optimiser warnings | $< clean: @del *.obj @del *.o32 @del *.lst @del *.map @del bcc.arg @del hc386.arg @del grammar.c @del tokdefs.h @del scanner.c @echo Cleaned # # dependencies # pkt_rx0.obj: msdos\pkt_rx0.asm bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h inet.obj: inet.c pcap-int.h pcap.h pcap-bpf.h grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \ pf.h pcap-namedb.h scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \ pcap-namedb.h tokdefs.h gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \ ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \ arcnet.h pf.h pcap-namedb.h nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \ pcap-namedb.h ethertype.h pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \ msdos\pktdrvr.h pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \ pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \ msdos\ndis2.h pkt_rx0.o32: msdos\pkt_rx0.asm bpf_filt.o32: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h bpf_imag.o32: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h bpf_dump.o32: bpf_dump.c pcap.h pcap-bpf.h etherent.o32: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h optimize.o32: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h savefile.o32: savefile.c pcap-int.h pcap.h pcap-bpf.h pcap.o32: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h inet.o32: inet.c pcap-int.h pcap.h pcap-bpf.h grammar.o32: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \ pf.h pcap-namedb.h scanner.o32: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \ pcap-namedb.h tokdefs.h gencode.o32: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \ ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \ arcnet.h pf.h pcap-namedb.h nametoad.o32: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \ pcap-namedb.h ethertype.h pcap-dos.o32: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \ msdos\pktdrvr.h pktdrvr.o32: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \ pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc ndis2.o32: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \ msdos\ndis2.h libpcap-0.9.7/./msdos/ndis2.h0000644000026300017500000004300210160767675013753 0ustar mcrmcr/* * Copyright (c) 1993,1994 * Texas A&M University. 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 Texas A&M University * and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY 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 UNIVERSITY 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. * * Developers: * David K. Hess, Douglas Lee Schales, David R. Safford * * Heavily modified for Metaware HighC + GNU C 2.8+ * Gisle Vanem 1998 */ #ifndef __PCAP_NDIS_H #define __PCAP_NDIS_H #if defined (__HIGHC__) #define pascal _CC(_CALLEE_POPS_STACK & ~_REVERSE_PARMS) /* calling convention */ #define CALLBACK(foo) pascal WORD foo #define PAS_PTR(x,arg) typedef FAR WORD pascal (*x) arg #define GUARD() _inline (0x9C,0xFA) /* pushfd, cli */ #define UNGUARD() _inline (0x9D) /* popfd */ #define FAR _far #elif defined(__GNUC__) #define CALLBACK(foo) WORD foo __attribute__((stdcall)) #define PAS_PTR(x,arg) typedef WORD (*x) arg __attribute__((stdcall)) #define GUARD() __asm__ __volatile__ ("pushfd; cli") #define UNGUARD() __asm__ __volatile__ ("popfd") #define FAR #elif defined (__TURBOC__) #define CALLBACK(foo) WORD pascal foo #define PAS_PTR(x,arg) typedef WORD pascal (_far *x) arg #define GUARD() _asm { pushf; cli } #define UNGUARD() _asm { popf } #define FAR _far #elif defined (__WATCOMC__) #define CALLBACK(foo) WORD pascal foo #define PAS_PTR(x,arg) typedef WORD pascal (_far *x) arg #define GUARD() _disable() #define UNGUARD() _enable() #define FAR _far #else #error Unsupported compiler #endif /* * Forwards */ struct _ReqBlock; struct _TxBufDescr; struct _TDBufDescr; /* * Protocol Manager API */ PAS_PTR (ProtMan, (struct _ReqBlock FAR*, WORD)); /* * System request */ PAS_PTR (SystemRequest, (DWORD, DWORD, WORD, WORD, WORD)); /* * MAC API */ PAS_PTR (TransmitChain, (WORD, WORD, struct _TxBufDescr FAR*, WORD)); PAS_PTR (TransferData, (WORD*,WORD, struct _TDBufDescr FAR*, WORD)); PAS_PTR (Request, (WORD, WORD, WORD, DWORD, WORD, WORD)); PAS_PTR (ReceiveRelease,(WORD, WORD)); PAS_PTR (IndicationOn, (WORD)); PAS_PTR (IndicationOff, (WORD)); typedef enum { HARDWARE_NOT_INSTALLED = 0, HARDWARE_FAILED_DIAG = 1, HARDWARE_FAILED_CONFIG = 2, HARDWARE_HARD_FAULT = 3, HARDWARE_SOFT_FAULT = 4, HARDWARE_OK = 7, HARDWARE_MASK = 0x0007, MAC_BOUND = 0x0008, MAC_OPEN = 0x0010, DIAG_IN_PROGRESS = 0x0020 } NdisMacStatus; typedef enum { STATUS_RING_STATUS = 1, STATUS_ADAPTER_CHECK = 2, STATUS_START_RESET = 3, STATUS_INTERRUPT = 4, STATUS_END_RESET = 5 } NdisStatus; typedef enum { FILTER_DIRECTED = 1, FILTER_BROADCAST = 2, FILTER_PROMISCUOUS = 4, FILTER_SOURCE_ROUTE = 8 } NdisPacketFilter; typedef enum { REQ_INITIATE_DIAGNOSTICS = 1, REQ_READ_ERROR_LOG = 2, REQ_SET_STATION_ADDRESS = 3, REQ_OPEN_ADAPTER = 4, REQ_CLOSE_ADAPTER = 5, REQ_RESET_MAC = 6, REQ_SET_PACKET_FILTER = 7, REQ_ADD_MULTICAST_ADDRESS = 8, REQ_DELETE_MULTICAST_ADDRESS = 9, REQ_UPDATE_STATISTICS = 10, REQ_CLEAR_STATISTICS = 11, REQ_INTERRUPT_REQUEST = 12, REQ_SET_FUNCTIONAL_ADDRESS = 13, REQ_SET_LOOKAHEAD = 14 } NdisGeneralRequest; typedef enum { SF_BROADCAST = 0x00000001L, SF_MULTICAST = 0x00000002L, SF_FUNCTIONAL = 0x00000004L, SF_PROMISCUOUS = 0x00000008L, SF_SOFT_ADDRESS = 0x00000010L, SF_STATS_CURRENT = 0x00000020L, SF_INITIATE_DIAGS = 0x00000040L, SF_LOOPBACK = 0x00000080L, SF_RECEIVE_CHAIN = 0x00000100L, SF_SOURCE_ROUTING = 0x00000200L, SF_RESET_MAC = 0x00000400L, SF_OPEN_CLOSE = 0x00000800L, SF_INTERRUPT_REQUEST = 0x00001000L, SF_SOURCE_ROUTING_BRIDGE = 0x00002000L, SF_VIRTUAL_ADDRESSES = 0x00004000L } NdisMacServiceFlags; typedef enum { REQ_INITIATE_BIND = 1, REQ_BIND = 2, REQ_INITIATE_PREBIND = 3, REQ_INITIATE_UNBIND = 4, REQ_UNBIND = 5 } NdisSysRequest; typedef enum { PM_GET_PROTOCOL_MANAGER_INFO = 1, PM_REGISTER_MODULE = 2, PM_BIND_AND_START = 3, PM_GET_PROTOCOL_MANAGER_LINKAGE = 4, PM_GET_PROTOCOL_INI_PATH = 5, PM_REGISTER_PROTOCOL_MANAGER_INFO = 6, PM_INIT_AND_REGISTER = 7, PM_UNBIND_AND_STOP = 8, PM_BIND_STATUS = 9, PM_REGISTER_STATUS = 10 } NdisProtManager; typedef enum { ERR_SUCCESS = 0x00, ERR_WAIT_FOR_RELEASE = 0x01, ERR_REQUEST_QUEUED = 0x02, ERR_FRAME_NOT_RECOGNIZED = 0x03, ERR_FRAME_REJECTED = 0x04, ERR_FORWARD_FRAME = 0x05, ERR_OUT_OF_RESOURCE = 0x06, ERR_INVALID_PARAMETER = 0x07, ERR_INVALID_FUNCTION = 0x08, ERR_NOT_SUPPORTED = 0x09, ERR_HARDWARE_ERROR = 0x0A, ERR_TRANSMIT_ERROR = 0x0B, ERR_NO_SUCH_DESTINATION = 0x0C, ERR_BUFFER_TOO_SMALL = 0x0D, ERR_ALREADY_STARTED = 0x20, ERR_INCOMPLETE_BINDING = 0x21, ERR_DRIVER_NOT_INITIALIZED = 0x22, ERR_HARDWARE_NOT_FOUND = 0x23, ERR_HARDWARE_FAILURE = 0x24, ERR_CONFIGURATION_FAILURE = 0x25, ERR_INTERRUPT_CONFLICT = 0x26, ERR_INCOMPATIBLE_MAC = 0x27, ERR_INITIALIZATION_FAILED = 0x28, ERR_NO_BINDING = 0x29, ERR_NETWORK_MAY_NOT_BE_CONNECTED = 0x2A, ERR_INCOMPATIBLE_OS_VERSION = 0x2B, ERR_ALREADY_REGISTERED = 0x2C, ERR_PATH_NOT_FOUND = 0x2D, ERR_INSUFFICIENT_MEMORY = 0x2E, ERR_INFO_NOT_FOUND = 0x2F, ERR_GENERAL_FAILURE = 0xFF } NdisError; #define NDIS_PARAM_INTEGER 0 #define NDIS_PARAM_STRING 1 #define NDIS_TX_BUF_LENGTH 8 #define NDIS_TD_BUF_LENGTH 1 #define NDIS_RX_BUF_LENGTH 8 #define NDIS_PTR_PHYSICAL 0 #define NDIS_PTR_VIRTUAL 2 #define NDIS_PATH "PROTMAN$" typedef struct _CommonChars { WORD tableSize; BYTE majorNdisVersion; /* 2 - Latest version */ BYTE minorNdisVersion; /* 0 */ WORD reserved1; BYTE majorModuleVersion; BYTE minorModuleVersion; DWORD moduleFlags; /* 0 - Binding at upper boundary supported * 1 - Binding at lower boundary supported * 2 - Dynamically bound. * 3-31 - Reserved, must be zero. */ BYTE moduleName[16]; BYTE protocolLevelUpper; /* 1 - MAC * 2 - Data Link * 3 - Network * 4 - Transport * 5 - Session * -1 - Not specified */ BYTE interfaceUpper; BYTE protocolLevelLower; /* 0 - Physical * 1 - MAC * 2 - Data Link * 3 - Network * 4 - Transport * 5 - Session * -1 - Not specified */ BYTE interfaceLower; WORD moduleId; WORD moduleDS; SystemRequest systemRequest; BYTE *serviceChars; BYTE *serviceStatus; BYTE *upperDispatchTable; BYTE *lowerDispatchTable; BYTE *reserved2; /* Must be NULL */ BYTE *reserved3; /* Must be NULL */ } CommonChars; typedef struct _MulticastList { WORD maxMulticastAddresses; WORD numberMulticastAddresses; BYTE multicastAddress[16][16]; } MulticastList; typedef struct _MacChars { WORD tableSize; BYTE macName[16]; WORD addressLength; BYTE permanentAddress[16]; BYTE currentAddress[16]; DWORD currentFunctionalAddress; MulticastList *multicastList; DWORD linkSpeed; DWORD serviceFlags; WORD maxFrameSize; DWORD txBufferSize; WORD txBufferAllocSize; DWORD rxBufferSize; WORD rxBufferAllocSize; BYTE ieeeVendor[3]; BYTE vendorAdapter; BYTE *vendorAdapterDescription; WORD interruptLevel; WORD txQueueDepth; WORD maxDataBlocks; } MacChars; typedef struct _ProtocolChars { WORD length; BYTE name[16]; WORD type; } ProtocolChars; typedef struct _MacUpperDispatch { CommonChars *backPointer; Request request; TransmitChain transmitChain; TransferData transferData; ReceiveRelease receiveRelease; IndicationOn indicationOn; IndicationOff indicationOff; } MacUpperDispatch; typedef struct _MacStatusTable { WORD tableSize; DWORD lastDiag; DWORD macStatus; WORD packetFilter; BYTE *mediaSpecificStats; DWORD lastClear; DWORD totalFramesRx; DWORD totalFramesCrc; DWORD totalBytesRx; DWORD totalDiscardBufSpaceRx; DWORD totalMulticastRx; DWORD totalBroadcastRx; DWORD obsolete1[5]; DWORD totalDiscardHwErrorRx; DWORD totalFramesTx; DWORD totalBytesTx; DWORD totalMulticastTx; DWORD totalBroadcastTx; DWORD obsolete2[2]; DWORD totalDiscardTimeoutTx; DWORD totalDiscardHwErrorTx; } MacStatusTable; typedef struct _ProtDispatch { CommonChars *backPointer; DWORD flags; /* 0 - handles non-LLC frames * 1 - handles specific-LSAP LLC frames * 2 - handles specific-LSAP LLC frames * 3-31 - reserved must be 0 */ void (*requestConfirm) (void); void (*transmitConfirm) (void); void (*receiveLookahead) (void); void (*indicationComplete) (void); void (*receiveChain) (void); void (*status) (void); } ProtDispatch; typedef struct _ReqBlock { WORD opcode; WORD status; BYTE FAR *pointer1; BYTE FAR *pointer2; WORD word1; } ReqBlock; typedef struct _TxBufDescrRec { BYTE txPtrType; BYTE dummy; WORD txDataLen; BYTE *txDataPtr; } TxBufDescrRec; typedef struct _TxBufDescr { WORD txImmedLen; BYTE *txImmedPtr; WORD txDataCount; TxBufDescrRec txBufDescrRec[NDIS_TX_BUF_LENGTH]; } TxBufDescr; typedef struct _TDBufDescrRec { BYTE tDPtrType; BYTE dummy; WORD tDDataLen; BYTE *tDDataPtr; } TDBufDescrRec; typedef struct _TDBufDescr { WORD tDDataCount; TDBufDescrRec tDBufDescrRec[NDIS_TD_BUF_LENGTH]; } TDBufDescr; typedef struct _RxBufDescrRec { WORD rxDataLen; BYTE *rxDataPtr; } RxBufDescrRec; typedef struct _RxBufDescr { WORD rxDataCount; RxBufDescrRec rxBufDescrRec[NDIS_RX_BUF_LENGTH]; } RxBufDescr; typedef struct _PktBuf { struct _PktBuf *nextLink; struct _PktBuf *prevLink; int handle; int length; int packetLength; DWORD sequence; BYTE *buffer; } PktBuf; typedef struct _CardHandle { BYTE moduleName[16]; CommonChars *common; } CardHandle; typedef struct _BindingsList { WORD numBindings; BYTE moduleName[2][16]; } BindingsList; typedef struct _FailingModules { BYTE upperModuleName[16]; BYTE lowerModuleName[16]; } FailingModules; typedef union _HardwareAddress { BYTE bytes[6]; WORD words[3]; struct { BYTE bytes[6]; } addr; } HardwareAddress; typedef struct _FddiHeader { BYTE frameControl; HardwareAddress etherDestHost; HardwareAddress etherSrcHost; } FddiHeader; typedef struct _EthernetIIHeader { HardwareAddress etherDestHost; HardwareAddress etherSrcHost; WORD etherType; } EthernetIIHeader; typedef struct _Ieee802Dot5Header { HardwareAddress etherDestHost; HardwareAddress etherSrcHost; BYTE routeInfo[30]; } Ieee802Dot5Header; typedef struct _Ieee802Dot2SnapHeader { BYTE dsap; /* 0xAA */ BYTE ssap; /* 0xAA */ BYTE control; /* 3 */ BYTE protocolId[5]; } Ieee802Dot2SnapHeader; /* * Prototypes */ extern char *NdisLastError (void); extern int NdisOpen (void); extern int NdisInit (int promis); extern int NdisRegisterAndBind (int promis); extern void NdisShutdown (void); extern void NdisCheckMacFeatures (struct _CardHandle *card); extern int NdisSendPacket (struct _PktBuf *pktBuf, int macId); /* * Assembly "glue" functions */ extern int systemRequestGlue(); extern int requestConfirmGlue(); extern int transmitConfirmGlue(); extern int receiveLookaheadGlue(); extern int indicationCompleteGlue(); extern int receiveChainGlue(); extern int statusGlue(); /* * IOCTL function */ #ifdef __SMALL__ extern int _far NdisGetLinkage (int handle, char *data, int size); #else extern int NdisGetLinkage (int handle, char *data, int size); #endif /* * NDIS callback handlers */ CALLBACK (NdisSystemRequest (DWORD,DWORD, WORD, WORD, WORD)); CALLBACK (NdisRequestConfirm ( WORD, WORD, WORD, WORD, WORD,WORD)); CALLBACK (NdisTransmitConfirm ( WORD, WORD, WORD, WORD, WORD)); CALLBACK (NdisReceiveLookahead ( WORD, WORD, WORD, BYTE*, BYTE*, WORD)); CALLBACK (NdisReceiveChain ( WORD, WORD, WORD, struct _RxBufDescr*, BYTE*, WORD)); CALLBACK (NdisStatusProc ( WORD, WORD, BYTE*, WORD,WORD)); CALLBACK (NdisIndicationComplete( WORD, WORD)); BYTE *NdisAllocStack (void); void NdisFreeStack (BYTE*); #ifdef __HIGHC__ #define RENAME_ASM_SYM(x) pragma Alias(x,"@" #x "") /* prepend `@' */ #define RENAME_C_SYM(x) pragma Alias(x,"_" #x "") /* prepend `_' */ RENAME_ASM_SYM (systemRequestGlue); RENAME_ASM_SYM (requestConfirmGlue); RENAME_ASM_SYM (transmitConfirmGlue); RENAME_ASM_SYM (receiveLookaheadGlue); RENAME_ASM_SYM (indicationCompleteGlue); RENAME_ASM_SYM (receiveChainGlue); RENAME_ASM_SYM (statusGlue); RENAME_ASM_SYM (NdisGetLinkage); RENAME_C_SYM (NdisSystemRequest); RENAME_C_SYM (NdisRequestConfirm); RENAME_C_SYM (NdisTransmitConfirm); RENAME_C_SYM (NdisReceiveLookahead); RENAME_C_SYM (NdisIndicationComplete); RENAME_C_SYM (NdisReceiveChain); RENAME_C_SYM (NdisStatusProc); RENAME_C_SYM (NdisAllocStack); RENAME_C_SYM (NdisFreeStack); #endif #endif libpcap-0.9.7/./msdos/readme.dos0000644000026300017500000001326410161355265014523 0ustar mcrmcr@(#) $Header: /tcpdump/master/libpcap/msdos/readme.dos,v 1.3 2004/12/19 19:47:01 guy Exp $ (LBL) libpcap for DOS --------------- This file contains some notes on building and using libpcap for MS-DOS. Look in `README' and `pcap.man' for usage and details. These targets are supported: - Borland C 4.0+ small or large model. - Metaware HighC 3.1+ with PharLap DOS-extender - GNU C 2.7+ with djgpp 2.01+ DOS extender - Watcom C 11.x with DOS4GW extender Note: the files in the libpcap.zip contains short trucated filenames. So for djgpp to work with these, disable the use of long file names by setting "LFN=n" in the environment. Files specific to DOS are pcap-dos.[ch] and the assembly and C files in the MSDOS sub-directory. Remember to built lipcap libraries from the top install directory. And not from the MSDOS sub-directory. Note for djgpp users: If you got the libpcap from the official site www.tcpdump, then that distribution does NOT contain any sources for building 32-bit drivers. Instead get the full version at http://www.bgnett.no/~giva/pcap/libpcap.zip and set "USE_32BIT_DRIVERS = 1" in msdos\common.dj. Requirements ------------ DOS-libpcap currently only works reliably with a real-mode Ethernet packet- driver. This driver must be installed prior to using any program (e.g. tcpdump) compiled with libpcap. Work is underway to implement protected- mode drivers for 32-bit targets (djgpp only). The 3Com 3c509 driver is working almost perfectly. Due to lack of LAN-cards, I've not had the opportunity to test other drivers. These 32-bit drivers are modified Linux drivers. Required packages ----------------- The following packages and tools must be present for all targets. 1. Watt-32 tcp/ip library. This library is *not* used to send or receive network data. It's mostly used to access the 'hosts' file and other features. Get 'watt32s*.zip' at: http://www.bgnett.no/~giva/ 2. Exception handler and disassember library (libexc.a) is needed if "USE_EXCEPT = 1" in common.dj. Available at: http://www.bgnett.no/~giva/misc/exc_dx07.zip 3. Flex & Bison is used to generate parser for the filter handler pcap_compile: ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/flx254b.zip ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsn128b.zip 4. NASM assembler v 0.98 or later is required when building djgpp and Watcom targets: ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/nasm098p.zip 5. sed (Stream Editor) is required for doing `make depend'. It's available at ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed*.zip A touch tool to update the time-stamp of a file. E.g. ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/grep*.zip 6. For djgpp rm.exe and cp.exe are required. These should already be part of your djgpp installation. Also required (experimental at the time) for djgpp is DLX 2.91 or later. This tool is for the generation of dynamically loadable modules. Compiling libpcap ----------------- Follow these steps in building libpcap: 1. Make sure you've installed Watt-32 properly (see it's `INSTALL' file). During that installation a environment variable `WATT_ROOT' is set. This variable is used for building libpcap also (`WATT_INC' is deducted from `WATT_ROOT'). djgpp users should also define environment variables `C_INCLUDE_PATH' and `LIBRARY_PATH' to point to the include directory and library directory respectively. E.g. put this in your AUTOEXEC.BAT: set C_INCLUDE_PATH=c:/net/watt/inc set LIBRARY_PATH=c:/net/watt/lib 2. Revise the msdos/common.dj file for your djgpp/gcc installation; - change the value of `GCCLIB' to match location of libgcc.a. - set `USE_32BIT_DRIVERS = 1' to build 32-bit driver objects. 3. Build pcap by using appropriate makefile. For djgpp, use: `make -f msdos/makefile.dj' (i.e. GNU `make') For a Watcom target say: `wmake -f msdos\makefile.wc' For a Borland target say: `maker -f msdos\Makefile pcap_bc.lib' (Borland's `maker.exe') And for a HighC/Pharlap target say: `maker -f msdos\Makefile pcap_hc.lib' (Borland's `maker.exe') You might like to change some `CFLAGS' -- only `DEBUG' define currently have any effect. It shows a rotating "fan" in upper right corner of screen. Remove `DEBUG' if you don't like it. You could add `-fomit-frame-pointer' to `CFLAGS' to speed up the generated code. But note, this makes debugging and crash-traceback difficult. Only add it if you're fully confident your application is 100% stable. Note: Code in `USE_NDIS2' does not work at the moment. 4. The resulting libraries are put in current directory. There's no test-program for `libpcap'. Linking the library with `tcpdump' is the ultimate test anyway. Extensions to libpcap --------------------- I've included some extra functions to DOS-libpcap: `pcap_config_hook (const char *name, const char *value)' Allows an application to set values of internal libpcap variables. `name' is typically a left-side keyword with an associated `value' that is called from application's configure process (see tcpdump's config.c file). libpcap keeps a set of tables that are searched for a name/value match. Currently only used to set debug-levels and parameters for the 32-bit network drivers. `pcap_set_wait (pcap_t *, void (*)(void), int)' : Only effective when reading offline traffic from dump-files. Function `pcap_offline_read()' will wait (and optionally yield) before printing next packet. This will simulate the pace the packets where actually recorded. Happy sniffing ! Gisle Vanem October 1999, 2004 libpcap-0.9.7/./msdos/makefile.dj0000644000026300017500000001236210161354522014644 0ustar mcrmcr# # GNU Makefile for DOS-libpcap. djgpp version. # # Use this makefile from the libpcap root directory. # E.g. like this: # # c:\net\pcap> make -f msdos/makefile.dj # # @(#) $Header: /tcpdump/master/libpcap/msdos/makefile.dj,v 1.2 2004/12/19 19:41:06 guy Exp $ (LBL) VPATH = missing msdos PREREQUISITES = scanner.c grammar.c tokdefs.h version.h msdos/pkt_stub.inc include msdos/common.dj DRIVER_DIR = ./msdos/pm_drvr CFLAGS += -DDEBUG -DNDIS_DEBUG -DHAVE_LIMITS_H -DHAVE_STRERROR \ -D_U_='__attribute__((unused))' -DHAVE_VERSION_H # CFLAGS += -Dyylval=pcap_lval -DBDEBUG -DNDEBUG SOURCES = grammar.c scanner.c bpf_filt.c bpf_imag.c bpf_dump.c \ etherent.c gencode.c nametoad.c pcap-dos.c optimize.c \ savefile.c pcap.c inet.c msdos\pktdrvr.c msdos/ndis2.c \ missing/snprintf.c OBJECTS = $(notdir $(SOURCES:.c=.o)) TEMPBIN = tmp.bin ifeq ($(USE_32BIT_DRIVERS),1) PM_OBJECTS = $(addprefix $(DRIVER_DIR)/, \ printk.o pci.o pci-scan.o bios32.o dma.o irq.o intwrap.o \ lock.o kmalloc.o quirks.o timer.o net_init.o) # # Static link of drivers # ifeq ($(USE_32BIT_MODULES),0) PM_OBJECTS += $(addprefix $(DRIVER_DIR)/, \ accton.o 8390.o 3c503.o 3c509.o 3c59x.o 3c515.o \ 3c575_cb.o 3c90x.o ne.o wd.o cs89x0.o rtl8139.o) endif endif all: libpcap.a ifeq ($(USE_32BIT_DRIVERS),1) $(PM_OBJECTS): $(MAKE) -f Makefile.dj -C $(DRIVER_DIR) $(notdir $@) endif libpcap.a: version.h $(OBJECTS) $(PM_OBJECTS) rm -f $@ ar rs $@ $^ msdos/pkt_stub.inc: msdos/bin2c.exe msdos/pkt_rx1.S $(ASM) -o $(TEMPBIN) -lmsdos/pkt_rx1.lst msdos/pkt_rx1.S ./msdos/bin2c $(TEMPBIN) > $@ rm -f $(TEMPBIN) grammar.c tokdefs.h: grammar.y rm -f grammar.c tokdefs.h $(YACC) --name-prefix=pcap_ --yacc --defines grammar.y mv -f y_tab.c grammar.c mv -f y_tab.h tokdefs.h version.h: ./VERSION @echo '/* Generated from VERSION. Do not edit */' > $@ sed -e 's/.*/static char pcap_version_string[] = "libpcap (&)";/' ./VERSION >> $@ scanner.c: scanner.l $(LEX) -Ppcap_ -7 -t $^ > $@ @echo msdos/bin2c.exe: msdos/bin2c.c $(CC) $*.c -o $*.exe clean: $(MAKE) -f Makefile.dj -C $(DRIVER_DIR) clean $(MAKE) -f Makefile.dj -C libcpcap clean rm -f $(OBJECTS) msdos/pkt_rx1.lst Makefile.bak $(PREREQUISITES) vclean: clean rm -f libpcap.a msdos/bin2c.exe # # Generated dependencies; Due to some hacks in gcc 2.95 and djgpp 2.03 # we must prevent "$(DJDIR)/bin/../include/sys/version.h" from beeing # included in dependency output (or else this makefile cannot be used on # another machine). We therefore use a special 'specs' file during # pre-processing. # MM_SPECS = specs.tmp MAKEFILE = msdos/Makefile.dj depend: $(PREREQUISITES) @echo Generating dependencies.. @cp $(MAKEFILE) Makefile.bak @echo "*cpp: %(cpp_cpu) %{posix:-D_POSIX_SOURCE} -remap" > $(MM_SPECS) sed -e "/^# DO NOT DELETE THIS LINE/,$$d" < Makefile.bak > $(MAKEFILE) echo "# DO NOT DELETE THIS LINE" >> $(MAKEFILE) $(CC) -MM -specs=$(MM_SPECS) $(CFLAGS) $(SOURCES) >> $(MAKEFILE) rm -f $(MM_SPECS) # # Manually generated dependencies # msdos/pktdrvr.c: msdos/pkt_stub.inc scanner.c: scanner.l grammar.c tokdefs.h: grammar.y grammar.h: grammar.y scanner.l: pcap-int.h pcap-namedb.h gencode.h grammar.h gnuc.h grammar.y: pcap-int.h gencode.h pcap-namedb.h gnuc.h # # Automatically generated dependencies # # DO NOT DELETE THIS LINE grammar.o: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h pf.h \ pcap-namedb.h scanner.o: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h pcap-namedb.h \ tokdefs.h bpf_filt.o: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h bpf_imag.o: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h bpf_dump.o: bpf_dump.c pcap.h pcap-bpf.h etherent.o: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h gencode.o: gencode.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \ pcap-bpf.h ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h \ ppp.h sll.h arcnet.h pf.h pcap-namedb.h nametoad.o: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \ pcap-namedb.h ethertype.h pcap-dos.o: pcap-dos.c msdos/pm_drvr/pmdrvr.h msdos/pm_drvr/iface.h \ msdos/pm_drvr/lock.h msdos/pm_drvr/ioport.h pcap-dos.h pcap-int.h \ pcap.h pcap-bpf.h msdos/pm_drvr/kmalloc.h msdos/pm_drvr/bitops.h \ msdos/pm_drvr/timer.h msdos/pm_drvr/dma.h msdos/pm_drvr/irq.h \ msdos/pm_drvr/printk.h msdos/pm_drvr/pci.h msdos/pm_drvr/bios32.h \ msdos/pm_drvr/module.h msdos/pm_drvr/3c501.h msdos/pm_drvr/3c503.h \ msdos/pm_drvr/3c509.h msdos/pm_drvr/3c59x.h msdos/pm_drvr/3c515.h \ msdos/pm_drvr/3c90x.h msdos/pm_drvr/3c575_cb.h msdos/pm_drvr/ne.h \ msdos/pm_drvr/wd.h msdos/pm_drvr/accton.h msdos/pm_drvr/cs89x0.h \ msdos/pm_drvr/rtl8139.h msdos/pm_drvr/ne2k-pci.h msdos/pktdrvr.h optimize.o: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h savefile.o: savefile.c pcap-int.h pcap.h pcap-bpf.h pcap.o: pcap.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \ pcap-bpf.h inet.o: inet.c pcap-int.h pcap.h pcap-bpf.h pktdrvr.o: msdos/pktdrvr.c gnuc.h pcap-dos.h msdos/pm_drvr/lock.h \ pcap-int.h pcap.h pcap-bpf.h msdos/pktdrvr.h msdos/pkt_stub.inc ndis2.o: msdos/ndis2.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \ pcap-bpf.h msdos/ndis2.h snprintf.o: missing/snprintf.c pcap-int.h pcap.h pcap-bpf.h libpcap-0.9.7/./msdos/ndis2.c0000644000026300017500000005714610160767675013764 0ustar mcrmcr/* * Copyright (c) 1993,1994 * Texas A&M University. 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 Texas A&M University * and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY 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 UNIVERSITY 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. * * Developers: * David K. Hess, Douglas Lee Schales, David R. Safford * * Heavily modified for Metaware HighC + GNU C 2.8+ * Gisle Vanem 1998 */ #include #include #include #include #include #include #include #include "pcap-dos.h" #include "pcap-int.h" #include "msdos/ndis2.h" #if defined(USE_NDIS2) /* * Packet buffer handling */ extern int FreePktBuf (PktBuf *buf); extern int EnquePktBuf (PktBuf *buf); extern PktBuf* AllocPktBuf (void); /* * Various defines */ #define MAX_NUM_DEBUG_STRINGS 90 #define DEBUG_STRING_LENGTH 80 #define STACK_POOL_SIZE 6 #define STACK_SIZE 256 #define MEDIA_FDDI 1 #define MEDIA_ETHERNET 2 #define MEDIA_TOKEN 3 static int startDebug = 0; static int stopDebug = 0; static DWORD droppedPackets = 0L; static WORD frameSize = 0; static WORD headerSize = 0; static int mediaType = 0; static char *lastErr = NULL; static BYTE debugStrings [MAX_NUM_DEBUG_STRINGS][DEBUG_STRING_LENGTH]; static BYTE *freeStacks [STACK_POOL_SIZE]; static int freeStackPtr = STACK_POOL_SIZE - 1; static ProtMan protManEntry = NULL; static WORD protManDS = 0; static volatile int xmitPending; static struct _PktBuf *txBufPending; static struct _CardHandle *handle; static struct _CommonChars common; static struct _ProtocolChars protChars; static struct _ProtDispatch lowerTable; static struct _FailingModules failingModules; static struct _BindingsList bindings; static struct { WORD err_num; char *err_text; } ndis_errlist[] = { { ERR_SUCCESS, "The function completed successfully.\n" }, { ERR_WAIT_FOR_RELEASE, "The ReceiveChain completed successfully but the protocol has\n" "retained control of the buffer.\n" }, { ERR_REQUEST_QUEUED, "The current request has been queued.\n" }, { ERR_FRAME_NOT_RECOGNIZED, "Frame not recognized.\n" }, { ERR_FRAME_REJECTED, "Frame was discarded.\n" }, { ERR_FORWARD_FRAME, "Protocol wishes to forward frame to another protocol.\n" }, { ERR_OUT_OF_RESOURCE, "Out of resource.\n" }, { ERR_INVALID_PARAMETER, "Invalid parameter.\n" }, { ERR_INVALID_FUNCTION, "Invalid function.\n" }, { ERR_NOT_SUPPORTED, "Not supported.\n" }, { ERR_HARDWARE_ERROR, "Hardware error.\n" }, { ERR_TRANSMIT_ERROR, "The packet was not transmitted due to an error.\n" }, { ERR_NO_SUCH_DESTINATION, "Token ring packet was not recognized when transmitted.\n" }, { ERR_BUFFER_TOO_SMALL, "Provided buffer was too small.\n" }, { ERR_ALREADY_STARTED, "Network drivers already started.\n" }, { ERR_INCOMPLETE_BINDING, "Protocol driver could not complete its bindings.\n" }, { ERR_DRIVER_NOT_INITIALIZED, "MAC did not initialize properly.\n" }, { ERR_HARDWARE_NOT_FOUND, "Hardware not found.\n" }, { ERR_HARDWARE_FAILURE, "Hardware failure.\n" }, { ERR_CONFIGURATION_FAILURE, "Configuration failure.\n" }, { ERR_INTERRUPT_CONFLICT, "Interrupt conflict.\n" }, { ERR_INCOMPATIBLE_MAC, "The MAC is not compatible with the protocol.\n" }, { ERR_INITIALIZATION_FAILED, "Initialization failed.\n" }, { ERR_NO_BINDING, "Binding did not occur.\n" }, { ERR_NETWORK_MAY_NOT_BE_CONNECTED, "The network may not be connected to the adapter.\n" }, { ERR_INCOMPATIBLE_OS_VERSION, "The version of the operating system is incompatible with the protocol.\n" }, { ERR_ALREADY_REGISTERED, "The protocol is already registered.\n" }, { ERR_PATH_NOT_FOUND, "PROTMAN.EXE could not be found.\n" }, { ERR_INSUFFICIENT_MEMORY, "Insufficient memory.\n" }, { ERR_INFO_NOT_FOUND, "Protocol Mananger info structure is lost or corrupted.\n" }, { ERR_GENERAL_FAILURE, "General failure.\n" } }; /* * Some handy macros */ #define PERROR(str) printf("%s (%d): %s\n", __FILE__,__LINE__,str) #define DEBUG_RING() (debugStrings[stopDebug+1 == MAX_NUM_DEBUG_STRINGS ? \ stopDebug = 0 : ++stopDebug]) /* * needs rewrite for DOSX */ #define MAC_DISPATCH(hnd) ((struct _MacUpperDispatch*)(hnd)->common->upperDispatchTable) #define MAC_STATUS(hnd) ((struct _MacStatusTable*) (hnd)->common->serviceStatus) #define MAC_CHAR(hnd) ((struct _MacChars*) (hnd)->common->serviceChars) #ifdef NDIS_DEBUG #define DEBUG0(str) printf (str) #define DEBUG1(fmt,a) printf (fmt,a) #define DEBUG2(fmt,a,b) printf (fmt,a,b) #define TRACE0(str) sprintf (DEBUG_RING(),str) #define TRACE1(fmt,a) sprintf (DEBUG_RING(),fmt,a) #else #define DEBUG0(str) ((void)0) #define DEBUG1(fmt,a) ((void)0) #define DEBUG2(fmt,a,b) ((void)0) #define TRACE0(str) ((void)0) #define TRACE1(fmt,a) ((void)0) #endif /* * This routine is called from both threads */ void NdisFreeStack (BYTE *aStack) { GUARD(); if (freeStackPtr == STACK_POOL_SIZE - 1) PERROR ("tried to free too many stacks"); freeStacks[++freeStackPtr] = aStack; if (freeStackPtr == 0) TRACE0 ("freeStackPtr went positive\n"); UNGUARD(); } /* * This routine is called from callbacks to allocate local data */ BYTE *NdisAllocStack (void) { BYTE *stack; GUARD(); if (freeStackPtr < 0) { /* Ran out of stack buffers. Return NULL which will start * dropping packets */ TRACE0 ("freeStackPtr went negative\n"); stack = 0; } else stack = freeStacks[freeStackPtr--]; UNGUARD(); return (stack); } CALLBACK (NdisSystemRequest (DWORD param1, DWORD param2, WORD param3, WORD opcode, WORD targetDS)) { static int bindEntry = 0; struct _CommonChars *macCommon; volatile WORD result; switch (opcode) { case REQ_INITIATE_BIND: macCommon = (struct _CommonChars*) param2; if (macCommon == NULL) { printf ("There is an NDIS misconfiguration.\n"); result = ERR_GENERAL_FAILURE; break; } DEBUG2 ("module name %s\n" "module type %s\n", macCommon->moduleName, ((MacChars*) macCommon->serviceChars)->macName); /* Binding to the MAC */ result = macCommon->systemRequest ((DWORD)&common, (DWORD)&macCommon, 0, REQ_BIND, macCommon->moduleDS); if (!strcmp(bindings.moduleName[bindEntry], handle->moduleName)) handle->common = macCommon; else PERROR ("unknown module"); ++bindEntry; break; case REQ_INITIATE_UNBIND: macCommon = (struct _CommonChars*) param2; result = macCommon->systemRequest ((DWORD)&common, 0, 0, REQ_UNBIND, macCommon->moduleDS); break; default: result = ERR_GENERAL_FAILURE; break; } ARGSUSED (param1); ARGSUSED (param3); ARGSUSED (targetDS); return (result); } CALLBACK (NdisRequestConfirm (WORD protId, WORD macId, WORD reqHandle, WORD status, WORD request, WORD protDS)) { ARGSUSED (protId); ARGSUSED (macId); ARGSUSED (reqHandle); ARGSUSED (status); ARGSUSED (request); ARGSUSED (protDS); return (ERR_SUCCESS); } CALLBACK (NdisTransmitConfirm (WORD protId, WORD macId, WORD reqHandle, WORD status, WORD protDS)) { xmitPending--; FreePktBuf (txBufPending); /* Add passed ECB back to the free list */ ARGSUSED (reqHandle); ARGSUSED (status); ARGSUSED (protDS); return (ERR_SUCCESS); } /* * The primary function for receiving packets */ CALLBACK (NdisReceiveLookahead (WORD macId, WORD frameSize, WORD bytesAvail, BYTE *buffer, BYTE *indicate, WORD protDS)) { int result; PktBuf *pktBuf; WORD bytesCopied; struct _TDBufDescr tDBufDescr; #if 0 TRACE1 ("lookahead length = %d, ", bytesAvail); TRACE1 ("ecb = %08lX, ", *ecb); TRACE1 ("count = %08lX\n", count); TRACE1 ("offset = %08lX, ", offset); TRACE1 ("timesAllowed = %d, ", timesAllowed); TRACE1 ("packet size = %d\n", look->dataLookAheadLen); #endif /* Allocate a buffer for the packet */ if ((pktBuf = AllocPktBuf()) == NULL) { droppedPackets++; return (ERR_FRAME_REJECTED); } /* * Now kludge things. Note we will have to undo this later. This will * make the packet contiguous after the MLID has done the requested copy. */ tDBufDescr.tDDataCount = 1; tDBufDescr.tDBufDescrRec[0].tDPtrType = NDIS_PTR_PHYSICAL; tDBufDescr.tDBufDescrRec[0].tDDataPtr = pktBuf->buffer; tDBufDescr.tDBufDescrRec[0].tDDataLen = pktBuf->length; tDBufDescr.tDBufDescrRec[0].dummy = 0; result = MAC_DISPATCH(handle)->transferData (&bytesCopied, 0, &tDBufDescr, handle->common->moduleDS); pktBuf->packetLength = bytesCopied; if (result == ERR_SUCCESS) EnquePktBuf(pktBuf); else FreePktBuf (pktBuf); ARGSUSED (frameSize); ARGSUSED (bytesAvail); ARGSUSED (indicate); ARGSUSED (protDS); return (ERR_SUCCESS); } CALLBACK (NdisIndicationComplete (WORD macId, WORD protDS)) { ARGSUSED (macId); ARGSUSED (protDS); /* We don't give a hoot about these. Just return */ return (ERR_SUCCESS); } /* * This is the OTHER way we may receive packets */ CALLBACK (NdisReceiveChain (WORD macId, WORD frameSize, WORD reqHandle, struct _RxBufDescr *rxBufDescr, BYTE *indicate, WORD protDS)) { struct _PktBuf *pktBuf; int i; /* * For now we copy the entire packet over to a PktBuf structure. This may be * a performance hit but this routine probably isn't called very much, and * it is a lot of work to do it otherwise. Also if it is a filter protocol * packet we could end up sucking up MAC buffes. */ if ((pktBuf = AllocPktBuf()) == NULL) { droppedPackets++; return (ERR_FRAME_REJECTED); } pktBuf->packetLength = 0; /* Copy the packet to the buffer */ for (i = 0; i < rxBufDescr->rxDataCount; ++i) { struct _RxBufDescrRec *rxDescr = &rxBufDescr->rxBufDescrRec[i]; memcpy (pktBuf->buffer + pktBuf->packetLength, rxDescr->rxDataPtr, rxDescr->rxDataLen); pktBuf->packetLength += rxDescr->rxDataLen; } EnquePktBuf (pktBuf); ARGSUSED (frameSize); ARGSUSED (reqHandle); ARGSUSED (indicate); ARGSUSED (protDS); /* This frees up the buffer for the MAC to use */ return (ERR_SUCCESS); } CALLBACK (NdisStatusProc (WORD macId, WORD param1, BYTE *indicate, WORD opcode, WORD protDS)) { switch (opcode) { case STATUS_RING_STATUS: break; case STATUS_ADAPTER_CHECK: break; case STATUS_START_RESET: break; case STATUS_INTERRUPT: break; case STATUS_END_RESET: break; default: break; } ARGSUSED (macId); ARGSUSED (param1); ARGSUSED (indicate); ARGSUSED (opcode); ARGSUSED (protDS); /* We don't need to do anything about this stuff yet */ return (ERR_SUCCESS); } /* * Tell the NDIS driver to start the delivery of the packet */ int NdisSendPacket (struct _PktBuf *pktBuf, int macId) { struct _TxBufDescr txBufDescr; int result; xmitPending++; txBufPending = pktBuf; /* we only have 1 pending Tx at a time */ txBufDescr.txImmedLen = 0; txBufDescr.txImmedPtr = NULL; txBufDescr.txDataCount = 1; txBufDescr.txBufDescrRec[0].txPtrType = NDIS_PTR_PHYSICAL; txBufDescr.txBufDescrRec[0].dummy = 0; txBufDescr.txBufDescrRec[0].txDataLen = pktBuf->packetLength; txBufDescr.txBufDescrRec[0].txDataPtr = pktBuf->buffer; result = MAC_DISPATCH(handle)->transmitChain (common.moduleId, pktBuf->handle, &txBufDescr, handle->common->moduleDS); switch (result) { case ERR_OUT_OF_RESOURCE: /* Note that this should not happen but if it does there is not * much we can do about it */ printf ("ERROR: transmit queue overflowed\n"); return (0); case ERR_SUCCESS: /* Everything was hunky dory and synchronous. Free up the * packet buffer */ xmitPending--; FreePktBuf (pktBuf); return (1); case ERR_REQUEST_QUEUED: /* Everything was hunky dory and asynchronous. Do nothing */ return (1); default: printf ("Tx fail, code = %04X\n", result); return (0); } } static int ndis_nerr = sizeof(ndis_errlist) / sizeof(ndis_errlist[0]); static char *Ndis_strerror (WORD errorCode) { static char buf[30]; int i; for (i = 0; i < ndis_nerr; i++) if (errorCode == ndis_errlist[i].err_num) return (ndis_errlist[i].err_text); sprintf (buf,"unknown error %d",errorCode); return (buf); } char *NdisLastError (void) { char *errStr = lastErr; lastErr = NULL; return (errStr); } int NdisOpen (void) { struct _ReqBlock reqBlock; int result; int ndisFd = open (NDIS_PATH, O_RDONLY); if (ndisFd < 0) { printf ("Could not open NDIS Protocol Manager device.\n"); return (0); } memset (&reqBlock, 0, sizeof(ReqBlock)); reqBlock.opcode = PM_GET_PROTOCOL_MANAGER_LINKAGE; result = NdisGetLinkage (ndisFd, (char*)&reqBlock, sizeof(ReqBlock)); if (result != 0) { printf ("Could not get Protocol Manager linkage.\n"); close (ndisFd); return (0); } close (ndisFd); protManEntry = (ProtMan) reqBlock.pointer1; protManDS = reqBlock.word1; DEBUG2 ("Entry Point = %04X:%04X\n", FP_SEG(protManEntry),FP_OFF(protManEntry)); DEBUG1 ("ProtMan DS = %04X\n", protManDS); return (1); } int NdisRegisterAndBind (int promis) { struct _ReqBlock reqBlock; WORD result; memset (&common,0,sizeof(common)); common.tableSize = sizeof (common); common.majorNdisVersion = 2; common.minorNdisVersion = 0; common.majorModuleVersion = 2; common.minorModuleVersion = 0; /* Indicates binding from below and dynamically loaded */ common.moduleFlags = 0x00000006L; strcpy (common.moduleName, "PCAP"); common.protocolLevelUpper = 0xFF; common.protocolLevelLower = 1; common.interfaceLower = 1; #ifdef __DJGPP__ common.moduleDS = _dos_ds; /* the callback data segment */ #else common.moduleDS = _DS; #endif common.systemRequest = (SystemRequest) systemRequestGlue; common.serviceChars = (BYTE*) &protChars; common.serviceStatus = NULL; common.upperDispatchTable = NULL; common.lowerDispatchTable = (BYTE*) &lowerTable; protChars.length = sizeof (protChars); protChars.name[0] = 0; protChars.type = 0; lowerTable.backPointer = &common; lowerTable.requestConfirm = requestConfirmGlue; lowerTable.transmitConfirm = transmitConfirmGlue; lowerTable.receiveLookahead = receiveLookaheadGlue; lowerTable.indicationComplete = indicationCompleteGlue; lowerTable.receiveChain = receiveChainGlue; lowerTable.status = statusGlue; lowerTable.flags = 3; if (promis) lowerTable.flags |= 4; /* promiscous mode (receive everything) */ bindings.numBindings = 1; strcpy (bindings.moduleName[0], handle->moduleName); /* Register ourselves with NDIS */ reqBlock.opcode = PM_REGISTER_MODULE; reqBlock.pointer1 = (BYTE FAR*) &common; reqBlock.pointer2 = (BYTE FAR*) &bindings; result = (*protManEntry) (&reqBlock, protManDS); if (result) { printf ("Protman registering failed: %s\n", Ndis_strerror(result)); return (0); } /* Start the binding process */ reqBlock.opcode = PM_BIND_AND_START; reqBlock.pointer1 = (BYTE FAR*) &failingModules; result = (*protManEntry) (&reqBlock, protManDS); if (result) { printf ("Start binding failed: %s\n", Ndis_strerror(result)); return (0); } return (1); } static int CheckMacFeatures (CardHandle *card) { DWORD serviceFlags; BYTE _far *mediaString; BYTE _far *mac_addr; DEBUG2 ("checking card features\n" "common table address = %08lX, macId = %d\n", card->common, card->common->moduleId); serviceFlags = MAC_CHAR (handle)->serviceFlags; if ((serviceFlags & SF_PROMISCUOUS) == 0) { printf ("The MAC %s does not support promiscuous mode.\n", card->moduleName); return (0); } mediaString = MAC_CHAR (handle)->macName; DEBUG1 ("media type = %s\n",mediaString); /* Get the media type. And set the header size */ if (!strncmp(mediaString,"802.3",5) || !strncmp(mediaString,"DIX",3) || !strncmp(mediaString,"DIX+802.3",9)) headerSize = sizeof (EthernetIIHeader); else if (!strncmp(mediaString,"FDDI",4)) headerSize = sizeof (FddiHeader) + sizeof (Ieee802Dot2SnapHeader); else { printf ("Unsupported MAC type: `%s'\n", mediaString); return (0); } frameSize = MAC_CHAR (handle)->maxFrameSize; mac_addr = MAC_CHAR (handle)->currentAddress; printf ("Hardware address: %02X:%02X:%02X:%02X:%02X:%02X\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); return (1); } static int NdisStartMac (CardHandle *card) { WORD result; /* Set the lookahead length */ result = MAC_DISPATCH(handle)->request (common.moduleId, 0, headerSize, 0, REQ_SET_LOOKAHEAD, card->common->moduleDS); /* We assume that if we got INVALID PARAMETER then either this * is not supported or will work anyway. NE2000 does this. */ if (result != ERR_SUCCESS && result != ERR_INVALID_PARAMETER) { DEBUG1 ("Set lookahead failed: %s\n", Ndis_strerror(result)); return (0); } /* Set the packet filter. Note that for some medias and drivers we * must specify all three flags or the card(s) will not operate correctly. */ result = MAC_DISPATCH(handle)->request (common.moduleId, 0, /* all packets */ FILTER_PROMISCUOUS | /* packets to us */ FILTER_DIRECTED | /* broadcasts */ FILTER_BROADCAST, 0, REQ_SET_PACKET_FILTER, card->common->moduleDS); if (result != ERR_SUCCESS) { DEBUG1 ("Set packet filter failed: %s\n", Ndis_strerror(result)); return (0); } /* If OPEN/CLOSE supported then open the adapter */ if (MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) { result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, NULL, REQ_OPEN_ADAPTER, card->common->moduleDS); if (result != ERR_SUCCESS) { DEBUG1 ("Opening the MAC failed: %s\n", Ndis_strerror(result)); return (0); } } return (1); } void NdisShutdown (void) { struct _ReqBlock reqBlock; int result, i; if (!handle) return; /* If the adapters support open and are open then close them */ if ((MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) && (MAC_STATUS(handle)->macStatus & MAC_OPEN)) { result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, 0, REQ_CLOSE_ADAPTER, handle->common->moduleDS); if (result != ERR_SUCCESS) { printf ("Closing the MAC failed: %s\n", Ndis_strerror(result)); return; } } /* Tell the Protocol Manager to unbind and stop */ reqBlock.opcode = PM_UNBIND_AND_STOP; reqBlock.pointer1 = (BYTE FAR*) &failingModules; reqBlock.pointer2 = NULL; result = (*protManEntry) (&reqBlock, protManDS); if (result) printf ("Unbind failed: %s\n", Ndis_strerror(result)); for (i = 0; i < STACK_POOL_SIZE; ++i) free (freeStacks[i] - STACK_SIZE); handle = NULL; } int NdisInit (int promis) { int i, result; /* Allocate the real mode stacks used for NDIS callbacks */ for (i = 0; i < STACK_POOL_SIZE; ++i) { freeStacks[i] = malloc (STACK_SIZE); if (!freeStacks[i]) return (0); freeStacks[i] += STACK_SIZE; } if (!NdisOpen()) return (0); if (!NdisRegisterAndBind(promis)) return (0); DEBUG1 ("My module id: %d\n", common.moduleId); DEBUG1 ("Handle id; %d\n", handle->common->moduleId); DEBUG1 ("MAC card: %-16s - ", handle->moduleName); atexit (NdisShutdown); if (!CheckMacFeatures(&handle)) return (0); switch (mediaType) { case MEDIA_FDDI: DEBUG0 ("Media type: FDDI"); break; case MEDIA_ETHERNET: DEBUG0 ("Media type: ETHERNET"); break; default: DEBUG0 ("Unsupported media.\n"); return (0); } DEBUG1 (" - Frame size: %d\n", frameSize); if (!NdisStartMac(&handle)) return (0); return (1); } #endif /* USE_NDIS2 */ libpcap-0.9.7/./msdos/CVS/0000755000026300017500000000000010651261567013211 5ustar mcrmcrlibpcap-0.9.7/./msdos/CVS/Entries0000644000026300017500000000130110651261567014540 0ustar mcrmcr/bin2c.c/1.1/Sat Dec 18 08:52:12 2004//Tlibpcap_0_9 /common.dj/1.2/Sun Dec 19 19:36:33 2004//Tlibpcap_0_9 /makefile/1.1/Sat Dec 18 08:52:12 2004//Tlibpcap_0_9 /makefile.dj/1.2/Sun Dec 19 19:41:06 2004//Tlibpcap_0_9 /makefile.wc/1.1/Sat Dec 18 08:52:13 2004//Tlibpcap_0_9 /ndis2.c/1.1/Sat Dec 18 08:52:13 2004//Tlibpcap_0_9 /ndis2.h/1.1/Sat Dec 18 08:52:13 2004//Tlibpcap_0_9 /ndis_0.asm/1.1/Sat Dec 18 08:52:13 2004//Tlibpcap_0_9 /pkt_rx0.asm/1.1/Sat Dec 18 08:52:13 2004//Tlibpcap_0_9 /pkt_rx1.s/1.1/Sat Dec 18 08:52:13 2004//Tlibpcap_0_9 /pktdrvr.c/1.1/Sat Dec 18 08:52:14 2004//Tlibpcap_0_9 /pktdrvr.h/1.1/Sat Dec 18 08:52:14 2004//Tlibpcap_0_9 /readme.dos/1.3/Sun Dec 19 19:47:01 2004//Tlibpcap_0_9 D libpcap-0.9.7/./msdos/CVS/Root0000644000026300017500000000004010245661232014041 0ustar mcrmcrcvs.tcpdump.org:/tcpdump/master libpcap-0.9.7/./msdos/CVS/Repository0000644000026300017500000000001610245661232015300 0ustar mcrmcrlibpcap/msdos libpcap-0.9.7/./msdos/CVS/Tag0000644000026300017500000000001510245661232013633 0ustar mcrmcrTlibpcap_0_9 libpcap-0.9.7/./msdos/bin2c.c0000644000026300017500000000163710160767674013733 0ustar mcrmcr#include #include #include #include static void Abort (char *fmt,...) { va_list args; va_start (args, fmt); vfprintf (stderr, fmt, args); va_end (args); exit (1); } int main (int argc, char **argv) { FILE *inFile; FILE *outFile = stdout; time_t now = time (NULL); int ch, i; if (argc != 2) Abort ("Usage: %s bin-file [> result]", argv[0]); if ((inFile = fopen(argv[1],"rb")) == NULL) Abort ("Cannot open %s\n", argv[1]); fprintf (outFile, "/* data statements for file %s at %.24s */\n" "/* Generated by BIN2C, G.Vanem 1995 */\n", argv[1], ctime(&now)); i = 0; while ((ch = fgetc(inFile)) != EOF) { if (i++ % 12 == 0) fputs ("\n ", outFile); fprintf (outFile, "0x%02X,", ch); } fputc ('\n', outFile); fclose (inFile); return (0); } libpcap-0.9.7/./msdos/pkt_rx1.s0000644000026300017500000001215410160767675014343 0ustar mcrmcr; ; This file requires NASM 0.97+ to assemble ; ; Currently used only for djgpp + DOS4GW targets ; ; these sizes MUST be equal to the sizes in PKTDRVR.H ; %define ETH_MTU 1500 ; max data size on Ethernet %define ETH_MIN 60 ; min/max total frame size %define ETH_MAX (ETH_MTU+2*6+2) %define NUM_RX_BUF 32 ; # of RX element buffers %define RX_SIZE (ETH_MAX+6) ; sizeof(RX_ELEMENT) = 1514+6 %idefine offset struc RX_ELEMENT .firstCount resw 1 ; # of bytes on 1st call .secondCount resw 1 ; # of bytes on 2nd call .handle resw 1 ; handle for upcall ; .timeStamp resw 4 ; 64-bit RDTSC value .destinAdr resb 6 ; packet destination address .sourceAdr resb 6 ; packet source address .protocol resw 1 ; packet protocol number .rxBuffer resb ETH_MTU ; RX buffer endstruc ;------------------------------------------- [org 0] ; assemble to .bin file _rxOutOfs dw offset _pktRxBuf ; ring buffer offsets _rxInOfs dw offset _pktRxBuf ; into _pktRxBuf _pktDrop dw 0,0 ; packet drop counter _pktTemp resb 20 ; temp work area _pktTxBuf resb (ETH_MAX) ; TX buffer _pktRxBuf resb (RX_SIZE*NUM_RX_BUF) ; RX structures LAST_OFS equ $ screenSeg dw 0B800h newInOffset dw 0 fanChars db '-\|/' fanIndex dw 0 %macro SHOW_RX 0 push es push bx mov bx, [screenSeg] mov es, bx ;; r-mode segment of colour screen mov di, 158 ;; upper right corner - 1 mov bx, [fanIndex] mov al, [fanChars+bx] ;; get write char mov ah, 15 ;; and white colour cld ;; Needed? stosw ;; write to screen at ES:EDI inc word [fanIndex] ;; update next index and word [fanIndex], 3 pop bx pop es %endmacro ;PutTimeStamp ; rdtsc ; mov [si].timeStamp, eax ; mov [si+4].timeStamp, edx ; ret ;------------------------------------------------------------------------ ; ; This routine gets called by the packet driver twice: ; 1st time (AX=0) it requests an address where to put the packet ; ; 2nd time (AX=1) the packet has been copied to this location (DS:SI) ; BX has client handle (stored in RX_ELEMENT.handle). ; CX has # of bytes in packet on both call. They should be equal. ; A test for equality is done by putting CX in _pktRxBuf [n].firstCount ; and _pktRxBuf[n].secondCount, and CL on first call in ; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive" ; (PKTDRVR.C) ; ;--------------------------------------------------------------------- _PktReceiver: pushf cli ; no distraction wanted ! push ds push bx mov bx, cs mov ds, bx mov es, bx ; ES = DS = CS or seg _DATA pop bx ; restore handle cmp ax, 0 ; first call? (AX=0) jne @post ; AX=1: second call, do post process %ifdef DEBUG SHOW_RX ; show that a packet is received %endif cmp cx, ETH_MAX ; size OK ? ja @skip ; no, too big mov ax, [_rxInOfs] add ax, RX_SIZE cmp ax, LAST_OFS jb @noWrap mov ax, offset _pktRxBuf @noWrap: cmp ax, [_rxOutOfs] je @dump mov di, [_rxInOfs] ; ES:DI -> _pktRxBuf[n] mov [newInOffset], ax mov [di], cx ; remember firstCount. mov [di+4], bx ; remember handle. add di, 6 ; ES:DI -> _pktRxBuf[n].destinAdr pop ds popf retf ; far return to driver with ES:DI @dump: add word [_pktDrop+0], 1 ; discard the packet on 1st call adc word [_pktDrop+2], 0 ; increment packets lost @skip: xor di, di ; return ES:DI = NIL pointer xor ax, ax mov es, ax pop ds popf retf @post: or si, si ; DS:SI->_pktRxBuf[n][n].destinAdr jz @discard ; make sure we don't use NULL-pointer ; ; push si ; call bpf_filter_match ; run the filter here some day ; pop si ; cmp ax, 0 ; je @discard mov [si-6+2], cx ; store _pktRxBuf[n].secondCount mov ax, [newInOffset] mov [_rxInOfs], ax ; update _pktRxBuf input offset ; call PutTimeStamp @discard: pop ds popf retf _pktRxEnd db 0 ; marker for end of r-mode code/data END libpcap-0.9.7/./msdos/common.dj0000644000026300017500000000301410161354101014342 0ustar mcrmcr# # Common defines for libpcap and 16/32-bit network drivers (djgpp) # # @(#) $Header: /tcpdump/master/libpcap/msdos/common.dj,v 1.2 2004/12/19 19:36:33 guy Exp $ (LBL) .SUFFIXES: .exe .wlm .dxe .l .y .PHONY: check_gcclib default: check_gcclib all GCCLIB = /djgpp/lib/gcc-lib/djgpp/3.31 MAKEFILE = Makefile.dj # # DLX 2.91+ lib. Change path to suite. # Not used anymore. Uses DXE3 now. # # DLX_LIB = $(DJDIR)/contrib/dlx.291/libdlx.a # DLX_LINK = $(DJDIR)/bin/dlxgen.exe WATT32_ROOT = $(subst \,/,$(WATT_ROOT)) ifeq ($(wildcard $(GCCLIB)/libgcc.a),) check_gcclib: @echo libgcc.a not found. Set \"$(GCCLIB)\" to \"/djgpp/lib/gcc-lib/djgpp/3.X\" endif # # Include 32-bit driver support # USE_32BIT_DRIVERS = 0 # # Use loadable driver modules instead of statically linking # all drivers. # USE_32BIT_MODULES = 0 # # Put interrupt sensitive code/data in locked sections # Do `make clean' in all affected directories after changing this. # USE_SECTION_LOCKING = 0 # # Set to 1 to use exception handler lib (only for me) # USE_EXCEPT = 0 CC = gcc.exe LD = ld.exe ASM = nasm.exe -fbin -dDEBUG YACC = bison.exe LEX = flex.exe CFLAGS = -g -gcoff -O2 -Wall -I. -I$(WATT32_ROOT)/inc ifeq ($(USE_EXCEPT),1) CFLAGS += -DUSE_EXCEPT EXC_LIB = d:/prog/mw/except/lib/libexc.a endif ifeq ($(USE_SECTION_LOCKING),1) CFLAGS += -DUSE_SECTION_LOCKING endif ifeq ($(USE_32BIT_DRIVERS),1) CFLAGS += -DUSE_32BIT_DRIVERS endif %.o: %.c $(CC) -c $(CFLAGS) $< @echo %.o: %.s $(CC) -c $(CFLAGS) -x assembler-with-cpp -o $@ $< @echo libpcap-0.9.7/./msdos/pktdrvr.c0000644000026300017500000011615410160767676014435 0ustar mcrmcr/* * File.........: pktdrvr.c * * Responsible..: Gisle Vanem, giva@bgnett.no * * Created......: 26.Sept 1995 * * Description..: Packet-driver interface for 16/32-bit C : * Borland C/C++ 3.0+ small/large model * Watcom C/C++ 11+, DOS4GW flat model * Metaware HighC 3.1+ and PharLap 386|DosX * GNU C/C++ 2.7+ and djgpp 2.x extender * * References...: PC/TCP Packet driver Specification. rev 1.09 * FTP Software Inc. * */ #include #include #include #include #include "gnuc.h" #include "pcap-dos.h" #include "pcap-int.h" #include "msdos/pktdrvr.h" #if (DOSX) #define NUM_RX_BUF 32 /* # of buffers in Rx FIFO queue */ #else #define NUM_RX_BUF 10 #endif #define DIM(x) (sizeof((x)) / sizeof(x[0])) #define PUTS(s) do { \ if (!pktInfo.quiet) \ pktInfo.error ? \ printf ("%s: %s\n", s, pktInfo.error) : \ printf ("%s\n", pktInfo.error = s); \ } while (0) #if defined(__HIGHC__) extern UINT _mwenv; #elif defined(__DJGPP__) #include #include #include #include #include #elif defined(__WATCOMC__) #include #include extern char _Extender; #else extern void far PktReceiver (void); #endif #if (DOSX & (DJGPP|DOS4GW)) #include struct DPMI_regs { DWORD r_di; DWORD r_si; DWORD r_bp; DWORD reserved; DWORD r_bx; DWORD r_dx; DWORD r_cx; DWORD r_ax; WORD r_flags; WORD r_es, r_ds, r_fs, r_gs; WORD r_ip, r_cs, r_sp, r_ss; }; /* Data located in a real-mode segment. This becomes far at runtime */ typedef struct { /* must match data/code in pkt_rx1.s */ WORD _rxOutOfs; WORD _rxInOfs; DWORD _pktDrop; BYTE _pktTemp [20]; TX_ELEMENT _pktTxBuf[1]; RX_ELEMENT _pktRxBuf[NUM_RX_BUF]; WORD _dummy[2]; /* screenSeg,newInOffset */ BYTE _fanChars[4]; WORD _fanIndex; BYTE _PktReceiver[15]; /* starts on a paragraph (16byte) */ } PktRealStub; #include static BYTE real_stub_array [] = { #include "pkt_stub.inc" /* generated opcode array */ }; #define rxOutOfs offsetof (PktRealStub,_rxOutOfs) #define rxInOfs offsetof (PktRealStub,_rxInOfs) #define PktReceiver offsetof (PktRealStub,_PktReceiver [para_skip]) #define pktDrop offsetof (PktRealStub,_pktDrop) #define pktTemp offsetof (PktRealStub,_pktTemp) #define pktTxBuf offsetof (PktRealStub,_pktTxBuf) #define FIRST_RX_BUF offsetof (PktRealStub,_pktRxBuf [0]) #define LAST_RX_BUF offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1]) #else extern WORD rxOutOfs; /* offsets into pktRxBuf FIFO queue */ extern WORD rxInOfs; extern DWORD pktDrop; /* # packets dropped in PktReceiver() */ extern BYTE pktRxEnd; /* marks the end of r-mode code/data */ extern RX_ELEMENT pktRxBuf [NUM_RX_BUF]; /* PktDrvr Rx buffers */ extern TX_ELEMENT pktTxBuf; /* PktDrvr Tx buffer */ extern char pktTemp[20]; /* PktDrvr temp area */ #define FIRST_RX_BUF (WORD) &pktRxBuf [0] #define LAST_RX_BUF (WORD) &pktRxBuf [NUM_RX_BUF-1] #endif #ifdef __BORLANDC__ /* Use Borland's inline functions */ #define memcpy __memcpy__ #define memcmp __memcmp__ #define memset __memset__ #endif #if (DOSX & PHARLAP) extern void PktReceiver (void); /* in pkt_rx0.asm */ static int RealCopy (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*); #undef FP_SEG #undef FP_OFF #define FP_OFF(x) ((WORD)(x)) #define FP_SEG(x) ((WORD)(realBase >> 16)) #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o)) #define r_ax eax #define r_bx ebx #define r_dx edx #define r_cx ecx #define r_si esi #define r_di edi #define r_ds ds #define r_es es LOCAL FARPTR protBase; LOCAL REALPTR realBase; LOCAL WORD realSeg; /* DOS para-address of allocated area */ LOCAL SWI_REGS reg; static WORD _far *rxOutOfsFp, *rxInOfsFp; #elif (DOSX & DJGPP) static _go32_dpmi_seginfo rm_mem; static __dpmi_regs reg; static DWORD realBase; static int para_skip = 0; #define DOS_ADDR(s,o) (((WORD)(s) << 4) + (o)) #define r_ax x.ax #define r_bx x.bx #define r_dx x.dx #define r_cx x.cx #define r_si x.si #define r_di x.di #define r_ds x.ds #define r_es x.es #elif (DOSX & DOS4GW) LOCAL struct DPMI_regs reg; LOCAL WORD rm_base_seg, rm_base_sel; LOCAL DWORD realBase; LOCAL int para_skip = 0; LOCAL DWORD dpmi_get_real_vector (int intr); LOCAL WORD dpmi_real_malloc (int size, WORD *selector); LOCAL void dpmi_real_free (WORD selector); #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o)) #else /* real-mode Borland etc. */ static struct { WORD r_ax, r_bx, r_cx, r_dx, r_bp; WORD r_si, r_di, r_ds, r_es, r_flags; } reg; #endif #ifdef __HIGHC__ #pragma Alias (pktDrop, "_pktDrop") #pragma Alias (pktRxBuf, "_pktRxBuf") #pragma Alias (pktTxBuf, "_pktTxBuf") #pragma Alias (pktTemp, "_pktTemp") #pragma Alias (rxOutOfs, "_rxOutOfs") #pragma Alias (rxInOfs, "_rxInOfs") #pragma Alias (pktRxEnd, "_pktRxEnd") #pragma Alias (PktReceiver,"_PktReceiver") #endif PUBLIC PKT_STAT pktStat; /* statistics for packets */ PUBLIC PKT_INFO pktInfo; /* packet-driver information */ PUBLIC PKT_RX_MODE receiveMode = PDRX_DIRECT; PUBLIC ETHER myAddress = { 0, 0, 0, 0, 0, 0 }; PUBLIC ETHER ethBroadcast = { 255,255,255,255,255,255 }; LOCAL struct { /* internal statistics */ DWORD tooSmall; /* size < ETH_MIN */ DWORD tooLarge; /* size > ETH_MAX */ DWORD badSync; /* count_1 != count_2 */ DWORD wrongHandle; /* upcall to wrong handle */ } intStat; /***************************************************************************/ PUBLIC const char *PktGetErrorStr (int errNum) { static const char *errStr[] = { "", "Invalid handle number", "No interfaces of specified class found", "No interfaces of specified type found", "No interfaces of specified number found", "Bad packet type specified", "Interface does not support multicast", "Packet driver cannot terminate", "Invalid receiver mode specified", "Insufficient memory space", "Type previously accessed, and not released", "Command out of range, or not implemented", "Cannot send packet (usually hardware error)", "Cannot change hardware address ( > 1 handle open)", "Hardware address has bad length or format", "Cannot reset interface (more than 1 handle open)", "Bad Check-sum", "Bad size", "Bad sync" , "Source hit" }; if (errNum < 0 || errNum >= DIM(errStr)) return ("Unknown driver error."); return (errStr [errNum]); } /**************************************************************************/ PUBLIC const char *PktGetClassName (WORD class) { switch (class) { case PD_ETHER: return ("DIX-Ether"); case PD_PRONET10: return ("ProNET-10"); case PD_IEEE8025: return ("IEEE 802.5"); case PD_OMNINET: return ("OmniNet"); case PD_APPLETALK: return ("AppleTalk"); case PD_SLIP: return ("SLIP"); case PD_STARTLAN: return ("StartLAN"); case PD_ARCNET: return ("ArcNet"); case PD_AX25: return ("AX.25"); case PD_KISS: return ("KISS"); case PD_IEEE8023_2: return ("IEEE 802.3 w/802.2 hdr"); case PD_FDDI8022: return ("FDDI w/802.2 hdr"); case PD_X25: return ("X.25"); case PD_LANstar: return ("LANstar"); case PD_PPP: return ("PPP"); default: return ("unknown"); } } /**************************************************************************/ PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode) { static const char *modeStr [] = { "Receiver turned off", "Receive only directly addressed packets", "Receive direct & broadcast packets", "Receive direct,broadcast and limited multicast packets", "Receive direct,broadcast and all multicast packets", "Receive all packets (promiscuouos mode)" }; if (mode > DIM(modeStr)) return ("??"); return (modeStr [mode-1]); } /**************************************************************************/ LOCAL __inline BOOL PktInterrupt (void) { BOOL okay; #if (DOSX & PHARLAP) _dx_real_int ((UINT)pktInfo.intr, ®); okay = ((reg.flags & 1) == 0); /* OK if carry clear */ #elif (DOSX & DJGPP) __dpmi_int ((int)pktInfo.intr, ®); okay = ((reg.x.flags & 1) == 0); #elif (DOSX & DOS4GW) union REGS r; struct SREGS s; memset (&r, 0, sizeof(r)); segread (&s); r.w.ax = 0x300; r.x.ebx = pktInfo.intr; r.w.cx = 0; s.es = FP_SEG (®); r.x.edi = FP_OFF (®); reg.r_flags = 0; reg.r_ss = reg.r_sp = 0; /* DPMI host provides stack */ int386x (0x31, &r, &r, &s); okay = (!r.w.cflag); #else reg.r_flags = 0; intr (pktInfo.intr, (struct REGPACK*)®); okay = ((reg.r_flags & 1) == 0); #endif if (okay) pktInfo.error = NULL; else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8); return (okay); } /**************************************************************************/ /* * Search for packet driver at interrupt 60h through 80h. If ASCIIZ * string "PKT DRVR" found at offset 3 in the interrupt handler, return * interrupt number, else return zero in pktInfo.intr */ PUBLIC BOOL PktSearchDriver (void) { BYTE intr = 0x20; BOOL found = FALSE; while (!found && intr < 0xFF) { static char str[12]; /* 3 + strlen("PKT DRVR") */ static char pktStr[9] = "PKT DRVR"; /* ASCIIZ string at ofs 3 */ DWORD rp; /* in interrupt routine */ #if (DOSX & PHARLAP) _dx_rmiv_get (intr, &rp); ReadRealMem (&str, (REALPTR)rp, sizeof(str)); #elif (DOSX & DJGPP) __dpmi_raddr realAdr; __dpmi_get_real_mode_interrupt_vector (intr, &realAdr); rp = (realAdr.segment << 4) + realAdr.offset16; dosmemget (rp, sizeof(str), &str); #elif (DOSX & DOS4GW) rp = dpmi_get_real_vector (intr); memcpy (&str, (void*)rp, sizeof(str)); #else _fmemcpy (&str, getvect(intr), sizeof(str)); #endif found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0; intr++; } pktInfo.intr = (found ? intr-1 : 0); return (found); } /**************************************************************************/ static BOOL PktSetAccess (void) { reg.r_ax = 0x0200 + pktInfo.class; reg.r_bx = 0xFFFF; reg.r_dx = 0; reg.r_cx = 0; #if (DOSX & PHARLAP) reg.ds = 0; reg.esi = 0; reg.es = RP_SEG (realBase); reg.edi = (WORD) &PktReceiver; #elif (DOSX & DJGPP) reg.x.ds = 0; reg.x.si = 0; reg.x.es = rm_mem.rm_segment; reg.x.di = PktReceiver; #elif (DOSX & DOS4GW) reg.r_ds = 0; reg.r_si = 0; reg.r_es = rm_base_seg; reg.r_di = PktReceiver; #else reg.r_ds = 0; reg.r_si = 0; reg.r_es = FP_SEG (&PktReceiver); reg.r_di = FP_OFF (&PktReceiver); #endif if (!PktInterrupt()) return (FALSE); pktInfo.handle = reg.r_ax; return (TRUE); } /**************************************************************************/ PUBLIC BOOL PktReleaseHandle (WORD handle) { reg.r_ax = 0x0300; reg.r_bx = handle; return PktInterrupt(); } /**************************************************************************/ PUBLIC BOOL PktTransmit (const void *eth, int len) { if (len > ETH_MTU) return (FALSE); reg.r_ax = 0x0400; /* Function 4, send pkt */ reg.r_cx = len; /* total size of frame */ #if (DOSX & DJGPP) dosmemput (eth, len, realBase+pktTxBuf); reg.x.ds = rm_mem.rm_segment; /* DOS data segment and */ reg.x.si = pktTxBuf; /* DOS offset to buffer */ #elif (DOSX & DOS4GW) memcpy ((void*)(realBase+pktTxBuf), eth, len); reg.r_ds = rm_base_seg; reg.r_si = pktTxBuf; #elif (DOSX & PHARLAP) memcpy (&pktTxBuf, eth, len); reg.r_ds = FP_SEG (&pktTxBuf); reg.r_si = FP_OFF (&pktTxBuf); #else reg.r_ds = FP_SEG (eth); reg.r_si = FP_OFF (eth); #endif return PktInterrupt(); } /**************************************************************************/ #if (DOSX & (DJGPP|DOS4GW)) LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx) #else LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx) #endif { WORD count_1, count_2; /* * We got an upcall to the same RMCB with wrong handle. * This can happen if we failed to release handle at program exit */ if (rx->handle != pktInfo.handle) { pktInfo.error = "Wrong handle"; intStat.wrongHandle++; PktReleaseHandle (rx->handle); return (FALSE); } count_1 = rx->firstCount; count_2 = rx->secondCount; if (count_1 != count_2) { pktInfo.error = "Bad sync"; intStat.badSync++; return (FALSE); } if (count_1 > ETH_MAX) { pktInfo.error = "Large esize"; intStat.tooLarge++; return (FALSE); } #if 0 if (count_1 < ETH_MIN) { pktInfo.error = "Small esize"; intStat.tooSmall++; return (FALSE); } #endif return (TRUE); } /**************************************************************************/ PUBLIC BOOL PktTerminHandle (WORD handle) { reg.r_ax = 0x0500; reg.r_bx = handle; return PktInterrupt(); } /**************************************************************************/ PUBLIC BOOL PktResetInterface (WORD handle) { reg.r_ax = 0x0700; reg.r_bx = handle; return PktInterrupt(); } /**************************************************************************/ PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode) { if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP) return (TRUE); reg.r_ax = 0x1400; reg.r_bx = pktInfo.handle; reg.r_cx = (WORD)mode; if (!PktInterrupt()) return (FALSE); receiveMode = mode; return (TRUE); } /**************************************************************************/ PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode) { reg.r_ax = 0x1500; reg.r_bx = pktInfo.handle; if (!PktInterrupt()) return (FALSE); *mode = reg.r_ax; return (TRUE); } /**************************************************************************/ static PKT_STAT initialStat; /* statistics at startup */ static BOOL resetStat = FALSE; /* statistics reset ? */ PUBLIC BOOL PktGetStatistics (WORD handle) { reg.r_ax = 0x1800; reg.r_bx = handle; if (!PktInterrupt()) return (FALSE); #if (DOSX & PHARLAP) ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat)); #elif (DOSX & DJGPP) dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat); #elif (DOSX & DOS4GW) memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat)); #else _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat)); #endif return (TRUE); } /**************************************************************************/ PUBLIC BOOL PktSessStatistics (WORD handle) { if (!PktGetStatistics(pktInfo.handle)) return (FALSE); if (resetStat) { pktStat.inPackets -= initialStat.inPackets; pktStat.outPackets -= initialStat.outPackets; pktStat.inBytes -= initialStat.inBytes; pktStat.outBytes -= initialStat.outBytes; pktStat.inErrors -= initialStat.inErrors; pktStat.outErrors -= initialStat.outErrors; pktStat.outErrors -= initialStat.outErrors; pktStat.lost -= initialStat.lost; } return (TRUE); } /**************************************************************************/ PUBLIC BOOL PktResetStatistics (WORD handle) { if (!PktGetStatistics(pktInfo.handle)) return (FALSE); memcpy (&initialStat, &pktStat, sizeof(initialStat)); resetStat = TRUE; return (TRUE); } /**************************************************************************/ PUBLIC BOOL PktGetAddress (ETHER *addr) { reg.r_ax = 0x0600; reg.r_bx = pktInfo.handle; reg.r_cx = sizeof (*addr); #if (DOSX & DJGPP) reg.x.es = rm_mem.rm_segment; reg.x.di = pktTemp; #elif (DOSX & DOS4GW) reg.r_es = rm_base_seg; reg.r_di = pktTemp; #else reg.r_es = FP_SEG (&pktTemp); reg.r_di = FP_OFF (&pktTemp); /* ES:DI = address for result */ #endif if (!PktInterrupt()) return (FALSE); #if (DOSX & PHARLAP) ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr)); #elif (DOSX & DJGPP) dosmemget (realBase+pktTemp, sizeof(*addr), addr); #elif (DOSX & DOS4GW) memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr)); #else memcpy ((void*)addr, &pktTemp, sizeof(*addr)); #endif return (TRUE); } /**************************************************************************/ PUBLIC BOOL PktSetAddress (const ETHER *addr) { /* copy addr to real-mode scrath area */ #if (DOSX & PHARLAP) WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr)); #elif (DOSX & DJGPP) dosmemput (addr, sizeof(*addr), realBase+pktTemp); #elif (DOSX & DOS4GW) memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr)); #else memcpy (&pktTemp, (void*)addr, sizeof(*addr)); #endif reg.r_ax = 0x1900; reg.r_cx = sizeof (*addr); /* address length */ #if (DOSX & DJGPP) reg.x.es = rm_mem.rm_segment; /* DOS offset to param */ reg.x.di = pktTemp; /* DOS segment to param */ #elif (DOSX & DOS4GW) reg.r_es = rm_base_seg; reg.r_di = pktTemp; #else reg.r_es = FP_SEG (&pktTemp); reg.r_di = FP_OFF (&pktTemp); #endif return PktInterrupt(); } /**************************************************************************/ PUBLIC BOOL PktGetDriverInfo (void) { pktInfo.majVer = 0; pktInfo.minVer = 0; memset (&pktInfo.name, 0, sizeof(pktInfo.name)); reg.r_ax = 0x01FF; reg.r_bx = 0; if (!PktInterrupt()) return (FALSE); pktInfo.number = reg.r_cx & 0xFF; pktInfo.class = reg.r_cx >> 8; #if 0 pktInfo.minVer = reg.r_bx % 10; pktInfo.majVer = reg.r_bx / 10; #else pktInfo.majVer = reg.r_bx; // !! #endif pktInfo.funcs = reg.r_ax & 0xFF; pktInfo.type = reg.r_dx & 0xFF; #if (DOSX & PHARLAP) ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name)); #elif (DOSX & DJGPP) dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name); #elif (DOSX & DOS4GW) memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name)); #else _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name)); #endif return (TRUE); } /**************************************************************************/ PUBLIC BOOL PktGetDriverParam (void) { reg.r_ax = 0x0A00; if (!PktInterrupt()) return (FALSE); #if (DOSX & PHARLAP) ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE); #elif (DOSX & DJGPP) dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer); #elif (DOSX & DOS4GW) memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE); #else _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE); #endif return (TRUE); } /**************************************************************************/ #if (DOSX & PHARLAP) PUBLIC int PktReceive (BYTE *buf, int max) { WORD inOfs = *rxInOfsFp; WORD outOfs = *rxOutOfsFp; if (outOfs != inOfs) { RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs); int size, len = max; if (CheckElement(head)) { size = min (head->firstCount, sizeof(RX_ELEMENT)); len = min (size, max); _fmemcpy (buf, &head->destin, len); } else size = -1; outOfs += sizeof (RX_ELEMENT); if (outOfs > LAST_RX_BUF) outOfs = FIRST_RX_BUF; *rxOutOfsFp = outOfs; return (size); } return (0); } PUBLIC void PktQueueBusy (BOOL busy) { *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp; if (*rxOutOfsFp > LAST_RX_BUF) *rxOutOfsFp = FIRST_RX_BUF; *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0; } PUBLIC WORD PktBuffersUsed (void) { WORD inOfs = *rxInOfsFp; WORD outOfs = *rxOutOfsFp; if (inOfs >= outOfs) return (inOfs - outOfs) / sizeof(RX_ELEMENT); return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT)); } PUBLIC DWORD PktRxDropped (void) { return (*(DWORD _far*)(protBase + (WORD)&pktDrop)); } #elif (DOSX & DJGPP) PUBLIC int PktReceive (BYTE *buf, int max) { WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs); if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs)) { RX_ELEMENT head; int size, len = max; head.firstCount = _farpeekw (_dos_ds, realBase+ofs); head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2); head.handle = _farpeekw (_dos_ds, realBase+ofs+4); if (CheckElement(&head)) { size = min (head.firstCount, sizeof(RX_ELEMENT)); len = min (size, max); dosmemget (realBase+ofs+6, len, buf); } else size = -1; ofs += sizeof (RX_ELEMENT); if (ofs > LAST_RX_BUF) _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF); else _farpokew (_dos_ds, realBase+rxOutOfs, ofs); return (size); } return (0); } PUBLIC void PktQueueBusy (BOOL busy) { WORD ofs; disable(); ofs = _farpeekw (_dos_ds, realBase+rxInOfs); if (busy) ofs += sizeof (RX_ELEMENT); if (ofs > LAST_RX_BUF) _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF); else _farpokew (_dos_ds, realBase+rxOutOfs, ofs); _farpokel (_dos_ds, realBase+pktDrop, 0UL); enable(); } PUBLIC WORD PktBuffersUsed (void) { WORD inOfs, outOfs; disable(); inOfs = _farpeekw (_dos_ds, realBase+rxInOfs); outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs); enable(); if (inOfs >= outOfs) return (inOfs - outOfs) / sizeof(RX_ELEMENT); return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT)); } PUBLIC DWORD PktRxDropped (void) { return _farpeekl (_dos_ds, realBase+pktDrop); } #elif (DOSX & DOS4GW) PUBLIC int PktReceive (BYTE *buf, int max) { WORD ofs = *(WORD*) (realBase+rxOutOfs); if (ofs != *(WORD*) (realBase+rxInOfs)) { RX_ELEMENT head; int size, len = max; head.firstCount = *(WORD*) (realBase+ofs); head.secondCount = *(WORD*) (realBase+ofs+2); head.handle = *(WORD*) (realBase+ofs+4); if (CheckElement(&head)) { size = min (head.firstCount, sizeof(RX_ELEMENT)); len = min (size, max); memcpy (buf, (const void*)(realBase+ofs+6), len); } else size = -1; ofs += sizeof (RX_ELEMENT); if (ofs > LAST_RX_BUF) *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF; else *(WORD*) (realBase+rxOutOfs) = ofs; return (size); } return (0); } PUBLIC void PktQueueBusy (BOOL busy) { WORD ofs; _disable(); ofs = *(WORD*) (realBase+rxInOfs); if (busy) ofs += sizeof (RX_ELEMENT); if (ofs > LAST_RX_BUF) *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF; else *(WORD*) (realBase+rxOutOfs) = ofs; *(DWORD*) (realBase+pktDrop) = 0UL; _enable(); } PUBLIC WORD PktBuffersUsed (void) { WORD inOfs, outOfs; _disable(); inOfs = *(WORD*) (realBase+rxInOfs); outOfs = *(WORD*) (realBase+rxOutOfs); _enable(); if (inOfs >= outOfs) return (inOfs - outOfs) / sizeof(RX_ELEMENT); return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT)); } PUBLIC DWORD PktRxDropped (void) { return *(DWORD*) (realBase+pktDrop); } #else /* real-mode small/large model */ PUBLIC int PktReceive (BYTE *buf, int max) { if (rxOutOfs != rxInOfs) { RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs); int size, len = max; if (CheckElement(head)) { size = min (head->firstCount, sizeof(RX_ELEMENT)); len = min (size, max); _fmemcpy (buf, &head->destin, len); } else size = -1; rxOutOfs += sizeof (RX_ELEMENT); if (rxOutOfs > LAST_RX_BUF) rxOutOfs = FIRST_RX_BUF; return (size); } return (0); } PUBLIC void PktQueueBusy (BOOL busy) { rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs; if (rxOutOfs > LAST_RX_BUF) rxOutOfs = FIRST_RX_BUF; pktDrop = 0L; } PUBLIC WORD PktBuffersUsed (void) { WORD inOfs = rxInOfs; WORD outOfs = rxOutOfs; if (inOfs >= outOfs) return ((inOfs - outOfs) / sizeof(RX_ELEMENT)); return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT)); } PUBLIC DWORD PktRxDropped (void) { return (pktDrop); } #endif /**************************************************************************/ LOCAL __inline void PktFreeMem (void) { #if (DOSX & PHARLAP) if (realSeg) { _dx_real_free (realSeg); realSeg = 0; } #elif (DOSX & DJGPP) if (rm_mem.rm_segment) { unsigned ofs; /* clear the DOS-mem to prevent further upcalls */ for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4) _farpokel (_dos_ds, realBase + ofs, 0); _go32_dpmi_free_dos_memory (&rm_mem); rm_mem.rm_segment = 0; } #elif (DOSX & DOS4GW) if (rm_base_sel) { dpmi_real_free (rm_base_sel); rm_base_sel = 0; } #endif } /**************************************************************************/ PUBLIC BOOL PktExitDriver (void) { if (pktInfo.handle) { if (!PktSetReceiverMode(PDRX_BROADCAST)) PUTS ("Error restoring receiver mode."); if (!PktReleaseHandle(pktInfo.handle)) PUTS ("Error releasing PKT-DRVR handle."); PktFreeMem(); pktInfo.handle = 0; } if (pcap_pkt_debug >= 1) printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, " "wrong-handle %lu\n", intStat.tooSmall, intStat.tooLarge, intStat.badSync, intStat.wrongHandle); return (TRUE); } #if (DOSX & (DJGPP|DOS4GW)) static void dump_pkt_stub (void) { int i; fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n", PktReceiver); for (i = 0; i < 15; i++) fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]); fputs ("\n", stderr); } #endif /* * Front end initialization routine */ PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode) { PKT_RX_MODE rxMode; BOOL writeInfo = (pcap_pkt_debug >= 3); pktInfo.quiet = (pcap_pkt_debug < 3); #if (DOSX & PHARLAP) && defined(__HIGHC__) if (_mwenv != 2) { fprintf (stderr, "Only Pharlap DOS extender supported.\n"); return (FALSE); } #endif #if (DOSX & PHARLAP) && defined(__WATCOMC__) if (_Extender != 1) { fprintf (stderr, "Only DOS4GW style extenders supported.\n"); return (FALSE); } #endif if (!PktSearchDriver()) { PUTS ("Packet driver not found."); PktFreeMem(); return (FALSE); } if (!PktGetDriverInfo()) { PUTS ("Error getting pkt-drvr information."); PktFreeMem(); return (FALSE); } #if (DOSX & PHARLAP) if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd, &realBase, &protBase, (USHORT*)&realSeg)) { rxOutOfsFp = (WORD _far *) (protBase + (WORD) &rxOutOfs); rxInOfsFp = (WORD _far *) (protBase + (WORD) &rxInOfs); *rxOutOfsFp = FIRST_RX_BUF; *rxInOfsFp = FIRST_RX_BUF; } else { PUTS ("Cannot allocate real-mode stub."); return (FALSE); } #elif (DOSX & (DJGPP|DOS4GW)) if (sizeof(real_stub_array) > 0xFFFF) { fprintf (stderr, "`real_stub_array[]' too big.\n"); return (FALSE); } #if (DOSX & DJGPP) rm_mem.size = (sizeof(real_stub_array) + 15) / 16; if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0) { PUTS ("real-mode init failed."); return (FALSE); } realBase = (rm_mem.rm_segment << 4); dosmemput (&real_stub_array, sizeof(real_stub_array), realBase); _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF); _farpokel (_dos_ds, realBase+rxInOfs, FIRST_RX_BUF); #elif (DOSX & DOS4GW) rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel); if (!rm_base_seg) { PUTS ("real-mode init failed."); return (FALSE); } realBase = (rm_base_seg << 4); memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array)); *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF; *(WORD*) (realBase+rxInOfs) = FIRST_RX_BUF; #endif { int pushf = PktReceiver; while (real_stub_array[pushf++] != 0x9C && /* pushf */ real_stub_array[pushf] != 0xFA) /* cli */ { if (++para_skip > 16) { fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n"); para_skip = 0; dump_pkt_stub(); return (FALSE); } } if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800) { fprintf (stderr, "`real_stub_array[]' is misaligned.\n"); return (FALSE); } } if (pcap_pkt_debug > 2) dump_pkt_stub(); #else rxOutOfs = FIRST_RX_BUF; rxInOfs = FIRST_RX_BUF; #endif if (!PktSetAccess()) { PUTS ("Error setting pkt-drvr access."); PktFreeMem(); return (FALSE); } if (!PktGetAddress(&myAddress)) { PUTS ("Error fetching adapter address."); PktFreeMem(); return (FALSE); } if (!PktSetReceiverMode(mode)) { PUTS ("Error setting receiver mode."); PktFreeMem(); return (FALSE); } if (!PktGetReceiverMode(&rxMode)) { PUTS ("Error getting receiver mode."); PktFreeMem(); return (FALSE); } if (writeInfo) printf ("Pkt-driver information:\n" " Version : %d.%d\n" " Name : %.15s\n" " Class : %u (%s)\n" " Type : %u\n" " Number : %u\n" " Funcs : %u\n" " Intr : %Xh\n" " Handle : %u\n" " Extended : %s\n" " Hi-perf : %s\n" " RX mode : %s\n" " Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n", pktInfo.majVer, pktInfo.minVer, pktInfo.name, pktInfo.class, PktGetClassName(pktInfo.class), pktInfo.type, pktInfo.number, pktInfo.funcs, pktInfo.intr, pktInfo.handle, pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No", pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No", PktRXmodeStr(rxMode), myAddress[0], myAddress[1], myAddress[2], myAddress[3], myAddress[4], myAddress[5]); #if defined(DEBUG) && (DOSX & PHARLAP) if (writeInfo) { DWORD rAdr = realBase + (WORD)&PktReceiver; unsigned sel, ofs; printf ("\nReceiver at %04X:%04X\n", RP_SEG(rAdr), RP_OFF(rAdr)); printf ("Realbase = %04X:%04X\n", RP_SEG(realBase),RP_OFF(realBase)); sel = _FP_SEG (protBase); ofs = _FP_OFF (protBase); printf ("Protbase = %04X:%08X\n", sel,ofs); printf ("RealSeg = %04X\n", realSeg); sel = _FP_SEG (rxOutOfsFp); ofs = _FP_OFF (rxOutOfsFp); printf ("rxOutOfsFp = %04X:%08X\n", sel,ofs); sel = _FP_SEG (rxInOfsFp); ofs = _FP_OFF (rxInOfsFp); printf ("rxInOfsFp = %04X:%08X\n", sel,ofs); printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n", *rxOutOfsFp, *rxInOfsFp); PktQueueBusy (TRUE); printf ("Busy: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n", *rxOutOfsFp, *rxInOfsFp); } #endif memset (&pktStat, 0, sizeof(pktStat)); /* clear statistics */ PktQueueBusy (TRUE); return (TRUE); } /* * DPMI functions only for Watcom + DOS4GW extenders */ #if (DOSX & DOS4GW) LOCAL DWORD dpmi_get_real_vector (int intr) { union REGS r; r.x.eax = 0x200; r.x.ebx = (DWORD) intr; int386 (0x31, &r, &r); return ((r.w.cx << 4) + r.w.dx); } LOCAL WORD dpmi_real_malloc (int size, WORD *selector) { union REGS r; r.x.eax = 0x0100; /* DPMI allocate DOS memory */ r.x.ebx = (size + 15) / 16; /* Number of paragraphs requested */ int386 (0x31, &r, &r); if (r.w.cflag & 1) return (0); *selector = r.w.dx; return (r.w.ax); /* Return segment address */ } LOCAL void dpmi_real_free (WORD selector) { union REGS r; r.x.eax = 0x101; /* DPMI free DOS memory */ r.x.ebx = selector; /* Selector to free */ int386 (0x31, &r, &r); } #endif #if defined(DOSX) && (DOSX & PHARLAP) /* * Description: * This routine allocates conventional memory for the specified block * of code (which must be within the first 64K of the protected mode * program segment) and copies the code to it. * * The caller should free up the conventional memory block when it * is done with the conventional memory. * * NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER. * * Calling arguments: * start_offs start of real mode code in program segment * end_offs 1 byte past end of real mode code in program segment * real_basep returned; real mode ptr to use as a base for the * real mode code (eg, to get the real mode FAR * addr of a function foo(), take * real_basep + (ULONG) foo). * This pointer is constructed such that * offsets within the real mode segment are * the same as the link-time offsets in the * protected mode program segment * prot_basep returned; prot mode ptr to use as a base for getting * to the conventional memory, also constructed * so that adding the prot mode offset of a * function or variable to the base gets you a * ptr to the function or variable in the * conventional memory block. * rmem_adrp returned; real mode para addr of allocated * conventional memory block, to be used to free * up the conventional memory when done. DO NOT * USE THIS TO CONSTRUCT A REAL MODE PTR, USE * REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT * CORRECTLY. * * Returned values: * 0 if error * 1 if success */ int RealCopy (ULONG start_offs, ULONG end_offs, REALPTR *real_basep, FARPTR *prot_basep, USHORT *rmem_adrp) { ULONG rm_base; /* base real mode para addr for accessing */ /* allocated conventional memory */ UCHAR *source; /* source pointer for copy */ FARPTR destin; /* destination pointer for copy */ ULONG len; /* number of bytes to copy */ ULONG temp; USHORT stemp; /* First check for valid inputs */ if (start_offs >= end_offs || end_offs > 0x10000) return (FALSE); /* Round start_offs down to a paragraph (16-byte) boundary so we can set up * the real mode pointer easily. Round up end_offs to make sure we allocate * enough paragraphs */ start_offs &= ~15; end_offs = (15 + (end_offs << 4)) >> 4; /* Allocate the conventional memory for our real mode code. Remember to * round byte count UP to 16-byte paragraph size. We alloc it * above the DOS data buffer so both the DOS data buffer and the appl * conventional mem block can still be resized. * * First just try to alloc it; if we can't get it, shrink the appl mem * block down to the minimum, try to alloc the memory again, then grow the * appl mem block back to the maximum. (Don't try to shrink the DOS data * buffer to free conventional memory; it wouldn't be good for this routine * to have the possible side effect of making file I/O run slower.) */ len = ((end_offs - start_offs) + 15) >> 4; if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE) { if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE) return (FALSE); if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE) *rmem_adrp = 0; if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE) { if (*rmem_adrp != 0) _dx_real_free (*rmem_adrp); return (FALSE); } if (*rmem_adrp == 0) return (FALSE); } /* Construct real mode & protected mode pointers to access the allocated * memory. Note we know start_offs is aligned on a paragraph (16-byte) * boundary, because we rounded it down. * * We make the offsets come out rights by backing off the real mode selector * by start_offs. */ rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4); RP_SET (*real_basep, 0, rm_base); FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM); /* Copy the real mode code/data to the allocated memory */ source = (UCHAR *) start_offs; destin = *prot_basep; FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep)); len = end_offs - start_offs; WriteFarMem (destin, source, len); return (TRUE); } #endif /* DOSX && (DOSX & PHARLAP) */ libpcap-0.9.7/./bpf_dump.c0000644000026300017500000000377707755532615013415 0ustar mcrmcr/* * Copyright (c) 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.14 2003/11/15 23:23:57 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include void bpf_dump(struct bpf_program *p, int option) { struct bpf_insn *insn; int i; int n = p->bf_len; insn = p->bf_insns; if (option > 2) { printf("%d\n", n); for (i = 0; i < n; ++insn, ++i) { printf("%u %u %u %u\n", insn->code, insn->jt, insn->jf, insn->k); } return ; } if (option > 1) { for (i = 0; i < n; ++insn, ++i) printf("{ 0x%x, %d, %d, 0x%08x },\n", insn->code, insn->jt, insn->jf, insn->k); return; } for (i = 0; i < n; ++insn, ++i) { #ifdef BDEBUG extern int bids[]; printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1); #endif puts(bpf_image(insn, i)); } } libpcap-0.9.7/./configure.in0000644000026300017500000005263510643174160013746 0ustar mcrmcrdnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.120.2.12 2007/06/15 17:57:26 guy Exp $ (LBL) dnl dnl Copyright (c) 1994, 1995, 1996, 1997 dnl The Regents of the University of California. All rights reserved. dnl dnl Process this file with autoconf to produce a configure script. dnl AC_REVISION($Revision: 1.120.2.12 $) AC_PREREQ(2.50) AC_INIT(pcap.c) AC_CANONICAL_SYSTEM AC_LBL_C_INIT(V_CCOPT, V_INCLS, V_LIBS) AC_LBL_C_INLINE AC_C___ATTRIBUTE__ AC_LBL_CHECK_TYPE(u_int8_t, u_char) AC_LBL_CHECK_TYPE(u_int16_t, u_short) AC_LBL_CHECK_TYPE(u_int32_t, u_int) dnl dnl libpcap doesn't itself use ; however, the test program dnl in "AC_LBL_FIXINCLUDES" in "aclocal.m4" uses it, so we have to dnl test for it and set "HAVE_SYS_IOCCOM_H" if we have it, otherwise dnl "AC_LBL_FIXINCLUDES" won't work on some platforms such as Solaris. dnl AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h limits.h paths.h) AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include #include ]) if test "$ac_cv_header_netinet_if_ether_h" != yes; then # # The simple test didn't work. # Do we need to include first? # Unset ac_cv_header_netinet_if_ether_h so we don't # treat the previous failure as a cached value and # suppress the next test. # AC_MSG_NOTICE([Rechecking with some additional includes]) unset ac_cv_header_netinet_if_ether_h AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include #include #include struct mbuf; struct rtentry; #include ]) fi AC_LBL_FIXINCLUDES AC_CHECK_FUNCS(strerror strlcpy) needsnprintf=no AC_CHECK_FUNCS(vsnprintf snprintf,, [needsnprintf=yes]) if test $needsnprintf = yes; then AC_LIBOBJ(snprintf) fi # # Do this before checking for ether_hostton(), as it's a # "gethostbyname() -ish function". # AC_LBL_LIBRARY_NET # # You are in a twisty little maze of UN*Xes, all different. # Some might not have ether_hostton(). # Some might have it, but not declare it in any header file. # Some might have it, but declare it in . # Some might have it, but declare it in # (And some might have it but document it as something declared in # , although appears to work.) # # Before you is a C compiler. # AC_CHECK_FUNCS(ether_hostton) if test "$ac_cv_func_ether_hostton" = yes; then # # OK, we have ether_hostton(). Do we have ? # if test "$ac_cv_header_netinet_if_ether_h" = yes; then # # Yes. Does it declare ether_hostton()? # AC_CHECK_DECL(ether_hostton, [ AC_DEFINE(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON,, [Define to 1 if netinet/if_ether.h declares `ether_hostton']) ],, [ #include #include #include #include struct mbuf; struct rtentry; #include #include ]) fi # # Did that succeed? # if test "$ac_cv_have_decl_ether_hostton" != yes; then # # No, how about , as on Linux? # AC_CHECK_HEADERS(netinet/ether.h) if test "$ac_cv_header_netinet_ether_h" = yes; then # # We have it - does it declare ether_hostton()? # Unset ac_cv_have_decl_ether_hostton so we don't # treat the previous failure as a cached value and # suppress the next test. # unset ac_cv_have_decl_ether_hostton AC_CHECK_DECL(ether_hostton, [ AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON,, [Define to 1 if netinet/ether.h declares `ether_hostton']) ],, [ #include ]) fi fi # # Is ether_hostton() declared? # if test "$ac_cv_have_decl_ether_hostton" != yes; then # # No, we'll have to declare it ourselves. # Do we have "struct ether_addr"? # AC_CHECK_TYPES(struct ether_addr,,, [ #include #include #include #include struct mbuf; struct rtentry; #include #include ]) AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 0, [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you don't.]) else AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 1, [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you don't.]) fi fi dnl to pacify those who hate protochain insn AC_MSG_CHECKING(if --disable-protochain option is specified) AC_ARG_ENABLE(protochain, [ --disable-protochain disable \"protochain\" insn]) case "x$enable_protochain" in xyes) enable_protochain=enabled ;; xno) enable_protochain=disabled ;; x) enable_protochain=enabled ;; esac if test "$enable_protochain" = "disabled"; then AC_DEFINE(NO_PROTOCHAIN,1,[do not use protochain]) fi AC_MSG_RESULT(${enable_protochain}) dnl 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. dnl dnl XXX This could be done for cross-compiling, but for now it's not. dnl if test -z "$with_pcap" && test "$cross_compiling" = yes; then AC_MSG_ERROR(pcap type not determined when cross-compiling; use --with-pcap=...) fi 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/bpf ; then # # Cloning BPF device. # V_PCAP=bpf AC_DEFINE(HAVE_CLONING_BPF,1,[define if you have a cloning BPF device]) 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/linux/socket.h ; then V_PCAP=linux elif test -r /usr/include/net/raw.h ; then V_PCAP=snoop elif test -r /usr/include/odmi.h ; then # # On AIX, the BPF devices might not yet be present - they're # created the first time libpcap runs after booting. # We check for odmi.h instead. # V_PCAP=bpf elif test -r /usr/include/sys/dlpi.h ; then V_PCAP=dlpi 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 fi AC_MSG_RESULT($V_PCAP) dnl dnl Now figure out how we get a list of interfaces and addresses, dnl if we support capturing. Don't bother if we don't support dnl capturing. dnl if test "$V_PCAP" = null then # # We can't capture, so we can't open any capture # devices, so we won't return any interfaces. # V_FINDALLDEVS=null else AC_CHECK_FUNC(getifaddrs,[ # # We have "getifaddrs()"; make sure we have # as well, just in case some platform is really weird. # AC_CHECK_HEADER(ifaddrs.h,[ # # We have the header, so we use "getifaddrs()" to # get the list of interfaces. # V_FINDALLDEVS=getad ],[ # # We don't have the header - give up. # XXX - we could also fall back on some other # mechanism, but, for now, this'll catch this # problem so that we can at least try to figure # out something to do on systems with "getifaddrs()" # but without "ifaddrs.h", if there is something # we can do on those systems. # AC_MSG_ERROR([Your system has getifaddrs() but doesn't have a usable .]) ]) ],[ # # Well, we don't have "getifaddrs()", so we have to use # some other mechanism; determine what that mechanism is. # # The first thing we use is the type of capture mechanism, # which is somewhat of a proxy for the OS we're using. # case "$V_PCAP" in dlpi) # # This might be Solaris 8 or later, with # SIOCGLIFCONF, or it might be some other OS # or some older version of Solaris, with # just SIOCGIFCONF. # AC_MSG_CHECKING(whether we have SIOCGLIFCONF) AC_CACHE_VAL(ac_cv_lbl_have_siocglifconf, AC_TRY_COMPILE( [#include #include #include #include #include ], [ioctl(0, SIOCGLIFCONF, (char *)0);], ac_cv_lbl_have_siocglifconf=yes, ac_cv_lbl_have_siocglifconf=no)) AC_MSG_RESULT($ac_cv_lbl_have_siocglifconf) if test $ac_cv_lbl_have_siocglifconf = yes ; then V_FINDALLDEVS=glifc else V_FINDALLDEVS=gifc fi ;; *) # # Assume we just have SIOCGIFCONF. # (XXX - on at least later Linux kernels, there's # another mechanism, and we should be using that # instead.) # V_FINDALLDEVS=gifc ;; esac]) fi AC_MSG_CHECKING(if --enable-ipv6 option is specified) AC_ARG_ENABLE(ipv6, [ --enable-ipv6 build IPv6-capable version]) if test "$enable_ipv6" = "yes"; then AC_DEFINE(INET6,1,[IPv6]) fi AC_MSG_RESULT(${enable_ipv6-no}) AC_MSG_CHECKING(whether to build optimizer debugging code) AC_ARG_ENABLE(optimizer-dbg, [ --enable-optimizer-dbg build optimizer debugging code]) if test "$enable_optimizer_dbg" = "yes"; then AC_DEFINE(BDEBUG,1,[Enable optimizer debugging]) fi AC_MSG_RESULT(${enable_optimizer_dbg-no}) AC_MSG_CHECKING(whether to build parser debugging code) AC_ARG_ENABLE(yydebug, [ --enable-yydebug build parser debugging code]) if test "$enable_yydebug" = "yes"; then AC_DEFINE(YYDEBUG,1,[Enable parser debugging]) fi AC_MSG_RESULT(${enable_yydebug-no}) 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, 1, [define if you have a /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", [/dev/dlpi directory]) else AC_MSG_RESULT(no) fi fi ;; linux) AC_MSG_CHECKING(Linux kernel version) if test "$cross_compiling" = yes; then AC_CACHE_VAL(ac_cv_linux_vers, ac_cv_linux_vers=unknown) else AC_CACHE_VAL(ac_cv_linux_vers, ac_cv_linux_vers=`uname -r 2>&1 | \ sed -n -e '$s/.* //' -e '$s/\..*//p'`) fi AC_MSG_RESULT($ac_cv_linux_vers) if test $ac_cv_linux_vers = unknown ; then AC_MSG_ERROR(cannot determine linux version when cross-compiling) fi if test $ac_cv_linux_vers -lt 2 ; then AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info) fi AC_LBL_TPACKET_STATS ;; dag) V_DEFS="$V_DEFS -DDAG_ONLY" ;; septel) V_DEFS="$V_DEFS -DSEPTEL_ONLY" ;; null) AC_MSG_WARN(cannot determine packet capture interface) AC_MSG_WARN((see the INSTALL doc for more info)) ;; esac AC_MSG_CHECKING(whether we have /proc/net/dev) if test -r /proc/net/dev ; then ac_cv_lbl_proc_net_dev=yes else ac_cv_lbl_proc_net_dev=no fi if test $ac_cv_lbl_proc_net_dev = yes; then AC_DEFINE(HAVE_PROC_NET_DEV, 1, [define if you have a /proc/net/dev]) fi AC_MSG_RESULT($ac_cv_lbl_proc_net_dev) # Check for Endace DAG card support. AC_ARG_WITH([dag], [ --with-dag[[=DIR]] include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present)], [ if test "$withval" = no then # User doesn't want DAG support. want_dag=no elif test "$withval" = yes then # User wants DAG support but hasn't specified a directory. want_dag=yes else # User wants DAG support and has specified a directory, so use the provided value. want_dag=yes dag_root=$withval fi ],[ # # Use DAG API if present, otherwise don't # want_dag=ifpresent ]) AC_ARG_WITH([dag-includes], [ --with-dag-includes=DIR Endace DAG include directory], [ # User wants DAG support and has specified a header directory, so use the provided value. want_dag=yes dag_include_dir=$withval ],[]) AC_ARG_WITH([dag-libraries], [ --with-dag-libraries=DIR Endace DAG library directory], [ # User wants DAG support and has specified a library directory, so use the provided value. want_dag=yes dag_lib_dir=$withval ],[]) case "$V_PCAP" in linux|bpf|dag) # # We support the DAG API if we're on Linux or BSD, or if we're # building a DAG-only libpcap. # ;; *) # # If the user explicitly requested DAG, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_dag = yes; then AC_MSG_ERROR([DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types]) elif test $want_dag = yes; then want_dag=no fi ;; esac ac_cv_lbl_dag_api=no if test "$want_dag" != no; then AC_MSG_CHECKING([whether we have DAG API headers]) # If necessary, set default paths for DAG API headers and libraries. if test -z "$dag_root"; then dag_root=/usr/local fi if test -z "$dag_include_dir"; then dag_include_dir="$dag_root/include" fi if test -z "$dag_lib_dir"; then dag_lib_dir="$dag_root/lib" fi if test -z "$dag_tools_dir"; then dag_tools_dir="$dag_root/tools" fi if test -r $dag_include_dir/dagapi.h; then ac_cv_lbl_dag_api=yes fi AC_MSG_RESULT([$ac_cv_lbl_dag_api ($dag_include_dir)]) fi if test $ac_cv_lbl_dag_api = yes; then AC_MSG_CHECKING([dagapi.o]) dagapi_obj=no if test -r $dag_tools_dir/dagapi.o; then # 2.4.x. dagapi_obj=$dag_tools_dir/dagapi.o elif test -r $dag_lib_dir/dagapi.o; then # 2.5.x. dagapi_obj=$dag_lib_dir/dagapi.o elif test -r $dag_lib_dir/libdag.a; then # 2.5.x. ar x $dag_lib_dir/libdag.a dagapi.o if test -r ./dagapi.o; then dagapi_obj=./dagapi.o else ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o if test -r ./libdag_la-dagapi.o; then dagapi_obj=./libdag_la-dagapi.o fi fi fi if test $dagapi_obj = no; then AC_MSG_RESULT([no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)]) ac_cv_lbl_dag_api=no else AC_MSG_RESULT([yes ($dagapi_obj)]) fi fi if test $ac_cv_lbl_dag_api = yes; then AC_MSG_CHECKING([dagopts.o]) dagopts_obj=no if test -r $dag_tools_dir/dagopts.o; then # 2.4.x. dagopts_obj=$dag_tools_dir/dagopts.o elif test -r $dag_lib_dir/dagopts.o; then # 2.5.x. dagopts_obj=$dag_lib_dir/dagopts.o elif test -r $dag_lib_dir/libdag.a; then # 2.5.x. ar x $dag_lib_dir/libdag.a dagopts.o if test -r ./dagopts.o; then dagopts_obj=./dagopts.o else ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o if test -r ./libdag_la-dagopts.o; then dagopts_obj=./libdag_la-dagopts.o fi fi fi if test $dagopts_obj = no; then AC_MSG_RESULT([no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)]) ac_cv_lbl_dag_api=no else AC_MSG_RESULT([yes ($dagopts_obj)]) fi fi if test $ac_cv_lbl_dag_api = yes; then # Under 2.5.x only we need to add dagreg.o. if test -r $dag_include_dir/dagreg.h; then AC_MSG_CHECKING([dagreg.o]) dagreg_obj=no if test -r $dag_lib_dir/dagreg.o; then # Object file is ready and waiting. dagreg_obj=$dag_lib_dir/dagreg.o elif test -r $dag_lib_dir/libdag.a; then # Extract from libdag.a. ar x $dag_lib_dir/libdag.a dagreg.o if test -r ./dagreg.o; then dagreg_obj=./dagreg.o else ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o if test -r ./libdag_la-dagreg.o; then dagreg_obj=./libdag_la-dagreg.o fi fi fi if test $dagreg_obj = no; then AC_MSG_RESULT([no (checked $dag_lib_dir $dag_lib_dir/libdag.a)]) ac_cv_lbl_dag_api=no else AC_MSG_RESULT([yes ($dagreg_obj)]) fi fi fi if test $ac_cv_lbl_dag_api = yes; then V_INCLS="$V_INCLS -I$dag_include_dir" V_LIBS="$V_LIBS $dagapi_obj $dagopts_obj $dagreg_obj" if test $V_PCAP != dag ; then SSRC="pcap-dag.c" fi # See if we can find a general version string. # Don't need to save and restore LIBS to prevent -ldag being # included if there's a found-action (arg 3). saved_ldflags=$LDFLAGS LDFLAGS="-L$dag_lib_dir" AC_CHECK_LIB([dag], [dag_attach_stream], [dag_version="2.5.x"], [dag_version="2.4.x"]) AC_CHECK_LIB([dag],[dag_get_erf_types], [ AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])] ) LDFLAGS=$saved_ldflags if test "$dag_version" = 2.5.x; then AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API]) DAGLIBS="-ldag" fi # See if we can find a specific version string. AC_MSG_CHECKING([the DAG API version]) if test -r "$dag_root/VERSION"; then dag_version="`cat $dag_root/VERSION`" fi AC_MSG_RESULT([$dag_version]) AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API]) fi if test $ac_cv_lbl_dag_api = no; then if test "$want_dag" = yes; then # User wanted DAG support but we couldn't find it. AC_MSG_ERROR([DAG API requested, but not found at $dag_root: use --without-dag]) fi if test "$V_PCAP" = dag; then # User requested "dag" capture type but the DAG API wasn't # found. AC_MSG_ERROR([Specifying the capture type as "dag" requires the DAG API to be present; use the --with-dag options to specify the location. (Try "./configure --help" for more information.)]) fi fi AC_ARG_WITH(septel, [ --with-septel[[=DIR]] include Septel support (located in directory DIR, if supplied). [default=yes, on Linux, if present]], [ if test "$withval" = no then want_septel=no elif test "$withval" = yes then want_septel=yes septel_root= else want_septel=yes septel_root=$withval fi ],[ # # Use Septel API if present, otherwise don't # want_septel=ifpresent septel_root=./../septel ]) ac_cv_lbl_septel_api=no case "$V_PCAP" in linux|septel) # # We support the Septel API if we're on Linux, or if we're building # a Septel-only libpcap. # ;; *) # # If the user explicitly requested Septel, tell them it's not # supported. # # If they expressed no preference, don't include it. # if test $want_septel = yes; then AC_MSG_ERROR(Septel support only available with 'linux' and 'septel' packet capture types) elif test $want_septel = yes; then want_septel=no fi ;; esac if test "$with_septel" != no; then AC_MSG_CHECKING(whether we have Septel API) if test -z "$septel_root"; then septel_root=$srcdir/../septel fi septel_tools_dir="$septel_root" septel_include_dir="$septel_root/INC" DEF="-DHAVE_SEPTEL_API" ac_cv_lbl_septel_api=no if test -r "$septel_include_dir/msg.h"; then V_INCLS="$V_INCLS -I$septel_include_dir" V_DEFS="$V_DEFS $DEF" V_LIBS="$V_LIBS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o " if test "$V_PCAP" != septel ; then SSRC="pcap-septel.c" fi ac_cv_lbl_septel_api=yes fi AC_MSG_RESULT($ac_cv_lbl_septel_api) if test $ac_cv_lbl_septel_api = no; then if test "$want_septel" = yes; then AC_MSG_ERROR(Septel API not found under directory $septel_root; use --without-septel) fi else AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have a Septel API]) fi fi if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then AC_MSG_ERROR(Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR) fi AC_LBL_LEX_AND_YACC(V_LEX, V_YACC, pcap_) if test "$V_LEX" = lex ; then # Some versions of lex can't handle the definitions section of scanner.l . # Try lexing it and complain if it can't deal. AC_CACHE_CHECK([for capable lex], tcpdump_cv_capable_lex, if lex -t scanner.l > /dev/null 2>&1; then tcpdump_cv_capable_lex=yes else tcpdump_cv_capable_lex=insufficient fi) if test $tcpdump_cv_capable_lex = insufficient ; then AC_MSG_ERROR([Your operating system's lex is insufficient to compile libpcap. flex is a lex replacement that has many advantages, including being able to compile libpcap. For more information, see http://www.gnu.org/software/flex/flex.html .]) fi fi DYEXT="so" case "$host_os" in aix*) dnl Workaround to enable certain features AC_DEFINE(_SUN,1,[define on AIX to get certain functions]) ;; hpux9*) AC_DEFINE(HAVE_HPUX9,1,[on HP-UX 9.x]) ;; hpux10.0*) ;; hpux10.1*) ;; hpux*) dnl HPUX 10.20 and above is similar to HPUX 9, but dnl not the same.... dnl dnl XXX - DYEXT should be set to "sl" if this is building dnl for 32-bit PA-RISC, but should be left as "so" for dnl 64-bit PA-RISC or, I suspect, IA-64. AC_DEFINE(HAVE_HPUX10_20_OR_LATER,1,[on HP-UX 10.20 or later]) ;; 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,1,[on sinix]) fi ;; solaris*) AC_DEFINE(HAVE_SOLARIS,1,[On solaris]) ;; darwin*) DYEXT="dylib" V_CCOPT="$V_CCOPT -fno-common" ;; linux*) V_CCOPT="$V_CCOPT -fPIC" ;; esac AC_PROG_RANLIB AC_LBL_DEVEL(V_CCOPT) AC_LBL_SOCKADDR_SA_LEN AC_LBL_SOCKADDR_STORAGE AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1 AC_LBL_UNALIGNED_ACCESS # # Makefile.in includes rules to generate version.h, so we assume # that it will be generated if autoconf is used. # AC_DEFINE(HAVE_VERSION_H, 1, [define if version.h is generated in the build procedure]) rm -f net ln -s ${srcdir}/bpf/net net AC_SUBST(V_CCOPT) AC_SUBST(V_DEFS) AC_SUBST(V_INCLS) AC_SUBST(V_LIBS) AC_SUBST(V_LEX) AC_SUBST(V_PCAP) AC_SUBST(V_FINDALLDEVS) AC_SUBST(V_RANLIB) AC_SUBST(V_YACC) AC_SUBST(SSRC) AC_SUBST(DYEXT) AC_SUBST(DAGLIBS) AC_PROG_INSTALL AC_CONFIG_HEADER(config.h) AC_OUTPUT(Makefile) if test -f .devel ; then make depend fi exit 0 libpcap-0.9.7/./pcap-septel.c0000644000026300017500000001742710255663533014024 0ustar mcrmcr/* * pcap-septel.c: Packet capture interface for Intel/Septel card. * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible. This code is compiled in several different ways depending on * whether SEPTEL_ONLY and HAVE_SEPTEL_API are defined. If HAVE_SEPTEL_API is * not defined it should not get compiled in, otherwise if SEPTEL_ONLY is * defined then the 'septel_' function calls are renamed to 'pcap_' * equivalents. If SEPTEL_ONLY is not defined then nothing is altered - the * septel_ functions will be called as required from their * pcap-linux/equivalents. * * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY * (+961 3 485243) */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-septel.c,v 1.1.2.2 2005/06/21 01:03:23 guy Exp $"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "pcap-int.h" #include #include #include #include #include #include #ifdef HAVE_SEPTEL_API #include #include #include #include #include #endif /* HAVE_SEPTEL_API */ #ifdef SEPTEL_ONLY /* This code is required when compiling for a Septel device only. */ #include "pcap-septel.h" /* Replace dag function names with pcap equivalent. */ #define septel_open_live pcap_open_live #define septel_platform_finddevs pcap_platform_finddevs #endif /* SEPTEL_ONLY */ static int septel_setfilter(pcap_t *p, struct bpf_program *fp); static int septel_stats(pcap_t *p, struct pcap_stat *ps); static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf); static void septel_platform_close(pcap_t *p) { } /* * Read at most max_packets from the capture queue and call the callback * for each of them. Returns the number of packets handled, -1 if an * error occured, or -2 if we were told to break out of the loop. */ static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { HDR *h; MSG *m; int processed = 0 ; int t = 0 ; /* identifier for the message queue of the module(upe) from which we are capturing * packets.These IDs are defined in system.txt . By default it is set to 0x2d * so change it to 0xdd for technical reason and therefore the module id for upe becomes: * LOCAL 0xdd * upe - Example user part task */ unsigned int id = 0xdd; /* process the packets */ do { unsigned short packet_len = 0; int caplen = 0; int counter = 0; struct pcap_pkthdr pcap_header; u_char *dp ; /* * Has "pcap_breakloop()" been called? */ loop: if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } /*repeat until a packet is read *a NULL message means : * when no packet is in queue or all packets in queue already read */ do { /* receive packet in non-blocking mode * GCT_grab is defined in the septel library software */ h = GCT_grab(id); m = (MSG*)h; /* a couter is added here to avoid an infinite loop * that will cause our capture program GUI to freeze while waiting * for a packet*/ counter++ ; } while ((m == NULL)&& (counter< 100)) ; if (m != NULL) { t = h->type ; /* catch only messages with type = 0xcf00 or 0x8f01 corrsponding to ss7 messages*/ /* XXX = why not use API_MSG_TX_REQ for 0xcf00 and API_MSG_RX_IND * for 0x8f01? */ if ((t != 0xcf00) && (t != 0x8f01)) { relm(h); goto loop ; } /* XXX - is API_MSG_RX_IND for an MTP2 or MTP3 message? */ dp = get_param(m);/* get pointer to MSG parameter area (m->param) */ packet_len = m->len; caplen = p->snapshot ; if (caplen > packet_len) { caplen = packet_len; } /* Run the packet filter if there is one. */ if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { /* get a time stamp , consisting of : * * pcap_header.ts.tv_sec: * ---------------------- * a UNIX format time-in-seconds when he packet was captured, * i.e. the number of seconds since Epoch time (January 1,1970, 00:00:00 GMT) * * pcap_header.ts.tv_usec : * ------------------------ * the number of microseconds since that second * when the packet was captured */ (void)gettimeofday(&pcap_header.ts, NULL); /* Fill in our own header data */ pcap_header.caplen = caplen; pcap_header.len = packet_len; /* Count the packet. */ p->md.stat.ps_recv++; /* Call the user supplied callback function */ callback(user, &pcap_header, dp); processed++ ; } /* after being processed the packet must be *released in order to receive another one */ relm(h); }else processed++; } while (processed < cnt) ; return processed ; } static int septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_) { strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards", PCAP_ERRBUF_SIZE); return (-1); } /* * Get a handle for a live capture from the given Septel device. Always pass a NULL device * The promisc flag is ignored because Septel cards have built-in tracing. * The to_ms parameter is also ignored as it is * not supported in hardware. * * See also pcap(3). */ pcap_t *septel_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { pcap_t *handle; handle = malloc(sizeof(*handle)); if (handle == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno)); return NULL; } /* Initialize some components of the pcap structure. */ memset(handle, 0, sizeof(*handle)); handle->snapshot = snaplen; handle->linktype = DLT_MTP2; handle->bufsize = 0; /* * "select()" and "poll()" don't work on Septel queues */ handle->selectable_fd = -1; handle->read_op = septel_read; handle->inject_op = septel_inject; handle->setfilter_op = septel_setfilter; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = septel_setnonblock; handle->stats_op = septel_stats; handle->close_op = septel_platform_close; return handle; fail: if (handle != NULL) { free(handle); } return NULL; } static int septel_stats(pcap_t *p, struct pcap_stat *ps) { /*p->md.stat.ps_recv = 0;*/ /*p->md.stat.ps_drop = 0;*/ *ps = p->md.stat; return 0; } int septel_platform_finddevs(pcap_if_t **devlistp, char *errbuf) { unsigned char *p; const char description[512]= "Intel/Septel device"; char name[512]="septel" ; int ret = 0; pcap_add_if(devlistp,name,0,description,errbuf); return (ret); } /* * Installs the given bpf filter program in the given pcap structure. There is * no attempt to store the filter in kernel memory as that is not supported * with Septel cards. */ static int septel_setfilter(pcap_t *p, struct bpf_program *fp) { if (!p) return -1; if (!fp) { strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf)); return -1; } /* Make our private copy of the filter */ if (install_bpf_program(p, fp) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return -1; } p->md.use_bpf = 0; return (0); } static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf) { return (0); } libpcap-0.9.7/./install-sh0000755000026300017500000001272106777230340013437 0ustar mcrmcr#! /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 fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi 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 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # 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 fi fi ## 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 fi pathcomp="${pathcomp}/" done fi 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 fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # 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 libpcap-0.9.7/./config.guess0000755000026300017500000012355707756336232013772 0ustar mcrmcr#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. timestamp='2003-10-16' # 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. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # 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 build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi 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 # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pegasos:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # 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 ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha*:OpenVMS:*:*) echo alpha-hp-vms exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; *:OS400:*:*) echo powerpc-ibm-os400 exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-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 fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` 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 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${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 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #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); } EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax 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 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi 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 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 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 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi 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 BSD 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/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then # avoid double evaluation of $set_cc_for_build test -n "$CC_FOR_BUILD" || eval $set_cc_for_build if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include 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); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 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 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix 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 fi 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 fi 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*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' 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/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; *:UNICOS/mp:*:*) echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) # Determine whether the default compiler uses glibc. eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #if __GLIBC__ >= 2 LIBC=gnu #else LIBC= #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` # GNU/KFreeBSD systems have a "k" prefix to indicate we are using # FreeBSD's kernel, but not the complete OS. case ${LIBC} in gnu) kernel_only='k' ;; esac echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:[34]*) echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' exit 0 ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # 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. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp 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 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*: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.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 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 fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # 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 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) case `uname -p` in *86) UNAME_PROCESSOR=i686 ;; powerpc) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[DGKLNPTVWY]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit 0 ;; *:DRAGONFLY:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly${UNAME_RELEASE} 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 eval $set_cc_for_build cat >$dummy.c < # include #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 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`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%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) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # 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); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # 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 fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libpcap-0.9.7/./INSTALL.txt0000644000026300017500000004021210262571366013276 0ustar mcrmcr@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.12.2.1 2005/06/20 21:30:14 guy Exp $ (LBL) To build libpcap, run "./configure" (a shell script). The configure script will determine your system attributes and generate an appropriate Makefile from Makefile.in. Next run "make". If everything goes well you can su to root and run "make install". However, you need not install libpcap if you just want to build tcpdump; just make sure the tcpdump and libpcap directory trees have the same parent directory. If configure says: configure: warning: cannot determine packet capture interface configure: warning: (see INSTALL for more info) then your system either does not support packet capture or your system does support packet capture but libpcap does not support that particular type. (If you have HP-UX, see below.) If your system uses a packet capture not supported by libpcap, please send us patches; don't forget to include an autoconf fragment suitable for use in configure.in. It is possible to override the default packet capture type, although the circumstance where this works are limited. For example if you have installed bpf under SunOS 4 and wish to build a snit libpcap: ./configure --with-pcap=snit Another example is to force a supported packet capture type in the case where the configure scripts fails to detect it. You will need an ANSI C compiler to build libpcap. The configure script will abort if your compiler is not ANSI compliant. If this happens, use the GNU C compiler, available via anonymous ftp: ftp://ftp.gnu.org/pub/gnu/gcc/ If you use flex, you must use version 2.4.6 or higher. The configure script automatically detects the version of flex and will not use it unless it is new enough. You can use "flex -V" to see what version you have (unless it's really old). The current version of flex is available via anonymous ftp: ftp://ftp.ee.lbl.gov/flex-*.tar.Z As of this writing, the current version is 2.5.4. If you use bison, you must use flex (and visa versa). The configure script automatically falls back to lex and yacc if both flex and bison are not found. Sometimes the stock C compiler does not interact well with flex and bison. The list of problems includes undefined references for alloca. You can get around this by installing gcc or manually disabling flex and bison with: ./configure --without-flex --without-bison If your system only has AT&T lex, this is okay unless your libpcap program uses other lex/yacc generated code. (Although it's possible to map the yy* identifiers with a script, we use flex and bison so we don't feel this is necessary.) Some systems support the Berkeley Packet Filter natively; for example out of the box OSF and BSD/OS have bpf. If your system does not support bpf, you will need to pick up: ftp://ftp.ee.lbl.gov/bpf-*.tar.Z Note well: you MUST have kernel source for your operating system in order to install bpf. An exception is SunOS 4; the bpf distribution includes replacement kernel objects for some of the standard SunOS 4 network device drivers. See the bpf INSTALL document for more information. If you use Solaris, there is a bug with bufmod(7) that is fixed in Solaris 2.3.2 (aka SunOS 5.3.2). Setting a snapshot length with the broken bufmod(7) results in data be truncated from the FRONT of the packet instead of the end. The work around is to not set a snapshot length but this results in performance problems since the entire packet is copied to user space. If you must run an older version of Solaris, there is a patch available from Sun; ask for bugid 1149065. After installing the patch, use "setenv BUFMOD_FIXED" to enable use of bufmod(7). However, we recommend you run a more current release of Solaris. If you use the SPARCompiler, you must be careful to not use the /usr/ucb/cc interface. If you do, you will get bogus warnings and perhaps errors. Either make sure your path has /opt/SUNWspro/bin before /usr/ucb or else: setenv CC /opt/SUNWspro/bin/cc before running configure. (You might have to do a "make distclean" if you already ran configure once). Also note that "make depend" won't work; while all of the known universe uses -M, the SPARCompiler uses -xM to generate makefile dependencies. If you are trying to do packet capture with a FORE ATM card, you may or may not be able to. They usually only release their driver in object code so unless their driver supports packet capture, there's not much libpcap can do. If you get an error like: tcpdump: recv_ack: bind error 0x??? when using DLPI, look for the DL_ERROR_ACK error return values, usually in /usr/include/sys/dlpi.h, and find the corresponding value. Under {DEC OSF/1, Digital UNIX, Tru64 UNIX}, packet capture must be enabled before it can be used. For instructions on how to enable packet filter support, see: ftp://ftp.digital.com/pub/Digital/dec-faq/Digital-UNIX Look for the "How do I configure the Berkeley Packet Filter and capture tcpdump traces?" item. Once you enable packet filter support, your OSF system will support bpf natively. Under Ultrix, packet capture must be enabled before it can be used. For instructions on how to enable packet filter support, see: ftp://ftp.digital.com/pub/Digital/dec-faq/ultrix If you use HP-UX, you must have at least version 9 and either the version of cc that supports ANSI C (cc -Aa) or else use the GNU C compiler. You must also buy the optional streams package. If you don't have: /usr/include/sys/dlpi.h /usr/include/sys/dlpi_ext.h then you don't have the streams package. In addition, we believe you need to install the "9.X LAN and DLPI drivers cumulative" patch (PHNE_6855) to make the version 9 DLPI work with libpcap. The DLPI streams package is standard starting with HP-UX 10. The HP implementation of DLPI is a little bit eccentric. Unlike Solaris, you must attach /dev/dlpi instead of the specific /dev/* network pseudo device entry in order to capture packets. The PPA is based on the ifnet "index" number. Under HP-UX 9, it is necessary to read /dev/kmem and the kernel symbol file (/hp-ux). Under HP-UX 10, DLPI can provide information for determining the PPA. It does not seem to be possible to trace the loopback interface. Unlike other DLPI implementations, PHYS implies MULTI and SAP and you get an error if you try to enable more than one promiscuous mode at a time. It is impossible to capture outbound packets on HP-UX 9. To do so on HP-UX 10, you will, apparently, need a late "LAN products cumulative patch" (at one point, it was claimed that this would be PHNE_18173 for s700/10.20; at another point, it was claimed that the required patches were PHNE_20892, PHNE_20725 and PHCO_10947, or newer patches), and to do so on HP-UX 11 you will, apparently, need the latest lancommon/DLPI patches and the latest driver patch for the interface(s) in use on HP-UX 11 (at one point, it was claimed that patches PHNE_19766, PHNE_19826, PHNE_20008, and PHNE_20735 did the trick). Furthermore, on HP-UX 10, you will need to turn on a kernel switch by doing echo 'lanc_outbound_promisc_flag/W 1' | adb -w /stand/vmunix /dev/mem You would have to arrange that this happen on reboots; the right way to do that would probably be to put it into an executable script file "/sbin/init.d/outbound_promisc" and making "/sbin/rc2.d/S350outbound_promisc" a symbolic link to that script. Finally, testing shows that there can't be more than one simultaneous DLPI user per network interface. If you use Linux, this version of libpcap is known to compile and run under Red Hat 4.0 with the 2.0.25 kernel. It may work with earlier 2.X versions but is guaranteed not to work with 1.X kernels. Running more than one libpcap program at a time, on a system with a 2.0.X kernel, can cause problems since promiscuous mode is implemented by twiddling the interface flags from the libpcap application; the packet capture mechanism in the 2.2 and later kernels doesn't have this problem. Also, packet timestamps aren't very good. This appears to be due to haphazard handling of the timestamp in the kernel. Note well: there is rumoured to be a version of tcpdump floating around called 3.0.3 that includes libpcap and is supposed to support Linux. You should be advised that neither the Network Research Group at LBNL nor the Tcpdump Group ever generated a release with this version number. The LBNL Network Research Group notes with interest that a standard cracker trick to get people to install trojans is to distribute bogus packages that have a version number higher than the current release. They also noted with annoyance that 90% of the Linux related bug reports they got are due to changes made to unofficial versions of their page. If you are having trouble but aren't using a version that came from tcpdump.org, please try that before submitting a bug report! On Linux, libpcap will not work if the kernel does not have the packet socket option enabled; see the README.linux file for information about this. If you use AIX, you may not be able to build libpcap from this release. We do not have an AIX system in house so it's impossible for us to test AIX patches submitted to us. We are told that you must link against /lib/pse.exp, that you must use AIX cc or a GNU C compiler newer than 2.7.2, and that you may need to run strload before running a libpcap application. Read the README.aix file for information on installing libpcap and configuring your system to be able to support libpcap. If you use NeXTSTEP, you will not be able to build libpcap from this release. We hope to support this operating system in some future release of libpcap. If you use SINIX, you should be able to build libpcap from this release. It is known to compile and run on SINIX-Y/N 5.42 with the C-DS V1.0 or V1.1 compiler. But note that in some releases of SINIX, yacc emits incorrect code; if grammar.y fails to compile, change every occurence of: #ifdef YYDEBUG to: #if YYDEBUG Another workaround is to use flex and bison. If you use SCO, you might have trouble building libpcap from this release. We do not have a machine running SCO and have not had reports of anyone successfully building on it. Since SCO apparently supports DLPI, it's possible the current version works. Meanwhile, SCO provides a tcpdump binary as part of their "Network/Security Tools" package: http://www.sco.com/technology/internet/goodies/#SECURITY There is also a README that explains how to enable packet capture. If you use UnixWare, you will not be able to build libpcap from this release. We hope to support this operating system in some future release of libpcap. Meanwhile, there appears to be an UnixWare port of libpcap 0.0 (and tcpdump 3.0) in: ftp://ftp1.freebird.org/pub/mirror/freebird/internet/systools/ UnixWare appears to use a hacked version of DLPI. If linking tcpdump fails with "Undefined: _alloca" when using bison on a Sun4, your version of bison is broken. In any case version 1.16 or higher is recommended (1.14 is known to cause problems 1.16 is known to work). Either pick up a current version from: ftp://ftp.gnu.org/pub/gnu/bison or hack around it by inserting the lines: #ifdef __GNUC__ #define alloca __builtin_alloca #else #ifdef sparc #include #else char *alloca (); #endif #endif right after the (100 line!) GNU license comment in bison.simple, remove grammar.[co] and fire up make again. If you use SunOS 4, your kernel must support streams NIT. If you run a libpcap program and it dies with: /dev/nit: No such device You must add streams NIT support to your kernel configuration, run config and boot the new kernel. If you are running a version of SunOS earlier than 4.1, you will need to replace the Sun supplied /sys/sun{3,4,4c}/OBJ/nit_if.o with the appropriate version from this distribution's SUNOS4 subdirectory and build a new kernel: nit_if.o.sun3-sunos4 (any flavor of sun3) nit_if.o.sun4c-sunos4.0.3c (SS1, SS1+, IPC, SLC, etc.) nit_if.o.sun4-sunos4 (Sun4's not covered by nit_if.o.sun4c-sunos4.0.3c) These nit replacements fix a bug that makes nit essentially unusable in pre-SunOS 4.1. In addition, our sun4c-sunos4.0.3c nit gives you timestamps to the resolution of the SS-1 clock (1 us) rather than the lousy 20ms timestamps Sun gives you (tcpdump will print out the full timestamp resolution if it finds it's running on a SS-1). FILES ----- CHANGES - description of differences between releases ChmodBPF/* - Mac OS X startup item to set ownership and permissions on /dev/bpf* CREDITS - people that have helped libpcap along FILES - list of files exported as part of the distribution INSTALL.txt - this file LICENSE - the license under which tcpdump is distributed Makefile.in - compilation rules (input to the configure script) README - description of distribution README.aix - notes on using libpcap on AIX README.dag - notes on using libpcap to capture on Endace DAG devices README.hpux - notes on using libpcap on HP-UX README.linux - notes on using libpcap on Linux README.macosx - notes on using libpcap on Mac OS X README.septel - notes on using libpcap to capture on Intel/Septel devices README.tru64 - notes on using libpcap on Digital/Tru64 UNIX README.Win32 - notes on using libpcap on Win32 systems (with WinPcap) SUNOS4 - pre-SunOS 4.1 replacement kernel nit modules VERSION - version of this release acconfig.h - support for post-2.13 autoconf aclocal.m4 - autoconf macros arcnet.h - ARCNET definitions atmuni31.h - ATM Q.2931 definitions bpf/net - copy of bpf_filter.c bpf_dump.c - BPF program printing routines bpf_filter.c - symlink to bpf/net/bpf_filter.c bpf_image.c - BPF disassembly routine config.guess - autoconf support config.h.in - autoconf input config.sub - autoconf support configure - configure script (run this first) configure.in - configure script source etherent.c - /etc/ethers support routines ethertype.h - Ethernet protocol types and names definitions fad-getad.c - pcap_findalldevs() for systems with getifaddrs() fad-gifc.c - pcap_findalldevs() for systems with only SIOCGIFLIST fad-glifc.c - pcap_findalldevs() for systems with SIOCGLIFCONF fad-null.c - pcap_findalldevs() for systems without capture support fad-win32.c - pcap_findalldevs() for WinPcap gencode.c - BPF code generation routines gencode.h - BPF code generation definitions grammar.y - filter string grammar inet.c - network routines install-sh - BSD style install script lbl/os-*.h - OS-dependent defines and prototypes llc.h - 802.2 LLC SAP definitions missing/* - replacements for missing library functions mkdep - construct Makefile dependency list msdos/* - drivers for MS-DOS capture support nametoaddr.c - hostname to address routines nlpid.h - OSI network layer protocol identifier definitions net - symlink to bpf/net optimize.c - BPF optimization routines packaging - packaging information for building libpcap RPMs pcap-bpf.c - BSD Packet Filter support pcap-bpf.h - BPF definitions pcap-dag.c - Endace DAG device capture support pcap-dag.h - Endace DAG device capture support pcap-dlpi.c - Data Link Provider Interface support pcap-dos.c - MS-DOS capture support pcap-dos.h - headers for MS-DOS capture support pcap-enet.c - enet support pcap-int.h - internal libpcap definitions pcap-linux.c - Linux packet socket support pcap-namedb.h - public libpcap name database definitions pcap-nit.c - SunOS Network Interface Tap support pcap-nit.h - SunOS Network Interface Tap definitions pcap-null.c - dummy monitor support (allows offline use of libpcap) pcap-pf.c - Ultrix and Digital/Tru64 UNIX Packet Filter support pcap-pf.h - Ultrix and Digital/Tru64 UNIX Packet Filter definitions pcap-septel.c - INTEL/Septel device capture support pcap-septel.h - INTEL/Septel device capture support pcap-stdinc.h - includes and #defines for compiling on Win32 systems pcap-snit.c - SunOS 4.x STREAMS-based Network Interface Tap support pcap-snoop.c - IRIX Snoop network monitoring support pcap-win32.c - WinPcap capture support pcap.3 - manual entry pcap.c - pcap utility routines pcap.h - public libpcap definitions pf.h - OpenBSD DLT_PFLOG definitions ppp.h - Point to Point Protocol definitions rawss7.h - information on DLT_ types for SS7 savefile.c - offline support scanner.l - filter string scanner sll.h - definitions for Linux cooked mode fake link-layer header sunatmpos.h - definitions for SunATM capturing Win32 - headers and routines for building on Win32 systems libpcap-0.9.7/./pcap-linux.c0000644000026300017500000017230710633321704013655 0ustar mcrmcr/* * pcap-linux.c: Packet capture interface to the Linux kernel * * Copyright (c) 2000 Torsten Landschoff * Sebastian Krahmer * * License: BSD * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. The names of the authors 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.110.2.14 2006/10/12 17:26:58 guy Exp $ (LBL)"; #endif /* * Known problems with 2.0[.x] kernels: * * - The loopback device gives every packet twice; on 2.2[.x] kernels, * if we use PF_PACKET, we can filter out the transmitted version * of the packet by using data in the "sockaddr_ll" returned by * "recvfrom()", but, on 2.0[.x] kernels, we have to use * PF_INET/SOCK_PACKET, which means "recvfrom()" supplies a * "sockaddr_pkt" which doesn't give us enough information to let * us do that. * * - We have to set the interface's IFF_PROMISC flag ourselves, if * we're to run in promiscuous mode, which means we have to turn * it off ourselves when we're done; the kernel doesn't keep track * of how many sockets are listening promiscuously, which means * it won't get turned off automatically when no sockets are * listening promiscuously. We catch "pcap_close()" and, for * interfaces we put into promiscuous mode, take them out of * promiscuous mode - which isn't necessarily the right thing to * do, if another socket also requested promiscuous mode between * the time when we opened the socket and the time when we close * the socket. * * - MSG_TRUNC isn't supported, so you can't specify that "recvfrom()" * return the amount of data that you could have read, rather than * the amount that was returned, so we can't just allocate a buffer * whose size is the snapshot length and pass the snapshot length * as the byte count, and also pass MSG_TRUNC, so that the return * value tells us how long the packet was on the wire. * * This means that, if we want to get the actual size of the packet, * so we can return it in the "len" field of the packet header, * we have to read the entire packet, not just the part that fits * within the snapshot length, and thus waste CPU time copying data * from the kernel that our caller won't see. * * We have to get the actual size, and supply it in "len", because * otherwise, the IP dissector in tcpdump, for example, will complain * about "truncated-ip", as the packet will appear to have been * shorter, on the wire, than the IP header said it should have been. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcap-int.h" #include "sll.h" #ifdef HAVE_DAG_API #include "pcap-dag.h" #endif /* HAVE_DAG_API */ #ifdef HAVE_SEPTEL_API #include "pcap-septel.h" #endif /* HAVE_SEPTEL_API */ #include #include #include #include #include #include #include #include #include #include #include #include /* * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET * sockets rather than SOCK_PACKET sockets. * * To use them, we include rather than * ; we do so because * * some Linux distributions (e.g., Slackware 4.0) have 2.2 or * later kernels and libc5, and don't provide a * file; * * not all versions of glibc2 have a file * that defines stuff needed for some of the 2.4-or-later-kernel * features, so if the system has a 2.4 or later kernel, we * still can't use those features. * * We're already including a number of other headers, and * this code is Linux-specific (no other OS has PF_PACKET sockets as * a raw packet capture mechanism), so it's not as if you gain any * useful portability by using * * XXX - should we just include even if PF_PACKET * isn't defined? It only defines one data structure in 2.0.x, so * it shouldn't cause any problems. */ #ifdef PF_PACKET # include /* * On at least some Linux distributions (for example, Red Hat 5.2), * there's no file, but PF_PACKET is defined if * you include , but doesn't define * any of the PF_PACKET stuff such as "struct sockaddr_ll" or any of * the PACKET_xxx stuff. * * So we check whether PACKET_HOST is defined, and assume that we have * PF_PACKET sockets only if it is defined. */ # ifdef PACKET_HOST # define HAVE_PF_PACKET_SOCKETS # endif /* PACKET_HOST */ #endif /* PF_PACKET */ #ifdef SO_ATTACH_FILTER #include #include #endif #ifndef __GLIBC__ typedef int socklen_t; #endif #ifndef MSG_TRUNC /* * This is being compiled on a system that lacks MSG_TRUNC; define it * with the value it has in the 2.2 and later kernels, so that, on * those kernels, when we pass it in the flags argument to "recvfrom()" * we're passing the right value and thus get the MSG_TRUNC behavior * we want. (We don't get that behavior on 2.0[.x] kernels, because * they didn't support MSG_TRUNC.) */ #define MSG_TRUNC 0x20 #endif #ifndef SOL_PACKET /* * This is being compiled on a system that lacks SOL_PACKET; define it * with the value it has in the 2.2 and later kernels, so that we can * set promiscuous mode in the good modern way rather than the old * 2.0-kernel crappy way. */ #define SOL_PACKET 263 #endif #define MAX_LINKHEADER_SIZE 256 /* * When capturing on all interfaces we use this as the buffer size. * Should be bigger then all MTUs that occur in real life. * 64kB should be enough for now. */ #define BIGGER_THAN_ALL_MTUS (64*1024) /* * Prototypes for internal functions */ static void map_arphrd_to_dlt(pcap_t *, int, int); static int live_open_old(pcap_t *, const char *, int, int, char *); static int live_open_new(pcap_t *, const char *, int, int, char *); static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *); static int pcap_read_packet(pcap_t *, pcap_handler, u_char *); static int pcap_inject_linux(pcap_t *, const void *, size_t); static int pcap_stats_linux(pcap_t *, struct pcap_stat *); static int pcap_setfilter_linux(pcap_t *, struct bpf_program *); static int pcap_setdirection_linux(pcap_t *, pcap_direction_t); static void pcap_close_linux(pcap_t *); /* * Wrap some ioctl calls */ #ifdef HAVE_PF_PACKET_SOCKETS static int iface_get_id(int fd, const char *device, char *ebuf); #endif static int iface_get_mtu(int fd, const char *device, char *ebuf); static int iface_get_arptype(int fd, const char *device, char *ebuf); #ifdef HAVE_PF_PACKET_SOCKETS static int iface_bind(int fd, int ifindex, char *ebuf); #endif static int iface_bind_old(int fd, const char *device, char *ebuf); #ifdef SO_ATTACH_FILTER static int fix_program(pcap_t *handle, struct sock_fprog *fcode); static int fix_offset(struct bpf_insn *p); static int set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode); static int reset_kernel_filter(pcap_t *handle); static struct sock_filter total_insn = BPF_STMT(BPF_RET | BPF_K, 0); static struct sock_fprog total_fcode = { 1, &total_insn }; #endif /* * Get a handle for a live capture from the given device. You can * pass NULL as device to get all packages (without link level * information of course). If you pass 1 as promisc the interface * will be set to promiscous mode (XXX: I think this usage should * be deprecated and functions be added to select that later allow * modification of that values -- Torsten). * * See also pcap(3). */ pcap_t * pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { pcap_t *handle; int mtu; int err; int live_open_ok = 0; struct utsname utsname; #ifdef HAVE_DAG_API if (strstr(device, "dag")) { return dag_open_live(device, snaplen, promisc, to_ms, ebuf); } #endif /* HAVE_DAG_API */ #ifdef HAVE_SEPTEL_API if (strstr(device, "septel")) { return septel_open_live(device, snaplen, promisc, to_ms, ebuf); } #endif /* HAVE_SEPTEL_API */ /* Allocate a handle for this session. */ handle = malloc(sizeof(*handle)); if (handle == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return NULL; } /* Initialize some components of the pcap structure. */ memset(handle, 0, sizeof(*handle)); handle->snapshot = snaplen; handle->md.timeout = to_ms; /* * NULL and "any" are special devices which give us the hint to * monitor all devices. */ if (!device || strcmp(device, "any") == 0) { device = NULL; handle->md.device = strdup("any"); if (promisc) { promisc = 0; /* Just a warning. */ snprintf(ebuf, PCAP_ERRBUF_SIZE, "Promiscuous mode not supported on the \"any\" device"); } } else handle->md.device = strdup(device); if (handle->md.device == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "strdup: %s", pcap_strerror(errno) ); free(handle); return NULL; } /* * Current Linux kernels use the protocol family PF_PACKET to * allow direct access to all packets on the network while * older kernels had a special socket type SOCK_PACKET to * implement this feature. * While this old implementation is kind of obsolete we need * to be compatible with older kernels for a while so we are * trying both methods with the newer method preferred. */ if ((err = live_open_new(handle, device, promisc, to_ms, ebuf)) == 1) live_open_ok = 1; else if (err == 0) { /* Non-fatal error; try old way */ if (live_open_old(handle, device, promisc, to_ms, ebuf)) live_open_ok = 1; } if (!live_open_ok) { /* * Both methods to open the packet socket failed. Tidy * up and report our failure (ebuf is expected to be * set by the functions above). */ if (handle->md.device != NULL) free(handle->md.device); free(handle); return NULL; } /* * Compute the buffer size. * * If we're using SOCK_PACKET, this might be a 2.0[.x] kernel, * and might require special handling - check. */ if (handle->md.sock_packet && (uname(&utsname) < 0 || strncmp(utsname.release, "2.0", 3) == 0)) { /* * We're using a SOCK_PACKET structure, and either * we couldn't find out what kernel release this is, * or it's a 2.0[.x] kernel. * * In the 2.0[.x] kernel, a "recvfrom()" on * a SOCK_PACKET socket, with MSG_TRUNC set, will * return the number of bytes read, so if we pass * a length based on the snapshot length, it'll * return the number of bytes from the packet * copied to userland, not the actual length * of the packet. * * This means that, for example, the IP dissector * in tcpdump will get handed a packet length less * than the length in the IP header, and will * complain about "truncated-ip". * * So we don't bother trying to copy from the * kernel only the bytes in which we're interested, * but instead copy them all, just as the older * versions of libpcap for Linux did. * * The buffer therefore needs to be big enough to * hold the largest packet we can get from this * device. Unfortunately, we can't get the MRU * of the network; we can only get the MTU. The * MTU may be too small, in which case a packet larger * than the buffer size will be truncated *and* we * won't get the actual packet size. * * However, if the snapshot length is larger than * the buffer size based on the MTU, we use the * snapshot length as the buffer size, instead; * this means that with a sufficiently large snapshot * length we won't artificially truncate packets * to the MTU-based size. * * This mess just one of many problems with packet * capture on 2.0[.x] kernels; you really want a * 2.2[.x] or later kernel if you want packet capture * to work well. */ mtu = iface_get_mtu(handle->fd, device, ebuf); if (mtu == -1) { pcap_close_linux(handle); free(handle); return NULL; } handle->bufsize = MAX_LINKHEADER_SIZE + mtu; if (handle->bufsize < handle->snapshot) handle->bufsize = handle->snapshot; } else { /* * This is a 2.2[.x] or later kernel (we know that * either because we're not using a SOCK_PACKET * socket - PF_PACKET is supported only in 2.2 * and later kernels - or because we checked the * kernel version). * * We can safely pass "recvfrom()" a byte count * based on the snapshot length. * * If we're in cooked mode, make the snapshot length * large enough to hold a "cooked mode" header plus * 1 byte of packet data (so we don't pass a byte * count of 0 to "recvfrom()"). */ if (handle->md.cooked) { if (handle->snapshot < SLL_HDR_LEN + 1) handle->snapshot = SLL_HDR_LEN + 1; } handle->bufsize = handle->snapshot; } /* Allocate the buffer */ handle->buffer = malloc(handle->bufsize + handle->offset); if (!handle->buffer) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); pcap_close_linux(handle); free(handle); return NULL; } /* * "handle->fd" is a socket, so "select()" and "poll()" * should work on it. */ handle->selectable_fd = handle->fd; handle->read_op = pcap_read_linux; handle->inject_op = pcap_inject_linux; handle->setfilter_op = pcap_setfilter_linux; handle->setdirection_op = pcap_setdirection_linux; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = pcap_stats_linux; handle->close_op = pcap_close_linux; return handle; } /* * Read at most max_packets from the capture stream and call the callback * for each of them. Returns the number of packets handled or -1 if an * error occured. */ static int pcap_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { /* * Currently, on Linux only one packet is delivered per read, * so we don't loop. */ return pcap_read_packet(handle, callback, user); } /* * Read a packet from the socket calling the handler provided by * the user. Returns the number of packets received or -1 if an * error occured. */ static int pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) { u_char *bp; int offset; #ifdef HAVE_PF_PACKET_SOCKETS struct sockaddr_ll from; struct sll_header *hdrp; #else struct sockaddr from; #endif socklen_t fromlen; int packet_len, caplen; struct pcap_pkthdr pcap_header; #ifdef HAVE_PF_PACKET_SOCKETS /* * If this is a cooked device, leave extra room for a * fake packet header. */ if (handle->md.cooked) offset = SLL_HDR_LEN; else offset = 0; #else /* * This system doesn't have PF_PACKET sockets, so it doesn't * support cooked devices. */ offset = 0; #endif /* Receive a single packet from the kernel */ bp = handle->buffer + handle->offset; do { /* * Has "pcap_breakloop()" been called? */ if (handle->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return -2 as an indication that we * were told to break out of the loop. */ handle->break_loop = 0; return -2; } fromlen = sizeof(from); packet_len = recvfrom( handle->fd, bp + offset, handle->bufsize - offset, MSG_TRUNC, (struct sockaddr *) &from, &fromlen); } while (packet_len == -1 && errno == EINTR); /* Check if an error occured */ if (packet_len == -1) { if (errno == EAGAIN) return 0; /* no packet there */ else { snprintf(handle->errbuf, sizeof(handle->errbuf), "recvfrom: %s", pcap_strerror(errno)); return -1; } } #ifdef HAVE_PF_PACKET_SOCKETS if (!handle->md.sock_packet) { /* * Unfortunately, there is a window between socket() and * bind() where the kernel may queue packets from any * interface. If we're bound to a particular interface, * discard packets not from that interface. * * (If socket filters are supported, we could do the * same thing we do when changing the filter; however, * that won't handle packet sockets without socket * filter support, and it's a bit more complicated. * It would save some instructions per packet, however.) */ if (handle->md.ifindex != -1 && from.sll_ifindex != handle->md.ifindex) return 0; /* * Do checks based on packet direction. * We can only do this if we're using PF_PACKET; the * address returned for SOCK_PACKET is a "sockaddr_pkt" * which lacks the relevant packet type information. */ if (from.sll_pkttype == PACKET_OUTGOING) { /* * Outgoing packet. * If this is from the loopback device, reject it; * we'll see the packet as an incoming packet as well, * and we don't want to see it twice. */ if (from.sll_ifindex == handle->md.lo_ifindex) return 0; /* * If the user only wants incoming packets, reject it. */ if (handle->direction == PCAP_D_IN) return 0; } else { /* * Incoming packet. * If the user only wants outgoing packets, reject it. */ if (handle->direction == PCAP_D_OUT) return 0; } } #endif #ifdef HAVE_PF_PACKET_SOCKETS /* * If this is a cooked device, fill in the fake packet header. */ if (handle->md.cooked) { /* * Add the length of the fake header to the length * of packet data we read. */ packet_len += SLL_HDR_LEN; hdrp = (struct sll_header *)bp; /* * Map the PACKET_ value to a LINUX_SLL_ value; we * want the same numerical value to be used in * the link-layer header even if the numerical values * for the PACKET_ #defines change, so that programs * that look at the packet type field will always be * able to handle DLT_LINUX_SLL captures. */ switch (from.sll_pkttype) { case PACKET_HOST: hdrp->sll_pkttype = htons(LINUX_SLL_HOST); break; case PACKET_BROADCAST: hdrp->sll_pkttype = htons(LINUX_SLL_BROADCAST); break; case PACKET_MULTICAST: hdrp->sll_pkttype = htons(LINUX_SLL_MULTICAST); break; case PACKET_OTHERHOST: hdrp->sll_pkttype = htons(LINUX_SLL_OTHERHOST); break; case PACKET_OUTGOING: hdrp->sll_pkttype = htons(LINUX_SLL_OUTGOING); break; default: hdrp->sll_pkttype = -1; break; } hdrp->sll_hatype = htons(from.sll_hatype); hdrp->sll_halen = htons(from.sll_halen); memcpy(hdrp->sll_addr, from.sll_addr, (from.sll_halen > SLL_ADDRLEN) ? SLL_ADDRLEN : from.sll_halen); hdrp->sll_protocol = from.sll_protocol; } #endif /* * XXX: According to the kernel source we should get the real * packet len if calling recvfrom with MSG_TRUNC set. It does * not seem to work here :(, but it is supported by this code * anyway. * To be honest the code RELIES on that feature so this is really * broken with 2.2.x kernels. * I spend a day to figure out what's going on and I found out * that the following is happening: * * The packet comes from a random interface and the packet_rcv * hook is called with a clone of the packet. That code inserts * the packet into the receive queue of the packet socket. * If a filter is attached to that socket that filter is run * first - and there lies the problem. The default filter always * cuts the packet at the snaplen: * * # tcpdump -d * (000) ret #68 * * So the packet filter cuts down the packet. The recvfrom call * says "hey, it's only 68 bytes, it fits into the buffer" with * the result that we don't get the real packet length. This * is valid at least until kernel 2.2.17pre6. * * We currently handle this by making a copy of the filter * program, fixing all "ret" instructions with non-zero * operands to have an operand of 65535 so that the filter * doesn't truncate the packet, and supplying that modified * filter to the kernel. */ caplen = packet_len; if (caplen > handle->snapshot) caplen = handle->snapshot; /* Run the packet filter if not using kernel filter */ if (!handle->md.use_bpf && handle->fcode.bf_insns) { if (bpf_filter(handle->fcode.bf_insns, bp, packet_len, caplen) == 0) { /* rejected by filter */ return 0; } } /* Fill in our own header data */ if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) { snprintf(handle->errbuf, sizeof(handle->errbuf), "SIOCGSTAMP: %s", pcap_strerror(errno)); return -1; } pcap_header.caplen = caplen; pcap_header.len = packet_len; /* * Count the packet. * * Arguably, we should count them before we check the filter, * as on many other platforms "ps_recv" counts packets * handed to the filter rather than packets that passed * the filter, but if filtering is done in the kernel, we * can't get a count of packets that passed the filter, * and that would mean the meaning of "ps_recv" wouldn't * be the same on all Linux systems. * * XXX - it's not the same on all systems in any case; * ideally, we should have a "get the statistics" call * that supplies more counts and indicates which of them * it supplies, so that we supply a count of packets * handed to the filter only on platforms where that * information is available. * * We count them here even if we can get the packet count * from the kernel, as we can only determine at run time * whether we'll be able to get it from the kernel (if * HAVE_TPACKET_STATS isn't defined, we can't get it from * the kernel, but if it is defined, the library might * have been built with a 2.4 or later kernel, but we * might be running on a 2.2[.x] kernel without Alexey * Kuznetzov's turbopacket patches, and thus the kernel * might not be able to supply those statistics). We * could, I guess, try, when opening the socket, to get * the statistics, and if we can not increment the count * here, but it's not clear that always incrementing * the count is more expensive than always testing a flag * in memory. * * We keep the count in "md.packets_read", and use that for * "ps_recv" if we can't get the statistics from the kernel. * We do that because, if we *can* get the statistics from * the kernel, we use "md.stat.ps_recv" and "md.stat.ps_drop" * as running counts, as reading the statistics from the * kernel resets the kernel statistics, and if we directly * increment "md.stat.ps_recv" here, that means it will * count packets *twice* on systems where we can get kernel * statistics - once here, and once in pcap_stats_linux(). */ handle->md.packets_read++; /* Call the user supplied callback function */ callback(userdata, &pcap_header, bp); return 1; } static int pcap_inject_linux(pcap_t *handle, const void *buf, size_t size) { int ret; #ifdef HAVE_PF_PACKET_SOCKETS if (!handle->md.sock_packet) { /* PF_PACKET socket */ if (handle->md.ifindex == -1) { /* * We don't support sending on the "any" device. */ strlcpy(handle->errbuf, "Sending packets isn't supported on the \"any\" device", PCAP_ERRBUF_SIZE); return (-1); } if (handle->md.cooked) { /* * We don't support sending on the "any" device. * * XXX - how do you send on a bound cooked-mode * socket? * Is a "sendto()" required there? */ strlcpy(handle->errbuf, "Sending packets isn't supported in cooked mode", PCAP_ERRBUF_SIZE); return (-1); } } #endif ret = send(handle->fd, buf, size, 0); if (ret == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } /* * Get the statistics for the given packet capture handle. * Reports the number of dropped packets iff the kernel supports * the PACKET_STATISTICS "getsockopt()" argument (2.4 and later * kernels, and 2.2[.x] kernels with Alexey Kuznetzov's turbopacket * patches); otherwise, that information isn't available, and we lie * and report 0 as the count of dropped packets. */ static int pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) { #ifdef HAVE_TPACKET_STATS struct tpacket_stats kstats; socklen_t len = sizeof (struct tpacket_stats); #endif #ifdef HAVE_TPACKET_STATS /* * Try to get the packet counts from the kernel. */ if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, &kstats, &len) > -1) { /* * On systems where the PACKET_STATISTICS "getsockopt()" * argument is supported on PF_PACKET sockets: * * "ps_recv" counts only packets that *passed* the * filter, not packets that didn't pass the filter. * This includes packets later dropped because we * ran out of buffer space. * * "ps_drop" counts packets dropped because we ran * out of buffer space. It doesn't count packets * dropped by the interface driver. It counts only * packets that passed the filter. * * Both statistics include packets not yet read from * the kernel by libpcap, and thus not yet seen by * the application. * * In "linux/net/packet/af_packet.c", at least in the * 2.4.9 kernel, "tp_packets" is incremented for every * packet that passes the packet filter *and* is * successfully queued on the socket; "tp_drops" is * incremented for every packet dropped because there's * not enough free space in the socket buffer. * * When the statistics are returned for a PACKET_STATISTICS * "getsockopt()" call, "tp_drops" is added to "tp_packets", * so that "tp_packets" counts all packets handed to * the PF_PACKET socket, including packets dropped because * there wasn't room on the socket buffer - but not * including packets that didn't pass the filter. * * In the BSD BPF, the count of received packets is * incremented for every packet handed to BPF, regardless * of whether it passed the filter. * * We can't make "pcap_stats()" work the same on both * platforms, but the best approximation is to return * "tp_packets" as the count of packets and "tp_drops" * as the count of drops. * * Keep a running total because each call to * getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, .... * resets the counters to zero. */ handle->md.stat.ps_recv += kstats.tp_packets; handle->md.stat.ps_drop += kstats.tp_drops; *stats = handle->md.stat; return 0; } else { /* * If the error was EOPNOTSUPP, fall through, so that * if you build the library on a system with * "struct tpacket_stats" and run it on a system * that doesn't, it works as it does if the library * is built on a system without "struct tpacket_stats". */ if (errno != EOPNOTSUPP) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s", pcap_strerror(errno)); return -1; } } #endif /* * On systems where the PACKET_STATISTICS "getsockopt()" argument * is not supported on PF_PACKET sockets: * * "ps_recv" counts only packets that *passed* the filter, * not packets that didn't pass the filter. It does not * count packets dropped because we ran out of buffer * space. * * "ps_drop" is not supported. * * "ps_recv" doesn't include packets not yet read from * the kernel by libpcap. * * We maintain the count of packets processed by libpcap in * "md.packets_read", for reasons described in the comment * at the end of pcap_read_packet(). We have no idea how many * packets were dropped. */ stats->ps_recv = handle->md.packets_read; stats->ps_drop = 0; return 0; } /* * Description string for the "any" device. */ static const char any_descr[] = "Pseudo-device that captures on all interfaces"; int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { if (pcap_add_if(alldevsp, "any", 0, any_descr, errbuf) < 0) return (-1); #ifdef HAVE_DAG_API if (dag_platform_finddevs(alldevsp, errbuf) < 0) return (-1); #endif /* HAVE_DAG_API */ #ifdef HAVE_SEPTEL_API if (septel_platform_finddevs(alldevsp, errbuf) < 0) return (-1); #endif /* HAVE_SEPTEL_API */ return (0); } /* * Attach the given BPF code to the packet capture device. */ static int pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter) { #ifdef SO_ATTACH_FILTER struct sock_fprog fcode; int can_filter_in_kernel; int err = 0; #endif if (!handle) return -1; if (!filter) { strncpy(handle->errbuf, "setfilter: No filter specified", sizeof(handle->errbuf)); return -1; } /* Make our private copy of the filter */ if (install_bpf_program(handle, filter) < 0) /* install_bpf_program() filled in errbuf */ return -1; /* * Run user level packet filter by default. Will be overriden if * installing a kernel filter succeeds. */ handle->md.use_bpf = 0; /* Install kernel level filter if possible */ #ifdef SO_ATTACH_FILTER #ifdef USHRT_MAX if (handle->fcode.bf_len > USHRT_MAX) { /* * fcode.len is an unsigned short for current kernel. * I have yet to see BPF-Code with that much * instructions but still it is possible. So for the * sake of correctness I added this check. */ fprintf(stderr, "Warning: Filter too complex for kernel\n"); fcode.len = 0; fcode.filter = NULL; can_filter_in_kernel = 0; } else #endif /* USHRT_MAX */ { /* * Oh joy, the Linux kernel uses struct sock_fprog instead * of struct bpf_program and of course the length field is * of different size. Pointed out by Sebastian * * Oh, and we also need to fix it up so that all "ret" * instructions with non-zero operands have 65535 as the * operand, and so that, if we're in cooked mode, all * memory-reference instructions use special magic offsets * in references to the link-layer header and assume that * the link-layer payload begins at 0; "fix_program()" * will do that. */ switch (fix_program(handle, &fcode)) { case -1: default: /* * Fatal error; just quit. * (The "default" case shouldn't happen; we * return -1 for that reason.) */ return -1; case 0: /* * The program performed checks that we can't make * work in the kernel. */ can_filter_in_kernel = 0; break; case 1: /* * We have a filter that'll work in the kernel. */ can_filter_in_kernel = 1; break; } } if (can_filter_in_kernel) { if ((err = set_kernel_filter(handle, &fcode)) == 0) { /* Installation succeded - using kernel filter. */ handle->md.use_bpf = 1; } else if (err == -1) /* Non-fatal error */ { /* * Print a warning if we weren't able to install * the filter for a reason other than "this kernel * isn't configured to support socket filters. */ if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) { fprintf(stderr, "Warning: Kernel filter failed: %s\n", pcap_strerror(errno)); } } } /* * If we're not using the kernel filter, get rid of any kernel * filter that might've been there before, e.g. because the * previous filter could work in the kernel, or because some other * code attached a filter to the socket by some means other than * calling "pcap_setfilter()". Otherwise, the kernel filter may * filter out packets that would pass the new userland filter. */ if (!handle->md.use_bpf) reset_kernel_filter(handle); /* * Free up the copy of the filter that was made by "fix_program()". */ if (fcode.filter != NULL) free(fcode.filter); if (err == -2) /* Fatal error */ return -1; #endif /* SO_ATTACH_FILTER */ return 0; } /* * Set direction flag: Which packets do we accept on a forwarding * single device? IN, OUT or both? */ static int pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d) { #ifdef HAVE_PF_PACKET_SOCKETS if (!handle->md.sock_packet) { handle->direction = d; return 0; } #endif /* * We're not using PF_PACKET sockets, so we can't determine * the direction of the packet. */ snprintf(handle->errbuf, sizeof(handle->errbuf), "Setting direction is not supported on SOCK_PACKET sockets"); return -1; } /* * Linux uses the ARP hardware type to identify the type of an * interface. pcap uses the DLT_xxx constants for this. This * function takes a pointer to a "pcap_t", and an ARPHRD_xxx * constant, as arguments, and sets "handle->linktype" to the * appropriate DLT_XXX constant and sets "handle->offset" to * the appropriate value (to make "handle->offset" plus link-layer * header length be a multiple of 4, so that the link-layer payload * will be aligned on a 4-byte boundary when capturing packets). * (If the offset isn't set here, it'll be 0; add code as appropriate * for cases where it shouldn't be 0.) * * If "cooked_ok" is non-zero, we can use DLT_LINUX_SLL and capture * in cooked mode; otherwise, we can't use cooked mode, so we have * to pick some type that works in raw mode, or fail. * * Sets the link type to -1 if unable to map the type. */ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) { switch (arptype) { case ARPHRD_ETHER: /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). * * XXX - are there any sorts of "fake Ethernet" that have * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as * a Cisco CMTS won't put traffic onto it or get traffic * bridged onto it? ISDN is handled in "live_open_new()", * as we fall back on cooked mode there; are there any * others? */ handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (handle->dlt_list != NULL) { handle->dlt_list[0] = DLT_EN10MB; handle->dlt_list[1] = DLT_DOCSIS; handle->dlt_count = 2; } /* FALLTHROUGH */ case ARPHRD_METRICOM: case ARPHRD_LOOPBACK: handle->linktype = DLT_EN10MB; handle->offset = 2; break; case ARPHRD_EETHER: handle->linktype = DLT_EN3MB; break; case ARPHRD_AX25: handle->linktype = DLT_AX25; break; case ARPHRD_PRONET: handle->linktype = DLT_PRONET; break; case ARPHRD_CHAOS: handle->linktype = DLT_CHAOS; break; #ifndef ARPHRD_IEEE802_TR #define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */ #endif case ARPHRD_IEEE802_TR: case ARPHRD_IEEE802: handle->linktype = DLT_IEEE802; handle->offset = 2; break; case ARPHRD_ARCNET: handle->linktype = DLT_ARCNET_LINUX; break; #ifndef ARPHRD_FDDI /* From Linux 2.2.13 */ #define ARPHRD_FDDI 774 #endif case ARPHRD_FDDI: handle->linktype = DLT_FDDI; handle->offset = 3; break; #ifndef ARPHRD_ATM /* FIXME: How to #include this? */ #define ARPHRD_ATM 19 #endif case ARPHRD_ATM: /* * The Classical IP implementation in ATM for Linux * supports both what RFC 1483 calls "LLC Encapsulation", * in which each packet has an LLC header, possibly * with a SNAP header as well, prepended to it, and * what RFC 1483 calls "VC Based Multiplexing", in which * different virtual circuits carry different network * layer protocols, and no header is prepended to packets. * * They both have an ARPHRD_ type of ARPHRD_ATM, so * you can't use the ARPHRD_ type to find out whether * captured packets will have an LLC header, and, * while there's a socket ioctl to *set* the encapsulation * type, there's no ioctl to *get* the encapsulation type. * * This means that * * programs that dissect Linux Classical IP frames * would have to check for an LLC header and, * depending on whether they see one or not, dissect * the frame as LLC-encapsulated or as raw IP (I * don't know whether there's any traffic other than * IP that would show up on the socket, or whether * there's any support for IPv6 in the Linux * Classical IP code); * * filter expressions would have to compile into * code that checks for an LLC header and does * the right thing. * * Both of those are a nuisance - and, at least on systems * that support PF_PACKET sockets, we don't have to put * up with those nuisances; instead, we can just capture * in cooked mode. That's what we'll do, if we can. * Otherwise, we'll just fail. */ if (cooked_ok) handle->linktype = DLT_LINUX_SLL; else handle->linktype = -1; break; #ifndef ARPHRD_IEEE80211 /* From Linux 2.4.6 */ #define ARPHRD_IEEE80211 801 #endif case ARPHRD_IEEE80211: handle->linktype = DLT_IEEE802_11; break; #ifndef ARPHRD_IEEE80211_PRISM /* From Linux 2.4.18 */ #define ARPHRD_IEEE80211_PRISM 802 #endif case ARPHRD_IEEE80211_PRISM: handle->linktype = DLT_PRISM_HEADER; break; #ifndef ARPHRD_IEEE80211_RADIOTAP /* new */ #define ARPHRD_IEEE80211_RADIOTAP 803 #endif case ARPHRD_IEEE80211_RADIOTAP: handle->linktype = DLT_IEEE802_11_RADIO; break; case ARPHRD_PPP: /* * Some PPP code in the kernel supplies no link-layer * header whatsoever to PF_PACKET sockets; other PPP * code supplies PPP link-layer headers ("syncppp.c"); * some PPP code might supply random link-layer * headers (PPP over ISDN - there's code in Ethereal, * for example, to cope with PPP-over-ISDN captures * with which the Ethereal developers have had to cope, * heuristically trying to determine which of the * oddball link-layer headers particular packets have). * * As such, we just punt, and run all PPP interfaces * in cooked mode, if we can; otherwise, we just treat * it as DLT_RAW, for now - if somebody needs to capture, * on a 2.0[.x] kernel, on PPP devices that supply a * link-layer header, they'll have to add code here to * map to the appropriate DLT_ type (possibly adding a * new DLT_ type, if necessary). */ if (cooked_ok) handle->linktype = DLT_LINUX_SLL; else { /* * XXX - handle ISDN types here? We can't fall * back on cooked sockets, so we'd have to * figure out from the device name what type of * link-layer encapsulation it's using, and map * that to an appropriate DLT_ value, meaning * we'd map "isdnN" devices to DLT_RAW (they * supply raw IP packets with no link-layer * header) and "isdY" devices to a new DLT_I4L_IP * type that has only an Ethernet packet type as * a link-layer header. * * But sometimes we seem to get random crap * in the link-layer header when capturing on * ISDN devices.... */ handle->linktype = DLT_RAW; } break; #ifndef ARPHRD_CISCO #define ARPHRD_CISCO 513 /* previously ARPHRD_HDLC */ #endif case ARPHRD_CISCO: handle->linktype = DLT_C_HDLC; break; /* Not sure if this is correct for all tunnels, but it * works for CIPE */ case ARPHRD_TUNNEL: #ifndef ARPHRD_SIT #define ARPHRD_SIT 776 /* From Linux 2.2.13 */ #endif case ARPHRD_SIT: case ARPHRD_CSLIP: case ARPHRD_SLIP6: case ARPHRD_CSLIP6: case ARPHRD_ADAPT: case ARPHRD_SLIP: #ifndef ARPHRD_RAWHDLC #define ARPHRD_RAWHDLC 518 #endif case ARPHRD_RAWHDLC: #ifndef ARPHRD_DLCI #define ARPHRD_DLCI 15 #endif case ARPHRD_DLCI: /* * XXX - should some of those be mapped to DLT_LINUX_SLL * instead? Should we just map all of them to DLT_LINUX_SLL? */ handle->linktype = DLT_RAW; break; #ifndef ARPHRD_FRAD #define ARPHRD_FRAD 770 #endif case ARPHRD_FRAD: handle->linktype = DLT_FRELAY; break; case ARPHRD_LOCALTLK: handle->linktype = DLT_LTALK; break; #ifndef ARPHRD_FCPP #define ARPHRD_FCPP 784 #endif case ARPHRD_FCPP: #ifndef ARPHRD_FCAL #define ARPHRD_FCAL 785 #endif case ARPHRD_FCAL: #ifndef ARPHRD_FCPL #define ARPHRD_FCPL 786 #endif case ARPHRD_FCPL: #ifndef ARPHRD_FCFABRIC #define ARPHRD_FCFABRIC 787 #endif case ARPHRD_FCFABRIC: /* * We assume that those all mean RFC 2625 IP-over- * Fibre Channel, with the RFC 2625 header at * the beginning of the packet. */ handle->linktype = DLT_IP_OVER_FC; break; #ifndef ARPHRD_IRDA #define ARPHRD_IRDA 783 #endif case ARPHRD_IRDA: /* Don't expect IP packet out of this interfaces... */ handle->linktype = DLT_LINUX_IRDA; /* We need to save packet direction for IrDA decoding, * so let's use "Linux-cooked" mode. Jean II */ //handle->md.cooked = 1; break; /* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation * is needed, please report it to */ #ifndef ARPHRD_LAPD #define ARPHRD_LAPD 8445 #endif case ARPHRD_LAPD: /* Don't expect IP packet out of this interfaces... */ handle->linktype = DLT_LINUX_LAPD; break; default: handle->linktype = -1; break; } } /* ===== Functions to interface to the newer kernels ================== */ /* * Try to open a packet socket using the new kernel interface. * Returns 0 on failure. * FIXME: 0 uses to mean success (Sebastian) */ static int live_open_new(pcap_t *handle, const char *device, int promisc, int to_ms, char *ebuf) { #ifdef HAVE_PF_PACKET_SOCKETS int sock_fd = -1, arptype; int err; int fatal_err = 0; struct packet_mreq mr; /* One shot loop used for error handling - bail out with break */ do { /* * Open a socket with protocol family packet. If a device is * given we try to open it in raw mode otherwise we use * the cooked interface. */ sock_fd = device ? socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); if (sock_fd == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno) ); break; } /* It seems the kernel supports the new interface. */ handle->md.sock_packet = 0; /* * Get the interface index of the loopback device. * If the attempt fails, don't fail, just set the * "md.lo_ifindex" to -1. * * XXX - can there be more than one device that loops * packets back, i.e. devices other than "lo"? If so, * we'd need to find them all, and have an array of * indices for them, and check all of them in * "pcap_read_packet()". */ handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", ebuf); /* * Default value for offset to align link-layer payload * on a 4-byte boundary. */ handle->offset = 0; /* * What kind of frames do we have to deal with? Fall back * to cooked mode if we have an unknown interface type. */ if (device) { /* Assume for now we don't need cooked mode. */ handle->md.cooked = 0; arptype = iface_get_arptype(sock_fd, device, ebuf); if (arptype == -1) { fatal_err = 1; break; } map_arphrd_to_dlt(handle, arptype, 1); if (handle->linktype == -1 || handle->linktype == DLT_LINUX_SLL || handle->linktype == DLT_LINUX_IRDA || handle->linktype == DLT_LINUX_LAPD || (handle->linktype == DLT_EN10MB && (strncmp("isdn", device, 4) == 0 || strncmp("isdY", device, 4) == 0))) { /* * Unknown interface type (-1), or a * device we explicitly chose to run * in cooked mode (e.g., PPP devices), * or an ISDN device (whose link-layer * type we can only determine by using * APIs that may be different on different * kernels) - reopen in cooked mode. */ if (close(sock_fd) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "close: %s", pcap_strerror(errno)); break; } sock_fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); if (sock_fd == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); break; } handle->md.cooked = 1; /* * Get rid of any link-layer type list * we allocated - this only supports cooked * capture. */ if (handle->dlt_list != NULL) { free(handle->dlt_list); handle->dlt_list = NULL; handle->dlt_count = 0; } if (handle->linktype == -1) { /* * Warn that we're falling back on * cooked mode; we may want to * update "map_arphrd_to_dlt()" * to handle the new type. */ snprintf(ebuf, PCAP_ERRBUF_SIZE, "arptype %d not " "supported by libpcap - " "falling back to cooked " "socket", arptype); } /* IrDA capture is not a real "cooked" capture, * it's IrLAP frames, not IP packets. */ if (handle->linktype != DLT_LINUX_IRDA && handle->linktype != DLT_LINUX_LAPD) handle->linktype = DLT_LINUX_SLL; } handle->md.ifindex = iface_get_id(sock_fd, device, ebuf); if (handle->md.ifindex == -1) break; if ((err = iface_bind(sock_fd, handle->md.ifindex, ebuf)) < 0) { if (err == -2) fatal_err = 1; break; } } else { /* * This is cooked mode. */ handle->md.cooked = 1; handle->linktype = DLT_LINUX_SLL; /* * We're not bound to a device. * XXX - true? Or true only if we're using * the "any" device? * For now, we're using this as an indication * that we can't transmit; stop doing that only * if we figure out how to transmit in cooked * mode. */ handle->md.ifindex = -1; } /* * Select promiscuous mode on if "promisc" is set. * * Do not turn allmulti mode on if we don't select * promiscuous mode - on some devices (e.g., Orinoco * wireless interfaces), allmulti mode isn't supported * and the driver implements it by turning promiscuous * mode on, and that screws up the operation of the * card as a normal networking interface, and on no * other platform I know of does starting a non- * promiscuous capture affect which multicast packets * are received by the interface. */ /* * Hmm, how can we set promiscuous mode on all interfaces? * I am not sure if that is possible at all. */ if (device && promisc) { memset(&mr, 0, sizeof(mr)); mr.mr_ifindex = handle->md.ifindex; mr.mr_type = PACKET_MR_PROMISC; if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "setsockopt: %s", pcap_strerror(errno)); break; } } /* Save the socket FD in the pcap structure */ handle->fd = sock_fd; return 1; } while(0); if (sock_fd != -1) close(sock_fd); if (fatal_err) { /* * Get rid of any link-layer type list we allocated. */ if (handle->dlt_list != NULL) free(handle->dlt_list); return -2; } else return 0; #else strncpy(ebuf, "New packet capturing interface not supported by build " "environment", PCAP_ERRBUF_SIZE); return 0; #endif } #ifdef HAVE_PF_PACKET_SOCKETS /* * Return the index of the given device name. Fill ebuf and return * -1 on failure. */ static int iface_get_id(int fd, const char *device, char *ebuf) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFINDEX: %s", pcap_strerror(errno)); return -1; } return ifr.ifr_ifindex; } /* * Bind the socket associated with FD to the given device. */ static int iface_bind(int fd, int ifindex, char *ebuf) { struct sockaddr_ll sll; int err; socklen_t errlen = sizeof(err); memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = ifindex; sll.sll_protocol = htons(ETH_P_ALL); if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "bind: %s", pcap_strerror(errno)); return -1; } /* Any pending errors, e.g., network is down? */ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); return -2; } if (err > 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "bind: %s", pcap_strerror(err)); return -2; } return 0; } #endif /* ===== Functions to interface to the older kernels ================== */ /* * With older kernels promiscuous mode is kind of interesting because we * have to reset the interface before exiting. The problem can't really * be solved without some daemon taking care of managing usage counts. * If we put the interface into promiscuous mode, we set a flag indicating * that we must take it out of that mode when the interface is closed, * and, when closing the interface, if that flag is set we take it out * of promiscuous mode. */ /* * List of pcaps for which we turned promiscuous mode on by hand. * If there are any such pcaps, we arrange to call "pcap_close_all()" * when we exit, and have it close all of them to turn promiscuous mode * off. */ static struct pcap *pcaps_to_close; /* * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to * be called on exit. */ static int did_atexit; static void pcap_close_all(void) { struct pcap *handle; while ((handle = pcaps_to_close) != NULL) pcap_close(handle); } static void pcap_close_linux( pcap_t *handle ) { struct pcap *p, *prevp; struct ifreq ifr; if (handle->md.clear_promisc) { /* * We put the interface into promiscuous mode; take * it out of promiscuous mode. * * XXX - if somebody else wants it in promiscuous mode, * this code cannot know that, so it'll take it out * of promiscuous mode. That's not fixable in 2.0[.x] * kernels. */ memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, handle->md.device, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { fprintf(stderr, "Can't restore interface flags (SIOCGIFFLAGS failed: %s).\n" "Please adjust manually.\n" "Hint: This can't happen with Linux >= 2.2.0.\n", strerror(errno)); } else { if (ifr.ifr_flags & IFF_PROMISC) { /* * Promiscuous mode is currently on; turn it * off. */ ifr.ifr_flags &= ~IFF_PROMISC; if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { fprintf(stderr, "Can't restore interface flags (SIOCSIFFLAGS failed: %s).\n" "Please adjust manually.\n" "Hint: This can't happen with Linux >= 2.2.0.\n", strerror(errno)); } } } /* * Take this pcap out of the list of pcaps for which we * have to take the interface out of promiscuous mode. */ for (p = pcaps_to_close, prevp = NULL; p != NULL; prevp = p, p = p->md.next) { if (p == handle) { /* * Found it. Remove it from the list. */ if (prevp == NULL) { /* * It was at the head of the list. */ pcaps_to_close = p->md.next; } else { /* * It was in the middle of the list. */ prevp->md.next = p->md.next; } break; } } } if (handle->md.device != NULL) free(handle->md.device); handle->md.device = NULL; pcap_close_common(handle); } /* * Try to open a packet socket using the old kernel interface. * Returns 0 on failure. * FIXME: 0 uses to mean success (Sebastian) */ static int live_open_old(pcap_t *handle, const char *device, int promisc, int to_ms, char *ebuf) { int arptype; struct ifreq ifr; do { /* Open the socket */ handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); if (handle->fd == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); break; } /* It worked - we are using the old interface */ handle->md.sock_packet = 1; /* ...which means we get the link-layer header. */ handle->md.cooked = 0; /* Bind to the given device */ if (!device) { strncpy(ebuf, "pcap_open_live: The \"any\" device isn't supported on 2.0[.x]-kernel systems", PCAP_ERRBUF_SIZE); break; } if (iface_bind_old(handle->fd, device, ebuf) == -1) break; /* * Try to get the link-layer type. */ arptype = iface_get_arptype(handle->fd, device, ebuf); if (arptype == -1) break; /* * Try to find the DLT_ type corresponding to that * link-layer type. */ map_arphrd_to_dlt(handle, arptype, 0); if (handle->linktype == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown arptype %d", arptype); break; } /* Go to promisc mode if requested */ if (promisc) { memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFFLAGS: %s", pcap_strerror(errno)); break; } if ((ifr.ifr_flags & IFF_PROMISC) == 0) { /* * Promiscuous mode isn't currently on, * so turn it on, and remember that * we should turn it off when the * pcap_t is closed. */ /* * If we haven't already done so, arrange * to have "pcap_close_all()" called when * we exit. */ if (!did_atexit) { if (atexit(pcap_close_all) == -1) { /* * "atexit()" failed; don't * put the interface in * promiscuous mode, just * give up. */ strncpy(ebuf, "atexit failed", PCAP_ERRBUF_SIZE); break; } did_atexit = 1; } ifr.ifr_flags |= IFF_PROMISC; if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSIFFLAGS: %s", pcap_strerror(errno)); break; } handle->md.clear_promisc = 1; /* * Add this to the list of pcaps * to close when we exit. */ handle->md.next = pcaps_to_close; pcaps_to_close = handle; } } /* * Default value for offset to align link-layer payload * on a 4-byte boundary. */ handle->offset = 0; return 1; } while (0); pcap_close_linux(handle); return 0; } /* * Bind the socket associated with FD to the given device using the * interface of the old kernels. */ static int iface_bind_old(int fd, const char *device, char *ebuf) { struct sockaddr saddr; int err; socklen_t errlen = sizeof(err); memset(&saddr, 0, sizeof(saddr)); strncpy(saddr.sa_data, device, sizeof(saddr.sa_data)); if (bind(fd, &saddr, sizeof(saddr)) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "bind: %s", pcap_strerror(errno)); return -1; } /* Any pending errors, e.g., network is down? */ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); return -1; } if (err > 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "bind: %s", pcap_strerror(err)); return -1; } return 0; } /* ===== System calls available on all supported kernels ============== */ /* * Query the kernel for the MTU of the given interface. */ static int iface_get_mtu(int fd, const char *device, char *ebuf) { struct ifreq ifr; if (!device) return BIGGER_THAN_ALL_MTUS; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s", pcap_strerror(errno)); return -1; } return ifr.ifr_mtu; } /* * Get the hardware type of the given interface as ARPHRD_xxx constant. */ static int iface_get_arptype(int fd, const char *device, char *ebuf) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFHWADDR: %s", pcap_strerror(errno)); return -1; } return ifr.ifr_hwaddr.sa_family; } #ifdef SO_ATTACH_FILTER static int fix_program(pcap_t *handle, struct sock_fprog *fcode) { size_t prog_size; register int i; register struct bpf_insn *p; struct bpf_insn *f; int len; /* * Make a copy of the filter, and modify that copy if * necessary. */ prog_size = sizeof(*handle->fcode.bf_insns) * handle->fcode.bf_len; len = handle->fcode.bf_len; f = (struct bpf_insn *)malloc(prog_size); if (f == NULL) { snprintf(handle->errbuf, sizeof(handle->errbuf), "malloc: %s", pcap_strerror(errno)); return -1; } memcpy(f, handle->fcode.bf_insns, prog_size); fcode->len = len; fcode->filter = (struct sock_filter *) f; for (i = 0; i < len; ++i) { p = &f[i]; /* * What type of instruction is this? */ switch (BPF_CLASS(p->code)) { case BPF_RET: /* * It's a return instruction; is the snapshot * length a constant, rather than the contents * of the accumulator? */ if (BPF_MODE(p->code) == BPF_K) { /* * Yes - if the value to be returned, * i.e. the snapshot length, is anything * other than 0, make it 65535, so that * the packet is truncated by "recvfrom()", * not by the filter. * * XXX - there's nothing we can easily do * if it's getting the value from the * accumulator; we'd have to insert * code to force non-zero values to be * 65535. */ if (p->k != 0) p->k = 65535; } break; case BPF_LD: case BPF_LDX: /* * It's a load instruction; is it loading * from the packet? */ switch (BPF_MODE(p->code)) { case BPF_ABS: case BPF_IND: case BPF_MSH: /* * Yes; are we in cooked mode? */ if (handle->md.cooked) { /* * Yes, so we need to fix this * instruction. */ if (fix_offset(p) < 0) { /* * We failed to do so. * Return 0, so our caller * knows to punt to userland. */ return 0; } } break; } break; } } return 1; /* we succeeded */ } static int fix_offset(struct bpf_insn *p) { /* * What's the offset? */ if (p->k >= SLL_HDR_LEN) { /* * It's within the link-layer payload; that starts at an * offset of 0, as far as the kernel packet filter is * concerned, so subtract the length of the link-layer * header. */ p->k -= SLL_HDR_LEN; } else if (p->k == 14) { /* * It's the protocol field; map it to the special magic * kernel offset for that field. */ p->k = SKF_AD_OFF + SKF_AD_PROTOCOL; } else { /* * It's within the header, but it's not one of those * fields; we can't do that in the kernel, so punt * to userland. */ return -1; } return 0; } static int set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode) { int total_filter_on = 0; int save_mode; int ret; int save_errno; /* * The socket filter code doesn't discard all packets queued * up on the socket when the filter is changed; this means * that packets that don't match the new filter may show up * after the new filter is put onto the socket, if those * packets haven't yet been read. * * This means, for example, that if you do a tcpdump capture * with a filter, the first few packets in the capture might * be packets that wouldn't have passed the filter. * * We therefore discard all packets queued up on the socket * when setting a kernel filter. (This isn't an issue for * userland filters, as the userland filtering is done after * packets are queued up.) * * To flush those packets, we put the socket in read-only mode, * and read packets from the socket until there are no more to * read. * * In order to keep that from being an infinite loop - i.e., * to keep more packets from arriving while we're draining * the queue - we put the "total filter", which is a filter * that rejects all packets, onto the socket before draining * the queue. * * This code deliberately ignores any errors, so that you may * get bogus packets if an error occurs, rather than having * the filtering done in userland even if it could have been * done in the kernel. */ if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER, &total_fcode, sizeof(total_fcode)) == 0) { char drain[1]; /* * Note that we've put the total filter onto the socket. */ total_filter_on = 1; /* * Save the socket's current mode, and put it in * non-blocking mode; we drain it by reading packets * until we get an error (which is normally a * "nothing more to be read" error). */ save_mode = fcntl(handle->fd, F_GETFL, 0); if (save_mode != -1 && fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) >= 0) { while (recv(handle->fd, &drain, sizeof drain, MSG_TRUNC) >= 0) ; save_errno = errno; fcntl(handle->fd, F_SETFL, save_mode); if (save_errno != EAGAIN) { /* Fatal error */ reset_kernel_filter(handle); snprintf(handle->errbuf, sizeof(handle->errbuf), "recv: %s", pcap_strerror(save_errno)); return -2; } } } /* * Now attach the new filter. */ ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER, fcode, sizeof(*fcode)); if (ret == -1 && total_filter_on) { /* * Well, we couldn't set that filter on the socket, * but we could set the total filter on the socket. * * This could, for example, mean that the filter was * too big to put into the kernel, so we'll have to * filter in userland; in any case, we'll be doing * filtering in userland, so we need to remove the * total filter so we see packets. */ save_errno = errno; /* * XXX - if this fails, we're really screwed; * we have the total filter on the socket, * and it won't come off. What do we do then? */ reset_kernel_filter(handle); errno = save_errno; } return ret; } static int reset_kernel_filter(pcap_t *handle) { /* * setsockopt() barfs unless it get a dummy parameter. * valgrind whines unless the value is initialized, * as it has no idea that setsockopt() ignores its * parameter. */ int dummy = 0; return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER, &dummy, sizeof(dummy)); } #endif libpcap-0.9.7/./VERSION0000644000026300017500000000000610643174157012474 0ustar mcrmcr0.9.7 libpcap-0.9.7/./pcap-pf.c0000644000026300017500000004067210235744355013133 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.91.2.2 2005/05/03 18:54:37 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include struct mbuf; struct rtentry; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Make "pcap.h" not include "pcap-bpf.h"; we are going to include the * native OS version, as we need various BPF ioctls from it. */ #define PCAP_DONT_INCLUDE_PCAP_BPF_H #include #include "pcap-int.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif static int pcap_setfilter_pf(pcap_t *, struct bpf_program *); /* * 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) static int pcap_read_pf(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; } snprintf(pc->errbuf, sizeof(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 pad = pc->fddipad; #endif while (cc > 0) { /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (pc->break_loop) { if (n == 0) { pc->break_loop = 0; return (-2); } else { pc->cc = cc; pc->bp = bp; return (n); } } if (cc < sizeof(*sp)) { snprintf(pc->errbuf, sizeof(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)) { snprintf(pc->errbuf, sizeof(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; 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. * #ifdef PCAP_FDDIPAD * Note: the filter code was generated assuming * that pc->fddipad was the amount of padding * before the header, as that's what's required * in the kernel, so we run the filter before * skipping that padding. #endif */ 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 #ifdef PCAP_FDDIPAD p += pad; buflen -= pad; #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); } static int pcap_inject_pf(pcap_t *p, const void *buf, size_t size) { int ret; ret = write(p->fd, buf, size); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } static int pcap_stats_pf(pcap_t *p, struct pcap_stat *ps) { /* * If packet filtering is being done in the kernel: * * "ps_recv" counts only packets that passed the filter. * This does not include packets dropped because we * ran out of buffer space. (XXX - perhaps it should, * by adding "ps_drop" to "ps_recv", for compatibility * with some other platforms. On the other hand, on * some platforms "ps_recv" counts only packets that * passed the filter, and on others it counts packets * that didn't pass the filter....) * * "ps_drop" counts packets that passed the kernel filter * (if any) but were dropped because the input queue was * full. * * "ps_ifdrop" counts packets dropped by the network * inteface (regardless of whether they would have passed * the input filter, of course). * * If packet filtering is not being done in the kernel: * * "ps_recv" counts only packets that passed the filter. * * "ps_drop" counts packets that were dropped because the * input queue was full, regardless of whether they passed * the userland filter. * * "ps_ifdrop" counts packets dropped by the network * inteface (regardless of whether they would have passed * the input filter, of course). * * These statistics don't include packets not yet read from * the kernel by libpcap, but they may include packets not * yet read from libpcap by the application. */ ps->ps_recv = p->md.TotAccepted; ps->ps_drop = p->md.TotDrops; ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed; return (0); } /* * We include the OS's , not our "pcap-bpf.h", so we probably * don't get DLT_DOCSIS defined. */ #ifndef DLT_DOCSIS #define DLT_DOCSIS 143 #endif pcap_t * pcap_open_live(const 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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "pcap_open_live: %s", pcap_strerror(errno)); return (0); } memset(p, 0, sizeof(*p)); /* * Initially try a read/write open (to allow the inject * method to work). If that fails due to permission * issues, fall back to read-only. This allows a * non-root user to be granted specific access to pcap * capabilities via file permissions. * * XXX - we should have an API that has a flag that * controls whether to open read-only or read-write, * so that denial of permission to send (or inability * to send, if sending packets isn't supported on * the device in question) can be indicated at open * time. * * XXX - we assume here that "pfopen()" does not, in fact, modify * its argument, even though it takes a "char *" rather than a * "const char *" as its first argument. That appears to be * the case, at least on Digital UNIX 4.0. */ p->fd = pfopen(device, O_RDWR); if (p->fd == -1 && errno == EACCES) p->fd = pfopen(device, O_RDONLY); if (p->fd < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\ your system may not be properly configured; see the packetfilter(4) man page\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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s", pcap_strerror(errno)); goto bad; } /* discover interface type */ if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } break; case ENDT_FDDI: p->linktype = DLT_FDDI; break; #ifdef ENDT_SLIP case ENDT_SLIP: p->linktype = DLT_SLIP; break; #endif #ifdef ENDT_PPP case ENDT_PPP: p->linktype = DLT_PPP; break; #endif #ifdef ENDT_LOOPBACK case ENDT_LOOPBACK: /* * It appears to use Ethernet framing, at least on * Digital UNIX 4.0. */ p->linktype = DLT_EN10MB; p->offset = 2; break; #endif #ifdef ENDT_TRN case ENDT_TRN: p->linktype = DLT_IEEE802; break; #endif default: /* * XXX - what about ENDT_IEEE802? The pfilt.h header * file calls this "IEEE 802 networks (non-Ethernet)", * but that doesn't specify a specific link layer type; * it could be 802.4, or 802.5 (except that 802.5 is * ENDT_TRN), or 802.6, or 802.11, or.... That's why * DLT_IEEE802 was hijacked to mean Token Ring in various * BSDs, and why we went along with that hijacking. * * XXX - what about ENDT_HDLC and ENDT_NULL? * Presumably, as ENDT_OTHER is just "Miscellaneous * framing", there's not much we can do, as that * doesn't specify a particular type of header. */ snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown data-link type %u", devparams.end_dev_type); goto bad; } /* set truncation */ #ifdef PCAP_FDDIPAD if (p->linktype == DLT_FDDI) { p->fddipad = PCAP_FDDIPAD; /* packetfilter includes the padding in the snapshot */ snaplen += PCAP_FDDIPAD; } else p->fddipad = 0; #endif if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s", pcap_strerror(errno)); goto bad; } p->snapshot = snaplen; /* accept all packets */ memset(&Filter, 0, sizeof(Filter)); Filter.enf_Priority = 37; /* anything > 2 */ Filter.enf_FilterLen = 0; /* means "always true" */ if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s", pcap_strerror(errno)); goto bad; } } p->bufsize = BUFSPACE; p->buffer = (u_char*)malloc(p->bufsize + p->offset); if (p->buffer == NULL) { strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } /* * "select()" and "poll()" work on packetfilter devices. */ p->selectable_fd = p->fd; p->read_op = pcap_read_pf; p->inject_op = pcap_inject_pf; p->setfilter_op = pcap_setfilter_pf; p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_pf; p->close_op = pcap_close_common; return (p); bad: if (p->fd >= 0) close(p->fd); /* * Get rid of any link-layer type list we allocated. */ if (p->dlt_list != NULL) free(p->dlt_list); free(p); return (NULL); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } static int pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp) { struct bpf_version bv; /* * See if BIOCVERSION works. If not, we assume the kernel doesn't * support BPF-style filters (it's not documented in the bpf(7) * or packetfiler(7) man pages, but the code used to fail if * BIOCSETF worked but BIOCVERSION didn't, and I've seen it do * kernel filtering in DU 4.0, so presumably BIOCVERSION works * there, at least). */ if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) >= 0) { /* * OK, we have the version of the BPF interpreter; * is it the same major version as us, and the same * or better minor version? */ if (bv.bv_major == BPF_MAJOR_VERSION && bv.bv_minor >= BPF_MINOR_VERSION) { /* * Yes. Try to install the filter. */ if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "BIOCSETF: %s", pcap_strerror(errno)); return (-1); } /* * OK, that succeeded. We're doing filtering in * the kernel. (We assume we don't have a * userland filter installed - that'd require * a previous version check to have failed but * this one to succeed.) * * XXX - this message should be supplied to the * application as a warning of some sort, * except that if it's a GUI application, it's * not clear that it should be displayed in * a window to annoy the user. */ fprintf(stderr, "tcpdump: Using kernel BPF filter\n"); p->md.use_bpf = 1; /* * Discard any previously-received packets, * as they might have passed whatever filter * was formerly in effect, but might not pass * this filter (BIOCSETF discards packets buffered * in the kernel, so you can lose packets in any * case). */ p->cc = 0; return (0); } /* * We can't use the kernel's BPF interpreter; don't give * up, just log a message and be inefficient. * * XXX - this should really be supplied to the application * as a warning of some sort. */ fprintf(stderr, "tcpdump: Requires BPF language %d.%d or higher; kernel is %d.%d\n", BPF_MAJOR_VERSION, BPF_MINOR_VERSION, bv.bv_major, bv.bv_minor); } /* * We couldn't do filtering in the kernel; do it in userland. */ if (install_bpf_program(p, fp) < 0) return (-1); /* * XXX - this message should be supplied by the application as * a warning of some sort. */ fprintf(stderr, "tcpdump: Filtering in user process\n"); p->md.use_bpf = 0; return (0); } libpcap-0.9.7/./pcap-snit.c0000644000026300017500000002546510235744356013507 0ustar mcrmcr/* * 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[] _U_ = "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.72.2.1 2005/05/03 18:54:38 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcap-int.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 *); static int pcap_stats_snit(pcap_t *p, struct pcap_stat *ps) { /* * "ps_recv" counts packets handed to the filter, not packets * that passed the filter. As filtering is done in userland, * this does not include packets dropped because we ran out * of buffer space. * * "ps_drop" counts packets dropped inside the "/dev/nit" * device because of flow control requirements or resource * exhaustion; it doesn't count packets dropped by the * interface driver, or packets dropped upstream. As filtering * is done in userland, it counts packets regardless of whether * they would've passed the filter. * * These statistics don't include packets not yet read from the * kernel by libpcap or packets not yet read from libpcap by the * application. */ *ps = p->md.stat; return (0); } static int pcap_read_snit(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); snprintf(p->errbuf, sizeof(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) { /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = bp; p->cc = ep - bp; return (n); } } ++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 pcap_inject_snit(pcap_t *p, const void *buf, size_t size) { struct strbuf ctl, data; /* * XXX - can we just do * ret = write(pd->f, buf, size); */ ctl.len = sizeof(*sa); /* XXX - what was this? */ ctl.buf = (char *)sa; data.buf = buf; data.len = size; ret = putmsg(p->fd, &ctl, &data); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); return (-1); } return (ret); } 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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s", pcap_strerror(errno)); return (-1); } return (0); } pcap_t * pcap_open_live(const 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) { strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); return (NULL); } if (snaplen < 96) /* * NIT requires a snapshot length of at least 96. */ snaplen = 96; memset(p, 0, sizeof(*p)); /* * Initially try a read/write open (to allow the inject * method to work). If that fails due to permission * issues, fall back to read-only. This allows a * non-root user to be granted specific access to pcap * capabilities via file permissions. * * XXX - we should have an API that has a flag that * controls whether to open read-only or read-write, * so that denial of permission to send (or inability * to send, if sending packets isn't supported on * the device in question) can be indicated at open * time. */ p->fd = fd = open(dev, O_RDWR); if (fd < 0 && errno == EACCES) p->fd = fd = open(dev, O_RDONLY); if (fd < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s", pcap_strerror(errno)); goto bad; } if (ioctl(fd, I_PUSH, "nbuf") < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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] = '\0'; si.ic_cmd = NIOCBIND; si.ic_len = sizeof(ifr); si.ic_dp = (char *)𝔦 if (ioctl(fd, I_STR, (char *)&si) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "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) { strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } /* * "p->fd" is an FD for a STREAMS device, so "select()" and * "poll()" should work on it. */ p->selectable_fd = p->fd; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } p->read_op = pcap_read_snit; p->inject_op = pcap_inject_snit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_snit; p->close_op = pcap_close_common; return (p); bad: if (fd >= 0) close(fd); free(p); return (NULL); } int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { return (0); } libpcap-0.9.7/./README.tru640000644000026300017500000000322707233475705013303 0ustar mcrmcrThe following instructions are applicable to Tru64 UNIX (formerly Digital UNIX (formerly DEC OSF/1)) version 4.0, and probably to later versions as well; at least some options apply to Digital UNIX 3.2 - perhaps all do. In order to use kernel packet filtering on this system, you have to configure it in such a way: Kernel configuration -------------------- The packet filtering kernel option must be enabled at kernel installation. If it was not the case, you can rebuild the kernel with "doconfig -c" after adding the following line in the kernel configuration file (/sys/conf/): option PACKETFILTER or use "doconfig" without any arguments to add the packet filter driver option via the kernel option menu (see the system administration documentation for information on how to do this). Device configuration -------------------- Devices used for packet filtering must be created thanks to the following command (executed in the /dev directory): ./MAKEDEV pfilt Interface configuration ----------------------- In order to capture all packets on a network, you may want to allow applications to put the interface on that network into "local copy" mode, so that tcpdump can see packets sent by the host on which it's running as well as packets received by that host, and to put the interface into "promiscuous" mode, so that tcpdump can see packets on the network segment not sent to the host on which it's running, by using the pfconfig(1) command: pfconfig +c +p or allow application to put any interface into "local copy" or "promiscuous" mode by using the command: pfconfig +c +p -a Note: all instructions given require root privileges.