First import of DHCP client service.
No pipe created yet.  Event model up and running.
Does not produce a dhcp offer yet but working on that.
Added: trunk/reactos/subsys/system/dhcp/
Added: trunk/reactos/subsys/system/dhcp/Makefile
Added: trunk/reactos/subsys/system/dhcp/adapter.c
Added: trunk/reactos/subsys/system/dhcp/alloc.c
Added: trunk/reactos/subsys/system/dhcp/compat.c
Added: trunk/reactos/subsys/system/dhcp/design.txt
Added: trunk/reactos/subsys/system/dhcp/dhclient.c
Added: trunk/reactos/subsys/system/dhcp/dhcp.rc
Added: trunk/reactos/subsys/system/dhcp/dhcpmain.c
Added: trunk/reactos/subsys/system/dhcp/dispatch.c
Added: trunk/reactos/subsys/system/dhcp/hash.c
Added: trunk/reactos/subsys/system/dhcp/include/
Added: trunk/reactos/subsys/system/dhcp/include/cdefs.h
Added: trunk/reactos/subsys/system/dhcp/include/debug.h
Added: trunk/reactos/subsys/system/dhcp/include/dhcp.h
Added: trunk/reactos/subsys/system/dhcp/include/dhcpd.h
Added: trunk/reactos/subsys/system/dhcp/include/dhctoken.h
Added: trunk/reactos/subsys/system/dhcp/include/hash.h
Added: trunk/reactos/subsys/system/dhcp/include/inet.h
Added: trunk/reactos/subsys/system/dhcp/include/osdep.h
Added: trunk/reactos/subsys/system/dhcp/include/predec.h
Added: trunk/reactos/subsys/system/dhcp/include/privsep.h
Added: trunk/reactos/subsys/system/dhcp/include/rosdhcp.h
Added: trunk/reactos/subsys/system/dhcp/include/site.h
Added: trunk/reactos/subsys/system/dhcp/include/stdint.h
Added: trunk/reactos/subsys/system/dhcp/include/sysconf.h
Added: trunk/reactos/subsys/system/dhcp/include/tree.h
Added: trunk/reactos/subsys/system/dhcp/include/version.h
Added: trunk/reactos/subsys/system/dhcp/memory.c
Added: trunk/reactos/subsys/system/dhcp/options.c
Added: trunk/reactos/subsys/system/dhcp/privsep.c
Added: trunk/reactos/subsys/system/dhcp/socket.c
Added: trunk/reactos/subsys/system/dhcp/tables.c
Added: trunk/reactos/subsys/system/dhcp/timer.c
Added: trunk/reactos/subsys/system/dhcp/tree.c
Added: trunk/reactos/subsys/system/dhcp/util.c

Added: trunk/reactos/subsys/system/dhcp/Makefile
--- trunk/reactos/subsys/system/dhcp/Makefile	2005-04-04 23:17:28 UTC (rev 14495)
+++ trunk/reactos/subsys/system/dhcp/Makefile	2005-04-04 23:45:33 UTC (rev 14496)
@@ -0,0 +1,30 @@
+#
+
+PATH_TO_TOP = ../../..
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE =  windows
+
+TARGET_NAME = dhcp
+
+TARGET_CFLAGS = -D__REACTOS__ -D_WIN32_WINNT=0x0501 -D__USE_W32API -Iinclude
+
+TARGET_OBJECTS = adapter.o alloc.o compat.o dhclient.o dispatch.o hash.o \
+		options.o privsep.o socket.o tables.o timer.o util.o
+
+TARGET_SDKLIBS = iphlpapi.a ws2_32.a ntdll.a
+
+TARGET_RC_SRCS = dhcp.rc
+
+TARGET_RC_BINSRC = 
+
+TARGET_RC_BINARIES = 
+
+default: all
+DEP_OBJECTS = $(TARGET_OBJECTS)
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+include $(TOOLS_PATH)/depend.mk

Added: trunk/reactos/subsys/system/dhcp/adapter.c
--- trunk/reactos/subsys/system/dhcp/adapter.c	2005-04-04 23:17:28 UTC (rev 14495)
+++ trunk/reactos/subsys/system/dhcp/adapter.c	2005-04-04 23:45:33 UTC (rev 14496)
@@ -0,0 +1,162 @@
+#include "rosdhcp.h"
+
+static LIST_ENTRY AdapterList;
+static WSADATA wsd;
+extern struct interface_info *ifi;
+
+DWORD GetAddress( PDHCP_ADAPTER Adapter ) {
+    PMIB_IPADDRTABLE AddressTable = NULL;
+    ULONG i, Size = 0, NumAddressRows;
+    DWORD Error = GetIpAddrTable( AddressTable, &Size, FALSE );
+
+    while( Error == ERROR_INSUFFICIENT_BUFFER ) {
+        free( AddressTable );
+        AddressTable = malloc( Size );
+        if( AddressTable ) 
+            Error = GetIpAddrTable( AddressTable, &Size, FALSE );
+    }
+    if( Error != ERROR_SUCCESS ) {
+        free( AddressTable );
+        return Error;
+    }
+
+    NumAddressRows = Size / sizeof(MIB_IPADDRTABLE);
+    for( i = 0; i < AddressTable->dwNumEntries; i++ ) {
+        DH_DbgPrint(MID_TRACE,
+                    ("Finding address for adapter %d: (%d -> %x)\n", 
+                     Adapter->IfMib.dwIndex, 
+                     AddressTable->table[i].dwIndex,
+                     AddressTable->table[i].dwAddr));
+        if( Adapter->IfMib.dwIndex == AddressTable->table[i].dwIndex ) {
+            memcpy( &Adapter->IfAddr, &AddressTable->table[i],
+                    sizeof( MIB_IPADDRROW ) );
+        }
+    }
+}
+
+void AdapterInit() {
+    PMIB_IFTABLE Table = malloc(sizeof(MIB_IFTABLE));
+    DWORD Error, Size, i;
+    PDHCP_ADAPTER Adapter = NULL;
+
+    WSAStartup(0x0101,&wsd);
+
+    InitializeListHead( &AdapterList );
+
+    DH_DbgPrint(MID_TRACE,("Getting Adapter List...\n"));
+
+    while( (Error = GetIfTable(Table, &Size, 0 )) == 
+           ERROR_INSUFFICIENT_BUFFER ) {
+        DH_DbgPrint(MID_TRACE,("Error %d, New Buffer Size: %d\n", Error, Size));
+        free( Table );
+        Table = malloc( Size );
+    }
+
+    if( Error != NO_ERROR ) goto term;
+
+    DH_DbgPrint(MID_TRACE,("Got Adapter List (%d entries)\n", Table->dwNumEntries));
+
+    for( i = 0; i < Table->dwNumEntries; i++ ) {
+        DH_DbgPrint(MID_TRACE,("Getting adapter %d attributes\n", i));
+        Adapter = calloc( sizeof( DHCP_ADAPTER ) + Table->table[i].dwMtu, 1 );
+        
+        if( Adapter ) {
+            memcpy( &Adapter->IfMib, &Table->table[i], 
+                    sizeof(Adapter->IfMib) );
+            GetAddress( Adapter );
+            InsertTailList( &AdapterList, &Adapter->ListEntry );
+            Adapter->DhclientInfo.next = ifi;
+            Adapter->DhclientInfo.client = &Adapter->DhclientState;
+            Adapter->DhclientInfo.rbuf = Adapter->recv_buf;
+            Adapter->DhclientInfo.rbuf_max = Table->table[i].dwMtu;
+            Adapter->DhclientInfo.rbuf_len = 
+                Adapter->DhclientInfo.rbuf_offset = 0;
+            Adapter->DhclientInfo.rfdesc = 
+                Adapter->DhclientInfo.wfdesc =
+                socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
+            Adapter->ListenAddr.sin_family = AF_INET;
+            Adapter->ListenAddr.sin_port = htons(LOCAL_PORT);
+            Adapter->BindStatus = 
+                (bind( Adapter->DhclientInfo.rfdesc,
+                       (struct sockaddr *)&Adapter->ListenAddr,
+                       sizeof(Adapter->ListenAddr) ) == 0) ?
+                0 : WSAGetLastError();
+            Adapter->DhclientState.config = &Adapter->DhclientConfig;
+            Adapter->DhclientConfig.initial_interval = DHCP_DISCOVER_INTERVAL;
+            Adapter->DhclientConfig.retry_interval = DHCP_DISCOVER_INTERVAL;
+            Adapter->DhclientConfig.select_interval = 1;
+            Adapter->DhclientConfig.reboot_timeout = DHCP_REBOOT_TIMEOUT;
+            Adapter->DhclientConfig.backoff_cutoff = DHCP_BACKOFF_MAX;
+            Adapter->DhclientState.interval = 
+                Adapter->DhclientConfig.retry_interval;
+            strncpy(Adapter->DhclientInfo.name, Adapter->IfMib.bDescr,
+                    sizeof(Adapter->DhclientInfo.name));
+            DH_DbgPrint(MID_TRACE,("Adapter Name: [%s]\n", Adapter->DhclientInfo.name));
+            ifi = &Adapter->DhclientInfo;
+        }
+    }
+
+    DH_DbgPrint(MID_TRACE,("done with AdapterInit\n"));
+
+term:
+    if( Table ) free( Table );
+}
+
+void AdapterStop() {
+    PLIST_ENTRY ListEntry;
+    PDHCP_ADAPTER Adapter;
+    while( !IsListEmpty( &AdapterList ) ) {
+        ListEntry = (PLIST_ENTRY)RemoveHeadList( &AdapterList );
+        Adapter = CONTAINING_RECORD( ListEntry, DHCP_ADAPTER, ListEntry );
+        free( Adapter );
+    }
+    WSACleanup();
+}
+
+PDHCP_ADAPTER AdapterFindIndex( unsigned int indx ) {
+    PDHCP_ADAPTER Adapter;
+    PLIST_ENTRY ListEntry;
+
+    for( ListEntry = AdapterList.Flink;
+         ListEntry != &AdapterList;
+         ListEntry = ListEntry->Flink ) {
+        Adapter = CONTAINING_RECORD( ListEntry, DHCP_ADAPTER, ListEntry );
+        if( Adapter->IfMib.dwIndex == indx ) return Adapter;
+    }
+
+    return NULL;
+}
+
+PDHCP_ADAPTER AdapterFindName( const WCHAR *name ) {
+    PDHCP_ADAPTER Adapter;
+    PLIST_ENTRY ListEntry;
+
+    for( ListEntry = AdapterList.Flink;
+         ListEntry != &AdapterList;
+         ListEntry = ListEntry->Flink ) {
+        Adapter = CONTAINING_RECORD( ListEntry, DHCP_ADAPTER, ListEntry );
+        if( !wcsicmp( Adapter->IfMib.wszName, name ) ) return Adapter;
+    }
+
+    return NULL;
+}
+
+PDHCP_ADAPTER AdapterGetFirst() {
+    if( IsListEmpty( &AdapterList ) ) return NULL; else {
+        return CONTAINING_RECORD
+            ( AdapterList.Flink, DHCP_ADAPTER, ListEntry );
+    }
+}
+
+PDHCP_ADAPTER AdapterGetNext( PDHCP_ADAPTER This ) 
+{ 
+    if( This->ListEntry.Flink == &AdapterList ) return NULL;
+    return CONTAINING_RECORD
+        ( This->ListEntry.Flink, DHCP_ADAPTER, ListEntry );
+}
+
+void if_register_send(struct interface_info *ip) {
+}
+
+void if_register_receive(struct interface_info *ip) {
+}

Added: trunk/reactos/subsys/system/dhcp/alloc.c
--- trunk/reactos/subsys/system/dhcp/alloc.c	2005-04-04 23:17:28 UTC (rev 14495)
+++ trunk/reactos/subsys/system/dhcp/alloc.c	2005-04-04 23:45:33 UTC (rev 14496)
@@ -0,0 +1,79 @@
+/*	$OpenBSD: alloc.c,v 1.9 2004/05/04 20:28:40 deraadt Exp $	*/
+
+/* Memory allocation... */
+
+/*
+ * Copyright (c) 1995, 1996, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ *    of its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises.  To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''.  To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include "rosdhcp.h"
+#include "dhcpd.h"
+
+struct string_list *
+new_string_list(size_t size)
+{
+	struct string_list *rval;
+
+	rval = calloc(1, sizeof(struct string_list) + size);
+	if (rval != NULL)
+		rval->string = ((char *)rval) + sizeof(struct string_list);
+	return (rval);
+}
+
+struct hash_table *
+new_hash_table(int count)
+{
+	struct hash_table *rval;
+
+	rval = calloc(1, sizeof(struct hash_table) -
+	    (DEFAULT_HASH_SIZE * sizeof(struct hash_bucket *)) +
+	    (count * sizeof(struct hash_bucket *)));
+	if (rval == NULL)
+		return (NULL);
+	rval->hash_count = count;
+	return (rval);
+}
+
+struct hash_bucket *
+new_hash_bucket(void)
+{
+	struct hash_bucket *rval = calloc(1, sizeof(struct hash_bucket));
+
+	return (rval);
+}
+
+void free_hash_bucket(struct hash_bucket *hb) { free(hb); }

Added: trunk/reactos/subsys/system/dhcp/compat.c
--- trunk/reactos/subsys/system/dhcp/compat.c	2005-04-04 23:17:28 UTC (rev 14495)
+++ trunk/reactos/subsys/system/dhcp/compat.c	2005-04-04 23:45:33 UTC (rev 14496)
@@ -0,0 +1,40 @@
+#include "rosdhcp.h"
+#include "dhcpd.h"
+#include "stdint.h"
+
+size_t strlcpy(char *d, const char *s, size_t bufsize)
+{
+        size_t len = strlen(s);
+        size_t ret = len;
+        if (bufsize > 0) {
+                if (len >= bufsize)
+                        len = bufsize-1;
+                memcpy(d, s, len);
+                d[len] = 0;
+        }
+        return ret;
+}
+
+// not really random :(
+u_int32_t arc4random()
+{
+	static int did_srand = 0;
+	u_int32_t ret;
+
+	if (!did_srand) {
+		srand(0);
+		did_srand = 1;
+	}
+
+	ret = rand() << 10 ^ rand();
+	return ret;
+}
+
+int inet_aton(const char *cp, struct in_addr *inp)
+{
+	inp->S_un.S_addr = inet_addr(cp);
+	if (INADDR_NONE == inp->S_un.S_addr)
+		return 0;
+
+	return 1;
+}

Added: trunk/reactos/subsys/system/dhcp/design.txt
--- trunk/reactos/subsys/system/dhcp/design.txt	2005-04-04 23:17:28 UTC (rev 14495)
+++ trunk/reactos/subsys/system/dhcp/design.txt	2005-04-04 23:45:33 UTC (rev 14496)
@@ -0,0 +1,29 @@
+Ok I need these things:
+
+1) Adapter concept thingy
+
+  Needs a name and index
+  Current IP address etc
+  interface_info
+
+  Must be able to get one from an adapter index or name
+  Must query the ip address and such
+  Must be able to set the address
+
+2) System state doodad
+
+  List of adapters
+  List of parameter changes
+  List of persistent stuff
+  
+  Must be able to initialize from the registry 
+  (persistent stuff, some adapter info)
+  Save changes to persistent set
+
+3) Parameter change set
+
+  TODO  
+
+4) Persistent queries
+
+  TODO
\ No newline at end of file

Added: trunk/reactos/subsys/system/dhcp/dhclient.c
--- trunk/reactos/subsys/system/dhcp/dhclient.c	2005-04-04 23:17:28 UTC (rev 14495)
+++ trunk/reactos/subsys/system/dhcp/dhclient.c	2005-04-04 23:45:33 UTC (rev 14496)
@@ -0,0 +1,2308 @@
+/*	$OpenBSD: dhclient.c,v 1.62 2004/12/05 18:35:51 deraadt Exp $	*/
+
+/*
+ * Copyright 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999
+ * The Internet Software Consortium.    All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ *    of its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises.  To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''.  To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ *
+ * This client was substantially modified and enhanced by Elliot Poger
+ * for use on Linux while he was working on the MosquitoNet project at
+ * Stanford.
+ *
+ * The current version owes much to Elliot's Linux enhancements, but
+ * was substantially reorganized and partially rewritten by Ted Lemon
+ * so as to use the same networking framework that the Internet Software
+ * Consortium DHCP server uses.   Much system-specific configuration code
+ * was moved into a shell script so that as support for more operating
+ * systems is added, it will not be necessary to port and maintain
+ * system-specific configuration code to these operating systems - instead,
+ * the shell script can invoke the native tools to accomplish the same
+ * purpose.
+ */
+
+#include <winsock2.h>
+#include "rosdhcp.h"
+#include "dhcpd.h"
+#include "privsep.h"
+
+#define	PERIOD 0x2e
+#define	hyphenchar(c) ((c) == 0x2d)
+#define	bslashchar(c) ((c) == 0x5c)
+#define	periodchar(c) ((c) == PERIOD)
+#define	asterchar(c) ((c) == 0x2a)
+#define	alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
+	    ((c) >= 0x61 && (c) <= 0x7a))
+#define	digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+
+#define	borderchar(c) (alphachar(c) || digitchar(c))
+#define	middlechar(c) (borderchar(c) || hyphenchar(c))
+#define	domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+
+unsigned long debug_trace_level = DEBUG_ULTRA;
+time_t cur_time;
+time_t default_lease_time = 43200; /* 12 hours... */
+
+char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
+char *path_dhclient_db = NULL;
+
+int log_perror = 1;
+int privfd;
+//int nullfd = -1;
+
+struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
+struct in_addr inaddr_any;
+struct sockaddr_in sockaddr_broadcast;
+
+/*
+ * ASSERT_STATE() does nothing now; it used to be
+ * assert (state_is == state_shouldbe).
+ */
+#define ASSERT_STATE(state_is, state_shouldbe) {}
+
+#define TIME_MAX 2147483647
+
+int		log_priority;
+int		no_daemon;
+int		unknown_ok = 1;
+int		routefd;
+
+struct interface_info	*ifi = NULL;
+
+void		 usage(void);
+int		 check_option(struct client_lease *l, int option);
+int		 ipv4addrs(char * buf);
+int		 res_hnok(const char *dn);
+char		*option_as_string(unsigned int code, unsigned char *data, int len);
+int		 fork_privchld(int, int);
+
+#define	ROUNDUP(a) \
+	    ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define	ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+time_t	scripttime;
+
+#if 0
+
+int
+findproto(char *cp, int n)
+{
+	struct sockaddr *sa;
+	int i;
+
+	if (n == 0)
+		return -1;
+	for (i = 1; i; i <<= 1) {
+		if (i & n) {
+			sa = (struct sockaddr *)cp;
+			switch (i) {
+			case RTA_IFA:
+			case RTA_DST:
+			case RTA_GATEWAY:
+			case RTA_NETMASK:
+				if (sa->sa_family == AF_INET)
+					return AF_INET;
+				if (sa->sa_family == AF_INET6)
+					return AF_INET6;
+				break;
+			case RTA_IFP:
+				break;
+			}
+			ADVANCE(cp, sa);
+		}
+	}
+	return (-1);
+}
+
+
+struct sockaddr *
+get_ifa(char *cp, int n)
+{
+	struct sockaddr *sa;
+	int i;
+
+	if (n == 0)
+		return (NULL);
+	for (i = 1; i; i <<= 1)
+		if (i & n) {
+			sa = (struct sockaddr *)cp;
+			if (i == RTA_IFA)
+				return (sa);
+			ADVANCE(cp, sa);
+		}
+
+	return (NULL);
+}
+struct iaddr defaddr = { 4 };
+
+/* ARGSUSED */
+void
+routehandler(struct protocol *p)
+{
+	char msg[2048];
+	struct rt_msghdr *rtm;
+	struct if_msghdr *ifm;
+	struct ifa_msghdr *ifam;
+	struct if_announcemsghdr *ifan;
+	struct client_lease *l;
+	time_t t = time(NULL);
+	struct sockaddr *sa;
+	struct iaddr a;
+	ssize_t n;
+
+	n = read(routefd, &msg, sizeof(msg));
+	rtm = (struct rt_msghdr *)msg;
+	if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
+	    rtm->rtm_version != RTM_VERSION)
+		return;
+
+	switch (rtm->rtm_type) {
+	case RTM_NEWADDR:
+		ifam = (struct ifa_msghdr *)rtm;
+		if (ifam->ifam_index != ifi->index)
+			break;
+		if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
+			break;
+		if (ifi == NULL)
+			goto die;
+		sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
+		if (sa == NULL)
+			goto die;
+
+		if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
+			error("king bula sez: len mismatch");
+		memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
+		if (addr_eq(a, defaddr))
+			break;
+
+		for (l = ifi->client->active; l != NULL; l = l->next)
+			if (addr_eq(a, l->address))
+				break;
+
+		if (l != NULL)	/* new addr is the one we set */
+			break;
+
+		goto die;
+	case RTM_DELADDR:
+		ifam = (struct ifa_msghdr *)rtm;
+		if (ifam->ifam_index != ifi->index)
+			break;
+		if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
+			break;
+		if (scripttime == 0 || t < scripttime + 10)
+			break;
+		goto die;
+	case RTM_IFINFO:
+		ifm = (struct if_msghdr *)rtm;
+		if (ifm->ifm_index != ifi->index)
+			break;
+		if ((rtm->rtm_flags & RTF_UP) == 0)
+			goto die;
+		break;
+	case RTM_IFANNOUNCE:
+		ifan = (struct if_announcemsghdr *)rtm;
+		if (ifan->ifan_what == IFAN_DEPARTURE &&
+		    ifan->ifan_index == ifi->index)
+			goto die;
+		break;
+	default:
+		break;
+	}
+	return;
+
+die:
+	script_init("FAIL", NULL);
+	if (ifi->client->alias)
+		script_write_params("alias_", ifi->client->alias);
+	script_go();
+	exit(1);
+}
+#endif
+
+int
+main(int argc, char *argv[])
+{
+	extern char		*__progname;
+	int			 ch, fd, quiet = 0, i = 0;
+	int			 pipe_fd[2];
+	struct passwd		*pw;
+
+        AdapterInit();
+
+	tzset();
+	time(&cur_time);
+
+	memset(&sockaddr_broadcast, 0, sizeof(sockaddr_broadcast));
+	sockaddr_broadcast.sin_family = AF_INET;
+	sockaddr_broadcast.sin_port = htons(REMOTE_PORT);
+	sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
+	inaddr_any.s_addr = INADDR_ANY;
+
+        DH_DbgPrint(MID_TRACE,("DHCP Service Started\n"));
+
+	read_client_conf();
+
+	if (!interface_link_status(ifi->name)) {
+            DH_DbgPrint(MID_TRACE,("%s: no link ", ifi->name));
+            Sleep(1000);
+            while (!interface_link_status(ifi->name)) {
+                DH_DbgPrint(MID_TRACE,("."));
+                if (++i > 10) {
+                    DH_DbgPrint(MID_TRACE,("Giving up for now on adapter [%s]\n", ifi->name));
+                }
+                Sleep(1000);
+            }
+            DH_DbgPrint(MID_TRACE,("Got link on [%s]\n", ifi->name));
+	}
+
+        DH_DbgPrint(MID_TRACE,("Discover Interfaces\n"));
+
+	/* set up the interface */
+	discover_interfaces(ifi);
+
+        DH_DbgPrint
+            (MID_TRACE,
+             ("Setting init state and restarting interface %p\n",ifi));
+
+	ifi->client->state = S_INIT;
+	state_reboot(ifi);
+
+	bootp_packet_handler = do_packet;
+
+        DH_DbgPrint(MID_TRACE,("Going into dispatch()\n"));
+
+	dispatch();
+
+	/* not reached */
+	return (0);
+}
+
+void
+usage(void)
+{
+//	extern char	*__progname;
+
+//	fprintf(stderr, "usage: %s [-dqu] ", __progname);
+	fprintf(stderr, "usage: dhclient [-dqu] ");
+	fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
+	exit(1);
+}
+
+/*
+ * Individual States:
+ *
+ * Each routine is called from the dhclient_state_machine() in one of
+ * these conditions:
+ * -> entering INIT state
+ * -> recvpacket_flag == 0: timeout in this state
+ * -> otherwise: received a packet in this state
+ *
+ * Return conditions as handled by dhclient_state_machine():
+ * Returns 1, sendpacket_flag = 1: send packet, reset timer.
+ * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
+ * Returns 0: finish the nap which was interrupted for no good reason.
+ *
+ * Several per-interface variables are used to keep track of the process:
+ *   active_lease: the lease that is being used on the interface
+ *                 (null pointer if not configured yet).
+ *   offered_leases: leases corresponding to DHCPOFFER messages that have
+ *                   been sent to us by DHCP servers.
+ *   acked_leases: leases corresponding to DHCPACK messages that have been
+ *                 sent to us by DHCP servers.
+ *   sendpacket: DHCP packet we're trying to send.
+ *   destination: IP address to send sendpacket to
+ * In addition, there are several relevant per-lease variables.
+ *   T1_expiry, T2_expiry, lease_expiry: lease milestones
+ * In the active lease, these control the process of renewing the lease;
+ * In leases on the acked_leases list, this simply determines when we
+ * can no longer legitimately use the lease.
+ */
+
+void
+state_reboot(void *ipp)
+{
+	struct interface_info *ip = ipp;
+
+	/* If we don't remember an active lease, go straight to INIT. */
+	if (!ip->client->active || ip->client->active->is_bootp) {
+		state_init(ip);
+		return;
+	}
+
+	/* We are in the rebooting state. */
+	ip->client->state = S_REBOOTING;
+
+	/* make_request doesn't initialize xid because it normally comes
+	   from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
+	   so pick an xid now. */
+	ip->client->xid = arc4random();
+
+	/* Make a DHCPREQUEST packet, and set appropriate per-interface
+	   flags. */
+	make_request(ip, ip->client->active);
+	ip->client->destination = iaddr_broadcast;
+	ip->client->first_sending = cur_time;
+	ip->client->interval = ip->client->config->initial_interval;
+
+	/* Zap the medium list... */
+	ip->client->medium = NULL;
+
+	/* Send out the first DHCPREQUEST packet. */
+	send_request(ip);
+}
+
+/*
+ * Called when a lease has completely expired and we've
+ * been unable to renew it.
+ */
+void
+state_init(void *ipp)
+{
+	struct interface_info *ip = ipp;
+
+	ASSERT_STATE(state, S_INIT);
+
+	/* Make a DHCPDISCOVER packet, and set appropriate per-interface
+	   flags. */
+	make_discover(ip, ip->client->active);
+	ip->client->xid = ip->client->packet.xid;
+	ip->client->destination = iaddr_broadcast;
+	ip->client->state = S_SELECTING;
+	ip->client->first_sending = cur_time;
+	ip->client->interval = ip->client->config->initial_interval;
+
+	/* Add an immediate timeout to cause the first DHCPDISCOVER packet
+	   to go out. */
+	send_discover(ip);
+}
+
+/*
+ * state_selecting is called when one or more DHCPOFFER packets
+ * have been received and a configurable period of time has passed.
+ */
+void
+state_selecting(void *ipp)
+{
+	struct interface_info *ip = ipp;
+	struct client_lease *lp, *next, *picked;
+
+	ASSERT_STATE(state, S_SELECTING);
+
+	/* Cancel state_selecting and send_discover timeouts, since either
+	   one could have got us here. */
+	cancel_timeout(state_selecting, ip);
+	cancel_timeout(send_discover, ip);
+
+	/* We have received one or more DHCPOFFER packets.   Currently,
+	   the only criterion by which we judge leases is whether or
+	   not we get a response when we arp for them. */
+	picked = NULL;
+	for (lp = ip->client->offered_leases; lp; lp = next) {
+		next = lp->next;
+
+		/* Check to see if we got an ARPREPLY for the address
+		   in this particular lease. */
+		if (!picked) {
+			script_init("ARPCHECK", lp->medium);
+			script_write_params("check_", lp);
+
+			/* If the ARPCHECK code detects another
+			   machine using the offered address, it exits
+			   nonzero.  We need to send a DHCPDECLINE and
+			   toss the lease. */
+			if (script_go()) {
+				make_decline(ip, lp);
+				send_decline(ip);
+				goto freeit;
+			}
+			picked = lp;
+			picked->next = NULL;
+		} else {
+freeit:
+			free_client_lease(lp);
+		}
+	}
+	ip->client->offered_leases = NULL;
+
+	/* If we just tossed all the leases we were offered, go back
+	   to square one. */
+	if (!picked) {
+		ip->client->state = S_INIT;
+		state_init(ip);
+		return;
+	}
+
+	/* If it was a BOOTREPLY, we can just take the address right now. */
+	if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
+		ip->client->new = picked;
+
+		/* Make up some lease expiry times
+		   XXX these should be configurable. */
+		ip->client->new->expiry = cur_time + 12000;
+		ip->client->new->renewal += cur_time + 8000;
+		ip->client->new->rebind += cur_time + 10000;
+
+		ip->client->state = S_REQUESTING;
+
+		/* Bind to the address we received. */
+		bind_lease(ip);
+		return;
+	}
+
+	/* Go to the REQUESTING state. */
+	ip->client->destination = iaddr_broadcast;
+	ip->client->state = S_REQUESTING;
+	ip->client->first_sending = cur_time;
+	ip->client->interval = ip->client->config->initial_interval;
+
+	/* Make a DHCPREQUEST packet from the lease we picked. */
+	make_request(ip, picked);
+	ip->client->xid = ip->client->packet.xid;
+
+	/* Toss the lease we picked - we'll get it back in a DHCPACK. */
+	free_client_lease(picked);
+
+	/* Add an immediate timeout to send the first DHCPREQUEST packet. */
+	send_request(ip);
+}
+
+/* state_requesting is called when we receive a DHCPACK message after
+   having sent out one or more DHCPREQUEST packets. */
+
+void
+dhcpack(struct packet *packet)
+{
+	struct interface_info *ip = packet->interface;
+	struct client_lease *lease;
+
+	/* If we're not receptive to an offer right now, or if the offer
+	   has an unrecognizable transaction id, then just drop it. */
+	if (packet->interface->client->xid != packet->raw->xid ||
+	    (packet->interface->hw_address.hlen != packet->raw->hlen) ||
+	    (memcmp(packet->interface->hw_address.haddr,
+	    packet->raw->chaddr, packet->raw->hlen)))
+		return;
+
+	if (ip->client->state != S_REBOOTING &&
+	    ip->client->state != S_REQUESTING &&
+	    ip->client->state != S_RENEWING &&
+	    ip->client->state != S_REBINDING)
+		return;
+
+	note("DHCPACK from %s", piaddr(packet->client_addr));
+
+	lease = packet_to_lease(packet);
+	if (!lease) {
+		note("packet_to_lease failed.");
+		return;
+	}
+
+	ip->client->new = lease;
+
+	/* Stop resending DHCPREQUEST. */
+	cancel_timeout(send_request, ip);
+
+	/* Figure out the lease time. */
+	if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
+		ip->client->new->expiry = getULong(
+		    ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
+	else
+		ip->client->new->expiry = default_lease_time;
+	/* A number that looks negative here is really just very large,
+	   because the lease expiry offset is unsigned. */
+	if (ip->client->new->expiry < 0)
+		ip->client->new->expiry = TIME_MAX;
+	/* XXX should be fixed by resetting the client state */
+	if (ip->client->new->expiry < 60)
+		ip->client->new->expiry = 60;
+
+	/* Take the server-provided renewal time if there is one;
+	   otherwise figure it out according to the spec. */
+	if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
+		ip->client->new->renewal = getULong(
+		    ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
+	else
+		ip->client->new->renewal = ip->client->new->expiry / 2;
+
+	/* Same deal with the rebind time. */
+	if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
+		ip->client->new->rebind = getULong(
+		    ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
+	else
+		ip->client->new->rebind = ip->client->new->renewal +
+		    ip->client->new->renewal / 2 + ip->client->new->renewal / 4;
+
+	ip->client->new->expiry += cur_time;
+	/* Lease lengths can never be negative. */
+	if (ip->client->new->expiry < cur_time)
+		ip->client->new->expiry = TIME_MAX;
+	ip->client->new->renewal += cur_time;
+	if (ip->client->new->renewal < cur_time)
+		ip->client->new->renewal = TIME_MAX;
+	ip->client->new->rebind += cur_time;
+	if (ip->client->new->rebind < cur_time)
+		ip->client->new->rebind = TIME_MAX;
+
+	bind_lease(ip);
+}
+
+void
+bind_lease(struct interface_info *ip)
+{
+	/* Remember the medium. */
+	ip->client->new->medium = ip->client->medium;
+
+	/* Write out the new lease. */
+	write_client_lease(ip, ip->client->new, 0);
+
+	/* Run the client script with the new parameters. */
+	script_init((ip->client->state == S_REQUESTING ? "BOUND" :
+	    (ip->client->state == S_RENEWING ? "RENEW" :
+	    (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
+	    ip->client->new->medium);
+	if (ip->client->active && ip->client->state != S_REBOOTING)
+		script_write_params("old_", ip->client->active);
+	script_write_params("new_", ip->client->new);
+	if (ip->client->alias)
+		script_write_params("alias_", ip->client->alias);
+	script_go();
+
+	/* Replace the old active lease with the new one. */
+	if (ip->client->active)
+		free_client_lease(ip->client->active);
+	ip->client->active = ip->client->new;
+	ip->client->new = NULL;
+
+	/* Set up a timeout to start the renewal process. */
+	add_timeout(ip->client->active->renewal, state_bound, ip);
+
+	note("bound to %s -- renewal in %d seconds.",
+	    piaddr(ip->client->active->address),
+	    ip->client->active->renewal - cur_time);
+	ip->client->state = S_BOUND;
+	reinitialize_interfaces();
+//	go_daemon();
+}
+
+/*
+ * state_bound is called when we've successfully bound to a particular
+ * lease, but the renewal time on that lease has expired.   We are
+ * expected to unicast a DHCPREQUEST to the server that gave us our
+ * original lease.
+ */
+void
+state_bound(void *ipp)
+{
+	struct interface_info *ip = ipp;
+
[truncated at 1000 lines; 7424 more skipped]