From: Andru Luvisi Date: Thu, 23 Jan 2003 14:44:30 -0800 (PST) It turns out that the problem we had with signals came from the fact that pcap_dispatch was never returning on Linux. SIGCHLD signals are blocked during pcap_dispatch and the quit_requested flag set by interrupts was never being checked later in the main loop. I got around this by setting a timeout (via setsockopt) on the underlying file descriptor. I don't know if this is the best solution, but it seems to work for us. --------------------------------------------------------------------------- Feb 13 2003 - Irwin Tillman Note that some of the code in this diff is from the Linux 'net-tools' package. That package is distributed under the GNU Public License. A copy of the GPL is included in the COPYING.GPL file included with dhcp-probe. The home of the net-tools package may be found via: http://freshmeat.net/projects/net-tools/?topic_id=150 --------------------------------------------------------------------------- diff -urN dhcp_probe-1.0.4.org/src/Makefile.in dhcp_probe-1.0.4/src/Makefile.in --- dhcp_probe-1.0.4.org/src/Makefile.in 2002-05-09 14:15:15.000000000 -0700 +++ dhcp_probe-1.0.4/src/Makefile.in 2003-01-22 10:41:23.000000000 -0800 @@ -68,7 +68,7 @@ sbin_PROGRAMS = dhcp_probe -dhcp_probe_SOURCES = bootp.c configfile.c dhcp_probe.c get_myeaddr.c get_myipaddr.c daemonize.c report.c utils.c bootp.h configfile.h dhcp_probe.h defaults.h defs.h get_myeaddr.h get_myipaddr.h daemonize.h report.h utils.h +dhcp_probe_SOURCES = bootp.c configfile.c dhcp_probe.c arp.c get_myeaddr.c get_myipaddr.c daemonize.c report.c utils.c bootp.h configfile.h dhcp_probe.h defaults.h defs.h arp.c get_myeaddr.h get_myipaddr.h daemonize.h report.h utils.h LDADD = $(top_builddir)/lib/libreplace.a @@ -82,7 +82,7 @@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ -dhcp_probe_OBJECTS = bootp.o configfile.o dhcp_probe.o get_myeaddr.o \ +dhcp_probe_OBJECTS = bootp.o configfile.o dhcp_probe.o arp.o get_myeaddr.o \ get_myipaddr.o daemonize.o report.o utils.o dhcp_probe_LDADD = $(LDADD) dhcp_probe_DEPENDENCIES = $(top_builddir)/lib/libreplace.a @@ -210,8 +210,9 @@ configfile.h report.h daemonize.o: daemonize.c ../config.h defs.h daemonize.h report.h dhcp_probe.o: dhcp_probe.c ../config.h defs.h defaults.h dhcp_probe.h \ - bootp.h daemonize.h get_myeaddr.h get_myipaddr.h configfile.h \ + bootp.h daemonize.h arp.h get_myeaddr.h get_myipaddr.h configfile.h \ report.h utils.h +arp.o: arp.c arp.h get_myeaddr.o: get_myeaddr.c ../config.h defs.h get_myeaddr.h report.h get_myipaddr.o: get_myipaddr.c ../config.h defs.h get_myipaddr.h \ report.h utils.h diff -urN dhcp_probe-1.0.4.org/src/arp.c dhcp_probe-1.0.4/src/arp.c --- dhcp_probe-1.0.4.org/src/arp.c 1969-12-31 16:00:00.000000000 -0800 +++ dhcp_probe-1.0.4/src/arp.c 2003-01-23 14:22:43.000000000 -0800 @@ -0,0 +1,23 @@ +/* From the Linux net-tools package */ + +#ifdef linux + +#include "arp.h" + +/* Get the hardware address to a specified interface name */ +int arp_getdevhw(char *ifname, struct sockaddr *sa, int sockfd) +{ + struct ifreq ifr; + struct hwtype *xhw; + + strcpy(ifr.ifr_name, ifname); + if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) { + fprintf(stderr, "arp: cant get HW-Address for `%s': %s.\n", ifname, strerror(errno)); + return (-1); + } + memcpy((char *) sa, (char *) &(ifr.ifr_hwaddr), sizeof(struct sockaddr)); + + return (0); +} + +#endif /* linux */ diff -urN dhcp_probe-1.0.4.org/src/arp.h dhcp_probe-1.0.4/src/arp.h --- dhcp_probe-1.0.4.org/src/arp.h 1969-12-31 16:00:00.000000000 -0800 +++ dhcp_probe-1.0.4/src/arp.h 2003-01-23 14:22:33.000000000 -0800 @@ -0,0 +1,29 @@ +/* From the Linux net-tools package */ + +#ifndef ARP_H +#define ARP_H + +#ifdef linux + +#include +#include +#include +#include +/* #include */ +/* #include */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Get the hardware address to a specified interface name */ +int arp_getdevhw(char *ifname, struct sockaddr *sa, int sockfd); + +#endif /* linux */ + +#endif /* ARP_H */ diff -urN dhcp_probe-1.0.4.org/src/daemonize.c dhcp_probe-1.0.4/src/daemonize.c --- dhcp_probe-1.0.4.org/src/daemonize.c 2001-01-27 14:25:08.000000000 -0800 +++ dhcp_probe-1.0.4/src/daemonize.c 2003-01-23 14:24:17.000000000 -0800 @@ -16,6 +16,11 @@ #include "daemonize.h" #include "report.h" +#ifdef linux +#include +#include +#include +#endif /* linux */ void daemonize(void) @@ -23,6 +28,9 @@ int i; pid_t pid; struct sigaction sa; +#ifdef linux + struct rlimit rlim; +#endif /* linux */ if ((pid = fork()) < 0) { report(LOG_ERR, "fork: %s", get_errmsg()); @@ -63,8 +71,18 @@ There is also no portable way to determine the maximum number of file descriptors; presently we'll rely on the non-portable OPEN_MAX constant. */ - for (i = 0; i < OPEN_MAX; i++) +#ifdef linux + if(getrlimit(RLIMIT_NOFILE, &rlim) != 0) { + perror("getrlimit"); + exit(1); + } + for (i = 0; i < rlim.rlim_cur; i++) close(i); +#else /* linux */ + for (i = 0; i < RLIMIT_NOFILE; i++) + close(i); +#endif /* linux */ + return; } diff -urN dhcp_probe-1.0.4.org/src/defs.h dhcp_probe-1.0.4/src/defs.h --- dhcp_probe-1.0.4.org/src/defs.h 2001-01-27 14:27:27.000000000 -0800 +++ dhcp_probe-1.0.4/src/defs.h 2003-01-23 14:25:01.000000000 -0800 @@ -100,10 +100,13 @@ #define PASTE(a,b) a ## b /* The declarations for these libsocket routines are missing from Solaris 2.6 and Solaris 7 headers */ -char *ether_ntoa (struct ether_addr *); -struct ether_addr *ether_aton(char *); -int ether_ntohost (char *hostname, struct ether_addr *e); -int ether_hostton (char *hostname, struct ether_addr *e); +/* These cause errors as duplicate declarations in Linux */ +#ifndef linux + char *ether_ntoa (struct ether_addr *); + struct ether_addr *ether_aton(char *); + int ether_ntohost (char *hostname, struct ether_addr *e); + int ether_hostton (char *hostname, struct ether_addr *e); +#endif /* not linux */ #endif /* not DEFS_H */ diff -urN dhcp_probe-1.0.4.org/src/dhcp_probe.c dhcp_probe-1.0.4/src/dhcp_probe.c --- dhcp_probe-1.0.4.org/src/dhcp_probe.c 2002-05-09 14:07:50.000000000 -0700 +++ dhcp_probe-1.0.4/src/dhcp_probe.c 2003-01-23 14:14:12.000000000 -0800 @@ -20,6 +20,7 @@ #include "dhcp_probe.h" #include "bootp.h" #include "daemonize.h" +#include "arp.h" #include "get_myeaddr.h" #include "get_myipaddr.h" #include "configfile.h" @@ -285,6 +286,13 @@ exit(1); } +#ifdef linux + if(arp_getdevhw(ifname, &my_eaddr, sockfd) < 0) { + report(LOG_ERR, "couldn't determine my ethernet addr for my IP address %s", inet_ntoa(my_ipaddr)); + cleanup(); + exit(1); + } +#else /* linux */ /* lookup ethernet address for specified IP address */ /* note that my_eaddr must be init'd before calling GetChaddr() */ if (get_myeaddr(sockfd, &my_ipaddr, &my_eaddr) < 0) { @@ -292,6 +300,7 @@ cleanup(); exit(1); } +#endif /* linux */ if (debug > 0) report(LOG_INFO, "using interface %s (IP address %s, hardware address %s)", @@ -401,6 +410,9 @@ cleanup(); exit(1); } +#ifdef linux + set_timeout(pd_template); +#endif /* linux */ if (pcap_errbuf[0] != '\0') /* even on success, a warning may be produced */ report(LOG_WARNING, "pcap_open_live %s: %s", ifname, pcap_errbuf); @@ -500,6 +512,9 @@ while (pcap_open_retries--) { pcap_errbuf[0] = '\0'; /* so we can tell if a warning was produced on success */ if ((pd = pcap_open_live(ifname, snaplen, promiscuous, GetResponse_wait_time(), pcap_errbuf)) != NULL) { +#ifdef linux + set_timeout(pd); +#endif /* linux */ break; /* success */ } else { /* failure */ if (pcap_open_retries == 0) { @@ -954,3 +969,22 @@ return; } +void +set_timeout(pcap_t *pc) +{ + struct timeval timeout; + int time_wait; + + time_wait = GetResponse_wait_time(); + timeout.tv_sec = time_wait / 1000; + timeout.tv_usec = (time_wait % 1000) * 1000; + if(setsockopt(pcap_fileno(pc), SOL_SOCKET, SO_RCVTIMEO, + &timeout, sizeof(timeout)) < 0) { + report(LOG_ERR, + "set_timeout: Unable to set receive timeout: %s", + strerror(errno)); + cleanup(); + exit(1); + } + +} diff -urN dhcp_probe-1.0.4.org/src/dhcp_probe.h dhcp_probe-1.0.4/src/dhcp_probe.h --- dhcp_probe-1.0.4.org/src/dhcp_probe.h 2000-12-22 14:00:32.000000000 -0800 +++ dhcp_probe-1.0.4/src/dhcp_probe.h 2003-01-23 10:06:24.000000000 -0800 @@ -48,6 +48,7 @@ void cleanup(void); void usage(void); void close_and_reopen_capture_file(void); +void set_timeout(pcap_t *pc);