]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSWindows/NSPTool/NSPTool.c
mDNSResponder-878.260.1.tar.gz
[apple/mdnsresponder.git] / mDNSWindows / NSPTool / NSPTool.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20
21 #include "CommonServices.h"
22 #include "DebugServices.h"
23
24 #include <guiddef.h>
25 #include <ws2spi.h>
26
27 //===========================================================================================================================
28 // Prototypes
29 //===========================================================================================================================
30
31 int main( int argc, char *argv[] );
32 DEBUG_LOCAL void Usage( void );
33 DEBUG_LOCAL int ProcessArgs( int argc, char *argv[] );
34 DEBUG_LOCAL OSStatus InstallNSP( const char *inName, const char *inGUID, const char *inPath );
35 DEBUG_LOCAL OSStatus RemoveNSP( const char *inGUID );
36 DEBUG_LOCAL OSStatus EnableNSP( const char *inGUID, BOOL inEnable );
37 DEBUG_LOCAL OSStatus ListNameSpaces( void );
38 DEBUG_LOCAL OSStatus ReorderNameSpaces( void );
39
40 DEBUG_LOCAL WCHAR * CharToWCharString( const char *inCharString, WCHAR *outWCharString );
41 DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, size_t inLen, char *outString );
42 DEBUG_LOCAL OSStatus StringToGUID( const char *inCharString, GUID *outGUID );
43
44 DEBUG_LOCAL BOOL gToolQuietMode = FALSE;
45
46 //===========================================================================================================================
47 // main
48 //===========================================================================================================================
49
50 int main( int argc, char *argv[] )
51 {
52 OSStatus err;
53
54 debug_initialize( kDebugOutputTypeMetaConsole );
55 debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
56
57 err = ProcessArgs( argc, argv );
58 return( (int) err );
59 }
60
61 //===========================================================================================================================
62 // Usage
63 //===========================================================================================================================
64
65 DEBUG_LOCAL void Usage( void )
66 {
67 fprintf( stderr, "\n" );
68 fprintf( stderr, "NSP Tool 1.0d1\n" );
69 fprintf( stderr, " Name Space Provider Tool\n" );
70 fprintf( stderr, "\n" );
71
72 fprintf( stderr, " -install <name> <guid> <path> - Installs a Name Space Provider\n" );
73 fprintf( stderr, "\n" );
74 fprintf( stderr, " <name> Name of the NSP\n" );
75 fprintf( stderr, " <guid> GUID of the NSP\n" );
76 fprintf( stderr, " <path> Path to the NSP file\n" );
77 fprintf( stderr, "\n" );
78
79 fprintf( stderr, " -remove <guid> - Removes a Name Space Provider\n" );
80 fprintf( stderr, "\n" );
81 fprintf( stderr, " <guid> GUID of the NSP\n" );
82 fprintf( stderr, "\n" );
83
84 fprintf( stderr, " -enable/-disable <guid> - Enables or Disables a Name Space Provider\n" );
85 fprintf( stderr, "\n" );
86 fprintf( stderr, " <guid> GUID of the NSP\n" );
87 fprintf( stderr, "\n" );
88
89 fprintf( stderr, " -list - Lists Name Space Providers\n" );
90 fprintf( stderr, " -reorder - Reorders Name Space Providers\n" );
91 fprintf( stderr, " -q - Enable quiet mode\n" );
92 fprintf( stderr, " -h[elp] - Help\n" );
93 fprintf( stderr, "\n" );
94 }
95
96 //===========================================================================================================================
97 // ProcessArgs
98 //===========================================================================================================================
99
100 DEBUG_LOCAL int ProcessArgs( int argc, char* argv[] )
101 {
102 OSStatus err;
103 int i;
104 const char * name;
105 const char * guid;
106 const char * path;
107
108 if( argc <= 1 )
109 {
110 Usage();
111 err = 0;
112 goto exit;
113 }
114 for( i = 1; i < argc; ++i )
115 {
116 if( strcmp( argv[ i ], "-install" ) == 0 )
117 {
118 // Install
119
120 if( argc <= ( i + 3 ) )
121 {
122 fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] );
123 Usage();
124 err = kParamErr;
125 goto exit;
126 }
127 name = argv[ ++i ];
128 guid = argv[ ++i ];
129 path = argv[ ++i ];
130
131 if( *name == '\0' )
132 {
133 name = "DotLocalNSP";
134 }
135 if( *guid == '\0' )
136 {
137 guid = "B600E6E9-553B-4a19-8696-335E5C896153";
138 }
139
140 err = InstallNSP( name, guid, path );
141 require_noerr( err, exit );
142 }
143 else if( strcmp( argv[ i ], "-remove" ) == 0 )
144 {
145 // Remove
146
147 if( argc <= ( i + 1 ) )
148 {
149 fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] );
150 Usage();
151 err = kParamErr;
152 goto exit;
153 }
154 guid = argv[ ++i ];
155 if( *guid == '\0' )
156 {
157 guid = "B600E6E9-553B-4a19-8696-335E5C896153";
158 }
159
160 err = RemoveNSP( guid );
161 require_noerr( err, exit );
162 }
163 else if( ( strcmp( argv[ i ], "-enable" ) == 0 ) ||
164 ( strcmp( argv[ i ], "-disable" ) == 0 ) )
165 {
166 BOOL enable;
167
168 // Enable/Disable
169
170 enable = ( strcmp( argv[ i ], "-enable" ) == 0 );
171 if( argc <= ( i + 1 ) )
172 {
173 fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] );
174 Usage();
175 err = kParamErr;
176 goto exit;
177 }
178 guid = argv[ ++i ];
179
180 err = EnableNSP( guid, enable );
181 require_noerr( err, exit );
182 }
183 else if( strcmp( argv[ i ], "-list" ) == 0 )
184 {
185 // List
186
187 err = ListNameSpaces();
188 require_noerr( err, exit );
189 }
190 else if( strcmp( argv[ i ], "-reorder" ) == 0 )
191 {
192 // Reorder
193
194 err = ReorderNameSpaces();
195 require_noerr( err, exit );
196 }
197 else if( strcmp( argv[ i ], "-q" ) == 0 )
198 {
199 gToolQuietMode = TRUE;
200 }
201 else if( ( strcmp( argv[ i ], "-help" ) == 0 ) ||
202 ( strcmp( argv[ i ], "-h" ) == 0 ) )
203 {
204 // Help
205
206 Usage();
207 err = 0;
208 goto exit;
209 }
210 else
211 {
212 fprintf( stderr, "\n### ERROR: unknown argment: \"%s\"\n\n", argv[ i ] );
213 Usage();
214 err = kParamErr;
215 goto exit;
216 }
217 }
218 err = kNoErr;
219
220 exit:
221 return( err );
222 }
223
224 #if 0
225 #pragma mark -
226 #endif
227
228 //===========================================================================================================================
229 // InstallNSP
230 //===========================================================================================================================
231
232 OSStatus InstallNSP( const char *inName, const char *inGUID, const char *inPath )
233 {
234 OSStatus err;
235 size_t size;
236 WSADATA wsd;
237 WCHAR name[ 256 ];
238 GUID guid;
239 WCHAR path[ MAX_PATH ];
240
241 require_action( inName && ( *inName != '\0' ), exit, err = kParamErr );
242 require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr );
243 require_action( inPath && ( *inPath != '\0' ), exit, err = kParamErr );
244
245 size = strlen( inName );
246 require_action( size < sizeof_array( name ), exit, err = kSizeErr );
247 CharToWCharString( inName, name );
248
249 err = StringToGUID( inGUID, &guid );
250 require_noerr( err, exit );
251
252 size = strlen( inPath );
253 require_action( size < sizeof_array( path ), exit, err = kSizeErr );
254 CharToWCharString( inPath, path );
255
256 err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
257 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
258 require_noerr( err, exit );
259
260 err = WSCInstallNameSpace( name, path, NS_DNS, 1, &guid );
261 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
262 WSACleanup();
263 require_noerr( err, exit );
264
265 if (!gToolQuietMode)
266 {
267 fprintf( stderr, "Installed NSP \"%s\" (%s) at %s\n", inName, inGUID, inPath );
268 }
269
270 exit:
271 if( err != kNoErr )
272 {
273 fprintf( stderr, "### FAILED (%d) to install \"%s\" (%s) Name Space Provider at %s\n", err, inName, inGUID, inPath );
274 }
275 return( err );
276 }
277
278 //===========================================================================================================================
279 // RemoveNSP
280 //===========================================================================================================================
281
282 DEBUG_LOCAL OSStatus RemoveNSP( const char *inGUID )
283 {
284 OSStatus err;
285 WSADATA wsd;
286 GUID guid;
287
288 require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr );
289
290 err = StringToGUID( inGUID, &guid );
291 require_noerr( err, exit );
292
293 err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
294 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
295 require_noerr( err, exit );
296
297 err = WSCUnInstallNameSpace( &guid );
298 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
299 WSACleanup();
300 require_noerr( err, exit );
301
302 if (!gToolQuietMode)
303 {
304 fprintf( stderr, "Removed NSP %s\n", inGUID );
305 }
306
307 exit:
308 if( err != kNoErr )
309 {
310 fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID );
311 }
312 return( err );
313 }
314
315 //===========================================================================================================================
316 // EnableNSP
317 //===========================================================================================================================
318
319 DEBUG_LOCAL OSStatus EnableNSP( const char *inGUID, BOOL inEnable )
320 {
321 OSStatus err;
322 WSADATA wsd;
323 GUID guid;
324
325 require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr );
326
327 err = StringToGUID( inGUID, &guid );
328 require_noerr( err, exit );
329
330 err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
331 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
332 require_noerr( err, exit );
333
334 err = WSCEnableNSProvider( &guid, inEnable );
335 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
336 WSACleanup();
337 require_noerr( err, exit );
338
339 if (!gToolQuietMode)
340 {
341 fprintf( stderr, "Removed NSP %s\n", inGUID );
342 }
343
344 exit:
345 if( err != kNoErr )
346 {
347 fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID );
348 }
349 return( err );
350 }
351
352 //===========================================================================================================================
353 // ListNameSpaces
354 //===========================================================================================================================
355
356 DEBUG_LOCAL OSStatus ListNameSpaces( void )
357 {
358 OSStatus err;
359 WSADATA wsd;
360 bool started;
361 int n;
362 int i;
363 DWORD size;
364 WSANAMESPACE_INFO * array;
365 char s[ 256 ];
366
367 array = NULL;
368 started = false;
369
370 err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
371 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
372 require_noerr( err, exit );
373 started = true;
374
375 // Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it.
376
377 size = 0;
378 n = WSAEnumNameSpaceProviders( &size, NULL );
379 err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
380 require_action( err == WSAEFAULT, exit, err = kUnknownErr );
381
382 array = (WSANAMESPACE_INFO *) malloc( size );
383 require_action( array, exit, err = kNoMemoryErr );
384
385 n = WSAEnumNameSpaceProviders( &size, array );
386 err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
387 require_noerr( err, exit );
388
389 fprintf( stdout, "\n" );
390 for( i = 0; i < n; ++i )
391 {
392 fprintf( stdout, "Name Space %d\n", i + 1 );
393 fprintf( stdout, " NSProviderId: %s\n", GUIDtoString( &array[ i ].NSProviderId, sizeof( s ), s ) );
394 fprintf( stdout, " dwNameSpace: %d\n", array[ i ].dwNameSpace );
395 fprintf( stdout, " fActive: %s\n", array[ i ].fActive ? "YES" : "NO" );
396 fprintf( stdout, " dwVersion: %d\n", array[ i ].dwVersion );
397 fprintf( stdout, " lpszIdentifier: \"%s\"\n", array[ i ].lpszIdentifier );
398 fprintf( stdout, "\n" );
399 }
400 err = kNoErr;
401
402 exit:
403 if( array )
404 {
405 free( array );
406 }
407 if( started )
408 {
409 WSACleanup();
410 }
411 if( err != kNoErr )
412 {
413 fprintf( stderr, "### FAILED (%d) to list Name Space Providers\n", err );
414 }
415 return( err );
416 }
417
418 //===========================================================================================================================
419 // ReorderNameSpaces
420 //===========================================================================================================================
421
422 DEBUG_LOCAL OSStatus ReorderNameSpaces( void )
423 {
424 OSStatus err;
425 WSADATA wsd;
426 bool started;
427 int n;
428 int i;
429 DWORD size;
430 WSANAMESPACE_INFO * array;
431 WCHAR name[ 256 ];
432 WCHAR path[ MAX_PATH ];
433
434 array = NULL;
435 started = false;
436
437 err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
438 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
439 require_noerr( err, exit );
440 started = true;
441
442 // Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it.
443
444 size = 0;
445 n = WSAEnumNameSpaceProviders( &size, NULL );
446 err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
447 require_action( err == WSAEFAULT, exit, err = kUnknownErr );
448
449 array = (WSANAMESPACE_INFO *) malloc( size );
450 require_action( array, exit, err = kNoMemoryErr );
451
452 n = WSAEnumNameSpaceProviders( &size, array );
453 err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
454 require_noerr( err, exit );
455
456 // Find the "Tcpip" NSP.
457
458 for( i = 0; i < n; ++i )
459 {
460 if( strcmp( array[ i ].lpszIdentifier, "Tcpip" ) == 0 )
461 {
462 break;
463 }
464 }
465 require_action( i < n, exit, err = kNotFoundErr );
466
467 // Uninstall it then re-install it to move it to the end.
468
469 size = (DWORD) strlen( array[ i ].lpszIdentifier );
470 require_action( size < sizeof_array( name ), exit, err = kSizeErr );
471 CharToWCharString( array[ i ].lpszIdentifier, name );
472
473 size = (DWORD) strlen( "%SystemRoot%\\System32\\mswsock.dll" );
474 require_action( size < sizeof_array( path ), exit, err = kSizeErr );
475 CharToWCharString( "%SystemRoot%\\System32\\mswsock.dll", path );
476
477 err = WSCUnInstallNameSpace( &array[ i ].NSProviderId );
478 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
479 require_noerr( err, exit );
480
481 err = WSCInstallNameSpace( name, path, NS_DNS, array[ i ].dwVersion, &array[ i ].NSProviderId );
482 err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
483 require_noerr( err, exit );
484
485 // Success!
486
487 fprintf( stderr, "Reordered \"Tcpip\" NSP to to the bottom of the NSP chain\n" );
488 err = kNoErr;
489
490 exit:
491 if( array )
492 {
493 free( array );
494 }
495 if( started )
496 {
497 WSACleanup();
498 }
499 if( err != kNoErr )
500 {
501 fprintf( stderr, "### FAILED (%d) to reorder Name Space Providers\n", err );
502 }
503 return( err );
504 }
505
506 #if 0
507 #pragma mark -
508 #endif
509
510 //===========================================================================================================================
511 // CharToWCharString
512 //===========================================================================================================================
513
514 DEBUG_LOCAL WCHAR * CharToWCharString( const char *inCharString, WCHAR *outWCharString )
515 {
516 const char * src;
517 WCHAR * dst;
518 char c;
519
520 check( inCharString );
521 check( outWCharString );
522
523 src = inCharString;
524 dst = outWCharString;
525 do
526 {
527 c = *src++;
528 *dst++ = (WCHAR) c;
529
530 } while( c != '\0' );
531
532 return( outWCharString );
533 }
534
535 //===========================================================================================================================
536 // GUIDtoString
537 //===========================================================================================================================
538
539 DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, size_t inLen, char *outString )
540 {
541 check( inGUID );
542 check( outString );
543
544 _snprintf( outString, inLen, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
545 inGUID->Data1, inGUID->Data2, inGUID->Data3,
546 inGUID->Data4[ 0 ], inGUID->Data4[ 1 ], inGUID->Data4[ 2 ], inGUID->Data4[ 3 ],
547 inGUID->Data4[ 4 ], inGUID->Data4[ 5 ], inGUID->Data4[ 6 ], inGUID->Data4[ 7 ] );
548 return( outString );
549 }
550
551 //===========================================================================================================================
552 // StringToGUID
553 //===========================================================================================================================
554
555 DEBUG_LOCAL OSStatus StringToGUID( const char *inCharString, GUID *outGUID )
556 {
557 OSStatus err;
558 int n;
559 unsigned int v[ 8 ];
560
561 check( inCharString );
562 check( outGUID );
563
564 n = sscanf( inCharString, "%lX-%hX-%hX-%02X%02X-%02X%02X%02X%02X%02X%02X",
565 &outGUID->Data1, &outGUID->Data2, &outGUID->Data3,
566 &v[ 0 ], &v[ 1 ], &v[ 2 ], &v[ 3 ], &v[ 4 ], &v[ 5 ], &v[ 6 ], &v[ 7 ] );
567 require_action( n == 11, exit, err = kFormatErr );
568
569 outGUID->Data4[ 0 ] = (unsigned char) v[ 0 ];
570 outGUID->Data4[ 1 ] = (unsigned char) v[ 1 ];
571 outGUID->Data4[ 2 ] = (unsigned char) v[ 2 ];
572 outGUID->Data4[ 3 ] = (unsigned char) v[ 3 ];
573 outGUID->Data4[ 4 ] = (unsigned char) v[ 4 ];
574 outGUID->Data4[ 5 ] = (unsigned char) v[ 5 ];
575 outGUID->Data4[ 6 ] = (unsigned char) v[ 6 ];
576 outGUID->Data4[ 7 ] = (unsigned char) v[ 7 ];
577 err = kNoErr;
578
579 exit:
580 return( err );
581 }