From 4089483e6ab31e8a899928d259a4b11535519124 Mon Sep 17 00:00:00 2001 From: pdw <> Date: Fri, 6 Jun 2003 22:42:35 +0000 Subject: [PATCH] Solaris/autoconf patch from Jonathan Abbey --- AUTHORS | 10 + CHANGES | 120 +++-- COPYING | 7 +- ChangeLog | 10 + Makefile.am | 9 +- NEWS | 3 + README | 15 +- addrs_dlpi.c | 395 ++++++++++++++ addrs_ioctl.c | 93 ++++ configure.in | 61 ++- dlcommon.c | 1365 +++++++++++++++++++++++++++++++++++++++++++++++++ dlcommon.h | 37 ++ iftop.c | 79 ++- options.c | 10 + options.h | 1 + 15 files changed, 2089 insertions(+), 126 deletions(-) create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 100644 NEWS create mode 100644 addrs_dlpi.c create mode 100644 addrs_ioctl.c create mode 100644 dlcommon.c create mode 100644 dlcommon.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..aeb660c --- /dev/null +++ b/AUTHORS @@ -0,0 +1,10 @@ +Another file that automake insists on. + +Written by + +Paul Warren, pdw@ex-parrot.com +Chris Lightfoot, chris@ex-parrot.com + +Mangled for Solaris by + +Jonathan Abbey, jonabbey@ganymeta.org \ No newline at end of file diff --git a/CHANGES b/CHANGES index aa430ce..7774b29 100644 --- a/CHANGES +++ b/CHANGES @@ -1,89 +1,109 @@ Change log for iftop $Id$ +0.13 + +* Fixed configure.in to properly specify libraries without the leading -l +* Separated the IP/ethernet identifying routine from iftop.c into addrs_ioctl.c +* Added addrs_dlpi.c, dlcommon.c, dlcommon.h to support the STREAMS DataLink + Programming Interface on Solaris +* Hacked options.h, options.c, iftop.c to enable promiscuous_but_choosy mode + which runs the interface in promiscuous mode but filters out non-broadcast + packets not addressed to or from the interface +* Added NEWS, AUTHORS, ChangeLog +* Improved interface auto-detect logic in iftop.c +* Fixed configure.in to not overload prefix in the pcap test section + Jonathan Abbey + 0.12 21/05/03 -Added 1-line display options ("t") -Added display scrolling ("j", "k") -Fixed code for obtaining hardware address (on Linux at least) -Added IP-based direction assignment +* Added 1-line display options ("t") +* Added display scrolling ("j", "k") +* Fixed code for obtaining hardware address (on Linux at least) +* Added IP-based direction assignment 0.11 08/01/03 -Added support for token ring networks -Token ring network direction determination +* Added support for token ring networks +* Token ring network direction determination Martin Garton -Added autoconf/automake build system -Improved network interface auto selection + +* Added autoconf/automake build system +* Improved network interface auto selection 0.10 29/10/02 -User selectable sort criteria -On-the-fly filter code changes -Shell escape -Alternative resolver back-ends -Improved totals display -Added regexp based screen filtering -Fixed pause functionality -Change option names to be more like tcpdump +* User selectable sort criteria +* On-the-fly filter code changes +* Shell escape +* Alternative resolver back-ends +* Improved totals display +* Added regexp based screen filtering +* Fixed pause functionality +* Change option names to be more like tcpdump 0.9 22/10/02 -Now works on FreeBSD -Added service resolution toggle ("R") -Added on-line help ("h") -More fixes to rate display -Improved interface selection (excludes lo:* and vmnet*) -Added bandwidth-in-bytes option. +* Now works on FreeBSD +* Added service resolution toggle ("R") +* Added on-line help ("h") +* More fixes to rate display +* Improved interface selection (excludes lo:* and vmnet*) +* Added bandwidth-in-bytes option. 0.8 17/10/02 -Added support for displaying port numbers -Minor fixes to rate display -Minor fix to netmask handling (specifying /32 was broken) -Updated RPM spec file - Iain Lea -Added pause functionality (P) -Changed behaviour of source/dest traffic aggregation +* Added support for displaying port numbers +* Minor fixes to rate display +* Minor fix to netmask handling (specifying /32 was broken) + +* Updated RPM spec file + Iain Lea + +* Added pause functionality (P) +* Changed behaviour of source/dest traffic aggregation 0.7 02/10/02 -Fixed missing sll.h file. +* Fixed missing sll.h file. 0.6 28/08/02 -Fixed segfault bug affecting some systems -Added support for Linux cooked sockets - Michael Bergbauer +* Fixed segfault bug affecting some systems + +* Added support for Linux cooked sockets + Michael Bergbauer 0.5 26/08/02 -Added support for monitoring PPP interfaces -Converted longs to double longs in various places to avoid overflow problems -Minor bug fixes (usage messages, exit on error) -Improved selection of default interface when none specified +* Added support for monitoring PPP interfaces +* Converted longs to double longs in various places to avoid overflow problems +* Minor bug fixes (usage messages, exit on error) +* Improved selection of default interface when none specified 0.4 16/04/02 -No code changes -Added RPM spec file - Riku Meskanen -Fixes to "make install" - Steve Baker +* No code changes + +* Added RPM spec file + Riku Meskanen + +* Fixes to "make install" + Steve Baker 0.3 13/04/02 -Fixed segfault bug. -Added src/dest aggregation. +* Fixed segfault bug. +* Added src/dest aggregation. 0.2 02/04/02 -Added -n option to analyse traffic flows across a network boundary. -Added cumulative traffic totals. -Graphs now optional. -UI more responsive to key presses. -Auto-sizing bar graph scale. +* Added -n option to analyse traffic flows across a network boundary. +* Added cumulative traffic totals. +* Graphs now optional. +* UI more responsive to key presses. +* Auto-sizing bar graph scale. 0.1 29/3/02 -First release. +* First release. diff --git a/COPYING b/COPYING index a52b16e..d60c31a 100644 --- a/COPYING +++ b/COPYING @@ -1,9 +1,8 @@ - GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -292,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - Copyright (C) 19yy + Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -314,7 +313,7 @@ Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..8874e6a --- /dev/null +++ b/ChangeLog @@ -0,0 +1,10 @@ +2003-06-04 Jonathan Abbey + * Fixed configure.in to properly specify libraries without the leading -l + * Separated the IP/ethernet identifying routine from iftop.c into addrs_ioctl.c + * Added addrs_dlpi.c, dlcommon.c, dlcommon.h to support the STREAMS DataLink Programming Interface on Solaris + * Hacked options.h, options.c, iftop.c to enable promiscuous_but_choosy mode which runs + the interface in promiscuous mode but filters out non-broadcast packets not addressed to or from the interface + * Added NEWS, AUTHORS, ChangeLog + * Improved interface auto-detect logic in iftop.c + * Fixed configure.in to not overload prefix in the pcap test section + \ No newline at end of file diff --git a/Makefile.am b/Makefile.am index 8783899..9a78924 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,12 +14,13 @@ sbin_PROGRAMS = iftop iftop_SOURCES = addr_hash.c edline.c hash.c iftop.c ns_hash.c \ options.c resolver.c screenfilter.c serv_hash.c \ - sorted_list.c threadprof.c ui.c util.c + sorted_list.c threadprof.c ui.c util.c \ + addrs_ioctl.c addrs_dlpi.c dlcommon.c noinst_HEADERS = addr_hash.h ether.h ethertype.h extract.h hash.h iftop.h \ integers.h ip.h llc.h ns_hash.h options.h resolver.h \ screenfilter.h serv_hash.h sll.h sorted_list.h tcp.h \ - threadprof.h token.h ui.h + threadprof.h token.h ui.h dlcommon.h man_MANS = iftop.8 @@ -30,8 +31,8 @@ iftop.cat: iftop.8 ## These need to be distributed along with configure: -EXTRA_DIST = bootstrap README CHANGES COPYING INSTALL TODO Makefile.OLD \ - $(man_MANS) iftop.cat +EXTRA_DIST = bootstrap README ChangeLog AUTHORS COPYING INSTALL TODO \ + Makefile.OLD $(man_MANS) iftop.cat MAINTERCLEANFILES = Makefile.in aclocal.m4 configure configuration.h.in \ stamp-h.in diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..bd483e2 --- /dev/null +++ b/NEWS @@ -0,0 +1,3 @@ +Hm, automake insists on there being a NEWS file in place. + +So, here's one, for the time being. \ No newline at end of file diff --git a/README b/README index 153d8ec..6db6262 100644 --- a/README +++ b/README @@ -26,10 +26,17 @@ option to configure. Solaris: -On Solaris, libpcap does not capture outgoing packets unless it is run on an -interface in promiscuous mode. Therefore, you will need to use the -p option -to iftop to get sensible results. Cf. - http://www.tcpdump.org/lists/workers/2002/02/msg00010.html +On Solaris, iftop has to run in promiscuous mode in order to capture +outgoing packets. iftop autoconfigures to run in promiscuous mode on +Solaris, but will filter out non-broadcast packets which are not +addressed to or from localhost. On Solaris, the -p option merely +disables that filter. + +If you have some other sort of system that behaves like Solaris in +needing promiscuous mode, you can pass --enable-default-promiscuous to +configure to enable this behavior. + +Cf. http://www.tcpdump.org/lists/workers/2002/02/msg00010.html The version of curses distributed with Solaris may not be sufficient for iftop's needs. You will probably need ncurses or similar. diff --git a/addrs_dlpi.c b/addrs_dlpi.c new file mode 100644 index 0000000..3c362d4 --- /dev/null +++ b/addrs_dlpi.c @@ -0,0 +1,395 @@ +/* + * addrs_dlpi.c: + * + * Provides the get_addrs_dlpi() function for use on systems that require + * the use of the System V STREAMS DataLink Programming Interface for + * acquiring low-level ethernet information about interfaces. + * + * Like Solaris. + * + */ + +#include "config.h" + +#ifdef HAVE_DLPI + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "dlcommon.h" + +extern char *split_dname(char *device, int *unitp); +extern char *strncpy2(char *dest, char *src, int n); +extern char *strncat2(char *dest, char *src, int n); + +/* + * This function identifies the IP address and ethernet address for the interface + * specified + * + * This function returns -1 on catastrophic failure, or a bitwise OR of the + * following values: + * + * 1 - Was able to get the ethernet address + * 2 - Was able to get the IP address + * + * This function should return 3 if all information was found + */ + +int +get_addrs_dlpi(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr) +{ + int got_hw_addr = 0; + int got_ip_addr = 0; + + int fd; + long buf[MAXDLBUF]; /* long aligned */ + union DL_primitives *dlp; + + char *cp; + int unit_num = 0; + int sap = 0; + + char *devname = NULL; + char *devname2 = NULL; + char fulldevpath[256]; + + struct ifreq ifr = {}; + + /* -- */ + + memset(if_hw_addr, 0, 6); + + // we want to be able to process either a fully qualified /dev/ge0 + // type interface definition, or just ge0. + + if (strncmp(interface, "/dev/", strlen("/dev/")) == 0) { + devname = interface + strlen("/dev/"); + } else { + devname = interface; + } + + strncpy2(fulldevpath, "/dev/", sizeof(fulldevpath)-1); + cp = strncat2(fulldevpath, interface, sizeof(fulldevpath)); + + if (strlen(cp) != 0) { + fprintf(stderr, "device name buffer overflow %s\n", fulldevpath); + return -1; + } + + fprintf(stderr,"if: %s\n", devname); + + // on Solaris, even though we are wanting to talk to ethernet device + // ge0, we have to open /dev/ge, then bind to unit 0. Dupe our + // full path, then identify and cut off the unit number + + devname2 = strdup(fulldevpath); + + cp = split_dname(devname2, &unit_num); + + if (cp == NULL) { + free(devname2); + return -1; + } else { + *cp = '\0'; /* null terminate devname2 right before numeric extension */ + } + + // devname2 should now be something akin to /dev/ge. Try to open + // it, and if it fails, fall back to the full /dev/ge0. + + if ((fd = open(devname2, O_RDWR)) < 0) { + if (errno != ENOENT) { + fprintf(stderr, "Couldn't open %s\n", devname2); + free(devname2); + return -1; + } else { + if ((fd = open(fulldevpath, O_RDWR)) < 0) { + fprintf(stderr, "Couldn't open %s\n", fulldevpath); + free(devname2); + return -1; + } + } + } + + free(devname2); + devname2 = NULL; + + /* Use the dlcommon functions to get access to the DLPI information for this + * interface. All of these functions exit() out on failure + */ + + dlp = (union DL_primitives*) buf; + + /* + * DLPI attach to our low-level device + */ + + dlattachreq(fd, unit_num); + dlokack(fd, buf); + + /* + * DLPI bind + */ + + dlbindreq(fd, sap, 0, DL_CLDLS, 0, 0); + dlbindack(fd, buf); + + /* + * DLPI DL_INFO_REQ + */ + + dlinforeq(fd); + dlinfoack(fd, buf); + + /* + printdlprim(dlp); // uncomment this to dump out info from DLPI + */ + + if (dlp->info_ack.dl_addr_length + dlp->info_ack.dl_sap_length == 6) { + memcpy(if_hw_addr, + OFFADDR(dlp, dlp->info_ack.dl_addr_offset), + dlp->info_ack.dl_addr_length); + got_hw_addr = 1; + } else { + fprintf(stderr, "Error, bad length for hardware interface %s -- %d\n", + interface, + dlp->info_ack.dl_addr_length); + close(fd); + return -1; + } + + close(fd); + + /* Get the IP address of the interface */ + +#ifdef SIOCGIFADDR + + fd = socket(PF_INET, SOCK_DGRAM, 0); /* any sort of IP socket will do */ + + strncpy(ifr.ifr_name, interface, IFNAMSIZ); + + (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET; + + if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) { + fprintf(stderr, "Error getting IP address for interface: %s\n", "ge0"); + perror("ioctl(SIOCGIFADDR)"); + close(fd); + return -1; + } + else { + memcpy(if_ip_addr, &((*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr), sizeof(struct in_addr)); + got_ip_addr = 2; + } +#else + fprintf(stderr, "Cannot obtain IP address on this platform\n"); +#endif + + close(fd); + + return got_hw_addr + got_ip_addr; +} + +/* + * 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. + */ +char * +split_dname(char *device, int *unitp) +{ + char *cp; + char *eos; + int unit; + + /* -- */ + + /* + * Look for a number at the end of the device name string. + */ + + cp = device + strlen(device) - 1; + if (*cp < '0' || *cp > '9') { + fprintf(stderr, "%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--; + + unit = (int) strtol(cp, &eos, 10); + if (*eos != '\0') { + fprintf(stderr, "%s bad unit number", device); + return (NULL); + } + *unitp = unit; + return (cp); +} + +/*------------------------------------------------------------------------------ + strncpy2() + +strncpy2() is like strncpy(), except that strncpy2() will always +insure that the buffer is null terminated. strncpy() will not +NULL terminate the destination buffer if the string is +characters long or longer, not counting the terminating NULL character. + + STRNCPY2() IS NOT A COMPATIBLE REPLACEMENT FOR STRNCPY()!! + +There are two reasons to use strncpy2(). + +The first reason is to guarantee that buffer's bounds are not +violated. In this case, should be the size of the buffer +minus one. + +i.e., + +char tempstring[MAXLINE]; + +strncpy2(tempstring, my_own_string, MAXLINE - 1); + +The second reason is to copy a specific number of characters from + to . In this case, should be the number of characters +you want to transfer, not including the terminating NULL character. + +The following example copies "abc" into tempstring, and NULL +terminates it. + +char tempstring[MAXLINE]; + +strncpy2(tempstring, "abcdef123", 3); + +strncpy2() returns a pointer to the first character in that was +not copied to . If all of was copied to , +strncpy2() will return a pointer to the NULL character terminating the + string. + +------------------------------------------------------------------------------*/ +char * +strncpy2(char *dest, char *src, int n) +{ + int + i = 0; + + char + *char_ptr; + + /* -- */ + + if ((!dest) || (!src)) + return(src); + + char_ptr = dest; + + while ((i++ < n) && *src) + *char_ptr++ = *src++; + + *char_ptr = '\0'; + + return(src); +} + +/*------------------------------------------------------------------------------ + strncat2() + +Similar to strncat except that is the size of the buffer +(INCLUDING SPACE FOR THE TRAILING NULL CHAR), NOT the number of +characters to add to the buffer. + + STRNCAT2() IS NOT A COMPATIBLE REPLACEMENT FOR STRNCAT()! + +strncat2() always guarantees that the will be null terminated, and that +the buffer limits will be honored. strncat2() will not write even one +byte beyond the end of the buffer. + +strncat2() concatenates up to - strlen() characters from + to . + +So if the buffer has a size of 20 bytes (including trailing NULL), +and contains a 19 character string, nothing will be done to +. + +If the string in is longer than characters upon entry to +strncat2(), will be truncated after the th character. + +strncat2() returns a pointer to the first character in the src buffer that +was not copied into dest.. so if strncat2() returns a non-zero character, +string truncation occurred in the concat operation. + +------------------------------------------------------------------------------*/ +char * +strncat2(char *dest, char *src, int n) +{ + int + i = 0; + + char + *dest_ptr, + *src_ptr; + + /* -- */ + + if (!dest || !src) + return NULL; + + dest_ptr = dest; + src_ptr = src; + + /* i = 0 */ + + while ((i < (n-1)) && *dest_ptr) + { + i++; + dest_ptr++; + } + + /* i is the number of characters in dest before the concatenation + operation.. a number between 0 and n-1 */ + + while ((i++ < (n-1)) && *src_ptr) + *dest_ptr++ = *src_ptr++; + + /* i is the number of characters in dest after the concatenation + operation, or n if the concat operation got truncated.. a number + between 0 and n + + We need to check src_ptr here because i will be equal to n if + was full before the concatenation operation started (which + effectively causes instant truncation even if the string is + empty.. + + We could just test src_ptr here, but that would report + a string truncation if was empty, which we don't + necessarily want. */ + + if ((i == n) && *src_ptr) + { + // we could log truncation here + } + + *dest_ptr = '\0'; + + /* should point to a non-empty substring only if the concatenation + operation got truncated. + + If src_ptr points to an empty string, the operation always + succeeded, either due to an empty or because of + sufficient room in . */ + + return(src_ptr); +} + +#endif /* HAVE_DLPI */ diff --git a/addrs_ioctl.c b/addrs_ioctl.c new file mode 100644 index 0000000..b2f68e7 --- /dev/null +++ b/addrs_ioctl.c @@ -0,0 +1,93 @@ +/* + * addrs_ioctl.c: + * + * Provides the get_addrs_ioctl() function for use on systems that + * support a simple socket ioctl for acquiring low-level ethernet + * information about interfaces. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "iftop.h" + +/* + * This function identifies the IP address and ethernet address for the requested + * interface + * + * This function returns -1 on catastrophic failure, or a bitwise OR of the + * following values: + * + * 1 - Was able to get the ethernet address + * 2 - Was able to get the IP address + * + * This function should return 3 if all information was found + */ + +int +get_addrs_ioctl(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr) +{ + int s; + struct ifreq ifr = {}; + int got_hw_addr = 0; + int got_ip_addr = 0; + + /* -- */ + + s = socket(PF_INET, SOCK_DGRAM, 0); /* any sort of IP socket will do */ + + if (s == -1) { + perror("socket"); + return -1; + } + + fprintf(stderr,"if: %s\n", interface); + + memset(if_hw_addr, 0, 6); + strncpy(ifr.ifr_name, interface, IFNAMSIZ); + +#ifdef SIOCGIFHWADDR + if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { + fprintf(stderr, "Error getting hardware address for interface: %s\n", interface); + perror("ioctl(SIOCGIFHWADDR)"); + close(s); + return -1; + } + else { + memcpy(if_hw_addr, ifr.ifr_hwaddr.sa_data, 6); + got_hw_addr = 1; + } +#else + fprintf(stderr, "Cannot obtain hardware address on this platform\n"); +#endif + + /* Get the IP address of the interface */ +#ifdef SIOCGIFADDR + (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET; + if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { + fprintf(stderr, "Error getting IP address for interface: %s\n", interface); + perror("ioctl(SIOCGIFADDR)"); + close(s); + return -1; + } + else { + memcpy(if_ip_addr, &((*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr), sizeof(struct in_addr)); + got_ip_addr = 2; + } +#else + fprintf(stderr, "Cannot obtain IP address on this platform\n"); +#endif + + close(s); + + return got_hw_addr + got_ip_addr; +} diff --git a/configure.in b/configure.in index f62c767..570851a 100644 --- a/configure.in +++ b/configure.in @@ -15,9 +15,13 @@ dnl Boilerplate configuration dnl AC_INIT(iftop.c) + AC_CONFIG_AUX_DIR(config) + +AC_CANONICAL_SYSTEM + AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(iftop, "0.12") +AM_INIT_AUTOMAKE(iftop, "0.13pre1") AC_DEFINE_UNQUOTED(IFTOP_VERSION, "$VERSION", [The iftop version number]) @@ -60,6 +64,12 @@ AC_C_CONST AC_TYPE_SIZE_T AC_HEADER_TIME +dnl +dnl Are we on a system that uses the STREAMS low-level DLPI interface? +dnl + +AC_CHECK_HEADER([sys/dlpi.h],[AC_DEFINE([HAVE_DLPI],1,[Are we running on a STREAMS system with DLPI?])]) + dnl Checks for library functions. AC_CHECK_FUNCS(regcomp select strdup strerror strspn) @@ -68,8 +78,8 @@ AC_SEARCH_LIBS(log, m) AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname)] ) -AC_SEARCH_LIBS(inet_aton, [-lsocket -lnsl]) -AC_SEARCH_LIBS(inet_pton, [-lsocket -lnsl]) +AC_SEARCH_LIBS(inet_aton, [socket nsl]) +AC_SEARCH_LIBS(inet_pton, [socket nsl]) AC_CHECK_FUNCS(inet_aton inet_pton) dnl @@ -143,7 +153,7 @@ dnl but that's probably not available on typical machines. if test x$resolver = xnetdb ; then dnl Best possibility is getnameinfo. use_getnameinfo=0 - AC_SEARCH_LIBS(getnameinfo, [-lnsl], [use_getnameinfo=1]) + AC_SEARCH_LIBS(getnameinfo, [nsl], [use_getnameinfo=1]) dnl XXX For the moment, don't use getnameinfo, since it isn't actually dnl thread safe on, e.g., NetBSD. @@ -154,7 +164,7 @@ if test x$resolver = xnetdb ; then AC_DEFINE(USE_GETNAMEINFO, 1, [use getnameinfo for name resolution]) else dnl Now see if we can use gethostbyaddr_r. - AC_SEARCH_LIBS(gethostbyaddr_r, [-lnsl], , [resolver=netdb_1thread]) + AC_SEARCH_LIBS(gethostbyaddr_r, [nsl], , [resolver=netdb_1thread]) dnl Still want gethostbyaddr_r.... if test x$resolver = xnetdb ; then @@ -195,7 +205,7 @@ dnl machine had a working gethostbyaddr_r, the user wouldn't be pissing about dnl with ARES. if test x$resolver = xares ; then dnl See if ares is to hand.... - AC_SEARCH_LIBS(ares_init, [-lares], [ + AC_SEARCH_LIBS(ares_init, [ares], [ AC_DEFINE(USE_ARES, 1, [use ARES for name resolution]) ], [ dnl no ares @@ -206,7 +216,7 @@ fi dnl Ugh. gethostbyaddr. if test x$resolver = xnetdb_1thread ; then - AC_SEARCH_LIBS(gethostbyaddr, [-lnsl], , [ + AC_SEARCH_LIBS(gethostbyaddr, [nsl], , [ AC_MSG_ERROR([not even gethostbyaddr is available What sort of UNIX system is this, anyway?]) ] @@ -232,15 +242,15 @@ fi AC_MSG_CHECKING([where to find pcap.h]) foundpcaph=0 oldCPPFLAGS=$CPPFLAGS -for prefix in "" $libpcap_prefix ; do +for test_prefix in "" $libpcap_prefix ; do for x in "" /pcap ; do - if test x$prefix != x ; then - CPPFLAGS="$oldCPPFLAGS -I$prefix/include$x" + if test x$test_prefix != x ; then + CPPFLAGS="$oldCPPFLAGS -I$test_prefix/include$x" fi AC_TRY_CPP([ #include ], [ - AC_MSG_RESULT([$prefix/include$x]) + AC_MSG_RESULT([$test_prefix/include$x]) foundpcaph=1 break ]) @@ -255,9 +265,9 @@ if test $foundpcaph = 0 ; then AC_MSG_ERROR([can't find pcap.h You're not going to get very far without libpcap.]) else - dnl assume that -lpcap is under $prefix/lib - if test x$prefix != x ; then - LDFLAGS="$LDFLAGS -L$prefix" + dnl assume that -lpcap is under $test_prefix/lib + if test x$test_prefix != x ; then + LDFLAGS="$LDFLAGS -L$test_prefix" fi AC_CHECK_LIB(pcap, pcap_open_live, , [ AC_MSG_ERROR([can't find libpcap @@ -341,9 +351,30 @@ else fi dnl -dnl Wahey! This might even work. +dnl Are we on a system (like Solaris) that requires promiscuous mode in order to +dnl see any outgoing packets? dnl +AC_MSG_CHECKING([if we need to enable promiscuous mode by default]) + +enable_default_promiscuous="no" + +case "$host_os" in +solaris*) enable_default_promiscuous="yes" ;; +esac + +AC_ARG_ENABLE(default-promiscuous, + [--enable-default-promiscuous If enabled, iftop will operate in promiscuous mode to capture outgoing packets]) + +AC_MSG_RESULT([$enable_default_promiscuous]) + +if test x"$enable_default_promiscuous" = x"yes"; then + AC_DEFINE([NEED_PROMISCUOUS_FOR_OUTGOING],1,[Enable default promiscuous mode to capture outgoing packets]) +fi + +dnl +dnl Wahey! This might even work. +dnl AC_SUBST(ac_aux_dir) diff --git a/dlcommon.c b/dlcommon.c new file mode 100644 index 0000000..748cea9 --- /dev/null +++ b/dlcommon.c @@ -0,0 +1,1365 @@ +/* + * Common (shared) DLPI test routines. + * Mostly pretty boring boilerplate sorta stuff. + * These can be split into individual library routines later + * but it's just convenient to keep them in a single file + * while they're being developed. + * + * Not supported: + * Connection Oriented stuff + * QOS stuff + */ + +#include "config.h" + +#ifdef HAVE_DLPI + +/* +typedef unsigned long ulong; +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include "dlcommon.h" + +#define CASERET(s) case s: return ("s") + +char *dlprim(); +char *dlstate(); +char *dlerrno(); +char *dlpromisclevel(); +char *dlservicemode(); +char *dlstyle(); +char *dlmactype(); + + +dlinforeq(fd) +int fd; +{ + dl_info_req_t info_req; + struct strbuf ctl; + int flags; + + info_req.dl_primitive = DL_INFO_REQ; + + ctl.maxlen = 0; + ctl.len = sizeof (info_req); + ctl.buf = (char *) &info_req; + + flags = RS_HIPRI; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlinforeq: putmsg"); +} + +dlinfoack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlinfoack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_INFO_ACK, dlp); + + if (ctl.len < sizeof (dl_info_ack_t)) + err("dlinfoack: response ctl.len too short: %d", ctl.len); + + if (flags != RS_HIPRI) + err("dlinfoack: DL_INFO_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_info_ack_t)) + err("dlinfoack: short response ctl.len: %d", ctl.len); +} + +dlattachreq(fd, ppa) +int fd; +u_long ppa; +{ + dl_attach_req_t attach_req; + struct strbuf ctl; + int flags; + + attach_req.dl_primitive = DL_ATTACH_REQ; + attach_req.dl_ppa = ppa; + + ctl.maxlen = 0; + ctl.len = sizeof (attach_req); + ctl.buf = (char *) &attach_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlattachreq: putmsg"); +} + +dlenabmultireq(fd, addr, length) +int fd; +char *addr; +int length; +{ + long buf[MAXDLBUF]; + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + dlp = (union DL_primitives*) buf; + + dlp->enabmulti_req.dl_primitive = DL_ENABMULTI_REQ; + dlp->enabmulti_req.dl_addr_length = length; + dlp->enabmulti_req.dl_addr_offset = sizeof (dl_enabmulti_req_t); + + (void) memcpy((char*)OFFADDR(buf, sizeof (dl_enabmulti_req_t)), addr, length); + + ctl.maxlen = 0; + ctl.len = sizeof (dl_enabmulti_req_t) + length; + ctl.buf = (char*) buf; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlenabmultireq: putmsg"); +} + +dldisabmultireq(fd, addr, length) +int fd; +char *addr; +int length; +{ + long buf[MAXDLBUF]; + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + dlp = (union DL_primitives*) buf; + + dlp->disabmulti_req.dl_primitive = DL_ENABMULTI_REQ; + dlp->disabmulti_req.dl_addr_length = length; + dlp->disabmulti_req.dl_addr_offset = sizeof (dl_disabmulti_req_t); + + (void) memcpy((char*)OFFADDR(buf, sizeof (dl_disabmulti_req_t)), addr, length); + + ctl.maxlen = 0; + ctl.len = sizeof (dl_disabmulti_req_t) + length; + ctl.buf = (char*) buf; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dldisabmultireq: putmsg"); +} + +dlpromisconreq(fd, level) +int fd; +u_long level; +{ + dl_promiscon_req_t promiscon_req; + struct strbuf ctl; + int flags; + + promiscon_req.dl_primitive = DL_PROMISCON_REQ; + promiscon_req.dl_level = level; + + ctl.maxlen = 0; + ctl.len = sizeof (promiscon_req); + ctl.buf = (char *) &promiscon_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlpromiscon: putmsg"); + +} + +dlpromiscoff(fd, level) +int fd; +u_long level; +{ + dl_promiscoff_req_t promiscoff_req; + struct strbuf ctl; + int flags; + + promiscoff_req.dl_primitive = DL_PROMISCOFF_REQ; + promiscoff_req.dl_level = level; + + ctl.maxlen = 0; + ctl.len = sizeof (promiscoff_req); + ctl.buf = (char *) &promiscoff_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlpromiscoff: putmsg"); +} + +dlphysaddrreq(fd, addrtype) +int fd; +u_long addrtype; +{ + dl_phys_addr_req_t phys_addr_req; + struct strbuf ctl; + int flags; + + phys_addr_req.dl_primitive = DL_PHYS_ADDR_REQ; + phys_addr_req.dl_addr_type = addrtype; + + ctl.maxlen = 0; + ctl.len = sizeof (phys_addr_req); + ctl.buf = (char *) &phys_addr_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlphysaddrreq: putmsg"); +} + +dlsetphysaddrreq(fd, addr, length) +int fd; +char *addr; +int length; +{ + long buf[MAXDLBUF]; + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + dlp = (union DL_primitives*) buf; + + dlp->set_physaddr_req.dl_primitive = DL_ENABMULTI_REQ; + dlp->set_physaddr_req.dl_addr_length = length; + dlp->set_physaddr_req.dl_addr_offset = sizeof (dl_set_phys_addr_req_t); + + (void) memcpy((char*)OFFADDR(buf, sizeof (dl_set_phys_addr_req_t)), addr, length); + + ctl.maxlen = 0; + ctl.len = sizeof (dl_set_phys_addr_req_t) + length; + ctl.buf = (char*) buf; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlsetphysaddrreq: putmsg"); +} + +dldetachreq(fd) +int fd; +{ + dl_detach_req_t detach_req; + struct strbuf ctl; + int flags; + + detach_req.dl_primitive = DL_DETACH_REQ; + + ctl.maxlen = 0; + ctl.len = sizeof (detach_req); + ctl.buf = (char *) &detach_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dldetachreq: putmsg"); +} + +dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest) +int fd; +u_long sap; +u_long max_conind; +u_long service_mode; +u_long conn_mgmt; +u_long xidtest; +{ + dl_bind_req_t bind_req; + struct strbuf ctl; + int flags; + + bind_req.dl_primitive = DL_BIND_REQ; + bind_req.dl_sap = sap; + bind_req.dl_max_conind = max_conind; + bind_req.dl_service_mode = service_mode; + bind_req.dl_conn_mgmt = conn_mgmt; + bind_req.dl_xidtest_flg = xidtest; + + ctl.maxlen = 0; + ctl.len = sizeof (bind_req); + ctl.buf = (char *) &bind_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlbindreq: putmsg"); +} + +dlunitdatareq(fd, addrp, addrlen, minpri, maxpri, datap, datalen) +int fd; +u_char *addrp; +int addrlen; +u_long minpri, maxpri; +u_char *datap; +int datalen; +{ + long buf[MAXDLBUF]; + union DL_primitives *dlp; + struct strbuf data, ctl; + + dlp = (union DL_primitives*) buf; + + dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; + dlp->unitdata_req.dl_dest_addr_length = addrlen; + dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t); + dlp->unitdata_req.dl_priority.dl_min = minpri; + dlp->unitdata_req.dl_priority.dl_max = maxpri; + + (void) memcpy(OFFADDR(dlp, sizeof (dl_unitdata_req_t)), addrp, addrlen); + + ctl.maxlen = 0; + ctl.len = sizeof (dl_unitdata_req_t) + addrlen; + ctl.buf = (char *) buf; + + data.maxlen = 0; + data.len = datalen; + data.buf = (char *) datap; + + if (putmsg(fd, &ctl, &data, 0) < 0) + syserr("dlunitdatareq: putmsg"); +} + +dlunbindreq(fd) +int fd; +{ + dl_unbind_req_t unbind_req; + struct strbuf ctl; + int flags; + + unbind_req.dl_primitive = DL_UNBIND_REQ; + + ctl.maxlen = 0; + ctl.len = sizeof (unbind_req); + ctl.buf = (char *) &unbind_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlunbindreq: putmsg"); +} + +dlokack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_OK_ACK, dlp); + + if (ctl.len < sizeof (dl_ok_ack_t)) + err("dlokack: response ctl.len too short: %d", ctl.len); + + if (flags != RS_HIPRI) + err("dlokack: DL_OK_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_ok_ack_t)) + err("dlokack: short response ctl.len: %d", ctl.len); +} + +dlerrorack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlerrorack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_ERROR_ACK, dlp); + + if (ctl.len < sizeof (dl_error_ack_t)) + err("dlerrorack: response ctl.len too short: %d", ctl.len); + + if (flags != RS_HIPRI) + err("dlerrorack: DL_OK_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_error_ack_t)) + err("dlerrorack: short response ctl.len: %d", ctl.len); +} + +dlbindack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_BIND_ACK, dlp); + + if (flags != RS_HIPRI) + err("dlbindack: DL_OK_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_bind_ack_t)) + err("dlbindack: short response ctl.len: %d", ctl.len); +} + +dlphysaddrack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlphysaddrack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_PHYS_ADDR_ACK, dlp); + + if (flags != RS_HIPRI) + err("dlbindack: DL_OK_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_phys_addr_ack_t)) + err("dlphysaddrack: short response ctl.len: %d", ctl.len); +} + +static void +sigalrm() +{ + (void) err("sigalrm: TIMEOUT"); +} + +strgetmsg(fd, ctlp, datap, flagsp, caller) +int fd; +struct strbuf *ctlp, *datap; +int *flagsp; +char *caller; +{ + int rc; + static char errmsg[80]; + + /* + * Start timer. + */ + (void) signal(SIGALRM, sigalrm); + if (alarm(MAXWAIT) < 0) { + (void) sprintf(errmsg, "%s: alarm", caller); + syserr(errmsg); + } + + /* + * Set flags argument and issue getmsg(). + */ + *flagsp = 0; + if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) { + (void) sprintf(errmsg, "%s: getmsg", caller); + syserr(errmsg); + } + + /* + * Stop timer. + */ + if (alarm(0) < 0) { + (void) sprintf(errmsg, "%s: alarm", caller); + syserr(errmsg); + } + + /* + * Check for MOREDATA and/or MORECTL. + */ + if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) + err("%s: MORECTL|MOREDATA", caller); + if (rc & MORECTL) + err("%s: MORECTL", caller); + if (rc & MOREDATA) + err("%s: MOREDATA", caller); + + /* + * Check for at least sizeof (long) control data portion. + */ + if (ctlp->len < sizeof (long)) + err("getmsg: control portion length < sizeof (long): %d", ctlp->len); +} + +expecting(prim, dlp) +int prim; +union DL_primitives *dlp; +{ + if (dlp->dl_primitive != (u_long)prim) { + printdlprim(dlp); + err("expected %s got %s", dlprim(prim), + dlprim(dlp->dl_primitive)); + exit(1); + } +} + +/* + * Print any DLPI msg in human readable format. + */ +printdlprim(dlp) +union DL_primitives *dlp; +{ + switch (dlp->dl_primitive) { + case DL_INFO_REQ: + printdlinforeq(dlp); + break; + + case DL_INFO_ACK: + printdlinfoack(dlp); + break; + + case DL_ATTACH_REQ: + printdlattachreq(dlp); + break; + + case DL_OK_ACK: + printdlokack(dlp); + break; + + case DL_ERROR_ACK: + printdlerrorack(dlp); + break; + + case DL_DETACH_REQ: + printdldetachreq(dlp); + break; + + case DL_BIND_REQ: + printdlbindreq(dlp); + break; + + case DL_BIND_ACK: + printdlbindack(dlp); + break; + + case DL_UNBIND_REQ: + printdlunbindreq(dlp); + break; + + case DL_SUBS_BIND_REQ: + printdlsubsbindreq(dlp); + break; + + case DL_SUBS_BIND_ACK: + printdlsubsbindack(dlp); + break; + + case DL_SUBS_UNBIND_REQ: + printdlsubsunbindreq(dlp); + break; + + case DL_ENABMULTI_REQ: + printdlenabmultireq(dlp); + break; + + case DL_DISABMULTI_REQ: + printdldisabmultireq(dlp); + break; + + case DL_PROMISCON_REQ: + printdlpromisconreq(dlp); + break; + + case DL_PROMISCOFF_REQ: + printdlpromiscoffreq(dlp); + break; + + case DL_UNITDATA_REQ: + printdlunitdatareq(dlp); + break; + + case DL_UNITDATA_IND: + printdlunitdataind(dlp); + break; + + case DL_UDERROR_IND: + printdluderrorind(dlp); + break; + + case DL_UDQOS_REQ: + printdludqosreq(dlp); + break; + + case DL_PHYS_ADDR_REQ: + printdlphysaddrreq(dlp); + break; + + case DL_PHYS_ADDR_ACK: + printdlphysaddrack(dlp); + break; + + case DL_SET_PHYS_ADDR_REQ: + printdlsetphysaddrreq(dlp); + break; + + default: + err("printdlprim: unknown primitive type 0x%x", + dlp->dl_primitive); + break; + } +} + +/* ARGSUSED */ +printdlinforeq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_INFO_REQ\n"); +} + +printdlinfoack(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + u_char brdcst[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->info_ack.dl_addr_offset), + dlp->info_ack.dl_addr_length, addr); + addrtostring(OFFADDR(dlp, dlp->info_ack.dl_brdcst_addr_offset), + dlp->info_ack.dl_brdcst_addr_length, brdcst); + + (void) printf("DL_INFO_ACK: max_sdu %d min_sdu %d\n", + dlp->info_ack.dl_max_sdu, + dlp->info_ack.dl_min_sdu); + (void) printf("addr_length %d mac_type %s current_state %s\n", + dlp->info_ack.dl_addr_length, + dlmactype(dlp->info_ack.dl_mac_type), + dlstate(dlp->info_ack.dl_current_state)); + (void) printf("sap_length %d service_mode %s qos_length %d\n", + dlp->info_ack.dl_sap_length, + dlservicemode(dlp->info_ack.dl_service_mode), + dlp->info_ack.dl_qos_length); + (void) printf("qos_offset %d qos_range_length %d qos_range_offset %d\n", + dlp->info_ack.dl_qos_offset, + dlp->info_ack.dl_qos_range_length, + dlp->info_ack.dl_qos_range_offset); + (void) printf("provider_style %s addr_offset %d version %d\n", + dlstyle(dlp->info_ack.dl_provider_style), + dlp->info_ack.dl_addr_offset, + dlp->info_ack.dl_version); + (void) printf("brdcst_addr_length %d brdcst_addr_offset %d\n", + dlp->info_ack.dl_brdcst_addr_length, + dlp->info_ack.dl_brdcst_addr_offset); + (void) printf("addr %s\n", addr); + (void) printf("brdcst_addr %s\n", brdcst); +} + +printdlattachreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_ATTACH_REQ: ppa %d\n", + dlp->attach_req.dl_ppa); +} + +printdlokack(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_OK_ACK: correct_primitive %s\n", + dlprim(dlp->ok_ack.dl_correct_primitive)); +} + +printdlerrorack(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_ERROR_ACK: error_primitive %s errno %s unix_errno %d\n", + dlprim(dlp->error_ack.dl_error_primitive), + dlerrno(dlp->error_ack.dl_errno), + dlp->error_ack.dl_unix_errno); +} + +printdlenabmultireq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->enabmulti_req.dl_addr_offset), + dlp->enabmulti_req.dl_addr_length, addr); + + (void) printf("DL_ENABMULTI_REQ: addr_length %d addr_offset %d\n", + dlp->enabmulti_req.dl_addr_length, + dlp->enabmulti_req.dl_addr_offset); + (void) printf("addr %s\n", addr); +} + +printdldisabmultireq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->disabmulti_req.dl_addr_offset), + dlp->disabmulti_req.dl_addr_length, addr); + + (void) printf("DL_DISABMULTI_REQ: addr_length %d addr_offset %d\n", + dlp->disabmulti_req.dl_addr_length, + dlp->disabmulti_req.dl_addr_offset); + (void) printf("addr %s\n", addr); +} + +printdlpromisconreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_PROMISCON_REQ: level %s\n", + dlpromisclevel(dlp->promiscon_req.dl_level)); +} + +printdlpromiscoffreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_PROMISCOFF_REQ: level %s\n", + dlpromisclevel(dlp->promiscoff_req.dl_level)); +} + +printdlphysaddrreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_PHYS_ADDR_REQ: addr_type 0x%x\n", + dlp->physaddr_req.dl_addr_type); +} + +printdlphysaddrack(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->physaddr_ack.dl_addr_offset), + dlp->physaddr_ack.dl_addr_length, addr); + + (void) printf("DL_PHYS_ADDR_ACK: addr_length %d addr_offset %d\n", + dlp->physaddr_ack.dl_addr_length, + dlp->physaddr_ack.dl_addr_offset); + (void) printf("addr %s\n", addr); +} + +printdlsetphysaddrreq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->set_physaddr_req.dl_addr_offset), + dlp->set_physaddr_req.dl_addr_length, addr); + + (void) printf("DL_SET_PHYS_ADDR_REQ: addr_length %d addr_offset %d\n", + dlp->set_physaddr_req.dl_addr_length, + dlp->set_physaddr_req.dl_addr_offset); + (void) printf("addr %s\n", addr); +} + +/* ARGSUSED */ +printdldetachreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_DETACH_REQ\n"); +} + +printdlbindreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_BIND_REQ: sap %d max_conind %d\n", + dlp->bind_req.dl_sap, + dlp->bind_req.dl_max_conind); + (void) printf("service_mode %s conn_mgmt %d xidtest_flg 0x%x\n", + dlservicemode(dlp->bind_req.dl_service_mode), + dlp->bind_req.dl_conn_mgmt, + dlp->bind_req.dl_xidtest_flg); +} + +printdlbindack(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->bind_ack.dl_addr_offset), + dlp->bind_ack.dl_addr_length, addr); + + (void) printf("DL_BIND_ACK: sap %d addr_length %d addr_offset %d\n", + dlp->bind_ack.dl_sap, + dlp->bind_ack.dl_addr_length, + dlp->bind_ack.dl_addr_offset); + (void) printf("max_conind %d xidtest_flg 0x%x\n", + dlp->bind_ack.dl_max_conind, + dlp->bind_ack.dl_xidtest_flg); + (void) printf("addr %s\n", addr); +} + +/* ARGSUSED */ +printdlunbindreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_UNBIND_REQ\n"); +} + +printdlsubsbindreq(dlp) +union DL_primitives *dlp; +{ + u_char sap[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->subs_bind_req.dl_subs_sap_offset), + dlp->subs_bind_req.dl_subs_sap_length, sap); + + (void) printf("DL_SUBS_BIND_REQ: subs_sap_offset %d sub_sap_len %d\n", + dlp->subs_bind_req.dl_subs_sap_offset, + dlp->subs_bind_req.dl_subs_sap_length); + (void) printf("sap %s\n", sap); +} + +printdlsubsbindack(dlp) +union DL_primitives *dlp; +{ + u_char sap[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->subs_bind_ack.dl_subs_sap_offset), + dlp->subs_bind_ack.dl_subs_sap_length, sap); + + (void) printf("DL_SUBS_BIND_ACK: subs_sap_offset %d sub_sap_length %d\n", + dlp->subs_bind_ack.dl_subs_sap_offset, + dlp->subs_bind_ack.dl_subs_sap_length); + (void) printf("sap %s\n", sap); +} + +printdlsubsunbindreq(dlp) +union DL_primitives *dlp; +{ + u_char sap[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->subs_unbind_req.dl_subs_sap_offset), + dlp->subs_unbind_req.dl_subs_sap_length, sap); + + (void) printf("DL_SUBS_UNBIND_REQ: subs_sap_offset %d sub_sap_length %d\n", + dlp->subs_unbind_req.dl_subs_sap_offset, + dlp->subs_unbind_req.dl_subs_sap_length); + (void) printf("sap %s\n", sap); +} + +printdlunitdatareq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->unitdata_req.dl_dest_addr_offset), + dlp->unitdata_req.dl_dest_addr_length, addr); + + (void) printf("DL_UNITDATA_REQ: dest_addr_length %d dest_addr_offset %d\n", + dlp->unitdata_req.dl_dest_addr_length, + dlp->unitdata_req.dl_dest_addr_offset); + (void) printf("dl_priority.min %d dl_priority.max %d\n", + dlp->unitdata_req.dl_priority.dl_min, + dlp->unitdata_req.dl_priority.dl_max); + (void) printf("addr %s\n", addr); +} + +printdlunitdataind(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_dest_addr_offset), + dlp->unitdata_ind.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_src_addr_offset), + dlp->unitdata_ind.dl_src_addr_length, src); + + (void) printf("DL_UNITDATA_IND: dest_addr_length %d dest_addr_offset %d\n", + dlp->unitdata_ind.dl_dest_addr_length, + dlp->unitdata_ind.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->unitdata_ind.dl_src_addr_length, + dlp->unitdata_ind.dl_src_addr_offset); + (void) printf("group_address 0x%x\n", + dlp->unitdata_ind.dl_group_address); + (void) printf("dest %s\n", dest); + (void) printf("src %s\n", src); +} + +printdluderrorind(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->uderror_ind.dl_dest_addr_offset), + dlp->uderror_ind.dl_dest_addr_length, addr); + + (void) printf("DL_UDERROR_IND: dest_addr_length %d dest_addr_offset %d\n", + dlp->uderror_ind.dl_dest_addr_length, + dlp->uderror_ind.dl_dest_addr_offset); + (void) printf("unix_errno %d errno %s\n", + dlp->uderror_ind.dl_unix_errno, + dlerrno(dlp->uderror_ind.dl_errno)); + (void) printf("addr %s\n", addr); +} + +printdltestreq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->test_req.dl_dest_addr_offset), + dlp->test_req.dl_dest_addr_length, addr); + + (void) printf("DL_TEST_REQ: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->test_req.dl_flag, + dlp->test_req.dl_dest_addr_length, + dlp->test_req.dl_dest_addr_offset); + (void) printf("dest_addr %s\n", addr); +} + +printdltestind(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->test_ind.dl_dest_addr_offset), + dlp->test_ind.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->test_ind.dl_src_addr_offset), + dlp->test_ind.dl_src_addr_length, src); + + (void) printf("DL_TEST_IND: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->test_ind.dl_flag, + dlp->test_ind.dl_dest_addr_length, + dlp->test_ind.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->test_ind.dl_src_addr_length, + dlp->test_ind.dl_src_addr_offset); + (void) printf("dest_addr %s\n", dest); + (void) printf("src_addr %s\n", src); +} + +printdltestres(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->test_res.dl_dest_addr_offset), + dlp->test_res.dl_dest_addr_length, dest); + + (void) printf("DL_TEST_RES: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->test_res.dl_flag, + dlp->test_res.dl_dest_addr_length, + dlp->test_res.dl_dest_addr_offset); + (void) printf("dest_addr %s\n", dest); +} + +printdltestcon(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->test_con.dl_dest_addr_offset), + dlp->test_con.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->test_con.dl_src_addr_offset), + dlp->test_con.dl_src_addr_length, src); + + (void) printf("DL_TEST_CON: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->test_con.dl_flag, + dlp->test_con.dl_dest_addr_length, + dlp->test_con.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->test_con.dl_src_addr_length, + dlp->test_con.dl_src_addr_offset); + (void) printf("dest_addr %s\n", dest); + (void) printf("src_addr %s\n", src); +} + +printdlxidreq(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->xid_req.dl_dest_addr_offset), + dlp->xid_req.dl_dest_addr_length, dest); + + (void) printf("DL_XID_REQ: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->xid_req.dl_flag, + dlp->xid_req.dl_dest_addr_length, + dlp->xid_req.dl_dest_addr_offset); + (void) printf("dest_addr %s\n", dest); +} + +printdlxidind(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_dest_addr_offset), + dlp->xid_ind.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_src_addr_offset), + dlp->xid_ind.dl_src_addr_length, src); + + (void) printf("DL_XID_IND: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->xid_ind.dl_flag, + dlp->xid_ind.dl_dest_addr_length, + dlp->xid_ind.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->xid_ind.dl_src_addr_length, + dlp->xid_ind.dl_src_addr_offset); + (void) printf("dest_addr %s\n", dest); + (void) printf("src_addr %s\n", src); +} + +printdlxidres(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->xid_res.dl_dest_addr_offset), + dlp->xid_res.dl_dest_addr_length, dest); + + (void) printf("DL_XID_RES: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->xid_res.dl_flag, + dlp->xid_res.dl_dest_addr_length, + dlp->xid_res.dl_dest_addr_offset); + (void) printf("dest_addr %s\n", dest); +} + +printdlxidcon(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->xid_con.dl_dest_addr_offset), + dlp->xid_con.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->xid_con.dl_src_addr_offset), + dlp->xid_con.dl_src_addr_length, src); + + (void) printf("DL_XID_CON: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->xid_con.dl_flag, + dlp->xid_con.dl_dest_addr_length, + dlp->xid_con.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->xid_con.dl_src_addr_length, + dlp->xid_con.dl_src_addr_offset); + (void) printf("dest_addr %s\n", dest); + (void) printf("src_addr %s\n", src); +} + +printdludqosreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_UDQOS_REQ: qos_length %d qos_offset %d\n", + dlp->udqos_req.dl_qos_length, + dlp->udqos_req.dl_qos_offset); +} + +/* + * Return string. + */ +addrtostring(addr, length, s) +u_char *addr; +u_long length; +u_char *s; +{ + int i; + + for (i = 0; i < length; i++) { + (void) sprintf((char*) s, "%x:", addr[i] & 0xff); + s = s + strlen((char*)s); + } + if (length) + *(--s) = '\0'; +} + +/* + * Return length + */ +stringtoaddr(sp, addr) +char *sp; +char *addr; +{ + int n = 0; + char *p; + int val; + + p = sp; + while (p = strtok(p, ":")) { + if (sscanf(p, "%x", &val) != 1) + err("stringtoaddr: invalid input string: %s", sp); + if (val > 0xff) + err("stringtoaddr: invalid input string: %s", sp); + *addr++ = val; + n++; + p = NULL; + } + + return (n); +} + + +static char +hexnibble(c) +char c; +{ + static char hextab[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' + }; + + return (hextab[c & 0x0f]); +} + +char* +dlprim(prim) +u_long prim; +{ + static char primbuf[80]; + + switch ((int)prim) { + CASERET(DL_INFO_REQ); + CASERET(DL_INFO_ACK); + CASERET(DL_ATTACH_REQ); + CASERET(DL_DETACH_REQ); + CASERET(DL_BIND_REQ); + CASERET(DL_BIND_ACK); + CASERET(DL_UNBIND_REQ); + CASERET(DL_OK_ACK); + CASERET(DL_ERROR_ACK); + CASERET(DL_SUBS_BIND_REQ); + CASERET(DL_SUBS_BIND_ACK); + CASERET(DL_UNITDATA_REQ); + CASERET(DL_UNITDATA_IND); + CASERET(DL_UDERROR_IND); + CASERET(DL_UDQOS_REQ); + CASERET(DL_CONNECT_REQ); + CASERET(DL_CONNECT_IND); + CASERET(DL_CONNECT_RES); + CASERET(DL_CONNECT_CON); + CASERET(DL_TOKEN_REQ); + CASERET(DL_TOKEN_ACK); + CASERET(DL_DISCONNECT_REQ); + CASERET(DL_DISCONNECT_IND); + CASERET(DL_RESET_REQ); + CASERET(DL_RESET_IND); + CASERET(DL_RESET_RES); + CASERET(DL_RESET_CON); + default: + (void) sprintf(primbuf, "unknown primitive 0x%x", prim); + return (primbuf); + } +} + + +char* +dlstate(state) +u_long state; +{ + static char statebuf[80]; + + switch (state) { + CASERET(DL_UNATTACHED); + CASERET(DL_ATTACH_PENDING); + CASERET(DL_DETACH_PENDING); + CASERET(DL_UNBOUND); + CASERET(DL_BIND_PENDING); + CASERET(DL_UNBIND_PENDING); + CASERET(DL_IDLE); + CASERET(DL_UDQOS_PENDING); + CASERET(DL_OUTCON_PENDING); + CASERET(DL_INCON_PENDING); + CASERET(DL_CONN_RES_PENDING); + CASERET(DL_DATAXFER); + CASERET(DL_USER_RESET_PENDING); + CASERET(DL_PROV_RESET_PENDING); + CASERET(DL_RESET_RES_PENDING); + CASERET(DL_DISCON8_PENDING); + CASERET(DL_DISCON9_PENDING); + CASERET(DL_DISCON11_PENDING); + CASERET(DL_DISCON12_PENDING); + CASERET(DL_DISCON13_PENDING); + CASERET(DL_SUBS_BIND_PND); + default: + (void) sprintf(statebuf, "unknown state 0x%x", state); + return (statebuf); + } +} + +char* +dlerrno(errno) +u_long errno; +{ + static char errnobuf[80]; + + switch (errno) { + CASERET(DL_ACCESS); + CASERET(DL_BADADDR); + CASERET(DL_BADCORR); + CASERET(DL_BADDATA); + CASERET(DL_BADPPA); + CASERET(DL_BADPRIM); + CASERET(DL_BADQOSPARAM); + CASERET(DL_BADQOSTYPE); + CASERET(DL_BADSAP); + CASERET(DL_BADTOKEN); + CASERET(DL_BOUND); + CASERET(DL_INITFAILED); + CASERET(DL_NOADDR); + CASERET(DL_NOTINIT); + CASERET(DL_OUTSTATE); + CASERET(DL_SYSERR); + CASERET(DL_UNSUPPORTED); + CASERET(DL_UNDELIVERABLE); + CASERET(DL_NOTSUPPORTED); + CASERET(DL_TOOMANY); + CASERET(DL_NOTENAB); + CASERET(DL_BUSY); + CASERET(DL_NOAUTO); + CASERET(DL_NOXIDAUTO); + CASERET(DL_NOTESTAUTO); + CASERET(DL_XIDAUTO); + CASERET(DL_TESTAUTO); + CASERET(DL_PENDING); + + default: + (void) sprintf(errnobuf, "unknown dlpi errno 0x%x", errno); + return (errnobuf); + } +} + +char* +dlpromisclevel(level) +u_long level; +{ + static char levelbuf[80]; + + switch (level) { + CASERET(DL_PROMISC_PHYS); + CASERET(DL_PROMISC_SAP); + CASERET(DL_PROMISC_MULTI); + default: + (void) sprintf(levelbuf, "unknown promisc level 0x%x", level); + return (levelbuf); + } +} + +char* +dlservicemode(servicemode) +u_long servicemode; +{ + static char servicemodebuf[80]; + + switch (servicemode) { + CASERET(DL_CODLS); + CASERET(DL_CLDLS); + CASERET(DL_CODLS|DL_CLDLS); + default: + (void) sprintf(servicemodebuf, + "unknown provider service mode 0x%x", servicemode); + return (servicemodebuf); + } +} + +char* +dlstyle(style) +long style; +{ + static char stylebuf[80]; + + switch (style) { + CASERET(DL_STYLE1); + CASERET(DL_STYLE2); + default: + (void) sprintf(stylebuf, "unknown provider style 0x%x", style); + return (stylebuf); + } +} + +char* +dlmactype(media) +u_long media; +{ + static char mediabuf[80]; + + switch (media) { + CASERET(DL_CSMACD); + CASERET(DL_TPB); + CASERET(DL_TPR); + CASERET(DL_METRO); + CASERET(DL_ETHER); + CASERET(DL_HDLC); + CASERET(DL_CHAR); + CASERET(DL_CTCA); + default: + (void) sprintf(mediabuf, "unknown media type 0x%x", media); + return (mediabuf); + } +} + +/*VARARGS1*/ +err(fmt, a1, a2, a3, a4) +char *fmt; +char *a1, *a2, *a3, *a4; +{ + (void) fprintf(stderr, fmt, a1, a2, a3, a4); + (void) fprintf(stderr, "\n"); + (void) exit(1); +} + +syserr(s) +char *s; +{ + (void) perror(s); + exit(1); +} + +strioctl(fd, cmd, timout, len, dp) +int fd; +int cmd; +int timout; +int len; +char *dp; +{ + struct strioctl sioc; + int rc; + + sioc.ic_cmd = cmd; + sioc.ic_timout = timout; + sioc.ic_len = len; + sioc.ic_dp = dp; + rc = ioctl(fd, I_STR, &sioc); + + if (rc < 0) + return (rc); + else + return (sioc.ic_len); +} + +#endif /* HAVE_DLPI */ diff --git a/dlcommon.h b/dlcommon.h new file mode 100644 index 0000000..0d1f35a --- /dev/null +++ b/dlcommon.h @@ -0,0 +1,37 @@ +#ifndef DLCOMMON_H +#define DLCOMMON_H + +/* + * Common DLPI Test Suite header file + * + */ + +/* + * Maximum control/data buffer size (in long's !!) for getmsg(). + */ +#define MAXDLBUF 8192 + +/* + * Maximum number of seconds we'll wait for any + * particular DLPI acknowledgment from the provider + * after issuing a request. + */ +#define MAXWAIT 15 + +/* + * Maximum address buffer length. + */ +#define MAXDLADDR 1024 + + +/* + * Handy macro. + */ +#define OFFADDR(s, n) (u_char*)((char*)(s) + (int)(n)) + +/* + * externs go here + */ +extern void sigalrm(); + +#endif /* !DLCOMMON_H */ diff --git a/iftop.c b/iftop.c index 4c57f15..6448c8c 100644 --- a/iftop.c +++ b/iftop.c @@ -222,6 +222,9 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) * source and dest arbitrarily (by numerical value) and account as * incoming. */ + else if (options.promiscuous_but_choosy) { + return; /* junk it */ + } else if(iptr->ip_src.s_addr < iptr->ip_dst.s_addr) { assign_addr_pair(&ap, iptr, 1); direction = 0; @@ -384,10 +387,13 @@ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkt if(have_hw_addr && memcmp(eptr->ether_shost, if_hw_addr, 6) == 0 ) { /* packet leaving this i/f */ dir = 1; - } - else if((have_hw_addr && memcmp(eptr->ether_dhost, if_hw_addr, 6) == 0) - || memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", eptr->ether_dhost, 6) == 0) { - /* packet entering this i/f (include broadcast packets here */ + } + else if(have_hw_addr && memcmp(eptr->ether_dhost, if_hw_addr, 6) == 0 ) { + /* packet entering this i/f */ + dir = 0; + } + else if (memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", eptr->ether_dhost, 6) == 0) { + /* broadcast packet, count as incoming */ dir = 0; } @@ -430,59 +436,34 @@ void packet_init() { char *m; int s; int i; - struct ifreq ifr = {}; int dlt; + int result; - /* First, get the address of the interface. If it isn't an ethernet - * interface whose address we can obtain, there's not a lot we can do. */ - s = socket(PF_INET, SOCK_DGRAM, 0); /* any sort of IP socket will do */ - if (s == -1) { - perror("socket"); - exit(1); - } - fprintf(stderr,"if: %s\n", options.interface); - memset(if_hw_addr, 0, 6); - strncpy(ifr.ifr_name, options.interface, IFNAMSIZ); -#ifdef SIOCGIFHWADDR - if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { - fprintf(stderr, "Error getting hardware address for interface: %s\n", options.interface); - perror("ioctl(SIOCGIFHWADDR)"); - } - else { - memcpy(if_hw_addr, ifr.ifr_hwaddr.sa_data, 6); - have_hw_addr = 1; - } +#ifdef HAVE_DLPI + result = get_addrs_dlpi(options.interface, if_hw_addr, &if_ip_addr); #else - fprintf(stderr, "Cannot obtain hardware address on this platform\n"); + result = get_addrs_ioctl(options.interface, if_hw_addr, &if_ip_addr); #endif + if (result < 0) { + exit(1); + } + + have_hw_addr = result & 1; + have_ip_addr = result & 2; + + if(have_ip_addr) { + fprintf(stderr, "IP address is: %s\n", inet_ntoa(if_ip_addr)); + } + if(have_hw_addr) { - fprintf(stderr, "MAC address is:"); - for (i = 0; i < 6; ++i) - fprintf(stderr, "%c%02x", i ? ':' : ' ', (unsigned int)if_hw_addr[i]); - fprintf(stderr, "\n"); + fprintf(stderr, "MAC address is:"); + for (i = 0; i < 6; ++i) + fprintf(stderr, "%c%02x", i ? ':' : ' ', (unsigned int)if_hw_addr[i]); + fprintf(stderr, "\n"); } - - /* Get the IP address of the interface */ -#ifdef SIOCGIFADDR - (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET; - if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { - fprintf(stderr, "Error getting IP address for interface: %s\n", options.interface); - perror("ioctl(SIOCGIFADDR)"); - } - else { - have_ip_addr = 1; - memcpy(&if_ip_addr, &((*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr), sizeof(struct sockaddr_in)); - } -#else - fprintf(stderr, "Cannot obtain IP address on this platform\n"); -#endif - - close(s); - - if(have_ip_addr) - fprintf(stderr, "IP address is: %s\n", inet_ntoa(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr)); + // exit(0); resolver_initialise(); pd = pcap_open_live(options.interface, CAPTURE_LENGTH, options.promiscuous, 1000, errbuf); diff --git a/options.c b/options.c index bec2070..4e6b7f4 100644 --- a/options.c +++ b/options.c @@ -4,6 +4,8 @@ * */ +#include "config.h" + #include #include @@ -37,6 +39,7 @@ char optstr[] = "+i:f:nN:hpbBP"; * likely to want to listen. We also compare candidate interfaces to lo. */ static char *bad_interface_names[] = { "lo:", + "lo", "dummy", "vmnet", NULL /* last entry must be NULL */ @@ -87,7 +90,13 @@ static void set_defaults() { inet_aton("255.255.255.0", &options.netfiltermask); options.dnsresolution = 1; options.portresolution = 1; +#ifdef NEED_PROMISCUOUS_FOR_OUTGOING + options.promiscuous = 1; + options.promiscuous_but_choosy = 1; +#else options.promiscuous = 0; + options.promiscuous_but_choosy = 0; +#endif options.showbars = 1; options.showports = OPTION_PORTS_OFF; options.aggregate_src = 0; @@ -200,6 +209,7 @@ void options_read(int argc, char **argv) { case 'p': options.promiscuous = 1; + options.promiscuous_but_choosy = 0; break; case 'P': diff --git a/options.h b/options.h index 1370386..4aa2a91 100644 --- a/options.h +++ b/options.h @@ -47,6 +47,7 @@ typedef struct { int dnsresolution; int portresolution; int promiscuous; + int promiscuous_but_choosy; int showbars; option_port_t showports; int aggregate_src;