summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 3728782)
raw | patch | inline | side by side (parent: 3728782)
author | Holger Weiss <hweiss@users.sourceforge.net> | |
Thu, 26 Jul 2007 00:02:28 +0000 (00:02 +0000) | ||
committer | Holger Weiss <hweiss@users.sourceforge.net> | |
Thu, 26 Jul 2007 00:02:28 +0000 (00:02 +0000) |
DHCP relay server in order to check remote subnets (Heiti Ernits and
Andreas Ericsson - 1218235)
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1762 f882894a-f735-0410-b71e-b25c423dba1c
Andreas Ericsson - 1218235)
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1762 f882894a-f735-0410-b71e-b25c423dba1c
NEWS | patch | blob | history | |
THANKS.in | patch | blob | history | |
configure.in | patch | blob | history | |
plugins-root/check_dhcp.c | patch | blob | history |
index ff9a5eefbc4a6d3a4eb97915a7796f0e4fb59d15..26e805ee06f127f8d4bee400abcb86de3fe413d6 100644 (file)
--- a/NEWS
+++ b/NEWS
Check_disk now calls stat() on all filesystems to check. (Old: only the ones selected using -p)
A meaningful error message (eg "Stale NFS Handle") is printed if stat fails.
Check_disk's --help now prints some examples for the new features introduced in 1.4.8
+ New check_dhcp -u/--unicast option for emulating a DHCP relay in order
+ to check DHCP servers on remote networks
1.4.9 4th June 2006
Inclusion of contrib/check_cluster2 as check_cluster with some improvements
diff --git a/THANKS.in b/THANKS.in
index 3644fe1a8c417b6c0896696a0f513a2bc4c6be57..d56a3f4a67f15dcf8e4c84e90d04a361308fbe9c 100644 (file)
--- a/THANKS.in
+++ b/THANKS.in
Aurelien Bompard
Christoph Schell
Andrew Elwell
+Heiti Ernits
diff --git a/configure.in b/configure.in
index 5b5b983b9b603d27512dd8de051d06e28a8ffa15..86f378096c2ceb43e3cf8c6f359e89b7b960123b 100644 (file)
--- a/configure.in
+++ b/configure.in
fi
+dnl used in check_dhcp
+AC_CHECK_HEADERS(sys/sockio.h)
+
case $host in
*bsd*)
AC_DEFINE(__bsd__,1,[bsd specific code in check_dhcp.c])
index 7cb2d30052d34aeaad82f218869e6f2a2169303e..a1d04c18e79522edf615ee3673f3b07137b0a0c8 100644 (file)
*
* $Id$
*
+* ------------------------------------------------------------------------
+* Unicast mode was originally implemented by Heiti of Boras Kommun with
+* general improvements as well as usability fixes and "forward"-porting by
+* Andreas Ericsson of OP5 AB.
+* ------------------------------------------------------------------------
+*
*****************************************************************************/
const char *progname = "check_dhcp";
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
+#if HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
#if defined( __linux__ )
#define DHCP_INFINITE_TIME 0xFFFFFFFF
#define DHCP_BROADCAST_FLAG 32768
+#define DHCP_UNICAST_FLAG 0
#define DHCP_SERVER_PORT 67
#define DHCP_CLIENT_PORT 68
#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */
#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */
+u_int8_t unicast = 0; /* unicast mode: mimic a DHCP relay */
+struct in_addr my_ip; /* our address (required for relay) */
+struct in_addr dhcp_ip; /* server to query (if in unicast mode) */
unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]="";
char network_interface_name[IFNAMSIZ]="eth0";
void print_help(void);
int get_hardware_address(int,char *);
+int get_ip_address(int,char *);
int send_dhcp_discover(int);
int get_dhcp_offer(int);
/* get hardware address of client machine */
get_hardware_address(dhcp_socket,network_interface_name);
+ if(unicast) /* get IP address of client machine */
+ get_ip_address(dhcp_socket,network_interface_name);
+
/* send DHCPDISCOVER packet */
send_dhcp_discover(dhcp_socket);
return OK;
}
+/* determines IP address of the client interface */
+int get_ip_address(int sock,char *interface_name){
+#if defined(SIOCGIFADDR)
+ struct ifreq ifr;
+
+ strncpy((char *)&ifr.ifr_name,interface_name,sizeof(ifr.ifr_name)-1);
+ ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';
+
+ if(ioctl(sock,SIOCGIFADDR,&ifr)<0){
+ printf(_("Error: Cannot determine IP address of interface %s\n"),
+ interface_name);
+ exit(STATE_UNKNOWN);
+ }
+
+ my_ip=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
+
+#else
+ printf(_("Error: Cannot get interface IP address on this platform.\n"));
+ exit(STATE_UNKNOWN);
+#endif
+
+ if(verbose)
+ printf(_("Pretending to be relay client %s\n"),inet_ntoa(my_ip));
+
+ return OK;
+ }
/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */
int send_dhcp_discover(int sock){
/* length of our hardware address */
discover_packet.hlen=ETHERNET_HARDWARE_ADDRESS_LENGTH;
- discover_packet.hops=0;
-
/* transaction id is supposed to be random */
srand(time(NULL));
packet_xid=random();
/*discover_packet.secs=htons(65535);*/
discover_packet.secs=0xFF;
- /* tell server it should broadcast its response */
- discover_packet.flags=htons(DHCP_BROADCAST_FLAG);
+ /*
+ * server needs to know if it should broadcast or unicast its response:
+ * 0x8000L == 32768 == 1 << 15 == broadcast, 0 == unicast
+ */
+ discover_packet.flags = unicast ? 0 : htons(DHCP_BROADCAST_FLAG);
/* our hardware address */
memcpy(discover_packet.chaddr,client_hardware_address,ETHERNET_HARDWARE_ADDRESS_LENGTH);
}
discover_packet.options[opts++]=DHCP_OPTION_END;
+ /* unicast fields */
+ if(unicast)
+ discover_packet.giaddr.s_addr = my_ip.s_addr;
+
+ /* see RFC 1542, 4.1.1 */
+ discover_packet.hops = unicast ? 1 : 0;
+
/* send the DHCPDISCOVER packet to broadcast address */
sockaddr_broadcast.sin_family=AF_INET;
sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT);
- sockaddr_broadcast.sin_addr.s_addr=INADDR_BROADCAST;
+ sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST;
bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero));
/* Set up the address we're going to bind to. */
bzero(&myname,sizeof(myname));
myname.sin_family=AF_INET;
- myname.sin_port=htons(DHCP_CLIENT_PORT);
- myname.sin_addr.s_addr=INADDR_ANY; /* listen on any address */
+ /* listen to DHCP server port if we're in unicast mode */
+ myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT);
+ myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY;
bzero(&myname.sin_zero,sizeof(myname.sin_zero));
/* create a socket for DHCP communications */
{"requestedip", required_argument,0,'r'},
{"timeout", required_argument,0,'t'},
{"interface", required_argument,0,'i'},
+ {"unicast", no_argument, 0,'u'},
{"verbose", no_argument, 0,'v'},
{"version", no_argument, 0,'V'},
{"help", no_argument, 0,'h'},
};
while(1){
- c=getopt_long(argc,argv,"+hVvt:s:r:t:i:",long_options,&option_index);
+ c=getopt_long(argc,argv,"+hVvt:s:r:t:i:u",long_options,&option_index);
i++;
switch(c){
case 's': /* DHCP server address */
- if(inet_aton(optarg,&ipaddress))
+ if(inet_aton(optarg,&ipaddress)){
add_requested_server(ipaddress);
+ inet_aton(optarg, &dhcp_ip);
+ if (verbose)
+ printf("querying %s\n",inet_ntoa(dhcp_ip));
+ }
/*
else
usage("Invalid server IP address\n");
break;
+ case 'u': /* unicast testing */
+ unicast=1;
+ break;
+
case 'V': /* version */
print_revision(progname,revision);
exit(STATE_OK);
printf (" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs"));
printf (" %s\n", "-i, --interface=STRING");
printf (" %s\n", _("Interface to to use for listening (i.e. eth0)"));
+ printf (" %s\n", "-u, --unicast");
+ printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s"));
return;
}
print_usage(void){
printf (_("Usage:"));
- printf ("%s [-s serverip] [-r requestedip] [-t timeout] [-i interface] [-v]\n",progname);
+ printf (" %s [-v] [-u] [-s serverip] [-r requestedip] [-t timeout]\n",progname);
+ printf (" [-i interface]\n");
return;
}