[monitoring-plugins] Refactor check_dhcp

Lorenz Kästle git at monitoring-plugins.org
Mon Jun 23 13:40:11 CEST 2025


 Module: monitoring-plugins
 Branch: master
 Commit: 0453d6d1e206c1f4c156bf73c473608a8c0da4f5
 Author: Lorenz Kästle <12514511+RincewindsHat at users.noreply.github.com>
   Date: Tue Apr  1 00:44:26 2025 +0200
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=0453d6d1

Refactor check_dhcp

---

 plugins-root/check_dhcp.c          | 741 ++++++++++++++++++++-----------------
 plugins-root/check_dhcp.d/config.h |  50 +++
 2 files changed, 448 insertions(+), 343 deletions(-)

diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c
index 70809956..3732d970 100644
--- a/plugins-root/check_dhcp.c
+++ b/plugins-root/check_dhcp.c
@@ -4,7 +4,7 @@
  *
  * License: GPL
  * Copyright (c) 2001-2004 Ethan Galstad (nagios at nagios.org)
- * Copyright (c) 2001-2023 Monitoring Plugins Development Team
+ * Copyright (c) 2001-2025 Monitoring Plugins Development Team
  *
  * Description:
  *
@@ -34,13 +34,17 @@
  *****************************************************************************/
 
 const char *progname = "check_dhcp";
-const char *copyright = "2001-2024";
+const char *copyright = "2001-2025";
 const char *email = "devel at monitoring-plugins.org";
 
-#include "common.h"
-#include "netutils.h"
-#include "utils.h"
+#include "../plugins/common.h"
+#include "../plugins/utils.h"
+#include "./check_dhcp.d/config.h"
+#include "../lib/output.h"
+#include "../lib/utils_base.h"
 
+#include "states.h"
+#include <stdint.h>
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -111,8 +115,9 @@ static long mac_addr_dlpi(const char *, int, u_char *);
 
 /**** Common definitions ****/
 
-#define OK    0
-#define ERROR -1
+#define OK           0
+#define ERROR        -1
+#define MAC_ADDR_LEN 6
 
 /**** DHCP definitions ****/
 
@@ -149,12 +154,6 @@ typedef struct dhcp_offer_struct {
 	struct dhcp_offer_struct *next;
 } dhcp_offer;
 
-typedef struct requested_server_struct {
-	struct in_addr server_address;
-	bool answered;
-	struct requested_server_struct *next;
-} requested_server;
-
 #define BOOTREQUEST 1
 #define BOOTREPLY   2
 
@@ -186,65 +185,60 @@ typedef struct requested_server_struct {
 #define ETHERNET_HARDWARE_ADDRESS        1 /* used in htype field of dhcp packet */
 #define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */
 
-static bool unicast = false;   /* unicast mode: mimic a DHCP relay */
-static bool exclusive = false; /* exclusive mode aka "rogue DHCP server detection" */
-static struct in_addr my_ip;   /* our address (required for relay) */
-static struct in_addr dhcp_ip; /* server to query (if in unicast mode) */
-static unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH] = "";
-static unsigned char *user_specified_mac = NULL;
-
-static char network_interface_name[IFNAMSIZ] = "eth0";
-
-static uint32_t packet_xid = 0;
-
-static uint32_t dhcp_lease_time = 0;
-static uint32_t dhcp_renewal_time = 0;
-static uint32_t dhcp_rebinding_time = 0;
-
-static int dhcpoffer_timeout = 2;
-
-static dhcp_offer *dhcp_offer_list = NULL;
-static requested_server *requested_server_list = NULL;
-
-static int valid_responses = 0; /* number of valid DHCPOFFERs we received */
-static int requested_servers = 0;
-static int requested_responses = 0;
-
-static bool request_specific_address = false;
-static bool received_requested_address = false;
 static int verbose = 0;
-static struct in_addr requested_address;
 
-static int process_arguments(int, char **);
-static int call_getopt(int, char **);
-static int validate_arguments(int);
+typedef struct process_arguments_wrapper {
+	int error;
+	check_dhcp_config config;
+} process_arguments_wrapper;
+
+static process_arguments_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
 void print_usage(void);
 static void print_help(void);
 
-static void resolve_host(const char *in, struct in_addr *out);
-static unsigned char *mac_aton(const char *);
-static void print_hardware_address(const unsigned char *);
-static int get_hardware_address(int, char *);
-static int get_ip_address(int, char *);
-
-static int send_dhcp_discover(int);
-static int get_dhcp_offer(int);
-
-static int get_results(void);
-
-static int add_dhcp_offer(struct in_addr, dhcp_packet *);
-static int free_dhcp_offer_list(void);
-static int free_requested_server_list(void);
-
-static int create_dhcp_socket(void);
-static int close_dhcp_socket(int);
-static int send_dhcp_packet(void *, int, int, struct sockaddr_in *);
-static int receive_dhcp_packet(void *, int, int, int, struct sockaddr_in *);
+static void resolve_host(const char * /*in*/, struct in_addr * /*out*/);
+static unsigned char *mac_aton(const char * /*string*/);
+static void print_hardware_address(const unsigned char * /*address*/);
+static int get_hardware_address(int /*sock*/, char * /*interface_name*/, unsigned char *client_hardware_address);
+
+typedef struct get_ip_address_wrapper {
+	int error;
+	struct in_addr my_ip;
+} get_ip_address_wrapper;
+static get_ip_address_wrapper get_ip_address(int /*sock*/, char * /*interface_name*/);
+
+typedef struct send_dhcp_discover_wrapper {
+	int error;
+	uint32_t packet_xid;
+} send_dhcp_discover_wrapper;
+static send_dhcp_discover_wrapper send_dhcp_discover(int socket, bool unicast, struct in_addr dhcp_ip, struct in_addr requested_address,
+													 bool request_specific_address, struct in_addr my_ip,
+													 unsigned char *client_hardware_address);
+typedef struct get_dhcp_offer_wrapper {
+	int error;
+	int valid_responses;
+	dhcp_offer *dhcp_offer_list;
+} get_dhcp_offer_wrapper;
+static get_dhcp_offer_wrapper get_dhcp_offer(int /*sock*/, int dhcpoffer_timeout, uint32_t packet_xid, dhcp_offer *dhcp_offer_list,
+											 const unsigned char *client_hardware_address);
+
+static mp_subcheck get_results(bool exclusive, int requested_servers, struct in_addr requested_address, bool request_specific_address,
+							   requested_server *requested_server_list, int valid_responses, dhcp_offer *dhcp_offer_list);
+
+typedef struct add_dhcp_offer_wrapper {
+	int error;
+	dhcp_offer *dhcp_offer_list;
+} add_dhcp_offer_wrapper;
+static add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr /*source*/, dhcp_packet * /*offer_packet*/, dhcp_offer *dhcp_offer_list);
+static int free_dhcp_offer_list(dhcp_offer *dhcp_offer_list);
+static int free_requested_server_list(requested_server *requested_server_list);
+
+static int create_dhcp_socket(bool /*unicast*/, char *network_interface_name);
+static int close_dhcp_socket(int /*sock*/);
+static int send_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, struct sockaddr_in * /*dest*/);
+static int receive_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, int /*timeout*/, struct sockaddr_in * /*address*/);
 
 int main(int argc, char **argv) {
-	int dhcp_socket;
-	int result = STATE_UNKNOWN;
-
 	setlocale(LC_ALL, "");
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
@@ -252,45 +246,80 @@ int main(int argc, char **argv) {
 	/* Parse extra opts if any */
 	argv = np_extra_opts(&argc, argv, progname);
 
-	if (process_arguments(argc, argv) != OK) {
+	process_arguments_wrapper tmp = process_arguments(argc, argv);
+
+	if (tmp.error != OK) {
 		usage4(_("Could not parse arguments"));
 	}
 
+	check_dhcp_config config = tmp.config;
+	if (config.output_format_is_set) {
+		mp_set_format(config.output_format);
+	}
+
 	/* create socket for DHCP communications */
-	dhcp_socket = create_dhcp_socket();
+	int dhcp_socket = create_dhcp_socket(config.unicast_mode, config.network_interface_name);
 
 	/* get hardware address of client machine */
-	if (user_specified_mac != NULL) {
-		memcpy(client_hardware_address, user_specified_mac, 6);
+	unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH] = "";
+	if (config.user_specified_mac != NULL) {
+		memcpy(client_hardware_address, config.user_specified_mac, MAC_ADDR_LEN);
 	} else {
-		get_hardware_address(dhcp_socket, network_interface_name);
+		get_hardware_address(dhcp_socket, config.network_interface_name, client_hardware_address);
 	}
 
-	if (unicast) { /* get IP address of client machine */
-		get_ip_address(dhcp_socket, network_interface_name);
+	struct in_addr my_ip = {0};
+
+	if (config.unicast_mode) { /* get IP address of client machine */
+		get_ip_address_wrapper tmp_get_ip = get_ip_address(dhcp_socket, config.network_interface_name);
+		if (tmp_get_ip.error == OK) {
+			my_ip = tmp_get_ip.my_ip;
+		} else {
+			// TODO failed to get own IP
+			die(STATE_UNKNOWN, "Failed to retrieve my own IP address in unicast mode");
+		}
 	}
 
 	/* send DHCPDISCOVER packet */
-	send_dhcp_discover(dhcp_socket);
+	send_dhcp_discover_wrapper disco_res = send_dhcp_discover(dhcp_socket, config.unicast_mode, config.dhcp_ip, config.requested_address,
+															  config.request_specific_address, my_ip, client_hardware_address);
+
+	if (disco_res.error != OK) {
+		// DO something?
+		die(STATE_UNKNOWN, "Failed to send DHCP discover");
+	}
 
 	/* wait for a DHCPOFFER packet */
-	get_dhcp_offer(dhcp_socket);
+	get_dhcp_offer_wrapper offer_res =
+		get_dhcp_offer(dhcp_socket, config.dhcpoffer_timeout, disco_res.packet_xid, NULL, client_hardware_address);
+
+	int valid_responses = 0;
+	dhcp_offer *dhcp_offer_list = NULL;
+	if (offer_res.error == OK) {
+		valid_responses = offer_res.valid_responses;
+		dhcp_offer_list = offer_res.dhcp_offer_list;
+	} else {
+		die(STATE_UNKNOWN, "Failed to get DHCP offers");
+	}
 
 	/* close socket we created */
 	close_dhcp_socket(dhcp_socket);
 
-	/* determine state/plugin output to return */
-	result = get_results();
+	mp_check overall = mp_check_init();
 
+	/* determine state/plugin output to return */
+	mp_subcheck sc_res = get_results(config.exclusive_mode, config.num_of_requested_servers, config.requested_address,
+									 config.request_specific_address, config.requested_server_list, valid_responses, dhcp_offer_list);
+	mp_add_subcheck_to_check(&overall, sc_res);
 	/* free allocated memory */
-	free_dhcp_offer_list();
-	free_requested_server_list();
+	free_dhcp_offer_list(dhcp_offer_list);
+	free_requested_server_list(config.requested_server_list);
 
-	return result;
+	mp_exit(overall);
 }
 
 /* determines hardware address on client machine */
-static int get_hardware_address(int sock, char *interface_name) {
+int get_hardware_address(int sock, char *interface_name, unsigned char *client_hardware_address) {
 
 #if defined(__linux__)
 	struct ifreq ifr;
@@ -304,7 +333,7 @@ static int get_hardware_address(int sock, char *interface_name) {
 		exit(STATE_UNKNOWN);
 	}
 
-	memcpy(&client_hardware_address[0], &ifr.ifr_hwaddr.sa_data, 6);
+	memcpy(&client_hardware_address[0], &ifr.ifr_hwaddr.sa_data, MAC_ADDR_LEN);
 
 #elif defined(__bsd__)
 	/* King 2004	see ACKNOWLEDGEMENTS */
@@ -404,7 +433,7 @@ static int get_hardware_address(int sock, char *interface_name) {
 }
 
 /* determines IP address of the client interface */
-static int get_ip_address(int sock, char *interface_name) {
+get_ip_address_wrapper get_ip_address(int sock, char *interface_name) {
 #if defined(SIOCGIFADDR)
 	struct ifreq ifr;
 
@@ -416,29 +445,28 @@ static int get_ip_address(int sock, char *interface_name) {
 		exit(STATE_UNKNOWN);
 	}
 
-	my_ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
-
 #else
 	printf(_("Error: Cannot get interface IP address on this platform.\n"));
 	exit(STATE_UNKNOWN);
 #endif
 
+	get_ip_address_wrapper result = {
+		.error = OK,
+		.my_ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr,
+	};
+
 	if (verbose) {
-		printf(_("Pretending to be relay client %s\n"), inet_ntoa(my_ip));
+		printf(_("Pretending to be relay client %s\n"), inet_ntoa(result.my_ip));
 	}
 
-	return OK;
+	return result;
 }
 
 /* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */
-static int send_dhcp_discover(int sock) {
-	dhcp_packet discover_packet;
-	struct sockaddr_in sockaddr_broadcast;
-	unsigned short opts;
-
-	/* clear the packet data structure */
-	bzero(&discover_packet, sizeof(discover_packet));
-
+static send_dhcp_discover_wrapper send_dhcp_discover(int sock, bool unicast, struct in_addr dhcp_ip, struct in_addr requested_address,
+													 bool request_specific_address, struct in_addr my_ip,
+													 unsigned char *client_hardware_address) {
+	dhcp_packet discover_packet = {0};
 	/* boot request flag (backward compatible with BOOTP servers) */
 	discover_packet.op = BOOTREQUEST;
 
@@ -448,12 +476,15 @@ static int send_dhcp_discover(int sock) {
 	/* length of our hardware address */
 	discover_packet.hlen = ETHERNET_HARDWARE_ADDRESS_LENGTH;
 
+	send_dhcp_discover_wrapper result = {
+		.error = OK,
+	};
 	/*
 	 * transaction ID is supposed to be random.
 	 */
 	srand(time(NULL) ^ getpid());
-	packet_xid = random();
-	discover_packet.xid = htonl(packet_xid);
+	result.packet_xid = random();
+	discover_packet.xid = htonl(result.packet_xid);
 
 	/*discover_packet.secs=htons(65535);*/
 	discover_packet.secs = 0xFF;
@@ -473,7 +504,7 @@ static int send_dhcp_discover(int sock) {
 	discover_packet.options[2] = '\x53';
 	discover_packet.options[3] = '\x63';
 
-	opts = 4;
+	unsigned short opts = 4;
 	/* DHCP message type is embedded in options field */
 	discover_packet.options[opts++] = DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */
 	discover_packet.options[opts++] = '\x01';                   /* DHCP message option length in bytes */
@@ -497,10 +528,11 @@ static int send_dhcp_discover(int sock) {
 	discover_packet.hops = unicast ? 1 : 0;
 
 	/* send the DHCPDISCOVER packet to broadcast address */
-	sockaddr_broadcast.sin_family = AF_INET;
-	sockaddr_broadcast.sin_port = htons(DHCP_SERVER_PORT);
-	sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST;
-	bzero(&sockaddr_broadcast.sin_zero, sizeof(sockaddr_broadcast.sin_zero));
+	struct sockaddr_in sockaddr_broadcast = {
+		.sin_family = AF_INET,
+		.sin_port = htons(DHCP_SERVER_PORT),
+		.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST,
+	};
 
 	if (verbose) {
 		printf(_("DHCPDISCOVER to %s port %d\n"), inet_ntoa(sockaddr_broadcast.sin_addr), ntohs(sockaddr_broadcast.sin_port));
@@ -518,25 +550,21 @@ static int send_dhcp_discover(int sock) {
 		printf("\n\n");
 	}
 
-	return OK;
+	return result;
 }
 
 /* waits for a DHCPOFFER message from one or more DHCP servers */
-static int get_dhcp_offer(int sock) {
-	dhcp_packet offer_packet;
-	struct sockaddr_in source;
-	struct sockaddr_in via;
-	int result = OK;
-	int responses = 0;
-	int x;
+get_dhcp_offer_wrapper get_dhcp_offer(int sock, int dhcpoffer_timeout, uint32_t packet_xid, dhcp_offer *dhcp_offer_list,
+									  const unsigned char *client_hardware_address) {
 	time_t start_time;
-	time_t current_time;
-
 	time(&start_time);
 
+	int result = OK;
+	int responses = 0;
+	int valid_responses = 0;
 	/* receive as many responses as we can */
-	for (responses = 0, valid_responses = 0;;) {
-
+	for (;;) {
+		time_t current_time;
 		time(&current_time);
 		if ((current_time - start_time) >= dhcpoffer_timeout) {
 			break;
@@ -546,9 +574,8 @@ static int get_dhcp_offer(int sock) {
 			printf("\n\n");
 		}
 
-		bzero(&source, sizeof(source));
-		bzero(&via, sizeof(via));
-		bzero(&offer_packet, sizeof(offer_packet));
+		struct sockaddr_in source = {0};
+		dhcp_packet offer_packet = {0};
 
 		result = OK;
 		result = receive_dhcp_packet(&offer_packet, sizeof(offer_packet), sock, dhcpoffer_timeout, &source);
@@ -559,16 +586,16 @@ static int get_dhcp_offer(int sock) {
 			}
 
 			continue;
-		} else {
-			if (verbose) {
-				printf(_("Result=OK\n"));
-			}
-
-			responses++;
 		}
+		if (verbose) {
+			printf(_("Result=OK\n"));
+		}
+
+		responses++;
 
 		/* The "source" is either a server or a relay. */
 		/* Save a copy of "source" into "via" even if it's via itself */
+		struct sockaddr_in via = {0};
 		memcpy(&via, &source, sizeof(source));
 
 		if (verbose) {
@@ -593,12 +620,12 @@ static int get_dhcp_offer(int sock) {
 			printf("DHCPOFFER chaddr: ");
 		}
 
-		for (x = 0; x < ETHERNET_HARDWARE_ADDRESS_LENGTH; x++) {
+		for (int i = 0; i < ETHERNET_HARDWARE_ADDRESS_LENGTH; i++) {
 			if (verbose) {
-				printf("%02X", (unsigned char)offer_packet.chaddr[x]);
+				printf("%02X", offer_packet.chaddr[i]);
 			}
 
-			if (offer_packet.chaddr[x] != client_hardware_address[x]) {
+			if (offer_packet.chaddr[i] != client_hardware_address[i]) {
 				result = ERROR;
 			}
 		}
@@ -621,7 +648,12 @@ static int get_dhcp_offer(int sock) {
 			printf("DHCPOFFER giaddr: %s\n", inet_ntoa(offer_packet.giaddr));
 		}
 
-		add_dhcp_offer(source.sin_addr, &offer_packet);
+		add_dhcp_offer_wrapper add_res = add_dhcp_offer(source.sin_addr, &offer_packet, dhcp_offer_list);
+		if (add_res.error != OK) {
+			// TODO
+		} else {
+			dhcp_offer_list = add_res.dhcp_offer_list;
+		}
 
 		valid_responses++;
 	}
@@ -631,14 +663,17 @@ static int get_dhcp_offer(int sock) {
 		printf(_("Valid responses for this machine: %d\n"), valid_responses);
 	}
 
-	return OK;
+	get_dhcp_offer_wrapper ret_val = {
+		.error = OK,
+		.valid_responses = valid_responses,
+		.dhcp_offer_list = dhcp_offer_list,
+	};
+	return ret_val;
 }
 
 /* sends a DHCP packet */
-static int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest) {
-	int result;
-
-	result = sendto(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)dest, sizeof(*dest));
+int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest) {
+	int result = sendto(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)dest, sizeof(*dest));
 
 	if (verbose) {
 		printf(_("send_dhcp_packet result: %d\n"), result);
@@ -652,23 +687,19 @@ static int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sock
 }
 
 /* receives a DHCP packet */
-static int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address) {
-	struct timeval tv;
-	fd_set readfds;
-	fd_set oobfds;
-	int recv_result;
-	socklen_t address_size;
-	struct sockaddr_in source_address;
-	int nfound;
-
+int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address) {
 	/* wait for data to arrive (up time timeout) */
-	tv.tv_sec = timeout;
-	tv.tv_usec = 0;
+	struct timeval timeout_val = {
+		.tv_sec = timeout,
+		.tv_usec = 0,
+	};
+	fd_set readfds;
 	FD_ZERO(&readfds);
+	fd_set oobfds;
 	FD_ZERO(&oobfds);
 	FD_SET(sock, &readfds);
 	FD_SET(sock, &oobfds);
-	nfound = select(sock + 1, &readfds, NULL, &oobfds, &tv);
+	int nfound = select(sock + 1, &readfds, NULL, &oobfds, &timeout_val);
 
 	/* make sure some data has arrived */
 	if (!FD_ISSET(sock, &readfds)) {
@@ -678,51 +709,44 @@ static int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int time
 		return ERROR;
 	}
 
-	else {
-		bzero(&source_address, sizeof(source_address));
-		address_size = sizeof(source_address);
-		recv_result = recvfrom(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)&source_address, &address_size);
-		if (verbose) {
-			printf("recv_result: %d\n", recv_result);
-		}
-
-		if (recv_result == -1) {
-			if (verbose) {
-				printf(_("recvfrom() failed, "));
-				printf("errno: (%d) -> %s\n", errno, strerror(errno));
-			}
-			return ERROR;
-		} else {
-			if (verbose) {
-				printf(_("receive_dhcp_packet() result: %d\n"), recv_result);
-				printf(_("receive_dhcp_packet() source: %s\n"), inet_ntoa(source_address.sin_addr));
-			}
+	struct sockaddr_in source_address = {0};
+	socklen_t address_size = sizeof(source_address);
+	int recv_result = recvfrom(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)&source_address, &address_size);
+	if (verbose) {
+		printf("recv_result: %d\n", recv_result);
+	}
 
-			memcpy(address, &source_address, sizeof(source_address));
-			return OK;
+	if (recv_result == -1) {
+		if (verbose) {
+			printf(_("recvfrom() failed, "));
+			printf("errno: (%d) -> %s\n", errno, strerror(errno));
 		}
+		return ERROR;
+	}
+	if (verbose) {
+		printf(_("receive_dhcp_packet() result: %d\n"), recv_result);
+		printf(_("receive_dhcp_packet() source: %s\n"), inet_ntoa(source_address.sin_addr));
 	}
 
+	memcpy(address, &source_address, sizeof(source_address));
 	return OK;
 }
 
 /* creates a socket for DHCP communication */
-static int create_dhcp_socket(void) {
-	struct sockaddr_in myname;
-	struct ifreq interface;
-	int sock;
-	int flag = 1;
-
+int create_dhcp_socket(bool unicast, char *network_interface_name) {
 	/* Set up the address we're going to bind to. */
-	bzero(&myname, sizeof(myname));
-	myname.sin_family = AF_INET;
 	/* listen to DHCP server port if we're in unicast mode */
-	myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT);
-	myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY;
-	bzero(&myname.sin_zero, sizeof(myname.sin_zero));
+	struct sockaddr_in myname = {
+		.sin_family = AF_INET,
+		.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT),
+		// TODO previously the next line was trying to use our own IP, we was not set
+		// until some point later, so it was removed. Recheck whether it is actually
+		// necessary/useful
+		.sin_addr.s_addr = INADDR_ANY,
+	};
 
 	/* create a socket for DHCP communications */
-	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 	if (sock < 0) {
 		printf(_("Error: Could not create socket!\n"));
 		exit(STATE_UNKNOWN);
@@ -733,7 +757,7 @@ static int create_dhcp_socket(void) {
 	}
 
 	/* set the reuse address flag so we don't get errors when restarting */
-	flag = 1;
+	int flag = 1;
 	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag)) < 0) {
 		printf(_("Error: Could not set reuse address option on DHCP socket!\n"));
 		exit(STATE_UNKNOWN);
@@ -745,6 +769,7 @@ static int create_dhcp_socket(void) {
 		exit(STATE_UNKNOWN);
 	}
 
+	struct ifreq interface;
 	/* bind socket to interface */
 #if defined(__linux__)
 	strncpy(interface.ifr_ifrn.ifrn_name, network_interface_name, IFNAMSIZ - 1);
@@ -769,18 +794,14 @@ static int create_dhcp_socket(void) {
 }
 
 /* closes DHCP socket */
-static int close_dhcp_socket(int sock) {
-
+int close_dhcp_socket(int sock) {
 	close(sock);
-
 	return OK;
 }
 
 /* adds a requested server address to list in memory */
-static int add_requested_server(struct in_addr server_address) {
-	requested_server *new_server;
-
-	new_server = (requested_server *)malloc(sizeof(requested_server));
+int add_requested_server(struct in_addr server_address, int *requested_servers, requested_server **requested_server_list) {
+	requested_server *new_server = (requested_server *)malloc(sizeof(requested_server));
 	if (new_server == NULL) {
 		return ERROR;
 	}
@@ -788,10 +809,10 @@ static int add_requested_server(struct in_addr server_address) {
 	new_server->server_address = server_address;
 	new_server->answered = false;
 
-	new_server->next = requested_server_list;
-	requested_server_list = new_server;
+	new_server->next = *requested_server_list;
+	*requested_server_list = new_server;
 
-	requested_servers++;
+	*requested_servers += 1;
 
 	if (verbose) {
 		printf(_("Requested server address: %s\n"), inet_ntoa(new_server->server_address));
@@ -801,29 +822,31 @@ static int add_requested_server(struct in_addr server_address) {
 }
 
 /* adds a DHCP OFFER to list in memory */
-static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) {
-	dhcp_offer *new_offer;
-	int x;
-	unsigned option_type;
-	unsigned option_length;
-	struct in_addr serv_ident = {0};
-
+add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet, dhcp_offer *dhcp_offer_list) {
 	if (offer_packet == NULL) {
-		return ERROR;
+		add_dhcp_offer_wrapper tmp = {
+			.error = ERROR,
+		};
+		return tmp;
 	}
 
+	uint32_t dhcp_lease_time = 0;
+	uint32_t dhcp_renewal_time = 0;
+	uint32_t dhcp_rebinding_time = 0;
+	dhcp_offer *new_offer;
+	struct in_addr serv_ident = {0};
 	/* process all DHCP options present in the packet */
-	for (x = 4; x < MAX_DHCP_OPTIONS_LENGTH - 1;) {
+	for (int dchp_opt_idx = 4; dchp_opt_idx < MAX_DHCP_OPTIONS_LENGTH - 1;) {
 
-		if ((int)offer_packet->options[x] == -1) {
+		if ((int)offer_packet->options[dchp_opt_idx] == -1) {
 			break;
 		}
 
 		/* get option type */
-		option_type = offer_packet->options[x++];
+		unsigned option_type = offer_packet->options[dchp_opt_idx++];
 
 		/* get option length */
-		option_length = offer_packet->options[x++];
+		unsigned option_length = offer_packet->options[dchp_opt_idx++];
 
 		if (verbose) {
 			printf("Option: %d (0x%02X)\n", option_type, option_length);
@@ -832,27 +855,27 @@ static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) {
 		/* get option data */
 		switch (option_type) {
 		case DHCP_OPTION_LEASE_TIME:
-			memcpy(&dhcp_lease_time, &offer_packet->options[x], sizeof(dhcp_lease_time));
+			memcpy(&dhcp_lease_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_lease_time));
 			dhcp_lease_time = ntohl(dhcp_lease_time);
 			break;
 		case DHCP_OPTION_RENEWAL_TIME:
-			memcpy(&dhcp_renewal_time, &offer_packet->options[x], sizeof(dhcp_renewal_time));
+			memcpy(&dhcp_renewal_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_renewal_time));
 			dhcp_renewal_time = ntohl(dhcp_renewal_time);
 			break;
 		case DHCP_OPTION_REBINDING_TIME:
-			memcpy(&dhcp_rebinding_time, &offer_packet->options[x], sizeof(dhcp_rebinding_time));
+			memcpy(&dhcp_rebinding_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_rebinding_time));
 			dhcp_rebinding_time = ntohl(dhcp_rebinding_time);
 			break;
 		case DHCP_OPTION_SERVER_IDENTIFIER:
-			memcpy(&serv_ident.s_addr, &offer_packet->options[x], sizeof(serv_ident.s_addr));
+			memcpy(&serv_ident.s_addr, &offer_packet->options[dchp_opt_idx], sizeof(serv_ident.s_addr));
 			break;
 		}
 
 		/* skip option data we're ignoring */
 		if (option_type == 0) { /* "pad" option, see RFC 2132 (3.1) */
-			x += 1;
+			dchp_opt_idx += 1;
 		} else {
-			x += option_length;
+			dchp_opt_idx += option_length;
 		}
 	}
 
@@ -876,7 +899,10 @@ static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) {
 	new_offer = (dhcp_offer *)malloc(sizeof(dhcp_offer));
 
 	if (new_offer == NULL) {
-		return ERROR;
+		add_dhcp_offer_wrapper tmp = {
+			.error = ERROR,
+		};
+		return tmp;
 	}
 
 	/*
@@ -907,15 +933,18 @@ static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) {
 	new_offer->next = dhcp_offer_list;
 	dhcp_offer_list = new_offer;
 
-	return OK;
+	add_dhcp_offer_wrapper result = {
+		.error = OK,
+		.dhcp_offer_list = dhcp_offer_list,
+	};
+
+	return result;
 }
 
 /* frees memory allocated to DHCP OFFER list */
-static int free_dhcp_offer_list(void) {
-	dhcp_offer *this_offer;
+int free_dhcp_offer_list(dhcp_offer *dhcp_offer_list) {
 	dhcp_offer *next_offer;
-
-	for (this_offer = dhcp_offer_list; this_offer != NULL; this_offer = next_offer) {
+	for (dhcp_offer *this_offer = dhcp_offer_list; this_offer != NULL; this_offer = next_offer) {
 		next_offer = this_offer->next;
 		free(this_offer);
 	}
@@ -924,11 +953,9 @@ static int free_dhcp_offer_list(void) {
 }
 
 /* frees memory allocated to requested server list */
-static int free_requested_server_list(void) {
-	requested_server *this_server;
+int free_requested_server_list(requested_server *requested_server_list) {
 	requested_server *next_server;
-
-	for (this_server = requested_server_list; this_server != NULL; this_server = next_server) {
+	for (requested_server *this_server = requested_server_list; this_server != NULL; this_server = next_server) {
 		next_server = this_server->next;
 		free(this_server);
 	}
@@ -937,22 +964,39 @@ static int free_requested_server_list(void) {
 }
 
 /* gets state and plugin output to return */
-static int get_results(void) {
-	dhcp_offer *temp_offer, *undesired_offer = NULL;
-	requested_server *temp_server;
-	int result;
-	uint32_t max_lease_time = 0;
-
-	received_requested_address = false;
+mp_subcheck get_results(bool exclusive, const int requested_servers, const struct in_addr requested_address, bool request_specific_address,
+						requested_server *requested_server_list, int valid_responses, dhcp_offer *dhcp_offer_list) {
+	mp_subcheck sc_dhcp_results = mp_subcheck_init();
+	sc_dhcp_results = mp_set_subcheck_default_state(sc_dhcp_results, STATE_OK);
 
-	/* checks responses from requested servers */
-	requested_responses = 0;
-	if (requested_servers > 0) {
+	/* we didn't receive any DHCPOFFERs */
+	if (dhcp_offer_list == NULL) {
+		sc_dhcp_results = mp_set_subcheck_state(sc_dhcp_results, STATE_CRITICAL);
+		xasprintf(&sc_dhcp_results.output, "%s", "No DHCP offers were received");
+		return sc_dhcp_results;
+	}
 
-		for (temp_server = requested_server_list; temp_server != NULL; temp_server = temp_server->next) {
+	if (valid_responses == 0) {
+		// No valid responses at all, so early exit here
+		sc_dhcp_results = mp_set_subcheck_state(sc_dhcp_results, STATE_CRITICAL);
+		xasprintf(&sc_dhcp_results.output, "No valid responses received");
+		return sc_dhcp_results;
+	}
 
-			for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
+	if (valid_responses == 1) {
+		xasprintf(&sc_dhcp_results.output, "Received %d DHCPOFFER", valid_responses);
+	} else {
+		xasprintf(&sc_dhcp_results.output, "Received %d DHCPOFFERs", valid_responses);
+	}
 
+	bool received_requested_address = false;
+	dhcp_offer *undesired_offer = NULL;
+	uint32_t max_lease_time = 0;
+	/* checks responses from requested servers */
+	int requested_responses = 0;
+	if (requested_servers > 0) {
+		for (requested_server *temp_server = requested_server_list; temp_server != NULL; temp_server = temp_server->next) {
+			for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
 				/* get max lease time we were offered */
 				if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) {
 					max_lease_time = temp_offer->lease_time;
@@ -963,7 +1007,7 @@ static int get_results(void) {
 					received_requested_address = true;
 				}
 
-				/* see if the servers we wanted a response from talked to us or not */
+				/* see if the servers we wanted a response from, talked to us or not */
 				if (!memcmp(&temp_offer->server_address, &temp_server->server_address, sizeof(temp_server->server_address))) {
 					if (verbose) {
 						printf(_("DHCP Server Match: Offerer=%s"), inet_ntoa(temp_offer->server_address));
@@ -973,6 +1017,7 @@ static int get_results(void) {
 						}
 						printf(_("\n"));
 					}
+
 					if (!temp_server->answered) {
 						requested_responses++;
 						temp_server->answered = true;
@@ -983,19 +1028,32 @@ static int get_results(void) {
 		}
 
 		/* exclusive mode: check for undesired offers */
-		for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
+		for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
 			if (!temp_offer->desired) {
 				undesired_offer = temp_offer; /* Checks only for the first undesired offer */
 				break;                        /* no further checks needed */
 			}
 		}
-	}
 
-	/* else check and see if we got our requested address from any server */
-	else {
+		mp_subcheck sc_rqust_srvs = mp_subcheck_init();
+		xasprintf(&sc_rqust_srvs.output, "%d of %d requested servers responded", requested_responses, requested_servers);
 
-		for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
+		if (requested_responses == requested_servers) {
+			sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_OK);
+		} else if (requested_responses == 0) {
+			sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_CRITICAL);
+		} else if (requested_responses < requested_servers) {
+			sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_WARNING);
+		} else {
+			// We received more(!) responses than we asked for?
+			// This case shouldn't happen, but is here for completion
+			sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_WARNING);
+		}
+		mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rqust_srvs);
 
+	} else {
+		/* else check and see if we got our requested address from any server */
+		for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) {
 			/* get max lease time we were offered */
 			if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) {
 				max_lease_time = temp_offer->lease_time;
@@ -1008,79 +1066,77 @@ static int get_results(void) {
 		}
 	}
 
-	result = STATE_OK;
-	if (valid_responses == 0) {
-		result = STATE_CRITICAL;
-	} else if (requested_servers > 0 && requested_responses == 0) {
-		result = STATE_CRITICAL;
-	} else if (requested_responses < requested_servers) {
-		result = STATE_WARNING;
-	} else if (request_specific_address && !received_requested_address) {
-		result = STATE_WARNING;
+	if (max_lease_time == DHCP_INFINITE_TIME) {
+		xasprintf(&sc_dhcp_results.output, "%s, max lease time = Infinity", sc_dhcp_results.output);
+	} else {
+		xasprintf(&sc_dhcp_results.output, "%s, max lease time = %" PRIu32 " seconds", sc_dhcp_results.output, max_lease_time);
 	}
 
-	if (exclusive && undesired_offer) {
-		result = STATE_CRITICAL;
-	}
+	if (exclusive) {
+		mp_subcheck sc_rogue_server = mp_subcheck_init();
 
-	if (result == 0) { /* garrett honeycutt 2005 */
-		printf("OK: ");
-	} else if (result == 1) {
-		printf("WARNING: ");
-	} else if (result == 2) {
-		printf("CRITICAL: ");
-	} else if (result == 3) {
-		printf("UNKNOWN: ");
-	}
+		if (undesired_offer != NULL) {
+			// We wanted to get a DHCPOFFER exclusively from one machine, but another one
+			// sent one (too)
+			sc_rogue_server = mp_set_subcheck_state(sc_rogue_server, STATE_CRITICAL);
 
-	/* we didn't receive any DHCPOFFERs */
-	if (dhcp_offer_list == NULL) {
-		printf(_("No DHCPOFFERs were received.\n"));
-		return result;
-	}
+			// Get the addresses for printout
+			// 1.address of the sending server
+			char server_address[INET_ADDRSTRLEN];
+			const char *server_address_transformed =
+				inet_ntop(AF_INET, &undesired_offer->server_address, server_address, sizeof(server_address));
+
+			if (server_address != server_address_transformed) {
+				die(STATE_UNKNOWN, "inet_ntop failed");
+			}
 
-	printf(_("Received %d DHCPOFFER(s)"), valid_responses);
+			// 2.address offered
+			char offered_address[INET_ADDRSTRLEN];
+			const char *offered_address_transformed =
+				inet_ntop(AF_INET, &undesired_offer->offered_address, offered_address, sizeof(offered_address));
 
-	if (exclusive && undesired_offer) {
-		printf(_(", Rogue DHCP Server detected! Server %s"), inet_ntoa(undesired_offer->server_address));
-		printf(_(" offered %s \n"), inet_ntoa(undesired_offer->offered_address));
-		return result;
-	}
+			if (offered_address != offered_address_transformed) {
+				die(STATE_UNKNOWN, "inet_ntop failed");
+			}
 
-	if (requested_servers > 0) {
-		printf(_(", %s%d of %d requested servers responded"),
-			   ((requested_responses < requested_servers) && requested_responses > 0) ? "only " : "", requested_responses,
-			   requested_servers);
+			xasprintf(&sc_rogue_server.output, "Rogue DHCP Server detected! Server %s offered %s", server_address, offered_address);
+		} else {
+			sc_rogue_server = mp_set_subcheck_state(sc_rogue_server, STATE_OK);
+			xasprintf(&sc_rogue_server.output, "No Rogue DHCP Server detected");
+		}
+		mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rogue_server);
 	}
 
 	if (request_specific_address) {
-		printf(_(", requested address (%s) was %soffered"), inet_ntoa(requested_address), (received_requested_address) ? "" : _("not "));
-	}
+		mp_subcheck sc_rqustd_addr = mp_subcheck_init();
 
-	printf(_(", max lease time = "));
-	if (max_lease_time == DHCP_INFINITE_TIME) {
-		printf(_("Infinity"));
-	} else {
-		printf("%lu sec", (unsigned long)max_lease_time);
-	}
+		if (received_requested_address) {
+			sc_rqustd_addr = mp_set_subcheck_state(sc_rqustd_addr, STATE_OK);
+			xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was offered", inet_ntoa(requested_address));
+		} else {
+			sc_rqustd_addr = mp_set_subcheck_state(sc_rqustd_addr, STATE_WARNING);
+			xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was NOT offered", inet_ntoa(requested_address));
+		}
 
-	printf(".\n");
+		mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rqustd_addr);
+	}
 
-	return result;
+	return sc_dhcp_results;
 }
 
 /* process command-line arguments */
-static int process_arguments(int argc, char **argv) {
+process_arguments_wrapper process_arguments(int argc, char **argv) {
 	if (argc < 1) {
-		return ERROR;
+		process_arguments_wrapper tmp = {
+			.error = ERROR,
+		};
+		return tmp;
 	}
 
-	call_getopt(argc, argv);
-	return validate_arguments(argc);
-}
+	enum {
+		output_format_index = CHAR_MAX + 1,
+	};
 
-static int call_getopt(int argc, char **argv) {
-	extern int optind;
 	int option_index = 0;
 	static struct option long_options[] = {{"serverip", required_argument, 0, 's'},
 										   {"requestedip", required_argument, 0, 'r'},
@@ -1092,65 +1148,55 @@ static int call_getopt(int argc, char **argv) {
 										   {"verbose", no_argument, 0, 'v'},
 										   {"version", no_argument, 0, 'V'},
 										   {"help", no_argument, 0, 'h'},
+										   {"output-format", required_argument, 0, output_format_index},
 										   {0, 0, 0, 0}};
 
-	int c = 0;
+	check_dhcp_config config = check_dhcp_config_init();
+	int option_char = 0;
 	while (true) {
-		c = getopt_long(argc, argv, "+hVvxt:s:r:t:i:m:u", long_options, &option_index);
+		option_char = getopt_long(argc, argv, "+hVvxt:s:r:t:i:m:u", long_options, &option_index);
 
-		if (c == -1 || c == EOF || c == 1) {
+		if (option_char == -1 || option_char == EOF || option_char == 1) {
 			break;
 		}
 
-		switch (c) {
-
+		switch (option_char) {
 		case 's': /* DHCP server address */
-			resolve_host(optarg, &dhcp_ip);
-			add_requested_server(dhcp_ip);
+			resolve_host(optarg, &config.dhcp_ip);
+			add_requested_server(config.dhcp_ip, &config.num_of_requested_servers, &config.requested_server_list);
 			break;
 
 		case 'r': /* address we are requested from DHCP servers */
-			resolve_host(optarg, &requested_address);
-			request_specific_address = true;
+			resolve_host(optarg, &config.requested_address);
+			config.request_specific_address = true;
 			break;
 
 		case 't': /* timeout */
-
-			/*
-				 if(is_intnonneg(optarg))
-				 */
 			if (atoi(optarg) > 0) {
-				dhcpoffer_timeout = atoi(optarg);
+				config.dhcpoffer_timeout = atoi(optarg);
 			}
-			/*
-				 else
-				 usage("Time interval must be a nonnegative integer\n");
-				 */
 			break;
 
 		case 'm': /* MAC address */
-
-			if ((user_specified_mac = mac_aton(optarg)) == NULL) {
+			if ((config.user_specified_mac = mac_aton(optarg)) == NULL) {
 				usage("Cannot parse MAC address.\n");
 			}
 			if (verbose) {
-				print_hardware_address(user_specified_mac);
+				print_hardware_address(config.user_specified_mac);
 			}
-
 			break;
 
 		case 'i': /* interface name */
-
-			strncpy(network_interface_name, optarg, sizeof(network_interface_name) - 1);
-			network_interface_name[sizeof(network_interface_name) - 1] = '\x0';
-
+			strncpy(config.network_interface_name, optarg, sizeof(config.network_interface_name) - 1);
+			config.network_interface_name[sizeof(config.network_interface_name) - 1] = '\x0';
 			break;
 
 		case 'u': /* unicast testing */
-			unicast = true;
+			config.unicast_mode = true;
 			break;
+
 		case 'x': /* exclusive testing aka "rogue DHCP server detection" */
-			exclusive = true;
+			config.exclusive_mode = true;
 			break;
 
 		case 'V': /* version */
@@ -1164,6 +1210,18 @@ static int call_getopt(int argc, char **argv) {
 		case 'v': /* verbose */
 			verbose = 1;
 			break;
+		case output_format_index: {
+			parsed_output_format parser = mp_parse_output_format(optarg);
+			if (!parser.parsing_success) {
+				// TODO List all available formats here, maybe add anothoer usage function
+				printf("Invalid output format: %s\n", optarg);
+				exit(STATE_UNKNOWN);
+			}
+
+			config.output_format_is_set = true;
+			config.output_format = parser.output_format;
+			break;
+		}
 		case '?': /* help */
 			usage5();
 			break;
@@ -1172,16 +1230,16 @@ static int call_getopt(int argc, char **argv) {
 			break;
 		}
 	}
-	return optind;
-}
-
-static int validate_arguments(int argc) {
 
 	if (argc - optind > 0) {
 		usage(_("Got unexpected non-option argument"));
 	}
 
-	return OK;
+	process_arguments_wrapper result = {
+		.config = config,
+		.error = OK,
+	};
+	return result;
 }
 
 #if defined(__sun__) || defined(__solaris__) || defined(__hpux__)
@@ -1300,7 +1358,7 @@ static int dl_bind(int fd, int sap, u_char *addr) {
  *
  ***********************************************************************/
 
-static long mac_addr_dlpi(const char *dev, int unit, u_char *addr) {
+long mac_addr_dlpi(const char *dev, int unit, u_char *addr) {
 	int fd;
 	u_char mac_addr[25];
 
@@ -1319,26 +1377,27 @@ static long mac_addr_dlpi(const char *dev, int unit, u_char *addr) {
 #endif
 
 /* resolve host name or die (TODO: move this to netutils.c!) */
-static void resolve_host(const char *in, struct in_addr *out) {
-	struct addrinfo hints, *ai;
+void resolve_host(const char *name, struct in_addr *out) {
+	struct addrinfo hints = {
+		.ai_family = PF_INET,
+	};
+	struct addrinfo *addr_info;
 
-	memset(&hints, 0, sizeof(hints));
-	hints.ai_family = PF_INET;
-	if (getaddrinfo(in, NULL, &hints, &ai) != 0) {
+	if (getaddrinfo(name, NULL, &hints, &addr_info) != 0) {
 		usage_va(_("Invalid hostname/address - %s"), optarg);
 	}
 
-	memcpy(out, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, sizeof(*out));
-	freeaddrinfo(ai);
+	memcpy(out, &((struct sockaddr_in *)addr_info->ai_addr)->sin_addr, sizeof(*out));
+	freeaddrinfo(addr_info);
 }
 
 /* parse MAC address string, return 6 bytes (unterminated) or NULL */
-static unsigned char *mac_aton(const char *string) {
-	static unsigned char result[6];
+unsigned char *mac_aton(const char *string) {
+	static unsigned char result[MAC_ADDR_LEN];
 	char tmp[3];
-	unsigned i, j;
+	unsigned byte_counter = 0;
 
-	for (i = 0, j = 0; string[i] != '\0' && j < sizeof(result); i++) {
+	for (int i = 0; string[i] != '\0' && byte_counter < sizeof(result); i++) {
 		/* ignore ':' and any other non-hex character */
 		if (!isxdigit(string[i]) || !isxdigit(string[i + 1])) {
 			continue;
@@ -1346,27 +1405,25 @@ static unsigned char *mac_aton(const char *string) {
 		tmp[0] = string[i];
 		tmp[1] = string[i + 1];
 		tmp[2] = '\0';
-		result[j] = strtol(tmp, (char **)NULL, 16);
+		result[byte_counter] = strtol(tmp, (char **)NULL, 16);
 		i++;
-		j++;
+		byte_counter++;
 	}
 
-	return (j == 6) ? result : NULL;
+	return (byte_counter == MAC_ADDR_LEN) ? result : NULL;
 }
 
-static void print_hardware_address(const unsigned char *address) {
-	int i;
+void print_hardware_address(const unsigned char *address) {
 
 	printf(_("Hardware address: "));
-	for (i = 0; i < 5; i++) {
-		printf("%2.2x:", address[i]);
+	for (int addr_idx = 0; addr_idx < MAC_ADDR_LEN; addr_idx++) {
+		printf("%2.2x:", address[addr_idx]);
 	}
-	printf("%2.2x", address[i]);
 	putchar('\n');
 }
 
 /* print usage help */
-static void print_help(void) {
+void print_help(void) {
 
 	print_revision(progname, NP_VERSION);
 
@@ -1382,6 +1439,7 @@ static void print_help(void) {
 	printf(UT_HELP_VRSN);
 	printf(UT_EXTRA_OPTS);
 
+	printf(UT_OUTPUT_FORMAT);
 	printf(UT_VERBOSE);
 
 	printf(" %s\n", "-s, --serverip=IPADDRESS");
@@ -1400,7 +1458,6 @@ static void print_help(void) {
 	printf("    %s\n", _("Only requested DHCP server may response (rogue DHCP server detection), requires -s"));
 
 	printf(UT_SUPPORT);
-	return;
 }
 
 void print_usage(void) {
@@ -1408,6 +1465,4 @@ void print_usage(void) {
 	printf("%s\n", _("Usage:"));
 	printf(" %s [-v] [-u] [-x] [-s serverip] [-r requestedip] [-t timeout]\n", progname);
 	printf("                  [-i interface] [-m mac]\n");
-
-	return;
 }
diff --git a/plugins-root/check_dhcp.d/config.h b/plugins-root/check_dhcp.d/config.h
new file mode 100644
index 00000000..f189068b
--- /dev/null
+++ b/plugins-root/check_dhcp.d/config.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "../../config.h"
+#include "../lib/states.h"
+#include <stdbool.h>
+#include <netinet/in.h>
+#include "net/if.h"
+#include "output.h"
+
+typedef struct requested_server_struct {
+	struct in_addr server_address;
+	bool answered;
+	struct requested_server_struct *next;
+} requested_server;
+
+typedef struct check_dhcp_config {
+	bool unicast_mode;   /* unicast mode: mimic a DHCP relay */
+	bool exclusive_mode; /* exclusive mode aka "rogue DHCP server detection" */
+	int num_of_requested_servers;
+	struct in_addr dhcp_ip; /* server to query (if in unicast mode) */
+	struct in_addr requested_address;
+	bool request_specific_address;
+
+	int dhcpoffer_timeout;
+	unsigned char *user_specified_mac;
+	char network_interface_name[IFNAMSIZ];
+	requested_server *requested_server_list;
+
+	mp_output_format output_format;
+	bool output_format_is_set;
+} check_dhcp_config;
+
+check_dhcp_config check_dhcp_config_init(void) {
+	check_dhcp_config tmp = {
+		.unicast_mode = false,
+		.exclusive_mode = false,
+		.num_of_requested_servers = 0,
+		.dhcp_ip = {0},
+		.requested_address = {0},
+		.request_specific_address = false,
+
+		.dhcpoffer_timeout = 2,
+		.user_specified_mac = NULL,
+		.network_interface_name = "eth0",
+		.requested_server_list = NULL,
+
+		.output_format_is_set = false,
+	};
+	return tmp;
+}



More information about the Commits mailing list