SF.net SVN: nagiosplug: [1762] nagiosplug/trunk

[email protected]
Newsgroups gmane.network.nagios.plugins.cvs
Message-ID <[email protected]>
Revision: 1762
          http://nagiosplug.svn.sourceforge.net/nagiosplug/?rev=1762&view=rev
Author:   hweiss
Date:     2007-07-25 17:02:28 -0700 (Wed, 25 Jul 2007)

Log Message:
-----------
New "-u, --unicast" option which gives check_dhcp the ability to mimic a
DHCP relay server in order to check remote subnets (Heiti Ernits and
Andreas Ericsson - 1218235)

Modified Paths:
--------------
    nagiosplug/trunk/NEWS
    nagiosplug/trunk/THANKS.in
    nagiosplug/trunk/configure.in
    nagiosplug/trunk/plugins-root/check_dhcp.c

Modified: nagiosplug/trunk/NEWS
===================================================================
--- nagiosplug/trunk/NEWS	2007-07-24 00:35:42 UTC (rev 1761)
+++ nagiosplug/trunk/NEWS	2007-07-26 00:02:28 UTC (rev 1762)
@@ -9,6 +9,8 @@
 	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

Modified: nagiosplug/trunk/THANKS.in
===================================================================
--- nagiosplug/trunk/THANKS.in	2007-07-24 00:35:42 UTC (rev 1761)
+++ nagiosplug/trunk/THANKS.in	2007-07-26 00:02:28 UTC (rev 1762)
@@ -223,3 +223,4 @@
 Aurelien Bompard
 Christoph Schell
 Andrew Elwell
+Heiti Ernits

Modified: nagiosplug/trunk/configure.in
===================================================================
--- nagiosplug/trunk/configure.in	2007-07-24 00:35:42 UTC (rev 1761)
+++ nagiosplug/trunk/configure.in	2007-07-26 00:02:28 UTC (rev 1762)
@@ -1450,6 +1450,9 @@
 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])

Modified: nagiosplug/trunk/plugins-root/check_dhcp.c
===================================================================
--- nagiosplug/trunk/plugins-root/check_dhcp.c	2007-07-24 00:35:42 UTC (rev 1761)
+++ nagiosplug/trunk/plugins-root/check_dhcp.c	2007-07-26 00:02:28 UTC (rev 1762)
@@ -33,6 +33,12 @@
 *
 * $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";
@@ -59,6 +65,9 @@
 #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__ )
 
@@ -190,6 +199,7 @@
 #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
@@ -197,6 +207,9 @@
 #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";
@@ -229,6 +242,7 @@
 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);
@@ -267,6 +281,9 @@
 	/* 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);
 
@@ -400,7 +417,33 @@
 	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){
 	dhcp_packet discover_packet;
@@ -421,8 +464,6 @@
 	/* 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();
@@ -435,8 +476,11 @@
 	/*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);
@@ -462,10 +506,17 @@
 	        }
 	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));
 
 
@@ -685,8 +736,9 @@
         /* 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 */
@@ -1035,6 +1087,7 @@
 		{"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'},
@@ -1042,7 +1095,7 @@
 	};
 
 	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++;
 
@@ -1063,8 +1116,12 @@
 		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");
@@ -1102,6 +1159,10 @@
 
 			break;
 
+		case 'u': /* unicast testing */
+			unicast=1;
+			break;
+
 		case 'V': /* version */
 			print_revision(progname,revision);
 			exit(STATE_OK);
@@ -1296,6 +1357,8 @@
   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;
 	}
@@ -1305,7 +1368,8 @@
 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;
 	}


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.