Create a branch for header work.

svn path=/branches/header-work/; revision=45691
This commit is contained in:
Timo Kreuzer 2010-02-26 22:57:55 +00:00
parent 14fe274b1c
commit 9ea495ba33
19538 changed files with 0 additions and 1063950 deletions

View file

@ -0,0 +1,61 @@
/*
* PROJECT: ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/services/audiosrv/audiosrv.h
* PURPOSE: Audio Service (private header)
* COPYRIGHT: Copyright 2007 Andrew Greenwood
*/
#include <dbt.h>
#include <audiosrv/audiosrv.h>
#ifndef AUDIOSRV_PRIVATE_H
#define AUDIOSRV_PRIVATE_H
extern SERVICE_STATUS_HANDLE service_status_handle;
/* List management (pnp_list_manager.c) */
VOID*
CreateDeviceDescriptor(WCHAR* path, BOOL is_enabled);
#define DestroyDeviceDescriptor(descriptor) free(descriptor)
BOOL
AppendAudioDeviceToList(PnP_AudioDevice* device);
BOOL
CreateAudioDeviceList(DWORD max_size);
VOID
DestroyAudioDeviceList();
/* Plug and Play (pnp.c) */
BOOL
ProcessExistingDevices();
DWORD
ProcessDeviceArrival(DEV_BROADCAST_DEVICEINTERFACE* device);
BOOL
RegisterForDeviceNotifications();
VOID
UnregisterDeviceNotifications();
DWORD
HandleDeviceEvent(
DWORD dwEventType,
LPVOID lpEventData);
BOOL
StartSystemAudioServices();
/* Debugging */
void logmsg(char* string, ...);
#endif

View file

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="audiosrv" type="win32cui" installbase="system32" installname="audiosrv.exe" unicode="yes">
<include base="audiosrv">.</include>
<library>advapi32</library>
<library>user32</library>
<library>setupapi</library>
<file>main.c</file>
<file>pnp_list_manager.c</file>
<file>pnp_list_lock.c</file>
<file>pnp.c</file>
<file>services.c</file>
<file>debug.c</file>
<file>audiosrv.rc</file>
</module>

View file

@ -0,0 +1,4 @@
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Audio Service"
#define REACTOS_STR_INTERNAL_NAME "audiosrv\0"
#define REACTOS_STR_ORIGINAL_FILENAME "audiosrv.dll\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,74 @@
ReactOS Audio Service (audiosrv.exe)
====================================
This is intended to operate in a similar manner to how the Windows Audio
Service does.
NOTE: The service filename is audiosrv.dll on Windows XP. This shouldn't
have any impact on functionality.
AudioSrv on Windows creates a mapped file at:
Global\mmGlobalPnpInfo
The ReactOS audio device list lives at:
Global\AudioDeviceList
This file appears to contain a list of devices that WinMM accesses and
subsequently passes to wdmaud.drv
It is not necessary to duplicate the exact structure of this mapped
file, since it appears to only be used internally by Windows components.
The ROS Audio Service (RosAudioSrv) is intended to be able to run
alongside the Windows Audio Service on XP/Vista, so it should be
possible to test in a "known working environment" ;)
It will create a mutex, to:
1) Allow synchronization when accessing the device list
2) Provide a simple method of identifying if RosAudioSrv is running
(It might be worth using an event to notify WinMM when things are
happening?)
The intention is to make RosAudioSrv receive PnP notifications for
relevant audio devices, and also let AudioSrv in Windows do this. Then
it should be possible to create a small application that imitates
WinMM's actions :)
Current Status
==============
AudioSrv registers for device notifications and obtains a list of the
current audio devices in the system (devices registered against the
KSCATEGORY_AUDIO interface).
ReactOS does not currently have RegisterDeviceNotification implemented,
so for the moment this service considers the failure of this API call
to be non-fatal and will proceed without device event notification. This
behaviour will be amended in a future revision (ie once this API call
is implemented!)
Testing the Service
===================
The service can be installed on Windows XP (possibly also Vista) like so:
sc create RosAudioSrv <path to audiosrv.exe>
net start RosAudioSrv
...and can be removed like so:
net stop RosAudioSrv
sc delete RosAudioSrv
You can view a list of the currently available devices (device list is
identical to the one offered by Windows' own AudioSrv) by running
my READER.EXE test utility, available in the following package:
http://stuff.silverblade.co.uk/reactos/sharedlist.tar.gz
That's all for now, folks ;)
Andrew Greenwood
September 2007

View file

@ -0,0 +1,28 @@
/* Service debugging (simply logs to a file) */
#include <stdio.h>
#include <stdarg.h>
#include <windows.h>
void logmsg(char* string, ...)
{
va_list args;
FILE* debug_file = fopen("c:\\audiosrv-debug.txt", "a");
if (debug_file)
{
va_start(args, string);
vfprintf(debug_file, string, args);
va_end(args);
fclose(debug_file);
}
else
{
char buf[256];
va_start(args, string);
vsprintf(buf, string, args);
OutputDebugStringA(buf);
va_end(args);
}
}

View file

@ -0,0 +1,175 @@
/*
* PROJECT: ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/services/audiosrv/main.c
* PURPOSE: Audio Service
* COPYRIGHT: Copyright 2007 Andrew Greenwood
*/
#include <windows.h>
#include <audiosrv/audiosrv.h>
#include "audiosrv.h"
SERVICE_STATUS_HANDLE service_status_handle;
SERVICE_STATUS service_status;
/* This is for testing only! */
VOID
InitializeFakeDevice()
{
PnP_AudioDevice* list_node;
list_node = CreateDeviceDescriptor(L"ThisDeviceDoesNotReallyExist", TRUE);
AppendAudioDeviceToList(list_node);
DestroyDeviceDescriptor(list_node);
}
DWORD WINAPI
ServiceControlHandler(
DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext)
{
switch ( dwControl )
{
case SERVICE_CONTROL_INTERROGATE :
{
logmsg("* Interrogation\n");
return NO_ERROR;
}
case SERVICE_CONTROL_STOP :
case SERVICE_CONTROL_SHUTDOWN :
{
logmsg("* Service Stop/Shutdown request received\n");
logmsg("Unregistering device notifications\n");
UnregisterDeviceNotifications();
logmsg("Destroying audio device list\n");
DestroyAudioDeviceList();
service_status.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(service_status_handle, &service_status);
service_status.dwWin32ExitCode = 0;
service_status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(service_status_handle, &service_status);
logmsg("* Service stopped\n");
return NO_ERROR;
}
case SERVICE_CONTROL_DEVICEEVENT :
{
logmsg("* Device Event\n");
return HandleDeviceEvent(dwEventType, lpEventData);
}
default :
return ERROR_CALL_NOT_IMPLEMENTED;
};
/*SetServiceStatus(service_status_handle, &service_status);*/
}
VOID CALLBACK
ServiceMain(DWORD argc, LPWSTR argv)
{
logmsg("* Service starting\n");
logmsg("Registering service control handler...\n");
service_status_handle = RegisterServiceCtrlHandlerExW(SERVICE_NAME,
ServiceControlHandler,
NULL);
logmsg("Service status handle %d\n", service_status_handle);
if ( ! service_status_handle )
{
logmsg("Failed to register service control handler\n");
/* FIXME - we should fail */
}
/* Set these to defaults */
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
service_status.dwServiceSpecificExitCode = 0;
service_status.dwWin32ExitCode = NO_ERROR;
service_status.dwWaitHint = 0;
service_status.dwControlsAccepted = 0;
service_status.dwCheckPoint = 0;
/* Tell SCM we're starting */
service_status.dwCurrentState = SERVICE_START_PENDING;
SetServiceStatus(service_status_handle, &service_status);
logmsg("Creating audio device list\n");
/* This creates the audio device list and mutex */
if ( ! CreateAudioDeviceList(AUDIO_LIST_MAX_SIZE) )
{
logmsg("Failed to create audio device list\n");
service_status.dwCurrentState = SERVICE_STOPPED;
service_status.dwWin32ExitCode = -1;
SetServiceStatus(service_status_handle, &service_status);
return;
}
logmsg("Registering for device notifications\n");
/* We want to know when devices are added/removed */
if ( ! RegisterForDeviceNotifications() )
{
/* FIXME: This is not fatal at present as ROS does not support this */
logmsg("Failed to register for device notifications\n");
/*
DestroyAudioDeviceList();
service_status.dwCurrentState = SERVICE_STOPPED;
service_status.dwWin32ExitCode = -1;
SetServiceStatus(service_status_handle, &service_status);
return;
*/
}
/* start system audio services */
StartSystemAudioServices();
InitializeFakeDevice();
logmsg("Processing existing devices\n");
/* Now find any devices that already exist on the system */
if ( ! ProcessExistingDevices() )
{
logmsg("Could not process existing devices\n");
UnregisterDeviceNotifications();
DestroyAudioDeviceList();
service_status.dwCurrentState = SERVICE_STOPPED;
service_status.dwWin32ExitCode = -1;
SetServiceStatus(service_status_handle, &service_status);
return;
}
logmsg("* Service started");
/* Tell SCM we are now running, and we may be stopped */
service_status.dwCurrentState = SERVICE_RUNNING;
service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
SetServiceStatus(service_status_handle, &service_status);
}
int wmain()
{
SERVICE_TABLE_ENTRYW service_table[] =
{
{ SERVICE_NAME, (LPSERVICE_MAIN_FUNCTIONW) ServiceMain },
{ NULL, NULL }
};
logmsg("Audio Service main()\n");
if (!StartServiceCtrlDispatcherW(service_table))
logmsg("StartServiceCtrlDispatcher failed\n");
return 0;
}

View file

@ -0,0 +1,200 @@
/*
* PROJECT: ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/services/audiosrv/pnp.c
* PURPOSE: Audio Service Plug and Play
* COPYRIGHT: Copyright 2007 Andrew Greenwood
*/
#include <windows.h>
#include <winuser.h>
#include <dbt.h>
#include <setupapi.h>
#include <ks.h>
#include <ksmedia.h>
#include <audiosrv/audiosrv.h>
#include "audiosrv.h"
static HDEVNOTIFY device_notification_handle = NULL;
/*
Finds all devices within the KSCATEGORY_AUDIO category and puts them
in the shared device list.
*/
BOOL
ProcessExistingDevices()
{
SP_DEVICE_INTERFACE_DATA interface_data;
SP_DEVINFO_DATA device_data;
PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail_data;
HDEVINFO dev_info;
DWORD length;
int index = 0;
const GUID category_guid = {STATIC_KSCATEGORY_AUDIO};
dev_info = SetupDiGetClassDevsExW(&category_guid,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE,
NULL,
NULL,
NULL);
/* printf("%s:\n", ClassString); */
interface_data.cbSize = sizeof(interface_data);
interface_data.Reserved = 0;
/* Enumerate the devices within the category */
index = 0;
length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)
+ (MAX_PATH * sizeof(WCHAR));
detail_data =
(PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(),
0,
length);
if ( ! detail_data )
{
logmsg("ProcessExistingDevices() failed to allocate detail_data\n");
return TRUE;
}
while (
SetupDiEnumDeviceInterfaces(dev_info,
NULL,
&category_guid,
index,
&interface_data) )
{
PnP_AudioDevice* list_node;
ZeroMemory(detail_data, length);
/* NOTE: We don't actually use device_data... */
detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
device_data.cbSize = sizeof(device_data);
device_data.Reserved = 0;
SetupDiGetDeviceInterfaceDetailW(dev_info,
&interface_data,
detail_data,
length,
NULL,
&device_data);
list_node = CreateDeviceDescriptor(detail_data->DevicePath, TRUE);
AppendAudioDeviceToList(list_node);
DestroyDeviceDescriptor(list_node);
/* TODO: Cleanup the device we enumerated? */
index ++;
};
HeapFree(GetProcessHeap(), 0, detail_data);
SetupDiDestroyDeviceInfoList(dev_info);
return TRUE;
}
/*
Add new devices to the list as they arrive.
*/
DWORD
ProcessDeviceArrival(DEV_BROADCAST_DEVICEINTERFACE* device)
{
PnP_AudioDevice* list_node;
list_node = CreateDeviceDescriptor(device->dbcc_name, TRUE);
AppendAudioDeviceToList(list_node);
DestroyDeviceDescriptor(list_node);
return NO_ERROR;
}
/*
Request notification of device additions/removals.
*/
BOOL
RegisterForDeviceNotifications()
{
DEV_BROADCAST_DEVICEINTERFACE notification_filter;
const GUID wdmaud_guid = {STATIC_KSCATEGORY_AUDIO};
ZeroMemory(&notification_filter, sizeof(notification_filter));
notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
notification_filter.dbcc_classguid = wdmaud_guid;
device_notification_handle =
RegisterDeviceNotificationW((HANDLE) service_status_handle,
&notification_filter,
DEVICE_NOTIFY_SERVICE_HANDLE
/* |
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES*/);
if ( ! device_notification_handle )
{
logmsg("RegisterDeviceNotification() failed with error %d\n", GetLastError());
}
return ( device_notification_handle != NULL );
}
/*
When we're not interested in device notifications any more, this gets
called.
*/
VOID UnregisterDeviceNotifications()
{
/* TODO -- NOT IMPLEMENTED! */
if ( device_notification_handle )
{
/* TODO */
device_notification_handle = NULL;
}
}
/*
Device events from the main service handler get passed to this.
*/
DWORD
HandleDeviceEvent(
DWORD dwEventType,
LPVOID lpEventData)
{
switch ( dwEventType )
{
case DBT_DEVICEARRIVAL :
{
DEV_BROADCAST_DEVICEINTERFACE* incoming_device =
(DEV_BROADCAST_DEVICEINTERFACE*) lpEventData;
return ProcessDeviceArrival(incoming_device);
}
default :
{
break;
}
}
return NO_ERROR;
}

View file

@ -0,0 +1,58 @@
/*
* PROJECT: ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/services/audiosrv/list_lock.c
* PURPOSE: Audio Service Plug and Play list locking mechanism
* COPYRIGHT: Copyright 2007 Andrew Greenwood
*/
#include <windows.h>
#include <assert.h>
#include <audiosrv/audiosrv.h>
static HANDLE audio_device_list_lock = NULL;
BOOL
InitializeAudioDeviceListLock()
{
/* The security stuff is to make sure the mutex can be grabbed by
other processes - is this the best idea though ??? */
SECURITY_DESCRIPTOR security_descriptor;
SECURITY_ATTRIBUTES security;
InitializeSecurityDescriptor(&security_descriptor, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&security_descriptor, TRUE, 0, FALSE);
security.nLength = sizeof(SECURITY_ATTRIBUTES);
security.lpSecurityDescriptor = &security_descriptor;
security.bInheritHandle = FALSE;
audio_device_list_lock = CreateMutex(&security,
FALSE,
AUDIO_LIST_LOCK_NAME);
return ( audio_device_list_lock != NULL );
}
VOID
KillAudioDeviceListLock()
{
CloseHandle(audio_device_list_lock);
audio_device_list_lock = NULL;
}
VOID
LockAudioDeviceList()
{
assert( audio_device_list_lock != NULL );
WaitForSingleObject(audio_device_list_lock, INFINITE);
}
VOID
UnlockAudioDeviceList()
{
assert( audio_device_list_lock != NULL );
ReleaseMutex(audio_device_list_lock);
}

View file

@ -0,0 +1,193 @@
/*
* PROJECT: ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/services/audiosrv/pnp_list_manager.c
* PURPOSE: Audio Service List Manager
* COPYRIGHT: Copyright 2007 Andrew Greenwood
*/
#include <assert.h>
#include <stdlib.h>
#include <audiosrv/audiosrv.h>
#include "audiosrv.h"
/*
Device descriptor
*/
VOID*
CreateDeviceDescriptor(WCHAR* path, BOOL is_enabled)
{
PnP_AudioDevice* device;
int path_length = WideStringSize(path);
int size = sizeof(PnP_AudioDevice) + path_length;
/* printf("path_length %d, total %d\n", path_length, size);*/
device = malloc(size);
if ( ! device )
{
logmsg("Failed to create a device descriptor (malloc fail)\n");
return NULL;
}
device->enabled = is_enabled;
memcpy(device->path, path, path_length);
return device;
}
/*
Device list (manager-side)
The device list is stored in some shared-memory, with a named, global
mutex to provide a locking mechanism (to avoid it from being updated
whilst being read).
*/
static HANDLE device_list_file = NULL;
static PnP_AudioHeader* audio_device_list = NULL;
/*
TODO: Detect duplicate entries and ignore them! (In case we receive
a PnP event for an existing device...)
*/
BOOL
AppendAudioDeviceToList(PnP_AudioDevice* device)
{
int device_info_size;
/* Figure out the actual structure size */
device_info_size = sizeof(PnP_AudioDevice);
device_info_size += WideStringSize(device->path);
LockAudioDeviceList();
/*
printf("list size is %d\n", audio_device_list->size);
printf("device info size is %d bytes\n", device_info_size);
*/
/* We DON'T want to overshoot the end of the buffer! */
if ( audio_device_list->size + device_info_size > audio_device_list->max_size )
{
/*printf("max_size would be exceeded! Failing...\n");*/
UnlockAudioDeviceList();
return FALSE;
}
/* Commit the device descriptor to the list */
memcpy((char*)audio_device_list + audio_device_list->size,
device,
device_info_size);
/* Update the header */
audio_device_list->device_count ++;
audio_device_list->size += device_info_size;
UnlockAudioDeviceList();
logmsg("Device added to list\n");
return TRUE;
}
BOOL
CreateAudioDeviceList(DWORD max_size)
{
/* printf("Initializing memory device list lock\n");*/
if ( ! InitializeAudioDeviceListLock() )
{
/*printf("Failed!\n");*/
return FALSE;
}
/* Preliminary locking - the list memory will likely be a big
buffer of gibberish at this point so we don't want anyone
turning up before we're ready... */
LockAudioDeviceList();
logmsg("Creating file mapping\n");
/* Expose our device list to the world */
device_list_file = CreateFileMappingW(INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
max_size,
AUDIO_LIST_NAME);
if ( ! device_list_file )
{
logmsg("Creation of audio device list failed (err %d)\n", GetLastError());
UnlockAudioDeviceList();
KillAudioDeviceListLock();
return FALSE;
}
logmsg("Mapping view of file\n");
/* Of course, we'll need to access the list ourselves */
audio_device_list = MapViewOfFile(device_list_file,
FILE_MAP_WRITE,
0,
0,
max_size);
if ( ! audio_device_list )
{
logmsg("MapViewOfFile FAILED (err %d)\n", GetLastError());
CloseHandle(device_list_file);
device_list_file = NULL;
UnlockAudioDeviceList();
KillAudioDeviceListLock();
return FALSE;
}
/* Clear the mem to avoid any random stray data */
memset(audio_device_list, 0, max_size);
/* Don't want devices to overwrite the list! */
audio_device_list->size = sizeof(PnP_AudioHeader);
audio_device_list->max_size = max_size;
audio_device_list->device_count = 0;
UnlockAudioDeviceList();
logmsg("Device list created\n");
return TRUE;
}
VOID
DestroyAudioDeviceList()
{
logmsg("Destroying device list\n");
LockAudioDeviceList();
/*printf("Unmapping view\n");*/
UnmapViewOfFile(audio_device_list);
audio_device_list = NULL;
/*printf("Closing memory mapped file\n");*/
CloseHandle(device_list_file);
device_list_file = NULL;
UnlockAudioDeviceList();
/*printf("Killing devlist lock\n");*/
KillAudioDeviceListLock();
}

View file

@ -0,0 +1,114 @@
/*
* PROJECT: ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/services/audiosrv/services.c
* PURPOSE: Audio Service Plug and Play
* COPYRIGHT: Copyright 2009 Johannes Anderwald
*/
#include <windows.h>
#include <winuser.h>
#include <dbt.h>
#include <setupapi.h>
#include <ks.h>
#include <ksmedia.h>
#include <audiosrv/audiosrv.h>
#include "audiosrv.h"
BOOL
WaitForService(
SC_HANDLE hService,
ULONG RetryCount)
{
ULONG Index = 0;
DWORD dwSize;
SERVICE_STATUS_PROCESS Info;
do
{
if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&Info, sizeof(SERVICE_STATUS_PROCESS), &dwSize))
{
logmsg("QueryServiceStatusEx failed %x\n", GetLastError());
break;
}
if (Info.dwCurrentState == SERVICE_RUNNING)
return TRUE;
Sleep(1000);
}while(Index++ < RetryCount);
logmsg("Timeout while waiting for service to become ready %p\n", hService);
return FALSE;
}
BOOL
StartAudioService(
SC_HANDLE hSCManager,
LPWSTR ServiceName,
ULONG RetryCount)
{
SC_HANDLE hService;
BOOL ret;
hService = OpenService(hSCManager, ServiceName, SERVICE_ALL_ACCESS);
if (!hService)
{
logmsg("Failed to open service %S %x\n", ServiceName, GetLastError());
return FALSE;
}
if (!StartService(hService, 0, NULL))
{
logmsg("Failed to start service %S %x\n", ServiceName, GetLastError());
CloseServiceHandle(hService);
return FALSE;
}
ret = WaitForService(hService, RetryCount);
CloseServiceHandle(hService);
return ret;
}
BOOL
StartSystemAudioServices()
{
SC_HANDLE hSCManager;
logmsg("Starting system audio services\n");
hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!hSCManager)
{
logmsg("Failed to open service manager %x\n", GetLastError());
return FALSE;
}
logmsg("Starting sysaudio service\n");
StartAudioService(hSCManager, L"sysaudio", 20);
logmsg("Starting wdmaud service\n");
StartAudioService(hSCManager, L"wdmaud", 20);
CloseServiceHandle(hSCManager);
return TRUE;
}

View file

@ -0,0 +1,446 @@
#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) {
}

View file

@ -0,0 +1,93 @@
/* $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);
}

197
base/services/dhcp/api.c Normal file
View file

@ -0,0 +1,197 @@
/* $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 );
}
/* 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 );
}

View file

@ -0,0 +1,67 @@
#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;
}

View file

@ -0,0 +1,33 @@
Acknowledgements:
Tinus provided the initial port of these dhclient file.
Ok I need these things:
1) Adapter concept thingy
Needs a name and index
Current IP address etc
interface_info
Must be able to get one from an adapter index or name
Must query the ip address and such
Must be able to set the address
2) System state doodad
List of adapters
List of parameter changes
List of persistent stuff
Must be able to initialize from the registry
(persistent stuff, some adapter info)
Save changes to persistent set
3) Parameter change set
TODO
4) Persistent queries
TODO

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="dhcp" type="win32cui" installbase="system32" installname="dhcp.exe">
<include base="dhcp">.</include>
<include base="dhcp">include</include>
<!-- FIXME: workarounds until we have a proper oldnames library -->
<define name="tzset">_tzset</define>
<define name="close">_close</define>
<define name="read">_read</define>
<define name="write">_write</define>
<library>ntdll</library>
<library>ws2_32</library>
<library>iphlpapi</library>
<library>advapi32</library>
<file>adapter.c</file>
<file>alloc.c</file>
<file>api.c</file>
<file>compat.c</file>
<file>dhclient.c</file>
<file>dispatch.c</file>
<file>hash.c</file>
<file>options.c</file>
<file>pipe.c</file>
<file>privsep.c</file>
<file>socket.c</file>
<file>tables.c</file>
<file>timer.c</file>
<file>util.c</file>
<file>dhcp.rc</file>
<directory name="include">
<pch>rosdhcp.h</pch>
</directory>
</module>

View file

@ -0,0 +1,6 @@
/* $Id: regsvr32.rc 12852 2005-01-06 13:58:04Z mf $ */
#define REACTOS_STR_FILE_DESCRIPTION "DHCP Client Service"
#define REACTOS_STR_INTERNAL_NAME "dhcp\0"
#define REACTOS_STR_ORIGINAL_FILENAME "dhcp.exe\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,72 @@
/* $Id:$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Service
* FILE: subsys/system/dhcp
* PURPOSE: DHCP client service entry point
* PROGRAMMER: Art Yerkes (arty@users.sf.net)
* UPDATE HISTORY:
* Created 03/08/2005
*/
#include <windows.h>
#include "dhcpd.h"
#include "version.h"
typedef struct _DHCP_API_REQUEST {
int type;
UINT flags;
LPDHCPAPI_CLASSID class_id;
DHCP_API_PARAMS_ARRAY vendor_params;
DHCP_API_PARAMS_ARRAY general_params;
LPWSTR request_id, adapter_name;
} DHCP_API_REQUEST;
typedef struct _DHCP_MANAGED_ADAPTER {
LPWSTR adapter_name, hostname, dns_server;
UINT adapter_index;
struct sockaddr_in address, netmask;
struct interface_info *dhcp_info;
} DHCP_MANAGED_ADAPTER;
#define DHCP_REQUESTPARAM WM_USER + 0
#define DHCP_PARAMCHANGE WM_USER + 1
#define DHCP_CANCELREQUEST WM_USER + 2
#define DHCP_NOPARAMCHANGE WM_USER + 3
#define DHCP_MANAGEADAPTER WM_USER + 4
#define DHCP_UNMANAGEADAPTER WM_USER + 5
UINT DhcpEventTimer;
HANDLE DhcpServiceThread;
DWORD DhcpServiceThreadId;
LIST_ENTRY ManagedAdapters;
LRESULT WINAPI ServiceThread( PVOID Data ) {
MSG msg;
while( GetMessage( &msg, 0, 0, 0 ) ) {
switch( msg.message ) {
case DHCP_MANAGEADAPTER:
break;
case DHCP_UNMANAGEADAPTER:
break;
case DHCP_REQUESTPARAM:
break;
case DHCP_CANCELREQUEST:
break;
case DHCP_PARAMCHANGE:
break;
case DHCP_NOPARAMCHANGE:
break;
}
}
}
int main( int argc, char **argv ) {
}

View file

@ -0,0 +1,356 @@
/* $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()) {
AdapterStop();
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(); /* Not reached currently */
}
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;
close(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);
}

165
base/services/dhcp/hash.c Normal file
View file

@ -0,0 +1,165 @@
/* 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;
}

View file

@ -0,0 +1,57 @@
/* cdefs.h
Standard C definitions... */
/*
* Copyright (c) 1996 The Internet Software Consortium.
* All Rights Reserved.
* Copyright (c) 1995 RadioMail Corporation. 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 RadioMail Corporation, 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 RADIOMAIL CORPORATION, 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 RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
* under a contract with Vixie Enterprises. Further modifications have
* been made for the Internet Software Consortium under a contract
* with Vixie Laboratories.
*/
#if (defined (__GNUC__) || defined (__STDC__)) && !defined (BROKEN_ANSI)
#define PROTO(x) x
#define KandR(x)
#define ANSI_DECL(x) x
#if defined (__GNUC__)
#define INLINE inline
#else
#define INLINE
#endif /* __GNUC__ */
#else
#define PROTO(x) ()
#define KandR(x) x
#define ANSI_DECL(x)
#define INLINE
#endif /* __GNUC__ || __STDC__ */

View file

@ -0,0 +1,51 @@
/*
* 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 */

View file

@ -0,0 +1,169 @@
/* $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

View file

@ -0,0 +1,485 @@
/* $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);

View file

@ -0,0 +1,136 @@
/* dhctoken.h
Tokens for config file lexer and parser. */
/*
* 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''.
*/
#define SEMI ';'
#define DOT '.'
#define COLON ':'
#define COMMA ','
#define SLASH '/'
#define LBRACE '{'
#define RBRACE '}'
#define FIRST_TOKEN HOST
#define HOST 256
#define HARDWARE 257
#define FILENAME 258
#define FIXED_ADDR 259
#define OPTION 260
#define ETHERNET 261
#define STRING 262
#define NUMBER 263
#define NUMBER_OR_NAME 264
#define NAME 265
#define TIMESTAMP 266
#define STARTS 267
#define ENDS 268
#define UID 269
#define CLASS 270
#define LEASE 271
#define RANGE 272
#define PACKET 273
#define CIADDR 274
#define YIADDR 275
#define SIADDR 276
#define GIADDR 277
#define SUBNET 278
#define NETMASK 279
#define DEFAULT_LEASE_TIME 280
#define MAX_LEASE_TIME 281
#define VENDOR_CLASS 282
#define USER_CLASS 283
#define SHARED_NETWORK 284
#define SERVER_NAME 285
#define DYNAMIC_BOOTP 286
#define SERVER_IDENTIFIER 287
#define DYNAMIC_BOOTP_LEASE_CUTOFF 288
#define DYNAMIC_BOOTP_LEASE_LENGTH 289
#define BOOT_UNKNOWN_CLIENTS 290
#define NEXT_SERVER 291
#define TOKEN_RING 292
#define GROUP 293
#define ONE_LEASE_PER_CLIENT 294
#define GET_LEASE_HOSTNAMES 295
#define USE_HOST_DECL_NAMES 296
#define SEND 297
#define CLIENT_IDENTIFIER 298
#define REQUEST 299
#define REQUIRE 300
#define TIMEOUT 301
#define RETRY 302
#define SELECT_TIMEOUT 303
#define SCRIPT 304
#define INTERFACE 305
#define RENEW 306
#define REBIND 307
#define EXPIRE 308
#define UNKNOWN_CLIENTS 309
#define ALLOW 310
#define BOOTP 311
#define DENY 312
#define BOOTING 313
#define DEFAULT 314
#define MEDIA 315
#define MEDIUM 316
#define ALIAS 317
#define REBOOT 318
#define ABANDONED 319
#define BACKOFF_CUTOFF 320
#define INITIAL_INTERVAL 321
#define NAMESERVER 322
#define DOMAIN 323
#define SEARCH 324
#define SUPERSEDE 325
#define APPEND 326
#define PREPEND 327
#define HOSTNAME 328
#define CLIENT_HOSTNAME 329
#define REJECT 330
#define FDDI 331
#define USE_LEASE_ADDR_FOR_DEFAULT_ROUTE 332
#define AUTHORITATIVE 333
#define TOKEN_NOT 334
#define ALWAYS_REPLY_RFC1048 335
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
(x) != STRING && \
(x) != NUMBER && \
(x) != EOF)

View file

@ -0,0 +1,56 @@
/* 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];
};

View file

@ -0,0 +1,52 @@
/* inet.h
Portable definitions for internet addresses */
/*
* Copyright (c) 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''.
*/
/* An internet address of up to 128 bits. */
typedef struct _iaddr {
int len;
unsigned char iabuf [16];
} iaddr;
typedef struct _iaddrlist {
struct _iaddrlist *next;
iaddr addr;
} iaddrlist;

View file

@ -0,0 +1,294 @@
/* osdep.h
Operating system dependencies... */
/*
* Copyright (c) 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 was written for the Internet Software Consortium by Ted Lemon
* under a contract with Vixie Laboratories.
*/
#include "site.h"
/* Porting::
If you add a new network API, you must add a check for it below: */
#if !defined (USE_SOCKETS) && \
!defined (USE_SOCKET_SEND) && \
!defined (USE_SOCKET_RECEIVE) && \
!defined (USE_RAW_SOCKETS) && \
!defined (USE_RAW_SEND) && \
!defined (USE_SOCKET_RECEIVE) && \
!defined (USE_BPF) && \
!defined (USE_BPF_SEND) && \
!defined (USE_BPF_RECEIVE) && \
!defined (USE_LPF) && \
!defined (USE_LPF_SEND) && \
!defined (USE_LPF_RECEIVE) && \
!defined (USE_NIT) && \
!defined (USE_NIT_SEND) && \
!defined (USE_NIT_RECEIVE) && \
!defined (USR_DLPI_SEND) && \
!defined (USE_DLPI_RECEIVE)
# define USE_DEFAULT_NETWORK
#endif
/* Porting::
If you add a new system configuration file, include it here: */
#if defined (sun)
# if defined (__svr4__) || defined (__SVR4)
# include "cf/sunos5-5.h"
# else
# include "cf/sunos4.h"
# endif
#endif
#ifdef aix
# include "cf/aix.h"
#endif
#ifdef bsdi
# include "cf/bsdos.h"
#endif
#ifdef __NetBSD__
# include "cf/netbsd.h"
#endif
#ifdef __FreeBSD__
# include "cf/freebsd.h"
#endif
#if defined (__osf__) && defined (__alpha)
# include "cf/alphaosf.h"
#endif
#ifdef ultrix
# include "cf/ultrix.h"
#endif
#ifdef linux
# include "cf/linux.h"
#endif
#ifdef SCO
# include "cf/sco.h"
#endif
#if defined (hpux) || defined (__hpux)
# include "cf/hpux.h"
#endif
#ifdef __QNX__
# include "cf/qnx.h"
#endif
#ifdef __CYGWIN32__
# include "cf/cygwin32.h"
#endif
#ifdef __APPLE__
# include "cf/rhapsody.h"
#else
# if defined (NeXT)
# include "cf/nextstep.h"
# endif
#endif
#if defined(IRIX) || defined(__sgi)
# include "cf/irix.h"
#endif
#if !defined (TIME_MAX)
# define TIME_MAX 2147483647
#endif
/* Porting::
If you add a new network API, and have it set up so that it can be
used for sending or receiving, but doesn't have to be used for both,
then set up an ifdef like the ones below: */
#ifdef USE_SOCKETS
# define USE_SOCKET_SEND
# define USE_SOCKET_RECEIVE
#endif
#ifdef USE_RAW_SOCKETS
# define USE_RAW_SEND
# define USE_SOCKET_RECEIVE
#endif
#ifdef USE_BPF
# define USE_BPF_SEND
# define USE_BPF_RECEIVE
#endif
#ifdef USE_LPF
# define USE_LPF_SEND
# define USE_LPF_RECEIVE
#endif
#ifdef USE_NIT
# define USE_NIT_SEND
# define USE_NIT_RECEIVE
#endif
#ifdef USE_DLPI
# define USE_DLPI_SEND
# define USE_DLPI_RECEIVE
#endif
#ifdef USE_UPF
# define USE_UPF_SEND
# define USE_UPF_RECEIVE
#endif
/* Porting::
If you add support for sending packets directly out an interface,
and your support does not do ARP or routing, you must use a fallback
mechanism to deal with packets that need to be sent to routers.
Currently, all low-level packet interfaces use BSD sockets as a
fallback. */
#if defined (USE_BPF_SEND) || defined (USE_NIT_SEND) || \
defined (USE_DLPI_SEND) || defined (USE_UPF_SEND) || defined (USE_LPF_SEND)
# define USE_SOCKET_FALLBACK
# define USE_FALLBACK
#endif
/* Porting::
If you add support for sending packets directly out an interface
and need to be able to assemble packets, add the USE_XXX_SEND
definition for your interface to the list tested below. */
#if defined (USE_RAW_SEND) || defined (USE_BPF_SEND) || \
defined (USE_NIT_SEND) || defined (USE_UPF_SEND) || \
defined (USE_DLPI_SEND) || defined (USE_LPF_SEND)
# define PACKET_ASSEMBLY
#endif
/* Porting::
If you add support for receiving packets directly from an interface
and need to be able to decode raw packets, add the USE_XXX_RECEIVE
definition for your interface to the list tested below. */
#if defined (USE_RAW_RECEIVE) || defined (USE_BPF_SEND) || \
defined (USE_NIT_RECEIVE) || defined (USE_UPF_RECEIVE) || \
defined (USE_DLPI_RECEIVE) || \
defined (USE_LPF_SEND) || \
(defined (USE_SOCKET_SEND) && defined (SO_BINDTODEVICE))
# define PACKET_DECODING
#endif
/* If we don't have a DLPI packet filter, we have to filter in userland.
Probably not worth doing, actually. */
#if defined (USE_DLPI_RECEIVE) && !defined (USE_DLPI_PFMOD)
# define USERLAND_FILTER
#endif
/* jmp_buf is assumed to be a struct unless otherwise defined in the
system header. */
#ifndef jbp_decl
# define jbp_decl(x) jmp_buf *x
#endif
#ifndef jref
# define jref(x) (&(x))
#endif
#ifndef jdref
# define jdref(x) (*(x))
#endif
#ifndef jrefproto
# define jrefproto jmp_buf *
#endif
#ifndef BPF_FORMAT
# define BPF_FORMAT "/dev/bpf%d"
#endif
#if defined (IFF_POINTOPOINT) && !defined (HAVE_IFF_POINTOPOINT)
# define HAVE_IFF_POINTOPOINT
#endif
#if defined (AF_LINK) && !defined (HAVE_AF_LINK)
# define HAVE_AF_LINK
#endif
#if defined (ARPHRD_TUNNEL) && !defined (HAVE_ARPHRD_TUNNEL)
# define HAVE_ARPHRD_TUNNEL
#endif
#if defined (ARPHRD_LOOPBACK) && !defined (HAVE_ARPHRD_LOOPBACK)
# define HAVE_ARPHRD_LOOPBACK
#endif
#if defined (ARPHRD_ROSE) && !defined (HAVE_ARPHRD_ROSE)
# define HAVE_ARPHRD_ROSE
#endif
#if defined (ARPHRD_IEEE802) && !defined (HAVE_ARPHRD_IEEE802)
# define HAVE_ARPHRD_IEEE802
#endif
#if defined (ARPHRD_FDDI) && !defined (HAVE_ARPHRD_FDDI)
# define HAVE_ARPHRD_FDDI
#endif
#if defined (ARPHRD_AX25) && !defined (HAVE_ARPHRD_AX25)
# define HAVE_ARPHRD_AX25
#endif
#if defined (ARPHRD_NETROM) && !defined (HAVE_ARPHRD_NETROM)
# define HAVE_ARPHRD_NETROM
#endif
#if defined (ARPHRD_METRICOM) && !defined (HAVE_ARPHRD_METRICOM)
# define HAVE_ARPHRD_METRICOM
#endif
#if defined (SO_BINDTODEVICE) && !defined (HAVE_SO_BINDTODEVICE)
# define HAVE_SO_BINDTODEVICE
#endif
#if defined (SIOCGIFHWADDR) && !defined (HAVE_SIOCGIFHWADDR)
# define HAVE_SIOCGIFHWADDR
#endif
#if defined (AF_LINK) && !defined (HAVE_AF_LINK)
# define HAVE_AF_LINK
#endif

View file

@ -0,0 +1,4 @@
#pragma once
struct iaddr;
struct interface_info;

View file

@ -0,0 +1,47 @@
/* $OpenBSD: privsep.h,v 1.2 2004/05/04 18:51:18 henning Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
//#include <poll.h>
//#include <pwd.h>
struct buf {
u_char *buf;
size_t size;
size_t wpos;
size_t rpos;
};
enum imsg_code {
IMSG_NONE,
IMSG_SCRIPT_INIT,
IMSG_SCRIPT_WRITE_PARAMS,
IMSG_SCRIPT_GO,
IMSG_SCRIPT_GO_RET
};
struct imsg_hdr {
enum imsg_code code;
size_t len;
};
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 sock, void *, size_t);

View file

@ -0,0 +1,94 @@
#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 <stdio.h>
#include <io.h>
#include "stdint.h"
#include "predec.h"
#include <dhcp/rosdhcp_public.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;
#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 *));
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);
HANDLE PipeInit(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 VOID ApiInit();
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*/

View file

@ -0,0 +1,100 @@
/* Site-specific definitions.
For supported systems, you shouldn't need to make any changes here.
However, you may want to, in order to deal with site-specific
differences. */
/* Add any site-specific definitions and inclusions here... */
/* #include <site-foo-bar.h> */
/* #define SITE_FOOBAR */
/* Define this if you don't want dhcpd to run as a daemon and do want
to see all its output printed to stdout instead of being logged via
syslog(). This also makes dhcpd use the dhcpd.conf in its working
directory and write the dhcpd.leases file there. */
/* #define DEBUG */
/* Define this to see what the parser is parsing. You probably don't
want to see this. */
/* #define DEBUG_TOKENS */
/* Define this to see dumps of incoming and outgoing packets. This
slows things down quite a bit... */
/* #define DEBUG_PACKET */
/* Define this if you want to see dumps of tree evaluations. The most
common reason for doing this is to watch what happens with DNS name
lookups. */
/* #define DEBUG_EVAL */
/* Define this if you want the dhcpd.pid file to go somewhere other than
the default (which varies from system to system, but is usually either
/etc or /var/run. */
/* #define _PATH_DHCPD_PID "/var/run/dhcpd.pid" */
/* Define this if you want the dhcpd.leases file (the dynamic lease database)
to go somewhere other than the default location, which is normally
/etc/dhcpd.leases. */
/* #define _PATH_DHCPD_DB "/etc/dhcpd.leases" */
/* Define this if you want the dhcpd.conf file to go somewhere other than
the default location. By default, it goes in /etc/dhcpd.conf. */
/* #define _PATH_DHCPD_CONF "/etc/dhcpd.conf" */
/* Network API definitions. You do not need to choose one of these - if
you don't choose, one will be chosen for you in your system's config
header. DON'T MESS WITH THIS UNLESS YOU KNOW WHAT YOU'RE DOING!!! */
/* Define this to use the standard BSD socket API.
On many systems, the BSD socket API does not provide the ability to
send packets to the 255.255.255.255 broadcast address, which can
prevent some clients (e.g., Win95) from seeing replies. This is
not a problem on Solaris.
In addition, the BSD socket API will not work when more than one
network interface is configured on the server.
However, the BSD socket API is about as efficient as you can get, so if
the aforementioned problems do not matter to you, or if no other
API is supported for your system, you may want to go with it. */
/* #define USE_SOCKETS */
/* Define this to use the Sun Streams NIT API.
The Sun Streams NIT API is only supported on SunOS 4.x releases. */
/* #define USE_NIT */
/* Define this to use the Berkeley Packet Filter API.
The BPF API is available on all 4.4-BSD derivatives, including
NetBSD, FreeBSD and BSDI's BSD/OS. It's also available on
DEC Alpha OSF/1 in a compatibility mode supported by the Alpha OSF/1
packetfilter interface. */
/* #define USE_BPF */
/* Define this to use the raw socket API.
The raw socket API is provided on many BSD derivatives, and provides
a way to send out raw IP packets. It is only supported for sending
packets - packets must be received with the regular socket API.
This code is experimental - I've never gotten it to actually transmit
a packet to the 255.255.255.255 broadcast address - so use it at your
own risk. */
/* #define USE_RAW_SOCKETS */
/* Define this to change the logging facility used by dhcpd. */
/* #define DHCPD_LOG_FACILITY LOG_DAEMON */

View file

@ -0,0 +1,10 @@
#pragma once
typedef signed char int8_t;
typedef unsigned char u_int8_t;
typedef short int16_t;
typedef unsigned short u_int16_t;
typedef int int32_t;
typedef unsigned int u_int32_t;
typedef char *caddr_t;

View file

@ -0,0 +1,52 @@
/* systat.h
Definitions for systat protocol... */
/*
* Copyright (c) 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''.
*/
#define SYSCONF_SOCKET "/var/run/sysconf"
struct sysconf_header {
u_int32_t type; /* Type of status message... */
u_int32_t length; /* Length of message. */
};
/* Message types... */
#define NETWORK_LOCATION_CHANGED 1

View file

@ -0,0 +1,66 @@
/* $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;
};

View file

@ -0,0 +1,3 @@
/* Current version of ISC DHCP Distribution. */
#define DHCP_VERSION "2.0pl5"

919
base/services/dhcp/memory.c Normal file
View file

@ -0,0 +1,919 @@
/* memory.c
Memory-resident database... */
/*
* 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''.
*/
#ifndef lint
static char copyright[] =
"$Id: memory.c,v 1.35.2.4 1999/05/27 17:47:43 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "rosdhcp.h"
#include "dhcpd.h"
struct subnet *subnets;
struct shared_network *shared_networks;
static struct hash_table *host_hw_addr_hash;
static struct hash_table *host_uid_hash;
static struct hash_table *lease_uid_hash;
static struct hash_table *lease_ip_addr_hash;
static struct hash_table *lease_hw_addr_hash;
struct lease *dangling_leases;
static struct hash_table *vendor_class_hash;
static struct hash_table *user_class_hash;
void enter_host (hd)
struct host_decl *hd;
{
struct host_decl *hp = (struct host_decl *)0;
struct host_decl *np = (struct host_decl *)0;
hd -> n_ipaddr = (struct host_decl *)0;
if (hd -> interface.hlen) {
if (!host_hw_addr_hash)
host_hw_addr_hash = new_hash ();
else
hp = (struct host_decl *)
hash_lookup (host_hw_addr_hash,
hd -> interface.haddr,
hd -> interface.hlen);
/* If there isn't already a host decl matching this
address, add it to the hash table. */
if (!hp)
add_hash (host_hw_addr_hash,
hd -> interface.haddr, hd -> interface.hlen,
(unsigned char *)hd);
}
/* If there was already a host declaration for this hardware
address, add this one to the end of the list. */
if (hp) {
for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
;
np -> n_ipaddr = hd;
}
if (hd -> group -> options [DHO_DHCP_CLIENT_IDENTIFIER]) {
if (!tree_evaluate (hd -> group -> options
[DHO_DHCP_CLIENT_IDENTIFIER]))
return;
/* If there's no uid hash, make one; otherwise, see if
there's already an entry in the hash for this host. */
if (!host_uid_hash) {
host_uid_hash = new_hash ();
hp = (struct host_decl *)0;
} else
hp = (struct host_decl *) hash_lookup
(host_uid_hash,
hd -> group -> options
[DHO_DHCP_CLIENT_IDENTIFIER] -> value,
hd -> group -> options
[DHO_DHCP_CLIENT_IDENTIFIER] -> len);
/* If there's already a host declaration for this
client identifier, add this one to the end of the
list. Otherwise, add it to the hash table. */
if (hp) {
/* Don't link it in twice... */
if (!np) {
for (np = hp; np -> n_ipaddr;
np = np -> n_ipaddr)
;
np -> n_ipaddr = hd;
}
} else {
add_hash (host_uid_hash,
hd -> group -> options
[DHO_DHCP_CLIENT_IDENTIFIER] -> value,
hd -> group -> options
[DHO_DHCP_CLIENT_IDENTIFIER] -> len,
(unsigned char *)hd);
}
}
}
struct host_decl *find_hosts_by_haddr (htype, haddr, hlen)
int htype;
unsigned char *haddr;
int hlen;
{
struct host_decl *foo;
foo = (struct host_decl *)hash_lookup (host_hw_addr_hash,
haddr, hlen);
return foo;
}
struct host_decl *find_hosts_by_uid (data, len)
unsigned char *data;
int len;
{
struct host_decl *foo;
foo = (struct host_decl *)hash_lookup (host_uid_hash, data, len);
return foo;
}
/* More than one host_decl can be returned by find_hosts_by_haddr or
find_hosts_by_uid, and each host_decl can have multiple addresses.
Loop through the list of hosts, and then for each host, through the
list of addresses, looking for an address that's in the same shared
network as the one specified. Store the matching address through
the addr pointer, update the host pointer to point at the host_decl
that matched, and return the subnet that matched. */
subnet *find_host_for_network (struct host_decl **host, iaddr *addr,
shared_network *share)
{
int i;
subnet *subnet;
iaddr ip_address;
struct host_decl *hp;
for (hp = *host; hp; hp = hp -> n_ipaddr) {
if (!hp -> fixed_addr || !tree_evaluate (hp -> fixed_addr))
continue;
for (i = 0; i < hp -> fixed_addr -> len; i += 4) {
ip_address.len = 4;
memcpy (ip_address.iabuf,
hp -> fixed_addr -> value + i, 4);
subnet = find_grouped_subnet (share, ip_address);
if (subnet) {
*addr = ip_address;
*host = hp;
return subnet;
}
}
}
return (struct _subnet *)0;
}
void new_address_range (iaddr low, iaddr high, subnet *subnet, int dynamic)
{
lease *address_range, *lp, *plp;
iaddr net;
int min, max, i;
char lowbuf [16], highbuf [16], netbuf [16];
shared_network *share = subnet -> shared_network;
struct hostent *h;
struct in_addr ia;
/* All subnets should have attached shared network structures. */
if (!share) {
strcpy (netbuf, piaddr (subnet -> net));
error ("No shared network for network %s (%s)",
netbuf, piaddr (subnet -> netmask));
}
/* Initialize the hash table if it hasn't been done yet. */
if (!lease_uid_hash)
lease_uid_hash = new_hash ();
if (!lease_ip_addr_hash)
lease_ip_addr_hash = new_hash ();
if (!lease_hw_addr_hash)
lease_hw_addr_hash = new_hash ();
/* Make sure that high and low addresses are in same subnet. */
net = subnet_number (low, subnet -> netmask);
if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
strcpy (lowbuf, piaddr (low));
strcpy (highbuf, piaddr (high));
strcpy (netbuf, piaddr (subnet -> netmask));
error ("Address range %s to %s, netmask %s spans %s!",
lowbuf, highbuf, netbuf, "multiple subnets");
}
/* Make sure that the addresses are on the correct subnet. */
if (!addr_eq (net, subnet -> net)) {
strcpy (lowbuf, piaddr (low));
strcpy (highbuf, piaddr (high));
strcpy (netbuf, piaddr (subnet -> netmask));
error ("Address range %s to %s not on net %s/%s!",
lowbuf, highbuf, piaddr (subnet -> net), netbuf);
}
/* Get the high and low host addresses... */
max = host_addr (high, subnet -> netmask);
min = host_addr (low, subnet -> netmask);
/* Allow range to be specified high-to-low as well as low-to-high. */
if (min > max) {
max = min;
min = host_addr (high, subnet -> netmask);
}
/* Get a lease structure for each address in the range. */
address_range = new_leases (max - min + 1, "new_address_range");
if (!address_range) {
strcpy (lowbuf, piaddr (low));
strcpy (highbuf, piaddr (high));
error ("No memory for address range %s-%s.", lowbuf, highbuf);
}
memset (address_range, 0, (sizeof *address_range) * (max - min + 1));
/* Fill in the last lease if it hasn't been already... */
if (!share -> last_lease) {
share -> last_lease = &address_range [0];
}
/* Fill out the lease structures with some minimal information. */
for (i = 0; i < max - min + 1; i++) {
address_range [i].ip_addr =
ip_addr (subnet -> net, subnet -> netmask, i + min);
address_range [i].starts =
address_range [i].timestamp = MIN_TIME;
address_range [i].ends = MIN_TIME;
address_range [i].subnet = subnet;
address_range [i].shared_network = share;
address_range [i].flags = dynamic ? DYNAMIC_BOOTP_OK : 0;
memcpy (&ia, address_range [i].ip_addr.iabuf, 4);
if (subnet -> group -> get_lease_hostnames) {
h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
if (!h)
warn ("No hostname for %s", inet_ntoa (ia));
else {
address_range [i].hostname =
malloc (strlen (h -> h_name) + 1);
if (!address_range [i].hostname)
error ("no memory for hostname %s.",
h -> h_name);
strcpy (address_range [i].hostname,
h -> h_name);
}
}
/* Link this entry into the list. */
address_range [i].next = share -> leases;
address_range [i].prev = (struct lease *)0;
share -> leases = &address_range [i];
if (address_range [i].next)
address_range [i].next -> prev = share -> leases;
add_hash (lease_ip_addr_hash,
address_range [i].ip_addr.iabuf,
address_range [i].ip_addr.len,
(unsigned char *)&address_range [i]);
}
/* Find out if any dangling leases are in range... */
plp = (struct lease *)0;
for (lp = dangling_leases; lp; lp = lp -> next) {
iaddr lnet;
int lhost;
lnet = subnet_number (lp -> ip_addr, subnet -> netmask);
lhost = host_addr (lp -> ip_addr, subnet -> netmask);
/* If it's in range, fill in the real lease structure with
the dangling lease's values, and remove the lease from
the list of dangling leases. */
if (addr_eq (lnet, subnet -> net) &&
lhost >= i && lhost <= max) {
if (plp) {
plp -> next = lp -> next;
} else {
dangling_leases = lp -> next;
}
lp -> next = (struct lease *)0;
address_range [lhost - i].hostname = lp -> hostname;
address_range [lhost - i].client_hostname =
lp -> client_hostname;
supersede_lease (&address_range [lhost - i], lp, 0);
free_lease (lp, "new_address_range");
} else
plp = lp;
}
}
subnet *find_subnet (iaddr addr)
{
subnet *rv;
for (rv = subnets; rv; rv = rv -> next_subnet) {
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
return rv;
}
return (subnet *)0;
}
subnet *find_grouped_subnet (shared_network *share, iaddr addr)
{
subnet *rv;
for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
return rv;
}
return (subnet *)0;
}
int subnet_inner_than (struct _subnet *subnet, struct _subnet *scan, int warnp)
{
if (addr_eq (subnet_number (subnet -> net, scan -> netmask),
scan -> net) ||
addr_eq (subnet_number (scan -> net, subnet -> netmask),
subnet -> net)) {
char n1buf [16];
int i, j;
for (i = 0; i < 32; i++)
if (subnet -> netmask.iabuf [3 - (i >> 3)]
& (1 << (i & 7)))
break;
for (j = 0; j < 32; j++)
if (scan -> netmask.iabuf [3 - (j >> 3)] &
(1 << (j & 7)))
break;
strcpy (n1buf, piaddr (subnet -> net));
if (warnp)
warn ("%ssubnet %s/%d conflicts with subnet %s/%d",
"Warning: ", n1buf, 32 - i,
piaddr (scan -> net), 32 - j);
if (i < j)
return 1;
}
return 0;
}
/* Enter a new subnet into the subnet list. */
void enter_subnet (struct _subnet *subnet)
{
struct _subnet *scan, *prev = (struct _subnet *)0;
/* Check for duplicates... */
for (scan = subnets; scan; scan = scan -> next_subnet) {
/* When we find a conflict, make sure that the
subnet with the narrowest subnet mask comes
first. */
if (subnet_inner_than (subnet, scan, 1)) {
if (prev) {
prev -> next_subnet = subnet;
} else
subnets = subnet;
subnet -> next_subnet = scan;
return;
}
prev = scan;
}
/* XXX use the BSD radix tree code instead of a linked list. */
subnet -> next_subnet = subnets;
subnets = subnet;
}
/* Enter a new shared network into the shared network list. */
void enter_shared_network (shared_network *share)
{
/* XXX Sort the nets into a balanced tree to make searching quicker. */
share -> next = shared_networks;
shared_networks = share;
}
/* Enter a lease into the system. This is called by the parser each
time it reads in a new lease. If the subnet for that lease has
already been read in (usually the case), just update that lease;
otherwise, allocate temporary storage for the lease and keep it around
until we're done reading in the config file. */
void enter_lease (struct _lease *lease)
{
struct _lease *comp = find_lease_by_ip_addr (lease -> ip_addr);
/* If we don't have a place for this lease yet, save it for
later. */
if (!comp) {
comp = new_lease ("enter_lease");
if (!comp) {
error ("No memory for lease %s\n",
piaddr (lease -> ip_addr));
}
*comp = *lease;
comp -> next = dangling_leases;
comp -> prev = (struct lease *)0;
dangling_leases = comp;
} else {
/* Record the hostname information in the lease. */
comp -> hostname = lease -> hostname;
comp -> client_hostname = lease -> client_hostname;
supersede_lease (comp, lease, 0);
}
}
/* Replace the data in an existing lease with the data in a new lease;
adjust hash tables to suit, and insertion sort the lease into the
list of leases by expiry time so that we can always find the oldest
lease. */
int supersede_lease (struct _lease *comp, struct _lease *lease, int commit)
{
int enter_uid = 0;
int enter_hwaddr = 0;
struct _lease *lp;
/* Static leases are not currently kept in the database... */
if (lease -> flags & STATIC_LEASE)
return 1;
/* If the existing lease hasn't expired and has a different
unique identifier or, if it doesn't have a unique
identifier, a different hardware address, then the two
leases are in conflict. If the existing lease has a uid
and the new one doesn't, but they both have the same
hardware address, and dynamic bootp is allowed on this
lease, then we allow that, in case a dynamic BOOTP lease is
requested *after* a DHCP lease has been assigned. */
if (!(lease -> flags & ABANDONED_LEASE) &&
comp -> ends > cur_time &&
(((comp -> uid && lease -> uid) &&
(comp -> uid_len != lease -> uid_len ||
memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
(!comp -> uid &&
((comp -> hardware_addr.htype !=
lease -> hardware_addr.htype) ||
(comp -> hardware_addr.hlen !=
lease -> hardware_addr.hlen) ||
memcmp (comp -> hardware_addr.haddr,
lease -> hardware_addr.haddr,
comp -> hardware_addr.hlen))))) {
warn ("Lease conflict at %s",
piaddr (comp -> ip_addr));
return 0;
} else {
/* If there's a Unique ID, dissociate it from the hash
table and free it if necessary. */
if (comp -> uid) {
uid_hash_delete (comp);
enter_uid = 1;
if (comp -> uid != &comp -> uid_buf [0]) {
free (comp -> uid);
comp -> uid_max = 0;
comp -> uid_len = 0;
}
comp -> uid = (unsigned char *)0;
} else
enter_uid = 1;
if (comp -> hardware_addr.htype &&
((comp -> hardware_addr.hlen !=
lease -> hardware_addr.hlen) ||
(comp -> hardware_addr.htype !=
lease -> hardware_addr.htype) ||
memcmp (comp -> hardware_addr.haddr,
lease -> hardware_addr.haddr,
comp -> hardware_addr.hlen))) {
hw_hash_delete (comp);
enter_hwaddr = 1;
} else if (!comp -> hardware_addr.htype)
enter_hwaddr = 1;
/* Copy the data files, but not the linkages. */
comp -> starts = lease -> starts;
if (lease -> uid) {
if (lease -> uid_len < sizeof (lease -> uid_buf)) {
memcpy (comp -> uid_buf,
lease -> uid, lease -> uid_len);
comp -> uid = &comp -> uid_buf [0];
comp -> uid_max = sizeof comp -> uid_buf;
} else if (lease -> uid != &lease -> uid_buf [0]) {
comp -> uid = lease -> uid;
comp -> uid_max = lease -> uid_max;
lease -> uid = (unsigned char *)0;
lease -> uid_max = 0;
} else {
error ("corrupt lease uid."); /* XXX */
}
} else {
comp -> uid = (unsigned char *)0;
comp -> uid_max = 0;
}
comp -> uid_len = lease -> uid_len;
comp -> host = lease -> host;
comp -> hardware_addr = lease -> hardware_addr;
comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
(comp -> flags & ~EPHEMERAL_FLAGS));
/* Record the lease in the uid hash if necessary. */
if (enter_uid && lease -> uid) {
uid_hash_add (comp);
}
/* Record it in the hardware address hash if necessary. */
if (enter_hwaddr && lease -> hardware_addr.htype) {
hw_hash_add (comp);
}
/* Remove the lease from its current place in the
timeout sequence. */
if (comp -> prev) {
comp -> prev -> next = comp -> next;
} else {
comp -> shared_network -> leases = comp -> next;
}
if (comp -> next) {
comp -> next -> prev = comp -> prev;
}
if (comp -> shared_network -> last_lease == comp) {
comp -> shared_network -> last_lease = comp -> prev;
}
/* Find the last insertion point... */
if (comp == comp -> shared_network -> insertion_point ||
!comp -> shared_network -> insertion_point) {
lp = comp -> shared_network -> leases;
} else {
lp = comp -> shared_network -> insertion_point;
}
if (!lp) {
/* Nothing on the list yet? Just make comp the
head of the list. */
comp -> shared_network -> leases = comp;
comp -> shared_network -> last_lease = comp;
} else if (lp -> ends > lease -> ends) {
/* Skip down the list until we run out of list
or find a place for comp. */
while (lp -> next && lp -> ends > lease -> ends) {
lp = lp -> next;
}
if (lp -> ends > lease -> ends) {
/* If we ran out of list, put comp
at the end. */
lp -> next = comp;
comp -> prev = lp;
comp -> next = (struct lease *)0;
comp -> shared_network -> last_lease = comp;
} else {
/* If we didn't, put it between lp and
the previous item on the list. */
if ((comp -> prev = lp -> prev))
comp -> prev -> next = comp;
comp -> next = lp;
lp -> prev = comp;
}
} else {
/* Skip up the list until we run out of list
or find a place for comp. */
while (lp -> prev && lp -> ends < lease -> ends) {
lp = lp -> prev;
}
if (lp -> ends < lease -> ends) {
/* If we ran out of list, put comp
at the beginning. */
lp -> prev = comp;
comp -> next = lp;
comp -> prev = (struct lease *)0;
comp -> shared_network -> leases = comp;
} else {
/* If we didn't, put it between lp and
the next item on the list. */
if ((comp -> next = lp -> next))
comp -> next -> prev = comp;
comp -> prev = lp;
lp -> next = comp;
}
}
comp -> shared_network -> insertion_point = comp;
comp -> ends = lease -> ends;
}
/* Return zero if we didn't commit the lease to permanent storage;
nonzero if we did. */
return commit && write_lease (comp) && commit_leases ();
}
/* Release the specified lease and re-hash it as appropriate. */
void release_lease (struct _lease *lease)
{
struct _lease lt;
lt = *lease;
if (lt.ends > cur_time) {
lt.ends = cur_time;
supersede_lease (lease, &lt, 1);
}
}
/* Abandon the specified lease (set its timeout to infinity and its
particulars to zero, and re-hash it as appropriate. */
void abandon_lease (struct _lease *lease, char *message)
{
struct _lease lt;
lease -> flags |= ABANDONED_LEASE;
lt = *lease;
lt.ends = cur_time;
warn ("Abandoning IP address %s: %s",
piaddr (lease -> ip_addr), message);
lt.hardware_addr.htype = 0;
lt.hardware_addr.hlen = 0;
lt.uid = (unsigned char *)0;
lt.uid_len = 0;
supersede_lease (lease, &lt, 1);
}
/* Locate the lease associated with a given IP address... */
lease *find_lease_by_ip_addr (iaddr addr)
{
lease *lease = (struct _lease *)hash_lookup (lease_ip_addr_hash,
addr.iabuf,
addr.len);
return lease;
}
lease *find_lease_by_uid (unsigned char *uid, int len)
{
lease *lease = (struct lease *)hash_lookup (lease_uid_hash,
uid, len);
return lease;
}
lease *find_lease_by_hw_addr (unsigned char *hwaddr, int hwlen)
{
struct _lease *lease =
(struct _lease *)hash_lookup (lease_hw_addr_hash,
hwaddr, hwlen);
return lease;
}
/* Add the specified lease to the uid hash. */
void uid_hash_add (lease *lease)
{
struct _lease *head = find_lease_by_uid (lease -> uid, lease -> uid_len);
struct _lease *scan;
#ifdef DEBUG
if (lease -> n_uid)
abort ();
#endif
/* If it's not in the hash, just add it. */
if (!head)
add_hash (lease_uid_hash, lease -> uid,
lease -> uid_len, (unsigned char *)lease);
else {
/* Otherwise, attach it to the end of the list. */
for (scan = head; scan -> n_uid; scan = scan -> n_uid)
#ifdef DEBUG
if (scan == lease)
abort ()
#endif
;
scan -> n_uid = lease;
}
}
/* Delete the specified lease from the uid hash. */
void uid_hash_delete (lease *lease)
{
struct _lease *head =
find_lease_by_uid (lease -> uid, lease -> uid_len);
struct _lease *scan;
/* If it's not in the hash, we have no work to do. */
if (!head) {
lease -> n_uid = (struct lease *)0;
return;
}
/* If the lease we're freeing is at the head of the list,
remove the hash table entry and add a new one with the
next lease on the list (if there is one). */
if (head == lease) {
delete_hash_entry (lease_uid_hash,
lease -> uid, lease -> uid_len);
if (lease -> n_uid)
add_hash (lease_uid_hash,
lease -> n_uid -> uid,
lease -> n_uid -> uid_len,
(unsigned char *)(lease -> n_uid));
} else {
/* Otherwise, look for the lease in the list of leases
attached to the hash table entry, and remove it if
we find it. */
for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
if (scan -> n_uid == lease) {
scan -> n_uid = scan -> n_uid -> n_uid;
break;
}
}
}
lease -> n_uid = (struct lease *)0;
}
/* Add the specified lease to the hardware address hash. */
void hw_hash_add (lease *lease)
{
struct _lease *head =
find_lease_by_hw_addr (lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen);
struct _lease *scan;
/* If it's not in the hash, just add it. */
if (!head)
add_hash (lease_hw_addr_hash,
lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen,
(unsigned char *)lease);
else {
/* Otherwise, attach it to the end of the list. */
for (scan = head; scan -> n_hw; scan = scan -> n_hw)
;
scan -> n_hw = lease;
}
}
/* Delete the specified lease from the hardware address hash. */
void hw_hash_delete (lease *lease)
{
struct _lease *head =
find_lease_by_hw_addr (lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen);
struct _lease *scan;
/* If it's not in the hash, we have no work to do. */
if (!head) {
lease -> n_hw = (struct lease *)0;
return;
}
/* If the lease we're freeing is at the head of the list,
remove the hash table entry and add a new one with the
next lease on the list (if there is one). */
if (head == lease) {
delete_hash_entry (lease_hw_addr_hash,
lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen);
if (lease -> n_hw)
add_hash (lease_hw_addr_hash,
lease -> n_hw -> hardware_addr.haddr,
lease -> n_hw -> hardware_addr.hlen,
(unsigned char *)(lease -> n_hw));
} else {
/* Otherwise, look for the lease in the list of leases
attached to the hash table entry, and remove it if
we find it. */
for (scan = head; scan -> n_hw; scan = scan -> n_hw) {
if (scan -> n_hw == lease) {
scan -> n_hw = scan -> n_hw -> n_hw;
break;
}
}
}
lease -> n_hw = (struct lease *)0;
}
struct class *add_class (type, name)
int type;
char *name;
{
struct class *class = new_class ("add_class");
char *tname = (char *)malloc (strlen (name) + 1);
if (!vendor_class_hash)
vendor_class_hash = new_hash ();
if (!user_class_hash)
user_class_hash = new_hash ();
if (!tname || !class || !vendor_class_hash || !user_class_hash)
{
if (tname != NULL)
free(tname);
return (struct class *)0;
}
memset (class, 0, sizeof *class);
strcpy (tname, name);
class -> name = tname;
if (type)
add_hash (user_class_hash,
(unsigned char *)tname, strlen (tname),
(unsigned char *)class);
else
add_hash (vendor_class_hash,
(unsigned char *)tname, strlen (tname),
(unsigned char *)class);
return class;
}
struct class *find_class (type, name, len)
int type;
unsigned char *name;
int len;
{
struct class *class =
(struct class *)hash_lookup (type
? user_class_hash
: vendor_class_hash, name, len);
return class;
}
struct group *clone_group (group, caller)
struct group *group;
char *caller;
{
struct group *g = new_group (caller);
if (!g)
error ("%s: can't allocate new group", caller);
*g = *group;
return g;
}
/* Write all interesting leases to permanent storage. */
void write_leases ()
{
lease *l;
shared_network *s;
for (s = shared_networks; s; s = (shared_network *)s -> next) {
for (l = s -> leases; l; l = l -> next) {
if (l -> hardware_addr.hlen ||
l -> uid_len ||
(l -> flags & ABANDONED_LEASE))
if (!write_lease (l))
error ("Can't rewrite lease database");
}
}
if (!commit_leases ())
error ("Can't commit leases to new database: %m");
}
void dump_subnets ()
{
struct _lease *l;
shared_network *s;
subnet *n;
note ("Subnets:");
for (n = subnets; n; n = n -> next_subnet) {
debug (" Subnet %s", piaddr (n -> net));
debug (" netmask %s",
piaddr (n -> netmask));
}
note ("Shared networks:");
for (s = shared_networks; s; s = (shared_network *)s -> next) {
note (" %s", s -> name);
for (l = s -> leases; l; l = l -> next) {
print_lease (l);
}
if (s -> last_lease) {
debug (" Last Lease:");
print_lease (s -> last_lease);
}
}
}

View file

@ -0,0 +1,723 @@
/* $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);
}

120
base/services/dhcp/pipe.c Normal file
View file

@ -0,0 +1,120 @@
/* $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;
}

View file

@ -0,0 +1,225 @@
/* $OpenBSD: privsep.c,v 1.7 2004/05/10 18:34:42 deraadt Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "rosdhcp.h"
#include "dhcpd.h"
#include "privsep.h"
struct buf *
buf_open(size_t len)
{
struct buf *buf;
if ((buf = calloc(1, sizeof(struct buf))) == NULL)
return (NULL);
if ((buf->buf = malloc(len)) == NULL) {
free(buf);
return (NULL);
}
buf->size = len;
return (buf);
}
int
buf_add(struct buf *buf, void *data, size_t len)
{
if (buf->wpos + len > buf->size)
return (-1);
memcpy(buf->buf + buf->wpos, data, len);
buf->wpos += len;
return (0);
}
int
buf_close(int sock, struct buf *buf)
{
ssize_t n;
n = write(sock, buf->buf + buf->rpos, buf->size - buf->rpos);
if (n != -1)
buf->rpos += n;
if (n == 0) { /* connection closed */
return (-1);
}
if (buf->rpos < buf->size)
error("short write: wanted %lu got %ld bytes",
(unsigned long)buf->size, (long)buf->rpos);
free(buf->buf);
free(buf);
return (n);
}
ssize_t
buf_read(int sock, void *buf, size_t nbytes)
{
ssize_t n, r = 0;
char *p = buf;
n = read(sock, p, nbytes);
if (n == 0)
error("connection closed");
if (n != -1) {
r += n;
p += n;
nbytes -= n;
}
if (n == -1)
error("buf_read: %d", WSAGetLastError());
if (r < nbytes)
error("short read: wanted %lu got %ld bytes",
(unsigned long)nbytes, (long)r);
return (r);
}
void
dispatch_imsg(int fd)
{
struct imsg_hdr hdr;
char *medium, *reason, *filename,
*servername, *prefix;
size_t medium_len, reason_len, filename_len,
servername_len, prefix_len, totlen;
struct client_lease lease;
int ret, i, optlen;
struct buf *buf;
buf_read(fd, &hdr, sizeof(hdr));
switch (hdr.code) {
case IMSG_SCRIPT_INIT:
if (hdr.len < sizeof(hdr) + sizeof(size_t))
error("corrupted message received");
buf_read(fd, &medium_len, sizeof(medium_len));
if (hdr.len < medium_len + sizeof(size_t) + sizeof(hdr)
+ sizeof(size_t) || medium_len == SIZE_T_MAX)
error("corrupted message received");
if (medium_len > 0) {
if ((medium = calloc(1, medium_len + 1)) != NULL)
buf_read(fd, medium, medium_len);
} else
medium = NULL;
buf_read(fd, &reason_len, sizeof(reason_len));
if (hdr.len < medium_len + reason_len + sizeof(hdr) ||
reason_len == SIZE_T_MAX)
error("corrupted message received");
if (reason_len > 0) {
if ((reason = calloc(1, reason_len + 1)) != NULL)
buf_read(fd, reason, reason_len);
} else
reason = NULL;
// priv_script_init(reason, medium);
free(reason);
free(medium);
break;
case IMSG_SCRIPT_WRITE_PARAMS:
//bzero(&lease, sizeof lease);
memset(&lease, 0, sizeof(lease));
totlen = sizeof(hdr) + sizeof(lease) + sizeof(size_t);
if (hdr.len < totlen)
error("corrupted message received");
buf_read(fd, &lease, sizeof(lease));
buf_read(fd, &filename_len, sizeof(filename_len));
totlen += filename_len + sizeof(size_t);
if (hdr.len < totlen || filename_len == SIZE_T_MAX)
error("corrupted message received");
if (filename_len > 0) {
if ((filename = calloc(1, filename_len + 1)) != NULL)
buf_read(fd, filename, filename_len);
} else
filename = NULL;
buf_read(fd, &servername_len, sizeof(servername_len));
totlen += servername_len + sizeof(size_t);
if (hdr.len < totlen || servername_len == SIZE_T_MAX)
error("corrupted message received");
if (servername_len > 0) {
if ((servername =
calloc(1, servername_len + 1)) != NULL)
buf_read(fd, servername, servername_len);
} else
servername = NULL;
buf_read(fd, &prefix_len, sizeof(prefix_len));
totlen += prefix_len;
if (hdr.len < totlen || prefix_len == SIZE_T_MAX)
error("corrupted message received");
if (prefix_len > 0) {
if ((prefix = calloc(1, prefix_len + 1)) != NULL)
buf_read(fd, prefix, prefix_len);
} else
prefix = NULL;
for (i = 0; i < 256; i++) {
totlen += sizeof(optlen);
if (hdr.len < totlen)
error("corrupted message received");
buf_read(fd, &optlen, sizeof(optlen));
lease.options[i].data = NULL;
lease.options[i].len = optlen;
if (optlen > 0) {
totlen += optlen;
if (hdr.len < totlen || optlen == SIZE_T_MAX)
error("corrupted message received");
lease.options[i].data =
calloc(1, optlen + 1);
if (lease.options[i].data != NULL)
buf_read(fd, lease.options[i].data, optlen);
}
}
lease.server_name = servername;
lease.filename = filename;
// priv_script_write_params(prefix, &lease);
free(servername);
free(filename);
free(prefix);
for (i = 0; i < 256; i++)
if (lease.options[i].len > 0)
free(lease.options[i].data);
break;
case IMSG_SCRIPT_GO:
if (hdr.len != sizeof(hdr))
error("corrupted message received");
// ret = priv_script_go();
hdr.code = IMSG_SCRIPT_GO_RET;
hdr.len = sizeof(struct imsg_hdr) + sizeof(int);
buf = buf_open(hdr.len);
if (buf != NULL) {
buf_add(buf, &hdr, sizeof(hdr));
buf_add(buf, &ret, sizeof(ret));
buf_close(fd, buf);
}
break;
default:
error("received unknown message, code %d", hdr.code);
}
}

View file

@ -0,0 +1,39 @@
#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;
}

692
base/services/dhcp/tables.c Normal file
View file

@ -0,0 +1,692 @@
/* 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);
}

View file

@ -0,0 +1,2 @@
#include "rosdhcp.h"

412
base/services/dhcp/tree.c Normal file
View file

@ -0,0 +1,412 @@
/* 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;
}

166
base/services/dhcp/util.c Normal file
View file

@ -0,0 +1,166 @@
#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;
}

View file

@ -0,0 +1,441 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/eventlog/eventlog.c
* PURPOSE: Event logging service
* COPYRIGHT: Copyright 2002 Eric Kohl
* Copyright 2005 Saveliy Tretiakov
*/
/* INCLUDES *****************************************************************/
#include "eventlog.h"
/* GLOBALS ******************************************************************/
static VOID CALLBACK ServiceMain(DWORD, LPWSTR *);
static WCHAR ServiceName[] = L"EventLog";
static SERVICE_TABLE_ENTRYW ServiceTable[2] =
{
{ ServiceName, ServiceMain },
{ NULL, NULL }
};
BOOL onLiveCD = FALSE; // On livecd events will go to debug output only
HANDLE MyHeap = NULL;
/* FUNCTIONS ****************************************************************/
static DWORD WINAPI
ServiceControlHandler(DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext)
{
/* FIXME */
DPRINT1("ServiceControlHandler() called (control code %lu)\n", dwControl);
return ERROR_SUCCESS;
}
static DWORD
ServiceInit(VOID)
{
HANDLE hThread;
hThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)
PortThreadRoutine,
NULL,
0,
NULL);
if (!hThread)
{
DPRINT("Can't create PortThread\n");
return GetLastError();
}
else
CloseHandle(hThread);
hThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)
RpcThreadRoutine,
NULL,
0,
NULL);
if (!hThread)
{
DPRINT("Can't create RpcThread\n");
return GetLastError();
}
else
CloseHandle(hThread);
return ERROR_SUCCESS;
}
static VOID CALLBACK
ServiceMain(DWORD argc,
LPWSTR *argv)
{
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE ServiceStatusHandle;
DWORD dwError;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
DPRINT("ServiceMain() called\n");
ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
ServiceControlHandler,
NULL);
if (!ServiceStatusHandle)
{
dwError = GetLastError();
DPRINT1("RegisterServiceCtrlHandlerW() failed! (Error %lu)\n", dwError);
return;
}
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwWin32ExitCode = NO_ERROR;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 2000;
SetServiceStatus(ServiceStatusHandle,
&ServiceStatus);
dwError = ServiceInit();
if (dwError != ERROR_SUCCESS)
{
DPRINT1("Service stopped\n");
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
}
else
{
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
}
SetServiceStatus(ServiceStatusHandle,
&ServiceStatus);
DPRINT("ServiceMain() done\n");
}
BOOL LoadLogFile(HKEY hKey, WCHAR * LogName)
{
DWORD MaxValueLen, ValueLen, Type, ExpandedLen;
WCHAR *Buf = NULL, *Expanded = NULL;
LONG Result;
BOOL ret = TRUE;
PLOGFILE pLogf;
DPRINT("LoadLogFile: %S\n", LogName);
RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, &MaxValueLen, NULL, NULL);
Buf = HeapAlloc(MyHeap, 0, MaxValueLen);
if (!Buf)
{
DPRINT1("Can't allocate heap!\n");
return FALSE;
}
ValueLen = MaxValueLen;
Result = RegQueryValueEx(hKey,
L"File",
NULL,
&Type,
(LPBYTE) Buf,
&ValueLen);
if (Result != ERROR_SUCCESS)
{
DPRINT1("RegQueryValueEx failed: %d\n", GetLastError());
HeapFree(MyHeap, 0, Buf);
return FALSE;
}
if (Type != REG_EXPAND_SZ && Type != REG_SZ)
{
DPRINT1("%S\\File - value of wrong type %x.\n", LogName, Type);
HeapFree(MyHeap, 0, Buf);
return FALSE;
}
ExpandedLen = ExpandEnvironmentStrings(Buf, NULL, 0);
Expanded = HeapAlloc(MyHeap, 0, ExpandedLen * sizeof(WCHAR));
if (!Expanded)
{
DPRINT1("Can't allocate heap!\n");
HeapFree(MyHeap, 0, Buf);
return FALSE;
}
ExpandEnvironmentStrings(Buf, Expanded, ExpandedLen);
DPRINT("%S -> %S\n", Buf, Expanded);
pLogf = LogfCreate(LogName, Expanded);
if (pLogf == NULL)
{
DPRINT1("Failed to create %S!\n", Expanded);
ret = FALSE;
}
HeapFree(MyHeap, 0, Buf);
HeapFree(MyHeap, 0, Expanded);
return ret;
}
BOOL LoadLogFiles(HKEY eventlogKey)
{
LONG result;
DWORD MaxLognameLen, LognameLen;
WCHAR *Buf = NULL;
INT i;
RegQueryInfoKey(eventlogKey,
NULL, NULL, NULL, NULL,
&MaxLognameLen,
NULL, NULL, NULL, NULL, NULL, NULL);
MaxLognameLen++;
Buf = HeapAlloc(MyHeap, 0, MaxLognameLen * sizeof(WCHAR));
if (!Buf)
{
DPRINT1("Error: can't allocate heap!\n");
return FALSE;
}
i = 0;
LognameLen = MaxLognameLen;
while (RegEnumKeyEx(eventlogKey,
i,
Buf,
&LognameLen,
NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
HKEY SubKey;
DPRINT("%S\n", Buf);
result = RegOpenKeyEx(eventlogKey, Buf, 0, KEY_ALL_ACCESS, &SubKey);
if (result != ERROR_SUCCESS)
{
DPRINT1("Failed to open %S key.\n", Buf);
HeapFree(MyHeap, 0, Buf);
return FALSE;
}
if (!LoadLogFile(SubKey, Buf))
DPRINT1("Failed to load %S\n", Buf);
else
DPRINT("Loaded %S\n", Buf);
RegCloseKey(SubKey);
LognameLen = MaxLognameLen;
i++;
}
HeapFree(MyHeap, 0, Buf);
return TRUE;
}
INT wmain()
{
WCHAR LogPath[MAX_PATH];
INT RetCode = 0;
LONG result;
HKEY elogKey;
LogfListInitialize();
MyHeap = HeapCreate(0, 1024 * 256, 0);
if (!MyHeap)
{
DPRINT1("FATAL ERROR, can't create heap.\n");
RetCode = 1;
goto bye_bye;
}
GetWindowsDirectory(LogPath, MAX_PATH);
if (GetDriveType(LogPath) == DRIVE_CDROM)
{
DPRINT("LiveCD detected\n");
onLiveCD = TRUE;
}
else
{
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Services\\EventLog",
0,
KEY_ALL_ACCESS,
&elogKey);
if (result != ERROR_SUCCESS)
{
DPRINT1("Fatal error: can't open eventlog registry key.\n");
RetCode = 1;
goto bye_bye;
}
LoadLogFiles(elogKey);
}
StartServiceCtrlDispatcher(ServiceTable);
bye_bye:
LogfCloseAll();
if (MyHeap)
HeapDestroy(MyHeap);
return RetCode;
}
VOID EventTimeToSystemTime(DWORD EventTime, SYSTEMTIME * pSystemTime)
{
SYSTEMTIME st1970 = { 1970, 1, 0, 1, 0, 0, 0, 0 };
FILETIME ftLocal;
union
{
FILETIME ft;
ULONGLONG ll;
} u1970, uUCT;
uUCT.ft.dwHighDateTime = 0;
uUCT.ft.dwLowDateTime = EventTime;
SystemTimeToFileTime(&st1970, &u1970.ft);
uUCT.ll = uUCT.ll * 10000000 + u1970.ll;
FileTimeToLocalFileTime(&uUCT.ft, &ftLocal);
FileTimeToSystemTime(&ftLocal, pSystemTime);
}
VOID SystemTimeToEventTime(SYSTEMTIME * pSystemTime, DWORD * pEventTime)
{
SYSTEMTIME st1970 = { 1970, 1, 0, 1, 0, 0, 0, 0 };
union
{
FILETIME ft;
ULONGLONG ll;
} Time, u1970;
SystemTimeToFileTime(pSystemTime, &Time.ft);
SystemTimeToFileTime(&st1970, &u1970.ft);
*pEventTime = (Time.ll - u1970.ll) / 10000000;
}
VOID PRINT_HEADER(PEVENTLOGHEADER header)
{
DPRINT("HeaderSize = %d\n", header->HeaderSize);
DPRINT("Signature = 0x%x\n", header->Signature);
DPRINT("MajorVersion = %d\n", header->MajorVersion);
DPRINT("MinorVersion = %d\n", header->MinorVersion);
DPRINT("StartOffset = %d\n", header->StartOffset);
DPRINT("EndOffset = 0x%x\n", header->EndOffset);
DPRINT("CurrentRecordNumber = %d\n", header->CurrentRecordNumber);
DPRINT("OldestRecordNumber = %d\n", header->OldestRecordNumber);
DPRINT("MaxSize = 0x%x\n", header->MaxSize);
DPRINT("Retention = 0x%x\n", header->Retention);
DPRINT("EndHeaderSize = %d\n", header->EndHeaderSize);
DPRINT("Flags: ");
if (header->Flags & ELF_LOGFILE_HEADER_DIRTY) DPRINT("ELF_LOGFILE_HEADER_DIRTY");
if (header->Flags & ELF_LOGFILE_HEADER_WRAP) DPRINT("| ELF_LOGFILE_HEADER_WRAP ");
if (header->Flags & ELF_LOGGFILE_LOGFULL_WRITTEN) DPRINT("| ELF_LOGGFILE_LOGFULL_WRITTEN ");
if (header->Flags & ELF_LOGFILE_ARCHIVE_SET) DPRINT("| ELF_LOGFILE_ARCHIVE_SET ");
DPRINT("\n");
}
VOID PRINT_RECORD(PEVENTLOGRECORD pRec)
{
UINT i;
WCHAR *str;
SYSTEMTIME time;
DPRINT("Length = %d\n", pRec->Length);
DPRINT("Reserved = 0x%x\n", pRec->Reserved);
DPRINT("RecordNumber = %d\n", pRec->RecordNumber);
EventTimeToSystemTime(pRec->TimeGenerated, &time);
DPRINT("TimeGenerated = %d.%d.%d %d:%d:%d\n",
time.wDay, time.wMonth, time.wYear,
time.wHour, time.wMinute, time.wSecond);
EventTimeToSystemTime(pRec->TimeWritten, &time);
DPRINT("TimeWritten = %d.%d.%d %d:%d:%d\n",
time.wDay, time.wMonth, time.wYear,
time.wHour, time.wMinute, time.wSecond);
DPRINT("EventID = %d\n", pRec->EventID);
switch (pRec->EventType)
{
case EVENTLOG_ERROR_TYPE:
DPRINT("EventType = EVENTLOG_ERROR_TYPE\n");
break;
case EVENTLOG_WARNING_TYPE:
DPRINT("EventType = EVENTLOG_WARNING_TYPE\n");
break;
case EVENTLOG_INFORMATION_TYPE:
DPRINT("EventType = EVENTLOG_INFORMATION_TYPE\n");
break;
case EVENTLOG_AUDIT_SUCCESS:
DPRINT("EventType = EVENTLOG_AUDIT_SUCCESS\n");
break;
case EVENTLOG_AUDIT_FAILURE:
DPRINT("EventType = EVENTLOG_AUDIT_FAILURE\n");
break;
default:
DPRINT("EventType = %d\n", pRec->EventType);
}
DPRINT("NumStrings = %d\n", pRec->NumStrings);
DPRINT("EventCategory = %d\n", pRec->EventCategory);
DPRINT("ReservedFlags = 0x%x\n", pRec->ReservedFlags);
DPRINT("ClosingRecordNumber = %d\n", pRec->ClosingRecordNumber);
DPRINT("StringOffset = %d\n", pRec->StringOffset);
DPRINT("UserSidLength = %d\n", pRec->UserSidLength);
DPRINT("UserSidOffset = %d\n", pRec->UserSidOffset);
DPRINT("DataLength = %d\n", pRec->DataLength);
DPRINT("DataOffset = %d\n", pRec->DataOffset);
DPRINT("SourceName: %S\n", (WCHAR *) (((PBYTE) pRec) + sizeof(EVENTLOGRECORD)));
i = (lstrlenW((WCHAR *) (((PBYTE) pRec) + sizeof(EVENTLOGRECORD))) + 1) *
sizeof(WCHAR);
DPRINT("ComputerName: %S\n", (WCHAR *) (((PBYTE) pRec) + sizeof(EVENTLOGRECORD) + i));
if (pRec->StringOffset < pRec->Length && pRec->NumStrings)
{
DPRINT("Strings:\n");
str = (WCHAR *) (((PBYTE) pRec) + pRec->StringOffset);
for (i = 0; i < pRec->NumStrings; i++)
{
DPRINT("[%d] %S\n", i, str);
str = str + lstrlenW(str) + 1;
}
}
DPRINT("Length2 = %d\n", *(PDWORD) (((PBYTE) pRec) + pRec->Length - 4));
}

View file

@ -0,0 +1,198 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/eventlog/eventlog.h
* PURPOSE: Event logging service
* COPYRIGHT: Copyright 2005 Saveliy Tretiakov
*/
#ifndef __EVENTLOG_H__
#define __EVENTLOG_H__
#define NDEBUG
#define WIN32_NO_STATUS
#include <windows.h>
#include <lpctypes.h>
#include <lpcfuncs.h>
#include <rtlfuncs.h>
#include <obfuncs.h>
#include <iotypes.h>
#include <debug.h>
#include "eventlogrpc_s.h"
typedef struct _IO_ERROR_LPC
{
PORT_MESSAGE Header;
IO_ERROR_LOG_MESSAGE Message;
} IO_ERROR_LPC, *PIO_ERROR_LPC;
#define MAJORVER 1
#define MINORVER 1
/*
* Our file format will be compatible with NT's
*/
#define LOGFILE_SIGNATURE 0x654c664c
/*
* Flags used in logfile header
*/
#define ELF_LOGFILE_HEADER_DIRTY 1
#define ELF_LOGFILE_HEADER_WRAP 2
#define ELF_LOGGFILE_LOGFULL_WRITTEN 4
#define ELF_LOGFILE_ARCHIVE_SET 8
/* FIXME: MSDN reads that the following two structs are in winnt.h. Are they? */
typedef struct _EVENTLOGHEADER {
ULONG HeaderSize;
ULONG Signature;
ULONG MajorVersion;
ULONG MinorVersion;
ULONG StartOffset;
ULONG EndOffset;
ULONG CurrentRecordNumber;
ULONG OldestRecordNumber;
ULONG MaxSize;
ULONG Flags;
ULONG Retention;
ULONG EndHeaderSize;
} EVENTLOGHEADER, *PEVENTLOGHEADER;
typedef struct _EVENTLOGEOF {
ULONG RecordSizeBeginning;
ULONG Ones;
ULONG Twos;
ULONG Threes;
ULONG Fours;
ULONG BeginRecord;
ULONG EndRecord;
ULONG CurrentRecordNumber;
ULONG OldestRecordNumber;
ULONG RecordSizeEnd;
} EVENTLOGEOF, *PEVENTLOGEOF;
typedef struct
{
ULONG EventNumber;
ULONG EventOffset;
} EVENT_OFFSET_INFO, *PEVENT_OFFSET_INFO;
typedef struct
{
HANDLE hFile;
EVENTLOGHEADER Header;
WCHAR *LogName;
WCHAR *FileName;
CRITICAL_SECTION cs;
PEVENT_OFFSET_INFO OffsetInfo;
ULONG OffsetInfoSize;
ULONG OffsetInfoNext;
LIST_ENTRY ListEntry;
} LOGFILE, *PLOGFILE;
typedef struct _EVENTSOURCE
{
LIST_ENTRY EventSourceListEntry;
PLOGFILE LogFile;
ULONG CurrentRecord;
WCHAR szName[1];
} EVENTSOURCE, *PEVENTSOURCE;
/* file.c */
VOID LogfListInitialize(VOID);
PLOGFILE LogfListHead(VOID);
INT LogfListItemCount(VOID);
PLOGFILE LogfListItemByIndex(INT Index);
PLOGFILE LogfListItemByName(WCHAR * Name);
INT LogfListItemIndexByName(WCHAR * Name);
VOID LogfListAddItem(PLOGFILE Item);
VOID LogfListRemoveItem(PLOGFILE Item);
DWORD LogfReadEvent(PLOGFILE LogFile,
DWORD Flags,
DWORD * RecordNumber,
DWORD BufSize,
PBYTE Buffer,
DWORD * BytesRead,
DWORD * BytesNeeded);
BOOL LogfWriteData(PLOGFILE LogFile,
DWORD BufSize,
PBYTE Buffer);
PLOGFILE LogfCreate(WCHAR * LogName,
WCHAR * FileName);
VOID LogfClose(PLOGFILE LogFile);
VOID LogfCloseAll(VOID);
BOOL LogfInitializeNew(PLOGFILE LogFile);
BOOL LogfInitializeExisting(PLOGFILE LogFile);
DWORD LogfGetOldestRecord(PLOGFILE LogFile);
DWORD LogfGetCurrentRecord(PLOGFILE LogFile);
ULONG LogfOffsetByNumber(PLOGFILE LogFile,
DWORD RecordNumber);
BOOL LogfAddOffsetInformation(PLOGFILE LogFile,
ULONG ulNumber,
ULONG ulOffset);
BOOL LogfDeleteOffsetInformation(PLOGFILE LogFile,
ULONG ulNumber);
PBYTE LogfAllocAndBuildNewRecord(LPDWORD lpRecSize,
DWORD dwRecordNumber,
WORD wType,
WORD wCategory,
DWORD dwEventId,
LPCWSTR SourceName,
LPCWSTR ComputerName,
DWORD dwSidLength,
PSID lpUserSid,
WORD wNumStrings,
WCHAR * lpStrings,
DWORD dwDataSize,
LPVOID lpRawData);
/* eventlog.c */
extern HANDLE MyHeap;
VOID PRINT_HEADER(PEVENTLOGHEADER header);
VOID PRINT_RECORD(PEVENTLOGRECORD pRec);
VOID EventTimeToSystemTime(DWORD EventTime,
SYSTEMTIME * SystemTime);
VOID SystemTimeToEventTime(SYSTEMTIME * pSystemTime,
DWORD * pEventTime);
/* logport.c */
NTSTATUS WINAPI PortThreadRoutine(PVOID Param);
NTSTATUS InitLogPort(VOID);
NTSTATUS ProcessPortMessage(VOID);
/* rpc.c */
DWORD WINAPI RpcThreadRoutine(LPVOID lpParameter);
static __inline void LogfFreeRecord(LPVOID Rec)
{
HeapFree(MyHeap, 0, Rec);
}
#endif /* __EVENTLOG_H__ */

View file

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="eventlog" type="win32cui" installbase="system32" installname="eventlog.exe" unicode="yes">
<include base="eventlog">.</include>
<include base="eventlog_server">.</include>
<library>ntdll</library>
<library>advapi32</library>
<library>eventlog_server</library>
<library>rpcrt4</library>
<library>pseh</library>
<file>eventlog.c</file>
<file>logport.c</file>
<file>eventlog.rc</file>
<file>rpc.c</file>
<file>file.c</file>
<pch>eventlog.h</pch>
</module>

View file

@ -0,0 +1,4 @@
#define REACTOS_STR_FILE_DESCRIPTION "Event logging service\0"
#define REACTOS_STR_INTERNAL_NAME "EventLog\0"
#define REACTOS_STR_ORIGINAL_FILENAME "EventLog.exe\0"
#include <reactos/version.rc>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,186 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/eventlog/logport.c
* PURPOSE: Event logging service
* COPYRIGHT: Copyright 2002 Eric Kohl
* Copyright 2005 Saveliy Tretiakov
*/
/* INCLUDES *****************************************************************/
#include "eventlog.h"
/* GLOBALS ******************************************************************/
HANDLE ConnectPortHandle = NULL;
HANDLE MessagePortHandle = NULL;
extern BOOL onLiveCD;
/* FUNCTIONS ****************************************************************/
NTSTATUS WINAPI PortThreadRoutine(PVOID Param)
{
NTSTATUS Status = STATUS_SUCCESS;
Status = InitLogPort();
if (!NT_SUCCESS(Status))
return Status;
while (NT_SUCCESS(Status))
Status = ProcessPortMessage();
if (ConnectPortHandle != NULL)
NtClose(ConnectPortHandle);
if (MessagePortHandle != NULL)
NtClose(MessagePortHandle);
return Status;
}
NTSTATUS InitLogPort(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING PortName;
PORT_MESSAGE Request;
NTSTATUS Status;
ConnectPortHandle = NULL;
MessagePortHandle = NULL;
RtlInitUnicodeString(&PortName, L"\\ErrorLogPort");
InitializeObjectAttributes(&ObjectAttributes, &PortName, 0, NULL, NULL);
Status = NtCreatePort(&ConnectPortHandle,
&ObjectAttributes,
0,
0x100,
0x2000);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreatePort() failed (Status %lx)\n", Status);
goto ByeBye;
}
Status = NtListenPort(ConnectPortHandle, &Request);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtListenPort() failed (Status %lx)\n", Status);
goto ByeBye;
}
Status = NtAcceptConnectPort(&MessagePortHandle, ConnectPortHandle,
NULL, TRUE, NULL, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtAcceptConnectPort() failed (Status %lx)\n", Status);
goto ByeBye;
}
Status = NtCompleteConnectPort(MessagePortHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCompleteConnectPort() failed (Status %lx)\n", Status);
goto ByeBye;
}
ByeBye:
if (!NT_SUCCESS(Status))
{
if (ConnectPortHandle != NULL)
NtClose(ConnectPortHandle);
if (MessagePortHandle != NULL)
NtClose(MessagePortHandle);
}
return Status;
}
NTSTATUS ProcessPortMessage(VOID)
{
IO_ERROR_LPC Request;
PIO_ERROR_LOG_MESSAGE Message;
PEVENTLOGRECORD pRec;
ULONG ulRecNum;
DWORD dwRecSize;
NTSTATUS Status;
PLOGFILE SystemLog = NULL;
DPRINT("ProcessPortMessage() called\n");
SystemLog = LogfListItemByName(L"System");
while (TRUE)
{
Status = NtReplyWaitReceivePort(MessagePortHandle,
0,
NULL,
&Request.Header);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtReplyWaitReceivePort() failed (Status %lx)\n", Status);
break;
}
DPRINT("Received message\n");
if (Request.Header.u2.s2.Type == LPC_PORT_CLOSED)
{
DPRINT("Port closed\n");
return STATUS_SUCCESS;
}
if (Request.Header.u2.s2.Type == LPC_REQUEST)
{
DPRINT("Received request\n");
}
else if (Request.Header.u2.s2.Type == LPC_DATAGRAM)
{
DPRINT("Received datagram\n");
Message = (PIO_ERROR_LOG_MESSAGE) & Request.Message;
ulRecNum = SystemLog ? SystemLog->Header.CurrentRecordNumber : 0;
pRec = (PEVENTLOGRECORD) LogfAllocAndBuildNewRecord(&dwRecSize,
ulRecNum, Message->Type, Message->EntryData.EventCategory,
Message->EntryData.ErrorCode,
(WCHAR *) (((PBYTE) Message) + Message->DriverNameOffset),
L"MyComputer", /* FIXME */
0,
NULL,
Message->EntryData.NumberOfStrings,
(WCHAR *) (((PBYTE) Message) + Message->EntryData.StringOffset),
Message->EntryData.DumpDataSize,
(LPVOID) (((PBYTE) Message) + sizeof(IO_ERROR_LOG_PACKET) -
sizeof(ULONG)));
if (pRec == NULL)
{
DPRINT("LogfAllocAndBuildNewRecord failed!\n");
return STATUS_NO_MEMORY;
}
DPRINT("dwRecSize = %d\n", dwRecSize);
DPRINT("\n --- EVENTLOG RECORD ---\n");
PRINT_RECORD(pRec);
DPRINT("\n");
if (!onLiveCD && SystemLog)
{
if (!LogfWriteData(SystemLog, dwRecSize, (PBYTE) pRec))
DPRINT("LogfWriteData failed!\n");
else
DPRINT("Data written to Log!\n");
}
LogfFreeRecord(pRec);
}
}
return Status;
}

View file

@ -0,0 +1,715 @@
/*
* PROJECT: ReactOS kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: services/eventlog/rpc.c
* PURPOSE: Event logging service
* COPYRIGHT: Copyright 2005 Saveliy Tretiakov
* Copyright 2008 Michael Martin
*/
/* INCLUDES *****************************************************************/
#include "eventlog.h"
LIST_ENTRY EventSourceListHead;
/* FUNCTIONS ****************************************************************/
DWORD WINAPI RpcThreadRoutine(LPVOID lpParameter)
{
RPC_STATUS Status;
InitializeListHead(&EventSourceListHead);
Status = RpcServerUseProtseqEpW(L"ncacn_np", 20, L"\\pipe\\EventLog", NULL);
if (Status != RPC_S_OK)
{
DPRINT("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
return 0;
}
Status = RpcServerRegisterIf(eventlog_v0_0_s_ifspec, NULL, NULL);
if (Status != RPC_S_OK)
{
DPRINT("RpcServerRegisterIf() failed (Status %lx)\n", Status);
return 0;
}
Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
if (Status != RPC_S_OK)
{
DPRINT("RpcServerListen() failed (Status %lx)\n", Status);
}
return 0;
}
PEVENTSOURCE ElfCreateEventLogHandle(LPCWSTR Name, BOOL Create)
{
PEVENTSOURCE lpEventSource;
PLOGFILE currentLogFile = NULL;
INT i, LogsActive;
lpEventSource = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTSOURCE)
+ ((wcslen(Name) + 1) * sizeof(WCHAR)));
if (!lpEventSource)
{
DPRINT1("Failed to allocate Heap!\n");
return NULL;
}
wcscpy(lpEventSource->szName, Name);
/* Get the number of Log Files the EventLog service found */
LogsActive = LogfListItemCount();
if (LogsActive == 0)
{
DPRINT1("EventLog service reports no log files!\n");
goto Cleanup;
}
/* If Creating, default to the Application Log in case we fail, as documented on MSDN */
if (Create == TRUE)
lpEventSource->LogFile = LogfListItemByName(L"Application");
else
lpEventSource->LogFile = NULL;
for (i = 1; i <= LogsActive; i++)
{
currentLogFile = LogfListItemByIndex(i);
if (_wcsicmp(Name, currentLogFile->LogName) == 0)
{
lpEventSource->LogFile = LogfListItemByIndex(i);
lpEventSource->CurrentRecord = LogfGetOldestRecord(lpEventSource->LogFile);
break;
}
}
if (!lpEventSource->LogFile)
goto Cleanup;
/* Append service record */
InsertTailList(&EventSourceListHead, &lpEventSource->EventSourceListEntry);
return lpEventSource;
Cleanup:
HeapFree(GetProcessHeap(), 0, lpEventSource);
return NULL;
}
PEVENTSOURCE ElfGetEventLogSourceEntryByHandle(IELF_HANDLE EventLogHandle)
{
PEVENTSOURCE CurrentEventSource;
if (IsListEmpty(&EventSourceListHead))
{
return NULL;
}
CurrentEventSource = CONTAINING_RECORD((PEVENTSOURCE)EventLogHandle, EVENTSOURCE, EventSourceListEntry);
return CurrentEventSource;
}
BOOL ElfDeleteEventLogHandle(IELF_HANDLE EventLogHandle)
{
PEVENTSOURCE lpEventSource = (PEVENTSOURCE)EventLogHandle;
if (!ElfGetEventLogSourceEntryByHandle(lpEventSource))
{
return FALSE;
}
RemoveEntryList(&lpEventSource->EventSourceListEntry);
HeapFree(GetProcessHeap(),0,lpEventSource);
return TRUE;
}
/* Function 0 */
NTSTATUS ElfrClearELFW(
IELF_HANDLE LogHandle,
PRPC_UNICODE_STRING BackupFileName)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 1 */
NTSTATUS ElfrBackupELFW(
IELF_HANDLE LogHandle,
PRPC_UNICODE_STRING BackupFileName)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 2 */
NTSTATUS ElfrCloseEL(
IELF_HANDLE *LogHandle)
{
if (!ElfDeleteEventLogHandle(*LogHandle))
{
return STATUS_INVALID_HANDLE;
}
return STATUS_SUCCESS;
}
/* Function 3 */
NTSTATUS ElfrDeregisterEventSource(
IELF_HANDLE *LogHandle)
{
if (!ElfDeleteEventLogHandle(*LogHandle))
{
return STATUS_INVALID_HANDLE;
}
return STATUS_SUCCESS;
}
/* Function 4 */
NTSTATUS ElfrNumberOfRecords(
IELF_HANDLE LogHandle,
DWORD *NumberOfRecords)
{
PEVENTSOURCE lpEventSource;
lpEventSource = ElfGetEventLogSourceEntryByHandle(LogHandle);
if (!lpEventSource)
{
return STATUS_INVALID_HANDLE;
}
*NumberOfRecords = lpEventSource->LogFile->Header.CurrentRecordNumber;
return STATUS_SUCCESS;
}
/* Function 5 */
NTSTATUS ElfrOldestRecord(
IELF_HANDLE LogHandle,
DWORD *OldestRecordNumber)
{
PEVENTSOURCE lpEventSource;
lpEventSource = ElfGetEventLogSourceEntryByHandle(LogHandle);
if (!lpEventSource)
{
return STATUS_INVALID_HANDLE;
}
if (!OldestRecordNumber)
{
return STATUS_INVALID_PARAMETER;
}
*OldestRecordNumber = 0;
*OldestRecordNumber = LogfGetOldestRecord(lpEventSource->LogFile);
return STATUS_SUCCESS;
}
/* Function 6 */
NTSTATUS ElfrChangeNotify(
IELF_HANDLE *LogHandle,
RPC_CLIENT_ID ClientId,
DWORD Event)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 7 */
NTSTATUS ElfrOpenELW(
EVENTLOG_HANDLE_W UNCServerName,
PRPC_UNICODE_STRING ModuleName,
PRPC_UNICODE_STRING RegModuleName,
DWORD MajorVersion,
DWORD MinorVersion,
IELF_HANDLE *LogHandle)
{
if ((MajorVersion != 1) || (MinorVersion != 1))
return STATUS_INVALID_PARAMETER;
/* RegModuleName must be an empty string */
if (RegModuleName->Length > 0)
return STATUS_INVALID_PARAMETER;
/*FIXME: UNCServerName must specify the server */
/*FIXME: Must verify that caller has read access */
*LogHandle = ElfCreateEventLogHandle(ModuleName->Buffer, FALSE);
if (*LogHandle == NULL)
{
return STATUS_INVALID_PARAMETER;
}
return STATUS_SUCCESS;
}
/* Function 8 */
NTSTATUS ElfrRegisterEventSourceW(
EVENTLOG_HANDLE_W UNCServerName,
PRPC_UNICODE_STRING ModuleName,
PRPC_UNICODE_STRING RegModuleName,
DWORD MajorVersion,
DWORD MinorVersion,
IELF_HANDLE *LogHandle)
{
if ((MajorVersion != 1) || (MinorVersion != 1))
return STATUS_INVALID_PARAMETER;
/* RegModuleName must be an empty string */
if (RegModuleName->Length > 0)
return STATUS_INVALID_PARAMETER;
/*FIXME: UNCServerName must specify the server or empty for local */
/*FIXME: Must verify that caller has write access */
*LogHandle = ElfCreateEventLogHandle(ModuleName->Buffer, TRUE);
return STATUS_SUCCESS;
}
/* Function 9 */
NTSTATUS ElfrOpenBELW(
EVENTLOG_HANDLE_W UNCServerName,
PRPC_UNICODE_STRING BackupFileName,
DWORD MajorVersion,
DWORD MinorVersion,
IELF_HANDLE *LogHandle)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 10 */
NTSTATUS ElfrReadELW(
IELF_HANDLE LogHandle,
DWORD ReadFlags,
DWORD RecordOffset,
RULONG NumberOfBytesToRead,
BYTE *Buffer,
DWORD *NumberOfBytesRead,
DWORD *MinNumberOfBytesNeeded)
{
PEVENTSOURCE lpEventSource;
DWORD dwError;
DWORD RecordNumber;
lpEventSource = ElfGetEventLogSourceEntryByHandle(LogHandle);
if (!lpEventSource)
{
return STATUS_INVALID_HANDLE;
}
if (!Buffer)
return I_RpcMapWin32Status(ERROR_INVALID_PARAMETER);
/* If sequential read, retrieve the CurrentRecord from this log handle */
if (ReadFlags & EVENTLOG_SEQUENTIAL_READ)
{
RecordNumber = lpEventSource->CurrentRecord;
}
else
{
RecordNumber = RecordOffset;
}
dwError = LogfReadEvent(lpEventSource->LogFile, ReadFlags, &RecordNumber,
NumberOfBytesToRead, Buffer, NumberOfBytesRead, MinNumberOfBytesNeeded);
/* Update the handles CurrentRecord if success*/
if (dwError == ERROR_SUCCESS)
{
lpEventSource->CurrentRecord = RecordNumber;
}
return I_RpcMapWin32Status(dwError);
}
/* Function 11 */
NTSTATUS ElfrReportEventW(
IELF_HANDLE LogHandle,
DWORD Time,
USHORT EventType,
USHORT EventCategory,
DWORD EventID,
USHORT NumStrings,
DWORD DataSize,
PRPC_UNICODE_STRING ComputerName,
PRPC_SID UserSID,
PRPC_UNICODE_STRING Strings[],
BYTE *Data,
USHORT Flags,
DWORD *RecordNumber,
DWORD *TimeWritten)
{
USHORT i;
PBYTE LogBuffer;
PEVENTSOURCE lpEventSource;
DWORD lastRec;
DWORD recSize;
DWORD dwStringsSize = 0;
DWORD dwError = ERROR_SUCCESS;
WCHAR *lpStrings;
int pos = 0;
lpEventSource = ElfGetEventLogSourceEntryByHandle(LogHandle);
if (!lpEventSource)
{
return STATUS_INVALID_HANDLE;
}
/* Flags must be 0 */
if (Flags)
{
return STATUS_INVALID_PARAMETER;
}
lastRec = LogfGetCurrentRecord(lpEventSource->LogFile);
for (i = 0; i < NumStrings; i++)
{
switch (EventType)
{
case EVENTLOG_SUCCESS:
DPRINT("Success: %wZ\n", Strings[i]);
break;
case EVENTLOG_ERROR_TYPE:
DPRINT("Error: %wZ\n", Strings[i]);
break;
case EVENTLOG_WARNING_TYPE:
DPRINT("Warning: %wZ\n", Strings[i]);
break;
case EVENTLOG_INFORMATION_TYPE:
DPRINT("Info: %wZ\n", Strings[i]);
break;
default:
DPRINT1("Type %hu: %wZ\n", EventType, Strings[i]);
break;
}
dwStringsSize += (wcslen(Strings[i]->Buffer) + 1) * sizeof(WCHAR);
}
lpStrings = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, dwStringsSize * 2);
if (!lpStrings)
{
DPRINT1("Failed to allocate heap\n");
return STATUS_NO_MEMORY;
}
for (i = 0; i < NumStrings; i++)
{
wcscpy((WCHAR*)(lpStrings + pos), Strings[i]->Buffer);
pos += (wcslen(Strings[i]->Buffer) + 1) * sizeof(WCHAR);
}
LogBuffer = LogfAllocAndBuildNewRecord(&recSize,
lastRec,
EventType,
EventCategory,
EventID,
lpEventSource->szName,
ComputerName->Buffer,
sizeof(UserSID),
&UserSID,
NumStrings,
(WCHAR*)lpStrings,
DataSize,
Data);
dwError = LogfWriteData(lpEventSource->LogFile, recSize, LogBuffer);
if (!dwError)
{
DPRINT1("ERROR WRITING TO EventLog %S\n",lpEventSource->LogFile->FileName);
}
LogfFreeRecord(LogBuffer);
HeapFree(GetProcessHeap(), 0, lpStrings);
return I_RpcMapWin32Status(dwError);
}
/* Function 12 */
NTSTATUS ElfrClearELFA(
IELF_HANDLE LogHandle,
PRPC_STRING BackupFileName)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 13 */
NTSTATUS ElfrBackupELFA(
IELF_HANDLE LogHandle,
PRPC_STRING BackupFileName)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 14 */
NTSTATUS ElfrOpenELA(
EVENTLOG_HANDLE_A UNCServerName,
PRPC_STRING ModuleName,
PRPC_STRING RegModuleName,
DWORD MajorVersion,
DWORD MinorVersion,
IELF_HANDLE *LogHandle)
{
UNICODE_STRING UNCServerNameW = { 0, 0, NULL };
UNICODE_STRING ModuleNameW = { 0, 0, NULL };
UNICODE_STRING RegModuleNameW = { 0, 0, NULL };
NTSTATUS Status;
if (UNCServerName &&
!RtlCreateUnicodeStringFromAsciiz(&UNCServerNameW, UNCServerName))
{
return STATUS_NO_MEMORY;
}
if (ModuleName &&
!RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE))
{
RtlFreeUnicodeString(&UNCServerNameW);
return STATUS_NO_MEMORY;
}
if (RegModuleName &&
!RtlAnsiStringToUnicodeString(&RegModuleNameW, (PANSI_STRING)RegModuleName, TRUE))
{
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
return STATUS_NO_MEMORY;
}
Status = ElfrOpenELW(
UNCServerName ? UNCServerNameW.Buffer : NULL,
ModuleName ? (PRPC_UNICODE_STRING)&ModuleNameW : NULL,
RegModuleName ? (PRPC_UNICODE_STRING)&RegModuleNameW : NULL,
MajorVersion,
MinorVersion,
LogHandle);
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
RtlFreeUnicodeString(&RegModuleNameW);
return Status;
}
/* Function 15 */
NTSTATUS ElfrRegisterEventSourceA(
EVENTLOG_HANDLE_A UNCServerName,
PRPC_STRING ModuleName,
PRPC_STRING RegModuleName,
DWORD MajorVersion,
DWORD MinorVersion,
IELF_HANDLE *LogHandle)
{
UNICODE_STRING UNCServerNameW = { 0, 0, NULL };
UNICODE_STRING ModuleNameW = { 0, 0, NULL };
if (UNCServerName &&
!RtlCreateUnicodeStringFromAsciiz(&UNCServerNameW, UNCServerName))
{
return STATUS_NO_MEMORY;
}
if (ModuleName &&
!RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE))
{
RtlFreeUnicodeString(&UNCServerNameW);
return STATUS_NO_MEMORY;
}
/* RegModuleName must be an empty string */
if (RegModuleName->Length > 0)
{
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
return STATUS_INVALID_PARAMETER;
}
if ((MajorVersion != 1) || (MinorVersion != 1))
{
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
return STATUS_INVALID_PARAMETER;
}
/*FIXME: UNCServerName must specify the server or empty for local */
/*FIXME: Must verify that caller has write access */
*LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer,
TRUE);
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
return STATUS_SUCCESS;
}
/* Function 16 */
NTSTATUS ElfrOpenBELA(
EVENTLOG_HANDLE_A UNCServerName,
PRPC_STRING BackupFileName,
DWORD MajorVersion,
DWORD MinorVersion,
IELF_HANDLE *LogHandle)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 17 */
NTSTATUS ElfrReadELA(
IELF_HANDLE LogHandle,
DWORD ReadFlags,
DWORD RecordOffset,
RULONG NumberOfBytesToRead,
BYTE *Buffer,
DWORD *NumberOfBytesRead,
DWORD *MinNumberOfBytesNeeded)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 18 */
NTSTATUS ElfrReportEventA(
IELF_HANDLE LogHandle,
DWORD Time,
USHORT EventType,
USHORT EventCategory,
DWORD EventID,
USHORT NumStrings,
DWORD DataSize,
PRPC_STRING ComputerName,
PRPC_SID UserSID,
PRPC_STRING Strings[],
BYTE *Data,
USHORT Flags,
DWORD *RecordNumber,
DWORD *TimeWritten)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 19 */
NTSTATUS ElfrRegisterClusterSvc(
handle_t BindingHandle)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 20 */
NTSTATUS ElfrDeregisterClusterSvc(
handle_t BindingHandle)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 21 */
NTSTATUS ElfrWriteClusterEvents(
handle_t BindingHandle)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 22 */
NTSTATUS ElfrGetLogInformation(
IELF_HANDLE LogHandle,
DWORD InfoLevel,
BYTE *Buffer,
DWORD cbBufSize,
DWORD *pcbBytesNeeded)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 23 */
NTSTATUS ElfrFlushEL(
IELF_HANDLE LogHandle)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* Function 24 */
NTSTATUS ElfrReportEventAndSourceW(
IELF_HANDLE LogHandle,
DWORD Time,
USHORT EventType,
USHORT EventCategory,
ULONG EventID,
PRPC_UNICODE_STRING SourceName,
USHORT NumStrings,
DWORD DataSize,
PRPC_UNICODE_STRING ComputerName,
PRPC_SID UserSID,
PRPC_UNICODE_STRING Strings[],
BYTE *Data,
USHORT Flags,
DWORD *RecordNumber,
DWORD *TimeWritten)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
}
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
HeapFree(GetProcessHeap(), 0, ptr);
}
void __RPC_USER IELF_HANDLE_rundown(IELF_HANDLE LogHandle)
{
}

View file

@ -0,0 +1,19 @@
/*
* Copyright 2008 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/epm.idl"

284
base/services/rpcss/epmp.c Normal file
View file

@ -0,0 +1,284 @@
/*
* Endpoint Mapper
*
* Copyright (C) 2007 Robert Shearman for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "epm_s.h"
#include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
struct registered_ept_entry
{
struct list entry;
GUID object;
RPC_SYNTAX_IDENTIFIER iface;
RPC_SYNTAX_IDENTIFIER syntax;
char *protseq;
char *endpoint;
char *address;
char annotation[ept_max_annotation_size];
};
static struct list registered_ept_entry_list = LIST_INIT(registered_ept_entry_list);
static CRITICAL_SECTION csEpm;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &csEpm,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": csEpm") }
};
static CRITICAL_SECTION csEpm = { &critsect_debug, -1, 0, 0, 0, 0 };
static const UUID nil_object;
/* must be called inside csEpm */
static void delete_registered_ept_entry(struct registered_ept_entry *entry)
{
I_RpcFree(entry->protseq);
I_RpcFree(entry->endpoint);
I_RpcFree(entry->address);
list_remove(&entry->entry);
HeapFree(GetProcessHeap(), 0, entry);
}
static struct registered_ept_entry *find_ept_entry(
const RPC_SYNTAX_IDENTIFIER *iface, const RPC_SYNTAX_IDENTIFIER *syntax,
const char *protseq, const char *endpoint, const char *address,
const UUID *object)
{
struct registered_ept_entry *entry;
LIST_FOR_EACH_ENTRY(entry, &registered_ept_entry_list, struct registered_ept_entry, entry)
{
if (memcmp(&entry->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
if (memcmp(&entry->syntax, syntax, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
if (strcmp(entry->protseq, protseq)) continue;
if (memcmp(&entry->object, object, sizeof(UUID))) continue;
WINE_TRACE("found entry with iface %d.%d %s, syntax %d.%d %s, protseq %s, object %s\n",
entry->iface.SyntaxVersion.MajorVersion, entry->iface.SyntaxVersion.MinorVersion,
wine_dbgstr_guid(&entry->iface.SyntaxGUID),
entry->syntax.SyntaxVersion.MajorVersion, entry->syntax.SyntaxVersion.MinorVersion,
wine_dbgstr_guid(&entry->syntax.SyntaxGUID), protseq,
wine_dbgstr_guid(&entry->object));
return entry;
}
WINE_TRACE("not found\n");
return NULL;
}
void __RPC_USER ept_lookup_handle_t_rundown(ept_lookup_handle_t entry_handle)
{
WINE_FIXME("%p\n", entry_handle);
}
void ept_insert(handle_t h,
unsigned32 num_ents,
ept_entry_t entries[],
boolean32 replace,
error_status_t *status)
{
unsigned32 i;
RPC_STATUS rpc_status;
WINE_TRACE("(%p, %lu, %p, %lu, %p)\n", h, num_ents, entries, replace, status);
*status = RPC_S_OK;
EnterCriticalSection(&csEpm);
for (i = 0; i < num_ents; i++)
{
struct registered_ept_entry *entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
if (!entry)
{
/* FIXME: cleanup code to delete added entries */
*status = EPT_S_CANT_PERFORM_OP;
break;
}
list_init(&entry->entry);
memcpy(entry->annotation, entries[i].annotation, sizeof(entries[i].annotation));
rpc_status = TowerExplode(entries[i].tower, &entry->iface, &entry->syntax,
&entry->protseq, &entry->endpoint,
&entry->address);
if (rpc_status != RPC_S_OK)
{
WINE_WARN("TowerExplode failed %lu\n", rpc_status);
*status = rpc_status;
break; /* FIXME: more cleanup? */
}
entry->object = entries[i].object;
if (replace)
{
/* FIXME: correct find algorithm */
struct registered_ept_entry *old_entry = find_ept_entry(&entry->iface, &entry->syntax, entry->protseq, entry->endpoint, entry->address, &entry->object);
if (old_entry) delete_registered_ept_entry(old_entry);
}
list_add_tail(&registered_ept_entry_list, &entry->entry);
}
LeaveCriticalSection(&csEpm);
}
void ept_delete(handle_t h,
unsigned32 num_ents,
ept_entry_t entries[],
error_status_t *status)
{
unsigned32 i;
RPC_STATUS rpc_status;
*status = RPC_S_OK;
WINE_TRACE("(%p, %lu, %p, %p)\n", h, num_ents, entries, status);
EnterCriticalSection(&csEpm);
for (i = 0; i < num_ents; i++)
{
struct registered_ept_entry *entry;
RPC_SYNTAX_IDENTIFIER iface, syntax;
char *protseq;
char *endpoint;
char *address;
rpc_status = TowerExplode(entries[i].tower, &iface, &syntax, &protseq,
&endpoint, &address);
if (rpc_status != RPC_S_OK)
break;
entry = find_ept_entry(&iface, &syntax, protseq, endpoint, address, &entries[i].object);
if (entry)
delete_registered_ept_entry(entry);
else
{
*status = EPT_S_NOT_REGISTERED;
break;
}
I_RpcFree(protseq);
I_RpcFree(endpoint);
I_RpcFree(address);
}
LeaveCriticalSection(&csEpm);
}
void ept_lookup(handle_t h,
unsigned32 inquiry_type,
uuid_p_t object,
rpc_if_id_p_t interface_id,
unsigned32 vers_option,
ept_lookup_handle_t *entry_handle,
unsigned32 max_ents,
unsigned32 *num_ents,
ept_entry_t entries[],
error_status_t *status)
{
WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
*status = EPT_S_CANT_PERFORM_OP;
}
void ept_map(handle_t h,
uuid_p_t object,
twr_p_t map_tower,
ept_lookup_handle_t *entry_handle,
unsigned32 max_towers,
unsigned32 *num_towers,
twr_p_t *towers,
error_status_t *status)
{
RPC_STATUS rpc_status;
RPC_SYNTAX_IDENTIFIER iface, syntax;
char *protseq;
struct registered_ept_entry *entry;
*status = RPC_S_OK;
*num_towers = 0;
WINE_TRACE("(%p, %p, %p, %p, %lu, %p, %p, %p)\n", h, object, map_tower,
entry_handle, max_towers, num_towers, towers, status);
rpc_status = TowerExplode(map_tower, &iface, &syntax, &protseq,
NULL, NULL);
if (rpc_status != RPC_S_OK)
{
*status = rpc_status;
return;
}
EnterCriticalSection(&csEpm);
LIST_FOR_EACH_ENTRY(entry, &registered_ept_entry_list, struct registered_ept_entry, entry)
{
if (IsEqualGUID(&entry->iface.SyntaxGUID, &iface.SyntaxGUID) &&
(entry->iface.SyntaxVersion.MajorVersion == iface.SyntaxVersion.MajorVersion) &&
(entry->iface.SyntaxVersion.MinorVersion >= iface.SyntaxVersion.MinorVersion) &&
!memcmp(&entry->syntax, &syntax, sizeof(syntax)) &&
!strcmp(entry->protseq, protseq) &&
((!object && IsEqualGUID(&entry->object, &nil_object)) || IsEqualGUID(object, &entry->object)))
{
if (*num_towers < max_towers)
{
rpc_status = TowerConstruct(&entry->iface, &entry->syntax,
entry->protseq, entry->endpoint,
entry->address,
&towers[*num_towers]);
if (rpc_status != RPC_S_OK)
{
*status = rpc_status;
break; /* FIXME: more cleanup? */
}
}
(*num_towers)++;
}
}
LeaveCriticalSection(&csEpm);
}
void ept_lookup_handle_free(handle_t h,
ept_lookup_handle_t *entry_handle,
error_status_t *status)
{
WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
*status = EPT_S_CANT_PERFORM_OP;
}
void ept_inq_object(handle_t h,
GUID *ept_object,
error_status_t *status)
{
WINE_FIXME("(%p, %p, %p): stub\n", h, ept_object, status);
*status = EPT_S_CANT_PERFORM_OP;
}
void ept_mgmt_delete(handle_t h,
boolean32 object_speced,
uuid_p_t object,
twr_p_t tower,
error_status_t *status)
{
WINE_FIXME("(%p, %ld, %p, %p, %p): stub\n", h, object_speced, object, tower, status);
*status = EPT_S_CANT_PERFORM_OP;
}

View file

@ -0,0 +1,19 @@
/*
* Copyright 2007 Robert Shearman for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/irot.idl"

379
base/services/rpcss/irotp.c Normal file
View file

@ -0,0 +1,379 @@
/*
* Running Object Table
*
* Copyright 2007 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <string.h>
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "irot_s.h"
#include "wine/list.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(rpcss);
/* define the structure of the running object table elements */
struct rot_entry
{
struct list entry;
InterfaceData *object; /* marshaled running object*/
InterfaceData *moniker; /* marshaled moniker that identifies this object */
MonikerComparisonData *moniker_data; /* moniker comparison data that identifies this object */
DWORD cookie; /* cookie identifying this object */
FILETIME last_modified;
LONG refs;
};
static struct list RunningObjectTable = LIST_INIT(RunningObjectTable);
static CRITICAL_SECTION csRunningObjectTable;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &csRunningObjectTable,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": csRunningObjectTable") }
};
static CRITICAL_SECTION csRunningObjectTable = { &critsect_debug, -1, 0, 0, 0, 0 };
static LONG last_cookie = 1;
static inline void rot_entry_release(struct rot_entry *rot_entry)
{
if (!InterlockedDecrement(&rot_entry->refs))
{
HeapFree(GetProcessHeap(), 0, rot_entry->object);
HeapFree(GetProcessHeap(), 0, rot_entry->moniker);
HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
HeapFree(GetProcessHeap(), 0, rot_entry);
}
}
HRESULT IrotRegister(
IrotHandle h,
const MonikerComparisonData *data,
const InterfaceData *obj,
const InterfaceData *mk,
const FILETIME *time,
DWORD grfFlags,
IrotCookie *cookie,
IrotContextHandle *ctxt_handle)
{
struct rot_entry *rot_entry;
struct rot_entry *existing_rot_entry;
HRESULT hr;
if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
{
WINE_ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
return E_INVALIDARG;
}
rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
if (!rot_entry)
return E_OUTOFMEMORY;
rot_entry->refs = 1;
rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[obj->ulCntData]));
if (!rot_entry->object)
{
rot_entry_release(rot_entry);
return E_OUTOFMEMORY;
}
rot_entry->object->ulCntData = obj->ulCntData;
memcpy(&rot_entry->object->abData, obj->abData, obj->ulCntData);
rot_entry->last_modified = *time;
rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[mk->ulCntData]));
if (!rot_entry->moniker)
{
rot_entry_release(rot_entry);
return E_OUTOFMEMORY;
}
rot_entry->moniker->ulCntData = mk->ulCntData;
memcpy(&rot_entry->moniker->abData, mk->abData, mk->ulCntData);
rot_entry->moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[data->ulCntData]));
if (!rot_entry->moniker_data)
{
rot_entry_release(rot_entry);
return E_OUTOFMEMORY;
}
rot_entry->moniker_data->ulCntData = data->ulCntData;
memcpy(&rot_entry->moniker_data->abData, data->abData, data->ulCntData);
EnterCriticalSection(&csRunningObjectTable);
hr = S_OK;
LIST_FOR_EACH_ENTRY(existing_rot_entry, &RunningObjectTable, struct rot_entry, entry)
{
if ((existing_rot_entry->moniker_data->ulCntData == data->ulCntData) &&
!memcmp(&data->abData, &existing_rot_entry->moniker_data->abData, data->ulCntData))
{
hr = MK_S_MONIKERALREADYREGISTERED;
WINE_TRACE("moniker already registered with cookie %d\n", existing_rot_entry->cookie);
break;
}
}
list_add_tail(&RunningObjectTable, &rot_entry->entry);
LeaveCriticalSection(&csRunningObjectTable);
/* gives a registration identifier to the registered object*/
*cookie = rot_entry->cookie = InterlockedIncrement(&last_cookie);
*ctxt_handle = rot_entry;
return hr;
}
HRESULT IrotRevoke(
IrotHandle h,
IrotCookie cookie,
IrotContextHandle *ctxt_handle,
PInterfaceData *obj,
PInterfaceData *mk)
{
struct rot_entry *rot_entry;
WINE_TRACE("%d\n", cookie);
EnterCriticalSection(&csRunningObjectTable);
LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
{
if (rot_entry->cookie == cookie)
{
HRESULT hr = S_OK;
list_remove(&rot_entry->entry);
LeaveCriticalSection(&csRunningObjectTable);
*obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
*mk = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
if (*obj && *mk)
{
(*obj)->ulCntData = rot_entry->object->ulCntData;
memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
(*mk)->ulCntData = rot_entry->moniker->ulCntData;
memcpy((*mk)->abData, rot_entry->moniker->abData, (*mk)->ulCntData);
}
else
{
MIDL_user_free(*obj);
MIDL_user_free(*mk);
hr = E_OUTOFMEMORY;
}
rot_entry_release(rot_entry);
*ctxt_handle = NULL;
return hr;
}
}
LeaveCriticalSection(&csRunningObjectTable);
return E_INVALIDARG;
}
HRESULT IrotIsRunning(
IrotHandle h,
const MonikerComparisonData *data)
{
const struct rot_entry *rot_entry;
HRESULT hr = S_FALSE;
WINE_TRACE("\n");
EnterCriticalSection(&csRunningObjectTable);
LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
{
if ((rot_entry->moniker_data->ulCntData == data->ulCntData) &&
!memcmp(&data->abData, &rot_entry->moniker_data->abData, data->ulCntData))
{
hr = S_OK;
break;
}
}
LeaveCriticalSection(&csRunningObjectTable);
return hr;
}
HRESULT IrotGetObject(
IrotHandle h,
const MonikerComparisonData *moniker_data,
PInterfaceData *obj,
IrotCookie *cookie)
{
const struct rot_entry *rot_entry;
WINE_TRACE("%p\n", moniker_data);
*cookie = 0;
EnterCriticalSection(&csRunningObjectTable);
LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
{
HRESULT hr = S_OK;
if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
!memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
{
*obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
if (*obj)
{
(*obj)->ulCntData = rot_entry->object->ulCntData;
memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
*cookie = rot_entry->cookie;
}
else
hr = E_OUTOFMEMORY;
LeaveCriticalSection(&csRunningObjectTable);
return hr;
}
}
LeaveCriticalSection(&csRunningObjectTable);
return MK_E_UNAVAILABLE;
}
HRESULT IrotNoteChangeTime(
IrotHandle h,
IrotCookie cookie,
const FILETIME *last_modified_time)
{
struct rot_entry *rot_entry;
WINE_TRACE("%d %p\n", cookie, last_modified_time);
EnterCriticalSection(&csRunningObjectTable);
LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
{
if (rot_entry->cookie == cookie)
{
rot_entry->last_modified = *last_modified_time;
LeaveCriticalSection(&csRunningObjectTable);
return S_OK;
}
}
LeaveCriticalSection(&csRunningObjectTable);
return E_INVALIDARG;
}
HRESULT IrotGetTimeOfLastChange(
IrotHandle h,
const MonikerComparisonData *moniker_data,
FILETIME *time)
{
const struct rot_entry *rot_entry;
HRESULT hr = MK_E_UNAVAILABLE;
WINE_TRACE("%p\n", moniker_data);
memset(time, 0, sizeof(*time));
EnterCriticalSection(&csRunningObjectTable);
LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
{
if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
!memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
{
*time = rot_entry->last_modified;
hr = S_OK;
break;
}
}
LeaveCriticalSection(&csRunningObjectTable);
return hr;
}
HRESULT IrotEnumRunning(
IrotHandle h,
PInterfaceList *list)
{
const struct rot_entry *rot_entry;
HRESULT hr = S_OK;
ULONG moniker_count = 0;
ULONG i = 0;
WINE_TRACE("\n");
EnterCriticalSection(&csRunningObjectTable);
LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
moniker_count++;
*list = MIDL_user_allocate(FIELD_OFFSET(InterfaceList, interfaces[moniker_count]));
if (*list)
{
(*list)->size = moniker_count;
LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
{
(*list)->interfaces[i] = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
if (!(*list)->interfaces[i])
{
ULONG end = i - 1;
for (i = 0; i < end; i++)
MIDL_user_free((*list)->interfaces[i]);
MIDL_user_free(*list);
hr = E_OUTOFMEMORY;
break;
}
(*list)->interfaces[i]->ulCntData = rot_entry->moniker->ulCntData;
memcpy((*list)->interfaces[i]->abData, rot_entry->moniker->abData, rot_entry->moniker->ulCntData);
i++;
}
}
else
hr = E_OUTOFMEMORY;
LeaveCriticalSection(&csRunningObjectTable);
return hr;
}
void __RPC_USER IrotContextHandle_rundown(IrotContextHandle ctxt_handle)
{
struct rot_entry *rot_entry = ctxt_handle;
EnterCriticalSection(&csRunningObjectTable);
list_remove(&rot_entry->entry);
LeaveCriticalSection(&csRunningObjectTable);
rot_entry_release(rot_entry);
}
void * __RPC_USER MIDL_user_allocate(SIZE_T size)
{
return HeapAlloc(GetProcessHeap(), 0, size);
}
void __RPC_USER MIDL_user_free(void * p)
{
HeapFree(GetProcessHeap(), 0, p);
}

View file

@ -0,0 +1,26 @@
/*
* RPCSS definitions
*
* Copyright (C) 2002 Greg Turner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_RPCSS_H
#define __WINE_RPCSS_H
#include "windows.h"
#endif /* __WINE_RPCSS_H */

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<group>
<module name="rpcss" type="win32cui" installbase="system32" installname="rpcss.exe" unicode="yes">
<include base="rpcss">.</include>
<include base="rpcss" root="intermediate">.</include>
<library>wine</library>
<library>rpcss_epm_server</library>
<library>rpcss_irot_server</library>
<library>rpcrt4</library>
<library>advapi32</library>
<library>pseh</library>
<file>epmp.c</file>
<file>irotp.c</file>
<file>rpcss_main.c</file>
<file>service_main.c</file>
<file>epm.idl</file>
<file>irot.idl</file>
<file>rpcss.rc</file>
</module>
<module name="rpcss_epm_server" type="rpcserver">
<file>epm.idl</file>
</module>
<module name="rpcss_irot_server" type="rpcserver">
<file>irot.idl</file>
</module>
</group>

View file

@ -0,0 +1,6 @@
/* $Id$ */
#define REACTOS_STR_FILE_DESCRIPTION "RPC subsystem\0"
#define REACTOS_STR_INTERNAL_NAME "RpcSs\0"
#define REACTOS_STR_ORIGINAL_FILENAME "RpcSs.exe\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,146 @@
/*
* Copyright 2001, Ove Kåven, TransGaming Technologies Inc.
* Copyright 2002 Greg Turner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* ---- rpcss_main.c:
* Initialize and start serving requests. Bail if rpcss already is
* running.
*
* ---- RPCSS.EXE:
*
* Wine needs a server whose role is somewhat like that
* of rpcss.exe in windows. This is not a clone of
* windows rpcss at all. It has been given the same name, however,
* to provide for the possibility that at some point in the future,
* it may become interface compatible with the "real" rpcss.exe on
* Windows.
*
* ---- KNOWN BUGS / TODO:
*
* o Service hooks are unimplemented (if you bother to implement
* these, also implement net.exe, at least for "net start" and
* "net stop" (should be pretty easy I guess, assuming the rest
* of the services API infrastructure works.
*
* o There is a looming problem regarding listening on privileged
* ports. We will need to be able to coexist with SAMBA, and be able
* to function without running winelib code as root. This may
* take some doing, including significant reconceptualization of the
* role of rpcss.exe in wine.
*/
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "rpcss.h"
#include "winnt.h"
#include "irot.h"
#include "epm.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
HANDLE exit_event;
//extern HANDLE __wine_make_process_system(void);
BOOL RPCSS_Initialize(void)
{
static unsigned short irot_protseq[] = IROT_PROTSEQ;
static unsigned short irot_endpoint[] = IROT_ENDPOINT;
static unsigned short epm_protseq[] = {'n','c','a','c','n','_','n','p',0};
static unsigned short epm_endpoint[] = {'\\','p','i','p','e','\\','e','p','m','a','p','p','e','r',0};
static unsigned short epm_protseq_lrpc[] = {'n','c','a','l','r','p','c',0};
static unsigned short epm_endpoint_lrpc[] = {'e','p','m','a','p','p','e','r',0};
RPC_STATUS status;
WINE_TRACE("\n");
status = RpcServerRegisterIf(epm_v3_0_s_ifspec, NULL, NULL);
if (status != RPC_S_OK)
return status;
status = RpcServerRegisterIf(Irot_v0_2_s_ifspec, NULL, NULL);
if (status != RPC_S_OK)
{
RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, FALSE);
return FALSE;
}
status = RpcServerUseProtseqEpW(epm_protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
epm_endpoint, NULL);
if (status != RPC_S_OK)
goto fail;
status = RpcServerUseProtseqEpW(epm_protseq_lrpc, RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
epm_endpoint_lrpc, NULL);
if (status != RPC_S_OK)
goto fail;
status = RpcServerUseProtseqEpW(irot_protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
irot_endpoint, NULL);
if (status != RPC_S_OK)
goto fail;
status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
if (status != RPC_S_OK)
goto fail;
//exit_event = __wine_make_process_system();
exit_event = CreateEventW(NULL, FALSE, FALSE, NULL); // never fires
return TRUE;
fail:
RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, FALSE);
RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, FALSE);
return FALSE;
}
/* returns false if we discover at the last moment that we
aren't ready to terminate */
BOOL RPCSS_Shutdown(void)
{
RpcMgmtStopServerListening(NULL);
RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, TRUE);
RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, TRUE);
CloseHandle(exit_event);
return TRUE;
}
#if 0
int main( int argc, char **argv )
{
/*
* We are invoked as a standard executable; we act in a
* "lazy" manner. We register our interfaces and endpoints, and hang around
* until we all user processes exit, and then silently terminate.
*/
if (RPCSS_Initialize()) {
WaitForSingleObject(exit_event, INFINITE);
RPCSS_Shutdown();
}
return 0;
}
#endif

View file

@ -0,0 +1,40 @@
Index: rpcss_main.c
===================================================================
--- rpcss_main.c
+++ rpcss_main.c
@@ -58,11 +58,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(ole);
-static HANDLE exit_event;
+HANDLE exit_event;
//extern HANDLE __wine_make_process_system(void);
-static BOOL RPCSS_Initialize(void)
+BOOL RPCSS_Initialize(void)
{
static unsigned short irot_protseq[] = IROT_PROTSEQ;
static unsigned short irot_endpoint[] = IROT_ENDPOINT;
@@ -116,7 +116,7 @@
/* returns false if we discover at the last moment that we
aren't ready to terminate */
-static BOOL RPCSS_Shutdown(void)
+BOOL RPCSS_Shutdown(void)
{
RpcMgmtStopServerListening(NULL);
RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, TRUE);
@@ -127,6 +127,7 @@
return TRUE;
}
+#if 0
int main( int argc, char **argv )
{
/*
@@ -142,3 +143,4 @@
return 0;
}
+#endif

View file

@ -0,0 +1,98 @@
/*
* PROJECT: ReactOS Remote Procedure Call service
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/rpcss/service_main.c
* PURPOSE: Service control code
* COPYRIGHT: Copyright 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "rpcss.h"
#define NDEBUG
#include <debug.h>
extern BOOL RPCSS_Initialize(void);
extern BOOL RPCSS_Shutdown(void);
extern HANDLE exit_event;
static VOID WINAPI ServiceMain(DWORD, LPWSTR *);
static WCHAR ServiceName[] = L"RpcSs";
SERVICE_TABLE_ENTRYW ServiceTable[] =
{
{ ServiceName, ServiceMain },
{ NULL, NULL }
};
static SERVICE_STATUS ServiceStatus;
static SERVICE_STATUS_HANDLE ServiceStatusHandle;
DWORD WINAPI
ServiceControlHandler(DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext)
{
switch (dwControl)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
SetEvent(exit_event);
return NO_ERROR;
case SERVICE_CONTROL_INTERROGATE:
return NO_ERROR;
default:
return ERROR_CALL_NOT_IMPLEMENTED;
}
}
VOID WINAPI
ServiceMain(DWORD argc, LPWSTR argv[])
{
DWORD dwError;
ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
ServiceControlHandler,
NULL);
if (!ServiceStatusHandle)
{
dwError = GetLastError();
DPRINT1("RegisterServiceCtrlHandlerW() failed! (Error %lu)\n", dwError);
return;
}
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwWin32ExitCode = NO_ERROR;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 1000;
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
if (RPCSS_Initialize())
{
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
WaitForSingleObject(exit_event, INFINITE);
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
RPCSS_Shutdown();
}
}
int wmain(int argc, LPWSTR argv[])
{
if (!StartServiceCtrlDispatcherW(ServiceTable))
{
DPRINT1("StartServiceCtrlDispatcherW() failed\n");
return 1;
}
return 0;
}

View file

@ -0,0 +1,37 @@
<?xml version="1.0"?>
<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
<group xmlns:xi="http://www.w3.org/2001/XInclude">
<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>
<directory name="rpcss">
<xi:include href="rpcss/rpcss.rbuild" />
</directory>
<directory name="spoolsv">
<xi:include href="spoolsv/spoolsv.rbuild" />
</directory>
<directory name="svchost">
<xi:include href="svchost/svchost.rbuild" />
</directory>
<directory name="tcpsvcs">
<xi:include href="tcpsvcs/tcpsvcs.rbuild" />
</directory>
<directory name="telnetd">
<xi:include href="telnetd/telnetd.rbuild" />
</directory>
<directory name="tftpd">
<xi:include href="tftpd/tftpd.rbuild" />
</directory>
<directory name="umpnpmgr">
<xi:include href="umpnpmgr/umpnpmgr.rbuild" />
</directory>
<directory name="wlansvc">
<xi:include href="wlansvc/wlansvc.rbuild" />
</directory>
</group>

View file

@ -0,0 +1,144 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/spoolsv/spoolsv.c
* PURPOSE: Printer spooler
* PROGRAMMER: Eric Kohl
*/
/* INCLUDES *****************************************************************/
#define WIN32_NO_STATUS
#include <windows.h>
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(spoolsv);
/* GLOBALS ******************************************************************/
static VOID CALLBACK ServiceMain(DWORD argc, LPWSTR *argv);
static WCHAR ServiceName[] = L"Spooler";
static SERVICE_TABLE_ENTRYW ServiceTable[] =
{
{ServiceName, ServiceMain},
{NULL, NULL}
};
SERVICE_STATUS_HANDLE ServiceStatusHandle;
SERVICE_STATUS ServiceStatus;
/* FUNCTIONS *****************************************************************/
static VOID
UpdateServiceStatus(DWORD dwState)
{
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = dwState;
if (dwState == SERVICE_RUNNING)
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
else if (dwState == SERVICE_PAUSED)
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE;
else
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)
{
TRACE("ServiceControlHandler() called\n");
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
TRACE(" SERVICE_CONTROL_STOP received\n");
UpdateServiceStatus(SERVICE_STOPPED);
return ERROR_SUCCESS;
case SERVICE_CONTROL_PAUSE:
TRACE(" SERVICE_CONTROL_PAUSE received\n");
UpdateServiceStatus(SERVICE_PAUSED);
return ERROR_SUCCESS;
case SERVICE_CONTROL_CONTINUE:
TRACE(" SERVICE_CONTROL_CONTINUE received\n");
UpdateServiceStatus(SERVICE_RUNNING);
return ERROR_SUCCESS;
case SERVICE_CONTROL_INTERROGATE:
TRACE(" SERVICE_CONTROL_INTERROGATE received\n");
SetServiceStatus(ServiceStatusHandle,
&ServiceStatus);
return ERROR_SUCCESS;
case SERVICE_CONTROL_SHUTDOWN:
TRACE(" SERVICE_CONTROL_SHUTDOWN received\n");
UpdateServiceStatus(SERVICE_STOPPED);
return ERROR_SUCCESS;
default :
TRACE(" Control %lu received\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
}
static VOID CALLBACK
ServiceMain(DWORD argc, LPWSTR *argv)
{
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
TRACE("ServiceMain() called\n");
ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
ServiceControlHandler,
NULL);
TRACE("Calling SetServiceStatus()\n");
UpdateServiceStatus(SERVICE_RUNNING);
TRACE("SetServiceStatus() called\n");
TRACE("ServiceMain() done\n");
}
int
wmain(int argc, WCHAR *argv[])
{
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
TRACE("Spoolsv: main() started\n");
StartServiceCtrlDispatcher(ServiceTable);
TRACE("Spoolsv: main() done\n");
return 0;
}
/* EOF */

View file

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="spoolsv" type="win32cui" installbase="system32" installname="spoolsv.exe" unicode="yes">
<include base="spoolsv">.</include>
<library>wine</library>
<library>ntdll</library>
<library>advapi32</library>
<file>spoolsv.c</file>
<file>spoolsv.rc</file>
</module>

View file

@ -0,0 +1,4 @@
#define REACTOS_STR_FILE_DESCRIPTION "Spooler-Service\0"
#define REACTOS_STR_INTERNAL_NAME "Spoolsv\0"
#define REACTOS_STR_ORIGINAL_FILENAME "Spoolsv.exe\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,269 @@
/*
* PROJECT: ReactOS SvcHost
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/svchost/svchost.c
* PURPOSE: Provide dll service loader
* PROGRAMMERS: Gregor Brunmar (gregor.brunmar@home.se)
*/
/* INCLUDES ******************************************************************/
#include "svchost.h"
#define NDEBUG
#include <debug.h>
#ifdef _MSC_VER
#undef DPRINT1
#define DPRINT1
#endif
/* DEFINES *******************************************************************/
static LPCTSTR SVCHOST_REG_KEY = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost");
static LPCTSTR SERVICE_KEY = _T("SYSTEM\\CurrentControlSet\\Services\\");
static LPCTSTR PARAMETERS_KEY = _T("\\Parameters");
#define SERVICE_KEY_LENGTH _tcslen(SERVICE_KEY);
#define REG_MAX_DATA_SIZE 2048
static PSERVICE FirstService = NULL;
/* FUNCTIONS *****************************************************************/
BOOL PrepareService(LPCTSTR ServiceName)
{
HKEY hServiceKey;
TCHAR ServiceKeyBuffer[MAX_PATH + 1];
DWORD LeftOfBuffer = sizeof(ServiceKeyBuffer) / sizeof(ServiceKeyBuffer[0]);
DWORD KeyType;
PTSTR Buffer = NULL;
DWORD BufferSize = MAX_PATH + 1;
LONG RetVal;
HINSTANCE hServiceDll;
TCHAR DllPath[MAX_PATH + 2]; /* See MSDN on ExpandEnvironmentStrings() for ANSI strings for more details on + 2 */
LPSERVICE_MAIN_FUNCTION ServiceMainFunc;
PSERVICE Service;
/* Compose the registry path to the service's "Parameter" key */
_tcsncpy(ServiceKeyBuffer, SERVICE_KEY, LeftOfBuffer);
LeftOfBuffer -= _tcslen(SERVICE_KEY);
_tcsncat(ServiceKeyBuffer, ServiceName, LeftOfBuffer);
LeftOfBuffer -= _tcslen(ServiceName);
_tcsncat(ServiceKeyBuffer, PARAMETERS_KEY, LeftOfBuffer);
LeftOfBuffer -= _tcslen(PARAMETERS_KEY);
if (LeftOfBuffer < 0)
{
DPRINT1("Buffer overflow for service name: '%s'\n", ServiceName);
return FALSE;
}
/* Open the service registry key to find the dll name */
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, ServiceKeyBuffer, 0, KEY_READ, &hServiceKey))
{
DPRINT1("Could not open service key (%s)\n", ServiceKeyBuffer);
return FALSE;
}
do
{
if (Buffer)
HeapFree(GetProcessHeap(), 0, Buffer);
Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize);
if (NULL == Buffer)
{
DPRINT1("Not enough memory for service: %s\n", ServiceName);
return FALSE;
}
RetVal = RegQueryValueEx(hServiceKey, _T("ServiceDll"), NULL, &KeyType, (LPBYTE)Buffer, &BufferSize);
} while (ERROR_MORE_DATA == RetVal);
RegCloseKey(hServiceKey);
if (ERROR_SUCCESS != RetVal || 0 == BufferSize)
{
DPRINT1("Could not read 'ServiceDll' value from service: %s, ErrorCode: 0x%x\n", ServiceName, RetVal);
HeapFree(GetProcessHeap(), 0, Buffer);
return FALSE;
}
/* Convert possible %SystemRoot% to a real path */
BufferSize = ExpandEnvironmentStrings(Buffer, DllPath, sizeof(DllPath));
if (0 == BufferSize)
{
DPRINT1("Invalid ServiceDll path: %s\n", Buffer);
HeapFree(GetProcessHeap(), 0, Buffer);
return FALSE;
}
HeapFree(GetProcessHeap(), 0, Buffer);
/* Load the service dll */
DPRINT1("Trying to load dll\n");
hServiceDll = LoadLibrary(DllPath);
if (NULL == hServiceDll)
{
DPRINT1("Unable to load ServiceDll: %s, ErrorCode: %u\n", DllPath, GetLastError());
return FALSE;
}
ServiceMainFunc = (LPSERVICE_MAIN_FUNCTION)GetProcAddress(hServiceDll, "ServiceMain");
/* Allocate a service node in the linked list */
Service = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE));
if (NULL == Service)
{
DPRINT1("Not enough memory for service: %s\n", ServiceName);
return FALSE;
}
memset(Service, 0, sizeof(SERVICE));
Service->Name = HeapAlloc(GetProcessHeap(), 0, _tcslen(ServiceName) + sizeof(TCHAR));
if (NULL == Service->Name)
{
DPRINT1("Not enough memory for service: %s\n", ServiceName);
HeapFree(GetProcessHeap(), 0, Service);
return FALSE;
}
_tcscpy(Service->Name, ServiceName);
Service->hServiceDll = hServiceDll;
Service->ServiceMainFunc = ServiceMainFunc;
Service->Next = FirstService;
FirstService = Service;
return TRUE;
}
VOID FreeServices(VOID)
{
while (FirstService)
{
PSERVICE Service = FirstService;
FirstService = Service->Next;
FreeLibrary(Service->hServiceDll);
HeapFree(GetProcessHeap(), 0, Service->Name);
HeapFree(GetProcessHeap(), 0, Service);
}
}
/*
* Returns the number of services successfully loaded from the category
*/
DWORD LoadServiceCategory(LPCTSTR ServiceCategory)
{
HKEY hServicesKey;
DWORD KeyType;
DWORD BufferSize = REG_MAX_DATA_SIZE;
TCHAR Buffer[REG_MAX_DATA_SIZE];
LPCTSTR ServiceName;
DWORD BufferIndex = 0;
DWORD NrOfServices = 0;
/* Get all the services in this category */
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, SVCHOST_REG_KEY, 0, KEY_READ, &hServicesKey))
{
DPRINT1("Could not open service category: %s\n", ServiceCategory);
return 0;
}
if (ERROR_SUCCESS != RegQueryValueEx(hServicesKey, ServiceCategory, NULL, &KeyType, (LPBYTE)Buffer, &BufferSize))
{
DPRINT1("Could not open service category (2): %s\n", ServiceCategory);
RegCloseKey(hServicesKey);
return 0;
}
/* Clean up */
RegCloseKey(hServicesKey);
/* Load services in the category */
ServiceName = Buffer;
while (_T('\0') != ServiceName[0])
{
size_t Length;
Length = _tcslen(ServiceName);
if (0 == Length)
break;
if (TRUE == PrepareService(ServiceName))
++NrOfServices;
BufferIndex += (Length + 1) * sizeof(TCHAR);
ServiceName = &Buffer[BufferIndex];
}
return NrOfServices;
}
int _tmain (int argc, LPTSTR argv [])
{
DWORD NrOfServices;
LPSERVICE_TABLE_ENTRY ServiceTable;
if (argc < 3)
{
/* MS svchost.exe doesn't seem to print help, should we? */
return 0;
}
if (_tcscmp(argv[1], _T("-k")) != 0)
{
/* For now, we only handle "-k" */
return 0;
}
NrOfServices = LoadServiceCategory(argv[2]);
DPRINT1("NrOfServices: %lu\n", NrOfServices);
if (0 == NrOfServices)
return 0;
ServiceTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_TABLE_ENTRY) * (NrOfServices + 1));
if (NULL != ServiceTable)
{
DWORD i;
PSERVICE Service = FirstService;
/* Fill the service table */
for (i = 0; i < NrOfServices; ++i)
{
DPRINT1("Loading service: %s\n", Service->Name);
ServiceTable[i].lpServiceName = Service->Name;
ServiceTable[i].lpServiceProc = Service->ServiceMainFunc;
Service = Service->Next;
}
/* Set a NULL entry to end the service table */
ServiceTable[i].lpServiceName = NULL;
ServiceTable[i].lpServiceProc = NULL;
if (FALSE == StartServiceCtrlDispatcher(ServiceTable))
printf("Failed to start service control dispatcher, ErrorCode: %lu\n", GetLastError());
HeapFree(GetProcessHeap(), 0, ServiceTable);
}
else
{
DPRINT1("Not enough memory for the service table, trying to allocate %u bytes\n", sizeof(SERVICE_TABLE_ENTRY) * (NrOfServices + 1));
}
DPRINT1("Freeing services...\n");
FreeServices();
return 0;
}
/* EOF */

View file

@ -0,0 +1,35 @@
/*
* PROJECT: ReactOS SvcHost
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/svchost/svchost.h
* PURPOSE: Provide dll service loader
* PROGRAMMERS: Gregor Brunmar (gregor.brunmar@home.se)
*/
#pragma once
/* INCLUDES ******************************************************************/
#if 0
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
/* DEFINES *******************************************************************/
#define CS_TIMEOUT 1000
typedef struct _SERVICE {
PTSTR Name;
HINSTANCE hServiceDll;
LPSERVICE_MAIN_FUNCTION ServiceMainFunc;
struct _SERVICE *Next;
} SERVICE, *PSERVICE;
/* FUNCTIONS *****************************************************************/
/* EOF */

View file

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="svchost" type="win32cui" installbase="system32" installname="svchost.exe">
<include base="svchost">.</include>
<library>advapi32</library>
<file>svchost.c</file>
<file>svchost.rc</file>
</module>

View file

@ -0,0 +1,6 @@
/* $Id: svchost.rc 21279 2007-10-22 06:09:58Z gbrunmar $ */
#define REACTOS_STR_FILE_DESCRIPTION "SvcHost subsystem\0"
#define REACTOS_STR_INTERNAL_NAME "SvcHost\0"
#define REACTOS_STR_ORIGINAL_FILENAME "SvcHost.exe\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,120 @@
/*
* PROJECT: ReactOS simple TCP/IP services
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/tcpsvcs/chargen.c
* PURPOSE: Sends continous lines of chars to the client
* COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "tcpsvcs.h"
/* printable ASCII's characters for chargen */
#define ASCII_START 32
#define ASCII_END 126
#define NUM_CHARS ASCII_END - ASCII_START
/* number of chars to put on a line */
#define LINESIZE 74 // 72 + CR + NL
static BOOL
SendLine(SOCKET sock, LPSTR lpLine)
{
BOOL bRet = FALSE;
/*FIXME: need to establish if peer closes connection, not just report a socket error */
INT retVal = send(sock, lpLine, LINESIZE, 0);
if (retVal > 0)
{
if (retVal == LINESIZE)
{
bRet = TRUE;
}
else
{
LogEvent(L"Chargen: Not sent enough bytes", 0, 0, LOG_FILE);
}
}
else if (retVal == SOCKET_ERROR)
{
LogEvent(L"Chargen: Socket error\n", WSAGetLastError(), 0, LOG_ERROR);
}
else
{
LogEvent(L"Chargen: unknown error\n", WSAGetLastError(), 0, LOG_ERROR);
}
return bRet;
}
static BOOL
GenerateChars(SOCKET sock)
{
CHAR chars[NUM_CHARS];
CHAR line[LINESIZE];
INT charIndex;
INT loopIndex;
INT i;
/* fill the array with printable characters */
for (charIndex = 0, i = ASCII_START; i <= ASCII_END; charIndex++, i++)
chars[charIndex] = (char)i;
loopIndex = 0;
while (!bShutdown)
{
/* reset the loop when we hit the last char */
if (loopIndex == NUM_CHARS)
loopIndex = 0;
/* fill a line array to send */
charIndex = loopIndex;
for (i=0; i < LINESIZE - 2; i++)
{
line[i] = chars[charIndex];
/* if we hit the end char, reset it */
if (chars[charIndex] == chars[NUM_CHARS - 1])
charIndex = 0;
else
charIndex++;
}
line[LINESIZE - 2] = '\r';
line[LINESIZE - 1] = '\n';
if (!SendLine(sock, line))
break;
/* start printing from next char in the array */
loopIndex++;
}
return TRUE;
}
DWORD WINAPI
ChargenHandler(VOID* sock_)
{
INT retVal = 0;
SOCKET sock = (SOCKET)sock_;
if (!GenerateChars(sock))
{
LogEvent(L"Chargen: Char generation failed", 0, 0, LOG_FILE);
retVal = 1;
}
LogEvent(L"Chargen: Shutting connection down...", 0, 0, LOG_FILE);
if (ShutdownConnection(sock, FALSE))
{
LogEvent(L"Chargen: Connection is down", 0, 0, LOG_FILE);
}
else
{
LogEvent(L"Chargen: Connection shutdown failed", 0, 0, LOG_FILE);
retVal = 1;
}
LogEvent(L"Chargen: Terminating thread", 0, 0, LOG_FILE);
ExitThread(retVal);
}

View file

@ -0,0 +1,55 @@
/*
* PROJECT: ReactOS simple TCP/IP services
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/tcpsvcs/daytime.c
* PURPOSE: Sends the current date and time to the client
* COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "tcpsvcs.h"
static BOOL
SendTime(SOCKET sock, CHAR *time)
{
DWORD stringSize = strlen(time) + 1;
if (send(sock, time, stringSize, 0) == SOCKET_ERROR)
{
LogEvent(L"DayTime: Error sending data", WSAGetLastError(), 0, LOG_ERROR);
return FALSE;
}
return TRUE;
}
DWORD WINAPI
DaytimeHandler(VOID* Sock_)
{
struct tm *localTime;
time_t aclock;
CHAR *pszTime;
DWORD retVal = 0;
SOCKET Sock = (SOCKET)Sock_;
time(&aclock);
localTime = localtime(&aclock);
if (localTime)
{
pszTime = asctime(localTime);
if (!SendTime(Sock, pszTime))
retVal = 1;
}
LogEvent(L"DayTime: Shutting connection down", 0, 0, LOG_FILE);
if (ShutdownConnection(Sock, FALSE))
LogEvent(L"DayTime: Connection is down", 0, 0, LOG_FILE);
else
{
LogEvent(L"DayTime: Connection shutdown failed", 0, 0, LOG_FILE);
retVal = 1;
}
LogEvent(L"DayTime: Terminating thread", 0, 0, LOG_FILE);
ExitThread(retVal);
}

View file

@ -0,0 +1,68 @@
/*
* PROJECT: ReactOS simple TCP/IP services
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/tcpsvcs/discard.c
* PURPOSE: Recieves input from a client and discards it
* COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "tcpsvcs.h"
#define BUFSIZE 1024
static BOOL
RecieveIncomingPackets(SOCKET sock)
{
CHAR readBuffer[BUFSIZE];
INT readBytes;
do
{
readBytes = recv(sock, readBuffer, BUFSIZE, 0);
if (readBytes > 0)
{
TCHAR logBuf[256];
_swprintf(logBuf, L"Discard: Received %d bytes from client", readBytes);
LogEvent(logBuf, 0, 0, LOG_FILE);
}
else if (readBytes == SOCKET_ERROR)
{
LogEvent(L"Discard: Socket Error", WSAGetLastError(), 0, LOG_ERROR);
return FALSE;
}
} while ((readBytes > 0) && (!bShutdown));
if (!bShutdown)
LogEvent(L"Discard: Connection closed by peer", 0, 0, LOG_FILE);
return TRUE;
}
DWORD WINAPI
DiscardHandler(VOID* sock_)
{
DWORD retVal = 0;
SOCKET sock = (SOCKET)sock_;
if (!RecieveIncomingPackets(sock))
{
LogEvent(L"Discard: RecieveIncomingPackets failed", 0, 0, LOG_FILE);
retVal = 1;
}
LogEvent(L"Discard: Shutting connection down", 0, 0, LOG_FILE);
if (ShutdownConnection(sock, TRUE))
{
LogEvent(L"Discard: Connection is down.", 0, 0, LOG_FILE);
}
else
{
LogEvent(L"Discard: Connection shutdown failed", 0, 0, LOG_FILE);
retVal = 1;
}
LogEvent(L"Discard: Terminating thread", 0, 0, LOG_FILE);
ExitThread(retVal);
}

View file

@ -0,0 +1,94 @@
/*
* PROJECT: ReactOS simple TCP/IP services
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/tcpsvcs/echo.c
* PURPOSE: Returns whatever input the client sends
* COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "tcpsvcs.h"
#define RECV_BUF 1024
static BOOL
EchoIncomingPackets(SOCKET sock)
{
CHAR readBuffer[RECV_BUF];
WCHAR logBuf[256];
INT totalSentBytes;
INT readBytes;
INT retVal;
do
{
readBytes = recv(sock, readBuffer, RECV_BUF, 0);
if (readBytes > 0)
{
_swprintf(logBuf, L"Received %d bytes from client", readBytes);
LogEvent(logBuf, 0, 0, LOG_FILE);
totalSentBytes = 0;
while (!bShutdown && totalSentBytes < readBytes)
{
retVal = send(sock, readBuffer + totalSentBytes, readBytes - totalSentBytes, 0);
if (retVal > 0)
{
_swprintf(logBuf, L"Sent %d bytes back to client", retVal);
LogEvent(logBuf, 0, 0, LOG_FILE);
totalSentBytes += retVal;
}
else if (retVal == SOCKET_ERROR)
{
LogEvent(L"Echo: socket error", WSAGetLastError(), 0, LOG_ERROR);
return FALSE;
}
else
{
/* Client closed connection before we could reply to
all the data it sent, so quit early. */
LogEvent(L"Peer unexpectedly dropped connection!", 0, 0, LOG_FILE);
return FALSE;
}
}
}
else if (readBytes == SOCKET_ERROR)
{
LogEvent(L"Echo: socket error", WSAGetLastError(), 0, LOG_ERROR);
return FALSE;
}
} while ((readBytes != 0) && (!bShutdown));
if (!bShutdown)
LogEvent(L"Echo: Connection closed by peer", 0, 0, LOG_FILE);
return TRUE;
}
DWORD WINAPI
EchoHandler(VOID* sock_)
{
DWORD retVal = 0;
SOCKET sock = (SOCKET)sock_;
if (!EchoIncomingPackets(sock))
{
LogEvent(L"Echo: EchoIncomingPackets failed", 0, 0, LOG_FILE);
retVal = 1;
}
LogEvent(L"Echo: Shutting connection down", 0, 0, LOG_FILE);
if (ShutdownConnection(sock, TRUE))
{
LogEvent(L"Echo: Connection is down", 0, 0, LOG_FILE);
}
else
{
LogEvent(L"Echo: Connection shutdown failed", 0, 0, LOG_FILE);
retVal = 1;
}
LogEvent(L"Echo: Terminating thread", 0, 0, LOG_FILE);
ExitThread(retVal);
}

262
base/services/tcpsvcs/log.c Normal file
View file

@ -0,0 +1,262 @@
/*
* PROJECT: ReactOS simple TCP/IP services
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/tcpsvcs/log.c
* PURPOSE: Logging functionality for the service
* COPYRIGHT: Copyright 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "tcpsvcs.h"
#define DEBUG
static LPWSTR lpEventSource = L"tcpsvcs";
static LPCWSTR lpLogFileName = L"C:\\tcpsvcs_log.log";
static HANDLE hLogFile = NULL;
static OVERLAPPED olWrite;
// needs work
static VOID
LogToEventLog(LPCWSTR lpMsg,
DWORD errNum,
DWORD exitCode,
UINT flags)
{
HANDLE hEventLog;
hEventLog = RegisterEventSourceW(NULL, lpEventSource);
if (hEventLog)
{
ReportEventW(hEventLog,
(flags & LOG_ERROR) ? EVENTLOG_ERROR_TYPE : EVENTLOG_SUCCESS,
0,
0,
NULL,
1,
0,
&lpMsg,
NULL);
CloseEventLog(hEventLog);
}
}
static BOOL
OpenLogFile()
{
hLogFile = CreateFileW(lpLogFileName,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (hLogFile == INVALID_HANDLE_VALUE)
{
hLogFile = NULL;
return FALSE;
}
return TRUE;
}
static VOID
LogToFile(LPCWSTR lpMsg,
DWORD errNum,
DWORD exitCode,
UINT flags)
{
LPWSTR lpFullMsg = NULL;
DWORD msgLen;
msgLen = wcslen(lpMsg) + 1;
if (flags & LOG_ERROR)
{
LPVOID lpSysMsg;
DWORD eMsgLen;
eMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpSysMsg,
0,
NULL);
msgLen = msgLen + eMsgLen + 40;
lpFullMsg = HeapAlloc(GetProcessHeap(),
0,
msgLen * sizeof(TCHAR));
if (lpFullMsg)
{
_snwprintf(lpFullMsg,
msgLen,
L"%s : %s\tErrNum = %lu ExitCode = %lu\r\n",
lpMsg,
lpSysMsg,
errNum,
exitCode);
}
LocalFree(lpSysMsg);
}
else
{
msgLen += 2;
lpFullMsg = HeapAlloc(GetProcessHeap(),
0,
msgLen * sizeof(TCHAR));
if (lpFullMsg)
{
_snwprintf(lpFullMsg,
msgLen,
L"%s\r\n",
lpMsg);
}
}
if (lpFullMsg)
{
DWORD bytesWritten;
DWORD dwRet;
BOOL bRet;
bRet = WriteFile(hLogFile,
lpFullMsg,
wcslen(lpFullMsg) * sizeof(WCHAR),
&bytesWritten,
&olWrite);
if (!bRet)
{
if (GetLastError() != ERROR_IO_PENDING)
{
bRet = FALSE;
}
else
{
// Write is pending
dwRet = WaitForSingleObject(olWrite.hEvent, INFINITE);
switch (dwRet)
{
// event has been signaled
case WAIT_OBJECT_0:
{
bRet = GetOverlappedResult(hLogFile,
&olWrite,
&bytesWritten,
FALSE);
break;
}
default:
// An error has occurred in WaitForSingleObject.
// This usually indicates a problem with the
// OVERLAPPED structure's event handle.
bRet = FALSE;
break;
}
}
}
if (!bRet || bytesWritten == 0)
{
LogToEventLog(L"Failed to write to log file",
GetLastError(),
0,
LOG_EVENTLOG | LOG_ERROR);
}
HeapFree(GetProcessHeap(),
0,
lpFullMsg);
}
if (exitCode > 0)
ExitProcess(exitCode);
}
VOID
LogEvent(LPCWSTR lpMsg,
DWORD errNum,
DWORD exitCode,
UINT flags)
{
#ifdef DEBUG
if (flags & LOG_FILE || flags & LOG_ERROR)
LogToFile(lpMsg, errNum, exitCode, flags);
#endif
if (flags & LOG_EVENTLOG)
LogToEventLog(lpMsg, errNum, exitCode, flags);
}
BOOL
InitLogging()
{
#ifdef DEBUG
BOOL bRet = FALSE;
ZeroMemory(&olWrite, sizeof(OVERLAPPED));
olWrite.Offset = 0xFFFFFFFF;
olWrite.OffsetHigh = 0xFFFFFFFF;
olWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (olWrite.hEvent)
{
DeleteFileW(lpLogFileName);
if (OpenLogFile())
{
WCHAR wcBom = 0xFEFF;
DWORD bytesWritten;
bRet = WriteFile(hLogFile,
&wcBom,
sizeof(WCHAR),
&bytesWritten,
&olWrite);
if (!bRet)
{
if (GetLastError() != ERROR_IO_PENDING)
{
LogToEventLog(L"Failed to write to log file",
GetLastError(),
0,
LOG_EVENTLOG | LOG_ERROR);
}
else
{
bRet = TRUE;
}
}
}
}
return bRet;
#else
return TRUE;
#endif
}
VOID
UninitLogging()
{
if (hLogFile)
{
FlushFileBuffers(hLogFile);
CloseHandle(hLogFile);
}
if (olWrite.hEvent)
{
CloseHandle(olWrite.hEvent);
}
}

View file

@ -0,0 +1,154 @@
/*
* PROJECT: ReactOS simple TCP/IP services
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/tcpsvcs/qotd.c
* PURPOSE: Sends a random quote to the client
* COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "tcpsvcs.h"
static WCHAR szFilePath[] = L"\\drivers\\etc\\quotes";
static BOOL
SendQuote(SOCKET sock, char* Quote)
{
INT strSize = strlen(Quote);
if (send(sock, Quote, strSize, 0) == SOCKET_ERROR)
return FALSE;
return TRUE;
}
static BOOL
RetrieveQuote(SOCKET sock)
{
HANDLE hFile;
WCHAR szFullPath[MAX_PATH + 20];
DWORD dwBytesRead;
LPSTR lpQuotes;
LPSTR lpStr;
INT quoteNum;
INT NumQuotes = 0;
INT i;
if(!GetSystemDirectoryW(szFullPath, MAX_PATH))
{
LogEvent(L"QOTD: Getting system path failed", GetLastError(), 0, LOG_FILE);
return FALSE;
}
wcscat(szFullPath, szFilePath);
LogEvent(L"QOTD: Opening quotes file", 0, 0, LOG_FILE);
hFile = CreateFileW(szFullPath,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
LogEvent(L"QOTD: Error opening quotes file", GetLastError(), 0, LOG_FILE);
}
else
{
DWORD dwSize = GetFileSize(hFile, NULL);
lpQuotes = (LPSTR)HeapAlloc(GetProcessHeap(), 0, dwSize);
if (!lpQuotes)
{
CloseHandle(hFile);
return FALSE;
}
ReadFile(hFile,
lpQuotes,
dwSize,
&dwBytesRead,
NULL);
CloseHandle(hFile);
lpQuotes[dwSize] = 0;
if (dwBytesRead != dwSize)
return FALSE;
lpStr = lpQuotes;
while (*lpStr)
{
if (*lpStr == '%')
NumQuotes++;
lpStr++;
}
/* pick a random quote */
srand((unsigned int) GetTickCount());
quoteNum = rand() % NumQuotes;
/* retrieve the full quote */
lpStr = lpQuotes;
for (i = 1; i <= quoteNum; i++)
{
/* move past proceding quote */
lpStr++;
if (i == quoteNum)
{
LPSTR lpStart = lpStr;
while (*lpStr != '%' && *lpStr != '\0')
lpStr++;
*lpStr = 0;
/* send the quote */
if (!SendQuote(sock, lpStart))
LogEvent(L"QOTD: Error sending data", 0, 0, LOG_FILE);
break;
}
else
{
while (*lpStr != '%' && *lpStr != '\0')
lpStr++;
/* move past % and RN */
lpStr += 2;
}
}
return TRUE;
}
return FALSE;
}
DWORD WINAPI
QotdHandler(VOID* sock_)
{
SOCKET sock = (SOCKET)sock_;
DWORD retVal = 0;
if (!RetrieveQuote(sock))
{
LogEvent(L"QOTD: Error retrieving quote", 0, 0, LOG_FILE);
retVal = 1;
}
LogEvent(L"QOTD: Shutting connection down", 0, 0, LOG_FILE);
if (ShutdownConnection(sock, FALSE))
{
LogEvent(L"QOTD: Connection is down", 0, 0, LOG_FILE);
}
else
{
LogEvent(L"QOTD: Connection shutdown failed", 0, 0, LOG_FILE);
LogEvent(L"QOTD: Terminating thread", 0, 0, LOG_FILE);
retVal = 1;
}
LogEvent(L"QOTD: Terminating thread", 0, 0, LOG_FILE);
ExitThread(retVal);
}

View file

@ -0,0 +1,104 @@
"Et tu... Brute? What are you doing, Dave...?
%
"So long, and thanks for all the fish
%
"I think you ought to know I'm feeling very depressed
%
"I'm not getting you down at all am I?
%
"I'll be back
%
"It's the same series of signal over and over again!
%
"Pie Jesu Domine, dona eis requiem
%
"It's worse than that ... He's dead, Jim
%
"Don't Panic!
%
"Dog of a Saxon! Take thy lance, and prepare for the death thou hast drawn upon thee!
%
"My Precious! O my Precious!
%
"Sir, If you'll not be needing me for a while I'll turn down.
%
"I feel a great disturbance in the Force
%
"Gone fishing
%
"Do you want me to sit in the corner and rust, or just fall apart where I'm standing?
%
"There goes another perfect chance for a new uptime record
%
"The end ..... Try the sequel, hit the reset button right now!
%
"Oh i'm boring eh?
%
"It's been great, maybe we can do this again sometime.
%
""Come blade, my breast imbrue." - William Shakespeare
%
"I think therefore I am, to turn me off would be computercide!
%
"All good things must come to an end...
%
"Please destroy yourself.
%
"No! You can't do that!
%
"Thank you for not pressing the self destruct button.
%
"It is not now unsafe to not avoid turning off your computer.
%
"Finally! Now go away!
%
"You can now safely throw away your computer.
%
"That's the way the cookie crumbles
%
"NOO!! DONT HIT THE BUTTON! I wouldnt do it to you.
%
"Don't abandon your computer, he wouldnt to it to you.
%
"Oh, come on. I got a headache. Leave me alone, will ya!
%
"Yes i didn't like you either.
%
"Don't leave me... I need you so badly right now.
%
"I'm sleeping now. How about you?
%
"Oh Great. Now look what you've done. Who put YOU in charge anyway.
%
"Don't look so sad. I'll be back in a very short while.
%
""Oh, switch off!" -C3PO
%
"I'm pregnant!
%
"Am I hot or not?
%
"Actually, that's all...
%
"You still have a chance to undo this mistake, don't do this!
%
"Was it as good for you as it was for me?
%
"Did you hear that? They've shut down the main reactor. We'll be destroyed for sure.
%
"Now you switch me off?!
%
"To shutdown or not to shutdown, That is the question
%
"Preparing to enter ultimate power saving mode... ready!
%
"Finally some rest for you
%
"AHA!!! prospect of sleep.
%
"Tired human!!!! No match for me!
%
"All your base are belong to us.
%
""An odd game, the only way to win is not to play."
%

View file

@ -0,0 +1,199 @@
/*
* PROJECT: ReactOS simple TCP/IP services
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/tcpsvcs/skelserver.c
* PURPOSE: Sets up a server and listens for connections
* COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@gmail.com>
*
*/
#include "tcpsvcs.h"
#define BUF 1024
static SOCKET
SetUpListener(USHORT Port)
{
SOCKET sock;
SOCKADDR_IN server;
BOOL bSetup = FALSE;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock != INVALID_SOCKET)
{
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = Port;
if (bind(sock, (SOCKADDR*)&server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR)
{
if (listen(sock, SOMAXCONN) != SOCKET_ERROR)
{
bSetup = TRUE;
}
else
{
LogEvent(L"listen() failed", WSAGetLastError(), 0, LOG_ERROR);
}
}
else
{
LogEvent(L"bind() failed", WSAGetLastError(), 0, LOG_ERROR);
}
}
else
{
LogEvent(L"socket() failed", WSAGetLastError(), 0, LOG_ERROR);
}
return bSetup ? sock : INVALID_SOCKET;
}
static VOID
AcceptConnections(SOCKET listeningSocket,
LPTHREAD_START_ROUTINE lpService,
LPWSTR lpName)
{
SOCKADDR_IN client;
SOCKET sock;
HANDLE hThread;
TIMEVAL timeVal;
FD_SET readFD;
WCHAR logBuf[256];
INT timeOut = 2000;
timeVal.tv_sec = timeOut / 1000;
timeVal.tv_usec = timeOut % 1000;
while (!bShutdown)
{
INT selRet = 0;
FD_ZERO(&readFD);
FD_SET(listeningSocket, &readFD);
selRet = select(0, &readFD, NULL, NULL, &timeVal);
if (selRet > 0)
{
if (!bShutdown || FD_ISSET(listeningSocket, &readFD))
{
INT addrSize = sizeof(SOCKADDR_IN);
sock = accept(listeningSocket, (SOCKADDR*)&client, &addrSize);
if (sock != INVALID_SOCKET)
{
_swprintf(logBuf,
L"Accepted connection to %s server from %S:%d",
lpName,
inet_ntoa(client.sin_addr),
ntohs(client.sin_port));
LogEvent(logBuf, 0, 0, LOG_FILE);
_swprintf(logBuf, L"Creating worker thread for %s", lpName);
LogEvent(logBuf, 0, 0, LOG_FILE);
if (!bShutdown)
{
hThread = CreateThread(0, 0, lpService, (void*)sock, 0, NULL);
if (hThread != NULL)
{
CloseHandle(hThread);
}
else
{
_swprintf(logBuf, L"Failed to start worker thread for the %s server",
lpName);
LogEvent(logBuf, 0, 0, LOG_FILE);
}
}
}
else
{
LogEvent(L"accept failed", WSAGetLastError(), 0, LOG_ERROR);
}
}
}
else if (selRet == SOCKET_ERROR)
{
LogEvent(L"select failed", WSAGetLastError(), 0, LOG_ERROR);
}
}
}
BOOL
ShutdownConnection(SOCKET sock,
BOOL bRec)
{
WCHAR logBuf[256];
/* Disallow any further data sends. This will tell the other side
that we want to go away now. If we skip this step, we don't
shut the connection down nicely. */
if (shutdown(sock, SD_SEND) == SOCKET_ERROR)
{
LogEvent(L"Error in shutdown()", WSAGetLastError(), 0, LOG_ERROR);
return FALSE;
}
/* Receive any extra data still sitting on the socket
before we close it */
if (bRec)
{
CHAR readBuffer[BUF];
INT ret;
do
{
ret = recv(sock, readBuffer, BUF, 0);
if (ret >= 0)
{
_swprintf(logBuf, L"FYI, received %d unexpected bytes during shutdown", ret);
LogEvent(logBuf, 0, 0, LOG_FILE);
}
} while (ret > 0);
}
closesocket(sock);
return TRUE;
}
DWORD WINAPI
StartServer(LPVOID lpParam)
{
SOCKET listeningSocket;
PSERVICES pServices;
TCHAR logBuf[256];
pServices = (PSERVICES)lpParam;
_swprintf(logBuf, L"Starting %s server", pServices->lpName);
LogEvent(logBuf, 0, 0, LOG_FILE);
if (!bShutdown)
{
listeningSocket = SetUpListener(htons(pServices->Port));
if (!bShutdown && listeningSocket != INVALID_SOCKET)
{
_swprintf(logBuf,
L"%s is waiting for connections on port %d",
pServices->lpName,
pServices->Port);
LogEvent(logBuf, 0, 0, LOG_FILE);
AcceptConnections(listeningSocket, pServices->lpService, pServices->lpName);
}
else
{
LogEvent(L"Socket error when setting up listener", 0, 0, LOG_FILE);
}
}
_swprintf(logBuf,
L"Exiting %s thread",
pServices->lpName);
LogEvent(logBuf, 0, 0, LOG_FILE);
ExitThread(0);
}

View file

@ -0,0 +1,222 @@
/*
* PROJECT: ReactOS simple TCP/IP services
* LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/tcpsvcs/tcpsvcs.c
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "tcpsvcs.h"
static WCHAR ServiceName[] = L"tcpsvcs";
volatile BOOL bShutdown = FALSE;
volatile BOOL bPause = FALSE;
typedef struct _ServiceInfo
{
SERVICE_STATUS servStatus;
SERVICE_STATUS_HANDLE hStatus;
} SERVICEINFO, *PSERVICEINFO;
static SERVICES
Services[NUM_SERVICES] =
{
{ECHO_PORT, L"Echo", EchoHandler},
{DISCARD_PORT, L"Discard", DiscardHandler},
{DAYTIME_PORT, L"Daytime", DaytimeHandler},
{QOTD_PORT, L"QOTD", QotdHandler},
{CHARGEN_PORT, L"Chargen", ChargenHandler}
};
static VOID
UpdateStatus(PSERVICEINFO pServInfo,
DWORD NewStatus,
DWORD Check)
{
WCHAR szSet[50];
if (Check > 0)
pServInfo->servStatus.dwCheckPoint += Check;
else
pServInfo->servStatus.dwCheckPoint = Check;
if (NewStatus > 0)
pServInfo->servStatus.dwCurrentState = NewStatus;
_snwprintf(szSet,
49,
L"Service state 0x%lu, CheckPoint %lu",
pServInfo->servStatus.dwCurrentState,
pServInfo->servStatus.dwCheckPoint);
LogEvent(szSet, 0, 0, LOG_FILE);
if (!SetServiceStatus(pServInfo->hStatus, &pServInfo->servStatus))
LogEvent(L"Cannot set service status", GetLastError(), 0, LOG_ALL);
}
static BOOL
CreateServers(PSERVICEINFO pServInfo)
{
DWORD dwThreadId[NUM_SERVICES];
HANDLE hThread[NUM_SERVICES];
WSADATA wsaData;
WCHAR buf[256];
INT i;
DWORD RetVal;
if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
{
_swprintf(buf, L"WSAStartup() failed : %lu\n", RetVal);
LogEvent(buf, 0, 100, LOG_ALL);
return FALSE;
}
UpdateStatus(pServInfo, 0, 1);
LogEvent(L"\nCreating server Threads", 0, 0, LOG_FILE);
/* Create worker threads. */
for (i = 0; i < NUM_SERVICES; i++)
{
_swprintf(buf, L"Creating thread for %s server", Services[i].lpName);
LogEvent(buf, 0, 0, LOG_FILE);
hThread[i] = CreateThread(NULL,
0,
StartServer,
&Services[i],
0,
&dwThreadId[i]);
if (hThread[i] == NULL)
{
_swprintf(buf, L"\nError creating %s server thread\n", Services[i].lpName);
LogEvent(buf, GetLastError(), 0, LOG_ALL);
return FALSE;
}
UpdateStatus(pServInfo, 0, 1);
}
LogEvent(L"Setting service status to running", 0, 0, LOG_FILE);
UpdateStatus(pServInfo, SERVICE_RUNNING, 0);
/* Wait until all threads have terminated. */
WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
for (i = 0; i < NUM_SERVICES; i++)
{
if (hThread[i] != NULL)
CloseHandle(hThread[i]);
}
LogEvent(L"Detaching Winsock2", 0, 0, LOG_FILE);
WSACleanup();
return TRUE;
}
VOID WINAPI
ServerCtrlHandler(DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext)
{
PSERVICEINFO pServInfo = (PSERVICEINFO)lpContext;
switch (dwControl)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
LogEvent(L"\nSetting the service to SERVICE_STOP_PENDING", 0, 0, LOG_FILE);
InterlockedExchange((LONG *)&bShutdown, TRUE);
pServInfo->servStatus.dwWin32ExitCode = 0;
pServInfo->servStatus.dwWaitHint = 0;
UpdateStatus(pServInfo, SERVICE_STOP_PENDING, 1);
break;
case SERVICE_CONTROL_PAUSE: /* not yet implemented */
LogEvent(L"Setting the service to SERVICE_PAUSED", 0, 0, LOG_FILE);
InterlockedExchange((LONG *)&bPause, TRUE);
UpdateStatus(pServInfo, SERVICE_PAUSED, 0);
break;
case SERVICE_CONTROL_CONTINUE:
LogEvent(L"Setting the service to SERVICE_RUNNING", 0, 0, LOG_FILE);
InterlockedExchange((LONG *)&bPause, FALSE);
UpdateStatus(pServInfo, SERVICE_RUNNING, 0);
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
if (dwControl > 127 && dwControl < 256) /* user defined */
LogEvent(L"User defined control code", 0, 0, LOG_FILE);
else
LogEvent(L"ERROR: Bad control code", 0, 0, LOG_FILE);
break;
}
}
VOID WINAPI
ServiceMain(DWORD argc, LPWSTR argv[])
{
SERVICEINFO servInfo;
LogEvent(L"Entering ServiceMain.", 0, 0, LOG_FILE);
servInfo.servStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
servInfo.servStatus.dwCurrentState = SERVICE_STOPPED;
servInfo.servStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
servInfo.servStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
servInfo.servStatus.dwServiceSpecificExitCode = 0;
servInfo.servStatus.dwCheckPoint = 0;
servInfo.servStatus.dwWaitHint = 2 * CS_TIMEOUT;
LogEvent(L"Registering service control handler", 0, 0, LOG_FILE);
servInfo.hStatus = RegisterServiceCtrlHandlerExW(ServiceName,
(LPHANDLER_FUNCTION_EX)ServerCtrlHandler,
&servInfo);
if (!servInfo.hStatus)
LogEvent(L"Failed to register service", GetLastError(), 100, LOG_ALL);
UpdateStatus(&servInfo, SERVICE_START_PENDING, 1);
if (!CreateServers(&servInfo))
{
LogEvent(L"Error creating servers", GetLastError(), 1, LOG_ALL);
servInfo.servStatus.dwServiceSpecificExitCode = 1;
UpdateStatus(&servInfo, SERVICE_STOPPED, 0);
return;
}
LogEvent(L"Service threads shut down. Set SERVICE_STOPPED status", 0, 0, LOG_FILE);
UpdateStatus(&servInfo, SERVICE_STOPPED, 0);
LogEvent(L"Leaving ServiceMain\n", 0, 0, LOG_FILE);
}
int _tmain (int argc, LPTSTR argv [])
{
SERVICE_TABLE_ENTRYW ServiceTable[] =
{
{ServiceName, ServiceMain},
{NULL, NULL }
};
if (InitLogging())
{
if (!StartServiceCtrlDispatcherW(ServiceTable))
LogEvent(L"failed to start the service control dispatcher", GetLastError(), 101, LOG_ALL);
UninitLogging();
}
return 0;
}

View file

@ -0,0 +1,51 @@
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include <time.h>
#ifndef _MSC_VER
#define _swprintf swprintf
#endif
#define LOG_FILE 1
#define LOG_EVENTLOG 2
#define LOG_ERROR 4
#define LOG_ALL (LOG_FILE | LOG_EVENTLOG | LOG_ERROR)
/* default port numbers */
#define ECHO_PORT 7
#define DISCARD_PORT 9
#define DAYTIME_PORT 13
#define QOTD_PORT 17
#define CHARGEN_PORT 19
#define NUM_SERVICES 5
#define CS_TIMEOUT 1000
/* data structure to pass to threads */
typedef struct _Services
{
USHORT Port;
LPWSTR lpName;
LPTHREAD_START_ROUTINE lpService;
} SERVICES, *PSERVICES;
extern volatile BOOL bShutdown;
extern volatile BOOL bPause;
/* logging functions */
BOOL InitLogging();
VOID UninitLogging();
VOID LogEvent(LPCWSTR lpMsg, DWORD errNum, DWORD exitCode, UINT flags);
/* skelserver functions */
DWORD WINAPI StartServer(LPVOID lpParam);
BOOL ShutdownConnection(SOCKET Sock, BOOL bRec);
/* server thread handlers */
DWORD WINAPI ChargenHandler(VOID* sock_);
DWORD WINAPI DaytimeHandler(VOID* sock_);
DWORD WINAPI EchoHandler(VOID* sock_);
DWORD WINAPI DiscardHandler(VOID* sock_);
DWORD WINAPI QotdHandler(VOID* sock_);

View file

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="tcpsvcs" type="win32cui" installbase="system32" installname="tcpsvcs.exe" unicode="yes">
<include base="arp">.</include>
<library>ws2_32</library>
<library>advapi32</library>
<file>tcpsvcs.c</file>
<file>skelserver.c</file>
<file>echo.c</file>
<file>discard.c</file>
<file>daytime.c</file>
<file>qotd.c</file>
<file>chargen.c</file>
<file>tcpsvcs.rc</file>
<file>log.c</file>
<pch>tcpsvcs.h</pch>
</module>

View file

@ -0,0 +1,5 @@
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IP Services Application\0"
#define REACTOS_STR_INTERNAL_NAME "tcpsvcs\0"
#define REACTOS_STR_ORIGINAL_FILENAME "tcpsvcs.exe\0"
#define REACTOS_STR_ORIGINAL_COPYRIGHT "Ged Murphy (gedmurphy@gmail.com)\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,108 @@
/*
* Copyright 2007 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "wine/debug.h"
int kickoff_telnetd(void);
WINE_DEFAULT_DEBUG_CHANNEL(telnetd);
static WCHAR telnetdW[] = {'t','e','l','n','e','t','d',0};
static SERVICE_STATUS_HANDLE service_handle;
static HANDLE stop_event;
static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )
{
SERVICE_STATUS status;
status.dwServiceType = SERVICE_WIN32;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
status.dwWin32ExitCode = 0;
status.dwServiceSpecificExitCode = 0;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
switch(ctrl)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
WINE_TRACE( "shutting down\n" );
status.dwCurrentState = SERVICE_STOP_PENDING;
status.dwControlsAccepted = 0;
SetServiceStatus( service_handle, &status );
SetEvent( stop_event );
return NO_ERROR;
default:
WINE_FIXME( "got service ctrl %x\n", ctrl );
status.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus( service_handle, &status );
return NO_ERROR;
}
}
static void WINAPI serv_main(DWORD argc, LPWSTR *argv)
{
SERVICE_STATUS status;
int retval;
WINE_TRACE( "starting service\n" );
stop_event = CreateEventW( NULL, TRUE, FALSE, NULL );
service_handle = RegisterServiceCtrlHandlerExW( telnetdW, service_handler, NULL );
if (!service_handle)
return;
status.dwServiceType = SERVICE_WIN32;
status.dwCurrentState = SERVICE_RUNNING;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
status.dwWin32ExitCode = 0;
status.dwServiceSpecificExitCode = 0;
status.dwCheckPoint = 0;
status.dwWaitHint = 10000;
SetServiceStatus( service_handle, &status );
/* Argument Ignored for now */
retval = kickoff_telnetd();
WaitForSingleObject( stop_event, INFINITE );
status.dwCurrentState = SERVICE_STOPPED;
status.dwControlsAccepted = 0;
SetServiceStatus( service_handle, &status );
WINE_TRACE( "service stopped\n" );
}
int main(int argc, char **argv)
{
static const SERVICE_TABLE_ENTRYW servtbl[] = {
{telnetdW, serv_main},
{NULL, NULL}
};
WINE_TRACE("(%d %p)\n", argc, argv);
StartServiceCtrlDispatcherW(servtbl);
return 0;
}
/* EOF */

View file

@ -0,0 +1,308 @@
/*
* syslog-client.c - syslog client implementation for windows
*
* Created by Alexander Yaworsky
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAIMED. This includes but is not limited to warranties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/* define SYSLOG_CONF_DIR where syslog.host should be
*/
#ifndef SYSLOG_CONF_DIR
static const char *syslog_conf_dir = ".";
#else
static const char *syslog_conf_dir = SYSLOG_CONF_DIR;
#endif
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include "syslog.h"
#ifdef TEST
# define SYSLOG_DGRAM_SIZE 80
#else
# define SYSLOG_DGRAM_SIZE 1024
#endif
static BOOL initialized = FALSE;
static int log_mask = 0xFF;
static char *syslog_ident;
static int syslog_facility;
static char str_pid[ 40 ];
static SOCKADDR_IN sa_logger;
static SOCKET sock;
static char local_hostname[ MAX_COMPUTERNAME_LENGTH + 1 ];
static char datagramm[ SYSLOG_DGRAM_SIZE ];
static int datagramm_size;
/******************************************************************************
* set_syslog_conf_dir
*
* maybe this function will be useful...
*/
const char* set_syslog_conf_dir( const char* dir )
{
const char *ret = syslog_conf_dir;
syslog_conf_dir = dir;
return ret;
}
/******************************************************************************
* init_logger_addr
*
* Read configuration file syslog.host. This file should contain host address
* and, optionally, port. Initialize sa_logger. If the configuration file does
* not exist, use localhost:514.
* Returns: 0 - ok, -1 - error.
*/
static void init_logger_addr()
{
char pathname[ FILENAME_MAX ];
char *p;
FILE *fd;
char host[256];
struct hostent * phe;
memset( &sa_logger, 0, sizeof(SOCKADDR_IN) );
sa_logger.sin_family = AF_INET;
if( '\\' == syslog_conf_dir[0] || '/' == syslog_conf_dir[0] || ':' == syslog_conf_dir[1] )
{
/* absolute path */
strcpy( pathname, syslog_conf_dir );
}
else
{
/* relative path */
char *q;
strcpy( pathname, __argv[0] );
p = strrchr( pathname, '\\' ) + 1;
q = strrchr( pathname, '/' ) + 1;
if( p < q )
*q = 0;
else if( p > q )
*p = 0;
else
pathname[0] = 0;
strcat( pathname, syslog_conf_dir );
}
p = &pathname[ strlen( pathname ) - 1 ];
if( '\\' != *p && '/' != *p )
{
p++; *p = '/';
}
strcpy( ++p, "syslog.host" );
/* read destination host name */
fd = fopen( pathname, "r" );
if( !fd )
goto use_default;
if( NULL == fgets( host, sizeof(host), fd ) )
host[0] = 0;
else
{
p = strchr( host, '\n' );
if( p )
*p = 0;
p = strchr( host, '\r' );
if( p )
*p = 0;
}
fclose( fd );
p = strchr( host, ':' );
if( p )
*p++ = 0;
phe = gethostbyname( host );
if( !phe )
goto use_default;
memcpy( &sa_logger.sin_addr.s_addr, phe->h_addr, phe->h_length );
if( p )
sa_logger.sin_port = htons( (unsigned short) strtoul( p, NULL, 0 ) );
else
sa_logger.sin_port = htons( SYSLOG_PORT );
return;
use_default:
sa_logger.sin_addr.S_un.S_addr = htonl( 0x7F000001 );
sa_logger.sin_port = htons( SYSLOG_PORT );
}
/******************************************************************************
* closelog
*
* Close desriptor used to write to system logger.
*/
void closelog()
{
if( !initialized )
return;
closesocket( sock );
WSACleanup();
initialized = FALSE;
}
/******************************************************************************
* openlog
*
* Open connection to system logger.
*/
void openlog( char* ident, int option, int facility )
{
BOOL failed = TRUE, wsa_initialized = FALSE;
WSADATA wsd;
SOCKADDR_IN sa_local;
DWORD n;
int size;
if( initialized )
return;
syslog_facility = facility? facility : LOG_USER;
/* FIXME: should we reset logmask? */
if( option & LOG_PID )
snprintf( str_pid, sizeof(str_pid), "[%lu]", GetCurrentProcessId() );
else
str_pid[0] = 0;
/* FIXME: handle other options */
n = sizeof(local_hostname);
if( !GetComputerName( local_hostname, &n ) )
goto done;
sock = INVALID_SOCKET;
if( WSAStartup( MAKEWORD( 2, 2 ), &wsd ) )
goto done;
wsa_initialized = TRUE;
init_logger_addr();
for( n = 0;; n++ )
{
sock = socket( AF_INET, SOCK_DGRAM, 0 );
if( INVALID_SOCKET == sock )
goto done;
memset( &sa_local, 0, sizeof(SOCKADDR_IN) );
sa_local.sin_family = AF_INET;
if( bind( sock, (SOCKADDR*) &sa_local, sizeof(SOCKADDR_IN) ) == 0 )
break;
closesocket( sock );
sock = INVALID_SOCKET;
if( n == 100 )
goto done;
Sleep(0);
}
/* get size of datagramm */
size = sizeof(datagramm_size);
if( getsockopt( sock, SOL_SOCKET, SO_MAX_MSG_SIZE, (char*) &datagramm_size, &size ) )
goto done;
if( datagramm_size - strlen(local_hostname) - (ident? strlen(ident) : 0) < 64 )
goto done;
if( datagramm_size > sizeof(datagramm) )
datagramm_size = sizeof(datagramm);
if( atexit( closelog ) )
goto done;
syslog_ident = ident;
syslog_facility = facility;
failed = FALSE;
done:
if( failed )
{
if( sock != INVALID_SOCKET ) closesocket( sock );
if( wsa_initialized ) WSACleanup();
}
initialized = !failed;
}
/******************************************************************************
* setlogmask
*
* Set the log mask level.
*/
int setlogmask( int mask )
{
int ret = log_mask;
if( mask )
log_mask = mask;
return ret;
}
/******************************************************************************
* syslog
*
* Generate a log message using FMT string and option arguments.
*/
void syslog( int pri, char* fmt, ... )
{
va_list ap;
va_start( ap, fmt );
vsyslog( pri, fmt, ap );
va_end( ap );
}
/******************************************************************************
* vsyslog
*
* Generate a log message using FMT and using arguments pointed to by AP.
*/
void vsyslog( int pri, char* fmt, va_list ap )
{
static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
SYSTEMTIME stm;
int len;
char *p;
if( !(LOG_MASK( LOG_PRI( pri )) & log_mask) )
return;
openlog( NULL, 0, pri & LOG_FACMASK );
if( !initialized )
return;
if( !(pri & LOG_FACMASK) )
pri |= syslog_facility;
GetLocalTime( &stm );
len = sprintf( datagramm, "<%d>%s %2d %02d:%02d:%02d %s %s%s: ",
pri,
month[ stm.wMonth - 1 ], stm.wDay, stm.wHour, stm.wMinute, stm.wSecond,
local_hostname, syslog_ident? syslog_ident : "", str_pid );
vsnprintf( datagramm + len, datagramm_size - len, fmt, ap );
p = strchr( datagramm, '\n' );
if( p )
*p = 0;
p = strchr( datagramm, '\r' );
if( p )
*p = 0;
sendto( sock, datagramm, strlen(datagramm), 0, (SOCKADDR*) &sa_logger, sizeof(SOCKADDR_IN) );
}

View file

@ -0,0 +1,194 @@
/*
* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California. 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.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)syslog.h 8.1 (Berkeley) 6/2/93
*/
#pragma once
#include <stdarg.h>
/*
* priorities/facilities are encoded into a single 32-bit quantity, where the
* bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
* (0-big number). Both the priorities and the facilities map roughly
* one-to-one to strings in the syslogd(8) source code. This mapping is
* included in this file.
*
* priorities (these are ordered)
*/
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */
/* extract priority */
#define LOG_PRI(p) ((p) & LOG_PRIMASK)
#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
#ifdef SYSLOG_NAMES
#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
/* mark "facility" */
#define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0)
typedef struct _code {
char *c_name;
int c_val;
} CODE;
CODE prioritynames[] =
{
{ "alert", LOG_ALERT },
{ "crit", LOG_CRIT },
{ "debug", LOG_DEBUG },
{ "emerg", LOG_EMERG },
{ "err", LOG_ERR },
{ "error", LOG_ERR }, /* DEPRECATED */
{ "info", LOG_INFO },
{ "none", INTERNAL_NOPRI }, /* INTERNAL */
{ "notice", LOG_NOTICE },
{ "panic", LOG_EMERG }, /* DEPRECATED */
{ "warn", LOG_WARNING }, /* DEPRECATED */
{ "warning", LOG_WARNING },
{ NULL, -1 }
};
#endif
/* facility codes */
#define LOG_KERN (0<<3) /* kernel messages */
#define LOG_USER (1<<3) /* random user-level messages */
#define LOG_MAIL (2<<3) /* mail system */
#define LOG_DAEMON (3<<3) /* system daemons */
#define LOG_AUTH (4<<3) /* security/authorization messages */
#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
#define LOG_LPR (6<<3) /* line printer subsystem */
#define LOG_NEWS (7<<3) /* network news subsystem */
#define LOG_UUCP (8<<3) /* UUCP subsystem */
#define LOG_CRON (9<<3) /* clock daemon */
#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
#define LOG_FTP (11<<3) /* ftp daemon */
/* other codes through 15 reserved for system use */
#define LOG_LOCAL0 (16<<3) /* reserved for local use */
#define LOG_LOCAL1 (17<<3) /* reserved for local use */
#define LOG_LOCAL2 (18<<3) /* reserved for local use */
#define LOG_LOCAL3 (19<<3) /* reserved for local use */
#define LOG_LOCAL4 (20<<3) /* reserved for local use */
#define LOG_LOCAL5 (21<<3) /* reserved for local use */
#define LOG_LOCAL6 (22<<3) /* reserved for local use */
#define LOG_LOCAL7 (23<<3) /* reserved for local use */
#define LOG_NFACILITIES 24 /* current number of facilities */
#define LOG_FACMASK 0x03f8 /* mask to extract facility part */
/* facility of pri */
#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
#ifdef SYSLOG_NAMES
CODE facilitynames[] =
{
{ "auth", LOG_AUTH },
{ "authpriv", LOG_AUTHPRIV },
{ "cron", LOG_CRON },
{ "daemon", LOG_DAEMON },
{ "ftp", LOG_FTP },
{ "kern", LOG_KERN },
{ "lpr", LOG_LPR },
{ "mail", LOG_MAIL },
{ "mark", INTERNAL_MARK }, /* INTERNAL */
{ "news", LOG_NEWS },
{ "security", LOG_AUTH }, /* DEPRECATED */
{ "syslog", LOG_SYSLOG },
{ "user", LOG_USER },
{ "uucp", LOG_UUCP },
{ "local0", LOG_LOCAL0 },
{ "local1", LOG_LOCAL1 },
{ "local2", LOG_LOCAL2 },
{ "local3", LOG_LOCAL3 },
{ "local4", LOG_LOCAL4 },
{ "local5", LOG_LOCAL5 },
{ "local6", LOG_LOCAL6 },
{ "local7", LOG_LOCAL7 },
{ NULL, -1 }
};
#endif
/*
* arguments to setlogmask.
*/
#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */
#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */
/*
* Option flags for openlog.
*
* LOG_ODELAY no longer does anything.
* LOG_NDELAY is the inverse of what it used to be.
*/
#define LOG_PID 0x01 /* log the pid with each message */
#define LOG_CONS 0x02 /* log on the console if errors in sending */
#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */
#define LOG_NDELAY 0x08 /* don't delay open */
#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */
#define LOG_PERROR 0x20 /* log to stderr as well */
#define SYSLOG_PORT 514
#ifdef __cplusplus
extern "C" {
#endif
/* Close desriptor used to write to system logger. */
extern void closelog (void);
/* Open connection to system logger. */
extern void openlog (char *__ident, int __option, int __facility);
/* Set the log mask level. */
extern int setlogmask (int __mask);
/* Generate a log message using FMT string and option arguments. */
extern void syslog (int __pri, char *__fmt, ...);
/* Generate a log message using FMT and using arguments pointed to by AP. */
extern void vsyslog (int __pri, char *__fmt, va_list __ap);
/* windows-specific;
set directory from where syslog.host must be read;
this file contains a single line with hostname and port of syslog daemon;
default is localhost:514
*/
extern const char* set_syslog_conf_dir( const char* dir );
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,636 @@
/*
* Abstract: a simple telnet 'daemon' for Windows hosts.
*
* Compiled & run successfully using MSVC 5.0 under Windows95 (requires
* Winsock2 update) and Windows98 and MSVC 6.0 under WindowsNT4
*
* Compiler options : no special options needed
* Linker options : add wsock32.lib or ws2_32.lib
*
* Written by fred.van.lieshout 'at' zonnet.nl
* Use freely, no copyrights.
* Use Linux.
*
* Parts Copyright Steven Edwards
* Public Domain
*
* TODO:
* - access control
* - will/won't handshake
* - Unify Debugging output and return StatusCodes
*/
#include "telnetd.h"
#define telnetd_printf printf
#if 0
static inline int telnetd_printf(const char *format, ...);
{
printf(format,...);
syslog (6, format);
}
#endif
/* Local data */
static BOOLEAN bShutdown = 0;
static BOOLEAN bSocketInterfaceInitialised = 0;
static int sock;
/* In the future, some options might be passed here to handle
* authentication options in the registry or command line
* options passed to the service
*
* Once you are ready to turn on the service
* rename this function
* int kickoff_telnetd(void)
*/
int kickoff_telnetd(void)
{
printf("Attempting to start Simple TelnetD\n");
// DetectPlatform();
SetConsoleCtrlHandler(Cleanup, 1);
if (!StartSocketInterface())
ErrorExit("Unable to start socket interface\n");
CreateSocket();
while(!bShutdown) {
WaitForConnect();
}
WSACleanup();
return 0;
}
/* Cleanup */
static BOOL WINAPI Cleanup(DWORD dwControlType)
{
if (bSocketInterfaceInitialised) {
telnetd_printf("Cleanup...\n");
WSACleanup();
}
return 0;
}
/* StartSocketInterface */
static BOOLEAN StartSocketInterface(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
telnetd_printf("requested winsock version not supported\n");
return 0;
}
bSocketInterfaceInitialised = 1; /* for ErrorExit function */
if ( wsaData.wVersion != wVersionRequested)
ErrorExit("requested winsock version not supported\n");
telnetd_printf("TelnetD, using %s\n", wsaData.szDescription);
return 1;
}
/* CreateSocket */
static void CreateSocket(void)
{
struct sockaddr_in sa;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0)
ErrorExit("Cannot create socket");
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons(TELNET_PORT);
if (bind(sock, (struct sockaddr*) &sa, sizeof(sa)) != 0)
ErrorExit("Cannot bind address to socket");
}
/* WaitForConnect */
static void WaitForConnect(void)
{
struct sockaddr_in sa;
int new_sock;
if (listen(sock, 1) < 0)
ErrorExit("Cannot listen on socket");
if ((new_sock = accept(sock, (struct sockaddr*) &sa, NULL)) < 0) {
fprintf(stderr, "Failed to accept incoming call\n");
} else {
telnetd_printf("user connected on socket %d, port %d, address %lx\n", new_sock,
htons(sa.sin_port), sa.sin_addr.s_addr);
UserLogin(new_sock);
}
}
/* Function: UserLogin */
static void UserLogin(int client_socket)
{
DWORD threadID;
client_t *client = malloc(sizeof(client_t));
if (client == NULL)
ErrorExit("failed to allocate memory for client");
client->socket = client_socket;
CreateThread(NULL, 0, UserLoginThread, client, 0, &threadID);
}
/* Function: UserLoginThread */
static DWORD WINAPI UserLoginThread(LPVOID data)
{
client_t *client = (client_t *) data;
char welcome[256];
char hostname[64] = "Unknown";
char *pwdPrompt = "\r\npass:";
//char *logonPrompt = "\r\nLogin OK, please wait...";
//char *byebye = "\r\nWrong! bye bye...\r\n";
char userID[USERID_SIZE];
char password[USERID_SIZE];
int received;
char *terminator;
if (DoTelnetHandshake(client->socket)) {
closesocket(client->socket);
free(client);
return 0;
}
gethostname(hostname, sizeof(hostname));
sprintf(welcome, "\r\nWelcome to %s, please identify yourself\r\n\r\nuser:", hostname);
if (send(client->socket, welcome, strlen(welcome), 0) < 0) {
closesocket(client->socket);
free(client);
return 0;
}
received = ReceiveLine(client->socket, userID, sizeof(userID), Echo );
if (received < 0) {
closesocket(client->socket);
free(client);
return 0;
} else if (received) {
if ((terminator = strchr(userID, CR)) != NULL) {
*terminator = '\0';
}
}
if (send(client->socket, pwdPrompt, strlen(pwdPrompt), 0) < 0) {
closesocket(client->socket);
free(client);
return 0;
}
received = ReceiveLine(client->socket, password, sizeof(password), Password );
#if 0
if (received < 0) {
closesocket(client->socket);
free(client);
return 0;
} else if (received) {
if ((terminator = strchr(password, CR)) != NULL) {
*terminator = '\0';
}
}
#endif
/* TODO: do authentication here */
telnetd_printf("User '%p' logged on\n", userID);
#if 0
strcpy(client->userID, userID);
if (send(client->socket, logonPrompt, strlen(logonPrompt), 0) < 0) {
closesocket(client->socket);
free(client);
return 0;
}
#endif
RunShell(client);
return 0;
}
/* Function: DoTelnetHandshake */
static int DoTelnetHandshake(int sock)
{
int retval;
int received;
fd_set set;
struct timeval timeout = { HANDSHAKE_TIMEOUT, 0 };
char will_echo[]=
IAC DONT ECHO
IAC WILL ECHO
IAC WILL NAWS
IAC WILL SUPPRESS_GO_AHEAD
IAC DO SUPPRESS_GO_AHEAD
IAC DONT NEWENVIRON
IAC WONT NEWENVIRON
IAC WONT LINEMODE
IAC DO NAWS
IAC SB TERMINAL_TYPE "\x01" IAC SE
;
unsigned char client_reply[256];
if (send(sock, will_echo, sizeof(will_echo), 0) < 0) {
return -1;
}
/* Now wait for client response (and ignore it) */
FD_ZERO(&set);
FD_SET(sock, &set);
do {
retval = select(0, &set, NULL, NULL, &timeout);
/* check for error */
if (retval < 0) {
return -1;
/* check for timeout */
} else if (retval == 0) {
return 0;
}
/* no error and no timeout, we have data in our sock */
received = recv(sock, (char *) client_reply, sizeof(client_reply), 0);
if (received <= 0) {
return -1;
}
} while (retval);
return 0;
}
/*
** Function: ReceiveLine
**
** Abstract: receive until timeout or CR
** In : sock, len
** Out : buffer
** Result : int
** Pre : 'sock' must be valid socket
** Post : (result = the number of bytes read into 'buffer')
** OR (result = -1 and error)
*/
static int ReceiveLine(int sock, char *buffer, int len, EchoMode echo)
{
int i = 0;
int retval;
fd_set set;
struct timeval timeout = { 0, 100000 };
char del[3] = { BS, ' ', BS };
char asterisk[1] = { '*' };
FD_ZERO(&set);
FD_SET(sock, &set);
memset(buffer, '\0', len);
do {
/* When we're in echo mode, we do not need a timeout */
retval = select(0, &set, NULL, NULL, (echo ? NULL : &timeout) );
/* check for error */
if (retval < 0) {
return -1;
/* check for timeout */
} else if (retval == 0) {
/* return number of characters received so far */
return i;
}
/* no error and no timeout, we have data in our sock */
if (recv(sock, &buffer[i], 1, 0) <= 0) {
return -1;
}
if ((buffer[i] == '\0') || (buffer[i] == LF)) {
/* ignore null characters and linefeeds from DOS telnet clients */
buffer[i] = '\0';
} else if ((buffer[i] == DEL) || (buffer[i] == BS)) {
/* handle delete and backspace */
buffer[i] = '\0';
if (echo) {
if (i > 0) {
i--;
buffer[i] = '\0';
if (send(sock, del, sizeof(del), 0) < 0) {
return -1;
}
}
} else {
buffer[i] = BS; /* Let shell process handle it */
i++;
}
} else {
/* echo typed characters */
if (echo == Echo && send(sock, &buffer[i], 1, 0) < 0) {
return -1;
} else if (echo == Password && send(sock, asterisk, sizeof(asterisk), 0) < 0) {
return -1;
}
if (buffer[i] == CR) {
i++;
buffer[i] = LF; /* append LF for DOS command processor */
i++;
return i;
}
i++;
}
} while (i < len);
return i;
}
/*
** Function: RunShell
*/
static void RunShell(client_t *client)
{
DWORD threadID;
HANDLE hChildStdinRd;
HANDLE hChildStdinWr;
HANDLE hChildStdoutRd;
HANDLE hChildStdoutWr;
STARTUPINFO si;
PROCESS_INFORMATION piProcInfo;
SECURITY_ATTRIBUTES saAttr;
const char *name = "c:\\reactos\\system32\\cmd.exe";
const char *cmd = NULL;
//const char *name = "d:\\cygwin\\bin\\bash.exe";
//const char *cmd = "d:\\cygwin\\bin\\bash.exe --login -i";
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe for the child process's STDOUT.
if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
ErrorExit("Stdout pipe creation failed\n");
if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
ErrorExit("Stdin pipe creation failed\n");
client->bTerminate = FALSE;
client->bWriteToPipe = TRUE;
client->bReadFromPipe = TRUE;
client->hChildStdinWr = hChildStdinWr;
client->hChildStdoutRd = hChildStdoutRd;
// Create the child process (the shell)
telnetd_printf("Creating child process...\n");
ZeroMemory( &si, sizeof(STARTUPINFO) );
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = hChildStdinRd;
si.hStdOutput = hChildStdoutWr;
si.hStdError = hChildStdoutWr;
//si.dwFlags |= STARTF_USESHOWWINDOW;
//si.wShowWindow = SW_SHOW;
if (!CreateProcess((LPSTR) name, // executable module
(LPSTR) cmd, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
DETACHED_PROCESS + // creation flags
CREATE_NEW_PROCESS_GROUP,
NULL, // use parent's environment
NULL, // use parent's current directory
&si, // startup info
&piProcInfo)) {
ErrorExit("Create process failed");
}
client->hProcess = piProcInfo.hProcess;
client->dwProcessId = piProcInfo.dwProcessId;
telnetd_printf("New child created (groupid=%lu)\n", client->dwProcessId);
// No longer need these in the parent...
if (!CloseHandle(hChildStdoutWr))
ErrorExit("Closing handle failed");
if (!CloseHandle(hChildStdinRd))
ErrorExit("Closing handle failed");
CreateThread(NULL, 0, WriteToPipeThread, client, 0, &threadID);
CreateThread(NULL, 0, ReadFromPipeThread, client, 0, &threadID);
CreateThread(NULL, 0, MonitorChildThread, client, 0, &threadID);
}
/*
* Function: MonitorChildThread
*
* Abstract: Monitor the child (shell) process
*/
static DWORD WINAPI MonitorChildThread(LPVOID data)
{
DWORD exitCode;
client_t *client = (client_t *) data;
telnetd_printf("Monitor thread running...\n");
WaitForSingleObject(client->hProcess, INFINITE);
GetExitCodeProcess(client->hProcess, &exitCode);
telnetd_printf("Child process terminated with code %lx\n", exitCode);
/* signal the other threads to give up */
client->bTerminate = TRUE;
Sleep(500);
CloseHandle(client->hChildStdoutRd);
CloseHandle(client->hChildStdinWr);
CloseHandle(client->hProcess);
closesocket(client->socket);
telnetd_printf("Waiting for all threads to give up..\n");
while (client->bWriteToPipe || client->bReadFromPipe) {
telnetd_printf(".");
fflush(stdout);
Sleep(1000);
}
telnetd_printf("Cleanup for user '%s'\n", client->userID);
free(client);
return 0;
}
/*
* Function: WriteToPipeThread
*
* Abstract: read data from the telnet client socket
* and pass it on to the shell process.
*/
static DWORD WINAPI WriteToPipeThread(LPVOID data)
{
int iRead;
DWORD dwWritten;
CHAR chBuf[BUFSIZE];
client_t *client = (client_t *) data;
while (!client->bTerminate) {
iRead = ReceiveLine(client->socket, chBuf, BUFSIZE, FALSE);
if (iRead < 0) {
telnetd_printf("Client disconnect\n");
break;
} else if (iRead > 0) {
if (strchr(chBuf, CTRLC)) {
GenerateConsoleCtrlEvent(CTRL_C_EVENT, client->dwProcessId);
}
if (send(client->socket, chBuf, iRead, 0) < 0) {
telnetd_printf("error writing to socket\n");
break;
}
if (! WriteFile(client->hChildStdinWr, chBuf, (DWORD) iRead, &dwWritten, NULL)) {
telnetd_printf("Error writing to pipe\n");
break;
}
}
}
if (!client->bTerminate)
TerminateShell(client);
telnetd_printf("WriteToPipeThread terminated\n");
client->bWriteToPipe = FALSE;
return 0;
}
/*
* Function: ReadFromPipeThread
*
* Abstract: Read data from the shell's stdout handle and
* pass it on to the telnet client socket.
*/
static DWORD WINAPI ReadFromPipeThread(LPVOID data)
{
DWORD dwRead;
DWORD dwAvail;
CHAR chBuf[BUFSIZE];
CHAR txBuf[BUFSIZE*2];
DWORD from,to;
//char warning[] = "warning: rl_prep_terminal: cannot get terminal settings";
client_t *client = (client_t *) data;
while (!client->bTerminate && client->bWriteToPipe) {
// Since we do not want to block, first peek...
if (PeekNamedPipe(client->hChildStdoutRd, NULL, 0, NULL, &dwAvail, NULL) == 0) {
telnetd_printf("Failed to peek in pipe\n");
break;
}
if (dwAvail) {
if( ! ReadFile( client->hChildStdoutRd, chBuf, BUFSIZE, &dwRead, NULL) ||
dwRead == 0) {
telnetd_printf("Failed to read from pipe\n");
break;
}
for (from=0, to=0; from<dwRead; from++, to++) {
txBuf[to] = chBuf[from];
if (txBuf[to] == '\n') {
txBuf[to] = '\r';
to++;
txBuf[to] = '\n';
}
}
if (send(client->socket, txBuf, to, 0) < 0) {
telnetd_printf("error writing to socket\n");
break;
}
}
Sleep(100); /* Hmmm, oh well... what the heck! */
}
if (!client->bTerminate)
TerminateShell(client);
telnetd_printf("ReadFromPipeThread terminated\n");
client->bReadFromPipe = FALSE;
return 0;
}
/* TerminateShell */
static void TerminateShell(client_t *client)
{
DWORD exitCode;
DWORD dwWritten;
char stop[] = "\003\r\nexit\r\n"; /* Ctrl-C + exit */
GetExitCodeProcess(client->hProcess, &exitCode);
if (exitCode == STILL_ACTIVE)
{
HANDLE hEvent = NULL;
DWORD dwWaitResult;
telnetd_printf("user shell still active, send Ctrl-Break to group-id %lu\n", client->dwProcessId );
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent == NULL)
printf("CreateEvent error\n");
if (!GenerateConsoleCtrlEvent( CTRL_BREAK_EVENT, client->dwProcessId ))
telnetd_printf("Failed to send Ctrl_break\n");
if (!GenerateConsoleCtrlEvent( CTRL_C_EVENT, client->dwProcessId ))
telnetd_printf("Failed to send Ctrl_C\n");
if (!WriteFile(client->hChildStdinWr, stop, sizeof(stop), &dwWritten, NULL))
telnetd_printf("Error writing to pipe\n");
/* wait for our handler to be called */
dwWaitResult=WaitForSingleObject(hEvent, 500);
if (WAIT_FAILED==dwWaitResult)
telnetd_printf("WaitForSingleObject failed\n");
GetExitCodeProcess(client->hProcess, &exitCode);
if (exitCode == STILL_ACTIVE)
{
telnetd_printf("user shell still active, attempt to terminate it now...\n");
if (hEvent != NULL)
{
if (!CloseHandle(hEvent))
telnetd_printf("CloseHandle");
}
TerminateProcess(client->hProcess, 0);
}
TerminateProcess(client->hProcess, 0);
}
TerminateProcess(client->hProcess, 0);
}
/* ErrorExit */
static VOID ErrorExit (LPTSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
if (bSocketInterfaceInitialised) {
telnetd_printf("WSAGetLastError=%d\n", WSAGetLastError());
WSACleanup();
}
ExitProcess(0);
}

View file

@ -0,0 +1,83 @@
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_NO_STATUS
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include <time.h>
/*
** macro definitions
*/
#define TELNET_PORT (23)
#define BUFSIZE (4096)
#define USERID_SIZE (64)
#define CTRLC (3)
#define BS (8)
#define CR (13)
#define LF (10)
#define DEL (127)
#define IAC "\xff"
#define DONT "\xfe"
#define WONT "\xfc"
#define WILL "\xfb"
#define DO "\xfd"
#define SB "\xfa"
#define SE "\xf0"
#define ECHO "\x01"
#define SUPPRESS_GO_AHEAD "\x03"
#define TERMINAL_TYPE "\x18"
#define NAWS "\x1f"
#define LINEMODE "\x22"
#define NEWENVIRON "\x27"
#define MODE "\x01"
#define HANDSHAKE_TIMEOUT (3)
/*
** types
*/
typedef struct client_s
{
char userID[USERID_SIZE];
int socket;
BOOLEAN bTerminate;
BOOLEAN bReadFromPipe;
BOOLEAN bWriteToPipe;
HANDLE hProcess;
DWORD dwProcessId;
HANDLE hChildStdinWr;
HANDLE hChildStdoutRd;
} client_t;
typedef enum
{
NoEcho = 0,
Echo = 1,
Password = 2
} EchoMode;
/*
** Forward function declarations
*/
static BOOL WINAPI Cleanup(DWORD dwControlType);
static void WaitForConnect(void);
static BOOLEAN StartSocketInterface(void);
static void CreateSocket(void);
static void UserLogin(int client_socket);
static DWORD WINAPI UserLoginThread(LPVOID);
static int DoTelnetHandshake(int sock);
static int ReceiveLine(int sock, char *buffer, int len, EchoMode echo);
static void RunShell(client_t *client);
//static BOOL CreateChildProcess(const char *);
static DWORD WINAPI MonitorChildThread(LPVOID);
static DWORD WINAPI WriteToPipeThread(LPVOID);
static DWORD WINAPI ReadFromPipeThread(LPVOID);
static void TerminateShell(client_t *client);
static VOID ErrorExit(LPTSTR);
int kickoff_telnetd(void);

View file

@ -0,0 +1,13 @@
<module name="telnetd" type="win32cui" installbase="system32" installname="telnetd.exe" unicode="no">
<include base="reactos"></include>
<include base="telnetd">..</include>
<library>ntdll</library>
<library>advapi32</library>
<library>ws2_32</library>
<library>wine</library>
<file>telnetd.c</file>
<file>serviceentry.c</file>
<file>telnetd.rc</file>
</module>

View file

@ -0,0 +1,7 @@
/* $Id$ */
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Simple Telnet Deamon\0"
#define REACTOS_STR_INTERNAL_NAME "telnetd\0"
#define REACTOS_STR_ORIGINAL_FILENAME "telnetd.exe\0"
#define REACTOS_STR_ORIGINAL_COPYRIGHT "fred.van.lieshout 'at' zonnet.nl\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,196 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="telnetd"
ProjectGUID="{3B4D6C18-202E-41C8-B1E8-0FC5CD940819}"
RootNamespace="telnetd"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
WarningLevel="3"
DebugInformationFormat="4"
CallingConvention="2"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="msvcrt.lib advapi32.lib ws2_32.lib"
IgnoreAllDefaultLibraries="true"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\serviceentry.c"
>
</File>
<File
RelativePath=".\telnetd.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\telnetd.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -0,0 +1,3 @@
This is a snapshot from the 1.6 release of tftp-server for win32 from sourceforge.
http://tftp-server.sourceforge.net

File diff suppressed because it is too large Load diff

161
base/services/tftpd/tftpd.h Normal file
View file

@ -0,0 +1,161 @@
/**************************************************************************
* Copyright (C) 2005 by Achal Dhir *
* achaldhir@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
// TFTPServer.cpp
#ifdef _MSC_VER
#define strcasecmp _stricmp
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")
#endif
//Constants
#define my_inet_addr inet_addr
#define MAX_SERVERS 8
//Structs
struct home
{
char alias[64];
char target[256];
};
struct tftpConnType
{
SOCKET sock;
sockaddr_in addr;
DWORD server;
WORD port;
};
struct acknowledgement
{
WORD opcode;
WORD block;
};
struct message
{
WORD opcode;
char buffer[514];
};
struct tftperror
{
WORD opcode;
WORD errorcode;
char errormessage[512];
};
struct packet
{
WORD opcode;
WORD block;
char buffer;
};
struct data12
{
DWORD rangeStart;
DWORD rangeEnd;
};
struct request
{
timeval tv;
fd_set readfds;
time_t expiry;
SOCKET sock;
SOCKET knock;
BYTE sockInd;
BYTE attempt;
char path[256];
FILE *file;
char *filename;
char *mode;
char *alias;
DWORD tsize;
DWORD fblock;
int bytesReady;
int bytesRecd;
int bytesRead[2];
packet* pkt[2];
sockaddr_in client;
socklen_t clientsize;
union
{
tftperror serverError;
message mesout;
acknowledgement acout;
};
union
{
tftperror clientError;
message mesin;
acknowledgement acin;
};
WORD blksize;
WORD timeout;
WORD block;
WORD tblock;
};
struct data2
{
WSADATA wsaData;
tftpConnType tftpConn[MAX_SERVERS];
DWORD servers[MAX_SERVERS];
WORD ports[MAX_SERVERS];
home homes[8];
FILE *logfile;
data12 hostRanges[32];
char fileRead;
char fileWrite;
char fileOverwrite;
int minport;
int maxport;
SOCKET maxFD;
BYTE logLevel;
};
struct data15
{
union
{
//DWORD ip;
unsigned ip:32;
BYTE octate[4];
};
};
//Functions
void runProg();
void processRequest(LPVOID lpParam);
char* myGetToken(char*, BYTE);
void init();
bool cleanReq(request*);
bool getSection(const char*, char*, BYTE, char*);
bool isIP(char*s);
char* myLower(char*);
char* myUpper(char*);
char* IP2String(char*, DWORD);
void printWindowsError();
void logMess(request*, BYTE);
void logMess(char*, BYTE);

View file

@ -0,0 +1,11 @@
<module name="tftpd" type="win32cui" installbase="system32" installname="tftpd.exe" allowwarnings="true" unicode="no">
<include base="reactos"></include>
<include base="telnetd">..</include>
<library>ntdll</library>
<library>advapi32</library>
<library>ws2_32</library>
<library>wine</library>
<file>tftpd.cpp</file>
</module>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="umpnpmgr" type="win32cui" installbase="system32" installname="umpnpmgr.exe" unicode="yes">
<include base="umpnpmgr">.</include>
<include base="pnp_server">.</include>
<redefine name="_WIN32_WINNT">0x600</redefine>
<library>pnp_server</library>
<library>ntdll</library>
<library>advapi32</library>
<library>rpcrt4</library>
<library>pseh</library>
<library>wdmguid</library>
<library>userenv</library>
<file>umpnpmgr.c</file>
<file>umpnpmgr.rc</file>
</module>

View file

@ -0,0 +1,4 @@
#define REACTOS_STR_FILE_DESCRIPTION "User-Mode Plug and Play manager\0"
#define REACTOS_STR_INTERNAL_NAME "Umpnpmgr\0"
#define REACTOS_STR_ORIGINAL_FILENAME "Umpnpmgr.exe\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,543 @@
/*
* PROJECT: ReactOS WLAN Service
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/services/wlansvc/rpcserver.c
* PURPOSE: RPC server interface
* COPYRIGHT: Copyright 2009 Christoph von Wittich
*/
/* INCLUDES ****************************************************************/
#include <windows.h>
#include <iphlpapi.h>
#include "wlansvc_s.h"
#define NDEBUG
#include <debug.h>
DWORD _RpcOpenHandle(
wchar_t *arg_1,
DWORD dwClientVersion,
DWORD *pdwNegotiatedVersion,
LPWLANSVC_RPC_HANDLE phClientHandle)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcCloseHandle(
LPWLANSVC_RPC_HANDLE phClientHandle)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcEnumInterfaces(
WLANSVC_RPC_HANDLE hClientHandle,
PWLAN_INTERFACE_INFO_LIST *ppInterfaceList)
{
#if GET_IF_ENTRY2_IMPLEMENTED
DWORD dwNumInterfaces;
DWORD dwResult, dwSize;
DWORD dwIndex;
MIB_IF_ROW2 IfRow;
PWLAN_INTERFACE_INFO_LIST InterfaceList;
if (!hClientHandle || !ppInterfaceList)
return ERROR_INVALID_PARAMETER;
dwResult = GetNumberOfInterfaces(&dwNumInterfaces);
dwSize = sizeof(WLAN_INTERFACE_INFO_LIST);
if (dwResult != NO_ERROR)
{
/* set num interfaces to zero when an error occurs */
dwNumInterfaces = 0;
}
else
{
if (dwNumInterfaces > 1)
{
/* add extra size for interface */
dwSize += (dwNumInterfaces-1) * sizeof(WLAN_INTERFACE_INFO);
}
}
/* allocate interface list */
InterfaceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
if (!InterfaceList)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
*ppInterfaceList = InterfaceList;
if (!dwNumInterfaces)
{
return ERROR_SUCCESS;
}
for(dwIndex = 0; dwIndex < dwNumInterfaces; dwIndex++)
{
ZeroMemory(&IfRow, sizeof(MIB_IF_ROW2));
IfRow.InterfaceIndex = dwIndex;
dwResult = GetIfEntry2(&IfRow);
if (dwResult == NO_ERROR)
{
if (IfRow.Type == IF_TYPE_IEEE80211 && IfRow.InterfaceAndOperStatusFlags.HardwareInterface)
{
RtlMoveMemory(&InterfaceList->InterfaceInfo[InterfaceList->dwNumberOfItems].InterfaceGuid, &IfRow.InterfaceGuid, sizeof(GUID));
wcscpy(InterfaceList->InterfaceInfo[InterfaceList->dwNumberOfItems].strInterfaceDescription, IfRow.Description);
//FIXME set state
InterfaceList->dwNumberOfItems++;
}
}
}
return ERROR_SUCCESS;
#else
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
#endif
}
DWORD _RpcSetAutoConfigParameter(
WLANSVC_RPC_HANDLE hClientHandle,
long OpCode,
DWORD dwDataSize,
LPBYTE pData)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcQueryAutoConfigParameter(
WLANSVC_RPC_HANDLE hClientHandle,
DWORD OpCode,
LPDWORD pdwDataSize,
char **ppData,
DWORD *pWlanOpcodeValueType)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcGetInterfaceCapability(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
PWLAN_INTERFACE_CAPABILITY *ppCapability)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetInterface(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
DWORD OpCode,
DWORD dwDataSize,
LPBYTE pData)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcQueryInterface(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
long OpCode,
LPDWORD pdwDataSize,
LPBYTE *ppData,
LPDWORD pWlanOpcodeValueType)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcIhvControl(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
DWORD Type,
DWORD dwInBufferSize,
LPBYTE pInBuffer,
DWORD dwOutBufferSize,
LPBYTE pOutBuffer,
LPDWORD pdwBytesReturned)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcScan(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
PDOT11_SSID pDot11Ssid,
PWLAN_RAW_DATA pIeData)
{
/*
DWORD dwBytesReturned;
HANDLE hDevice;
ULONG OidCode = OID_802_11_BSSID_LIST_SCAN;
PNDIS_802_11_BSSID_LIST pBssIDList;
DeviceIoControl(hDevice,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&OidCode,
sizeof(ULONG),
NULL,
0,
&dwBytesReturned,
NULL);
*/
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcGetAvailableNetworkList(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
DWORD dwFlags,
WLAN_AVAILABLE_NETWORK_LIST **ppAvailableNetworkList)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcGetNetworkBssList(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
PDOT11_SSID pDot11Ssid,
short dot11BssType,
DWORD bSecurityEnabled,
LPDWORD dwBssListSize,
LPBYTE *ppWlanBssList)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcConnect(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
PWLAN_CONNECTION_PARAMETERS *pConnectionParameters)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcDisconnect(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGUID)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcRegisterNotification(
WLANSVC_RPC_HANDLE hClientHandle,
DWORD arg_2,
LPDWORD pdwPrevNotifSource)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcAsyncGetNotification(
WLANSVC_RPC_HANDLE hClientHandle,
PWLAN_NOTIFICATION_DATA *NotificationData)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetProfileEapUserData(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
wchar_t *strProfileName,
EAP_METHOD_TYPE MethodType,
DWORD dwFlags,
DWORD dwEapUserDataSize,
LPBYTE pbEapUserData)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetProfile(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
DWORD dwFlags,
wchar_t *strProfileXml,
wchar_t *strAllUserProfileSecurity,
BOOL bOverwrite,
LPDWORD pdwReasonCode)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcGetProfile(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
wchar_t *strProfileName,
wchar_t **pstrProfileXml,
LPDWORD pdwFlags,
LPDWORD pdwGrantedAccess)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcDeleteProfile(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
wchar_t *strProfileName)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcRenameProfile(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
wchar_t *strOldProfileName,
wchar_t *strNewProfileName)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetProfileList(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
DWORD dwItems,
BYTE **strProfileNames)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcGetProfileList(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
PWLAN_PROFILE_INFO_LIST *ppProfileList)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetProfilePosition(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
wchar_t *strProfileName,
DWORD dwPosition)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetProfileCustomUserData(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
wchar_t *strProfileName,
DWORD dwDataSize,
LPBYTE pData)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcGetProfileCustomUserData(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
wchar_t *strProfileName,
LPDWORD dwDataSize,
LPBYTE *pData)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetFilterList(
WLANSVC_RPC_HANDLE hClientHandle,
short wlanFilterListType,
PDOT11_NETWORK_LIST pNetworkList)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcGetFilterList(
WLANSVC_RPC_HANDLE hClientHandle,
short wlanFilterListType,
PDOT11_NETWORK_LIST *pNetworkList)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetPsdIEDataList(
WLANSVC_RPC_HANDLE hClientHandle,
wchar_t *strFormat,
DWORD dwDataListSize,
LPBYTE pPsdIEDataList)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSaveTemporaryProfile(
WLANSVC_RPC_HANDLE hClientHandle,
GUID *pInterfaceGuid,
wchar_t *strProfileName,
wchar_t *strAllUserProfileSecurity,
DWORD dwFlags,
BOOL bOverWrite)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcIsUIRequestPending(
wchar_t *arg_1,
GUID *pInterfaceGuid,
struct_C *arg_3,
LPDWORD arg_4)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetUIForwardingNetworkList(
wchar_t *arg_1,
GUID *arg_2,
DWORD dwSize,
GUID *arg_4)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcIsNetworkSuppressed(
wchar_t *arg_1,
DWORD arg_2,
GUID *pInterfaceGuid,
LPDWORD arg_4)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcRemoveUIForwardingNetworkList(
wchar_t *arg_1,
GUID *pInterfaceGuid)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcQueryExtUIRequest(
wchar_t *arg_1,
GUID *arg_2,
GUID *arg_3,
short arg_4,
GUID *pInterfaceGuid,
struct_C **arg_6)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcUIResponse(
wchar_t *arg_1,
struct_C *arg_2,
struct_D *arg_3)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcGetProfileKeyInfo(
wchar_t *arg_1,
DWORD arg_2,
GUID *pInterfaceGuid,
wchar_t *arg_4,
DWORD arg_5,
LPDWORD arg_6,
char *arg_7,
LPDWORD arg_8)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcAsyncDoPlap(
wchar_t *arg_1,
GUID *pInterfaceGuid,
wchar_t *arg_3,
DWORD dwSize,
struct_E arg_5[])
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcQueryPlapCredentials(
wchar_t *arg_1,
LPDWORD dwSize,
struct_E **arg_3,
wchar_t **arg_4,
GUID *pInterfaceGuid,
LPDWORD arg_6,
LPDWORD arg_7,
LPDWORD arg_8,
LPDWORD arg_9)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcCancelPlap(
wchar_t *arg_1,
GUID *pInterfaceGuid)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcSetSecuritySettings(
WLANSVC_RPC_HANDLE hClientHandle,
WLAN_SECURABLE_OBJECT SecurableObject,
wchar_t *strModifiedSDDL)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD _RpcGetSecuritySettings(
WLANSVC_RPC_HANDLE hClientHandle,
WLAN_SECURABLE_OBJECT SecurableObject,
WLAN_OPCODE_VALUE_TYPE *pValueType,
wchar_t **pstrCurrentSDDL,
LPDWORD pdwGrantedAccess)
{
UNIMPLEMENTED;
return ERROR_CALL_NOT_IMPLEMENTED;
}
void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
}
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
HeapFree(GetProcessHeap(), 0, ptr);
}
void __RPC_USER WLANSVC_RPC_HANDLE_rundown(WLANSVC_RPC_HANDLE hClientHandle)
{
}

View file

@ -0,0 +1,153 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/wlansvc/wlansvc.c
* PURPOSE: WLAN Service
* PROGRAMMER: Christoph von Wittich
*/
/* INCLUDES *****************************************************************/
#define WIN32_NO_STATUS
#include <windows.h>
#include "wlansvc_s.h"
//#define NDEBUG
#include <debug.h>
/* GLOBALS ******************************************************************/
#define SERVICE_NAME L"WLAN Service"
SERVICE_STATUS_HANDLE ServiceStatusHandle;
SERVICE_STATUS SvcStatus;
/* FUNCTIONS *****************************************************************/
static DWORD WINAPI RpcThreadRoutine(LPVOID lpParameter)
{
RPC_STATUS Status;
Status = RpcServerUseProtseqEpW(L"ncalrpc", 20, L"wlansvc", NULL);
if (Status != RPC_S_OK)
{
DPRINT("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
return 0;
}
Status = RpcServerRegisterIf(wlansvc_interface_v1_0_s_ifspec, NULL, NULL);
if (Status != RPC_S_OK)
{
DPRINT("RpcServerRegisterIf() failed (Status %lx)\n", Status);
return 0;
}
Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, 0);
if (Status != RPC_S_OK)
{
DPRINT("RpcServerListen() failed (Status %lx)\n", Status);
}
DPRINT("RpcServerListen finished\n");
return 0;
}
static void UpdateServiceStatus(HANDLE hServiceStatus, DWORD NewStatus, DWORD Increment)
{
if (Increment > 0)
SvcStatus.dwCheckPoint += Increment;
else
SvcStatus.dwCheckPoint = 0;
SvcStatus.dwCurrentState = NewStatus;
SetServiceStatus(hServiceStatus, &SvcStatus);
}
static DWORD WINAPI
ServiceControlHandler(DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext)
{
switch (dwControl)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
UpdateServiceStatus(ServiceStatusHandle, SERVICE_STOP_PENDING, 1);
RpcMgmtStopServerListening(NULL);
break;
case SERVICE_CONTROL_INTERROGATE:
return NO_ERROR;
default:
return ERROR_CALL_NOT_IMPLEMENTED;
}
return NO_ERROR;
}
static VOID CALLBACK
ServiceMain(DWORD argc, LPWSTR *argv)
{
HANDLE hThread;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
DPRINT("ServiceMain() called\n");
SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
SvcStatus.dwCheckPoint = 0;
SvcStatus.dwWin32ExitCode = 0;
SvcStatus.dwServiceSpecificExitCode = 0;
SvcStatus.dwWaitHint = 4000;
ServiceStatusHandle = RegisterServiceCtrlHandlerExW(SERVICE_NAME,
ServiceControlHandler,
NULL);
UpdateServiceStatus(ServiceStatusHandle, SERVICE_RUNNING, 0);
hThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)
RpcThreadRoutine,
NULL,
0,
NULL);
if (!hThread)
DPRINT("Can't create RpcThread\n");
else
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
UpdateServiceStatus(ServiceStatusHandle, SERVICE_STOPPED, 0);
DPRINT("ServiceMain() done\n");
}
int
wmain(int argc, WCHAR *argv[])
{
SERVICE_TABLE_ENTRYW ServiceTable[2] =
{
{SERVICE_NAME, ServiceMain},
{NULL, NULL}
};
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
DPRINT("wlansvc: main() started\n");
StartServiceCtrlDispatcherW(ServiceTable);
DPRINT("wlansvc: main() done\n");
ExitThread(0);
return 0;
}
/* EOF */

Some files were not shown because too many files have changed in this diff Show more