mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
442 lines
9.9 KiB
442 lines
9.9 KiB
/*++
|
|
|
|
Module Name:
|
|
|
|
dgipxs.c
|
|
|
|
Abstract:
|
|
|
|
All IPX-specific code goes here.
|
|
This file is #included by winsock.c.
|
|
|
|
Author:
|
|
|
|
Jeff Roberts (jroberts) 3-Dec-1994
|
|
|
|
Revision History:
|
|
|
|
3-Dec-1994 jroberts
|
|
|
|
Created this module.
|
|
|
|
--*/
|
|
|
|
static char
|
|
HexDigits[16] =
|
|
{
|
|
'0', '1', '2', '3',
|
|
'4', '5', '6', '7',
|
|
'8', '9', 'a', 'b',
|
|
'c', 'd', 'e', 'f'
|
|
};
|
|
|
|
BOOL
|
|
register_name(
|
|
char *,
|
|
ADDRESS_TYPE *,
|
|
RPC_CHAR *
|
|
);
|
|
|
|
DWORD
|
|
set_service_wrapper(
|
|
char *unique_name,
|
|
ADDRESS_TYPE *netaddr,
|
|
DWORD reg
|
|
);
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
RegisterEndpoint(
|
|
IN void * pServerAddress,
|
|
IN RPC_CHAR * pEndpoint,
|
|
OUT PDG_SERVER_TRANS_ADDRESS * ppTransAddress,
|
|
OUT RPC_CHAR PAPI * NetworkAddress,
|
|
IN unsigned int NetworkAddressLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Registers an endpoint for sending and receiving.
|
|
|
|
Arguments:
|
|
|
|
pServerAddress - Pointer to the DG_ADDRESS object that this transport
|
|
address is to be associated with. This is a 'void *' instead of
|
|
a 'PDG_ADDRESS' because we don't want to include or link in all
|
|
sorts of garbage associated with DG_ADDRESS.
|
|
|
|
pEndpoint - name of the endpoint to create.
|
|
|
|
ppTransAddress - Where to place a pointer to the newly created transport
|
|
address structure.
|
|
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OUT_OF_MEMORY
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
{
|
|
RPC_STATUS Status = RPC_S_OK;
|
|
ADDRESS_TYPE Server;
|
|
char hostname[MAX_HOSTNAME_LEN];
|
|
int length = sizeof(Server);
|
|
SOCKET Socket;
|
|
UNICODE_STRING UnicodeHostName;
|
|
ANSI_STRING AsciiHostName;
|
|
struct ENDPOINT_INFO * pInfo;
|
|
|
|
if ( NetworkAddressLength < (2 * (NETADDR_LEN + 1)) )
|
|
return( RPC_P_NETWORK_ADDRESS_TOO_SMALL );
|
|
|
|
*ppTransAddress = (PDG_SERVER_TRANS_ADDRESS) CreateTransAddress(
|
|
pServerAddress,
|
|
pEndpoint,
|
|
&Status
|
|
);
|
|
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
pInfo = (struct ENDPOINT_INFO *) (*ppTransAddress)->pTsap;
|
|
if (getsockname( pInfo->Socket,
|
|
(struct sockaddr *) &Server,
|
|
&length ))
|
|
{
|
|
DeleteTransAddress( ppTransAddress );
|
|
return RPC_S_CANT_CREATE_ENDPOINT;
|
|
}
|
|
if (!register_name( hostname, &Server, pEndpoint ))
|
|
{
|
|
DeleteTransAddress( ppTransAddress );
|
|
return RPC_S_CANT_CREATE_ENDPOINT;
|
|
}
|
|
|
|
RtlInitAnsiString ( &AsciiHostName, hostname );
|
|
|
|
//
|
|
// Covert NetworkAddress to Unicode
|
|
//
|
|
RtlAnsiStringToUnicodeString ( &UnicodeHostName, &AsciiHostName, TRUE);
|
|
//
|
|
// Now copy it to where the caller said to
|
|
//
|
|
memcpy ( NetworkAddress, UnicodeHostName.Buffer,
|
|
UnicodeHostName.Length + sizeof (UNICODE_NULL));
|
|
|
|
//
|
|
// Free string overhead
|
|
//
|
|
RtlFreeUnicodeString ( &UnicodeHostName );
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
DeregisterEndpoint(
|
|
IN OUT PDG_SERVER_TRANS_ADDRESS * pServerTransAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deregisters an endpoint. This serves as a psuedo-destructor for a
|
|
DG_UDP_SERVER_TRANS_ADDRESS.
|
|
|
|
Arguments:
|
|
|
|
pServerTransAddress - transport address to delete.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(0 && "this fn is never used");
|
|
return RPC_S_INTERNAL_ERROR;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
CreateServerEndpoint(
|
|
IN char * pEndpoint,
|
|
IN void * pServerAddr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given an endpoint name make a sockaddr using 'this' host's hostname.
|
|
|
|
Arguments:
|
|
|
|
|
|
pTransAddress - Server's transport address information.
|
|
|
|
pNcaPacketHeader - Pointer to buffer to place incoming pkt into.
|
|
|
|
pDataLength - Number of bytes read in.
|
|
|
|
pEndpoint - Pointer to the server port num to forward to.
|
|
This is in string format.
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
<return from MapStatusCode>
|
|
|
|
Revision History:
|
|
Connie Hoppe (CLH) (connieh) 23-Feb-94 Created.
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
char * pCharServerName;
|
|
int Endpoint;
|
|
int EndpointLength;
|
|
int i;
|
|
int length;
|
|
|
|
ADDRESS_TYPE * pServerAddress = (ADDRESS_TYPE *) pServerAddr;
|
|
|
|
SOCKET dummy;
|
|
int zero_success;
|
|
ADDRESS_TYPE dummy_address;
|
|
|
|
//
|
|
// convert the endpoint to a number.
|
|
//
|
|
EndpointLength = strlen(pEndpoint);
|
|
|
|
for (i=0, Endpoint=0 ; i< EndpointLength ; i++)
|
|
{
|
|
if ( ((char)pEndpoint[i] >= '0') && ((char)pEndpoint[i] <= '9'))
|
|
{
|
|
Endpoint *= 10;
|
|
Endpoint += (char)pEndpoint[i]-'0';
|
|
}
|
|
}
|
|
|
|
pServerAddress->s.sa_family = ADDRESS_FAMILY;
|
|
pServerAddress->s.sa_socket = htons((unsigned short) Endpoint);
|
|
|
|
memset( &dummy_address, 0, sizeof(dummy_address) );
|
|
dummy_address.s.sa_family = ADDRESS_FAMILY;
|
|
zero_success = 0;
|
|
dummy = socket( ADDRESS_FAMILY, SOCK_DGRAM, PROTOCOL );
|
|
if (dummy != INVALID_SOCKET)
|
|
{
|
|
length = sizeof ( *pServerAddress );
|
|
zero_success = bind( dummy, &dummy_address.unused,
|
|
length );
|
|
if (zero_success == 0)
|
|
zero_success = getsockname ( dummy, (struct sockaddr *) pServerAddress,
|
|
&length );
|
|
closesocket( dummy );
|
|
pServerAddress->s.sa_socket = htons((unsigned short) Endpoint);
|
|
}
|
|
else
|
|
zero_success = 1;
|
|
|
|
if (zero_success != 0)
|
|
{
|
|
return RPC_S_CANT_CREATE_ENDPOINT;
|
|
}
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
QueryClientAddress
|
|
(
|
|
IN void * pOriginalEndpoint,
|
|
OUT RPC_CHAR * pClientAddress
|
|
)
|
|
{
|
|
int i;
|
|
RPC_CHAR * pString;
|
|
SOCKADDR_IPX * pSockAddr = (SOCKADDR_IPX *) pOriginalEndpoint;
|
|
|
|
//
|
|
// address looks like "~11111111222222222222".
|
|
//
|
|
pString = pClientAddress;
|
|
*(pString++) = '~';
|
|
|
|
for (i=0; i < 4; i++)
|
|
{
|
|
unsigned char Byte = pSockAddr->sa_netnum[i];
|
|
*(pString++) = HexDigits[Byte / 16];
|
|
*(pString++) = HexDigits[Byte % 16];
|
|
}
|
|
|
|
for (i=0; i < 6; i++)
|
|
{
|
|
unsigned char Byte = pSockAddr->sa_nodenum[i];
|
|
*(pString++) = HexDigits[Byte / 16];
|
|
*(pString++) = HexDigits[Byte % 16];
|
|
}
|
|
|
|
*pString = '\0';
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
QueryClientEndpoint
|
|
(
|
|
IN void * pOriginalEndpoint,
|
|
OUT RPC_CHAR * pClientEndpoint
|
|
)
|
|
{
|
|
SOCKADDR_IPX * pSockAddr = (SOCKADDR_IPX *) pOriginalEndpoint;
|
|
unsigned NativeSocket = ntohs(pSockAddr->sa_socket);
|
|
char AnsiBuffer[6];
|
|
|
|
char * pAnsi = AnsiBuffer;
|
|
RPC_CHAR * pUni = pClientEndpoint;
|
|
|
|
//
|
|
// Convert endpoint to an ASCII string, and thence to Unicode.
|
|
//
|
|
_ultoa(NativeSocket, AnsiBuffer, 10);
|
|
|
|
do
|
|
{
|
|
*pUni++ = *pAnsi;
|
|
}
|
|
while ( *pAnsi++ );
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
|
|
int
|
|
SetTransportSpecificSocketOptions(
|
|
SOCKET Socket
|
|
)
|
|
{
|
|
unsigned PacketType;
|
|
|
|
PacketType = 4;
|
|
if (setsockopt(
|
|
Socket,
|
|
NSPROTO_IPX,
|
|
IPX_PTYPE,
|
|
(char *) &PacketType,
|
|
sizeof(PacketType)) != 0)
|
|
{
|
|
return WSAGetLastError();
|
|
}
|
|
}
|
|
|
|
GUID SERVICE_TYPE = { 0x000b0640, 0, 0, { 0xC0,0,0,0,0,0,0,0x46 } };
|
|
|
|
|
|
DWORD set_service_wrapper( char *unique_name, ADDRESS_TYPE *netaddr,
|
|
DWORD reg )
|
|
{
|
|
SERVICE_INFOA info;
|
|
DWORD flags = 0;
|
|
SERVICE_ADDRESSES addresses;
|
|
DWORD result;
|
|
|
|
// Fill in the service info structure.
|
|
info.lpServiceType = &SERVICE_TYPE;
|
|
info.lpServiceName = unique_name;
|
|
info.lpComment = "RPC Service";
|
|
info.lpLocale = "The west pole";
|
|
info.dwDisplayHint = 0;
|
|
info.dwVersion = 0;
|
|
info.dwTime = 0;
|
|
info.lpMachineName = unique_name;
|
|
info.lpServiceAddress = &addresses;
|
|
info.ServiceSpecificInfo.cbSize = 0;
|
|
|
|
// Fill in the service addresses structure.
|
|
addresses.dwAddressCount = 1;
|
|
addresses.Addresses[0].dwAddressType = AF_IPX;
|
|
addresses.Addresses[0].dwPrincipalLength = 0;
|
|
addresses.Addresses[0].dwAddressLength = sizeof(ADDRESS_TYPE);
|
|
addresses.Addresses[0].lpAddress = (BYTE *) netaddr;
|
|
addresses.Addresses[0].lpPrincipal = NULL;
|
|
|
|
// Set the service.
|
|
result = SetServiceA( NS_SAP, reg, 0, &info, NULL, &flags );
|
|
if (result == -1)
|
|
result = WSAGetLastError();
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL register_name(
|
|
char *string,
|
|
ADDRESS_TYPE *netaddr,
|
|
RPC_CHAR *endpoint )
|
|
{
|
|
DWORD i;
|
|
unsigned char c;
|
|
DWORD result;
|
|
DWORD length;
|
|
char machine_name[MAX_COMPUTERNAME_LENGTH+1];
|
|
|
|
// Get the computer address. Start with the tilde.
|
|
string[0] = '~';
|
|
|
|
/* Convert the network number. */
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
c = netaddr->s.sa_netnum[i];
|
|
if (c < 0xA0)
|
|
string[2*i+1] = ((c & 0xF0) >> 4) + '0';
|
|
else
|
|
string[2*i+1] = ((c & 0xF0) >> 4) + 'A' - 10;
|
|
if ((c & 0x0F) < 0x0A)
|
|
string[2*i+2] = (c & 0x0F) + '0';
|
|
else
|
|
string[2*i+2] = (c & 0x0F) + 'A' - 10;
|
|
}
|
|
|
|
/* Convert the node number. */
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
c = netaddr->s.sa_nodenum[i];
|
|
if (c < 0xA0)
|
|
string[2*i+9] = ((c & 0xF0) >> 4) + '0';
|
|
else
|
|
string[2*i+9] = ((c & 0xF0) >> 4) + 'A' - 10;
|
|
if ((c & 0x0F) < 0x0A)
|
|
string[2*i+10] = (c & 0x0F) + '0';
|
|
else
|
|
string[2*i+10] = (c & 0x0F) + 'A' - 10;
|
|
}
|
|
|
|
/* Append a null. */
|
|
string[21] = '\0';
|
|
|
|
// Register the machine name.
|
|
length = MAX_COMPUTERNAME_LENGTH+1;
|
|
if (!GetComputerName( machine_name, &length ))
|
|
return FALSE;
|
|
result = set_service_wrapper( machine_name, netaddr, SERVICE_REGISTER );
|
|
return (result == 0 || result == ERROR_ALREADY_REGISTERED);
|
|
}
|
|
|
|
|