summaryrefslogtreecommitdiffstats
path: root/plugins-root/check_dhcp.c
diff options
context:
space:
mode:
authorJan Wagner <waja@cyconet.org>2023-10-17 13:39:37 +0200
committerJan Wagner <waja@cyconet.org>2023-10-17 13:39:37 +0200
commit2a047014385022c8dc06dad4da0428db14898689 (patch)
tree00abea46325decf0c72870ee8f9ec1472e8e5344 /plugins-root/check_dhcp.c
parentf39211c26408af582121f519d89c8abf70e6d437 (diff)
parente23a75d954311b3be429a9020e4d317b89615ee7 (diff)
downloadmonitoring-plugins-2a04701.tar.gz
Merge branch 'master' of github.com:monitoring-plugins/monitoring-plugins
Diffstat (limited to 'plugins-root/check_dhcp.c')
-rw-r--r--plugins-root/check_dhcp.c738
1 files changed, 376 insertions, 362 deletions
diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c
index 2d22619b..6b07df51 100644
--- a/plugins-root/check_dhcp.c
+++ b/plugins-root/check_dhcp.c
@@ -1,40 +1,40 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dhcp plugin 3 * Monitoring check_dhcp plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org) 6 * Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org)
7* Copyright (c) 2001-2007 Monitoring Plugins Development Team 7 * Copyright (c) 2001-2007 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_dhcp plugin 11 * This file contains the check_dhcp plugin
12* 12 *
13* This plugin tests the availability of DHCP servers on a network. 13 * This plugin tests the availability of DHCP servers on a network.
14* 14 *
15* Unicast mode was originally implemented by Heiti of Boras Kommun with 15 * Unicast mode was originally implemented by Heiti of Boras Kommun with
16* general improvements as well as usability fixes and "forward"-porting by 16 * general improvements as well as usability fixes and "forward"-porting by
17* Andreas Ericsson of OP5 AB. 17 * Andreas Ericsson of OP5 AB.
18* 18 *
19* 19 *
20* This program is free software: you can redistribute it and/or modify 20 * This program is free software: you can redistribute it and/or modify
21* it under the terms of the GNU General Public License as published by 21 * it under the terms of the GNU General Public License as published by
22* the Free Software Foundation, either version 3 of the License, or 22 * the Free Software Foundation, either version 3 of the License, or
23* (at your option) any later version. 23 * (at your option) any later version.
24* 24 *
25* This program is distributed in the hope that it will be useful, 25 * This program is distributed in the hope that it will be useful,
26* but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28* GNU General Public License for more details. 28 * GNU General Public License for more details.
29* 29 *
30* You should have received a copy of the GNU General Public License 30 * You should have received a copy of the GNU General Public License
31* along with this program. If not, see <http://www.gnu.org/licenses/>. 31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32* 32 *
33* 33 *
34*****************************************************************************/ 34 *****************************************************************************/
35 35
36const char *progname = "check_dhcp"; 36const char *progname = "check_dhcp";
37const char *copyright = "2001-2007"; 37const char *copyright = "2001-2023";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include "common.h" 40#include "common.h"
@@ -57,9 +57,10 @@ const char *email = "devel@monitoring-plugins.org";
57#include <netinet/in.h> 57#include <netinet/in.h>
58#include <net/if.h> 58#include <net/if.h>
59#include <arpa/inet.h> 59#include <arpa/inet.h>
60
60#if HAVE_SYS_SOCKIO_H 61#if HAVE_SYS_SOCKIO_H
61#include <sys/sockio.h> 62#include <sys/sockio.h>
62#endif 63#endif // HAVE_SYS_SOCKIO_H
63 64
64#if defined( __linux__ ) 65#if defined( __linux__ )
65 66
@@ -98,10 +99,6 @@ static struct strbuf dat = {AREA_SZ, 0, (char *)dat_area};
98#define GOT_INTR 4 99#define GOT_INTR 4
99#define GOT_ERR 128 100#define GOT_ERR 128
100 101
101#define u_int8_t uint8_t
102#define u_int16_t uint16_t
103#define u_int32_t uint32_t
104
105static int get_msg(int); 102static int get_msg(int);
106static int check_ctrl(int); 103static int check_ctrl(int);
107static int put_ctrl(int, int, int); 104static int put_ctrl(int, int, int);
@@ -110,7 +107,7 @@ static int dl_open(const char *, int, int *);
110static int dl_bind(int, int, u_char *); 107static int dl_bind(int, int, u_char *);
111long mac_addr_dlpi( const char *, int, u_char *); 108long mac_addr_dlpi( const char *, int, u_char *);
112 109
113#endif 110#endif // __sun__ || __solaris__ || __hpux
114 111
115 112
116 113
@@ -119,9 +116,6 @@ long mac_addr_dlpi( const char *, int, u_char *);
119#define OK 0 116#define OK 0
120#define ERROR -1 117#define ERROR -1
121 118
122#define FALSE 0
123#define TRUE 1
124
125 119
126/**** DHCP definitions ****/ 120/**** DHCP definitions ****/
127 121
@@ -132,39 +126,40 @@ long mac_addr_dlpi( const char *, int, u_char *);
132 126
133 127
134typedef struct dhcp_packet_struct{ 128typedef struct dhcp_packet_struct{
135 u_int8_t op; /* packet type */ 129 uint8_t op; /* packet type */
136 u_int8_t htype; /* type of hardware address for this machine (Ethernet, etc) */ 130 uint8_t htype; /* type of hardware address for this machine (Ethernet, etc) */
137 u_int8_t hlen; /* length of hardware address (of this machine) */ 131 uint8_t hlen; /* length of hardware address (of this machine) */
138 u_int8_t hops; /* hops */ 132 uint8_t hops; /* hops */
139 u_int32_t xid; /* random transaction id number - chosen by this machine */ 133 uint32_t xid; /* random transaction id number - chosen by this machine */
140 u_int16_t secs; /* seconds used in timing */ 134 uint16_t secs; /* seconds used in timing */
141 u_int16_t flags; /* flags */ 135 uint16_t flags; /* flags */
142 struct in_addr ciaddr; /* IP address of this machine (if we already have one) */ 136 struct in_addr ciaddr; /* IP address of this machine (if we already have one) */
143 struct in_addr yiaddr; /* IP address of this machine (offered by the DHCP server) */ 137 struct in_addr yiaddr; /* IP address of this machine (offered by the DHCP server) */
144 struct in_addr siaddr; /* IP address of next server */ 138 struct in_addr siaddr; /* IP address of next server */
145 struct in_addr giaddr; /* IP address of DHCP relay */ 139 struct in_addr giaddr; /* IP address of DHCP relay */
146 unsigned char chaddr [MAX_DHCP_CHADDR_LENGTH]; /* hardware address of this machine */ 140 unsigned char chaddr [MAX_DHCP_CHADDR_LENGTH]; /* hardware address of this machine */
147 char sname [MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */ 141 char sname [MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */
148 char file [MAX_DHCP_FILE_LENGTH]; /* boot file name (used for diskless booting?) */ 142 char file [MAX_DHCP_FILE_LENGTH]; /* boot file name (used for diskless booting?) */
149 char options[MAX_DHCP_OPTIONS_LENGTH]; /* options */ 143 char options[MAX_DHCP_OPTIONS_LENGTH]; /* options */
150 }dhcp_packet; 144}dhcp_packet;
151 145
152 146
153typedef struct dhcp_offer_struct{ 147typedef struct dhcp_offer_struct{
154 struct in_addr server_address; /* address of DHCP server that sent this offer */ 148 struct in_addr server_address; /* address of DHCP server that sent this offer */
155 struct in_addr offered_address; /* the IP address that was offered to us */ 149 struct in_addr offered_address; /* the IP address that was offered to us */
156 u_int32_t lease_time; /* lease time in seconds */ 150 uint32_t lease_time; /* lease time in seconds */
157 u_int32_t renewal_time; /* renewal time in seconds */ 151 uint32_t renewal_time; /* renewal time in seconds */
158 u_int32_t rebinding_time; /* rebinding time in seconds */ 152 uint32_t rebinding_time; /* rebinding time in seconds */
153 bool desired; /* is this offer desired (necessary in exclusive mode) */
159 struct dhcp_offer_struct *next; 154 struct dhcp_offer_struct *next;
160 }dhcp_offer; 155}dhcp_offer;
161 156
162 157
163typedef struct requested_server_struct{ 158typedef struct requested_server_struct{
164 struct in_addr server_address; 159 struct in_addr server_address;
165 int answered; 160 bool answered;
166 struct requested_server_struct *next; 161 struct requested_server_struct *next;
167 }requested_server; 162}requested_server;
168 163
169 164
170#define BOOTREQUEST 1 165#define BOOTREQUEST 1
@@ -198,7 +193,8 @@ typedef struct requested_server_struct{
198#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */ 193#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */
199#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */ 194#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */
200 195
201u_int8_t unicast = 0; /* unicast mode: mimic a DHCP relay */ 196bool unicast = false; /* unicast mode: mimic a DHCP relay */
197bool exclusive = false; /* exclusive mode aka "rogue DHCP server detection" */
202struct in_addr my_ip; /* our address (required for relay) */ 198struct in_addr my_ip; /* our address (required for relay) */
203struct in_addr dhcp_ip; /* server to query (if in unicast mode) */ 199struct in_addr dhcp_ip; /* server to query (if in unicast mode) */
204unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]=""; 200unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]="";
@@ -206,11 +202,11 @@ unsigned char *user_specified_mac=NULL;
206 202
207char network_interface_name[IFNAMSIZ]="eth0"; 203char network_interface_name[IFNAMSIZ]="eth0";
208 204
209u_int32_t packet_xid=0; 205uint32_t packet_xid=0;
210 206
211u_int32_t dhcp_lease_time=0; 207uint32_t dhcp_lease_time=0;
212u_int32_t dhcp_renewal_time=0; 208uint32_t dhcp_renewal_time=0;
213u_int32_t dhcp_rebinding_time=0; 209uint32_t dhcp_rebinding_time=0;
214 210
215int dhcpoffer_timeout=2; 211int dhcpoffer_timeout=2;
216 212
@@ -221,8 +217,8 @@ int valid_responses=0; /* number of valid DHCPOFFERs we received */
221int requested_servers=0; 217int requested_servers=0;
222int requested_responses=0; 218int requested_responses=0;
223 219
224int request_specific_address=FALSE; 220bool request_specific_address=false;
225int received_requested_address=FALSE; 221bool received_requested_address=false;
226int verbose=0; 222int verbose=0;
227struct in_addr requested_address; 223struct in_addr requested_address;
228 224
@@ -268,7 +264,7 @@ int main(int argc, char **argv){
268 264
269 if(process_arguments(argc,argv)!=OK){ 265 if(process_arguments(argc,argv)!=OK){
270 usage4 (_("Could not parse arguments")); 266 usage4 (_("Could not parse arguments"));
271 } 267 }
272 268
273 /* create socket for DHCP communications */ 269 /* create socket for DHCP communications */
274 dhcp_socket=create_dhcp_socket(); 270 dhcp_socket=create_dhcp_socket();
@@ -299,7 +295,7 @@ int main(int argc, char **argv){
299 free_requested_server_list(); 295 free_requested_server_list();
300 296
301 return result; 297 return result;
302 } 298}
303 299
304 300
305 301
@@ -314,83 +310,83 @@ int get_hardware_address(int sock,char *interface_name){
314 310
315 /* try and grab hardware address of requested interface */ 311 /* try and grab hardware address of requested interface */
316 if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){ 312 if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){
317 printf(_("Error: Could not get hardware address of interface '%s'\n"),interface_name); 313 printf(_("Error: Could not get hardware address of interface '%s'\n"),interface_name);
318 exit(STATE_UNKNOWN); 314 exit(STATE_UNKNOWN);
319 } 315 }
320 316
321 memcpy(&client_hardware_address[0],&ifr.ifr_hwaddr.sa_data,6); 317 memcpy(&client_hardware_address[0],&ifr.ifr_hwaddr.sa_data,6);
322 318
323#elif defined(__bsd__) 319#elif defined(__bsd__)
324 /* King 2004 see ACKNOWLEDGEMENTS */ 320 /* King 2004 see ACKNOWLEDGEMENTS */
325 321
326 size_t len; 322 size_t len;
327 int mib[6]; 323 int mib[6];
328 char *buf; 324 char *buf;
329 unsigned char *ptr; 325 unsigned char *ptr;
330 struct if_msghdr *ifm; 326 struct if_msghdr *ifm;
331 struct sockaddr_dl *sdl; 327 struct sockaddr_dl *sdl;
332 328
333 mib[0] = CTL_NET; 329 mib[0] = CTL_NET;
334 mib[1] = AF_ROUTE; 330 mib[1] = AF_ROUTE;
335 mib[2] = 0; 331 mib[2] = 0;
336 mib[3] = AF_LINK; 332 mib[3] = AF_LINK;
337 mib[4] = NET_RT_IFLIST; 333 mib[4] = NET_RT_IFLIST;
338 334
339 if((mib[5] = if_nametoindex(interface_name)) == 0){ 335 if((mib[5] = if_nametoindex(interface_name)) == 0){
340 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno)); 336 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno));
341 exit(STATE_UNKNOWN); 337 exit(STATE_UNKNOWN);
342 } 338 }
343 339
344 if(sysctl(mib, 6, NULL, &len, NULL, 0) < 0){ 340 if(sysctl(mib, 6, NULL, &len, NULL, 0) < 0){
345 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno)); 341 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno));
346 exit(STATE_UNKNOWN); 342 exit(STATE_UNKNOWN);
347 } 343 }
348 344
349 if((buf = malloc(len)) == NULL){ 345 if((buf = malloc(len)) == NULL){
350 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno)); 346 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno));
351 exit(4); 347 exit(4);
352 } 348 }
353 349
354 if(sysctl(mib, 6, buf, &len, NULL, 0) < 0){ 350 if(sysctl(mib, 6, buf, &len, NULL, 0) < 0){
355 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno)); 351 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno));
356 exit(STATE_UNKNOWN); 352 exit(STATE_UNKNOWN);
357 } 353 }
358 354
359 ifm = (struct if_msghdr *)buf; 355 ifm = (struct if_msghdr *)buf;
360 sdl = (struct sockaddr_dl *)(ifm + 1); 356 sdl = (struct sockaddr_dl *)(ifm + 1);
361 ptr = (unsigned char *)LLADDR(sdl); 357 ptr = (unsigned char *)LLADDR(sdl);
362 memcpy(&client_hardware_address[0], ptr, 6) ; 358 memcpy(&client_hardware_address[0], ptr, 6) ;
363 /* King 2004 */ 359 /* King 2004 */
364 360
365#elif defined(__sun__) || defined(__solaris__) 361#elif defined(__sun__) || defined(__solaris__)
366 362
367 /* Kompf 2000-2003 see ACKNOWLEDGEMENTS */ 363 /* Kompf 2000-2003 see ACKNOWLEDGEMENTS */
368 long stat; 364 long stat;
369 char dev[20] = "/dev/"; 365 char dev[20] = "/dev/";
370 char *p; 366 char *p;
371 int unit; 367 int unit;
372 368
373 /* get last number from interfacename, eg lnc0, e1000g0*/ 369 /* get last number from interfacename, eg lnc0, e1000g0*/
374 int i; 370 int i;
375 p = interface_name + strlen(interface_name) -1; 371 p = interface_name + strlen(interface_name) -1;
376 for(i = strlen(interface_name) -1; i > 0; p--) { 372 for(i = strlen(interface_name) -1; i > 0; p--) {
377 if(isalpha(*p)) 373 if(isalpha(*p))
378 break; 374 break;
379 } 375 }
380 p++; 376 p++;
381 if( p != interface_name ){ 377 if( p != interface_name ){
382 unit = atoi(p) ; 378 unit = atoi(p) ;
383 strncat(dev, interface_name, 6) ; 379 strncat(dev, interface_name, 6) ;
384 } 380 }
385 else{ 381 else{
386 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name); 382 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name);
387 exit(STATE_UNKNOWN); 383 exit(STATE_UNKNOWN);
388 } 384 }
389 stat = mac_addr_dlpi(dev, unit, client_hardware_address); 385 stat = mac_addr_dlpi(dev, unit, client_hardware_address);
390 if(stat != 0){ 386 if(stat != 0){
391 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 387 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
392 exit(STATE_UNKNOWN); 388 exit(STATE_UNKNOWN);
393 } 389 }
394 390
395#elif defined(__hpux__) 391#elif defined(__hpux__)
396 392
@@ -402,8 +398,8 @@ int get_hardware_address(int sock,char *interface_name){
402 if(stat != 0){ 398 if(stat != 0){
403 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 399 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
404 exit(STATE_UNKNOWN); 400 exit(STATE_UNKNOWN);
405 } 401 }
406 /* Kompf 2000-2003 */ 402 /* Kompf 2000-2003 */
407 403
408#else 404#else
409 printf(_("Error: can't get MAC address for this architecture. Use the --mac option.\n")); 405 printf(_("Error: can't get MAC address for this architecture. Use the --mac option.\n"));
@@ -414,7 +410,7 @@ int get_hardware_address(int sock,char *interface_name){
414 print_hardware_address(client_hardware_address); 410 print_hardware_address(client_hardware_address);
415 411
416 return OK; 412 return OK;
417 } 413}
418 414
419/* determines IP address of the client interface */ 415/* determines IP address of the client interface */
420int get_ip_address(int sock,char *interface_name){ 416int get_ip_address(int sock,char *interface_name){
@@ -426,9 +422,9 @@ int get_ip_address(int sock,char *interface_name){
426 422
427 if(ioctl(sock,SIOCGIFADDR,&ifr)<0){ 423 if(ioctl(sock,SIOCGIFADDR,&ifr)<0){
428 printf(_("Error: Cannot determine IP address of interface %s\n"), 424 printf(_("Error: Cannot determine IP address of interface %s\n"),
429 interface_name); 425 interface_name);
430 exit(STATE_UNKNOWN); 426 exit(STATE_UNKNOWN);
431 } 427 }
432 428
433 my_ip=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 429 my_ip=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
434 430
@@ -441,13 +437,13 @@ int get_ip_address(int sock,char *interface_name){
441 printf(_("Pretending to be relay client %s\n"),inet_ntoa(my_ip)); 437 printf(_("Pretending to be relay client %s\n"),inet_ntoa(my_ip));
442 438
443 return OK; 439 return OK;
444 } 440}
445 441
446/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ 442/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */
447int send_dhcp_discover(int sock){ 443int send_dhcp_discover(int sock){
448 dhcp_packet discover_packet; 444 dhcp_packet discover_packet;
449 struct sockaddr_in sockaddr_broadcast; 445 struct sockaddr_in sockaddr_broadcast;
450 unsigned short opts; 446 unsigned short opts;
451 447
452 448
453 /* clear the packet data structure */ 449 /* clear the packet data structure */
@@ -488,19 +484,19 @@ int send_dhcp_discover(int sock){
488 discover_packet.options[2]='\x53'; 484 discover_packet.options[2]='\x53';
489 discover_packet.options[3]='\x63'; 485 discover_packet.options[3]='\x63';
490 486
491 opts = 4; 487 opts = 4;
492 /* DHCP message type is embedded in options field */ 488 /* DHCP message type is embedded in options field */
493 discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ 489 discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */
494 discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */ 490 discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */
495 discover_packet.options[opts++]=DHCPDISCOVER; 491 discover_packet.options[opts++]=DHCPDISCOVER;
496 492
497 /* the IP address we're requesting */ 493 /* the IP address we're requesting */
498 if(request_specific_address==TRUE){ 494 if(request_specific_address){
499 discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS; 495 discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS;
500 discover_packet.options[opts++]='\x04'; 496 discover_packet.options[opts++]='\x04';
501 memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address)); 497 memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address));
502 opts += sizeof(requested_address); 498 opts += sizeof(requested_address);
503 } 499 }
504 discover_packet.options[opts++]=DHCP_OPTION_END; 500 discover_packet.options[opts++]=DHCP_OPTION_END;
505 501
506 /* unicast fields */ 502 /* unicast fields */
@@ -511,8 +507,8 @@ int send_dhcp_discover(int sock){
511 discover_packet.hops = unicast ? 1 : 0; 507 discover_packet.hops = unicast ? 1 : 0;
512 508
513 /* send the DHCPDISCOVER packet to broadcast address */ 509 /* send the DHCPDISCOVER packet to broadcast address */
514 sockaddr_broadcast.sin_family=AF_INET; 510 sockaddr_broadcast.sin_family=AF_INET;
515 sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT); 511 sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT);
516 sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST; 512 sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST;
517 bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero)); 513 bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero));
518 514
@@ -524,7 +520,7 @@ int send_dhcp_discover(int sock){
524 printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); 520 printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr));
525 printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); 521 printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr));
526 printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr)); 522 printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr));
527 } 523 }
528 524
529 /* send the DHCPDISCOVER packet out */ 525 /* send the DHCPDISCOVER packet out */
530 send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast); 526 send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast);
@@ -533,7 +529,7 @@ int send_dhcp_discover(int sock){
533 printf("\n\n"); 529 printf("\n\n");
534 530
535 return OK; 531 return OK;
536 } 532}
537 533
538 534
539 535
@@ -573,13 +569,13 @@ int get_dhcp_offer(int sock){
573 printf(_("Result=ERROR\n")); 569 printf(_("Result=ERROR\n"));
574 570
575 continue; 571 continue;
576 } 572 }
577 else{ 573 else{
578 if(verbose) 574 if(verbose)
579 printf(_("Result=OK\n")); 575 printf(_("Result=OK\n"));
580 576
581 responses++; 577 responses++;
582 } 578 }
583 579
584 /* The "source" is either a server or a relay. */ 580 /* The "source" is either a server or a relay. */
585 /* Save a copy of "source" into "via" even if it's via itself */ 581 /* Save a copy of "source" into "via" even if it's via itself */
@@ -589,7 +585,7 @@ int get_dhcp_offer(int sock){
589 printf(_("DHCPOFFER from IP address %s"),inet_ntoa(source.sin_addr)); 585 printf(_("DHCPOFFER from IP address %s"),inet_ntoa(source.sin_addr));
590 printf(_(" via %s\n"),inet_ntoa(via.sin_addr)); 586 printf(_(" via %s\n"),inet_ntoa(via.sin_addr));
591 printf("DHCPOFFER XID: %u (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid)); 587 printf("DHCPOFFER XID: %u (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid));
592 } 588 }
593 589
594 /* check packet xid to see if its the same as the one we used in the discover packet */ 590 /* check packet xid to see if its the same as the one we used in the discover packet */
595 if(ntohl(offer_packet.xid)!=packet_xid){ 591 if(ntohl(offer_packet.xid)!=packet_xid){
@@ -597,7 +593,7 @@ int get_dhcp_offer(int sock){
597 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid); 593 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid);
598 594
599 continue; 595 continue;
600 } 596 }
601 597
602 /* check hardware address */ 598 /* check hardware address */
603 result=OK; 599 result=OK;
@@ -610,7 +606,7 @@ int get_dhcp_offer(int sock){
610 606
611 if(offer_packet.chaddr[x]!=client_hardware_address[x]) 607 if(offer_packet.chaddr[x]!=client_hardware_address[x])
612 result=ERROR; 608 result=ERROR;
613 } 609 }
614 if(verbose) 610 if(verbose)
615 printf("\n"); 611 printf("\n");
616 612
@@ -619,27 +615,27 @@ int get_dhcp_offer(int sock){
619 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n")); 615 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n"));
620 616
621 continue; 617 continue;
622 } 618 }
623 619
624 if(verbose){ 620 if(verbose){
625 printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr)); 621 printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr));
626 printf("DHCPOFFER yiaddr: %s\n",inet_ntoa(offer_packet.yiaddr)); 622 printf("DHCPOFFER yiaddr: %s\n",inet_ntoa(offer_packet.yiaddr));
627 printf("DHCPOFFER siaddr: %s\n",inet_ntoa(offer_packet.siaddr)); 623 printf("DHCPOFFER siaddr: %s\n",inet_ntoa(offer_packet.siaddr));
628 printf("DHCPOFFER giaddr: %s\n",inet_ntoa(offer_packet.giaddr)); 624 printf("DHCPOFFER giaddr: %s\n",inet_ntoa(offer_packet.giaddr));
629 } 625 }
630 626
631 add_dhcp_offer(source.sin_addr,&offer_packet); 627 add_dhcp_offer(source.sin_addr,&offer_packet);
632 628
633 valid_responses++; 629 valid_responses++;
634 } 630 }
635 631
636 if(verbose){ 632 if(verbose){
637 printf(_("Total responses seen on the wire: %d\n"),responses); 633 printf(_("Total responses seen on the wire: %d\n"),responses);
638 printf(_("Valid responses for this machine: %d\n"),valid_responses); 634 printf(_("Valid responses for this machine: %d\n"),valid_responses);
639 } 635 }
640 636
641 return OK; 637 return OK;
642 } 638}
643 639
644 640
645 641
@@ -656,14 +652,14 @@ int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in
656 return ERROR; 652 return ERROR;
657 653
658 return OK; 654 return OK;
659 } 655}
660 656
661 657
662 658
663/* receives a DHCP packet */ 659/* receives a DHCP packet */
664int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){ 660int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){
665 struct timeval tv; 661 struct timeval tv;
666 fd_set readfds; 662 fd_set readfds;
667 fd_set oobfds; 663 fd_set oobfds;
668 int recv_result; 664 int recv_result;
669 socklen_t address_size; 665 socklen_t address_size;
@@ -671,88 +667,88 @@ int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, st
671 int nfound; 667 int nfound;
672 668
673 669
674 /* wait for data to arrive (up time timeout) */ 670 /* wait for data to arrive (up time timeout) */
675 tv.tv_sec=timeout; 671 tv.tv_sec=timeout;
676 tv.tv_usec=0; 672 tv.tv_usec=0;
677 FD_ZERO(&readfds); 673 FD_ZERO(&readfds);
678 FD_ZERO(&oobfds); 674 FD_ZERO(&oobfds);
679 FD_SET(sock,&readfds); 675 FD_SET(sock,&readfds);
680 FD_SET(sock,&oobfds); 676 FD_SET(sock,&oobfds);
681 nfound = select(sock+1,&readfds,NULL,&oobfds,&tv); 677 nfound = select(sock+1,&readfds,NULL,&oobfds,&tv);
682 678
683 /* make sure some data has arrived */ 679 /* make sure some data has arrived */
684 if(!FD_ISSET(sock,&readfds)){ 680 if(!FD_ISSET(sock,&readfds)){
685 if(verbose) 681 if(verbose)
686 printf(_("No (more) data received (nfound: %d)\n"), nfound); 682 printf(_("No (more) data received (nfound: %d)\n"), nfound);
687 return ERROR; 683 return ERROR;
688 } 684 }
689 685
690 else{ 686 else{
691 bzero(&source_address,sizeof(source_address)); 687 bzero(&source_address,sizeof(source_address));
692 address_size=sizeof(source_address); 688 address_size=sizeof(source_address);
693 recv_result=recvfrom(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)&source_address,&address_size); 689 recv_result=recvfrom(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)&source_address,&address_size);
694 if(verbose) 690 if(verbose)
695 printf("recv_result: %d\n",recv_result); 691 printf("recv_result: %d\n",recv_result);
696 692
697 if(recv_result==-1){ 693 if(recv_result==-1){
698 if(verbose){ 694 if(verbose){
699 printf(_("recvfrom() failed, ")); 695 printf(_("recvfrom() failed, "));
700 printf("errno: (%d) -> %s\n",errno,strerror(errno)); 696 printf("errno: (%d) -> %s\n",errno,strerror(errno));
701 } 697 }
702 return ERROR; 698 return ERROR;
703 } 699 }
704 else{ 700 else{
705 if(verbose){ 701 if(verbose){
706 printf(_("receive_dhcp_packet() result: %d\n"),recv_result); 702 printf(_("receive_dhcp_packet() result: %d\n"),recv_result);
707 printf(_("receive_dhcp_packet() source: %s\n"),inet_ntoa(source_address.sin_addr)); 703 printf(_("receive_dhcp_packet() source: %s\n"),inet_ntoa(source_address.sin_addr));
708 } 704 }
709 705
710 memcpy(address,&source_address,sizeof(source_address)); 706 memcpy(address,&source_address,sizeof(source_address));
711 return OK; 707 return OK;
712 } 708 }
713 } 709 }
714 710
715 return OK; 711 return OK;
716 } 712}
717 713
718 714
719/* creates a socket for DHCP communication */ 715/* creates a socket for DHCP communication */
720int create_dhcp_socket(void){ 716int create_dhcp_socket(void){
721 struct sockaddr_in myname; 717 struct sockaddr_in myname;
722 struct ifreq interface; 718 struct ifreq interface;
723 int sock; 719 int sock;
724 int flag=1; 720 int flag=1;
725 721
726 /* Set up the address we're going to bind to. */ 722 /* Set up the address we're going to bind to. */
727 bzero(&myname,sizeof(myname)); 723 bzero(&myname,sizeof(myname));
728 myname.sin_family=AF_INET; 724 myname.sin_family=AF_INET;
729 /* listen to DHCP server port if we're in unicast mode */ 725 /* listen to DHCP server port if we're in unicast mode */
730 myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT); 726 myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT);
731 myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY; 727 myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY;
732 bzero(&myname.sin_zero,sizeof(myname.sin_zero)); 728 bzero(&myname.sin_zero,sizeof(myname.sin_zero));
733 729
734 /* create a socket for DHCP communications */ 730 /* create a socket for DHCP communications */
735 sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); 731 sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
736 if(sock<0){ 732 if(sock<0){
737 printf(_("Error: Could not create socket!\n")); 733 printf(_("Error: Could not create socket!\n"));
738 exit(STATE_UNKNOWN); 734 exit(STATE_UNKNOWN);
739 } 735 }
740 736
741 if(verbose) 737 if(verbose)
742 printf("DHCP socket: %d\n",sock); 738 printf("DHCP socket: %d\n",sock);
743 739
744 /* set the reuse address flag so we don't get errors when restarting */ 740 /* set the reuse address flag so we don't get errors when restarting */
745 flag=1; 741 flag=1;
746 if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){ 742 if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){
747 printf(_("Error: Could not set reuse address option on DHCP socket!\n")); 743 printf(_("Error: Could not set reuse address option on DHCP socket!\n"));
748 exit(STATE_UNKNOWN); 744 exit(STATE_UNKNOWN);
749 } 745 }
750 746
751 /* set the broadcast option - we need this to listen to DHCP broadcast messages */ 747 /* set the broadcast option - we need this to listen to DHCP broadcast messages */
752 if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){ 748 if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){
753 printf(_("Error: Could not set broadcast option on DHCP socket!\n")); 749 printf(_("Error: Could not set broadcast option on DHCP socket!\n"));
754 exit(STATE_UNKNOWN); 750 exit(STATE_UNKNOWN);
755 } 751 }
756 752
757 /* bind socket to interface */ 753 /* bind socket to interface */
758#if defined(__linux__) 754#if defined(__linux__)
@@ -761,21 +757,21 @@ int create_dhcp_socket(void){
761 if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){ 757 if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){
762 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name); 758 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name);
763 exit(STATE_UNKNOWN); 759 exit(STATE_UNKNOWN);
764 } 760 }
765 761
766#else 762#else
767 strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1); 763 strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1);
768 interface.ifr_name[IFNAMSIZ-1]='\0'; 764 interface.ifr_name[IFNAMSIZ-1]='\0';
769#endif 765#endif
770 766
771 /* bind the socket */ 767 /* bind the socket */
772 if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){ 768 if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){
773 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"),DHCP_CLIENT_PORT); 769 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"),DHCP_CLIENT_PORT);
774 exit(STATE_UNKNOWN); 770 exit(STATE_UNKNOWN);
775 } 771 }
776 772
777 return sock; 773 return sock;
778 } 774}
779 775
780 776
781/* closes DHCP socket */ 777/* closes DHCP socket */
@@ -784,7 +780,7 @@ int close_dhcp_socket(int sock){
784 close(sock); 780 close(sock);
785 781
786 return OK; 782 return OK;
787 } 783}
788 784
789 785
790/* adds a requested server address to list in memory */ 786/* adds a requested server address to list in memory */
@@ -796,7 +792,7 @@ int add_requested_server(struct in_addr server_address){
796 return ERROR; 792 return ERROR;
797 793
798 new_server->server_address=server_address; 794 new_server->server_address=server_address;
799 new_server->answered=FALSE; 795 new_server->answered=false;
800 796
801 new_server->next=requested_server_list; 797 new_server->next=requested_server_list;
802 requested_server_list=new_server; 798 requested_server_list=new_server;
@@ -807,7 +803,7 @@ int add_requested_server(struct in_addr server_address){
807 printf(_("Requested server address: %s\n"),inet_ntoa(new_server->server_address)); 803 printf(_("Requested server address: %s\n"),inet_ntoa(new_server->server_address));
808 804
809 return OK; 805 return OK;
810 } 806}
811 807
812 808
813 809
@@ -840,29 +836,29 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
840 836
841 /* get option data */ 837 /* get option data */
842 switch(option_type){ 838 switch(option_type){
843 case DHCP_OPTION_LEASE_TIME: 839 case DHCP_OPTION_LEASE_TIME:
844 memcpy(&dhcp_lease_time, &offer_packet->options[x],sizeof(dhcp_lease_time)); 840 memcpy(&dhcp_lease_time, &offer_packet->options[x],sizeof(dhcp_lease_time));
845 dhcp_lease_time = ntohl(dhcp_lease_time); 841 dhcp_lease_time = ntohl(dhcp_lease_time);
846 break; 842 break;
847 case DHCP_OPTION_RENEWAL_TIME: 843 case DHCP_OPTION_RENEWAL_TIME:
848 memcpy(&dhcp_renewal_time, &offer_packet->options[x],sizeof(dhcp_renewal_time)); 844 memcpy(&dhcp_renewal_time, &offer_packet->options[x],sizeof(dhcp_renewal_time));
849 dhcp_renewal_time = ntohl(dhcp_renewal_time); 845 dhcp_renewal_time = ntohl(dhcp_renewal_time);
850 break; 846 break;
851 case DHCP_OPTION_REBINDING_TIME: 847 case DHCP_OPTION_REBINDING_TIME:
852 memcpy(&dhcp_rebinding_time, &offer_packet->options[x],sizeof(dhcp_rebinding_time)); 848 memcpy(&dhcp_rebinding_time, &offer_packet->options[x],sizeof(dhcp_rebinding_time));
853 dhcp_rebinding_time = ntohl(dhcp_rebinding_time); 849 dhcp_rebinding_time = ntohl(dhcp_rebinding_time);
854 break; 850 break;
855 case DHCP_OPTION_SERVER_IDENTIFIER: 851 case DHCP_OPTION_SERVER_IDENTIFIER:
856 memcpy(&serv_ident.s_addr, &offer_packet->options[x],sizeof(serv_ident.s_addr)); 852 memcpy(&serv_ident.s_addr, &offer_packet->options[x],sizeof(serv_ident.s_addr));
857 break; 853 break;
858 } 854 }
859 855
860 /* skip option data we're ignoring */ 856 /* skip option data we're ignoring */
861 if(option_type==0) /* "pad" option, see RFC 2132 (3.1) */ 857 if(option_type==0) /* "pad" option, see RFC 2132 (3.1) */
862 x+=1; 858 x+=1;
863 else 859 else
864 x+=option_length; 860 x+=option_length;
865 } 861 }
866 862
867 if(verbose){ 863 if(verbose){
868 if(dhcp_lease_time==DHCP_INFINITE_TIME) 864 if(dhcp_lease_time==DHCP_INFINITE_TIME)
@@ -876,7 +872,7 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
876 if(dhcp_rebinding_time==DHCP_INFINITE_TIME) 872 if(dhcp_rebinding_time==DHCP_INFINITE_TIME)
877 printf(_("Rebinding Time: Infinite\n")); 873 printf(_("Rebinding Time: Infinite\n"));
878 printf(_("Rebinding Time: %lu seconds\n"),(unsigned long)dhcp_rebinding_time); 874 printf(_("Rebinding Time: %lu seconds\n"),(unsigned long)dhcp_rebinding_time);
879 } 875 }
880 876
881 new_offer=(dhcp_offer *)malloc(sizeof(dhcp_offer)); 877 new_offer=(dhcp_offer *)malloc(sizeof(dhcp_offer));
882 878
@@ -900,19 +896,20 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
900 new_offer->lease_time=dhcp_lease_time; 896 new_offer->lease_time=dhcp_lease_time;
901 new_offer->renewal_time=dhcp_renewal_time; 897 new_offer->renewal_time=dhcp_renewal_time;
902 new_offer->rebinding_time=dhcp_rebinding_time; 898 new_offer->rebinding_time=dhcp_rebinding_time;
899 new_offer->desired=false; /* exclusive mode: we'll check that in get_results */
903 900
904 901
905 if(verbose){ 902 if(verbose){
906 printf(_("Added offer from server @ %s"),inet_ntoa(new_offer->server_address)); 903 printf(_("Added offer from server @ %s"),inet_ntoa(new_offer->server_address));
907 printf(_(" of IP address %s\n"),inet_ntoa(new_offer->offered_address)); 904 printf(_(" of IP address %s\n"),inet_ntoa(new_offer->offered_address));
908 } 905 }
909 906
910 /* add new offer to head of list */ 907 /* add new offer to head of list */
911 new_offer->next=dhcp_offer_list; 908 new_offer->next=dhcp_offer_list;
912 dhcp_offer_list=new_offer; 909 dhcp_offer_list=new_offer;
913 910
914 return OK; 911 return OK;
915 } 912}
916 913
917 914
918/* frees memory allocated to DHCP OFFER list */ 915/* frees memory allocated to DHCP OFFER list */
@@ -923,10 +920,10 @@ int free_dhcp_offer_list(void){
923 for(this_offer=dhcp_offer_list;this_offer!=NULL;this_offer=next_offer){ 920 for(this_offer=dhcp_offer_list;this_offer!=NULL;this_offer=next_offer){
924 next_offer=this_offer->next; 921 next_offer=this_offer->next;
925 free(this_offer); 922 free(this_offer);
926 } 923 }
927 924
928 return OK; 925 return OK;
929 } 926}
930 927
931 928
932/* frees memory allocated to requested server list */ 929/* frees memory allocated to requested server list */
@@ -937,20 +934,20 @@ int free_requested_server_list(void){
937 for(this_server=requested_server_list;this_server!=NULL;this_server=next_server){ 934 for(this_server=requested_server_list;this_server!=NULL;this_server=next_server){
938 next_server=this_server->next; 935 next_server=this_server->next;
939 free(this_server); 936 free(this_server);
940 } 937 }
941 938
942 return OK; 939 return OK;
943 } 940}
944 941
945 942
946/* gets state and plugin output to return */ 943/* gets state and plugin output to return */
947int get_results(void){ 944int get_results(void){
948 dhcp_offer *temp_offer; 945 dhcp_offer *temp_offer, *undesired_offer=NULL;
949 requested_server *temp_server; 946 requested_server *temp_server;
950 int result; 947 int result;
951 u_int32_t max_lease_time=0; 948 uint32_t max_lease_time=0;
952 949
953 received_requested_address=FALSE; 950 received_requested_address=false;
954 951
955 /* checks responses from requested servers */ 952 /* checks responses from requested servers */
956 requested_responses=0; 953 requested_responses=0;
@@ -966,7 +963,7 @@ int get_results(void){
966 963
967 /* see if we got the address we requested */ 964 /* see if we got the address we requested */
968 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 965 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address)))
969 received_requested_address=TRUE; 966 received_requested_address=true;
970 967
971 /* see if the servers we wanted a response from talked to us or not */ 968 /* see if the servers we wanted a response from talked to us or not */
972 if(!memcmp(&temp_offer->server_address,&temp_server->server_address,sizeof(temp_server->server_address))){ 969 if(!memcmp(&temp_offer->server_address,&temp_server->server_address,sizeof(temp_server->server_address))){
@@ -976,16 +973,24 @@ int get_results(void){
976 if(temp_server->answered) 973 if(temp_server->answered)
977 printf(_(" (duplicate)")); 974 printf(_(" (duplicate)"));
978 printf(_("\n")); 975 printf(_("\n"));
979 } 976 }
980 if(temp_server->answered == FALSE){ 977 if(!temp_server->answered){
981 requested_responses++; 978 requested_responses++;
982 temp_server->answered=TRUE; 979 temp_server->answered=true;
983 } 980 temp_offer->desired=true;
984 } 981 }
985 } 982 }
986 } 983 }
984 }
987 985
988 } 986 /* exclusive mode: check for undesired offers */
987 for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next) {
988 if (!temp_offer->desired) {
989 undesired_offer=temp_offer; /* Checks only for the first undesired offer */
990 break; /* no further checks needed */
991 }
992 }
993 }
989 994
990 /* else check and see if we got our requested address from any server */ 995 /* else check and see if we got our requested address from any server */
991 else{ 996 else{
@@ -998,9 +1003,9 @@ int get_results(void){
998 1003
999 /* see if we got the address we requested */ 1004 /* see if we got the address we requested */
1000 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 1005 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address)))
1001 received_requested_address=TRUE; 1006 received_requested_address=true;
1002 } 1007 }
1003 } 1008 }
1004 1009
1005 result=STATE_OK; 1010 result=STATE_OK;
1006 if(valid_responses==0) 1011 if(valid_responses==0)
@@ -1009,9 +1014,12 @@ int get_results(void){
1009 result=STATE_CRITICAL; 1014 result=STATE_CRITICAL;
1010 else if(requested_responses<requested_servers) 1015 else if(requested_responses<requested_servers)
1011 result=STATE_WARNING; 1016 result=STATE_WARNING;
1012 else if(request_specific_address==TRUE && received_requested_address==FALSE) 1017 else if(request_specific_address && !received_requested_address)
1013 result=STATE_WARNING; 1018 result=STATE_WARNING;
1014 1019
1020 if(exclusive && undesired_offer)
1021 result=STATE_CRITICAL;
1022
1015 if(result==0) /* garrett honeycutt 2005 */ 1023 if(result==0) /* garrett honeycutt 2005 */
1016 printf("OK: "); 1024 printf("OK: ");
1017 else if(result==1) 1025 else if(result==1)
@@ -1025,15 +1033,22 @@ int get_results(void){
1025 if(dhcp_offer_list==NULL){ 1033 if(dhcp_offer_list==NULL){
1026 printf(_("No DHCPOFFERs were received.\n")); 1034 printf(_("No DHCPOFFERs were received.\n"));
1027 return result; 1035 return result;
1028 } 1036 }
1029 1037
1030 printf(_("Received %d DHCPOFFER(s)"),valid_responses); 1038 printf(_("Received %d DHCPOFFER(s)"),valid_responses);
1031 1039
1040
1041 if(exclusive && undesired_offer){
1042 printf(_(", Rogue DHCP Server detected! Server %s"),inet_ntoa(undesired_offer->server_address));
1043 printf(_(" offered %s \n"),inet_ntoa(undesired_offer->offered_address));
1044 return result;
1045 }
1046
1032 if(requested_servers>0) 1047 if(requested_servers>0)
1033 printf(_(", %s%d of %d requested servers responded"),((requested_responses<requested_servers) && requested_responses>0)?"only ":"",requested_responses,requested_servers); 1048 printf(_(", %s%d of %d requested servers responded"),((requested_responses<requested_servers) && requested_responses>0)?"only ":"",requested_responses,requested_servers);
1034 1049
1035 if(request_specific_address==TRUE) 1050 if(request_specific_address)
1036 printf(_(", requested address (%s) was %soffered"),inet_ntoa(requested_address),(received_requested_address==TRUE)?"":_("not ")); 1051 printf(_(", requested address (%s) was %soffered"),inet_ntoa(requested_address),(received_requested_address)?"":_("not "));
1037 1052
1038 printf(_(", max lease time = ")); 1053 printf(_(", max lease time = "));
1039 if(max_lease_time==DHCP_INFINITE_TIME) 1054 if(max_lease_time==DHCP_INFINITE_TIME)
@@ -1044,17 +1059,15 @@ int get_results(void){
1044 printf(".\n"); 1059 printf(".\n");
1045 1060
1046 return result; 1061 return result;
1047 } 1062}
1048 1063
1049 1064
1050/* process command-line arguments */ 1065/* process command-line arguments */
1051int process_arguments(int argc, char **argv){ 1066int process_arguments(int argc, char **argv){
1052 int arg_index;
1053
1054 if(argc<1) 1067 if(argc<1)
1055 return ERROR; 1068 return ERROR;
1056 1069
1057 arg_index = call_getopt(argc,argv); 1070 call_getopt(argc,argv);
1058 return validate_arguments(argc); 1071 return validate_arguments(argc);
1059} 1072}
1060 1073
@@ -1071,87 +1084,89 @@ int call_getopt(int argc, char **argv){
1071 {"interface", required_argument,0,'i'}, 1084 {"interface", required_argument,0,'i'},
1072 {"mac", required_argument,0,'m'}, 1085 {"mac", required_argument,0,'m'},
1073 {"unicast", no_argument, 0,'u'}, 1086 {"unicast", no_argument, 0,'u'},
1087 {"exclusive", no_argument, 0,'x'},
1074 {"verbose", no_argument, 0,'v'}, 1088 {"verbose", no_argument, 0,'v'},
1075 {"version", no_argument, 0,'V'}, 1089 {"version", no_argument, 0,'V'},
1076 {"help", no_argument, 0,'h'}, 1090 {"help", no_argument, 0,'h'},
1077 {0,0,0,0} 1091 {0,0,0,0}
1078 }; 1092 };
1079 1093
1080 while(1){ 1094 int c=0;
1081 int c=0; 1095 while(true){
1082 1096 c=getopt_long(argc,argv,"+hVvxt:s:r:t:i:m:u",long_options,&option_index);
1083 c=getopt_long(argc,argv,"+hVvt:s:r:t:i:m:u",long_options,&option_index);
1084 1097
1085 if(c==-1||c==EOF||c==1) 1098 if(c==-1||c==EOF||c==1)
1086 break; 1099 break;
1087 1100
1088 switch(c){ 1101 switch(c){
1089 1102
1090 case 's': /* DHCP server address */ 1103 case 's': /* DHCP server address */
1091 resolve_host(optarg,&dhcp_ip); 1104 resolve_host(optarg,&dhcp_ip);
1092 add_requested_server(dhcp_ip); 1105 add_requested_server(dhcp_ip);
1093 break; 1106 break;
1094 1107
1095 case 'r': /* address we are requested from DHCP servers */ 1108 case 'r': /* address we are requested from DHCP servers */
1096 resolve_host(optarg,&requested_address); 1109 resolve_host(optarg,&requested_address);
1097 request_specific_address=TRUE; 1110 request_specific_address=true;
1098 break; 1111 break;
1099 1112
1100 case 't': /* timeout */ 1113 case 't': /* timeout */
1101 1114
1102 /* 1115 /*
1103 if(is_intnonneg(optarg)) 1116 if(is_intnonneg(optarg))
1104 */ 1117 */
1105 if(atoi(optarg)>0) 1118 if(atoi(optarg)>0)
1106 dhcpoffer_timeout=atoi(optarg); 1119 dhcpoffer_timeout=atoi(optarg);
1107 /* 1120 /*
1108 else 1121 else
1109 usage("Time interval must be a nonnegative integer\n"); 1122 usage("Time interval must be a nonnegative integer\n");
1110 */ 1123 */
1111 break; 1124 break;
1112 1125
1113 case 'm': /* MAC address */ 1126 case 'm': /* MAC address */
1114 1127
1115 if((user_specified_mac=mac_aton(optarg)) == NULL) 1128 if((user_specified_mac=mac_aton(optarg)) == NULL)
1116 usage("Cannot parse MAC address.\n"); 1129 usage("Cannot parse MAC address.\n");
1117 if(verbose) 1130 if(verbose)
1118 print_hardware_address(user_specified_mac); 1131 print_hardware_address(user_specified_mac);
1119 1132
1120 break; 1133 break;
1121 1134
1122 case 'i': /* interface name */ 1135 case 'i': /* interface name */
1123 1136
1124 strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1); 1137 strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1);
1125 network_interface_name[sizeof(network_interface_name)-1]='\x0'; 1138 network_interface_name[sizeof(network_interface_name)-1]='\x0';
1126 1139
1127 break; 1140 break;
1128 1141
1129 case 'u': /* unicast testing */ 1142 case 'u': /* unicast testing */
1130 unicast=1; 1143 unicast=true;
1131 break; 1144 break;
1132 1145 case 'x': /* exclusive testing aka "rogue DHCP server detection" */
1133 case 'V': /* version */ 1146 exclusive=true;
1134 print_revision(progname, NP_VERSION); 1147 break;
1135 exit(STATE_UNKNOWN); 1148
1136 1149 case 'V': /* version */
1137 case 'h': /* help */ 1150 print_revision(progname, NP_VERSION);
1138 print_help(); 1151 exit(STATE_UNKNOWN);
1139 exit(STATE_UNKNOWN); 1152
1140 1153 case 'h': /* help */
1141 case 'v': /* verbose */ 1154 print_help();
1142 verbose=1; 1155 exit(STATE_UNKNOWN);
1143 break; 1156
1144 1157 case 'v': /* verbose */
1145 case '?': /* help */ 1158 verbose=1;
1146 usage5 (); 1159 break;
1147 break; 1160 case '?': /* help */
1148 1161 usage5 ();
1149 default: 1162 break;
1150 break; 1163
1151 } 1164 default:
1152 } 1165 break;
1166 }
1167 }
1153 return optind; 1168 return optind;
1154 } 1169}
1155 1170
1156 1171
1157int validate_arguments(int argc){ 1172int validate_arguments(int argc){
@@ -1178,21 +1193,21 @@ static int get_msg(int fd){
1178 if(res < 0){ 1193 if(res < 0){
1179 if(errno == EINTR){ 1194 if(errno == EINTR){
1180 return(GOT_INTR); 1195 return(GOT_INTR);
1181 } 1196 }
1182 else{ 1197 else{
1183 printf("%s\n", "get_msg FAILED."); 1198 printf("%s\n", "get_msg FAILED.");
1184 return(GOT_ERR); 1199 return(GOT_ERR);
1185 }
1186 } 1200 }
1201 }
1187 if(ctl.len > 0){ 1202 if(ctl.len > 0){
1188 ret |= GOT_CTRL; 1203 ret |= GOT_CTRL;
1189 } 1204 }
1190 if(dat.len > 0){ 1205 if(dat.len > 0){
1191 ret |= GOT_DATA; 1206 ret |= GOT_DATA;
1192 } 1207 }
1193 1208
1194 return(ret); 1209 return(ret);
1195 } 1210}
1196 1211
1197/* verify that dl_primitive in ctl_area = prim */ 1212/* verify that dl_primitive in ctl_area = prim */
1198static int check_ctrl(int prim){ 1213static int check_ctrl(int prim){
@@ -1201,10 +1216,10 @@ static int check_ctrl(int prim){
1201 if(err_ack->dl_primitive != prim){ 1216 if(err_ack->dl_primitive != prim){
1202 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno)); 1217 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno));
1203 exit(STATE_UNKNOWN); 1218 exit(STATE_UNKNOWN);
1204 } 1219 }
1205 1220
1206 return 0; 1221 return 0;
1207 } 1222}
1208 1223
1209/* put a control message on a stream */ 1224/* put a control message on a stream */
1210static int put_ctrl(int fd, int len, int pri){ 1225static int put_ctrl(int fd, int len, int pri){
@@ -1213,10 +1228,10 @@ static int put_ctrl(int fd, int len, int pri){
1213 if(putmsg(fd, &ctl, 0, pri) < 0){ 1228 if(putmsg(fd, &ctl, 0, pri) < 0){
1214 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno)); 1229 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno));
1215 exit(STATE_UNKNOWN); 1230 exit(STATE_UNKNOWN);
1216 } 1231 }
1217 1232
1218 return 0; 1233 return 0;
1219 } 1234}
1220 1235
1221/* put a control + data message on a stream */ 1236/* put a control + data message on a stream */
1222static int put_both(int fd, int clen, int dlen, int pri){ 1237static int put_both(int fd, int clen, int dlen, int pri){
@@ -1226,10 +1241,10 @@ static int put_both(int fd, int clen, int dlen, int pri){
1226 if(putmsg(fd, &ctl, &dat, pri) < 0){ 1241 if(putmsg(fd, &ctl, &dat, pri) < 0){
1227 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno)); 1242 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno));
1228 exit(STATE_UNKNOWN); 1243 exit(STATE_UNKNOWN);
1229 } 1244 }
1230 1245
1231 return 0; 1246 return 0;
1232 } 1247}
1233 1248
1234/* open file descriptor and attach */ 1249/* open file descriptor and attach */
1235static int dl_open(const char *dev, int unit, int *fd){ 1250static int dl_open(const char *dev, int unit, int *fd){
@@ -1238,13 +1253,13 @@ static int dl_open(const char *dev, int unit, int *fd){
1238 if((*fd = open(dev, O_RDWR)) == -1){ 1253 if((*fd = open(dev, O_RDWR)) == -1){
1239 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno)); 1254 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno));
1240 exit(STATE_UNKNOWN); 1255 exit(STATE_UNKNOWN);
1241 } 1256 }
1242 attach_req->dl_primitive = DL_ATTACH_REQ; 1257 attach_req->dl_primitive = DL_ATTACH_REQ;
1243 attach_req->dl_ppa = unit; 1258 attach_req->dl_ppa = unit;
1244 put_ctrl(*fd, sizeof(dl_attach_req_t), 0); 1259 put_ctrl(*fd, sizeof(dl_attach_req_t), 0);
1245 get_msg(*fd); 1260 get_msg(*fd);
1246 return check_ctrl(DL_OK_ACK); 1261 return check_ctrl(DL_OK_ACK);
1247 } 1262}
1248 1263
1249/* send DL_BIND_REQ */ 1264/* send DL_BIND_REQ */
1250static int dl_bind(int fd, int sap, u_char *addr){ 1265static int dl_bind(int fd, int sap, u_char *addr){
@@ -1262,12 +1277,12 @@ static int dl_bind(int fd, int sap, u_char *addr){
1262 if (GOT_ERR == check_ctrl(DL_BIND_ACK)){ 1277 if (GOT_ERR == check_ctrl(DL_BIND_ACK)){
1263 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno)); 1278 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno));
1264 exit(STATE_UNKNOWN); 1279 exit(STATE_UNKNOWN);
1265 } 1280 }
1266 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr, 1281 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr,
1267 bind_ack->dl_addr_length); 1282 bind_ack->dl_addr_length);
1268 1283
1269 return 0; 1284 return 0;
1270 } 1285}
1271 1286
1272/*********************************************************************** 1287/***********************************************************************
1273 * interface: 1288 * interface:
@@ -1286,15 +1301,15 @@ long mac_addr_dlpi( const char *dev, int unit, u_char *addr){
1286 u_char mac_addr[25]; 1301 u_char mac_addr[25];
1287 1302
1288 if(GOT_ERR != dl_open(dev, unit, &fd)){ 1303 if(GOT_ERR != dl_open(dev, unit, &fd)){
1289 if(GOT_ERR != dl_bind(fd, INSAP, mac_addr)){ 1304 if(GOT_ERR != dl_bind(fd, INSAP, mac_addr)){
1290 bcopy( mac_addr, addr, 6); 1305 bcopy( mac_addr, addr, 6);
1291 return 0; 1306 return 0;
1292 }
1293 } 1307 }
1294 close(fd); 1308 }
1309 close(fd);
1295 1310
1296 return -1; 1311 return -1;
1297 } 1312}
1298 1313
1299/* Kompf 2000-2003 */ 1314/* Kompf 2000-2003 */
1300#endif 1315#endif
@@ -1311,7 +1326,7 @@ void resolve_host(const char *in,struct in_addr *out){
1311 1326
1312 memcpy(out,&((struct sockaddr_in *)ai->ai_addr)->sin_addr,sizeof(*out)); 1327 memcpy(out,&((struct sockaddr_in *)ai->ai_addr)->sin_addr,sizeof(*out));
1313 freeaddrinfo(ai); 1328 freeaddrinfo(ai);
1314 } 1329}
1315 1330
1316 1331
1317/* parse MAC address string, return 6 bytes (unterminated) or NULL */ 1332/* parse MAC address string, return 6 bytes (unterminated) or NULL */
@@ -1330,10 +1345,10 @@ unsigned char *mac_aton(const char *string){
1330 result[j]=strtol(tmp,(char **)NULL,16); 1345 result[j]=strtol(tmp,(char **)NULL,16);
1331 i++; 1346 i++;
1332 j++; 1347 j++;
1333 } 1348 }
1334 1349
1335 return (j==6) ? result : NULL; 1350 return (j==6) ? result : NULL;
1336 } 1351}
1337 1352
1338 1353
1339void print_hardware_address(const unsigned char *address){ 1354void print_hardware_address(const unsigned char *address){
@@ -1344,7 +1359,7 @@ void print_hardware_address(const unsigned char *address){
1344 printf("%2.2x:", address[i]); 1359 printf("%2.2x:", address[i]);
1345 printf("%2.2x", address[i]); 1360 printf("%2.2x", address[i]);
1346 putchar('\n'); 1361 putchar('\n');
1347 } 1362}
1348 1363
1349 1364
1350/* print usage help */ 1365/* print usage help */
@@ -1357,7 +1372,7 @@ void print_help(void){
1357 1372
1358 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network.")); 1373 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network."));
1359 1374
1360 printf ("\n\n"); 1375 printf ("\n\n");
1361 1376
1362 print_usage(); 1377 print_usage();
1363 1378
@@ -1367,32 +1382,31 @@ void print_help(void){
1367 printf (UT_VERBOSE); 1382 printf (UT_VERBOSE);
1368 1383
1369 printf (" %s\n", "-s, --serverip=IPADDRESS"); 1384 printf (" %s\n", "-s, --serverip=IPADDRESS");
1370 printf (" %s\n", _("IP address of DHCP server that we must hear from")); 1385 printf (" %s\n", _("IP address of DHCP server that we must hear from"));
1371 printf (" %s\n", "-r, --requestedip=IPADDRESS"); 1386 printf (" %s\n", "-r, --requestedip=IPADDRESS");
1372 printf (" %s\n", _("IP address that should be offered by at least one DHCP server")); 1387 printf (" %s\n", _("IP address that should be offered by at least one DHCP server"));
1373 printf (" %s\n", "-t, --timeout=INTEGER"); 1388 printf (" %s\n", "-t, --timeout=INTEGER");
1374 printf (" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs")); 1389 printf (" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs"));
1375 printf (" %s\n", "-i, --interface=STRING"); 1390 printf (" %s\n", "-i, --interface=STRING");
1376 printf (" %s\n", _("Interface to to use for listening (i.e. eth0)")); 1391 printf (" %s\n", _("Interface to to use for listening (i.e. eth0)"));
1377 printf (" %s\n", "-m, --mac=STRING"); 1392 printf (" %s\n", "-m, --mac=STRING");
1378 printf (" %s\n", _("MAC address to use in the DHCP request")); 1393 printf (" %s\n", _("MAC address to use in the DHCP request"));
1379 printf (" %s\n", "-u, --unicast"); 1394 printf (" %s\n", "-u, --unicast");
1380 printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s")); 1395 printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s"));
1381 1396 printf (" %s\n", "-x, --exclusive");
1382 printf (UT_SUPPORT); 1397 printf (" %s\n", _("Only requested DHCP server may response (rogue DHCP server detection), requires -s"));
1398
1399 printf (UT_SUPPORT);
1383 return; 1400 return;
1384 } 1401}
1385 1402
1386 1403
1387void 1404void
1388print_usage(void){ 1405print_usage(void){
1389 1406
1390 printf ("%s\n", _("Usage:")); 1407 printf ("%s\n", _("Usage:"));
1391 printf (" %s [-v] [-u] [-s serverip] [-r requestedip] [-t timeout]\n",progname); 1408 printf (" %s [-v] [-u] [-x] [-s serverip] [-r requestedip] [-t timeout]\n",progname);
1392 printf (" [-i interface] [-m mac]\n"); 1409 printf (" [-i interface] [-m mac]\n");
1393 1410
1394 return; 1411 return;
1395 } 1412}
1396
1397
1398