summaryrefslogtreecommitdiffstats
path: root/plugins-root/check_dhcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins-root/check_dhcp.c')
-rw-r--r--plugins-root/check_dhcp.c1558
1 files changed, 807 insertions, 751 deletions
diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c
index 4b8f5e27..daed9cb0 100644
--- a/plugins-root/check_dhcp.c
+++ b/plugins-root/check_dhcp.c
@@ -4,7 +4,7 @@
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-2025 Monitoring Plugins Development Team
8 * 8 *
9 * Description: 9 * Description:
10 * 10 *
@@ -34,13 +34,17 @@
34 *****************************************************************************/ 34 *****************************************************************************/
35 35
36const char *progname = "check_dhcp"; 36const char *progname = "check_dhcp";
37const char *copyright = "2001-2023"; 37const char *copyright = "2001-2025";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include "common.h" 40#include "../plugins/common.h"
41#include "netutils.h" 41#include "../plugins/utils.h"
42#include "utils.h" 42#include "./check_dhcp.d/config.h"
43#include "../lib/output.h"
44#include "../lib/utils_base.h"
43 45
46#include "states.h"
47#include <stdint.h>
44#include <ctype.h> 48#include <ctype.h>
45#include <stdio.h> 49#include <stdio.h>
46#include <stdlib.h> 50#include <stdlib.h>
@@ -59,45 +63,45 @@ const char *email = "devel@monitoring-plugins.org";
59#include <arpa/inet.h> 63#include <arpa/inet.h>
60 64
61#if HAVE_SYS_SOCKIO_H 65#if HAVE_SYS_SOCKIO_H
62#include <sys/sockio.h> 66# include <sys/sockio.h>
63#endif // HAVE_SYS_SOCKIO_H 67#endif // HAVE_SYS_SOCKIO_H
64 68
65#if defined( __linux__ ) 69#if defined(__linux__)
66 70
67#include <linux/if_ether.h> 71# include <linux/if_ether.h>
68#include <features.h> 72# include <features.h>
69 73
70#elif defined (__bsd__) 74#elif defined(__bsd__)
71 75
72#include <netinet/if_ether.h> 76# include <netinet/if_ether.h>
73#include <sys/param.h> 77# include <sys/param.h>
74#include <sys/sysctl.h> 78# include <sys/sysctl.h>
75#include <net/if_dl.h> 79# include <net/if_dl.h>
76 80
77#elif defined(__sun__) || defined(__solaris__) || defined(__hpux__) 81#elif defined(__sun__) || defined(__solaris__) || defined(__hpux__)
78 82
79#define INSAP 22 83# define INSAP 22
80#define OUTSAP 24 84# define OUTSAP 24
81 85
82#include <signal.h> 86# include <signal.h>
83#include <ctype.h> 87# include <ctype.h>
84#include <sys/stropts.h> 88# include <sys/stropts.h>
85#include <sys/poll.h> 89# include <sys/poll.h>
86#include <sys/dlpi.h> 90# include <sys/dlpi.h>
87 91
88#define bcopy(source, destination, length) memcpy(destination, source, length) 92# define bcopy(source, destination, length) memcpy(destination, source, length)
89 93
90#define AREA_SZ 5000 /* buffer length in bytes */ 94# define AREA_SZ 5000 /* buffer length in bytes */
91static u_long ctl_area[AREA_SZ]; 95static u_long ctl_area[AREA_SZ];
92static u_long dat_area[AREA_SZ]; 96static u_long dat_area[AREA_SZ];
93static struct strbuf ctl = {AREA_SZ, 0, (char *)ctl_area}; 97static struct strbuf ctl = {AREA_SZ, 0, (char *)ctl_area};
94static struct strbuf dat = {AREA_SZ, 0, (char *)dat_area}; 98static struct strbuf dat = {AREA_SZ, 0, (char *)dat_area};
95 99
96#define GOT_CTRL 1 100# define GOT_CTRL 1
97#define GOT_DATA 2 101# define GOT_DATA 2
98#define GOT_BOTH 3 102# define GOT_BOTH 3
99#define GOT_INTR 4 103# define GOT_INTR 4
100#define GOT_ERR 128 104# define GOT_ERR 128
101 105
102static int get_msg(int); 106static int get_msg(int);
103static int check_ctrl(int); 107static int check_ctrl(int);
@@ -105,226 +109,241 @@ static int put_ctrl(int, int, int);
105static int put_both(int, int, int, int); 109static int put_both(int, int, int, int);
106static int dl_open(const char *, int, int *); 110static int dl_open(const char *, int, int *);
107static int dl_bind(int, int, u_char *); 111static int dl_bind(int, int, u_char *);
108long mac_addr_dlpi( const char *, int, u_char *); 112static long mac_addr_dlpi(const char *, int, u_char *);
109 113
110#endif // __sun__ || __solaris__ || __hpux 114#endif // __sun__ || __solaris__ || __hpux
111 115
112
113
114/**** Common definitions ****/ 116/**** Common definitions ****/
115 117
116#define OK 0 118#define OK 0
117#define ERROR -1 119#define ERROR -1
118 120#define MAC_ADDR_LEN 6
119 121
120/**** DHCP definitions ****/ 122/**** DHCP definitions ****/
121 123
122#define MAX_DHCP_CHADDR_LENGTH 16 124#define MAX_DHCP_CHADDR_LENGTH 16
123#define MAX_DHCP_SNAME_LENGTH 64 125#define MAX_DHCP_SNAME_LENGTH 64
124#define MAX_DHCP_FILE_LENGTH 128 126#define MAX_DHCP_FILE_LENGTH 128
125#define MAX_DHCP_OPTIONS_LENGTH 312 127#define MAX_DHCP_OPTIONS_LENGTH 312
126 128
127 129typedef struct dhcp_packet_struct {
128typedef struct dhcp_packet_struct{ 130 uint8_t op; /* packet type */
129 uint8_t op; /* packet type */ 131 uint8_t htype; /* type of hardware address for this machine (Ethernet, etc) */
130 uint8_t htype; /* type of hardware address for this machine (Ethernet, etc) */ 132 uint8_t hlen; /* length of hardware address (of this machine) */
131 uint8_t hlen; /* length of hardware address (of this machine) */ 133 uint8_t hops; /* hops */
132 uint8_t hops; /* hops */ 134 uint32_t xid; /* random transaction id number - chosen by this machine */
133 uint32_t xid; /* random transaction id number - chosen by this machine */ 135 uint16_t secs; /* seconds used in timing */
134 uint16_t secs; /* seconds used in timing */ 136 uint16_t flags; /* flags */
135 uint16_t flags; /* flags */ 137 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) */ 138 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) */ 139 struct in_addr siaddr; /* IP address of next server */
138 struct in_addr siaddr; /* IP address of next server */ 140 struct in_addr giaddr; /* IP address of DHCP relay */
139 struct in_addr giaddr; /* IP address of DHCP relay */ 141 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 */ 142 char sname[MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */
141 char sname [MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */ 143 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?) */ 144 char options[MAX_DHCP_OPTIONS_LENGTH]; /* options */
143 char options[MAX_DHCP_OPTIONS_LENGTH]; /* options */ 145} dhcp_packet;
144}dhcp_packet; 146
145 147typedef struct dhcp_offer_struct {
146 148 struct in_addr server_address; /* address of DHCP server that sent this offer */
147typedef struct dhcp_offer_struct{ 149 struct in_addr offered_address; /* the IP address that was offered to us */
148 struct in_addr server_address; /* address of DHCP server that sent this offer */
149 struct in_addr offered_address; /* the IP address that was offered to us */
150 uint32_t lease_time; /* lease time in seconds */ 150 uint32_t lease_time; /* lease time in seconds */
151 uint32_t renewal_time; /* renewal time in seconds */ 151 uint32_t renewal_time; /* renewal time in seconds */
152 uint32_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) */ 153 bool desired; /* is this offer desired (necessary in exclusive mode) */
154 struct dhcp_offer_struct *next; 154 struct dhcp_offer_struct *next;
155}dhcp_offer; 155} dhcp_offer;
156 156
157 157#define BOOTREQUEST 1
158typedef struct requested_server_struct{ 158#define BOOTREPLY 2
159 struct in_addr server_address; 159
160 bool answered; 160#define DHCPDISCOVER 1
161 struct requested_server_struct *next; 161#define DHCPOFFER 2
162}requested_server; 162#define DHCPREQUEST 3
163 163#define DHCPDECLINE 4
164 164#define DHCPACK 5
165#define BOOTREQUEST 1 165#define DHCPNACK 6
166#define BOOTREPLY 2 166#define DHCPRELEASE 7
167 167
168#define DHCPDISCOVER 1 168#define DHCP_OPTION_MESSAGE_TYPE 53
169#define DHCPOFFER 2 169#define DHCP_OPTION_HOST_NAME 12
170#define DHCPREQUEST 3 170#define DHCP_OPTION_BROADCAST_ADDRESS 28
171#define DHCPDECLINE 4 171#define DHCP_OPTION_REQUESTED_ADDRESS 50
172#define DHCPACK 5 172#define DHCP_OPTION_LEASE_TIME 51
173#define DHCPNACK 6 173#define DHCP_OPTION_SERVER_IDENTIFIER 54
174#define DHCPRELEASE 7 174#define DHCP_OPTION_RENEWAL_TIME 58
175 175#define DHCP_OPTION_REBINDING_TIME 59
176#define DHCP_OPTION_MESSAGE_TYPE 53 176#define DHCP_OPTION_END 255
177#define DHCP_OPTION_HOST_NAME 12 177
178#define DHCP_OPTION_BROADCAST_ADDRESS 28 178#define DHCP_INFINITE_TIME 0xFFFFFFFF
179#define DHCP_OPTION_REQUESTED_ADDRESS 50
180#define DHCP_OPTION_LEASE_TIME 51
181#define DHCP_OPTION_SERVER_IDENTIFIER 54
182#define DHCP_OPTION_RENEWAL_TIME 58
183#define DHCP_OPTION_REBINDING_TIME 59
184#define DHCP_OPTION_END 255
185
186#define DHCP_INFINITE_TIME 0xFFFFFFFF
187 179
188#define DHCP_BROADCAST_FLAG 32768 180#define DHCP_BROADCAST_FLAG 32768
189 181
190#define DHCP_SERVER_PORT 67 182#define DHCP_SERVER_PORT 67
191#define DHCP_CLIENT_PORT 68 183#define DHCP_CLIENT_PORT 68
192
193#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */
194#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */
195
196bool unicast = false; /* unicast mode: mimic a DHCP relay */
197bool exclusive = false; /* exclusive mode aka "rogue DHCP server detection" */
198struct in_addr my_ip; /* our address (required for relay) */
199struct in_addr dhcp_ip; /* server to query (if in unicast mode) */
200unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]="";
201unsigned char *user_specified_mac=NULL;
202 184
203char network_interface_name[IFNAMSIZ]="eth0"; 185#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */
186#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */
204 187
205uint32_t packet_xid=0; 188static int verbose = 0;
206 189
207uint32_t dhcp_lease_time=0; 190typedef struct process_arguments_wrapper {
208uint32_t dhcp_renewal_time=0; 191 int error;
209uint32_t dhcp_rebinding_time=0; 192 check_dhcp_config config;
193} process_arguments_wrapper;
210 194
211int dhcpoffer_timeout=2; 195static process_arguments_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
212
213dhcp_offer *dhcp_offer_list=NULL;
214requested_server *requested_server_list=NULL;
215
216int valid_responses=0; /* number of valid DHCPOFFERs we received */
217int requested_servers=0;
218int requested_responses=0;
219
220bool request_specific_address=false;
221bool received_requested_address=false;
222int verbose=0;
223struct in_addr requested_address;
224
225
226int process_arguments(int, char **);
227int call_getopt(int, char **);
228int validate_arguments(int);
229void print_usage(void); 196void print_usage(void);
230void print_help(void); 197static void print_help(void);
231 198
232void resolve_host(const char *in,struct in_addr *out); 199static void resolve_host(const char * /*in*/, struct in_addr * /*out*/);
233unsigned char *mac_aton(const char *); 200static unsigned char *mac_aton(const char * /*string*/);
234void print_hardware_address(const unsigned char *); 201static void print_hardware_address(const unsigned char * /*address*/);
235int get_hardware_address(int,char *); 202static int get_hardware_address(int /*sock*/, char * /*interface_name*/, unsigned char *client_hardware_address);
236int get_ip_address(int,char *); 203
237 204typedef struct get_ip_address_wrapper {
238int send_dhcp_discover(int); 205 int error;
239int get_dhcp_offer(int); 206 struct in_addr my_ip;
207} get_ip_address_wrapper;
208static get_ip_address_wrapper get_ip_address(int /*sock*/, char * /*interface_name*/);
209
210typedef struct send_dhcp_discover_wrapper {
211 int error;
212 uint32_t packet_xid;
213} send_dhcp_discover_wrapper;
214static send_dhcp_discover_wrapper send_dhcp_discover(int socket, bool unicast, struct in_addr dhcp_ip, struct in_addr requested_address,
215 bool request_specific_address, struct in_addr my_ip,
216 unsigned char *client_hardware_address);
217typedef struct get_dhcp_offer_wrapper {
218 int error;
219 int valid_responses;
220 dhcp_offer *dhcp_offer_list;
221} get_dhcp_offer_wrapper;
222static get_dhcp_offer_wrapper get_dhcp_offer(int /*sock*/, int dhcpoffer_timeout, uint32_t packet_xid, dhcp_offer *dhcp_offer_list,
223 const unsigned char *client_hardware_address);
224
225static mp_subcheck get_results(bool exclusive, int requested_servers, struct in_addr requested_address, bool request_specific_address,
226 requested_server *requested_server_list, int valid_responses, dhcp_offer *dhcp_offer_list);
227
228typedef struct add_dhcp_offer_wrapper {
229 int error;
230 dhcp_offer *dhcp_offer_list;
231} add_dhcp_offer_wrapper;
232static add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr /*source*/, dhcp_packet * /*offer_packet*/, dhcp_offer *dhcp_offer_list);
233static int free_dhcp_offer_list(dhcp_offer *dhcp_offer_list);
234static int free_requested_server_list(requested_server *requested_server_list);
235
236static int create_dhcp_socket(bool /*unicast*/, char *network_interface_name);
237static int close_dhcp_socket(int /*sock*/);
238static int send_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, struct sockaddr_in * /*dest*/);
239static int receive_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, int /*timeout*/, struct sockaddr_in * /*address*/);
240
241int main(int argc, char **argv) {
242 setlocale(LC_ALL, "");
243 bindtextdomain(PACKAGE, LOCALEDIR);
244 textdomain(PACKAGE);
240 245
241int get_results(void); 246 /* Parse extra opts if any */
242 247 argv = np_extra_opts(&argc, argv, progname);
243int add_dhcp_offer(struct in_addr,dhcp_packet *);
244int free_dhcp_offer_list(void);
245int free_requested_server_list(void);
246
247int create_dhcp_socket(void);
248int close_dhcp_socket(int);
249int send_dhcp_packet(void *,int,int,struct sockaddr_in *);
250int receive_dhcp_packet(void *,int,int,int,struct sockaddr_in *);
251
252
253
254int main(int argc, char **argv){
255 int dhcp_socket;
256 int result = STATE_UNKNOWN;
257 248
258 setlocale (LC_ALL, ""); 249 process_arguments_wrapper tmp = process_arguments(argc, argv);
259 bindtextdomain (PACKAGE, LOCALEDIR);
260 textdomain (PACKAGE);
261 250
262 /* Parse extra opts if any */ 251 if (tmp.error != OK) {
263 argv=np_extra_opts(&argc, argv, progname); 252 usage4(_("Could not parse arguments"));
253 }
264 254
265 if(process_arguments(argc,argv)!=OK){ 255 check_dhcp_config config = tmp.config;
266 usage4 (_("Could not parse arguments")); 256 if (config.output_format_is_set) {
257 mp_set_format(config.output_format);
267 } 258 }
268 259
269 /* create socket for DHCP communications */ 260 /* create socket for DHCP communications */
270 dhcp_socket=create_dhcp_socket(); 261 int dhcp_socket = create_dhcp_socket(config.unicast_mode, config.network_interface_name);
271 262
272 /* get hardware address of client machine */ 263 /* get hardware address of client machine */
273 if(user_specified_mac!=NULL) 264 unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH] = "";
274 memcpy(client_hardware_address,user_specified_mac,6); 265 if (config.user_specified_mac != NULL) {
275 else 266 memcpy(client_hardware_address, config.user_specified_mac, MAC_ADDR_LEN);
276 get_hardware_address(dhcp_socket,network_interface_name); 267 } else {
268 get_hardware_address(dhcp_socket, config.network_interface_name, client_hardware_address);
269 }
277 270
278 if(unicast) /* get IP address of client machine */ 271 struct in_addr my_ip = {0};
279 get_ip_address(dhcp_socket,network_interface_name); 272
273 if (config.unicast_mode) { /* get IP address of client machine */
274 get_ip_address_wrapper tmp_get_ip = get_ip_address(dhcp_socket, config.network_interface_name);
275 if (tmp_get_ip.error == OK) {
276 my_ip = tmp_get_ip.my_ip;
277 } else {
278 // TODO failed to get own IP
279 die(STATE_UNKNOWN, "Failed to retrieve my own IP address in unicast mode");
280 }
281 }
280 282
281 /* send DHCPDISCOVER packet */ 283 /* send DHCPDISCOVER packet */
282 send_dhcp_discover(dhcp_socket); 284 send_dhcp_discover_wrapper disco_res = send_dhcp_discover(dhcp_socket, config.unicast_mode, config.dhcp_ip, config.requested_address,
285 config.request_specific_address, my_ip, client_hardware_address);
286
287 if (disco_res.error != OK) {
288 // DO something?
289 die(STATE_UNKNOWN, "Failed to send DHCP discover");
290 }
283 291
284 /* wait for a DHCPOFFER packet */ 292 /* wait for a DHCPOFFER packet */
285 get_dhcp_offer(dhcp_socket); 293 get_dhcp_offer_wrapper offer_res =
294 get_dhcp_offer(dhcp_socket, config.dhcpoffer_timeout, disco_res.packet_xid, NULL, client_hardware_address);
295
296 int valid_responses = 0;
297 dhcp_offer *dhcp_offer_list = NULL;
298 if (offer_res.error == OK) {
299 valid_responses = offer_res.valid_responses;
300 dhcp_offer_list = offer_res.dhcp_offer_list;
301 } else {
302 die(STATE_UNKNOWN, "Failed to get DHCP offers");
303 }
286 304
287 /* close socket we created */ 305 /* close socket we created */
288 close_dhcp_socket(dhcp_socket); 306 close_dhcp_socket(dhcp_socket);
289 307
290 /* determine state/plugin output to return */ 308 mp_check overall = mp_check_init();
291 result=get_results();
292 309
310 /* determine state/plugin output to return */
311 mp_subcheck sc_res = get_results(config.exclusive_mode, config.num_of_requested_servers, config.requested_address,
312 config.request_specific_address, config.requested_server_list, valid_responses, dhcp_offer_list);
313 mp_add_subcheck_to_check(&overall, sc_res);
293 /* free allocated memory */ 314 /* free allocated memory */
294 free_dhcp_offer_list(); 315 free_dhcp_offer_list(dhcp_offer_list);
295 free_requested_server_list(); 316 free_requested_server_list(config.requested_server_list);
296 317
297 return result; 318 mp_exit(overall);
298} 319}
299 320
300
301
302/* determines hardware address on client machine */ 321/* determines hardware address on client machine */
303int get_hardware_address(int sock,char *interface_name){ 322int get_hardware_address(int sock, char *interface_name, unsigned char *client_hardware_address) {
304 323
305#if defined(__linux__) 324#if defined(__linux__)
306 struct ifreq ifr; 325 struct ifreq ifr;
307 326
308 strncpy((char *)&ifr.ifr_name,interface_name,sizeof(ifr.ifr_name)-1); 327 strncpy((char *)&ifr.ifr_name, interface_name, sizeof(ifr.ifr_name) - 1);
309 ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0'; 328 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
310 329
311 /* try and grab hardware address of requested interface */ 330 /* try and grab hardware address of requested interface */
312 if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){ 331 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
313 printf(_("Error: Could not get hardware address of interface '%s'\n"),interface_name); 332 printf(_("Error: Could not get hardware address of interface '%s'\n"), interface_name);
314 exit(STATE_UNKNOWN); 333 exit(STATE_UNKNOWN);
315 } 334 }
316 335
317 memcpy(&client_hardware_address[0],&ifr.ifr_hwaddr.sa_data,6); 336 memcpy(&client_hardware_address[0], &ifr.ifr_hwaddr.sa_data, MAC_ADDR_LEN);
318 337
319#elif defined(__bsd__) 338#elif defined(__bsd__)
320 /* King 2004 see ACKNOWLEDGEMENTS */ 339 /* King 2004 see ACKNOWLEDGEMENTS */
321 340
322 size_t len; 341 size_t len;
323 int mib[6]; 342 int mib[6];
324 char *buf; 343 char *buf;
325 unsigned char *ptr; 344 unsigned char *ptr;
326 struct if_msghdr *ifm; 345 struct if_msghdr *ifm;
327 struct sockaddr_dl *sdl; 346 struct sockaddr_dl *sdl;
328 347
329 mib[0] = CTL_NET; 348 mib[0] = CTL_NET;
330 mib[1] = AF_ROUTE; 349 mib[1] = AF_ROUTE;
@@ -332,22 +351,22 @@ int get_hardware_address(int sock,char *interface_name){
332 mib[3] = AF_LINK; 351 mib[3] = AF_LINK;
333 mib[4] = NET_RT_IFLIST; 352 mib[4] = NET_RT_IFLIST;
334 353
335 if((mib[5] = if_nametoindex(interface_name)) == 0){ 354 if ((mib[5] = if_nametoindex(interface_name)) == 0) {
336 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno)); 355 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno));
337 exit(STATE_UNKNOWN); 356 exit(STATE_UNKNOWN);
338 } 357 }
339 358
340 if(sysctl(mib, 6, NULL, &len, NULL, 0) < 0){ 359 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
341 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno)); 360 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno));
342 exit(STATE_UNKNOWN); 361 exit(STATE_UNKNOWN);
343 } 362 }
344 363
345 if((buf = malloc(len)) == NULL){ 364 if ((buf = malloc(len)) == NULL) {
346 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno)); 365 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno));
347 exit(4); 366 exit(4);
348 } 367 }
349 368
350 if(sysctl(mib, 6, buf, &len, NULL, 0) < 0){ 369 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
351 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno)); 370 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno));
352 exit(STATE_UNKNOWN); 371 exit(STATE_UNKNOWN);
353 } 372 }
@@ -355,7 +374,7 @@ int get_hardware_address(int sock,char *interface_name){
355 ifm = (struct if_msghdr *)buf; 374 ifm = (struct if_msghdr *)buf;
356 sdl = (struct sockaddr_dl *)(ifm + 1); 375 sdl = (struct sockaddr_dl *)(ifm + 1);
357 ptr = (unsigned char *)LLADDR(sdl); 376 ptr = (unsigned char *)LLADDR(sdl);
358 memcpy(&client_hardware_address[0], ptr, 6) ; 377 memcpy(&client_hardware_address[0], ptr, 6);
359 /* King 2004 */ 378 /* King 2004 */
360 379
361#elif defined(__sun__) || defined(__solaris__) 380#elif defined(__sun__) || defined(__solaris__)
@@ -368,22 +387,22 @@ int get_hardware_address(int sock,char *interface_name){
368 387
369 /* get last number from interfacename, eg lnc0, e1000g0*/ 388 /* get last number from interfacename, eg lnc0, e1000g0*/
370 int i; 389 int i;
371 p = interface_name + strlen(interface_name) -1; 390 p = interface_name + strlen(interface_name) - 1;
372 for(i = strlen(interface_name) -1; i > 0; p--) { 391 for (i = strlen(interface_name) - 1; i > 0; p--) {
373 if(isalpha(*p)) 392 if (isalpha(*p)) {
374 break; 393 break;
394 }
375 } 395 }
376 p++; 396 p++;
377 if( p != interface_name ){ 397 if (p != interface_name) {
378 unit = atoi(p) ; 398 unit = atoi(p);
379 strncat(dev, interface_name, 6) ; 399 strncat(dev, interface_name, 6);
380 } 400 } else {
381 else{
382 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name); 401 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name);
383 exit(STATE_UNKNOWN); 402 exit(STATE_UNKNOWN);
384 } 403 }
385 stat = mac_addr_dlpi(dev, unit, client_hardware_address); 404 stat = mac_addr_dlpi(dev, unit, client_hardware_address);
386 if(stat != 0){ 405 if (stat != 0) {
387 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 406 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
388 exit(STATE_UNKNOWN); 407 exit(STATE_UNKNOWN);
389 } 408 }
@@ -391,11 +410,11 @@ int get_hardware_address(int sock,char *interface_name){
391#elif defined(__hpux__) 410#elif defined(__hpux__)
392 411
393 long stat; 412 long stat;
394 char dev[20] = "/dev/dlpi" ; 413 char dev[20] = "/dev/dlpi";
395 int unit = 0; 414 int unit = 0;
396 415
397 stat = mac_addr_dlpi(dev, unit, client_hardware_address); 416 stat = mac_addr_dlpi(dev, unit, client_hardware_address);
398 if(stat != 0){ 417 if (stat != 0) {
399 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 418 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
400 exit(STATE_UNKNOWN); 419 exit(STATE_UNKNOWN);
401 } 420 }
@@ -406,68 +425,69 @@ int get_hardware_address(int sock,char *interface_name){
406 exit(STATE_UNKNOWN); 425 exit(STATE_UNKNOWN);
407#endif 426#endif
408 427
409 if(verbose) 428 if (verbose) {
410 print_hardware_address(client_hardware_address); 429 print_hardware_address(client_hardware_address);
430 }
411 431
412 return OK; 432 return OK;
413} 433}
414 434
415/* determines IP address of the client interface */ 435/* determines IP address of the client interface */
416int get_ip_address(int sock,char *interface_name){ 436get_ip_address_wrapper get_ip_address(int sock, char *interface_name) {
417#if defined(SIOCGIFADDR) 437#if defined(SIOCGIFADDR)
418 struct ifreq ifr; 438 struct ifreq ifr;
419 439
420 strncpy((char *)&ifr.ifr_name,interface_name,sizeof(ifr.ifr_name)-1); 440 strncpy((char *)&ifr.ifr_name, interface_name, sizeof(ifr.ifr_name) - 1);
421 ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0'; 441 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
422 442
423 if(ioctl(sock,SIOCGIFADDR,&ifr)<0){ 443 if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) {
424 printf(_("Error: Cannot determine IP address of interface %s\n"), 444 printf(_("Error: Cannot determine IP address of interface %s\n"), interface_name);
425 interface_name);
426 exit(STATE_UNKNOWN); 445 exit(STATE_UNKNOWN);
427 } 446 }
428 447
429 my_ip=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
430
431#else 448#else
432 printf(_("Error: Cannot get interface IP address on this platform.\n")); 449 printf(_("Error: Cannot get interface IP address on this platform.\n"));
433 exit(STATE_UNKNOWN); 450 exit(STATE_UNKNOWN);
434#endif 451#endif
435 452
436 if(verbose) 453 get_ip_address_wrapper result = {
437 printf(_("Pretending to be relay client %s\n"),inet_ntoa(my_ip)); 454 .error = OK,
455 .my_ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr,
456 };
438 457
439 return OK; 458 if (verbose) {
459 printf(_("Pretending to be relay client %s\n"), inet_ntoa(result.my_ip));
460 }
461
462 return result;
440} 463}
441 464
442/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ 465/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */
443int send_dhcp_discover(int sock){ 466static send_dhcp_discover_wrapper send_dhcp_discover(int sock, bool unicast, struct in_addr dhcp_ip, struct in_addr requested_address,
444 dhcp_packet discover_packet; 467 bool request_specific_address, struct in_addr my_ip,
445 struct sockaddr_in sockaddr_broadcast; 468 unsigned char *client_hardware_address) {
446 unsigned short opts; 469 dhcp_packet discover_packet = {0};
447
448
449 /* clear the packet data structure */
450 bzero(&discover_packet,sizeof(discover_packet));
451
452
453 /* boot request flag (backward compatible with BOOTP servers) */ 470 /* boot request flag (backward compatible with BOOTP servers) */
454 discover_packet.op=BOOTREQUEST; 471 discover_packet.op = BOOTREQUEST;
455 472
456 /* hardware address type */ 473 /* hardware address type */
457 discover_packet.htype=ETHERNET_HARDWARE_ADDRESS; 474 discover_packet.htype = ETHERNET_HARDWARE_ADDRESS;
458 475
459 /* length of our hardware address */ 476 /* length of our hardware address */
460 discover_packet.hlen=ETHERNET_HARDWARE_ADDRESS_LENGTH; 477 discover_packet.hlen = ETHERNET_HARDWARE_ADDRESS_LENGTH;
461 478
479 send_dhcp_discover_wrapper result = {
480 .error = OK,
481 };
462 /* 482 /*
463 * transaction ID is supposed to be random. 483 * transaction ID is supposed to be random.
464 */ 484 */
465 srand(time(NULL)^getpid()); 485 srand(time(NULL) ^ getpid());
466 packet_xid=random(); 486 result.packet_xid = random();
467 discover_packet.xid=htonl(packet_xid); 487 discover_packet.xid = htonl(result.packet_xid);
468 488
469 /*discover_packet.secs=htons(65535);*/ 489 /*discover_packet.secs=htons(65535);*/
470 discover_packet.secs=0xFF; 490 discover_packet.secs = 0xFF;
471 491
472 /* 492 /*
473 * server needs to know if it should broadcast or unicast its response: 493 * server needs to know if it should broadcast or unicast its response:
@@ -476,408 +496,414 @@ int send_dhcp_discover(int sock){
476 discover_packet.flags = unicast ? 0 : htons(DHCP_BROADCAST_FLAG); 496 discover_packet.flags = unicast ? 0 : htons(DHCP_BROADCAST_FLAG);
477 497
478 /* our hardware address */ 498 /* our hardware address */
479 memcpy(discover_packet.chaddr,client_hardware_address,ETHERNET_HARDWARE_ADDRESS_LENGTH); 499 memcpy(discover_packet.chaddr, client_hardware_address, ETHERNET_HARDWARE_ADDRESS_LENGTH);
480 500
481 /* first four bytes of options field is magic cookie (as per RFC 2132) */ 501 /* first four bytes of options field is magic cookie (as per RFC 2132) */
482 discover_packet.options[0]='\x63'; 502 discover_packet.options[0] = '\x63';
483 discover_packet.options[1]='\x82'; 503 discover_packet.options[1] = '\x82';
484 discover_packet.options[2]='\x53'; 504 discover_packet.options[2] = '\x53';
485 discover_packet.options[3]='\x63'; 505 discover_packet.options[3] = '\x63';
486 506
487 opts = 4; 507 unsigned short opts = 4;
488 /* DHCP message type is embedded in options field */ 508 /* DHCP message type is embedded in options field */
489 discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ 509 discover_packet.options[opts++] = DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */
490 discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */ 510 discover_packet.options[opts++] = '\x01'; /* DHCP message option length in bytes */
491 discover_packet.options[opts++]=DHCPDISCOVER; 511 discover_packet.options[opts++] = DHCPDISCOVER;
492 512
493 /* the IP address we're requesting */ 513 /* the IP address we're requesting */
494 if(request_specific_address){ 514 if (request_specific_address) {
495 discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS; 515 discover_packet.options[opts++] = DHCP_OPTION_REQUESTED_ADDRESS;
496 discover_packet.options[opts++]='\x04'; 516 discover_packet.options[opts++] = '\x04';
497 memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address)); 517 memcpy(&discover_packet.options[opts], &requested_address, sizeof(requested_address));
498 opts += sizeof(requested_address); 518 opts += sizeof(requested_address);
499 } 519 }
500 discover_packet.options[opts++]= (char)DHCP_OPTION_END; 520 discover_packet.options[opts++] = (char)DHCP_OPTION_END;
501 521
502 /* unicast fields */ 522 /* unicast fields */
503 if(unicast) 523 if (unicast) {
504 discover_packet.giaddr.s_addr = my_ip.s_addr; 524 discover_packet.giaddr.s_addr = my_ip.s_addr;
525 }
505 526
506 /* see RFC 1542, 4.1.1 */ 527 /* see RFC 1542, 4.1.1 */
507 discover_packet.hops = unicast ? 1 : 0; 528 discover_packet.hops = unicast ? 1 : 0;
508 529
509 /* send the DHCPDISCOVER packet to broadcast address */ 530 /* send the DHCPDISCOVER packet to broadcast address */
510 sockaddr_broadcast.sin_family=AF_INET; 531 struct sockaddr_in sockaddr_broadcast = {
511 sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT); 532 .sin_family = AF_INET,
512 sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST; 533 .sin_port = htons(DHCP_SERVER_PORT),
513 bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero)); 534 .sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST,
514 535 };
515 536
516 if(verbose){ 537 if (verbose) {
517 printf(_("DHCPDISCOVER to %s port %d\n"),inet_ntoa(sockaddr_broadcast.sin_addr),ntohs(sockaddr_broadcast.sin_port)); 538 printf(_("DHCPDISCOVER to %s port %d\n"), inet_ntoa(sockaddr_broadcast.sin_addr), ntohs(sockaddr_broadcast.sin_port));
518 printf("DHCPDISCOVER XID: %u (0x%X)\n",ntohl(discover_packet.xid),ntohl(discover_packet.xid)); 539 printf("DHCPDISCOVER XID: %u (0x%X)\n", ntohl(discover_packet.xid), ntohl(discover_packet.xid));
519 printf("DHCDISCOVER ciaddr: %s\n",inet_ntoa(discover_packet.ciaddr)); 540 printf("DHCDISCOVER ciaddr: %s\n", inet_ntoa(discover_packet.ciaddr));
520 printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); 541 printf("DHCDISCOVER yiaddr: %s\n", inet_ntoa(discover_packet.yiaddr));
521 printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); 542 printf("DHCDISCOVER siaddr: %s\n", inet_ntoa(discover_packet.siaddr));
522 printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr)); 543 printf("DHCDISCOVER giaddr: %s\n", inet_ntoa(discover_packet.giaddr));
523 } 544 }
524 545
525 /* send the DHCPDISCOVER packet out */ 546 /* send the DHCPDISCOVER packet out */
526 send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast); 547 send_dhcp_packet(&discover_packet, sizeof(discover_packet), sock, &sockaddr_broadcast);
527 548
528 if(verbose) 549 if (verbose) {
529 printf("\n\n"); 550 printf("\n\n");
551 }
530 552
531 return OK; 553 return result;
532} 554}
533 555
534
535
536
537/* waits for a DHCPOFFER message from one or more DHCP servers */ 556/* waits for a DHCPOFFER message from one or more DHCP servers */
538int get_dhcp_offer(int sock){ 557get_dhcp_offer_wrapper get_dhcp_offer(int sock, int dhcpoffer_timeout, uint32_t packet_xid, dhcp_offer *dhcp_offer_list,
539 dhcp_packet offer_packet; 558 const unsigned char *client_hardware_address) {
540 struct sockaddr_in source;
541 struct sockaddr_in via;
542 int result=OK;
543 int responses=0;
544 int x;
545 time_t start_time; 559 time_t start_time;
546 time_t current_time;
547
548 time(&start_time); 560 time(&start_time);
549 561
562 int result = OK;
563 int responses = 0;
564 int valid_responses = 0;
550 /* receive as many responses as we can */ 565 /* receive as many responses as we can */
551 for(responses=0,valid_responses=0;;){ 566 for (;;) {
552 567 time_t current_time;
553 time(&current_time); 568 time(&current_time);
554 if((current_time-start_time)>=dhcpoffer_timeout) 569 if ((current_time - start_time) >= dhcpoffer_timeout) {
555 break; 570 break;
571 }
556 572
557 if(verbose) 573 if (verbose) {
558 printf("\n\n"); 574 printf("\n\n");
575 }
559 576
560 bzero(&source,sizeof(source)); 577 struct sockaddr_in source = {0};
561 bzero(&via,sizeof(via)); 578 dhcp_packet offer_packet = {0};
562 bzero(&offer_packet,sizeof(offer_packet));
563 579
564 result=OK; 580 result = OK;
565 result=receive_dhcp_packet(&offer_packet,sizeof(offer_packet),sock,dhcpoffer_timeout,&source); 581 result = receive_dhcp_packet(&offer_packet, sizeof(offer_packet), sock, dhcpoffer_timeout, &source);
566 582
567 if(result!=OK){ 583 if (result != OK) {
568 if(verbose) 584 if (verbose) {
569 printf(_("Result=ERROR\n")); 585 printf(_("Result=ERROR\n"));
586 }
570 587
571 continue; 588 continue;
572 } 589 }
573 else{ 590 if (verbose) {
574 if(verbose) 591 printf(_("Result=OK\n"));
575 printf(_("Result=OK\n"));
576
577 responses++;
578 } 592 }
579 593
594 responses++;
595
580 /* The "source" is either a server or a relay. */ 596 /* The "source" is either a server or a relay. */
581 /* Save a copy of "source" into "via" even if it's via itself */ 597 /* Save a copy of "source" into "via" even if it's via itself */
582 memcpy(&via,&source,sizeof(source)) ; 598 struct sockaddr_in via = {0};
599 memcpy(&via, &source, sizeof(source));
583 600
584 if(verbose){ 601 if (verbose) {
585 printf(_("DHCPOFFER from IP address %s"),inet_ntoa(source.sin_addr)); 602 printf(_("DHCPOFFER from IP address %s"), inet_ntoa(source.sin_addr));
586 printf(_(" via %s\n"),inet_ntoa(via.sin_addr)); 603 printf(_(" via %s\n"), inet_ntoa(via.sin_addr));
587 printf("DHCPOFFER XID: %u (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid)); 604 printf("DHCPOFFER XID: %u (0x%X)\n", ntohl(offer_packet.xid), ntohl(offer_packet.xid));
588 } 605 }
589 606
590 /* check packet xid to see if its the same as the one we used in the discover packet */ 607 /* check packet xid to see if its the same as the one we used in the discover packet */
591 if(ntohl(offer_packet.xid)!=packet_xid){ 608 if (ntohl(offer_packet.xid) != packet_xid) {
592 if(verbose) 609 if (verbose) {
593 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid); 610 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"), ntohl(offer_packet.xid),
611 packet_xid);
612 }
594 613
595 continue; 614 continue;
596 } 615 }
597 616
598 /* check hardware address */ 617 /* check hardware address */
599 result=OK; 618 result = OK;
600 if(verbose) 619 if (verbose) {
601 printf("DHCPOFFER chaddr: "); 620 printf("DHCPOFFER chaddr: ");
621 }
602 622
603 for(x=0;x<ETHERNET_HARDWARE_ADDRESS_LENGTH;x++){ 623 for (int i = 0; i < ETHERNET_HARDWARE_ADDRESS_LENGTH; i++) {
604 if(verbose) 624 if (verbose) {
605 printf("%02X",(unsigned char)offer_packet.chaddr[x]); 625 printf("%02X", offer_packet.chaddr[i]);
626 }
606 627
607 if(offer_packet.chaddr[x]!=client_hardware_address[x]) 628 if (offer_packet.chaddr[i] != client_hardware_address[i]) {
608 result=ERROR; 629 result = ERROR;
630 }
609 } 631 }
610 if(verbose) 632 if (verbose) {
611 printf("\n"); 633 printf("\n");
634 }
612 635
613 if(result==ERROR){ 636 if (result == ERROR) {
614 if(verbose) 637 if (verbose) {
615 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n")); 638 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n"));
639 }
616 640
617 continue; 641 continue;
618 } 642 }
619 643
620 if(verbose){ 644 if (verbose) {
621 printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr)); 645 printf("DHCPOFFER ciaddr: %s\n", inet_ntoa(offer_packet.ciaddr));
622 printf("DHCPOFFER yiaddr: %s\n",inet_ntoa(offer_packet.yiaddr)); 646 printf("DHCPOFFER yiaddr: %s\n", inet_ntoa(offer_packet.yiaddr));
623 printf("DHCPOFFER siaddr: %s\n",inet_ntoa(offer_packet.siaddr)); 647 printf("DHCPOFFER siaddr: %s\n", inet_ntoa(offer_packet.siaddr));
624 printf("DHCPOFFER giaddr: %s\n",inet_ntoa(offer_packet.giaddr)); 648 printf("DHCPOFFER giaddr: %s\n", inet_ntoa(offer_packet.giaddr));
625 } 649 }
626 650
627 add_dhcp_offer(source.sin_addr,&offer_packet); 651 add_dhcp_offer_wrapper add_res = add_dhcp_offer(source.sin_addr, &offer_packet, dhcp_offer_list);
652 if (add_res.error != OK) {
653 // TODO
654 } else {
655 dhcp_offer_list = add_res.dhcp_offer_list;
656 }
628 657
629 valid_responses++; 658 valid_responses++;
630 } 659 }
631 660
632 if(verbose){ 661 if (verbose) {
633 printf(_("Total responses seen on the wire: %d\n"),responses); 662 printf(_("Total responses seen on the wire: %d\n"), responses);
634 printf(_("Valid responses for this machine: %d\n"),valid_responses); 663 printf(_("Valid responses for this machine: %d\n"), valid_responses);
635 } 664 }
636 665
637 return OK; 666 get_dhcp_offer_wrapper ret_val = {
667 .error = OK,
668 .valid_responses = valid_responses,
669 .dhcp_offer_list = dhcp_offer_list,
670 };
671 return ret_val;
638} 672}
639 673
640
641
642/* sends a DHCP packet */ 674/* sends a DHCP packet */
643int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest){ 675int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest) {
644 int result; 676 int result = sendto(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)dest, sizeof(*dest));
645
646 result=sendto(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)dest,sizeof(*dest));
647 677
648 if(verbose) 678 if (verbose) {
649 printf(_("send_dhcp_packet result: %d\n"),result); 679 printf(_("send_dhcp_packet result: %d\n"), result);
680 }
650 681
651 if(result<0) 682 if (result < 0) {
652 return ERROR; 683 return ERROR;
684 }
653 685
654 return OK; 686 return OK;
655} 687}
656 688
657
658
659/* receives a DHCP packet */ 689/* receives a DHCP packet */
660int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){ 690int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address) {
661 struct timeval tv;
662 fd_set readfds;
663 fd_set oobfds;
664 int recv_result;
665 socklen_t address_size;
666 struct sockaddr_in source_address;
667 int nfound;
668
669
670 /* wait for data to arrive (up time timeout) */ 691 /* wait for data to arrive (up time timeout) */
671 tv.tv_sec=timeout; 692 struct timeval timeout_val = {
672 tv.tv_usec=0; 693 .tv_sec = timeout,
694 .tv_usec = 0,
695 };
696 fd_set readfds;
673 FD_ZERO(&readfds); 697 FD_ZERO(&readfds);
698 fd_set oobfds;
674 FD_ZERO(&oobfds); 699 FD_ZERO(&oobfds);
675 FD_SET(sock,&readfds); 700 FD_SET(sock, &readfds);
676 FD_SET(sock,&oobfds); 701 FD_SET(sock, &oobfds);
677 nfound = select(sock+1,&readfds,NULL,&oobfds,&tv); 702 int nfound = select(sock + 1, &readfds, NULL, &oobfds, &timeout_val);
678 703
679 /* make sure some data has arrived */ 704 /* make sure some data has arrived */
680 if(!FD_ISSET(sock,&readfds)){ 705 if (!FD_ISSET(sock, &readfds)) {
681 if(verbose) 706 if (verbose) {
682 printf(_("No (more) data received (nfound: %d)\n"), nfound); 707 printf(_("No (more) data received (nfound: %d)\n"), nfound);
708 }
683 return ERROR; 709 return ERROR;
684 } 710 }
685 711
686 else{ 712 struct sockaddr_in source_address = {0};
687 bzero(&source_address,sizeof(source_address)); 713 socklen_t address_size = sizeof(source_address);
688 address_size=sizeof(source_address); 714 int 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); 715 if (verbose) {
690 if(verbose) 716 printf("recv_result: %d\n", recv_result);
691 printf("recv_result: %d\n",recv_result); 717 }
692
693 if(recv_result==-1){
694 if(verbose){
695 printf(_("recvfrom() failed, "));
696 printf("errno: (%d) -> %s\n",errno,strerror(errno));
697 }
698 return ERROR;
699 }
700 else{
701 if(verbose){
702 printf(_("receive_dhcp_packet() result: %d\n"),recv_result);
703 printf(_("receive_dhcp_packet() source: %s\n"),inet_ntoa(source_address.sin_addr));
704 }
705 718
706 memcpy(address,&source_address,sizeof(source_address)); 719 if (recv_result == -1) {
707 return OK; 720 if (verbose) {
721 printf(_("recvfrom() failed, "));
722 printf("errno: (%d) -> %s\n", errno, strerror(errno));
708 } 723 }
724 return ERROR;
725 }
726 if (verbose) {
727 printf(_("receive_dhcp_packet() result: %d\n"), recv_result);
728 printf(_("receive_dhcp_packet() source: %s\n"), inet_ntoa(source_address.sin_addr));
709 } 729 }
710 730
731 memcpy(address, &source_address, sizeof(source_address));
711 return OK; 732 return OK;
712} 733}
713 734
714
715/* creates a socket for DHCP communication */ 735/* creates a socket for DHCP communication */
716int create_dhcp_socket(void){ 736int create_dhcp_socket(bool unicast, char *network_interface_name) {
717 struct sockaddr_in myname;
718 struct ifreq interface;
719 int sock;
720 int flag=1;
721
722 /* Set up the address we're going to bind to. */ 737 /* Set up the address we're going to bind to. */
723 bzero(&myname,sizeof(myname));
724 myname.sin_family=AF_INET;
725 /* listen to DHCP server port if we're in unicast mode */ 738 /* listen to DHCP server port if we're in unicast mode */
726 myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT); 739 struct sockaddr_in myname = {
727 myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY; 740 .sin_family = AF_INET,
728 bzero(&myname.sin_zero,sizeof(myname.sin_zero)); 741 .sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT),
742 // TODO previously the next line was trying to use our own IP, we was not set
743 // until some point later, so it was removed. Recheck whether it is actually
744 // necessary/useful
745 .sin_addr.s_addr = INADDR_ANY,
746 };
729 747
730 /* create a socket for DHCP communications */ 748 /* create a socket for DHCP communications */
731 sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); 749 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
732 if(sock<0){ 750 if (sock < 0) {
733 printf(_("Error: Could not create socket!\n")); 751 printf(_("Error: Could not create socket!\n"));
734 exit(STATE_UNKNOWN); 752 exit(STATE_UNKNOWN);
735 } 753 }
736 754
737 if(verbose) 755 if (verbose) {
738 printf("DHCP socket: %d\n",sock); 756 printf("DHCP socket: %d\n", sock);
757 }
739 758
740 /* set the reuse address flag so we don't get errors when restarting */ 759 /* set the reuse address flag so we don't get errors when restarting */
741 flag=1; 760 int flag = 1;
742 if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){ 761 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag)) < 0) {
743 printf(_("Error: Could not set reuse address option on DHCP socket!\n")); 762 printf(_("Error: Could not set reuse address option on DHCP socket!\n"));
744 exit(STATE_UNKNOWN); 763 exit(STATE_UNKNOWN);
745 } 764 }
746 765
747 /* set the broadcast option - we need this to listen to DHCP broadcast messages */ 766 /* set the broadcast option - we need this to listen to DHCP broadcast messages */
748 if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){ 767 if (!unicast && setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&flag, sizeof flag) < 0) {
749 printf(_("Error: Could not set broadcast option on DHCP socket!\n")); 768 printf(_("Error: Could not set broadcast option on DHCP socket!\n"));
750 exit(STATE_UNKNOWN); 769 exit(STATE_UNKNOWN);
751 } 770 }
752 771
772 struct ifreq interface;
753 /* bind socket to interface */ 773 /* bind socket to interface */
754#if defined(__linux__) 774#if defined(__linux__)
755 strncpy(interface.ifr_ifrn.ifrn_name,network_interface_name,IFNAMSIZ-1); 775 strncpy(interface.ifr_ifrn.ifrn_name, network_interface_name, IFNAMSIZ - 1);
756 interface.ifr_ifrn.ifrn_name[IFNAMSIZ-1]='\0'; 776 interface.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = '\0';
757 if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){ 777 if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&interface, sizeof(interface)) < 0) {
758 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name); 778 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"), network_interface_name);
759 exit(STATE_UNKNOWN); 779 exit(STATE_UNKNOWN);
760 } 780 }
761 781
762#else 782#else
763 strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1); 783 strncpy(interface.ifr_name, network_interface_name, IFNAMSIZ - 1);
764 interface.ifr_name[IFNAMSIZ-1]='\0'; 784 interface.ifr_name[IFNAMSIZ - 1] = '\0';
765#endif 785#endif
766 786
767 /* bind the socket */ 787 /* bind the socket */
768 if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){ 788 if (bind(sock, (struct sockaddr *)&myname, sizeof(myname)) < 0) {
769 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"),DHCP_CLIENT_PORT); 789 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"), DHCP_CLIENT_PORT);
770 exit(STATE_UNKNOWN); 790 exit(STATE_UNKNOWN);
771 } 791 }
772 792
773 return sock; 793 return sock;
774} 794}
775 795
776
777/* closes DHCP socket */ 796/* closes DHCP socket */
778int close_dhcp_socket(int sock){ 797int close_dhcp_socket(int sock) {
779
780 close(sock); 798 close(sock);
781
782 return OK; 799 return OK;
783} 800}
784 801
785
786/* adds a requested server address to list in memory */ 802/* adds a requested server address to list in memory */
787int add_requested_server(struct in_addr server_address){ 803int add_requested_server(struct in_addr server_address, int *requested_servers, requested_server **requested_server_list) {
788 requested_server *new_server; 804 requested_server *new_server = (requested_server *)malloc(sizeof(requested_server));
789 805 if (new_server == NULL) {
790 new_server=(requested_server *)malloc(sizeof(requested_server));
791 if(new_server==NULL)
792 return ERROR; 806 return ERROR;
807 }
793 808
794 new_server->server_address=server_address; 809 new_server->server_address = server_address;
795 new_server->answered=false; 810 new_server->answered = false;
796 811
797 new_server->next=requested_server_list; 812 new_server->next = *requested_server_list;
798 requested_server_list=new_server; 813 *requested_server_list = new_server;
799 814
800 requested_servers++; 815 *requested_servers += 1;
801 816
802 if(verbose) 817 if (verbose) {
803 printf(_("Requested server address: %s\n"),inet_ntoa(new_server->server_address)); 818 printf(_("Requested server address: %s\n"), inet_ntoa(new_server->server_address));
819 }
804 820
805 return OK; 821 return OK;
806} 822}
807 823
808
809
810
811/* adds a DHCP OFFER to list in memory */ 824/* adds a DHCP OFFER to list in memory */
812int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){ 825add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet, dhcp_offer *dhcp_offer_list) {
826 if (offer_packet == NULL) {
827 add_dhcp_offer_wrapper tmp = {
828 .error = ERROR,
829 };
830 return tmp;
831 }
832
833 uint32_t dhcp_lease_time = 0;
834 uint32_t dhcp_renewal_time = 0;
835 uint32_t dhcp_rebinding_time = 0;
813 dhcp_offer *new_offer; 836 dhcp_offer *new_offer;
814 int x;
815 unsigned option_type;
816 unsigned option_length;
817 struct in_addr serv_ident = {0}; 837 struct in_addr serv_ident = {0};
818
819 if(offer_packet==NULL)
820 return ERROR;
821
822 /* process all DHCP options present in the packet */ 838 /* process all DHCP options present in the packet */
823 for(x=4;x<MAX_DHCP_OPTIONS_LENGTH-1;){ 839 for (int dchp_opt_idx = 4; dchp_opt_idx < MAX_DHCP_OPTIONS_LENGTH - 1;) {
824 840
825 if((int)offer_packet->options[x]==-1) 841 if ((int)offer_packet->options[dchp_opt_idx] == -1) {
826 break; 842 break;
843 }
827 844
828 /* get option type */ 845 /* get option type */
829 option_type=offer_packet->options[x++]; 846 unsigned option_type = offer_packet->options[dchp_opt_idx++];
830 847
831 /* get option length */ 848 /* get option length */
832 option_length=offer_packet->options[x++]; 849 unsigned option_length = offer_packet->options[dchp_opt_idx++];
833 850
834 if(verbose) 851 if (verbose) {
835 printf("Option: %d (0x%02X)\n",option_type,option_length); 852 printf("Option: %d (0x%02X)\n", option_type, option_length);
853 }
836 854
837 /* get option data */ 855 /* get option data */
838 switch(option_type){ 856 switch (option_type) {
839 case DHCP_OPTION_LEASE_TIME: 857 case DHCP_OPTION_LEASE_TIME:
840 memcpy(&dhcp_lease_time, &offer_packet->options[x],sizeof(dhcp_lease_time)); 858 memcpy(&dhcp_lease_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_lease_time));
841 dhcp_lease_time = ntohl(dhcp_lease_time); 859 dhcp_lease_time = ntohl(dhcp_lease_time);
842 break; 860 break;
843 case DHCP_OPTION_RENEWAL_TIME: 861 case DHCP_OPTION_RENEWAL_TIME:
844 memcpy(&dhcp_renewal_time, &offer_packet->options[x],sizeof(dhcp_renewal_time)); 862 memcpy(&dhcp_renewal_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_renewal_time));
845 dhcp_renewal_time = ntohl(dhcp_renewal_time); 863 dhcp_renewal_time = ntohl(dhcp_renewal_time);
846 break; 864 break;
847 case DHCP_OPTION_REBINDING_TIME: 865 case DHCP_OPTION_REBINDING_TIME:
848 memcpy(&dhcp_rebinding_time, &offer_packet->options[x],sizeof(dhcp_rebinding_time)); 866 memcpy(&dhcp_rebinding_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_rebinding_time));
849 dhcp_rebinding_time = ntohl(dhcp_rebinding_time); 867 dhcp_rebinding_time = ntohl(dhcp_rebinding_time);
850 break; 868 break;
851 case DHCP_OPTION_SERVER_IDENTIFIER: 869 case DHCP_OPTION_SERVER_IDENTIFIER:
852 memcpy(&serv_ident.s_addr, &offer_packet->options[x],sizeof(serv_ident.s_addr)); 870 memcpy(&serv_ident.s_addr, &offer_packet->options[dchp_opt_idx], sizeof(serv_ident.s_addr));
853 break; 871 break;
854 } 872 }
855 873
856 /* skip option data we're ignoring */ 874 /* skip option data we're ignoring */
857 if(option_type==0) /* "pad" option, see RFC 2132 (3.1) */ 875 if (option_type == 0) { /* "pad" option, see RFC 2132 (3.1) */
858 x+=1; 876 dchp_opt_idx += 1;
859 else 877 } else {
860 x+=option_length; 878 dchp_opt_idx += option_length;
879 }
861 } 880 }
862 881
863 if(verbose){ 882 if (verbose) {
864 if(dhcp_lease_time==DHCP_INFINITE_TIME) 883 if (dhcp_lease_time == DHCP_INFINITE_TIME) {
865 printf(_("Lease Time: Infinite\n")); 884 printf(_("Lease Time: Infinite\n"));
866 else 885 } else {
867 printf(_("Lease Time: %lu seconds\n"),(unsigned long)dhcp_lease_time); 886 printf(_("Lease Time: %lu seconds\n"), (unsigned long)dhcp_lease_time);
868 if(dhcp_renewal_time==DHCP_INFINITE_TIME) 887 }
888 if (dhcp_renewal_time == DHCP_INFINITE_TIME) {
869 printf(_("Renewal Time: Infinite\n")); 889 printf(_("Renewal Time: Infinite\n"));
870 else 890 } else {
871 printf(_("Renewal Time: %lu seconds\n"),(unsigned long)dhcp_renewal_time); 891 printf(_("Renewal Time: %lu seconds\n"), (unsigned long)dhcp_renewal_time);
872 if(dhcp_rebinding_time==DHCP_INFINITE_TIME) 892 }
893 if (dhcp_rebinding_time == DHCP_INFINITE_TIME) {
873 printf(_("Rebinding Time: Infinite\n")); 894 printf(_("Rebinding Time: Infinite\n"));
874 printf(_("Rebinding Time: %lu seconds\n"),(unsigned long)dhcp_rebinding_time); 895 }
896 printf(_("Rebinding Time: %lu seconds\n"), (unsigned long)dhcp_rebinding_time);
875 } 897 }
876 898
877 new_offer=(dhcp_offer *)malloc(sizeof(dhcp_offer)); 899 new_offer = (dhcp_offer *)malloc(sizeof(dhcp_offer));
878 900
879 if(new_offer==NULL) 901 if (new_offer == NULL) {
880 return ERROR; 902 add_dhcp_offer_wrapper tmp = {
903 .error = ERROR,
904 };
905 return tmp;
906 }
881 907
882 /* 908 /*
883 * RFC 2131 (2.) says: "DHCP clarifies the interpretation of the 909 * RFC 2131 (2.) says: "DHCP clarifies the interpretation of the
@@ -891,298 +917,336 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
891 * DHCPOFFER from. If 'serv_ident' isn't available for some reason, we 917 * DHCPOFFER from. If 'serv_ident' isn't available for some reason, we
892 * use 'source'. 918 * use 'source'.
893 */ 919 */
894 new_offer->server_address=serv_ident.s_addr?serv_ident:source; 920 new_offer->server_address = serv_ident.s_addr ? serv_ident : source;
895 new_offer->offered_address=offer_packet->yiaddr; 921 new_offer->offered_address = offer_packet->yiaddr;
896 new_offer->lease_time=dhcp_lease_time; 922 new_offer->lease_time = dhcp_lease_time;
897 new_offer->renewal_time=dhcp_renewal_time; 923 new_offer->renewal_time = dhcp_renewal_time;
898 new_offer->rebinding_time=dhcp_rebinding_time; 924 new_offer->rebinding_time = dhcp_rebinding_time;
899 new_offer->desired=false; /* exclusive mode: we'll check that in get_results */ 925 new_offer->desired = false; /* exclusive mode: we'll check that in get_results */
900 926
901 927 if (verbose) {
902 if(verbose){ 928 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)); 929 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));
905 } 930 }
906 931
907 /* add new offer to head of list */ 932 /* add new offer to head of list */
908 new_offer->next=dhcp_offer_list; 933 new_offer->next = dhcp_offer_list;
909 dhcp_offer_list=new_offer; 934 dhcp_offer_list = new_offer;
910 935
911 return OK; 936 add_dhcp_offer_wrapper result = {
912} 937 .error = OK,
938 .dhcp_offer_list = dhcp_offer_list,
939 };
913 940
941 return result;
942}
914 943
915/* frees memory allocated to DHCP OFFER list */ 944/* frees memory allocated to DHCP OFFER list */
916int free_dhcp_offer_list(void){ 945int free_dhcp_offer_list(dhcp_offer *dhcp_offer_list) {
917 dhcp_offer *this_offer;
918 dhcp_offer *next_offer; 946 dhcp_offer *next_offer;
919 947 for (dhcp_offer *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){ 948 next_offer = this_offer->next;
921 next_offer=this_offer->next;
922 free(this_offer); 949 free(this_offer);
923 } 950 }
924 951
925 return OK; 952 return OK;
926} 953}
927 954
928
929/* frees memory allocated to requested server list */ 955/* frees memory allocated to requested server list */
930int free_requested_server_list(void){ 956int free_requested_server_list(requested_server *requested_server_list) {
931 requested_server *this_server;
932 requested_server *next_server; 957 requested_server *next_server;
933 958 for (requested_server *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){ 959 next_server = this_server->next;
935 next_server=this_server->next;
936 free(this_server); 960 free(this_server);
937 } 961 }
938 962
939 return OK; 963 return OK;
940} 964}
941 965
942
943/* gets state and plugin output to return */ 966/* gets state and plugin output to return */
944int get_results(void){ 967mp_subcheck get_results(bool exclusive, const int requested_servers, const struct in_addr requested_address, bool request_specific_address,
945 dhcp_offer *temp_offer, *undesired_offer=NULL; 968 requested_server *requested_server_list, int valid_responses, dhcp_offer *dhcp_offer_list) {
946 requested_server *temp_server; 969 mp_subcheck sc_dhcp_results = mp_subcheck_init();
947 int result; 970 sc_dhcp_results = mp_set_subcheck_default_state(sc_dhcp_results, STATE_OK);
948 uint32_t max_lease_time=0;
949
950 received_requested_address=false;
951 971
952 /* checks responses from requested servers */ 972 /* we didn't receive any DHCPOFFERs */
953 requested_responses=0; 973 if (dhcp_offer_list == NULL) {
954 if(requested_servers>0){ 974 sc_dhcp_results = mp_set_subcheck_state(sc_dhcp_results, STATE_CRITICAL);
975 xasprintf(&sc_dhcp_results.output, "%s", "No DHCPOFFERs were received");
976 return sc_dhcp_results;
977 }
955 978
956 for(temp_server=requested_server_list;temp_server!=NULL;temp_server=temp_server->next){ 979 if (valid_responses == 0) {
980 // No valid responses at all, so early exit here
981 sc_dhcp_results = mp_set_subcheck_state(sc_dhcp_results, STATE_CRITICAL);
982 xasprintf(&sc_dhcp_results.output, "No valid responses received");
983 return sc_dhcp_results;
984 }
957 985
958 for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next){ 986 if (valid_responses == 1) {
987 xasprintf(&sc_dhcp_results.output, "Received %d DHCPOFFER", valid_responses);
988 } else {
989 xasprintf(&sc_dhcp_results.output, "Received %d DHCPOFFERs", valid_responses);
990 }
959 991
992 bool received_requested_address = false;
993 dhcp_offer *undesired_offer = NULL;
994 uint32_t max_lease_time = 0;
995 /* checks responses from requested servers */
996 int requested_responses = 0;
997 if (requested_servers > 0) {
998 for (requested_server *temp_server = requested_server_list; temp_server != NULL; temp_server = temp_server->next) {
999 for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
960 /* get max lease time we were offered */ 1000 /* get max lease time we were offered */
961 if(temp_offer->lease_time>max_lease_time || temp_offer->lease_time==DHCP_INFINITE_TIME) 1001 if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) {
962 max_lease_time=temp_offer->lease_time; 1002 max_lease_time = temp_offer->lease_time;
1003 }
963 1004
964 /* see if we got the address we requested */ 1005 /* see if we got the address we requested */
965 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 1006 if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address))) {
966 received_requested_address=true; 1007 received_requested_address = true;
967 1008 }
968 /* see if the servers we wanted a response from talked to us or not */ 1009
969 if(!memcmp(&temp_offer->server_address,&temp_server->server_address,sizeof(temp_server->server_address))){ 1010 /* see if the servers we wanted a response from, talked to us or not */
970 if(verbose){ 1011 if (!memcmp(&temp_offer->server_address, &temp_server->server_address, sizeof(temp_server->server_address))) {
971 printf(_("DHCP Server Match: Offerer=%s"),inet_ntoa(temp_offer->server_address)); 1012 if (verbose) {
972 printf(_(" Requested=%s"),inet_ntoa(temp_server->server_address)); 1013 printf(_("DHCP Server Match: Offerer=%s"), inet_ntoa(temp_offer->server_address));
973 if(temp_server->answered) 1014 printf(_(" Requested=%s"), inet_ntoa(temp_server->server_address));
1015 if (temp_server->answered) {
974 printf(_(" (duplicate)")); 1016 printf(_(" (duplicate)"));
1017 }
975 printf(_("\n")); 1018 printf(_("\n"));
976 } 1019 }
977 if(!temp_server->answered){ 1020
1021 if (!temp_server->answered) {
978 requested_responses++; 1022 requested_responses++;
979 temp_server->answered=true; 1023 temp_server->answered = true;
980 temp_offer->desired=true; 1024 temp_offer->desired = true;
981 } 1025 }
982 } 1026 }
983 } 1027 }
984 } 1028 }
985 1029
986 /* exclusive mode: check for undesired offers */ 1030 /* exclusive mode: check for undesired offers */
987 for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next) { 1031 for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
988 if (!temp_offer->desired) { 1032 if (!temp_offer->desired) {
989 undesired_offer=temp_offer; /* Checks only for the first undesired offer */ 1033 undesired_offer = temp_offer; /* Checks only for the first undesired offer */
990 break; /* no further checks needed */ 1034 break; /* no further checks needed */
991 } 1035 }
992 } 1036 }
993 }
994
995 /* else check and see if we got our requested address from any server */
996 else{
997 1037
998 for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next){ 1038 mp_subcheck sc_rqust_srvs = mp_subcheck_init();
1039 xasprintf(&sc_rqust_srvs.output, "%d of %d requested servers responded", requested_responses, requested_servers);
1040
1041 if (requested_responses == requested_servers) {
1042 sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_OK);
1043 } else if (requested_responses == 0) {
1044 sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_CRITICAL);
1045 } else if (requested_responses < requested_servers) {
1046 sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_WARNING);
1047 } else {
1048 // We received more(!) responses than we asked for?
1049 // This case shouldn't happen, but is here for completion
1050 sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_WARNING);
1051 }
1052 mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rqust_srvs);
999 1053
1054 } else {
1055 /* else check and see if we got our requested address from any server */
1056 for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
1000 /* get max lease time we were offered */ 1057 /* get max lease time we were offered */
1001 if(temp_offer->lease_time>max_lease_time || temp_offer->lease_time==DHCP_INFINITE_TIME) 1058 if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) {
1002 max_lease_time=temp_offer->lease_time; 1059 max_lease_time = temp_offer->lease_time;
1060 }
1003 1061
1004 /* see if we got the address we requested */ 1062 /* see if we got the address we requested */
1005 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 1063 if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address))) {
1006 received_requested_address=true; 1064 received_requested_address = true;
1065 }
1007 } 1066 }
1008 } 1067 }
1009 1068
1010 result=STATE_OK; 1069 if (max_lease_time == DHCP_INFINITE_TIME) {
1011 if(valid_responses==0) 1070 xasprintf(&sc_dhcp_results.output, "%s, max lease time = Infinity", sc_dhcp_results.output);
1012 result=STATE_CRITICAL; 1071 } else {
1013 else if(requested_servers>0 && requested_responses==0) 1072 xasprintf(&sc_dhcp_results.output, "%s, max lease time = %" PRIu32 " seconds", sc_dhcp_results.output, max_lease_time);
1014 result=STATE_CRITICAL;
1015 else if(requested_responses<requested_servers)
1016 result=STATE_WARNING;
1017 else if(request_specific_address && !received_requested_address)
1018 result=STATE_WARNING;
1019
1020 if(exclusive && undesired_offer)
1021 result=STATE_CRITICAL;
1022
1023 if(result==0) /* garrett honeycutt 2005 */
1024 printf("OK: ");
1025 else if(result==1)
1026 printf("WARNING: ");
1027 else if(result==2)
1028 printf("CRITICAL: ");
1029 else if(result==3)
1030 printf("UNKNOWN: ");
1031
1032 /* we didn't receive any DHCPOFFERs */
1033 if(dhcp_offer_list==NULL){
1034 printf(_("No DHCPOFFERs were received.\n"));
1035 return result;
1036 } 1073 }
1037 1074
1038 printf(_("Received %d DHCPOFFER(s)"),valid_responses); 1075 if (exclusive) {
1076 mp_subcheck sc_rogue_server = mp_subcheck_init();
1039 1077
1078 if (undesired_offer != NULL) {
1079 // We wanted to get a DHCPOFFER exclusively from one machine, but another one
1080 // sent one (too)
1081 sc_rogue_server = mp_set_subcheck_state(sc_rogue_server, STATE_CRITICAL);
1040 1082
1041 if(exclusive && undesired_offer){ 1083 // Get the addresses for printout
1042 printf(_(", Rogue DHCP Server detected! Server %s"),inet_ntoa(undesired_offer->server_address)); 1084 // 1.address of the sending server
1043 printf(_(" offered %s \n"),inet_ntoa(undesired_offer->offered_address)); 1085 char server_address[INET_ADDRSTRLEN];
1044 return result; 1086 const char *server_address_transformed =
1045 } 1087 inet_ntop(AF_INET, &undesired_offer->server_address, server_address, sizeof(server_address));
1046 1088
1047 if(requested_servers>0) 1089 if (server_address != server_address_transformed) {
1048 printf(_(", %s%d of %d requested servers responded"),((requested_responses<requested_servers) && requested_responses>0)?"only ":"",requested_responses,requested_servers); 1090 die(STATE_UNKNOWN, "inet_ntop failed");
1091 }
1049 1092
1050 if(request_specific_address) 1093 // 2.address offered
1051 printf(_(", requested address (%s) was %soffered"),inet_ntoa(requested_address),(received_requested_address)?"":_("not ")); 1094 char offered_address[INET_ADDRSTRLEN];
1095 const char *offered_address_transformed =
1096 inet_ntop(AF_INET, &undesired_offer->offered_address, offered_address, sizeof(offered_address));
1052 1097
1053 printf(_(", max lease time = ")); 1098 if (offered_address != offered_address_transformed) {
1054 if(max_lease_time==DHCP_INFINITE_TIME) 1099 die(STATE_UNKNOWN, "inet_ntop failed");
1055 printf(_("Infinity")); 1100 }
1056 else
1057 printf("%lu sec",(unsigned long)max_lease_time);
1058 1101
1059 printf(".\n"); 1102 xasprintf(&sc_rogue_server.output, "Rogue DHCP Server detected! Server %s offered %s", server_address, offered_address);
1103 } else {
1104 sc_rogue_server = mp_set_subcheck_state(sc_rogue_server, STATE_OK);
1105 xasprintf(&sc_rogue_server.output, "No Rogue DHCP Server detected");
1106 }
1107 mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rogue_server);
1108 }
1060 1109
1061 return result; 1110 if (request_specific_address) {
1062} 1111 mp_subcheck sc_rqustd_addr = mp_subcheck_init();
1063 1112
1113 if (received_requested_address) {
1114 sc_rqustd_addr = mp_set_subcheck_state(sc_rqustd_addr, STATE_OK);
1115 xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was offered", inet_ntoa(requested_address));
1116 } else {
1117 sc_rqustd_addr = mp_set_subcheck_state(sc_rqustd_addr, STATE_WARNING);
1118 xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was NOT offered", inet_ntoa(requested_address));
1119 }
1064 1120
1065/* process command-line arguments */ 1121 mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rqustd_addr);
1066int process_arguments(int argc, char **argv){ 1122 }
1067 if(argc<1)
1068 return ERROR;
1069 1123
1070 call_getopt(argc,argv); 1124 return sc_dhcp_results;
1071 return validate_arguments(argc);
1072} 1125}
1073 1126
1127/* process command-line arguments */
1128process_arguments_wrapper process_arguments(int argc, char **argv) {
1129 if (argc < 1) {
1130 process_arguments_wrapper tmp = {
1131 .error = ERROR,
1132 };
1133 return tmp;
1134 }
1074 1135
1075 1136 enum {
1076int call_getopt(int argc, char **argv){ 1137 output_format_index = CHAR_MAX + 1,
1077 extern int optind;
1078 int option_index = 0;
1079 static struct option long_options[] =
1080 {
1081 {"serverip", required_argument,0,'s'},
1082 {"requestedip", required_argument,0,'r'},
1083 {"timeout", required_argument,0,'t'},
1084 {"interface", required_argument,0,'i'},
1085 {"mac", required_argument,0,'m'},
1086 {"unicast", no_argument, 0,'u'},
1087 {"exclusive", no_argument, 0,'x'},
1088 {"verbose", no_argument, 0,'v'},
1089 {"version", no_argument, 0,'V'},
1090 {"help", no_argument, 0,'h'},
1091 {0,0,0,0}
1092 }; 1138 };
1093 1139
1094 int c=0; 1140 int option_index = 0;
1095 while(true){ 1141 static struct option long_options[] = {{"serverip", required_argument, 0, 's'},
1096 c=getopt_long(argc,argv,"+hVvxt:s:r:t:i:m:u",long_options,&option_index); 1142 {"requestedip", required_argument, 0, 'r'},
1097 1143 {"timeout", required_argument, 0, 't'},
1098 if(c==-1||c==EOF||c==1) 1144 {"interface", required_argument, 0, 'i'},
1145 {"mac", required_argument, 0, 'm'},
1146 {"unicast", no_argument, 0, 'u'},
1147 {"exclusive", no_argument, 0, 'x'},
1148 {"verbose", no_argument, 0, 'v'},
1149 {"version", no_argument, 0, 'V'},
1150 {"help", no_argument, 0, 'h'},
1151 {"output-format", required_argument, 0, output_format_index},
1152 {0, 0, 0, 0}};
1153
1154 check_dhcp_config config = check_dhcp_config_init();
1155 int option_char = 0;
1156 while (true) {
1157 option_char = getopt_long(argc, argv, "+hVvxt:s:r:t:i:m:u", long_options, &option_index);
1158
1159 if (option_char == -1 || option_char == EOF || option_char == 1) {
1099 break; 1160 break;
1161 }
1100 1162
1101 switch(c){ 1163 switch (option_char) {
1102 1164 case 's': /* DHCP server address */
1103 case 's': /* DHCP server address */ 1165 resolve_host(optarg, &config.dhcp_ip);
1104 resolve_host(optarg,&dhcp_ip); 1166 add_requested_server(config.dhcp_ip, &config.num_of_requested_servers, &config.requested_server_list);
1105 add_requested_server(dhcp_ip); 1167 break;
1106 break;
1107
1108 case 'r': /* address we are requested from DHCP servers */
1109 resolve_host(optarg,&requested_address);
1110 request_specific_address=true;
1111 break;
1112
1113 case 't': /* timeout */
1114
1115 /*
1116 if(is_intnonneg(optarg))
1117 */
1118 if(atoi(optarg)>0)
1119 dhcpoffer_timeout=atoi(optarg);
1120 /*
1121 else
1122 usage("Time interval must be a nonnegative integer\n");
1123 */
1124 break;
1125 1168
1126 case 'm': /* MAC address */ 1169 case 'r': /* address we are requested from DHCP servers */
1170 resolve_host(optarg, &config.requested_address);
1171 config.request_specific_address = true;
1172 break;
1127 1173
1128 if((user_specified_mac=mac_aton(optarg)) == NULL) 1174 case 't': /* timeout */
1129 usage("Cannot parse MAC address.\n"); 1175 if (atoi(optarg) > 0) {
1130 if(verbose) 1176 config.dhcpoffer_timeout = atoi(optarg);
1131 print_hardware_address(user_specified_mac); 1177 }
1178 break;
1132 1179
1133 break; 1180 case 'm': /* MAC address */
1181 if ((config.user_specified_mac = mac_aton(optarg)) == NULL) {
1182 usage("Cannot parse MAC address.\n");
1183 }
1184 if (verbose) {
1185 print_hardware_address(config.user_specified_mac);
1186 }
1187 break;
1134 1188
1135 case 'i': /* interface name */ 1189 case 'i': /* interface name */
1190 strncpy(config.network_interface_name, optarg, sizeof(config.network_interface_name) - 1);
1191 config.network_interface_name[sizeof(config.network_interface_name) - 1] = '\x0';
1192 break;
1136 1193
1137 strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1); 1194 case 'u': /* unicast testing */
1138 network_interface_name[sizeof(network_interface_name)-1]='\x0'; 1195 config.unicast_mode = true;
1196 break;
1139 1197
1140 break; 1198 case 'x': /* exclusive testing aka "rogue DHCP server detection" */
1199 config.exclusive_mode = true;
1200 break;
1141 1201
1142 case 'u': /* unicast testing */ 1202 case 'V': /* version */
1143 unicast=true; 1203 print_revision(progname, NP_VERSION);
1144 break; 1204 exit(STATE_UNKNOWN);
1145 case 'x': /* exclusive testing aka "rogue DHCP server detection" */
1146 exclusive=true;
1147 break;
1148 1205
1149 case 'V': /* version */ 1206 case 'h': /* help */
1150 print_revision(progname, NP_VERSION); 1207 print_help();
1151 exit(STATE_UNKNOWN); 1208 exit(STATE_UNKNOWN);
1152 1209
1153 case 'h': /* help */ 1210 case 'v': /* verbose */
1154 print_help(); 1211 verbose = 1;
1212 break;
1213 case output_format_index: {
1214 parsed_output_format parser = mp_parse_output_format(optarg);
1215 if (!parser.parsing_success) {
1216 // TODO List all available formats here, maybe add anothoer usage function
1217 printf("Invalid output format: %s\n", optarg);
1155 exit(STATE_UNKNOWN); 1218 exit(STATE_UNKNOWN);
1219 }
1156 1220
1157 case 'v': /* verbose */ 1221 config.output_format_is_set = true;
1158 verbose=1; 1222 config.output_format = parser.output_format;
1159 break; 1223 break;
1160 case '?': /* help */ 1224 }
1161 usage5 (); 1225 case '?': /* help */
1162 break; 1226 usage5();
1227 break;
1163 1228
1164 default: 1229 default:
1165 break; 1230 break;
1166 } 1231 }
1167 } 1232 }
1168 return optind;
1169}
1170 1233
1171 1234 if (argc - optind > 0) {
1172int validate_arguments(int argc){
1173
1174 if(argc - optind > 0)
1175 usage(_("Got unexpected non-option argument")); 1235 usage(_("Got unexpected non-option argument"));
1236 }
1176 1237
1177 return OK; 1238 process_arguments_wrapper result = {
1239 .config = config,
1240 .error = OK,
1241 };
1242 return result;
1178} 1243}
1179 1244
1180
1181#if defined(__sun__) || defined(__solaris__) || defined(__hpux__) 1245#if defined(__sun__) || defined(__solaris__) || defined(__hpux__)
1182/* Kompf 2000-2003 see ACKNOWLEDGEMENTS */ 1246/* Kompf 2000-2003 see ACKNOWLEDGEMENTS */
1183 1247
1184/* get a message from a stream; return type of message */ 1248/* get a message from a stream; return type of message */
1185static int get_msg(int fd){ 1249static int get_msg(int fd) {
1186 int flags = 0; 1250 int flags = 0;
1187 int res, ret; 1251 int res, ret;
1188 ctl_area[0] = 0; 1252 ctl_area[0] = 0;
@@ -1190,30 +1254,29 @@ static int get_msg(int fd){
1190 ret = 0; 1254 ret = 0;
1191 res = getmsg(fd, &ctl, &dat, &flags); 1255 res = getmsg(fd, &ctl, &dat, &flags);
1192 1256
1193 if(res < 0){ 1257 if (res < 0) {
1194 if(errno == EINTR){ 1258 if (errno == EINTR) {
1195 return(GOT_INTR); 1259 return (GOT_INTR);
1196 } 1260 } else {
1197 else{
1198 printf("%s\n", "get_msg FAILED."); 1261 printf("%s\n", "get_msg FAILED.");
1199 return(GOT_ERR); 1262 return (GOT_ERR);
1200 } 1263 }
1201 } 1264 }
1202 if(ctl.len > 0){ 1265 if (ctl.len > 0) {
1203 ret |= GOT_CTRL; 1266 ret |= GOT_CTRL;
1204 } 1267 }
1205 if(dat.len > 0){ 1268 if (dat.len > 0) {
1206 ret |= GOT_DATA; 1269 ret |= GOT_DATA;
1207 } 1270 }
1208 1271
1209 return(ret); 1272 return (ret);
1210} 1273}
1211 1274
1212/* verify that dl_primitive in ctl_area = prim */ 1275/* verify that dl_primitive in ctl_area = prim */
1213static int check_ctrl(int prim){ 1276static int check_ctrl(int prim) {
1214 dl_error_ack_t *err_ack = (dl_error_ack_t *)ctl_area; 1277 dl_error_ack_t *err_ack = (dl_error_ack_t *)ctl_area;
1215 1278
1216 if(err_ack->dl_primitive != prim){ 1279 if (err_ack->dl_primitive != prim) {
1217 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno)); 1280 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno));
1218 exit(STATE_UNKNOWN); 1281 exit(STATE_UNKNOWN);
1219 } 1282 }
@@ -1222,35 +1285,35 @@ static int check_ctrl(int prim){
1222} 1285}
1223 1286
1224/* put a control message on a stream */ 1287/* put a control message on a stream */
1225static int put_ctrl(int fd, int len, int pri){ 1288static int put_ctrl(int fd, int len, int pri) {
1226 1289
1227 ctl.len = len; 1290 ctl.len = len;
1228 if(putmsg(fd, &ctl, 0, pri) < 0){ 1291 if (putmsg(fd, &ctl, 0, pri) < 0) {
1229 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno)); 1292 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno));
1230 exit(STATE_UNKNOWN); 1293 exit(STATE_UNKNOWN);
1231 } 1294 }
1232 1295
1233 return 0; 1296 return 0;
1234} 1297}
1235 1298
1236/* put a control + data message on a stream */ 1299/* put a control + data message on a stream */
1237static int put_both(int fd, int clen, int dlen, int pri){ 1300static int put_both(int fd, int clen, int dlen, int pri) {
1238 1301
1239 ctl.len = clen; 1302 ctl.len = clen;
1240 dat.len = dlen; 1303 dat.len = dlen;
1241 if(putmsg(fd, &ctl, &dat, pri) < 0){ 1304 if (putmsg(fd, &ctl, &dat, pri) < 0) {
1242 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno)); 1305 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno));
1243 exit(STATE_UNKNOWN); 1306 exit(STATE_UNKNOWN);
1244 } 1307 }
1245 1308
1246 return 0; 1309 return 0;
1247} 1310}
1248 1311
1249/* open file descriptor and attach */ 1312/* open file descriptor and attach */
1250static int dl_open(const char *dev, int unit, int *fd){ 1313static int dl_open(const char *dev, int unit, int *fd) {
1251 dl_attach_req_t *attach_req = (dl_attach_req_t *)ctl_area; 1314 dl_attach_req_t *attach_req = (dl_attach_req_t *)ctl_area;
1252 1315
1253 if((*fd = open(dev, O_RDWR)) == -1){ 1316 if ((*fd = open(dev, O_RDWR)) == -1) {
1254 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno)); 1317 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno));
1255 exit(STATE_UNKNOWN); 1318 exit(STATE_UNKNOWN);
1256 } 1319 }
@@ -1262,7 +1325,7 @@ static int dl_open(const char *dev, int unit, int *fd){
1262} 1325}
1263 1326
1264/* send DL_BIND_REQ */ 1327/* send DL_BIND_REQ */
1265static int dl_bind(int fd, int sap, u_char *addr){ 1328static int dl_bind(int fd, int sap, u_char *addr) {
1266 dl_bind_req_t *bind_req = (dl_bind_req_t *)ctl_area; 1329 dl_bind_req_t *bind_req = (dl_bind_req_t *)ctl_area;
1267 dl_bind_ack_t *bind_ack = (dl_bind_ack_t *)ctl_area; 1330 dl_bind_ack_t *bind_ack = (dl_bind_ack_t *)ctl_area;
1268 1331
@@ -1274,12 +1337,11 @@ static int dl_bind(int fd, int sap, u_char *addr){
1274 bind_req->dl_xidtest_flg = 0; 1337 bind_req->dl_xidtest_flg = 0;
1275 put_ctrl(fd, sizeof(dl_bind_req_t), 0); 1338 put_ctrl(fd, sizeof(dl_bind_req_t), 0);
1276 get_msg(fd); 1339 get_msg(fd);
1277 if (GOT_ERR == check_ctrl(DL_BIND_ACK)){ 1340 if (GOT_ERR == check_ctrl(DL_BIND_ACK)) {
1278 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno)); 1341 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno));
1279 exit(STATE_UNKNOWN); 1342 exit(STATE_UNKNOWN);
1280 } 1343 }
1281 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr, 1344 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr, bind_ack->dl_addr_length);
1282 bind_ack->dl_addr_length);
1283 1345
1284 return 0; 1346 return 0;
1285} 1347}
@@ -1296,13 +1358,13 @@ static int dl_bind(int fd, int sap, u_char *addr){
1296 * 1358 *
1297 ***********************************************************************/ 1359 ***********************************************************************/
1298 1360
1299long mac_addr_dlpi( const char *dev, int unit, u_char *addr){ 1361long mac_addr_dlpi(const char *dev, int unit, u_char *addr) {
1300 int fd; 1362 int fd;
1301 u_char mac_addr[25]; 1363 u_char mac_addr[25];
1302 1364
1303 if(GOT_ERR != dl_open(dev, unit, &fd)){ 1365 if (GOT_ERR != dl_open(dev, unit, &fd)) {
1304 if(GOT_ERR != dl_bind(fd, INSAP, mac_addr)){ 1366 if (GOT_ERR != dl_bind(fd, INSAP, mac_addr)) {
1305 bcopy( mac_addr, addr, 6); 1367 bcopy(mac_addr, addr, 6);
1306 return 0; 1368 return 0;
1307 } 1369 }
1308 } 1370 }
@@ -1314,99 +1376,93 @@ long mac_addr_dlpi( const char *dev, int unit, u_char *addr){
1314/* Kompf 2000-2003 */ 1376/* Kompf 2000-2003 */
1315#endif 1377#endif
1316 1378
1317
1318/* resolve host name or die (TODO: move this to netutils.c!) */ 1379/* resolve host name or die (TODO: move this to netutils.c!) */
1319void resolve_host(const char *in,struct in_addr *out){ 1380void resolve_host(const char *name, struct in_addr *out) {
1320 struct addrinfo hints, *ai; 1381 struct addrinfo hints = {
1382 .ai_family = PF_INET,
1383 };
1384 struct addrinfo *addr_info;
1321 1385
1322 memset(&hints,0,sizeof(hints)); 1386 if (getaddrinfo(name, NULL, &hints, &addr_info) != 0) {
1323 hints.ai_family=PF_INET; 1387 usage_va(_("Invalid hostname/address - %s"), optarg);
1324 if (getaddrinfo(in,NULL,&hints,&ai) != 0) 1388 }
1325 usage_va(_("Invalid hostname/address - %s"),optarg);
1326 1389
1327 memcpy(out,&((struct sockaddr_in *)ai->ai_addr)->sin_addr,sizeof(*out)); 1390 memcpy(out, &((struct sockaddr_in *)addr_info->ai_addr)->sin_addr, sizeof(*out));
1328 freeaddrinfo(ai); 1391 freeaddrinfo(addr_info);
1329} 1392}
1330 1393
1331
1332/* parse MAC address string, return 6 bytes (unterminated) or NULL */ 1394/* parse MAC address string, return 6 bytes (unterminated) or NULL */
1333unsigned char *mac_aton(const char *string){ 1395unsigned char *mac_aton(const char *string) {
1334 static unsigned char result[6]; 1396 static unsigned char result[MAC_ADDR_LEN];
1335 char tmp[3]; 1397 char tmp[3];
1336 unsigned i, j; 1398 unsigned byte_counter = 0;
1337 1399
1338 for(i=0, j=0; string[i] != '\0' && j < sizeof(result); i++){ 1400 for (int i = 0; string[i] != '\0' && byte_counter < sizeof(result); i++) {
1339 /* ignore ':' and any other non-hex character */ 1401 /* ignore ':' and any other non-hex character */
1340 if(!isxdigit(string[i]) || !isxdigit(string[i+1])) 1402 if (!isxdigit(string[i]) || !isxdigit(string[i + 1])) {
1341 continue; 1403 continue;
1342 tmp[0]=string[i]; 1404 }
1343 tmp[1]=string[i+1]; 1405 tmp[0] = string[i];
1344 tmp[2]='\0'; 1406 tmp[1] = string[i + 1];
1345 result[j]=strtol(tmp,(char **)NULL,16); 1407 tmp[2] = '\0';
1408 result[byte_counter] = strtol(tmp, (char **)NULL, 16);
1346 i++; 1409 i++;
1347 j++; 1410 byte_counter++;
1348 } 1411 }
1349 1412
1350 return (j==6) ? result : NULL; 1413 return (byte_counter == MAC_ADDR_LEN) ? result : NULL;
1351} 1414}
1352 1415
1353 1416void print_hardware_address(const unsigned char *address) {
1354void print_hardware_address(const unsigned char *address){
1355 int i;
1356 1417
1357 printf(_("Hardware address: ")); 1418 printf(_("Hardware address: "));
1358 for (i=0; i<5; i++) 1419 for (int addr_idx = 0; addr_idx < MAC_ADDR_LEN; addr_idx++) {
1359 printf("%2.2x:", address[i]); 1420 printf("%2.2x:", address[addr_idx]);
1360 printf("%2.2x", address[i]); 1421 }
1361 putchar('\n'); 1422 putchar('\n');
1362} 1423}
1363 1424
1364
1365/* print usage help */ 1425/* print usage help */
1366void print_help(void){ 1426void print_help(void) {
1367 1427
1368 print_revision(progname, NP_VERSION); 1428 print_revision(progname, NP_VERSION);
1369 1429
1370 printf("Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org)\n"); 1430 printf("Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org)\n");
1371 printf (COPYRIGHT, copyright, email); 1431 printf(COPYRIGHT, copyright, email);
1372 1432
1373 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network.")); 1433 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network."));
1374 1434
1375 printf ("\n\n"); 1435 printf("\n\n");
1376 1436
1377 print_usage(); 1437 print_usage();
1378 1438
1379 printf (UT_HELP_VRSN); 1439 printf(UT_HELP_VRSN);
1380 printf (UT_EXTRA_OPTS); 1440 printf(UT_EXTRA_OPTS);
1381 1441
1382 printf (UT_VERBOSE); 1442 printf(UT_OUTPUT_FORMAT);
1383 1443 printf(UT_VERBOSE);
1384 printf (" %s\n", "-s, --serverip=IPADDRESS"); 1444
1385 printf (" %s\n", _("IP address of DHCP server that we must hear from")); 1445 printf(" %s\n", "-s, --serverip=IPADDRESS");
1386 printf (" %s\n", "-r, --requestedip=IPADDRESS"); 1446 printf(" %s\n", _("IP address of DHCP server that we must hear from"));
1387 printf (" %s\n", _("IP address that should be offered by at least one DHCP server")); 1447 printf(" %s\n", "-r, --requestedip=IPADDRESS");
1388 printf (" %s\n", "-t, --timeout=INTEGER"); 1448 printf(" %s\n", _("IP address that should be offered by at least one DHCP server"));
1389 printf (" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs")); 1449 printf(" %s\n", "-t, --timeout=INTEGER");
1390 printf (" %s\n", "-i, --interface=STRING"); 1450 printf(" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs"));
1391 printf (" %s\n", _("Interface to to use for listening (i.e. eth0)")); 1451 printf(" %s\n", "-i, --interface=STRING");
1392 printf (" %s\n", "-m, --mac=STRING"); 1452 printf(" %s\n", _("Interface to to use for listening (i.e. eth0)"));
1393 printf (" %s\n", _("MAC address to use in the DHCP request")); 1453 printf(" %s\n", "-m, --mac=STRING");
1394 printf (" %s\n", "-u, --unicast"); 1454 printf(" %s\n", _("MAC address to use in the DHCP request"));
1395 printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s")); 1455 printf(" %s\n", "-u, --unicast");
1396 printf (" %s\n", "-x, --exclusive"); 1456 printf(" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s"));
1397 printf (" %s\n", _("Only requested DHCP server may response (rogue DHCP server detection), requires -s")); 1457 printf(" %s\n", "-x, --exclusive");
1398 1458 printf(" %s\n", _("Only requested DHCP server may response (rogue DHCP server detection), requires -s"));
1399 printf (UT_SUPPORT); 1459
1400 return; 1460 printf(UT_SUPPORT);
1401} 1461}
1402 1462
1463void print_usage(void) {
1403 1464
1404void 1465 printf("%s\n", _("Usage:"));
1405print_usage(void){ 1466 printf(" %s [-v] [-u] [-x] [-s serverip] [-r requestedip] [-t timeout]\n", progname);
1406 1467 printf(" [-i interface] [-m mac]\n");
1407 printf ("%s\n", _("Usage:"));
1408 printf (" %s [-v] [-u] [-x] [-s serverip] [-r requestedip] [-t timeout]\n",progname);
1409 printf (" [-i interface] [-m mac]\n");
1410
1411 return;
1412} 1468}