mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-06-13 05:15:36 +08:00

The sources can be obtained via: http://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-544.tar.gz
1073 lines
41 KiB
C
1073 lines
41 KiB
C
/* -*- Mode: C; tab-width: 4 -*-
|
|
*
|
|
* Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
|
|
This file contains the platform support for DNSSD and related Java classes.
|
|
It is used to shim through to the underlying <dns_sd.h> API.
|
|
*/
|
|
|
|
// AUTO_CALLBACKS should be set to 1 if the underlying mDNS implementation fires response
|
|
// callbacks automatically (as in the early Windows prototypes).
|
|
// AUTO_CALLBACKS should be set to 0 if the client must call DNSServiceProcessResult() to
|
|
// invoke response callbacks (as is true on Mac OS X, Posix, Windows, etc.).
|
|
// (Invoking callbacks automatically on a different thread sounds attractive, but while
|
|
// the client gains by not needing to add an event source to its main event loop, it loses
|
|
// by being forced to deal with concurrency and locking, which can be a bigger burden.)
|
|
#ifndef AUTO_CALLBACKS
|
|
#define AUTO_CALLBACKS 0
|
|
#endif
|
|
|
|
#if !AUTO_CALLBACKS
|
|
#ifdef _WIN32
|
|
#include <winsock2.h>
|
|
#else //_WIN32
|
|
#include <sys/types.h>
|
|
#include <sys/select.h>
|
|
#endif // _WIN32
|
|
#endif // AUTO_CALLBACKS
|
|
|
|
#include <dns_sd.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#ifdef _WIN32
|
|
#include <winsock2.h>
|
|
#include <iphlpapi.h>
|
|
static char * win32_if_indextoname( DWORD ifIndex, char * nameBuff);
|
|
static DWORD win32_if_nametoindex( const char * nameStr );
|
|
#define if_indextoname win32_if_indextoname
|
|
#define if_nametoindex win32_if_nametoindex
|
|
#define IF_NAMESIZE MAX_ADAPTER_NAME_LENGTH
|
|
#else // _WIN32
|
|
#include <sys/socket.h>
|
|
#include <net/if.h>
|
|
#endif // _WIN32
|
|
|
|
// When compiling with "-Wshadow" set, including jni.h produces the following error:
|
|
// /System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/jni.h:609: warning: declaration of 'index' shadows a global declaration
|
|
// To work around this, we use the preprocessor to map the identifier 'index', which appears harmlessly in function prototype declarations,
|
|
// to something 'jni_index', which doesn't conflict
|
|
#define index jni_index
|
|
#include "DNSSD.java.h"
|
|
#undef index
|
|
|
|
//#include <syslog.h>
|
|
|
|
// convenience definition
|
|
#ifdef __GNUC__
|
|
#define _UNUSED __attribute__ ((unused))
|
|
#else
|
|
#define _UNUSED
|
|
#endif
|
|
|
|
enum {
|
|
kInterfaceVersionOne = 1,
|
|
kInterfaceVersionCurrent // Must match version in .jar file
|
|
};
|
|
|
|
typedef struct OpContext OpContext;
|
|
|
|
struct OpContext
|
|
{
|
|
DNSServiceRef ServiceRef;
|
|
JNIEnv *Env;
|
|
jobject JavaObj;
|
|
jobject ClientObj;
|
|
jmethodID Callback;
|
|
jmethodID Callback2;
|
|
};
|
|
|
|
// For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall.
|
|
#if AUTO_CALLBACKS
|
|
JavaVM *gJavaVM = NULL;
|
|
#endif
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv *pEnv, jclass cls,
|
|
jint callerVersion)
|
|
{
|
|
/* Ensure that caller & interface versions match. */
|
|
if ( callerVersion != kInterfaceVersionCurrent)
|
|
return kDNSServiceErr_Incompatible;
|
|
|
|
#if AUTO_CALLBACKS
|
|
{
|
|
jsize numVMs;
|
|
|
|
if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs))
|
|
return kDNSServiceErr_BadState;
|
|
}
|
|
#endif
|
|
|
|
// Set AppleDNSSD.hasAutoCallbacks
|
|
{
|
|
#if AUTO_CALLBACKS
|
|
jboolean hasAutoC = JNI_TRUE;
|
|
#else
|
|
jboolean hasAutoC = JNI_FALSE;
|
|
#endif
|
|
jfieldID hasAutoCField = (*pEnv)->GetStaticFieldID( pEnv, cls, "hasAutoCallbacks", "Z");
|
|
(*pEnv)->SetStaticBooleanField( pEnv, cls, hasAutoCField, hasAutoC);
|
|
}
|
|
|
|
return kDNSServiceErr_NoError;
|
|
}
|
|
|
|
|
|
static const char* SafeGetUTFChars( JNIEnv *pEnv, jstring str)
|
|
// Wrapper for JNI GetStringUTFChars() that returns NULL for null str.
|
|
{
|
|
return str != NULL ? (*pEnv)->GetStringUTFChars( pEnv, str, 0) : NULL;
|
|
}
|
|
|
|
static void SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff)
|
|
// Wrapper for JNI GetStringUTFChars() that handles null str.
|
|
{
|
|
if ( str != NULL)
|
|
(*pEnv)->ReleaseStringUTFChars( pEnv, str, buff);
|
|
}
|
|
|
|
|
|
#if AUTO_CALLBACKS
|
|
static void SetupCallbackState( JNIEnv **ppEnv)
|
|
{
|
|
(*gJavaVM)->AttachCurrentThread( gJavaVM, (void**) ppEnv, NULL);
|
|
}
|
|
|
|
static void TeardownCallbackState( void )
|
|
{
|
|
(*gJavaVM)->DetachCurrentThread( gJavaVM);
|
|
}
|
|
|
|
#else // AUTO_CALLBACKS
|
|
|
|
static void SetupCallbackState( JNIEnv **ppEnv _UNUSED)
|
|
{
|
|
// No setup necessary if ProcessResults() has been called
|
|
}
|
|
|
|
static void TeardownCallbackState( void )
|
|
{
|
|
// No teardown necessary if ProcessResults() has been called
|
|
}
|
|
#endif // AUTO_CALLBACKS
|
|
|
|
|
|
static OpContext *NewContext( JNIEnv *pEnv, jobject owner,
|
|
const char *callbackName, const char *callbackSig)
|
|
// Create and initialize a new OpContext.
|
|
{
|
|
OpContext *pContext = (OpContext*) malloc( sizeof *pContext);
|
|
|
|
if ( pContext != NULL)
|
|
{
|
|
jfieldID clientField = (*pEnv)->GetFieldID( pEnv, (*pEnv)->GetObjectClass( pEnv, owner),
|
|
"fListener", "Lcom/apple/dnssd/BaseListener;");
|
|
|
|
pContext->JavaObj = (*pEnv)->NewWeakGlobalRef( pEnv, owner); // must convert local ref to global to cache;
|
|
pContext->ClientObj = (*pEnv)->GetObjectField( pEnv, owner, clientField);
|
|
pContext->ClientObj = (*pEnv)->NewWeakGlobalRef( pEnv, pContext->ClientObj); // must convert local ref to global to cache
|
|
pContext->Callback = (*pEnv)->GetMethodID( pEnv,
|
|
(*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
|
|
callbackName, callbackSig);
|
|
pContext->Callback2 = NULL; // not always used
|
|
}
|
|
|
|
return pContext;
|
|
}
|
|
|
|
|
|
static void ReportError( JNIEnv *pEnv, jobject target, jobject service, DNSServiceErrorType err)
|
|
// Invoke operationFailed() method on target with err.
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, target);
|
|
jmethodID opFailed = (*pEnv)->GetMethodID( pEnv, cls, "operationFailed",
|
|
"(Lcom/apple/dnssd/DNSSDService;I)V");
|
|
|
|
(*pEnv)->CallVoidMethod( pEnv, target, opFailed, service, err);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv *pEnv, jobject pThis)
|
|
/* Deallocate the dns_sd service browser and set the Java object's fNativeContext field to 0. */
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
|
|
if ( contextField != 0)
|
|
{
|
|
OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
|
|
if ( pContext != NULL)
|
|
{
|
|
// MUST clear fNativeContext first, BEFORE calling DNSServiceRefDeallocate()
|
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, 0);
|
|
if ( pContext->ServiceRef != NULL)
|
|
DNSServiceRefDeallocate( pContext->ServiceRef);
|
|
|
|
(*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj);
|
|
(*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj);
|
|
free( pContext);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis)
|
|
/* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */
|
|
{
|
|
// BlockForData() not supported with AUTO_CALLBACKS
|
|
#if !AUTO_CALLBACKS
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
|
|
if ( contextField != 0)
|
|
{
|
|
OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
|
|
if ( pContext != NULL)
|
|
{
|
|
fd_set readFDs;
|
|
int sd = DNSServiceRefSockFD( pContext->ServiceRef);
|
|
struct timeval timeout = { 1, 0 };
|
|
FD_ZERO( &readFDs);
|
|
FD_SET( sd, &readFDs);
|
|
|
|
// Q: Why do we poll here?
|
|
// A: Because there's no other thread-safe way to do it.
|
|
// Mac OS X terminates a select() call if you close one of the sockets it's listening on, but Linux does not,
|
|
// and arguably Linux is correct (See <http://www.ussg.iu.edu/hypermail/linux/kernel/0405.1/0418.html>)
|
|
// The problem is that the Mac OS X behaviour assumes that it's okay for one thread to close a socket while
|
|
// some other thread is monitoring that socket in select(), but the difficulty is that there's no general way
|
|
// to make that thread-safe, because there's no atomic way to enter select() and release a lock simultaneously.
|
|
// If we try to do this without holding any lock, then right as we jump to the select() routine,
|
|
// some other thread could stop our operation (thereby closing the socket),
|
|
// and then that thread (or even some third, unrelated thread)
|
|
// could do some other DNS-SD operation (or some other operation that opens a new file descriptor)
|
|
// and then we'd blindly resume our fall into the select() call, now blocking on a file descriptor
|
|
// that may coincidentally have the same numerical value, but is semantically unrelated
|
|
// to the true file descriptor we thought we were blocking on.
|
|
// We can't stop this race condition from happening, but at least if we wake up once a second we can detect
|
|
// when fNativeContext has gone to zero, and thereby discover that we were blocking on the wrong fd.
|
|
|
|
if (select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout) == 1) return(1);
|
|
}
|
|
}
|
|
#endif // !AUTO_CALLBACKS
|
|
return(0);
|
|
}
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv *pEnv, jobject pThis)
|
|
/* Call through to DNSServiceProcessResult() while data remains on socket. */
|
|
{
|
|
#if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS
|
|
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
|
|
DNSServiceErrorType err = kDNSServiceErr_BadState;
|
|
|
|
if ( pContext != NULL)
|
|
{
|
|
int sd = DNSServiceRefSockFD( pContext->ServiceRef);
|
|
fd_set readFDs;
|
|
struct timeval zeroTimeout = { 0, 0 };
|
|
|
|
pContext->Env = pEnv;
|
|
|
|
FD_ZERO( &readFDs);
|
|
FD_SET( sd, &readFDs);
|
|
|
|
err = kDNSServiceErr_NoError;
|
|
if (0 < select(sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout))
|
|
{
|
|
err = DNSServiceProcessResult(pContext->ServiceRef);
|
|
// Use caution here!
|
|
// We cannot touch any data structures associated with this operation!
|
|
// The DNSServiceProcessResult() routine should have invoked our callback,
|
|
// and our callback could have terminated the operation with op.stop();
|
|
// and that means HaltOperation() will have been called, which frees pContext.
|
|
// Basically, from here we just have to get out without touching any stale
|
|
// data structures that could blow up on us! Particularly, any attempt
|
|
// to loop here reading more results from the file descriptor is unsafe.
|
|
}
|
|
}
|
|
return err;
|
|
#endif // AUTO_CALLBACKS
|
|
}
|
|
|
|
|
|
static void DNSSD_API ServiceBrowseReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
|
|
DNSServiceErrorType errorCode, const char *serviceName, const char *regtype,
|
|
const char *replyDomain, void *context)
|
|
{
|
|
OpContext *pContext = (OpContext*) context;
|
|
|
|
SetupCallbackState( &pContext->Env);
|
|
|
|
if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
|
|
{
|
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
{
|
|
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
|
|
( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
|
|
pContext->JavaObj, flags, interfaceIndex,
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, regtype),
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
|
|
}
|
|
else
|
|
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
|
|
}
|
|
|
|
TeardownCallbackState();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv *pEnv, jobject pThis,
|
|
jint flags, jint ifIndex, jstring regType, jstring domain)
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
|
|
if ( contextField != 0)
|
|
pContext = NewContext( pEnv, pThis, "serviceFound",
|
|
"(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
|
else
|
|
err = kDNSServiceErr_BadParam;
|
|
|
|
if ( pContext != NULL)
|
|
{
|
|
const char *regStr = SafeGetUTFChars( pEnv, regType);
|
|
const char *domainStr = SafeGetUTFChars( pEnv, domain);
|
|
|
|
pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
|
|
(*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
|
|
"serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
|
|
|
err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext);
|
|
if ( err == kDNSServiceErr_NoError)
|
|
{
|
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
}
|
|
|
|
SafeReleaseUTFChars( pEnv, regType, regStr);
|
|
SafeReleaseUTFChars( pEnv, domain, domainStr);
|
|
}
|
|
else
|
|
err = kDNSServiceErr_NoMemory;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
static void DNSSD_API 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)
|
|
{
|
|
OpContext *pContext = (OpContext*) context;
|
|
jclass txtCls;
|
|
jmethodID txtCtor;
|
|
jbyteArray txtBytes;
|
|
jobject txtObj;
|
|
jbyte *pBytes;
|
|
|
|
SetupCallbackState( &pContext->Env);
|
|
|
|
txtCls = (*pContext->Env)->FindClass( pContext->Env, "com/apple/dnssd/TXTRecord");
|
|
txtCtor = (*pContext->Env)->GetMethodID( pContext->Env, txtCls, "<init>", "([B)V");
|
|
|
|
if ( pContext->ClientObj != NULL && pContext->Callback != NULL && txtCtor != NULL &&
|
|
NULL != ( txtBytes = (*pContext->Env)->NewByteArray( pContext->Env, txtLen)))
|
|
{
|
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
{
|
|
// Since Java ints are defined to be big-endian, we canonicalize 'port' from a 16-bit
|
|
// pattern into a number here.
|
|
port = ( ((unsigned char*) &port)[0] << 8) | ((unsigned char*) &port)[1];
|
|
|
|
// Initialize txtBytes with contents of txtRecord
|
|
pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, txtBytes, NULL);
|
|
memcpy( pBytes, txtRecord, txtLen);
|
|
(*pContext->Env)->ReleaseByteArrayElements( pContext->Env, txtBytes, pBytes, JNI_COMMIT);
|
|
|
|
// Construct txtObj with txtBytes
|
|
txtObj = (*pContext->Env)->NewObject( pContext->Env, txtCls, txtCtor, txtBytes);
|
|
(*pContext->Env)->DeleteLocalRef( pContext->Env, txtBytes);
|
|
|
|
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
|
|
pContext->JavaObj, flags, interfaceIndex,
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, fullname),
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, hosttarget),
|
|
port, txtObj);
|
|
}
|
|
else
|
|
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
|
|
}
|
|
|
|
TeardownCallbackState();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv *pEnv, jobject pThis,
|
|
jint flags, jint ifIndex, jstring serviceName, jstring regType, jstring domain)
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
|
|
if ( contextField != 0)
|
|
pContext = NewContext( pEnv, pThis, "serviceResolved",
|
|
"(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V");
|
|
else
|
|
err = kDNSServiceErr_BadParam;
|
|
|
|
if ( pContext != NULL)
|
|
{
|
|
const char *servStr = SafeGetUTFChars( pEnv, serviceName);
|
|
const char *regStr = SafeGetUTFChars( pEnv, regType);
|
|
const char *domainStr = SafeGetUTFChars( pEnv, domain);
|
|
|
|
err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex,
|
|
servStr, regStr, domainStr, ServiceResolveReply, pContext);
|
|
if ( err == kDNSServiceErr_NoError)
|
|
{
|
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
}
|
|
|
|
SafeReleaseUTFChars( pEnv, serviceName, servStr);
|
|
SafeReleaseUTFChars( pEnv, regType, regStr);
|
|
SafeReleaseUTFChars( pEnv, domain, domainStr);
|
|
}
|
|
else
|
|
err = kDNSServiceErr_NoMemory;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
static void DNSSD_API ServiceRegisterReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags,
|
|
DNSServiceErrorType errorCode, const char *serviceName,
|
|
const char *regType, const char *domain, void *context)
|
|
{
|
|
OpContext *pContext = (OpContext*) context;
|
|
|
|
SetupCallbackState( &pContext->Env);
|
|
|
|
if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
|
|
{
|
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
{
|
|
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
|
|
pContext->JavaObj, flags,
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, regType),
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, domain));
|
|
}
|
|
else
|
|
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
|
|
}
|
|
TeardownCallbackState();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL 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)
|
|
{
|
|
//syslog(LOG_ERR, "BR");
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
jbyte *pBytes;
|
|
jsize numBytes;
|
|
|
|
//syslog(LOG_ERR, "BR: contextField %d", contextField);
|
|
|
|
if ( contextField != 0)
|
|
pContext = NewContext( pEnv, pThis, "serviceRegistered",
|
|
"(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
|
else
|
|
err = kDNSServiceErr_BadParam;
|
|
|
|
if ( pContext != NULL)
|
|
{
|
|
const char *servStr = SafeGetUTFChars( pEnv, serviceName);
|
|
const char *regStr = SafeGetUTFChars( pEnv, regType);
|
|
const char *domainStr = SafeGetUTFChars( pEnv, domain);
|
|
const char *hostStr = SafeGetUTFChars( pEnv, host);
|
|
|
|
//syslog(LOG_ERR, "BR: regStr %s", regStr);
|
|
|
|
// Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a
|
|
// big-endian number into a 16-bit pattern here.
|
|
uint16_t portBits = port;
|
|
portBits = ( ((unsigned char*) &portBits)[0] << 8) | ((unsigned char*) &portBits)[1];
|
|
|
|
pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL;
|
|
numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0;
|
|
|
|
err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr,
|
|
domainStr, hostStr, portBits,
|
|
numBytes, pBytes, ServiceRegisterReply, pContext);
|
|
if ( err == kDNSServiceErr_NoError)
|
|
{
|
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
}
|
|
|
|
if ( pBytes != NULL)
|
|
(*pEnv)->ReleaseByteArrayElements( pEnv, txtRecord, pBytes, 0);
|
|
|
|
SafeReleaseUTFChars( pEnv, serviceName, servStr);
|
|
SafeReleaseUTFChars( pEnv, regType, regStr);
|
|
SafeReleaseUTFChars( pEnv, domain, domainStr);
|
|
SafeReleaseUTFChars( pEnv, host, hostStr);
|
|
}
|
|
else
|
|
err = kDNSServiceErr_NoMemory;
|
|
|
|
return err;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv *pEnv, jobject pThis,
|
|
jint flags, jint rrType, jbyteArray rData, jint ttl, jobject destObj)
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
|
|
jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
jbyte *pBytes;
|
|
jsize numBytes;
|
|
DNSRecordRef recRef;
|
|
|
|
if ( contextField != 0)
|
|
pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
|
|
if ( pContext == NULL || pContext->ServiceRef == NULL)
|
|
return kDNSServiceErr_BadParam;
|
|
|
|
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
|
|
numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
|
|
|
|
err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl);
|
|
if ( err == kDNSServiceErr_NoError)
|
|
{
|
|
(*pEnv)->SetLongField(pEnv, destObj, recField, (long) recRef);
|
|
}
|
|
|
|
if ( pBytes != NULL)
|
|
(*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
|
|
|
|
return err;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Update( JNIEnv *pEnv, jobject pThis,
|
|
jint flags, jbyteArray rData, jint ttl)
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
|
|
jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
jbyte *pBytes;
|
|
jsize numBytes;
|
|
DNSRecordRef recRef = NULL;
|
|
|
|
if ( ownerField != 0)
|
|
{
|
|
jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
|
|
jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
|
|
if ( contextField != 0)
|
|
pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, ownerObj, contextField);
|
|
}
|
|
if ( recField != 0)
|
|
recRef = (DNSRecordRef) (long) (*pEnv)->GetLongField(pEnv, pThis, recField);
|
|
if ( pContext == NULL || pContext->ServiceRef == NULL)
|
|
return kDNSServiceErr_BadParam;
|
|
|
|
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
|
|
numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
|
|
|
|
err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl);
|
|
|
|
if ( pBytes != NULL)
|
|
(*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
|
|
|
|
return err;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv *pEnv, jobject pThis)
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
|
|
jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
DNSRecordRef recRef = NULL;
|
|
|
|
if ( ownerField != 0)
|
|
{
|
|
jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
|
|
jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
|
|
if ( contextField != 0)
|
|
pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, ownerObj, contextField);
|
|
}
|
|
if ( recField != 0)
|
|
recRef = (DNSRecordRef) (long) (*pEnv)->GetLongField(pEnv, pThis, recField);
|
|
if ( pContext == NULL || pContext->ServiceRef == NULL)
|
|
return kDNSServiceErr_BadParam;
|
|
|
|
err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, 0);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection( JNIEnv *pEnv, jobject pThis)
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
|
|
if ( contextField != 0)
|
|
pContext = NewContext( pEnv, pThis, "recordRegistered", "(Lcom/apple/dnssd/DNSRecord;I)V");
|
|
else
|
|
err = kDNSServiceErr_BadParam;
|
|
|
|
if ( pContext != NULL)
|
|
{
|
|
err = DNSServiceCreateConnection( &pContext->ServiceRef);
|
|
if ( err == kDNSServiceErr_NoError)
|
|
{
|
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
}
|
|
}
|
|
else
|
|
err = kDNSServiceErr_NoMemory;
|
|
|
|
return err;
|
|
}
|
|
|
|
struct RecordRegistrationRef
|
|
{
|
|
OpContext *Context;
|
|
jobject RecordObj;
|
|
};
|
|
typedef struct RecordRegistrationRef RecordRegistrationRef;
|
|
|
|
static void DNSSD_API RegisterRecordReply( DNSServiceRef sdRef _UNUSED,
|
|
DNSRecordRef recordRef _UNUSED, DNSServiceFlags flags,
|
|
DNSServiceErrorType errorCode, void *context)
|
|
{
|
|
RecordRegistrationRef *regEnvelope = (RecordRegistrationRef*) context;
|
|
OpContext *pContext = regEnvelope->Context;
|
|
|
|
SetupCallbackState( &pContext->Env);
|
|
|
|
if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
|
|
{
|
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
{
|
|
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
|
|
regEnvelope->RecordObj, flags);
|
|
}
|
|
else
|
|
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
|
|
}
|
|
|
|
(*pContext->Env)->DeleteWeakGlobalRef( pContext->Env, regEnvelope->RecordObj);
|
|
free( regEnvelope);
|
|
|
|
TeardownCallbackState();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL 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)
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
|
|
jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
|
|
const char *nameStr = SafeGetUTFChars( pEnv, fullname);
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
jbyte *pBytes;
|
|
jsize numBytes;
|
|
DNSRecordRef recRef;
|
|
RecordRegistrationRef *regEnvelope;
|
|
|
|
if ( contextField != 0)
|
|
pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
|
|
if ( pContext == NULL || pContext->ServiceRef == NULL || nameStr == NULL)
|
|
return kDNSServiceErr_BadParam;
|
|
|
|
regEnvelope = calloc( 1, sizeof *regEnvelope);
|
|
if ( regEnvelope == NULL)
|
|
return kDNSServiceErr_NoMemory;
|
|
regEnvelope->Context = pContext;
|
|
regEnvelope->RecordObj = (*pEnv)->NewWeakGlobalRef( pEnv, destObj); // must convert local ref to global to cache
|
|
|
|
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
|
|
numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
|
|
|
|
err = DNSServiceRegisterRecord( pContext->ServiceRef, &recRef, flags, ifIndex,
|
|
nameStr, rrType, rrClass, numBytes, pBytes, ttl,
|
|
RegisterRecordReply, regEnvelope);
|
|
|
|
if ( err == kDNSServiceErr_NoError)
|
|
{
|
|
(*pEnv)->SetLongField(pEnv, destObj, recField, (long) recRef);
|
|
}
|
|
else
|
|
{
|
|
if ( regEnvelope->RecordObj != NULL)
|
|
(*pEnv)->DeleteWeakGlobalRef( pEnv, regEnvelope->RecordObj);
|
|
free( regEnvelope);
|
|
}
|
|
|
|
if ( pBytes != NULL)
|
|
(*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
|
|
|
|
SafeReleaseUTFChars( pEnv, fullname, nameStr);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
static void DNSSD_API 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)
|
|
{
|
|
OpContext *pContext = (OpContext*) context;
|
|
jbyteArray rDataObj;
|
|
jbyte *pBytes;
|
|
|
|
SetupCallbackState( &pContext->Env);
|
|
|
|
if ( pContext->ClientObj != NULL && pContext->Callback != NULL &&
|
|
NULL != ( rDataObj = (*pContext->Env)->NewByteArray( pContext->Env, rdlen)))
|
|
{
|
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
{
|
|
// Initialize rDataObj with contents of rdata
|
|
pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, rDataObj, NULL);
|
|
memcpy( pBytes, rdata, rdlen);
|
|
(*pContext->Env)->ReleaseByteArrayElements( pContext->Env, rDataObj, pBytes, JNI_COMMIT);
|
|
|
|
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
|
|
pContext->JavaObj, flags, interfaceIndex,
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
|
|
rrtype, rrclass, rDataObj, ttl);
|
|
}
|
|
else
|
|
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
|
|
}
|
|
TeardownCallbackState();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv *pEnv, jobject pThis,
|
|
jint flags, jint ifIndex, jstring serviceName, jint rrtype, jint rrclass)
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
|
|
if ( contextField != 0)
|
|
pContext = NewContext( pEnv, pThis, "queryAnswered",
|
|
"(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V");
|
|
else
|
|
err = kDNSServiceErr_BadParam;
|
|
|
|
if ( pContext != NULL)
|
|
{
|
|
const char *servStr = SafeGetUTFChars( pEnv, serviceName);
|
|
|
|
err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr,
|
|
rrtype, rrclass, ServiceQueryReply, pContext);
|
|
if ( err == kDNSServiceErr_NoError)
|
|
{
|
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
}
|
|
|
|
SafeReleaseUTFChars( pEnv, serviceName, servStr);
|
|
}
|
|
else
|
|
err = kDNSServiceErr_NoMemory;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
static void DNSSD_API DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
|
|
DNSServiceErrorType errorCode, const char *replyDomain, void *context)
|
|
{
|
|
OpContext *pContext = (OpContext*) context;
|
|
|
|
SetupCallbackState( &pContext->Env);
|
|
|
|
if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
|
|
{
|
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
{
|
|
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
|
|
( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
|
|
pContext->JavaObj, flags, interfaceIndex,
|
|
(*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
|
|
}
|
|
else
|
|
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
|
|
}
|
|
TeardownCallbackState();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv *pEnv, jobject pThis,
|
|
jint flags, jint ifIndex)
|
|
{
|
|
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
|
|
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
|
|
OpContext *pContext = NULL;
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
|
|
if ( contextField != 0)
|
|
pContext = NewContext( pEnv, pThis, "domainFound",
|
|
"(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
|
|
else
|
|
err = kDNSServiceErr_BadParam;
|
|
|
|
if ( pContext != NULL)
|
|
{
|
|
pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
|
|
(*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
|
|
"domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
|
|
|
|
err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex,
|
|
DomainEnumReply, pContext);
|
|
if ( err == kDNSServiceErr_NoError)
|
|
{
|
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
}
|
|
}
|
|
else
|
|
err = kDNSServiceErr_NoMemory;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv *pEnv, jobject pThis _UNUSED,
|
|
jstring serviceName, jstring regtype, jstring domain, jobjectArray pOut)
|
|
{
|
|
DNSServiceErrorType err = kDNSServiceErr_NoError;
|
|
const char *nameStr = SafeGetUTFChars( pEnv, serviceName);
|
|
const char *regStr = SafeGetUTFChars( pEnv, regtype);
|
|
const char *domStr = SafeGetUTFChars( pEnv, domain);
|
|
char buff[ kDNSServiceMaxDomainName + 1];
|
|
|
|
err = DNSServiceConstructFullName( buff, nameStr, regStr, domStr);
|
|
|
|
if ( err == kDNSServiceErr_NoError)
|
|
{
|
|
// pOut is expected to be a String[1] array.
|
|
(*pEnv)->SetObjectArrayElement( pEnv, pOut, 0, (*pEnv)->NewStringUTF( pEnv, buff));
|
|
}
|
|
|
|
SafeReleaseUTFChars( pEnv, serviceName, nameStr);
|
|
SafeReleaseUTFChars( pEnv, regtype, regStr);
|
|
SafeReleaseUTFChars( pEnv, domain, domStr);
|
|
|
|
return err;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv *pEnv, jobject pThis _UNUSED,
|
|
jint flags, jint ifIndex, jstring fullName,
|
|
jint rrtype, jint rrclass, jbyteArray rdata)
|
|
{
|
|
jbyte *pBytes;
|
|
jsize numBytes;
|
|
const char *nameStr = SafeGetUTFChars( pEnv, fullName);
|
|
|
|
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL);
|
|
numBytes = (*pEnv)->GetArrayLength( pEnv, rdata);
|
|
|
|
DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes);
|
|
|
|
if ( pBytes != NULL)
|
|
(*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0);
|
|
|
|
SafeReleaseUTFChars( pEnv, fullName, nameStr);
|
|
}
|
|
|
|
#define LOCAL_ONLY_NAME "loo"
|
|
#define P2P_NAME "p2p"
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv *pEnv, jobject pThis _UNUSED,
|
|
jint ifIndex)
|
|
{
|
|
char *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE];
|
|
|
|
if (ifIndex == (jint) kDNSServiceInterfaceIndexP2P)
|
|
p = P2P_NAME;
|
|
else if (ifIndex != (jint) kDNSServiceInterfaceIndexLocalOnly)
|
|
p = if_indextoname( ifIndex, nameBuff );
|
|
|
|
return (*pEnv)->NewStringUTF( pEnv, p);
|
|
}
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName( JNIEnv *pEnv, jobject pThis _UNUSED,
|
|
jstring ifName)
|
|
{
|
|
uint32_t ifIndex = kDNSServiceInterfaceIndexLocalOnly;
|
|
const char *nameStr = SafeGetUTFChars( pEnv, ifName);
|
|
|
|
if (strcmp(nameStr, P2P_NAME) == 0)
|
|
ifIndex = kDNSServiceInterfaceIndexP2P;
|
|
else if (strcmp(nameStr, LOCAL_ONLY_NAME))
|
|
ifIndex = if_nametoindex( nameStr);
|
|
|
|
SafeReleaseUTFChars( pEnv, ifName, nameStr);
|
|
|
|
return ifIndex;
|
|
}
|
|
|
|
|
|
#if defined(_WIN32)
|
|
static char*
|
|
win32_if_indextoname( DWORD ifIndex, char * nameBuff)
|
|
{
|
|
PIP_ADAPTER_INFO pAdapterInfo = NULL;
|
|
PIP_ADAPTER_INFO pAdapter = NULL;
|
|
DWORD dwRetVal = 0;
|
|
char * ifName = NULL;
|
|
ULONG ulOutBufLen = 0;
|
|
|
|
if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
|
|
|
|
if (pAdapterInfo == NULL)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
|
|
|
|
if (dwRetVal != NO_ERROR)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pAdapter = pAdapterInfo;
|
|
while (pAdapter)
|
|
{
|
|
if (pAdapter->Index == ifIndex)
|
|
{
|
|
// It would be better if we passed in the length of nameBuff to this
|
|
// function, so we would have absolute certainty that no buffer
|
|
// overflows would occur. Buffer overflows *shouldn't* occur because
|
|
// nameBuff is of size MAX_ADAPTER_NAME_LENGTH.
|
|
strcpy( nameBuff, pAdapter->AdapterName );
|
|
ifName = nameBuff;
|
|
break;
|
|
}
|
|
|
|
pAdapter = pAdapter->Next;
|
|
}
|
|
|
|
exit:
|
|
|
|
if (pAdapterInfo != NULL)
|
|
{
|
|
free( pAdapterInfo );
|
|
pAdapterInfo = NULL;
|
|
}
|
|
|
|
return ifName;
|
|
}
|
|
|
|
|
|
static DWORD
|
|
win32_if_nametoindex( const char * nameStr )
|
|
{
|
|
PIP_ADAPTER_INFO pAdapterInfo = NULL;
|
|
PIP_ADAPTER_INFO pAdapter = NULL;
|
|
DWORD dwRetVal = 0;
|
|
DWORD ifIndex = 0;
|
|
ULONG ulOutBufLen = 0;
|
|
|
|
if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
|
|
|
|
if (pAdapterInfo == NULL)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
|
|
|
|
if (dwRetVal != NO_ERROR)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pAdapter = pAdapterInfo;
|
|
while (pAdapter)
|
|
{
|
|
if (strcmp(pAdapter->AdapterName, nameStr) == 0)
|
|
{
|
|
ifIndex = pAdapter->Index;
|
|
break;
|
|
}
|
|
|
|
pAdapter = pAdapter->Next;
|
|
}
|
|
|
|
exit:
|
|
|
|
if (pAdapterInfo != NULL)
|
|
{
|
|
free( pAdapterInfo );
|
|
pAdapterInfo = NULL;
|
|
}
|
|
|
|
return ifIndex;
|
|
}
|
|
#endif
|
|
|
|
|
|
// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
|
|
// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
|
|
// To expand "version" to its value before making the string, use STRINGIFY(version) instead
|
|
#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
|
|
#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
|
|
|
|
// NOT static -- otherwise the compiler may optimize it out
|
|
// The "@(#) " pattern is a special prefix the "what" command looks for
|
|
const char VersionString_SCCS[] = "@(#) libjdns_sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
|