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