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