Solaris/autoconf patch from Jonathan Abbey <jonabbey@ganymeta.org>
This commit is contained in:
10
AUTHORS
Normal file
10
AUTHORS
Normal file
@@ -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
|
||||
120
CHANGES
120
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 <jonabbey@ganymeta.org>
|
||||
|
||||
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 <Martin.Garton@DCSTRANS.COM>
|
||||
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 <iain@bricbrac.de>
|
||||
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 <iain@bricbrac.de>
|
||||
|
||||
* 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 <michael@noname.franken.de>
|
||||
* Fixed segfault bug affecting some systems
|
||||
|
||||
* Added support for Linux cooked sockets
|
||||
Michael Bergbauer <michael@noname.franken.de>
|
||||
|
||||
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 <mesrik@cc.jyu.fi>
|
||||
Fixes to "make install"
|
||||
Steve Baker <sjb@ambrielconsulting.com>
|
||||
* No code changes
|
||||
|
||||
* Added RPM spec file
|
||||
Riku Meskanen <mesrik@cc.jyu.fi>
|
||||
|
||||
* Fixes to "make install"
|
||||
Steve Baker <sjb@ambrielconsulting.com>
|
||||
|
||||
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.
|
||||
|
||||
7
COPYING
7
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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.
|
||||
|
||||
10
ChangeLog
Normal file
10
ChangeLog
Normal file
@@ -0,0 +1,10 @@
|
||||
2003-06-04 Jonathan Abbey <jonabbey@ganymeta.org>
|
||||
* 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
|
||||
|
||||
@@ -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
|
||||
|
||||
3
NEWS
Normal file
3
NEWS
Normal file
@@ -0,0 +1,3 @@
|
||||
Hm, automake insists on there being a NEWS file in place.
|
||||
|
||||
So, here's one, for the time being.
|
||||
15
README
15
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.
|
||||
|
||||
395
addrs_dlpi.c
Normal file
395
addrs_dlpi.c
Normal file
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/dlpi.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#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 <dest> buffer is null terminated. strncpy() will not
|
||||
NULL terminate the destination buffer if the <src> string is <n>
|
||||
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 <dest> buffer's bounds are not
|
||||
violated. In this case, <n> should be the size of the <dest> 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
|
||||
<src> to <dest>. In this case, <n> 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 <src> that was
|
||||
not copied to <dest>. If all of <src> was copied to <dest>,
|
||||
strncpy2() will return a pointer to the NULL character terminating the
|
||||
<src> 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 <n> is the size of the <dest> 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 <dest> will be null terminated, and that
|
||||
the buffer limits will be honored. strncat2() will not write even one
|
||||
byte beyond the end of the <dest> buffer.
|
||||
|
||||
strncat2() concatenates up to <n-1> - strlen(<dest>) characters from
|
||||
<src> to <dest>.
|
||||
|
||||
So if the <dest> buffer has a size of 20 bytes (including trailing NULL),
|
||||
and <dest> contains a 19 character string, nothing will be done to
|
||||
<dest>.
|
||||
|
||||
If the string in <dest> is longer than <n-1> characters upon entry to
|
||||
strncat2(), <dest> will be truncated after the <n-1>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
|
||||
<dest> was full before the concatenation operation started (which
|
||||
effectively causes instant truncation even if the <src> string is
|
||||
empty..
|
||||
|
||||
We could just test src_ptr here, but that would report
|
||||
a string truncation if <src> 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 <src> or because of
|
||||
sufficient room in <dest>. */
|
||||
|
||||
return(src_ptr);
|
||||
}
|
||||
|
||||
#endif /* HAVE_DLPI */
|
||||
93
addrs_ioctl.c
Normal file
93
addrs_ioctl.c
Normal file
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
61
configure.in
61
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 <pcap.h>
|
||||
], [
|
||||
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)
|
||||
|
||||
|
||||
1365
dlcommon.c
Normal file
1365
dlcommon.c
Normal file
File diff suppressed because it is too large
Load Diff
37
dlcommon.h
Normal file
37
dlcommon.h
Normal file
@@ -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 */
|
||||
79
iftop.c
79
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);
|
||||
|
||||
10
options.c
10
options.c
@@ -4,6 +4,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -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':
|
||||
|
||||
Reference in New Issue
Block a user