X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=plugins-root%2Fcheck_dhcp.c;h=2a1875c405431048c3099a5ec8834ffd72599dcd;hb=b48c2bdd59783197c93cde531e6e8b9747c0a88f;hp=db673893ffb1d50a018e76740ee717bdfa89a1a8;hpb=6f60c0ac81933976fdc2e7e763fc1d03312e3b3f;p=nagiosplug.git
diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c
index db67389..2a1875c 100644
--- a/plugins-root/check_dhcp.c
+++ b/plugins-root/check_dhcp.c
@@ -1,55 +1,47 @@
-/******************************************************************************
-*
+/*****************************************************************************
+*
* Nagios check_dhcp plugin
-*
+*
* License: GPL
* Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org)
-* Copyright (c) 2001-2006 Nagios Plugin Development Team
-*
-* Last Modified: $Date$
-*
+* Copyright (c) 2001-2007 Nagios Plugin Development Team
+*
* Description:
-*
+*
* This file contains the check_dhcp plugin
-*
-* This plugin tests the availability of DHCP servers on a network.
-*
-*
-* License Information:
-*
-* This program is free software; you can redistribute it and/or modify
+*
+* This plugin tests the availability of DHCP servers on a network.
+*
+* 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.
+*
+*
+* 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
-* the Free Software Foundation; either version 2 of the License, or
+* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-* $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.
-* ------------------------------------------------------------------------
-*
+* along with this program. If not, see .
+*
+*
*****************************************************************************/
const char *progname = "check_dhcp";
-const char *revision = "$Revision$";
-const char *copyright = "2001-2006";
+const char *copyright = "2001-2007";
const char *email = "nagiosplug-devel@lists.sourceforge.net";
#include "common.h"
#include "netutils.h"
#include "utils.h"
+#include
#include
#include
#include
@@ -83,8 +75,8 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net";
#elif defined(__sun__) || defined(__solaris__) || defined(__hpux__)
-#define INSAP 22
-#define OUTSAP 24
+#define INSAP 22
+#define OUTSAP 24
#include
#include
@@ -94,17 +86,17 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net";
#define bcopy(source, destination, length) memcpy(destination, source, length)
-#define AREA_SZ 5000 /* buffer length in bytes */
+#define AREA_SZ 5000 /* buffer length in bytes */
static u_long ctl_area[AREA_SZ];
static u_long dat_area[AREA_SZ];
static struct strbuf ctl = {AREA_SZ, 0, (char *)ctl_area};
static struct strbuf dat = {AREA_SZ, 0, (char *)dat_area};
-#define GOT_CTRL 1
-#define GOT_DATA 2
-#define GOT_BOTH 3
-#define GOT_INTR 4
-#define GOT_ERR 128
+#define GOT_CTRL 1
+#define GOT_DATA 2
+#define GOT_BOTH 3
+#define GOT_INTR 4
+#define GOT_ERR 128
#define u_int8_t uint8_t
#define u_int16_t uint16_t
@@ -199,7 +191,6 @@ typedef struct requested_server_struct{
#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
@@ -211,6 +202,7 @@ 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]="";
+unsigned char *user_specified_mac=NULL;
char network_interface_name[IFNAMSIZ]="eth0";
@@ -226,7 +218,7 @@ dhcp_offer *dhcp_offer_list=NULL;
requested_server *requested_server_list=NULL;
int valid_responses=0; /* number of valid DHCPOFFERs we received */
-int requested_servers=0;
+int requested_servers=0;
int requested_responses=0;
int request_specific_address=FALSE;
@@ -241,6 +233,9 @@ int validate_arguments(void);
void print_usage(void);
void print_help(void);
+void resolve_host(const char *in,struct in_addr *out);
+unsigned char *mac_aton(const char *);
+void print_hardware_address(const unsigned char *);
int get_hardware_address(int,char *);
int get_ip_address(int,char *);
@@ -264,22 +259,28 @@ int main(int argc, char **argv){
int dhcp_socket;
int result = STATE_UNKNOWN;
- /* this plugin almost certainly needs root permissions. */
- np_warn_if_not_root();
-
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
+ /* Parse extra opts if any */
+ argv=np_extra_opts(&argc, argv, progname);
+
if(process_arguments(argc,argv)!=OK){
usage4 (_("Could not parse arguments"));
}
+ /* this plugin almost certainly needs root permissions. */
+ np_warn_if_not_root();
+
/* create socket for DHCP communications */
dhcp_socket=create_dhcp_socket();
/* get hardware address of client machine */
- get_hardware_address(dhcp_socket,network_interface_name);
+ if(user_specified_mac!=NULL)
+ memcpy(client_hardware_address,user_specified_mac,6);
+ else
+ get_hardware_address(dhcp_socket,network_interface_name);
if(unicast) /* get IP address of client machine */
get_ip_address(dhcp_socket,network_interface_name);
@@ -308,14 +309,12 @@ int main(int argc, char **argv){
/* determines hardware address on client machine */
int get_hardware_address(int sock,char *interface_name){
- int i;
-
#if defined(__linux__)
struct ifreq ifr;
strncpy((char *)&ifr.ifr_name,interface_name,sizeof(ifr.ifr_name)-1);
ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';
-
+
/* try and grab hardware address of requested interface */
if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){
printf(_("Error: Could not get hardware address of interface '%s'\n"),interface_name);
@@ -379,7 +378,7 @@ int get_hardware_address(int sock,char *interface_name){
unit = atoi(p) ;
*p = '\0' ;
strncat(dev, interface_name, 6) ;
- }
+ }
else{
printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name);
exit(STATE_UNKNOWN);
@@ -404,16 +403,12 @@ int get_hardware_address(int sock,char *interface_name){
/* Kompf 2000-2003 */
#else
- printf(_("Error: can't get MAC address for this architecture.\n"));
+ printf(_("Error: can't get MAC address for this architecture. Use the --mac option.\n"));
exit(STATE_UNKNOWN);
#endif
- if(verbose){
- printf(_("Hardware address: "));
- for (i=0; i<6; ++i)
- printf("%2.2x", client_hardware_address[i]);
- printf( "\n");
- }
+ if(verbose)
+ print_hardware_address(client_hardware_address);
return OK;
}
@@ -509,7 +504,7 @@ int send_dhcp_discover(int sock){
opts += sizeof(requested_address);
}
discover_packet.options[opts++]=DHCP_OPTION_END;
-
+
/* unicast fields */
if(unicast)
discover_packet.giaddr.s_addr = my_ip.s_addr;
@@ -536,7 +531,7 @@ int send_dhcp_discover(int sock){
/* send the DHCPDISCOVER packet out */
send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast);
- if(verbose)
+ if(verbose)
printf("\n\n");
return OK;
@@ -565,7 +560,7 @@ int get_dhcp_offer(int sock){
if((current_time-start_time)>=dhcpoffer_timeout)
break;
- if(verbose)
+ if(verbose)
printf("\n\n");
bzero(&source,sizeof(source));
@@ -574,7 +569,7 @@ int get_dhcp_offer(int sock){
result=OK;
result=receive_dhcp_packet(&offer_packet,sizeof(offer_packet),sock,dhcpoffer_timeout,&source);
-
+
if(result!=OK){
if(verbose)
printf(_("Result=ERROR\n"));
@@ -582,7 +577,7 @@ int get_dhcp_offer(int sock){
continue;
}
else{
- if(verbose)
+ if(verbose)
printf(_("Result=OK\n"));
responses++;
@@ -627,7 +622,7 @@ int get_dhcp_offer(int sock){
printf("\n");
if(result==ERROR){
- if(verbose)
+ if(verbose)
printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n"));
continue;
@@ -661,7 +656,7 @@ int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in
result=sendto(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)dest,sizeof(*dest));
- if(verbose)
+ if(verbose)
printf(_("send_dhcp_packet result: %d\n"),result);
if(result<0)
@@ -767,7 +762,7 @@ int create_dhcp_socket(void){
}
/* set the broadcast option - we need this to listen to DHCP broadcast messages */
- if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){
+ if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){
printf(_("Error: Could not set broadcast option on DHCP socket!\n"));
exit(STATE_UNKNOWN);
}
@@ -854,7 +849,7 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
/* get option length */
option_length=offer_packet->options[x++];
- if(verbose)
+ if(verbose)
printf("Option: %d (0x%02X)\n",option_type,option_length);
/* get option data */
@@ -955,7 +950,7 @@ int free_requested_server_list(void){
next_server=this_server->next;
free(this_server);
}
-
+
return OK;
}
@@ -980,7 +975,7 @@ int get_results(void){
/* get max lease time we were offered */
if(temp_offer->lease_time>max_lease_time || temp_offer->lease_time==DHCP_INFINITE_TIME)
max_lease_time=temp_offer->lease_time;
-
+
/* see if we got the address we requested */
if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address)))
received_requested_address=TRUE;
@@ -990,7 +985,7 @@ int get_results(void){
if(verbose){
printf(_("DHCP Server Match: Offerer=%s"),inet_ntoa(temp_offer->server_address));
printf(_(" Requested=%s"),inet_ntoa(temp_server->server_address));
- if(temp_server->answered)
+ if(temp_server->answered)
printf(_(" (duplicate)"));
printf(_("\n"));
}
@@ -1012,7 +1007,7 @@ int get_results(void){
/* get max lease time we were offered */
if(temp_offer->lease_time>max_lease_time || temp_offer->lease_time==DHCP_INFINITE_TIME)
max_lease_time=temp_offer->lease_time;
-
+
/* see if we got the address we requested */
if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address)))
received_requested_address=TRUE;
@@ -1088,15 +1083,15 @@ int process_arguments(int argc, char **argv){
int call_getopt(int argc, char **argv){
int c=0;
int i=0;
- struct in_addr ipaddress;
int option_index = 0;
static struct option long_options[] =
- {
+ {
{"serverip", required_argument,0,'s'},
{"requestedip", required_argument,0,'r'},
{"timeout", required_argument,0,'t'},
{"interface", required_argument,0,'i'},
+ {"mac", required_argument,0,'m'},
{"unicast", no_argument, 0,'u'},
{"verbose", no_argument, 0,'v'},
{"version", no_argument, 0,'V'},
@@ -1105,7 +1100,7 @@ int call_getopt(int argc, char **argv){
};
while(1){
- c=getopt_long(argc,argv,"+hVvt:s:r:t:i:u",long_options,&option_index);
+ c=getopt_long(argc,argv,"+hVvt:s:r:t:i:m:u",long_options,&option_index);
i++;
@@ -1126,27 +1121,13 @@ int call_getopt(int argc, char **argv){
switch(c){
case 's': /* DHCP server address */
- 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");
- */
+ resolve_host(optarg,&dhcp_ip);
+ add_requested_server(dhcp_ip);
break;
case 'r': /* address we are requested from DHCP servers */
- if(inet_aton(optarg,&ipaddress)){
- requested_address=ipaddress;
- request_specific_address=TRUE;
- }
- /*
- else
- usage("Invalid requested IP address\n");
- */
+ resolve_host(optarg,&requested_address);
+ request_specific_address=TRUE;
break;
case 't': /* timeout */
@@ -1162,6 +1143,15 @@ int call_getopt(int argc, char **argv){
*/
break;
+ case 'm': /* MAC address */
+
+ if((user_specified_mac=mac_aton(optarg)) == NULL)
+ usage("Cannot parse MAC address.\n");
+ if(verbose)
+ print_hardware_address(user_specified_mac);
+
+ break;
+
case 'i': /* interface name */
strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1);
@@ -1174,7 +1164,7 @@ int call_getopt(int argc, char **argv){
break;
case 'V': /* version */
- print_revision(progname,revision);
+ print_revision(progname, NP_VERSION);
exit(STATE_OK);
case 'h': /* help */
@@ -1312,7 +1302,7 @@ static int dl_bind(int fd, int sap, u_char *addr){
/***********************************************************************
* interface:
- * function mac_addr_dlpi - get the mac address of the interface with
+ * function mac_addr_dlpi - get the mac address of the interface with
* type dev (eg lnc, hme) and unit (0, 1 ..)
*
* parameter: addr: an array of six bytes, has to be allocated by the caller
@@ -1341,23 +1331,71 @@ long mac_addr_dlpi( const char *dev, int unit, u_char *addr){
#endif
+/* resolve host name or die (TODO: move this to netutils.c!) */
+void resolve_host(const char *in,struct in_addr *out){
+ struct addrinfo hints, *ai;
+
+ memset(&hints,0,sizeof(hints));
+ hints.ai_family=PF_INET;
+ if (getaddrinfo(in,NULL,&hints,&ai) != 0)
+ usage_va(_("Invalid hostname/address - %s"),optarg);
+
+ memcpy(out,&((struct sockaddr_in *)ai->ai_addr)->sin_addr,sizeof(*out));
+ freeaddrinfo(ai);
+ }
+
+
+/* parse MAC address string, return 6 bytes (unterminated) or NULL */
+unsigned char *mac_aton(const char *string){
+ static unsigned char result[6];
+ char tmp[3];
+ unsigned i, j;
+
+ for(i=0, j=0; string[i] != '\0' && j < sizeof(result); i++){
+ /* ignore ':' and any other non-hex character */
+ if(!isxdigit(string[i]) || !isxdigit(string[i+1]))
+ continue;
+ tmp[0]=string[i];
+ tmp[1]=string[i+1];
+ tmp[2]='\0';
+ result[j]=strtol(tmp,(char **)NULL,16);
+ i++;
+ j++;
+ }
+
+ return (j==6) ? result : NULL;
+ }
+
+
+void print_hardware_address(const unsigned char *address){
+ int i;
+
+ printf(_("Hardware address: "));
+ for (i=0; i<5; i++)
+ printf("%2.2x:", address[i]);
+ printf("%2.2x", address[i]);
+ putchar('\n');
+ }
+
+
/* print usage help */
void print_help(void){
- print_revision(progname,revision);
+ print_revision(progname, NP_VERSION);
printf("Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org)\n");
printf (COPYRIGHT, copyright, email);
-
+
printf("%s\n", _("This plugin tests the availability of DHCP servers on a network."));
printf ("\n\n");
print_usage();
- printf (_(UT_HELP_VRSN));
+ printf (UT_HELP_VRSN);
+ printf (UT_EXTRA_OPTS);
- printf (_(UT_VERBOSE));
+ printf (UT_VERBOSE);
printf (" %s\n", "-s, --serverip=IPADDRESS");
printf (" %s\n", _("IP address of DHCP server that we must hear from"));
@@ -1367,20 +1405,23 @@ void print_help(void){
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", "-m, --mac=STRING");
+ printf (" %s\n", _("MAC address to use in the DHCP request"));
printf (" %s\n", "-u, --unicast");
printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s"));
+ printf (UT_SUPPORT);
return;
}
void
print_usage(void){
-
- printf (_("Usage:"));
+
+ printf ("%s\n", _("Usage:"));
printf (" %s [-v] [-u] [-s serverip] [-r requestedip] [-t timeout]\n",progname);
- printf (" [-i interface]\n");
-
+ printf (" [-i interface] [-m mac]\n");
+
return;
}