MES3.0はLinuxの下位互換性であり、MES3.0のユーザープログラムは原則としてLinuxでも同じソースコードで動作します。
以下、MES3.0で動作確認されたLinuxとソースコード互換のDHCPクライアントの例です。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/route.h>
#include "dhcp.h"

unsigned int DhcpServerIP;	///< IP address of the DHCP server that offered lease
unsigned int DhcpClientIP;
unsigned int DhcpNetmask;
unsigned int DhcpGatewayIP;
unsigned int DhcpDNSServerIP;
unsigned int DhcpTransactID;    ///< Unique transaction ID that identifies DHCP request/replies
unsigned int DhcpLeaseTime;     ///< Number of seconds left in DHCP lease
unsigned char macaddr[6];

//#define	NET_DEBUG	3

static int ifup(char *dev, int ip, int mask) {
	int			sk, ret;
	struct ifreq		ifr;
	struct sockaddr_in	*s_in;

	sk = socket(AF_INET, SOCK_DGRAM, 0);
	strncpy(ifr.ifr_name, dev, IFNAMSIZ-1);
	ret = ioctl(sk, SIOCGIFFLAGS, &ifr);
	if(ret == -1) return -1;
	ifr.ifr_flags |= IFF_UP;
	ioctl(sk, SIOCSIFFLAGS, &ifr);
	s_in = (struct sockaddr_in *)&ifr.ifr_addr;
	s_in->sin_family = AF_INET;
	s_in->sin_addr.s_addr = htonl(ip);
	ioctl(sk, SIOCSIFADDR, &ifr);
	s_in->sin_addr.s_addr = htonl(mask);
	ioctl(sk, SIOCSIFNETMASK, &ifr);
	close(sk);
	return 0;
}

static int dhcpIn(char *dev, int sock, int len, struct netDhcpHeader *packet) {
	struct ifreq		ifr;
	struct sockaddr_in	*s_in;
	unsigned char		msgtype;
	unsigned char		*optptr;
	unsigned int		val;

	s_in = (struct sockaddr_in *)&ifr.ifr_addr;
#if NET_DEBUG >= 3
	dhcpPrintHeader(packet);
#endif
	// check that this is a reply, and for me
	if(packet->bootp.op != BOOTP_OP_BOOTREPLY ||
	   packet->bootp.htype != BOOTP_HTYPE_ETHERNET ||
	   packet->bootp.hlen != BOOTP_HLEN_ETHERNET ||
	   be32toh(packet->cookie) != 0x63825363 ||
	   be32toh(packet->bootp.xid) != DhcpTransactID) return -1;

	// process incoming packet
	// check reply type
	dhcpGetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &msgtype);
#if NET_DEBUG >= 2
	printf("DHCP: Received msgtype = %d\n", msgtype);
#endif

	if(msgtype == DHCP_MSG_DHCPOFFER) {
		// get DHCP server ID
		val = 0;
		dhcpGetOption(packet->options, DHCP_OPT_SERVERID, 4, &val);
		if(val == 0) {
			val = packet->bootp.siaddr;
		}
		DhcpServerIP = be32toh(val);
		DhcpGatewayIP = DhcpServerIP;
		DhcpDNSServerIP = DhcpServerIP;
		DhcpClientIP = be32toh(packet->bootp.yiaddr);
#ifdef NET_DEBUG
		printf("DHCP: Got offer from server ");
		val = DhcpServerIP;
		printf("%d.%d.%d.%d\n", (val >> 24) & 0xff, (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); 
		printf("DHCP: Sending request in response to offer\n");
#endif
		// get netmask
		val = 0;
		dhcpGetOption(packet->options, DHCP_OPT_NETMASK, 4, &val);
		DhcpNetmask = htobe32(val);
		if(DhcpNetmask == 0) DhcpNetmask = 0xffffff00;
		// get gateway
		val = 0;
		dhcpGetOption(packet->options, DHCP_OPT_ROUTERS, 4, &val);
		if(val != 0) DhcpGatewayIP = htobe32(val);
		// get gateway
		val = 0;
		dhcpGetOption(packet->options, DHCP_OPT_DNSSERVERS, 4, &val);
		if(val != 0) DhcpDNSServerIP = htobe32(val);
	} else if(msgtype == DHCP_MSG_DHCPACK) {
		// get netmask
		val = 0;
		dhcpGetOption(packet->options, DHCP_OPT_NETMASK, 4, &val);
		DhcpNetmask = htobe32(val);
		if(DhcpNetmask == 0) DhcpNetmask = 0xffffff00;
		// get gateway
		val = 0;
		dhcpGetOption(packet->options, DHCP_OPT_ROUTERS, 4, &val);
		if(val != 0) DhcpGatewayIP = htobe32(val);
		// get gateway
		val = 0;
		dhcpGetOption(packet->options, DHCP_OPT_DNSSERVERS, 4, &val);
		if(val != 0) DhcpDNSServerIP = htobe32(val);
		// get lease time
		dhcpGetOption(packet->options, DHCP_OPT_LEASETIME, 4, &val);
		DhcpLeaseTime = htobe32(val);
		// assign new network info
		strncpy(ifr.ifr_name, dev, IFNAMSIZ-1);
		s_in->sin_family = AF_INET;
		s_in->sin_addr.s_addr = packet->bootp.yiaddr;
		ioctl(sock, SIOCSIFADDR, &ifr);
		s_in->sin_addr.s_addr = htonl(DhcpNetmask);
		ioctl(sock, SIOCSIFNETMASK, &ifr);
		ifup(dev, be32toh(packet->bootp.yiaddr), DhcpNetmask);
#ifdef NET_DEBUG
		// print netmask
		val = DhcpNetmask;
		printf("Mask : %d.%d.%d.%d\n", (val >> 24) & 0xff, (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); 
		// print gateway
		val = DhcpGatewayIP;
		printf("GW : %d.%d.%d.%d\n", (val >> 24) & 0xff, (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); 
		// print dns server
		val = DhcpDNSServerIP;
		printf("DNS : %d.%d.%d.%d\n", (val >> 24) & 0xff, (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); 
		printf("DHCP: Got request ACK, bind complete\n");
#endif
	} else {
		return -1;	
	}
	return msgtype;
}

static int dhcpRequest(char *dev, int sock) {
	struct ifreq		ifr;
	struct sockaddr_in	*s_in;
	struct sockaddr_in	target;
	struct netDhcpHeader*	packet;
	unsigned char		*options;
	unsigned int		ip, val;
	int			net, ret, count;
	unsigned char		buf[8];

	s_in = (struct sockaddr_in *)&ifr.ifr_addr;
	strncpy(ifr.ifr_name, dev, IFNAMSIZ-1);
	s_in->sin_family = AF_INET;
	ret = ioctl(sock, SIOCGIFADDR, &ifr);
	if(ret == -1) {
#ifdef NET_DEBUG
		printf("SIOCGIFADDR error\n");
#endif
		return -1;
	}
	ip = ntohl(s_in->sin_addr.s_addr);
	memcpy(macaddr, ifr.ifr_hwaddr.sa_data, 6);

	// get buffer area
	packet = (struct netDhcpHeader*)malloc(DHCP_HEADER_LEN + 512);
	if(packet == 0) return -1;
	options = packet->options;
	bzero((char*)packet, DHCP_HEADER_LEN + 512);

	// build BOOTP/DHCP header
	packet->bootp.op = BOOTP_OP_BOOTREQUEST;        // request type
	packet->bootp.htype = BOOTP_HTYPE_ETHERNET;
	packet->bootp.hlen = BOOTP_HLEN_ETHERNET;
	packet->bootp.hops = 0;
	packet->bootp.xid = htobe32(DhcpTransactID);
	packet->bootp.secs = 0;
	packet->bootp.ciaddr = htobe32(ip);
	packet->bootp.flags = (ip == 0) ? 0 : htobe16(0x8000);
	packet->bootp.yiaddr = 0;
	packet->bootp.siaddr = 0;
	packet->bootp.giaddr = 0;
	memcpy(&packet->bootp.chaddr[0], macaddr, 6); // fill client hardware address
	// build DHCP request
	// begin with magic cookie
	packet->cookie = htobe32(0x63825363);
	// set operation
	count = 0;
	if(ip != 0) {
		buf[0] = DHCP_MSG_DHCPRELEASE;
	} else if(DhcpServerIP == 0) {
		buf[0] = DHCP_MSG_DHCPDISCOVER;
	} else {
		val = htobe32(DhcpServerIP);
		count += 2 + 4;
		options = dhcpSetOption(options, DHCP_OPT_SERVERID, 4, &val);
		if(DhcpClientIP != 0) {
			val = htobe32(DhcpClientIP);
			count += 2 + 4;
			options = dhcpSetOption(options, DHCP_OPT_REQUESTEDIP, 4, &val);
		}
		buf[0] = DHCP_MSG_DHCPREQUEST;
	}
#ifdef NET_DEBUG
	switch(buf[0]) {
	case DHCP_MSG_DHCPDISCOVER:
		printf("DHCP: Discover sending Query\n");
		break;
	case DHCP_MSG_DHCPREQUEST:
		printf("DHCP: Request sending Query\n");
		break;
	default:
		printf("DHCP: Sending Query\n");
	}
#endif
	count += 2 + 1;
	options = dhcpSetOption(options, DHCP_OPT_DHCPMSGTYPE, 1, buf);
	buf[0] = BOOTP_HTYPE_ETHERNET;
	memcpy(&buf[1], macaddr, 6);
	count += 2 + 7;
	options = dhcpSetOption(options, DHCP_OPT_CLIENT_IDENT, 7, buf);
	if(ip == 0) {
		buf[0] = DHCP_OPT_NETMASK;
		buf[1] = DHCP_OPT_ROUTERS;
		buf[2] = DHCP_OPT_DNSSERVERS;
		buf[3] = DHCP_OPT_DOMAINNAME;
		count += 2 + 4;
		options = dhcpSetOption(options, DHCP_OPT_PARAMREQLIST, 4, buf);
	}
	count++;
	options = dhcpSetOption(options, DHCP_OPT_END, 0, 0);
	// send request
	target.sin_family = AF_INET;
	target.sin_port = htons(DHCP_UDP_SERVER_PORT);
	target.sin_addr.s_addr = 0xffffffff;
	if(sendto(sock, (char*)packet, DHCP_HEADER_LEN + count, 0, (struct sockaddr *)&target, sizeof(target)) == -1) {
		free((char*)packet);
		return -1;
	}
	return 0;
}

static void dhcpTimer(void) {
	// this function to be called once per second

	// decrement lease time
	if(DhcpLeaseTime) DhcpLeaseTime--;
}

static unsigned char dhcpGetOption(unsigned char* options, unsigned char optcode, unsigned char optlen, void* optvalptr) {
	unsigned char i;

	// parse for desired option
	for (;;) {
		// skip pad characters
		if(*options == DHCP_OPT_PAD) options++;
		// break if end reached
		else if(*options == DHCP_OPT_END) break;
		// check for desired option
		else if(*options == optcode) {
			// found desired option
			// limit size to actual option length
			optlen = (optlen < *(options+1)) ? optlen : *(options+1);
			//if(*(options+1) < optlen)
			//  optlen = *(options+1);
			// copy contents of option
			for(i = 0; i < optlen; i++)
				*(((unsigned char*)optvalptr)+i) = *(options+i+2);
			// return length of option
			return *(options+1);
		} else {
			// skip to next option
			options++;
			options+=*options;
			options++;
		}
	}
	// failed to find desired option
	return 0;
}

static unsigned char* dhcpSetOption(unsigned char* options, unsigned char optcode, unsigned char optlen, void* optvalptr) {
	// use current options address as write point
	// set optcode
	*options++ = optcode;
	// set optlen
	*options++ = optlen;
	// copy in argument/data
	while(optlen--) {
		*options++ = *(unsigned char*)optvalptr++;
	}
	// write end marker
	*options = DHCP_OPT_END;

	// return address of end marker, to be used as a future write point
	return options;
}

#ifdef NET_DEBUG
static void dhcpPrintHeader(struct netDhcpHeader* packet) {
	int	ip;

	printf("DHCP Packet:\n");
	// print op
	printf("Op      : ");
	switch(packet->bootp.op) {
		case BOOTP_OP_BOOTREQUEST: printf("BOOTREQUEST\n"); break;
		case BOOTP_OP_BOOTREPLY: printf("BOOTREPLY\n"); break;
		default: printf("UNKNOWN\n"); break;
	}
	// print transaction ID
	printf("XID     : 0x%08x\n", packet->bootp.xid);

	// print client IP address
	ip = be32toh(packet->bootp.ciaddr);
	printf("%d.%d.%d.%d\n", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 
	// print 'your' IP address
	ip = be32toh(packet->bootp.yiaddr);
	printf("%d.%d.%d.%d\n", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 
	// print server IP address
	ip = be32toh(packet->bootp.siaddr);
	printf("%d.%d.%d.%d\n", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 
	// print gateway IP address
	ip = be32toh(packet->bootp.giaddr);
	printf("%d.%d.%d.%d\n", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 
	// print client hardware address
	printf("%s\n", packet->bootp.chaddr);
}
#endif

extern int	start;

int main(int argc, char **argv) {
	struct ifreq	   ifr;
	struct sockaddr_in *s_in;
	struct sockaddr_in myaddr, target;
	struct timeval	tv;
	struct rtentry		stuRTEntry;
	struct sockaddr_in	stcAddr;
	int		net, sock, size, ret, retry, msgtype, retry2, addr;
	int		retrynum, addrlen;
	unsigned int	ip;
	char		dev[8], *buf;
	char		flag;
	char		buff[INET_ADDRSTRLEN + 1];
	FILE		*fp;

	s_in = (struct sockaddr_in *)&ifr.ifr_addr;
#ifdef NET_DEBUG
	printf("DHCP Client 2008/4/15 8:28 coded.\n");
#endif
	if(argc == 1 || argc >= 4) return -1;
	flag = 0;
	retrynum = 3;
	if(argc == 3) {
		if(argv[2][0] == 'd') {
			flag = 1;
		} else if(isdigit(argv[2][0])) {
			retrynum = atoi(argv[2]);
		}
	}
	strcpy(dev, argv[1]);
	buf = malloc(1024);
	if(buf == 0) return -1;
	for(retry = retrynum;retry >= 0;retry--) {
#if defined(NET_DEBUG) || defined(PGM_DEBUG)
		printf("-----Retry %d-----\n", retrynum - retry);
#endif
		sock = socket(AF_INET, SOCK_DGRAM, 0);
		strncpy(ifr.ifr_name, dev, IFNAMSIZ-1);
		ioctl(sock, SIOCGIFFLAGS, &ifr);
		s_in->sin_family = AF_INET;
		ioctl(sock, SIOCGIFADDR, &ifr);
		ip = ntohl(s_in->sin_addr.s_addr);
		ioctl(sock, SIOCGIFHWADDR, &ifr);
		memcpy(macaddr, ifr.ifr_hwaddr.sa_data, 6);
		close(sock);
		if((ifr.ifr_flags & IFF_UP) == 0) {
#ifdef NET_DEBUG
			printf("NIC is disabled\n");
#endif
		} else {
			if(ip != 0) {
				// set transaction ID based on mac address
				DhcpTransactID = *((unsigned int*)&macaddr) - retry;
				sock = socket(AF_INET, SOCK_DGRAM, 0);
				if(sock == -1) continue;
				myaddr.sin_family = AF_INET;
				myaddr.sin_port = htons(DHCP_UDP_CLIENT_PORT);
				myaddr.sin_addr.s_addr = INADDR_ANY;
				bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
				dhcpRequest(dev, sock);
				close(sock);
			}
		}
		// socket
		sock = socket(AF_INET, SOCK_DGRAM, 0);
		if(sock == -1) {
#ifdef NET_DEBUG
			printf("Fail(3)\n");
#endif
			continue;
		}
		strncpy(ifr.ifr_name, dev, IFNAMSIZ-1);
		s_in->sin_family = AF_INET;
		s_in->sin_addr.s_addr = 0;
		ioctl(sock, SIOCSIFADDR, &ifr);
		s_in->sin_addr.s_addr = 0;
		net = ioctl(sock, SIOCSIFNETMASK, &ifr);
		ret = ifup(dev, 0, 0);
		if(flag == 1) return 0;
		if(ret == -1) {
#ifdef NET_DEBUG
			printf("Fail(1)\n");
#endif
			continue;
		}
		// get interface mac address
		ret = ioctl(sock, SIOCGIFHWADDR, &ifr);
		memcpy(macaddr, ifr.ifr_hwaddr.sa_data, 6);
		if(ret == -1) {
#ifdef NET_DEBUG
			printf("Fail(2)\n");
#endif
			continue;
		}
		// set transaction ID based on mac address
		DhcpTransactID = *((unsigned int*)&macaddr) - retry;
		// reset lease time
		DhcpLeaseTime = 0;

		myaddr.sin_family = AF_INET;
		myaddr.sin_port = htons(DHCP_UDP_CLIENT_PORT);
		myaddr.sin_addr.s_addr = INADDR_ANY;

		tv.tv_sec = 4;
		tv.tv_usec = 0;
		setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

		if(bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
			close(sock);
#ifdef NET_DEBUG
			printf("Fail(4)\n");
#endif
			continue;
		}
		DhcpServerIP = 0;
		DhcpClientIP = 0;
		/***********************/
		/**** SEND DISCOVER ****/
		/***********************/

		if(dhcpRequest(dev, sock) == -1) {
			close(sock);
#ifdef NET_DEBUG
			printf("Fail(5)\n");
#endif
			continue;
		}
		for(retry2 = 0;retry2 < 3;) {
			bzero(buf, 1024);
			size = recvfrom(sock, buf, 1024, 0, (struct sockaddr *)&target, &addrlen);
			if(size <= 0) {
				retry2++;
				dhcpRequest(dev, sock);
			} else {
				msgtype = dhcpIn(dev, sock, size, (struct netDhcpHeader *)buf);
				if(msgtype != DHCP_MSG_DHCPACK) break;
			}
		}
		if(size <= 0) {
			close(sock);
#ifdef NET_DEBUG
			printf("Fail(6)\n");
#endif
			continue;
		}
		if(msgtype != DHCP_MSG_DHCPOFFER) {
			close(sock);
#ifdef NET_DEBUG
			printf("Fail(7)\n");
#endif
			continue;
		}

		/**********************/
		/**** SEND REQUEST ****/
		/**********************/

		if(dhcpRequest(dev, sock) == -1) {
			close(sock);
#ifdef NET_DEBUG
			printf("Fail(8)\n");
#endif
			continue;
		}

		for(retry2 = 0;retry2 < 3;) {
			bzero(buf, 1024);
			size = recvfrom(sock, buf, 1024, 0, (struct sockaddr *)&target, &addrlen);
			if(size <= 0) {
				retry2++;
				dhcpRequest(dev, sock);
			} else {
				msgtype = dhcpIn(dev, sock, size, (struct netDhcpHeader *)buf);
				if(msgtype != DHCP_MSG_DHCPOFFER) break;
			}
		}
		if(size <= 0) {
#ifdef NET_DEBUG
			printf("Fail(9)\n");
			printf("DHCP-ACK not received, but set ip.\n");
#endif
		} else if(msgtype != DHCP_MSG_DHCPACK) {
#ifdef NET_DEBUG
			printf("Fail(10)\n");
			printf("DHCP-ACK not received, but set ip.\n");
#endif
		}
		// assign new network info
		strncpy(ifr.ifr_name, dev, IFNAMSIZ-1);
		s_in->sin_family = AF_INET;
		s_in->sin_addr.s_addr = htonl(DhcpClientIP);
		ioctl(sock, SIOCSIFADDR, &ifr);
		s_in->sin_addr.s_addr = htonl(DhcpNetmask);
		ioctl(sock, SIOCSIFNETMASK, &ifr);
		ifup(dev, DhcpClientIP, DhcpNetmask);

		memset(&stuRTEntry, 0x00, sizeof(stuRTEntry));
		stcAddr.sin_family = AF_INET;
		stcAddr.sin_port = 0;
		stcAddr.sin_addr.s_addr = htonl(DhcpGatewayIP);
		memcpy(&stuRTEntry.rt_gateway, (char*)&stcAddr, sizeof(stcAddr));
		stuRTEntry.rt_dev = dev;
		stuRTEntry.rt_metric = 100;
		stuRTEntry.rt_flags = (RTF_UP | RTF_GATEWAY);
		stcAddr.sin_addr.s_addr = INADDR_ANY;
		memcpy(&stuRTEntry.rt_dst, (char*)&stcAddr, sizeof(stcAddr));
		memcpy(&stuRTEntry.rt_genmask, (char*)&stcAddr, sizeof(stcAddr));
		ret = ioctl(sock, SIOCADDRT, &stuRTEntry);
		close(sock);
		addr = htonl(DhcpDNSServerIP);
		inet_ntop(AF_INET, &addr, buff, INET_ADDRSTRLEN);
		fp = fopen("/etc/resolv.conf", "w");
		fprintf(fp, "nameserver %s", buff);
		fclose(fp);
		free(buf);
		return 0;
	}
	free(buf);
	return -1;
}
/// Bootp Header (DHCP is transported by BOOTP/UDP/IP)
struct netBootpHeader {
	unsigned char	op;		///< Message op-code / message type
	unsigned char	htype;		///< Hardware address type   (Ethernet=1)
	unsigned char	hlen;		///< Hardware address length (Ethernet=6 byte MAC addr)
	unsigned char	hops;		///< hop count (client set to zero)
	unsigned int	xid;		///< Transaction ID (randomly chosen by client, must remain same)
	unsigned short	secs;		///< Seconds elapsed since DHCP negotiation began (filled by client)
	unsigned short	flags;		///< Flags
	unsigned int    ciaddr;		///< Client IP address (filled only if already bound, renewing, or rebinding)
	unsigned int    yiaddr;		///< 'Your' IP address (client)
	unsigned int    siaddr;		///< Server IP address
	unsigned int    giaddr;		///< Gateway IP address
	unsigned char	chaddr[16];	///< Client Hardware Address
	unsigned char	sname[64];	///< Server Host Name
	unsigned char	file[128];	///< Boot file name (null-term string)
} __attribute__ ((packed));

#define BOOTP_HEADER_LEN	236	///< length of BOOTP header not including options

#define BOOTP_OP_BOOTREQUEST	1	///< BOOTP Request operation (message from client to server)
#define BOOTP_OP_BOOTREPLY	2	///< BOOTP Reply operation (message from server to client)

#define BOOTP_HTYPE_ETHERNET	1
#define BOOTP_HLEN_ETHERNET     6

/// DHCP Header
struct netDhcpHeader {
	struct netBootpHeader bootp;	///< BOOTP header
	unsigned int	cookie;		///< magic cookie value
	unsigned char	options[];	///< DHCP options
}__attribute__ ((packed));

#define DHCP_HEADER_LEN		240	///< length of DHCP header not including options

#define DHCP_UDP_SERVER_PORT	67	///< UDP port where DHCP requests should be sent
#define DHCP_UDP_CLIENT_PORT    68	///< UDP port clients will receive DHCP replies

#define DHCP_OPT_PAD		0   ///< token padding value (make be skipped)
#define DHCP_OPT_NETMASK        1   ///< subnet mask client should use (4 byte mask)
#define DHCP_OPT_ROUTERS        3   ///< routers client should use (IP addr list)
#define DHCP_OPT_TIMESERVERS    4   ///< time servers client should use (IP addr list)
#define DHCP_OPT_NAMESERVERS    5   ///< name servers client should use (IP addr list)
#define DHCP_OPT_DNSSERVERS     6   ///< DNS servers client should use (IP addr list)
#define DHCP_OPT_HOSTNAME       12  ///< host name client should use (string)
#define DHCP_OPT_DOMAINNAME     15  ///< domain name client should use (string)
#define DHCP_OPT_REQUESTEDIP    50  ///< IP address requested by client (IP address)
#define DHCP_OPT_LEASETIME      51  ///< DHCP Lease Time (uint32 seconds)
#define DHCP_OPT_DHCPMSGTYPE    53  ///< DHCP message type (1 byte)
#define DHCP_OPT_SERVERID       54  ///< Server Identifier (IP address)
#define DHCP_OPT_PARAMREQLIST   55  ///< Paramerter Request List (n OPT codes)
#define DHCP_OPT_RENEWALTIME    58  ///< DHCP Lease Renewal Time (uint32 seconds)
#define DHCP_OPT_REBINDTIME     59  ///< DHCP Lease Rebinding Time (uint32 seconds)
#define DHCP_OPT_CLIENT_IDENT   61  ///< DHCP Client identifer
#define DHCP_OPT_END            255 ///< token end value (marks end of options list)

#define DHCP_MSG_DHCPDISCOVER   1   ///< DISCOVER is broadcast by client to solicit OFFER from any/all DHCP servers.
#define DHCP_MSG_DHCPOFFER      2   ///< OFFER(s) are made to client by server to offer IP address and config info.
#define DHCP_MSG_DHCPREQUEST    3   ///< REQUEST is made my client in response to best/favorite OFFER message.
#define DHCP_MSG_DHCPDECLINE    4   ///< DECLINE may be sent by client to server to indicate IP already in use.
#define DHCP_MSG_DHCPACK        5   ///< ACK is sent to client by server in confirmation of REQUEST, contains config and IP.
#define DHCP_MSG_DHCPNAK        6   ///< NAK is sent to client by server to indicate problem with REQUEST.
#define DHCP_MSG_DHCPRELEASE    7   ///< RELEASE is sent by client to server to relinquish DHCP lease on IP address, etc.
#define DHCP_MSG_DHCPINFORM     8   ///< INFORM is sent by client to server to request config info, IP address configured locally.

static int dhcpIn(char *dev, int sock, int len, struct netDhcpHeader *packet);
static int dhcpRequest(char *dev, int sock);
static void dhcpTimer(void);
static unsigned char dhcpGetOption(unsigned char* options, unsigned char optcode, unsigned char optlen, void* optvalptr);
static unsigned char* dhcpSetOption(unsigned char* options, unsigned char optcode, unsigned char optlen, void* optvalptr);
static void dhcpPrintHeader(struct netDhcpHeader* packet);