<directory name="audiosrv">
<xi:include href="audiosrv/audiosrv.rbuild" />
</directory>
- <directory name="dhcp">
- <xi:include href="dhcp/dhcp.rbuild" />
- </directory>
<directory name="eventlog">
<xi:include href="eventlog/eventlog.rbuild" />
</directory>
; SvcHost services
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost",,0x00000012
-HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost", "netsvcs",0x00010000,""
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost", "netsvcs",0x00010000,"DHCP"
; EOF
; SvcHost services
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost",,0x00000012
-HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost", "netsvcs",0x00010000,""
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost", "netsvcs",0x00010000,"DHCP"
; EOF
; DHCP client service
HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","DisplayName",0x00000000,"DHCP Client"
HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Description",0x00000000,"Attempts to obtain network settings automatically from an available DHCP server"
-HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ErrorControl",0x00010001,0x00000000
-HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Group",0x00000000,"Network"
-HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ImagePath",0x00020000,"%SystemRoot%\system32\dhcp.exe"
+HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Group",0x00000000,"TDI"
+HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ImagePath",0x00020000,"%SystemRoot%\system32\svchost.exe -k netsvcs"
HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ObjectName",0x00000000,"LocalSystem"
HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Start",0x00010001,0x00000002
-HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Type",0x00010001,0x00000010
+HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Type",0x00010001,0x00000020
+HKLM,"SYSTEM\CurrentControlSet\Services\DHCP\Parameters","ServiceDll",0x00020000,"%SystemRoot%\system32\dhcpcsvc.dll"
; Event logging service
HKLM,"SYSTEM\CurrentControlSet\Services\EventLog",,0x00000010
base\applications\write\write.exe 1
base\services\audiosrv\audiosrv.exe 1
-base\services\dhcp\dhcp.exe 1
base\services\eventlog\eventlog.exe 1
base\services\rpcss\rpcss.exe 1
base\services\spoolsv\spoolsv.exe 1
--- /dev/null
+#include "rosdhcp.h"
+
+static SOCKET DhcpSocket = INVALID_SOCKET;
+static LIST_ENTRY AdapterList;
+static WSADATA wsd;
+
+PCHAR *GetSubkeyNames( PCHAR MainKeyName, PCHAR Append ) {
+ int i = 0;
+ DWORD Error;
+ HKEY MainKey;
+ PCHAR *Out, OutKeyName;
+ DWORD CharTotal = 0, AppendLen = 1 + strlen(Append);
+ DWORD MaxSubKeyLen = 0, MaxSubKeys = 0;
+
+ Error = RegOpenKey( HKEY_LOCAL_MACHINE, MainKeyName, &MainKey );
+
+ if( Error ) return NULL;
+
+ Error = RegQueryInfoKey
+ ( MainKey,
+ NULL, NULL, NULL,
+ &MaxSubKeys, &MaxSubKeyLen,
+ NULL, NULL, NULL, NULL, NULL, NULL );
+
+ DH_DbgPrint(MID_TRACE,("MaxSubKeys: %d, MaxSubKeyLen %d\n",
+ MaxSubKeys, MaxSubKeyLen));
+
+ CharTotal = (sizeof(PCHAR) + MaxSubKeyLen + AppendLen) * (MaxSubKeys + 1);
+
+ DH_DbgPrint(MID_TRACE,("AppendLen: %d, CharTotal: %d\n",
+ AppendLen, CharTotal));
+
+ Out = (CHAR**) malloc( CharTotal );
+ OutKeyName = ((PCHAR)&Out[MaxSubKeys+1]);
+
+ if( !Out ) { RegCloseKey( MainKey ); return NULL; }
+
+ i = 0;
+ do {
+ Out[i] = OutKeyName;
+ Error = RegEnumKey( MainKey, i, OutKeyName, MaxSubKeyLen );
+ if( !Error ) {
+ strcat( OutKeyName, Append );
+ DH_DbgPrint(MID_TRACE,("[%d]: %s\n", i, OutKeyName));
+ OutKeyName += strlen(OutKeyName) + 1;
+ i++;
+ } else Out[i] = 0;
+ } while( Error == ERROR_SUCCESS );
+
+ RegCloseKey( MainKey );
+
+ return Out;
+}
+
+PCHAR RegReadString( HKEY Root, PCHAR Subkey, PCHAR Value ) {
+ PCHAR SubOut = NULL;
+ DWORD SubOutLen = 0, Error = 0;
+ HKEY ValueKey = NULL;
+
+ DH_DbgPrint(MID_TRACE,("Looking in %x:%s:%s\n", Root, Subkey, Value ));
+
+ if( Subkey && strlen(Subkey) ) {
+ if( RegOpenKey( Root, Subkey, &ValueKey ) != ERROR_SUCCESS )
+ goto regerror;
+ } else ValueKey = Root;
+
+ DH_DbgPrint(MID_TRACE,("Got Key %x\n", ValueKey));
+
+ if( (Error = RegQueryValueEx( ValueKey, Value, NULL, NULL,
+ (LPBYTE)SubOut, &SubOutLen )) != ERROR_SUCCESS )
+ goto regerror;
+
+ DH_DbgPrint(MID_TRACE,("Value %s has size %d\n", Value, SubOutLen));
+
+ if( !(SubOut = (CHAR*) malloc(SubOutLen)) )
+ goto regerror;
+
+ if( (Error = RegQueryValueEx( ValueKey, Value, NULL, NULL,
+ (LPBYTE)SubOut, &SubOutLen )) != ERROR_SUCCESS )
+ goto regerror;
+
+ DH_DbgPrint(MID_TRACE,("Value %s is %s\n", Value, SubOut));
+
+ goto cleanup;
+
+regerror:
+ if( SubOut ) { free( SubOut ); SubOut = NULL; }
+cleanup:
+ if( ValueKey && ValueKey != Root ) {
+ DH_DbgPrint(MID_TRACE,("Closing key %x\n", ValueKey));
+ RegCloseKey( ValueKey );
+ }
+
+ DH_DbgPrint(MID_TRACE,("Returning %x with error %d\n", SubOut, Error));
+
+ return SubOut;
+}
+
+HKEY FindAdapterKey( PDHCP_ADAPTER Adapter ) {
+ int i = 0;
+ PCHAR EnumKeyName =
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\"
+ "{4D36E972-E325-11CE-BFC1-08002BE10318}";
+ PCHAR TargetKeyNameStart =
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
+ PCHAR TargetKeyName = NULL;
+ PCHAR *EnumKeysLinkage = GetSubkeyNames( EnumKeyName, "\\Linkage" );
+ PCHAR *EnumKeysTop = GetSubkeyNames( EnumKeyName, "" );
+ PCHAR RootDevice = NULL;
+ HKEY EnumKey, OutKey = NULL;
+ DWORD Error = ERROR_SUCCESS;
+
+ if( !EnumKeysLinkage || !EnumKeysTop ) goto cleanup;
+
+ Error = RegOpenKey( HKEY_LOCAL_MACHINE, EnumKeyName, &EnumKey );
+
+ if( Error ) goto cleanup;
+
+ for( i = 0; EnumKeysLinkage[i]; i++ ) {
+ RootDevice = RegReadString
+ ( EnumKey, EnumKeysLinkage[i], "RootDevice" );
+
+ if( RootDevice &&
+ !strcmp( RootDevice, Adapter->DhclientInfo.name ) ) {
+ TargetKeyName =
+ (CHAR*) malloc( strlen( TargetKeyNameStart ) +
+ strlen( RootDevice ) + 1);
+ if( !TargetKeyName ) goto cleanup;
+ sprintf( TargetKeyName, "%s%s",
+ TargetKeyNameStart, RootDevice );
+ Error = RegCreateKeyExA( HKEY_LOCAL_MACHINE, TargetKeyName, 0, NULL, 0, KEY_READ, NULL, &OutKey, NULL );
+ break;
+ } else {
+ free( RootDevice ); RootDevice = 0;
+ }
+ }
+
+cleanup:
+ if( RootDevice ) free( RootDevice );
+ if( EnumKeysLinkage ) free( EnumKeysLinkage );
+ if( EnumKeysTop ) free( EnumKeysTop );
+ if( TargetKeyName ) free( TargetKeyName );
+
+ return OutKey;
+}
+
+BOOL PrepareAdapterForService( PDHCP_ADAPTER Adapter ) {
+ HKEY AdapterKey = NULL;
+ PCHAR IPAddress = NULL, Netmask = NULL, DefaultGateway = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+ DWORD Error = ERROR_SUCCESS;
+
+ Adapter->DhclientState.config = &Adapter->DhclientConfig;
+ strncpy(Adapter->DhclientInfo.name, (char*)Adapter->IfMib.bDescr,
+ sizeof(Adapter->DhclientInfo.name));
+
+ AdapterKey = FindAdapterKey( Adapter );
+ if( AdapterKey )
+ IPAddress = RegReadString( AdapterKey, NULL, "IPAddress" );
+
+ if( IPAddress && strcmp( IPAddress, "0.0.0.0" ) ) {
+ /* Non-automatic case */
+ DH_DbgPrint
+ (MID_TRACE,("Adapter Name: [%s] (Bind Status %x) (static %s)\n",
+ Adapter->DhclientInfo.name,
+ Adapter->BindStatus,
+ IPAddress));
+
+ Adapter->DhclientState.state = S_STATIC;
+
+ Netmask = RegReadString( AdapterKey, NULL, "Subnetmask" );
+
+ Status = AddIPAddress( inet_addr( IPAddress ),
+ inet_addr( Netmask ? Netmask : "255.255.255.0" ),
+ Adapter->IfMib.dwIndex,
+ &Adapter->NteContext,
+ &Adapter->NteInstance );
+
+ DefaultGateway = RegReadString( AdapterKey, NULL, "DefaultGateway" );
+
+ if( DefaultGateway ) {
+ Adapter->RouterMib.dwForwardDest = 0;
+ Adapter->RouterMib.dwForwardMask = 0;
+ Adapter->RouterMib.dwForwardMetric1 = 1;
+ Adapter->RouterMib.dwForwardIfIndex = Adapter->IfMib.dwIndex;
+ Adapter->RouterMib.dwForwardNextHop = inet_addr(DefaultGateway);
+ Error = CreateIpForwardEntry( &Adapter->RouterMib );
+ if( Error )
+ warning("Failed to set default gateway %s: %ld\n",
+ DefaultGateway, Error);
+ }
+
+ if( DefaultGateway ) free( DefaultGateway );
+ if( Netmask ) free( Netmask );
+ } else {
+ /* Automatic case */
+ DH_DbgPrint
+ (MID_TRACE,("Adapter Name: [%s] (Bind Status %x) (dynamic)\n",
+ Adapter->DhclientInfo.name,
+ Adapter->BindStatus));
+
+ Adapter->DhclientInfo.client->state = S_INIT;
+ }
+
+ if( IPAddress ) free( IPAddress );
+
+ return TRUE;
+}
+
+void AdapterInit() {
+ WSAStartup(0x0101,&wsd);
+
+ InitializeListHead( &AdapterList );
+}
+
+int
+InterfaceConnected(MIB_IFROW IfEntry)
+{
+ if (IfEntry.dwOperStatus == IF_OPER_STATUS_CONNECTED ||
+ IfEntry.dwOperStatus == IF_OPER_STATUS_OPERATIONAL)
+ return 1;
+
+ DH_DbgPrint(MID_TRACE,("Interface %d is down\n", IfEntry.dwIndex));
+ return 0;
+}
+
+/*
+ * XXX Figure out the way to bind a specific adapter to a socket.
+ */
+BOOLEAN AdapterDiscover() {
+ PMIB_IFTABLE Table = (PMIB_IFTABLE) malloc(sizeof(MIB_IFTABLE));
+ DWORD Error, Size = sizeof(MIB_IFTABLE);
+ PDHCP_ADAPTER Adapter = NULL;
+ struct interface_info *ifi = NULL;
+ int i;
+ BOOLEAN ret = TRUE;
+
+ 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 = (PMIB_IFTABLE) malloc( Size );
+ }
+
+ if( Error != NO_ERROR ) {
+ ret = FALSE;
+ goto term;
+ }
+
+ DH_DbgPrint(MID_TRACE,("Got Adapter List (%d entries)\n", Table->dwNumEntries));
+
+ for( i = Table->dwNumEntries - 1; i >= 0; i-- ) {
+ DH_DbgPrint(MID_TRACE,("Getting adapter %d attributes\n",
+ Table->table[i].dwIndex));
+
+ if ((Adapter = AdapterFindByHardwareAddress(Table->table[i].bPhysAddr, Table->table[i].dwPhysAddrLen)))
+ {
+ /* This is an existing adapter */
+ if (InterfaceConnected(Table->table[i])) {
+ /* We're still active so we stay in the list */
+ ifi = &Adapter->DhclientInfo;
+ } else {
+ /* We've lost our link so out we go */
+ RemoveEntryList(&Adapter->ListEntry);
+ free(Adapter);
+ }
+
+ continue;
+ }
+
+ Adapter = (DHCP_ADAPTER*) calloc( sizeof( DHCP_ADAPTER ) + Table->table[i].dwMtu, 1 );
+
+ if( Adapter && Table->table[i].dwType == MIB_IF_TYPE_ETHERNET && InterfaceConnected(Table->table[i])) {
+ memcpy( &Adapter->IfMib, &Table->table[i],
+ sizeof(Adapter->IfMib) );
+ 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;
+ memcpy(Adapter->DhclientInfo.hw_address.haddr,
+ Adapter->IfMib.bPhysAddr,
+ Adapter->IfMib.dwPhysAddrLen);
+ Adapter->DhclientInfo.hw_address.hlen =
+ Adapter->IfMib.dwPhysAddrLen;
+ /* I'm not sure where else to set this, but
+ some DHCP servers won't take a zero.
+ We checked the hardware type earlier in
+ the if statement. */
+ Adapter->DhclientInfo.hw_address.htype =
+ HTYPE_ETHER;
+
+ if( DhcpSocket == INVALID_SOCKET ) {
+ DhcpSocket =
+ Adapter->DhclientInfo.rfdesc =
+ Adapter->DhclientInfo.wfdesc =
+ socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
+
+ if (DhcpSocket != INVALID_SOCKET) {
+ 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();
+ } else {
+ error("socket() failed: %d\n", WSAGetLastError());
+ }
+ } else {
+ Adapter->DhclientInfo.rfdesc =
+ Adapter->DhclientInfo.wfdesc = DhcpSocket;
+ }
+
+ Adapter->DhclientConfig.timeout = DHCP_PANIC_TIMEOUT;
+ 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;
+
+ if( PrepareAdapterForService( Adapter ) ) {
+ Adapter->DhclientInfo.next = ifi;
+ ifi = &Adapter->DhclientInfo;
+
+ read_client_conf(&Adapter->DhclientInfo);
+
+ if (Adapter->DhclientInfo.client->state == S_INIT)
+ {
+ add_protocol(Adapter->DhclientInfo.name,
+ Adapter->DhclientInfo.rfdesc,
+ got_one, &Adapter->DhclientInfo);
+
+ state_init(&Adapter->DhclientInfo);
+ }
+
+ InsertTailList( &AdapterList, &Adapter->ListEntry );
+ } else { free( Adapter ); Adapter = 0; }
+ } else { free( Adapter ); Adapter = 0; }
+
+ if( !Adapter )
+ DH_DbgPrint(MID_TRACE,("Adapter %d was rejected\n",
+ Table->table[i].dwIndex));
+ }
+
+ DH_DbgPrint(MID_TRACE,("done with AdapterInit\n"));
+
+term:
+ if( Table ) free( Table );
+ return ret;
+}
+
+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 AdapterFindInfo( struct interface_info *ip ) {
+ PDHCP_ADAPTER Adapter;
+ PLIST_ENTRY ListEntry;
+
+ for( ListEntry = AdapterList.Flink;
+ ListEntry != &AdapterList;
+ ListEntry = ListEntry->Flink ) {
+ Adapter = CONTAINING_RECORD( ListEntry, DHCP_ADAPTER, ListEntry );
+ if( ip == &Adapter->DhclientInfo ) return Adapter;
+ }
+
+ return NULL;
+}
+
+PDHCP_ADAPTER AdapterFindByHardwareAddress( u_int8_t haddr[16], u_int8_t hlen ) {
+ PDHCP_ADAPTER Adapter;
+ PLIST_ENTRY ListEntry;
+
+ for(ListEntry = AdapterList.Flink;
+ ListEntry != &AdapterList;
+ ListEntry = ListEntry->Flink) {
+ Adapter = CONTAINING_RECORD( ListEntry, DHCP_ADAPTER, ListEntry );
+ if (Adapter->DhclientInfo.hw_address.hlen == hlen &&
+ !memcmp(Adapter->DhclientInfo.hw_address.haddr,
+ haddr,
+ hlen)) 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) {
+}
--- /dev/null
+/* $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
+dfree(void *ptr, char *name)
+{
+ if (!ptr) {
+ warning("dfree %s: free on null pointer.", name);
+ return;
+ }
+ free(ptr);
+}
+
+void
+free_hash_bucket(struct hash_bucket *ptr, char *name)
+{
+ dfree(ptr, name);
+}
--- /dev/null
+/* $Id: $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: subsys/system/dhcp/api.c
+ * PURPOSE: DHCP client api handlers
+ * PROGRAMMER: arty
+ */
+
+#include "rosdhcp.h"
+#include <winsock2.h>
+#include <iphlpapi.h>
+
+#define NDEBUG
+#include <reactos/debug.h>
+
+static CRITICAL_SECTION ApiCriticalSection;
+
+VOID ApiInit() {
+ InitializeCriticalSection( &ApiCriticalSection );
+}
+
+VOID ApiLock() {
+ EnterCriticalSection( &ApiCriticalSection );
+}
+
+VOID ApiUnlock() {
+ LeaveCriticalSection( &ApiCriticalSection );
+}
+
+VOID ApiFree() {
+ DeleteCriticalSection( &ApiCriticalSection );
+}
+
+/* This represents the service portion of the DHCP client API */
+
+DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
+ COMM_DHCP_REPLY Reply;
+ PDHCP_ADAPTER Adapter;
+
+ ApiLock();
+
+ Adapter = AdapterFindIndex( Req->AdapterIndex );
+
+ Reply.Reply = Adapter ? 1 : 0;
+
+ if( Adapter ) {
+ add_protocol( Adapter->DhclientInfo.name,
+ Adapter->DhclientInfo.rfdesc, got_one,
+ &Adapter->DhclientInfo );
+ Adapter->DhclientInfo.client->state = S_INIT;
+ state_reboot(&Adapter->DhclientInfo);
+ }
+
+ ApiUnlock();
+
+ return Send( &Reply );
+}
+
+DWORD DSQueryHWInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
+ COMM_DHCP_REPLY Reply;
+ PDHCP_ADAPTER Adapter;
+
+ ApiLock();
+
+ Adapter = AdapterFindIndex( Req->AdapterIndex );
+
+ Reply.Reply = Adapter ? 1 : 0;
+
+ if (Adapter) {
+ Reply.QueryHWInfo.AdapterIndex = Req->AdapterIndex;
+ Reply.QueryHWInfo.MediaType = Adapter->IfMib.dwType;
+ Reply.QueryHWInfo.Mtu = Adapter->IfMib.dwMtu;
+ Reply.QueryHWInfo.Speed = Adapter->IfMib.dwSpeed;
+ }
+
+ ApiUnlock();
+
+ return Send( &Reply );
+}
+
+DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
+ COMM_DHCP_REPLY Reply;
+ PDHCP_ADAPTER Adapter;
+ struct protocol* proto;
+
+ ApiLock();
+
+ Adapter = AdapterFindIndex( Req->AdapterIndex );
+
+ Reply.Reply = Adapter ? 1 : 0;
+
+ if( Adapter ) {
+ if (Adapter->NteContext)
+ DeleteIPAddress( Adapter->NteContext );
+
+ proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
+ if (proto)
+ remove_protocol(proto);
+ }
+
+ ApiUnlock();
+
+ return Send( &Reply );
+}
+
+DWORD DSRenewIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
+ COMM_DHCP_REPLY Reply;
+ PDHCP_ADAPTER Adapter;
+
+ ApiLock();
+
+ Adapter = AdapterFindIndex( Req->AdapterIndex );
+
+ if( !Adapter || Adapter->DhclientState.state == S_STATIC ) {
+ Reply.Reply = 0;
+ ApiUnlock();
+ return Send( &Reply );
+ }
+
+ Reply.Reply = 1;
+
+ add_protocol( Adapter->DhclientInfo.name,
+ Adapter->DhclientInfo.rfdesc, got_one,
+ &Adapter->DhclientInfo );
+ Adapter->DhclientInfo.client->state = S_INIT;
+ state_reboot(&Adapter->DhclientInfo);
+
+ ApiUnlock();
+
+ return Send( &Reply );
+}
+
+DWORD DSStaticRefreshParams( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
+ NTSTATUS Status;
+ COMM_DHCP_REPLY Reply;
+ PDHCP_ADAPTER Adapter;
+ struct protocol* proto;
+
+ ApiLock();
+
+ Adapter = AdapterFindIndex( Req->AdapterIndex );
+
+ Reply.Reply = Adapter ? 1 : 0;
+
+ if( Adapter ) {
+ if (Adapter->NteContext)
+ DeleteIPAddress( Adapter->NteContext );
+ Adapter->DhclientState.state = S_STATIC;
+ proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
+ if (proto)
+ remove_protocol(proto);
+ Status = AddIPAddress( Req->Body.StaticRefreshParams.IPAddress,
+ Req->Body.StaticRefreshParams.Netmask,
+ Req->AdapterIndex,
+ &Adapter->NteContext,
+ &Adapter->NteInstance );
+ Reply.Reply = NT_SUCCESS(Status);
+ }
+
+ ApiUnlock();
+
+ return Send( &Reply );
+}
+
+DWORD DSGetAdapterInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
+ COMM_DHCP_REPLY Reply;
+ PDHCP_ADAPTER Adapter;
+
+ ApiLock();
+
+ Adapter = AdapterFindIndex( Req->AdapterIndex );
+
+ Reply.Reply = Adapter ? 1 : 0;
+
+ if( Adapter ) {
+ Reply.GetAdapterInfo.DhcpEnabled = (S_STATIC != Adapter->DhclientState.state);
+ if (S_BOUND == Adapter->DhclientState.state) {
+ if (sizeof(Reply.GetAdapterInfo.DhcpServer) ==
+ Adapter->DhclientState.active->serveraddress.len) {
+ memcpy(&Reply.GetAdapterInfo.DhcpServer,
+ Adapter->DhclientState.active->serveraddress.iabuf,
+ Adapter->DhclientState.active->serveraddress.len);
+ } else {
+ DPRINT1("Unexpected server address len %d\n",
+ Adapter->DhclientState.active->serveraddress.len);
+ Reply.GetAdapterInfo.DhcpServer = htonl(INADDR_NONE);
+ }
+ Reply.GetAdapterInfo.LeaseObtained = Adapter->DhclientState.active->obtained;
+ Reply.GetAdapterInfo.LeaseExpires = Adapter->DhclientState.active->expiry;
+ } else {
+ Reply.GetAdapterInfo.DhcpServer = htonl(INADDR_NONE);
+ Reply.GetAdapterInfo.LeaseObtained = 0;
+ Reply.GetAdapterInfo.LeaseExpires = 0;
+ }
+ }
+
+ ApiUnlock();
+
+ return Send( &Reply );
+}
--- /dev/null
+#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)
+/* inet_addr code from ROS, slightly modified. */
+{
+ ULONG Octets[4] = {0,0,0,0};
+ ULONG i = 0;
+
+ if(!cp)
+ return 0;
+
+ while(*cp)
+ {
+ CHAR c = *cp;
+ cp++;
+
+ if(c == '.')
+ {
+ i++;
+ continue;
+ }
+
+ if(c < '0' || c > '9')
+ return 0;
+
+ Octets[i] *= 10;
+ Octets[i] += (c - '0');
+
+ if(Octets[i] > 255)
+ return 0;
+ }
+
+ inp->S_un.S_addr = (Octets[3] << 24) + (Octets[2] << 16) + (Octets[1] << 8) + Octets[0];
+ return 1;
+}
+
--- /dev/null
+/* $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 "rosdhcp.h"
+#include "dhcpd.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 = 0; /* DEBUG_ULTRA */
+
+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;
+
+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);
+int check_arp( struct interface_info *ip, struct client_lease *lp );
+
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+time_t scripttime;
+
+static WCHAR ServiceName[] = L"DHCP";
+
+SERVICE_STATUS_HANDLE ServiceStatusHandle = 0;
+SERVICE_STATUS ServiceStatus;
+
+
+/* XXX Implement me */
+int check_arp( struct interface_info *ip, struct client_lease *lp ) {
+ return 1;
+}
+
+
+static VOID
+UpdateServiceStatus(DWORD dwState)
+{
+ ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ ServiceStatus.dwCurrentState = dwState;
+
+ ServiceStatus.dwControlsAccepted = 0;
+
+ ServiceStatus.dwWin32ExitCode = 0;
+ ServiceStatus.dwServiceSpecificExitCode = 0;
+ ServiceStatus.dwCheckPoint = 0;
+
+ if (dwState == SERVICE_START_PENDING ||
+ dwState == SERVICE_STOP_PENDING ||
+ dwState == SERVICE_PAUSE_PENDING ||
+ dwState == SERVICE_CONTINUE_PENDING)
+ ServiceStatus.dwWaitHint = 10000;
+ else
+ ServiceStatus.dwWaitHint = 0;
+
+ SetServiceStatus(ServiceStatusHandle,
+ &ServiceStatus);
+}
+
+
+static DWORD WINAPI
+ServiceControlHandler(DWORD dwControl,
+ DWORD dwEventType,
+ LPVOID lpEventData,
+ LPVOID lpContext)
+{
+ switch (dwControl)
+ {
+ case SERVICE_CONTROL_STOP:
+ UpdateServiceStatus(SERVICE_STOP_PENDING);
+ UpdateServiceStatus(SERVICE_STOPPED);
+ return ERROR_SUCCESS;
+
+ case SERVICE_CONTROL_PAUSE:
+ UpdateServiceStatus(SERVICE_PAUSED);
+ return ERROR_SUCCESS;
+
+ case SERVICE_CONTROL_CONTINUE:
+ UpdateServiceStatus(SERVICE_START_PENDING);
+ UpdateServiceStatus(SERVICE_RUNNING);
+ return ERROR_SUCCESS;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ SetServiceStatus(ServiceStatusHandle,
+ &ServiceStatus);
+ return ERROR_SUCCESS;
+
+ case SERVICE_CONTROL_SHUTDOWN:
+ UpdateServiceStatus(SERVICE_STOP_PENDING);
+ UpdateServiceStatus(SERVICE_STOPPED);
+ return ERROR_SUCCESS;
+
+ default :
+ return ERROR_CALL_NOT_IMPLEMENTED;
+ }
+}
+
+
+VOID NTAPI
+ServiceMain(DWORD argc, LPWSTR *argv)
+{
+ ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
+ ServiceControlHandler,
+ NULL);
+ if (!ServiceStatusHandle)
+ {
+ DbgPrint("DHCPCSVC: Unable to register service control handler (%x)\n", GetLastError);
+ return;
+ }
+
+ UpdateServiceStatus(SERVICE_START_PENDING);
+
+ ApiInit();
+ AdapterInit();
+
+ tzset();
+
+ 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;
+ bootp_packet_handler = do_packet;
+
+ if (PipeInit() == INVALID_HANDLE_VALUE)
+ {
+ DbgPrint("DHCPCSVC: PipeInit() failed!\n");
+ AdapterStop();
+ ApiFree();
+ UpdateServiceStatus(SERVICE_STOPPED);
+ }
+
+ DH_DbgPrint(MID_TRACE,("DHCP Service Started\n"));
+
+ UpdateServiceStatus(SERVICE_RUNNING);
+
+ DH_DbgPrint(MID_TRACE,("Going into dispatch()\n"));
+
+ DbgPrint("DHCPCSVC: DHCP service is starting up\n");
+
+ dispatch();
+
+ DbgPrint("DHCPCSVC: DHCP service is shutting down\n");
+
+ //AdapterStop();
+ //ApiFree();
+ /* FIXME: Close pipe and kill pipe thread */
+
+ UpdateServiceStatus(SERVICE_STOPPED);
+}
+
+/*
+ * 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;
+ ULONG foo = (ULONG) GetTickCount();
+
+ /* 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 = RtlRandom(&foo);
+
+ /* Make a DHCPREQUEST packet, and set appropriate per-interface
+ flags. */
+ make_request(ip, ip->client->active);
+ ip->client->destination = iaddr_broadcast;
+ time(&ip->client->first_sending);
+ 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;
+ time(&ip->client->first_sending);
+ 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;
+ time_t cur_time;
+
+ ASSERT_STATE(state, S_SELECTING);
+
+ time(&cur_time);
+
+ /* 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) {
+ if( !check_arp(ip,lp) ) 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;
+ time_t cur_time;
+
+ time(&cur_time);
+
+ /* 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 = DHCP_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;
+
+#ifdef __REACTOS__
+ ip->client->new->obtained = cur_time;
+#endif
+ 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 set_name_servers( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
+ CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
+ HKEY RegKey;
+
+ strcat(Buffer, Adapter->DhclientInfo.name);
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer, 0, KEY_WRITE, &RegKey ) != ERROR_SUCCESS)
+ return;
+
+
+ if( new_lease->options[DHO_DOMAIN_NAME_SERVERS].len ) {
+
+ struct iaddr nameserver;
+ char *nsbuf;
+ int i, addrs =
+ new_lease->options[DHO_DOMAIN_NAME_SERVERS].len / sizeof(ULONG);
+
+ nsbuf = malloc( addrs * sizeof(IP_ADDRESS_STRING) );
+
+ if( nsbuf) {
+ nsbuf[0] = 0;
+ for( i = 0; i < addrs; i++ ) {
+ nameserver.len = sizeof(ULONG);
+ memcpy( nameserver.iabuf,
+ new_lease->options[DHO_DOMAIN_NAME_SERVERS].data +
+ (i * sizeof(ULONG)), sizeof(ULONG) );
+ strcat( nsbuf, piaddr(nameserver) );
+ if( i != addrs-1 ) strcat( nsbuf, "," );
+ }
+
+ DH_DbgPrint(MID_TRACE,("Setting DhcpNameserver: %s\n", nsbuf));
+
+ RegSetValueExA( RegKey, "DhcpNameServer", 0, REG_SZ,
+ (LPBYTE)nsbuf, strlen(nsbuf) + 1 );
+ free( nsbuf );
+ }
+
+ } else {
+ RegDeleteValueW( RegKey, L"DhcpNameServer" );
+ }
+
+ RegCloseKey( RegKey );
+
+}
+
+void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
+ CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
+ struct iaddr netmask;
+ HKEY hkey;
+ int i;
+ DWORD dwEnableDHCP;
+
+ strcat(Buffer, Adapter->DhclientInfo.name);
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer, 0, KEY_WRITE, &hkey) != ERROR_SUCCESS)
+ hkey = NULL;
+
+
+ if( Adapter->NteContext )
+ DeleteIPAddress( Adapter->NteContext );
+
+ /* Set up our default router if we got one from the DHCP server */
+ if( new_lease->options[DHO_SUBNET_MASK].len ) {
+ NTSTATUS Status;
+
+ memcpy( netmask.iabuf,
+ new_lease->options[DHO_SUBNET_MASK].data,
+ new_lease->options[DHO_SUBNET_MASK].len );
+ Status = AddIPAddress
+ ( *((ULONG*)new_lease->address.iabuf),
+ *((ULONG*)netmask.iabuf),
+ Adapter->IfMib.dwIndex,
+ &Adapter->NteContext,
+ &Adapter->NteInstance );
+ if (hkey) {
+ RegSetValueExA(hkey, "DhcpIPAddress", 0, REG_SZ, (LPBYTE)piaddr(new_lease->address), strlen(piaddr(new_lease->address))+1);
+ Buffer[0] = '\0';
+ for(i = 0; i < new_lease->options[DHO_SUBNET_MASK].len; i++)
+ {
+ sprintf(&Buffer[strlen(Buffer)], "%u", new_lease->options[DHO_SUBNET_MASK].data[i]);
+ if (i + 1 < new_lease->options[DHO_SUBNET_MASK].len)
+ strcat(Buffer, ".");
+ }
+ RegSetValueExA(hkey, "DhcpSubnetMask", 0, REG_SZ, (LPBYTE)Buffer, strlen(Buffer)+1);
+ RegSetValueExA(hkey, "IPAddress", 0, REG_SZ, (LPBYTE)"0.0.0.0", 8);
+ RegSetValueExA(hkey, "SubnetMask", 0, REG_SZ, (LPBYTE)"0.0.0.0", 8);
+ dwEnableDHCP = 1;
+ RegSetValueExA(hkey, "EnableDHCP", 0, REG_DWORD, (LPBYTE)&dwEnableDHCP, sizeof(DWORD));
+ }
+
+ if( !NT_SUCCESS(Status) )
+ warning("AddIPAddress: %lx\n", Status);
+ }
+
+ if( new_lease->options[DHO_ROUTERS].len ) {
+ NTSTATUS Status;
+
+ Adapter->RouterMib.dwForwardDest = 0; /* Default route */
+ Adapter->RouterMib.dwForwardMask = 0;
+ Adapter->RouterMib.dwForwardMetric1 = 1;
+ Adapter->RouterMib.dwForwardIfIndex = Adapter->IfMib.dwIndex;
+
+ if( Adapter->RouterMib.dwForwardNextHop ) {
+ /* If we set a default route before, delete it before continuing */
+ DeleteIpForwardEntry( &Adapter->RouterMib );
+ }
+
+ Adapter->RouterMib.dwForwardNextHop =
+ *((ULONG*)new_lease->options[DHO_ROUTERS].data);
+
+ Status = CreateIpForwardEntry( &Adapter->RouterMib );
+
+ if( !NT_SUCCESS(Status) )
+ warning("CreateIpForwardEntry: %lx\n", Status);
+
+ if (hkey) {
+ Buffer[0] = '\0';
+ for(i = 0; i < new_lease->options[DHO_ROUTERS].len; i++)
+ {
+ sprintf(&Buffer[strlen(Buffer)], "%u", new_lease->options[DHO_ROUTERS].data[i]);
+ if (i + 1 < new_lease->options[DHO_ROUTERS].len)
+ strcat(Buffer, ".");
+ }
+ RegSetValueExA(hkey, "DhcpDefaultGateway", 0, REG_SZ, (LPBYTE)Buffer, strlen(Buffer)+1);
+ RegSetValueExA(hkey, "DefaultGateway", 0, REG_SZ, (LPBYTE)"0.0.0.0", 8);
+ }
+ }
+
+ if (hkey)
+ RegCloseKey(hkey);
+}
+
+
+void
+bind_lease(struct interface_info *ip)
+{
+ PDHCP_ADAPTER Adapter;
+ struct client_lease *new_lease = ip->client->new;
+ time_t cur_time;
+
+ time(&cur_time);
+
+ /* Remember the medium. */
+ ip->client->new->medium = ip->client->medium;
+ ip->client->active = ip->client->new;
+ ip->client->new = NULL;
+
+ /* Set up a timeout to start the renewal process. */
+ /* Timeout of zero means no timeout (some implementations seem to use
+ * one day).
+ */
+ if( ip->client->active->renewal - cur_time )
+ add_timeout(ip->client->active->renewal, state_bound, ip);
+
+ note("bound to %s -- renewal in %ld seconds.",
+ piaddr(ip->client->active->address),
+ (long int)(ip->client->active->renewal - cur_time));
+
+ ip->client->state = S_BOUND;
+
+ Adapter = AdapterFindInfo( ip );
+
+ if( Adapter ) setup_adapter( Adapter, new_lease );
+ else {
+ warning("Could not find adapter for info %p\n", ip);
+ return;
+ }
+ set_name_servers( Adapter, new_lease );
+}
+
+/*
+ * 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;
+
+ ASSERT_STATE(state, S_BOUND);
+
+ /* T1 has expired. */
+ make_request(ip, ip->client->active);
+ ip->client->xid = ip->client->packet.xid;
+
+ if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
+ memcpy(ip->client->destination.iabuf, ip->client->active->
+ options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
+ ip->client->destination.len = 4;
+ } else
+ ip->client->destination = iaddr_broadcast;
+
+ time(&ip->client->first_sending);
+ ip->client->interval = ip->client->config->initial_interval;
+ ip->client->state = S_RENEWING;
+
+ /* Send the first packet immediately. */
+ send_request(ip);
+}
+
+void
+bootp(struct packet *packet)
+{
+ struct iaddrlist *ap;
+
+ if (packet->raw->op != BOOTREPLY)
+ return;
+
+ /* If there's a reject list, make sure this packet's sender isn't
+ on it. */
+ for (ap = packet->interface->client->config->reject_list;
+ ap; ap = ap->next) {
+ if (addr_eq(packet->client_addr, ap->addr)) {
+ note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
+ return;
+ }
+ }
+ dhcpoffer(packet);
+}
+
+void
+dhcp(struct packet *packet)
+{
+ struct iaddrlist *ap;
+ void (*handler)(struct packet *);
+ char *type;
+
+ switch (packet->packet_type) {
+ case DHCPOFFER:
+ handler = dhcpoffer;
+ type = "DHCPOFFER";
+ break;
+ case DHCPNAK:
+ handler = dhcpnak;
+ type = "DHCPNACK";
+ break;
+ case DHCPACK:
+ handler = dhcpack;
+ type = "DHCPACK";
+ break;
+ default:
+ return;
+ }
+
+ /* If there's a reject list, make sure this packet's sender isn't
+ on it. */
+ for (ap = packet->interface->client->config->reject_list;
+ ap; ap = ap->next) {
+ if (addr_eq(packet->client_addr, ap->addr)) {
+ note("%s from %s rejected.", type, piaddr(ap->addr));
+ return;
+ }
+ }
+ (*handler)(packet);
+}
+
+void
+dhcpoffer(struct packet *packet)
+{
+ struct interface_info *ip = packet->interface;
+ struct client_lease *lease, *lp;
+ int i;
+ int arp_timeout_needed = 0, stop_selecting;
+ char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
+ "DHCPOFFER" : "BOOTREPLY";
+ time_t cur_time;
+
+ time(&cur_time);
+
+ /* If we're not receptive to an offer right now, or if the offer
+ has an unrecognizable transaction id, then just drop it. */
+ if (ip->client->state != S_SELECTING ||
+ 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;
+
+ note("%s from %s", name, piaddr(packet->client_addr));
+
+
+ /* If this lease doesn't supply the minimum required parameters,
+ blow it off. */
+ for (i = 0; ip->client->config->required_options[i]; i++) {
+ if (!packet->options[ip->client->config->
+ required_options[i]].len) {
+ note("%s isn't satisfactory.", name);
+ return;
+ }
+ }
+
+ /* If we've already seen this lease, don't record it again. */
+ for (lease = ip->client->offered_leases;
+ lease; lease = lease->next) {
+ if (lease->address.len == sizeof(packet->raw->yiaddr) &&
+ !memcmp(lease->address.iabuf,
+ &packet->raw->yiaddr, lease->address.len)) {
+ debug("%s already seen.", name);
+ return;
+ }
+ }
+
+ lease = packet_to_lease(packet);
+ if (!lease) {
+ note("packet_to_lease failed.");
+ return;
+ }
+
+ /* If this lease was acquired through a BOOTREPLY, record that
+ fact. */
+ if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
+ lease->is_bootp = 1;
+
+ /* Record the medium under which this lease was offered. */
+ lease->medium = ip->client->medium;
+
+ /* Send out an ARP Request for the offered IP address. */
+ if( !check_arp( ip, lease ) ) {
+ note("Arp check failed\n");
+ return;
+ }
+
+ /* Figure out when we're supposed to stop selecting. */
+ stop_selecting =
+ ip->client->first_sending + ip->client->config->select_interval;
+
+ /* If this is the lease we asked for, put it at the head of the
+ list, and don't mess with the arp request timeout. */
+ if (lease->address.len == ip->client->requested_address.len &&
+ !memcmp(lease->address.iabuf,
+ ip->client->requested_address.iabuf,
+ ip->client->requested_address.len)) {
+ lease->next = ip->client->offered_leases;
+ ip->client->offered_leases = lease;
+ } else {
+ /* If we already have an offer, and arping for this
+ offer would take us past the selection timeout,
+ then don't extend the timeout - just hope for the
+ best. */
+ if (ip->client->offered_leases &&
+ (cur_time + arp_timeout_needed) > stop_selecting)
+ arp_timeout_needed = 0;
+
+ /* Put the lease at the end of the list. */
+ lease->next = NULL;
+ if (!ip->client->offered_leases)
+ ip->client->offered_leases = lease;
+ else {
+ for (lp = ip->client->offered_leases; lp->next;
+ lp = lp->next)
+ ; /* nothing */
+ lp->next = lease;
+ }
+ }
+
+ /* If we're supposed to stop selecting before we've had time
+ to wait for the ARPREPLY, add some delay to wait for
+ the ARPREPLY. */
+ if (stop_selecting - cur_time < arp_timeout_needed)
+ stop_selecting = cur_time + arp_timeout_needed;
+
+ /* If the selecting interval has expired, go immediately to
+ state_selecting(). Otherwise, time out into
+ state_selecting at the select interval. */
+ if (stop_selecting <= 0)
+ state_selecting(ip);
+ else {
+ add_timeout(stop_selecting, state_selecting, ip);
+ cancel_timeout(send_discover, ip);
+ }
+}
+
+/* Allocate a client_lease structure and initialize it from the parameters
+ in the specified packet. */
+
+struct client_lease *
+packet_to_lease(struct packet *packet)
+{
+ struct client_lease *lease;
+ int i;
+
+ lease = malloc(sizeof(struct client_lease));
+
+ if (!lease) {
+ warning("dhcpoffer: no memory to record lease.");
+ return (NULL);
+ }
+
+ memset(lease, 0, sizeof(*lease));
+
+ /* Copy the lease options. */
+ for (i = 0; i < 256; i++) {
+ if (packet->options[i].len) {
+ lease->options[i].data =
+ malloc(packet->options[i].len + 1);
+ if (!lease->options[i].data) {
+ warning("dhcpoffer: no memory for option %d", i);
+ free_client_lease(lease);
+ return (NULL);
+ } else {
+ memcpy(lease->options[i].data,
+ packet->options[i].data,
+ packet->options[i].len);
+ lease->options[i].len =
+ packet->options[i].len;
+ lease->options[i].data[lease->options[i].len] =
+ 0;
+ }
+ if (!check_option(lease,i)) {
+ /* ignore a bogus lease offer */
+ warning("Invalid lease option - ignoring offer");
+ free_client_lease(lease);
+ return (NULL);
+ }
+ }
+ }
+
+ lease->address.len = sizeof(packet->raw->yiaddr);
+ memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
+#ifdef __REACTOS__
+ lease->serveraddress.len = sizeof(packet->raw->siaddr);
+ memcpy(lease->serveraddress.iabuf, &packet->raw->siaddr, lease->address.len);
+#endif
+
+ /* If the server name was filled out, copy it. */
+ if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
+ !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
+ packet->raw->sname[0]) {
+ lease->server_name = malloc(DHCP_SNAME_LEN + 1);
+ if (!lease->server_name) {
+ warning("dhcpoffer: no memory for server name.");
+ free_client_lease(lease);
+ return (NULL);
+ }
+ memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
+ lease->server_name[DHCP_SNAME_LEN]='\0';
+ if (!res_hnok(lease->server_name) ) {
+ warning("Bogus server name %s", lease->server_name );
+ free_client_lease(lease);
+ return (NULL);
+ }
+
+ }
+
+ /* Ditto for the filename. */
+ if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
+ !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
+ packet->raw->file[0]) {
+ /* Don't count on the NUL terminator. */
+ lease->filename = malloc(DHCP_FILE_LEN + 1);
+ if (!lease->filename) {
+ warning("dhcpoffer: no memory for filename.");
+ free_client_lease(lease);
+ return (NULL);
+ }
+ memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
+ lease->filename[DHCP_FILE_LEN]='\0';
+ }
+ return lease;
+}
+
+void
+dhcpnak(struct packet *packet)
+{
+ struct interface_info *ip = packet->interface;
+
+ /* 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("DHCPNAK from %s", piaddr(packet->client_addr));
+
+ if (!ip->client->active) {
+ note("DHCPNAK with no active lease.\n");
+ return;
+ }
+
+ free_client_lease(ip->client->active);
+ ip->client->active = NULL;
+
+ /* Stop sending DHCPREQUEST packets... */
+ cancel_timeout(send_request, ip);
+
+ ip->client->state = S_INIT;
+ state_init(ip);
+}
+
+/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
+ one after the right interval has expired. If we don't get an offer by
+ the time we reach the panic interval, call the panic function. */
+
+void
+send_discover(void *ipp)
+{
+ struct interface_info *ip = ipp;
+ int interval, increase = 1;
+ time_t cur_time;
+
+ DH_DbgPrint(MID_TRACE,("Doing discover on interface %p\n",ip));
+
+ time(&cur_time);
+
+ /* Figure out how long it's been since we started transmitting. */
+ interval = cur_time - ip->client->first_sending;
+
+ /* If we're past the panic timeout, call the script and tell it
+ we haven't found anything for this interface yet. */
+ if (interval > ip->client->config->timeout) {
+ state_panic(ip);
+ return;
+ }
+
+ /* If we're selecting media, try the whole list before doing
+ the exponential backoff, but if we've already received an
+ offer, stop looping, because we obviously have it right. */
+ if (!ip->client->offered_leases &&
+ ip->client->config->media) {
+ int fail = 0;
+
+ if (ip->client->medium) {
+ ip->client->medium = ip->client->medium->next;
+ increase = 0;
+ }
+ if (!ip->client->medium) {
+ if (fail)
+ error("No valid media types for %s!", ip->name);
+ ip->client->medium = ip->client->config->media;
+ increase = 1;
+ }
+
+ note("Trying medium \"%s\" %d", ip->client->medium->string,
+ increase);
+ /* XXX Support other media types eventually */
+ }
+
+ /*
+ * If we're supposed to increase the interval, do so. If it's
+ * currently zero (i.e., we haven't sent any packets yet), set
+ * it to one; otherwise, add to it a random number between zero
+ * and two times itself. On average, this means that it will
+ * double with every transmission.
+ */
+ if (increase) {
+ if (!ip->client->interval)
+ ip->client->interval =
+ ip->client->config->initial_interval;
+ else {
+ ip->client->interval += (rand() >> 2) %
+ (2 * ip->client->interval);
+ }
+
+ /* Don't backoff past cutoff. */
+ if (ip->client->interval >
+ ip->client->config->backoff_cutoff)
+ ip->client->interval =
+ ((ip->client->config->backoff_cutoff / 2)
+ + ((rand() >> 2) %
+ ip->client->config->backoff_cutoff));
+ } else if (!ip->client->interval)
+ ip->client->interval =
+ ip->client->config->initial_interval;
+
+ /* If the backoff would take us to the panic timeout, just use that
+ as the interval. */
+ if (cur_time + ip->client->interval >
+ ip->client->first_sending + ip->client->config->timeout)
+ ip->client->interval =
+ (ip->client->first_sending +
+ ip->client->config->timeout) - cur_time + 1;
+
+ /* Record the number of seconds since we started sending. */
+ if (interval < 65536)
+ ip->client->packet.secs = htons(interval);
+ else
+ ip->client->packet.secs = htons(65535);
+ ip->client->secs = ip->client->packet.secs;
+
+ note("DHCPDISCOVER on %s to %s port %d interval %ld",
+ ip->name, inet_ntoa(sockaddr_broadcast.sin_addr),
+ ntohs(sockaddr_broadcast.sin_port), (long int)ip->client->interval);
+
+ /* Send out a packet. */
+ (void)send_packet(ip, &ip->client->packet, ip->client->packet_length,
+ inaddr_any, &sockaddr_broadcast, NULL);
+
+ DH_DbgPrint(MID_TRACE,("discover timeout: now %x -> then %x\n",
+ cur_time, cur_time + ip->client->interval));
+
+ add_timeout(cur_time + ip->client->interval, send_discover, ip);
+}
+
+/*
+ * state_panic gets called if we haven't received any offers in a preset
+ * amount of time. When this happens, we try to use existing leases
+ * that haven't yet expired, and failing that, we call the client script
+ * and hope it can do something.
+ */
+void
+state_panic(void *ipp)
+{
+ struct interface_info *ip = ipp;
+ time_t cur_time;
+
+ time(&cur_time);
+
+ note("No DHCPOFFERS received.");
+
+ note("No working leases in persistent database - sleeping.\n");
+ ip->client->state = S_INIT;
+ add_timeout(cur_time + ip->client->config->retry_interval, state_init,
+ ip);
+ /* XXX Take any failure actions necessary */
+}
+
+void
+send_request(void *ipp)
+{
+ struct interface_info *ip = ipp;
+ struct sockaddr_in destination;
+ struct in_addr from;
+ int interval;
+ time_t cur_time;
+
+ time(&cur_time);
+
+ /* Figure out how long it's been since we started transmitting. */
+ interval = cur_time - ip->client->first_sending;
+
+ /* If we're in the INIT-REBOOT or REQUESTING state and we're
+ past the reboot timeout, go to INIT and see if we can
+ DISCOVER an address... */
+ /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
+ means either that we're on a network with no DHCP server,
+ or that our server is down. In the latter case, assuming
+ that there is a backup DHCP server, DHCPDISCOVER will get
+ us a new address, but we could also have successfully
+ reused our old address. In the former case, we're hosed
+ anyway. This is not a win-prone situation. */
+ if ((ip->client->state == S_REBOOTING ||
+ ip->client->state == S_REQUESTING) &&
+ interval > ip->client->config->reboot_timeout) {
+ ip->client->state = S_INIT;
+ cancel_timeout(send_request, ip);
+ state_init(ip);
+ return;
+ }
+
+ /* If we're in the reboot state, make sure the media is set up
+ correctly. */
+ if (ip->client->state == S_REBOOTING &&
+ !ip->client->medium &&
+ ip->client->active->medium ) {
+ /* If the medium we chose won't fly, go to INIT state. */
+ /* XXX Nothing for now */
+
+ /* Record the medium. */
+ ip->client->medium = ip->client->active->medium;
+ }
+
+ /* If the lease has expired, relinquish the address and go back
+ to the INIT state. */
+ if (ip->client->state != S_REQUESTING &&
+ cur_time > ip->client->active->expiry) {
+ PDHCP_ADAPTER Adapter = AdapterFindInfo( ip );
+ /* Run the client script with the new parameters. */
+ /* No script actions necessary in the expiry case */
+ /* Now do a preinit on the interface so that we can
+ discover a new address. */
+
+ if( Adapter )
+ DeleteIPAddress( Adapter->NteContext );
+
+ ip->client->state = S_INIT;
+ state_init(ip);
+ return;
+ }
+
+ /* Do the exponential backoff... */
+ if (!ip->client->interval)
+ ip->client->interval = ip->client->config->initial_interval;
+ else
+ ip->client->interval += ((rand() >> 2) %
+ (2 * ip->client->interval));
+
+ /* Don't backoff past cutoff. */
+ if (ip->client->interval >
+ ip->client->config->backoff_cutoff)
+ ip->client->interval =
+ ((ip->client->config->backoff_cutoff / 2) +
+ ((rand() >> 2) % ip->client->interval));
+
+ /* If the backoff would take us to the expiry time, just set the
+ timeout to the expiry time. */
+ if (ip->client->state != S_REQUESTING &&
+ cur_time + ip->client->interval >
+ ip->client->active->expiry)
+ ip->client->interval =
+ ip->client->active->expiry - cur_time + 1;
+
+ /* If the lease T2 time has elapsed, or if we're not yet bound,
+ broadcast the DHCPREQUEST rather than unicasting. */
+ memset(&destination, 0, sizeof(destination));
+ if (ip->client->state == S_REQUESTING ||
+ ip->client->state == S_REBOOTING ||
+ cur_time > ip->client->active->rebind)
+ destination.sin_addr.s_addr = INADDR_BROADCAST;
+ else
+ memcpy(&destination.sin_addr.s_addr,
+ ip->client->destination.iabuf,
+ sizeof(destination.sin_addr.s_addr));
+ destination.sin_port = htons(REMOTE_PORT);
+ destination.sin_family = AF_INET;
+// destination.sin_len = sizeof(destination);
+
+ if (ip->client->state != S_REQUESTING)
+ memcpy(&from, ip->client->active->address.iabuf,
+ sizeof(from));
+ else
+ from.s_addr = INADDR_ANY;
+
+ /* Record the number of seconds since we started sending. */
+ if (ip->client->state == S_REQUESTING)
+ ip->client->packet.secs = ip->client->secs;
+ else {
+ if (interval < 65536)
+ ip->client->packet.secs = htons(interval);
+ else
+ ip->client->packet.secs = htons(65535);
+ }
+
+ note("DHCPREQUEST on %s to %s port %d", ip->name,
+ inet_ntoa(destination.sin_addr), ntohs(destination.sin_port));
+
+ /* Send out a packet. */
+ (void) send_packet(ip, &ip->client->packet, ip->client->packet_length,
+ from, &destination, NULL);
+
+ add_timeout(cur_time + ip->client->interval, send_request, ip);
+}
+
+void
+send_decline(void *ipp)
+{
+ struct interface_info *ip = ipp;
+
+ note("DHCPDECLINE on %s to %s port %d", ip->name,
+ inet_ntoa(sockaddr_broadcast.sin_addr),
+ ntohs(sockaddr_broadcast.sin_port));
+
+ /* Send out a packet. */
+ (void) send_packet(ip, &ip->client->packet, ip->client->packet_length,
+ inaddr_any, &sockaddr_broadcast, NULL);
+}
+
+void
+make_discover(struct interface_info *ip, struct client_lease *lease)
+{
+ unsigned char discover = DHCPDISCOVER;
+ struct tree_cache *options[256];
+ struct tree_cache option_elements[256];
+ int i;
+ ULONG foo = (ULONG) GetTickCount();
+
+ memset(option_elements, 0, sizeof(option_elements));
+ memset(options, 0, sizeof(options));
+ memset(&ip->client->packet, 0, sizeof(ip->client->packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options[i] = &option_elements[i];
+ options[i]->value = &discover;
+ options[i]->len = sizeof(discover);
+ options[i]->buf_size = sizeof(discover);
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Request the options we want */
+ i = DHO_DHCP_PARAMETER_REQUEST_LIST;
+ options[i] = &option_elements[i];
+ options[i]->value = ip->client->config->requested_options;
+ options[i]->len = ip->client->config->requested_option_count;
+ options[i]->buf_size =
+ ip->client->config->requested_option_count;
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* If we had an address, try to get it again. */
+ if (lease) {
+ ip->client->requested_address = lease->address;
+ i = DHO_DHCP_REQUESTED_ADDRESS;
+ options[i] = &option_elements[i];
+ options[i]->value = lease->address.iabuf;
+ options[i]->len = lease->address.len;
+ options[i]->buf_size = lease->address.len;
+ options[i]->timeout = 0xFFFFFFFF;
+ } else
+ ip->client->requested_address.len = 0;
+
+ /* Send any options requested in the config file. */
+ for (i = 0; i < 256; i++)
+ if (!options[i] &&
+ ip->client->config->send_options[i].data) {
+ options[i] = &option_elements[i];
+ options[i]->value =
+ ip->client->config->send_options[i].data;
+ options[i]->len =
+ ip->client->config->send_options[i].len;
+ options[i]->buf_size =
+ ip->client->config->send_options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+ }
+
+ /* Set up the option buffer... */
+ ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
+ options, 0, 0, 0, NULL, 0);
+ if (ip->client->packet_length < BOOTP_MIN_LEN)
+ ip->client->packet_length = BOOTP_MIN_LEN;
+
+ ip->client->packet.op = BOOTREQUEST;
+ ip->client->packet.htype = ip->hw_address.htype;
+ ip->client->packet.hlen = ip->hw_address.hlen;
+ ip->client->packet.hops = 0;
+ ip->client->packet.xid = RtlRandom(&foo);
+ ip->client->packet.secs = 0; /* filled in by send_discover. */
+ ip->client->packet.flags = 0;
+
+ memset(&(ip->client->packet.ciaddr),
+ 0, sizeof(ip->client->packet.ciaddr));
+ memset(&(ip->client->packet.yiaddr),
+ 0, sizeof(ip->client->packet.yiaddr));
+ memset(&(ip->client->packet.siaddr),
+ 0, sizeof(ip->client->packet.siaddr));
+ memset(&(ip->client->packet.giaddr),
+ 0, sizeof(ip->client->packet.giaddr));
+ memcpy(ip->client->packet.chaddr,
+ ip->hw_address.haddr, ip->hw_address.hlen);
+}
+
+
+void
+make_request(struct interface_info *ip, struct client_lease * lease)
+{
+ unsigned char request = DHCPREQUEST;
+ struct tree_cache *options[256];
+ struct tree_cache option_elements[256];
+ int i;
+
+ memset(options, 0, sizeof(options));
+ memset(&ip->client->packet, 0, sizeof(ip->client->packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options[i] = &option_elements[i];
+ options[i]->value = &request;
+ options[i]->len = sizeof(request);
+ options[i]->buf_size = sizeof(request);
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Request the options we want */
+ i = DHO_DHCP_PARAMETER_REQUEST_LIST;
+ options[i] = &option_elements[i];
+ options[i]->value = ip->client->config->requested_options;
+ options[i]->len = ip->client->config->requested_option_count;
+ options[i]->buf_size =
+ ip->client->config->requested_option_count;
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* If we are requesting an address that hasn't yet been assigned
+ to us, use the DHCP Requested Address option. */
+ if (ip->client->state == S_REQUESTING) {
+ /* Send back the server identifier... */
+ i = DHO_DHCP_SERVER_IDENTIFIER;
+ options[i] = &option_elements[i];
+ options[i]->value = lease->options[i].data;
+ options[i]->len = lease->options[i].len;
+ options[i]->buf_size = lease->options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+ }
+ if (ip->client->state == S_REQUESTING ||
+ ip->client->state == S_REBOOTING) {
+ ip->client->requested_address = lease->address;
+ i = DHO_DHCP_REQUESTED_ADDRESS;
+ options[i] = &option_elements[i];
+ options[i]->value = lease->address.iabuf;
+ options[i]->len = lease->address.len;
+ options[i]->buf_size = lease->address.len;
+ options[i]->timeout = 0xFFFFFFFF;
+ } else
+ ip->client->requested_address.len = 0;
+
+ /* Send any options requested in the config file. */
+ for (i = 0; i < 256; i++)
+ if (!options[i] &&
+ ip->client->config->send_options[i].data) {
+ options[i] = &option_elements[i];
+ options[i]->value =
+ ip->client->config->send_options[i].data;
+ options[i]->len =
+ ip->client->config->send_options[i].len;
+ options[i]->buf_size =
+ ip->client->config->send_options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+ }
+
+ /* Set up the option buffer... */
+ ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
+ options, 0, 0, 0, NULL, 0);
+ if (ip->client->packet_length < BOOTP_MIN_LEN)
+ ip->client->packet_length = BOOTP_MIN_LEN;
+
+ ip->client->packet.op = BOOTREQUEST;
+ ip->client->packet.htype = ip->hw_address.htype;
+ ip->client->packet.hlen = ip->hw_address.hlen;
+ ip->client->packet.hops = 0;
+ ip->client->packet.xid = ip->client->xid;
+ ip->client->packet.secs = 0; /* Filled in by send_request. */
+
+ /* If we own the address we're requesting, put it in ciaddr;
+ otherwise set ciaddr to zero. */
+ if (ip->client->state == S_BOUND ||
+ ip->client->state == S_RENEWING ||
+ ip->client->state == S_REBINDING) {
+ memcpy(&ip->client->packet.ciaddr,
+ lease->address.iabuf, lease->address.len);
+ ip->client->packet.flags = 0;
+ } else {
+ memset(&ip->client->packet.ciaddr, 0,
+ sizeof(ip->client->packet.ciaddr));
+ ip->client->packet.flags = 0;
+ }
+
+ memset(&ip->client->packet.yiaddr, 0,
+ sizeof(ip->client->packet.yiaddr));
+ memset(&ip->client->packet.siaddr, 0,
+ sizeof(ip->client->packet.siaddr));
+ memset(&ip->client->packet.giaddr, 0,
+ sizeof(ip->client->packet.giaddr));
+ memcpy(ip->client->packet.chaddr,
+ ip->hw_address.haddr, ip->hw_address.hlen);
+}
+
+void
+make_decline(struct interface_info *ip, struct client_lease *lease)
+{
+ struct tree_cache *options[256], message_type_tree;
+ struct tree_cache requested_address_tree;
+ struct tree_cache server_id_tree, client_id_tree;
+ unsigned char decline = DHCPDECLINE;
+ int i;
+
+ memset(options, 0, sizeof(options));
+ memset(&ip->client->packet, 0, sizeof(ip->client->packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options[i] = &message_type_tree;
+ options[i]->value = &decline;
+ options[i]->len = sizeof(decline);
+ options[i]->buf_size = sizeof(decline);
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Send back the server identifier... */
+ i = DHO_DHCP_SERVER_IDENTIFIER;
+ options[i] = &server_id_tree;
+ options[i]->value = lease->options[i].data;
+ options[i]->len = lease->options[i].len;
+ options[i]->buf_size = lease->options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Send back the address we're declining. */
+ i = DHO_DHCP_REQUESTED_ADDRESS;
+ options[i] = &requested_address_tree;
+ options[i]->value = lease->address.iabuf;
+ options[i]->len = lease->address.len;
+ options[i]->buf_size = lease->address.len;
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Send the uid if the user supplied one. */
+ i = DHO_DHCP_CLIENT_IDENTIFIER;
+ if (ip->client->config->send_options[i].len) {
+ options[i] = &client_id_tree;
+ options[i]->value = ip->client->config->send_options[i].data;
+ options[i]->len = ip->client->config->send_options[i].len;
+ options[i]->buf_size = ip->client->config->send_options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+ }
+
+
+ /* Set up the option buffer... */
+ ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
+ options, 0, 0, 0, NULL, 0);
+ if (ip->client->packet_length < BOOTP_MIN_LEN)
+ ip->client->packet_length = BOOTP_MIN_LEN;
+
+ ip->client->packet.op = BOOTREQUEST;
+ ip->client->packet.htype = ip->hw_address.htype;
+ ip->client->packet.hlen = ip->hw_address.hlen;
+ ip->client->packet.hops = 0;
+ ip->client->packet.xid = ip->client->xid;
+ ip->client->packet.secs = 0; /* Filled in by send_request. */
+ ip->client->packet.flags = 0;
+
+ /* ciaddr must always be zero. */
+ memset(&ip->client->packet.ciaddr, 0,
+ sizeof(ip->client->packet.ciaddr));
+ memset(&ip->client->packet.yiaddr, 0,
+ sizeof(ip->client->packet.yiaddr));
+ memset(&ip->client->packet.siaddr, 0,
+ sizeof(ip->client->packet.siaddr));
+ memset(&ip->client->packet.giaddr, 0,
+ sizeof(ip->client->packet.giaddr));
+ memcpy(ip->client->packet.chaddr,
+ ip->hw_address.haddr, ip->hw_address.hlen);
+}
+
+void
+free_client_lease(struct client_lease *lease)
+{
+ int i;
+
+ if (lease->server_name)
+ free(lease->server_name);
+ if (lease->filename)
+ free(lease->filename);
+ for (i = 0; i < 256; i++) {
+ if (lease->options[i].len)
+ free(lease->options[i].data);
+ }
+ free(lease);
+}
+
+FILE *leaseFile;
+
+void
+rewrite_client_leases(struct interface_info *ifi)
+{
+ struct client_lease *lp;
+
+ if (!leaseFile) {
+ leaseFile = fopen(path_dhclient_db, "w");
+ if (!leaseFile)
+ error("can't create %s", path_dhclient_db);
+ } else {
+ fflush(leaseFile);
+ rewind(leaseFile);
+ }
+
+ for (lp = ifi->client->leases; lp; lp = lp->next)
+ write_client_lease(ifi, lp, 1);
+ if (ifi->client->active)
+ write_client_lease(ifi, ifi->client->active, 1);
+
+ fflush(leaseFile);
+}
+
+void
+write_client_lease(struct interface_info *ip, struct client_lease *lease,
+ int rewrite)
+{
+ static int leases_written;
+ struct tm *t;
+ int i;
+
+ if (!rewrite) {
+ if (leases_written++ > 20) {
+ rewrite_client_leases(ip);
+ leases_written = 0;
+ }
+ }
+
+ /* If the lease came from the config file, we don't need to stash
+ a copy in the lease database. */
+ if (lease->is_static)
+ return;
+
+ if (!leaseFile) { /* XXX */
+ leaseFile = fopen(path_dhclient_db, "w");
+ if (!leaseFile) {
+ error("can't create %s", path_dhclient_db);
+ return;
+ }
+ }
+
+ fprintf(leaseFile, "lease {\n");
+ if (lease->is_bootp)
+ fprintf(leaseFile, " bootp;\n");
+ fprintf(leaseFile, " interface \"%s\";\n", ip->name);
+ fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
+ if (lease->filename)
+ fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
+ if (lease->server_name)
+ fprintf(leaseFile, " server-name \"%s\";\n",
+ lease->server_name);
+ if (lease->medium)
+ fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
+ for (i = 0; i < 256; i++)
+ if (lease->options[i].len)
+ fprintf(leaseFile, " option %s %s;\n",
+ dhcp_options[i].name,
+ pretty_print_option(i, lease->options[i].data,
+ lease->options[i].len, 1, 1));
+
+ t = gmtime(&lease->renewal);
+ if (t)
+ fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
+ t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ t = gmtime(&lease->rebind);
+ if (t)
+ fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
+ t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ t = gmtime(&lease->expiry);
+ if (t)
+ fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
+ t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ fprintf(leaseFile, "}\n");
+ fflush(leaseFile);
+}
+
+void
+priv_script_init(struct interface_info *ip, char *reason, char *medium)
+{
+ if (ip) {
+ // XXX Do we need to do anything?
+ }
+}
+
+void
+priv_script_write_params(struct interface_info *ip, char *prefix, struct client_lease *lease)
+{
+ u_int8_t dbuf[1500];
+ int i, len = 0;
+
+#if 0
+ script_set_env(ip->client, prefix, "ip_address",
+ piaddr(lease->address));
+#endif
+
+ if (lease->options[DHO_SUBNET_MASK].len &&
+ (lease->options[DHO_SUBNET_MASK].len <
+ sizeof(lease->address.iabuf))) {
+ struct iaddr netmask, subnet, broadcast;
+
+ memcpy(netmask.iabuf, lease->options[DHO_SUBNET_MASK].data,
+ lease->options[DHO_SUBNET_MASK].len);
+ netmask.len = lease->options[DHO_SUBNET_MASK].len;
+
+ subnet = subnet_number(lease->address, netmask);
+ if (subnet.len) {
+#if 0
+ script_set_env(ip->client, prefix, "network_number",
+ piaddr(subnet));
+#endif
+ if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
+ broadcast = broadcast_addr(subnet, netmask);
+ if (broadcast.len)
+#if 0
+ script_set_env(ip->client, prefix,
+ "broadcast_address",
+ piaddr(broadcast));
+#else
+ ;
+#endif
+ }
+ }
+ }
+
+#if 0
+ if (lease->filename)
+ script_set_env(ip->client, prefix, "filename", lease->filename);
+ if (lease->server_name)
+ script_set_env(ip->client, prefix, "server_name",
+ lease->server_name);
+#endif
+
+ for (i = 0; i < 256; i++) {
+ u_int8_t *dp = NULL;
+
+ if (ip->client->config->defaults[i].len) {
+ if (lease->options[i].len) {
+ switch (
+ ip->client->config->default_actions[i]) {
+ case ACTION_DEFAULT:
+ dp = lease->options[i].data;
+ len = lease->options[i].len;
+ break;
+ case ACTION_SUPERSEDE:
+supersede:
+ dp = ip->client->
+ config->defaults[i].data;
+ len = ip->client->
+ config->defaults[i].len;
+ break;
+ case ACTION_PREPEND:
+ len = ip->client->
+ config->defaults[i].len +
+ lease->options[i].len;
+ if (len >= sizeof(dbuf)) {
+ warning("no space to %s %s",
+ "prepend option",
+ dhcp_options[i].name);
+ goto supersede;
+ }
+ dp = dbuf;
+ memcpy(dp,
+ ip->client->
+ config->defaults[i].data,
+ ip->client->
+ config->defaults[i].len);
+ memcpy(dp + ip->client->
+ config->defaults[i].len,
+ lease->options[i].data,
+ lease->options[i].len);
+ dp[len] = '\0';
+ break;
+ case ACTION_APPEND:
+ len = ip->client->
+ config->defaults[i].len +
+ lease->options[i].len + 1;
+ if (len > sizeof(dbuf)) {
+ warning("no space to %s %s",
+ "append option",
+ dhcp_options[i].name);
+ goto supersede;
+ }
+ dp = dbuf;
+ memcpy(dp,
+ lease->options[i].data,
+ lease->options[i].len);
+ memcpy(dp + lease->options[i].len,
+ ip->client->
+ config->defaults[i].data,
+ ip->client->
+ config->defaults[i].len);
+ dp[len-1] = '\0';
+ }
+ } else {
+ dp = ip->client->
+ config->defaults[i].data;
+ len = ip->client->
+ config->defaults[i].len;
+ }
+ } else if (lease->options[i].len) {
+ len = lease->options[i].len;
+ dp = lease->options[i].data;
+ } else {
+ len = 0;
+ }
+#if 0
+ if (len) {
+ char name[256];
+
+ if (dhcp_option_ev_name(name, sizeof(name),
+ &dhcp_options[i]))
+ script_set_env(ip->client, prefix, name,
+ pretty_print_option(i, dp, len, 0, 0));
+ }
+#endif
+ }
+#if 0
+ snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
+ script_set_env(ip->client, prefix, "expiry", tbuf);
+#endif
+}
+
+int
+dhcp_option_ev_name(char *buf, size_t buflen, struct dhcp_option *option)
+{
+ int i;
+
+ for (i = 0; option->name[i]; i++) {
+ if (i + 1 == buflen)
+ return 0;
+ if (option->name[i] == '-')
+ buf[i] = '_';
+ else
+ buf[i] = option->name[i];
+ }
+
+ buf[i] = 0;
+ return 1;
+}
+
+#if 0
+void
+go_daemon(void)
+{
+ static int state = 0;
+
+ if (no_daemon || state)
+ return;
+
+ state = 1;
+
+ /* Stop logging to stderr... */
+ log_perror = 0;
+
+ if (daemon(1, 0) == -1)
+ error("daemon");
+
+ /* we are chrooted, daemon(3) fails to open /dev/null */
+ if (nullfd != -1) {
+ dup2(nullfd, STDIN_FILENO);
+ dup2(nullfd, STDOUT_FILENO);
+ dup2(nullfd, STDERR_FILENO);
+ close(nullfd);
+ nullfd = -1;
+ }
+}
+#endif
+
+int
+check_option(struct client_lease *l, int option)
+{
+ char *opbuf;
+ char *sbuf;
+
+ /* we use this, since this is what gets passed to dhclient-script */
+
+ opbuf = pretty_print_option(option, l->options[option].data,
+ l->options[option].len, 0, 0);
+
+ sbuf = option_as_string(option, l->options[option].data,
+ l->options[option].len);
+
+ switch (option) {
+ case DHO_SUBNET_MASK:
+ case DHO_TIME_SERVERS:
+ case DHO_NAME_SERVERS:
+ case DHO_ROUTERS:
+ case DHO_DOMAIN_NAME_SERVERS:
+ case DHO_LOG_SERVERS:
+ case DHO_COOKIE_SERVERS:
+ case DHO_LPR_SERVERS:
+ case DHO_IMPRESS_SERVERS:
+ case DHO_RESOURCE_LOCATION_SERVERS:
+ case DHO_SWAP_SERVER:
+ case DHO_BROADCAST_ADDRESS:
+ case DHO_NIS_SERVERS:
+ case DHO_NTP_SERVERS:
+ case DHO_NETBIOS_NAME_SERVERS:
+ case DHO_NETBIOS_DD_SERVER:
+ case DHO_FONT_SERVERS:
+ case DHO_DHCP_SERVER_IDENTIFIER:
+ if (!ipv4addrs(opbuf)) {
+ warning("Invalid IP address in option(%d): %s", option, opbuf);
+ return (0);
+ }
+ return (1) ;
+ case DHO_HOST_NAME:
+ case DHO_DOMAIN_NAME:
+ case DHO_NIS_DOMAIN:
+ if (!res_hnok(sbuf))
+ warning("Bogus Host Name option %d: %s (%s)", option,
+ sbuf, opbuf);
+ return (1);
+ case DHO_PAD:
+ case DHO_TIME_OFFSET:
+ case DHO_BOOT_SIZE:
+ case DHO_MERIT_DUMP:
+ case DHO_ROOT_PATH:
+ case DHO_EXTENSIONS_PATH:
+ case DHO_IP_FORWARDING:
+ case DHO_NON_LOCAL_SOURCE_ROUTING:
+ case DHO_POLICY_FILTER:
+ case DHO_MAX_DGRAM_REASSEMBLY:
+ case DHO_DEFAULT_IP_TTL:
+ case DHO_PATH_MTU_AGING_TIMEOUT:
+ case DHO_PATH_MTU_PLATEAU_TABLE:
+ case DHO_INTERFACE_MTU:
+ case DHO_ALL_SUBNETS_LOCAL:
+ case DHO_PERFORM_MASK_DISCOVERY:
+ case DHO_MASK_SUPPLIER:
+ case DHO_ROUTER_DISCOVERY:
+ case DHO_ROUTER_SOLICITATION_ADDRESS:
+ case DHO_STATIC_ROUTES:
+ case DHO_TRAILER_ENCAPSULATION:
+ case DHO_ARP_CACHE_TIMEOUT:
+ case DHO_IEEE802_3_ENCAPSULATION:
+ case DHO_DEFAULT_TCP_TTL:
+ case DHO_TCP_KEEPALIVE_INTERVAL:
+ case DHO_TCP_KEEPALIVE_GARBAGE:
+ case DHO_VENDOR_ENCAPSULATED_OPTIONS:
+ case DHO_NETBIOS_NODE_TYPE:
+ case DHO_NETBIOS_SCOPE:
+ case DHO_X_DISPLAY_MANAGER:
+ case DHO_DHCP_REQUESTED_ADDRESS:
+ case DHO_DHCP_LEASE_TIME:
+ case DHO_DHCP_OPTION_OVERLOAD:
+ case DHO_DHCP_MESSAGE_TYPE:
+ case DHO_DHCP_PARAMETER_REQUEST_LIST:
+ case DHO_DHCP_MESSAGE:
+ case DHO_DHCP_MAX_MESSAGE_SIZE:
+ case DHO_DHCP_RENEWAL_TIME:
+ case DHO_DHCP_REBINDING_TIME:
+ case DHO_DHCP_CLASS_IDENTIFIER:
+ case DHO_DHCP_CLIENT_IDENTIFIER:
+ case DHO_DHCP_USER_CLASS_ID:
+ case DHO_END:
+ return (1);
+ default:
+ warning("unknown dhcp option value 0x%x", option);
+ return (unknown_ok);
+ }
+}
+
+int
+res_hnok(const char *dn)
+{
+ int pch = PERIOD, ch = *dn++;
+
+ while (ch != '\0') {
+ int nch = *dn++;
+
+ if (periodchar(ch)) {
+ ;
+ } else if (periodchar(pch)) {
+ if (!borderchar(ch))
+ return (0);
+ } else if (periodchar(nch) || nch == '\0') {
+ if (!borderchar(ch))
+ return (0);
+ } else {
+ if (!middlechar(ch))
+ return (0);
+ }
+ pch = ch, ch = nch;
+ }
+ return (1);
+}
+
+/* Does buf consist only of dotted decimal ipv4 addrs?
+ * return how many if so,
+ * otherwise, return 0
+ */
+int
+ipv4addrs(char * buf)
+{
+ char *tmp;
+ struct in_addr jnk;
+ int i = 0;
+
+ note("Input: %s", buf);
+
+ do {
+ tmp = strtok(buf, " ");
+ note("got %s", tmp);
+ if( tmp && inet_aton(tmp, &jnk) ) i++;
+ buf = NULL;
+ } while( tmp );
+
+ return (i);
+}
+
+
+char *
+option_as_string(unsigned int code, unsigned char *data, int len)
+{
+ static char optbuf[32768]; /* XXX */
+ char *op = optbuf;
+ int opleft = sizeof(optbuf);
+ unsigned char *dp = data;
+
+ if (code > 255)
+ error("option_as_string: bad code %d", code);
+
+ for (; dp < data + len; dp++) {
+ if (!isascii(*dp) || !isprint(*dp)) {
+ if (dp + 1 != data + len || *dp != 0) {
+ _snprintf(op, opleft, "\\%03o", *dp);
+ op += 4;
+ opleft -= 4;
+ }
+ } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
+ *dp == '`' || *dp == '\\') {
+ *op++ = '\\';
+ *op++ = *dp;
+ opleft -= 2;
+ } else {
+ *op++ = *dp;
+ opleft--;
+ }
+ }
+ if (opleft < 1)
+ goto toobig;
+ *op = 0;
+ return optbuf;
+toobig:
+ warning("dhcp option too large");
+ return "<error>";
+}
+
* COPYRIGHT: Copyright 2005 Art Yerkes <ayerkes@speakeasy.net>
*/
-#include <winsock2.h>
-#include <dhcpcsdk.h>
-#include <time.h>
-#include <dhcp/rosdhcp_public.h>
+#include <rosdhcp.h>
#define NDEBUG
#include <debug.h>
-#define DHCP_TIMEOUT 1000
+static HANDLE PipeHandle = INVALID_HANDLE_VALUE;
DWORD APIENTRY DhcpCApiInitialize(LPDWORD Version) {
- *Version = 2;
- return 0;
+ DWORD PipeMode;
+
+ /* Wait for the pipe to be available */
+ if (WaitNamedPipeW(DHCP_PIPE_NAME, NMPWAIT_USE_DEFAULT_WAIT))
+ {
+ /* It's available, let's try to open it */
+ PipeHandle = CreateFileW(DHCP_PIPE_NAME,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+
+ /* Check if we succeeded in opening the pipe */
+ if (PipeHandle == INVALID_HANDLE_VALUE)
+ {
+ /* We didn't */
+ return GetLastError();
+ }
+ else
+ {
+ /* Change the pipe into message mode */
+ PipeMode = PIPE_READMODE_MESSAGE;
+ if (!SetNamedPipeHandleState(PipeHandle, &PipeMode, NULL, NULL))
+ {
+ /* Mode change failed */
+ CloseHandle(PipeHandle);
+ PipeHandle = INVALID_HANDLE_VALUE;
+ return GetLastError();
+ }
+ else
+ {
+ /* We're good to go */
+ *Version = 2;
+ return NO_ERROR;
+ }
+ }
+ }
+ else
+ {
+ /* No good, we failed */
+ return GetLastError();
+ }
}
VOID APIENTRY DhcpCApiCleanup() {
+ CloseHandle(PipeHandle);
+ PipeHandle = INVALID_HANDLE_VALUE;
}
DWORD APIENTRY DhcpQueryHWInfo( DWORD AdapterIndex,
DWORD BytesRead;
BOOL Result;
+ ASSERT(PipeHandle != INVALID_HANDLE_VALUE);
+
Req.Type = DhcpReqQueryHWInfo;
Req.AdapterIndex = AdapterIndex;
- Result = CallNamedPipeW
- ( DHCP_PIPE_NAME, &Req, sizeof(Req), &Reply, sizeof(Reply),
- &BytesRead, DHCP_TIMEOUT );
+ Result = TransactNamedPipe(PipeHandle,
+ &Req, sizeof(Req),
+ &Reply, sizeof(Reply),
+ &BytesRead, NULL);
+ if (!Result)
+ {
+ /* Pipe transaction failed */
+ return 0;
+ }
if( !Reply.Reply ) return 0;
else {
DWORD BytesRead;
BOOL Result;
+ ASSERT(PipeHandle != INVALID_HANDLE_VALUE);
+
Req.Type = DhcpReqLeaseIpAddress;
Req.AdapterIndex = AdapterIndex;
- Result = CallNamedPipeW
- ( DHCP_PIPE_NAME, &Req, sizeof(Req), &Reply, sizeof(Reply),
- &BytesRead, DHCP_TIMEOUT );
+ Result = TransactNamedPipe(PipeHandle,
+ &Req, sizeof(Req),
+ &Reply, sizeof(Reply),
+ &BytesRead, NULL);
+ if (!Result)
+ {
+ /* Pipe transaction failed */
+ return 0;
+ }
return Reply.Reply;
}
DWORD BytesRead;
BOOL Result;
+ ASSERT(PipeHandle != INVALID_HANDLE_VALUE);
+
Req.Type = DhcpReqReleaseIpAddress;
Req.AdapterIndex = AdapterIndex;
- Result = CallNamedPipeW
- ( DHCP_PIPE_NAME, &Req, sizeof(Req), &Reply, sizeof(Reply),
- &BytesRead, DHCP_TIMEOUT );
+ Result = TransactNamedPipe(PipeHandle,
+ &Req, sizeof(Req),
+ &Reply, sizeof(Reply),
+ &BytesRead, NULL);
+ if (!Result)
+ {
+ /* Pipe transaction failed */
+ return 0;
+ }
return Reply.Reply;
}
DWORD BytesRead;
BOOL Result;
+ ASSERT(PipeHandle != INVALID_HANDLE_VALUE);
+
Req.Type = DhcpReqRenewIpAddress;
Req.AdapterIndex = AdapterIndex;
- Result = CallNamedPipeW
- ( DHCP_PIPE_NAME, &Req, sizeof(Req), &Reply, sizeof(Reply),
- &BytesRead, DHCP_TIMEOUT );
+ Result = TransactNamedPipe(PipeHandle,
+ &Req, sizeof(Req),
+ &Reply, sizeof(Reply),
+ &BytesRead, NULL);
+ if (!Result)
+ {
+ /* Pipe transaction failed */
+ return 0;
+ }
return Reply.Reply;
}
DWORD BytesRead;
BOOL Result;
+ ASSERT(PipeHandle != INVALID_HANDLE_VALUE);
+
Req.Type = DhcpReqStaticRefreshParams;
Req.AdapterIndex = AdapterIndex;
Req.Body.StaticRefreshParams.IPAddress = Address;
Req.Body.StaticRefreshParams.Netmask = Netmask;
- Result = CallNamedPipeW
- ( DHCP_PIPE_NAME, &Req, sizeof(Req), &Reply, sizeof(Reply),
- &BytesRead, DHCP_TIMEOUT );
+ Result = TransactNamedPipe(PipeHandle,
+ &Req, sizeof(Req),
+ &Reply, sizeof(Reply),
+ &BytesRead, NULL);
+ if (!Result)
+ {
+ /* Pipe transaction failed */
+ return 0;
+ }
return Reply.Reply;
}
DWORD SubnetMask,
int DhcpAction)
{
- DPRINT1("DhcpNotifyConfigChange not implemented yet\n");
+ DbgPrint("DHCPCSVC: DhcpNotifyConfigChange not implemented yet\n");
return 0;
}
DWORD BytesRead;
BOOL Result;
+ ASSERT(PipeHandle != INVALID_HANDLE_VALUE);
+
Req.Type = DhcpReqGetAdapterInfo;
Req.AdapterIndex = AdapterIndex;
- Result = CallNamedPipeW
- ( DHCP_PIPE_NAME, &Req, sizeof(Req), &Reply, sizeof(Reply),
- &BytesRead, DHCP_TIMEOUT );
+ Result = TransactNamedPipe(PipeHandle,
+ &Req, sizeof(Req),
+ &Reply, sizeof(Reply),
+ &BytesRead, NULL);
if ( 0 != Result && 0 != Reply.Reply ) {
*DhcpEnabled = Reply.GetAdapterInfo.DhcpEnabled;
<importlibrary definition="dhcpcsvc.spec" />
<include base="dhcpcsvc">include</include>
<library>ntdll</library>
+ <library>msvcrt</library>
<library>ws2_32</library>
<library>iphlpapi</library>
+ <library>advapi32</library>
+ <library>oldnames</library>
+ <file>adapter.c</file>
+ <file>alloc.c</file>
+ <file>api.c</file>
+ <file>compat.c</file>
+ <file>dhclient.c</file>
<file>dhcpcsvc.c</file>
<file>dhcpcsvc.rc</file>
+ <file>dispatch.c</file>
+ <file>hash.c</file>
+ <file>options.c</file>
+ <file>pipe.c</file>
+ <file>socket.c</file>
+ <file>tables.c</file>
+ <file>util.c</file>
+ <directory name="include">
+ <pch>rosdhcp.h</pch>
+ </directory>
</module>
@ stub McastRenewAddress
@ stub McastRequestAddress
@ stdcall DhcpRosGetAdapterInfo(long ptr ptr ptr ptr)
-# The Windows DHCP client service is implemented in the DLL too
-#@ stub ServiceMain
+@ stdcall ServiceMain(long ptr)
--- /dev/null
+/* $OpenBSD: dispatch.c,v 1.31 2004/09/21 04:07:03 david 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''.
+ */
+
+#include "rosdhcp.h"
+#include "dhcpd.h"
+//#include <sys/ioctl.h>
+
+//#include <net/if_media.h>
+//#include <ifaddrs.h>
+//#include <poll.h>
+
+struct protocol *protocols = NULL;
+struct timeout *timeouts = NULL;
+static struct timeout *free_timeouts = NULL;
+void (*bootp_packet_handler)(struct interface_info *,
+ struct dhcp_packet *, int, unsigned int,
+ struct iaddr, struct hardware *);
+
+/*
+ * Wait for packets to come in using poll(). When a packet comes in,
+ * call receive_packet to receive the packet and possibly strip hardware
+ * addressing information from it, and then call through the
+ * bootp_packet_handler hook to try to do something with it.
+ */
+void
+dispatch(void)
+{
+ int count, to_msec, err;
+ struct protocol *l;
+ fd_set fds;
+ time_t howlong, cur_time;
+ struct timeval timeval;
+
+ if (!AdapterDiscover())
+ return;
+
+ ApiLock();
+
+ do {
+ /*
+ * Call any expired timeouts, and then if there's still
+ * a timeout registered, time out the select call then.
+ */
+ time(&cur_time);
+
+ if (timeouts) {
+ struct timeout *t;
+
+ if (timeouts->when <= cur_time) {
+ t = timeouts;
+ timeouts = timeouts->next;
+ (*(t->func))(t->what);
+ t->next = free_timeouts;
+ free_timeouts = t;
+ continue;
+ }
+
+ /*
+ * Figure timeout in milliseconds, and check for
+ * potential overflow, so we can cram into an
+ * int for poll, while not polling with a
+ * negative timeout and blocking indefinitely.
+ */
+ howlong = timeouts->when - cur_time;
+ if (howlong > INT_MAX / 1000)
+ howlong = INT_MAX / 1000;
+ to_msec = howlong * 1000;
+ } else
+ to_msec = 5000;
+
+ /* Set up the descriptors to be polled. */
+ FD_ZERO(&fds);
+
+ for (l = protocols; l; l = l->next)
+ FD_SET(l->fd, &fds);
+
+ /* Wait for a packet or a timeout... XXX */
+ timeval.tv_sec = to_msec / 1000;
+ timeval.tv_usec = to_msec % 1000;
+
+ ApiUnlock();
+
+ if (protocols)
+ count = select(0, &fds, NULL, NULL, &timeval);
+ else {
+ Sleep(to_msec);
+ count = 0;
+ }
+
+ ApiLock();
+
+ DH_DbgPrint(MID_TRACE,("Select: %d\n", count));
+
+ /* Not likely to be transitory... */
+ if (count == SOCKET_ERROR) {
+ err = WSAGetLastError();
+ error("poll: %d", err);
+ break;
+ }
+
+ for (l = protocols; l; l = l->next) {
+ struct interface_info *ip;
+ ip = l->local;
+ if (FD_ISSET(l->fd, &fds)) {
+ if (ip && (l->handler != got_one ||
+ !ip->dead)) {
+ DH_DbgPrint(MID_TRACE,("Handling %x\n", l));
+ (*(l->handler))(l);
+ }
+ }
+ }
+ } while (1);
+
+ ApiUnlock();
+}
+
+void
+got_one(struct protocol *l)
+{
+ struct sockaddr_in from;
+ struct hardware hfrom;
+ struct iaddr ifrom;
+ ssize_t result;
+ union {
+ /*
+ * Packet input buffer. Must be as large as largest
+ * possible MTU.
+ */
+ unsigned char packbuf[4095];
+ struct dhcp_packet packet;
+ } u;
+ struct interface_info *ip = l->local;
+ PDHCP_ADAPTER adapter;
+
+ if ((result = receive_packet(ip, u.packbuf, sizeof(u), &from,
+ &hfrom)) == -1) {
+ warning("receive_packet failed on %s: %d", ip->name,
+ WSAGetLastError());
+ ip->errors++;
+ if (ip->errors > 20) {
+ /* our interface has gone away. */
+ warning("Interface %s no longer appears valid.",
+ ip->name);
+ ip->dead = 1;
+ closesocket(l->fd);
+ remove_protocol(l);
+ adapter = AdapterFindInfo(ip);
+ if (adapter) {
+ RemoveEntryList(&adapter->ListEntry);
+ free(adapter);
+ }
+ }
+ return;
+ }
+ if (result == 0)
+ return;
+
+ if (bootp_packet_handler) {
+ ifrom.len = 4;
+ memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len);
+
+
+ adapter = AdapterFindByHardwareAddress(u.packet.chaddr,
+ u.packet.hlen);
+
+ if (!adapter) {
+ warning("Discarding packet with a non-matching target physical address\n");
+ return;
+ }
+
+ (*bootp_packet_handler)(&adapter->DhclientInfo, &u.packet, result,
+ from.sin_port, ifrom, &hfrom);
+ }
+}
+
+void
+add_timeout(time_t when, void (*where)(void *), void *what)
+{
+ struct timeout *t, *q;
+
+ DH_DbgPrint(MID_TRACE,("Adding timeout %x %p %x\n", when, where, what));
+ /* See if this timeout supersedes an existing timeout. */
+ t = NULL;
+ for (q = timeouts; q; q = q->next) {
+ if (q->func == where && q->what == what) {
+ if (t)
+ t->next = q->next;
+ else
+ timeouts = q->next;
+ break;
+ }
+ t = q;
+ }
+
+ /* If we didn't supersede a timeout, allocate a timeout
+ structure now. */
+ if (!q) {
+ if (free_timeouts) {
+ q = free_timeouts;
+ free_timeouts = q->next;
+ q->func = where;
+ q->what = what;
+ } else {
+ q = malloc(sizeof(struct timeout));
+ if (!q) {
+ error("Can't allocate timeout structure!");
+ return;
+ }
+ q->func = where;
+ q->what = what;
+ }
+ }
+
+ q->when = when;
+
+ /* Now sort this timeout into the timeout list. */
+
+ /* Beginning of list? */
+ if (!timeouts || timeouts->when > q->when) {
+ q->next = timeouts;
+ timeouts = q;
+ return;
+ }
+
+ /* Middle of list? */
+ for (t = timeouts; t->next; t = t->next) {
+ if (t->next->when > q->when) {
+ q->next = t->next;
+ t->next = q;
+ return;
+ }
+ }
+
+ /* End of list. */
+ t->next = q;
+ q->next = NULL;
+}
+
+void
+cancel_timeout(void (*where)(void *), void *what)
+{
+ struct timeout *t, *q;
+
+ /* Look for this timeout on the list, and unlink it if we find it. */
+ t = NULL;
+ for (q = timeouts; q; q = q->next) {
+ if (q->func == where && q->what == what) {
+ if (t)
+ t->next = q->next;
+ else
+ timeouts = q->next;
+ break;
+ }
+ t = q;
+ }
+
+ /* If we found the timeout, put it on the free list. */
+ if (q) {
+ q->next = free_timeouts;
+ free_timeouts = q;
+ }
+}
+
+/* Add a protocol to the list of protocols... */
+void
+add_protocol(char *name, int fd, void (*handler)(struct protocol *),
+ void *local)
+{
+ struct protocol *p;
+
+ p = malloc(sizeof(*p));
+ if (!p)
+ error("can't allocate protocol struct for %s", name);
+
+ p->fd = fd;
+ p->handler = handler;
+ p->local = local;
+ p->next = protocols;
+ protocols = p;
+}
+
+void
+remove_protocol(struct protocol *proto)
+{
+ struct protocol *p, *next, *prev;
+
+ prev = NULL;
+ for (p = protocols; p; p = next) {
+ next = p->next;
+ if (p == proto) {
+ if (prev)
+ prev->next = p->next;
+ else
+ protocols = p->next;
+ free(p);
+ }
+ }
+}
+
+struct protocol *
+find_protocol_by_adapter(struct interface_info *info)
+{
+ struct protocol *p;
+
+ for( p = protocols; p; p = p->next ) {
+ if( p->local == (void *)info ) return p;
+ }
+
+ return NULL;
+}
+
+int
+interface_link_status(char *ifname)
+{
+ return (1);
+}
--- /dev/null
+/* hash.c
+
+ Routines for manipulating hash tables... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 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''.
+ */
+
+#define lint
+#ifndef lint
+static char copyright[] =
+"$Id: hash.c,v 1.9.2.3 1999/04/09 17:39:41 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "rosdhcp.h"
+
+static __inline int do_hash PROTO ((unsigned char *, int, int));
+
+struct hash_table *new_hash ()
+{
+ struct hash_table *rv = new_hash_table (DEFAULT_HASH_SIZE);
+ if (!rv)
+ return rv;
+ memset (&rv -> buckets [0], 0,
+ DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *));
+ return rv;
+}
+
+static __inline int do_hash (name, len, size)
+ unsigned char *name;
+ int len;
+ int size;
+{
+ register int accum = 0;
+ register unsigned char *s = name;
+ int i = len;
+ while (i--) {
+ /* Add the character in... */
+ accum += *s++;
+ /* Add carry back in... */
+ while (accum > 255) {
+ accum = (accum & 255) + (accum >> 8);
+ }
+ }
+ return accum % size;
+}
+
+void add_hash (table, name, len, pointer)
+ struct hash_table *table;
+ int len;
+ unsigned char *name;
+ unsigned char *pointer;
+{
+ int hashno;
+ struct hash_bucket *bp;
+
+ if (!table)
+ return;
+ if (!len)
+ len = strlen ((char *)name);
+
+ hashno = do_hash (name, len, table -> hash_count);
+ bp = new_hash_bucket ();
+
+ if (!bp) {
+ warn ("Can't add %s to hash table.", name);
+ return;
+ }
+ bp -> name = name;
+ bp -> value = pointer;
+ bp -> next = table -> buckets [hashno];
+ bp -> len = len;
+ table -> buckets [hashno] = bp;
+}
+
+void delete_hash_entry (table, name, len)
+ struct hash_table *table;
+ int len;
+ unsigned char *name;
+{
+ int hashno;
+ struct hash_bucket *bp, *pbp = (struct hash_bucket *)0;
+
+ if (!table)
+ return;
+ if (!len)
+ len = strlen ((char *)name);
+
+ hashno = do_hash (name, len, table -> hash_count);
+
+ /* Go through the list looking for an entry that matches;
+ if we find it, delete it. */
+ for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
+ if ((!bp -> len &&
+ !strcmp ((char *)bp -> name, (char *)name)) ||
+ (bp -> len == len &&
+ !memcmp (bp -> name, name, len))) {
+ if (pbp) {
+ pbp -> next = bp -> next;
+ } else {
+ table -> buckets [hashno] = bp -> next;
+ }
+ free_hash_bucket (bp, "delete_hash_entry");
+ break;
+ }
+ pbp = bp; /* jwg, 9/6/96 - nice catch! */
+ }
+}
+
+unsigned char *hash_lookup (table, name, len)
+ struct hash_table *table;
+ unsigned char *name;
+ int len;
+{
+ int hashno;
+ struct hash_bucket *bp;
+
+ if (!table)
+ return (unsigned char *)0;
+
+ if (!len)
+ len = strlen ((char *)name);
+
+ hashno = do_hash (name, len, table -> hash_count);
+
+ for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
+ if (len == bp -> len && !memcmp (bp -> name, name, len))
+ return bp -> value;
+ }
+ return (unsigned char *)0;
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS TCP/IP protocol driver
+ * FILE: include/debug.h
+ * PURPOSE: Debugging support macros
+ * DEFINES: DBG - Enable debug output
+ * NASSERT - Disable assertions
+ */
+
+#pragma once
+
+#define NORMAL_MASK 0x000000FF
+#define SPECIAL_MASK 0xFFFFFF00
+#define MIN_TRACE 0x00000001
+#define MID_TRACE 0x00000002
+#define MAX_TRACE 0x00000003
+
+#define DEBUG_ADAPTER 0x00000100
+#define DEBUG_ULTRA 0xFFFFFFFF
+
+#if DBG
+
+extern unsigned long debug_trace_level;
+
+#ifdef _MSC_VER
+
+#define DH_DbgPrint(_t_, _x_) \
+ if (((debug_trace_level & NORMAL_MASK) >= _t_) || \
+ ((debug_trace_level & _t_) > NORMAL_MASK)) { \
+ DbgPrint("(%s:%d) ", __FILE__, __LINE__); \
+ DbgPrint _x_ ; \
+ }
+
+#else /* _MSC_VER */
+
+#define DH_DbgPrint(_t_, _x_) \
+ if (((debug_trace_level & NORMAL_MASK) >= _t_) || \
+ ((debug_trace_level & _t_) > NORMAL_MASK)) { \
+ DbgPrint("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \
+ DbgPrint _x_ ; \
+ }
+
+#endif /* _MSC_VER */
+
+#else /* DBG */
+
+#define DH_DbgPrint(_t_, _x_)
+
+#endif /* DBG */
+
+/* EOF */
--- /dev/null
+/* $OpenBSD: dhcp.h,v 1.5 2004/05/04 15:49:49 deraadt Exp $ */
+
+/* Protocol structures... */
+
+/*
+ * Copyright (c) 1995, 1996 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''.
+ */
+
+#define DHCP_UDP_OVERHEAD (14 + /* Ethernet header */ \
+ 20 + /* IP header */ \
+ 8) /* UDP header */
+#define DHCP_SNAME_LEN 64
+#define DHCP_FILE_LEN 128
+#define DHCP_FIXED_NON_UDP 236
+#define DHCP_FIXED_LEN (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD)
+ /* Everything but options. */
+#define DHCP_MTU_MAX 1500
+#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN)
+
+#define BOOTP_MIN_LEN 300
+#define DHCP_MIN_LEN 548
+
+struct dhcp_packet {
+ u_int8_t op; /* Message opcode/type */
+ u_int8_t htype; /* Hardware addr type (see net/if_types.h) */
+ u_int8_t hlen; /* Hardware addr length */
+ u_int8_t hops; /* Number of relay agent hops from client */
+ u_int32_t xid; /* Transaction ID */
+ u_int16_t secs; /* Seconds since client started looking */
+ u_int16_t flags; /* Flag bits */
+ struct in_addr ciaddr; /* Client IP address (if already in use) */
+ struct in_addr yiaddr; /* Client IP address */
+ struct in_addr siaddr; /* IP address of next server to talk to */
+ struct in_addr giaddr; /* DHCP relay agent IP address */
+ unsigned char chaddr[16]; /* Client hardware address */
+ char sname[DHCP_SNAME_LEN]; /* Server name */
+ char file[DHCP_FILE_LEN]; /* Boot filename */
+ unsigned char options[DHCP_OPTION_LEN];
+ /* Optional parameters
+ (actual length dependent on MTU). */
+};
+
+/* BOOTP (rfc951) message types */
+#define BOOTREQUEST 1
+#define BOOTREPLY 2
+
+/* Possible values for flags field... */
+#define BOOTP_BROADCAST 32768L
+
+/* Possible values for hardware type (htype) field... */
+#define HTYPE_ETHER 1 /* Ethernet */
+#define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */
+#define HTYPE_FDDI 8 /* FDDI... */
+
+/* Magic cookie validating dhcp options field (and bootp vendor
+ extensions field). */
+#define DHCP_OPTIONS_COOKIE "\143\202\123\143"
+
+
+/* DHCP Option codes: */
+
+#define DHO_PAD 0
+#define DHO_SUBNET_MASK 1
+#define DHO_TIME_OFFSET 2
+#define DHO_ROUTERS 3
+#define DHO_TIME_SERVERS 4
+#define DHO_NAME_SERVERS 5
+#define DHO_DOMAIN_NAME_SERVERS 6
+#define DHO_LOG_SERVERS 7
+#define DHO_COOKIE_SERVERS 8
+#define DHO_LPR_SERVERS 9
+#define DHO_IMPRESS_SERVERS 10
+#define DHO_RESOURCE_LOCATION_SERVERS 11
+#define DHO_HOST_NAME 12
+#define DHO_BOOT_SIZE 13
+#define DHO_MERIT_DUMP 14
+#define DHO_DOMAIN_NAME 15
+#define DHO_SWAP_SERVER 16
+#define DHO_ROOT_PATH 17
+#define DHO_EXTENSIONS_PATH 18
+#define DHO_IP_FORWARDING 19
+#define DHO_NON_LOCAL_SOURCE_ROUTING 20
+#define DHO_POLICY_FILTER 21
+#define DHO_MAX_DGRAM_REASSEMBLY 22
+#define DHO_DEFAULT_IP_TTL 23
+#define DHO_PATH_MTU_AGING_TIMEOUT 24
+#define DHO_PATH_MTU_PLATEAU_TABLE 25
+#define DHO_INTERFACE_MTU 26
+#define DHO_ALL_SUBNETS_LOCAL 27
+#define DHO_BROADCAST_ADDRESS 28
+#define DHO_PERFORM_MASK_DISCOVERY 29
+#define DHO_MASK_SUPPLIER 30
+#define DHO_ROUTER_DISCOVERY 31
+#define DHO_ROUTER_SOLICITATION_ADDRESS 32
+#define DHO_STATIC_ROUTES 33
+#define DHO_TRAILER_ENCAPSULATION 34
+#define DHO_ARP_CACHE_TIMEOUT 35
+#define DHO_IEEE802_3_ENCAPSULATION 36
+#define DHO_DEFAULT_TCP_TTL 37
+#define DHO_TCP_KEEPALIVE_INTERVAL 38
+#define DHO_TCP_KEEPALIVE_GARBAGE 39
+#define DHO_NIS_DOMAIN 40
+#define DHO_NIS_SERVERS 41
+#define DHO_NTP_SERVERS 42
+#define DHO_VENDOR_ENCAPSULATED_OPTIONS 43
+#define DHO_NETBIOS_NAME_SERVERS 44
+#define DHO_NETBIOS_DD_SERVER 45
+#define DHO_NETBIOS_NODE_TYPE 46
+#define DHO_NETBIOS_SCOPE 47
+#define DHO_FONT_SERVERS 48
+#define DHO_X_DISPLAY_MANAGER 49
+#define DHO_DHCP_REQUESTED_ADDRESS 50
+#define DHO_DHCP_LEASE_TIME 51
+#define DHO_DHCP_OPTION_OVERLOAD 52
+#define DHO_DHCP_MESSAGE_TYPE 53
+#define DHO_DHCP_SERVER_IDENTIFIER 54
+#define DHO_DHCP_PARAMETER_REQUEST_LIST 55
+#define DHO_DHCP_MESSAGE 56
+#define DHO_DHCP_MAX_MESSAGE_SIZE 57
+#define DHO_DHCP_RENEWAL_TIME 58
+#define DHO_DHCP_REBINDING_TIME 59
+#define DHO_DHCP_CLASS_IDENTIFIER 60
+#define DHO_DHCP_CLIENT_IDENTIFIER 61
+#define DHO_DHCP_USER_CLASS_ID 77
+#define DHO_END 255
+
+/* DHCP message types. */
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
--- /dev/null
+/* $OpenBSD: dhcpd.h,v 1.33 2004/05/06 22:29:15 deraadt Exp $ */
+
+/*
+ * Copyright (c) 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''.
+ */
+
+#pragma once
+
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include "stdint.h"
+
+#define IFNAMSIZ MAX_INTERFACE_NAME_LEN
+
+#define ETH_ALEN 6
+#define ETHER_ADDR_LEN ETH_ALEN
+#include <pshpack1.h>
+struct ether_header
+{
+ u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */
+ u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */
+ u_int16_t ether_type; /* packet type ID field */
+};
+#include <poppack.h>
+
+struct ip
+ {
+ unsigned int ip_hl:4; /* header length */
+ unsigned int ip_v:4; /* version */
+ u_int8_t ip_tos; /* type of service */
+ u_short ip_len; /* total length */
+ u_short ip_id; /* identification */
+ u_short ip_off; /* fragment offset field */
+#define IP_RF 0x8000 /* reserved fragment flag */
+#define IP_DF 0x4000 /* dont fragment flag */
+#define IP_MF 0x2000 /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+ u_int8_t ip_ttl; /* time to live */
+ u_int8_t ip_p; /* protocol */
+ u_short ip_sum; /* checksum */
+ struct in_addr ip_src, ip_dst; /* source and dest address */
+ };
+
+struct udphdr {
+ u_int16_t uh_sport; /* source port */
+ u_int16_t uh_dport; /* destination port */
+ u_int16_t uh_ulen; /* udp length */
+ u_int16_t uh_sum; /* udp checksum */
+};
+
+#define ETHERTYPE_IP 0x0800
+#define IPTOS_LOWDELAY 0x10
+#define ARPHRD_ETHER 1
+
+// FIXME: I have no idea what this should be!
+#define SIZE_T_MAX 1600
+
+#define USE_SOCKET_RECEIVE
+#define USE_SOCKET_SEND
+
+#include <sys/types.h>
+#include <sys/stat.h>
+//#include <sys/time.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+//#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+//#include <unistd.h>
+
+#include "dhcp.h"
+#include "tree.h"
+
+#define LOCAL_PORT 68
+#define REMOTE_PORT 67
+
+struct option_data {
+ int len;
+ u_int8_t *data;
+};
+
+struct string_list {
+ struct string_list *next;
+ char *string;
+};
+
+struct iaddr {
+ int len;
+ unsigned char iabuf[16];
+};
+
+struct iaddrlist {
+ struct iaddrlist *next;
+ struct iaddr addr;
+};
+
+struct packet {
+ struct dhcp_packet *raw;
+ int packet_length;
+ int packet_type;
+ int options_valid;
+ int client_port;
+ struct iaddr client_addr;
+ struct interface_info *interface;
+ struct hardware *haddr;
+ struct option_data options[256];
+};
+
+struct hardware {
+ u_int8_t htype;
+ u_int8_t hlen;
+ u_int8_t haddr[16];
+};
+
+struct client_lease {
+ struct client_lease *next;
+ time_t expiry, renewal, rebind;
+ struct iaddr address;
+ char *server_name;
+#ifdef __REACTOS__
+ time_t obtained;
+ struct iaddr serveraddress;
+#endif
+ char *filename;
+ struct string_list *medium;
+ unsigned int is_static : 1;
+ unsigned int is_bootp : 1;
+ struct option_data options[256];
+};
+
+/* Possible states in which the client can be. */
+enum dhcp_state {
+ S_REBOOTING,
+ S_INIT,
+ S_SELECTING,
+ S_REQUESTING,
+ S_BOUND,
+ S_RENEWING,
+ S_REBINDING,
+ S_STATIC
+};
+
+struct client_config {
+ struct option_data defaults[256];
+ enum {
+ ACTION_DEFAULT,
+ ACTION_SUPERSEDE,
+ ACTION_PREPEND,
+ ACTION_APPEND
+ } default_actions[256];
+
+ struct option_data send_options[256];
+ u_int8_t required_options[256];
+ u_int8_t requested_options[256];
+ int requested_option_count;
+ time_t timeout;
+ time_t initial_interval;
+ time_t retry_interval;
+ time_t select_interval;
+ time_t reboot_timeout;
+ time_t backoff_cutoff;
+ struct string_list *media;
+ char *script_name;
+ enum { IGNORE, ACCEPT, PREFER }
+ bootp_policy;
+ struct string_list *medium;
+ struct iaddrlist *reject_list;
+};
+
+struct client_state {
+ struct client_lease *active;
+ struct client_lease *new;
+ struct client_lease *offered_leases;
+ struct client_lease *leases;
+ struct client_lease *alias;
+ enum dhcp_state state;
+ struct iaddr destination;
+ u_int32_t xid;
+ u_int16_t secs;
+ time_t first_sending;
+ time_t interval;
+ struct string_list *medium;
+ struct dhcp_packet packet;
+ int packet_length;
+ struct iaddr requested_address;
+ struct client_config *config;
+};
+
+struct interface_info {
+ struct interface_info *next;
+ struct hardware hw_address;
+ struct in_addr primary_address;
+ char name[IFNAMSIZ];
+ int rfdesc;
+ int wfdesc;
+ unsigned char *rbuf;
+ size_t rbuf_max;
+ size_t rbuf_offset;
+ size_t rbuf_len;
+ struct client_state *client;
+ int noifmedia;
+ int errors;
+ int dead;
+ u_int16_t index;
+};
+
+struct timeout {
+ struct timeout *next;
+ time_t when;
+ void (*func)(void *);
+ void *what;
+};
+
+struct protocol {
+ struct protocol *next;
+ int fd;
+ void (*handler)(struct protocol *);
+ void *local;
+};
+
+#define DEFAULT_HASH_SIZE 97
+
+struct hash_bucket {
+ struct hash_bucket *next;
+ unsigned char *name;
+ int len;
+ unsigned char *value;
+};
+
+struct hash_table {
+ int hash_count;
+ struct hash_bucket *buckets[DEFAULT_HASH_SIZE];
+};
+
+/* Default path to dhcpd config file. */
+#define _PATH_DHCLIENT_CONF "/etc/dhclient.conf"
+#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases"
+#define DHCPD_LOG_FACILITY LOG_DAEMON
+
+#define MAX_TIME 0x7fffffff
+#define MIN_TIME 0
+
+/* External definitions... */
+
+/* options.c */
+int cons_options(struct packet *, struct dhcp_packet *, int,
+ struct tree_cache **, int, int, int, u_int8_t *, int);
+char *pretty_print_option(unsigned int,
+ unsigned char *, int, int, int);
+void do_packet(struct interface_info *, struct dhcp_packet *,
+ int, unsigned int, struct iaddr, struct hardware *);
+
+/* errwarn.c */
+extern int warnings_occurred;
+#ifdef _MSC_VER
+void error(char *, ...);
+int warning(char *, ...);
+int note(char *, ...);
+int debug(char *, ...);
+int parse_warn(char *, ...);
+#else
+void error(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+int warning(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+int note(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+int debug(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+int parse_warn(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+#endif
+
+/* conflex.c */
+extern int lexline, lexchar;
+extern char *token_line, *tlname;
+extern char comments[4096];
+extern int comment_index;
+extern int eol_token;
+void new_parse(char *);
+int next_token(char **, FILE *);
+int peek_token(char **, FILE *);
+
+/* parse.c */
+void skip_to_semi(FILE *);
+int parse_semi(FILE *);
+char *parse_string(FILE *);
+int parse_ip_addr(FILE *, struct iaddr *);
+void parse_hardware_param(FILE *, struct hardware *);
+void parse_lease_time(FILE *, time_t *);
+unsigned char *parse_numeric_aggregate(FILE *, unsigned char *, int *,
+ int, int, int);
+void convert_num(unsigned char *, char *, int, int);
+time_t parse_date(FILE *);
+
+/* tree.c */
+pair cons(caddr_t, pair);
+
+/* alloc.c */
+struct string_list *new_string_list(size_t size);
+struct hash_table *new_hash_table(int);
+struct hash_bucket *new_hash_bucket(void);
+void dfree(void *, char *);
+void free_hash_bucket(struct hash_bucket *, char *);
+
+
+/* bpf.c */
+int if_register_bpf(struct interface_info *);
+void if_register_send(struct interface_info *);
+void if_register_receive(struct interface_info *);
+ssize_t send_packet(struct interface_info *, struct dhcp_packet *, size_t,
+ struct in_addr, struct sockaddr_in *, struct hardware *);
+ssize_t receive_packet(struct interface_info *, unsigned char *, size_t,
+ struct sockaddr_in *, struct hardware *);
+
+/* dispatch.c */
+extern void (*bootp_packet_handler)(struct interface_info *,
+ struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *);
+void discover_interfaces(struct interface_info *);
+void reinitialize_interfaces(void);
+void dispatch(void);
+void got_one(struct protocol *);
+void add_timeout(time_t, void (*)(void *), void *);
+void cancel_timeout(void (*)(void *), void *);
+void add_protocol(char *, int, void (*)(struct protocol *), void *);
+void remove_protocol(struct protocol *);
+struct protocol *find_protocol_by_adapter( struct interface_info * );
+int interface_link_status(char *);
+
+/* hash.c */
+struct hash_table *new_hash(void);
+void add_hash(struct hash_table *, unsigned char *, int, unsigned char *);
+unsigned char *hash_lookup(struct hash_table *, unsigned char *, int);
+
+/* tables.c */
+extern struct dhcp_option dhcp_options[256];
+extern unsigned char dhcp_option_default_priority_list[];
+extern int sizeof_dhcp_option_default_priority_list;
+extern struct hash_table universe_hash;
+extern struct universe dhcp_universe;
+void initialize_universes(void);
+
+/* convert.c */
+u_int32_t getULong(unsigned char *);
+int32_t getLong(unsigned char *);
+u_int16_t getUShort(unsigned char *);
+int16_t getShort(unsigned char *);
+void putULong(unsigned char *, u_int32_t);
+void putLong(unsigned char *, int32_t);
+void putUShort(unsigned char *, unsigned int);
+void putShort(unsigned char *, int);
+
+/* inet.c */
+struct iaddr subnet_number(struct iaddr, struct iaddr);
+struct iaddr broadcast_addr(struct iaddr, struct iaddr);
+int addr_eq(struct iaddr, struct iaddr);
+char *piaddr(struct iaddr);
+
+/* dhclient.c */
+extern char *path_dhclient_conf;
+extern char *path_dhclient_db;
+extern time_t cur_time;
+extern int log_priority;
+extern int log_perror;
+
+extern struct client_config top_level_config;
+
+void dhcpoffer(struct packet *);
+void dhcpack(struct packet *);
+void dhcpnak(struct packet *);
+
+void send_discover(void *);
+void send_request(void *);
+void send_decline(void *);
+
+void state_reboot(void *);
+void state_init(void *);
+void state_selecting(void *);
+void state_requesting(void *);
+void state_bound(void *);
+void state_panic(void *);
+
+void bind_lease(struct interface_info *);
+
+void make_discover(struct interface_info *, struct client_lease *);
+void make_request(struct interface_info *, struct client_lease *);
+void make_decline(struct interface_info *, struct client_lease *);
+
+void free_client_lease(struct client_lease *);
+void rewrite_client_leases(struct interface_info *);
+void write_client_lease(struct interface_info *, struct client_lease *, int);
+
+void priv_script_init(struct interface_info *, char *, char *);
+void priv_script_write_params(struct interface_info *, char *, struct client_lease *);
+int priv_script_go(void);
+
+void script_init(char *, struct string_list *);
+void script_write_params(char *, struct client_lease *);
+int script_go(void);
+void client_envadd(struct client_state *,
+ const char *, const char *, const char *, ...);
+void script_set_env(struct client_state *, const char *, const char *,
+ const char *);
+void script_flush_env(struct client_state *);
+int dhcp_option_ev_name(char *, size_t, struct dhcp_option *);
+
+struct client_lease *packet_to_lease(struct packet *);
+void go_daemon(void);
+void client_location_changed(void);
+
+void bootp(struct packet *);
+void dhcp(struct packet *);
+
+/* packet.c */
+void assemble_hw_header(struct interface_info *, unsigned char *,
+ int *, struct hardware *);
+void assemble_udp_ip_header(unsigned char *, int *, u_int32_t, u_int32_t,
+ unsigned int, unsigned char *, int);
+ssize_t decode_hw_header(unsigned char *, int, struct hardware *);
+ssize_t decode_udp_ip_header(unsigned char *, int, struct sockaddr_in *,
+ unsigned char *, int);
+
+/* ethernet.c */
+void assemble_ethernet_header(struct interface_info *, unsigned char *,
+ int *, struct hardware *);
+ssize_t decode_ethernet_header(struct interface_info *, unsigned char *,
+ int, struct hardware *);
+
+/* clparse.c */
+int read_client_conf(struct interface_info *);
+void read_client_leases(void);
+void parse_client_statement(FILE *, struct interface_info *,
+ struct client_config *);
+int parse_X(FILE *, u_int8_t *, int);
+int parse_option_list(FILE *, u_int8_t *);
+void parse_interface_declaration(FILE *, struct client_config *);
+struct interface_info *interface_or_dummy(char *);
+void make_client_state(struct interface_info *);
+void make_client_config(struct interface_info *, struct client_config *);
+void parse_client_lease_statement(FILE *, int);
+void parse_client_lease_declaration(FILE *, struct client_lease *,
+ struct interface_info **);
+struct dhcp_option *parse_option_decl(FILE *, struct option_data *);
+void parse_string_list(FILE *, struct string_list **, int);
+void parse_reject_statement(FILE *, struct client_config *);
+
+/* privsep.c */
+struct buf *buf_open(size_t);
+int buf_add(struct buf *, void *, size_t);
+int buf_close(int, struct buf *);
+ssize_t buf_read(int, void *, size_t);
+void dispatch_imsg(int);
--- /dev/null
+/* hash.h
+
+ Definitions for hashing... */
+
+/*
+ * Copyright (c) 1995, 1996 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''.
+ */
+
+#define DEFAULT_HASH_SIZE 97
+
+struct hash_bucket {
+ struct hash_bucket *next;
+ unsigned char *name;
+ int len;
+ unsigned char *value;
+};
+
+struct hash_table {
+ int hash_count;
+ struct hash_bucket *buckets [DEFAULT_HASH_SIZE];
+};
+
--- /dev/null
+#ifndef ROSDHCP_H
+#define ROSDHCP_H
+
+#define WIN32_NO_STATUS
+#include <winsock2.h>
+#define NTOS_MODE_USER
+#include <ndk/ntndk.h>
+#include <iprtrmib.h>
+#include <iphlpapi.h>
+#include <dhcpcsdk.h>
+#include <dhcp/rosdhcp_public.h>
+#include <stdio.h>
+#include <time.h>
+#include "debug.h"
+#define IFNAMSIZ MAX_INTERFACE_NAME_LEN
+#undef interface /* wine/objbase.h -- Grrr */
+
+#undef IGNORE
+#undef ACCEPT
+#undef PREFER
+#define DHCP_DISCOVER_INTERVAL 15
+#define DHCP_REBOOT_TIMEOUT 300
+#define DHCP_PANIC_TIMEOUT DHCP_REBOOT_TIMEOUT * 3
+#define DHCP_BACKOFF_MAX 300
+#define DHCP_DEFAULT_LEASE_TIME 43200 /* 12 hours */
+#define _PATH_DHCLIENT_PID "\\systemroot\\system32\\drivers\\etc\\dhclient.pid"
+typedef void *VOIDPTR;
+typedef unsigned char u_int8_t;
+typedef unsigned short u_int16_t;
+typedef unsigned int u_int32_t;
+typedef char *caddr_t;
+
+#ifndef _SSIZE_T_DEFINED
+#define _SSIZE_T_DEFINED
+#undef ssize_t
+#ifdef _WIN64
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)
+ typedef int ssize_t __attribute__ ((mode (DI)));
+#else
+ typedef __int64 ssize_t;
+#endif
+#else
+ typedef int ssize_t;
+#endif
+#endif
+
+typedef u_int32_t uintTIME;
+#define TIME uintTIME
+#include "dhcpd.h"
+
+#define INLINE inline
+#define PROTO(x) x
+
+typedef void (*handler_t) PROTO ((struct packet *));
+
+struct iaddr;
+struct interface_info;
+
+typedef struct _DHCP_ADAPTER {
+ LIST_ENTRY ListEntry;
+ MIB_IFROW IfMib;
+ MIB_IPFORWARDROW RouterMib;
+ MIB_IPADDRROW IfAddr;
+ SOCKADDR Address;
+ ULONG NteContext,NteInstance;
+ struct interface_info DhclientInfo;
+ struct client_state DhclientState;
+ struct client_config DhclientConfig;
+ struct sockaddr_in ListenAddr;
+ unsigned int BindStatus;
+ unsigned char recv_buf[1];
+} DHCP_ADAPTER, *PDHCP_ADAPTER;
+
+typedef DWORD (*PipeSendFunc)( COMM_DHCP_REPLY *Reply );
+
+#define random rand
+#define srandom srand
+
+void AdapterInit(VOID);
+BOOLEAN AdapterDiscover(VOID);
+void AdapterStop(VOID);
+extern PDHCP_ADAPTER AdapterGetFirst();
+extern PDHCP_ADAPTER AdapterGetNext(PDHCP_ADAPTER);
+extern PDHCP_ADAPTER AdapterFindIndex( unsigned int AdapterIndex );
+extern PDHCP_ADAPTER AdapterFindInfo( struct interface_info *info );
+extern PDHCP_ADAPTER AdapterFindByHardwareAddress( u_int8_t haddr[16], u_int8_t hlen );
+extern HANDLE PipeInit();
+extern VOID ApiInit();
+extern VOID ApiFree();
+extern VOID ApiLock();
+extern VOID ApiUnlock();
+extern DWORD DSQueryHWInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req );
+extern DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req );
+extern DWORD DSRenewIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req );
+extern DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req );
+extern DWORD DSStaticRefreshParams( PipeSendFunc Send, COMM_DHCP_REQ *Req );
+extern DWORD DSGetAdapterInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req );
+extern int inet_aton(const char *s, struct in_addr *addr);
+int warn( char *format, ... );
+#endif/*ROSDHCP_H*/
--- /dev/null
+/* $OpenBSD: tree.h,v 1.5 2004/05/06 22:29:15 deraadt Exp $ */
+
+/* Definitions for address trees... */
+
+/*
+ * Copyright (c) 1995 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''.
+ */
+
+/* A pair of pointers, suitable for making a linked list. */
+typedef struct _pair {
+ caddr_t car;
+ struct _pair *cdr;
+} *pair;
+
+struct tree_cache {
+ unsigned char *value;
+ int len;
+ int buf_size;
+ time_t timeout;
+};
+
+struct universe {
+ char *name;
+ struct hash_table *hash;
+ struct dhcp_option *options[256];
+};
+
+struct dhcp_option {
+ char *name;
+ char *format;
+ struct universe *universe;
+ unsigned char code;
+};
--- /dev/null
+/* $OpenBSD: options.c,v 1.15 2004/12/26 03:17:07 deraadt Exp $ */
+
+/* DHCP options parsing and reassembly. */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 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 <ctype.h>
+#include <string.h>
+
+#define DHCP_OPTION_DATA
+#include "rosdhcp.h"
+#include "dhcpd.h"
+
+int bad_options = 0;
+int bad_options_max = 5;
+
+void parse_options(struct packet *);
+void parse_option_buffer(struct packet *, unsigned char *, int);
+int store_options(unsigned char *, int, struct tree_cache **,
+ unsigned char *, int, int, int, int);
+
+
+/*
+ * Parse all available options out of the specified packet.
+ */
+void
+parse_options(struct packet *packet)
+{
+ /* Initially, zero all option pointers. */
+ memset(packet->options, 0, sizeof(packet->options));
+
+ /* If we don't see the magic cookie, there's nothing to parse. */
+ if (memcmp(packet->raw->options, DHCP_OPTIONS_COOKIE, 4)) {
+ packet->options_valid = 0;
+ return;
+ }
+
+ /*
+ * Go through the options field, up to the end of the packet or
+ * the End field.
+ */
+ parse_option_buffer(packet, &packet->raw->options[4],
+ packet->packet_length - DHCP_FIXED_NON_UDP - 4);
+
+ /*
+ * If we parsed a DHCP Option Overload option, parse more
+ * options out of the buffer(s) containing them.
+ */
+ if (packet->options_valid &&
+ packet->options[DHO_DHCP_OPTION_OVERLOAD].data) {
+ if (packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)
+ parse_option_buffer(packet,
+ (unsigned char *)packet->raw->file,
+ sizeof(packet->raw->file));
+ if (packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)
+ parse_option_buffer(packet,
+ (unsigned char *)packet->raw->sname,
+ sizeof(packet->raw->sname));
+ }
+}
+
+/*
+ * Parse options out of the specified buffer, storing addresses of
+ * option values in packet->options and setting packet->options_valid if
+ * no errors are encountered.
+ */
+void
+parse_option_buffer(struct packet *packet,
+ unsigned char *buffer, int length)
+{
+ unsigned char *s, *t, *end = buffer + length;
+ int len, code;
+
+ for (s = buffer; *s != DHO_END && s < end; ) {
+ code = s[0];
+
+ /* Pad options don't have a length - just skip them. */
+ if (code == DHO_PAD) {
+ s++;
+ continue;
+ }
+ if (s + 2 > end) {
+ len = 65536;
+ goto bogus;
+ }
+
+ /*
+ * All other fields (except end, see above) have a
+ * one-byte length.
+ */
+ len = s[1];
+
+ /*
+ * If the length is outrageous, silently skip the rest,
+ * and mark the packet bad. Unfortunately some crappy
+ * dhcp servers always seem to give us garbage on the
+ * end of a packet. so rather than keep refusing, give
+ * up and try to take one after seeing a few without
+ * anything good.
+ */
+ if (s + len + 2 > end) {
+ bogus:
+ bad_options++;
+ warning("option %s (%d) %s.",
+ dhcp_options[code].name, len,
+ "larger than buffer");
+ if (bad_options == bad_options_max) {
+ packet->options_valid = 1;
+ bad_options = 0;
+ warning("Many bogus options seen in offers. "
+ "Taking this offer in spite of bogus "
+ "options - hope for the best!");
+ } else {
+ warning("rejecting bogus offer.");
+ packet->options_valid = 0;
+ }
+ return;
+ }
+ /*
+ * If we haven't seen this option before, just make
+ * space for it and copy it there.
+ */
+ if (!packet->options[code].data) {
+ if (!(t = calloc(1, len + 1)))
+ error("Can't allocate storage for option %s.",
+ dhcp_options[code].name);
+ /*
+ * Copy and NUL-terminate the option (in case
+ * it's an ASCII string.
+ */
+ memcpy(t, &s[2], len);
+ t[len] = 0;
+ packet->options[code].len = len;
+ packet->options[code].data = t;
+ } else {
+ /*
+ * If it's a repeat, concatenate it to whatever
+ * we last saw. This is really only required
+ * for clients, but what the heck...
+ */
+ t = calloc(1, len + packet->options[code].len + 1);
+ if (!t) {
+ error("Can't expand storage for option %s.",
+ dhcp_options[code].name);
+ return;
+ }
+ memcpy(t, packet->options[code].data,
+ packet->options[code].len);
+ memcpy(t + packet->options[code].len,
+ &s[2], len);
+ packet->options[code].len += len;
+ t[packet->options[code].len] = 0;
+ free(packet->options[code].data);
+ packet->options[code].data = t;
+ }
+ s += len + 2;
+ }
+ packet->options_valid = 1;
+}
+
+/*
+ * cons options into a big buffer, and then split them out into the
+ * three separate buffers if needed. This allows us to cons up a set of
+ * vendor options using the same routine.
+ */
+int
+cons_options(struct packet *inpacket, struct dhcp_packet *outpacket,
+ int mms, struct tree_cache **options,
+ int overload, /* Overload flags that may be set. */
+ int terminate, int bootpp, u_int8_t *prl, int prl_len)
+{
+ unsigned char priority_list[300], buffer[4096];
+ int priority_len, main_buffer_size, mainbufix, bufix;
+ int option_size, length;
+
+ /*
+ * If the client has provided a maximum DHCP message size, use
+ * that; otherwise, if it's BOOTP, only 64 bytes; otherwise use
+ * up to the minimum IP MTU size (576 bytes).
+ *
+ * XXX if a BOOTP client specifies a max message size, we will
+ * honor it.
+ */
+ if (!mms &&
+ inpacket &&
+ inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data &&
+ (inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].len >=
+ sizeof(u_int16_t)))
+ mms = getUShort(
+ inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data);
+
+ if (mms)
+ main_buffer_size = mms - DHCP_FIXED_LEN;
+ else if (bootpp)
+ main_buffer_size = 64;
+ else
+ main_buffer_size = 576 - DHCP_FIXED_LEN;
+
+ if (main_buffer_size > sizeof(buffer))
+ main_buffer_size = sizeof(buffer);
+
+ /* Preload the option priority list with mandatory options. */
+ priority_len = 0;
+ priority_list[priority_len++] = DHO_DHCP_MESSAGE_TYPE;
+ priority_list[priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
+ priority_list[priority_len++] = DHO_DHCP_LEASE_TIME;
+ priority_list[priority_len++] = DHO_DHCP_MESSAGE;
+
+ /*
+ * If the client has provided a list of options that it wishes
+ * returned, use it to prioritize. Otherwise, prioritize based
+ * on the default priority list.
+ */
+ if (inpacket &&
+ inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data) {
+ int prlen =
+ inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].len;
+ if (prlen + priority_len > sizeof(priority_list))
+ prlen = sizeof(priority_list) - priority_len;
+
+ memcpy(&priority_list[priority_len],
+ inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data,
+ prlen);
+ priority_len += prlen;
+ prl = priority_list;
+ } else if (prl) {
+ if (prl_len + priority_len > sizeof(priority_list))
+ prl_len = sizeof(priority_list) - priority_len;
+
+ memcpy(&priority_list[priority_len], prl, prl_len);
+ priority_len += prl_len;
+ prl = priority_list;
+ } else {
+ memcpy(&priority_list[priority_len],
+ dhcp_option_default_priority_list,
+ sizeof_dhcp_option_default_priority_list);
+ priority_len += sizeof_dhcp_option_default_priority_list;
+ }
+
+ /* Copy the options into the big buffer... */
+ option_size = store_options(
+ buffer,
+ (main_buffer_size - 7 + ((overload & 1) ? DHCP_FILE_LEN : 0) +
+ ((overload & 2) ? DHCP_SNAME_LEN : 0)),
+ options, priority_list, priority_len, main_buffer_size,
+ (main_buffer_size + ((overload & 1) ? DHCP_FILE_LEN : 0)),
+ terminate);
+
+ /* Put the cookie up front... */
+ memcpy(outpacket->options, DHCP_OPTIONS_COOKIE, 4);
+ mainbufix = 4;
+
+ /*
+ * If we're going to have to overload, store the overload option
+ * at the beginning. If we can, though, just store the whole
+ * thing in the packet's option buffer and leave it at that.
+ */
+ if (option_size <= main_buffer_size - mainbufix) {
+ memcpy(&outpacket->options[mainbufix],
+ buffer, option_size);
+ mainbufix += option_size;
+ if (mainbufix < main_buffer_size)
+ outpacket->options[mainbufix++] = DHO_END;
+ length = DHCP_FIXED_NON_UDP + mainbufix;
+ } else {
+ outpacket->options[mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
+ outpacket->options[mainbufix++] = 1;
+ if (option_size >
+ main_buffer_size - mainbufix + DHCP_FILE_LEN)
+ outpacket->options[mainbufix++] = 3;
+ else
+ outpacket->options[mainbufix++] = 1;
+
+ memcpy(&outpacket->options[mainbufix],
+ buffer, main_buffer_size - mainbufix);
+ bufix = main_buffer_size - mainbufix;
+ length = DHCP_FIXED_NON_UDP + mainbufix;
+ if (overload & 1) {
+ if (option_size - bufix <= DHCP_FILE_LEN) {
+ memcpy(outpacket->file,
+ &buffer[bufix], option_size - bufix);
+ mainbufix = option_size - bufix;
+ if (mainbufix < DHCP_FILE_LEN)
+ outpacket->file[mainbufix++] = (char)DHO_END;
+ while (mainbufix < DHCP_FILE_LEN)
+ outpacket->file[mainbufix++] = (char)DHO_PAD;
+ } else {
+ memcpy(outpacket->file,
+ &buffer[bufix], DHCP_FILE_LEN);
+ bufix += DHCP_FILE_LEN;
+ }
+ }
+ if ((overload & 2) && option_size < bufix) {
+ memcpy(outpacket->sname,
+ &buffer[bufix], option_size - bufix);
+
+ mainbufix = option_size - bufix;
+ if (mainbufix < DHCP_SNAME_LEN)
+ outpacket->file[mainbufix++] = (char)DHO_END;
+ while (mainbufix < DHCP_SNAME_LEN)
+ outpacket->file[mainbufix++] = (char)DHO_PAD;
+ }
+ }
+ return (length);
+}
+
+/*
+ * Store all the requested options into the requested buffer.
+ */
+int
+store_options(unsigned char *buffer, int buflen, struct tree_cache **options,
+ unsigned char *priority_list, int priority_len, int first_cutoff,
+ int second_cutoff, int terminate)
+{
+ int bufix = 0, option_stored[256], i, ix, tto;
+
+ /* Zero out the stored-lengths array. */
+ memset(option_stored, 0, sizeof(option_stored));
+
+ /*
+ * Copy out the options in the order that they appear in the
+ * priority list...
+ */
+ for (i = 0; i < priority_len; i++) {
+ /* Code for next option to try to store. */
+ int code = priority_list[i];
+ int optstart;
+
+ /*
+ * Number of bytes left to store (some may already have
+ * been stored by a previous pass).
+ */
+ int length;
+
+ /* If no data is available for this option, skip it. */
+ if (!options[code]) {
+ continue;
+ }
+
+ /*
+ * The client could ask for things that are mandatory,
+ * in which case we should avoid storing them twice...
+ */
+ if (option_stored[code])
+ continue;
+ option_stored[code] = 1;
+
+ /* We should now have a constant length for the option. */
+ length = options[code]->len;
+
+ /* Do we add a NUL? */
+ if (terminate && dhcp_options[code].format[0] == 't') {
+ length++;
+ tto = 1;
+ } else
+ tto = 0;
+
+ /* Try to store the option. */
+
+ /*
+ * If the option's length is more than 255, we must
+ * store it in multiple hunks. Store 255-byte hunks
+ * first. However, in any case, if the option data will
+ * cross a buffer boundary, split it across that
+ * boundary.
+ */
+ ix = 0;
+
+ optstart = bufix;
+ while (length) {
+ unsigned char incr = length > 255 ? 255 : length;
+
+ /*
+ * If this hunk of the buffer will cross a
+ * boundary, only go up to the boundary in this
+ * pass.
+ */
+ if (bufix < first_cutoff &&
+ bufix + incr > first_cutoff)
+ incr = first_cutoff - bufix;
+ else if (bufix < second_cutoff &&
+ bufix + incr > second_cutoff)
+ incr = second_cutoff - bufix;
+
+ /*
+ * If this option is going to overflow the
+ * buffer, skip it.
+ */
+ if (bufix + 2 + incr > buflen) {
+ bufix = optstart;
+ break;
+ }
+
+ /* Everything looks good - copy it in! */
+ buffer[bufix] = code;
+ buffer[bufix + 1] = incr;
+ if (tto && incr == length) {
+ memcpy(buffer + bufix + 2,
+ options[code]->value + ix, incr - 1);
+ buffer[bufix + 2 + incr - 1] = 0;
+ } else
+ memcpy(buffer + bufix + 2,
+ options[code]->value + ix, incr);
+ length -= incr;
+ ix += incr;
+ bufix += 2 + incr;
+ }
+ }
+ return (bufix);
+}
+
+/*
+ * Format the specified option so that a human can easily read it.
+ */
+char *
+pretty_print_option(unsigned int code, unsigned char *data, int len,
+ int emit_commas, int emit_quotes)
+{
+ static char optbuf[32768]; /* XXX */
+ int hunksize = 0, numhunk = -1, numelem = 0;
+ char fmtbuf[32], *op = optbuf;
+ int i, j, k, opleft = sizeof(optbuf);
+ unsigned char *dp = data;
+ struct in_addr foo;
+ char comma;
+
+ /* Code should be between 0 and 255. */
+ if (code > 255)
+ error("pretty_print_option: bad code %d", code);
+
+ if (emit_commas)
+ comma = ',';
+ else
+ comma = ' ';
+
+ /* Figure out the size of the data. */
+ for (i = 0; dhcp_options[code].format[i]; i++) {
+ if (!numhunk) {
+ warning("%s: Excess information in format string: %s",
+ dhcp_options[code].name,
+ &(dhcp_options[code].format[i]));
+ break;
+ }
+ numelem++;
+ fmtbuf[i] = dhcp_options[code].format[i];
+ switch (dhcp_options[code].format[i]) {
+ case 'A':
+ --numelem;
+ fmtbuf[i] = 0;
+ numhunk = 0;
+ break;
+ case 'X':
+ for (k = 0; k < len; k++)
+ if (!isascii(data[k]) ||
+ !isprint(data[k]))
+ break;
+ if (k == len) {
+ fmtbuf[i] = 't';
+ numhunk = -2;
+ } else {
+ fmtbuf[i] = 'x';
+ hunksize++;
+ comma = ':';
+ numhunk = 0;
+ }
+ fmtbuf[i + 1] = 0;
+ break;
+ case 't':
+ fmtbuf[i] = 't';
+ fmtbuf[i + 1] = 0;
+ numhunk = -2;
+ break;
+ case 'I':
+ case 'l':
+ case 'L':
+ hunksize += 4;
+ break;
+ case 's':
+ case 'S':
+ hunksize += 2;
+ break;
+ case 'b':
+ case 'B':
+ case 'f':
+ hunksize++;
+ break;
+ case 'e':
+ break;
+ default:
+ warning("%s: garbage in format string: %s",
+ dhcp_options[code].name,
+ &(dhcp_options[code].format[i]));
+ break;
+ }
+ }
+
+ /* Check for too few bytes... */
+ if (hunksize > len) {
+ warning("%s: expecting at least %d bytes; got %d",
+ dhcp_options[code].name, hunksize, len);
+ return ("<error>");
+ }
+ /* Check for too many bytes... */
+ if (numhunk == -1 && hunksize < len)
+ warning("%s: %d extra bytes",
+ dhcp_options[code].name, len - hunksize);
+
+ /* If this is an array, compute its size. */
+ if (!numhunk)
+ numhunk = len / hunksize;
+ /* See if we got an exact number of hunks. */
+ if (numhunk > 0 && numhunk * hunksize < len)
+ warning("%s: %d extra bytes at end of array",
+ dhcp_options[code].name, len - numhunk * hunksize);
+
+ /* A one-hunk array prints the same as a single hunk. */
+ if (numhunk < 0)
+ numhunk = 1;
+
+ /* Cycle through the array (or hunk) printing the data. */
+ for (i = 0; i < numhunk; i++) {
+ for (j = 0; j < numelem; j++) {
+ int opcount;
+ switch (fmtbuf[j]) {
+ case 't':
+ if (emit_quotes) {
+ *op++ = '"';
+ opleft--;
+ }
+ for (; dp < data + len; dp++) {
+ if (!isascii(*dp) ||
+ !isprint(*dp)) {
+ if (dp + 1 != data + len ||
+ *dp != 0) {
+ _snprintf(op, opleft,
+ "\\%03o", *dp);
+ op += 4;
+ opleft -= 4;
+ }
+ } else if (*dp == '"' ||
+ *dp == '\'' ||
+ *dp == '$' ||
+ *dp == '`' ||
+ *dp == '\\') {
+ *op++ = '\\';
+ *op++ = *dp;
+ opleft -= 2;
+ } else {
+ *op++ = *dp;
+ opleft--;
+ }
+ }
+ if (emit_quotes) {
+ *op++ = '"';
+ opleft--;
+ }
+
+ *op = 0;
+ break;
+ case 'I':
+ foo.s_addr = htonl(getULong(dp));
+ strncpy(op, inet_ntoa(foo), opleft - 1);
+ op[opleft - 1] = ANSI_NULL;
+ opcount = strlen(op);
+ if (opcount >= opleft)
+ goto toobig;
+ opleft -= opcount;
+ dp += 4;
+ break;
+ case 'l':
+ opcount = _snprintf(op, opleft, "%ld",
+ (long)getLong(dp));
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ dp += 4;
+ break;
+ case 'L':
+ opcount = _snprintf(op, opleft, "%ld",
+ (unsigned long)getULong(dp));
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ dp += 4;
+ break;
+ case 's':
+ opcount = _snprintf(op, opleft, "%d",
+ getShort(dp));
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ dp += 2;
+ break;
+ case 'S':
+ opcount = _snprintf(op, opleft, "%d",
+ getUShort(dp));
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ dp += 2;
+ break;
+ case 'b':
+ opcount = _snprintf(op, opleft, "%d",
+ *(char *)dp++);
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ break;
+ case 'B':
+ opcount = _snprintf(op, opleft, "%d", *dp++);
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ break;
+ case 'x':
+ opcount = _snprintf(op, opleft, "%x", *dp++);
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ break;
+ case 'f':
+ opcount = (size_t) strncpy(op, *dp++ ? "true" : "false", opleft - 1);
+ op[opleft - 1] = ANSI_NULL;
+ if (opcount >= opleft)
+ goto toobig;
+ opleft -= opcount;
+ break;
+ default:
+ warning("Unexpected format code %c", fmtbuf[j]);
+ }
+ op += strlen(op);
+ opleft -= strlen(op);
+ if (opleft < 1)
+ goto toobig;
+ if (j + 1 < numelem && comma != ':') {
+ *op++ = ' ';
+ opleft--;
+ }
+ }
+ if (i + 1 < numhunk) {
+ *op++ = comma;
+ opleft--;
+ }
+ if (opleft < 1)
+ goto toobig;
+
+ }
+ return (optbuf);
+ toobig:
+ warning("dhcp option too large");
+ return ("<error>");
+}
+
+void
+do_packet(struct interface_info *interface, struct dhcp_packet *packet,
+ int len, unsigned int from_port, struct iaddr from, struct hardware *hfrom)
+{
+ struct packet tp;
+ int i;
+
+ if (packet->hlen > sizeof(packet->chaddr)) {
+ note("Discarding packet with invalid hlen.");
+ return;
+ }
+
+ memset(&tp, 0, sizeof(tp));
+ tp.raw = packet;
+ tp.packet_length = len;
+ tp.client_port = from_port;
+ tp.client_addr = from;
+ tp.interface = interface;
+ tp.haddr = hfrom;
+
+ parse_options(&tp);
+ if (tp.options_valid &&
+ tp.options[DHO_DHCP_MESSAGE_TYPE].data)
+ tp.packet_type = tp.options[DHO_DHCP_MESSAGE_TYPE].data[0];
+ if (tp.packet_type)
+ dhcp(&tp);
+ else
+ bootp(&tp);
+
+ /* Free the data associated with the options. */
+ for (i = 0; i < 256; i++)
+ if (tp.options[i].len && tp.options[i].data)
+ free(tp.options[i].data);
+}
--- /dev/null
+/* $Id: $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: subsys/system/dhcp/pipe.c
+ * PURPOSE: DHCP client pipe
+ * PROGRAMMER: arty
+ */
+
+#include <rosdhcp.h>
+
+#define NDEBUG
+#include <reactos/debug.h>
+
+static HANDLE CommPipe = INVALID_HANDLE_VALUE, CommThread;
+DWORD CommThrId;
+
+#define COMM_PIPE_OUTPUT_BUFFER sizeof(COMM_DHCP_REQ)
+#define COMM_PIPE_INPUT_BUFFER sizeof(COMM_DHCP_REPLY)
+#define COMM_PIPE_DEFAULT_TIMEOUT 1000
+
+DWORD PipeSend( COMM_DHCP_REPLY *Reply ) {
+ DWORD Written = 0;
+ BOOL Success =
+ WriteFile( CommPipe,
+ Reply,
+ sizeof(*Reply),
+ &Written,
+ NULL );
+ return Success ? Written : -1;
+}
+
+DWORD WINAPI PipeThreadProc( LPVOID Parameter ) {
+ DWORD BytesRead, BytesWritten;
+ COMM_DHCP_REQ Req;
+ COMM_DHCP_REPLY Reply;
+ BOOL Result, Connected;
+
+ while( TRUE ) {
+ Connected = ConnectNamedPipe( CommPipe, NULL ) ?
+ TRUE : GetLastError() == ERROR_PIPE_CONNECTED;
+
+ if (!Connected) {
+ DbgPrint("DHCP: Could not connect named pipe\n");
+ CloseHandle( CommPipe );
+ CommPipe = INVALID_HANDLE_VALUE;
+ break;
+ }
+
+ Result = ReadFile( CommPipe, &Req, sizeof(Req), &BytesRead, NULL );
+ if( Result ) {
+ switch( Req.Type ) {
+ case DhcpReqQueryHWInfo:
+ BytesWritten = DSQueryHWInfo( PipeSend, &Req );
+ break;
+
+ case DhcpReqLeaseIpAddress:
+ BytesWritten = DSLeaseIpAddress( PipeSend, &Req );
+ break;
+
+ case DhcpReqReleaseIpAddress:
+ BytesWritten = DSReleaseIpAddressLease( PipeSend, &Req );
+ break;
+
+ case DhcpReqRenewIpAddress:
+ BytesWritten = DSRenewIpAddressLease( PipeSend, &Req );
+ break;
+
+ case DhcpReqStaticRefreshParams:
+ BytesWritten = DSStaticRefreshParams( PipeSend, &Req );
+ break;
+
+ case DhcpReqGetAdapterInfo:
+ BytesWritten = DSGetAdapterInfo( PipeSend, &Req );
+ break;
+
+ default:
+ DPRINT1("Unrecognized request type %d\n", Req.Type);
+ ZeroMemory( &Reply, sizeof( COMM_DHCP_REPLY ) );
+ Reply.Reply = 0;
+ BytesWritten = PipeSend( &Reply );
+ break;
+ }
+ }
+ DisconnectNamedPipe( CommPipe );
+ }
+
+ return TRUE;
+}
+
+HANDLE PipeInit() {
+ CommPipe = CreateNamedPipeW
+ ( DHCP_PIPE_NAME,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ 1,
+ COMM_PIPE_OUTPUT_BUFFER,
+ COMM_PIPE_INPUT_BUFFER,
+ COMM_PIPE_DEFAULT_TIMEOUT,
+ NULL );
+
+ if( CommPipe == INVALID_HANDLE_VALUE ) {
+ DbgPrint("DHCP: Could not create named pipe\n");
+ return CommPipe;
+ }
+
+ CommThread = CreateThread( NULL, 0, PipeThreadProc, NULL, 0, &CommThrId );
+
+ if( !CommThread ) {
+ CloseHandle( CommPipe );
+ CommPipe = INVALID_HANDLE_VALUE;
+ }
+
+ return CommPipe;
+}
+
+VOID PipeDestroy() {
+ CloseHandle( CommPipe );
+ CommPipe = INVALID_HANDLE_VALUE;
+}
--- /dev/null
+#include "rosdhcp.h"
+
+SOCKET ServerSocket;
+
+void SocketInit() {
+ ServerSocket = socket( AF_INET, SOCK_DGRAM, 0 );
+}
+
+ssize_t send_packet( struct interface_info *ip,
+ struct dhcp_packet *p,
+ size_t size,
+ struct in_addr addr,
+ struct sockaddr_in *broadcast,
+ struct hardware *hardware ) {
+ int result =
+ sendto( ip->wfdesc, (char *)p, size, 0,
+ (struct sockaddr *)broadcast, sizeof(*broadcast) );
+
+ if (result < 0) {
+ note ("send_packet: %x", result);
+ if (result == WSAENETUNREACH)
+ note ("send_packet: please consult README file%s",
+ " regarding broadcast address.");
+ }
+
+ return result;
+}
+
+ssize_t receive_packet(struct interface_info *ip,
+ unsigned char *packet_data,
+ size_t packet_len,
+ struct sockaddr_in *dest,
+ struct hardware *hardware ) {
+ int recv_addr_size = sizeof(*dest);
+ int result =
+ recvfrom (ip -> rfdesc, (char *)packet_data, packet_len, 0,
+ (struct sockaddr *)dest, &recv_addr_size );
+ return result;
+}
--- /dev/null
+/* tables.c
+
+ Tables of information... */
+
+/*
+ * Copyright (c) 1995, 1996 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''.
+ */
+#define lint
+#ifndef lint
+static char copyright[] =
+"$Id: tables.c,v 1.13.2.4 1999/04/24 16:46:44 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "rosdhcp.h"
+
+/* DHCP Option names, formats and codes, from RFC1533.
+
+ Format codes:
+
+ e - end of data
+ I - IP address
+ l - 32-bit signed integer
+ L - 32-bit unsigned integer
+ s - 16-bit signed integer
+ S - 16-bit unsigned integer
+ b - 8-bit signed integer
+ B - 8-bit unsigned integer
+ t - ASCII text
+ f - flag (true or false)
+ A - array of whatever precedes (e.g., IA means array of IP addresses)
+*/
+
+struct universe dhcp_universe;
+struct dhcp_option dhcp_options [256] = {
+ { "pad", "", &dhcp_universe, 0 },
+ { "subnet-mask", "I", &dhcp_universe, 1 },
+ { "time-offset", "l", &dhcp_universe, 2 },
+ { "routers", "IA", &dhcp_universe, 3 },
+ { "time-servers", "IA", &dhcp_universe, 4 },
+ { "ien116-name-servers", "IA", &dhcp_universe, 5 },
+ { "domain-name-servers", "IA", &dhcp_universe, 6 },
+ { "log-servers", "IA", &dhcp_universe, 7 },
+ { "cookie-servers", "IA", &dhcp_universe, 8 },
+ { "lpr-servers", "IA", &dhcp_universe, 9 },
+ { "impress-servers", "IA", &dhcp_universe, 10 },
+ { "resource-location-servers", "IA", &dhcp_universe, 11 },
+ { "host-name", "X", &dhcp_universe, 12 },
+ { "boot-size", "S", &dhcp_universe, 13 },
+ { "merit-dump", "t", &dhcp_universe, 14 },
+ { "domain-name", "t", &dhcp_universe, 15 },
+ { "swap-server", "I", &dhcp_universe, 16 },
+ { "root-path", "t", &dhcp_universe, 17 },
+ { "extensions-path", "t", &dhcp_universe, 18 },
+ { "ip-forwarding", "f", &dhcp_universe, 19 },
+ { "non-local-source-routing", "f", &dhcp_universe, 20 },
+ { "policy-filter", "IIA", &dhcp_universe, 21 },
+ { "max-dgram-reassembly", "S", &dhcp_universe, 22 },
+ { "default-ip-ttl", "B", &dhcp_universe, 23 },
+ { "path-mtu-aging-timeout", "L", &dhcp_universe, 24 },
+ { "path-mtu-plateau-table", "SA", &dhcp_universe, 25 },
+ { "interface-mtu", "S", &dhcp_universe, 26 },
+ { "all-subnets-local", "f", &dhcp_universe, 27 },
+ { "broadcast-address", "I", &dhcp_universe, 28 },
+ { "perform-mask-discovery", "f", &dhcp_universe, 29 },
+ { "mask-supplier", "f", &dhcp_universe, 30 },
+ { "router-discovery", "f", &dhcp_universe, 31 },
+ { "router-solicitation-address", "I", &dhcp_universe, 32 },
+ { "static-routes", "IIA", &dhcp_universe, 33 },
+ { "trailer-encapsulation", "f", &dhcp_universe, 34 },
+ { "arp-cache-timeout", "L", &dhcp_universe, 35 },
+ { "ieee802-3-encapsulation", "f", &dhcp_universe, 36 },
+ { "default-tcp-ttl", "B", &dhcp_universe, 37 },
+ { "tcp-keepalive-interval", "L", &dhcp_universe, 38 },
+ { "tcp-keepalive-garbage", "f", &dhcp_universe, 39 },
+ { "nis-domain", "t", &dhcp_universe, 40 },
+ { "nis-servers", "IA", &dhcp_universe, 41 },
+ { "ntp-servers", "IA", &dhcp_universe, 42 },
+ { "vendor-encapsulated-options", "X", &dhcp_universe, 43 },
+ { "netbios-name-servers", "IA", &dhcp_universe, 44 },
+ { "netbios-dd-server", "IA", &dhcp_universe, 45 },
+ { "netbios-node-type", "B", &dhcp_universe, 46 },
+ { "netbios-scope", "t", &dhcp_universe, 47 },
+ { "font-servers", "IA", &dhcp_universe, 48 },
+ { "x-display-manager", "IA", &dhcp_universe, 49 },
+ { "dhcp-requested-address", "I", &dhcp_universe, 50 },
+ { "dhcp-lease-time", "L", &dhcp_universe, 51 },
+ { "dhcp-option-overload", "B", &dhcp_universe, 52 },
+ { "dhcp-message-type", "B", &dhcp_universe, 53 },
+ { "dhcp-server-identifier", "I", &dhcp_universe, 54 },
+ { "dhcp-parameter-request-list", "BA", &dhcp_universe, 55 },
+ { "dhcp-message", "t", &dhcp_universe, 56 },
+ { "dhcp-max-message-size", "S", &dhcp_universe, 57 },
+ { "dhcp-renewal-time", "L", &dhcp_universe, 58 },
+ { "dhcp-rebinding-time", "L", &dhcp_universe, 59 },
+ { "dhcp-class-identifier", "t", &dhcp_universe, 60 },
+ { "dhcp-client-identifier", "X", &dhcp_universe, 61 },
+ { "option-62", "X", &dhcp_universe, 62 },
+ { "option-63", "X", &dhcp_universe, 63 },
+ { "nisplus-domain", "t", &dhcp_universe, 64 },
+ { "nisplus-servers", "IA", &dhcp_universe, 65 },
+ { "tftp-server-name", "t", &dhcp_universe, 66 },
+ { "bootfile-name", "t", &dhcp_universe, 67 },
+ { "mobile-ip-home-agent", "IA", &dhcp_universe, 68 },
+ { "smtp-server", "IA", &dhcp_universe, 69 },
+ { "pop-server", "IA", &dhcp_universe, 70 },
+ { "nntp-server", "IA", &dhcp_universe, 71 },
+ { "www-server", "IA", &dhcp_universe, 72 },
+ { "finger-server", "IA", &dhcp_universe, 73 },
+ { "irc-server", "IA", &dhcp_universe, 74 },
+ { "streettalk-server", "IA", &dhcp_universe, 75 },
+ { "streettalk-directory-assistance-server", "IA", &dhcp_universe, 76 },
+ { "user-class", "t", &dhcp_universe, 77 },
+ { "option-78", "X", &dhcp_universe, 78 },
+ { "option-79", "X", &dhcp_universe, 79 },
+ { "option-80", "X", &dhcp_universe, 80 },
+ { "option-81", "X", &dhcp_universe, 81 },
+ { "option-82", "X", &dhcp_universe, 82 },
+ { "option-83", "X", &dhcp_universe, 83 },
+ { "option-84", "X", &dhcp_universe, 84 },
+ { "nds-servers", "IA", &dhcp_universe, 85 },
+ { "nds-tree-name", "X", &dhcp_universe, 86 },
+ { "nds-context", "X", &dhcp_universe, 87 },
+ { "option-88", "X", &dhcp_universe, 88 },
+ { "option-89", "X", &dhcp_universe, 89 },
+ { "option-90", "X", &dhcp_universe, 90 },
+ { "option-91", "X", &dhcp_universe, 91 },
+ { "option-92", "X", &dhcp_universe, 92 },
+ { "option-93", "X", &dhcp_universe, 93 },
+ { "option-94", "X", &dhcp_universe, 94 },
+ { "option-95", "X", &dhcp_universe, 95 },
+ { "option-96", "X", &dhcp_universe, 96 },
+ { "option-97", "X", &dhcp_universe, 97 },
+ { "option-98", "X", &dhcp_universe, 98 },
+ { "option-99", "X", &dhcp_universe, 99 },
+ { "option-100", "X", &dhcp_universe, 100 },
+ { "option-101", "X", &dhcp_universe, 101 },
+ { "option-102", "X", &dhcp_universe, 102 },
+ { "option-103", "X", &dhcp_universe, 103 },
+ { "option-104", "X", &dhcp_universe, 104 },
+ { "option-105", "X", &dhcp_universe, 105 },
+ { "option-106", "X", &dhcp_universe, 106 },
+ { "option-107", "X", &dhcp_universe, 107 },
+ { "option-108", "X", &dhcp_universe, 108 },
+ { "option-109", "X", &dhcp_universe, 109 },
+ { "option-110", "X", &dhcp_universe, 110 },
+ { "option-111", "X", &dhcp_universe, 111 },
+ { "option-112", "X", &dhcp_universe, 112 },
+ { "option-113", "X", &dhcp_universe, 113 },
+ { "option-114", "X", &dhcp_universe, 114 },
+ { "option-115", "X", &dhcp_universe, 115 },
+ { "option-116", "X", &dhcp_universe, 116 },
+ { "option-117", "X", &dhcp_universe, 117 },
+ { "option-118", "X", &dhcp_universe, 118 },
+ { "option-119", "X", &dhcp_universe, 119 },
+ { "option-120", "X", &dhcp_universe, 120 },
+ { "option-121", "X", &dhcp_universe, 121 },
+ { "option-122", "X", &dhcp_universe, 122 },
+ { "option-123", "X", &dhcp_universe, 123 },
+ { "option-124", "X", &dhcp_universe, 124 },
+ { "option-125", "X", &dhcp_universe, 125 },
+ { "option-126", "X", &dhcp_universe, 126 },
+ { "option-127", "X", &dhcp_universe, 127 },
+ { "option-128", "X", &dhcp_universe, 128 },
+ { "option-129", "X", &dhcp_universe, 129 },
+ { "option-130", "X", &dhcp_universe, 130 },
+ { "option-131", "X", &dhcp_universe, 131 },
+ { "option-132", "X", &dhcp_universe, 132 },
+ { "option-133", "X", &dhcp_universe, 133 },
+ { "option-134", "X", &dhcp_universe, 134 },
+ { "option-135", "X", &dhcp_universe, 135 },
+ { "option-136", "X", &dhcp_universe, 136 },
+ { "option-137", "X", &dhcp_universe, 137 },
+ { "option-138", "X", &dhcp_universe, 138 },
+ { "option-139", "X", &dhcp_universe, 139 },
+ { "option-140", "X", &dhcp_universe, 140 },
+ { "option-141", "X", &dhcp_universe, 141 },
+ { "option-142", "X", &dhcp_universe, 142 },
+ { "option-143", "X", &dhcp_universe, 143 },
+ { "option-144", "X", &dhcp_universe, 144 },
+ { "option-145", "X", &dhcp_universe, 145 },
+ { "option-146", "X", &dhcp_universe, 146 },
+ { "option-147", "X", &dhcp_universe, 147 },
+ { "option-148", "X", &dhcp_universe, 148 },
+ { "option-149", "X", &dhcp_universe, 149 },
+ { "option-150", "X", &dhcp_universe, 150 },
+ { "option-151", "X", &dhcp_universe, 151 },
+ { "option-152", "X", &dhcp_universe, 152 },
+ { "option-153", "X", &dhcp_universe, 153 },
+ { "option-154", "X", &dhcp_universe, 154 },
+ { "option-155", "X", &dhcp_universe, 155 },
+ { "option-156", "X", &dhcp_universe, 156 },
+ { "option-157", "X", &dhcp_universe, 157 },
+ { "option-158", "X", &dhcp_universe, 158 },
+ { "option-159", "X", &dhcp_universe, 159 },
+ { "option-160", "X", &dhcp_universe, 160 },
+ { "option-161", "X", &dhcp_universe, 161 },
+ { "option-162", "X", &dhcp_universe, 162 },
+ { "option-163", "X", &dhcp_universe, 163 },
+ { "option-164", "X", &dhcp_universe, 164 },
+ { "option-165", "X", &dhcp_universe, 165 },
+ { "option-166", "X", &dhcp_universe, 166 },
+ { "option-167", "X", &dhcp_universe, 167 },
+ { "option-168", "X", &dhcp_universe, 168 },
+ { "option-169", "X", &dhcp_universe, 169 },
+ { "option-170", "X", &dhcp_universe, 170 },
+ { "option-171", "X", &dhcp_universe, 171 },
+ { "option-172", "X", &dhcp_universe, 172 },
+ { "option-173", "X", &dhcp_universe, 173 },
+ { "option-174", "X", &dhcp_universe, 174 },
+ { "option-175", "X", &dhcp_universe, 175 },
+ { "option-176", "X", &dhcp_universe, 176 },
+ { "option-177", "X", &dhcp_universe, 177 },
+ { "option-178", "X", &dhcp_universe, 178 },
+ { "option-179", "X", &dhcp_universe, 179 },
+ { "option-180", "X", &dhcp_universe, 180 },
+ { "option-181", "X", &dhcp_universe, 181 },
+ { "option-182", "X", &dhcp_universe, 182 },
+ { "option-183", "X", &dhcp_universe, 183 },
+ { "option-184", "X", &dhcp_universe, 184 },
+ { "option-185", "X", &dhcp_universe, 185 },
+ { "option-186", "X", &dhcp_universe, 186 },
+ { "option-187", "X", &dhcp_universe, 187 },
+ { "option-188", "X", &dhcp_universe, 188 },
+ { "option-189", "X", &dhcp_universe, 189 },
+ { "option-190", "X", &dhcp_universe, 190 },
+ { "option-191", "X", &dhcp_universe, 191 },
+ { "option-192", "X", &dhcp_universe, 192 },
+ { "option-193", "X", &dhcp_universe, 193 },
+ { "option-194", "X", &dhcp_universe, 194 },
+ { "option-195", "X", &dhcp_universe, 195 },
+ { "option-196", "X", &dhcp_universe, 196 },
+ { "option-197", "X", &dhcp_universe, 197 },
+ { "option-198", "X", &dhcp_universe, 198 },
+ { "option-199", "X", &dhcp_universe, 199 },
+ { "option-200", "X", &dhcp_universe, 200 },
+ { "option-201", "X", &dhcp_universe, 201 },
+ { "option-202", "X", &dhcp_universe, 202 },
+ { "option-203", "X", &dhcp_universe, 203 },
+ { "option-204", "X", &dhcp_universe, 204 },
+ { "option-205", "X", &dhcp_universe, 205 },
+ { "option-206", "X", &dhcp_universe, 206 },
+ { "option-207", "X", &dhcp_universe, 207 },
+ { "option-208", "X", &dhcp_universe, 208 },
+ { "option-209", "X", &dhcp_universe, 209 },
+ { "option-210", "X", &dhcp_universe, 210 },
+ { "option-211", "X", &dhcp_universe, 211 },
+ { "option-212", "X", &dhcp_universe, 212 },
+ { "option-213", "X", &dhcp_universe, 213 },
+ { "option-214", "X", &dhcp_universe, 214 },
+ { "option-215", "X", &dhcp_universe, 215 },
+ { "option-216", "X", &dhcp_universe, 216 },
+ { "option-217", "X", &dhcp_universe, 217 },
+ { "option-218", "X", &dhcp_universe, 218 },
+ { "option-219", "X", &dhcp_universe, 219 },
+ { "option-220", "X", &dhcp_universe, 220 },
+ { "option-221", "X", &dhcp_universe, 221 },
+ { "option-222", "X", &dhcp_universe, 222 },
+ { "option-223", "X", &dhcp_universe, 223 },
+ { "option-224", "X", &dhcp_universe, 224 },
+ { "option-225", "X", &dhcp_universe, 225 },
+ { "option-226", "X", &dhcp_universe, 226 },
+ { "option-227", "X", &dhcp_universe, 227 },
+ { "option-228", "X", &dhcp_universe, 228 },
+ { "option-229", "X", &dhcp_universe, 229 },
+ { "option-230", "X", &dhcp_universe, 230 },
+ { "option-231", "X", &dhcp_universe, 231 },
+ { "option-232", "X", &dhcp_universe, 232 },
+ { "option-233", "X", &dhcp_universe, 233 },
+ { "option-234", "X", &dhcp_universe, 234 },
+ { "option-235", "X", &dhcp_universe, 235 },
+ { "option-236", "X", &dhcp_universe, 236 },
+ { "option-237", "X", &dhcp_universe, 237 },
+ { "option-238", "X", &dhcp_universe, 238 },
+ { "option-239", "X", &dhcp_universe, 239 },
+ { "option-240", "X", &dhcp_universe, 240 },
+ { "option-241", "X", &dhcp_universe, 241 },
+ { "option-242", "X", &dhcp_universe, 242 },
+ { "option-243", "X", &dhcp_universe, 243 },
+ { "option-244", "X", &dhcp_universe, 244 },
+ { "option-245", "X", &dhcp_universe, 245 },
+ { "option-246", "X", &dhcp_universe, 246 },
+ { "option-247", "X", &dhcp_universe, 247 },
+ { "option-248", "X", &dhcp_universe, 248 },
+ { "option-249", "X", &dhcp_universe, 249 },
+ { "option-250", "X", &dhcp_universe, 250 },
+ { "option-251", "X", &dhcp_universe, 251 },
+ { "option-252", "X", &dhcp_universe, 252 },
+ { "option-253", "X", &dhcp_universe, 253 },
+ { "option-254", "X", &dhcp_universe, 254 },
+ { "option-end", "e", &dhcp_universe, 255 },
+};
+
+/* Default dhcp option priority list (this is ad hoc and should not be
+ mistaken for a carefully crafted and optimized list). */
+unsigned char dhcp_option_default_priority_list [] = {
+ DHO_DHCP_REQUESTED_ADDRESS,
+ DHO_DHCP_OPTION_OVERLOAD,
+ DHO_DHCP_MAX_MESSAGE_SIZE,
+ DHO_DHCP_RENEWAL_TIME,
+ DHO_DHCP_REBINDING_TIME,
+ DHO_DHCP_CLASS_IDENTIFIER,
+ DHO_DHCP_CLIENT_IDENTIFIER,
+ DHO_SUBNET_MASK,
+ DHO_TIME_OFFSET,
+ DHO_ROUTERS,
+ DHO_TIME_SERVERS,
+ DHO_NAME_SERVERS,
+ DHO_DOMAIN_NAME_SERVERS,
+ DHO_HOST_NAME,
+ DHO_LOG_SERVERS,
+ DHO_COOKIE_SERVERS,
+ DHO_LPR_SERVERS,
+ DHO_IMPRESS_SERVERS,
+ DHO_RESOURCE_LOCATION_SERVERS,
+ DHO_HOST_NAME,
+ DHO_BOOT_SIZE,
+ DHO_MERIT_DUMP,
+ DHO_DOMAIN_NAME,
+ DHO_SWAP_SERVER,
+ DHO_ROOT_PATH,
+ DHO_EXTENSIONS_PATH,
+ DHO_IP_FORWARDING,
+ DHO_NON_LOCAL_SOURCE_ROUTING,
+ DHO_POLICY_FILTER,
+ DHO_MAX_DGRAM_REASSEMBLY,
+ DHO_DEFAULT_IP_TTL,
+ DHO_PATH_MTU_AGING_TIMEOUT,
+ DHO_PATH_MTU_PLATEAU_TABLE,
+ DHO_INTERFACE_MTU,
+ DHO_ALL_SUBNETS_LOCAL,
+ DHO_BROADCAST_ADDRESS,
+ DHO_PERFORM_MASK_DISCOVERY,
+ DHO_MASK_SUPPLIER,
+ DHO_ROUTER_DISCOVERY,
+ DHO_ROUTER_SOLICITATION_ADDRESS,
+ DHO_STATIC_ROUTES,
+ DHO_TRAILER_ENCAPSULATION,
+ DHO_ARP_CACHE_TIMEOUT,
+ DHO_IEEE802_3_ENCAPSULATION,
+ DHO_DEFAULT_TCP_TTL,
+ DHO_TCP_KEEPALIVE_INTERVAL,
+ DHO_TCP_KEEPALIVE_GARBAGE,
+ DHO_NIS_DOMAIN,
+ DHO_NIS_SERVERS,
+ DHO_NTP_SERVERS,
+ DHO_VENDOR_ENCAPSULATED_OPTIONS,
+ DHO_NETBIOS_NAME_SERVERS,
+ DHO_NETBIOS_DD_SERVER,
+ DHO_NETBIOS_NODE_TYPE,
+ DHO_NETBIOS_SCOPE,
+ DHO_FONT_SERVERS,
+ DHO_X_DISPLAY_MANAGER,
+ DHO_DHCP_PARAMETER_REQUEST_LIST,
+
+ /* Presently-undefined options... */
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+ 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
+ 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+ 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
+ 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
+ 251, 252, 253, 254,
+};
+
+int sizeof_dhcp_option_default_priority_list =
+ sizeof dhcp_option_default_priority_list;
+
+
+char *hardware_types [] = {
+ "unknown-0",
+ "ethernet",
+ "unknown-2",
+ "unknown-3",
+ "unknown-4",
+ "unknown-5",
+ "token-ring",
+ "unknown-7",
+ "fddi",
+ "unknown-9",
+ "unknown-10",
+ "unknown-11",
+ "unknown-12",
+ "unknown-13",
+ "unknown-14",
+ "unknown-15",
+ "unknown-16",
+ "unknown-17",
+ "unknown-18",
+ "unknown-19",
+ "unknown-20",
+ "unknown-21",
+ "unknown-22",
+ "unknown-23",
+ "unknown-24",
+ "unknown-25",
+ "unknown-26",
+ "unknown-27",
+ "unknown-28",
+ "unknown-29",
+ "unknown-30",
+ "unknown-31",
+ "unknown-32",
+ "unknown-33",
+ "unknown-34",
+ "unknown-35",
+ "unknown-36",
+ "unknown-37",
+ "unknown-38",
+ "unknown-39",
+ "unknown-40",
+ "unknown-41",
+ "unknown-42",
+ "unknown-43",
+ "unknown-44",
+ "unknown-45",
+ "unknown-46",
+ "unknown-47",
+ "unknown-48",
+ "unknown-49",
+ "unknown-50",
+ "unknown-51",
+ "unknown-52",
+ "unknown-53",
+ "unknown-54",
+ "unknown-55",
+ "unknown-56",
+ "unknown-57",
+ "unknown-58",
+ "unknown-59",
+ "unknown-60",
+ "unknown-61",
+ "unknown-62",
+ "unknown-63",
+ "unknown-64",
+ "unknown-65",
+ "unknown-66",
+ "unknown-67",
+ "unknown-68",
+ "unknown-69",
+ "unknown-70",
+ "unknown-71",
+ "unknown-72",
+ "unknown-73",
+ "unknown-74",
+ "unknown-75",
+ "unknown-76",
+ "unknown-77",
+ "unknown-78",
+ "unknown-79",
+ "unknown-80",
+ "unknown-81",
+ "unknown-82",
+ "unknown-83",
+ "unknown-84",
+ "unknown-85",
+ "unknown-86",
+ "unknown-87",
+ "unknown-88",
+ "unknown-89",
+ "unknown-90",
+ "unknown-91",
+ "unknown-92",
+ "unknown-93",
+ "unknown-94",
+ "unknown-95",
+ "unknown-96",
+ "unknown-97",
+ "unknown-98",
+ "unknown-99",
+ "unknown-100",
+ "unknown-101",
+ "unknown-102",
+ "unknown-103",
+ "unknown-104",
+ "unknown-105",
+ "unknown-106",
+ "unknown-107",
+ "unknown-108",
+ "unknown-109",
+ "unknown-110",
+ "unknown-111",
+ "unknown-112",
+ "unknown-113",
+ "unknown-114",
+ "unknown-115",
+ "unknown-116",
+ "unknown-117",
+ "unknown-118",
+ "unknown-119",
+ "unknown-120",
+ "unknown-121",
+ "unknown-122",
+ "unknown-123",
+ "unknown-124",
+ "unknown-125",
+ "unknown-126",
+ "unknown-127",
+ "unknown-128",
+ "unknown-129",
+ "unknown-130",
+ "unknown-131",
+ "unknown-132",
+ "unknown-133",
+ "unknown-134",
+ "unknown-135",
+ "unknown-136",
+ "unknown-137",
+ "unknown-138",
+ "unknown-139",
+ "unknown-140",
+ "unknown-141",
+ "unknown-142",
+ "unknown-143",
+ "unknown-144",
+ "unknown-145",
+ "unknown-146",
+ "unknown-147",
+ "unknown-148",
+ "unknown-149",
+ "unknown-150",
+ "unknown-151",
+ "unknown-152",
+ "unknown-153",
+ "unknown-154",
+ "unknown-155",
+ "unknown-156",
+ "unknown-157",
+ "unknown-158",
+ "unknown-159",
+ "unknown-160",
+ "unknown-161",
+ "unknown-162",
+ "unknown-163",
+ "unknown-164",
+ "unknown-165",
+ "unknown-166",
+ "unknown-167",
+ "unknown-168",
+ "unknown-169",
+ "unknown-170",
+ "unknown-171",
+ "unknown-172",
+ "unknown-173",
+ "unknown-174",
+ "unknown-175",
+ "unknown-176",
+ "unknown-177",
+ "unknown-178",
+ "unknown-179",
+ "unknown-180",
+ "unknown-181",
+ "unknown-182",
+ "unknown-183",
+ "unknown-184",
+ "unknown-185",
+ "unknown-186",
+ "unknown-187",
+ "unknown-188",
+ "unknown-189",
+ "unknown-190",
+ "unknown-191",
+ "unknown-192",
+ "unknown-193",
+ "unknown-194",
+ "unknown-195",
+ "unknown-196",
+ "unknown-197",
+ "unknown-198",
+ "unknown-199",
+ "unknown-200",
+ "unknown-201",
+ "unknown-202",
+ "unknown-203",
+ "unknown-204",
+ "unknown-205",
+ "unknown-206",
+ "unknown-207",
+ "unknown-208",
+ "unknown-209",
+ "unknown-210",
+ "unknown-211",
+ "unknown-212",
+ "unknown-213",
+ "unknown-214",
+ "unknown-215",
+ "unknown-216",
+ "unknown-217",
+ "unknown-218",
+ "unknown-219",
+ "unknown-220",
+ "unknown-221",
+ "unknown-222",
+ "unknown-223",
+ "unknown-224",
+ "unknown-225",
+ "unknown-226",
+ "unknown-227",
+ "unknown-228",
+ "unknown-229",
+ "unknown-230",
+ "unknown-231",
+ "unknown-232",
+ "unknown-233",
+ "unknown-234",
+ "unknown-235",
+ "unknown-236",
+ "unknown-237",
+ "unknown-238",
+ "unknown-239",
+ "unknown-240",
+ "unknown-241",
+ "unknown-242",
+ "unknown-243",
+ "unknown-244",
+ "unknown-245",
+ "unknown-246",
+ "unknown-247",
+ "unknown-248",
+ "unknown-249",
+ "unknown-250",
+ "unknown-251",
+ "unknown-252",
+ "unknown-253",
+ "unknown-254",
+ "unknown-255" };
+
+
+
+struct hash_table universe_hash;
+
+void initialize_universes()
+{
+ int i;
+
+ dhcp_universe.name = "dhcp";
+ dhcp_universe.hash = new_hash ();
+ if (!dhcp_universe.hash)
+ error ("Can't allocate dhcp option hash table.");
+ for (i = 0; i < 256; i++) {
+ dhcp_universe.options [i] = &dhcp_options [i];
+ add_hash (dhcp_universe.hash,
+ (unsigned char *)dhcp_options [i].name, 0,
+ (unsigned char *)&dhcp_options [i]);
+ }
+ universe_hash.hash_count = DEFAULT_HASH_SIZE;
+ add_hash (&universe_hash,
+ (unsigned char *)dhcp_universe.name, 0,
+ (unsigned char *)&dhcp_universe);
+}
--- /dev/null
+/* tree.c
+
+ Routines for manipulating parse trees... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997 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''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: tree.c,v 1.10 1997/05/09 08:14:57 mellon Exp $ Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "rosdhcp.h"
+
+static TIME tree_evaluate_recurse PROTO ((int *, unsigned char **, int *,
+ struct tree *));
+static TIME do_host_lookup PROTO ((int *, unsigned char **, int *,
+ struct dns_host_entry *));
+static void do_data_copy PROTO ((int *, unsigned char **, int *,
+ unsigned char *, int));
+
+pair cons (car, cdr)
+ caddr_t car;
+ pair cdr;
+{
+ pair foo = (pair)dmalloc (sizeof *foo, "cons");
+ if (!foo)
+ error ("no memory for cons.");
+ foo -> car = car;
+ foo -> cdr = cdr;
+ return foo;
+}
+
+struct tree_cache *tree_cache (tree)
+ struct tree *tree;
+{
+ struct tree_cache *tc;
+
+ tc = new_tree_cache ("tree_cache");
+ if (!tc)
+ return 0;
+ tc -> value = (unsigned char *)0;
+ tc -> len = tc -> buf_size = 0;
+ tc -> timeout = 0;
+ tc -> tree = tree;
+ return tc;
+}
+
+struct tree *tree_host_lookup (name)
+ char *name;
+{
+ struct tree *nt;
+ nt = new_tree ("tree_host_lookup");
+ if (!nt)
+ error ("No memory for host lookup tree node.");
+ nt -> op = TREE_HOST_LOOKUP;
+ nt -> data.host_lookup.host = enter_dns_host (name);
+ return nt;
+}
+
+struct dns_host_entry *enter_dns_host (name)
+ char *name;
+{
+ struct dns_host_entry *dh;
+
+ if (!(dh = (struct dns_host_entry *)dmalloc
+ (sizeof (struct dns_host_entry), "enter_dns_host"))
+ || !(dh -> hostname = dmalloc (strlen (name) + 1,
+ "enter_dns_host")))
+ error ("Can't allocate space for new host.");
+ strcpy (dh -> hostname, name);
+ dh -> data = (unsigned char *)0;
+ dh -> data_len = 0;
+ dh -> buf_len = 0;
+ dh -> timeout = 0;
+ return dh;
+}
+
+struct tree *tree_const (data, len)
+ unsigned char *data;
+ int len;
+{
+ struct tree *nt;
+ if (!(nt = new_tree ("tree_const"))
+ || !(nt -> data.const_val.data =
+ (unsigned char *)dmalloc (len, "tree_const")))
+ error ("No memory for constant data tree node.");
+ nt -> op = TREE_CONST;
+ memcpy (nt -> data.const_val.data, data, len);
+ nt -> data.const_val.len = len;
+ return nt;
+}
+
+struct tree *tree_concat (left, right)
+ struct tree *left, *right;
+{
+ struct tree *nt;
+
+ /* If we're concatenating a null tree to a non-null tree, just
+ return the non-null tree; if both trees are null, return
+ a null tree. */
+ if (!left)
+ return right;
+ if (!right)
+ return left;
+
+ /* If both trees are constant, combine them. */
+ if (left -> op == TREE_CONST && right -> op == TREE_CONST) {
+ unsigned char *buf = dmalloc (left -> data.const_val.len
+ + right -> data.const_val.len,
+ "tree_concat");
+ if (!buf)
+ error ("No memory to concatenate constants.");
+ memcpy (buf, left -> data.const_val.data,
+ left -> data.const_val.len);
+ memcpy (buf + left -> data.const_val.len,
+ right -> data.const_val.data,
+ right -> data.const_val.len);
+ dfree (left -> data.const_val.data, "tree_concat");
+ dfree (right -> data.const_val.data, "tree_concat");
+ left -> data.const_val.data = buf;
+ left -> data.const_val.len += right -> data.const_val.len;
+ free_tree (right, "tree_concat");
+ return left;
+ }
+
+ /* Otherwise, allocate a new node to concatenate the two. */
+ if (!(nt = new_tree ("tree_concat")))
+ error ("No memory for data tree concatenation node.");
+ nt -> op = TREE_CONCAT;
+ nt -> data.concat.left = left;
+ nt -> data.concat.right = right;
+ return nt;
+}
+
+struct tree *tree_limit (tree, limit)
+ struct tree *tree;
+ int limit;
+{
+ struct tree *rv;
+
+ /* If the tree we're limiting is constant, limit it now. */
+ if (tree -> op == TREE_CONST) {
+ if (tree -> data.const_val.len > limit)
+ tree -> data.const_val.len = limit;
+ return tree;
+ }
+
+ /* Otherwise, put in a node which enforces the limit on evaluation. */
+ rv = new_tree ("tree_limit");
+ if (!rv)
+ return (struct tree *)0;
+ rv -> op = TREE_LIMIT;
+ rv -> data.limit.tree = tree;
+ rv -> data.limit.limit = limit;
+ return rv;
+}
+
+int tree_evaluate (tree_cache)
+ struct tree_cache *tree_cache;
+{
+ unsigned char *bp = tree_cache -> value;
+ int bc = tree_cache -> buf_size;
+ int bufix = 0;
+
+ /* If there's no tree associated with this cache, it evaluates
+ to a constant and that was detected at startup. */
+ if (!tree_cache -> tree)
+ return 1;
+
+ /* Try to evaluate the tree without allocating more memory... */
+ tree_cache -> timeout = tree_evaluate_recurse (&bufix, &bp, &bc,
+ tree_cache -> tree);
+
+ /* No additional allocation needed? */
+ if (bufix <= bc) {
+ tree_cache -> len = bufix;
+ return 1;
+ }
+
+ /* If we can't allocate more memory, return with what we
+ have (maybe nothing). */
+ if (!(bp = (unsigned char *)dmalloc (bufix, "tree_evaluate")))
+ return 0;
+
+ /* Record the change in conditions... */
+ bc = bufix;
+ bufix = 0;
+
+ /* Note that the size of the result shouldn't change on the
+ second call to tree_evaluate_recurse, since we haven't
+ changed the ``current'' time. */
+ tree_evaluate_recurse (&bufix, &bp, &bc, tree_cache -> tree);
+
+ /* Free the old buffer if needed, then store the new buffer
+ location and size and return. */
+ if (tree_cache -> value)
+ dfree (tree_cache -> value, "tree_evaluate");
+ tree_cache -> value = bp;
+ tree_cache -> len = bufix;
+ tree_cache -> buf_size = bc;
+ return 1;
+}
+
+static TIME tree_evaluate_recurse (bufix, bufp, bufcount, tree)
+ int *bufix;
+ unsigned char **bufp;
+ int *bufcount;
+ struct tree *tree;
+{
+ int limit;
+ TIME t1, t2;
+
+ switch (tree -> op) {
+ case TREE_CONCAT:
+ t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
+ tree -> data.concat.left);
+ t2 = tree_evaluate_recurse (bufix, bufp, bufcount,
+ tree -> data.concat.right);
+ if (t1 > t2)
+ return t2;
+ return t1;
+
+ case TREE_HOST_LOOKUP:
+ return do_host_lookup (bufix, bufp, bufcount,
+ tree -> data.host_lookup.host);
+
+ case TREE_CONST:
+ do_data_copy (bufix, bufp, bufcount,
+ tree -> data.const_val.data,
+ tree -> data.const_val.len);
+ t1 = MAX_TIME;
+ return t1;
+
+ case TREE_LIMIT:
+ limit = *bufix + tree -> data.limit.limit;
+ t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
+ tree -> data.limit.tree);
+ *bufix = limit;
+ return t1;
+
+ default:
+ warn ("Bad node id in tree: %d.");
+ t1 = MAX_TIME;
+ return t1;
+ }
+}
+
+static TIME do_host_lookup (bufix, bufp, bufcount, dns)
+ int *bufix;
+ unsigned char **bufp;
+ int *bufcount;
+ struct dns_host_entry *dns;
+{
+ struct hostent *h;
+ int i;
+ int new_len;
+
+#ifdef DEBUG_EVAL
+ debug ("time: now = %d dns = %d %d diff = %d",
+ cur_time, dns -> timeout, cur_time - dns -> timeout);
+#endif
+
+ /* If the record hasn't timed out, just copy the data and return. */
+ if (cur_time <= dns -> timeout) {
+#ifdef DEBUG_EVAL
+ debug ("easy copy: %x %d %x",
+ dns -> data, dns -> data_len,
+ dns -> data ? *(int *)(dns -> data) : 0);
+#endif
+ do_data_copy (bufix, bufp, bufcount,
+ dns -> data, dns -> data_len);
+ return dns -> timeout;
+ }
+#ifdef DEBUG_EVAL
+ debug ("Looking up %s", dns -> hostname);
+#endif
+
+ /* Otherwise, look it up... */
+ h = gethostbyname (dns -> hostname);
+ if (!h) {
+#ifndef NO_H_ERRNO
+ switch (h_errno) {
+ case HOST_NOT_FOUND:
+#endif
+ warn ("%s: host unknown.", dns -> hostname);
+#ifndef NO_H_ERRNO
+ break;
+ case TRY_AGAIN:
+ warn ("%s: temporary name server failure",
+ dns -> hostname);
+ break;
+ case NO_RECOVERY:
+ warn ("%s: name server failed", dns -> hostname);
+ break;
+ case NO_DATA:
+ warn ("%s: no A record associated with address",
+ dns -> hostname);
+ }
+#endif /* !NO_H_ERRNO */
+
+ /* Okay to try again after a minute. */
+ return cur_time + 60;
+ }
+
+#ifdef DEBUG_EVAL
+ debug ("Lookup succeeded; first address is %x",
+ h -> h_addr_list [0]);
+#endif
+
+ /* Count the number of addresses we got... */
+ for (i = 0; h -> h_addr_list [i]; i++)
+ ;
+
+ /* Do we need to allocate more memory? */
+ new_len = i * h -> h_length;
+ if (dns -> buf_len < i) {
+ unsigned char *buf =
+ (unsigned char *)dmalloc (new_len, "do_host_lookup");
+ /* If we didn't get more memory, use what we have. */
+ if (!buf) {
+ new_len = dns -> buf_len;
+ if (!dns -> buf_len) {
+ dns -> timeout = cur_time + 60;
+ return dns -> timeout;
+ }
+ } else {
+ if (dns -> data)
+ dfree (dns -> data, "do_host_lookup");
+ dns -> data = buf;
+ dns -> buf_len = new_len;
+ }
+ }
+
+ /* Addresses are conveniently stored one to the buffer, so we
+ have to copy them out one at a time... :'( */
+ for (i = 0; i < new_len / h -> h_length; i++) {
+ memcpy (dns -> data + h -> h_length * i,
+ h -> h_addr_list [i], h -> h_length);
+ }
+#ifdef DEBUG_EVAL
+ debug ("dns -> data: %x h -> h_addr_list [0]: %x",
+ *(int *)(dns -> data), h -> h_addr_list [0]);
+#endif
+ dns -> data_len = new_len;
+
+ /* Set the timeout for an hour from now.
+ XXX This should really use the time on the DNS reply. */
+ dns -> timeout = cur_time + 3600;
+
+#ifdef DEBUG_EVAL
+ debug ("hard copy: %x %d %x",
+ dns -> data, dns -> data_len, *(int *)(dns -> data));
+#endif
+ do_data_copy (bufix, bufp, bufcount, dns -> data, dns -> data_len);
+ return dns -> timeout;
+}
+
+static void do_data_copy (bufix, bufp, bufcount, data, len)
+ int *bufix;
+ unsigned char **bufp;
+ int *bufcount;
+ unsigned char *data;
+ int len;
+{
+ int space = *bufcount - *bufix;
+
+ /* If there's more space than we need, use only what we need. */
+ if (space > len)
+ space = len;
+
+ /* Copy as much data as will fit, then increment the buffer index
+ by the amount we actually had to copy, which could be more. */
+ if (space > 0)
+ memcpy (*bufp + *bufix, data, space);
+ *bufix += len;
+}
--- /dev/null
+#include <stdarg.h>
+#include "rosdhcp.h"
+
+#define NDEBUG
+#include <reactos/debug.h>
+
+char *piaddr( struct iaddr addr ) {
+ struct sockaddr_in sa;
+ memcpy(&sa.sin_addr,addr.iabuf,sizeof(sa.sin_addr));
+ return inet_ntoa( sa.sin_addr );
+}
+
+int note( char *format, ... ) {
+ char buf[0x100];
+ int ret;
+ va_list arg_begin;
+ va_start( arg_begin, format );
+
+ ret = _vsnprintf( buf, sizeof(buf), format, arg_begin );
+
+ DPRINT("NOTE: %s\n", buf);
+
+ return ret;
+}
+
+int debug( char *format, ... ) {
+ char buf[0x100];
+ int ret;
+ va_list arg_begin;
+ va_start( arg_begin, format );
+
+ ret = _vsnprintf( buf, sizeof(buf), format, arg_begin );
+
+ DPRINT("DEBUG: %s\n", buf);
+
+ return ret;
+}
+
+int warn( char *format, ... ) {
+ char buf[0x100];
+ int ret;
+ va_list arg_begin;
+ va_start( arg_begin, format );
+
+ ret = _vsnprintf( buf, sizeof(buf), format, arg_begin );
+
+ DPRINT("WARN: %s\n", buf);
+
+ return ret;
+}
+
+int warning( char *format, ... ) {
+ char buf[0x100];
+ int ret;
+ va_list arg_begin;
+ va_start( arg_begin, format );
+
+ ret = _vsnprintf( buf, sizeof(buf), format, arg_begin );
+
+ DPRINT("WARNING: %s\n", buf);
+
+ return ret;
+}
+
+void error( char *format, ... ) {
+ char buf[0x100];
+ va_list arg_begin;
+ va_start( arg_begin, format );
+
+ _vsnprintf( buf, sizeof(buf), format, arg_begin );
+
+ DPRINT1("ERROR: %s\n", buf);
+}
+
+int16_t getShort( unsigned char *data ) {
+ return (int16_t) ntohs(*(int16_t*) data);
+}
+
+u_int16_t getUShort( unsigned char *data ) {
+ return (u_int16_t) ntohs(*(u_int16_t*) data);
+}
+
+int32_t getLong( unsigned char *data ) {
+ return (int32_t) ntohl(*(u_int32_t*) data);
+}
+
+u_int32_t getULong( unsigned char *data ) {
+ return ntohl(*(u_int32_t*)data);
+}
+
+int addr_eq( struct iaddr a, struct iaddr b ) {
+ return a.len == b.len && !memcmp( a.iabuf, b.iabuf, a.len );
+}
+
+void *dmalloc( int size, char *name ) { return malloc( size ); }
+
+int read_client_conf(struct interface_info *ifi) {
+ /* What a strange dance */
+ struct client_config *config;
+ char ComputerName [MAX_COMPUTERNAME_LENGTH + 1];
+ LPSTR lpCompName;
+ DWORD ComputerNameSize = sizeof ComputerName / sizeof ComputerName[0];
+
+ if ((ifi!= NULL) && (ifi->client->config != NULL))
+ config = ifi->client->config;
+ else
+ {
+ warn("util.c read_client_conf poorly implemented!");
+ return 0;
+ }
+
+
+ GetComputerName(ComputerName, & ComputerNameSize);
+ debug("Hostname: %s, length: %lu",
+ ComputerName, ComputerNameSize);
+ /* This never gets freed since it's only called once */
+ lpCompName =
+ HeapAlloc(GetProcessHeap(), 0, ComputerNameSize + 1);
+ if (lpCompName !=NULL) {
+ memcpy(lpCompName, ComputerName, ComputerNameSize + 1);
+ /* Send our hostname, some dhcpds use this to update DNS */
+ config->send_options[DHO_HOST_NAME].data = (u_int8_t*)lpCompName;
+ config->send_options[DHO_HOST_NAME].len = ComputerNameSize;
+ debug("Hostname: %s, length: %d",
+ config->send_options[DHO_HOST_NAME].data,
+ config->send_options[DHO_HOST_NAME].len);
+ } else {
+ error("Failed to allocate heap for hostname");
+ }
+ /* Both Linux and Windows send this */
+ config->send_options[DHO_DHCP_CLIENT_IDENTIFIER].data =
+ ifi->hw_address.haddr;
+ config->send_options[DHO_DHCP_CLIENT_IDENTIFIER].len =
+ ifi->hw_address.hlen;
+
+ /* Setup the requested option list */
+ config->requested_options
+ [config->requested_option_count++] = DHO_SUBNET_MASK;
+ config->requested_options
+ [config->requested_option_count++] = DHO_BROADCAST_ADDRESS;
+ config->requested_options
+ [config->requested_option_count++] = DHO_TIME_OFFSET;
+ config->requested_options
+ [config->requested_option_count++] = DHO_ROUTERS;
+ config->requested_options
+ [config->requested_option_count++] = DHO_DOMAIN_NAME;
+ config->requested_options
+ [config->requested_option_count++] = DHO_DOMAIN_NAME_SERVERS;
+ config->requested_options
+ [config->requested_option_count++] = DHO_HOST_NAME;
+ config->requested_options
+ [config->requested_option_count++] = DHO_NTP_SERVERS;
+
+ warn("util.c read_client_conf poorly implemented!");
+ return 0;
+}
+
+struct iaddr broadcast_addr( struct iaddr addr, struct iaddr mask ) {
+ struct iaddr bcast = { 0 };
+ return bcast;
+}
+
+struct iaddr subnet_number( struct iaddr addr, struct iaddr mask ) {
+ struct iaddr bcast = { 0 };
+ return bcast;
+}
#include "iphlpapi_private.h"
#include "dhcp.h"
+#include "dhcpcsdk.h"
+#include "dhcpcapi.h"
#include <assert.h>
#define NDEBUG
time_t *LeaseObtained,
time_t *LeaseExpires)
{
- return DhcpRosGetAdapterInfo(AdapterIndex, DhcpEnabled, DhcpServer,
- LeaseObtained, LeaseExpires);
+ DWORD Status, Version = 0;
+
+ Status = DhcpCApiInitialize(&Version);
+ if (Status == ERROR_NOT_READY)
+ {
+ /* The DHCP server isn't running yet */
+ *DhcpEnabled = FALSE;
+ *DhcpServer = htonl(INADDR_NONE);
+ *LeaseObtained = 0;
+ *LeaseExpires = 0;
+ return ERROR_SUCCESS;
+ }
+ else if (Status != ERROR_SUCCESS)
+ {
+ return Status;
+ }
+
+ Status = DhcpRosGetAdapterInfo(AdapterIndex, DhcpEnabled, DhcpServer,
+ LeaseObtained, LeaseExpires);
+
+ DhcpCApiCleanup();
+
+ return Status;
}
<importlibrary definition="iphlpapi.spec" />
<include base="iphlpapi">.</include>
<include base="ReactOS">include/reactos/wine</include>
- <include base="dhcp">include</include>
+ <include base="dhcpcsvc">include</include>
<include base="tdilib">.</include>
<library>wine</library>
<library>ntdll</library>
#include "route.h"
#include "wine/debug.h"
#include "dhcpcsdk.h"
-#include "dhcp/rosdhcp_public.h"
+#include "dhcpcapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
+ DWORD Version;
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls( hinstDLL );
*/
DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
{
- COMM_DHCP_REPLY Reply;
- COMM_DHCP_REQ Request;
- DWORD BytesRead;
+ DWORD Status, Version = 0;
- Request.AdapterIndex = AdapterInfo->Index;
- Request.Type = DhcpReqReleaseIpAddress;
+ if (!AdapterInfo || !AdapterInfo->Name)
+ return ERROR_INVALID_PARAMETER;
- TRACE("AdapterInfo %p\n", AdapterInfo);
+ /* Maybe we should do this in DllMain */
+ if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS)
+ return ERROR_PROC_NOT_FOUND;
- if (CallNamedPipe(DHCP_PIPE_NAME,
- &Request,
- sizeof(Request),
- &Reply,
- sizeof(Reply),
- &BytesRead,
- NMPWAIT_USE_DEFAULT_WAIT))
- {
- if (Reply.Reply)
- return NO_ERROR;
+ if (DhcpReleaseIpAddressLease(AdapterInfo->Index))
+ Status = ERROR_SUCCESS;
+ else
+ Status = ERROR_PROC_NOT_FOUND;
- return ERROR_INVALID_PARAMETER;
- }
+ DhcpCApiCleanup();
- return ERROR_PROC_NOT_FOUND;
+ return Status;
}
*/
DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
{
- COMM_DHCP_REPLY Reply;
- COMM_DHCP_REQ Request;
- DWORD BytesRead;
+ DWORD Status, Version = 0;
- Request.AdapterIndex = AdapterInfo->Index;
- Request.Type = DhcpReqRenewIpAddress;
+ if (!AdapterInfo || !AdapterInfo->Name)
+ return ERROR_INVALID_PARAMETER;
- TRACE("AdapterInfo %p\n", AdapterInfo);
+ /* Maybe we should do this in DllMain */
+ if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS)
+ return ERROR_PROC_NOT_FOUND;
- if (CallNamedPipe(DHCP_PIPE_NAME,
- &Request,
- sizeof(Request),
- &Reply,
- sizeof(Reply),
- &BytesRead,
- NMPWAIT_USE_DEFAULT_WAIT))
- {
- if (Reply.Reply)
- return NO_ERROR;
+ if (DhcpRenewIpAddressLease(AdapterInfo->Index))
+ Status = ERROR_SUCCESS;
+ else
+ Status = ERROR_PROC_NOT_FOUND;
- return ERROR_INVALID_PARAMETER;
- }
+ DhcpCApiCleanup();
- return ERROR_PROC_NOT_FOUND;
+ return Status;
}
#ifndef _DHCPCAPI_H
#define _DHCPCAPI_H
-#include <windows.h>
-#include <accctrl.h>
-
#ifdef __cplusplus
extern "C" {
#endif
- VOID WINAPI DhcpLeaseIpAddress( ULONG AdapterIndex );
- VOID WINAPI DhcpReleaseIpAddressLease( ULONG AdapterIndex );
- VOID WINAPI DhcpStaticRefreshParams
- ( ULONG AdapterIndex, ULONG IpAddress, ULONG NetMask );
+DWORD APIENTRY DhcpLeaseIpAddress( DWORD AdapterIndex );
+DWORD APIENTRY DhcpQueryHWInfo( DWORD AdapterIndex,
+ PDWORD MediaType,
+ PDWORD Mtu,
+ PDWORD Speed );
+DWORD APIENTRY DhcpReleaseIpAddressLease( DWORD AdapterIndex );
+DWORD APIENTRY DhcpRenewIpAddressLease( DWORD AdapterIndex );
+DWORD APIENTRY DhcpStaticRefreshParams( DWORD AdapterIndex,
+ DWORD Address,
+ DWORD Netmask );
+DWORD APIENTRY
+DhcpNotifyConfigChange(LPWSTR ServerName,
+ LPWSTR AdapterName,
+ BOOL NewIpAddress,
+ DWORD IpIndex,
+ DWORD IpAddress,
+ DWORD SubnetMask,
+ int DhcpAction);
+DWORD APIENTRY DhcpRosGetAdapterInfo( DWORD AdapterIndex,
+ PBOOL DhcpEnabled,
+ PDWORD DhcpServer,
+ time_t *LeaseObtained,
+ time_t *LeaseExpires );
#ifdef __cplusplus
}