147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* -*- Mode: C; tab-width: 4 -*-
247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *
347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *
547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * you may not use this file except in compliance with the License.
747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * You may obtain a copy of the License at
847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *
947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *     http://www.apache.org/licenses/LICENSE-2.0
1047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *
1147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Unless required by applicable law or agreed to in writing, software
1247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
1347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * See the License for the specific language governing permissions and
1547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * limitations under the License.
1647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *
1747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Formatting notes:
1847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion
1947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>,
2047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * but for the sake of brevity here I will say just this: Curly braces are not syntactially
2147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * part of an "if" statement; they are the beginning and ending markers of a compound statement;
2247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * therefore common sense dictates that if they are part of a compound statement then they
2347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * should be indented to the same level as everything else in that compound statement.
2447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Indenting curly braces at the same level as the "if" implies that curly braces are
2547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * part of the "if", which is false. (This is as misleading as people who write "char* x,y;"
2647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * thinking that variables x and y are both of type "char*" -- and anyone who doesn't
2747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * understand why variable y is not of type "char*" just proves the point that poor code
2847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * layout leads people to unfortunate misunderstandings about how the C language really works.)
2947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
3047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
3147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSEmbeddedAPI.h"           // Defines the interface provided to the client layer above
3247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "DNSCommon.h"
3347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSPosix.h"				 // Defines the specific types needed to run mDNS on this platform
3447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "dns_sd.h"
3547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
3647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <assert.h>
3747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdio.h>
3847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdlib.h>
3947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <errno.h>
4047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <string.h>
4147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <unistd.h>
42dd52342e088715929196886494c5055f9186d5c3Robert Greenwalt#ifndef __ANDROID__
43dd52342e088715929196886494c5055f9186d5c3Robert Greenwalt  #include <syslog.h>
44dd52342e088715929196886494c5055f9186d5c3Robert Greenwalt#endif
4547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdarg.h>
4647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <fcntl.h>
4747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/types.h>
4847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/time.h>
4947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/socket.h>
5047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/uio.h>
5147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/select.h>
5247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netinet/in.h>
5347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <arpa/inet.h>
5447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <time.h>                   // platform support for UTC time
5547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
5647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if USES_NETLINK
5747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <asm/types.h>
5847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <linux/netlink.h>
5947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <linux/rtnetlink.h>
6047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#else // USES_NETLINK
6147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <net/route.h>
6247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <net/if.h>
6347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif // USES_NETLINK
6447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
6547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSUNP.h"
6647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "GenLinkedList.h"
6747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
682fd068f98fa215f2681ddbe89fd7404d53218be3Christopher Lane// Disallow SO_REUSEPORT on Android because we use >3.9 kernel headers to build binaries targeted to 3.4.x.
692fd068f98fa215f2681ddbe89fd7404d53218be3Christopher Lane#ifdef __ANDROID__
702fd068f98fa215f2681ddbe89fd7404d53218be3Christopher Lane#undef SO_REUSEPORT
712fd068f98fa215f2681ddbe89fd7404d53218be3Christopher Lane#endif
722fd068f98fa215f2681ddbe89fd7404d53218be3Christopher Lane
73f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt// __ANDROID__ : replaced assert(close(..)) at several points in this file.
74f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt
7547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// ***************************************************************************
7647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Structures
7747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
7847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// We keep a list of client-supplied event sources in PosixEventSource records
7947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstruct PosixEventSource
8047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
8147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSPosixEventCallback		Callback;
8247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	void						*Context;
8347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int							fd;
8447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct  PosixEventSource	*Next;
8547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	};
8647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct PosixEventSource	PosixEventSource;
8747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
8847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Context record for interface change callback
8947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstruct IfChangeRec
9047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
9147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int	NotifySD;
9247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNS *mDNS;
9347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	};
9447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct IfChangeRec	IfChangeRec;
9547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
9647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Note that static data is initialized to zero in (modern) C.
9747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic fd_set			gEventFDs;
9847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int				gMaxFD;					// largest fd in gEventFDs
9947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic GenLinkedList	gEventSources;			// linked list of PosixEventSource's
10047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic sigset_t			gEventSignalSet;		// Signals which event loop listens for
10147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic sigset_t			gEventSignals;			// Signals which were received while inside loop
10247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
10347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// ***************************************************************************
10447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Globals (for debugging)
10547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
10647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int num_registered_interfaces = 0;
10747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int num_pkts_accepted = 0;
10847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int num_pkts_rejected = 0;
10947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
11047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// ***************************************************************************
11147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Functions
11247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
11347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint gMDNSPlatformPosixVerboseLevel = 0;
11447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
11547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define PosixErrorToStatus(errNum) ((errNum) == 0 ? mStatus_NoError : mStatus_UnknownErr)
11647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
11747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipAddr, mDNSIPPort *ipPort)
11847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
11947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	switch (sa->sa_family)
12047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
12147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		case AF_INET:
12247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
12347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			struct sockaddr_in *sin          = (struct sockaddr_in*)sa;
12447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ipAddr->type                     = mDNSAddrType_IPv4;
12547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ipAddr->ip.v4.NotAnInteger       = sin->sin_addr.s_addr;
12647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (ipPort) ipPort->NotAnInteger = sin->sin_port;
12747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			break;
12847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
12947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
13047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
13147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		case AF_INET6:
13247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
13347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			struct sockaddr_in6 *sin6        = (struct sockaddr_in6*)sa;
13447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN
13547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			assert(sin6->sin6_len == sizeof(*sin6));
13647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
13747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ipAddr->type                     = mDNSAddrType_IPv6;
13847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ipAddr->ip.v6                    = *(mDNSv6Addr*)&sin6->sin6_addr;
13947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (ipPort) ipPort->NotAnInteger = sin6->sin6_port;
14047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			break;
14147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
14247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
14347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
14447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		default:
14547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			verbosedebugf("SockAddrTomDNSAddr: Uknown address family %d\n", sa->sa_family);
14647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ipAddr->type = mDNSAddrType_None;
14747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (ipPort) ipPort->NotAnInteger = 0;
14847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			break;
14947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
15047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
15147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
15247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK
15347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** Send and Receive
15447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
15547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
15647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine when it needs to send a packet.
15747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
15847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstPort)
15947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
16047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int                     err = 0;
16147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct sockaddr_storage to;
16247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixNetworkInterface * thisIntf = (PosixNetworkInterface *)(InterfaceID);
16347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int sendingsocket = -1;
16447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
16547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)src;	// Will need to use this parameter once we implement mDNSPlatformUDPSocket/mDNSPlatformUDPClose
16647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
16747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m != NULL);
16847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(msg != NULL);
16947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(end != NULL);
17047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert((((char *) end) - ((char *) msg)) > 0);
17147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
17247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (dstPort.NotAnInteger == 0)
17347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
17447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		LogMsg("mDNSPlatformSendUDP: Invalid argument -dstPort is set to 0");
17547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return PosixErrorToStatus(EINVAL);
17647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
17747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (dst->type == mDNSAddrType_IPv4)
17847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
17947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct sockaddr_in *sin = (struct sockaddr_in*)&to;
18047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN
18147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sin->sin_len            = sizeof(*sin);
18247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
18347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sin->sin_family         = AF_INET;
18447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sin->sin_port           = dstPort.NotAnInteger;
18547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sin->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
18647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sendingsocket           = thisIntf ? thisIntf->multicastSocket4 : m->p->unicastSocket4;
18747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
18847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
18947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
19047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else if (dst->type == mDNSAddrType_IPv6)
19147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
19247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&to;
19347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		mDNSPlatformMemZero(sin6, sizeof(*sin6));
19447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN
19547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sin6->sin6_len            = sizeof(*sin6);
19647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
19747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sin6->sin6_family         = AF_INET6;
19847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sin6->sin6_port           = dstPort.NotAnInteger;
19947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sin6->sin6_addr           = *(struct in6_addr*)&dst->ip.v6;
20047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sendingsocket             = thisIntf ? thisIntf->multicastSocket6 : m->p->unicastSocket6;
20147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
20247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
20347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
20447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (sendingsocket >= 0)
20547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		err = sendto(sendingsocket, msg, (char*)end - (char*)msg, 0, (struct sockaddr *)&to, GET_SA_LEN(to));
20647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
20747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if      (err > 0) err = 0;
20847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else if (err < 0)
20947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
21047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		static int MessageCount = 0;
21147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
21247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (!mDNSAddressIsAllDNSLinkGroup(dst))
21347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
21447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
21547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (MessageCount < 1000)
21647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
21747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			MessageCount++;
21847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (thisIntf)
21947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a on interface %#a/%s/%d",
22047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt							  errno, strerror(errno), dst, &thisIntf->coreIntf.ip, thisIntf->intfName, thisIntf->index);
22147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			else
22247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a", errno, strerror(errno), dst);
22347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
22447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
22547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
22647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return PosixErrorToStatus(err);
22747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
22847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
22947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// This routine is called when the main loop detects that data is available on a socket.
23047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int skt)
23147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
23247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSAddr   senderAddr, destAddr;
23347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSIPPort senderPort;
23447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ssize_t                 packetLen;
23547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSMessage              packet;
23647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct my_in_pktinfo    packetInfo;
23747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct sockaddr_storage from;
23847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	socklen_t               fromLen;
23947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int                     flags;
24047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSu8					ttl;
24147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSBool                reject;
24247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const mDNSInterfaceID InterfaceID = intf ? intf->coreIntf.InterfaceID : NULL;
24347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
24447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m    != NULL);
24547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(skt  >= 0);
24647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
24747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	fromLen = sizeof(from);
24847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	flags   = 0;
24947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	packetLen = recvfrom_flags(skt, &packet, sizeof(packet), &flags, (struct sockaddr *) &from, &fromLen, &packetInfo, &ttl);
25047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
25147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (packetLen >= 0)
25247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
25347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		SockAddrTomDNSAddr((struct sockaddr*)&from, &senderAddr, &senderPort);
25447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		SockAddrTomDNSAddr((struct sockaddr*)&packetInfo.ipi_addr, &destAddr, NULL);
25547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
25647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// If we have broken IP_RECVDSTADDR functionality (so far
25747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// I've only seen this on OpenBSD) then apply a hack to
25847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// convince mDNS Core that this isn't a spoof packet.
25947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Basically what we do is check to see whether the
26047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// packet arrived as a multicast and, if so, set its
26147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// destAddr to the mDNS address.
26247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		//
26347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// I must admit that I could just be doing something
26447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// wrong on OpenBSD and hence triggering this problem
26547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// but I'm at a loss as to how.
26647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		//
26747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// If this platform doesn't have IP_PKTINFO or IP_RECVDSTADDR, then we have
26847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// no way to tell the destination address or interface this packet arrived on,
26947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// so all we can do is just assume it's a multicast
27047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
27147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		#if HAVE_BROKEN_RECVDSTADDR || (!defined(IP_PKTINFO) && !defined(IP_RECVDSTADDR))
27247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if ((destAddr.NotAnInteger == 0) && (flags & MSG_MCAST))
27347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				{
27447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				destAddr.type = senderAddr.type;
27547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if      (senderAddr.type == mDNSAddrType_IPv4) destAddr.ip.v4 = AllDNSLinkGroup_v4.ip.v4;
27647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				else if (senderAddr.type == mDNSAddrType_IPv6) destAddr.ip.v6 = AllDNSLinkGroup_v6.ip.v6;
27747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
27847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		#endif
27947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
28047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// We only accept the packet if the interface on which it came
28147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// in matches the interface associated with this socket.
28247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// We do this match by name or by index, depending on which
28347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// information is available.  recvfrom_flags sets the name
28447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// to "" if the name isn't available, or the index to -1
28547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// if the index is available.  This accomodates the various
28647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// different capabilities of our target platforms.
28747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
28847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		reject = mDNSfalse;
28947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (!intf)
29047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
29147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// Ignore multicasts accidentally delivered to our unicast receiving socket
29247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (mDNSAddrIsDNSMulticast(&destAddr)) packetLen = -1;
29347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
29447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else
29547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
29647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if      (packetInfo.ipi_ifname[0] != 0) reject = (strcmp(packetInfo.ipi_ifname, intf->intfName) != 0);
29747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			else if (packetInfo.ipi_ifindex != -1)  reject = (packetInfo.ipi_ifindex != intf->index);
29847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
29947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (reject)
30047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				{
30147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				verbosedebugf("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d/%d",
30247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					&senderAddr, &destAddr, packetInfo.ipi_ifname, packetInfo.ipi_ifindex,
30347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					&intf->coreIntf.ip, intf->intfName, intf->index, skt);
30447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				packetLen = -1;
30547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				num_pkts_rejected++;
30647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (num_pkts_rejected > (num_pkts_accepted + 1) * (num_registered_interfaces + 1) * 2)
30747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					{
30847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					fprintf(stderr,
30947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						"*** WARNING: Received %d packets; Accepted %d packets; Rejected %d packets because of interface mismatch\n",
31047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						num_pkts_accepted + num_pkts_rejected, num_pkts_accepted, num_pkts_rejected);
31147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					num_pkts_accepted = 0;
31247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					num_pkts_rejected = 0;
31347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					}
31447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
31547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			else
31647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				{
31747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				verbosedebugf("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d/%d",
31847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					&senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index, skt);
31947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				num_pkts_accepted++;
32047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
32147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
32247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
32347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
32447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (packetLen >= 0)
32547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		mDNSCoreReceive(m, &packet, (mDNSu8 *)&packet + packetLen,
32647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			&senderAddr, senderPort, &destAddr, MulticastDNSPort, InterfaceID);
32747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
32847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
32947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS * const m, TCPSocketFlags flags, mDNSIPPort * port)
33047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
33147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)m;			// Unused
33247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)flags;		// Unused
33347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)port;			// Unused
33447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return NULL;
33547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
33647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
33747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd)
33847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
33947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)flags;		// Unused
34047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)sd;			// Unused
34147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return NULL;
34247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
34347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
34447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
34547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
34647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)sock;			// Unused
34747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return -1;
34847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
34947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
35047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname, mDNSInterfaceID InterfaceID,
35147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt										  TCPConnectionCallback callback, void *context)
35247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
35347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)sock;			// Unused
35447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)dst;			// Unused
35547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)dstport;		// Unused
35647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)hostname;     // Unused
35747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)InterfaceID;	// Unused
35847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)callback;		// Unused
35947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)context;		// Unused
36047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return(mStatus_UnsupportedErr);
36147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
36247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
36347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
36447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
36547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)sock;			// Unused
36647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
36747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
36847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool * closed)
36947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
37047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)sock;			// Unused
37147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)buf;			// Unused
37247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)buflen;		// Unused
37347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)closed;		// Unused
37447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
37547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
37647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
37747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
37847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
37947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)sock;			// Unused
38047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)msg;			// Unused
38147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)len;			// Unused
38247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
38347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
38447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
38547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS * const m, mDNSIPPort port)
38647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
38747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)m;			// Unused
38847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)port;			// Unused
38947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return NULL;
39047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
39147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
39247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void           mDNSPlatformUDPClose(UDPSocket *sock)
39347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
39447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)sock;			// Unused
39547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
39647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
39747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
39847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
39947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)m;			// Unused
40047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)InterfaceID;			// Unused
40147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
40247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
40347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
40447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
40547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)msg;			// Unused
40647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)end;			// Unused
40747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)InterfaceID;			// Unused
40847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
40947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
41047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
41147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
41247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)m;			// Unused
41347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)tpa;			// Unused
41447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)tha;			// Unused
41547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)InterfaceID;			// Unused
41647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
41747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
41847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
41947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
42047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return(mStatus_UnsupportedErr);
42147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
42247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
42347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformTLSTearDownCerts(void)
42447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
42547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
42647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
42747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
42847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
42947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) m;
43047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) allowSleep;
43147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) reason;
43247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
43347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
43447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK
43547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark -
43647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark - /etc/hosts support
43747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
43847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
43947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
44047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    {
44147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    (void)m;  // unused
44247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)rr;
44347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)result;
44447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
44547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
44647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
44747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK
44847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** DDNS Config Platform Functions
44947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
45047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
45147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains)
45247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
45347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) m;
45447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) setservers;
45547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) fqdn;
45647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) setsearch;
45747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) RegDomains;
45847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) BrowseDomains;
45947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
46047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
46147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS * const m, mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router)
46247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
46347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) m;
46447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) v4;
46547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) v6;
46647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) router;
46747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
46847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return mStatus_UnsupportedErr;
46947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
47047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
47147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
47247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
47347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) dname;
47447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) status;
47547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
47647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
47747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK
47847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** Init and Term
47947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
48047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
48147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// This gets the current hostname, truncating it at the first dot if necessary
48247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void GetUserSpecifiedRFC1034ComputerName(domainlabel *const namelabel)
48347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
48447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int len = 0;
485afc86e3216439a9437ea54905853275111eac4e2Robert Greenwalt#ifndef __ANDROID__
48647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	gethostname((char *)(&namelabel->c[1]), MAX_DOMAIN_LABEL);
487afc86e3216439a9437ea54905853275111eac4e2Robert Greenwalt#else
488afc86e3216439a9437ea54905853275111eac4e2Robert Greenwalt	// use an appropriate default label rather than the linux default of 'localhost'
489afc86e3216439a9437ea54905853275111eac4e2Robert Greenwalt	strncpy(&namelabel->c[1], "Android", MAX_DOMAIN_LABEL);
490afc86e3216439a9437ea54905853275111eac4e2Robert Greenwalt#endif
49147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (len < MAX_DOMAIN_LABEL && namelabel->c[len+1] && namelabel->c[len+1] != '.') len++;
49247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	namelabel->c[0] = len;
49347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
49447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
49547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// On OS X this gets the text of the field labelled "Computer Name" in the Sharing Prefs Control Panel
49647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Other platforms can either get the information from the appropriate place,
49747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// or they can alternatively just require all registering services to provide an explicit name
49847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
49947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
50047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// On Unix we have no better name than the host name, so we just use that.
50147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	GetUserSpecifiedRFC1034ComputerName(namelabel);
50247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
50347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
50447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport int ParseDNSServers(mDNS *m, const char *filePath)
50547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
50647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char line[256];
50747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char nameserver[16];
50847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char keyword[10];
50947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int  numOfServers = 0;
51047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	FILE *fp = fopen(filePath, "r");
51147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (fp == NULL) return -1;
51247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (fgets(line,sizeof(line),fp))
51347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
51447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct in_addr ina;
51547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		line[255]='\0';		// just to be safe
51647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (sscanf(line,"%10s %15s", keyword, nameserver) != 2) continue;	// it will skip whitespaces
51747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (strncasecmp(keyword,"nameserver",10)) continue;
51847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (inet_aton(nameserver, (struct in_addr *)&ina) != 0)
51947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
52047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			mDNSAddr DNSAddr;
52147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			DNSAddr.type = mDNSAddrType_IPv4;
52247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			DNSAddr.ip.v4.NotAnInteger = ina.s_addr;
52347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, &DNSAddr, UnicastDNSPort, mDNSfalse, 0);
52447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			numOfServers++;
52547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
52654bbef089d469dba7032c9cefa703647a0e917f1Dave Platt		}
52754bbef089d469dba7032c9cefa703647a0e917f1Dave Platt    //  __ANDROID__ : if fp was opened, it needs to be closed
52854bbef089d469dba7032c9cefa703647a0e917f1Dave Platt	int fp_closed = fclose(fp);
52954bbef089d469dba7032c9cefa703647a0e917f1Dave Platt	assert(fp_closed == 0);
53047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return (numOfServers > 0) ? 0 : -1;
53147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
53247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
53347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Searches the interface list looking for the named interface.
53447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Returns a pointer to if it found, or NULL otherwise.
53547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal PosixNetworkInterface *SearchForInterfaceByName(mDNS *const m, const char *intfName)
53647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
53747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixNetworkInterface *intf;
53847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
53947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m != NULL);
54047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(intfName != NULL);
54147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
54247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	intf = (PosixNetworkInterface*)(m->HostInterfaces);
54347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while ((intf != NULL) && (strcmp(intf->intfName, intfName) != 0))
54447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf = (PosixNetworkInterface *)(intf->coreIntf.next);
54547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
54647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return intf;
54747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
54847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
54947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 index)
55047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
55147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixNetworkInterface *intf;
55247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
55347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m != NULL);
55447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
55547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
55647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (index == kDNSServiceInterfaceIndexP2P      ) return(mDNSInterface_P2P);
55747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (index == kDNSServiceInterfaceIndexAny      ) return(mDNSInterface_Any);
55847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
55947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	intf = (PosixNetworkInterface*)(m->HostInterfaces);
56047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while ((intf != NULL) && (mDNSu32) intf->index != index)
56147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf = (PosixNetworkInterface *)(intf->coreIntf.next);
56247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
56347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return (mDNSInterfaceID) intf;
56447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
56547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
56647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange)
56747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
56847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixNetworkInterface *intf;
56947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) suppressNetworkChange; // Unused
57047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
57147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m != NULL);
57247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
57347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
57447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (id == mDNSInterface_P2P      ) return(kDNSServiceInterfaceIndexP2P);
57547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (id == mDNSInterface_Any      ) return(kDNSServiceInterfaceIndexAny);
57647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
57747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	intf = (PosixNetworkInterface*)(m->HostInterfaces);
57847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while ((intf != NULL) && (mDNSInterfaceID) intf != id)
57947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf = (PosixNetworkInterface *)(intf->coreIntf.next);
58047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
58147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return intf ? intf->index : 0;
58247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
58347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
58447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Frees the specified PosixNetworkInterface structure. The underlying
58547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// interface must have already been deregistered with the mDNS core.
58647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf)
58747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
58847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(intf != NULL);
58947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (intf->intfName != NULL)        free((void *)intf->intfName);
590f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt	if (intf->multicastSocket4 != -1)
591f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		{
592f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		int ipv4_closed = close(intf->multicastSocket4);
593f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		assert(ipv4_closed == 0);
594f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		}
59547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
596f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt	if (intf->multicastSocket6 != -1)
597f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		{
598f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		int ipv6_closed = close(intf->multicastSocket6);
599f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		assert(ipv6_closed == 0);
600f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		}
60147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
60247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	free(intf);
60347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
60447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
60547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Grab the first interface, deregister it, free it, and repeat until done.
60647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void ClearInterfaceList(mDNS *const m)
60747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
60847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m != NULL);
60947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
61047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (m->HostInterfaces)
61147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
61247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		PosixNetworkInterface *intf = (PosixNetworkInterface*)(m->HostInterfaces);
61347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		mDNS_DeregisterInterface(m, &intf->coreIntf, mDNSfalse);
61447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "Deregistered interface %s\n", intf->intfName);
61547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		FreePosixNetworkInterface(intf);
61647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
61747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	num_registered_interfaces = 0;
61847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	num_pkts_accepted = 0;
61947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	num_pkts_rejected = 0;
62047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
62147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
62247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Sets up a send/receive socket.
62347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
62447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
62547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interfaceIndex, int *sktPtr)
62647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
62747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int err = 0;
62847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	static const int kOn = 1;
62947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	static const int kIntTwoFiveFive = 255;
63047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	static const unsigned char kByteTwoFiveFive = 255;
63147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const mDNSBool JoinMulticastGroup = (port.NotAnInteger != 0);
63247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
63347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) interfaceIndex;	// This parameter unused on plaforms that don't have IPv6
63447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(intfAddr != NULL);
63547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(sktPtr != NULL);
63647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(*sktPtr == -1);
63747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
63847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Open the socket...
63947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if      (intfAddr->sa_family == AF_INET) *sktPtr = socket(PF_INET,  SOCK_DGRAM, IPPROTO_UDP);
64047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
64147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else if (intfAddr->sa_family == AF_INET6) *sktPtr = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
64247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
64347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else return EINVAL;
64447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
64547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*sktPtr < 0) { err = errno; perror((intfAddr->sa_family == AF_INET) ? "socket AF_INET" : "socket AF_INET6"); }
64647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
64747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// ... with a shared UDP port, if it's for multicast receiving
64847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0 && port.NotAnInteger)
64947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
65047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		#if defined(SO_REUSEPORT)
65147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn));
65247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		#elif defined(SO_REUSEADDR)
65347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
65447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		#else
65547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			#error This platform has no way to avoid address busy errors on multicast.
65647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		#endif
65747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err < 0) { err = errno; perror("setsockopt - SO_REUSExxxx"); }
65847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
65947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
66047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// We want to receive destination addresses and interface identifiers.
66147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (intfAddr->sa_family == AF_INET)
66247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
66347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct ip_mreq imr;
66447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct sockaddr_in bindAddr;
66547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
66647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
66747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			#if defined(IP_PKTINFO)									// Linux
66847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				err = setsockopt(*sktPtr, IPPROTO_IP, IP_PKTINFO, &kOn, sizeof(kOn));
66947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (err < 0) { err = errno; perror("setsockopt - IP_PKTINFO"); }
67047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			#elif defined(IP_RECVDSTADDR) || defined(IP_RECVIF)		// BSD and Solaris
67147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				#if defined(IP_RECVDSTADDR)
67247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					err = setsockopt(*sktPtr, IPPROTO_IP, IP_RECVDSTADDR, &kOn, sizeof(kOn));
67347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					if (err < 0) { err = errno; perror("setsockopt - IP_RECVDSTADDR"); }
67447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				#endif
67547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				#if defined(IP_RECVIF)
67647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					if (err == 0)
67747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						{
67847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						err = setsockopt(*sktPtr, IPPROTO_IP, IP_RECVIF, &kOn, sizeof(kOn));
67947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						if (err < 0) { err = errno; perror("setsockopt - IP_RECVIF"); }
68047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						}
68147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				#endif
68247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			#else
68347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				#warning This platform has no way to get the destination interface information -- will only work for single-homed hosts
68447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			#endif
68547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
68647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	#if defined(IP_RECVTTL)									// Linux
68747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
68847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
68947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			setsockopt(*sktPtr, IPPROTO_IP, IP_RECVTTL, &kOn, sizeof(kOn));
69047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// We no longer depend on being able to get the received TTL, so don't worry if the option fails
69147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
69247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	#endif
69347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Add multicast group membership on this interface
69447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0 && JoinMulticastGroup)
69547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
69647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			imr.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
69747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			imr.imr_interface        = ((struct sockaddr_in*)intfAddr)->sin_addr;
69847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
69947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("setsockopt - IP_ADD_MEMBERSHIP"); }
70047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
70147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
70247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Specify outgoing interface too
70347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0 && JoinMulticastGroup)
70447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
70547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_IF, &((struct sockaddr_in*)intfAddr)->sin_addr, sizeof(struct in_addr));
70647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_IF"); }
70747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
70847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
70947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Per the mDNS spec, send unicast packets with TTL 255
71047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
71147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
71247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, IPPROTO_IP, IP_TTL, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
71347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("setsockopt - IP_TTL"); }
71447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
71547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
71647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// and multicast packets with TTL 255 too
71747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// There's some debate as to whether IP_MULTICAST_TTL is an int or a byte so we just try both.
71847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
71947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
72047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_TTL, &kByteTwoFiveFive, sizeof(kByteTwoFiveFive));
72147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0 && errno == EINVAL)
72247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_TTL, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
72347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_TTL"); }
72447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
72547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
72647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// And start listening for packets
72747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
72847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
72947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			bindAddr.sin_family      = AF_INET;
73047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			bindAddr.sin_port        = port.NotAnInteger;
73147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			bindAddr.sin_addr.s_addr = INADDR_ANY; // Want to receive multicasts AND unicasts on this socket
73247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = bind(*sktPtr, (struct sockaddr *) &bindAddr, sizeof(bindAddr));
73347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("bind"); fflush(stderr); }
73447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
73547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		} // endif (intfAddr->sa_family == AF_INET)
73647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
73747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
73847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else if (intfAddr->sa_family == AF_INET6)
73947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
74047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct ipv6_mreq imr6;
74147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct sockaddr_in6 bindAddr6;
74247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	#if defined(IPV6_PKTINFO)
74347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
74447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
74547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_2292_PKTINFO, &kOn, sizeof(kOn));
74647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (err < 0) { err = errno; perror("setsockopt - IPV6_PKTINFO"); }
74747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
74847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	#else
74947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		#warning This platform has no way to get the destination interface information for IPv6 -- will only work for single-homed hosts
75047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	#endif
75147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	#if defined(IPV6_HOPLIMIT)
75247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
75347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
75447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_2292_HOPLIMIT, &kOn, sizeof(kOn));
75547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (err < 0) { err = errno; perror("setsockopt - IPV6_HOPLIMIT"); }
75647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
75747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	#endif
75847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
75947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Add multicast group membership on this interface
76047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0 && JoinMulticastGroup)
76147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
76247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			imr6.ipv6mr_multiaddr       = *(const struct in6_addr*)&AllDNSLinkGroup_v6.ip.v6;
76347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			imr6.ipv6mr_interface       = interfaceIndex;
76447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			//LogMsg("Joining %.16a on %d", &imr6.ipv6mr_multiaddr, imr6.ipv6mr_interface);
76547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_JOIN_GROUP, &imr6, sizeof(imr6));
76647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0)
76747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				{
76847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				err = errno;
76947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				verbosedebugf("IPV6_JOIN_GROUP %.16a on %d failed.\n", &imr6.ipv6mr_multiaddr, imr6.ipv6mr_interface);
77047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				perror("setsockopt - IPV6_JOIN_GROUP");
77147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
77247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
77347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
77447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Specify outgoing interface too
77547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0 && JoinMulticastGroup)
77647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
77747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			u_int	multicast_if = interfaceIndex;
77847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_if, sizeof(multicast_if));
77947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_IF"); }
78047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
78147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
78247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// We want to receive only IPv6 packets on this socket.
78347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Without this option, we may get IPv4 addresses as mapped addresses.
78447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
78547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
78647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_V6ONLY, &kOn, sizeof(kOn));
78747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("setsockopt - IPV6_V6ONLY"); }
78847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
78947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
79047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Per the mDNS spec, send unicast packets with TTL 255
79147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
79247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
79347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
79447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("setsockopt - IPV6_UNICAST_HOPS"); }
79547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
79647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
79747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// and multicast packets with TTL 255 too
79847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// There's some debate as to whether IPV6_MULTICAST_HOPS is an int or a byte so we just try both.
79947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
80047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
80147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kByteTwoFiveFive, sizeof(kByteTwoFiveFive));
80247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0 && errno == EINVAL)
80347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
80447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_HOPS"); }
80547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
80647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
80747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// And start listening for packets
80847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err == 0)
80947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
81047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			mDNSPlatformMemZero(&bindAddr6, sizeof(bindAddr6));
81147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN
81247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			bindAddr6.sin6_len         = sizeof(bindAddr6);
81347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
81447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			bindAddr6.sin6_family      = AF_INET6;
81547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			bindAddr6.sin6_port        = port.NotAnInteger;
81647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			bindAddr6.sin6_flowinfo    = 0;
81747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			bindAddr6.sin6_addr        = in6addr_any; // Want to receive multicasts AND unicasts on this socket
81847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			bindAddr6.sin6_scope_id    = 0;
81947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = bind(*sktPtr, (struct sockaddr *) &bindAddr6, sizeof(bindAddr6));
82047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) { err = errno; perror("bind"); fflush(stderr); }
82147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
82247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		} // endif (intfAddr->sa_family == AF_INET6)
82347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
82447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
82547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Set the socket to non-blocking.
82647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0)
82747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
82847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		err = fcntl(*sktPtr, F_GETFL, 0);
82947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err < 0) err = errno;
83047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else
83147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
83247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = fcntl(*sktPtr, F_SETFL, err | O_NONBLOCK);
83347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err < 0) err = errno;
83447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
83547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
83647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
83747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Clean up
838f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt	if (err != 0 && *sktPtr != -1)
839f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		{
840f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		int sktClosed = close(*sktPtr);
841f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		assert(sktClosed == 0);
842f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		*sktPtr = -1;
843f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		}
84447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert((err == 0) == (*sktPtr != -1));
84547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return err;
84647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
84747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
84847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Creates a PosixNetworkInterface for the interface whose IP address is
84947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// intfAddr and whose name is intfName and registers it with mDNS core.
85047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct sockaddr *intfMask, const char *intfName, int intfIndex)
85147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
85247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int err = 0;
85347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixNetworkInterface *intf;
85447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixNetworkInterface *alias = NULL;
85547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
85647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m != NULL);
85747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(intfAddr != NULL);
85847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(intfName != NULL);
85947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(intfMask != NULL);
86047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
86147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Allocate the interface structure itself.
86247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	intf = (PosixNetworkInterface*)malloc(sizeof(*intf));
86347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (intf == NULL) { assert(0); err = ENOMEM; }
86447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
86547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// And make a copy of the intfName.
86647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0)
86747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
86847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf->intfName = strdup(intfName);
86947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (intf->intfName == NULL) { assert(0); err = ENOMEM; }
87047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
87147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
87247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0)
87347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
87447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Set up the fields required by the mDNS core.
87547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		SockAddrTomDNSAddr(intfAddr, &intf->coreIntf.ip, NULL);
87647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		SockAddrTomDNSAddr(intfMask, &intf->coreIntf.mask, NULL);
87747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
87847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		//LogMsg("SetupOneInterface: %#a %#a",  &intf->coreIntf.ip,  &intf->coreIntf.mask);
87947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		strncpy(intf->coreIntf.ifname, intfName, sizeof(intf->coreIntf.ifname));
88047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf->coreIntf.ifname[sizeof(intf->coreIntf.ifname)-1] = 0;
88147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf->coreIntf.Advertise = m->AdvertiseLocalAddresses;
88247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf->coreIntf.McastTxRx = mDNStrue;
88347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
88447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Set up the extra fields in PosixNetworkInterface.
88547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		assert(intf->intfName != NULL);         // intf->intfName already set up above
88647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf->index                = intfIndex;
88747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf->multicastSocket4     = -1;
88847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
88947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf->multicastSocket6     = -1;
89047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
89147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		alias                      = SearchForInterfaceByName(m, intf->intfName);
89247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (alias == NULL) alias   = intf;
89347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		intf->coreIntf.InterfaceID = (mDNSInterfaceID)alias;
89447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
89547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (alias != intf)
89647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			debugf("SetupOneInterface: %s %#a is an alias of %#a", intfName, &intf->coreIntf.ip, &alias->coreIntf.ip);
89747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
89847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
89947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Set up the multicast socket
90047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0)
90147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
90247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (alias->multicastSocket4 == -1 && intfAddr->sa_family == AF_INET)
90347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocket4);
90447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
90547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else if (alias->multicastSocket6 == -1 && intfAddr->sa_family == AF_INET6)
90647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocket6);
90747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
90847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
90947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
91047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// The interface is all ready to go, let's register it with the mDNS core.
91147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0)
91247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		err = mDNS_RegisterInterface(m, &intf->coreIntf, mDNSfalse);
91347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
91447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Clean up.
91547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0)
91647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
91747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		num_registered_interfaces++;
91847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		debugf("SetupOneInterface: %s %#a Registered", intf->intfName, &intf->coreIntf.ip);
91947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (gMDNSPlatformPosixVerboseLevel > 0)
92047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			fprintf(stderr, "Registered interface %s\n", intf->intfName);
92147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
92247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
92347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
92447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Use intfName instead of intf->intfName in the next line to avoid dereferencing NULL.
92547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		debugf("SetupOneInterface: %s %#a failed to register %d", intfName, &intf->coreIntf.ip, err);
92647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (intf) { FreePosixNetworkInterface(intf); intf = NULL; }
92747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
92847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
92947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert((err == 0) == (intf != NULL));
93047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
93147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return err;
93247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
93347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
93447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Call get_ifi_info() to obtain a list of active interfaces and call SetupOneInterface() on each one.
93547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int SetupInterfaceList(mDNS *const m)
93647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
93747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSBool        foundav4       = mDNSfalse;
93847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int             err            = 0;
93947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct ifi_info *intfList      = get_ifi_info(AF_INET, mDNStrue);
94047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct ifi_info *firstLoopback = NULL;
94147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
94247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m != NULL);
94347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	debugf("SetupInterfaceList");
94447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
94547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (intfList == NULL) err = ENOENT;
94647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
94747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
94847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0)		/* Link the IPv6 list to the end of the IPv4 list */
94947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
95047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct ifi_info **p = &intfList;
95147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		while (*p) p = &(*p)->ifi_next;
95247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*p = get_ifi_info(AF_INET6, mDNStrue);
95347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
95447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
95547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
95647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0)
95747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
95847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct ifi_info *i = intfList;
95947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		while (i)
96047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
96147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (     ((i->ifi_addr->sa_family == AF_INET)
96247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
96347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					  || (i->ifi_addr->sa_family == AF_INET6)
96447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
96547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				) &&  (i->ifi_flags & IFF_UP) && !(i->ifi_flags & IFF_POINTOPOINT))
96647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				{
96747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (i->ifi_flags & IFF_LOOPBACK)
96847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					{
96947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					if (firstLoopback == NULL)
97047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						firstLoopback = i;
97147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					}
97247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				else
97347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					{
97447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					if (SetupOneInterface(m, i->ifi_addr, i->ifi_netmask, i->ifi_name, i->ifi_index) == 0)
97547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						if (i->ifi_addr->sa_family == AF_INET)
97647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt							foundav4 = mDNStrue;
97747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					}
97847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
97947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			i = i->ifi_next;
98047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
98147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
98247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// If we found no normal interfaces but we did find a loopback interface, register the
98347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// loopback interface.  This allows self-discovery if no interfaces are configured.
98447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Temporary workaround: Multicast loopback on IPv6 interfaces appears not to work.
98547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// In the interim, we skip loopback interface only if we found at least one v4 interface to use
98647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// if ((m->HostInterfaces == NULL) && (firstLoopback != NULL))
98747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (!foundav4 && firstLoopback)
98847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			(void) SetupOneInterface(m, firstLoopback->ifi_addr, firstLoopback->ifi_netmask, firstLoopback->ifi_name, firstLoopback->ifi_index);
98947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
99047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
99147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Clean up.
99247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (intfList != NULL) free_ifi_info(intfList);
99347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return err;
99447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
99547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
99647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if USES_NETLINK
99747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
99847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// See <http://www.faqs.org/rfcs/rfc3549.html> for a description of NetLink
99947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
100047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Open a socket that will receive interface change notifications
100147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mStatus OpenIfNotifySocket(int *pFD)
100247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
100347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mStatus					err = mStatus_NoError;
100447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct sockaddr_nl		snl;
100547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int sock;
100647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int ret;
100747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
100847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
100947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (sock < 0)
101047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return errno;
101147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
101247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Configure read to be non-blocking because inbound msg size is not known in advance
101347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) fcntl(sock, F_SETFL, O_NONBLOCK);
101447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
101547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	/* Subscribe the socket to Link & IP addr notifications. */
101647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSPlatformMemZero(&snl, sizeof snl);
101747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	snl.nl_family = AF_NETLINK;
101847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
101947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ret = bind(sock, (struct sockaddr *) &snl, sizeof snl);
102047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (0 == ret)
102147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*pFD = sock;
102247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
102347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		err = errno;
102447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
102547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return err;
102647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
102747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
102847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if MDNS_DEBUGMSGS
102947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void		PrintNetLinkMsg(const struct nlmsghdr *pNLMsg)
103047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
103147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char *kNLMsgTypes[] = { "", "NLMSG_NOOP", "NLMSG_ERROR", "NLMSG_DONE", "NLMSG_OVERRUN" };
103247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char *kNLRtMsgTypes[] = { "RTM_NEWLINK", "RTM_DELLINK", "RTM_GETLINK", "RTM_NEWADDR", "RTM_DELADDR", "RTM_GETADDR" };
103347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
103447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	printf("nlmsghdr len=%d, type=%s, flags=0x%x\n", pNLMsg->nlmsg_len,
103547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			pNLMsg->nlmsg_type < RTM_BASE ? kNLMsgTypes[pNLMsg->nlmsg_type] : kNLRtMsgTypes[pNLMsg->nlmsg_type - RTM_BASE],
103647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			pNLMsg->nlmsg_flags);
103747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
103847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (RTM_NEWLINK <= pNLMsg->nlmsg_type && pNLMsg->nlmsg_type <= RTM_GETLINK)
103947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
104047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct ifinfomsg	*pIfInfo = (struct ifinfomsg*) NLMSG_DATA(pNLMsg);
104147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		printf("ifinfomsg family=%d, type=%d, index=%d, flags=0x%x, change=0x%x\n", pIfInfo->ifi_family,
104247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				pIfInfo->ifi_type, pIfInfo->ifi_index, pIfInfo->ifi_flags, pIfInfo->ifi_change);
104347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
104447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
104547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else if (RTM_NEWADDR <= pNLMsg->nlmsg_type && pNLMsg->nlmsg_type <= RTM_GETADDR)
104647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
104747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct ifaddrmsg	*pIfAddr = (struct ifaddrmsg*) NLMSG_DATA(pNLMsg);
104847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		printf("ifaddrmsg family=%d, index=%d, flags=0x%x\n", pIfAddr->ifa_family,
104947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				pIfAddr->ifa_index, pIfAddr->ifa_flags);
105047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
105147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	printf("\n");
105247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
105347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
105447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
105547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSu32		ProcessRoutingNotification(int sd)
105647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Read through the messages on sd and if any indicate that any interface records should
105747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
105847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
105947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ssize_t					readCount;
106047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char					buff[4096];
106147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct nlmsghdr			*pNLMsg = (struct nlmsghdr*) buff;
106247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSu32				result = 0;
106347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
106447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// The structure here is more complex than it really ought to be because,
106547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// unfortunately, there's no good way to size a buffer in advance large
106647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// enough to hold all pending data and so avoid message fragmentation.
106747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// (Note that FIONREAD is not supported on AF_NETLINK.)
106847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
106947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	readCount = read(sd, buff, sizeof buff);
107047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (1)
107147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
107247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Make sure we've got an entire nlmsghdr in the buffer, and payload, too.
107347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// If not, discard already-processed messages in buffer and read more data.
107447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (((char*) &pNLMsg[1] > (buff + readCount)) ||	// i.e. *pNLMsg extends off end of buffer
107547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			 ((char*) pNLMsg + pNLMsg->nlmsg_len > (buff + readCount)))
107647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
107747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (buff < (char*) pNLMsg)		// we have space to shuffle
107847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				{
107947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				// discard processed data
108047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				readCount -= ((char*) pNLMsg - buff);
108147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				memmove(buff, pNLMsg, readCount);
108247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				pNLMsg = (struct nlmsghdr*) buff;
108347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
108447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				// read more data
108547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				readCount += read(sd, buff + readCount, sizeof buff - readCount);
108647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				continue;					// spin around and revalidate with new readCount
108747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
108847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			else
108947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				break;	// Otherwise message does not fit in buffer
109047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
109147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
109247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if MDNS_DEBUGMSGS
109347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		PrintNetLinkMsg(pNLMsg);
109447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
109547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
109647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Process the NetLink message
109747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK)
109847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
109947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR)
110047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
110147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
110247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Advance pNLMsg to the next message in the buffer
110347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE)
110447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
110547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ssize_t	len = readCount - ((char*)pNLMsg - buff);
110647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			pNLMsg = NLMSG_NEXT(pNLMsg, len);
110747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
110847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else
110947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			break;	// all done!
111047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
111147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
111247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return result;
111347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
111447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
111547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#else // USES_NETLINK
111647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
111747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Open a socket that will receive interface change notifications
111847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mStatus OpenIfNotifySocket(int *pFD)
111947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
112047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	*pFD = socket(AF_ROUTE, SOCK_RAW, 0);
112147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
112247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*pFD < 0)
112347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return mStatus_UnknownErr;
112447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
112547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Configure read to be non-blocking because inbound msg size is not known in advance
112647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) fcntl(*pFD, F_SETFL, O_NONBLOCK);
112747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
112847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return mStatus_NoError;
112947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
113047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
113147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if MDNS_DEBUGMSGS
113247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void		PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg)
113347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
113447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char *kRSMsgTypes[] = { "", "RTM_ADD", "RTM_DELETE", "RTM_CHANGE", "RTM_GET", "RTM_LOSING",
113547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					"RTM_REDIRECT", "RTM_MISS", "RTM_LOCK", "RTM_OLDADD", "RTM_OLDDEL", "RTM_RESOLVE",
113647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					"RTM_NEWADDR", "RTM_DELADDR", "RTM_IFINFO", "RTM_NEWMADDR", "RTM_DELMADDR" };
113747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
113847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int		index = pRSMsg->ifam_type == RTM_IFINFO ? ((struct if_msghdr*) pRSMsg)->ifm_index : pRSMsg->ifam_index;
113947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
114047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	printf("ifa_msghdr len=%d, type=%s, index=%d\n", pRSMsg->ifam_msglen, kRSMsgTypes[pRSMsg->ifam_type], index);
114147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
114247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
114347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
114447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSu32		ProcessRoutingNotification(int sd)
114547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Read through the messages on sd and if any indicate that any interface records should
114647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
114747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
114847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ssize_t					readCount;
114947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char					buff[4096];
115047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct ifa_msghdr		*pRSMsg = (struct ifa_msghdr*) buff;
115147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSu32				result = 0;
115247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
115347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	readCount = read(sd, buff, sizeof buff);
115447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (readCount < (ssize_t) sizeof(struct ifa_msghdr))
115547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return mStatus_UnsupportedErr;		// cannot decipher message
115647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
115747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if MDNS_DEBUGMSGS
115847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PrintRoutingSocketMsg(pRSMsg);
115947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
116047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
116147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Process the message
116247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (pRSMsg->ifam_type == RTM_NEWADDR || pRSMsg->ifam_type == RTM_DELADDR ||
116347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		 pRSMsg->ifam_type == RTM_IFINFO)
116447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
116547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (pRSMsg->ifam_type == RTM_IFINFO)
116647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index;
116747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else
116847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result |= 1 << pRSMsg->ifam_index;
116947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
117047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
117147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return result;
117247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
117347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
117447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif // USES_NETLINK
117547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
117647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Called when data appears on interface change notification socket
117747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void InterfaceChangeCallback(int fd, short filter, void *context)
117847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
117947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	IfChangeRec		*pChgRec = (IfChangeRec*) context;
118047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	fd_set			readFDs;
118147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSu32		changedInterfaces = 0;
118247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct timeval	zeroTimeout = { 0, 0 };
118347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
118447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)fd; // Unused
118547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)filter; // Unused
118647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
118747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	FD_ZERO(&readFDs);
118847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	FD_SET(pChgRec->NotifySD, &readFDs);
1189dd52342e088715929196886494c5055f9186d5c3Robert Greenwalt
119047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	do
119147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
119247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		changedInterfaces |= ProcessRoutingNotification(pChgRec->NotifySD);
119347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
119447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout));
119547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
119647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Currently we rebuild the entire interface list whenever any interface change is
119747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// detected. If this ever proves to be a performance issue in a multi-homed
119847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// configuration, more care should be paid to changedInterfaces.
119947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (changedInterfaces)
120047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS);
120147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
120247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
120347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Register with either a Routing Socket or RtNetLink to listen for interface changes.
120447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mStatus WatchForInterfaceChange(mDNS *const m)
120547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
120647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mStatus		err;
120747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	IfChangeRec	*pChgRec;
120847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
120947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	pChgRec = (IfChangeRec*) mDNSPlatformMemAllocate(sizeof *pChgRec);
121047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (pChgRec == NULL)
121147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return mStatus_NoMemoryErr;
121247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
121347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	pChgRec->mDNS = m;
121447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	err = OpenIfNotifySocket(&pChgRec->NotifySD);
121547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == 0)
121647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		err = mDNSPosixAddFDToEventLoop(pChgRec->NotifySD, InterfaceChangeCallback, pChgRec);
121747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
121847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return err;
121947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
122047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
122147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
122247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
122347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
122447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
122547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
122647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int err;
122747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
122847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct sockaddr_in s5353;
122947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	s5353.sin_family      = AF_INET;
123047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	s5353.sin_port        = MulticastDNSPort.NotAnInteger;
123147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	s5353.sin_addr.s_addr = 0;
123247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	err = bind(s, (struct sockaddr *)&s5353, sizeof(s5353));
123347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	close(s);
123447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err) debugf("No unicast UDP responses");
123547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else     debugf("Unicast UDP responses okay");
123647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return(err == 0);
123747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
123847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
123947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine to initialise the platform-specific data.
124047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mStatus mDNSPlatformInit(mDNS *const m)
124147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
124247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int err = 0;
124347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct sockaddr sa;
124447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m != NULL);
124547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
124647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (mDNSPlatformInit_CanReceiveUnicast()) m->CanReceiveUnicastOn5353 = mDNStrue;
124747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
124847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Tell mDNS core the names of this machine.
124947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
125047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Set up the nice label
125147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	m->nicelabel.c[0] = 0;
125247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	GetUserSpecifiedFriendlyComputerName(&m->nicelabel);
125347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Computer");
125447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
125547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Set up the RFC 1034-compliant label
125647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	m->hostlabel.c[0] = 0;
125747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	GetUserSpecifiedRFC1034ComputerName(&m->hostlabel);
125847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (m->hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->hostlabel, "Computer");
125947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
126047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNS_SetFQDN(m);
126147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
126247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sa.sa_family = AF_INET;
126347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	m->p->unicastSocket4 = -1;
126447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket4);
126547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
126647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sa.sa_family = AF_INET6;
126747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	m->p->unicastSocket6 = -1;
126847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket6);
126947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
127047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
127147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Tell mDNS core about the network interfaces on this machine.
127247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == mStatus_NoError) err = SetupInterfaceList(m);
127347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
127447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Tell mDNS core about DNS Servers
127547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNS_Lock(m);
127647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == mStatus_NoError) ParseDNSServers(m, uDNS_SERVERS_FILE);
127747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNS_Unlock(m);
127847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
127947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == mStatus_NoError)
128047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
128147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		err = WatchForInterfaceChange(m);
128247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Failure to observe interface changes is non-fatal.
128347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (err != mStatus_NoError)
128447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
128547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			fprintf(stderr, "mDNS(%d) WARNING: Unable to detect interface changes (%d).\n", getpid(), err);
128647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = mStatus_NoError;
128747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
128847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
128947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
129047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// We don't do asynchronous initialization on the Posix platform, so by the time
129147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// we get here the setup will already have succeeded or failed.  If it succeeded,
129247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// we should just call mDNSCoreInitComplete() immediately.
129347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err == mStatus_NoError)
129447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		mDNSCoreInitComplete(m, mStatus_NoError);
129547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
129647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return PosixErrorToStatus(err);
129747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
129847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
129947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine to clean up the platform-specific data.
130047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// In our case all we need to do is to tear down every network interface.
130147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformClose(mDNS *const m)
130247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
130347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m != NULL);
130447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ClearInterfaceList(m);
1305f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt	if (m->p->unicastSocket4 != -1)
1306f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		{
1307f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		int ipv4_closed = close(m->p->unicastSocket4);
1308f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		assert(ipv4_closed == 0);
1309f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		}
131047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
1311f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt	if (m->p->unicastSocket6 != -1)
1312f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		{
1313f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		int ipv6_closed = close(m->p->unicastSocket6);
1314f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		assert(ipv6_closed == 0);
1315f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		}
131647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
131747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
131847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
131947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
132047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
132147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int err;
132247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ClearInterfaceList(m);
132347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	err = SetupInterfaceList(m);
132447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return PosixErrorToStatus(err);
132547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
132647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
132747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK
132847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** Locking
132947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
133047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
133147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// On the Posix platform, locking is a no-op because we only ever enter
133247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core on the main thread.
133347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
133447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine when it wants to prevent
133547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// the platform from reentering mDNS core code.
133647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void    mDNSPlatformLock   (const mDNS *const m)
133747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
133847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) m;	// Unused
133947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
134047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
134147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine when it release the lock taken by
134247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNSPlatformLock and allow the platform to reenter mDNS core code.
134347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void    mDNSPlatformUnlock (const mDNS *const m)
134447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
134547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) m;	// Unused
134647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
134747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
134847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK
134947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** Strings
135047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
135147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
135247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine to copy C strings.
135347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// On the Posix platform this maps directly to the ANSI C strcpy.
135447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void    mDNSPlatformStrCopy(void *dst, const void *src)
135547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
135647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	strcpy((char *)dst, (char *)src);
135747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
135847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
135947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine to get the length of a C string.
136047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// On the Posix platform this maps directly to the ANSI C strlen.
136147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mDNSu32  mDNSPlatformStrLen (const void *src)
136247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
136347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return strlen((char*)src);
136447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
136547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
136647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine to copy memory.
136747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// On the Posix platform this maps directly to the ANSI C memcpy.
136847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void    mDNSPlatformMemCopy(void *dst, const void *src, mDNSu32 len)
136947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
137047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	memcpy(dst, src, len);
137147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
137247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
137347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine to test whether blocks of memory are byte-for-byte
137447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// identical. On the Posix platform this is a simple wrapper around ANSI C memcmp.
137547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mDNSBool mDNSPlatformMemSame(const void *dst, const void *src, mDNSu32 len)
137647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
137747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return memcmp(dst, src, len) == 0;
137847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
137947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
138047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// mDNS core calls this routine to clear blocks of memory.
138147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// On the Posix platform this is a simple wrapper around ANSI C memset.
138247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void    mDNSPlatformMemZero(void *dst, mDNSu32 len)
138347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
138447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	memset(dst, 0, len);
138547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
138647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
138747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void *  mDNSPlatformMemAllocate(mDNSu32 len) { return(malloc(len)); }
138847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void    mDNSPlatformMemFree    (void *mem)   { free(mem); }
138947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
139047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
139147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
139247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct timeval tv;
139347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	gettimeofday(&tv, NULL);
139447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return(tv.tv_usec);
139547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
139647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
139747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mDNSs32  mDNSPlatformOneSecond = 1024;
139847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
139947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mStatus mDNSPlatformTimeInit(void)
140047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
140147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// No special setup is required on Posix -- we just use gettimeofday();
140247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// This is not really safe, because gettimeofday can go backwards if the user manually changes the date or time
140347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// We should find a better way to do this
140447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return(mStatus_NoError);
140547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
140647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
140747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mDNSs32  mDNSPlatformRawTime()
140847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
140947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct timeval tv;
141047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	gettimeofday(&tv, NULL);
141147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// tv.tv_sec is seconds since 1st January 1970 (GMT, with no adjustment for daylight savings time)
141247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// tv.tv_usec is microseconds since the start of this second (i.e. values 0 to 999999)
141347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// We use the lower 22 bits of tv.tv_sec for the top 22 bits of our result
141447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// and we multiply tv.tv_usec by 16 / 15625 to get a value in the range 0-1023 to go in the bottom 10 bits.
141547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// This gives us a proper modular (cyclic) counter that has a resolution of roughly 1ms (actually 1/1024 second)
141647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// and correctly cycles every 2^22 seconds (4194304 seconds = approx 48 days).
141747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return((tv.tv_sec << 10) | (tv.tv_usec * 16 / 15625));
141847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
141947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
142047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mDNSs32 mDNSPlatformUTC(void)
142147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
142247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return time(NULL);
142347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
142447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
142547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
142647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
142747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) m;
142847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) InterfaceID;
142947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) EthAddr;
143047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) IPAddr;
143147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) iteration;
143247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
143347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
143447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
143547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
143647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) rr;
143747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) intf;
143847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
143947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 1;
144047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
144147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
144247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void mDNSPosixAddToFDSet(int *nfds, fd_set *readfds, int s)
144347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
144447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*nfds < s + 1) *nfds = s + 1;
144547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	FD_SET(s, readfds);
144647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
144747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
144847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPosixGetFDSet(mDNS *m, int *nfds, fd_set *readfds, struct timeval *timeout)
144947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
145047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSs32 ticks;
145147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct timeval interval;
145247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
145347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// 1. Call mDNS_Execute() to let mDNSCore do what it needs to do
145447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSs32 nextevent = mDNS_Execute(m);
145547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
145647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// 2. Build our list of active file descriptors
145747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixNetworkInterface *info = (PosixNetworkInterface *)(m->HostInterfaces);
145847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (m->p->unicastSocket4 != -1) mDNSPosixAddToFDSet(nfds, readfds, m->p->unicastSocket4);
145947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
146047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (m->p->unicastSocket6 != -1) mDNSPosixAddToFDSet(nfds, readfds, m->p->unicastSocket6);
146147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
146247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (info)
146347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
146447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (info->multicastSocket4 != -1) mDNSPosixAddToFDSet(nfds, readfds, info->multicastSocket4);
146547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
146647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (info->multicastSocket6 != -1) mDNSPosixAddToFDSet(nfds, readfds, info->multicastSocket6);
146747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
146847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		info = (PosixNetworkInterface *)(info->coreIntf.next);
146947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
147047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
147147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// 3. Calculate the time remaining to the next scheduled event (in struct timeval format)
147247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ticks = nextevent - mDNS_TimeNow(m);
147347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (ticks < 1) ticks = 1;
147447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	interval.tv_sec  = ticks >> 10;						// The high 22 bits are seconds
147547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	interval.tv_usec = ((ticks & 0x3FF) * 15625) / 16;	// The low 10 bits are 1024ths
147647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
147747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// 4. If client's proposed timeout is more than what we want, then reduce it
147847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (timeout->tv_sec > interval.tv_sec ||
147947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		(timeout->tv_sec == interval.tv_sec && timeout->tv_usec > interval.tv_usec))
148047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*timeout = interval;
148147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
148247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
148347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSPosixProcessFDSet(mDNS *const m, fd_set *readfds)
148447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
148547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixNetworkInterface *info;
148647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(m       != NULL);
148747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	assert(readfds != NULL);
148847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	info = (PosixNetworkInterface *)(m->HostInterfaces);
148947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
149047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (m->p->unicastSocket4 != -1 && FD_ISSET(m->p->unicastSocket4, readfds))
149147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
149247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		FD_CLR(m->p->unicastSocket4, readfds);
149347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		SocketDataReady(m, NULL, m->p->unicastSocket4);
149447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
149547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
149647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (m->p->unicastSocket6 != -1 && FD_ISSET(m->p->unicastSocket6, readfds))
149747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
149847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		FD_CLR(m->p->unicastSocket6, readfds);
149947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		SocketDataReady(m, NULL, m->p->unicastSocket6);
150047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
150147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
150247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
150347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (info)
150447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
150547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (info->multicastSocket4 != -1 && FD_ISSET(info->multicastSocket4, readfds))
150647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
150747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			FD_CLR(info->multicastSocket4, readfds);
150847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			SocketDataReady(m, info, info->multicastSocket4);
150947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
151047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6
151147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (info->multicastSocket6 != -1 && FD_ISSET(info->multicastSocket6, readfds))
151247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
151347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			FD_CLR(info->multicastSocket6, readfds);
151447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			SocketDataReady(m, info, info->multicastSocket6);
151547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
151647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
151747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		info = (PosixNetworkInterface *)(info->coreIntf.next);
151847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
151947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
152047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
152147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// update gMaxFD
152247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void	DetermineMaxEventFD(void)
152347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
152447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixEventSource	*iSource;
152547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
152647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	gMaxFD = 0;
152747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (iSource=(PosixEventSource*)gEventSources.Head; iSource; iSource = iSource->Next)
152847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (gMaxFD < iSource->fd)
152947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			gMaxFD = iSource->fd;
153047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
153147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
153247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Add a file descriptor to the set that mDNSPosixRunEventLoopOnce() listens to.
153347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNSPosixAddFDToEventLoop(int fd, mDNSPosixEventCallback callback, void *context)
153447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
153547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixEventSource	*newSource;
153647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
153747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (gEventSources.LinkOffset == 0)
153847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		InitLinkedList(&gEventSources, offsetof(PosixEventSource, Next));
153947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
154047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (fd >= (int) FD_SETSIZE || fd < 0)
154147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return mStatus_UnsupportedErr;
154247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (callback == NULL)
154347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return mStatus_BadParamErr;
154447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
154547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	newSource = (PosixEventSource*) malloc(sizeof *newSource);
154647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (NULL == newSource)
154747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return mStatus_NoMemoryErr;
154847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
154947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	newSource->Callback = callback;
155047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	newSource->Context = context;
155147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	newSource->fd = fd;
155247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
155347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	AddToTail(&gEventSources, newSource);
155447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	FD_SET(fd, &gEventFDs);
155547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
155647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DetermineMaxEventFD();
155747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
155847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return mStatus_NoError;
155947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
156047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
156147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Remove a file descriptor from the set that mDNSPosixRunEventLoopOnce() listens to.
156247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNSPosixRemoveFDFromEventLoop(int fd)
156347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
156447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PosixEventSource	*iSource;
156547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
156647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (iSource=(PosixEventSource*)gEventSources.Head; iSource; iSource = iSource->Next)
156747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
156847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (fd == iSource->fd)
156947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
157047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			FD_CLR(fd, &gEventFDs);
157147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			RemoveFromList(&gEventSources, iSource);
157247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			free(iSource);
157347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			DetermineMaxEventFD();
157447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return mStatus_NoError;
157547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
157647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
157747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return mStatus_NoSuchNameErr;
157847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
157947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
158047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Simply note the received signal in gEventSignals.
158147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void	NoteSignal(int signum)
158247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
158347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sigaddset(&gEventSignals, signum);
158447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
158547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
158647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Tell the event package to listen for signal and report it in mDNSPosixRunEventLoopOnce().
158747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNSPosixListenForSignalInEventLoop(int signum)
158847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
158947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct sigaction	action;
159047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mStatus				err;
159147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
159247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSPlatformMemZero(&action, sizeof action);		// more portable than member-wise assignment
159347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	action.sa_handler = NoteSignal;
159447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	err = sigaction(signum, &action, (struct sigaction*) NULL);
159547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
159647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sigaddset(&gEventSignalSet, signum);
159747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
159847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return err;
159947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
160047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
160147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Tell the event package to stop listening for signal in mDNSPosixRunEventLoopOnce().
160247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNSPosixIgnoreSignalInEventLoop(int signum)
160347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
160447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct sigaction	action;
160547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mStatus				err;
160647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
160747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSPlatformMemZero(&action, sizeof action);		// more portable than member-wise assignment
160847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	action.sa_handler = SIG_DFL;
160947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	err = sigaction(signum, &action, (struct sigaction*) NULL);
161047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
161147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sigdelset(&gEventSignalSet, signum);
161247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
161347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return err;
161447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
161547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
161647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Do a single pass through the attendent event sources and dispatch any found to their callbacks.
161747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Return as soon as internal timeout expires, or a signal we're listening for is received.
161847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNSPosixRunEventLoopOnce(mDNS *m, const struct timeval *pTimeout,
161947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt									sigset_t *pSignalsReceived, mDNSBool *pDataDispatched)
162047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
162147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	fd_set			listenFDs = gEventFDs;
162247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int				fdMax = 0, numReady;
162347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct timeval	timeout = *pTimeout;
162447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
162547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Include the sockets that are listening to the wire in our select() set
162647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	mDNSPosixGetFDSet(m, &fdMax, &listenFDs, &timeout);	// timeout may get modified
162747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (fdMax < gMaxFD)
162847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		fdMax = gMaxFD;
162947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
163047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	numReady = select(fdMax + 1, &listenFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout);
163147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
163247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// If any data appeared, invoke its callback
163347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (numReady > 0)
163447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
163547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		PosixEventSource	*iSource;
163647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
163747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		(void) mDNSPosixProcessFDSet(m, &listenFDs);	// call this first to process wire data for clients
163847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
163947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		for (iSource=(PosixEventSource*)gEventSources.Head; iSource; iSource = iSource->Next)
164047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
164147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (FD_ISSET(iSource->fd, &listenFDs))
164247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				{
164347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				iSource->Callback(iSource->fd, 0, iSource->Context);
164447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				break;	// in case callback removed elements from gEventSources
164547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
164647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
164747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*pDataDispatched = mDNStrue;
164847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
164947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
165047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*pDataDispatched = mDNSfalse;
165147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
165247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) sigprocmask(SIG_BLOCK, &gEventSignalSet, (sigset_t*) NULL);
165347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	*pSignalsReceived = gEventSignals;
165447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sigemptyset(&gEventSignals);
165547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void) sigprocmask(SIG_UNBLOCK, &gEventSignalSet, (sigset_t*) NULL);
165647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
165747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return mStatus_NoError;
165847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
1659