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