]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSShared/Java/JNISupport.c
mDNSResponder-161.1.tar.gz
[apple/mdnsresponder.git] / mDNSShared / Java / JNISupport.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 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: JNISupport.c,v $
20 Revision 1.21 2007/09/18 19:09:02 cheshire
21 <rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
22
23 Revision 1.20 2007/03/13 01:41:46 cheshire
24 Fixed compile warnings when building 32-bit
25
26 Revision 1.19 2007/03/13 00:28:03 vazquez
27 <rdar://problem/4625928> Java: Rename exported symbols in libjdns_sd.jnilib
28
29 Revision 1.18 2007/03/13 00:10:14 vazquez
30 <rdar://problem/4455206> Java: 64 bit JNI patch
31
32 Revision 1.17 2006/08/14 23:25:08 cheshire
33 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
34
35 Revision 1.16 2006/07/14 02:35:47 cheshire
36 Added (commented out) syslog debugging messages
37
38 Revision 1.15 2006/06/27 19:34:43 cheshire
39 <rdar://problem/4430023> txtRecord parameter of DNSServiceResolveReply() should be unsigned char *
40
41 Revision 1.14 2006/06/20 23:03:35 rpantos
42 <rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
43
44 Revision 1.13 2005/10/26 01:52:24 cheshire
45 <rdar://problem/4316286> Race condition in Java code (doesn't work at all on Linux)
46
47 Revision 1.12 2005/07/13 19:20:32 cheshire
48 <rdar://problem/4175511> Race condition in Java API
49 Additional cleanup suggested by Roger -- NewContext() doesn't need ownerClass parameter any more
50
51 Revision 1.11 2005/07/11 01:55:21 cheshire
52 <rdar://problem/4175511> Race condition in Java API
53
54 Revision 1.10 2005/07/05 13:01:52 cheshire
55 <rdar://problem/4169791> If mDNSResponder daemon is stopped, Java API spins, burning CPU time
56
57 Revision 1.9 2004/12/11 03:01:00 rpantos
58 <rdar://problem/3907498> Java DNSRecord API should be cleaned up
59
60 Revision 1.8 2004/11/30 23:51:05 cheshire
61 Remove double semicolons
62
63 Revision 1.7 2004/11/23 08:12:04 shersche
64 Implement if_nametoindex and if_indextoname for Win32 platforms
65
66 Revision 1.6 2004/11/23 03:41:14 cheshire
67 Change JNISupport.c to call if_indextoname & if_nametoindex directly.
68 (May require some additional glue code to work on Windows.)
69
70 Revision 1.5 2004/11/17 17:07:44 cheshire
71 Updated comment about AUTO_CALLBACKS
72
73 Revision 1.4 2004/11/12 03:23:09 rpantos
74 rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex.
75
76 Revision 1.3 2004/06/18 04:44:17 rpantos
77 Adapt to API unification on Windows
78
79 Revision 1.2 2004/05/28 23:34:42 ksekar
80 <rdar://problem/3672903>: Java project build errors
81
82 Revision 1.1 2004/04/30 16:29:35 rpantos
83 First checked in.
84
85
86 This file contains the platform support for DNSSD and related Java classes.
87 It is used to shim through to the underlying <dns_sd.h> API.
88 */
89
90 // AUTO_CALLBACKS should be set to 1 if the underlying mDNS implementation fires response
91 // callbacks automatically (as in the early Windows prototypes).
92 // AUTO_CALLBACKS should be set to 0 if the client must call DNSServiceProcessResult() to
93 // invoke response callbacks (as is true on Mac OS X, Posix, Windows, etc.).
94 // (Invoking callbacks automatically on a different thread sounds attractive, but while
95 // the client gains by not needing to add an event source to its main event loop, it loses
96 // by being forced to deal with concurrency and locking, which can be a bigger burden.)
97 #ifndef AUTO_CALLBACKS
98 #define AUTO_CALLBACKS 0
99 #endif
100
101 #if !AUTO_CALLBACKS
102 #ifdef _WIN32
103 #include <winsock2.h>
104 #else //_WIN32
105 #include <sys/types.h>
106 #include <sys/select.h>
107 #endif // _WIN32
108 #endif // AUTO_CALLBACKS
109
110 #include <dns_sd.h>
111
112 #include <stdio.h>
113 #include <stdlib.h>
114 #include <string.h>
115 #ifdef _WIN32
116 #include <winsock2.h>
117 #include <iphlpapi.h>
118 static char * if_indextoname( DWORD ifIndex, char * nameBuff);
119 static DWORD if_nametoindex( const char * nameStr );
120 #define IF_NAMESIZE MAX_ADAPTER_NAME_LENGTH
121 #else // _WIN32
122 #include <sys/socket.h>
123 #include <net/if.h>
124 #endif // _WIN32
125 #include <jni.h>
126
127 #include "DNSSD.java.h"
128
129 //#include <syslog.h>
130
131 // convenience definition
132 #ifdef __GNUC__
133 #define _UNUSED __attribute__ ((unused))
134 #else
135 #define _UNUSED
136 #endif
137
138 enum {
139 kInterfaceVersionOne = 1,
140 kInterfaceVersionCurrent // Must match version in .jar file
141 };
142
143 typedef struct OpContext OpContext;
144
145 struct OpContext
146 {
147 DNSServiceRef ServiceRef;
148 JNIEnv *Env;
149 jobject JavaObj;
150 jobject ClientObj;
151 jmethodID Callback;
152 jmethodID Callback2;
153 };
154
155 // For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall.
156 #if AUTO_CALLBACKS
157 JavaVM *gJavaVM = NULL;
158 #endif
159
160
161 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv *pEnv, jclass cls,
162 jint callerVersion)
163 {
164 /* Ensure that caller & interface versions match. */
165 if ( callerVersion != kInterfaceVersionCurrent)
166 return kDNSServiceErr_Incompatible;
167
168 #if AUTO_CALLBACKS
169 {
170 jsize numVMs;
171
172 if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs))
173 return kDNSServiceErr_BadState;
174 }
175 #endif
176
177 // Set AppleDNSSD.hasAutoCallbacks
178 {
179 #if AUTO_CALLBACKS
180 jboolean hasAutoC = JNI_TRUE;
181 #else
182 jboolean hasAutoC = JNI_FALSE;
183 #endif
184 jfieldID hasAutoCField = (*pEnv)->GetStaticFieldID( pEnv, cls, "hasAutoCallbacks", "Z");
185 (*pEnv)->SetStaticBooleanField( pEnv, cls, hasAutoCField, hasAutoC);
186 }
187
188 return kDNSServiceErr_NoError;
189 }
190
191
192 static const char* SafeGetUTFChars( JNIEnv *pEnv, jstring str)
193 // Wrapper for JNI GetStringUTFChars() that returns NULL for null str.
194 {
195 return str != NULL ? (*pEnv)->GetStringUTFChars( pEnv, str, 0) : NULL;
196 }
197
198 static void SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff)
199 // Wrapper for JNI GetStringUTFChars() that handles null str.
200 {
201 if ( str != NULL)
202 (*pEnv)->ReleaseStringUTFChars( pEnv, str, buff);
203 }
204
205
206 #if AUTO_CALLBACKS
207 static void SetupCallbackState( JNIEnv **ppEnv)
208 {
209 (*gJavaVM)->AttachCurrentThread( gJavaVM, (void**) ppEnv, NULL);
210 }
211
212 static void TeardownCallbackState( void )
213 {
214 (*gJavaVM)->DetachCurrentThread( gJavaVM);
215 }
216
217 #else // AUTO_CALLBACKS
218
219 static void SetupCallbackState( JNIEnv **ppEnv _UNUSED)
220 {
221 // No setup necessary if ProcessResults() has been called
222 }
223
224 static void TeardownCallbackState( void )
225 {
226 // No teardown necessary if ProcessResults() has been called
227 }
228 #endif // AUTO_CALLBACKS
229
230
231 static OpContext *NewContext( JNIEnv *pEnv, jobject owner,
232 const char *callbackName, const char *callbackSig)
233 // Create and initialize a new OpContext.
234 {
235 OpContext *pContext = (OpContext*) malloc( sizeof *pContext);
236
237 if ( pContext != NULL)
238 {
239 jfieldID clientField = (*pEnv)->GetFieldID( pEnv, (*pEnv)->GetObjectClass( pEnv, owner),
240 "fListener", "Lcom/apple/dnssd/BaseListener;");
241
242 pContext->JavaObj = (*pEnv)->NewWeakGlobalRef( pEnv, owner); // must convert local ref to global to cache;
243 pContext->ClientObj = (*pEnv)->GetObjectField( pEnv, owner, clientField);
244 pContext->ClientObj = (*pEnv)->NewWeakGlobalRef( pEnv, pContext->ClientObj); // must convert local ref to global to cache
245 pContext->Callback = (*pEnv)->GetMethodID( pEnv,
246 (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
247 callbackName, callbackSig);
248 pContext->Callback2 = NULL; // not always used
249 }
250
251 return pContext;
252 }
253
254
255 static void ReportError( JNIEnv *pEnv, jobject target, jobject service, DNSServiceErrorType err)
256 // Invoke operationFailed() method on target with err.
257 {
258 jclass cls = (*pEnv)->GetObjectClass( pEnv, target);
259 jmethodID opFailed = (*pEnv)->GetMethodID( pEnv, cls, "operationFailed",
260 "(Lcom/apple/dnssd/DNSSDService;I)V");
261
262 (*pEnv)->CallVoidMethod( pEnv, target, opFailed, service, err);
263 }
264
265 JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv *pEnv, jobject pThis)
266 /* Deallocate the dns_sd service browser and set the Java object's fNativeContext field to 0. */
267 {
268 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
269 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
270
271 if ( contextField != 0)
272 {
273 OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
274 if ( pContext != NULL)
275 {
276 // MUST clear fNativeContext first, BEFORE calling DNSServiceRefDeallocate()
277 (*pEnv)->SetLongField(pEnv, pThis, contextField, 0);
278 if ( pContext->ServiceRef != NULL)
279 DNSServiceRefDeallocate( pContext->ServiceRef);
280
281 (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj);
282 (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj);
283 free( pContext);
284 }
285 }
286 }
287
288
289 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis)
290 /* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */
291 {
292 // BlockForData() not supported with AUTO_CALLBACKS
293 #if !AUTO_CALLBACKS
294 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
295 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
296
297 if ( contextField != 0)
298 {
299 OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
300 if ( pContext != NULL)
301 {
302 fd_set readFDs;
303 int sd = DNSServiceRefSockFD( pContext->ServiceRef);
304 struct timeval timeout = { 1, 0 };
305 FD_ZERO( &readFDs);
306 FD_SET( sd, &readFDs);
307
308 // Q: Why do we poll here?
309 // A: Because there's no other thread-safe way to do it.
310 // Mac OS X terminates a select() call if you close one of the sockets it's listening on, but Linux does not,
311 // and arguably Linux is correct (See <http://www.ussg.iu.edu/hypermail/linux/kernel/0405.1/0418.html>)
312 // The problem is that the Mac OS X behaviour assumes that it's okay for one thread to close a socket while
313 // some other thread is monitoring that socket in select(), but the difficulty is that there's no general way
314 // to make that thread-safe, because there's no atomic way to enter select() and release a lock simultaneously.
315 // If we try to do this without holding any lock, then right as we jump to the select() routine,
316 // some other thread could stop our operation (thereby closing the socket),
317 // and then that thread (or even some third, unrelated thread)
318 // could do some other DNS-SD operation (or some other operation that opens a new file descriptor)
319 // and then we'd blindly resume our fall into the select() call, now blocking on a file descriptor
320 // that may coincidentally have the same numerical value, but is semantically unrelated
321 // to the true file descriptor we thought we were blocking on.
322 // We can't stop this race condition from happening, but at least if we wake up once a second we can detect
323 // when fNativeContext has gone to zero, and thereby discover that we were blocking on the wrong fd.
324
325 if (select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout) == 1) return(1);
326 }
327 }
328 #endif // !AUTO_CALLBACKS
329 return(0);
330 }
331
332
333 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv *pEnv, jobject pThis)
334 /* Call through to DNSServiceProcessResult() while data remains on socket. */
335 {
336 #if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS
337
338 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
339 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
340 OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
341 DNSServiceErrorType err = kDNSServiceErr_BadState;
342
343 if ( pContext != NULL)
344 {
345 int sd = DNSServiceRefSockFD( pContext->ServiceRef);
346 fd_set readFDs;
347 struct timeval zeroTimeout = { 0, 0 };
348
349 pContext->Env = pEnv;
350
351 FD_ZERO( &readFDs);
352 FD_SET( sd, &readFDs);
353
354 err = kDNSServiceErr_NoError;
355 if (0 < select(sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout))
356 {
357 err = DNSServiceProcessResult(pContext->ServiceRef);
358 // Use caution here!
359 // We cannot touch any data structures associated with this operation!
360 // The DNSServiceProcessResult() routine should have invoked our callback,
361 // and our callback could have terminated the operation with op.stop();
362 // and that means HaltOperation() will have been called, which frees pContext.
363 // Basically, from here we just have to get out without touching any stale
364 // data structures that could blow up on us! Particularly, any attempt
365 // to loop here reading more results from the file descriptor is unsafe.
366 }
367 }
368 return err;
369 #endif // AUTO_CALLBACKS
370 }
371
372
373 static void DNSSD_API ServiceBrowseReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
374 DNSServiceErrorType errorCode, const char *serviceName, const char *regtype,
375 const char *replyDomain, void *context)
376 {
377 OpContext *pContext = (OpContext*) context;
378
379 SetupCallbackState( &pContext->Env);
380
381 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
382 {
383 if ( errorCode == kDNSServiceErr_NoError)
384 {
385 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
386 ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
387 pContext->JavaObj, flags, interfaceIndex,
388 (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
389 (*pContext->Env)->NewStringUTF( pContext->Env, regtype),
390 (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
391 }
392 else
393 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
394 }
395
396 TeardownCallbackState();
397 }
398
399 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv *pEnv, jobject pThis,
400 jint flags, jint ifIndex, jstring regType, jstring domain)
401 {
402 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
403 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
404 OpContext *pContext = NULL;
405 DNSServiceErrorType err = kDNSServiceErr_NoError;
406
407 if ( contextField != 0)
408 pContext = NewContext( pEnv, pThis, "serviceFound",
409 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
410 else
411 err = kDNSServiceErr_BadParam;
412
413 if ( pContext != NULL)
414 {
415 const char *regStr = SafeGetUTFChars( pEnv, regType);
416 const char *domainStr = SafeGetUTFChars( pEnv, domain);
417
418 pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
419 (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
420 "serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
421
422 err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext);
423 if ( err == kDNSServiceErr_NoError)
424 {
425 (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
426 }
427
428 SafeReleaseUTFChars( pEnv, regType, regStr);
429 SafeReleaseUTFChars( pEnv, domain, domainStr);
430 }
431 else
432 err = kDNSServiceErr_NoMemory;
433
434 return err;
435 }
436
437
438 static void DNSSD_API ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
439 DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget,
440 uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context)
441 {
442 OpContext *pContext = (OpContext*) context;
443 jclass txtCls;
444 jmethodID txtCtor;
445 jbyteArray txtBytes;
446 jobject txtObj;
447 jbyte *pBytes;
448
449 SetupCallbackState( &pContext->Env);
450
451 txtCls = (*pContext->Env)->FindClass( pContext->Env, "com/apple/dnssd/TXTRecord");
452 txtCtor = (*pContext->Env)->GetMethodID( pContext->Env, txtCls, "<init>", "([B)V");
453
454 if ( pContext->ClientObj != NULL && pContext->Callback != NULL && txtCtor != NULL &&
455 NULL != ( txtBytes = (*pContext->Env)->NewByteArray( pContext->Env, txtLen)))
456 {
457 if ( errorCode == kDNSServiceErr_NoError)
458 {
459 // Since Java ints are defined to be big-endian, we canonicalize 'port' from a 16-bit
460 // pattern into a number here.
461 port = ( ((unsigned char*) &port)[0] << 8) | ((unsigned char*) &port)[1];
462
463 // Initialize txtBytes with contents of txtRecord
464 pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, txtBytes, NULL);
465 memcpy( pBytes, txtRecord, txtLen);
466 (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, txtBytes, pBytes, JNI_COMMIT);
467
468 // Construct txtObj with txtBytes
469 txtObj = (*pContext->Env)->NewObject( pContext->Env, txtCls, txtCtor, txtBytes);
470 (*pContext->Env)->DeleteLocalRef( pContext->Env, txtBytes);
471
472 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
473 pContext->JavaObj, flags, interfaceIndex,
474 (*pContext->Env)->NewStringUTF( pContext->Env, fullname),
475 (*pContext->Env)->NewStringUTF( pContext->Env, hosttarget),
476 port, txtObj);
477 }
478 else
479 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
480 }
481
482 TeardownCallbackState();
483 }
484
485 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv *pEnv, jobject pThis,
486 jint flags, jint ifIndex, jstring serviceName, jstring regType, jstring domain)
487 {
488 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
489 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
490 OpContext *pContext = NULL;
491 DNSServiceErrorType err = kDNSServiceErr_NoError;
492
493 if ( contextField != 0)
494 pContext = NewContext( pEnv, pThis, "serviceResolved",
495 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V");
496 else
497 err = kDNSServiceErr_BadParam;
498
499 if ( pContext != NULL)
500 {
501 const char *servStr = SafeGetUTFChars( pEnv, serviceName);
502 const char *regStr = SafeGetUTFChars( pEnv, regType);
503 const char *domainStr = SafeGetUTFChars( pEnv, domain);
504
505 err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex,
506 servStr, regStr, domainStr, ServiceResolveReply, pContext);
507 if ( err == kDNSServiceErr_NoError)
508 {
509 (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
510 }
511
512 SafeReleaseUTFChars( pEnv, serviceName, servStr);
513 SafeReleaseUTFChars( pEnv, regType, regStr);
514 SafeReleaseUTFChars( pEnv, domain, domainStr);
515 }
516 else
517 err = kDNSServiceErr_NoMemory;
518
519 return err;
520 }
521
522
523 static void DNSSD_API ServiceRegisterReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags,
524 DNSServiceErrorType errorCode, const char *serviceName,
525 const char *regType, const char *domain, void *context)
526 {
527 OpContext *pContext = (OpContext*) context;
528
529 SetupCallbackState( &pContext->Env);
530
531 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
532 {
533 if ( errorCode == kDNSServiceErr_NoError)
534 {
535 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
536 pContext->JavaObj, flags,
537 (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
538 (*pContext->Env)->NewStringUTF( pContext->Env, regType),
539 (*pContext->Env)->NewStringUTF( pContext->Env, domain));
540 }
541 else
542 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
543 }
544 TeardownCallbackState();
545 }
546
547 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNIEnv *pEnv, jobject pThis,
548 jint ifIndex, jint flags, jstring serviceName, jstring regType,
549 jstring domain, jstring host, jint port, jbyteArray txtRecord)
550 {
551 //syslog(LOG_ERR, "BR");
552 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
553 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
554 OpContext *pContext = NULL;
555 DNSServiceErrorType err = kDNSServiceErr_NoError;
556 jbyte *pBytes;
557 jsize numBytes;
558
559 //syslog(LOG_ERR, "BR: contextField %d", contextField);
560
561 if ( contextField != 0)
562 pContext = NewContext( pEnv, pThis, "serviceRegistered",
563 "(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
564 else
565 err = kDNSServiceErr_BadParam;
566
567 if ( pContext != NULL)
568 {
569 const char *servStr = SafeGetUTFChars( pEnv, serviceName);
570 const char *regStr = SafeGetUTFChars( pEnv, regType);
571 const char *domainStr = SafeGetUTFChars( pEnv, domain);
572 const char *hostStr = SafeGetUTFChars( pEnv, host);
573
574 //syslog(LOG_ERR, "BR: regStr %s", regStr);
575
576 // Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a
577 // big-endian number into a 16-bit pattern here.
578 uint16_t portBits = port;
579 portBits = ( ((unsigned char*) &portBits)[0] << 8) | ((unsigned char*) &portBits)[1];
580
581 pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL;
582 numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0;
583
584 err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr,
585 domainStr, hostStr, portBits,
586 numBytes, pBytes, ServiceRegisterReply, pContext);
587 if ( err == kDNSServiceErr_NoError)
588 {
589 (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
590 }
591
592 if ( pBytes != NULL)
593 (*pEnv)->ReleaseByteArrayElements( pEnv, txtRecord, pBytes, 0);
594
595 SafeReleaseUTFChars( pEnv, serviceName, servStr);
596 SafeReleaseUTFChars( pEnv, regType, regStr);
597 SafeReleaseUTFChars( pEnv, domain, domainStr);
598 SafeReleaseUTFChars( pEnv, host, hostStr);
599 }
600 else
601 err = kDNSServiceErr_NoMemory;
602
603 return err;
604 }
605
606 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv *pEnv, jobject pThis,
607 jint flags, jint rrType, jbyteArray rData, jint ttl, jobject destObj)
608 {
609 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
610 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
611 jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
612 jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
613 OpContext *pContext = NULL;
614 DNSServiceErrorType err = kDNSServiceErr_NoError;
615 jbyte *pBytes;
616 jsize numBytes;
617 DNSRecordRef recRef;
618
619 if ( contextField != 0)
620 pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
621 if ( pContext == NULL || pContext->ServiceRef == NULL)
622 return kDNSServiceErr_BadParam;
623
624 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
625 numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
626
627 err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl);
628 if ( err == kDNSServiceErr_NoError)
629 {
630 (*pEnv)->SetLongField(pEnv, destObj, recField, (long) recRef);
631 }
632
633 if ( pBytes != NULL)
634 (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
635
636 return err;
637 }
638
639 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Update( JNIEnv *pEnv, jobject pThis,
640 jint flags, jbyteArray rData, jint ttl)
641 {
642 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
643 jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
644 jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
645 OpContext *pContext = NULL;
646 DNSServiceErrorType err = kDNSServiceErr_NoError;
647 jbyte *pBytes;
648 jsize numBytes;
649 DNSRecordRef recRef = NULL;
650
651 if ( ownerField != 0)
652 {
653 jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
654 jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
655 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
656 if ( contextField != 0)
657 pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, ownerObj, contextField);
658 }
659 if ( recField != 0)
660 recRef = (DNSRecordRef) (long) (*pEnv)->GetLongField(pEnv, pThis, recField);
661 if ( pContext == NULL || pContext->ServiceRef == NULL)
662 return kDNSServiceErr_BadParam;
663
664 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
665 numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
666
667 err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl);
668
669 if ( pBytes != NULL)
670 (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
671
672 return err;
673 }
674
675 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv *pEnv, jobject pThis)
676 {
677 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
678 jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
679 jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
680 OpContext *pContext = NULL;
681 DNSServiceErrorType err = kDNSServiceErr_NoError;
682 DNSRecordRef recRef = NULL;
683
684 if ( ownerField != 0)
685 {
686 jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
687 jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
688 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
689 if ( contextField != 0)
690 pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, ownerObj, contextField);
691 }
692 if ( recField != 0)
693 recRef = (DNSRecordRef) (long) (*pEnv)->GetLongField(pEnv, pThis, recField);
694 if ( pContext == NULL || pContext->ServiceRef == NULL)
695 return kDNSServiceErr_BadParam;
696
697 err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, 0);
698
699 return err;
700 }
701
702
703 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection( JNIEnv *pEnv, jobject pThis)
704 {
705 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
706 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
707 OpContext *pContext = NULL;
708 DNSServiceErrorType err = kDNSServiceErr_NoError;
709
710 if ( contextField != 0)
711 pContext = NewContext( pEnv, pThis, "recordRegistered", "(Lcom/apple/dnssd/DNSRecord;I)V");
712 else
713 err = kDNSServiceErr_BadParam;
714
715 if ( pContext != NULL)
716 {
717 err = DNSServiceCreateConnection( &pContext->ServiceRef);
718 if ( err == kDNSServiceErr_NoError)
719 {
720 (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
721 }
722 }
723 else
724 err = kDNSServiceErr_NoMemory;
725
726 return err;
727 }
728
729 struct RecordRegistrationRef
730 {
731 OpContext *Context;
732 jobject RecordObj;
733 };
734 typedef struct RecordRegistrationRef RecordRegistrationRef;
735
736 static void DNSSD_API RegisterRecordReply( DNSServiceRef sdRef _UNUSED,
737 DNSRecordRef recordRef _UNUSED, DNSServiceFlags flags,
738 DNSServiceErrorType errorCode, void *context)
739 {
740 RecordRegistrationRef *regEnvelope = (RecordRegistrationRef*) context;
741 OpContext *pContext = regEnvelope->Context;
742
743 SetupCallbackState( &pContext->Env);
744
745 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
746 {
747 if ( errorCode == kDNSServiceErr_NoError)
748 {
749 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
750 regEnvelope->RecordObj, flags);
751 }
752 else
753 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
754 }
755
756 (*pContext->Env)->DeleteWeakGlobalRef( pContext->Env, regEnvelope->RecordObj);
757 free( regEnvelope);
758
759 TeardownCallbackState();
760 }
761
762 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_RegisterRecord( JNIEnv *pEnv, jobject pThis,
763 jint flags, jint ifIndex, jstring fullname, jint rrType, jint rrClass,
764 jbyteArray rData, jint ttl, jobject destObj)
765 {
766 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
767 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
768 jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
769 jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
770 const char *nameStr = SafeGetUTFChars( pEnv, fullname);
771 OpContext *pContext = NULL;
772 DNSServiceErrorType err = kDNSServiceErr_NoError;
773 jbyte *pBytes;
774 jsize numBytes;
775 DNSRecordRef recRef;
776 RecordRegistrationRef *regEnvelope;
777
778 if ( contextField != 0)
779 pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
780 if ( pContext == NULL || pContext->ServiceRef == NULL || nameStr == NULL)
781 return kDNSServiceErr_BadParam;
782
783 regEnvelope = calloc( 1, sizeof *regEnvelope);
784 if ( regEnvelope == NULL)
785 return kDNSServiceErr_NoMemory;
786 regEnvelope->Context = pContext;
787 regEnvelope->RecordObj = (*pEnv)->NewWeakGlobalRef( pEnv, destObj); // must convert local ref to global to cache
788
789 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
790 numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
791
792 err = DNSServiceRegisterRecord( pContext->ServiceRef, &recRef, flags, ifIndex,
793 nameStr, rrType, rrClass, numBytes, pBytes, ttl,
794 RegisterRecordReply, regEnvelope);
795
796 if ( err == kDNSServiceErr_NoError)
797 {
798 (*pEnv)->SetLongField(pEnv, destObj, recField, (long) recRef);
799 }
800 else
801 {
802 if ( regEnvelope->RecordObj != NULL)
803 (*pEnv)->DeleteWeakGlobalRef( pEnv, regEnvelope->RecordObj);
804 free( regEnvelope);
805 }
806
807 if ( pBytes != NULL)
808 (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
809
810 SafeReleaseUTFChars( pEnv, fullname, nameStr);
811
812 return err;
813 }
814
815
816 static void DNSSD_API ServiceQueryReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
817 DNSServiceErrorType errorCode, const char *serviceName,
818 uint16_t rrtype, uint16_t rrclass, uint16_t rdlen,
819 const void *rdata, uint32_t ttl, void *context)
820 {
821 OpContext *pContext = (OpContext*) context;
822 jbyteArray rDataObj;
823 jbyte *pBytes;
824
825 SetupCallbackState( &pContext->Env);
826
827 if ( pContext->ClientObj != NULL && pContext->Callback != NULL &&
828 NULL != ( rDataObj = (*pContext->Env)->NewByteArray( pContext->Env, rdlen)))
829 {
830 if ( errorCode == kDNSServiceErr_NoError)
831 {
832 // Initialize rDataObj with contents of rdata
833 pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, rDataObj, NULL);
834 memcpy( pBytes, rdata, rdlen);
835 (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, rDataObj, pBytes, JNI_COMMIT);
836
837 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
838 pContext->JavaObj, flags, interfaceIndex,
839 (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
840 rrtype, rrclass, rDataObj, ttl);
841 }
842 else
843 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
844 }
845 TeardownCallbackState();
846 }
847
848 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv *pEnv, jobject pThis,
849 jint flags, jint ifIndex, jstring serviceName, jint rrtype, jint rrclass)
850 {
851 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
852 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
853 OpContext *pContext = NULL;
854 DNSServiceErrorType err = kDNSServiceErr_NoError;
855
856 if ( contextField != 0)
857 pContext = NewContext( pEnv, pThis, "queryAnswered",
858 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V");
859 else
860 err = kDNSServiceErr_BadParam;
861
862 if ( pContext != NULL)
863 {
864 const char *servStr = SafeGetUTFChars( pEnv, serviceName);
865
866 err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr,
867 rrtype, rrclass, ServiceQueryReply, pContext);
868 if ( err == kDNSServiceErr_NoError)
869 {
870 (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
871 }
872
873 SafeReleaseUTFChars( pEnv, serviceName, servStr);
874 }
875 else
876 err = kDNSServiceErr_NoMemory;
877
878 return err;
879 }
880
881
882 static void DNSSD_API DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
883 DNSServiceErrorType errorCode, const char *replyDomain, void *context)
884 {
885 OpContext *pContext = (OpContext*) context;
886
887 SetupCallbackState( &pContext->Env);
888
889 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
890 {
891 if ( errorCode == kDNSServiceErr_NoError)
892 {
893 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
894 ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
895 pContext->JavaObj, flags, interfaceIndex,
896 (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
897 }
898 else
899 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
900 }
901 TeardownCallbackState();
902 }
903
904 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv *pEnv, jobject pThis,
905 jint flags, jint ifIndex)
906 {
907 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
908 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
909 OpContext *pContext = NULL;
910 DNSServiceErrorType err = kDNSServiceErr_NoError;
911
912 if ( contextField != 0)
913 pContext = NewContext( pEnv, pThis, "domainFound",
914 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
915 else
916 err = kDNSServiceErr_BadParam;
917
918 if ( pContext != NULL)
919 {
920 pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
921 (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
922 "domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
923
924 err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex,
925 DomainEnumReply, pContext);
926 if ( err == kDNSServiceErr_NoError)
927 {
928 (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
929 }
930 }
931 else
932 err = kDNSServiceErr_NoMemory;
933
934 return err;
935 }
936
937
938 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv *pEnv, jobject pThis _UNUSED,
939 jstring serviceName, jstring regtype, jstring domain, jobjectArray pOut)
940 {
941 DNSServiceErrorType err = kDNSServiceErr_NoError;
942 const char *nameStr = SafeGetUTFChars( pEnv, serviceName);
943 const char *regStr = SafeGetUTFChars( pEnv, regtype);
944 const char *domStr = SafeGetUTFChars( pEnv, domain);
945 char buff[ kDNSServiceMaxDomainName + 1];
946
947 err = DNSServiceConstructFullName( buff, nameStr, regStr, domStr);
948
949 if ( err == kDNSServiceErr_NoError)
950 {
951 // pOut is expected to be a String[1] array.
952 (*pEnv)->SetObjectArrayElement( pEnv, pOut, 0, (*pEnv)->NewStringUTF( pEnv, buff));
953 }
954
955 SafeReleaseUTFChars( pEnv, serviceName, nameStr);
956 SafeReleaseUTFChars( pEnv, regtype, regStr);
957 SafeReleaseUTFChars( pEnv, domain, domStr);
958
959 return err;
960 }
961
962 JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv *pEnv, jobject pThis _UNUSED,
963 jint flags, jint ifIndex, jstring fullName,
964 jint rrtype, jint rrclass, jbyteArray rdata)
965 {
966 jbyte *pBytes;
967 jsize numBytes;
968 const char *nameStr = SafeGetUTFChars( pEnv, fullName);
969
970 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL);
971 numBytes = (*pEnv)->GetArrayLength( pEnv, rdata);
972
973 DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes);
974
975 if ( pBytes != NULL)
976 (*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0);
977
978 SafeReleaseUTFChars( pEnv, fullName, nameStr);
979 }
980
981 #define LOCAL_ONLY_NAME "loo"
982
983 JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv *pEnv, jobject pThis _UNUSED,
984 jint ifIndex)
985 {
986 char *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE];
987
988 if (ifIndex != (jint) kDNSServiceInterfaceIndexLocalOnly)
989 p = if_indextoname( ifIndex, nameBuff );
990
991 return (*pEnv)->NewStringUTF( pEnv, p);
992 }
993
994
995 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName( JNIEnv *pEnv, jobject pThis _UNUSED,
996 jstring ifName)
997 {
998 uint32_t ifIndex = kDNSServiceInterfaceIndexLocalOnly;
999 const char *nameStr = SafeGetUTFChars( pEnv, ifName);
1000
1001 if (strcmp(nameStr, LOCAL_ONLY_NAME))
1002 ifIndex = if_nametoindex( nameStr);
1003
1004 SafeReleaseUTFChars( pEnv, ifName, nameStr);
1005
1006 return ifIndex;
1007 }
1008
1009
1010 #if defined(_WIN32)
1011 static char*
1012 if_indextoname( DWORD ifIndex, char * nameBuff)
1013 {
1014 PIP_ADAPTER_INFO pAdapterInfo = NULL;
1015 PIP_ADAPTER_INFO pAdapter = NULL;
1016 DWORD dwRetVal = 0;
1017 char * ifName = NULL;
1018 ULONG ulOutBufLen = 0;
1019
1020 if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
1021 {
1022 goto exit;
1023 }
1024
1025 pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
1026
1027 if (pAdapterInfo == NULL)
1028 {
1029 goto exit;
1030 }
1031
1032 dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
1033
1034 if (dwRetVal != NO_ERROR)
1035 {
1036 goto exit;
1037 }
1038
1039 pAdapter = pAdapterInfo;
1040 while (pAdapter)
1041 {
1042 if (pAdapter->Index == ifIndex)
1043 {
1044 // It would be better if we passed in the length of nameBuff to this
1045 // function, so we would have absolute certainty that no buffer
1046 // overflows would occur. Buffer overflows *shouldn't* occur because
1047 // nameBuff is of size MAX_ADAPTER_NAME_LENGTH.
1048 strcpy( nameBuff, pAdapter->AdapterName );
1049 ifName = nameBuff;
1050 break;
1051 }
1052
1053 pAdapter = pAdapter->Next;
1054 }
1055
1056 exit:
1057
1058 if (pAdapterInfo != NULL)
1059 {
1060 free( pAdapterInfo );
1061 pAdapterInfo = NULL;
1062 }
1063
1064 return ifName;
1065 }
1066
1067
1068 static DWORD
1069 if_nametoindex( const char * nameStr )
1070 {
1071 PIP_ADAPTER_INFO pAdapterInfo = NULL;
1072 PIP_ADAPTER_INFO pAdapter = NULL;
1073 DWORD dwRetVal = 0;
1074 DWORD ifIndex = 0;
1075 ULONG ulOutBufLen = 0;
1076
1077 if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
1078 {
1079 goto exit;
1080 }
1081
1082 pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
1083
1084 if (pAdapterInfo == NULL)
1085 {
1086 goto exit;
1087 }
1088
1089 dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
1090
1091 if (dwRetVal != NO_ERROR)
1092 {
1093 goto exit;
1094 }
1095
1096 pAdapter = pAdapterInfo;
1097 while (pAdapter)
1098 {
1099 if (strcmp(pAdapter->AdapterName, nameStr) == 0)
1100 {
1101 ifIndex = pAdapter->Index;
1102 break;
1103 }
1104
1105 pAdapter = pAdapter->Next;
1106 }
1107
1108 exit:
1109
1110 if (pAdapterInfo != NULL)
1111 {
1112 free( pAdapterInfo );
1113 pAdapterInfo = NULL;
1114 }
1115
1116 return ifIndex;
1117 }
1118 #endif
1119
1120
1121 // Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
1122 // e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
1123 // To expand "version" to its value before making the string, use STRINGIFY(version) instead
1124 #define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) #s
1125 #define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
1126
1127 // NOT static -- otherwise the compiler may optimize it out
1128 // The "@(#) " pattern is a special prefix the "what" command looks for
1129 const char VersionString_SCCS[] = "@(#) libjdns_sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";