diff --git a/reactos/drivers/lib/ip/network/ip.c b/reactos/drivers/lib/ip/network/ip.c index 4b6871efc0c..ef23f27b5d1 100644 --- a/reactos/drivers/lib/ip/network/ip.c +++ b/reactos/drivers/lib/ip/network/ip.c @@ -244,13 +244,29 @@ BOOLEAN IPRegisterInterface( */ { KIRQL OldIrql; + UINT ChosenIndex = 1; + BOOLEAN IndexHasBeenChosen; IP_ADDRESS NetworkAddress; PNEIGHBOR_CACHE_ENTRY NCE; + IF_LIST_ITER(Interface); TI_DbgPrint(MID_TRACE, ("Called. IF (0x%X).\n", IF)); TcpipAcquireSpinLock(&IF->Lock, &OldIrql); + /* Choose an index */ + do { + IndexHasBeenChosen = TRUE; + ForEachInterface(Interface) { + if( Interface->Index == ChosenIndex ) { + ChosenIndex++; + IndexHasBeenChosen = FALSE; + } + } EndFor(Interface); + } while( !IndexHasBeenChosen ); + + IF->Index = ChosenIndex; + /* Add a permanent neighbor for this NTE */ NCE = NBAddNeighbor(IF, &IF->Unicast, IF->Address, IF->AddressLength, diff --git a/reactos/drivers/net/tcpip/include/dispatch.h b/reactos/drivers/net/tcpip/include/dispatch.h index 5108ff55695..bd559517b11 100644 --- a/reactos/drivers/net/tcpip/include/dispatch.h +++ b/reactos/drivers/net/tcpip/include/dispatch.h @@ -56,6 +56,14 @@ NTSTATUS DispTdiSetInformationEx( PIRP Irp, PIO_STACK_LOCATION IrpSp); +NTSTATUS DispTdiSetIPAddress( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS DispTdiDeleteIPAddress( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + #endif /* __DISPATCH_H */ /* EOF */ diff --git a/reactos/drivers/net/tcpip/include/ip.h b/reactos/drivers/net/tcpip/include/ip.h index 9986897fa3b..68950cebcee 100644 --- a/reactos/drivers/net/tcpip/include/ip.h +++ b/reactos/drivers/net/tcpip/include/ip.h @@ -153,10 +153,16 @@ typedef struct _IP_INTERFACE { UNICODE_STRING Name; /* Adapter name */ PUCHAR Address; /* Pointer to interface address */ UINT AddressLength; /* Length of address in bytes */ + UINT Index; /* Index of adapter (used to add ip addr) */ LL_TRANSMIT_ROUTINE Transmit; /* Pointer to transmit function */ PVOID TCPContext; /* TCP Content for this interface */ } IP_INTERFACE, *PIP_INTERFACE; +typedef struct _IP_SET_ADDRESS { + ULONG NteIndex; + IPv4_RAW_ADDRESS Address; + IPv4_RAW_ADDRESS Netmask; +} IP_SET_ADDRESS, *PIP_SET_ADDRESS; #define IP_PROTOCOL_TABLE_SIZE 0x100 diff --git a/reactos/drivers/net/tcpip/include/ticonsts.h b/reactos/drivers/net/tcpip/include/ticonsts.h index ab0b2425fb2..ca26064f111 100644 --- a/reactos/drivers/net/tcpip/include/ticonsts.h +++ b/reactos/drivers/net/tcpip/include/ticonsts.h @@ -45,6 +45,12 @@ #define IOCTL_TCP_SET_INFORMATION_EX \ _TCP_CTL_CODE(1, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_SET_IP_ADDRESS \ + _TCP_CTL_CODE(14, METHOD_BUFFERED, FILE_WRITE_ACCESS) + +#define IOCTL_DELETE_IP_ADDRESS \ + _TCP_CTL_CODE(16, METHOD_BUFFERED, FILE_WRITE_ACCESS) + /* Unique error values for log entries */ #define TI_ERROR_DRIVERENTRY 0 diff --git a/reactos/drivers/net/tcpip/tcpip/dispatch.c b/reactos/drivers/net/tcpip/tcpip/dispatch.c index ec417f99b36..0f25e9e41a5 100644 --- a/reactos/drivers/net/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/net/tcpip/tcpip/dispatch.c @@ -1465,4 +1465,56 @@ NTSTATUS DispTdiSetInformationEx( return Status; } +/* TODO: Support multiple addresses per interface. + * For now just set the nte context to the interface index. + * + * Later on, create an NTE context and NTE instance + */ + +NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { + NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST; + PIP_SET_ADDRESS IpAddrChange = + (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer; + IF_LIST_ITER(IF); + + ForEachInterface(IF) { + if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) { + Status = STATUS_DUPLICATE_OBJECTID; + break; + } + if( IF->Index == IpAddrChange->NteIndex ) { + IF->Unicast.Type = IP_ADDRESS_V4; + IF->Unicast.Address.IPv4Address = IpAddrChange->Address; + IF->Netmask.Type = IP_ADDRESS_V4; + IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask; + IpAddrChange->Address = IF->Index; + Status = STATUS_SUCCESS; + Irp->IoStatus.Information = IF->Index; + break; + } + } EndFor(IF); + + Irp->IoStatus.Status = Status; + return Status; +} + +NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer; + IF_LIST_ITER(IF); + + ForEachInterface(IF) { + if( IF->Index == *NteIndex ) { + IF->Unicast.Type = IP_ADDRESS_V4; + IF->Unicast.Address.IPv4Address = 0; + IF->Netmask.Type = IP_ADDRESS_V4; + IF->Netmask.Address.IPv4Address = 0; + Status = STATUS_SUCCESS; + } + } EndFor(IF); + + Irp->IoStatus.Status = Status; + return Status; +} + /* EOF */ diff --git a/reactos/drivers/net/tcpip/tcpip/iinfo.c b/reactos/drivers/net/tcpip/tcpip/iinfo.c index 4d47b555c50..857e0a323fc 100644 --- a/reactos/drivers/net/tcpip/tcpip/iinfo.c +++ b/reactos/drivers/net/tcpip/tcpip/iinfo.c @@ -33,7 +33,7 @@ TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID *ID, RtlZeroMemory( OutData, sizeof(IFENTRY) + MAX_IFDESCR_LEN ); - OutData->Index = ID->tei_instance + 1; + OutData->Index = Interface->Index; /* viz: tcpip keeps those indices */ OutData->Type = Interface == Loopback ? MIB_IF_TYPE_LOOPBACK : MIB_IF_TYPE_ETHERNET; @@ -104,5 +104,7 @@ TDI_STATUS InfoInterfaceTdiSetEx( UINT InfoClass, TDIEntityID *id, PCHAR Buffer, UINT BufferSize ) { + TI_DbgPrint("Got Request: Class %x Type %x Id %x, EntityID %x:%x\n", + InfoClass, InfoId, id->tei_entity, id->tei_instance); return TDI_INVALID_REQUEST; } diff --git a/reactos/drivers/net/tcpip/tcpip/main.c b/reactos/drivers/net/tcpip/tcpip/main.c index eb5101dd974..ca9e274ff95 100644 --- a/reactos/drivers/net/tcpip/tcpip/main.c +++ b/reactos/drivers/net/tcpip/tcpip/main.c @@ -9,7 +9,7 @@ */ #include "precomp.h" -#define NDEBUG +//#define NDEBUG #ifndef NDEBUG DWORD DebugTraceLevel = DEBUG_ULTRA & ~(DEBUG_LOCK | DEBUG_PBUFFER); @@ -578,6 +578,16 @@ TiDispatch( Status = DispTdiSetInformationEx(Irp, IrpSp); break; + case IOCTL_SET_IP_ADDRESS: + TI_DbgPrint(MIN_TRACE, ("SET_IP_ADDRESS\n")); + Status = DispTdiSetIPAddress(Irp, IrpSp); + break; + + case IOCTL_DELETE_IP_ADDRESS: + TI_DbgPrint(MIN_TRACE, ("DELETE_IP_ADDRESS\n")); + Status = DispTdiDeleteIPAddress(Irp, IrpSp); + break; + default: TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode)); diff --git a/reactos/include/tcpioctl.h b/reactos/include/tcpioctl.h index b1e113daab7..49d5b794280 100644 --- a/reactos/include/tcpioctl.h +++ b/reactos/include/tcpioctl.h @@ -37,4 +37,10 @@ #define IOCTL_TCP_SET_INFORMATION_EX \ _TCP_CTL_CODE(1, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_SET_IP_ADDRESS \ + _TCP_CTL_CODE(14, METHOD_BUFFERED, FILE_WRITE_ACCESS) + +#define IOCTL_DELETE_IP_ADDRESS \ + _TCP_CTL_CODE(16, METHOD_BUFFERED, FILE_WRITE_ACCESS) + #endif/*_TCPIOCTL_H*/ diff --git a/reactos/lib/iphlpapi/ifenum_reactos.c b/reactos/lib/iphlpapi/ifenum_reactos.c index ac19823be84..073983d8a9a 100644 --- a/reactos/lib/iphlpapi/ifenum_reactos.c +++ b/reactos/lib/iphlpapi/ifenum_reactos.c @@ -754,6 +754,8 @@ DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry) sizeof(info.if_info) ); } + DPRINT1("entry->bDescr = %s\n", entry->bDescr); + closeTcpFile( tcpFile ); } @@ -795,3 +797,72 @@ char *toIPAddressString(unsigned int addr, char string[16]) } return string; } + +NTSTATUS addIPAddress( IPAddr Address, IPMask Mask, DWORD IfIndex, + PULONG NteContext, PULONG NteInstance ) +{ + HANDLE tcpFile; + NTSTATUS status = openTcpFile( &tcpFile ); + IP_SET_DATA Data; + IO_STATUS_BLOCK Iosb; + + DPRINT("Called.\n"); + + if( !NT_SUCCESS(status) ) return status; + + Data.NteContext = IfIndex; + Data.NewAddress = Address; + Data.NewNetmask = Mask; + + status = NtDeviceIoControlFile( tcpFile, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_SET_IP_ADDRESS, + &Data, + sizeof(Data), + &Data, + sizeof(Data) ); + + closeTcpFile( tcpFile ); + + if( NT_SUCCESS(status) ) { + *NteContext = Iosb.Information; + *NteInstance = Data.NewAddress; + } + + switch( status ) { + case STATUS_SUCCESS: return ERROR_SUCCESS; + case STATUS_DEVICE_DOES_NOT_EXIST: return ERROR_DEV_NOT_EXIST; + default: return status; + } +} + +NTSTATUS deleteIpAddress( ULONG NteContext ) +{ + HANDLE tcpFile; + NTSTATUS status = openTcpFile( &tcpFile ); + USHORT TheNteContext = NteContext; + IO_STATUS_BLOCK Iosb; + + DPRINT("Called.\n"); + + if( !NT_SUCCESS(status) ) return status; + + status = NtDeviceIoControlFile( tcpFile, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DELETE_IP_ADDRESS, + &NteContext, + sizeof(USHORT), + NULL, + 0 ); + + closeTcpFile( tcpFile ); + + if( NT_SUCCESS(status) ) return ERROR_SUCCESS; + else return ERROR_GEN_FAILURE; +} diff --git a/reactos/lib/iphlpapi/iphlpapi_main.c b/reactos/lib/iphlpapi/iphlpapi_main.c index 7cb92952e77..3baddf6074d 100644 --- a/reactos/lib/iphlpapi/iphlpapi_main.c +++ b/reactos/lib/iphlpapi/iphlpapi_main.c @@ -82,11 +82,9 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) * DWORD * */ -DWORD WINAPI AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG NTEContext, PULONG NTEInstance) +DWORD WINAPI AddIPAddress(IPAddr Address, IPMask Netmask, DWORD IfIndex, PULONG NteContext, PULONG NteInstance) { - FIXME(":stub\n"); - /* marking Win2K+ functions not supported */ - return ERROR_NOT_SUPPORTED; + return addIPAddress( Address, Netmask, IfIndex, NteContext, NteInstance ); } @@ -404,9 +402,7 @@ DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex) DWORD WINAPI DeleteIPAddress(ULONG NTEContext) { TRACE("NTEContext %ld\n", NTEContext); - FIXME(":stub\n"); - /* marking Win2K+ functions not supported */ - return ERROR_NOT_SUPPORTED; + return deleteIpAddress( NTEContext ); } diff --git a/reactos/lib/iphlpapi/iphlpapi_private.h b/reactos/lib/iphlpapi/iphlpapi_private.h index 92b9be872b6..1d52a9f4605 100644 --- a/reactos/lib/iphlpapi/iphlpapi_private.h +++ b/reactos/lib/iphlpapi/iphlpapi_private.h @@ -82,6 +82,12 @@ typedef struct _IFInfo { IPAddrEntry ip_addr; } IFInfo; +typedef struct _IP_SET_DATA { + ULONG NteContext; + ULONG NewAddress; + ULONG NewNetmask; +} IP_SET_DATA, *PIP_SET_DATA; + typedef enum _IPHLPAddrType { IPAAddr, IPABcast, IPAMask, IFMtu, IFStatus } IPHLPAddrType;