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