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(a)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(a)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(a)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]