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