X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/blobdiff_plain/4a95efb2b76a7c3a5d05400dff1773abe5adcf54..83fb1e36c79aee7f897e5ff0e6eeed1d9d526a14:/mDNSVxWorks/mDNSVxWorksIPv4Only.c diff --git a/mDNSVxWorks/mDNSVxWorksIPv4Only.c b/mDNSVxWorks/mDNSVxWorksIPv4Only.c index 83f23c1..efb1f7a 100644 --- a/mDNSVxWorks/mDNSVxWorksIPv4Only.c +++ b/mDNSVxWorks/mDNSVxWorksIPv4Only.c @@ -5,72 +5,72 @@ * 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. - Contains: mDNS platform plugin for VxWorks. + Contains: mDNS platform plugin for VxWorks. - Copyright: Copyright (C) 2002-2004 Apple Computer, Inc., All Rights Reserved. + Copyright: Copyright (C) 2002-2004 Apple Computer, Inc., All Rights Reserved. - Notes for non-Apple platforms: + Notes for non-Apple platforms: - TARGET_NON_APPLE should be defined to 1 to avoid relying on Apple-only header files, macros, or functions. + TARGET_NON_APPLE should be defined to 1 to avoid relying on Apple-only header files, macros, or functions. - To Do: + To Do: - - Add support for IPv6 (needs VxWorks IPv6 support). -*/ + - Add support for IPv6 (needs VxWorks IPv6 support). + */ // Set up the debug library to use the default category (see DebugServicesLite.h for details). -#if( !TARGET_NON_APPLE ) - #define DEBUG_USE_DEFAULT_CATEGORY 1 +#if ( !TARGET_NON_APPLE ) + #define DEBUG_USE_DEFAULT_CATEGORY 1 #endif -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "vxWorks.h" -#include "ifLib.h" -#include "inetLib.h" -#include "pipeDrv.h" -#include "selectLib.h" -#include "semLib.h" -#include "sockLib.h" -#include "sysLib.h" -#include "taskLib.h" -#include "tickLib.h" - -#include "config.h" - -#if( !TARGET_NON_APPLE ) - #include "ACP/ACPUtilities.h" - #include "Support/DebugServicesLite.h" - #include "Support/MiscUtilities.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vxWorks.h" +#include "ifLib.h" +#include "inetLib.h" +#include "pipeDrv.h" +#include "selectLib.h" +#include "semLib.h" +#include "sockLib.h" +#include "sysLib.h" +#include "taskLib.h" +#include "tickLib.h" + +#include "config.h" + +#if ( !TARGET_NON_APPLE ) + #include "ACP/ACPUtilities.h" + #include "Support/DebugServicesLite.h" + #include "Support/MiscUtilities.h" #endif -#include "mDNSEmbeddedAPI.h" +#include "mDNSEmbeddedAPI.h" -#include "mDNSVxWorks.h" +#include "mDNSVxWorks.h" #if 0 #pragma mark == Preprocessor == @@ -80,8 +80,8 @@ // Preprocessor //=========================================================================================================================== -#if( !TARGET_NON_APPLE ) - debug_log_new_default_category( mdns ); +#if ( !TARGET_NON_APPLE ) +debug_log_new_default_category( mdns ); #endif #if 0 @@ -92,27 +92,27 @@ // Constants //=========================================================================================================================== -#define DEBUG_NAME "[mDNS] " +#define DEBUG_NAME "[mDNS] " -#define kMDNSDefaultName "My-Device" +#define kMDNSDefaultName "My-Device" -#define kMDNSTaskName "tMDNS" -#define kMDNSTaskPriority 102 -#define kMDNSTaskStackSize 49152 +#define kMDNSTaskName "tMDNS" +#define kMDNSTaskPriority 102 +#define kMDNSTaskStackSize 49152 -#define kMDNSPipeName "/pipe/mDNS" -#define kMDNSPipeMessageQueueSize 32 -#define kMDNSPipeMessageSize 1 +#define kMDNSPipeName "/pipe/mDNS" +#define kMDNSPipeMessageQueueSize 32 +#define kMDNSPipeMessageSize 1 -#define kInvalidSocketRef -1 +#define kInvalidSocketRef -1 -typedef uint8_t MDNSPipeCommandCode; +typedef uint8_t MDNSPipeCommandCode; enum { - kMDNSPipeCommandCodeInvalid = 0, - kMDNSPipeCommandCodeReschedule = 1, - kMDNSPipeCommandCodeReconfigure = 2, - kMDNSPipeCommandCodeQuit = 3 + kMDNSPipeCommandCodeInvalid = 0, + kMDNSPipeCommandCodeReschedule = 1, + kMDNSPipeCommandCodeReconfigure = 2, + kMDNSPipeCommandCodeQuit = 3 }; #if 0 @@ -123,24 +123,24 @@ enum // Structures //=========================================================================================================================== -typedef int MDNSSocketRef; +typedef int MDNSSocketRef; -struct MDNSInterfaceItem +struct MDNSInterfaceItem { - MDNSInterfaceItem * next; - char name[ 32 ]; - MDNSSocketRef multicastSocketRef; - MDNSSocketRef sendingSocketRef; - NetworkInterfaceInfo hostSet; - mDNSBool hostRegistered; - - int sendMulticastCounter; - int sendUnicastCounter; - int sendErrorCounter; - - int recvCounter; - int recvErrorCounter; - int recvLoopCounter; + MDNSInterfaceItem * next; + char name[ 32 ]; + MDNSSocketRef multicastSocketRef; + MDNSSocketRef sendingSocketRef; + NetworkInterfaceInfo hostSet; + mDNSBool hostRegistered; + + int sendMulticastCounter; + int sendUnicastCounter; + int sendErrorCounter; + + int recvCounter; + int recvErrorCounter; + int recvLoopCounter; }; #if 0 @@ -151,32 +151,32 @@ struct MDNSInterfaceItem // Macros //=========================================================================================================================== -#if( TARGET_NON_APPLE ) - - // Do-nothing versions of the debugging macros for non-Apple platforms. - - #define check(assertion) - #define check_string( assertion, cstring ) - #define check_noerr(err) - #define check_noerr_string( error, cstring ) - #define check_errno( assertion, errno_value ) - #define debug_string( cstring ) - #define require( assertion, label ) do { if( !(assertion) ) goto label; } while(0) - #define require_string( assertion, label, string ) require(assertion, label) - #define require_quiet( assertion, label ) require( assertion, label ) - #define require_noerr( error, label ) do { if( (error) != 0 ) goto label; } while(0) - #define require_noerr_quiet( assertion, label ) require_noerr( assertion, label ) - #define require_noerr_action( error, label, action ) do { if( (error) != 0 ) { {action;}; goto label; } } while(0) - #define require_noerr_action_quiet( assertion, label, action ) require_noerr_action( assertion, label, action ) - #define require_action( assertion, label, action ) do { if( !(assertion) ) { {action;}; goto label; } } while(0) - #define require_action_quiet( assertion, label, action ) require_action( assertion, label, action ) - #define require_action_string( assertion, label, action, cstring ) do { if( !(assertion) ) { {action;}; goto label; } } while(0) - #define require_errno( assertion, errno_value, label ) do { if( !(assertion) ) goto label; } while(0) - #define require_errno_action( assertion, errno_value, label, action ) do { if( !(assertion) ) { {action;}; goto label; } } while(0) - - #define dlog( ARGS... ) - - #define DEBUG_UNUSED( X ) (void)( X ) +#if ( TARGET_NON_APPLE ) + +// Do-nothing versions of the debugging macros for non-Apple platforms. + + #define check(assertion) + #define check_string( assertion, cstring ) + #define check_noerr(err) + #define check_noerr_string( error, cstring ) + #define check_errno( assertion, errno_value ) + #define debug_string( cstring ) + #define require( assertion, label ) do { if( !(assertion) ) goto label;} while(0) + #define require_string( assertion, label, string ) require(assertion, label) + #define require_quiet( assertion, label ) require( assertion, label ) + #define require_noerr( error, label ) do { if( (error) != 0 ) goto label;} while(0) + #define require_noerr_quiet( assertion, label ) require_noerr( assertion, label ) + #define require_noerr_action( error, label, action ) do { if( (error) != 0 ) { {action;}; goto label; } } while(0) + #define require_noerr_action_quiet( assertion, label, action ) require_noerr_action( assertion, label, action ) + #define require_action( assertion, label, action ) do { if( !(assertion) ) { {action;}; goto label; } } while(0) + #define require_action_quiet( assertion, label, action ) require_action( assertion, label, action ) + #define require_action_string( assertion, label, action, cstring ) do { if( !(assertion) ) { {action;}; goto label; } } while(0) + #define require_errno( assertion, errno_value, label ) do { if( !(assertion) ) goto label;} while(0) + #define require_errno_action( assertion, errno_value, label, action ) do { if( !(assertion) ) { {action;}; goto label; } } while(0) + + #define dlog( ARGS... ) + + #define DEBUG_UNUSED( X ) (void)( X ) #endif #if 0 @@ -193,61 +193,61 @@ extern struct ifnet * ifIndexToIfp(int ifIndex); // Platform Internals -mDNSlocal void SetupNames( mDNS * const inMDNS ); -mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ); -mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS ); -mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inAddr, MDNSInterfaceItem **outItem ); -mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, MDNSInterfaceItem *inItem ); +mDNSlocal void SetupNames( mDNS * const inMDNS ); +mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ); +mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS ); +mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inAddr, MDNSInterfaceItem **outItem ); +mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, MDNSInterfaceItem *inItem ); mDNSlocal mStatus - SetupSocket( - mDNS * const inMDNS, - const struct ifaddrs * inAddr, - mDNSIPPort inPort, - MDNSSocketRef * outSocketRef ); +SetupSocket( + mDNS * const inMDNS, + const struct ifaddrs * inAddr, + mDNSIPPort inPort, + MDNSSocketRef * outSocketRef ); // Commands -mDNSlocal mStatus SetupCommandPipe( mDNS * const inMDNS ); -mDNSlocal mStatus TearDownCommandPipe( mDNS * const inMDNS ); -mDNSlocal mStatus SendCommand( const mDNS * const inMDNS, MDNSPipeCommandCode inCommandCode ); -mDNSlocal mStatus ProcessCommand( mDNS * const inMDNS ); -mDNSlocal void ProcessCommandReconfigure( mDNS *inMDNS ); +mDNSlocal mStatus SetupCommandPipe( mDNS * const inMDNS ); +mDNSlocal mStatus TearDownCommandPipe( mDNS * const inMDNS ); +mDNSlocal mStatus SendCommand( const mDNS * const inMDNS, MDNSPipeCommandCode inCommandCode ); +mDNSlocal mStatus ProcessCommand( mDNS * const inMDNS ); +mDNSlocal void ProcessCommandReconfigure( mDNS *inMDNS ); // Threads -mDNSlocal mStatus SetupTask( mDNS * const inMDNS ); -mDNSlocal mStatus TearDownTask( mDNS * const inMDNS ); -mDNSlocal void Task( mDNS *inMDNS ); -mDNSlocal mStatus TaskInit( mDNS *inMDNS ); -mDNSlocal void TaskSetupReadSet( mDNS *inMDNS, fd_set *outReadSet, int *outMaxSocket ); -mDNSlocal void TaskSetupTimeout( mDNS *inMDNS, mDNSs32 inNextTaskTime, struct timeval *outTimeout ); -mDNSlocal void TaskProcessPacket( mDNS *inMDNS, MDNSInterfaceItem *inItem, MDNSSocketRef inSocketRef ); +mDNSlocal mStatus SetupTask( mDNS * const inMDNS ); +mDNSlocal mStatus TearDownTask( mDNS * const inMDNS ); +mDNSlocal void Task( mDNS *inMDNS ); +mDNSlocal mStatus TaskInit( mDNS *inMDNS ); +mDNSlocal void TaskSetupReadSet( mDNS *inMDNS, fd_set *outReadSet, int *outMaxSocket ); +mDNSlocal void TaskSetupTimeout( mDNS *inMDNS, mDNSs32 inNextTaskTime, struct timeval *outTimeout ); +mDNSlocal void TaskProcessPacket( mDNS *inMDNS, MDNSInterfaceItem *inItem, MDNSSocketRef inSocketRef ); // Utilities -#if( TARGET_NON_APPLE ) - mDNSlocal void GenerateUniqueHostName( char *outName, long *ioSeed ); - mDNSlocal void GenerateUniqueDNSName( char *outName, long *ioSeed ); +#if ( TARGET_NON_APPLE ) +mDNSlocal void GenerateUniqueHostName( char *outName, long *ioSeed ); +mDNSlocal void GenerateUniqueDNSName( char *outName, long *ioSeed ); #endif // Platform Accessors -#ifdef __cplusplus - extern "C" { +#ifdef __cplusplus +extern "C" { #endif -typedef struct mDNSPlatformInterfaceInfo mDNSPlatformInterfaceInfo; -struct mDNSPlatformInterfaceInfo +typedef struct mDNSPlatformInterfaceInfo mDNSPlatformInterfaceInfo; +struct mDNSPlatformInterfaceInfo { - const char * name; - mDNSAddr ip; + const char * name; + mDNSAddr ip; }; -mDNSexport mStatus mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID ); -mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo ); +mDNSexport mStatus mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID ); +mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo ); -#ifdef __cplusplus - } +#ifdef __cplusplus +} #endif #if 0 @@ -258,13 +258,13 @@ mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInter // Globals //=========================================================================================================================== -mDNSlocal mDNS * gMDNSPtr = NULL; -mDNSlocal mDNS_PlatformSupport gMDNSPlatformSupport; -mDNSlocal mDNSs32 gMDNSTicksToMicrosecondsMultiplier = 0; +mDNSlocal mDNS * gMDNSPtr = NULL; +mDNSlocal mDNS_PlatformSupport gMDNSPlatformSupport; +mDNSlocal mDNSs32 gMDNSTicksToMicrosecondsMultiplier = 0; // Platform support -mDNSs32 mDNSPlatformOneSecond; +mDNSs32 mDNSPlatformOneSecond; #if 0 #pragma mark - @@ -275,14 +275,14 @@ mDNSs32 mDNSPlatformOneSecond; // mDNSReconfigure //=========================================================================================================================== -void mDNSReconfigure( void ) +void mDNSReconfigure( void ) { - // Send a "reconfigure" command to the MDNS task. - - if( gMDNSPtr ) - { - SendCommand( gMDNSPtr, kMDNSPipeCommandCodeReconfigure ); - } + // Send a "reconfigure" command to the MDNS task. + + if( gMDNSPtr ) + { + SendCommand( gMDNSPtr, kMDNSPipeCommandCodeReconfigure ); + } } #if 0 @@ -294,100 +294,100 @@ void mDNSReconfigure( void ) // mDNSPlatformInit //=========================================================================================================================== -mStatus mDNSPlatformInit( mDNS * const inMDNS ) +mStatus mDNSPlatformInit( mDNS * const inMDNS ) { - mStatus err; - - dlog( kDebugLevelInfo, DEBUG_NAME "platform init\n" ); - - // Initialize variables. - - mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) ); - inMDNS->p = &gMDNSPlatformSupport; - inMDNS->p->commandPipe = ERROR; - inMDNS->p->task = ERROR; - inMDNS->p->rescheduled = 1; // Default to rescheduled until fully initialized. - mDNSPlatformOneSecond = sysClkRateGet(); - gMDNSTicksToMicrosecondsMultiplier = ( 1000000L / mDNSPlatformOneSecond ); - - // Allocate semaphores. - - inMDNS->p->lockID = semMCreate( SEM_Q_FIFO ); - require_action( inMDNS->p->lockID, exit, err = mStatus_NoMemoryErr ); - - inMDNS->p->readyEvent = semBCreate( SEM_Q_FIFO, SEM_EMPTY ); - require_action( inMDNS->p->readyEvent, exit, err = mStatus_NoMemoryErr ); - - inMDNS->p->quitEvent = semBCreate( SEM_Q_FIFO, SEM_EMPTY ); - require_action( inMDNS->p->quitEvent, exit, err = mStatus_NoMemoryErr ); - - gMDNSPtr = inMDNS; - - // Set up the task and wait for it to initialize. Initialization is done from the task instead of here to avoid - // stack space issues. Some of the initialization may require a larger stack than the current task supports. - - err = SetupTask( inMDNS ); - require_noerr( err, exit ); - - err = semTake( inMDNS->p->readyEvent, WAIT_FOREVER ); - require_noerr( err, exit ); - err = inMDNS->p->taskInitErr; - require_noerr( err, exit ); - - mDNSCoreInitComplete( inMDNS, err ); - + mStatus err; + + dlog( kDebugLevelInfo, DEBUG_NAME "platform init\n" ); + + // Initialize variables. + + mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) ); + inMDNS->p = &gMDNSPlatformSupport; + inMDNS->p->commandPipe = ERROR; + inMDNS->p->task = ERROR; + inMDNS->p->rescheduled = 1; // Default to rescheduled until fully initialized. + mDNSPlatformOneSecond = sysClkRateGet(); + gMDNSTicksToMicrosecondsMultiplier = ( 1000000L / mDNSPlatformOneSecond ); + + // Allocate semaphores. + + inMDNS->p->lockID = semMCreate( SEM_Q_FIFO ); + require_action( inMDNS->p->lockID, exit, err = mStatus_NoMemoryErr ); + + inMDNS->p->readyEvent = semBCreate( SEM_Q_FIFO, SEM_EMPTY ); + require_action( inMDNS->p->readyEvent, exit, err = mStatus_NoMemoryErr ); + + inMDNS->p->quitEvent = semBCreate( SEM_Q_FIFO, SEM_EMPTY ); + require_action( inMDNS->p->quitEvent, exit, err = mStatus_NoMemoryErr ); + + gMDNSPtr = inMDNS; + + // Set up the task and wait for it to initialize. Initialization is done from the task instead of here to avoid + // stack space issues. Some of the initialization may require a larger stack than the current task supports. + + err = SetupTask( inMDNS ); + require_noerr( err, exit ); + + err = semTake( inMDNS->p->readyEvent, WAIT_FOREVER ); + require_noerr( err, exit ); + err = inMDNS->p->taskInitErr; + require_noerr( err, exit ); + + mDNSCoreInitComplete( inMDNS, err ); + exit: - if( err ) - { - mDNSPlatformClose( inMDNS ); - } - dlog( kDebugLevelInfo, DEBUG_NAME "platform init done (err=%ld)\n", err ); - return( err ); + if( err ) + { + mDNSPlatformClose( inMDNS ); + } + dlog( kDebugLevelInfo, DEBUG_NAME "platform init done (err=%ld)\n", err ); + return( err ); } //=========================================================================================================================== // mDNSPlatformClose //=========================================================================================================================== -void mDNSPlatformClose( mDNS * const inMDNS ) +void mDNSPlatformClose( mDNS * const inMDNS ) { - mStatus err; - - dlog( kDebugLevelInfo, DEBUG_NAME "platform close\n" ); - check( inMDNS ); - - // Tear everything down. - - err = TearDownTask( inMDNS ); - check_noerr( err ); - - err = TearDownInterfaceList( inMDNS ); - check_noerr( err ); - - err = TearDownCommandPipe( inMDNS ); - check_noerr( err ); - - gMDNSPtr = NULL; - - // Release semaphores. - - if( inMDNS->p->quitEvent ) - { - semDelete( inMDNS->p->quitEvent ); - inMDNS->p->quitEvent = 0; - } - if( inMDNS->p->readyEvent ) - { - semDelete( inMDNS->p->readyEvent ); - inMDNS->p->readyEvent = 0; - } - if( inMDNS->p->lockID ) - { - semDelete( inMDNS->p->lockID ); - inMDNS->p->lockID = 0; - } - - dlog( kDebugLevelInfo, DEBUG_NAME "platform close done\n" ); + mStatus err; + + dlog( kDebugLevelInfo, DEBUG_NAME "platform close\n" ); + check( inMDNS ); + + // Tear everything down. + + err = TearDownTask( inMDNS ); + check_noerr( err ); + + err = TearDownInterfaceList( inMDNS ); + check_noerr( err ); + + err = TearDownCommandPipe( inMDNS ); + check_noerr( err ); + + gMDNSPtr = NULL; + + // Release semaphores. + + if( inMDNS->p->quitEvent ) + { + semDelete( inMDNS->p->quitEvent ); + inMDNS->p->quitEvent = 0; + } + if( inMDNS->p->readyEvent ) + { + semDelete( inMDNS->p->readyEvent ); + inMDNS->p->readyEvent = 0; + } + if( inMDNS->p->lockID ) + { + semDelete( inMDNS->p->lockID ); + inMDNS->p->lockID = 0; + } + + dlog( kDebugLevelInfo, DEBUG_NAME "platform close done\n" ); } //=========================================================================================================================== @@ -395,73 +395,73 @@ void mDNSPlatformClose( mDNS * const inMDNS ) //=========================================================================================================================== mStatus - mDNSPlatformSendUDP( - const mDNS * const inMDNS, - const void * const inMsg, - const mDNSu8 * const inMsgEnd, - mDNSInterfaceID inInterfaceID, - const mDNSAddr * inDstIP, - mDNSIPPort inDstPort ) +mDNSPlatformSendUDP( + const mDNS * const inMDNS, + const void * const inMsg, + const mDNSu8 * const inMsgEnd, + mDNSInterfaceID inInterfaceID, + const mDNSAddr * inDstIP, + mDNSIPPort inDstPort ) { - mStatus err; - MDNSInterfaceItem * item; - struct sockaddr_in addr; - int n; - - dlog( kDebugLevelChatty, DEBUG_NAME "platform send UDP\n" ); - - // Check parameters. - - check( inMDNS ); - check( inMsg ); - check( inMsgEnd ); - check( inInterfaceID ); - check( inDstIP ); - if( inDstIP->type != mDNSAddrType_IPv4 ) - { - err = mStatus_BadParamErr; - goto exit; - } - -#if( DEBUG ) - // Make sure the InterfaceID is valid. - - for( item = inMDNS->p->interfaceList; item; item = item->next ) - { - if( item == (MDNSInterfaceItem *) inInterfaceID ) - { - break; - } - } - require_action( item, exit, err = mStatus_NoSuchNameErr ); + mStatus err; + MDNSInterfaceItem * item; + struct sockaddr_in addr; + int n; + + dlog( kDebugLevelChatty, DEBUG_NAME "platform send UDP\n" ); + + // Check parameters. + + check( inMDNS ); + check( inMsg ); + check( inMsgEnd ); + check( inInterfaceID ); + check( inDstIP ); + if( inDstIP->type != mDNSAddrType_IPv4 ) + { + err = mStatus_BadParamErr; + goto exit; + } + +#if ( DEBUG ) + // Make sure the InterfaceID is valid. + + for( item = inMDNS->p->interfaceList; item; item = item->next ) + { + if( item == (MDNSInterfaceItem *) inInterfaceID ) + { + break; + } + } + require_action( item, exit, err = mStatus_NoSuchNameErr ); #endif - // Send the packet. - - item = (MDNSInterfaceItem *) inInterfaceID; - check( item->sendingSocketRef != kInvalidSocketRef ); - - mDNSPlatformMemZero( &addr, sizeof( addr ) ); - addr.sin_family = AF_INET; - addr.sin_port = inDstPort.NotAnInteger; - addr.sin_addr.s_addr = inDstIP->ip.v4.NotAnInteger; - - n = inMsgEnd - ( (const mDNSu8 * const) inMsg ); - n = sendto( item->sendingSocketRef, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) ); - check_errno( n, errno ); - - item->sendErrorCounter += ( n < 0 ); - item->sendMulticastCounter += ( inDstPort.NotAnInteger == MulticastDNSPort.NotAnInteger ); - item->sendUnicastCounter += ( inDstPort.NotAnInteger != MulticastDNSPort.NotAnInteger ); - - dlog( kDebugLevelChatty, DEBUG_NAME "sent (to=%u.%u.%u.%u:%hu)\n", - inDstIP->ip.v4.b[ 0 ], inDstIP->ip.v4.b[ 1 ], inDstIP->ip.v4.b[ 2 ], inDstIP->ip.v4.b[ 3 ], - htons( inDstPort.NotAnInteger ) ); - err = mStatus_NoError; + // Send the packet. + + item = (MDNSInterfaceItem *) inInterfaceID; + check( item->sendingSocketRef != kInvalidSocketRef ); + + mDNSPlatformMemZero( &addr, sizeof( addr ) ); + addr.sin_family = AF_INET; + addr.sin_port = inDstPort.NotAnInteger; + addr.sin_addr.s_addr = inDstIP->ip.v4.NotAnInteger; + + n = inMsgEnd - ( (const mDNSu8 * const) inMsg ); + n = sendto( item->sendingSocketRef, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) ); + check_errno( n, errno ); + + item->sendErrorCounter += ( n < 0 ); + item->sendMulticastCounter += ( inDstPort.NotAnInteger == MulticastDNSPort.NotAnInteger ); + item->sendUnicastCounter += ( inDstPort.NotAnInteger != MulticastDNSPort.NotAnInteger ); + + dlog( kDebugLevelChatty, DEBUG_NAME "sent (to=%u.%u.%u.%u:%hu)\n", + inDstIP->ip.v4.b[ 0 ], inDstIP->ip.v4.b[ 1 ], inDstIP->ip.v4.b[ 2 ], inDstIP->ip.v4.b[ 3 ], + htons( inDstPort.NotAnInteger ) ); + err = mStatus_NoError; exit: - dlog( kDebugLevelChatty, DEBUG_NAME "platform send UDP done\n" ); - return( err ); + dlog( kDebugLevelChatty, DEBUG_NAME "platform send UDP done\n" ); + return( err ); } //=========================================================================================================================== @@ -469,87 +469,87 @@ exit: //=========================================================================================================================== mDNSexport mStatus mDNSPlatformTCPConnect(const mDNSAddr *dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID, - TCPConnectionCallback callback, void *context, int *descriptor) - { - (void)dst; // Unused - (void)dstport; // Unused - (void)InterfaceID; // Unused - (void)callback; // Unused - (void)context; // Unused - (void)descriptor; // Unused - return(mStatus_UnsupportedErr); - } + TCPConnectionCallback callback, void *context, int *descriptor) +{ + (void)dst; // Unused + (void)dstport; // Unused + (void)InterfaceID; // Unused + (void)callback; // Unused + (void)context; // Unused + (void)descriptor; // Unused + return(mStatus_UnsupportedErr); +} mDNSexport void mDNSPlatformTCPCloseConnection(int sd) - { - (void)sd; // Unused - } +{ + (void)sd; // Unused +} mDNSexport long mDNSPlatformReadTCP(int sd, void *buf, unsigned long buflen) - { - (void)sd; // Unused - (void)buf; // Unused - (void)buflen; // Unused - return(0); - } +{ + (void)sd; // Unused + (void)buf; // Unused + (void)buflen; // Unused + return(0); +} mDNSexport long mDNSPlatformWriteTCP(int sd, const char *msg, unsigned long len) - { - (void)sd; // Unused - (void)msg; // Unused - (void)len; // Unused - return(0); - } +{ + (void)sd; // Unused + (void)msg; // Unused + (void)len; // Unused + return(0); +} //=========================================================================================================================== // mDNSPlatformLock //=========================================================================================================================== -void mDNSPlatformLock( const mDNS * const inMDNS ) +void mDNSPlatformLock( const mDNS * const inMDNS ) { - check( inMDNS->p->lockID ); - - if( inMDNS->p->lockID ) - { - #if( TARGET_NON_APPLE ) - semTake( inMDNS->p->lockID, WAIT_FOREVER ); - #else - semTakeDeadlockDetect( inMDNS->p->lockID, WAIT_FOREVER ); - #endif - } + check( inMDNS->p->lockID ); + + if( inMDNS->p->lockID ) + { + #if ( TARGET_NON_APPLE ) + semTake( inMDNS->p->lockID, WAIT_FOREVER ); + #else + semTakeDeadlockDetect( inMDNS->p->lockID, WAIT_FOREVER ); + #endif + } } //=========================================================================================================================== // mDNSPlatformUnlock //=========================================================================================================================== -void mDNSPlatformUnlock( const mDNS * const inMDNS ) +void mDNSPlatformUnlock( const mDNS * const inMDNS ) { - check( inMDNS ); - check( inMDNS->p ); - check( inMDNS->p->lockID ); - check_string( inMDNS->p->task != ERROR, "mDNS task not started" ); - - // When an API routine is called, "m->NextScheduledEvent" is reset to "timenow" before calling mDNSPlatformUnlock() - // Since our main mDNS_Execute() loop is on a different thread, we need to wake up that thread to: - // (a) handle immediate work (if any) resulting from this API call - // (b) calculate the next sleep time between now and the next interesting event - - if( ( mDNS_TimeNow(inMDNS) - inMDNS->NextScheduledEvent ) >= 0 ) - { - // We only need to send the reschedule event when called from a task other than the mDNS task since if we are - // called from mDNS task, we'll loop back and call mDNS_Execute. This avoids filling up the command queue. - - if( ( inMDNS->p->rescheduled++ == 0 ) && ( taskIdSelf() != inMDNS->p->task ) ) - { - SendCommand( inMDNS, kMDNSPipeCommandCodeReschedule ); - } - } - - if( inMDNS->p->lockID ) - { - semGive( inMDNS->p->lockID ); - } + check( inMDNS ); + check( inMDNS->p ); + check( inMDNS->p->lockID ); + check_string( inMDNS->p->task != ERROR, "mDNS task not started" ); + + // When an API routine is called, "m->NextScheduledEvent" is reset to "timenow" before calling mDNSPlatformUnlock() + // Since our main mDNS_Execute() loop is on a different thread, we need to wake up that thread to: + // (a) handle immediate work (if any) resulting from this API call + // (b) calculate the next sleep time between now and the next interesting event + + if( ( mDNS_TimeNow(inMDNS) - inMDNS->NextScheduledEvent ) >= 0 ) + { + // We only need to send the reschedule event when called from a task other than the mDNS task since if we are + // called from mDNS task, we'll loop back and call mDNS_Execute. This avoids filling up the command queue. + + if( ( inMDNS->p->rescheduled++ == 0 ) && ( taskIdSelf() != inMDNS->p->task ) ) + { + SendCommand( inMDNS, kMDNSPipeCommandCodeReschedule ); + } + } + + if( inMDNS->p->lockID ) + { + semGive( inMDNS->p->lockID ); + } } //=========================================================================================================================== @@ -558,83 +558,83 @@ void mDNSPlatformUnlock( const mDNS * const inMDNS ) mDNSu32 mDNSPlatformStrLen( const void *inSrc ) { - check( inSrc ); - - return( (mDNSu32) strlen( (const char *) inSrc ) ); + check( inSrc ); + + return( (mDNSu32) strlen( (const char *) inSrc ) ); } //=========================================================================================================================== // mDNSPlatformStrCopy //=========================================================================================================================== -void mDNSPlatformStrCopy( void *inDst, const void *inSrc ) +void mDNSPlatformStrCopy( void *inDst, const void *inSrc ) { - check( inSrc ); - check( inDst ); - - strcpy( (char *) inDst, (const char*) inSrc ); + check( inSrc ); + check( inDst ); + + strcpy( (char *) inDst, (const char*) inSrc ); } //=========================================================================================================================== // mDNSPlatformMemCopy //=========================================================================================================================== -void mDNSPlatformMemCopy( void *inDst, const void *inSrc, mDNSu32 inSize ) +void mDNSPlatformMemCopy( void *inDst, const void *inSrc, mDNSu32 inSize ) { - check( inSrc ); - check( inDst ); - - memcpy( inDst, inSrc, inSize ); + check( inSrc ); + check( inDst ); + + memcpy( inDst, inSrc, inSize ); } //=========================================================================================================================== // mDNSPlatformMemSame //=========================================================================================================================== -mDNSBool mDNSPlatformMemSame( const void *inDst, const void *inSrc, mDNSu32 inSize ) +mDNSBool mDNSPlatformMemSame( const void *inDst, const void *inSrc, mDNSu32 inSize ) { - check( inSrc ); - check( inDst ); - - return( memcmp( inSrc, inDst, inSize ) == 0 ); + check( inSrc ); + check( inDst ); + + return( memcmp( inSrc, inDst, inSize ) == 0 ); } //=========================================================================================================================== // mDNSPlatformMemZero //=========================================================================================================================== -void mDNSPlatformMemZero( void *inDst, mDNSu32 inSize ) +void mDNSPlatformMemZero( void *inDst, mDNSu32 inSize ) { - check( inDst ); - - memset( inDst, 0, inSize ); + check( inDst ); + + memset( inDst, 0, inSize ); } //=========================================================================================================================== // mDNSPlatformMemAllocate //=========================================================================================================================== -mDNSexport void * mDNSPlatformMemAllocate( mDNSu32 inSize ) +mDNSexport void * mDNSPlatformMemAllocate( mDNSu32 inSize ) { - void * mem; - - check( inSize > 0 ); - - mem = malloc( inSize ); - check( mem ); - - return( mem ); + void * mem; + + check( inSize > 0 ); + + mem = malloc( inSize ); + check( mem ); + + return( mem ); } //=========================================================================================================================== // mDNSPlatformMemFree //=========================================================================================================================== -mDNSexport void mDNSPlatformMemFree( void *inMem ) +mDNSexport void mDNSPlatformMemFree( void *inMem ) { - check( inMem ); - - free( inMem ); + check( inMem ); + + free( inMem ); } //=========================================================================================================================== @@ -643,7 +643,7 @@ mDNSexport void mDNSPlatformMemFree( void *inMem ) mDNSexport mDNSu32 mDNSPlatformRandomSeed(void) { - return( tickGet() ); + return( tickGet() ); } //=========================================================================================================================== @@ -652,122 +652,122 @@ mDNSexport mDNSu32 mDNSPlatformRandomSeed(void) mDNSexport mStatus mDNSPlatformTimeInit( void ) { - // No special setup is required on VxWorks -- we just use tickGet(). - return( mStatus_NoError ); + // No special setup is required on VxWorks -- we just use tickGet(). + return( mStatus_NoError ); } //=========================================================================================================================== // mDNSPlatformRawTime //=========================================================================================================================== -mDNSs32 mDNSPlatformRawTime( void ) +mDNSs32 mDNSPlatformRawTime( void ) { - return( (mDNSs32) tickGet() ); + return( (mDNSs32) tickGet() ); } //=========================================================================================================================== // mDNSPlatformUTC //=========================================================================================================================== -mDNSexport mDNSs32 mDNSPlatformUTC( void ) +mDNSexport mDNSs32 mDNSPlatformUTC( void ) { - return( -1 ); + return( -1 ); } //=========================================================================================================================== // mDNSPlatformInterfaceNameToID //=========================================================================================================================== -mStatus mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID ) +mStatus mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID ) { - mStatus err; - MDNSInterfaceItem * ifd; - - check( inMDNS ); - check( inMDNS->p ); - check( inName ); - - // Search for an interface with the specified name, - - for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next ) - { - if( strcmp( ifd->name, inName ) == 0 ) - { - break; - } - } - if( !ifd ) - { - err = mStatus_NoSuchNameErr; - goto exit; - } - - // Success! - - if( outID ) - { - *outID = (mDNSInterfaceID) ifd; - } - err = mStatus_NoError; - + mStatus err; + MDNSInterfaceItem * ifd; + + check( inMDNS ); + check( inMDNS->p ); + check( inName ); + + // Search for an interface with the specified name, + + for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next ) + { + if( strcmp( ifd->name, inName ) == 0 ) + { + break; + } + } + if( !ifd ) + { + err = mStatus_NoSuchNameErr; + goto exit; + } + + // Success! + + if( outID ) + { + *outID = (mDNSInterfaceID) ifd; + } + err = mStatus_NoError; + exit: - return( err ); + return( err ); } //=========================================================================================================================== // mDNSPlatformInterfaceIDToInfo //=========================================================================================================================== -mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo ) +mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo ) { - mStatus err; - MDNSInterfaceItem * ifd; - - check( inMDNS ); - check( inID ); - check( outInfo ); - - // Search for an interface with the specified ID, - - for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next ) - { - if( ifd == (MDNSInterfaceItem *) inID ) - { - break; - } - } - if( !ifd ) - { - err = mStatus_NoSuchNameErr; - goto exit; - } - - // Success! - - outInfo->name = ifd->name; - outInfo->ip = ifd->hostSet.ip; - err = mStatus_NoError; - + mStatus err; + MDNSInterfaceItem * ifd; + + check( inMDNS ); + check( inID ); + check( outInfo ); + + // Search for an interface with the specified ID, + + for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next ) + { + if( ifd == (MDNSInterfaceItem *) inID ) + { + break; + } + } + if( !ifd ) + { + err = mStatus_NoSuchNameErr; + goto exit; + } + + // Success! + + outInfo->name = ifd->name; + outInfo->ip = ifd->hostSet.ip; + err = mStatus_NoError; + exit: - return( err ); + return( err ); } //=========================================================================================================================== // debugf_ //=========================================================================================================================== -#if( MDNS_DEBUGMSGS ) +#if ( MDNS_DEBUGMSGS ) mDNSexport void debugf_( const char *format, ... ) { - char buffer[ 512 ]; - va_list args; - mDNSu32 length; - - va_start( args, format ); - length = mDNS_vsnprintf( buffer, sizeof( buffer ), format, args ); - va_end( args ); - - dlog( kDebugLevelInfo, "%s\n", buffer ); + char buffer[ 512 ]; + va_list args; + mDNSu32 length; + + va_start( args, format ); + length = mDNS_vsnprintf( buffer, sizeof( buffer ), format, args ); + va_end( args ); + + dlog( kDebugLevelInfo, "%s\n", buffer ); } #endif @@ -775,18 +775,18 @@ mDNSexport void debugf_( const char *format, ... ) // verbosedebugf_ //=========================================================================================================================== -#if( MDNS_DEBUGMSGS > 1 ) +#if ( MDNS_DEBUGMSGS > 1 ) mDNSexport void verbosedebugf_( const char *format, ... ) { - char buffer[ 512 ]; - va_list args; - mDNSu32 length; - - va_start( args, format ); - length = mDNS_vsnprintf( buffer, sizeof( buffer ), format, args ); - va_end( args ); - - dlog( kDebugLevelVerbose, "%s\n", buffer ); + char buffer[ 512 ]; + va_list args; + mDNSu32 length; + + va_start( args, format ); + length = mDNS_vsnprintf( buffer, sizeof( buffer ), format, args ); + va_end( args ); + + dlog( kDebugLevelVerbose, "%s\n", buffer ); } #endif @@ -796,15 +796,15 @@ mDNSexport void verbosedebugf_( const char *format, ... ) void LogMsg( const char *inFormat, ... ) { - char buffer[ 512 ]; - va_list args; - mDNSu32 length; - - va_start( args, inFormat ); - length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args ); - va_end( args ); - - dlog( kDebugLevelWarning, "%s\n", buffer ); + char buffer[ 512 ]; + va_list args; + mDNSu32 length; + + va_start( args, inFormat ); + length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args ); + va_end( args ); + + dlog( kDebugLevelWarning, "%s\n", buffer ); } #if 0 @@ -816,261 +816,261 @@ void LogMsg( const char *inFormat, ... ) // SetupNames //=========================================================================================================================== -mDNSlocal void SetupNames( mDNS * const inMDNS ) +mDNSlocal void SetupNames( mDNS * const inMDNS ) { - char tempCString[ 128 ]; - mDNSu8 tempPString[ 128 ]; - mDNSu8 * namePtr; - - // Set up the host name. - - tempCString[ 0 ] = '\0'; - GenerateUniqueHostName( tempCString, NULL ); - check( tempCString[ 0 ] != '\0' ); - if( tempCString[ 0 ] == '\0' ) - { - // No name so use the default. - - strcpy( tempCString, kMDNSDefaultName ); - } - inMDNS->nicelabel.c[ 0 ] = strlen( tempCString ); - memcpy( &inMDNS->nicelabel.c[ 1 ], tempCString, inMDNS->nicelabel.c[ 0 ] ); - check( inMDNS->nicelabel.c[ 0 ] > 0 ); - - // Set up the DNS name. - - tempCString[ 0 ] = '\0'; - GenerateUniqueDNSName( tempCString, NULL ); - if( tempCString[ 0 ] != '\0' ) - { - tempPString[ 0 ] = strlen( tempCString ); - memcpy( &tempPString[ 1 ], tempCString, tempPString[ 0 ] ); - namePtr = tempPString; - } - else - { - // No DNS name so use the host name. - - namePtr = inMDNS->nicelabel.c; - } - ConvertUTF8PstringToRFC1034HostLabel( namePtr, &inMDNS->hostlabel ); - if( inMDNS->hostlabel.c[ 0 ] == 0 ) - { - // Nice name has no characters that are representable as an RFC 1034 name (e.g. Japanese) so use the default. - - MakeDomainLabelFromLiteralString( &inMDNS->hostlabel, kMDNSDefaultName ); - } - check( inMDNS->hostlabel.c[ 0 ] > 0 ); - - mDNS_SetFQDN( inMDNS ); - - dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] ); - dlog( kDebugLevelInfo, DEBUG_NAME "host name \"%.*s\"\n", inMDNS->hostlabel.c[ 0 ], &inMDNS->hostlabel.c[ 1 ] ); + char tempCString[ 128 ]; + mDNSu8 tempPString[ 128 ]; + mDNSu8 * namePtr; + + // Set up the host name. + + tempCString[ 0 ] = '\0'; + GenerateUniqueHostName( tempCString, NULL ); + check( tempCString[ 0 ] != '\0' ); + if( tempCString[ 0 ] == '\0' ) + { + // No name so use the default. + + strcpy( tempCString, kMDNSDefaultName ); + } + inMDNS->nicelabel.c[ 0 ] = strlen( tempCString ); + memcpy( &inMDNS->nicelabel.c[ 1 ], tempCString, inMDNS->nicelabel.c[ 0 ] ); + check( inMDNS->nicelabel.c[ 0 ] > 0 ); + + // Set up the DNS name. + + tempCString[ 0 ] = '\0'; + GenerateUniqueDNSName( tempCString, NULL ); + if( tempCString[ 0 ] != '\0' ) + { + tempPString[ 0 ] = strlen( tempCString ); + memcpy( &tempPString[ 1 ], tempCString, tempPString[ 0 ] ); + namePtr = tempPString; + } + else + { + // No DNS name so use the host name. + + namePtr = inMDNS->nicelabel.c; + } + ConvertUTF8PstringToRFC1034HostLabel( namePtr, &inMDNS->hostlabel ); + if( inMDNS->hostlabel.c[ 0 ] == 0 ) + { + // Nice name has no characters that are representable as an RFC 1034 name (e.g. Japanese) so use the default. + + MakeDomainLabelFromLiteralString( &inMDNS->hostlabel, kMDNSDefaultName ); + } + check( inMDNS->hostlabel.c[ 0 ] > 0 ); + + mDNS_SetFQDN( inMDNS ); + + dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] ); + dlog( kDebugLevelInfo, DEBUG_NAME "host name \"%.*s\"\n", inMDNS->hostlabel.c[ 0 ], &inMDNS->hostlabel.c[ 1 ] ); } //=========================================================================================================================== // SetupInterfaceList //=========================================================================================================================== -mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) +mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS ) { - mStatus err; - struct ifaddrs * addrs; - struct ifaddrs * p; - uint32_t flagMask; - uint32_t flagTest; - MDNSInterfaceItem ** next; - MDNSInterfaceItem * item; - - addrs = NULL; - - dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface list\n" ); - check( inMDNS ); - - // Tear down any existing interfaces that may be set up. - - TearDownInterfaceList( inMDNS ); - inMDNS->p->interfaceList = NULL; - next = &inMDNS->p->interfaceList; - - // Set up each interface that is active, multicast-capable, and not the loopback interface or point-to-point. - - flagMask = IFF_UP | IFF_MULTICAST | IFF_LOOPBACK | IFF_POINTOPOINT; - flagTest = IFF_UP | IFF_MULTICAST; - - err = getifaddrs( &addrs ); - require_noerr( err, exit ); - - for( p = addrs; p; p = p->ifa_next ) - { - if( ( p->ifa_flags & flagMask ) == flagTest ) - { - err = SetupInterface( inMDNS, p, &item ); - require_noerr( err, exit ); - - *next = item; - next = &item->next; - } - } - err = mStatus_NoError; - + mStatus err; + struct ifaddrs * addrs; + struct ifaddrs * p; + uint32_t flagMask; + uint32_t flagTest; + MDNSInterfaceItem ** next; + MDNSInterfaceItem * item; + + addrs = NULL; + + dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface list\n" ); + check( inMDNS ); + + // Tear down any existing interfaces that may be set up. + + TearDownInterfaceList( inMDNS ); + inMDNS->p->interfaceList = NULL; + next = &inMDNS->p->interfaceList; + + // Set up each interface that is active, multicast-capable, and not the loopback interface or point-to-point. + + flagMask = IFF_UP | IFF_MULTICAST | IFF_LOOPBACK | IFF_POINTOPOINT; + flagTest = IFF_UP | IFF_MULTICAST; + + err = getifaddrs( &addrs ); + require_noerr( err, exit ); + + for( p = addrs; p; p = p->ifa_next ) + { + if( ( p->ifa_flags & flagMask ) == flagTest ) + { + err = SetupInterface( inMDNS, p, &item ); + require_noerr( err, exit ); + + *next = item; + next = &item->next; + } + } + err = mStatus_NoError; + exit: - if( addrs ) - { - freeifaddrs( addrs ); - } - if( err ) - { - TearDownInterfaceList( inMDNS ); - } - dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface list done (err=%ld)\n", err ); - return( err ); + if( addrs ) + { + freeifaddrs( addrs ); + } + if( err ) + { + TearDownInterfaceList( inMDNS ); + } + dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface list done (err=%ld)\n", err ); + return( err ); } //=========================================================================================================================== // TearDownInterfaceList //=========================================================================================================================== -mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS ) +mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS ) { - dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down interface list\n" ); - check( inMDNS ); - - // Tear down all the interfaces. - - while( inMDNS->p->interfaceList ) - { - MDNSInterfaceItem * item; - - item = inMDNS->p->interfaceList; - inMDNS->p->interfaceList = item->next; - - TearDownInterface( inMDNS, item ); - } - - dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down interface list done\n" ); - return( mStatus_NoError ); + dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down interface list\n" ); + check( inMDNS ); + + // Tear down all the interfaces. + + while( inMDNS->p->interfaceList ) + { + MDNSInterfaceItem * item; + + item = inMDNS->p->interfaceList; + inMDNS->p->interfaceList = item->next; + + TearDownInterface( inMDNS, item ); + } + + dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down interface list done\n" ); + return( mStatus_NoError ); } //=========================================================================================================================== // SetupInterface //=========================================================================================================================== -mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inAddr, MDNSInterfaceItem **outItem ) +mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inAddr, MDNSInterfaceItem **outItem ) { - mStatus err; - MDNSInterfaceItem * item; - MDNSSocketRef socketRef; - const struct sockaddr_in * ipv4, *mask; - - dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface (name=%s)\n", inAddr->ifa_name ); - check( inMDNS ); - check( inAddr ); - check( inAddr->ifa_addr ); - ipv4 = (const struct sockaddr_in *) inAddr->ifa_addr; - mask = (const struct sockaddr_in *) inAddr->ifa_netmask; - check( outItem ); - - // Allocate memory for the info item. - - item = (MDNSInterfaceItem *) calloc( 1, sizeof( *item ) ); - require_action( item, exit, err = mStatus_NoMemoryErr ); - strcpy( item->name, inAddr->ifa_name ); - item->multicastSocketRef = kInvalidSocketRef; - item->sendingSocketRef = kInvalidSocketRef; - - // Set up the multicast DNS (port 5353) socket for this interface. - - err = SetupSocket( inMDNS, inAddr, MulticastDNSPort, &socketRef ); - require_noerr( err, exit ); - item->multicastSocketRef = socketRef; - - // Set up the sending socket for this interface. - - err = SetupSocket( inMDNS, inAddr, zeroIPPort, &socketRef ); - require_noerr( err, exit ); - item->sendingSocketRef = socketRef; - - // Register this interface with mDNS. - - item->hostSet.InterfaceID = (mDNSInterfaceID) item; - item->hostSet.ip .type = mDNSAddrType_IPv4; - item->hostSet.ip .ip.v4.NotAnInteger = ipv4->sin_addr.s_addr; - item->hostSet.mask.type = mDNSAddrType_IPv4; - item->hostSet.mask.ip.v4.NotAnInteger = mask->sin_addr.s_addr; - item->hostSet.ifname[0] = 0; - item->hostSet.Advertise = inMDNS->AdvertiseLocalAddresses; - item->hostSet.McastTxRx = mDNStrue; - - err = mDNS_RegisterInterface( inMDNS, &item->hostSet, mDNSfalse ); - require_noerr( err, exit ); - item->hostRegistered = mDNStrue; - - dlog( kDebugLevelInfo, DEBUG_NAME "Registered IP address: %u.%u.%u.%u\n", - item->hostSet.ip.ip.v4.b[ 0 ], item->hostSet.ip.ip.v4.b[ 1 ], - item->hostSet.ip.ip.v4.b[ 2 ], item->hostSet.ip.ip.v4.b[ 3 ] ); - - // Success! - - *outItem = item; - item = NULL; - + mStatus err; + MDNSInterfaceItem * item; + MDNSSocketRef socketRef; + const struct sockaddr_in * ipv4, *mask; + + dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface (name=%s)\n", inAddr->ifa_name ); + check( inMDNS ); + check( inAddr ); + check( inAddr->ifa_addr ); + ipv4 = (const struct sockaddr_in *) inAddr->ifa_addr; + mask = (const struct sockaddr_in *) inAddr->ifa_netmask; + check( outItem ); + + // Allocate memory for the info item. + + item = (MDNSInterfaceItem *) calloc( 1, sizeof( *item ) ); + require_action( item, exit, err = mStatus_NoMemoryErr ); + strcpy( item->name, inAddr->ifa_name ); + item->multicastSocketRef = kInvalidSocketRef; + item->sendingSocketRef = kInvalidSocketRef; + + // Set up the multicast DNS (port 5353) socket for this interface. + + err = SetupSocket( inMDNS, inAddr, MulticastDNSPort, &socketRef ); + require_noerr( err, exit ); + item->multicastSocketRef = socketRef; + + // Set up the sending socket for this interface. + + err = SetupSocket( inMDNS, inAddr, zeroIPPort, &socketRef ); + require_noerr( err, exit ); + item->sendingSocketRef = socketRef; + + // Register this interface with mDNS. + + item->hostSet.InterfaceID = (mDNSInterfaceID) item; + item->hostSet.ip.type = mDNSAddrType_IPv4; + item->hostSet.ip.ip.v4.NotAnInteger = ipv4->sin_addr.s_addr; + item->hostSet.mask.type = mDNSAddrType_IPv4; + item->hostSet.mask.ip.v4.NotAnInteger = mask->sin_addr.s_addr; + item->hostSet.ifname[0] = 0; + item->hostSet.Advertise = inMDNS->AdvertiseLocalAddresses; + item->hostSet.McastTxRx = mDNStrue; + + err = mDNS_RegisterInterface( inMDNS, &item->hostSet, mDNSfalse ); + require_noerr( err, exit ); + item->hostRegistered = mDNStrue; + + dlog( kDebugLevelInfo, DEBUG_NAME "Registered IP address: %u.%u.%u.%u\n", + item->hostSet.ip.ip.v4.b[ 0 ], item->hostSet.ip.ip.v4.b[ 1 ], + item->hostSet.ip.ip.v4.b[ 2 ], item->hostSet.ip.ip.v4.b[ 3 ] ); + + // Success! + + *outItem = item; + item = NULL; + exit: - if( item ) - { - TearDownInterface( inMDNS, item ); - } - dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface done (name=%s, err=%ld)\n", inAddr->ifa_name, err ); - return( err ); + if( item ) + { + TearDownInterface( inMDNS, item ); + } + dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface done (name=%s, err=%ld)\n", inAddr->ifa_name, err ); + return( err ); } //=========================================================================================================================== // TearDownInterface //=========================================================================================================================== -mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, MDNSInterfaceItem *inItem ) +mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, MDNSInterfaceItem *inItem ) { - MDNSSocketRef socketRef; - - check( inMDNS ); - check( inItem ); - - // Deregister this interface with mDNS. - - dlog( kDebugLevelInfo, DEBUG_NAME "Deregistering IP address: %u.%u.%u.%u\n", - inItem->hostSet.ip.ip.v4.b[ 0 ], inItem->hostSet.ip.ip.v4.b[ 1 ], - inItem->hostSet.ip.ip.v4.b[ 2 ], inItem->hostSet.ip.ip.v4.b[ 3 ] ); - - if( inItem->hostRegistered ) - { - inItem->hostRegistered = mDNSfalse; - mDNS_DeregisterInterface( inMDNS, &inItem->hostSet, mDNSfalse ); - } - - // Close the multicast socket. - - socketRef = inItem->multicastSocketRef; - inItem->multicastSocketRef = kInvalidSocketRef; - if( socketRef != kInvalidSocketRef ) - { - dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down multicast socket %d\n", socketRef ); - close( socketRef ); - } - - // Close the sending socket. - - socketRef = inItem->sendingSocketRef; - inItem->sendingSocketRef = kInvalidSocketRef; - if( socketRef != kInvalidSocketRef ) - { - dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down sending socket %d\n", socketRef ); - close( socketRef ); - } - - // Free the memory used by the interface info. - - free( inItem ); - return( mStatus_NoError ); + MDNSSocketRef socketRef; + + check( inMDNS ); + check( inItem ); + + // Deregister this interface with mDNS. + + dlog( kDebugLevelInfo, DEBUG_NAME "Deregistering IP address: %u.%u.%u.%u\n", + inItem->hostSet.ip.ip.v4.b[ 0 ], inItem->hostSet.ip.ip.v4.b[ 1 ], + inItem->hostSet.ip.ip.v4.b[ 2 ], inItem->hostSet.ip.ip.v4.b[ 3 ] ); + + if( inItem->hostRegistered ) + { + inItem->hostRegistered = mDNSfalse; + mDNS_DeregisterInterface( inMDNS, &inItem->hostSet, mDNSfalse ); + } + + // Close the multicast socket. + + socketRef = inItem->multicastSocketRef; + inItem->multicastSocketRef = kInvalidSocketRef; + if( socketRef != kInvalidSocketRef ) + { + dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down multicast socket %d\n", socketRef ); + close( socketRef ); + } + + // Close the sending socket. + + socketRef = inItem->sendingSocketRef; + inItem->sendingSocketRef = kInvalidSocketRef; + if( socketRef != kInvalidSocketRef ) + { + dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down sending socket %d\n", socketRef ); + close( socketRef ); + } + + // Free the memory used by the interface info. + + free( inItem ); + return( mStatus_NoError ); } //=========================================================================================================================== @@ -1078,124 +1078,124 @@ mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, MDNSInterfaceItem *inI //=========================================================================================================================== mDNSlocal mStatus - SetupSocket( - mDNS * const inMDNS, - const struct ifaddrs * inAddr, - mDNSIPPort inPort, - MDNSSocketRef * outSocketRef ) +SetupSocket( + mDNS * const inMDNS, + const struct ifaddrs * inAddr, + mDNSIPPort inPort, + MDNSSocketRef * outSocketRef ) { - mStatus err; - MDNSSocketRef socketRef; - int option; - unsigned char optionByte; - struct ip_mreq mreq; - const struct sockaddr_in * ipv4; - struct sockaddr_in addr; - mDNSv4Addr ip; - - dlog( kDebugLevelVerbose, DEBUG_NAME "setting up socket done\n" ); - check( inMDNS ); - check( inAddr ); - check( inAddr->ifa_addr ); - ipv4 = (const struct sockaddr_in *) inAddr->ifa_addr; - check( outSocketRef ); - - // Set up a UDP socket for multicast DNS. - - socketRef = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); - require_errno_action( socketRef, errno, exit, err = mStatus_UnknownErr ); - - // A port of zero means this socket is for sending and should be set up for sending. Otherwise, it is for receiving - // and should be set up for receiving. The reason for separate sending vs receiving sockets is to workaround problems - // with VxWorks IP stack when using dynamic IP configuration such as DHCP (problems binding to wildcard IP when the - // IP address later changes). Since we have to bind the Multicast DNS address to workaround these issues we have to - // use a separate sending socket since it is illegal to send a packet with a multicast source address (RFC 1122). - - if( inPort.NotAnInteger != zeroIPPort.NotAnInteger ) - { - // Turn on reuse port option so multiple servers can listen for Multicast DNS packets. - - option = 1; - err = setsockopt( socketRef, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) ); - check_errno( err, errno ); - - // Join the all-DNS multicast group so we receive Multicast DNS packets. - - ip.NotAnInteger = ipv4->sin_addr.s_addr; - mreq.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger; - mreq.imr_interface.s_addr = ip.NotAnInteger; - err = setsockopt( socketRef, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof( mreq ) ); - check_errno( err, errno ); - - // Bind to the multicast DNS address and port 5353. - - mDNSPlatformMemZero( &addr, sizeof( addr ) ); - addr.sin_family = AF_INET; - addr.sin_port = inPort.NotAnInteger; - addr.sin_addr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger; - err = bind( socketRef, (struct sockaddr *) &addr, sizeof( addr ) ); - check_errno( err, errno ); - - dlog( kDebugLevelVerbose, DEBUG_NAME "setting up socket done (%s, %u.%u.%u.%u:%u, %d)\n", - inAddr->ifa_name, ip.b[ 0 ], ip.b[ 1 ], ip.b[ 2 ], ip.b[ 3 ], ntohs( inPort.NotAnInteger ), socketRef ); - } - else - { - // Bind to the interface address and multicast DNS port. - - ip.NotAnInteger = ipv4->sin_addr.s_addr; - mDNSPlatformMemZero( &addr, sizeof( addr ) ); - addr.sin_family = AF_INET; - addr.sin_port = MulticastDNSPort.NotAnInteger; - addr.sin_addr.s_addr = ip.NotAnInteger; - err = bind( socketRef, (struct sockaddr *) &addr, sizeof( addr ) ); - check_errno( err, errno ); - - // Direct multicast packets to the specified interface. - - addr.sin_addr.s_addr = ip.NotAnInteger; - err = setsockopt( socketRef, IPPROTO_IP, IP_MULTICAST_IF, (char *) &addr.sin_addr, sizeof( addr.sin_addr ) ); - check_errno( err, errno ); - - // Set the TTL of outgoing unicast packets to 255 (helps against spoofing). - - option = 255; - err = setsockopt( socketRef, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) ); - check_errno( err, errno ); - - // Set the TTL of outgoing multicast packets to 255 (helps against spoofing). - - optionByte = 255; - err = setsockopt( socketRef, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &optionByte, sizeof( optionByte ) ); - check_errno( err, errno ); - - // WARNING: Setting this option causes unicast responses to be routed to the wrong interface so they are - // WARNING: disabled. These options were only hints to improve 802.11 performance (and not implemented) anyway. - + mStatus err; + MDNSSocketRef socketRef; + int option; + unsigned char optionByte; + struct ip_mreq mreq; + const struct sockaddr_in * ipv4; + struct sockaddr_in addr; + mDNSv4Addr ip; + + dlog( kDebugLevelVerbose, DEBUG_NAME "setting up socket done\n" ); + check( inMDNS ); + check( inAddr ); + check( inAddr->ifa_addr ); + ipv4 = (const struct sockaddr_in *) inAddr->ifa_addr; + check( outSocketRef ); + + // Set up a UDP socket for multicast DNS. + + socketRef = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + require_errno_action( socketRef, errno, exit, err = mStatus_UnknownErr ); + + // A port of zero means this socket is for sending and should be set up for sending. Otherwise, it is for receiving + // and should be set up for receiving. The reason for separate sending vs receiving sockets is to workaround problems + // with VxWorks IP stack when using dynamic IP configuration such as DHCP (problems binding to wildcard IP when the + // IP address later changes). Since we have to bind the Multicast DNS address to workaround these issues we have to + // use a separate sending socket since it is illegal to send a packet with a multicast source address (RFC 1122). + + if( inPort.NotAnInteger != zeroIPPort.NotAnInteger ) + { + // Turn on reuse port option so multiple servers can listen for Multicast DNS packets. + + option = 1; + err = setsockopt( socketRef, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) ); + check_errno( err, errno ); + + // Join the all-DNS multicast group so we receive Multicast DNS packets. + + ip.NotAnInteger = ipv4->sin_addr.s_addr; + mreq.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger; + mreq.imr_interface.s_addr = ip.NotAnInteger; + err = setsockopt( socketRef, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof( mreq ) ); + check_errno( err, errno ); + + // Bind to the multicast DNS address and port 5353. + + mDNSPlatformMemZero( &addr, sizeof( addr ) ); + addr.sin_family = AF_INET; + addr.sin_port = inPort.NotAnInteger; + addr.sin_addr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger; + err = bind( socketRef, (struct sockaddr *) &addr, sizeof( addr ) ); + check_errno( err, errno ); + + dlog( kDebugLevelVerbose, DEBUG_NAME "setting up socket done (%s, %u.%u.%u.%u:%u, %d)\n", + inAddr->ifa_name, ip.b[ 0 ], ip.b[ 1 ], ip.b[ 2 ], ip.b[ 3 ], ntohs( inPort.NotAnInteger ), socketRef ); + } + else + { + // Bind to the interface address and multicast DNS port. + + ip.NotAnInteger = ipv4->sin_addr.s_addr; + mDNSPlatformMemZero( &addr, sizeof( addr ) ); + addr.sin_family = AF_INET; + addr.sin_port = MulticastDNSPort.NotAnInteger; + addr.sin_addr.s_addr = ip.NotAnInteger; + err = bind( socketRef, (struct sockaddr *) &addr, sizeof( addr ) ); + check_errno( err, errno ); + + // Direct multicast packets to the specified interface. + + addr.sin_addr.s_addr = ip.NotAnInteger; + err = setsockopt( socketRef, IPPROTO_IP, IP_MULTICAST_IF, (char *) &addr.sin_addr, sizeof( addr.sin_addr ) ); + check_errno( err, errno ); + + // Set the TTL of outgoing unicast packets to 255 (helps against spoofing). + + option = 255; + err = setsockopt( socketRef, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) ); + check_errno( err, errno ); + + // Set the TTL of outgoing multicast packets to 255 (helps against spoofing). + + optionByte = 255; + err = setsockopt( socketRef, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &optionByte, sizeof( optionByte ) ); + check_errno( err, errno ); + + // WARNING: Setting this option causes unicast responses to be routed to the wrong interface so they are + // WARNING: disabled. These options were only hints to improve 802.11 performance (and not implemented) anyway. + #if 0 - // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to maximize 802.11 multicast rate. - - option = IPTOS_LOWDELAY | IPTOS_THROUGHPUT; - err = setsockopt( socketRef, IPPROTO_IP, IP_TOS, (char *) &option, sizeof( option ) ); - check_errno( err, errno ); + // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to maximize 802.11 multicast rate. + + option = IPTOS_LOWDELAY | IPTOS_THROUGHPUT; + err = setsockopt( socketRef, IPPROTO_IP, IP_TOS, (char *) &option, sizeof( option ) ); + check_errno( err, errno ); #endif - - dlog( kDebugLevelVerbose, DEBUG_NAME "setting up sending socket done (%s, %u.%u.%u.%u, %d)\n", - inAddr->ifa_name, ip.b[ 0 ], ip.b[ 1 ], ip.b[ 2 ], ip.b[ 3 ], socketRef ); - } - - // Success! - - *outSocketRef = socketRef; - socketRef = kInvalidSocketRef; - err = mStatus_NoError; - + + dlog( kDebugLevelVerbose, DEBUG_NAME "setting up sending socket done (%s, %u.%u.%u.%u, %d)\n", + inAddr->ifa_name, ip.b[ 0 ], ip.b[ 1 ], ip.b[ 2 ], ip.b[ 3 ], socketRef ); + } + + // Success! + + *outSocketRef = socketRef; + socketRef = kInvalidSocketRef; + err = mStatus_NoError; + exit: - if( socketRef != kInvalidSocketRef ) - { - close( socketRef ); - } - return( err ); + if( socketRef != kInvalidSocketRef ) + { + close( socketRef ); + } + return( err ); } #if 0 @@ -1207,147 +1207,147 @@ exit: // SetupCommandPipe //=========================================================================================================================== -mDNSlocal mStatus SetupCommandPipe( mDNS * const inMDNS ) +mDNSlocal mStatus SetupCommandPipe( mDNS * const inMDNS ) { - mStatus err; - - // Clean up any leftover command pipe. - - TearDownCommandPipe( inMDNS ); - - // Create the pipe device and open it. - - pipeDevCreate( kMDNSPipeName, kMDNSPipeMessageQueueSize, kMDNSPipeMessageSize ); - - inMDNS->p->commandPipe = open( kMDNSPipeName, O_RDWR, 0 ); - require_errno_action( inMDNS->p->commandPipe, errno, exit, err = mStatus_UnsupportedErr ); - - err = mStatus_NoError; - + mStatus err; + + // Clean up any leftover command pipe. + + TearDownCommandPipe( inMDNS ); + + // Create the pipe device and open it. + + pipeDevCreate( kMDNSPipeName, kMDNSPipeMessageQueueSize, kMDNSPipeMessageSize ); + + inMDNS->p->commandPipe = open( kMDNSPipeName, O_RDWR, 0 ); + require_errno_action( inMDNS->p->commandPipe, errno, exit, err = mStatus_UnsupportedErr ); + + err = mStatus_NoError; + exit: - return( err ); + return( err ); } //=========================================================================================================================== // TearDownCommandPipe //=========================================================================================================================== -mDNSlocal mStatus TearDownCommandPipe( mDNS * const inMDNS ) +mDNSlocal mStatus TearDownCommandPipe( mDNS * const inMDNS ) { - if( inMDNS->p->commandPipe != ERROR ) - { - close( inMDNS->p->commandPipe ); + if( inMDNS->p->commandPipe != ERROR ) + { + close( inMDNS->p->commandPipe ); #ifdef _WRS_VXWORKS_5_X - // pipeDevDelete is not defined in older versions of VxWorks - pipeDevDelete( kMDNSPipeName, FALSE ); + // pipeDevDelete is not defined in older versions of VxWorks + pipeDevDelete( kMDNSPipeName, FALSE ); #endif - inMDNS->p->commandPipe = ERROR; - } - return( mStatus_NoError ); + inMDNS->p->commandPipe = ERROR; + } + return( mStatus_NoError ); } //=========================================================================================================================== // SendCommand //=========================================================================================================================== -mDNSlocal mStatus SendCommand( const mDNS * const inMDNS, MDNSPipeCommandCode inCommandCode ) +mDNSlocal mStatus SendCommand( const mDNS * const inMDNS, MDNSPipeCommandCode inCommandCode ) { - mStatus err; - - require_action( inMDNS->p->commandPipe != ERROR, exit, err = mStatus_NotInitializedErr ); - - err = write( inMDNS->p->commandPipe, &inCommandCode, sizeof( inCommandCode ) ); - require_errno( err, errno, exit ); - - err = mStatus_NoError; - + mStatus err; + + require_action( inMDNS->p->commandPipe != ERROR, exit, err = mStatus_NotInitializedErr ); + + err = write( inMDNS->p->commandPipe, &inCommandCode, sizeof( inCommandCode ) ); + require_errno( err, errno, exit ); + + err = mStatus_NoError; + exit: - return( err ); + return( err ); } //=========================================================================================================================== // ProcessCommand //=========================================================================================================================== -mDNSlocal mStatus ProcessCommand( mDNS * const inMDNS ) +mDNSlocal mStatus ProcessCommand( mDNS * const inMDNS ) { - mStatus err; - MDNSPipeCommandCode commandCode; - - require_action( inMDNS->p->commandPipe != ERROR, exit, err = mStatus_NotInitializedErr ); - - // Read the command code from the pipe and dispatch it. - - err = read( inMDNS->p->commandPipe, &commandCode, sizeof( commandCode ) ); - require_errno( err, errno, exit ); - - switch( commandCode ) - { - case kMDNSPipeCommandCodeReschedule: - - // Reschedule event. Do nothing here, but this will cause mDNS_Execute to run before waiting again. - - dlog( kDebugLevelChatty, DEBUG_NAME "reschedule\n" ); - break; - - case kMDNSPipeCommandCodeReconfigure: - ProcessCommandReconfigure( inMDNS ); - break; - - case kMDNSPipeCommandCodeQuit: - - // Quit requested. Set quit flag and bump the config ID to let the thread exit normally. - - dlog( kDebugLevelVerbose, DEBUG_NAME "processing pipe quit command\n" ); - inMDNS->p->quit = mDNStrue; - ++inMDNS->p->configID; - break; - - default: - dlog( kDebugLevelError, DEBUG_NAME "unknown pipe command code (code=0x%08X)\n", commandCode ); - err = mStatus_BadParamErr; - goto exit; - break; - } - err = mStatus_NoError; + mStatus err; + MDNSPipeCommandCode commandCode; + + require_action( inMDNS->p->commandPipe != ERROR, exit, err = mStatus_NotInitializedErr ); + + // Read the command code from the pipe and dispatch it. + + err = read( inMDNS->p->commandPipe, &commandCode, sizeof( commandCode ) ); + require_errno( err, errno, exit ); + + switch( commandCode ) + { + case kMDNSPipeCommandCodeReschedule: + + // Reschedule event. Do nothing here, but this will cause mDNS_Execute to run before waiting again. + + dlog( kDebugLevelChatty, DEBUG_NAME "reschedule\n" ); + break; + + case kMDNSPipeCommandCodeReconfigure: + ProcessCommandReconfigure( inMDNS ); + break; + + case kMDNSPipeCommandCodeQuit: + + // Quit requested. Set quit flag and bump the config ID to let the thread exit normally. + + dlog( kDebugLevelVerbose, DEBUG_NAME "processing pipe quit command\n" ); + inMDNS->p->quit = mDNStrue; + ++inMDNS->p->configID; + break; + + default: + dlog( kDebugLevelError, DEBUG_NAME "unknown pipe command code (code=0x%08X)\n", commandCode ); + err = mStatus_BadParamErr; + goto exit; + break; + } + err = mStatus_NoError; exit: - return( err ); + return( err ); } //=========================================================================================================================== // ProcessCommandReconfigure //=========================================================================================================================== -mDNSlocal void ProcessCommandReconfigure( mDNS *inMDNS ) +mDNSlocal void ProcessCommandReconfigure( mDNS *inMDNS ) { - mStatus err; - - dlog( kDebugLevelVerbose, DEBUG_NAME "processing pipe reconfigure command\n" ); - - // Tear down the existing interfaces and set up new ones using the new IP info. - - mDNSPlatformLock( inMDNS ); - - err = TearDownInterfaceList( inMDNS ); - check_noerr( err ); - - err = SetupInterfaceList( inMDNS ); - check_noerr( err ); - - mDNSPlatformUnlock( inMDNS ); - - // Inform clients of the change. - - mDNS_ConfigChanged(m); - - // Force mDNS to update. - - mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this - - // Bump the config ID so the main processing loop detects the configuration change. - - ++inMDNS->p->configID; + mStatus err; + + dlog( kDebugLevelVerbose, DEBUG_NAME "processing pipe reconfigure command\n" ); + + // Tear down the existing interfaces and set up new ones using the new IP info. + + mDNSPlatformLock( inMDNS ); + + err = TearDownInterfaceList( inMDNS ); + check_noerr( err ); + + err = SetupInterfaceList( inMDNS ); + check_noerr( err ); + + mDNSPlatformUnlock( inMDNS ); + + // Inform clients of the change. + + mDNS_ConfigChanged(m); + + // Force mDNS to update. + + mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this + + // Bump the config ID so the main processing loop detects the configuration change. + + ++inMDNS->p->configID; } #if 0 @@ -1359,319 +1359,319 @@ mDNSlocal void ProcessCommandReconfigure( mDNS *inMDNS ) // SetupTask //=========================================================================================================================== -mDNSlocal mStatus SetupTask( mDNS * const inMDNS ) +mDNSlocal mStatus SetupTask( mDNS * const inMDNS ) { - mStatus err; - int task; - - dlog( kDebugLevelVerbose, DEBUG_NAME "setting up thread\n" ); - check( inMDNS ); - - // Create our main thread. Note: The task will save off its ID in the globals. We cannot do it here because the - // task invokes code that needs it and the task may begin execution before taskSpawn returns the task ID. - // This also means code in this thread context cannot rely on the task ID until the task has fully initialized. - - task = taskSpawn( kMDNSTaskName, kMDNSTaskPriority, 0, kMDNSTaskStackSize, (FUNCPTR) Task, - (int) inMDNS, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - require_action( task != ERROR, exit, err = mStatus_NoMemoryErr ); - - err = mStatus_NoError; - + mStatus err; + int task; + + dlog( kDebugLevelVerbose, DEBUG_NAME "setting up thread\n" ); + check( inMDNS ); + + // Create our main thread. Note: The task will save off its ID in the globals. We cannot do it here because the + // task invokes code that needs it and the task may begin execution before taskSpawn returns the task ID. + // This also means code in this thread context cannot rely on the task ID until the task has fully initialized. + + task = taskSpawn( kMDNSTaskName, kMDNSTaskPriority, 0, kMDNSTaskStackSize, (FUNCPTR) Task, + (int) inMDNS, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + require_action( task != ERROR, exit, err = mStatus_NoMemoryErr ); + + err = mStatus_NoError; + exit: - dlog( kDebugLevelVerbose, DEBUG_NAME "setting up thread done (err=%ld, id=%d)\n", err, task ); - return( err ); + dlog( kDebugLevelVerbose, DEBUG_NAME "setting up thread done (err=%ld, id=%d)\n", err, task ); + return( err ); } //=========================================================================================================================== // TearDownTask //=========================================================================================================================== -mDNSlocal mStatus TearDownTask( mDNS * const inMDNS ) +mDNSlocal mStatus TearDownTask( mDNS * const inMDNS ) { - mStatus err; - - dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down thread\n" ); - check( inMDNS ); - - // Send a quit command to cause the thread to exit. - - SendCommand( inMDNS, kMDNSPipeCommandCodeQuit ); - - // Wait for the thread to signal it has exited. Timeout in 10 seconds to handle a hung thread. - - if( inMDNS->p->quitEvent ) - { - err = semTake( inMDNS->p->quitEvent, sysClkRateGet() * 10 ); - check_noerr( err ); - } - err = mStatus_NoError; - - dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down thread done (err=%ld)\n", err ); - return( err ); + mStatus err; + + dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down thread\n" ); + check( inMDNS ); + + // Send a quit command to cause the thread to exit. + + SendCommand( inMDNS, kMDNSPipeCommandCodeQuit ); + + // Wait for the thread to signal it has exited. Timeout in 10 seconds to handle a hung thread. + + if( inMDNS->p->quitEvent ) + { + err = semTake( inMDNS->p->quitEvent, sysClkRateGet() * 10 ); + check_noerr( err ); + } + err = mStatus_NoError; + + dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down thread done (err=%ld)\n", err ); + return( err ); } //=========================================================================================================================== // Task //=========================================================================================================================== -mDNSlocal void Task( mDNS *inMDNS ) +mDNSlocal void Task( mDNS *inMDNS ) { - mStatus err; - fd_set allReadSet; - MDNSInterfaceItem * item; - int maxSocket; - long configID; - struct timeval timeout; - - dlog( kDebugLevelVerbose, DEBUG_NAME "task starting\n" ); - check( inMDNS ); - - // Set up everything up. - - err = TaskInit( inMDNS ); - require_noerr( err, exit ); - - // Main Processing Loop. - - while( !inMDNS->p->quit ) - { - // Set up the read set here to avoid the overhead of setting it up each iteration of the main processing loop. - // If the configuration changes, the server ID will be bumped, causing this code to set up the read set again. - - TaskSetupReadSet( inMDNS, &allReadSet, &maxSocket ); - configID = inMDNS->p->configID; - dlog( kDebugLevelVerbose, DEBUG_NAME "task starting processing loop (configID=%ld)\n", configID ); - - while( configID == inMDNS->p->configID ) - { - mDNSs32 nextTaskTime; - fd_set readSet; - int n; - - // Give the mDNS core a chance to do its work. Reset the rescheduled flag before calling mDNS_Execute - // so anything that needs processing during or after causes a re-schedule to wake up the thread. The - // reschedule flag is set to 1 after processing a waking up to prevent redundant reschedules while - // processing packets. This introduces a window for a race condition because the thread wake-up and - // reschedule set are not atomic, but this would be benign. Even if the reschedule flag is "corrupted" - // like this, it would only result in a redundant reschedule since it will loop back to mDNS_Execute. - - inMDNS->p->rescheduled = 0; - nextTaskTime = mDNS_Execute( inMDNS ); - TaskSetupTimeout( inMDNS, nextTaskTime, &timeout ); - - // Wait until something occurs (e.g. command, incoming packet, or timeout). - - readSet = allReadSet; - n = select( maxSocket + 1, &readSet, NULL, NULL, &timeout ); - inMDNS->p->rescheduled = 1; - check_errno( n, errno ); - dlog( kDebugLevelChatty - 1, DEBUG_NAME "task select result = %d\n", n ); - if( n == 0 ) - { - // Next task timeout occurred. Loop back up to give mDNS core a chance to work. - - dlog( kDebugLevelChatty, DEBUG_NAME "next task timeout occurred (%ld)\n", mDNS_TimeNow(inMDNS) ); - continue; - } - - // Scan the read set to determine if any sockets have something pending and process them. - - n = 0; - for( item = inMDNS->p->interfaceList; item; item = item->next ) - { - if( FD_ISSET( item->multicastSocketRef, &readSet ) ) - { - TaskProcessPacket( inMDNS, item, item->multicastSocketRef ); - ++n; - } - } - - // Check for a pending command and process it. - - if( FD_ISSET( inMDNS->p->commandPipe, &readSet ) ) - { - ProcessCommand( inMDNS ); - ++n; - } - check( n > 0 ); - } - } + mStatus err; + fd_set allReadSet; + MDNSInterfaceItem * item; + int maxSocket; + long configID; + struct timeval timeout; + + dlog( kDebugLevelVerbose, DEBUG_NAME "task starting\n" ); + check( inMDNS ); + + // Set up everything up. + + err = TaskInit( inMDNS ); + require_noerr( err, exit ); + + // Main Processing Loop. + + while( !inMDNS->p->quit ) + { + // Set up the read set here to avoid the overhead of setting it up each iteration of the main processing loop. + // If the configuration changes, the server ID will be bumped, causing this code to set up the read set again. + + TaskSetupReadSet( inMDNS, &allReadSet, &maxSocket ); + configID = inMDNS->p->configID; + dlog( kDebugLevelVerbose, DEBUG_NAME "task starting processing loop (configID=%ld)\n", configID ); + + while( configID == inMDNS->p->configID ) + { + mDNSs32 nextTaskTime; + fd_set readSet; + int n; + + // Give the mDNS core a chance to do its work. Reset the rescheduled flag before calling mDNS_Execute + // so anything that needs processing during or after causes a re-schedule to wake up the thread. The + // reschedule flag is set to 1 after processing a waking up to prevent redundant reschedules while + // processing packets. This introduces a window for a race condition because the thread wake-up and + // reschedule set are not atomic, but this would be benign. Even if the reschedule flag is "corrupted" + // like this, it would only result in a redundant reschedule since it will loop back to mDNS_Execute. + + inMDNS->p->rescheduled = 0; + nextTaskTime = mDNS_Execute( inMDNS ); + TaskSetupTimeout( inMDNS, nextTaskTime, &timeout ); + + // Wait until something occurs (e.g. command, incoming packet, or timeout). + + readSet = allReadSet; + n = select( maxSocket + 1, &readSet, NULL, NULL, &timeout ); + inMDNS->p->rescheduled = 1; + check_errno( n, errno ); + dlog( kDebugLevelChatty - 1, DEBUG_NAME "task select result = %d\n", n ); + if( n == 0 ) + { + // Next task timeout occurred. Loop back up to give mDNS core a chance to work. + + dlog( kDebugLevelChatty, DEBUG_NAME "next task timeout occurred (%ld)\n", mDNS_TimeNow(inMDNS) ); + continue; + } + + // Scan the read set to determine if any sockets have something pending and process them. + + n = 0; + for( item = inMDNS->p->interfaceList; item; item = item->next ) + { + if( FD_ISSET( item->multicastSocketRef, &readSet ) ) + { + TaskProcessPacket( inMDNS, item, item->multicastSocketRef ); + ++n; + } + } + + // Check for a pending command and process it. + + if( FD_ISSET( inMDNS->p->commandPipe, &readSet ) ) + { + ProcessCommand( inMDNS ); + ++n; + } + check( n > 0 ); + } + } exit: - // Signal we've quit. - - check( inMDNS->p->quitEvent ); - semGive( inMDNS->p->quitEvent ); - - dlog( kDebugLevelInfo, DEBUG_NAME "task ended\n" ); + // Signal we've quit. + + check( inMDNS->p->quitEvent ); + semGive( inMDNS->p->quitEvent ); + + dlog( kDebugLevelInfo, DEBUG_NAME "task ended\n" ); } //=========================================================================================================================== // TaskInit //=========================================================================================================================== -mDNSlocal mStatus TaskInit( mDNS *inMDNS ) +mDNSlocal mStatus TaskInit( mDNS *inMDNS ) { - mStatus err; - - dlog( kDebugLevelVerbose, DEBUG_NAME "task init\n" ); - check( inMDNS->p->readyEvent ); - - inMDNS->p->task = taskIdSelf(); - - err = SetupCommandPipe( inMDNS ); - require_noerr( err, exit ); - - SetupNames( inMDNS ); - - err = SetupInterfaceList( inMDNS ); - require_noerr( err, exit ); - + mStatus err; + + dlog( kDebugLevelVerbose, DEBUG_NAME "task init\n" ); + check( inMDNS->p->readyEvent ); + + inMDNS->p->task = taskIdSelf(); + + err = SetupCommandPipe( inMDNS ); + require_noerr( err, exit ); + + SetupNames( inMDNS ); + + err = SetupInterfaceList( inMDNS ); + require_noerr( err, exit ); + exit: - // Signal the "ready" semaphore to indicate the task initialization code has completed (success or not). - - inMDNS->p->taskInitErr = err; - semGive( inMDNS->p->readyEvent ); + // Signal the "ready" semaphore to indicate the task initialization code has completed (success or not). + + inMDNS->p->taskInitErr = err; + semGive( inMDNS->p->readyEvent ); - dlog( kDebugLevelVerbose, DEBUG_NAME "task init done (err=%ld)\n", err ); - return( err ); + dlog( kDebugLevelVerbose, DEBUG_NAME "task init done (err=%ld)\n", err ); + return( err ); } //=========================================================================================================================== // TaskSetupReadSet //=========================================================================================================================== -mDNSlocal void TaskSetupReadSet( mDNS *inMDNS, fd_set *outReadSet, int *outMaxSocket ) +mDNSlocal void TaskSetupReadSet( mDNS *inMDNS, fd_set *outReadSet, int *outMaxSocket ) { - MDNSInterfaceItem * item; - int maxSocket; - - dlog( kDebugLevelVerbose, DEBUG_NAME "task setting up read set\n" ); - check( inMDNS ); - check( outReadSet ); - check( outMaxSocket ); - - // Initialize the read set. Default the max socket to -1 so "maxSocket + 1" (as needed by select) is zero. This - // should never happen since we should always have at least one interface, but it's just to be safe. - - FD_ZERO( outReadSet ); - maxSocket = -1; - - // Add all the receiving sockets to the read set. - - for( item = inMDNS->p->interfaceList; item; item = item->next ) - { - FD_SET( item->multicastSocketRef, outReadSet ); - if( item->multicastSocketRef > maxSocket ) - { - maxSocket = item->multicastSocketRef; - } - } - - // Add the command pipe to the read set. - - FD_SET( inMDNS->p->commandPipe, outReadSet ); - if( inMDNS->p->commandPipe > maxSocket ) - { - maxSocket = inMDNS->p->commandPipe; - } - check( maxSocket > 0 ); - *outMaxSocket = maxSocket; - - dlog( kDebugLevelVerbose, DEBUG_NAME "task setting up read set done (maxSocket=%d)\n", maxSocket ); + MDNSInterfaceItem * item; + int maxSocket; + + dlog( kDebugLevelVerbose, DEBUG_NAME "task setting up read set\n" ); + check( inMDNS ); + check( outReadSet ); + check( outMaxSocket ); + + // Initialize the read set. Default the max socket to -1 so "maxSocket + 1" (as needed by select) is zero. This + // should never happen since we should always have at least one interface, but it's just to be safe. + + FD_ZERO( outReadSet ); + maxSocket = -1; + + // Add all the receiving sockets to the read set. + + for( item = inMDNS->p->interfaceList; item; item = item->next ) + { + FD_SET( item->multicastSocketRef, outReadSet ); + if( item->multicastSocketRef > maxSocket ) + { + maxSocket = item->multicastSocketRef; + } + } + + // Add the command pipe to the read set. + + FD_SET( inMDNS->p->commandPipe, outReadSet ); + if( inMDNS->p->commandPipe > maxSocket ) + { + maxSocket = inMDNS->p->commandPipe; + } + check( maxSocket > 0 ); + *outMaxSocket = maxSocket; + + dlog( kDebugLevelVerbose, DEBUG_NAME "task setting up read set done (maxSocket=%d)\n", maxSocket ); } //=========================================================================================================================== // TaskSetupTimeout //=========================================================================================================================== -mDNSlocal void TaskSetupTimeout( mDNS *inMDNS, mDNSs32 inNextTaskTime, struct timeval *outTimeout ) +mDNSlocal void TaskSetupTimeout( mDNS *inMDNS, mDNSs32 inNextTaskTime, struct timeval *outTimeout ) { - mDNSs32 delta; - - // Calculate how long to wait before performing idle processing. - - delta = inNextTaskTime - mDNS_TimeNow(inMDNS); - if( delta <= 0 ) - { - // The next task time is now or in the past. Set the timeout to fire immediately. - - outTimeout->tv_sec = 0; - outTimeout->tv_usec = 0; - } - else - { - // Calculate the seconds and microseconds until the timeout should occur. Add one to the ticks remainder - // before multiplying to account for integer rounding error and avoid firing the timeout too early. - - outTimeout->tv_sec = delta / mDNSPlatformOneSecond; - outTimeout->tv_usec = ( ( delta % mDNSPlatformOneSecond ) + 1 ) * gMDNSTicksToMicrosecondsMultiplier; - - // Check if the microseconds is more than 1 second. If so, bump the seconds instead. - - if( outTimeout->tv_usec >= 1000000L ) - { - outTimeout->tv_sec += 1; - outTimeout->tv_usec = 0; - } - } - - dlog( kDebugLevelChatty, DEBUG_NAME "next task in %ld:%ld seconds (%ld)\n", - outTimeout->tv_sec, outTimeout->tv_usec, inNextTaskTime ); + mDNSs32 delta; + + // Calculate how long to wait before performing idle processing. + + delta = inNextTaskTime - mDNS_TimeNow(inMDNS); + if( delta <= 0 ) + { + // The next task time is now or in the past. Set the timeout to fire immediately. + + outTimeout->tv_sec = 0; + outTimeout->tv_usec = 0; + } + else + { + // Calculate the seconds and microseconds until the timeout should occur. Add one to the ticks remainder + // before multiplying to account for integer rounding error and avoid firing the timeout too early. + + outTimeout->tv_sec = delta / mDNSPlatformOneSecond; + outTimeout->tv_usec = ( ( delta % mDNSPlatformOneSecond ) + 1 ) * gMDNSTicksToMicrosecondsMultiplier; + + // Check if the microseconds is more than 1 second. If so, bump the seconds instead. + + if( outTimeout->tv_usec >= 1000000L ) + { + outTimeout->tv_sec += 1; + outTimeout->tv_usec = 0; + } + } + + dlog( kDebugLevelChatty, DEBUG_NAME "next task in %ld:%ld seconds (%ld)\n", + outTimeout->tv_sec, outTimeout->tv_usec, inNextTaskTime ); } //=========================================================================================================================== // TaskProcessPacket //=========================================================================================================================== -mDNSlocal void TaskProcessPacket( mDNS *inMDNS, MDNSInterfaceItem *inItem, MDNSSocketRef inSocketRef ) +mDNSlocal void TaskProcessPacket( mDNS *inMDNS, MDNSInterfaceItem *inItem, MDNSSocketRef inSocketRef ) { - int n; - DNSMessage packet; - struct sockaddr_in addr; - int addrSize; - mDNSu8 * packetEndPtr; - mDNSAddr srcAddr; - mDNSIPPort srcPort; - mDNSAddr dstAddr; - mDNSIPPort dstPort; - - // Receive the packet. - - addrSize = sizeof( addr ); - n = recvfrom( inSocketRef, (char *) &packet, sizeof( packet ), 0, (struct sockaddr *) &addr, &addrSize ); - check( n >= 0 ); - if( n >= 0 ) - { - // Set up the src/dst/interface info. - - srcAddr.type = mDNSAddrType_IPv4; - srcAddr.ip.v4.NotAnInteger = addr.sin_addr.s_addr; - srcPort.NotAnInteger = addr.sin_port; - dstAddr.type = mDNSAddrType_IPv4; - dstAddr.ip.v4 = AllDNSLinkGroup_v4.ip.v4; - dstPort = MulticastDNSPort; - - dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" ); - dlog( kDebugLevelChatty, DEBUG_NAME " size = %d\n", n ); - dlog( kDebugLevelChatty, DEBUG_NAME " src = %u.%u.%u.%u:%hu\n", - srcAddr.ip.v4.b[ 0 ], srcAddr.ip.v4.b[ 1 ], srcAddr.ip.v4.b[ 2 ], srcAddr.ip.v4.b[ 3 ], - ntohs( srcPort.NotAnInteger ) ); - dlog( kDebugLevelChatty, DEBUG_NAME " dst = %u.%u.%u.%u:%hu\n", - dstAddr.ip.v4.b[ 0 ], dstAddr.ip.v4.b[ 1 ], dstAddr.ip.v4.b[ 2 ], dstAddr.ip.v4.b[ 3 ], - ntohs( dstPort.NotAnInteger ) ); - dlog( kDebugLevelChatty, DEBUG_NAME " interface = 0x%08X\n", (int) inItem->hostSet.InterfaceID ); - dlog( kDebugLevelChatty, DEBUG_NAME "--\n" ); - - // Dispatch the packet to mDNS. - - packetEndPtr = ( (mDNSu8 *) &packet ) + n; - mDNSCoreReceive( inMDNS, &packet, packetEndPtr, &srcAddr, srcPort, &dstAddr, dstPort, inItem->hostSet.InterfaceID ); - } - - // Update counters. - - inItem->recvCounter += 1; - inItem->recvErrorCounter += ( n < 0 ); + int n; + DNSMessage packet; + struct sockaddr_in addr; + int addrSize; + mDNSu8 * packetEndPtr; + mDNSAddr srcAddr; + mDNSIPPort srcPort; + mDNSAddr dstAddr; + mDNSIPPort dstPort; + + // Receive the packet. + + addrSize = sizeof( addr ); + n = recvfrom( inSocketRef, (char *) &packet, sizeof( packet ), 0, (struct sockaddr *) &addr, &addrSize ); + check( n >= 0 ); + if( n >= 0 ) + { + // Set up the src/dst/interface info. + + srcAddr.type = mDNSAddrType_IPv4; + srcAddr.ip.v4.NotAnInteger = addr.sin_addr.s_addr; + srcPort.NotAnInteger = addr.sin_port; + dstAddr.type = mDNSAddrType_IPv4; + dstAddr.ip.v4 = AllDNSLinkGroup_v4.ip.v4; + dstPort = MulticastDNSPort; + + dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" ); + dlog( kDebugLevelChatty, DEBUG_NAME " size = %d\n", n ); + dlog( kDebugLevelChatty, DEBUG_NAME " src = %u.%u.%u.%u:%hu\n", + srcAddr.ip.v4.b[ 0 ], srcAddr.ip.v4.b[ 1 ], srcAddr.ip.v4.b[ 2 ], srcAddr.ip.v4.b[ 3 ], + ntohs( srcPort.NotAnInteger ) ); + dlog( kDebugLevelChatty, DEBUG_NAME " dst = %u.%u.%u.%u:%hu\n", + dstAddr.ip.v4.b[ 0 ], dstAddr.ip.v4.b[ 1 ], dstAddr.ip.v4.b[ 2 ], dstAddr.ip.v4.b[ 3 ], + ntohs( dstPort.NotAnInteger ) ); + dlog( kDebugLevelChatty, DEBUG_NAME " interface = 0x%08X\n", (int) inItem->hostSet.InterfaceID ); + dlog( kDebugLevelChatty, DEBUG_NAME "--\n" ); + + // Dispatch the packet to mDNS. + + packetEndPtr = ( (mDNSu8 *) &packet ) + n; + mDNSCoreReceive( inMDNS, &packet, packetEndPtr, &srcAddr, srcPort, &dstAddr, dstPort, inItem->hostSet.InterfaceID ); + } + + // Update counters. + + inItem->recvCounter += 1; + inItem->recvErrorCounter += ( n < 0 ); } #if 0 @@ -1679,36 +1679,36 @@ mDNSlocal void TaskProcessPacket( mDNS *inMDNS, MDNSInterfaceItem *inItem, MDNSS #pragma mark == Utilities == #endif -#if( TARGET_NON_APPLE ) +#if ( TARGET_NON_APPLE ) //=========================================================================================================================== // GenerateUniqueHostName // // Non-Apple platform stub routine to generate a unique name for the device. Should be implemented to return a unique name. //=========================================================================================================================== -mDNSlocal void GenerateUniqueHostName( char *outName, long *ioSeed ) +mDNSlocal void GenerateUniqueHostName( char *outName, long *ioSeed ) { - DEBUG_UNUSED( ioSeed ); - - // $$$ Non-Apple Platforms: Fill in appropriate name for device. - - mDNSPlatformStrCopy( outName, kMDNSDefaultName ); + DEBUG_UNUSED( ioSeed ); + + // $$$ Non-Apple Platforms: Fill in appropriate name for device. + + mDNSPlatformStrCopy( outName, kMDNSDefaultName ); } //=========================================================================================================================== // GenerateUniqueDNSName // -// Non-Apple platform stub routine to generate a unique RFC 1034-compatible DNS name for the device. Should be +// Non-Apple platform stub routine to generate a unique RFC 1034-compatible DNS name for the device. Should be // implemented to return a unique name. //=========================================================================================================================== -mDNSlocal void GenerateUniqueDNSName( char *outName, long *ioSeed ) +mDNSlocal void GenerateUniqueDNSName( char *outName, long *ioSeed ) { - DEBUG_UNUSED( ioSeed ); - - // $$$ Non-Apple Platforms: Fill in appropriate DNS name for device. - - mDNSPlatformStrCopy( outName, kMDNSDefaultName ); + DEBUG_UNUSED( ioSeed ); + + // $$$ Non-Apple Platforms: Fill in appropriate DNS name for device. + + mDNSPlatformStrCopy( outName, kMDNSDefaultName ); } #endif @@ -1720,229 +1720,229 @@ mDNSlocal void GenerateUniqueDNSName( char *outName, long *ioSeed ) // getifaddrs //=========================================================================================================================== -int getifaddrs( struct ifaddrs **outAddrs ) +int getifaddrs( struct ifaddrs **outAddrs ) { - int err; - struct ifaddrs * head; - struct ifaddrs ** next; - struct ifaddrs * ifa; - int i; - struct ifnet * ifp; - char ipString[ INET_ADDR_LEN ]; - int n; - - head = NULL; - next = &head; - - i = 1; - for( ;; ) - { - ifp = ifIndexToIfp( i ); - if( !ifp ) - { - break; - } - ++i; - - // Allocate and initialize the ifaddrs structure and attach it to the linked list. - - ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) ); - require_action( ifa, exit, err = ENOMEM ); - - *next = ifa; - next = &ifa->ifa_next; - - // Fetch the name. - - ifa->ifa_name = (char *) malloc( 16 ); - require_action( ifa->ifa_name, exit, err = ENOMEM ); - - n = sprintf( ifa->ifa_name, "%s%d", ifp->if_name, ifp->if_unit ); - require_action( n < 16, exit, err = ENOBUFS ); - - // Fetch the address. - - ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( struct sockaddr_in ) ); - require_action( ifa->ifa_addr, exit, err = ENOMEM ); - - ipString[ 0 ] = '\0'; - #if( TARGET_NON_APPLE ) - err = ifAddrGet( ifa->ifa_name, ipString ); - require_noerr( err, exit ); - #else - err = ifAddrGetNonAlias( ifa->ifa_name, ipString ); - require_noerr( err, exit ); - #endif - - err = sock_pton( ipString, AF_INET, ifa->ifa_addr, 0, NULL ); - require_noerr( err, exit ); - - // Fetch flags. - - ifa->ifa_flags = ifp->if_flags; - } - - // Success! - - if( outAddrs ) - { - *outAddrs = head; - head = NULL; - } - err = 0; + int err; + struct ifaddrs * head; + struct ifaddrs ** next; + struct ifaddrs * ifa; + int i; + struct ifnet * ifp; + char ipString[ INET_ADDR_LEN ]; + int n; + + head = NULL; + next = &head; + + i = 1; + for( ;; ) + { + ifp = ifIndexToIfp( i ); + if( !ifp ) + { + break; + } + ++i; + + // Allocate and initialize the ifaddrs structure and attach it to the linked list. + + ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) ); + require_action( ifa, exit, err = ENOMEM ); + + *next = ifa; + next = &ifa->ifa_next; + + // Fetch the name. + + ifa->ifa_name = (char *) malloc( 16 ); + require_action( ifa->ifa_name, exit, err = ENOMEM ); + + n = sprintf( ifa->ifa_name, "%s%d", ifp->if_name, ifp->if_unit ); + require_action( n < 16, exit, err = ENOBUFS ); + + // Fetch the address. + + ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( struct sockaddr_in ) ); + require_action( ifa->ifa_addr, exit, err = ENOMEM ); + + ipString[ 0 ] = '\0'; + #if ( TARGET_NON_APPLE ) + err = ifAddrGet( ifa->ifa_name, ipString ); + require_noerr( err, exit ); + #else + err = ifAddrGetNonAlias( ifa->ifa_name, ipString ); + require_noerr( err, exit ); + #endif + + err = sock_pton( ipString, AF_INET, ifa->ifa_addr, 0, NULL ); + require_noerr( err, exit ); + + // Fetch flags. + + ifa->ifa_flags = ifp->if_flags; + } + + // Success! + + if( outAddrs ) + { + *outAddrs = head; + head = NULL; + } + err = 0; exit: - if( head ) - { - freeifaddrs( head ); - } - return( err ); + if( head ) + { + freeifaddrs( head ); + } + return( err ); } //=========================================================================================================================== // freeifaddrs //=========================================================================================================================== -void freeifaddrs( struct ifaddrs *inAddrs ) +void freeifaddrs( struct ifaddrs *inAddrs ) { - struct ifaddrs * p; - struct ifaddrs * q; - - // Free each piece of the structure. Set to null after freeing to handle macro-aliased fields. - - for( p = inAddrs; p; p = q ) - { - q = p->ifa_next; - - if( p->ifa_name ) - { - free( p->ifa_name ); - p->ifa_name = NULL; - } - if( p->ifa_addr ) - { - free( p->ifa_addr ); - p->ifa_addr = NULL; - } - if( p->ifa_netmask ) - { - free( p->ifa_netmask ); - p->ifa_netmask = NULL; - } - if( p->ifa_dstaddr ) - { - free( p->ifa_dstaddr ); - p->ifa_dstaddr = NULL; - } - if( p->ifa_data ) - { - free( p->ifa_data ); - p->ifa_data = NULL; - } - free( p ); - } + struct ifaddrs * p; + struct ifaddrs * q; + + // Free each piece of the structure. Set to null after freeing to handle macro-aliased fields. + + for( p = inAddrs; p; p = q ) + { + q = p->ifa_next; + + if( p->ifa_name ) + { + free( p->ifa_name ); + p->ifa_name = NULL; + } + if( p->ifa_addr ) + { + free( p->ifa_addr ); + p->ifa_addr = NULL; + } + if( p->ifa_netmask ) + { + free( p->ifa_netmask ); + p->ifa_netmask = NULL; + } + if( p->ifa_dstaddr ) + { + free( p->ifa_dstaddr ); + p->ifa_dstaddr = NULL; + } + if( p->ifa_data ) + { + free( p->ifa_data ); + p->ifa_data = NULL; + } + free( p ); + } } //=========================================================================================================================== // sock_pton //=========================================================================================================================== -int sock_pton( const char *inString, int inFamily, void *outAddr, size_t inAddrSize, size_t *outAddrSize ) +int sock_pton( const char *inString, int inFamily, void *outAddr, size_t inAddrSize, size_t *outAddrSize ) { - int err; - - if( inFamily == AF_INET ) - { - struct sockaddr_in * ipv4; - - if( inAddrSize == 0 ) - { - inAddrSize = sizeof( struct sockaddr_in ); - } - if( inAddrSize < sizeof( struct sockaddr_in ) ) - { - err = EINVAL; - goto exit; - } - - ipv4 = (struct sockaddr_in *) outAddr; - err = inet_aton( (char *) inString, &ipv4->sin_addr ); - if( err == 0 ) - { - ipv4->sin_family = AF_INET; - if( outAddrSize ) - { - *outAddrSize = sizeof( struct sockaddr_in ); - } - } - } -#if( defined( AF_INET6 ) ) - else if( inFamily == AF_INET6 ) // $$$ TO DO: Add IPv6 support. - { - err = EAFNOSUPPORT; - goto exit; - } + int err; + + if( inFamily == AF_INET ) + { + struct sockaddr_in * ipv4; + + if( inAddrSize == 0 ) + { + inAddrSize = sizeof( struct sockaddr_in ); + } + if( inAddrSize < sizeof( struct sockaddr_in ) ) + { + err = EINVAL; + goto exit; + } + + ipv4 = (struct sockaddr_in *) outAddr; + err = inet_aton( (char *) inString, &ipv4->sin_addr ); + if( err == 0 ) + { + ipv4->sin_family = AF_INET; + if( outAddrSize ) + { + *outAddrSize = sizeof( struct sockaddr_in ); + } + } + } +#if ( defined( AF_INET6 ) ) + else if( inFamily == AF_INET6 ) // $$$ TO DO: Add IPv6 support. + { + err = EAFNOSUPPORT; + goto exit; + } #endif - else - { - err = EAFNOSUPPORT; - goto exit; - } + else + { + err = EAFNOSUPPORT; + goto exit; + } exit: - return( err ); + return( err ); } //=========================================================================================================================== // sock_ntop //=========================================================================================================================== -char * sock_ntop( const void *inAddr, size_t inAddrSize, char *inBuffer, size_t inBufferSize ) +char * sock_ntop( const void *inAddr, size_t inAddrSize, char *inBuffer, size_t inBufferSize ) { - const struct sockaddr * addr; - - addr = (const struct sockaddr *) inAddr; - if( addr->sa_family == AF_INET ) - { - struct sockaddr_in * ipv4; - - if( inAddrSize == 0 ) - { - inAddrSize = sizeof( struct sockaddr_in ); - } - if( inAddrSize < sizeof( struct sockaddr_in ) ) - { - errno = EINVAL; - inBuffer = NULL; - goto exit; - } - if( inBufferSize < 16 ) - { - errno = ENOBUFS; - inBuffer = NULL; - goto exit; - } - - ipv4 = (struct sockaddr_in *) addr; - inet_ntoa_b( ipv4->sin_addr, inBuffer ); - } -#if( defined( AF_INET6 ) ) - else if( addr->sa_family == AF_INET6 ) // $$$ TO DO: Add IPv6 support. - { - errno = EAFNOSUPPORT; - inBuffer = NULL; - goto exit; - } + const struct sockaddr * addr; + + addr = (const struct sockaddr *) inAddr; + if( addr->sa_family == AF_INET ) + { + struct sockaddr_in * ipv4; + + if( inAddrSize == 0 ) + { + inAddrSize = sizeof( struct sockaddr_in ); + } + if( inAddrSize < sizeof( struct sockaddr_in ) ) + { + errno = EINVAL; + inBuffer = NULL; + goto exit; + } + if( inBufferSize < 16 ) + { + errno = ENOBUFS; + inBuffer = NULL; + goto exit; + } + + ipv4 = (struct sockaddr_in *) addr; + inet_ntoa_b( ipv4->sin_addr, inBuffer ); + } +#if ( defined( AF_INET6 ) ) + else if( addr->sa_family == AF_INET6 ) // $$$ TO DO: Add IPv6 support. + { + errno = EAFNOSUPPORT; + inBuffer = NULL; + goto exit; + } #endif - else - { - errno = EAFNOSUPPORT; - inBuffer = NULL; - goto exit; - } - + else + { + errno = EAFNOSUPPORT; + inBuffer = NULL; + goto exit; + } + exit: - return( inBuffer ); + return( inBuffer ); } #if 0 @@ -1950,139 +1950,139 @@ exit: #pragma mark == Debugging == #endif -#if( DEBUG ) +#if ( DEBUG ) -void mDNSShow( BOOL inShowRecords ); -void mDNSShowRecords( void ); -void mDNSShowTXT( const void *inTXT, size_t inTXTSize ); +void mDNSShow( BOOL inShowRecords ); +void mDNSShowRecords( void ); +void mDNSShowTXT( const void *inTXT, size_t inTXTSize ); //=========================================================================================================================== // mDNSShow //=========================================================================================================================== -void mDNSShow( BOOL inShowRecords ) +void mDNSShow( BOOL inShowRecords ) { - MDNSInterfaceItem * item; - mDNSAddr ip; - int n; - - if( !gMDNSPtr ) - { - printf( "### mDNS not initialized\n" ); - return; - } - - // Globals - - printf( "\n-- mDNS globals --\n" ); - printf( " sizeof( mDNS ) = %d\n", (int) sizeof( mDNS ) ); - printf( " sizeof( ResourceRecord ) = %d\n", (int) sizeof( ResourceRecord ) ); - printf( " sizeof( AuthRecord ) = %d\n", (int) sizeof( AuthRecord ) ); - printf( " sizeof( CacheRecord ) = %d\n", (int) sizeof( CacheRecord ) ); - printf( " gMDNSPtr = 0x%08lX\n", (unsigned long) gMDNSPtr ); - printf( " gMDNSTicksToMicrosecondsMultiplier = %ld\n", gMDNSTicksToMicrosecondsMultiplier ); - printf( " lockID = 0x%08lX\n", (unsigned long) gMDNSPtr->p->lockID ); - printf( " readyEvent = 0x%08lX\n", (unsigned long) gMDNSPtr->p->readyEvent ); - printf( " taskInitErr = %ld\n", gMDNSPtr->p->taskInitErr ); - printf( " quitEvent = 0x%08lX\n", (unsigned long) gMDNSPtr->p->quitEvent ); - printf( " commandPipe = %d\n", gMDNSPtr->p->commandPipe ); - printf( " task = 0x%08lX\n", (unsigned long) gMDNSPtr->p->task ); - printf( " quit = %d\n", gMDNSPtr->p->quit ); - printf( " configID = %ld\n", gMDNSPtr->p->configID ); - printf( " rescheduled = %d\n", gMDNSPtr->p->rescheduled ); - printf( " nicelabel = \"%.*s\"\n", gMDNSPtr->nicelabel.c[ 0 ], (char *) &gMDNSPtr->nicelabel.c[ 1 ] ); - printf( " hostLabel = \"%.*s\"\n", gMDNSPtr->hostlabel.c[ 0 ], (char *) &gMDNSPtr->hostlabel.c[ 1 ] ); - printf( "\n"); - - // Interfaces - - printf( "\n-- mDNS interfaces --\n" ); - n = 1; - for( item = gMDNSPtr->p->interfaceList; item; item = item->next ) - { - printf( " -- interface %u --\n", n ); - printf( " name = \"%s\"\n", item->name ); - printf( " multicastSocketRef = %d\n", item->multicastSocketRef ); - printf( " sendingSocketRef = %d\n", item->sendingSocketRef ); - ip = item->hostSet.ip; - printf( " hostSet.ip = %u.%u.%u.%u\n", ip.ip.v4.b[ 0 ], ip.ip.v4.b[ 1 ], - ip.ip.v4.b[ 2 ], ip.ip.v4.b[ 3 ] ); - printf( " hostSet.advertise = %s\n", item->hostSet.Advertise ? "YES" : "NO" ); - printf( " hostRegistered = %s\n", item->hostRegistered ? "YES" : "NO" ); - printf( " --\n" ); - printf( " sendMulticastCounter = %d\n", item->sendMulticastCounter ); - printf( " sendUnicastCounter = %d\n", item->sendUnicastCounter ); - printf( " sendErrorCounter = %d\n", item->sendErrorCounter ); - printf( " recvCounter = %d\n", item->recvCounter ); - printf( " recvErrorCounter = %d\n", item->recvErrorCounter ); - printf( " recvLoopCounter = %d\n", item->recvLoopCounter ); - printf( "\n" ); - ++n; - } - - // Resource Records - - if( inShowRecords ) - { - mDNSShowRecords(); - } + MDNSInterfaceItem * item; + mDNSAddr ip; + int n; + + if( !gMDNSPtr ) + { + printf( "### mDNS not initialized\n" ); + return; + } + + // Globals + + printf( "\n-- mDNS globals --\n" ); + printf( " sizeof( mDNS ) = %d\n", (int) sizeof( mDNS ) ); + printf( " sizeof( ResourceRecord ) = %d\n", (int) sizeof( ResourceRecord ) ); + printf( " sizeof( AuthRecord ) = %d\n", (int) sizeof( AuthRecord ) ); + printf( " sizeof( CacheRecord ) = %d\n", (int) sizeof( CacheRecord ) ); + printf( " gMDNSPtr = 0x%08lX\n", (unsigned long) gMDNSPtr ); + printf( " gMDNSTicksToMicrosecondsMultiplier = %ld\n", gMDNSTicksToMicrosecondsMultiplier ); + printf( " lockID = 0x%08lX\n", (unsigned long) gMDNSPtr->p->lockID ); + printf( " readyEvent = 0x%08lX\n", (unsigned long) gMDNSPtr->p->readyEvent ); + printf( " taskInitErr = %ld\n", gMDNSPtr->p->taskInitErr ); + printf( " quitEvent = 0x%08lX\n", (unsigned long) gMDNSPtr->p->quitEvent ); + printf( " commandPipe = %d\n", gMDNSPtr->p->commandPipe ); + printf( " task = 0x%08lX\n", (unsigned long) gMDNSPtr->p->task ); + printf( " quit = %d\n", gMDNSPtr->p->quit ); + printf( " configID = %ld\n", gMDNSPtr->p->configID ); + printf( " rescheduled = %d\n", gMDNSPtr->p->rescheduled ); + printf( " nicelabel = \"%.*s\"\n", gMDNSPtr->nicelabel.c[ 0 ], (char *) &gMDNSPtr->nicelabel.c[ 1 ] ); + printf( " hostLabel = \"%.*s\"\n", gMDNSPtr->hostlabel.c[ 0 ], (char *) &gMDNSPtr->hostlabel.c[ 1 ] ); + printf( "\n"); + + // Interfaces + + printf( "\n-- mDNS interfaces --\n" ); + n = 1; + for( item = gMDNSPtr->p->interfaceList; item; item = item->next ) + { + printf( " -- interface %u --\n", n ); + printf( " name = \"%s\"\n", item->name ); + printf( " multicastSocketRef = %d\n", item->multicastSocketRef ); + printf( " sendingSocketRef = %d\n", item->sendingSocketRef ); + ip = item->hostSet.ip; + printf( " hostSet.ip = %u.%u.%u.%u\n", ip.ip.v4.b[ 0 ], ip.ip.v4.b[ 1 ], + ip.ip.v4.b[ 2 ], ip.ip.v4.b[ 3 ] ); + printf( " hostSet.advertise = %s\n", item->hostSet.Advertise ? "YES" : "NO" ); + printf( " hostRegistered = %s\n", item->hostRegistered ? "YES" : "NO" ); + printf( " --\n" ); + printf( " sendMulticastCounter = %d\n", item->sendMulticastCounter ); + printf( " sendUnicastCounter = %d\n", item->sendUnicastCounter ); + printf( " sendErrorCounter = %d\n", item->sendErrorCounter ); + printf( " recvCounter = %d\n", item->recvCounter ); + printf( " recvErrorCounter = %d\n", item->recvErrorCounter ); + printf( " recvLoopCounter = %d\n", item->recvLoopCounter ); + printf( "\n" ); + ++n; + } + + // Resource Records + + if( inShowRecords ) + { + mDNSShowRecords(); + } } //=========================================================================================================================== // mDNSShowRecords //=========================================================================================================================== -void mDNSShowRecords( void ) +void mDNSShowRecords( void ) { - MDNSInterfaceItem * item; - int n; - AuthRecord * record; - char name[ MAX_ESCAPED_DOMAIN_NAME ]; - - printf( "\n-- mDNS resource records --\n" ); - n = 1; - for( record = gMDNSPtr->ResourceRecords; record; record = record->next ) - { - item = (MDNSInterfaceItem *) record->resrec.InterfaceID; - ConvertDomainNameToCString( &record->resrec.name, name ); - printf( " -- record %d --\n", n ); - printf( " interface = 0x%08X (%s)\n", (int) item, item ? item->name : "" ); - printf( " name = \"%s\"\n", name ); - printf( "\n" ); - ++n; - } - printf( "\n"); + MDNSInterfaceItem * item; + int n; + AuthRecord * record; + char name[ MAX_ESCAPED_DOMAIN_NAME ]; + + printf( "\n-- mDNS resource records --\n" ); + n = 1; + for( record = gMDNSPtr->ResourceRecords; record; record = record->next ) + { + item = (MDNSInterfaceItem *) record->resrec.InterfaceID; + ConvertDomainNameToCString( &record->resrec.name, name ); + printf( " -- record %d --\n", n ); + printf( " interface = 0x%08X (%s)\n", (int) item, item ? item->name : "" ); + printf( " name = \"%s\"\n", name ); + printf( "\n" ); + ++n; + } + printf( "\n"); } //=========================================================================================================================== // mDNSShowTXT //=========================================================================================================================== -void mDNSShowTXT( const void *inTXT, size_t inTXTSize ) +void mDNSShowTXT( const void *inTXT, size_t inTXTSize ) { - const mDNSu8 * p; - const mDNSu8 * end; - int i; - mDNSu8 size; - - printf( "\nTXT record (%u bytes):\n\n", inTXTSize ); - - p = (const mDNSu8 *) inTXT; - end = p + inTXTSize; - i = 0; - - while( p < end ) - { - size = *p++; - if( ( p + size ) > end ) - { - printf( "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" ); - break; - } - printf( "%2d (%3d bytes): \"%.*s\"\n", i, size, size, p ); - p += size; - ++i; - } - printf( "\n" ); + const mDNSu8 * p; + const mDNSu8 * end; + int i; + mDNSu8 size; + + printf( "\nTXT record (%u bytes):\n\n", inTXTSize ); + + p = (const mDNSu8 *) inTXT; + end = p + inTXTSize; + i = 0; + + while( p < end ) + { + size = *p++; + if( ( p + size ) > end ) + { + printf( "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" ); + break; + } + printf( "%2d (%3d bytes): \"%.*s\"\n", i, size, size, p ); + p += size; + ++i; + } + printf( "\n" ); } -#endif // DEBUG +#endif // DEBUG