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