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