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.
445 lines
8.1 KiB
445 lines
8.1 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
GetServ.c
|
|
|
|
Abstract:
|
|
|
|
This module contains support for the getprotobyY WinSock APIs.
|
|
|
|
Author:
|
|
|
|
David Treadwell (davidtr) 29-Jun-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "winsockp.h"
|
|
|
|
#define SERVDB ACCESS_THREAD_DATA( SERVDB, GETSERV )
|
|
#define servf ACCESS_THREAD_DATA( servf, GETSERV )
|
|
#define line ACCESS_THREAD_DATA( line, GETSERV )
|
|
#define serv ACCESS_THREAD_DATA( serv, GETSERV )
|
|
#define serv_aliases ACCESS_THREAD_DATA( serv_aliases, GETSERV )
|
|
#define stayopen ACCESS_THREAD_DATA( stayopen, GETSERV )
|
|
|
|
static char *any();
|
|
|
|
struct servent *
|
|
_pgetservebyport(
|
|
IN const int port,
|
|
IN const char *name
|
|
);
|
|
|
|
struct servent *
|
|
_pgetservebyname(
|
|
IN const char *name,
|
|
IN const char *proto
|
|
);
|
|
|
|
DWORD
|
|
BytesInServent (
|
|
IN PSERVENT Servent
|
|
);
|
|
|
|
DWORD
|
|
CopyServentToBuffer (
|
|
IN char FAR *Buffer,
|
|
IN int BufferLength,
|
|
IN PSERVENT Servent
|
|
);
|
|
|
|
|
|
void
|
|
setservent (
|
|
int f
|
|
)
|
|
{
|
|
if (servf == NULL) {
|
|
servf = SockOpenNetworkDataBase("services", SERVDB, SERVDB_SIZE, "r");
|
|
} else {
|
|
rewind(servf);
|
|
}
|
|
|
|
stayopen |= f;
|
|
|
|
} // setservent
|
|
|
|
|
|
void
|
|
endservent (
|
|
void
|
|
)
|
|
{
|
|
if (servf && !stayopen) {
|
|
fclose(servf);
|
|
servf = NULL;
|
|
}
|
|
|
|
} // endservent
|
|
|
|
|
|
struct servent *
|
|
getservent (
|
|
void
|
|
)
|
|
{
|
|
char *p;
|
|
register char *cp, **q;
|
|
|
|
if (servf == NULL && (servf = fopen(SERVDB, "r" )) == NULL) {
|
|
IF_DEBUG(GETXBYY) {
|
|
WS_PRINT(("\tERROR: cannot open services database file %s\n",
|
|
SERVDB));
|
|
}
|
|
return (NULL);
|
|
}
|
|
|
|
again:
|
|
|
|
if ((p = fgets(line, BUFSIZ, servf)) == NULL) {
|
|
return (NULL);
|
|
}
|
|
|
|
if (*p == '#') {
|
|
goto again;
|
|
}
|
|
|
|
cp = any(p, "#\n");
|
|
|
|
if (cp == NULL) {
|
|
goto again;
|
|
}
|
|
|
|
*cp = '\0';
|
|
serv.s_name = p;
|
|
p = any(p, " \t");
|
|
|
|
if (p == NULL) {
|
|
goto again;
|
|
}
|
|
|
|
*p++ = '\0';
|
|
|
|
while (*p == ' ' || *p == '\t') {
|
|
p++;
|
|
}
|
|
|
|
cp = any(p, ",/");
|
|
|
|
if (cp == NULL) {
|
|
goto again;
|
|
}
|
|
|
|
*cp++ = '\0';
|
|
serv.s_port = htons((USHORT)atoi(p));
|
|
serv.s_proto = cp;
|
|
q = serv.s_aliases = serv_aliases;
|
|
cp = any(cp, " \t");
|
|
|
|
if (cp != NULL) {
|
|
*cp++ = '\0';
|
|
}
|
|
|
|
while (cp && *cp) {
|
|
|
|
if (*cp == ' ' || *cp == '\t') {
|
|
cp++;
|
|
continue;
|
|
}
|
|
|
|
if (q < &serv_aliases[MAXALIASES - 1]) {
|
|
*q++ = cp;
|
|
}
|
|
|
|
cp = any(cp, " \t");
|
|
|
|
if (cp != NULL) {
|
|
*cp++ = '\0';
|
|
}
|
|
}
|
|
|
|
*q = NULL;
|
|
return (&serv);
|
|
|
|
} // getservent
|
|
|
|
static char *
|
|
any (
|
|
IN char *cp,
|
|
IN char *match
|
|
)
|
|
{
|
|
register char *mp, c;
|
|
|
|
while (c = *cp) {
|
|
|
|
for (mp = match; *mp; mp++) {
|
|
if (*mp == c) {
|
|
return (cp);
|
|
}
|
|
}
|
|
|
|
cp++;
|
|
}
|
|
|
|
return ((char *)0);
|
|
|
|
} // any
|
|
|
|
|
|
|
|
struct servent *
|
|
_pgetservebyname(
|
|
IN const char *name,
|
|
IN const char *proto
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Internal form of above
|
|
--*/
|
|
{
|
|
register struct servent *p;
|
|
register char **cp;
|
|
|
|
WS_ENTER( "GETXBYYSP_getservbyname", (PVOID)name, (PVOID)proto, NULL, NULL );
|
|
|
|
if ( !SockEnterApi( FALSE, TRUE, TRUE ) ) {
|
|
WS_EXIT( "GETXBYYSP_getservbyname", 0, TRUE );
|
|
return NULL;
|
|
}
|
|
|
|
setservent(0);
|
|
|
|
while (p = getservent()) {
|
|
|
|
if (_stricmp(name, p->s_name) == 0) {
|
|
goto gotname;
|
|
}
|
|
|
|
for (cp = p->s_aliases; *cp; cp++) {
|
|
if (_stricmp(name, *cp) == 0) {
|
|
goto gotname;
|
|
}
|
|
}
|
|
|
|
continue;
|
|
|
|
gotname:
|
|
if (proto == 0 || _stricmp(p->s_proto, proto) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
endservent();
|
|
|
|
SockThreadProcessingGetXByY = FALSE;
|
|
|
|
if ( p == NULL ) {
|
|
SetLastError( WSANO_DATA );
|
|
}
|
|
|
|
WS_EXIT( "GETXBYYSP_getservbyname", (INT)p, FALSE );
|
|
return (p);
|
|
}
|
|
|
|
//
|
|
// internal form of above
|
|
//
|
|
struct servent *
|
|
_pgetservebyport(
|
|
IN const int port,
|
|
IN const char *proto
|
|
)
|
|
{
|
|
register struct servent *p;
|
|
|
|
WS_ENTER( "GETXBYYSP_getservbyport", (PVOID)port, (PVOID)proto, NULL, NULL );
|
|
|
|
if ( !SockEnterApi( FALSE, TRUE, TRUE ) ) {
|
|
WS_EXIT( "GETXBYYSP_getservbyport", 0, TRUE );
|
|
return NULL;
|
|
}
|
|
|
|
setservent(0);
|
|
|
|
while (p = getservent()) {
|
|
|
|
if ((unsigned short)p->s_port != (unsigned short)port) {
|
|
continue;
|
|
}
|
|
|
|
if (proto == 0 || _stricmp(p->s_proto, proto) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
endservent();
|
|
|
|
SockThreadProcessingGetXByY = FALSE;
|
|
|
|
if ( p == NULL ) {
|
|
SetLastError( WSANO_DATA );
|
|
}
|
|
|
|
WS_EXIT( "GETXBYYSP_getservbyport", (INT)p, FALSE );
|
|
return (p);
|
|
|
|
} // GETXBYYSP_getservbyport
|
|
|
|
|
|
|
|
DWORD
|
|
CopyServentToBuffer (
|
|
IN char FAR *Buffer,
|
|
IN int BufferLength,
|
|
IN PSERVENT Servent
|
|
)
|
|
{
|
|
DWORD requiredBufferLength;
|
|
DWORD bytesFilled;
|
|
PCHAR currentLocation = Buffer;
|
|
DWORD aliasCount;
|
|
DWORD i;
|
|
PSERVENT outputServent = (PSERVENT)Buffer;
|
|
|
|
//
|
|
// Determine how many bytes are needed to fully copy the structure.
|
|
//
|
|
|
|
requiredBufferLength = BytesInServent( Servent );
|
|
|
|
//
|
|
// Zero the user buffer.
|
|
//
|
|
|
|
if ( (DWORD)BufferLength > requiredBufferLength ) {
|
|
RtlZeroMemory( Buffer, requiredBufferLength );
|
|
} else {
|
|
RtlZeroMemory( Buffer, BufferLength );
|
|
}
|
|
|
|
//
|
|
// Copy over the servent structure if it fits.
|
|
//
|
|
|
|
bytesFilled = sizeof(*Servent);
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
RtlCopyMemory( currentLocation, Servent, sizeof(*Servent) );
|
|
currentLocation = Buffer + bytesFilled;
|
|
|
|
outputServent->s_name = NULL;
|
|
outputServent->s_aliases = NULL;
|
|
outputServent->s_proto = NULL;
|
|
|
|
//
|
|
// Count the service's aliases and set up an array to hold pointers to
|
|
// them.
|
|
//
|
|
|
|
for ( aliasCount = 0;
|
|
Servent->s_aliases[aliasCount] != NULL;
|
|
aliasCount++ );
|
|
|
|
bytesFilled += (aliasCount+1) * sizeof(char FAR *);
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
Servent->s_aliases = NULL;
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
outputServent->s_aliases = (char FAR * FAR *)currentLocation;
|
|
currentLocation = Buffer + bytesFilled;
|
|
|
|
//
|
|
// Copy the service name if it fits.
|
|
//
|
|
|
|
bytesFilled += strlen( Servent->s_name ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
outputServent->s_name = currentLocation;
|
|
|
|
RtlCopyMemory( currentLocation, Servent->s_name, strlen( Servent->s_name ) + 1 );
|
|
currentLocation = Buffer + bytesFilled;
|
|
|
|
//
|
|
// Copy the protocol name if it fits.
|
|
//
|
|
|
|
bytesFilled += strlen( Servent->s_proto ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
outputServent->s_proto = currentLocation;
|
|
|
|
RtlCopyMemory( currentLocation, Servent->s_proto, strlen( Servent->s_proto ) + 1 );
|
|
currentLocation = Buffer + bytesFilled;
|
|
|
|
//
|
|
// Start filling in aliases.
|
|
//
|
|
|
|
for ( i = 0; i < aliasCount; i++ ) {
|
|
|
|
bytesFilled += strlen( Servent->s_aliases[i] ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
outputServent->s_aliases[i] = NULL;
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
outputServent->s_aliases[i] = currentLocation;
|
|
|
|
RtlCopyMemory(
|
|
currentLocation,
|
|
Servent->s_aliases[i],
|
|
strlen( Servent->s_aliases[i] ) + 1
|
|
);
|
|
|
|
currentLocation = Buffer + bytesFilled;
|
|
}
|
|
|
|
outputServent->s_aliases[i] = NULL;
|
|
|
|
return requiredBufferLength;
|
|
|
|
} // CopyServentToBuffer
|
|
|
|
|
|
DWORD
|
|
BytesInServent (
|
|
IN PSERVENT Servent
|
|
)
|
|
{
|
|
DWORD total;
|
|
int i;
|
|
|
|
total = sizeof(SERVENT);
|
|
total += strlen( Servent->s_name ) + 1;
|
|
total += strlen( Servent->s_proto ) + 1;
|
|
total += sizeof(char *);
|
|
|
|
for ( i = 0; Servent->s_aliases[i] != NULL; i++ ) {
|
|
total += strlen( Servent->s_aliases[i] ) + 1 + sizeof(char *);
|
|
}
|
|
|
|
return total;
|
|
|
|
} // BytesInServent
|
|
|
|
|
|
|