15ffb0c9bSToomas Soome /* -*- Mode: C; tab-width: 4 -*-
25ffb0c9bSToomas Soome *
3*472cd20dSToomas Soome * Copyright (c) 2002-2020 Apple Inc. All rights reserved.
45ffb0c9bSToomas Soome *
5cda73f64SToomas Soome * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
65ffb0c9bSToomas Soome * ("Apple") in consideration of your agreement to the following terms, and your
75ffb0c9bSToomas Soome * use, installation, modification or redistribution of this Apple software
85ffb0c9bSToomas Soome * constitutes acceptance of these terms. If you do not agree with these terms,
95ffb0c9bSToomas Soome * please do not use, install, modify or redistribute this Apple software.
105ffb0c9bSToomas Soome *
115ffb0c9bSToomas Soome * In consideration of your agreement to abide by the following terms, and subject
125ffb0c9bSToomas Soome * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
135ffb0c9bSToomas Soome * copyrights in this original Apple software (the "Apple Software"), to use,
145ffb0c9bSToomas Soome * reproduce, modify and redistribute the Apple Software, with or without
155ffb0c9bSToomas Soome * modifications, in source and/or binary forms; provided that if you redistribute
165ffb0c9bSToomas Soome * the Apple Software in its entirety and without modifications, you must retain
175ffb0c9bSToomas Soome * this notice and the following text and disclaimers in all such redistributions of
185ffb0c9bSToomas Soome * the Apple Software. Neither the name, trademarks, service marks or logos of
19cda73f64SToomas Soome * Apple Inc. may be used to endorse or promote products derived from the
205ffb0c9bSToomas Soome * Apple Software without specific prior written permission from Apple. Except as
215ffb0c9bSToomas Soome * expressly stated in this notice, no other rights or licenses, express or implied,
225ffb0c9bSToomas Soome * are granted by Apple herein, including but not limited to any patent rights that
235ffb0c9bSToomas Soome * may be infringed by your derivative works or by other works in which the Apple
245ffb0c9bSToomas Soome * Software may be incorporated.
255ffb0c9bSToomas Soome *
265ffb0c9bSToomas Soome * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
275ffb0c9bSToomas Soome * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
285ffb0c9bSToomas Soome * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
295ffb0c9bSToomas Soome * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
305ffb0c9bSToomas Soome * COMBINATION WITH YOUR PRODUCTS.
315ffb0c9bSToomas Soome *
325ffb0c9bSToomas Soome * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
335ffb0c9bSToomas Soome * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
345ffb0c9bSToomas Soome * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
355ffb0c9bSToomas Soome * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
365ffb0c9bSToomas Soome * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
375ffb0c9bSToomas Soome * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
385ffb0c9bSToomas Soome * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
395ffb0c9bSToomas Soome *
405ffb0c9bSToomas Soome To build this tool, copy and paste the following into a command line:
415ffb0c9bSToomas Soome
425ffb0c9bSToomas Soome OS X:
435ffb0c9bSToomas Soome gcc dns-sd.c -o dns-sd
445ffb0c9bSToomas Soome
455ffb0c9bSToomas Soome POSIX systems:
465ffb0c9bSToomas Soome gcc dns-sd.c -o dns-sd -I../mDNSShared -ldns_sd
475ffb0c9bSToomas Soome
485ffb0c9bSToomas Soome Windows:
495ffb0c9bSToomas Soome cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT ws2_32.lib ..\mDNSWindows\DLL\Release\dnssd.lib
505ffb0c9bSToomas Soome (may require that you run a Visual Studio script such as vsvars32.bat first)
515ffb0c9bSToomas Soome */
525ffb0c9bSToomas Soome
535ffb0c9bSToomas Soome // For testing changes to dnssd_clientstub.c, uncomment this line and the code will be compiled
545ffb0c9bSToomas Soome // with an embedded copy of the client stub instead of linking the system library version at runtime.
555ffb0c9bSToomas Soome // This also useful to work around link errors when you're working on an older version of Mac OS X,
565ffb0c9bSToomas Soome // and trying to build a newer version of the "dns-sd" command which uses new API entry points that
575ffb0c9bSToomas Soome // aren't in the system's /usr/lib/libSystem.dylib.
585ffb0c9bSToomas Soome //#define TEST_NEW_CLIENTSTUB 1
595ffb0c9bSToomas Soome
605ffb0c9bSToomas Soome #include <ctype.h>
615ffb0c9bSToomas Soome #include <stdio.h> // For stdout, stderr
625ffb0c9bSToomas Soome #include <stdlib.h> // For exit()
635ffb0c9bSToomas Soome #include <string.h> // For strlen(), strcpy()
645ffb0c9bSToomas Soome #include <errno.h> // For errno, EINTR
655ffb0c9bSToomas Soome #include <time.h>
665ffb0c9bSToomas Soome #include <sys/types.h> // For u_char
67*472cd20dSToomas Soome #ifdef APPLE_OSX_mDNSResponder
68*472cd20dSToomas Soome #include <inttypes.h> // For PRId64
69*472cd20dSToomas Soome #endif // APPLE_OSX_mDNSResponder
70*472cd20dSToomas Soome
71*472cd20dSToomas Soome #if APPLE_OSX_mDNSResponder
72*472cd20dSToomas Soome #include <xpc/xpc.h>
73*472cd20dSToomas Soome #include "xpc_clients.h"
74*472cd20dSToomas Soome #endif
755ffb0c9bSToomas Soome
765ffb0c9bSToomas Soome #ifdef _WIN32
775ffb0c9bSToomas Soome #include <winsock2.h>
785ffb0c9bSToomas Soome #include <ws2tcpip.h>
795ffb0c9bSToomas Soome #include <Iphlpapi.h>
805ffb0c9bSToomas Soome #include <process.h>
815ffb0c9bSToomas Soome typedef int pid_t;
825ffb0c9bSToomas Soome #define getpid _getpid
835ffb0c9bSToomas Soome #define strcasecmp _stricmp
845ffb0c9bSToomas Soome #define snprintf _snprintf
855ffb0c9bSToomas Soome static const char kFilePathSep = '\\';
865ffb0c9bSToomas Soome #ifndef HeapEnableTerminationOnCorruption
875ffb0c9bSToomas Soome # define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS)1
885ffb0c9bSToomas Soome #endif
895ffb0c9bSToomas Soome #if !defined(IFNAMSIZ)
905ffb0c9bSToomas Soome #define IFNAMSIZ 16
915ffb0c9bSToomas Soome #endif
925ffb0c9bSToomas Soome #define if_nametoindex if_nametoindex_win
935ffb0c9bSToomas Soome #define if_indextoname if_indextoname_win
945ffb0c9bSToomas Soome
955ffb0c9bSToomas Soome typedef PCHAR (WINAPI * if_indextoname_funcptr_t)(ULONG index, PCHAR name);
965ffb0c9bSToomas Soome typedef ULONG (WINAPI * if_nametoindex_funcptr_t)(PCSTR name);
975ffb0c9bSToomas Soome
if_nametoindex_win(const char * ifname)985ffb0c9bSToomas Soome unsigned if_nametoindex_win(const char *ifname)
995ffb0c9bSToomas Soome {
1005ffb0c9bSToomas Soome HMODULE library;
1015ffb0c9bSToomas Soome unsigned index = 0;
1025ffb0c9bSToomas Soome
1035ffb0c9bSToomas Soome // Try and load the IP helper library dll
1045ffb0c9bSToomas Soome if ((library = LoadLibrary(TEXT("Iphlpapi")) ) != NULL )
1055ffb0c9bSToomas Soome {
1065ffb0c9bSToomas Soome if_nametoindex_funcptr_t if_nametoindex_funcptr;
1075ffb0c9bSToomas Soome
1085ffb0c9bSToomas Soome // On Vista and above there is a Posix like implementation of if_nametoindex
1095ffb0c9bSToomas Soome if ((if_nametoindex_funcptr = (if_nametoindex_funcptr_t) GetProcAddress(library, "if_nametoindex")) != NULL )
1105ffb0c9bSToomas Soome {
1115ffb0c9bSToomas Soome index = if_nametoindex_funcptr(ifname);
1125ffb0c9bSToomas Soome }
1135ffb0c9bSToomas Soome
1145ffb0c9bSToomas Soome FreeLibrary(library);
1155ffb0c9bSToomas Soome }
1165ffb0c9bSToomas Soome
1175ffb0c9bSToomas Soome return index;
1185ffb0c9bSToomas Soome }
1195ffb0c9bSToomas Soome
if_indextoname_win(unsigned ifindex,char * ifname)1205ffb0c9bSToomas Soome char * if_indextoname_win( unsigned ifindex, char *ifname)
1215ffb0c9bSToomas Soome {
1225ffb0c9bSToomas Soome HMODULE library;
1235ffb0c9bSToomas Soome char * name = NULL;
1245ffb0c9bSToomas Soome
1255ffb0c9bSToomas Soome // Try and load the IP helper library dll
1265ffb0c9bSToomas Soome if ((library = LoadLibrary(TEXT("Iphlpapi")) ) != NULL )
1275ffb0c9bSToomas Soome {
1285ffb0c9bSToomas Soome if_indextoname_funcptr_t if_indextoname_funcptr;
1295ffb0c9bSToomas Soome
1305ffb0c9bSToomas Soome // On Vista and above there is a Posix like implementation of if_indextoname
1315ffb0c9bSToomas Soome if ((if_indextoname_funcptr = (if_indextoname_funcptr_t) GetProcAddress(library, "if_indextoname")) != NULL )
1325ffb0c9bSToomas Soome {
1335ffb0c9bSToomas Soome name = if_indextoname_funcptr(ifindex, ifname);
1345ffb0c9bSToomas Soome }
1355ffb0c9bSToomas Soome
1365ffb0c9bSToomas Soome FreeLibrary(library);
1375ffb0c9bSToomas Soome }
1385ffb0c9bSToomas Soome
1395ffb0c9bSToomas Soome return name;
1405ffb0c9bSToomas Soome }
1415ffb0c9bSToomas Soome
_sa_len(const struct sockaddr * addr)1425ffb0c9bSToomas Soome static size_t _sa_len(const struct sockaddr *addr)
1435ffb0c9bSToomas Soome {
1445ffb0c9bSToomas Soome if (addr->sa_family == AF_INET) return (sizeof(struct sockaddr_in));
1455ffb0c9bSToomas Soome else if (addr->sa_family == AF_INET6) return (sizeof(struct sockaddr_in6));
1465ffb0c9bSToomas Soome else return (sizeof(struct sockaddr));
1475ffb0c9bSToomas Soome }
1485ffb0c9bSToomas Soome
1495ffb0c9bSToomas Soome # define SA_LEN(addr) (_sa_len(addr))
1505ffb0c9bSToomas Soome
1515ffb0c9bSToomas Soome #else
1525ffb0c9bSToomas Soome #include <unistd.h> // For getopt() and optind
1535ffb0c9bSToomas Soome #include <netdb.h> // For getaddrinfo()
1545ffb0c9bSToomas Soome #include <sys/time.h> // For struct timeval
1555ffb0c9bSToomas Soome #include <sys/socket.h> // For AF_INET
1565ffb0c9bSToomas Soome #include <netinet/in.h> // For struct sockaddr_in()
1575ffb0c9bSToomas Soome #include <arpa/inet.h> // For inet_addr()
1585ffb0c9bSToomas Soome #include <net/if.h> // For if_nametoindex()
1595ffb0c9bSToomas Soome static const char kFilePathSep = '/';
1605ffb0c9bSToomas Soome // #ifndef NOT_HAVE_SA_LEN
1615ffb0c9bSToomas Soome // #define SA_LEN(addr) ((addr)->sa_len)
1625ffb0c9bSToomas Soome // #else
1635ffb0c9bSToomas Soome #define SA_LEN(addr) (((addr)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
1645ffb0c9bSToomas Soome // #endif
1655ffb0c9bSToomas Soome #endif
1665ffb0c9bSToomas Soome
1675ffb0c9bSToomas Soome #if (TEST_NEW_CLIENTSTUB && !defined(__APPLE_API_PRIVATE))
1685ffb0c9bSToomas Soome #define __APPLE_API_PRIVATE 1
1695ffb0c9bSToomas Soome #endif
1705ffb0c9bSToomas Soome
1715ffb0c9bSToomas Soome // DNSServiceSetDispatchQueue is not supported on 10.6 & prior
1725ffb0c9bSToomas Soome #if !TEST_NEW_CLIENTSTUB && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ % 10) <= 1060)
1735ffb0c9bSToomas Soome #undef _DNS_SD_LIBDISPATCH
1745ffb0c9bSToomas Soome #endif
1755ffb0c9bSToomas Soome #include "dns_sd.h"
176*472cd20dSToomas Soome #include "dns_sd_private.h"
1775ffb0c9bSToomas Soome #include "ClientCommon.h"
178*472cd20dSToomas Soome #include <stdarg.h>
179*472cd20dSToomas Soome
1805ffb0c9bSToomas Soome
1815ffb0c9bSToomas Soome #if TEST_NEW_CLIENTSTUB
1825ffb0c9bSToomas Soome #include "../mDNSShared/dnssd_ipc.c"
1835ffb0c9bSToomas Soome #include "../mDNSShared/dnssd_clientlib.c"
1845ffb0c9bSToomas Soome #include "../mDNSShared/dnssd_clientstub.c"
1855ffb0c9bSToomas Soome #endif
1865ffb0c9bSToomas Soome
187*472cd20dSToomas Soome #ifndef MIN
188*472cd20dSToomas Soome #define MIN(x, y) ((x) < (y) ? (x) : (y))
189*472cd20dSToomas Soome #endif
1905ffb0c9bSToomas Soome //*************************************************************************************************************
1915ffb0c9bSToomas Soome // Globals
1925ffb0c9bSToomas Soome
1935ffb0c9bSToomas Soome #define DS_FIXED_SIZE 4
1945ffb0c9bSToomas Soome typedef struct
1955ffb0c9bSToomas Soome {
1965ffb0c9bSToomas Soome unsigned short keyTag;
197c1de7575SRichard Lowe unsigned char alg;
1985ffb0c9bSToomas Soome unsigned char digestType;
1995ffb0c9bSToomas Soome unsigned char *digest;
2005ffb0c9bSToomas Soome } rdataDS;
2015ffb0c9bSToomas Soome
2025ffb0c9bSToomas Soome #define DNSKEY_FIXED_SIZE 4
2035ffb0c9bSToomas Soome typedef struct
2045ffb0c9bSToomas Soome {
2055ffb0c9bSToomas Soome unsigned short flags;
2065ffb0c9bSToomas Soome unsigned char proto;
2075ffb0c9bSToomas Soome unsigned char alg;
2085ffb0c9bSToomas Soome unsigned char *data;
2095ffb0c9bSToomas Soome } rdataDNSKey;
2105ffb0c9bSToomas Soome
211c1de7575SRichard Lowe //size of rdataRRSIG excluding signerName and signature (which are variable fields)
2125ffb0c9bSToomas Soome #define RRSIG_FIXED_SIZE 18
2135ffb0c9bSToomas Soome typedef struct
2145ffb0c9bSToomas Soome {
2155ffb0c9bSToomas Soome unsigned short typeCovered;
216c1de7575SRichard Lowe unsigned char alg;
2175ffb0c9bSToomas Soome unsigned char labels;
2185ffb0c9bSToomas Soome unsigned int origTTL;
2195ffb0c9bSToomas Soome unsigned int sigExpireTime;
2205ffb0c9bSToomas Soome unsigned int sigInceptTime;
2215ffb0c9bSToomas Soome unsigned short keyTag;
2225ffb0c9bSToomas Soome char signerName[256];
2235ffb0c9bSToomas Soome //unsigned char *signature
2245ffb0c9bSToomas Soome } rdataRRSig;
2255ffb0c9bSToomas Soome
2265ffb0c9bSToomas Soome #define RR_TYPE_SIZE 16
2275ffb0c9bSToomas Soome
2285ffb0c9bSToomas Soome typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
2295ffb0c9bSToomas Soome
2305ffb0c9bSToomas Soome static int operation;
2315ffb0c9bSToomas Soome static uint32_t opinterface = kDNSServiceInterfaceIndexAny;
2325ffb0c9bSToomas Soome static DNSServiceRef client = NULL;
2335ffb0c9bSToomas Soome static DNSServiceRef client_pa = NULL; // DNSServiceRef for RegisterProxyAddressRecord
2345ffb0c9bSToomas Soome static DNSServiceRef sc1, sc2, sc3; // DNSServiceRefs for kDNSServiceFlagsShareConnection testing
2355ffb0c9bSToomas Soome
2365ffb0c9bSToomas Soome static int num_printed;
2375ffb0c9bSToomas Soome static char addtest = 0;
2385ffb0c9bSToomas Soome static DNSRecordRef record = NULL;
2395ffb0c9bSToomas Soome static char myhinfoW[14] = "\002PC\012Windows XP";
2405ffb0c9bSToomas Soome static char myhinfoX[ 9] = "\003Mac\004OS X";
2415ffb0c9bSToomas Soome static char updatetest[3] = "\002AA";
2425ffb0c9bSToomas Soome static char bigNULL[8192]; // 8K is maximum rdata we support
2435ffb0c9bSToomas Soome
2445ffb0c9bSToomas Soome #if _DNS_SD_LIBDISPATCH
2455ffb0c9bSToomas Soome dispatch_queue_t main_queue;
2465ffb0c9bSToomas Soome dispatch_source_t timer_source;
2475ffb0c9bSToomas Soome #endif
2485ffb0c9bSToomas Soome
2495ffb0c9bSToomas Soome // Note: the select() implementation on Windows (Winsock2) fails with any timeout much larger than this
2505ffb0c9bSToomas Soome #define LONG_TIME 100000000
2515ffb0c9bSToomas Soome
2525ffb0c9bSToomas Soome static volatile int stopNow = 0;
2535ffb0c9bSToomas Soome static volatile int timeOut = LONG_TIME;
2545ffb0c9bSToomas Soome
2555ffb0c9bSToomas Soome #if _DNS_SD_LIBDISPATCH
2565ffb0c9bSToomas Soome #define EXIT_IF_LIBDISPATCH_FATAL_ERROR(E) \
2575ffb0c9bSToomas Soome if (main_queue && (E) == kDNSServiceErr_ServiceNotRunning) { fprintf(stderr, "Error code %d\n", (E)); exit(0); }
2585ffb0c9bSToomas Soome #else
2595ffb0c9bSToomas Soome #define EXIT_IF_LIBDISPATCH_FATAL_ERROR(E)
2605ffb0c9bSToomas Soome #endif
2615ffb0c9bSToomas Soome
2625ffb0c9bSToomas Soome //*************************************************************************************************************
2635ffb0c9bSToomas Soome // Supporting Utility Functions
GetRRClass(const char * s)264c1de7575SRichard Lowe static uint16_t GetRRClass(const char *s)
2655ffb0c9bSToomas Soome {
266c1de7575SRichard Lowe if (!strcasecmp(s, "IN"))
2675ffb0c9bSToomas Soome return kDNSServiceClass_IN;
2685ffb0c9bSToomas Soome else
2695ffb0c9bSToomas Soome return(atoi(s));
270c1de7575SRichard Lowe }
2715ffb0c9bSToomas Soome
GetRRType(const char * s)2725ffb0c9bSToomas Soome static uint16_t GetRRType(const char *s)
2735ffb0c9bSToomas Soome {
2745ffb0c9bSToomas Soome if (!strcasecmp(s, "A" )) return(kDNSServiceType_A);
2755ffb0c9bSToomas Soome else if (!strcasecmp(s, "NS" )) return(kDNSServiceType_NS);
2765ffb0c9bSToomas Soome else if (!strcasecmp(s, "MD" )) return(kDNSServiceType_MD);
2775ffb0c9bSToomas Soome else if (!strcasecmp(s, "MF" )) return(kDNSServiceType_MF);
2785ffb0c9bSToomas Soome else if (!strcasecmp(s, "CNAME" )) return(kDNSServiceType_CNAME);
2795ffb0c9bSToomas Soome else if (!strcasecmp(s, "SOA" )) return(kDNSServiceType_SOA);
2805ffb0c9bSToomas Soome else if (!strcasecmp(s, "MB" )) return(kDNSServiceType_MB);
2815ffb0c9bSToomas Soome else if (!strcasecmp(s, "MG" )) return(kDNSServiceType_MG);
2825ffb0c9bSToomas Soome else if (!strcasecmp(s, "MR" )) return(kDNSServiceType_MR);
2835ffb0c9bSToomas Soome else if (!strcasecmp(s, "NULL" )) return(kDNSServiceType_NULL);
2845ffb0c9bSToomas Soome else if (!strcasecmp(s, "WKS" )) return(kDNSServiceType_WKS);
2855ffb0c9bSToomas Soome else if (!strcasecmp(s, "PTR" )) return(kDNSServiceType_PTR);
2865ffb0c9bSToomas Soome else if (!strcasecmp(s, "HINFO" )) return(kDNSServiceType_HINFO);
2875ffb0c9bSToomas Soome else if (!strcasecmp(s, "MINFO" )) return(kDNSServiceType_MINFO);
2885ffb0c9bSToomas Soome else if (!strcasecmp(s, "MX" )) return(kDNSServiceType_MX);
2895ffb0c9bSToomas Soome else if (!strcasecmp(s, "TXT" )) return(kDNSServiceType_TXT);
2905ffb0c9bSToomas Soome else if (!strcasecmp(s, "RP" )) return(kDNSServiceType_RP);
2915ffb0c9bSToomas Soome else if (!strcasecmp(s, "AFSDB" )) return(kDNSServiceType_AFSDB);
2925ffb0c9bSToomas Soome else if (!strcasecmp(s, "X25" )) return(kDNSServiceType_X25);
2935ffb0c9bSToomas Soome else if (!strcasecmp(s, "ISDN" )) return(kDNSServiceType_ISDN);
2945ffb0c9bSToomas Soome else if (!strcasecmp(s, "RT" )) return(kDNSServiceType_RT);
2955ffb0c9bSToomas Soome else if (!strcasecmp(s, "NSAP" )) return(kDNSServiceType_NSAP);
2965ffb0c9bSToomas Soome else if (!strcasecmp(s, "NSAP_PTR")) return(kDNSServiceType_NSAP_PTR);
2975ffb0c9bSToomas Soome else if (!strcasecmp(s, "SIG" )) return(kDNSServiceType_SIG);
2985ffb0c9bSToomas Soome else if (!strcasecmp(s, "KEY" )) return(kDNSServiceType_KEY);
2995ffb0c9bSToomas Soome else if (!strcasecmp(s, "PX" )) return(kDNSServiceType_PX);
3005ffb0c9bSToomas Soome else if (!strcasecmp(s, "GPOS" )) return(kDNSServiceType_GPOS);
3015ffb0c9bSToomas Soome else if (!strcasecmp(s, "AAAA" )) return(kDNSServiceType_AAAA);
3025ffb0c9bSToomas Soome else if (!strcasecmp(s, "LOC" )) return(kDNSServiceType_LOC);
3035ffb0c9bSToomas Soome else if (!strcasecmp(s, "NXT" )) return(kDNSServiceType_NXT);
3045ffb0c9bSToomas Soome else if (!strcasecmp(s, "EID" )) return(kDNSServiceType_EID);
3055ffb0c9bSToomas Soome else if (!strcasecmp(s, "NIMLOC" )) return(kDNSServiceType_NIMLOC);
3065ffb0c9bSToomas Soome else if (!strcasecmp(s, "SRV" )) return(kDNSServiceType_SRV);
3075ffb0c9bSToomas Soome else if (!strcasecmp(s, "ATMA" )) return(kDNSServiceType_ATMA);
3085ffb0c9bSToomas Soome else if (!strcasecmp(s, "NAPTR" )) return(kDNSServiceType_NAPTR);
3095ffb0c9bSToomas Soome else if (!strcasecmp(s, "KX" )) return(kDNSServiceType_KX);
3105ffb0c9bSToomas Soome else if (!strcasecmp(s, "CERT" )) return(kDNSServiceType_CERT);
3115ffb0c9bSToomas Soome else if (!strcasecmp(s, "A6" )) return(kDNSServiceType_A6);
3125ffb0c9bSToomas Soome else if (!strcasecmp(s, "DNAME" )) return(kDNSServiceType_DNAME);
3135ffb0c9bSToomas Soome else if (!strcasecmp(s, "SINK" )) return(kDNSServiceType_SINK);
3145ffb0c9bSToomas Soome else if (!strcasecmp(s, "OPT" )) return(kDNSServiceType_OPT);
3155ffb0c9bSToomas Soome else if (!strcasecmp(s, "TKEY" )) return(kDNSServiceType_TKEY);
3165ffb0c9bSToomas Soome else if (!strcasecmp(s, "TSIG" )) return(kDNSServiceType_TSIG);
3175ffb0c9bSToomas Soome else if (!strcasecmp(s, "IXFR" )) return(kDNSServiceType_IXFR);
3185ffb0c9bSToomas Soome else if (!strcasecmp(s, "AXFR" )) return(kDNSServiceType_AXFR);
3195ffb0c9bSToomas Soome else if (!strcasecmp(s, "MAILB" )) return(kDNSServiceType_MAILB);
3205ffb0c9bSToomas Soome else if (!strcasecmp(s, "MAILA" )) return(kDNSServiceType_MAILA);
3215ffb0c9bSToomas Soome else if (!strcasecmp(s, "dnskey" )) return(kDNSServiceType_DNSKEY);
3225ffb0c9bSToomas Soome else if (!strcasecmp(s, "ds" )) return(kDNSServiceType_DS);
3235ffb0c9bSToomas Soome else if (!strcasecmp(s, "rrsig" )) return(kDNSServiceType_RRSIG);
3245ffb0c9bSToomas Soome else if (!strcasecmp(s, "nsec" )) return(kDNSServiceType_NSEC);
325*472cd20dSToomas Soome else if (!strcasecmp(s, "SVCB" )) return(kDNSServiceType_SVCB);
326*472cd20dSToomas Soome else if (!strcasecmp(s, "HTTPS" )) return(kDNSServiceType_HTTPS);
3275ffb0c9bSToomas Soome else if (!strcasecmp(s, "ANY" )) return(kDNSServiceType_ANY);
3285ffb0c9bSToomas Soome else return(atoi(s));
3295ffb0c9bSToomas Soome }
3305ffb0c9bSToomas Soome
DNSTypeName(unsigned short rr_type)3315ffb0c9bSToomas Soome static char *DNSTypeName(unsigned short rr_type)
3325ffb0c9bSToomas Soome {
3335ffb0c9bSToomas Soome switch (rr_type)
3345ffb0c9bSToomas Soome {
335c65ebfc7SToomas Soome case kDNSServiceType_A: return("Addr");
336c65ebfc7SToomas Soome case kDNSServiceType_NS: return("NS");
337c65ebfc7SToomas Soome case kDNSServiceType_MD: return("MD");
338c65ebfc7SToomas Soome case kDNSServiceType_MF: return("MF");
339c65ebfc7SToomas Soome case kDNSServiceType_CNAME: return("CNAME");
340c65ebfc7SToomas Soome case kDNSServiceType_SOA: return("SOA");
341c65ebfc7SToomas Soome case kDNSServiceType_MB: return("MB");
342c65ebfc7SToomas Soome case kDNSServiceType_MG: return("MG");
343c65ebfc7SToomas Soome case kDNSServiceType_MR: return("MR");
344c65ebfc7SToomas Soome case kDNSServiceType_NULL: return("NULL");
345c65ebfc7SToomas Soome case kDNSServiceType_WKS: return("WKS");
346c65ebfc7SToomas Soome case kDNSServiceType_PTR: return("PTR");
347c65ebfc7SToomas Soome case kDNSServiceType_HINFO: return("HINFO");
348c65ebfc7SToomas Soome case kDNSServiceType_MINFO: return("MINFO");
349c65ebfc7SToomas Soome case kDNSServiceType_MX: return("MX");
350c65ebfc7SToomas Soome case kDNSServiceType_TXT: return("TXT");
351c65ebfc7SToomas Soome case kDNSServiceType_RP: return("RP");
352c65ebfc7SToomas Soome case kDNSServiceType_AFSDB: return("AFSDB");
353c65ebfc7SToomas Soome case kDNSServiceType_X25: return("X25");
354c65ebfc7SToomas Soome case kDNSServiceType_ISDN: return("ISDN");
355c65ebfc7SToomas Soome case kDNSServiceType_RT: return("RT");
356c65ebfc7SToomas Soome case kDNSServiceType_NSAP: return("NSAP");
357c65ebfc7SToomas Soome case kDNSServiceType_NSAP_PTR: return("NSAP_PTR");
358c65ebfc7SToomas Soome case kDNSServiceType_SIG: return("SIG");
359c65ebfc7SToomas Soome case kDNSServiceType_KEY: return("KEY");
360c65ebfc7SToomas Soome case kDNSServiceType_PX: return("PX");
361c65ebfc7SToomas Soome case kDNSServiceType_GPOS: return("GPOS");
362c65ebfc7SToomas Soome case kDNSServiceType_AAAA: return("AAAA");
363c65ebfc7SToomas Soome case kDNSServiceType_LOC: return("LOC");
364c65ebfc7SToomas Soome case kDNSServiceType_NXT: return("NXT");
365c65ebfc7SToomas Soome case kDNSServiceType_EID: return("EID");
366c65ebfc7SToomas Soome case kDNSServiceType_NIMLOC: return("NIMLOC");
367c65ebfc7SToomas Soome case kDNSServiceType_SRV: return("SRV");
368c65ebfc7SToomas Soome case kDNSServiceType_ATMA: return("ATMA");
369c65ebfc7SToomas Soome case kDNSServiceType_NAPTR: return("NAPTR");
370c65ebfc7SToomas Soome case kDNSServiceType_KX: return("KX");
371c65ebfc7SToomas Soome case kDNSServiceType_CERT: return("CERT");
372c65ebfc7SToomas Soome case kDNSServiceType_A6: return("A6");
373c65ebfc7SToomas Soome case kDNSServiceType_DNAME: return("DNAME");
374c65ebfc7SToomas Soome case kDNSServiceType_SINK: return("SINK");
375c65ebfc7SToomas Soome case kDNSServiceType_OPT: return("OPT");
376c65ebfc7SToomas Soome case kDNSServiceType_APL: return("APL");
377c65ebfc7SToomas Soome case kDNSServiceType_DS: return("DS");
378c65ebfc7SToomas Soome case kDNSServiceType_SSHFP: return("SSHFP");
379c65ebfc7SToomas Soome case kDNSServiceType_IPSECKEY: return("IPSECKEY");
380c65ebfc7SToomas Soome case kDNSServiceType_RRSIG: return("RRSIG");
381c65ebfc7SToomas Soome case kDNSServiceType_NSEC: return("NSEC");
382c65ebfc7SToomas Soome case kDNSServiceType_DNSKEY: return("DNSKEY");
383c65ebfc7SToomas Soome case kDNSServiceType_DHCID: return("DHCID");
384c65ebfc7SToomas Soome case kDNSServiceType_NSEC3: return("NSEC3");
385c65ebfc7SToomas Soome case kDNSServiceType_NSEC3PARAM: return("NSEC3PARAM");
386c65ebfc7SToomas Soome case kDNSServiceType_HIP: return("HIP");
387c65ebfc7SToomas Soome case kDNSServiceType_SPF: return("SPF");
388c65ebfc7SToomas Soome case kDNSServiceType_UINFO: return("UINFO");
389c65ebfc7SToomas Soome case kDNSServiceType_UID: return("UID");
390c65ebfc7SToomas Soome case kDNSServiceType_GID: return("GID");
391c65ebfc7SToomas Soome case kDNSServiceType_UNSPEC: return("UNSPEC");
392c65ebfc7SToomas Soome case kDNSServiceType_TKEY: return("TKEY");
393c65ebfc7SToomas Soome case kDNSServiceType_TSIG: return("TSIG");
394c65ebfc7SToomas Soome case kDNSServiceType_IXFR: return("IXFR");
395c65ebfc7SToomas Soome case kDNSServiceType_AXFR: return("AXFR");
396c65ebfc7SToomas Soome case kDNSServiceType_MAILB: return("MAILB");
397c65ebfc7SToomas Soome case kDNSServiceType_MAILA: return("MAILA");
398*472cd20dSToomas Soome case kDNSServiceType_SVCB: return("SVCB");
399*472cd20dSToomas Soome case kDNSServiceType_HTTPS: return("HTTPS");
400c65ebfc7SToomas Soome case kDNSServiceType_ANY: return("ANY");
401c1de7575SRichard Lowe default:
4025ffb0c9bSToomas Soome {
4035ffb0c9bSToomas Soome static char buffer[RR_TYPE_SIZE];
4045ffb0c9bSToomas Soome snprintf(buffer, sizeof(buffer), "TYPE%d", rr_type);
4055ffb0c9bSToomas Soome return(buffer);
4065ffb0c9bSToomas Soome }
4075ffb0c9bSToomas Soome }
4085ffb0c9bSToomas Soome }
4095ffb0c9bSToomas Soome
swap16(unsigned short x)4105ffb0c9bSToomas Soome static unsigned short swap16(unsigned short x)
4115ffb0c9bSToomas Soome {
4125ffb0c9bSToomas Soome unsigned char *ptr = (unsigned char *)&x;
4135ffb0c9bSToomas Soome return (unsigned short)((unsigned short)ptr[0] << 8 | ptr[1]);
4145ffb0c9bSToomas Soome }
4155ffb0c9bSToomas Soome
swap32(unsigned int x)416c1de7575SRichard Lowe static unsigned int swap32(unsigned int x)
4175ffb0c9bSToomas Soome {
4185ffb0c9bSToomas Soome unsigned char *ptr = (unsigned char *)&x;
4195ffb0c9bSToomas Soome return (unsigned int)((unsigned int)ptr[0] << 24 | (unsigned int)ptr[1] << 16 | (unsigned int)ptr[2] << 8 | ptr[3]);
4205ffb0c9bSToomas Soome }
keytag(unsigned char * key,unsigned int keysize)421c1de7575SRichard Lowe static unsigned int keytag(unsigned char *key, unsigned int keysize)
4225ffb0c9bSToomas Soome {
4235ffb0c9bSToomas Soome unsigned long ac;
4245ffb0c9bSToomas Soome unsigned int i;
4255ffb0c9bSToomas Soome
4265ffb0c9bSToomas Soome for (ac = 0, i = 0; i < keysize; ++i)
4275ffb0c9bSToomas Soome ac += (i & 1) ? key[i] : key[i] << 8;
4285ffb0c9bSToomas Soome ac += (ac >> 16) & 0xFFFF;
4295ffb0c9bSToomas Soome return ac & 0xFFFF;
4305ffb0c9bSToomas Soome }
4315ffb0c9bSToomas Soome
4323b436d06SToomas Soome // Base 64 encoding according to <https://tools.ietf.org/html/rfc4648#section-4>.
4333b436d06SToomas Soome #define kBase64EncodingTable "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
4343b436d06SToomas Soome
base64Encode(char * buffer,size_t buflen,void * rdata,size_t rdlen)4353b436d06SToomas Soome static void base64Encode(char *buffer, size_t buflen, void *rdata, size_t rdlen)
4365ffb0c9bSToomas Soome {
4373b436d06SToomas Soome const uint8_t *src = (const uint8_t *)rdata;
4383b436d06SToomas Soome const uint8_t *const end = &src[rdlen];
4393b436d06SToomas Soome char *dst = buffer;
4403b436d06SToomas Soome const char *lim;
4413b436d06SToomas Soome
4423b436d06SToomas Soome if (buflen == 0) return;
4433b436d06SToomas Soome lim = &buffer[buflen - 1];
4443b436d06SToomas Soome while ((src < end) && (dst < lim))
4453b436d06SToomas Soome {
4463b436d06SToomas Soome uint32_t i;
4473b436d06SToomas Soome const size_t rem = (size_t)(end - src);
4483b436d06SToomas Soome
4493b436d06SToomas Soome // Form a 24-bit input group. If less than 24 bits remain, pad with zero bits.
4503b436d06SToomas Soome if ( rem >= 3) i = (src[0] << 16) | (src[1] << 8) | src[2]; // 24 bits are equal to 4 6-bit groups.
4513b436d06SToomas Soome else if (rem == 2) i = (src[0] << 16) | (src[1] << 8); // 16 bits are treated as 3 6-bit groups + 1 pad
4523b436d06SToomas Soome else i = src[0] << 16; // 8 bits are treated as 2 6-bit groups + 2 pads
4533b436d06SToomas Soome
4543b436d06SToomas Soome // Encode each 6-bit group.
4553b436d06SToomas Soome *dst++ = kBase64EncodingTable[(i >> 18) & 0x3F];
4563b436d06SToomas Soome if (dst < lim) *dst++ = kBase64EncodingTable[(i >> 12) & 0x3F];
4573b436d06SToomas Soome if (dst < lim) *dst++ = (rem >= 2) ? kBase64EncodingTable[(i >> 6) & 0x3F] : '=';
4583b436d06SToomas Soome if (dst < lim) *dst++ = (rem >= 3) ? kBase64EncodingTable[ i & 0x3F] : '=';
4593b436d06SToomas Soome src += (rem > 3) ? 3 : rem;
4603b436d06SToomas Soome }
4613b436d06SToomas Soome *dst = '\0';
4625ffb0c9bSToomas Soome }
4635ffb0c9bSToomas Soome
GetProtocol(const char * s)4645ffb0c9bSToomas Soome static DNSServiceProtocol GetProtocol(const char *s)
4655ffb0c9bSToomas Soome {
4665ffb0c9bSToomas Soome if (!strcasecmp(s, "v4" )) return(kDNSServiceProtocol_IPv4);
4675ffb0c9bSToomas Soome else if (!strcasecmp(s, "v6" )) return(kDNSServiceProtocol_IPv6);
4685ffb0c9bSToomas Soome else if (!strcasecmp(s, "v4v6" )) return(kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6);
4695ffb0c9bSToomas Soome else if (!strcasecmp(s, "v6v4" )) return(kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6);
4705ffb0c9bSToomas Soome else if (!strcasecmp(s, "udp" )) return(kDNSServiceProtocol_UDP);
4715ffb0c9bSToomas Soome else if (!strcasecmp(s, "tcp" )) return(kDNSServiceProtocol_TCP);
4725ffb0c9bSToomas Soome else if (!strcasecmp(s, "udptcp" )) return(kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP);
4735ffb0c9bSToomas Soome else if (!strcasecmp(s, "tcpudp" )) return(kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP);
4745ffb0c9bSToomas Soome else return(atoi(s));
4755ffb0c9bSToomas Soome }
4765ffb0c9bSToomas Soome
4775ffb0c9bSToomas Soome
4785ffb0c9bSToomas Soome //*************************************************************************************************************
4795ffb0c9bSToomas Soome // Sample callback functions for each of the operation types
4805ffb0c9bSToomas Soome
481c65ebfc7SToomas Soome #define printtimestamp() printtimestamp_F(stdout)
482c65ebfc7SToomas Soome
printtimestamp_F(FILE * outstream)483c65ebfc7SToomas Soome static void printtimestamp_F(FILE *outstream)
4845ffb0c9bSToomas Soome {
4855ffb0c9bSToomas Soome struct tm tm;
4865ffb0c9bSToomas Soome int ms;
4875ffb0c9bSToomas Soome static char date[16];
4885ffb0c9bSToomas Soome static char new_date[16];
4895ffb0c9bSToomas Soome #ifdef _WIN32
4905ffb0c9bSToomas Soome SYSTEMTIME sysTime;
4915ffb0c9bSToomas Soome time_t uct = time(NULL);
4925ffb0c9bSToomas Soome tm = *localtime(&uct);
4935ffb0c9bSToomas Soome GetLocalTime(&sysTime);
4945ffb0c9bSToomas Soome ms = sysTime.wMilliseconds;
4955ffb0c9bSToomas Soome #else
4965ffb0c9bSToomas Soome struct timeval tv;
4975ffb0c9bSToomas Soome gettimeofday(&tv, NULL);
4985ffb0c9bSToomas Soome localtime_r((time_t*)&tv.tv_sec, &tm);
4995ffb0c9bSToomas Soome ms = tv.tv_usec/1000;
5005ffb0c9bSToomas Soome #endif
5015ffb0c9bSToomas Soome strftime(new_date, sizeof(new_date), "%a %d %b %Y", &tm);
5025ffb0c9bSToomas Soome if (strncmp(date, new_date, sizeof(new_date)))
5035ffb0c9bSToomas Soome {
504c65ebfc7SToomas Soome fprintf(outstream, "DATE: ---%s---\n", new_date); //display date only if it has changed
5055ffb0c9bSToomas Soome strncpy(date, new_date, sizeof(date));
5065ffb0c9bSToomas Soome }
507c65ebfc7SToomas Soome fprintf(outstream, "%2d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms);
5085ffb0c9bSToomas Soome }
5095ffb0c9bSToomas Soome
5105ffb0c9bSToomas Soome // formating time to RFC 4034 format
FormatTime(unsigned long te,unsigned char * buf,int bufsize)511c1de7575SRichard Lowe static void FormatTime(unsigned long te, unsigned char *buf, int bufsize)
5125ffb0c9bSToomas Soome {
5135ffb0c9bSToomas Soome struct tm tmTime;
5145ffb0c9bSToomas Soome #ifdef _WIN32
5155ffb0c9bSToomas Soome __time32_t t = (__time32_t) te;
5165ffb0c9bSToomas Soome _gmtime32_s(&tmTime, &t);
5175ffb0c9bSToomas Soome #else
5185ffb0c9bSToomas Soome // Time since epoch : strftime takes "tm". Convert seconds to "tm" using
5195ffb0c9bSToomas Soome // gmtime_r first and then use strftime
5205ffb0c9bSToomas Soome time_t t = (time_t)te;
5215ffb0c9bSToomas Soome gmtime_r(&t, &tmTime);
5225ffb0c9bSToomas Soome #endif
5235ffb0c9bSToomas Soome strftime((char *)buf, bufsize, "%Y%m%d%H%M%S", &tmTime);
5245ffb0c9bSToomas Soome }
5255ffb0c9bSToomas Soome
print_usage(const char * arg0,int print_all)5265ffb0c9bSToomas Soome static void print_usage(const char *arg0, int print_all)
5275ffb0c9bSToomas Soome {
528c65ebfc7SToomas Soome // Print the commonly used command line options. These are listed in "the order they have been in historically".
529*472cd20dSToomas Soome fprintf(stderr, "%s -E (Enumerate recommended registration domains)\n", arg0);
530*472cd20dSToomas Soome fprintf(stderr, "%s -F (Enumerate recommended browsing domains)\n", arg0);
531*472cd20dSToomas Soome fprintf(stderr, "%s -R <Name> <Type> <Domain> <Port> [<TXT>...] (Register a service)\n", arg0);
532*472cd20dSToomas Soome fprintf(stderr, "%s -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...] (Register Proxy)\n", arg0);
533*472cd20dSToomas Soome fprintf(stderr, "%s -B <Type> <Domain> (Browse for service instances)\n", arg0);
534*472cd20dSToomas Soome fprintf(stderr, "%s -Z <Type> <Domain> (Output results in Zone File format)\n", arg0);
535*472cd20dSToomas Soome fprintf(stderr, "%s -L <Name> <Type> <Domain> (Resolve (‘lookup’) a service instance)\n", arg0);
536*472cd20dSToomas Soome fprintf(stderr, "%s -Q <name> <rrtype> <rrclass> (Generic query for any record type)\n", arg0);
537*472cd20dSToomas Soome fprintf(stderr, "%s -q <name> <rrtype> <rrclass> (Generic query, using SuppressUnusable)\n", arg0);
538*472cd20dSToomas Soome fprintf(stderr, "%s -G v4/v6/v4v6 <hostname> (Get address information for hostname)\n", arg0);
539*472cd20dSToomas Soome fprintf(stderr, "%s -X udp/tcp/udptcp <IntPort> <ExtPort> <TTL> (NAT Port Mapping)\n", arg0);
540*472cd20dSToomas Soome fprintf(stderr, "%s -H (Print usage for complete command list)\n", arg0);
541*472cd20dSToomas Soome fprintf(stderr, "%s -V (Get version of currently running daemon / system service)\n", arg0);
542*472cd20dSToomas Soome #ifdef APPLE_OSX_mDNSResponder
543*472cd20dSToomas Soome fprintf(stderr, "%s -O [-compress|-stdout](Dump the state of mDNSResponder to file / STDOUT)\n", arg0);
544*472cd20dSToomas Soome #endif // APPLE_OSX_mDNSResponder
5455ffb0c9bSToomas Soome
546c65ebfc7SToomas Soome if (print_all) // Print all available options for dns-sd tool. Keep these in alphabetical order for easier maintenance.
5475ffb0c9bSToomas Soome {
548c65ebfc7SToomas Soome fprintf(stderr, "\n");
549*472cd20dSToomas Soome fprintf(stderr, "%s -A (Test Adding/Updating/Deleting a record)\n", arg0);
550*472cd20dSToomas Soome fprintf(stderr, "%s -C <name> <rrtype> <rrclass> (Query; reconfirming each result)\n", arg0);
551*472cd20dSToomas Soome fprintf(stderr, "%s -I (Test registering and then immediately updating TXT record)\n", arg0);
552*472cd20dSToomas Soome fprintf(stderr, "%s -N (Test adding a large NULL record)\n", arg0);
553*472cd20dSToomas Soome fprintf(stderr, "%s -M (Test creating a registration with multiple TXT records)\n", arg0);
554*472cd20dSToomas Soome fprintf(stderr, "%s -S (Test multiple operations on a shared socket)\n", arg0);
555*472cd20dSToomas Soome fprintf(stderr, "%s -T (Test creating a large TXT record)\n", arg0);
556*472cd20dSToomas Soome fprintf(stderr, "%s -U (Test updating a TXT record)\n", arg0);
557*472cd20dSToomas Soome fprintf(stderr, "%s -ble (Use kDNSServiceInterfaceIndexBLE)\n", arg0);
558*472cd20dSToomas Soome fprintf(stderr, "%s -i <Interface> (Run dns-sd cmd on a specific interface (en0/en1)\n", arg0);
559*472cd20dSToomas Soome fprintf(stderr, "%s -includep2p (Set kDNSServiceFlagsIncludeP2P flag)\n", arg0);
560*472cd20dSToomas Soome fprintf(stderr, "%s -includeAWDL (Set kDNSServiceFlagsIncludeAWDL flag)\n", arg0);
561*472cd20dSToomas Soome fprintf(stderr, "%s -intermediates (Set kDNSServiceFlagsReturnIntermediates flag)\n", arg0);
562*472cd20dSToomas Soome fprintf(stderr, "%s -ku (Set kDNSServiceFlagsKnownUnique flag)\n", arg0);
563*472cd20dSToomas Soome fprintf(stderr, "%s -lo (Run dns-sd cmd using local only interface)\n", arg0);
564*472cd20dSToomas Soome fprintf(stderr, "%s -p2p (Use kDNSServiceInterfaceIndexP2P)\n", arg0);
565*472cd20dSToomas Soome fprintf(stderr, "%s -tc (Set kDNSServiceFlagsBackgroundTrafficClass flag)\n", arg0);
566*472cd20dSToomas Soome fprintf(stderr, "%s -test (Run basic API input range tests)\n", arg0);
567*472cd20dSToomas Soome fprintf(stderr, "%s -t1 (Set kDNSServiceFlagsThresholdOne flag)\n", arg0);
568*472cd20dSToomas Soome fprintf(stderr, "%s -tFinder (Set kDNSServiceFlagsThresholdFinder flag)\n", arg0);
569*472cd20dSToomas Soome fprintf(stderr, "%s -timeout (Set kDNSServiceFlagsTimeout flag)\n", arg0);
570*472cd20dSToomas Soome fprintf(stderr, "%s -unicastResponse (Set kDNSServiceFlagsUnicastResponse flag)\n", arg0);
571*472cd20dSToomas Soome fprintf(stderr, "%s -autoTrigger (Set kDNSServiceFlagsAutoTrigger flag)\n", arg0);
572*472cd20dSToomas Soome fprintf(stderr, "%s -enableDNSSEC (Enable DNSSEC validation for the '-Q' query)\n", arg0);
5735ffb0c9bSToomas Soome }
5745ffb0c9bSToomas Soome }
5755ffb0c9bSToomas Soome
5765ffb0c9bSToomas Soome #define DomainMsg(X) (((X) &kDNSServiceFlagsDefault) ? "(Default)" : \
5775ffb0c9bSToomas Soome ((X) &kDNSServiceFlagsAdd) ? "Added" : "Removed")
5785ffb0c9bSToomas Soome
5795ffb0c9bSToomas Soome #define MAX_LABELS 128
5805ffb0c9bSToomas Soome
enum_reply(DNSServiceRef sdref,const DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * replyDomain,void * context)5815ffb0c9bSToomas Soome static void DNSSD_API enum_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex,
5825ffb0c9bSToomas Soome DNSServiceErrorType errorCode, const char *replyDomain, void *context)
5835ffb0c9bSToomas Soome {
5845ffb0c9bSToomas Soome DNSServiceFlags partialflags = flags & ~(kDNSServiceFlagsMoreComing | kDNSServiceFlagsAdd | kDNSServiceFlagsDefault);
5855ffb0c9bSToomas Soome int labels = 0, depth = 0, i, initial = 0;
5865ffb0c9bSToomas Soome char text[64];
5875ffb0c9bSToomas Soome const char *label[MAX_LABELS];
5885ffb0c9bSToomas Soome
5895ffb0c9bSToomas Soome (void)sdref; // Unused
5905ffb0c9bSToomas Soome (void)ifIndex; // Unused
5915ffb0c9bSToomas Soome (void)context; // Unused
5925ffb0c9bSToomas Soome EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
5935ffb0c9bSToomas Soome
5945ffb0c9bSToomas Soome // 1. Print the header
5955ffb0c9bSToomas Soome if (num_printed++ == 0) printf("Timestamp Recommended %s domain\n", operation == 'E' ? "Registration" : "Browsing");
5965ffb0c9bSToomas Soome printtimestamp();
5975ffb0c9bSToomas Soome if (errorCode)
5985ffb0c9bSToomas Soome printf("Error code %d\n", errorCode);
5995ffb0c9bSToomas Soome else if (!*replyDomain)
6005ffb0c9bSToomas Soome printf("Error: No reply domain\n");
6015ffb0c9bSToomas Soome else
6025ffb0c9bSToomas Soome {
6035ffb0c9bSToomas Soome printf("%-10s", DomainMsg(flags));
6045ffb0c9bSToomas Soome printf("%-8s", (flags & kDNSServiceFlagsMoreComing) ? "(More)" : "");
6055ffb0c9bSToomas Soome if (partialflags) printf("Flags: %4X ", partialflags);
6065ffb0c9bSToomas Soome else printf(" ");
6075ffb0c9bSToomas Soome
6085ffb0c9bSToomas Soome // 2. Count the labels
6095ffb0c9bSToomas Soome while (replyDomain && *replyDomain && labels < MAX_LABELS)
6105ffb0c9bSToomas Soome {
6115ffb0c9bSToomas Soome label[labels++] = replyDomain;
6125ffb0c9bSToomas Soome replyDomain = GetNextLabel(replyDomain, text);
6135ffb0c9bSToomas Soome }
6145ffb0c9bSToomas Soome
6155ffb0c9bSToomas Soome // 3. Decide if we're going to clump the last two or three labels (e.g. "apple.com", or "nicta.com.au")
6165ffb0c9bSToomas Soome if (labels >= 3 && replyDomain - label[labels-1] <= 3 && label[labels-1] - label[labels-2] <= 4) initial = 3;
6175ffb0c9bSToomas Soome else if (labels >= 2 && replyDomain - label[labels-1] <= 4) initial = 2;
6185ffb0c9bSToomas Soome else initial = 1;
6195ffb0c9bSToomas Soome labels -= initial;
6205ffb0c9bSToomas Soome
6215ffb0c9bSToomas Soome // 4. Print the initial one-, two- or three-label clump
6225ffb0c9bSToomas Soome for (i=0; i<initial; i++)
6235ffb0c9bSToomas Soome {
6245ffb0c9bSToomas Soome GetNextLabel(label[labels+i], text);
6255ffb0c9bSToomas Soome if (i>0) printf(".");
6265ffb0c9bSToomas Soome printf("%s", text);
6275ffb0c9bSToomas Soome }
6285ffb0c9bSToomas Soome printf("\n");
6295ffb0c9bSToomas Soome
6305ffb0c9bSToomas Soome // 5. Print the remainder of the hierarchy
6315ffb0c9bSToomas Soome for (depth=0; depth<labels; depth++)
6325ffb0c9bSToomas Soome {
6335ffb0c9bSToomas Soome printf(" ");
6345ffb0c9bSToomas Soome for (i=0; i<=depth; i++) printf("- ");
6355ffb0c9bSToomas Soome GetNextLabel(label[labels-1-depth], text);
6365ffb0c9bSToomas Soome printf("> %s\n", text);
6375ffb0c9bSToomas Soome }
6385ffb0c9bSToomas Soome }
6395ffb0c9bSToomas Soome
6405ffb0c9bSToomas Soome if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
6415ffb0c9bSToomas Soome }
6425ffb0c9bSToomas Soome
CopyLabels(char * dst,const char * lim,const char ** srcp,int labels)6435ffb0c9bSToomas Soome static int CopyLabels(char *dst, const char *lim, const char **srcp, int labels)
6445ffb0c9bSToomas Soome {
6455ffb0c9bSToomas Soome const char *src = *srcp;
6465ffb0c9bSToomas Soome while (*src != '.' || --labels > 0)
6475ffb0c9bSToomas Soome {
6485ffb0c9bSToomas Soome if (*src == '\\') *dst++ = *src++; // Make sure "\." doesn't confuse us
6495ffb0c9bSToomas Soome if (!*src || dst >= lim) return -1;
6505ffb0c9bSToomas Soome *dst++ = *src++;
6515ffb0c9bSToomas Soome if (!*src || dst >= lim) return -1;
6525ffb0c9bSToomas Soome }
6535ffb0c9bSToomas Soome *dst++ = 0;
6545ffb0c9bSToomas Soome *srcp = src + 1; // skip over final dot
6555ffb0c9bSToomas Soome return 0;
6565ffb0c9bSToomas Soome }
6575ffb0c9bSToomas Soome
zonedata_resolve(DNSServiceRef sdref,const DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullname,const char * hosttarget,uint16_t opaqueport,uint16_t txtLen,const unsigned char * txt,void * context)6585ffb0c9bSToomas Soome static void DNSSD_API zonedata_resolve(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
6595ffb0c9bSToomas Soome const char *fullname, const char *hosttarget, uint16_t opaqueport, uint16_t txtLen, const unsigned char *txt, void *context)
6605ffb0c9bSToomas Soome {
6615ffb0c9bSToomas Soome union { uint16_t s; u_char b[2]; } port = { opaqueport };
6625ffb0c9bSToomas Soome uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1];
6635ffb0c9bSToomas Soome
6645ffb0c9bSToomas Soome const char *p = fullname;
6655ffb0c9bSToomas Soome char n[kDNSServiceMaxDomainName];
6665ffb0c9bSToomas Soome char t[kDNSServiceMaxDomainName];
6675ffb0c9bSToomas Soome
6685ffb0c9bSToomas Soome const unsigned char *max = txt + txtLen;
6695ffb0c9bSToomas Soome
6705ffb0c9bSToomas Soome (void)sdref; // Unused
6715ffb0c9bSToomas Soome (void)ifIndex; // Unused
6725ffb0c9bSToomas Soome (void)context; // Unused
6735ffb0c9bSToomas Soome
6745ffb0c9bSToomas Soome //if (!(flags & kDNSServiceFlagsAdd)) return;
6755ffb0c9bSToomas Soome if (errorCode) { printf("Error code %d\n", errorCode); return; }
6765ffb0c9bSToomas Soome
6775ffb0c9bSToomas Soome if (CopyLabels(n, n + kDNSServiceMaxDomainName, &p, 3)) return; // Fetch name+type
6785ffb0c9bSToomas Soome p = fullname;
6795ffb0c9bSToomas Soome if (CopyLabels(t, t + kDNSServiceMaxDomainName, &p, 1)) return; // Skip first label
6805ffb0c9bSToomas Soome if (CopyLabels(t, t + kDNSServiceMaxDomainName, &p, 2)) return; // Fetch next two labels (service type)
6815ffb0c9bSToomas Soome
6825ffb0c9bSToomas Soome if (num_printed++ == 0)
6835ffb0c9bSToomas Soome {
6845ffb0c9bSToomas Soome printf("\n");
6855ffb0c9bSToomas Soome printf("; To direct clients to browse a different domain, substitute that domain in place of '@'\n");
6865ffb0c9bSToomas Soome printf("%-47s PTR %s\n", "lb._dns-sd._udp", "@");
6875ffb0c9bSToomas Soome printf("\n");
6885ffb0c9bSToomas Soome printf("; In the list of services below, the SRV records will typically reference dot-local Multicast DNS names.\n");
6895ffb0c9bSToomas Soome printf("; When transferring this zone file data to your unicast DNS server, you'll need to replace those dot-local\n");
6905ffb0c9bSToomas Soome printf("; names with the correct fully-qualified (unicast) domain name of the target host offering the service.\n");
6915ffb0c9bSToomas Soome }
6925ffb0c9bSToomas Soome
6935ffb0c9bSToomas Soome printf("\n");
6945ffb0c9bSToomas Soome printf("%-47s PTR %s\n", t, n);
6955ffb0c9bSToomas Soome printf("%-47s SRV 0 0 %d %s ; Replace with unicast FQDN of target host\n", n, PortAsNumber, hosttarget);
6965ffb0c9bSToomas Soome printf("%-47s TXT ", n);
6975ffb0c9bSToomas Soome
6985ffb0c9bSToomas Soome while (txt < max)
6995ffb0c9bSToomas Soome {
7005ffb0c9bSToomas Soome const unsigned char *const end = txt + 1 + txt[0];
7015ffb0c9bSToomas Soome txt++; // Skip over length byte
7025ffb0c9bSToomas Soome printf(" \"");
7035ffb0c9bSToomas Soome while (txt<end)
7045ffb0c9bSToomas Soome {
7055ffb0c9bSToomas Soome if (*txt == '\\' || *txt == '\"') printf("\\");
7065ffb0c9bSToomas Soome printf("%c", *txt++);
7075ffb0c9bSToomas Soome }
7085ffb0c9bSToomas Soome printf("\"");
7095ffb0c9bSToomas Soome }
7105ffb0c9bSToomas Soome printf("\n");
7115ffb0c9bSToomas Soome
7125ffb0c9bSToomas Soome DNSServiceRefDeallocate(sdref);
7135ffb0c9bSToomas Soome free(context);
7145ffb0c9bSToomas Soome
7155ffb0c9bSToomas Soome if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
7165ffb0c9bSToomas Soome }
7175ffb0c9bSToomas Soome
zonedata_browse(DNSServiceRef sdref,const DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * replyName,const char * replyType,const char * replyDomain,void * context)7185ffb0c9bSToomas Soome static void DNSSD_API zonedata_browse(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
7195ffb0c9bSToomas Soome const char *replyName, const char *replyType, const char *replyDomain, void *context)
7205ffb0c9bSToomas Soome {
7215ffb0c9bSToomas Soome DNSServiceRef *newref;
7225ffb0c9bSToomas Soome
7235ffb0c9bSToomas Soome (void)sdref; // Unused
7245ffb0c9bSToomas Soome (void)context; // Unused
7255ffb0c9bSToomas Soome EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
7265ffb0c9bSToomas Soome
7275ffb0c9bSToomas Soome if (!(flags & kDNSServiceFlagsAdd)) return;
7285ffb0c9bSToomas Soome if (errorCode) { printf("Error code %d\n", errorCode); return; }
7295ffb0c9bSToomas Soome
7305ffb0c9bSToomas Soome newref = malloc(sizeof(*newref));
7315ffb0c9bSToomas Soome *newref = client;
7325ffb0c9bSToomas Soome DNSServiceResolve(newref, kDNSServiceFlagsShareConnection, ifIndex, replyName, replyType, replyDomain, zonedata_resolve, newref);
7335ffb0c9bSToomas Soome }
7345ffb0c9bSToomas Soome
browse_reply(DNSServiceRef sdref,const DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * replyName,const char * replyType,const char * replyDomain,void * context)7355ffb0c9bSToomas Soome static void DNSSD_API browse_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
7365ffb0c9bSToomas Soome const char *replyName, const char *replyType, const char *replyDomain, void *context)
7375ffb0c9bSToomas Soome {
7385ffb0c9bSToomas Soome char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
7395ffb0c9bSToomas Soome (void)sdref; // Unused
7405ffb0c9bSToomas Soome (void)context; // Unused
7415ffb0c9bSToomas Soome EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
7425ffb0c9bSToomas Soome
7435ffb0c9bSToomas Soome if (num_printed++ == 0) printf("Timestamp A/R Flags if %-20s %-20s %s\n", "Domain", "Service Type", "Instance Name");
7445ffb0c9bSToomas Soome printtimestamp();
745c1de7575SRichard Lowe if (errorCode)
7465ffb0c9bSToomas Soome printf("Error code %d\n", errorCode);
747c1de7575SRichard Lowe else
748c1de7575SRichard Lowe printf("%s %8X %3d %-20s %-20s %s\n",
7495ffb0c9bSToomas Soome op, flags, ifIndex, replyDomain, replyType, replyName);
7505ffb0c9bSToomas Soome if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
7515ffb0c9bSToomas Soome
7525ffb0c9bSToomas Soome // To test selective cancellation of operations of shared sockets,
7535ffb0c9bSToomas Soome // cancel the current operation when we've got a multiple of five results
7545ffb0c9bSToomas Soome //if (operation == 'S' && num_printed % 5 == 0) DNSServiceRefDeallocate(sdref);
7555ffb0c9bSToomas Soome }
7565ffb0c9bSToomas Soome
ShowTXTRecord(uint16_t txtLen,const unsigned char * txtRecord)7575ffb0c9bSToomas Soome static void ShowTXTRecord(uint16_t txtLen, const unsigned char *txtRecord)
7585ffb0c9bSToomas Soome {
7595ffb0c9bSToomas Soome const unsigned char *ptr = txtRecord;
7605ffb0c9bSToomas Soome const unsigned char *max = txtRecord + txtLen;
7615ffb0c9bSToomas Soome while (ptr < max)
7625ffb0c9bSToomas Soome {
7635ffb0c9bSToomas Soome const unsigned char *const end = ptr + 1 + ptr[0];
7645ffb0c9bSToomas Soome if (end > max) { printf("<< invalid data >>"); break; }
7655ffb0c9bSToomas Soome if (++ptr < end) printf(" "); // As long as string is non-empty, begin with a space
7665ffb0c9bSToomas Soome while (ptr<end)
7675ffb0c9bSToomas Soome {
7685ffb0c9bSToomas Soome // We'd like the output to be shell-friendly, so that it can be copied and pasted unchanged into a "dns-sd -R" command.
7695ffb0c9bSToomas Soome // However, this is trickier than it seems. Enclosing a string in double quotes doesn't necessarily make it
7705ffb0c9bSToomas Soome // shell-safe, because shells still expand variables like $foo even when they appear inside quoted strings.
7715ffb0c9bSToomas Soome // Enclosing a string in single quotes is better, but when using single quotes even backslash escapes are ignored,
7725ffb0c9bSToomas Soome // meaning there's simply no way to represent a single quote (or apostrophe) inside a single-quoted string.
7735ffb0c9bSToomas Soome // The only remaining solution is not to surround the string with quotes at all, but instead to use backslash
7745ffb0c9bSToomas Soome // escapes to encode spaces and all other known shell metacharacters.
7755ffb0c9bSToomas Soome // (If we've missed any known shell metacharacters, please let us know.)
7765ffb0c9bSToomas Soome // In addition, non-printing ascii codes (0-31) are displayed as \xHH, using a two-digit hex value.
7775ffb0c9bSToomas Soome // Because '\' is itself a shell metacharacter (the shell escape character), it has to be escaped as "\\" to survive
7785ffb0c9bSToomas Soome // the round-trip to the shell and back. This means that a single '\' is represented here as EIGHT backslashes:
7795ffb0c9bSToomas Soome // The C compiler eats half of them, resulting in four appearing in the output.
7805ffb0c9bSToomas Soome // The shell parses those four as a pair of "\\" sequences, passing two backslashes to the "dns-sd -R" command.
7815ffb0c9bSToomas Soome // The "dns-sd -R" command interprets this single "\\" pair as an escaped literal backslash. Sigh.
7825ffb0c9bSToomas Soome if (strchr(" &;`'\"|*?~<>^()[]{}$", *ptr)) printf("\\");
7835ffb0c9bSToomas Soome if (*ptr == '\\') printf("\\\\\\\\");
7845ffb0c9bSToomas Soome else if (*ptr >= ' ' ) printf("%c", *ptr);
7855ffb0c9bSToomas Soome else printf("\\\\x%02X", *ptr);
7865ffb0c9bSToomas Soome ptr++;
7875ffb0c9bSToomas Soome }
7885ffb0c9bSToomas Soome }
7895ffb0c9bSToomas Soome }
7905ffb0c9bSToomas Soome
resolve_reply(DNSServiceRef sdref,const DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullname,const char * hosttarget,uint16_t opaqueport,uint16_t txtLen,const unsigned char * txtRecord,void * context)7915ffb0c9bSToomas Soome static void DNSSD_API resolve_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
7925ffb0c9bSToomas Soome const char *fullname, const char *hosttarget, uint16_t opaqueport, uint16_t txtLen, const unsigned char *txtRecord, void *context)
7935ffb0c9bSToomas Soome {
7945ffb0c9bSToomas Soome union { uint16_t s; u_char b[2]; } port = { opaqueport };
7955ffb0c9bSToomas Soome uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1];
7965ffb0c9bSToomas Soome
7975ffb0c9bSToomas Soome (void)sdref; // Unused
7985ffb0c9bSToomas Soome (void)ifIndex; // Unused
7995ffb0c9bSToomas Soome (void)context; // Unused
8005ffb0c9bSToomas Soome EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
8015ffb0c9bSToomas Soome
802c65ebfc7SToomas Soome printtimestamp();
803c65ebfc7SToomas Soome
804c65ebfc7SToomas Soome printf("%s ", fullname);
805c65ebfc7SToomas Soome
806c65ebfc7SToomas Soome if (errorCode == kDNSServiceErr_NoSuchRecord) printf("No Such Record");
807c65ebfc7SToomas Soome else if (errorCode) printf("error code %d\n", errorCode);
808c65ebfc7SToomas Soome else printf("can be reached at %s:%u (interface %d)", hosttarget, PortAsNumber, ifIndex);
809c65ebfc7SToomas Soome
810c65ebfc7SToomas Soome if (flags) printf(" Flags: %X", flags);
811c65ebfc7SToomas Soome
812c65ebfc7SToomas Soome // Don't show degenerate TXT records containing nothing but a single empty string
813c65ebfc7SToomas Soome if (!errorCode && txtLen > 1) { printf("\n"); ShowTXTRecord(txtLen, txtRecord); }
814c65ebfc7SToomas Soome
815c65ebfc7SToomas Soome printf("\n");
8165ffb0c9bSToomas Soome
8175ffb0c9bSToomas Soome if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
8185ffb0c9bSToomas Soome }
8195ffb0c9bSToomas Soome
myTimerCallBack(void)8205ffb0c9bSToomas Soome static void myTimerCallBack(void)
8215ffb0c9bSToomas Soome {
8225ffb0c9bSToomas Soome DNSServiceErrorType err = kDNSServiceErr_Unknown;
8235ffb0c9bSToomas Soome
8245ffb0c9bSToomas Soome switch (operation)
8255ffb0c9bSToomas Soome {
8265ffb0c9bSToomas Soome case 'A':
8275ffb0c9bSToomas Soome {
8285ffb0c9bSToomas Soome switch (addtest)
8295ffb0c9bSToomas Soome {
8305ffb0c9bSToomas Soome case 0: printf("Adding Test HINFO record\n");
8315ffb0c9bSToomas Soome err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_HINFO, sizeof(myhinfoW), &myhinfoW[0], 0);
8325ffb0c9bSToomas Soome addtest = 1;
8335ffb0c9bSToomas Soome break;
8345ffb0c9bSToomas Soome case 1: printf("Updating Test HINFO record\n");
8355ffb0c9bSToomas Soome err = DNSServiceUpdateRecord(client, record, 0, sizeof(myhinfoX), &myhinfoX[0], 0);
8365ffb0c9bSToomas Soome addtest = 2;
8375ffb0c9bSToomas Soome break;
8385ffb0c9bSToomas Soome case 2: printf("Removing Test HINFO record\n");
8395ffb0c9bSToomas Soome err = DNSServiceRemoveRecord(client, record, 0);
8405ffb0c9bSToomas Soome addtest = 0;
8415ffb0c9bSToomas Soome break;
8425ffb0c9bSToomas Soome }
8435ffb0c9bSToomas Soome }
8445ffb0c9bSToomas Soome break;
8455ffb0c9bSToomas Soome
8465ffb0c9bSToomas Soome case 'U':
8475ffb0c9bSToomas Soome {
8485ffb0c9bSToomas Soome if (updatetest[1] != 'Z') updatetest[1]++;
8495ffb0c9bSToomas Soome else updatetest[1] = 'A';
850c65ebfc7SToomas Soome // The following line toggles the string length between 1 and 2 characters.
8515ffb0c9bSToomas Soome updatetest[0] = 3 - updatetest[0];
8525ffb0c9bSToomas Soome updatetest[2] = updatetest[1];
8535ffb0c9bSToomas Soome printtimestamp();
8545ffb0c9bSToomas Soome printf("Updating Test TXT record to %c\n", updatetest[1]);
8555ffb0c9bSToomas Soome err = DNSServiceUpdateRecord(client, NULL, 0, 1+updatetest[0], &updatetest[0], 0);
8565ffb0c9bSToomas Soome }
8575ffb0c9bSToomas Soome break;
8585ffb0c9bSToomas Soome
8595ffb0c9bSToomas Soome case 'N':
8605ffb0c9bSToomas Soome {
8615ffb0c9bSToomas Soome printf("Adding big NULL record\n");
8625ffb0c9bSToomas Soome err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_NULL, sizeof(bigNULL), &bigNULL[0], 0);
8635ffb0c9bSToomas Soome if (err) printf("Failed: %d\n", err);else printf("Succeeded\n");
8645ffb0c9bSToomas Soome timeOut = LONG_TIME;
8655ffb0c9bSToomas Soome #if _DNS_SD_LIBDISPATCH
8665ffb0c9bSToomas Soome if (timer_source)
8675ffb0c9bSToomas Soome dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)timeOut * NSEC_PER_SEC),
8685ffb0c9bSToomas Soome (uint64_t)timeOut * NSEC_PER_SEC, 0);
8695ffb0c9bSToomas Soome #endif
8705ffb0c9bSToomas Soome }
8715ffb0c9bSToomas Soome break;
8725ffb0c9bSToomas Soome }
8735ffb0c9bSToomas Soome
8745ffb0c9bSToomas Soome if (err != kDNSServiceErr_NoError)
8755ffb0c9bSToomas Soome {
8765ffb0c9bSToomas Soome fprintf(stderr, "DNSService add/update/remove failed %ld\n", (long int)err);
8775ffb0c9bSToomas Soome stopNow = 1;
8785ffb0c9bSToomas Soome }
8795ffb0c9bSToomas Soome }
8805ffb0c9bSToomas Soome
reg_reply(DNSServiceRef sdref,const DNSServiceFlags flags,DNSServiceErrorType errorCode,const char * name,const char * regtype,const char * domain,void * context)8815ffb0c9bSToomas Soome static void DNSSD_API reg_reply(DNSServiceRef sdref, const DNSServiceFlags flags, DNSServiceErrorType errorCode,
8825ffb0c9bSToomas Soome const char *name, const char *regtype, const char *domain, void *context)
8835ffb0c9bSToomas Soome {
8845ffb0c9bSToomas Soome (void)sdref; // Unused
8855ffb0c9bSToomas Soome (void)flags; // Unused
8865ffb0c9bSToomas Soome (void)context; // Unused
8875ffb0c9bSToomas Soome EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
8885ffb0c9bSToomas Soome
8895ffb0c9bSToomas Soome printtimestamp();
8905ffb0c9bSToomas Soome printf("Got a reply for service %s.%s%s: ", name, regtype, domain);
8915ffb0c9bSToomas Soome
8925ffb0c9bSToomas Soome if (errorCode == kDNSServiceErr_NoError)
8935ffb0c9bSToomas Soome {
8945ffb0c9bSToomas Soome if (flags & kDNSServiceFlagsAdd) printf("Name now registered and active\n");
8955ffb0c9bSToomas Soome else printf("Name registration removed\n");
8965ffb0c9bSToomas Soome if (operation == 'A' || operation == 'U' || operation == 'N')
8975ffb0c9bSToomas Soome {
8985ffb0c9bSToomas Soome timeOut = 5;
8995ffb0c9bSToomas Soome #if _DNS_SD_LIBDISPATCH
9005ffb0c9bSToomas Soome if (timer_source)
9015ffb0c9bSToomas Soome dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)timeOut * NSEC_PER_SEC),
9025ffb0c9bSToomas Soome (uint64_t)timeOut * NSEC_PER_SEC, 0);
9035ffb0c9bSToomas Soome #endif
9045ffb0c9bSToomas Soome }
9055ffb0c9bSToomas Soome }
9065ffb0c9bSToomas Soome else if (errorCode == kDNSServiceErr_NameConflict)
9075ffb0c9bSToomas Soome {
9085ffb0c9bSToomas Soome printf("Name in use, please choose another\n");
9095ffb0c9bSToomas Soome exit(-1);
9105ffb0c9bSToomas Soome }
9115ffb0c9bSToomas Soome else
9125ffb0c9bSToomas Soome printf("Error %d\n", errorCode);
9135ffb0c9bSToomas Soome
9145ffb0c9bSToomas Soome if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
9155ffb0c9bSToomas Soome }
9165ffb0c9bSToomas Soome
snprintf_safe(char * str,size_t size,const char * format,...)917*472cd20dSToomas Soome static int snprintf_safe(char *str, size_t size, const char *format, ...)
918*472cd20dSToomas Soome {
919*472cd20dSToomas Soome int length = 0;
920*472cd20dSToomas Soome va_list ptr;
921*472cd20dSToomas Soome va_start(ptr, format);
922*472cd20dSToomas Soome int result = vsnprintf(str, size, format, ptr);
923*472cd20dSToomas Soome va_end(ptr);
924*472cd20dSToomas Soome if (result > 0 && size > 0)
925*472cd20dSToomas Soome {
926*472cd20dSToomas Soome length = MIN((size_t)result, size-1);
927*472cd20dSToomas Soome }
928*472cd20dSToomas Soome return length;
929*472cd20dSToomas Soome }
930*472cd20dSToomas Soome
9315ffb0c9bSToomas Soome // Output the wire-format domainname pointed to by rd
snprintd(char * p,int max,const unsigned char ** rd)9325ffb0c9bSToomas Soome static int snprintd(char *p, int max, const unsigned char **rd)
9335ffb0c9bSToomas Soome {
9345ffb0c9bSToomas Soome const char *const buf = p;
9355ffb0c9bSToomas Soome const char *const end = p + max;
936*472cd20dSToomas Soome while (**rd)
937*472cd20dSToomas Soome {
938*472cd20dSToomas Soome p += snprintf_safe(p, end-p, "%.*s.", **rd, *rd+1);
939*472cd20dSToomas Soome *rd += 1 + **rd;
9405ffb0c9bSToomas Soome }
9415ffb0c9bSToomas Soome *rd += 1; // Advance over the final zero byte
9425ffb0c9bSToomas Soome return(p-buf);
9435ffb0c9bSToomas Soome }
9445ffb0c9bSToomas Soome
ParseDNSSECRecords(uint16_t rrtype,char * rdb,size_t rdb_size,unsigned const char * rd,uint16_t rdlen)9453b436d06SToomas Soome static void ParseDNSSECRecords(uint16_t rrtype, char *rdb, size_t rdb_size, unsigned const char *rd, uint16_t rdlen)
9465ffb0c9bSToomas Soome {
9473b436d06SToomas Soome char *p = rdb;
9483b436d06SToomas Soome switch (rrtype)
9495ffb0c9bSToomas Soome {
9505ffb0c9bSToomas Soome case kDNSServiceType_DS:
9515ffb0c9bSToomas Soome {
9525ffb0c9bSToomas Soome unsigned char *ptr;
9535ffb0c9bSToomas Soome int i;
9545ffb0c9bSToomas Soome rdataDS *rrds = (rdataDS *)rd;
955*472cd20dSToomas Soome p += snprintf_safe(p, rdb + rdb_size - p, "%d %d %d ",
9565ffb0c9bSToomas Soome rrds->alg, swap16(rrds->keyTag), rrds->digestType);
9575ffb0c9bSToomas Soome ptr = (unsigned char *)(rd + DS_FIXED_SIZE);
9585ffb0c9bSToomas Soome for (i = 0; i < (rdlen - DS_FIXED_SIZE); i++)
959*472cd20dSToomas Soome p += snprintf_safe(p, rdb + rdb_size - p, "%x", ptr[i]);
960*472cd20dSToomas Soome break;
961*472cd20dSToomas Soome }
962*472cd20dSToomas Soome
9635ffb0c9bSToomas Soome case kDNSServiceType_DNSKEY:
9645ffb0c9bSToomas Soome {
9655ffb0c9bSToomas Soome rdataDNSKey *rrkey = (rdataDNSKey *)rd;
966*472cd20dSToomas Soome p += snprintf_safe(p, rdb + rdb_size - p, "%d %d %d %u ", swap16(rrkey->flags), rrkey->proto,
9675ffb0c9bSToomas Soome rrkey->alg, (unsigned int)keytag((unsigned char *)rrkey, rdlen));
9685ffb0c9bSToomas Soome base64Encode(p, rdb + rdb_size - p, (unsigned char *)(rd + DNSKEY_FIXED_SIZE), rdlen - DNSKEY_FIXED_SIZE);
9695ffb0c9bSToomas Soome break;
9705ffb0c9bSToomas Soome }
971c1de7575SRichard Lowe
972c1de7575SRichard Lowe case kDNSServiceType_NSEC:
9735ffb0c9bSToomas Soome {
9745ffb0c9bSToomas Soome unsigned char *next = (unsigned char *)rd;
9755ffb0c9bSToomas Soome int len, bitmaplen;
9765ffb0c9bSToomas Soome int win, wlen, type;
9775ffb0c9bSToomas Soome unsigned char *bmap;
9785ffb0c9bSToomas Soome char *l = NULL;
979c1de7575SRichard Lowe
9805ffb0c9bSToomas Soome l = p;
9815ffb0c9bSToomas Soome p += snprintd(p, rdb + rdb_size - p, &rd);
9825ffb0c9bSToomas Soome len = p - l + 1;
983c1de7575SRichard Lowe
9845ffb0c9bSToomas Soome bitmaplen = rdlen - len;
9855ffb0c9bSToomas Soome bmap = (unsigned char *)((unsigned char *)next + len);
986c1de7575SRichard Lowe
9875ffb0c9bSToomas Soome while (bitmaplen > 0)
9885ffb0c9bSToomas Soome {
9895ffb0c9bSToomas Soome int i;
990c1de7575SRichard Lowe
9915ffb0c9bSToomas Soome if (bitmaplen < 3)
9925ffb0c9bSToomas Soome {
9935ffb0c9bSToomas Soome printf("Case NSEC: malformed nsec, bitmaplen %d short\n", bitmaplen);
9945ffb0c9bSToomas Soome break;
995c1de7575SRichard Lowe }
996c1de7575SRichard Lowe
9975ffb0c9bSToomas Soome win = *bmap++;
9985ffb0c9bSToomas Soome wlen = *bmap++;
9995ffb0c9bSToomas Soome bitmaplen -= 2;
10005ffb0c9bSToomas Soome if (bitmaplen < wlen || wlen < 1 || wlen > 32)
10015ffb0c9bSToomas Soome {
10025ffb0c9bSToomas Soome printf("Case NSEC: malformed nsec, bitmaplen %d wlen %d\n", bitmaplen, wlen);
10035ffb0c9bSToomas Soome break;
10045ffb0c9bSToomas Soome }
10055ffb0c9bSToomas Soome if (win < 0 || win >= 256)
10065ffb0c9bSToomas Soome {
10075ffb0c9bSToomas Soome printf("Case NSEC: malformed nsec, bad window win %d\n", win);
10085ffb0c9bSToomas Soome break;
10095ffb0c9bSToomas Soome }
10105ffb0c9bSToomas Soome type = win * 256;
10115ffb0c9bSToomas Soome for (i = 0; i < wlen * 8; i++)
10125ffb0c9bSToomas Soome {
10135ffb0c9bSToomas Soome if (bmap[i>>3] & (128 >> (i&7)))
1014*472cd20dSToomas Soome p += snprintf_safe(p, rdb + rdb_size - p, " %s ", DNSTypeName(type + i));
10155ffb0c9bSToomas Soome }
10165ffb0c9bSToomas Soome bmap += wlen;
10175ffb0c9bSToomas Soome bitmaplen -= wlen;
10185ffb0c9bSToomas Soome }
10195ffb0c9bSToomas Soome break;
10205ffb0c9bSToomas Soome }
1021c1de7575SRichard Lowe
1022c1de7575SRichard Lowe case kDNSServiceType_RRSIG:
10235ffb0c9bSToomas Soome {
10245ffb0c9bSToomas Soome rdataRRSig *rrsig = (rdataRRSig *)rd;
10255ffb0c9bSToomas Soome unsigned char expTimeBuf[64];
10265ffb0c9bSToomas Soome unsigned char inceptTimeBuf[64];
10275ffb0c9bSToomas Soome unsigned long inceptClock;
10285ffb0c9bSToomas Soome unsigned long expClock;
10295ffb0c9bSToomas Soome const unsigned char *q = NULL;
10305ffb0c9bSToomas Soome char *k = NULL;
10315ffb0c9bSToomas Soome int len;
1032c1de7575SRichard Lowe
10335ffb0c9bSToomas Soome expClock = (unsigned long)swap32(rrsig->sigExpireTime);
10345ffb0c9bSToomas Soome FormatTime(expClock, expTimeBuf, sizeof(expTimeBuf));
1035c1de7575SRichard Lowe
10365ffb0c9bSToomas Soome inceptClock = (unsigned long)swap32(rrsig->sigInceptTime);
10375ffb0c9bSToomas Soome FormatTime(inceptClock, inceptTimeBuf, sizeof(inceptTimeBuf));
1038*472cd20dSToomas Soome
1039*472cd20dSToomas Soome p += snprintf_safe(p, rdb + rdb_size - p, " %-7s %d %d %d %s %s %7d ",
10405ffb0c9bSToomas Soome DNSTypeName(swap16(rrsig->typeCovered)), rrsig->alg, rrsig->labels, swap32(rrsig->origTTL),
10415ffb0c9bSToomas Soome expTimeBuf, inceptTimeBuf, swap16(rrsig->keyTag));
1042c1de7575SRichard Lowe
10435ffb0c9bSToomas Soome q = (const unsigned char *)&rrsig->signerName;
10445ffb0c9bSToomas Soome k = p;
10455ffb0c9bSToomas Soome p += snprintd(p, rdb + rdb_size - p, &q);
10465ffb0c9bSToomas Soome len = p - k + 1;
10473b436d06SToomas Soome
10483b436d06SToomas Soome if ((&rdb[rdb_size] - p) >= 2)
10493b436d06SToomas Soome {
10503b436d06SToomas Soome *p++ = ' ';
10513b436d06SToomas Soome *p = '\0';
10523b436d06SToomas Soome }
10535ffb0c9bSToomas Soome base64Encode(p, rdb + rdb_size - p, (unsigned char *)(rd + len + RRSIG_FIXED_SIZE), rdlen - (len + RRSIG_FIXED_SIZE));
10545ffb0c9bSToomas Soome break;
10555ffb0c9bSToomas Soome }
10565ffb0c9bSToomas Soome }
1057c1de7575SRichard Lowe return;
10585ffb0c9bSToomas Soome }
10595ffb0c9bSToomas Soome
qr_reply(DNSServiceRef sdref,const DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullname,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata,uint32_t ttl,void * context)10605ffb0c9bSToomas Soome static void DNSSD_API qr_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
10615ffb0c9bSToomas Soome const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
10625ffb0c9bSToomas Soome {
10635ffb0c9bSToomas Soome char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
10645ffb0c9bSToomas Soome const unsigned char *rd = rdata;
10655ffb0c9bSToomas Soome const unsigned char *end = (const unsigned char *) rdata + rdlen;
10665ffb0c9bSToomas Soome char rdb[1000] = "0.0.0.0", *p = rdb;
10675ffb0c9bSToomas Soome int unknowntype = 0;
10685ffb0c9bSToomas Soome char dnssec_status[15] = "Unknown";
10695ffb0c9bSToomas Soome char rr_type[RR_TYPE_SIZE];
1070*472cd20dSToomas Soome char rr_class[6];
10715ffb0c9bSToomas Soome DNSServiceFlags check_flags = flags;//local flags for dnssec status checking
1072*472cd20dSToomas Soome int8_t enable_dnssec = ((check_flags & kDNSServiceFlagsEnableDNSSEC) != 0);
1073*472cd20dSToomas Soome static int8_t enabled_dnssec_before = -1;
1074*472cd20dSToomas Soome
1075*472cd20dSToomas Soome if (enabled_dnssec_before == -1) {
1076*472cd20dSToomas Soome enabled_dnssec_before = enable_dnssec;
1077*472cd20dSToomas Soome }
10785ffb0c9bSToomas Soome
10795ffb0c9bSToomas Soome (void)sdref; // Unused
10805ffb0c9bSToomas Soome (void)ifIndex; // Unused
10815ffb0c9bSToomas Soome (void)ttl; // Unused
10825ffb0c9bSToomas Soome (void)context; // Unused
10835ffb0c9bSToomas Soome EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
10845ffb0c9bSToomas Soome
10855ffb0c9bSToomas Soome if (num_printed++ == 0)
10865ffb0c9bSToomas Soome {
1087*472cd20dSToomas Soome printf("Timestamp A/R Flags if %-30s%-6s%-7s%s Rdata\n", "Name", "Type", "Class", enable_dnssec ? " DNSSECResult " : "");
10885ffb0c9bSToomas Soome }
10895ffb0c9bSToomas Soome printtimestamp();
10905ffb0c9bSToomas Soome
10915ffb0c9bSToomas Soome switch (rrclass)
10925ffb0c9bSToomas Soome {
10935ffb0c9bSToomas Soome case kDNSServiceClass_IN:
10945ffb0c9bSToomas Soome strncpy(rr_class, "IN", sizeof(rr_class));
10955ffb0c9bSToomas Soome break;
10965ffb0c9bSToomas Soome default:
10975ffb0c9bSToomas Soome snprintf(rr_class, sizeof(rr_class), "%d", rrclass);
10985ffb0c9bSToomas Soome break;
10995ffb0c9bSToomas Soome }
11005ffb0c9bSToomas Soome strncpy(rr_type, DNSTypeName(rrtype), sizeof(rr_type));
11015ffb0c9bSToomas Soome
11025ffb0c9bSToomas Soome if (!errorCode) //to avoid printing garbage in rdata
11035ffb0c9bSToomas Soome {
1104*472cd20dSToomas Soome switch (rrtype)
11055ffb0c9bSToomas Soome {
1106*472cd20dSToomas Soome case kDNSServiceType_A:
1107*472cd20dSToomas Soome snprintf_safe(rdb, sizeof(rdb), "%d.%d.%d.%d", rd[0], rd[1], rd[2], rd[3]);
1108*472cd20dSToomas Soome break;
1109*472cd20dSToomas Soome
1110*472cd20dSToomas Soome case kDNSServiceType_NS:
1111*472cd20dSToomas Soome case kDNSServiceType_CNAME:
1112*472cd20dSToomas Soome case kDNSServiceType_PTR:
1113*472cd20dSToomas Soome case kDNSServiceType_DNAME:
1114*472cd20dSToomas Soome snprintd(p, sizeof(rdb), &rd);
1115*472cd20dSToomas Soome break;
1116*472cd20dSToomas Soome
1117*472cd20dSToomas Soome case kDNSServiceType_SOA:
1118*472cd20dSToomas Soome p += snprintd(p, rdb + sizeof(rdb) - p, &rd); // mname
1119*472cd20dSToomas Soome p += snprintf_safe(p, rdb + sizeof(rdb) - p, " ");
1120*472cd20dSToomas Soome p += snprintd(p, rdb + sizeof(rdb) - p, &rd); // rname
1121*472cd20dSToomas Soome snprintf(p, rdb + sizeof(rdb) - p, " Ser %d Ref %d Ret %d Exp %d Min %d",
1122*472cd20dSToomas Soome ntohl(((uint32_t*)rd)[0]), ntohl(((uint32_t*)rd)[1]), ntohl(((uint32_t*)rd)[2]), ntohl(((uint32_t*)rd)[3]), ntohl(((uint32_t*)rd)[4]));
1123*472cd20dSToomas Soome break;
1124*472cd20dSToomas Soome
1125*472cd20dSToomas Soome case kDNSServiceType_AAAA:
1126*472cd20dSToomas Soome snprintf(rdb, sizeof(rdb), "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X",
1127*472cd20dSToomas Soome rd[0x0], rd[0x1], rd[0x2], rd[0x3], rd[0x4], rd[0x5], rd[0x6], rd[0x7],
1128*472cd20dSToomas Soome rd[0x8], rd[0x9], rd[0xA], rd[0xB], rd[0xC], rd[0xD], rd[0xE], rd[0xF]);
1129*472cd20dSToomas Soome break;
1130*472cd20dSToomas Soome
1131*472cd20dSToomas Soome case kDNSServiceType_SRV:
1132*472cd20dSToomas Soome p += snprintf_safe(p, rdb + sizeof(rdb) - p, "%d %d %d ", // priority, weight, port
1133*472cd20dSToomas Soome ntohs(*(unsigned short*)rd), ntohs(*(unsigned short*)(rd+2)), ntohs(*(unsigned short*)(rd+4)));
1134*472cd20dSToomas Soome rd += 6;
1135*472cd20dSToomas Soome snprintd(p, rdb + sizeof(rdb) - p, &rd); // target host
1136*472cd20dSToomas Soome break;
1137*472cd20dSToomas Soome
1138*472cd20dSToomas Soome case kDNSServiceType_DS:
1139*472cd20dSToomas Soome case kDNSServiceType_DNSKEY:
1140*472cd20dSToomas Soome case kDNSServiceType_NSEC:
1141*472cd20dSToomas Soome case kDNSServiceType_RRSIG:
1142*472cd20dSToomas Soome ParseDNSSECRecords(rrtype, rdb, sizeof(rdb), rd, rdlen);
1143*472cd20dSToomas Soome break;
1144*472cd20dSToomas Soome
1145*472cd20dSToomas Soome default:
1146*472cd20dSToomas Soome snprintf(rdb, sizeof(rdb), "%d bytes%s", rdlen, rdlen ? ":" : "");
1147*472cd20dSToomas Soome unknowntype = 1;
1148*472cd20dSToomas Soome break;
11495ffb0c9bSToomas Soome }
11505ffb0c9bSToomas Soome }
11515ffb0c9bSToomas Soome
1152*472cd20dSToomas Soome if (check_flags & kDNSServiceFlagsSecure)
1153*472cd20dSToomas Soome strncpy(dnssec_status, "Secure ", sizeof(dnssec_status));
1154*472cd20dSToomas Soome else if (check_flags & kDNSServiceFlagsInsecure)
1155*472cd20dSToomas Soome strncpy(dnssec_status, "Insecure ", sizeof(dnssec_status));
1156*472cd20dSToomas Soome else if (check_flags & kDNSServiceFlagsIndeterminate)
1157*472cd20dSToomas Soome strncpy(dnssec_status, "Indeterminate ", sizeof(dnssec_status));
1158*472cd20dSToomas Soome else if (check_flags & kDNSServiceFlagsBogus)
1159*472cd20dSToomas Soome strncpy(dnssec_status, "Bogus ", sizeof(dnssec_status));
11605ffb0c9bSToomas Soome else
1161*472cd20dSToomas Soome strncpy(dnssec_status, " ", sizeof(dnssec_status));
1162*472cd20dSToomas Soome
1163*472cd20dSToomas Soome printf("%s%9X%3d %-30s%-7s%-6s %s%s",
1164*472cd20dSToomas Soome op, flags, ifIndex, fullname, rr_type, rr_class, enabled_dnssec_before ? dnssec_status : "", rdb);
1165*472cd20dSToomas Soome
1166*472cd20dSToomas Soome
11675ffb0c9bSToomas Soome if (unknowntype)
1168c1de7575SRichard Lowe {
1169c1de7575SRichard Lowe while (rd < end)
11705ffb0c9bSToomas Soome printf(" %02X", *rd++);
11715ffb0c9bSToomas Soome }
11725ffb0c9bSToomas Soome if (errorCode)
11735ffb0c9bSToomas Soome {
1174c1de7575SRichard Lowe if (errorCode == kDNSServiceErr_NoSuchRecord)
11755ffb0c9bSToomas Soome printf(" No Such Record");
1176*472cd20dSToomas Soome else if (errorCode == kDNSServiceErr_NoAuth)
1177*472cd20dSToomas Soome printf(" No Authorization");
11785ffb0c9bSToomas Soome else if (errorCode == kDNSServiceErr_Timeout)
11795ffb0c9bSToomas Soome {
11805ffb0c9bSToomas Soome printf(" No Such Record\n");
11815ffb0c9bSToomas Soome printf("Query Timed Out\n");
11825ffb0c9bSToomas Soome exit(1);
11835ffb0c9bSToomas Soome }
11845ffb0c9bSToomas Soome }
11855ffb0c9bSToomas Soome printf("\n");
11865ffb0c9bSToomas Soome
11875ffb0c9bSToomas Soome if (operation == 'C')
11885ffb0c9bSToomas Soome if (flags & kDNSServiceFlagsAdd)
11895ffb0c9bSToomas Soome DNSServiceReconfirmRecord(flags, ifIndex, fullname, rrtype, rrclass, rdlen, rdata);
11905ffb0c9bSToomas Soome
1191c1de7575SRichard Lowe if (!(flags & kDNSServiceFlagsMoreComing))
11925ffb0c9bSToomas Soome fflush(stdout);
11935ffb0c9bSToomas Soome }
11945ffb0c9bSToomas Soome
port_mapping_create_reply(DNSServiceRef sdref,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,uint32_t publicAddress,uint32_t protocol,uint16_t privatePort,uint16_t publicPort,uint32_t ttl,void * context)11955ffb0c9bSToomas Soome static void DNSSD_API port_mapping_create_reply(DNSServiceRef sdref, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, uint32_t publicAddress, uint32_t protocol, uint16_t privatePort, uint16_t publicPort, uint32_t ttl, void *context)
11965ffb0c9bSToomas Soome {
11975ffb0c9bSToomas Soome (void)sdref; // Unused
11985ffb0c9bSToomas Soome (void)flags; // Unused
11995ffb0c9bSToomas Soome (void)context; // Unused
12005ffb0c9bSToomas Soome EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
12015ffb0c9bSToomas Soome
12025ffb0c9bSToomas Soome if (num_printed++ == 0) printf("Timestamp if %-20s %-15s %-15s %-15s %-6s\n", "External Address", "Protocol", "Internal Port", "External Port", "TTL");
12035ffb0c9bSToomas Soome printtimestamp();
12045ffb0c9bSToomas Soome if (errorCode && errorCode != kDNSServiceErr_DoubleNAT) printf("Error code %d\n", errorCode);
12055ffb0c9bSToomas Soome else
12065ffb0c9bSToomas Soome {
12075ffb0c9bSToomas Soome const unsigned char *digits = (const unsigned char *)&publicAddress;
12085ffb0c9bSToomas Soome char addr[256];
12095ffb0c9bSToomas Soome
12105ffb0c9bSToomas Soome snprintf(addr, sizeof(addr), "%d.%d.%d.%d", digits[0], digits[1], digits[2], digits[3]);
12115ffb0c9bSToomas Soome printf("%-4d %-20s %-15d %-15d %-15d %-6d%s\n", ifIndex, addr, protocol, ntohs(privatePort), ntohs(publicPort), ttl, errorCode == kDNSServiceErr_DoubleNAT ? " Double NAT" : "");
12125ffb0c9bSToomas Soome }
12135ffb0c9bSToomas Soome
12145ffb0c9bSToomas Soome if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
12155ffb0c9bSToomas Soome }
12165ffb0c9bSToomas Soome
addrinfo_reply(DNSServiceRef sdref,const DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * hostname,const struct sockaddr * address,uint32_t ttl,void * context)12175ffb0c9bSToomas Soome static void DNSSD_API addrinfo_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl, void *context)
12185ffb0c9bSToomas Soome {
12195ffb0c9bSToomas Soome char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
12205ffb0c9bSToomas Soome char addr[256] = "";
1221c1de7575SRichard Lowe char dnssec_status[15] = "Unknown";
12225ffb0c9bSToomas Soome DNSServiceFlags check_flags = flags;
12235ffb0c9bSToomas Soome (void) sdref;
12245ffb0c9bSToomas Soome (void) context;
1225*472cd20dSToomas Soome unsigned char enable_dnssec = ((check_flags & kDNSServiceFlagsEnableDNSSEC) != 0);
12265ffb0c9bSToomas Soome
12275ffb0c9bSToomas Soome EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
12285ffb0c9bSToomas Soome
12295ffb0c9bSToomas Soome if (num_printed++ == 0)
12305ffb0c9bSToomas Soome {
1231*472cd20dSToomas Soome printf("Timestamp A/R Flags if %-38s %-44s %s%s\n", "Hostname", "Address", "TTL", enable_dnssec ? "DNSSECResult" : "");
12325ffb0c9bSToomas Soome }
12335ffb0c9bSToomas Soome printtimestamp();
1234c1de7575SRichard Lowe
12355ffb0c9bSToomas Soome if (address && address->sa_family == AF_INET)
12365ffb0c9bSToomas Soome {
12375ffb0c9bSToomas Soome const unsigned char *b = (const unsigned char *) &((struct sockaddr_in *)address)->sin_addr;
12385ffb0c9bSToomas Soome snprintf(addr, sizeof(addr), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
12395ffb0c9bSToomas Soome }
12405ffb0c9bSToomas Soome else if (address && address->sa_family == AF_INET6)
12415ffb0c9bSToomas Soome {
12425ffb0c9bSToomas Soome char if_name[IFNAMSIZ]; // Older Linux distributions don't define IF_NAMESIZE
12435ffb0c9bSToomas Soome const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *)address;
12445ffb0c9bSToomas Soome const unsigned char *b = (const unsigned char * )&s6->sin6_addr;
12455ffb0c9bSToomas Soome if (!if_indextoname(s6->sin6_scope_id, if_name))
12465ffb0c9bSToomas Soome snprintf(if_name, sizeof(if_name), "<%d>", s6->sin6_scope_id);
1247985cc36cSToomas Soome snprintf(addr, sizeof(addr), "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X%%%s",
12485ffb0c9bSToomas Soome b[0x0], b[0x1], b[0x2], b[0x3], b[0x4], b[0x5], b[0x6], b[0x7],
12495ffb0c9bSToomas Soome b[0x8], b[0x9], b[0xA], b[0xB], b[0xC], b[0xD], b[0xE], b[0xF], if_name);
12505ffb0c9bSToomas Soome }
12515ffb0c9bSToomas Soome
1252*472cd20dSToomas Soome if (enable_dnssec)
12535ffb0c9bSToomas Soome {
12545ffb0c9bSToomas Soome if (check_flags & kDNSServiceFlagsSecure)
1255*472cd20dSToomas Soome strncpy(dnssec_status, " Secure", sizeof(dnssec_status));
12565ffb0c9bSToomas Soome else if (check_flags & kDNSServiceFlagsInsecure)
1257*472cd20dSToomas Soome strncpy(dnssec_status, " Insecure", sizeof(dnssec_status));
12585ffb0c9bSToomas Soome else if (check_flags & kDNSServiceFlagsIndeterminate)
1259*472cd20dSToomas Soome strncpy(dnssec_status, " Indeterminate", sizeof(dnssec_status));
1260c1de7575SRichard Lowe else if (check_flags & kDNSServiceFlagsBogus)
1261*472cd20dSToomas Soome strncpy(dnssec_status, " Bogus", sizeof(dnssec_status));
12625ffb0c9bSToomas Soome }
1263c1de7575SRichard Lowe
1264*472cd20dSToomas Soome printf("%s%9X%3d %-38s %-44s %d%s", op, flags, interfaceIndex, hostname, addr, ttl, enable_dnssec ? dnssec_status : "");
1265*472cd20dSToomas Soome
12665ffb0c9bSToomas Soome if (errorCode)
12675ffb0c9bSToomas Soome {
1268c1de7575SRichard Lowe if (errorCode == kDNSServiceErr_NoSuchRecord)
12695ffb0c9bSToomas Soome printf(" No Such Record");
1270c1de7575SRichard Lowe else
12715ffb0c9bSToomas Soome printf(" Error code %d", errorCode);
12725ffb0c9bSToomas Soome }
12735ffb0c9bSToomas Soome printf("\n");
12745ffb0c9bSToomas Soome
1275c1de7575SRichard Lowe if (!(flags & kDNSServiceFlagsMoreComing))
12765ffb0c9bSToomas Soome fflush(stdout);
12775ffb0c9bSToomas Soome }
12785ffb0c9bSToomas Soome
12795ffb0c9bSToomas Soome //*************************************************************************************************************
12805ffb0c9bSToomas Soome // The main test function
12815ffb0c9bSToomas Soome
HandleEvents(void)12825ffb0c9bSToomas Soome static void HandleEvents(void)
12835ffb0c9bSToomas Soome #if _DNS_SD_LIBDISPATCH
12845ffb0c9bSToomas Soome {
12855ffb0c9bSToomas Soome main_queue = dispatch_get_main_queue();
12865ffb0c9bSToomas Soome if (client) DNSServiceSetDispatchQueue(client, main_queue);
12875ffb0c9bSToomas Soome if (client_pa) DNSServiceSetDispatchQueue(client_pa, main_queue);
12885ffb0c9bSToomas Soome if (operation == 'A' || operation == 'U' || operation == 'N')
12895ffb0c9bSToomas Soome {
12905ffb0c9bSToomas Soome timer_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, main_queue);
12915ffb0c9bSToomas Soome if (timer_source)
12925ffb0c9bSToomas Soome {
12935ffb0c9bSToomas Soome // Start the timer "timeout" seconds into the future and repeat it every "timeout" seconds
12945ffb0c9bSToomas Soome dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)timeOut * NSEC_PER_SEC),
12955ffb0c9bSToomas Soome (uint64_t)timeOut * NSEC_PER_SEC, 0);
12965ffb0c9bSToomas Soome dispatch_source_set_event_handler(timer_source, ^{myTimerCallBack();});
12975ffb0c9bSToomas Soome dispatch_resume(timer_source);
12985ffb0c9bSToomas Soome }
12995ffb0c9bSToomas Soome }
13005ffb0c9bSToomas Soome dispatch_main();
13015ffb0c9bSToomas Soome }
13025ffb0c9bSToomas Soome #else
13035ffb0c9bSToomas Soome {
13045ffb0c9bSToomas Soome int dns_sd_fd = client ? DNSServiceRefSockFD(client ) : -1;
13055ffb0c9bSToomas Soome int dns_sd_fd2 = client_pa ? DNSServiceRefSockFD(client_pa) : -1;
13065ffb0c9bSToomas Soome int nfds = dns_sd_fd + 1;
13075ffb0c9bSToomas Soome fd_set readfds;
13085ffb0c9bSToomas Soome struct timeval tv;
13095ffb0c9bSToomas Soome int result;
13105ffb0c9bSToomas Soome
13115ffb0c9bSToomas Soome if (dns_sd_fd2 > dns_sd_fd) nfds = dns_sd_fd2 + 1;
13125ffb0c9bSToomas Soome
13135ffb0c9bSToomas Soome while (!stopNow)
13145ffb0c9bSToomas Soome {
13155ffb0c9bSToomas Soome // 1. Set up the fd_set as usual here.
13165ffb0c9bSToomas Soome // This example client has no file descriptors of its own,
13175ffb0c9bSToomas Soome // but a real application would call FD_SET to add them to the set here
13185ffb0c9bSToomas Soome FD_ZERO(&readfds);
13195ffb0c9bSToomas Soome
13205ffb0c9bSToomas Soome // 2. Add the fd for our client(s) to the fd_set
13215ffb0c9bSToomas Soome if (client ) FD_SET(dns_sd_fd, &readfds);
13225ffb0c9bSToomas Soome if (client_pa) FD_SET(dns_sd_fd2, &readfds);
13235ffb0c9bSToomas Soome
13245ffb0c9bSToomas Soome // 3. Set up the timeout.
13255ffb0c9bSToomas Soome tv.tv_sec = timeOut;
13265ffb0c9bSToomas Soome tv.tv_usec = 0;
13275ffb0c9bSToomas Soome
13285ffb0c9bSToomas Soome result = select(nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
13295ffb0c9bSToomas Soome if (result > 0)
13305ffb0c9bSToomas Soome {
13315ffb0c9bSToomas Soome DNSServiceErrorType err = kDNSServiceErr_NoError;
13325ffb0c9bSToomas Soome if (client && FD_ISSET(dns_sd_fd, &readfds)) err = DNSServiceProcessResult(client );
13335ffb0c9bSToomas Soome else if (client_pa && FD_ISSET(dns_sd_fd2, &readfds)) err = DNSServiceProcessResult(client_pa);
1334c65ebfc7SToomas Soome if (err) { printtimestamp_F(stderr); fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); stopNow = 1; }
13355ffb0c9bSToomas Soome }
13365ffb0c9bSToomas Soome else if (result == 0)
13375ffb0c9bSToomas Soome myTimerCallBack();
13385ffb0c9bSToomas Soome else
13395ffb0c9bSToomas Soome {
13405ffb0c9bSToomas Soome printf("select() returned %d errno %d %s\n", result, errno, strerror(errno));
13415ffb0c9bSToomas Soome if (errno != EINTR) stopNow = 1;
13425ffb0c9bSToomas Soome }
13435ffb0c9bSToomas Soome }
13445ffb0c9bSToomas Soome }
13455ffb0c9bSToomas Soome #endif
13465ffb0c9bSToomas Soome
getfirstoption(int argc,char ** argv,const char * optstr,int * pOptInd)13475ffb0c9bSToomas Soome static int getfirstoption(int argc, char **argv, const char *optstr, int *pOptInd)
13485ffb0c9bSToomas Soome // Return the recognized option in optstr and the option index of the next arg.
13495ffb0c9bSToomas Soome #if NOT_HAVE_GETOPT
13505ffb0c9bSToomas Soome {
13515ffb0c9bSToomas Soome int i;
13525ffb0c9bSToomas Soome for (i=1; i < argc; i++)
13535ffb0c9bSToomas Soome {
13545ffb0c9bSToomas Soome if (argv[i][0] == '-' && &argv[i][1] &&
13555ffb0c9bSToomas Soome NULL != strchr(optstr, argv[i][1]))
13565ffb0c9bSToomas Soome {
13575ffb0c9bSToomas Soome *pOptInd = i + 1;
13585ffb0c9bSToomas Soome return argv[i][1];
13595ffb0c9bSToomas Soome }
13605ffb0c9bSToomas Soome }
13615ffb0c9bSToomas Soome return -1;
13625ffb0c9bSToomas Soome }
13635ffb0c9bSToomas Soome #else
13645ffb0c9bSToomas Soome {
13655ffb0c9bSToomas Soome int o = getopt(argc, (char *const *)argv, optstr);
13665ffb0c9bSToomas Soome *pOptInd = optind;
13675ffb0c9bSToomas Soome return o;
13685ffb0c9bSToomas Soome }
13695ffb0c9bSToomas Soome #endif
13705ffb0c9bSToomas Soome
MyRegisterRecordCallback(DNSServiceRef service,DNSRecordRef rec,const DNSServiceFlags flags,DNSServiceErrorType errorCode,void * context)13715ffb0c9bSToomas Soome static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordRef rec, const DNSServiceFlags flags,
13725ffb0c9bSToomas Soome DNSServiceErrorType errorCode, void *context)
13735ffb0c9bSToomas Soome {
13745ffb0c9bSToomas Soome char *name = (char *)context;
13755ffb0c9bSToomas Soome
13765ffb0c9bSToomas Soome (void)service; // Unused
13775ffb0c9bSToomas Soome (void)rec; // Unused
13785ffb0c9bSToomas Soome (void)flags; // Unused
13795ffb0c9bSToomas Soome EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
13805ffb0c9bSToomas Soome
13815ffb0c9bSToomas Soome printtimestamp();
13825ffb0c9bSToomas Soome printf("Got a reply for record %s: ", name);
13835ffb0c9bSToomas Soome
13845ffb0c9bSToomas Soome switch (errorCode)
13855ffb0c9bSToomas Soome {
13865ffb0c9bSToomas Soome case kDNSServiceErr_NoError: printf("Name now registered and active\n"); break;
13875ffb0c9bSToomas Soome case kDNSServiceErr_NameConflict: printf("Name in use, please choose another\n"); exit(-1);
13885ffb0c9bSToomas Soome default: printf("Error %d\n", errorCode); break;
13895ffb0c9bSToomas Soome }
13905ffb0c9bSToomas Soome if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
13915ffb0c9bSToomas Soome }
13925ffb0c9bSToomas Soome
getip(const char * const name,struct sockaddr_storage * result)13935ffb0c9bSToomas Soome static void getip(const char *const name, struct sockaddr_storage *result)
13945ffb0c9bSToomas Soome {
13955ffb0c9bSToomas Soome struct addrinfo *addrs = NULL;
13965ffb0c9bSToomas Soome int err = getaddrinfo(name, NULL, NULL, &addrs);
13975ffb0c9bSToomas Soome if (err) fprintf(stderr, "getaddrinfo error %d for %s", err, name);
13985ffb0c9bSToomas Soome else memcpy(result, addrs->ai_addr, SA_LEN(addrs->ai_addr));
13995ffb0c9bSToomas Soome if (addrs) freeaddrinfo(addrs);
14005ffb0c9bSToomas Soome }
14015ffb0c9bSToomas Soome
RegisterProxyAddressRecord(DNSServiceRef sdref,const char * host,const char * ip,DNSServiceFlags flags)14025ffb0c9bSToomas Soome static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef sdref, const char *host, const char *ip, DNSServiceFlags flags)
14035ffb0c9bSToomas Soome {
14045ffb0c9bSToomas Soome // Call getip() after the call DNSServiceCreateConnection().
14055ffb0c9bSToomas Soome // On the Win32 platform, WinSock must be initialized for getip() to succeed.
14065ffb0c9bSToomas Soome // Any DNSService* call will initialize WinSock for us, so we make sure
14075ffb0c9bSToomas Soome // DNSServiceCreateConnection() is called before getip() is.
14085ffb0c9bSToomas Soome struct sockaddr_storage hostaddr;
1409cda73f64SToomas Soome memset(&hostaddr, 0, sizeof(hostaddr));
14105ffb0c9bSToomas Soome getip(ip, &hostaddr);
14115ffb0c9bSToomas Soome flags |= kDNSServiceFlagsUnique;
14125ffb0c9bSToomas Soome if (hostaddr.ss_family == AF_INET)
14135ffb0c9bSToomas Soome return(DNSServiceRegisterRecord(sdref, &record, flags, opinterface, host,
14145ffb0c9bSToomas Soome kDNSServiceType_A, kDNSServiceClass_IN, 4, &((struct sockaddr_in *)&hostaddr)->sin_addr, 240, MyRegisterRecordCallback, (void*)host));
14155ffb0c9bSToomas Soome else if (hostaddr.ss_family == AF_INET6)
14165ffb0c9bSToomas Soome return(DNSServiceRegisterRecord(sdref, &record, flags, opinterface, host,
14175ffb0c9bSToomas Soome kDNSServiceType_AAAA, kDNSServiceClass_IN, 16, &((struct sockaddr_in6*)&hostaddr)->sin6_addr, 240, MyRegisterRecordCallback, (void*)host));
14185ffb0c9bSToomas Soome else return(kDNSServiceErr_BadParam);
14195ffb0c9bSToomas Soome }
14205ffb0c9bSToomas Soome
14215ffb0c9bSToomas Soome #define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0' ) : \
14225ffb0c9bSToomas Soome ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) : \
14235ffb0c9bSToomas Soome ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : 0)
14245ffb0c9bSToomas Soome
14255ffb0c9bSToomas Soome #define HexPair(P) ((HexVal((P)[0]) << 4) | HexVal((P)[1]))
14265ffb0c9bSToomas Soome
1427*472cd20dSToomas Soome #define MAXTXTRecordSize 8900
RegisterService(DNSServiceRef * sdref,const char * nam,const char * typ,const char * dom,const char * host,const char * port,int argc,char ** argv,DNSServiceFlags flags)14285ffb0c9bSToomas Soome static DNSServiceErrorType RegisterService(DNSServiceRef *sdref,
14295ffb0c9bSToomas Soome const char *nam, const char *typ, const char *dom, const char *host, const char *port, int argc, char **argv, DNSServiceFlags flags)
14305ffb0c9bSToomas Soome {
14315ffb0c9bSToomas Soome uint16_t PortAsNumber = atoi(port);
14325ffb0c9bSToomas Soome Opaque16 registerPort = { { PortAsNumber >> 8, PortAsNumber & 0xFF } };
1433*472cd20dSToomas Soome unsigned char txt[MAXTXTRecordSize];
1434*472cd20dSToomas Soome txt[0] = '\0';
14355ffb0c9bSToomas Soome unsigned char *ptr = txt;
14365ffb0c9bSToomas Soome int i;
14375ffb0c9bSToomas Soome
14385ffb0c9bSToomas Soome if (nam[0] == '.' && nam[1] == 0) nam = ""; // We allow '.' on the command line as a synonym for empty string
14395ffb0c9bSToomas Soome if (dom[0] == '.' && dom[1] == 0) dom = ""; // We allow '.' on the command line as a synonym for empty string
14405ffb0c9bSToomas Soome
14415ffb0c9bSToomas Soome printf("Registering Service %s.%s%s%s", nam[0] ? nam : "<<Default>>", typ, dom[0] ? "." : "", dom);
14425ffb0c9bSToomas Soome if (host && *host) printf(" host %s", host);
14435ffb0c9bSToomas Soome printf(" port %s", port);
14445ffb0c9bSToomas Soome
14455ffb0c9bSToomas Soome if (argc)
14465ffb0c9bSToomas Soome {
14475ffb0c9bSToomas Soome for (i = 0; i < argc; i++)
14485ffb0c9bSToomas Soome {
14495ffb0c9bSToomas Soome const char *p = argv[i];
1450*472cd20dSToomas Soome if (ptr >= txt + sizeof(txt))
1451*472cd20dSToomas Soome return kDNSServiceErr_BadParam;
14525ffb0c9bSToomas Soome *ptr = 0;
1453*472cd20dSToomas Soome while (*p && *ptr < 255)
14545ffb0c9bSToomas Soome {
1455*472cd20dSToomas Soome if (ptr + 1 + *ptr >= txt + sizeof(txt))
1456*472cd20dSToomas Soome return kDNSServiceErr_BadParam;
14575ffb0c9bSToomas Soome if (p[0] != '\\' || p[1] == 0) { ptr[++*ptr] = *p; p+=1; }
14585ffb0c9bSToomas Soome else if (p[1] == 'x' && isxdigit(p[2]) && isxdigit(p[3])) { ptr[++*ptr] = HexPair(p+2); p+=4; }
14595ffb0c9bSToomas Soome else { ptr[++*ptr] = p[1]; p+=2; }
14605ffb0c9bSToomas Soome }
14615ffb0c9bSToomas Soome ptr += 1 + *ptr;
14625ffb0c9bSToomas Soome }
14635ffb0c9bSToomas Soome printf(" TXT");
14645ffb0c9bSToomas Soome ShowTXTRecord(ptr-txt, txt);
14655ffb0c9bSToomas Soome }
14665ffb0c9bSToomas Soome printf("\n");
14675ffb0c9bSToomas Soome
14685ffb0c9bSToomas Soome //flags |= kDNSServiceFlagsAllowRemoteQuery;
14695ffb0c9bSToomas Soome //flags |= kDNSServiceFlagsNoAutoRename;
14705ffb0c9bSToomas Soome
14715ffb0c9bSToomas Soome return(DNSServiceRegister(sdref, flags, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, (uint16_t) (ptr-txt), txt, reg_reply, NULL));
14725ffb0c9bSToomas Soome }
14735ffb0c9bSToomas Soome
14745ffb0c9bSToomas Soome #define TypeBufferSize 80
gettype(char * buffer,char * typ)14755ffb0c9bSToomas Soome static char *gettype(char *buffer, char *typ)
14765ffb0c9bSToomas Soome {
14775ffb0c9bSToomas Soome if (!typ || !*typ || (typ[0] == '.' && typ[1] == 0)) typ = "_http._tcp";
14785ffb0c9bSToomas Soome if (!strchr(typ, '.')) { snprintf(buffer, TypeBufferSize, "%s._tcp", typ); typ = buffer; }
14795ffb0c9bSToomas Soome return(typ);
14805ffb0c9bSToomas Soome }
14815ffb0c9bSToomas Soome
1482c65ebfc7SToomas Soome // Do some basic tests to verify API handles > 63 byte strings gracefully with
1483c65ebfc7SToomas Soome // a returned error code.
1484c65ebfc7SToomas Soome
1485c65ebfc7SToomas Soome #define STRING_64_BYTES "_123456789012345678901234567890123456789012345678901234567890123"
1486c65ebfc7SToomas Soome
API_string_limit_test()1487c65ebfc7SToomas Soome static int API_string_limit_test()
14885ffb0c9bSToomas Soome {
1489c65ebfc7SToomas Soome const char * regtype;
1490c65ebfc7SToomas Soome DNSServiceRef sdRef = NULL;
1491c65ebfc7SToomas Soome const char * longHost = STRING_64_BYTES ".local";
1492c65ebfc7SToomas Soome const char * longDomain = "hostname." STRING_64_BYTES;
14935ffb0c9bSToomas Soome
1494c65ebfc7SToomas Soome printf("Testing for error returns when various strings are > 63 bytes.\n");
14955ffb0c9bSToomas Soome
1496c65ebfc7SToomas Soome printf("DNSServiceGetAddrInfo(), hostname = %s\n", longHost);
1497c65ebfc7SToomas Soome if (DNSServiceGetAddrInfo(&sdRef, 0, 0, 0, longHost, addrinfo_reply, 0) == 0)
1498c65ebfc7SToomas Soome {
1499c65ebfc7SToomas Soome printf("DNSServiceGetAddrInfo(): expected error return\n");
1500c65ebfc7SToomas Soome return 1;
1501c65ebfc7SToomas Soome };
15025ffb0c9bSToomas Soome
1503c65ebfc7SToomas Soome printf("DNSServiceGetAddrInfo(), hostname = %s\n", longDomain);
1504c65ebfc7SToomas Soome if (DNSServiceGetAddrInfo(&sdRef, 0, 0, 0, longDomain, addrinfo_reply, 0) == 0)
1505c65ebfc7SToomas Soome {
1506c65ebfc7SToomas Soome printf("DNSServiceGetAddrInfo(): expected error return\n");
1507c65ebfc7SToomas Soome return 1;
1508c65ebfc7SToomas Soome };
1509c65ebfc7SToomas Soome
1510c65ebfc7SToomas Soome printf("DNSServiceResolve(), name = %s\n", STRING_64_BYTES);
1511c65ebfc7SToomas Soome if (DNSServiceResolve(&sdRef, 0, 0, STRING_64_BYTES, "_test._tcp", "local", resolve_reply, NULL) == 0)
1512c65ebfc7SToomas Soome {
1513c65ebfc7SToomas Soome printf("DNSServiceResolve(): expected error return\n");
1514c65ebfc7SToomas Soome return 1;
1515c65ebfc7SToomas Soome };
1516c65ebfc7SToomas Soome
1517c65ebfc7SToomas Soome regtype = STRING_64_BYTES "._tcp";
1518c65ebfc7SToomas Soome printf("DNSServiceResolve(), regtype = %s\n", regtype);
1519c65ebfc7SToomas Soome if (DNSServiceResolve(&sdRef, 0, 0, "instanceName", regtype, "local", resolve_reply, NULL) == 0)
1520c65ebfc7SToomas Soome {
1521c65ebfc7SToomas Soome printf("DNSServiceResolve(): expected error return\n");
1522c65ebfc7SToomas Soome return 1;
1523c65ebfc7SToomas Soome };
1524c65ebfc7SToomas Soome
1525c65ebfc7SToomas Soome printf("DNSServiceResolve(), domain = %s\n", STRING_64_BYTES);
1526c65ebfc7SToomas Soome if (DNSServiceResolve(&sdRef, 0, 0, "instanceName", "_test._tcp", STRING_64_BYTES, resolve_reply, NULL) == 0)
1527c65ebfc7SToomas Soome {
1528c65ebfc7SToomas Soome printf("DNSServiceResolve(): expected error return\n");
1529c65ebfc7SToomas Soome return 1;
1530c65ebfc7SToomas Soome };
1531c65ebfc7SToomas Soome
1532c65ebfc7SToomas Soome printf("Testing for error returns when various strings are > 63 bytes: PASSED\n");
1533c65ebfc7SToomas Soome return 0;
1534c65ebfc7SToomas Soome }
1535c65ebfc7SToomas Soome
API_NULL_input_test()1536c65ebfc7SToomas Soome static int API_NULL_input_test()
1537c65ebfc7SToomas Soome {
1538c65ebfc7SToomas Soome printf("Running basic API input range tests with various pointer parameters set to NULL:\n");
1539c65ebfc7SToomas Soome
1540c65ebfc7SToomas Soome // Test that API's handle NULL pointers by returning an error when appropriate.
1541c65ebfc7SToomas Soome
1542c65ebfc7SToomas Soome // DNSServiceRefSockFD()
1543c65ebfc7SToomas Soome if (DNSServiceRefSockFD(0) != -1)
1544c65ebfc7SToomas Soome {
1545c65ebfc7SToomas Soome printf("DNSServiceRefSockFD(): expected dnssd_InvalidSocket return\n");
1546c65ebfc7SToomas Soome return 1;
1547c65ebfc7SToomas Soome }
15485ffb0c9bSToomas Soome
1549c65ebfc7SToomas Soome // DNSServiceProcessResult()
1550c65ebfc7SToomas Soome if (DNSServiceProcessResult(0) == 0)
15515ffb0c9bSToomas Soome {
1552c65ebfc7SToomas Soome printf("DNSServiceProcessResult(): expected error return\n");
1553c65ebfc7SToomas Soome return 1;
15545ffb0c9bSToomas Soome }
15555ffb0c9bSToomas Soome
1556c65ebfc7SToomas Soome // DNSServiceRefDeallocate(): no return value, just verify it doesn't crash
1557c65ebfc7SToomas Soome DNSServiceRefDeallocate(0);
1558c65ebfc7SToomas Soome
1559c65ebfc7SToomas Soome // DNSServiceGetProperty()
15605ffb0c9bSToomas Soome {
1561c65ebfc7SToomas Soome uint32_t result;
1562c65ebfc7SToomas Soome uint32_t size;
1563c65ebfc7SToomas Soome
1564c65ebfc7SToomas Soome if ( (DNSServiceGetProperty( 0, &result, &size) == 0)
1565c65ebfc7SToomas Soome || (DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, 0, &size) == 0)
1566c65ebfc7SToomas Soome || (DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &result, 0) == 0)
1567c65ebfc7SToomas Soome )
1568c65ebfc7SToomas Soome {
1569c65ebfc7SToomas Soome printf("DNSServiceGetProperty(): expected error return\n");
1570c65ebfc7SToomas Soome return 1;
1571c65ebfc7SToomas Soome }
15725ffb0c9bSToomas Soome }
15735ffb0c9bSToomas Soome
1574c65ebfc7SToomas Soome // DNSServiceResolve()
15755ffb0c9bSToomas Soome {
1576c65ebfc7SToomas Soome DNSServiceRef sdRef;
1577c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1578c65ebfc7SToomas Soome uint32_t interfaceIndex = 0;
1579c65ebfc7SToomas Soome const char *name = "name";
1580c65ebfc7SToomas Soome const char *regtype = "_test._tcp";
1581c65ebfc7SToomas Soome const char *domain = "local";
1582c65ebfc7SToomas Soome DNSServiceResolveReply callBack = 0;
1583c65ebfc7SToomas Soome void *context = 0; // can be a NULL pointer
1584c65ebfc7SToomas Soome
1585c65ebfc7SToomas Soome if ( (DNSServiceResolve( 0, flags, interfaceIndex, name, regtype, domain, callBack, context) == 0)
1586c65ebfc7SToomas Soome || (DNSServiceResolve(&sdRef, flags, interfaceIndex, 0, regtype, domain, callBack, context) == 0)
1587c65ebfc7SToomas Soome || (DNSServiceResolve(&sdRef, flags, interfaceIndex, name, 0, domain, callBack, context) == 0)
1588c65ebfc7SToomas Soome || (DNSServiceResolve(&sdRef, flags, interfaceIndex, name, regtype, 0, callBack, context) == 0)
1589c65ebfc7SToomas Soome || (DNSServiceResolve(&sdRef, flags, interfaceIndex, name, regtype, domain, callBack, context) == 0)
1590c65ebfc7SToomas Soome )
1591c65ebfc7SToomas Soome {
1592c65ebfc7SToomas Soome printf("DNSServiceResolve(): expected error return\n");
1593c65ebfc7SToomas Soome return 1;
1594c65ebfc7SToomas Soome }
15955ffb0c9bSToomas Soome }
15965ffb0c9bSToomas Soome
1597c65ebfc7SToomas Soome // DNSServiceQueryRecord()
15985ffb0c9bSToomas Soome {
1599c65ebfc7SToomas Soome DNSServiceRef sdRef;
1600c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1601c65ebfc7SToomas Soome uint32_t interfaceIndex = 0;
1602c65ebfc7SToomas Soome const char *fullname = "fullname";
1603c65ebfc7SToomas Soome uint16_t rrtype = 0;
1604c65ebfc7SToomas Soome uint16_t rrclass = 0;
1605c65ebfc7SToomas Soome DNSServiceQueryRecordReply callBack = 0;
1606c65ebfc7SToomas Soome void *context = 0; /* may be NULL */
1607c65ebfc7SToomas Soome
1608c65ebfc7SToomas Soome if ( (DNSServiceQueryRecord( 0, flags, interfaceIndex, fullname, rrtype, rrclass, callBack, context) == 0)
1609c65ebfc7SToomas Soome || (DNSServiceQueryRecord(&sdRef, flags, interfaceIndex, 0, rrtype, rrclass, callBack, context) == 0)
1610c65ebfc7SToomas Soome || (DNSServiceQueryRecord(&sdRef, flags, interfaceIndex, fullname, rrtype, rrclass, 0, context) == 0)
1611c65ebfc7SToomas Soome )
1612c65ebfc7SToomas Soome {
1613c65ebfc7SToomas Soome printf("DNSServiceQueryRecord(): expected error return\n");
1614c65ebfc7SToomas Soome return 1;
1615c65ebfc7SToomas Soome }
16165ffb0c9bSToomas Soome }
16175ffb0c9bSToomas Soome
1618c65ebfc7SToomas Soome // DNSServiceGetAddrInfo()
16195ffb0c9bSToomas Soome {
1620c65ebfc7SToomas Soome DNSServiceRef sdRef;
1621c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1622c65ebfc7SToomas Soome uint32_t interfaceIndex = 0;
1623c65ebfc7SToomas Soome DNSServiceProtocol protocol = kDNSServiceProtocol_IPv4|kDNSServiceProtocol_IPv6;
1624c65ebfc7SToomas Soome const char *hostname = "host.local";
1625c65ebfc7SToomas Soome DNSServiceGetAddrInfoReply callBack = 0;
1626c65ebfc7SToomas Soome void *context = 0; // may be NULL
1627c65ebfc7SToomas Soome
1628c65ebfc7SToomas Soome if ( (DNSServiceGetAddrInfo( 0, flags, interfaceIndex, protocol, hostname, callBack, context) == 0)
1629c65ebfc7SToomas Soome || (DNSServiceGetAddrInfo(&sdRef, flags, interfaceIndex, protocol, 0, callBack, context) == 0)
1630c65ebfc7SToomas Soome || (DNSServiceGetAddrInfo(&sdRef, flags, interfaceIndex, protocol, hostname, 0, context) == 0)
1631c65ebfc7SToomas Soome )
1632c65ebfc7SToomas Soome {
1633c65ebfc7SToomas Soome printf("DNSServiceGetAddrInfo(): expected error return\n");
1634c65ebfc7SToomas Soome return 1;
1635c65ebfc7SToomas Soome }
16365ffb0c9bSToomas Soome }
16375ffb0c9bSToomas Soome
1638c65ebfc7SToomas Soome // DNSServiceBrowse()
16395ffb0c9bSToomas Soome {
1640c65ebfc7SToomas Soome DNSServiceRef sdRef;
1641c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1642c65ebfc7SToomas Soome uint32_t interfaceIndex = 0;
1643c65ebfc7SToomas Soome const char *regtype = "_test._tcp";
1644c65ebfc7SToomas Soome const char *domain = 0; /* may be NULL */
1645c65ebfc7SToomas Soome DNSServiceBrowseReply callBack = 0;
1646c65ebfc7SToomas Soome void *context = 0; /* may be NULL */
1647c65ebfc7SToomas Soome
1648c65ebfc7SToomas Soome if ( (DNSServiceBrowse( 0, flags, interfaceIndex, regtype, domain, callBack, context) == 0)
1649c65ebfc7SToomas Soome || (DNSServiceBrowse(&sdRef, flags, interfaceIndex, 0, domain, callBack, context) == 0)
1650c65ebfc7SToomas Soome || (DNSServiceBrowse(&sdRef, flags, interfaceIndex, regtype, domain, 0, context) == 0)
1651c65ebfc7SToomas Soome )
1652c65ebfc7SToomas Soome {
1653c65ebfc7SToomas Soome printf("DNSServiceBrowse(): expected error return\n");
1654c65ebfc7SToomas Soome return 1;
1655c65ebfc7SToomas Soome }
16565ffb0c9bSToomas Soome }
16575ffb0c9bSToomas Soome
1658c65ebfc7SToomas Soome #if APPLE_OSX_mDNSResponder
1659c65ebfc7SToomas Soome // DNSServiceSetDefaultDomainForUser()
1660c65ebfc7SToomas Soome if (DNSServiceSetDefaultDomainForUser(0, 0) == 0)
1661c65ebfc7SToomas Soome {
1662c65ebfc7SToomas Soome printf("DNSServiceSetDefaultDomainForUser(): expected error return\n");
1663c65ebfc7SToomas Soome return 1;
1664c65ebfc7SToomas Soome }
1665c65ebfc7SToomas Soome #endif
1666c65ebfc7SToomas Soome
1667c65ebfc7SToomas Soome // DNSServiceRegister()
16685ffb0c9bSToomas Soome {
1669c65ebfc7SToomas Soome DNSServiceRef sdRef;
1670c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1671c65ebfc7SToomas Soome uint32_t interfaceIndex = 0;
1672c65ebfc7SToomas Soome const char *name = 0; /* may be NULL */
1673c65ebfc7SToomas Soome const char *regtype = "_test._tcp";
1674c65ebfc7SToomas Soome const char *domain = 0; /* may be NULL */
1675c65ebfc7SToomas Soome const char *host = 0; /* may be NULL */
1676c65ebfc7SToomas Soome uint16_t port = 0x2211; /* In network byte order */
1677c65ebfc7SToomas Soome uint16_t txtLen = 1;
1678c65ebfc7SToomas Soome const void *txtRecord = "\0"; /* may be NULL */
1679c65ebfc7SToomas Soome DNSServiceRegisterReply callBack = 0; /* may be NULL */
1680c65ebfc7SToomas Soome void *context = 0; /* may be NULL */
1681c65ebfc7SToomas Soome
1682c65ebfc7SToomas Soome if ( (DNSServiceRegister( 0, flags, interfaceIndex, name, regtype, domain, host, port, txtLen, txtRecord, callBack, context) == 0)
1683c65ebfc7SToomas Soome || (DNSServiceRegister(&sdRef, flags, interfaceIndex, name, 0, domain, host, port, txtLen, txtRecord, callBack, context) == 0)
1684c65ebfc7SToomas Soome )
1685c65ebfc7SToomas Soome {
1686c65ebfc7SToomas Soome printf("DNSServiceRegister(): expected error return\n");
1687c65ebfc7SToomas Soome return 1;
1688c65ebfc7SToomas Soome }
16895ffb0c9bSToomas Soome }
16905ffb0c9bSToomas Soome
1691c65ebfc7SToomas Soome // DNSServiceEnumerateDomains()
16925ffb0c9bSToomas Soome {
1693c65ebfc7SToomas Soome DNSServiceRef sdRef;
1694c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1695c65ebfc7SToomas Soome uint32_t interfaceIndex = 0;
1696c65ebfc7SToomas Soome DNSServiceDomainEnumReply callBack = 0;
1697c65ebfc7SToomas Soome void *context = 0; /* may be NULL */
1698c65ebfc7SToomas Soome
1699c65ebfc7SToomas Soome if ( (DNSServiceEnumerateDomains( 0, flags, interfaceIndex, callBack, context) == 0)
1700c65ebfc7SToomas Soome || (DNSServiceEnumerateDomains(&sdRef, flags, interfaceIndex, 0, context) == 0)
1701c65ebfc7SToomas Soome )
1702c65ebfc7SToomas Soome {
1703c65ebfc7SToomas Soome printf("DNSServiceEnumerateDomains(): expected error return\n");
1704c65ebfc7SToomas Soome return 1;
1705c65ebfc7SToomas Soome }
17065ffb0c9bSToomas Soome }
17075ffb0c9bSToomas Soome
1708c65ebfc7SToomas Soome // DNSServiceCreateConnection()
1709c65ebfc7SToomas Soome if (DNSServiceCreateConnection(0) == 0)
17105ffb0c9bSToomas Soome {
1711c65ebfc7SToomas Soome printf("DNSServiceCreateConnection(): expected error return\n");
1712c65ebfc7SToomas Soome return 1;
17135ffb0c9bSToomas Soome }
1714c65ebfc7SToomas Soome
1715c65ebfc7SToomas Soome #if APPLE_OSX_mDNSResponder
1716c65ebfc7SToomas Soome // DNSServiceCreateDelegateConnection()
1717c65ebfc7SToomas Soome if (DNSServiceCreateDelegateConnection(0, 0, 0) == 0)
17185ffb0c9bSToomas Soome {
1719c65ebfc7SToomas Soome printf("DNSServiceCreateDelegateConnection(): expected error return\n");
1720c65ebfc7SToomas Soome return 1;
17215ffb0c9bSToomas Soome }
1722c65ebfc7SToomas Soome #endif
1723c65ebfc7SToomas Soome
1724c65ebfc7SToomas Soome // DNSServiceRegisterRecord()
17255ffb0c9bSToomas Soome {
1726c65ebfc7SToomas Soome DNSServiceRef sdRef;
1727c65ebfc7SToomas Soome DNSRecordRef RecordRef;
1728c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1729c65ebfc7SToomas Soome uint32_t interfaceIndex = 0;
1730c65ebfc7SToomas Soome const char *fullname = "test1._test._tcp.local";
1731c65ebfc7SToomas Soome uint16_t rrtype = kDNSServiceType_TXT;
1732c65ebfc7SToomas Soome uint16_t rrclass = kDNSServiceClass_IN;
1733c65ebfc7SToomas Soome uint16_t rdlen = 1;
1734c65ebfc7SToomas Soome const void *rdata = "\0";
1735c65ebfc7SToomas Soome uint32_t ttl = 0;
1736c65ebfc7SToomas Soome DNSServiceRegisterRecordReply callBack = 0;
1737c65ebfc7SToomas Soome void *context = 0; /* may be NULL */
1738c65ebfc7SToomas Soome
1739c65ebfc7SToomas Soome // Need an initialize sdRef
1740c65ebfc7SToomas Soome if (DNSServiceCreateConnection(&sdRef))
1741c65ebfc7SToomas Soome {
1742c65ebfc7SToomas Soome printf("DNSServiceCreateConnection(): failed\n");
1743c65ebfc7SToomas Soome return 1;
1744c65ebfc7SToomas Soome }
1745c65ebfc7SToomas Soome
1746c65ebfc7SToomas Soome if ( (DNSServiceRegisterRecord( 0, &RecordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata, ttl, callBack, context) == 0)
1747c65ebfc7SToomas Soome || (DNSServiceRegisterRecord(sdRef, &RecordRef, flags, interfaceIndex, 0, rrtype, rrclass, rdlen, rdata, ttl, callBack, context) == 0)
1748c65ebfc7SToomas Soome || (DNSServiceRegisterRecord(sdRef, &RecordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, 0, ttl, callBack, context) == 0)
1749c65ebfc7SToomas Soome || (DNSServiceRegisterRecord(sdRef, &RecordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata, ttl, 0, context) == 0)
1750c65ebfc7SToomas Soome )
1751c65ebfc7SToomas Soome {
1752c65ebfc7SToomas Soome printf("DNSServiceRegisterRecord(): expected error return\n");
1753c65ebfc7SToomas Soome return 1;
1754c65ebfc7SToomas Soome }
17555ffb0c9bSToomas Soome }
17565ffb0c9bSToomas Soome
1757c65ebfc7SToomas Soome // DNSServiceAddRecord(), DNSServiceUpdateRecord(), and DNSServiceRemoveRecord() verify that they
1758c65ebfc7SToomas Soome // get a valid DNSServiceRef returned from DNSServiceRegister()
1759c65ebfc7SToomas Soome {
1760c65ebfc7SToomas Soome DNSServiceErrorType err;
1761c65ebfc7SToomas Soome Opaque16 registerPort = { { 0x12, 0x34 } };
1762c65ebfc7SToomas Soome static const char TXT[] = "\xC" "First String";
1763c65ebfc7SToomas Soome DNSServiceRef sdRef;
1764c65ebfc7SToomas Soome
1765c65ebfc7SToomas Soome DNSRecordRef RecordRef;
1766c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1767c65ebfc7SToomas Soome uint16_t rrtype = kDNSServiceType_TXT;
1768c65ebfc7SToomas Soome uint16_t rdlen = 1;
1769c65ebfc7SToomas Soome const void *rdata = "\0";
1770c65ebfc7SToomas Soome uint32_t ttl = 100;
1771c65ebfc7SToomas Soome
1772c65ebfc7SToomas Soome err = DNSServiceRegister(&sdRef, 0, 0, "Test", "_test._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL);
1773c65ebfc7SToomas Soome if (err)
1774c65ebfc7SToomas Soome {
1775c65ebfc7SToomas Soome printf("DNSServiceRegister() failed with: %d\n", err);
1776c65ebfc7SToomas Soome return 1;
1777c65ebfc7SToomas Soome }
1778c65ebfc7SToomas Soome
1779c65ebfc7SToomas Soome // DNSServiceAddRecord()
1780c65ebfc7SToomas Soome if ( (DNSServiceAddRecord( 0, &RecordRef, flags, rrtype, rdlen, rdata, ttl) == 0)
1781c65ebfc7SToomas Soome || (DNSServiceAddRecord(sdRef, 0, flags, rrtype, rdlen, rdata, ttl) == 0)
1782c65ebfc7SToomas Soome || (DNSServiceAddRecord(sdRef, &RecordRef, flags, rrtype, rdlen, 0, ttl) == 0)
1783c65ebfc7SToomas Soome )
1784c65ebfc7SToomas Soome
1785c65ebfc7SToomas Soome {
1786c65ebfc7SToomas Soome printf("DNSServiceAddRecord(): expected error return\n");
1787c65ebfc7SToomas Soome return 1;
1788c65ebfc7SToomas Soome }
1789c65ebfc7SToomas Soome
1790c65ebfc7SToomas Soome // (rdlen == 0 && rdata == 0) should indicate a TXT with rdata containing only a 0 length byte.
1791c65ebfc7SToomas Soome if (DNSServiceAddRecord(sdRef, &RecordRef, flags, rrtype, 0, 0, ttl) == kDNSServiceErr_BadParam)
1792c65ebfc7SToomas Soome {
1793c65ebfc7SToomas Soome printf("DNSServiceAddRecord(): with (rdlen == 0 && rdata == 0) returned kDNSServiceErr_BadParam\n");
1794c65ebfc7SToomas Soome return 1;
1795c65ebfc7SToomas Soome }
1796c65ebfc7SToomas Soome
1797c65ebfc7SToomas Soome // DNSServiceUpdateRecord()
1798c65ebfc7SToomas Soome // Note, RecordRef can be NULL per explanation with declaration in dns_sd.h
1799c65ebfc7SToomas Soome if ( (DNSServiceUpdateRecord( 0, RecordRef, flags, rdlen, rdata, ttl) == 0)
1800c65ebfc7SToomas Soome || (DNSServiceUpdateRecord(sdRef, RecordRef, flags, rdlen, 0, ttl) == 0)
1801c65ebfc7SToomas Soome )
1802c65ebfc7SToomas Soome {
1803c65ebfc7SToomas Soome printf("DNSServiceUpdateRecord(): expected error return\n");
1804c65ebfc7SToomas Soome return 1;
1805c65ebfc7SToomas Soome }
1806c65ebfc7SToomas Soome
1807c65ebfc7SToomas Soome // (rdlen == 0 && rdata == 0) should indicate a TXT with rdata containing only a 0 length byte.
1808c65ebfc7SToomas Soome if (DNSServiceUpdateRecord(sdRef, RecordRef, flags, 0, 0, ttl) == kDNSServiceErr_BadParam)
1809c65ebfc7SToomas Soome {
1810c65ebfc7SToomas Soome printf("DNSServiceUpdateRecord(): with (rdlen == 0 && rdata == 0) returned kDNSServiceErr_BadParam\n");
1811c65ebfc7SToomas Soome return 1;
1812c65ebfc7SToomas Soome }
1813c65ebfc7SToomas Soome
1814c65ebfc7SToomas Soome // DNSServiceRemoveRecord()
1815c65ebfc7SToomas Soome if ( (DNSServiceRemoveRecord( 0, RecordRef, flags) == 0)
1816c65ebfc7SToomas Soome || (DNSServiceRemoveRecord(sdRef, 0, flags) == 0)
1817c65ebfc7SToomas Soome )
1818c65ebfc7SToomas Soome {
1819c65ebfc7SToomas Soome printf("DNSServiceRemoveRecord(): expected error return\n");
1820c65ebfc7SToomas Soome return 1;
1821c65ebfc7SToomas Soome }
1822c65ebfc7SToomas Soome
1823c65ebfc7SToomas Soome DNSServiceRefDeallocate(sdRef);
1824c65ebfc7SToomas Soome }
1825c65ebfc7SToomas Soome
1826c65ebfc7SToomas Soome // DNSServiceReconfirmRecord()
1827c65ebfc7SToomas Soome {
1828c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1829c65ebfc7SToomas Soome uint32_t interfaceIndex = 0;
1830c65ebfc7SToomas Soome const char *fullname = "aaa._test._tcp.local";
1831c65ebfc7SToomas Soome uint16_t rrtype = kDNSServiceType_TXT;
1832c65ebfc7SToomas Soome uint16_t rrclass = kDNSServiceClass_IN;
1833c65ebfc7SToomas Soome uint16_t rdlen = 1;
1834c65ebfc7SToomas Soome const void *rdata = "\0";
1835c65ebfc7SToomas Soome
1836c65ebfc7SToomas Soome if ( (DNSServiceReconfirmRecord(flags, interfaceIndex, 0, rrtype, rrclass, rdlen, rdata) == 0)
1837c65ebfc7SToomas Soome || (DNSServiceReconfirmRecord(flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, 0) == 0)
1838c65ebfc7SToomas Soome )
1839c65ebfc7SToomas Soome {
1840c65ebfc7SToomas Soome printf("DNSServiceReconfirmRecord(): expected error return\n");
1841c65ebfc7SToomas Soome return 1;
1842c65ebfc7SToomas Soome }
1843c65ebfc7SToomas Soome // (rdlen == 0 && rdata == 0) should indicate a TXT with rdata containing only a 0 length byte.
1844c65ebfc7SToomas Soome if (DNSServiceReconfirmRecord(flags, interfaceIndex, fullname, rrtype, rrclass, 0, 0) == kDNSServiceErr_BadParam)
1845c65ebfc7SToomas Soome {
1846c65ebfc7SToomas Soome printf("DNSServiceReconfirmRecord(): with (rdlen == 0 && rdata == 0) returned kDNSServiceErr_BadParam\n");
1847c65ebfc7SToomas Soome return 1;
1848c65ebfc7SToomas Soome }
1849c65ebfc7SToomas Soome }
1850c65ebfc7SToomas Soome
1851c65ebfc7SToomas Soome
1852c65ebfc7SToomas Soome printf("Basic API input range tests: PASSED\n");
1853c65ebfc7SToomas Soome return 0;
1854c65ebfc7SToomas Soome }
1855c65ebfc7SToomas Soome
API_input_range_test()1856c65ebfc7SToomas Soome static int API_input_range_test()
1857c65ebfc7SToomas Soome {
1858c65ebfc7SToomas Soome
1859c65ebfc7SToomas Soome if (API_string_limit_test())
1860c65ebfc7SToomas Soome return 1;
1861c65ebfc7SToomas Soome
1862c65ebfc7SToomas Soome if (API_NULL_input_test())
1863c65ebfc7SToomas Soome return 1;
1864c65ebfc7SToomas Soome
1865c65ebfc7SToomas Soome return 0;
1866c65ebfc7SToomas Soome }
1867c65ebfc7SToomas Soome
1868*472cd20dSToomas Soome #ifdef APPLE_OSX_mDNSResponder
1869*472cd20dSToomas Soome static void handle_state_dump_request(uint8_t if_compress_state_dump, uint8_t if_dump_to_stdout);
1870*472cd20dSToomas Soome #endif // APPLE_OSX_mDNSResponder
main(int argc,char ** argv)1871c65ebfc7SToomas Soome int main(int argc, char **argv)
1872c65ebfc7SToomas Soome {
1873c65ebfc7SToomas Soome DNSServiceErrorType err;
1874c65ebfc7SToomas Soome char buffer[TypeBufferSize], *typ, *dom;
1875c65ebfc7SToomas Soome int opi;
1876c65ebfc7SToomas Soome DNSServiceFlags flags = 0;
1877*472cd20dSToomas Soome unsigned char enable_dnssec = 0;
1878c65ebfc7SToomas Soome
1879c65ebfc7SToomas Soome // Extract the program name from argv[0], which by convention contains the path to this executable.
1880c65ebfc7SToomas Soome // Note that this is just a voluntary convention, not enforced by the kernel --
1881c65ebfc7SToomas Soome // the process calling exec() can pass bogus data in argv[0] if it chooses to.
1882c65ebfc7SToomas Soome const char *a0 = strrchr(argv[0], kFilePathSep) + 1;
1883c65ebfc7SToomas Soome if (a0 == (const char *)1) a0 = argv[0];
1884c65ebfc7SToomas Soome
1885c65ebfc7SToomas Soome #if defined(_WIN32)
1886c65ebfc7SToomas Soome HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
1887c65ebfc7SToomas Soome #endif
1888c65ebfc7SToomas Soome
1889c65ebfc7SToomas Soome #if TEST_NEW_CLIENTSTUB
1890c65ebfc7SToomas Soome printf("Using embedded copy of dnssd_clientstub instead of system library\n");
1891c65ebfc7SToomas Soome if (sizeof(argv) == 8) printf("Running in 64-bit mode\n");
1892c65ebfc7SToomas Soome #endif
1893c65ebfc7SToomas Soome
1894c65ebfc7SToomas Soome // Test code for TXTRecord functions
1895c65ebfc7SToomas Soome //TXTRecordRef txtRecord;
1896c65ebfc7SToomas Soome //TXTRecordCreate(&txtRecord, 0, NULL);
1897c65ebfc7SToomas Soome //TXTRecordSetValue(&txtRecord, "aaa", 1, "b");
1898c65ebfc7SToomas Soome //printf("%d\n", TXTRecordContainsKey(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), "Aaa"));
1899c65ebfc7SToomas Soome
1900c65ebfc7SToomas Soome while (argc > 1)
19015ffb0c9bSToomas Soome {
1902c65ebfc7SToomas Soome int entryCount;
1903c65ebfc7SToomas Soome
1904c65ebfc7SToomas Soome // record current argc to see if we process an argument in this pass
1905c65ebfc7SToomas Soome entryCount = argc;
1906c65ebfc7SToomas Soome
1907c65ebfc7SToomas Soome if (argc > 1 && !strcmp(argv[1], "-test"))
1908c65ebfc7SToomas Soome {
1909c65ebfc7SToomas Soome argc--;
1910c65ebfc7SToomas Soome argv++;
1911c65ebfc7SToomas Soome return API_input_range_test();
1912c65ebfc7SToomas Soome }
1913c65ebfc7SToomas Soome
1914c65ebfc7SToomas Soome if (argc > 1 && !strcmp(argv[1], "-lo"))
1915c65ebfc7SToomas Soome {
1916c65ebfc7SToomas Soome argc--;
1917c65ebfc7SToomas Soome argv++;
1918c65ebfc7SToomas Soome opinterface = kDNSServiceInterfaceIndexLocalOnly;
1919c65ebfc7SToomas Soome printf("Using LocalOnly\n");
1920c65ebfc7SToomas Soome }
1921c65ebfc7SToomas Soome
1922c65ebfc7SToomas Soome if (argc > 1 && (!strcasecmp(argv[1], "-p2p")))
1923c65ebfc7SToomas Soome {
1924c65ebfc7SToomas Soome argc--;
1925c65ebfc7SToomas Soome argv++;
1926c65ebfc7SToomas Soome opinterface = kDNSServiceInterfaceIndexP2P;
1927c65ebfc7SToomas Soome }
1928c65ebfc7SToomas Soome
1929c65ebfc7SToomas Soome if (argc > 1 && (!strcasecmp(argv[1], "-ble")))
1930c65ebfc7SToomas Soome {
1931c65ebfc7SToomas Soome argc--;
1932c65ebfc7SToomas Soome argv++;
1933c65ebfc7SToomas Soome opinterface = kDNSServiceInterfaceIndexBLE;
1934c65ebfc7SToomas Soome }
19353b436d06SToomas Soome
19363b436d06SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-allowexpired"))
19373b436d06SToomas Soome {
19383b436d06SToomas Soome argc--;
19393b436d06SToomas Soome argv++;
19403b436d06SToomas Soome flags |= kDNSServiceFlagsAllowExpiredAnswers;
19413b436d06SToomas Soome printf("Setting kDNSServiceFlagsAllowExpiredAnswers\n");
19423b436d06SToomas Soome }
19433b436d06SToomas Soome
1944c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-includep2p"))
1945c65ebfc7SToomas Soome {
1946c65ebfc7SToomas Soome argc--;
1947c65ebfc7SToomas Soome argv++;
1948c65ebfc7SToomas Soome flags |= kDNSServiceFlagsIncludeP2P;
1949c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsIncludeP2P\n");
1950c65ebfc7SToomas Soome }
1951c65ebfc7SToomas Soome
1952c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-fmc"))
1953c65ebfc7SToomas Soome {
1954c65ebfc7SToomas Soome argc--;
1955c65ebfc7SToomas Soome argv++;
1956c65ebfc7SToomas Soome flags |= kDNSServiceFlagsForceMulticast;
1957c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsForceMulticast flag for this request\n");
1958c65ebfc7SToomas Soome }
1959c65ebfc7SToomas Soome
1960c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-includeAWDL"))
1961c65ebfc7SToomas Soome {
1962c65ebfc7SToomas Soome argc--;
1963c65ebfc7SToomas Soome argv++;
1964c65ebfc7SToomas Soome flags |= kDNSServiceFlagsIncludeAWDL;
1965c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsIncludeAWDL\n");
1966c65ebfc7SToomas Soome }
1967c65ebfc7SToomas Soome
1968c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-intermediates"))
1969c65ebfc7SToomas Soome {
1970c65ebfc7SToomas Soome argc--;
1971c65ebfc7SToomas Soome argv++;
1972c65ebfc7SToomas Soome flags |= kDNSServiceFlagsReturnIntermediates;
1973c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsReturnIntermediates\n");
1974c65ebfc7SToomas Soome }
1975c65ebfc7SToomas Soome
1976c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-tc"))
1977c65ebfc7SToomas Soome {
1978c65ebfc7SToomas Soome argc--;
1979c65ebfc7SToomas Soome argv++;
1980c65ebfc7SToomas Soome flags |= kDNSServiceFlagsBackgroundTrafficClass;
1981c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsBackgroundTrafficClass\n");
1982c65ebfc7SToomas Soome }
1983c65ebfc7SToomas Soome
1984c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-t1"))
1985c65ebfc7SToomas Soome {
1986c65ebfc7SToomas Soome argc--;
1987c65ebfc7SToomas Soome argv++;
1988c65ebfc7SToomas Soome flags |= kDNSServiceFlagsThresholdOne;
1989c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsThresholdOne\n");
1990c65ebfc7SToomas Soome }
1991c65ebfc7SToomas Soome
1992c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-tFinder"))
1993c65ebfc7SToomas Soome {
1994c65ebfc7SToomas Soome argc--;
1995c65ebfc7SToomas Soome argv++;
1996c65ebfc7SToomas Soome flags |= kDNSServiceFlagsThresholdFinder;
1997c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsThresholdFinder\n");
1998c65ebfc7SToomas Soome }
1999c65ebfc7SToomas Soome
2000c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-wo"))
2001c65ebfc7SToomas Soome {
2002c65ebfc7SToomas Soome argc--;
2003c65ebfc7SToomas Soome argv++;
2004c65ebfc7SToomas Soome flags |= kDNSServiceFlagsWakeOnlyService;
2005c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsWakeOnlyService\n");
2006c65ebfc7SToomas Soome }
2007c65ebfc7SToomas Soome
2008c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-ku"))
2009c65ebfc7SToomas Soome {
2010c65ebfc7SToomas Soome argc--;
2011c65ebfc7SToomas Soome argv++;
2012c65ebfc7SToomas Soome flags |= kDNSServiceFlagsKnownUnique;
2013c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsKnownUnique\n");
2014c65ebfc7SToomas Soome }
2015c65ebfc7SToomas Soome
2016c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-unicastResponse"))
2017c65ebfc7SToomas Soome {
2018c65ebfc7SToomas Soome argc--;
2019c65ebfc7SToomas Soome argv++;
2020c65ebfc7SToomas Soome flags |= kDNSServiceFlagsUnicastResponse;
2021c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsUnicastResponse\n");
2022c65ebfc7SToomas Soome }
2023c65ebfc7SToomas Soome
2024c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-timeout"))
2025c65ebfc7SToomas Soome {
2026c65ebfc7SToomas Soome argc--;
2027c65ebfc7SToomas Soome argv++;
2028c65ebfc7SToomas Soome flags |= kDNSServiceFlagsTimeout;
2029c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsTimeout\n");
2030c65ebfc7SToomas Soome }
2031c65ebfc7SToomas Soome
2032c65ebfc7SToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-autoTrigger"))
2033c65ebfc7SToomas Soome {
2034c65ebfc7SToomas Soome argc--;
2035c65ebfc7SToomas Soome argv++;
2036c65ebfc7SToomas Soome flags |= kDNSServiceFlagsAutoTrigger;
2037c65ebfc7SToomas Soome printf("Setting kDNSServiceFlagsAutoTrigger\n");
2038c65ebfc7SToomas Soome }
2039c65ebfc7SToomas Soome
2040*472cd20dSToomas Soome if (argc > 1 && !strcasecmp(argv[1], "-enableDNSSEC"))
2041c65ebfc7SToomas Soome {
2042c65ebfc7SToomas Soome argc--;
2043c65ebfc7SToomas Soome argv++;
2044*472cd20dSToomas Soome enable_dnssec = 1;
2045*472cd20dSToomas Soome printf("Enable DNSSEC validation for the '-Q' query\n");
2046c65ebfc7SToomas Soome }
2047c65ebfc7SToomas Soome
2048c65ebfc7SToomas Soome if (argc > 2 && !strcmp(argv[1], "-i"))
2049c65ebfc7SToomas Soome {
2050c65ebfc7SToomas Soome opinterface = if_nametoindex(argv[2]);
2051c65ebfc7SToomas Soome if (!opinterface) opinterface = atoi(argv[2]);
2052c65ebfc7SToomas Soome if (!opinterface) { fprintf(stderr, "Unknown interface %s\n", argv[2]); goto Fail; }
2053c65ebfc7SToomas Soome argc -= 2;
2054c65ebfc7SToomas Soome argv += 2;
2055c65ebfc7SToomas Soome }
2056c65ebfc7SToomas Soome
2057c65ebfc7SToomas Soome // Exit loop if if we didn't match one of the multi character options.
2058c65ebfc7SToomas Soome if (argc == entryCount)
2059c65ebfc7SToomas Soome break;
20605ffb0c9bSToomas Soome }
20615ffb0c9bSToomas Soome
20625ffb0c9bSToomas Soome if (argc < 2) goto Fail; // Minimum command line is the command name and one argument
2063c65ebfc7SToomas Soome operation = getfirstoption(argc, argv, "ABCDEFHILMNPQRSTUVZhlq"
20645ffb0c9bSToomas Soome "X"
20655ffb0c9bSToomas Soome "Gg"
20665ffb0c9bSToomas Soome , &opi);
20675ffb0c9bSToomas Soome if (operation == -1) goto Fail;
20685ffb0c9bSToomas Soome
20695ffb0c9bSToomas Soome if (opinterface) printf("Using interface %d\n", opinterface);
20705ffb0c9bSToomas Soome
20715ffb0c9bSToomas Soome switch (operation)
20725ffb0c9bSToomas Soome {
20735ffb0c9bSToomas Soome case 'E': printf("Looking for recommended registration domains:\n");
20745ffb0c9bSToomas Soome err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsRegistrationDomains, opinterface, enum_reply, NULL);
20755ffb0c9bSToomas Soome break;
20765ffb0c9bSToomas Soome
20775ffb0c9bSToomas Soome case 'F': printf("Looking for recommended browsing domains:\n");
20785ffb0c9bSToomas Soome err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsBrowseDomains, opinterface, enum_reply, NULL);
20795ffb0c9bSToomas Soome //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "nicta.com.au.", NULL);
20805ffb0c9bSToomas Soome //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "bonjour.nicta.com.au.", NULL);
20815ffb0c9bSToomas Soome //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "ibm.com.", NULL);
20825ffb0c9bSToomas Soome //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "dns-sd.ibm.com.", NULL);
20835ffb0c9bSToomas Soome break;
20845ffb0c9bSToomas Soome
20855ffb0c9bSToomas Soome case 'B': typ = (argc < opi+1) ? "" : argv[opi+0];
20865ffb0c9bSToomas Soome dom = (argc < opi+2) ? "" : argv[opi+1]; // Missing domain argument is the same as empty string i.e. use system default(s)
20875ffb0c9bSToomas Soome typ = gettype(buffer, typ);
20885ffb0c9bSToomas Soome if (dom[0] == '.' && dom[1] == 0) dom[0] = 0; // We allow '.' on the command line as a synonym for empty string
20895ffb0c9bSToomas Soome printf("Browsing for %s%s%s\n", typ, dom[0] ? "." : "", dom);
20905ffb0c9bSToomas Soome err = DNSServiceBrowse(&client, flags, opinterface, typ, dom, browse_reply, NULL);
20915ffb0c9bSToomas Soome break;
20925ffb0c9bSToomas Soome
20935ffb0c9bSToomas Soome case 'Z': typ = (argc < opi+1) ? "" : argv[opi+0];
20945ffb0c9bSToomas Soome dom = (argc < opi+2) ? "" : argv[opi+1]; // Missing domain argument is the same as empty string i.e. use system default(s)
20955ffb0c9bSToomas Soome typ = gettype(buffer, typ);
20965ffb0c9bSToomas Soome if (dom[0] == '.' && dom[1] == 0) dom[0] = 0; // We allow '.' on the command line as a synonym for empty string
20975ffb0c9bSToomas Soome printf("Browsing for %s%s%s\n", typ, dom[0] ? "." : "", dom);
20985ffb0c9bSToomas Soome err = DNSServiceCreateConnection(&client);
2099cda73f64SToomas Soome if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); }
21005ffb0c9bSToomas Soome sc1 = client;
21015ffb0c9bSToomas Soome err = DNSServiceBrowse(&sc1, kDNSServiceFlagsShareConnection, opinterface, typ, dom, zonedata_browse, NULL);
21025ffb0c9bSToomas Soome break;
21035ffb0c9bSToomas Soome
21045ffb0c9bSToomas Soome case 'l':
21055ffb0c9bSToomas Soome case 'L': {
21065ffb0c9bSToomas Soome if (argc < opi+2) goto Fail;
21075ffb0c9bSToomas Soome typ = (argc < opi+2) ? "" : argv[opi+1];
21085ffb0c9bSToomas Soome dom = (argc < opi+3) ? "local" : argv[opi+2];
21095ffb0c9bSToomas Soome typ = gettype(buffer, typ);
21105ffb0c9bSToomas Soome if (dom[0] == '.' && dom[1] == 0) dom = "local"; // We allow '.' on the command line as a synonym for "local"
21115ffb0c9bSToomas Soome printf("Lookup %s.%s.%s\n", argv[opi+0], typ, dom);
21125ffb0c9bSToomas Soome if (operation == 'l') flags |= kDNSServiceFlagsWakeOnResolve;
21135ffb0c9bSToomas Soome err = DNSServiceResolve(&client, flags, opinterface, argv[opi+0], typ, dom, resolve_reply, NULL);
21145ffb0c9bSToomas Soome break;
21155ffb0c9bSToomas Soome }
21165ffb0c9bSToomas Soome
21175ffb0c9bSToomas Soome case 'R': if (argc < opi+4) goto Fail;
21185ffb0c9bSToomas Soome typ = (argc < opi+2) ? "" : argv[opi+1];
21195ffb0c9bSToomas Soome dom = (argc < opi+3) ? "" : argv[opi+2];
21205ffb0c9bSToomas Soome typ = gettype(buffer, typ);
21215ffb0c9bSToomas Soome if (dom[0] == '.' && dom[1] == 0) dom[0] = 0; // We allow '.' on the command line as a synonym for empty string
21225ffb0c9bSToomas Soome err = RegisterService(&client, argv[opi+0], typ, dom, NULL, argv[opi+3], argc-(opi+4), argv+(opi+4), flags);
21235ffb0c9bSToomas Soome break;
21245ffb0c9bSToomas Soome
21255ffb0c9bSToomas Soome
21265ffb0c9bSToomas Soome case 'P': if (argc < opi+6) goto Fail;
21275ffb0c9bSToomas Soome err = DNSServiceCreateConnection(&client_pa);
21285ffb0c9bSToomas Soome if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); }
21295ffb0c9bSToomas Soome err = RegisterProxyAddressRecord(client_pa, argv[opi+4], argv[opi+5], flags);
21305ffb0c9bSToomas Soome if (err) break;
21315ffb0c9bSToomas Soome err = RegisterService(&client, argv[opi+0], gettype(buffer, argv[opi+1]), argv[opi+2], argv[opi+4], argv[opi+3], argc-(opi+6), argv+(opi+6), flags);
21325ffb0c9bSToomas Soome break;
21335ffb0c9bSToomas Soome
21345ffb0c9bSToomas Soome case 'q':
21355ffb0c9bSToomas Soome case 'Q':
21365ffb0c9bSToomas Soome case 'C': {
21375ffb0c9bSToomas Soome uint16_t rrtype, rrclass;
21385ffb0c9bSToomas Soome flags |= kDNSServiceFlagsReturnIntermediates;
21395ffb0c9bSToomas Soome if (operation == 'q')
21405ffb0c9bSToomas Soome flags |= kDNSServiceFlagsSuppressUnusable;
2141*472cd20dSToomas Soome if (enable_dnssec)
2142*472cd20dSToomas Soome flags |= kDNSServiceFlagsEnableDNSSEC;
2143c1de7575SRichard Lowe if (argc < opi+1)
21445ffb0c9bSToomas Soome goto Fail;
21455ffb0c9bSToomas Soome rrtype = (argc <= opi+1) ? kDNSServiceType_A : GetRRType(argv[opi+1]);
21465ffb0c9bSToomas Soome rrclass = (argc <= opi+2) ? kDNSServiceClass_IN : GetRRClass(argv[opi+2]);
21475ffb0c9bSToomas Soome if (rrtype == kDNSServiceType_TXT || rrtype == kDNSServiceType_PTR)
21485ffb0c9bSToomas Soome flags |= kDNSServiceFlagsLongLivedQuery;
21495ffb0c9bSToomas Soome err = DNSServiceQueryRecord(&client, flags, opinterface, argv[opi+0], rrtype, rrclass, qr_reply, NULL);
21505ffb0c9bSToomas Soome break;
21515ffb0c9bSToomas Soome }
21525ffb0c9bSToomas Soome
21535ffb0c9bSToomas Soome case 'A':
21545ffb0c9bSToomas Soome case 'U':
21555ffb0c9bSToomas Soome case 'N': {
21565ffb0c9bSToomas Soome Opaque16 registerPort = { { 0x12, 0x34 } };
21575ffb0c9bSToomas Soome static const char TXT[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
21585ffb0c9bSToomas Soome printf("Registering Service Test._testupdate._tcp.local.\n");
21595ffb0c9bSToomas Soome err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testupdate._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL);
21605ffb0c9bSToomas Soome break;
21615ffb0c9bSToomas Soome }
21625ffb0c9bSToomas Soome
21635ffb0c9bSToomas Soome case 'T': {
21645ffb0c9bSToomas Soome Opaque16 registerPort = { { 0x23, 0x45 } };
21655ffb0c9bSToomas Soome char TXT[1024];
21665ffb0c9bSToomas Soome unsigned int i;
21675ffb0c9bSToomas Soome for (i=0; i<sizeof(TXT); i++)
21685ffb0c9bSToomas Soome if ((i & 0x1F) == 0) TXT[i] = 0x1F;else TXT[i] = 'A' + (i >> 5);
21695ffb0c9bSToomas Soome printf("Registering Service Test._testlargetxt._tcp.local.\n");
21705ffb0c9bSToomas Soome err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testlargetxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT), TXT, reg_reply, NULL);
21715ffb0c9bSToomas Soome break;
21725ffb0c9bSToomas Soome }
21735ffb0c9bSToomas Soome
21745ffb0c9bSToomas Soome case 'M': {
21755ffb0c9bSToomas Soome pid_t pid = getpid();
21765ffb0c9bSToomas Soome Opaque16 registerPort = { { pid >> 8, pid & 0xFF } };
21775ffb0c9bSToomas Soome static const char TXT1[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
21785ffb0c9bSToomas Soome static const char TXT2[] = "\xD" "Fourth String" "\xC" "Fifth String" "\xC" "Sixth String";
21795ffb0c9bSToomas Soome printf("Registering Service Test._testdualtxt._tcp.local.\n");
21805ffb0c9bSToomas Soome err = DNSServiceRegister(&client, flags, opinterface, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL);
21815ffb0c9bSToomas Soome if (!err) err = DNSServiceAddRecord(client, &record, flags, kDNSServiceType_TXT, sizeof(TXT2)-1, TXT2, 0);
21825ffb0c9bSToomas Soome break;
21835ffb0c9bSToomas Soome }
21845ffb0c9bSToomas Soome
21855ffb0c9bSToomas Soome case 'I': {
21865ffb0c9bSToomas Soome pid_t pid = getpid();
21875ffb0c9bSToomas Soome Opaque16 registerPort = { { pid >> 8, pid & 0xFF } };
21885ffb0c9bSToomas Soome static const char TXT[] = "\x09" "Test Data";
21895ffb0c9bSToomas Soome printf("Registering Service Test._testtxt._tcp.local.\n");
21905ffb0c9bSToomas Soome err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testtxt._tcp.", "", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
21915ffb0c9bSToomas Soome if (!err) err = DNSServiceUpdateRecord(client, NULL, 0, sizeof(TXT)-1, TXT, 0);
21925ffb0c9bSToomas Soome break;
21935ffb0c9bSToomas Soome }
21945ffb0c9bSToomas Soome
21955ffb0c9bSToomas Soome case 'X': {
21965ffb0c9bSToomas Soome if (argc == opi) // If no arguments, just fetch IP address
21975ffb0c9bSToomas Soome err = DNSServiceNATPortMappingCreate(&client, 0, 0, 0, 0, 0, 0, port_mapping_create_reply, NULL);
21985ffb0c9bSToomas Soome else if (argc >= opi+2 && atoi(argv[opi+0]) == 0)
21995ffb0c9bSToomas Soome {
22005ffb0c9bSToomas Soome DNSServiceProtocol prot = GetProtocol(argv[opi+0]); // Must specify TCP or UDP
22015ffb0c9bSToomas Soome uint16_t IntPortAsNumber = atoi(argv[opi+1]); // Must specify internal port
22025ffb0c9bSToomas Soome uint16_t ExtPortAsNumber = (argc < opi+3) ? 0 : atoi(argv[opi+2]); // Optional desired external port
22035ffb0c9bSToomas Soome uint32_t ttl = (argc < opi+4) ? 0 : atoi(argv[opi+3]); // Optional desired lease lifetime
22045ffb0c9bSToomas Soome Opaque16 intp = { { IntPortAsNumber >> 8, IntPortAsNumber & 0xFF } };
22055ffb0c9bSToomas Soome Opaque16 extp = { { ExtPortAsNumber >> 8, ExtPortAsNumber & 0xFF } };
22065ffb0c9bSToomas Soome err = DNSServiceNATPortMappingCreate(&client, 0, 0, prot, intp.NotAnInteger, extp.NotAnInteger, ttl, port_mapping_create_reply, NULL);
22075ffb0c9bSToomas Soome }
22085ffb0c9bSToomas Soome else goto Fail;
22095ffb0c9bSToomas Soome break;
22105ffb0c9bSToomas Soome }
22115ffb0c9bSToomas Soome
22125ffb0c9bSToomas Soome case 'G': {
22135ffb0c9bSToomas Soome flags |= kDNSServiceFlagsReturnIntermediates;
2214c65ebfc7SToomas Soome
2215*472cd20dSToomas Soome if (argc != opi+2)
22165ffb0c9bSToomas Soome goto Fail;
2217c1de7575SRichard Lowe else
22185ffb0c9bSToomas Soome err = DNSServiceGetAddrInfo(&client, flags, opinterface, GetProtocol(argv[opi+0]), argv[opi+1], addrinfo_reply, NULL);
22195ffb0c9bSToomas Soome break;
22205ffb0c9bSToomas Soome }
22215ffb0c9bSToomas Soome
22225ffb0c9bSToomas Soome case 'S': {
22235ffb0c9bSToomas Soome Opaque16 registerPort = { { 0x23, 0x45 } }; // 9029 decimal
22245ffb0c9bSToomas Soome unsigned char txtrec[16] = "\xF" "/path=test.html";
22255ffb0c9bSToomas Soome DNSRecordRef rec;
22265ffb0c9bSToomas Soome unsigned char nulrec[4] = "1234";
22275ffb0c9bSToomas Soome
22285ffb0c9bSToomas Soome err = DNSServiceCreateConnection(&client);
22295ffb0c9bSToomas Soome if (err) { fprintf(stderr, "DNSServiceCreateConnection failed %ld\n", (long int)err); return (-1); }
22305ffb0c9bSToomas Soome
22315ffb0c9bSToomas Soome sc1 = client;
22325ffb0c9bSToomas Soome err = DNSServiceBrowse(&sc1, kDNSServiceFlagsShareConnection, opinterface, "_http._tcp", "", browse_reply, NULL);
22335ffb0c9bSToomas Soome if (err) { fprintf(stderr, "DNSServiceBrowse _http._tcp failed %ld\n", (long int)err); return (-1); }
22345ffb0c9bSToomas Soome
22355ffb0c9bSToomas Soome sc2 = client;
22365ffb0c9bSToomas Soome err = DNSServiceBrowse(&sc2, kDNSServiceFlagsShareConnection, opinterface, "_ftp._tcp", "", browse_reply, NULL);
22375ffb0c9bSToomas Soome if (err) { fprintf(stderr, "DNSServiceBrowse _ftp._tcp failed %ld\n", (long int)err); return (-1); }
22385ffb0c9bSToomas Soome
22395ffb0c9bSToomas Soome sc3 = client;
22405ffb0c9bSToomas Soome err = DNSServiceRegister(&sc3, kDNSServiceFlagsShareConnection, opinterface, "kDNSServiceFlagsShareConnection",
22415ffb0c9bSToomas Soome "_http._tcp", "local", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
22425ffb0c9bSToomas Soome if (err) { fprintf(stderr, "SharedConnection DNSServiceRegister failed %ld\n", (long int)err); return (-1); }
22435ffb0c9bSToomas Soome
22445ffb0c9bSToomas Soome err = DNSServiceUpdateRecord(sc3, NULL, 0, sizeof(txtrec), txtrec, 0);
22455ffb0c9bSToomas Soome if (err) { fprintf(stderr, "SharedConnection DNSServiceUpdateRecord failed %ld\n", (long int)err); return (-1); }
22465ffb0c9bSToomas Soome
22475ffb0c9bSToomas Soome err = DNSServiceAddRecord(sc3, &rec, 0, kDNSServiceType_NULL, sizeof(nulrec), nulrec, 0);
22485ffb0c9bSToomas Soome if (err) { fprintf(stderr, "SharedConnection DNSServiceAddRecord failed %ld\n", (long int)err); return (-1); }
22495ffb0c9bSToomas Soome
22505ffb0c9bSToomas Soome err = DNSServiceRemoveRecord(sc3, rec, 0);
22515ffb0c9bSToomas Soome if (err) { fprintf(stderr, "SharedConnection DNSServiceRemoveRecord failed %ld\n", (long int)err); return (-1); }
22525ffb0c9bSToomas Soome
22535ffb0c9bSToomas Soome break;
22545ffb0c9bSToomas Soome }
22555ffb0c9bSToomas Soome
22565ffb0c9bSToomas Soome case 'V': {
22575ffb0c9bSToomas Soome uint32_t v;
22585ffb0c9bSToomas Soome uint32_t size = sizeof(v);
22595ffb0c9bSToomas Soome err = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &v, &size);
22605ffb0c9bSToomas Soome if (err) fprintf(stderr, "DNSServiceGetProperty failed %ld\n", (long int)err);
22615ffb0c9bSToomas Soome else printf("Currently running daemon (system service) is version %d.%d.%d\n", v / 10000, v / 100 % 100, v % 100);
22625ffb0c9bSToomas Soome exit(0);
22635ffb0c9bSToomas Soome }
2264*472cd20dSToomas Soome #ifdef APPLE_OSX_mDNSResponder
2265*472cd20dSToomas Soome case 'O': {
2266*472cd20dSToomas Soome // check if the user specifies the flag "-compress"
2267*472cd20dSToomas Soome uint8_t if_compress_state_dump = 0;
2268*472cd20dSToomas Soome uint8_t if_dump_to_stdout = 0;
2269*472cd20dSToomas Soome
2270*472cd20dSToomas Soome if (argc > opi+1) {
2271*472cd20dSToomas Soome printf("dns-sd: illegal option count\n");
2272*472cd20dSToomas Soome goto Fail;
2273*472cd20dSToomas Soome }
2274*472cd20dSToomas Soome
2275*472cd20dSToomas Soome if (argc == opi+1) {
2276*472cd20dSToomas Soome const char *param = argv[opi];
2277*472cd20dSToomas Soome if (strcasecmp("-compress", param) == 0) {
2278*472cd20dSToomas Soome if_compress_state_dump = 1;
2279*472cd20dSToomas Soome } else if (strcasecmp("-stdout", param) == 0) {
2280*472cd20dSToomas Soome if_dump_to_stdout = 1;
2281*472cd20dSToomas Soome } else {
2282*472cd20dSToomas Soome printf("dns-sd: illegal option %s \n", param);
2283*472cd20dSToomas Soome goto Fail;
2284*472cd20dSToomas Soome }
2285*472cd20dSToomas Soome }
2286*472cd20dSToomas Soome handle_state_dump_request(if_compress_state_dump, if_dump_to_stdout);
2287*472cd20dSToomas Soome err = kDNSServiceErr_NoError;
2288*472cd20dSToomas Soome break;
2289*472cd20dSToomas Soome }
2290*472cd20dSToomas Soome #endif // APPLE_OSX_mDNSResponder
22915ffb0c9bSToomas Soome
22925ffb0c9bSToomas Soome case 'H': goto Fail;
22935ffb0c9bSToomas Soome
22945ffb0c9bSToomas Soome default: goto Fail;
22955ffb0c9bSToomas Soome }
2296*472cd20dSToomas Soome #ifdef APPLE_OSX_mDNSResponder
2297*472cd20dSToomas Soome // state dump does not need to create DNSServiceRef, so we can return directly here without cleaning up.
2298*472cd20dSToomas Soome if (operation == 'O')
2299*472cd20dSToomas Soome return 0;
2300*472cd20dSToomas Soome #endif // APPLE_OSX_mDNSResponder
23015ffb0c9bSToomas Soome
23025ffb0c9bSToomas Soome if (!client || err != kDNSServiceErr_NoError)
23035ffb0c9bSToomas Soome {
23045ffb0c9bSToomas Soome fprintf(stderr, "DNSService call failed %ld%s\n", (long int)err,
23055ffb0c9bSToomas Soome (err == kDNSServiceErr_ServiceNotRunning) ? " (Service Not Running)" : "");
23065ffb0c9bSToomas Soome return (-1);
23075ffb0c9bSToomas Soome }
23085ffb0c9bSToomas Soome printtimestamp();
23095ffb0c9bSToomas Soome printf("...STARTING...\n");
23105ffb0c9bSToomas Soome HandleEvents();
23115ffb0c9bSToomas Soome
23125ffb0c9bSToomas Soome // Be sure to deallocate the DNSServiceRef when you're finished
23135ffb0c9bSToomas Soome if (client ) DNSServiceRefDeallocate(client );
23145ffb0c9bSToomas Soome if (client_pa) DNSServiceRefDeallocate(client_pa);
23155ffb0c9bSToomas Soome return 0;
23165ffb0c9bSToomas Soome
23175ffb0c9bSToomas Soome Fail:
23185ffb0c9bSToomas Soome if (operation == 'H') print_usage(a0,1);
23195ffb0c9bSToomas Soome else print_usage(a0,0);
23205ffb0c9bSToomas Soome return 0;
2321*472cd20dSToomas Soome }
2322*472cd20dSToomas Soome
2323*472cd20dSToomas Soome #ifdef APPLE_OSX_mDNSResponder
2324*472cd20dSToomas Soome /*
2325*472cd20dSToomas Soome * if_compress_state_dump and if_dump_to_stdout cannot be set at the same time.
2326*472cd20dSToomas Soome */
handle_state_dump_request(uint8_t if_compress_state_dump,uint8_t if_dump_to_stdout)2327*472cd20dSToomas Soome static void handle_state_dump_request(uint8_t if_compress_state_dump, uint8_t if_dump_to_stdout)
2328*472cd20dSToomas Soome {
2329*472cd20dSToomas Soome // create xpc connection to the xpc server for log utility
2330*472cd20dSToomas Soome xpc_connection_t log_utility_connection = xpc_connection_create_mach_service(kDNSLogUtilityService, dispatch_get_main_queue(), XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
2331*472cd20dSToomas Soome xpc_connection_set_event_handler(log_utility_connection, ^(xpc_object_t event){
2332*472cd20dSToomas Soome printf("Connecting to %s, status: %s\n", kDNSLogUtilityService, xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
2333*472cd20dSToomas Soome });
2334*472cd20dSToomas Soome xpc_connection_resume(log_utility_connection);
2335*472cd20dSToomas Soome
2336*472cd20dSToomas Soome // set option for the state dump
2337*472cd20dSToomas Soome xpc_object_t xpc_dict = xpc_dictionary_create(NULL, NULL, 0);
2338*472cd20dSToomas Soome uint64_t dump_option;
2339*472cd20dSToomas Soome if (if_compress_state_dump) {
2340*472cd20dSToomas Soome dump_option = full_state_with_compression;
2341*472cd20dSToomas Soome }
2342*472cd20dSToomas Soome else if (if_dump_to_stdout) {
2343*472cd20dSToomas Soome // we pass the stdout directly to xpc server
2344*472cd20dSToomas Soome dump_option = full_state_to_stdout;
2345*472cd20dSToomas Soome xpc_dictionary_set_fd(xpc_dict, kDNSStateDumpFD, STDOUT_FILENO);
2346*472cd20dSToomas Soome }
2347*472cd20dSToomas Soome else {
2348*472cd20dSToomas Soome dump_option = full_state;
2349*472cd20dSToomas Soome }
2350*472cd20dSToomas Soome
2351*472cd20dSToomas Soome xpc_dictionary_set_uint64(xpc_dict, kDNSStateDump, dump_option);
2352*472cd20dSToomas Soome
2353*472cd20dSToomas Soome // send the request and handle the response from xpc server
2354*472cd20dSToomas Soome xpc_connection_send_message_with_reply(log_utility_connection, xpc_dict, dispatch_get_main_queue(), ^(xpc_object_t recv_msg){
2355*472cd20dSToomas Soome xpc_type_t msg_type = xpc_get_type(recv_msg);
2356*472cd20dSToomas Soome
2357*472cd20dSToomas Soome if (msg_type != XPC_TYPE_DICTIONARY) {
2358*472cd20dSToomas Soome printf("Received unexpected reply from daemon, error: \"%s\"\nUnexpected reply Contents:\n%s\n",
2359*472cd20dSToomas Soome xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION), xpc_copy_description(recv_msg));
2360*472cd20dSToomas Soome exit(1);
2361*472cd20dSToomas Soome }
2362*472cd20dSToomas Soome
2363*472cd20dSToomas Soome // get the response dictionary
2364*472cd20dSToomas Soome uint32_t return_code = (uint32_t)xpc_dictionary_get_uint64(recv_msg, kDNSDaemonReply);
2365*472cd20dSToomas Soome if (return_code != kDNSMsg_NoError) {
2366*472cd20dSToomas Soome const char *error_description = xpc_dictionary_get_string(recv_msg, kDNSErrorDescription);
2367*472cd20dSToomas Soome printf("XPC service returns error, description: %s\n", error_description);
2368*472cd20dSToomas Soome exit(1);
2369*472cd20dSToomas Soome }
2370*472cd20dSToomas Soome
2371*472cd20dSToomas Soome // print the state information returned from the XPC server
2372*472cd20dSToomas Soome if (dump_option != full_state_to_stdout) {
2373*472cd20dSToomas Soome const char *path = xpc_dictionary_get_string(recv_msg, kDNSDumpFilePath);
2374*472cd20dSToomas Soome printf("State Dump Is Saved to: %s\n", path);
2375*472cd20dSToomas Soome }
2376*472cd20dSToomas Soome
2377*472cd20dSToomas Soome int64_t time_used = xpc_dictionary_get_int64(recv_msg, kDNSStateDumpTimeUsed);
2378*472cd20dSToomas Soome printf(" Time Used: %" PRId64 " ms\n", time_used);
23795ffb0c9bSToomas Soome
2380*472cd20dSToomas Soome xpc_release(xpc_dict);
2381*472cd20dSToomas Soome exit(0);
2382*472cd20dSToomas Soome });
2383*472cd20dSToomas Soome
2384*472cd20dSToomas Soome dispatch_main();
23855ffb0c9bSToomas Soome }
2386*472cd20dSToomas Soome #endif // APPLE_OSX_mDNSResponder
23875ffb0c9bSToomas Soome
23885ffb0c9bSToomas Soome // Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
23895ffb0c9bSToomas Soome // e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
23905ffb0c9bSToomas Soome // To expand "version" to its value before making the string, use STRINGIFY(version) instead
23915ffb0c9bSToomas Soome #define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
23925ffb0c9bSToomas Soome #define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
23935ffb0c9bSToomas Soome
23945ffb0c9bSToomas Soome // NOT static -- otherwise the compiler may optimize it out
23955ffb0c9bSToomas Soome // The "@(#) " pattern is a special prefix the "what" command looks for
23963b436d06SToomas Soome #ifndef MDNS_VERSIONSTR_NODTS
23973b436d06SToomas Soome const char VersionString_SCCS[] = "@(#) dns-sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
23983b436d06SToomas Soome #else
239967ad1fc6SToomas Soome const char VersionString_SCCS[] = "@(#) dns-sd " STRINGIFY(mDNSResponderVersion);
24003b436d06SToomas Soome #endif
24015ffb0c9bSToomas Soome
24025ffb0c9bSToomas Soome #if _BUILDING_XCODE_PROJECT_
24035ffb0c9bSToomas Soome // If the process crashes, then this string will be magically included in the automatically-generated crash log
24045ffb0c9bSToomas Soome const char *__crashreporter_info__ = VersionString_SCCS + 5;
24055ffb0c9bSToomas Soome asm (".desc ___crashreporter_info__, 0x10");
24065ffb0c9bSToomas Soome #endif
2407