diff --git a/FILES b/FILES index fcef49b..3076fd1 100644 --- a/FILES +++ b/FILES @@ -27,6 +27,10 @@ configure configure.in etherent.c ethertype.h +fad-getad.c +fad-gifc.c +fad-glifc.c +fad-null.c gencode.c gencode.h grammar.y diff --git a/Makefile.in b/Makefile.in index f56ca55..cfd5c4c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,7 +17,7 @@ # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # -# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.88 2001-01-18 04:05:12 guy Exp $ (LBL) +# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.89 2002-07-27 18:45:34 guy Exp $ (LBL) # # Various configurable paths (remember to edit Makefile.in, not Makefile) @@ -70,16 +70,17 @@ YACC = @V_YACC@ $(CC) $(CFLAGS) -c $(srcdir)/$*.c PSRC = pcap-@V_PCAP@.c +FSRC = fad-@V_FINDALLDEVS@.c 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) $(CSRC) $(GENSRC) +SRC = $(PSRC) $(FSRC) $(CSRC) $(GENSRC) # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection -OBJ = $(PSRC:.c=.o) $(CSRC:.c=.o) $(GENSRC:.c=.o) # $(LIBOBJS) +OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.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 = \ diff --git a/aclocal.m4 b/aclocal.m4 index fd89e31..f5924e4 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.79 2002-07-13 09:34:59 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.80 2002-07-27 18:45:34 guy Exp $ (LBL) dnl dnl Copyright (c) 1995, 1996, 1997, 1998 dnl The Regents of the University of California. All rights reserved. @@ -459,6 +459,31 @@ AC_DEFUN(AC_LBL_SOCKADDR_SA_LEN, 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 diff --git a/config.h.in b/config.h.in index 7025060..83800a8 100644 --- a/config.h.in +++ b/config.h.in @@ -104,6 +104,9 @@ /* if struct sockaddr has sa_len */ #undef HAVE_SOCKADDR_SA_LEN +/* if struct sockaddr_storage exists */ +#undef HAVE_SOCKADDR_STORAGE + /* if ppa_info_t_dl_module_id exists */ #undef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 diff --git a/configure b/configure index e0dbddc..76d31f9 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh -# From configure.in Revision: 1.95 +# From configure.in Revision: 1.96 @@ -44,6 +44,8 @@ + + @@ -632,7 +634,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:636: checking host system type" >&5 +echo "configure:638: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -653,7 +655,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 -echo "configure:657: checking target system type" >&5 +echo "configure:659: checking target system type" >&5 target_alias=$target case "$target_alias" in @@ -671,7 +673,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:675: checking build system type" >&5 +echo "configure:677: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -719,7 +721,7 @@ fi # Extract the first word of "shlicc2", so it can be a program name with args. set dummy shlicc2; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:723: checking for $ac_word" >&5 +echo "configure:725: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_SHLICC2'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -760,7 +762,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:764: checking for $ac_word" >&5 +echo "configure:766: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -790,7 +792,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:794: checking for $ac_word" >&5 +echo "configure:796: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -841,7 +843,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:845: checking for $ac_word" >&5 +echo "configure:847: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -873,7 +875,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:877: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:879: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -884,12 +886,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 888 "configure" +#line 890 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:893: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -915,12 +917,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:919: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:921: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:924: checking whether we are using GNU C" >&5 +echo "configure:926: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -929,7 +931,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:933: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:935: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -948,7 +950,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:952: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:954: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -985,7 +987,7 @@ fi V_CCOPT="-O2" else echo $ac_n "checking gcc version""... $ac_c" 1>&6 -echo "configure:989: checking gcc version" >&5 +echo "configure:991: checking gcc version" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_gcc_vers'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1003,19 +1005,19 @@ fi fi else echo $ac_n "checking that $CC handles ansi prototypes""... $ac_c" 1>&6 -echo "configure:1007: checking that $CC handles ansi prototypes" >&5 +echo "configure:1009: checking that $CC handles ansi prototypes" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_cc_ansi_prototypes'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { int frob(int, char *) ; return 0; } EOF -if { (eval echo configure:1019: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1021: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_cc_ansi_prototypes=yes else @@ -1033,21 +1035,21 @@ fi hpux*) echo $ac_n "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)""... $ac_c" 1>&6 -echo "configure:1037: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5 +echo "configure:1039: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5 savedcflags="$CFLAGS" CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS" if eval "test \"`echo '$''{'ac_cv_lbl_cc_hpux_cc_aa'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { int frob(int, char *) ; return 0; } EOF -if { (eval echo configure:1051: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1053: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_cc_hpux_cc_aa=yes else @@ -1091,12 +1093,12 @@ EOF ultrix*) echo $ac_n "checking that Ultrix $CC hacks const in prototypes""... $ac_c" 1>&6 -echo "configure:1095: checking that Ultrix $CC hacks const in prototypes" >&5 +echo "configure:1097: checking that Ultrix $CC hacks const in prototypes" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_cc_const_proto'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { @@ -1104,7 +1106,7 @@ struct a { int b; }; void c(const struct a *) ; return 0; } EOF -if { (eval echo configure:1108: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1110: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_cc_const_proto=yes else @@ -1128,7 +1130,7 @@ EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:1132: checking for inline" >&5 +echo "configure:1134: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1138,7 +1140,7 @@ else for ac_lbl_inline in inline __inline__ __inline do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1164: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_lbl_cc_inline=yes else @@ -1186,13 +1188,13 @@ EOF echo $ac_n "checking for __attribute__""... $ac_c" 1>&6 -echo "configure:1190: checking for __attribute__" >&5 +echo "configure:1192: checking for __attribute__" >&5 if eval "test \"`echo '$''{'ac_cv___attribute__'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -1209,7 +1211,7 @@ foo(void) ; return 0; } EOF -if { (eval echo configure:1213: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1215: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv___attribute__=yes else @@ -1231,12 +1233,12 @@ echo "$ac_t""$ac_cv___attribute__" 1>&6 echo $ac_n "checking for u_int8_t using $CC""... $ac_c" 1>&6 -echo "configure:1235: checking for u_int8_t using $CC" >&5 +echo "configure:1237: checking for u_int8_t using $CC" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_have_u_int8_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1255: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_have_u_int8_t=yes else @@ -1269,12 +1271,12 @@ EOF fi echo $ac_n "checking for u_int16_t using $CC""... $ac_c" 1>&6 -echo "configure:1273: checking for u_int16_t using $CC" >&5 +echo "configure:1275: checking for u_int16_t using $CC" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_have_u_int16_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1293: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_have_u_int16_t=yes else @@ -1307,12 +1309,12 @@ EOF fi echo $ac_n "checking for u_int32_t using $CC""... $ac_c" 1>&6 -echo "configure:1311: checking for u_int32_t using $CC" >&5 +echo "configure:1313: checking for u_int32_t using $CC" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_have_u_int32_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1331: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_have_u_int32_t=yes else @@ -1346,7 +1348,7 @@ EOF fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1350: checking how to run the C preprocessor" >&5 +echo "configure:1352: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1361,13 +1363,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1371: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1373: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1378,13 +1380,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1388: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1390: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1395,13 +1397,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1405: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1407: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1429,17 +1431,17 @@ for ac_hdr in sys/ioccom.h sys/sockio.h ifaddrs.h limits.h netinet/if_ether.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1433: checking for $ac_hdr" >&5 +echo "configure:1435: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1443: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1445: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1468,12 +1470,12 @@ done if test "$GCC" = yes ; then echo $ac_n "checking for ANSI ioctl definitions""... $ac_c" 1>&6 -echo "configure:1472: checking for ANSI ioctl definitions" >&5 +echo "configure:1474: checking for ANSI ioctl definitions" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_gcc_fixincludes'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1498: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_gcc_fixincludes=yes else @@ -1515,12 +1517,12 @@ fi for ac_func in ether_hostton strerror strlcpy do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1519: checking for $ac_func" >&5 +echo "configure:1521: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1549: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1569,7 +1571,7 @@ done echo $ac_n "checking if --disable-protochain option is specified""... $ac_c" 1>&6 -echo "configure:1573: checking if --disable-protochain option is specified" >&5 +echo "configure:1575: checking if --disable-protochain option is specified" >&5 # Check whether --enable-protochain or --disable-protochain was given. if test "${enable_protochain+set}" = set; then enableval="$enable_protochain" @@ -1600,7 +1602,7 @@ if test "${with_pcap+set}" = set; then fi echo $ac_n "checking packet capture type""... $ac_c" 1>&6 -echo "configure:1604: checking packet capture type" >&5 +echo "configure:1606: checking packet capture type" >&5 if test ! -z "$with_pcap" ; then V_PCAP="$withval" elif test -r /dev/bpf0 ; then @@ -1630,8 +1632,132 @@ else fi echo "$ac_t""$V_PCAP" 1>&6 +echo $ac_n "checking for getifaddrs""... $ac_c" 1>&6 +echo "configure:1637: checking for getifaddrs" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getifaddrs'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getifaddrs(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getifaddrs) || defined (__stub___getifaddrs) +choke me +#else +getifaddrs(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1665: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_getifaddrs=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getifaddrs=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getifaddrs`\" = yes"; then + echo "$ac_t""yes" 1>&6 + + # + # We have "getifaddrs()", so we use that to get the list + # + V_FINDALLDEVS=getad + +else + echo "$ac_t""no" 1>&6 + + # + # 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, with just SIOCGIFCONF. + # + echo $ac_n "checking whether we have SIOCGLIFCONF""... $ac_c" 1>&6 +echo "configure:1703: checking whether we have SIOCGLIFCONF" >&5 + if eval "test \"`echo '$''{'ac_cv_lbl_have_siocglifconf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < + #include + #include + #include + #include +int main() { +ioctl(0, SIOCGLIFCONF, (char *)0); +; return 0; } +EOF +if { (eval echo configure:1719: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_lbl_have_siocglifconf=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_lbl_have_siocglifconf=no +fi +rm -f conftest* +fi + + echo "$ac_t""$ac_cv_lbl_have_siocglifconf" 1>&6 + if test $ac_cv_lbl_have_siocglifconf = yes ; then + V_FINDALLDEVS=glifc + else + V_FINDALLDEVS=gifc + fi + ;; + + null) + # + # We can't capture, so we can't open any capture + # devices, so we won't return any interfaces. + # + V_FINDALLDEVS=null + ;; + + *) + # + # 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 + + echo $ac_n "checking if --enable-ipv6 option is specified""... $ac_c" 1>&6 -echo "configure:1635: checking if --enable-ipv6 option is specified" >&5 +echo "configure:1761: checking if --enable-ipv6 option is specified" >&5 # Check whether --enable-ipv6 or --disable-ipv6 was given. if test "${enable_ipv6+set}" = set; then enableval="$enable_ipv6" @@ -1647,7 +1773,7 @@ fi echo "$ac_t""${enable_ipv6-no}" 1>&6 echo $ac_n "checking whether to build optimizer debugging code""... $ac_c" 1>&6 -echo "configure:1651: checking whether to build optimizer debugging code" >&5 +echo "configure:1777: checking whether to build optimizer debugging code" >&5 # Check whether --enable-optimizer-dbg or --disable-optimizer-dbg was given. if test "${enable_optimizer_dbg+set}" = set; then enableval="$enable_optimizer_dbg" @@ -1663,7 +1789,7 @@ fi echo "$ac_t""${enable_optimizer_dbg-no}" 1>&6 echo $ac_n "checking whether to build parser debugging code""... $ac_c" 1>&6 -echo "configure:1667: checking whether to build parser debugging code" >&5 +echo "configure:1793: checking whether to build parser debugging code" >&5 # Check whether --enable-yydebug or --disable-yydebug was given. if test "${enable_yydebug+set}" = set; then enableval="$enable_yydebug" @@ -1685,17 +1811,17 @@ dlpi) do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1689: checking for $ac_hdr" >&5 +echo "configure:1815: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1699: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1825: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1722,7 +1848,7 @@ fi done echo $ac_n "checking for /dev/dlpi device""... $ac_c" 1>&6 -echo "configure:1726: checking for /dev/dlpi device" >&5 +echo "configure:1852: checking for /dev/dlpi device" >&5 if test -c /dev/dlpi ; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF @@ -1733,7 +1859,7 @@ EOF echo "$ac_t""no" 1>&6 dir="/dev/dlpi" echo $ac_n "checking for $dir directory""... $ac_c" 1>&6 -echo "configure:1737: checking for $dir directory" >&5 +echo "configure:1863: checking for $dir directory" >&5 if test -d $dir ; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <&6 -echo "configure:1752: checking Linux kernel version" >&5 +echo "configure:1878: checking Linux kernel version" >&5 if test "$cross_compiling" = yes; then if eval "test \"`echo '$''{'ac_cv_linux_vers'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1773,12 +1899,12 @@ fi { echo "configure: error: version 2 or higher required; see the INSTALL doc for more info" 1>&2; exit 1; } fi echo $ac_n "checking if if_packet.h has tpacket_stats defined""... $ac_c" 1>&6 -echo "configure:1777: checking if if_packet.h has tpacket_stats defined" >&5 +echo "configure:1903: checking if if_packet.h has tpacket_stats defined" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_tpacket_stats'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -1786,7 +1912,7 @@ int main() { struct tpacket_stats stats ; return 0; } EOF -if { (eval echo configure:1790: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1916: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_tpacket_stats=yes else @@ -1815,7 +1941,7 @@ null) esac echo $ac_n "checking whether we have /proc/net/dev""... $ac_c" 1>&6 -echo "configure:1819: checking whether we have /proc/net/dev" >&5 +echo "configure:1945: checking whether we have /proc/net/dev" >&5 if test -r /proc/net/dev ; then ac_cv_lbl_proc_net_dev=yes else @@ -1849,7 +1975,7 @@ 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 $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1853: checking for $ac_word" >&5 +echo "configure:1979: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_V_LEX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1883,7 +2009,7 @@ test -n "$V_LEX" || V_LEX="lex" if test "$V_LEX" = flex ; then # The -V flag was added in 2.4 echo $ac_n "checking for flex 2.4 or higher""... $ac_c" 1>&6 -echo "configure:1887: checking for flex 2.4 or higher" >&5 +echo "configure:2013: checking for flex 2.4 or higher" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_flex_v24'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1909,7 +2035,7 @@ 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 $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1913: checking for $ac_word" >&5 +echo "configure:2039: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_V_YACC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1956,7 +2082,7 @@ 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 $ac_n "checking for capable lex""... $ac_c" 1>&6 -echo "configure:1960: checking for capable lex" >&5 +echo "configure:2086: checking for capable lex" >&5 if eval "test \"`echo '$''{'tcpdump_cv_capable_lex'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2007,19 +2133,19 @@ EOF sinix*) echo $ac_n "checking if SINIX compiler defines sinix""... $ac_c" 1>&6 -echo "configure:2011: checking if SINIX compiler defines sinix" >&5 +echo "configure:2137: checking if SINIX compiler defines sinix" >&5 if eval "test \"`echo '$''{'ac_cv_cc_sinix_defined'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2149: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cc_sinix_defined=yes else @@ -2051,7 +2177,7 @@ esac # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2055: checking for $ac_word" >&5 +echo "configure:2181: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2119,12 +2245,12 @@ EOF fi echo $ac_n "checking if sockaddr struct has sa_len member""... $ac_c" 1>&6 -echo "configure:2123: checking if sockaddr struct has sa_len member" >&5 +echo "configure:2249: checking if sockaddr struct has sa_len member" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_sockaddr_has_sa_len'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -2133,7 +2259,7 @@ int main() { u_int i = sizeof(((struct sockaddr *)0)->sa_len) ; return 0; } EOF -if { (eval echo configure:2137: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2263: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_sockaddr_has_sa_len=yes else @@ -2153,13 +2279,48 @@ EOF fi +echo $ac_n "checking if sockaddr_storage struct exists""... $ac_c" 1>&6 +echo "configure:2284: checking if sockaddr_storage struct exists" >&5 + if eval "test \"`echo '$''{'ac_cv_lbl_has_sockaddr_storage'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +# include +int main() { +u_int i = sizeof (struct sockaddr_storage) +; return 0; } +EOF +if { (eval echo configure:2298: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_lbl_has_sockaddr_storage=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_lbl_has_sockaddr_storage=no +fi +rm -f conftest* +fi + + echo "$ac_t""$ac_cv_lbl_has_sockaddr_storage" 1>&6 + if test $ac_cv_lbl_has_sockaddr_storage = yes ; then + cat >> confdefs.h <<\EOF +#define HAVE_SOCKADDR_STORAGE 1 +EOF + + fi + echo $ac_n "checking if dl_hp_ppa_info_t struct has dl_module_id_1 member""... $ac_c" 1>&6 -echo "configure:2158: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5 +echo "configure:2319: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -2169,7 +2330,7 @@ int main() { u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1) ; return 0; } EOF -if { (eval echo configure:2173: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2334: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes else @@ -2190,7 +2351,7 @@ EOF fi echo $ac_n "checking if unaligned accesses fail""... $ac_c" 1>&6 -echo "configure:2194: checking if unaligned accesses fail" >&5 +echo "configure:2355: checking if unaligned accesses fail" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_unaligned_fail'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2263,6 +2424,7 @@ 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: @@ -2275,7 +2437,7 @@ ln -s ${srcdir}/bpf/net net # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:2279: checking for a BSD compatible install" >&5 +echo "configure:2441: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2487,6 +2649,7 @@ s%@RANLIB@%$RANLIB%g s%@V_CCOPT@%$V_CCOPT%g s%@V_INCLS@%$V_INCLS%g s%@V_PCAP@%$V_PCAP%g +s%@V_FINDALLDEVS@%$V_FINDALLDEVS%g s%@V_RANLIB@%$V_RANLIB%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g diff --git a/configure.in b/configure.in index 48daa88..9a2db7b 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.95 2002-06-28 10:34:36 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.96 2002-07-27 18:45:35 guy Exp $ (LBL) dnl dnl Copyright (c) 1994, 1995, 1996, 1997 dnl The Regents of the University of California. All rights reserved. @@ -6,7 +6,7 @@ dnl dnl Process this file with autoconf to produce a configure script. dnl -AC_REVISION($Revision: 1.95 $) +AC_REVISION($Revision: 1.96 $) AC_INIT(pcap.c) AC_CANONICAL_SYSTEM @@ -87,6 +87,67 @@ else fi AC_MSG_RESULT($V_PCAP) +dnl +dnl Now figure out how we get a list of interfaces and addresses. +dnl +AC_CHECK_FUNC(getifaddrs,[ + # + # We have "getifaddrs()", so we use that to get the list + # + V_FINDALLDEVS=getad +],[ + # + # 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, 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 + ;; + + null) + # + # We can't capture, so we can't open any capture + # devices, so we won't return any interfaces. + # + V_FINDALLDEVS=null + ;; + + *) + # + # 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]) + 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 @@ -232,6 +293,8 @@ 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 @@ -243,6 +306,7 @@ AC_SUBST(V_CCOPT) AC_SUBST(V_INCLS) AC_SUBST(V_LEX) AC_SUBST(V_PCAP) +AC_SUBST(V_FINDALLDEVS) AC_SUBST(V_RANLIB) AC_SUBST(V_YACC) diff --git a/fad-getad.c b/fad-getad.c new file mode 100644 index 0000000..7ffd484 --- /dev/null +++ b/fad-getad.c @@ -0,0 +1,154 @@ +/* -*- 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[] = + "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.1 2002-07-27 18:46:21 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 "getifaddrs()". + */ +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + pcap_if_t *devlist = NULL; + struct ifaddrs *ifap, *ifa; + struct sockaddr *broadaddr, *dstaddr; + int ret = 0; + + /* + * 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_broadaddr" may be non-null even on + * non-broadcast interfaces; "ifa_dstaddr" + * was, on at least one FreeBSD 4.1 system, + * non-null on a non-point-to-point + * interface. + */ + if (ifa->ifa_flags & IFF_BROADCAST) + broadaddr = ifa->ifa_broadaddr; + else + broadaddr = NULL; + if (ifa->ifa_flags & IFF_POINTOPOINT) + dstaddr = ifa->ifa_dstaddr; + else + dstaddr = NULL; + + /* + * Add information for this address to the list. + */ + if (add_addr_to_iflist(&devlist, ifa->ifa_name, + ifa->ifa_flags, ifa->ifa_addr, ifa->ifa_netmask, + broadaddr, dstaddr, 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); +} diff --git a/fad-gifc.c b/fad-gifc.c new file mode 100644 index 0000000..69da023 --- /dev/null +++ b/fad-gifc.c @@ -0,0 +1,471 @@ +/* -*- 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[] = + "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.1 2002-07-27 18:46:21 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 + +#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 */ + +/* + * 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. + * + * GNU libc uses neither scheme, but has an "SA_LEN()" macro that + * determines the size based on the address family. + */ +#ifndef SA_LEN +#ifdef HAVE_SOCKADDR_SA_LEN +#define SA_LEN(addr) ((addr)->sa_len) +#else /* HAVE_SOCKADDR_SA_LEN */ +#ifdef HAVE_SOCKADDR_STORAGE +#define SA_LEN(addr) (sizeof (struct sockaddr_storage)) +#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 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; + struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; + struct sockaddr *netmask, *broadaddr, *dstaddr; + 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 get the entire interface list or fail to get it 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) + break; + free(buf); + buf_size *= 2; + } + + ifrp = (struct ifreq *)buf; + ifend = (struct ifreq *)(buf + ifc.ifc_len); + + for (; ifrp < ifend; ifrp = ifnext) { + n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name); + if (n < sizeof(*ifrp)) + ifnext = ifrp + 1; + else + ifnext = (struct ifreq *)((char *)ifrp + n); + + /* + * 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; + } 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; + + /* + * 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; + } 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; + } 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.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; + } 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; + } else + dstaddr = NULL; + + /* + * Add information for this address to the list. + */ + if (add_addr_to_iflist(&devlist, ifrp->ifr_name, + ifrflags.ifr_flags, &ifrp->ifr_addr, + netmask, broadaddr, dstaddr, 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); +} diff --git a/fad-glifc.c b/fad-glifc.c new file mode 100644 index 0000000..76c25fe --- /dev/null +++ b/fad-glifc.c @@ -0,0 +1,322 @@ +/* -*- 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[] = + "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.1 2002-07-27 18:46:21 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; + 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; + + /* + * 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; + + /* + * 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, + netmask, broadaddr, dstaddr, 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); +} diff --git a/fad-null.c b/fad-null.c new file mode 100644 index 0000000..fec53cf --- /dev/null +++ b/fad-null.c @@ -0,0 +1,65 @@ +/* -*- 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[] = + "@(#) $Header: /tcpdump/master/libpcap/fad-null.c,v 1.1 2002-07-27 18:46:21 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); +} diff --git a/inet.c b/inet.c index a7c276f..75ecc12 100644 --- a/inet.c +++ b/inet.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.48 2002-07-11 09:06:35 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.49 2002-07-27 18:45:35 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -97,8 +97,9 @@ struct rtentry; /* declarations in */ * 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, and some might use - * the new BSD scheme. + * 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. * * GNU libc uses neither scheme, but has an "SA_LEN()" macro that * determines the size based on the address family. @@ -107,7 +108,11 @@ struct rtentry; /* declarations in */ #ifdef HAVE_SOCKADDR_SA_LEN #define SA_LEN(addr) ((addr)->sa_len) #else /* HAVE_SOCKADDR_SA_LEN */ +#ifdef HAVE_SOCKADDR_STORAGE +#define SA_LEN(addr) (sizeof (struct sockaddr_storage)) +#else /* HAVE_SOCKADDR_STORAGE */ #define SA_LEN(addr) (sizeof (struct sockaddr)) +#endif /* HAVE_SOCKADDR_STORAGE */ #endif /* HAVE_SOCKADDR_SA_LEN */ #endif /* SA_LEN */ @@ -317,7 +322,7 @@ add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, char *name, return (0); } -static int +int add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags, struct sockaddr *addr, struct sockaddr *netmask, struct sockaddr *broadaddr, struct sockaddr *dstaddr, char *errbuf) @@ -436,460 +441,6 @@ pcap_add_if(pcap_if_t **devlist, char *name, u_int flags, errbuf)); } -/* - * 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. - */ -#ifdef HAVE_IFADDRS_H -int -pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) -{ - pcap_if_t *devlist = NULL; - struct ifaddrs *ifap, *ifa; - struct sockaddr *broadaddr, *dstaddr; - int ret = 0; - - /* - * 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_broadaddr" may be non-null even on - * non-broadcast interfaces; "ifa_dstaddr" - * was, on at least one FreeBSD 4.1 system, - * non-null on a non-point-to-point - * interface. - */ - if (ifa->ifa_flags & IFF_BROADCAST) - broadaddr = ifa->ifa_broadaddr; - else - broadaddr = NULL; - if (ifa->ifa_flags & IFF_POINTOPOINT) - dstaddr = ifa->ifa_dstaddr; - else - dstaddr = NULL; - - /* - * Add information for this address to the list. - */ - if (add_addr_to_iflist(&devlist, ifa->ifa_name, - ifa->ifa_flags, ifa->ifa_addr, ifa->ifa_netmask, - broadaddr, dstaddr, 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); -} -#else /* HAVE_IFADDRS_H */ -#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 */ - -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; - struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; - struct sockaddr *netmask, *broadaddr, *dstaddr; - 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 get the entire interface list or fail to get it 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) - break; - free(buf); - buf_size *= 2; - } - - ifrp = (struct ifreq *)buf; - ifend = (struct ifreq *)(buf + ifc.ifc_len); - - for (; ifrp < ifend; ifrp = ifnext) { - n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name); - if (n < sizeof(*ifrp)) - ifnext = ifrp + 1; - else - ifnext = (struct ifreq *)((char *)ifrp + n); - - /* - * 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; - } 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; - - /* - * 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; - } 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; - } 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.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; - } 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; - } else - dstaddr = NULL; - - /* - * Add information for this address to the list. - */ - if (add_addr_to_iflist(&devlist, ifrp->ifr_name, - ifrflags.ifr_flags, &ifrp->ifr_addr, - netmask, broadaddr, dstaddr, 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); -} -#endif /* HAVE_IFADDRS_H */ /* * Free a list of interfaces. diff --git a/pcap-int.h b/pcap-int.h index d6a49d3..7b86969 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -30,7 +30,7 @@ * 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.35 2002-07-11 09:06:38 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.36 2002-07-27 18:45:35 guy Exp $ (LBL) */ #ifndef pcap_int_h @@ -203,6 +203,8 @@ int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); * "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 **, char *, u_int, struct sockaddr *, + struct sockaddr *, struct sockaddr *, struct sockaddr *, char *); int pcap_add_if(pcap_if_t **, char *, u_int, const char *, char *);