X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=plugins-root%2Fcheck_dhcp.c;h=bdd348f20dc50c54a3e0872ba0d1e6cfdf21c6b2;hb=c326b4dc1dd42a50875578f0e7580125a1ddc03c;hp=993531cd73cad20bc528bb84db404e02892915e1;hpb=9b2a0c3d29395059ac380cffd3454535b1692a50;p=nagiosplug.git
diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c
index 993531c..bdd348f 100644
--- a/plugins-root/check_dhcp.c
+++ b/plugins-root/check_dhcp.c
@@ -1,49 +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$
-*
+* 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
@@ -59,6 +57,9 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net";
#include
#include
#include
+#if HAVE_SYS_SOCKIO_H
+#include
+#endif
#if defined( __linux__ )
@@ -74,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
@@ -85,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
@@ -185,6 +186,7 @@ typedef struct requested_server_struct{
#define DHCP_OPTION_SERVER_IDENTIFIER 54
#define DHCP_OPTION_RENEWAL_TIME 58
#define DHCP_OPTION_REBINDING_TIME 59
+#define DHCP_OPTION_END 255
#define DHCP_INFINITE_TIME 0xFFFFFFFF
@@ -196,7 +198,11 @@ typedef struct requested_server_struct{
#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]="";
+unsigned char *user_specified_mac=NULL;
char network_interface_name[IFNAMSIZ]="eth0";
@@ -212,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;
@@ -227,7 +233,11 @@ 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 *);
int send_dhcp_discover(int);
int get_dhcp_offer(int);
@@ -252,16 +262,28 @@ int main(int argc, char **argv){
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);
/* send DHCPDISCOVER packet */
send_dhcp_discover(dhcp_socket);
@@ -287,13 +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));
-
+ 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);
@@ -357,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);
@@ -382,25 +403,48 @@ 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;
}
+/* 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;
struct sockaddr_in sockaddr_broadcast;
+ unsigned short opts;
/* clear the packet data structure */
@@ -416,9 +460,10 @@ 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 */
+ /*
+ * transaction ID is supposed to be random. We won't use the address so
+ * we don't care about high entropy here. time(2) is good enough.
+ */
srand(time(NULL));
packet_xid=random();
discover_packet.xid=htonl(packet_xid);
@@ -430,8 +475,11 @@ int send_dhcp_discover(int sock){
/*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);
@@ -442,28 +490,38 @@ int send_dhcp_discover(int sock){
discover_packet.options[2]='\x53';
discover_packet.options[3]='\x63';
+ opts = 4;
/* DHCP message type is embedded in options field */
- discover_packet.options[4]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */
- discover_packet.options[5]='\x01'; /* DHCP message option length in bytes */
- discover_packet.options[6]=DHCPDISCOVER;
+ discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */
+ discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */
+ discover_packet.options[opts++]=DHCPDISCOVER;
/* the IP address we're requesting */
if(request_specific_address==TRUE){
- discover_packet.options[7]=DHCP_OPTION_REQUESTED_ADDRESS;
- discover_packet.options[8]='\x04';
- memcpy(&discover_packet.options[9],&requested_address,sizeof(requested_address));
+ discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS;
+ discover_packet.options[opts++]='\x04';
+ memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address));
+ opts += sizeof(requested_address);
}
-
+ 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));
if(verbose){
printf(_("DHCPDISCOVER to %s port %d\n"),inet_ntoa(sockaddr_broadcast.sin_addr),ntohs(sockaddr_broadcast.sin_port));
- printf("DHCPDISCOVER XID: %lu (0x%X)\n",ntohl(discover_packet.xid),ntohl(discover_packet.xid));
+ printf("DHCPDISCOVER XID: %u (0x%X)\n",ntohl(discover_packet.xid),ntohl(discover_packet.xid));
printf("DHCDISCOVER ciaddr: %s\n",inet_ntoa(discover_packet.ciaddr));
printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr));
printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr));
@@ -473,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;
@@ -488,7 +546,6 @@ int get_dhcp_offer(int sock){
struct sockaddr_in source;
struct sockaddr_in via;
int result=OK;
- int timeout=1;
int responses=0;
int x;
time_t start_time;
@@ -503,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));
@@ -512,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"));
@@ -520,7 +577,7 @@ int get_dhcp_offer(int sock){
continue;
}
else{
- if(verbose)
+ if(verbose)
printf(_("Result=OK\n"));
responses++;
@@ -538,13 +595,13 @@ int get_dhcp_offer(int sock){
if(verbose){
printf(_("DHCPOFFER from IP address %s"),inet_ntoa(source.sin_addr));
printf(_(" via %s\n"),inet_ntoa(via.sin_addr));
- printf("DHCPOFFER XID: %lu (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid));
+ printf("DHCPOFFER XID: %u (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid));
}
/* check packet xid to see if its the same as the one we used in the discover packet */
if(ntohl(offer_packet.xid)!=packet_xid){
if(verbose)
- printf(_("DHCPOFFER XID (%lu) did not match DHCPDISCOVER XID (%lu) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid);
+ printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid);
continue;
}
@@ -565,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;
@@ -595,12 +652,11 @@ int get_dhcp_offer(int sock){
/* sends a DHCP packet */
int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest){
- struct sockaddr_in myname;
int result;
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)
@@ -615,22 +671,26 @@ int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in
int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){
struct timeval tv;
fd_set readfds;
+ fd_set oobfds;
int recv_result;
socklen_t address_size;
struct sockaddr_in source_address;
+ int nfound;
/* wait for data to arrive (up time timeout) */
tv.tv_sec=timeout;
tv.tv_usec=0;
FD_ZERO(&readfds);
+ FD_ZERO(&oobfds);
FD_SET(sock,&readfds);
- select(sock+1,&readfds,NULL,NULL,&tv);
+ FD_SET(sock,&oobfds);
+ nfound = select(sock+1,&readfds,NULL,&oobfds,&tv);
/* make sure some data has arrived */
if(!FD_ISSET(sock,&readfds)){
if(verbose)
- printf(_("No (more) data received\n"));
+ printf(_("No (more) data received (nfound: %d)\n"), nfound);
return ERROR;
}
@@ -679,8 +739,9 @@ int create_dhcp_socket(void){
/* 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 */
@@ -701,21 +762,23 @@ 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);
}
/* bind socket to interface */
#if defined(__linux__)
- strncpy(interface.ifr_ifrn.ifrn_name,network_interface_name,IFNAMSIZ);
+ strncpy(interface.ifr_ifrn.ifrn_name,network_interface_name,IFNAMSIZ-1);
+ interface.ifr_ifrn.ifrn_name[IFNAMSIZ-1]='\0';
if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){
printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name);
exit(STATE_UNKNOWN);
}
#else
- strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ);
+ strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1);
+ interface.ifr_name[IFNAMSIZ-1]='\0';
#endif
/* bind the socket */
@@ -786,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 */
@@ -887,7 +950,7 @@ int free_requested_server_list(void){
next_server=this_server->next;
free(this_server);
}
-
+
return OK;
}
@@ -912,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;
@@ -922,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"));
}
@@ -944,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;
@@ -1020,15 +1083,16 @@ 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'},
{"help", no_argument, 0,'h'},
@@ -1036,7 +1100,7 @@ int call_getopt(int argc, char **argv){
};
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:m:u",long_options,&option_index);
i++;
@@ -1057,23 +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);
- /*
- 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 */
@@ -1089,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);
@@ -1096,8 +1159,12 @@ int call_getopt(int argc, char **argv){
break;
+ case 'u': /* unicast testing */
+ unicast=1;
+ break;
+
case 'V': /* version */
- print_revision(progname,revision);
+ print_revision(progname, NP_VERSION);
exit(STATE_OK);
case 'h': /* help */
@@ -1235,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
@@ -1264,14 +1331,61 @@ 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");
@@ -1279,6 +1393,7 @@ void print_help(void){
print_usage();
printf (_(UT_HELP_VRSN));
+ printf (_(UT_EXTRA_OPTS));
printf (_(UT_VERBOSE));
@@ -1290,17 +1405,29 @@ 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"));
+
+#ifdef NP_EXTRA_OPTS
+ printf ("\n");
+ printf ("%s\n", _("Notes:"));
+ printf (_(UT_EXTRA_OPTS_NOTES));
+#endif
+ printf (_(UT_SUPPORT));
return;
}
void
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] [-m mac]\n");
+
return;
}