diff options
Diffstat (limited to 'mDNSResponder/mDNSWindows/NSPTool/NSPTool.c')
-rw-r--r-- | mDNSResponder/mDNSWindows/NSPTool/NSPTool.c | 581 |
1 files changed, 581 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSWindows/NSPTool/NSPTool.c b/mDNSResponder/mDNSWindows/NSPTool/NSPTool.c new file mode 100644 index 00000000..f3052d16 --- /dev/null +++ b/mDNSResponder/mDNSWindows/NSPTool/NSPTool.c @@ -0,0 +1,581 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "CommonServices.h" +#include "DebugServices.h" + +#include <guiddef.h> +#include <ws2spi.h> + +//=========================================================================================================================== +// Prototypes +//=========================================================================================================================== + +int main( int argc, char *argv[] ); +DEBUG_LOCAL void Usage( void ); +DEBUG_LOCAL int ProcessArgs( int argc, char *argv[] ); +DEBUG_LOCAL OSStatus InstallNSP( const char *inName, const char *inGUID, const char *inPath ); +DEBUG_LOCAL OSStatus RemoveNSP( const char *inGUID ); +DEBUG_LOCAL OSStatus EnableNSP( const char *inGUID, BOOL inEnable ); +DEBUG_LOCAL OSStatus ListNameSpaces( void ); +DEBUG_LOCAL OSStatus ReorderNameSpaces( void ); + +DEBUG_LOCAL WCHAR * CharToWCharString( const char *inCharString, WCHAR *outWCharString ); +DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, char *outString ); +DEBUG_LOCAL OSStatus StringToGUID( const char *inCharString, GUID *outGUID ); + +DEBUG_LOCAL BOOL gToolQuietMode = FALSE; + +//=========================================================================================================================== +// main +//=========================================================================================================================== + +int main( int argc, char *argv[] ) +{ + OSStatus err; + + debug_initialize( kDebugOutputTypeMetaConsole ); + debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose ); + + err = ProcessArgs( argc, argv ); + return( (int) err ); +} + +//=========================================================================================================================== +// Usage +//=========================================================================================================================== + +DEBUG_LOCAL void Usage( void ) +{ + fprintf( stderr, "\n" ); + fprintf( stderr, "NSP Tool 1.0d1\n" ); + fprintf( stderr, " Name Space Provider Tool\n" ); + fprintf( stderr, "\n" ); + + fprintf( stderr, " -install <name> <guid> <path> - Installs a Name Space Provider\n" ); + fprintf( stderr, "\n" ); + fprintf( stderr, " <name> Name of the NSP\n" ); + fprintf( stderr, " <guid> GUID of the NSP\n" ); + fprintf( stderr, " <path> Path to the NSP file\n" ); + fprintf( stderr, "\n" ); + + fprintf( stderr, " -remove <guid> - Removes a Name Space Provider\n" ); + fprintf( stderr, "\n" ); + fprintf( stderr, " <guid> GUID of the NSP\n" ); + fprintf( stderr, "\n" ); + + fprintf( stderr, " -enable/-disable <guid> - Enables or Disables a Name Space Provider\n" ); + fprintf( stderr, "\n" ); + fprintf( stderr, " <guid> GUID of the NSP\n" ); + fprintf( stderr, "\n" ); + + fprintf( stderr, " -list - Lists Name Space Providers\n" ); + fprintf( stderr, " -reorder - Reorders Name Space Providers\n" ); + fprintf( stderr, " -q - Enable quiet mode\n" ); + fprintf( stderr, " -h[elp] - Help\n" ); + fprintf( stderr, "\n" ); +} + +//=========================================================================================================================== +// ProcessArgs +//=========================================================================================================================== + +DEBUG_LOCAL int ProcessArgs( int argc, char* argv[] ) +{ + OSStatus err; + int i; + const char * name; + const char * guid; + const char * path; + + if( argc <= 1 ) + { + Usage(); + err = 0; + goto exit; + } + for( i = 1; i < argc; ++i ) + { + if( strcmp( argv[ i ], "-install" ) == 0 ) + { + // Install + + if( argc <= ( i + 3 ) ) + { + fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] ); + Usage(); + err = kParamErr; + goto exit; + } + name = argv[ ++i ]; + guid = argv[ ++i ]; + path = argv[ ++i ]; + + if( *name == '\0' ) + { + name = "DotLocalNSP"; + } + if( *guid == '\0' ) + { + guid = "B600E6E9-553B-4a19-8696-335E5C896153"; + } + + err = InstallNSP( name, guid, path ); + require_noerr( err, exit ); + } + else if( strcmp( argv[ i ], "-remove" ) == 0 ) + { + // Remove + + if( argc <= ( i + 1 ) ) + { + fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] ); + Usage(); + err = kParamErr; + goto exit; + } + guid = argv[ ++i ]; + if( *guid == '\0' ) + { + guid = "B600E6E9-553B-4a19-8696-335E5C896153"; + } + + err = RemoveNSP( guid ); + require_noerr( err, exit ); + } + else if( ( strcmp( argv[ i ], "-enable" ) == 0 ) || + ( strcmp( argv[ i ], "-disable" ) == 0 ) ) + { + BOOL enable; + + // Enable/Disable + + enable = ( strcmp( argv[ i ], "-enable" ) == 0 ); + if( argc <= ( i + 1 ) ) + { + fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] ); + Usage(); + err = kParamErr; + goto exit; + } + guid = argv[ ++i ]; + + err = EnableNSP( guid, enable ); + require_noerr( err, exit ); + } + else if( strcmp( argv[ i ], "-list" ) == 0 ) + { + // List + + err = ListNameSpaces(); + require_noerr( err, exit ); + } + else if( strcmp( argv[ i ], "-reorder" ) == 0 ) + { + // Reorder + + err = ReorderNameSpaces(); + require_noerr( err, exit ); + } + else if( strcmp( argv[ i ], "-q" ) == 0 ) + { + gToolQuietMode = TRUE; + } + else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || + ( strcmp( argv[ i ], "-h" ) == 0 ) ) + { + // Help + + Usage(); + err = 0; + goto exit; + } + else + { + fprintf( stderr, "\n### ERROR: unknown argment: \"%s\"\n\n", argv[ i ] ); + Usage(); + err = kParamErr; + goto exit; + } + } + err = kNoErr; + +exit: + return( err ); +} + +#if 0 +#pragma mark - +#endif + +//=========================================================================================================================== +// InstallNSP +//=========================================================================================================================== + +OSStatus InstallNSP( const char *inName, const char *inGUID, const char *inPath ) +{ + OSStatus err; + size_t size; + WSADATA wsd; + WCHAR name[ 256 ]; + GUID guid; + WCHAR path[ MAX_PATH ]; + + require_action( inName && ( *inName != '\0' ), exit, err = kParamErr ); + require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr ); + require_action( inPath && ( *inPath != '\0' ), exit, err = kParamErr ); + + size = strlen( inName ); + require_action( size < sizeof_array( name ), exit, err = kSizeErr ); + CharToWCharString( inName, name ); + + err = StringToGUID( inGUID, &guid ); + require_noerr( err, exit ); + + size = strlen( inPath ); + require_action( size < sizeof_array( path ), exit, err = kSizeErr ); + CharToWCharString( inPath, path ); + + err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + + err = WSCInstallNameSpace( name, path, NS_DNS, 1, &guid ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + WSACleanup(); + require_noerr( err, exit ); + + if (!gToolQuietMode) + { + fprintf( stderr, "Installed NSP \"%s\" (%s) at %s\n", inName, inGUID, inPath ); + } + +exit: + if( err != kNoErr ) + { + fprintf( stderr, "### FAILED (%d) to install \"%s\" (%s) Name Space Provider at %s\n", err, inName, inGUID, inPath ); + } + return( err ); +} + +//=========================================================================================================================== +// RemoveNSP +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus RemoveNSP( const char *inGUID ) +{ + OSStatus err; + WSADATA wsd; + GUID guid; + + require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr ); + + err = StringToGUID( inGUID, &guid ); + require_noerr( err, exit ); + + err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + + err = WSCUnInstallNameSpace( &guid ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + WSACleanup(); + require_noerr( err, exit ); + + if (!gToolQuietMode) + { + fprintf( stderr, "Removed NSP %s\n", inGUID ); + } + +exit: + if( err != kNoErr ) + { + fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID ); + } + return( err ); +} + +//=========================================================================================================================== +// EnableNSP +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus EnableNSP( const char *inGUID, BOOL inEnable ) +{ + OSStatus err; + WSADATA wsd; + GUID guid; + + require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr ); + + err = StringToGUID( inGUID, &guid ); + require_noerr( err, exit ); + + err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + + err = WSCEnableNSProvider( &guid, inEnable ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + WSACleanup(); + require_noerr( err, exit ); + + if (!gToolQuietMode) + { + fprintf( stderr, "Removed NSP %s\n", inGUID ); + } + +exit: + if( err != kNoErr ) + { + fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID ); + } + return( err ); +} + +//=========================================================================================================================== +// ListNameSpaces +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus ListNameSpaces( void ) +{ + OSStatus err; + WSADATA wsd; + bool started; + int n; + int i; + DWORD size; + WSANAMESPACE_INFO * array; + char s[ 256 ]; + + array = NULL; + started = false; + + err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + started = true; + + // Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it. + + size = 0; + n = WSAEnumNameSpaceProviders( &size, NULL ); + err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); + require_action( err == WSAEFAULT, exit, err = kUnknownErr ); + + array = (WSANAMESPACE_INFO *) malloc( size ); + require_action( array, exit, err = kNoMemoryErr ); + + n = WSAEnumNameSpaceProviders( &size, array ); + err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); + require_noerr( err, exit ); + + fprintf( stdout, "\n" ); + for( i = 0; i < n; ++i ) + { + fprintf( stdout, "Name Space %d\n", i + 1 ); + fprintf( stdout, " NSProviderId: %s\n", GUIDtoString( &array[ i ].NSProviderId, s ) ); + fprintf( stdout, " dwNameSpace: %d\n", array[ i ].dwNameSpace ); + fprintf( stdout, " fActive: %s\n", array[ i ].fActive ? "YES" : "NO" ); + fprintf( stdout, " dwVersion: %d\n", array[ i ].dwVersion ); + fprintf( stdout, " lpszIdentifier: \"%s\"\n", array[ i ].lpszIdentifier ); + fprintf( stdout, "\n" ); + } + err = kNoErr; + +exit: + if( array ) + { + free( array ); + } + if( started ) + { + WSACleanup(); + } + if( err != kNoErr ) + { + fprintf( stderr, "### FAILED (%d) to list Name Space Providers\n", err ); + } + return( err ); +} + +//=========================================================================================================================== +// ReorderNameSpaces +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus ReorderNameSpaces( void ) +{ + OSStatus err; + WSADATA wsd; + bool started; + int n; + int i; + DWORD size; + WSANAMESPACE_INFO * array; + WCHAR name[ 256 ]; + WCHAR path[ MAX_PATH ]; + + array = NULL; + started = false; + + err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + started = true; + + // Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it. + + size = 0; + n = WSAEnumNameSpaceProviders( &size, NULL ); + err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); + require_action( err == WSAEFAULT, exit, err = kUnknownErr ); + + array = (WSANAMESPACE_INFO *) malloc( size ); + require_action( array, exit, err = kNoMemoryErr ); + + n = WSAEnumNameSpaceProviders( &size, array ); + err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); + require_noerr( err, exit ); + + // Find the "Tcpip" NSP. + + for( i = 0; i < n; ++i ) + { + if( strcmp( array[ i ].lpszIdentifier, "Tcpip" ) == 0 ) + { + break; + } + } + require_action( i < n, exit, err = kNotFoundErr ); + + // Uninstall it then re-install it to move it to the end. + + size = (DWORD) strlen( array[ i ].lpszIdentifier ); + require_action( size < sizeof_array( name ), exit, err = kSizeErr ); + CharToWCharString( array[ i ].lpszIdentifier, name ); + + size = (DWORD) strlen( "%SystemRoot%\\System32\\mswsock.dll" ); + require_action( size < sizeof_array( path ), exit, err = kSizeErr ); + CharToWCharString( "%SystemRoot%\\System32\\mswsock.dll", path ); + + err = WSCUnInstallNameSpace( &array[ i ].NSProviderId ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + + err = WSCInstallNameSpace( name, path, NS_DNS, array[ i ].dwVersion, &array[ i ].NSProviderId ); + err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); + require_noerr( err, exit ); + + // Success! + + fprintf( stderr, "Reordered \"Tcpip\" NSP to to the bottom of the NSP chain\n" ); + err = kNoErr; + +exit: + if( array ) + { + free( array ); + } + if( started ) + { + WSACleanup(); + } + if( err != kNoErr ) + { + fprintf( stderr, "### FAILED (%d) to reorder Name Space Providers\n", err ); + } + return( err ); +} + +#if 0 +#pragma mark - +#endif + +//=========================================================================================================================== +// CharToWCharString +//=========================================================================================================================== + +DEBUG_LOCAL WCHAR * CharToWCharString( const char *inCharString, WCHAR *outWCharString ) +{ + const char * src; + WCHAR * dst; + char c; + + check( inCharString ); + check( outWCharString ); + + src = inCharString; + dst = outWCharString; + do + { + c = *src++; + *dst++ = (WCHAR) c; + + } while( c != '\0' ); + + return( outWCharString ); +} + +//=========================================================================================================================== +// GUIDtoString +//=========================================================================================================================== + +DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, char *outString ) +{ + check( inGUID ); + check( outString ); + + sprintf( outString, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + inGUID->Data1, inGUID->Data2, inGUID->Data3, + inGUID->Data4[ 0 ], inGUID->Data4[ 1 ], inGUID->Data4[ 2 ], inGUID->Data4[ 3 ], + inGUID->Data4[ 4 ], inGUID->Data4[ 5 ], inGUID->Data4[ 6 ], inGUID->Data4[ 7 ] ); + return( outString ); +} + +//=========================================================================================================================== +// StringToGUID +//=========================================================================================================================== + +DEBUG_LOCAL OSStatus StringToGUID( const char *inCharString, GUID *outGUID ) +{ + OSStatus err; + int n; + unsigned int v[ 8 ]; + + check( inCharString ); + check( outGUID ); + + n = sscanf( inCharString, "%lX-%hX-%hX-%02X%02X-%02X%02X%02X%02X%02X%02X", + &outGUID->Data1, &outGUID->Data2, &outGUID->Data3, + &v[ 0 ], &v[ 1 ], &v[ 2 ], &v[ 3 ], &v[ 4 ], &v[ 5 ], &v[ 6 ], &v[ 7 ] ); + require_action( n == 11, exit, err = kFormatErr ); + + outGUID->Data4[ 0 ] = (unsigned char) v[ 0 ]; + outGUID->Data4[ 1 ] = (unsigned char) v[ 1 ]; + outGUID->Data4[ 2 ] = (unsigned char) v[ 2 ]; + outGUID->Data4[ 3 ] = (unsigned char) v[ 3 ]; + outGUID->Data4[ 4 ] = (unsigned char) v[ 4 ]; + outGUID->Data4[ 5 ] = (unsigned char) v[ 5 ]; + outGUID->Data4[ 6 ] = (unsigned char) v[ 6 ]; + outGUID->Data4[ 7 ] = (unsigned char) v[ 7 ]; + err = kNoErr; + +exit: + return( err ); +} |