3661 Sync mDNS with upstream

Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Robert Mustacchi <rm@joyent.com>
This commit is contained in:
Toomas Soome 2015-10-17 22:57:47 +03:00 committed by Robert Mustacchi
parent 8551f527ef
commit 5ffb0c9b03
74 changed files with 45290 additions and 27275 deletions

View File

@ -30,6 +30,11 @@ exception_lists/closed-bins
exception_lists/copyright
exception_lists/cstyle
exception_lists/hdrchk
usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.c
usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.h
usr/src/cmd/cmd-inet/usr.bin/dns-sd/dns-sd.c
usr/src/cmd/cmd-inet/usr.lib/mdnsd/THIRDPARTYLICENSE
usr/src/cmd/cmd-inet/usr.lib/mdnsd/*.[ch]
usr/src/cmd/dtrace/test/tst/common/*/*.out
usr/src/cmd/krb5/kadmin/cli/kadmin_ct.c
usr/src/cmd/krb5/kadmin/cli/kadmin.h
@ -340,6 +345,11 @@ usr/src/lib/krb5/ss/mit-sipb-copyright.h
usr/src/lib/krb5/ss/options.c
usr/src/lib/krb5/ss/std_rqs.c
usr/src/lib/krb5/ss/utils.c
usr/src/lib/libdns_sd/THIRDPARTYLICENSE
usr/src/lib/libdns_sd/common/*.[ch]
usr/src/lib/libdns_sd/java/common/JNISupport.c
usr/src/lib/libdns_sd/java/com/apple/dnssd/*.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/*
usr/src/lib/librstp/common/*.[ch]
usr/src/lib/librstp/common/[CRT]*
# these have copyrights that the nit checker doesn't grok

View File

@ -1,3 +1,21 @@
usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.[ch]
usr/src/cmd/cmd-inet/usr.bin/dns-sd/dns-sd.c
usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSDigest.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/PosixDaemon.c
usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNS.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSEmbeddedAPI.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/nsec.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/dnssec.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.[ch]
usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.[ch]
usr/src/cmd/krb5/kadmin/cli/kadmin_ct.c
usr/src/cmd/krb5/kadmin/cli/kadmin.c
usr/src/cmd/krb5/kadmin/cli/kadmin.h
@ -570,6 +588,12 @@ usr/src/lib/krb5/ss/ss_internal.h
usr/src/lib/krb5/ss/ss.h
usr/src/lib/krb5/ss/std_rqs.c
usr/src/lib/krb5/ss/utils.c
usr/src/lib/libdns_sd/common/dnssd_clientlib.c
usr/src/lib/libdns_sd/common/dnssd_clientstub.c
usr/src/lib/libdns_sd/common/dnssd_ipc.c
usr/src/lib/libdns_sd/common/dnssd_ipc.h
usr/src/lib/libdns_sd/common/dns_sd.h
usr/src/lib/libdns_sd/java/common/JNISupport.c
usr/src/lib/libgss/g_glue.c
usr/src/lib/libresolv2/common
usr/src/lib/librstp/common/base.h

View File

@ -1,3 +1,17 @@
usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/dnssec.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSEmbeddedAPI.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/nsec.h
usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.h
usr/src/cmd/krb5/kadmin/cli/kadmin.h
usr/src/cmd/krb5/kadmin/dbutil/import_err.h
usr/src/cmd/krb5/kadmin/dbutil/kdb5_util.h
@ -135,6 +149,8 @@ usr/src/lib/krb5/ss/mit-sipb-copyright.h
usr/src/lib/krb5/ss/ss_internal.h
usr/src/lib/krb5/ss/ss.h
usr/src/lib/libc/port/locale/utils.h
usr/src/lib/libdns_sd/common/dns_sd.h
usr/src/lib/libdns_sd/common/dnssd_ipc.h
usr/src/lib/librstp/common/base.h
usr/src/lib/librstp/common/choose.h
usr/src/lib/librstp/common/edge.h

35
exception_lists/jstyle Normal file
View File

@ -0,0 +1,35 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2016 Toomas Soome <tsoome@me.com>
#
usr/src/lib/libdns_sd/java/com/apple/dnssd/BaseListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/BrowseListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSRecord.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSD.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDException.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRegistration.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDService.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/DomainListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/QueryListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterRecordListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/ResolveListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/TXTRecord.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingBrowseListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingDomainListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingQueryListener.java
usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingResolveListener.java

View File

@ -21,9 +21,11 @@
# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
# Copyright (c) 2013 by Delphix. All rights reserved.
# Copyright 2016 Toomas Soome <tsoome@me.com>
#
syntax: glob
usr/src/cmd/cmd-inet/usr.bin/dns-sd/dns-sd.c
usr/src/cmd/localedef/data/zh_CN.UTF-8.src
usr/src/cmd/localedef/data/zh_HK.UTF-8.src
usr/src/cmd/localedef/data/zh_MO.UTF-8.src

View File

@ -23,15 +23,16 @@
# Use is subject to license terms.
#
# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
# Copyright 2016 Toomas Soome <tsoome@me.com>
#
PROG= dns-sd finger rdate ruptime rwho whois
PROG= finger rdate ruptime rwho whois
SUIDPROG= rcp rlogin rsh
ALL= $(PROG) $(SUIDPROG)
SRCS= $(ALL:%=%.c)
KCMDPROGS= rcp rlogin rsh
SUBDIRS= chat ftp nc nca netstat \
SUBDIRS= chat dns-sd ftp nc nca netstat \
pppd pppdump pppstats rdist talk telnet tftp
SUBDIR1= talk
MSGSUBDIRS= nca talk
@ -78,12 +79,10 @@ CERRWARN += -_gcc=-Wno-unused-function
# PROGS are lint clean.
$(LINTCLEAN) := CFLAGS += $(CCVERBOSE)
dns-sd := CFLAGS += $(C99_ENABLE)
finger := CFLAGS += $(CCVERBOSE)
# Enable large file support for reading the lastlog file.
finger := CPPFLAGS += -D_FILE_OFFSET_BITS=64
dns-sd := LDLIBS += -lsocket -ldns_sd
finger := LDLIBS += -lnsl -lcurses -lsocket
rcp lint-rcp := LDLIBS += -lsocket -lsec -lsendfile
rdate lint-rdate:= LDLIBS += -lsocket

View File

@ -1,805 +0,0 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
*
* Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
* ("Apple") in consideration of your agreement to the following terms, and your
* use, installation, modification or redistribution of this Apple software
* constitutes acceptance of these terms. If you do not agree with these terms,
* please do not use, install, modify or redistribute this Apple software.
*
* In consideration of your agreement to abide by the following terms, and subject
* to these terms, Apple grants you a personal, non-exclusive license, under Apple's
* copyrights in this original Apple software (the "Apple Software"), to use,
* reproduce, modify and redistribute the Apple Software, with or without
* modifications, in source and/or binary forms; provided that if you redistribute
* the Apple Software in its entirety and without modifications, you must retain
* this notice and the following text and disclaimers in all such redistributions of
* the Apple Software. Neither the name, trademarks, service marks or logos of
* Apple Computer, Inc. may be used to endorse or promote products derived from the
* Apple Software without specific prior written permission from Apple. Except as
* expressly stated in this notice, no other rights or licenses, express or implied,
* are granted by Apple herein, including but not limited to any patent rights that
* may be infringed by your derivative works or by other works in which the Apple
* Software may be incorporated.
*
* The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
* COMBINATION WITH YOUR PRODUCTS.
*
* IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
* OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Formatting notes:
* This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion
* on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>,
* but for the sake of brevity here I will say just this: Curly braces are not syntactially
* part of an "if" statement; they are the beginning and ending markers of a compound statement;
* therefore common sense dictates that if they are part of a compound statement then they
* should be indented to the same level as everything else in that compound statement.
* Indenting curly braces at the same level as the "if" implies that curly braces are
* part of the "if", which is false. (This is as misleading as people who write "char* x,y;"
* thinking that variables x and y are both of type "char*" -- and anyone who doesn't
* understand why variable y is not of type "char*" just proves the point that poor code
* layout leads people to unfortunate misunderstandings about how the C language really works.)
To build this tool, copy and paste the following into a command line:
OS X:
gcc dns-sd.c -o dns-sd
POSIX systems:
gcc dns-sd.c -o dns-sd -I../mDNSShared -ldns_sd
Windows:
cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT ws2_32.lib ..\mDNSWindows\DLL\Release\dnssd.lib
(may require that you run a Visual Studio script such as vsvars32.bat first)
*/
#pragma ident "%Z%%M% %I% %E% SMI"
// For testing changes to dnssd_clientstub.c, uncomment this line and the #include below
// #define __APPLE_API_PRIVATE 1
#include "dns_sd.h"
#include <ctype.h>
#include <stdio.h> // For stdout, stderr
#include <stdlib.h> // For exit()
#include <string.h> // For strlen(), strcpy(), bzero()
#include <errno.h> // For errno, EINTR
#include <time.h>
#include <sys/types.h> // For u_char
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <process.h>
typedef int pid_t;
#define getpid _getpid
#define strcasecmp _stricmp
#define snprintf _snprintf
static const char kFilePathSep = '\\';
#else
#include <unistd.h> // For getopt() and optind
#include <netdb.h> // For getaddrinfo()
#include <sys/time.h> // For struct timeval
#include <sys/socket.h> // For AF_INET
#include <netinet/in.h> // For struct sockaddr_in()
#include <arpa/inet.h> // For inet_addr()
static const char kFilePathSep = '/';
#endif
//#include "../mDNSShared/dnssd_clientstub.c"
//*************************************************************************************************************
// Globals
typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
static int operation;
static uint32_t opinterface = kDNSServiceInterfaceIndexAny;
static DNSServiceRef client = NULL;
static DNSServiceRef client2 = NULL;
static int num_printed;
static char addtest = 0;
static DNSRecordRef record = NULL;
static char myhinfoW[14] = "\002PC\012Windows XP";
static char myhinfoX[ 9] = "\003Mac\004OS X";
static char updatetest[3] = "\002AA";
static char bigNULL[8200];
// Note: the select() implementation on Windows (Winsock2) fails with any timeout much larger than this
#define LONG_TIME 100000000
static volatile int stopNow = 0;
static volatile int timeOut = LONG_TIME;
//*************************************************************************************************************
// Supporting Utility Function
static uint16_t GetRRType(const char *s)
{
if (!strcasecmp(s, "A" )) return(kDNSServiceType_A);
else if (!strcasecmp(s, "NS" )) return(kDNSServiceType_NS);
else if (!strcasecmp(s, "MD" )) return(kDNSServiceType_MD);
else if (!strcasecmp(s, "MF" )) return(kDNSServiceType_MF);
else if (!strcasecmp(s, "CNAME" )) return(kDNSServiceType_CNAME);
else if (!strcasecmp(s, "SOA" )) return(kDNSServiceType_SOA);
else if (!strcasecmp(s, "MB" )) return(kDNSServiceType_MB);
else if (!strcasecmp(s, "MG" )) return(kDNSServiceType_MG);
else if (!strcasecmp(s, "MR" )) return(kDNSServiceType_MR);
else if (!strcasecmp(s, "NULL" )) return(kDNSServiceType_NULL);
else if (!strcasecmp(s, "WKS" )) return(kDNSServiceType_WKS);
else if (!strcasecmp(s, "PTR" )) return(kDNSServiceType_PTR);
else if (!strcasecmp(s, "HINFO" )) return(kDNSServiceType_HINFO);
else if (!strcasecmp(s, "MINFO" )) return(kDNSServiceType_MINFO);
else if (!strcasecmp(s, "MX" )) return(kDNSServiceType_MX);
else if (!strcasecmp(s, "TXT" )) return(kDNSServiceType_TXT);
else if (!strcasecmp(s, "RP" )) return(kDNSServiceType_RP);
else if (!strcasecmp(s, "AFSDB" )) return(kDNSServiceType_AFSDB);
else if (!strcasecmp(s, "X25" )) return(kDNSServiceType_X25);
else if (!strcasecmp(s, "ISDN" )) return(kDNSServiceType_ISDN);
else if (!strcasecmp(s, "RT" )) return(kDNSServiceType_RT);
else if (!strcasecmp(s, "NSAP" )) return(kDNSServiceType_NSAP);
else if (!strcasecmp(s, "NSAP_PTR")) return(kDNSServiceType_NSAP_PTR);
else if (!strcasecmp(s, "SIG" )) return(kDNSServiceType_SIG);
else if (!strcasecmp(s, "KEY" )) return(kDNSServiceType_KEY);
else if (!strcasecmp(s, "PX" )) return(kDNSServiceType_PX);
else if (!strcasecmp(s, "GPOS" )) return(kDNSServiceType_GPOS);
else if (!strcasecmp(s, "AAAA" )) return(kDNSServiceType_AAAA);
else if (!strcasecmp(s, "LOC" )) return(kDNSServiceType_LOC);
else if (!strcasecmp(s, "NXT" )) return(kDNSServiceType_NXT);
else if (!strcasecmp(s, "EID" )) return(kDNSServiceType_EID);
else if (!strcasecmp(s, "NIMLOC" )) return(kDNSServiceType_NIMLOC);
else if (!strcasecmp(s, "SRV" )) return(kDNSServiceType_SRV);
else if (!strcasecmp(s, "ATMA" )) return(kDNSServiceType_ATMA);
else if (!strcasecmp(s, "NAPTR" )) return(kDNSServiceType_NAPTR);
else if (!strcasecmp(s, "KX" )) return(kDNSServiceType_KX);
else if (!strcasecmp(s, "CERT" )) return(kDNSServiceType_CERT);
else if (!strcasecmp(s, "A6" )) return(kDNSServiceType_A6);
else if (!strcasecmp(s, "DNAME" )) return(kDNSServiceType_DNAME);
else if (!strcasecmp(s, "SINK" )) return(kDNSServiceType_SINK);
else if (!strcasecmp(s, "OPT" )) return(kDNSServiceType_OPT);
else if (!strcasecmp(s, "TKEY" )) return(kDNSServiceType_TKEY);
else if (!strcasecmp(s, "TSIG" )) return(kDNSServiceType_TSIG);
else if (!strcasecmp(s, "IXFR" )) return(kDNSServiceType_IXFR);
else if (!strcasecmp(s, "AXFR" )) return(kDNSServiceType_AXFR);
else if (!strcasecmp(s, "MAILB" )) return(kDNSServiceType_MAILB);
else if (!strcasecmp(s, "MAILA" )) return(kDNSServiceType_MAILA);
else if (!strcasecmp(s, "ANY" )) return(kDNSServiceType_ANY);
else return(atoi(s));
}
//*************************************************************************************************************
// Sample callback functions for each of the operation types
static void printtimestamp(void)
{
struct tm tm;
int ms;
#ifdef _WIN32
SYSTEMTIME sysTime;
time_t uct = time(NULL);
tm = *localtime(&uct);
GetLocalTime(&sysTime);
ms = sysTime.wMilliseconds;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
localtime_r((time_t*)&tv.tv_sec, &tm);
ms = tv.tv_usec/1000;
#endif
printf("%2d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms);
}
#define DomainMsg(X) (((X) & kDNSServiceFlagsDefault) ? "(Default)" : \
((X) & kDNSServiceFlagsAdd) ? "Added" : "Removed")
static const char *GetNextLabel(const char *cstr, char label[64])
{
char *ptr = label;
while (*cstr && *cstr != '.') // While we have characters in the label...
{
char c = *cstr++;
if (c == '\\')
{
c = *cstr++;
if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
{
int v0 = cstr[-1] - '0'; // then interpret as three-digit decimal
int v1 = cstr[ 0] - '0';
int v2 = cstr[ 1] - '0';
int val = v0 * 100 + v1 * 10 + v2;
if (val <= 255) { c = (char)val; cstr += 2; } // If valid three-digit decimal value, use it
}
}
*ptr++ = c;
if (ptr >= label+64) return(NULL);
}
if (*cstr) cstr++; // Skip over the trailing dot (if present)
*ptr++ = 0;
return(cstr);
}
static void DNSSD_API enum_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t ifIndex,
DNSServiceErrorType errorCode, const char *replyDomain, void *context)
{
DNSServiceFlags partialflags = flags & ~(kDNSServiceFlagsMoreComing | kDNSServiceFlagsAdd | kDNSServiceFlagsDefault);
int labels = 0, depth = 0, i, initial = 0;
char text[64];
const char *label[128];
(void)client; // Unused
(void)ifIndex; // Unused
(void)context; // Unused
// 1. Print the header
if (num_printed++ == 0) printf("Timestamp Recommended %s domain\n", operation == 'E' ? "Registration" : "Browsing");
printtimestamp();
if (errorCode)
printf("Error code %d\n", errorCode);
else if (!*replyDomain)
printf("Error: No reply domain\n");
else
{
printf("%-10s", DomainMsg(flags));
printf("%-8s", (flags & kDNSServiceFlagsMoreComing) ? "(More)" : "");
if (partialflags) printf("Flags: %4X ", partialflags);
else printf(" ");
// 2. Count the labels
while (*replyDomain)
{
label[labels++] = replyDomain;
replyDomain = GetNextLabel(replyDomain, text);
}
// 3. Decide if we're going to clump the last two or three labels (e.g. "apple.com", or "nicta.com.au")
if (labels >= 3 && replyDomain - label[labels-1] <= 3 && label[labels-1] - label[labels-2] <= 4) initial = 3;
else if (labels >= 2 && replyDomain - label[labels-1] <= 4) initial = 2;
else initial = 1;
labels -= initial;
// 4. Print the initial one-, two- or three-label clump
for (i=0; i<initial; i++)
{
GetNextLabel(label[labels+i], text);
if (i>0) printf(".");
printf("%s", text);
}
printf("\n");
// 5. Print the remainder of the hierarchy
for (depth=0; depth<labels; depth++)
{
printf(" ");
for (i=0; i<=depth; i++) printf("- ");
GetNextLabel(label[labels-1-depth], text);
printf("> %s\n", text);
}
}
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
static void DNSSD_API browse_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
const char *replyName, const char *replyType, const char *replyDomain, void *context)
{
char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
(void)client; // Unused
(void)context; // Unused
if (num_printed++ == 0) printf("Timestamp A/R Flags if %-25s %-25s %s\n", "Domain", "Service Type", "Instance Name");
printtimestamp();
if (errorCode) printf("Error code %d\n", errorCode);
else printf("%s%6X%3d %-25s %-25s %s\n", op, flags, ifIndex, replyDomain, replyType, replyName);
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
static void ShowTXTRecord(uint16_t txtLen, const unsigned char *txtRecord)
{
const unsigned char *ptr = txtRecord;
const unsigned char *max = txtRecord + txtLen;
while (ptr < max)
{
const unsigned char *const end = ptr + 1 + ptr[0];
if (end > max) { printf("<< invalid data >>"); break; }
if (++ptr < end) printf(" "); // As long as string is non-empty, begin with a space
while (ptr<end)
{
// We'd like the output to be shell-friendly, so that it can be copied and pasted unchanged into a "dns-sd -R" command.
// However, this is trickier than it seems. Enclosing a string in double quotes doesn't necessarily make it
// shell-safe, because shells still expand variables like $foo even when they appear inside quoted strings.
// Enclosing a string in single quotes is better, but when using single quotes even backslash escapes are ignored,
// meaning there's simply no way to represent a single quote (or apostrophe) inside a single-quoted string.
// The only remaining solution is not to surround the string with quotes at all, but instead to use backslash
// escapes to encode spaces and all other known shell metacharacters.
// (If we've missed any known shell metacharacters, please let us know.)
// In addition, non-printing ascii codes (0-31) are displayed as \xHH, using a two-digit hex value.
// Because '\' is itself a shell metacharacter (the shell escape character), it has to be escaped as "\\" to survive
// the round-trip to the shell and back. This means that a single '\' is represented here as EIGHT backslashes:
// The C compiler eats half of them, resulting in four appearing in the output.
// The shell parses those four as a pair of "\\" sequences, passing two backslashes to the "dns-sd -R" command.
// The "dns-sd -R" command interprets this single "\\" pair as an escaped literal backslash. Sigh.
if (strchr(" &;`'\"|*?~<>^()[]{}$", *ptr)) printf("\\");
if (*ptr == '\\') printf("\\\\\\\\");
else if (*ptr >= ' ' ) printf("%c", *ptr);
else printf("\\\\x%02X", *ptr);
ptr++;
}
}
}
static void DNSSD_API resolve_reply(DNSServiceRef client, 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)
{
union { uint16_t s; u_char b[2]; } port = { opaqueport };
uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1];
(void)client; // Unused
(void)ifIndex; // Unused
(void)context; // Unused
printtimestamp();
if (errorCode) printf("Error code %d\n", errorCode);
else
{
printf("%s can be reached at %s:%u", fullname, hosttarget, PortAsNumber);
if (flags) printf(" Flags: %X", flags);
// Don't show degenerate TXT records containing nothing but a single empty string
if (txtLen > 1) { printf("\n"); ShowTXTRecord(txtLen, txtRecord); }
printf("\n");
}
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
static void myTimerCallBack(void)
{
DNSServiceErrorType err = kDNSServiceErr_Unknown;
switch (operation)
{
case 'A':
{
switch (addtest)
{
case 0: printf("Adding Test HINFO record\n");
err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_HINFO, sizeof(myhinfoW), &myhinfoW[0], 0);
addtest = 1;
break;
case 1: printf("Updating Test HINFO record\n");
err = DNSServiceUpdateRecord(client, record, 0, sizeof(myhinfoX), &myhinfoX[0], 0);
addtest = 2;
break;
case 2: printf("Removing Test HINFO record\n");
err = DNSServiceRemoveRecord(client, record, 0);
addtest = 0;
break;
}
}
break;
case 'U':
{
if (updatetest[1] != 'Z') updatetest[1]++;
else updatetest[1] = 'A';
updatetest[0] = 3 - updatetest[0];
updatetest[2] = updatetest[1];
printf("Updating Test TXT record to %c\n", updatetest[1]);
err = DNSServiceUpdateRecord(client, NULL, 0, 1+updatetest[0], &updatetest[0], 0);
}
break;
case 'N':
{
printf("Adding big NULL record\n");
err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_NULL, sizeof(bigNULL), &bigNULL[0], 0);
timeOut = LONG_TIME;
}
break;
}
if (err != kDNSServiceErr_NoError)
{
fprintf(stderr, "DNSService call failed %ld\n", (long int)err);
stopNow = 1;
}
}
static void DNSSD_API reg_reply(DNSServiceRef client, const DNSServiceFlags flags, DNSServiceErrorType errorCode,
const char *name, const char *regtype, const char *domain, void *context)
{
(void)client; // Unused
(void)flags; // Unused
(void)context; // Unused
printf("Got a reply for %s.%s%s: ", name, regtype, domain);
if (errorCode == kDNSServiceErr_NoError)
{
printf("Name now registered and active\n");
if (operation == 'A' || operation == 'U' || operation == 'N') timeOut = 5;
}
else if (errorCode == kDNSServiceErr_NameConflict)
{
printf("Name in use, please choose another\n");
exit(-1);
}
else
printf("Error %d\n", errorCode);
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
static void DNSSD_API 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)
{
char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
const unsigned char *rd = rdata;
const unsigned char *end = (const unsigned char *) rdata + rdlen;
char rdb[1000];
int unknowntype = 0;
(void)sdRef; // Unused
(void)flags; // Unused
(void)ifIndex; // Unused
(void)ttl; // Unused
(void)context; // Unused
if (num_printed++ == 0) printf("Timestamp A/R Flags if %-30s%4s%4s Rdata\n", "Name", "T", "C");
printtimestamp();
if (errorCode)
printf("Error code %d\n", errorCode);
else
{
switch (rrtype)
{
case kDNSServiceType_A: sprintf(rdb, "%d.%d.%d.%d", rd[0], rd[1], rd[2], rd[3]); break;
case kDNSServiceType_AAAA: sprintf(rdb, "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X",
rd[0x0], rd[0x1], rd[0x2], rd[0x3], rd[0x4], rd[0x5], rd[0x6], rd[0x7],
rd[0x8], rd[0x9], rd[0xA], rd[0xB], rd[0xC], rd[0xD], rd[0xE], rd[0xF]); break;
break;
default : sprintf(rdb, "%d bytes%s", rdlen, rdlen ? ":" : ""); unknowntype = 1; break;
}
printf("%s%6X%3d %-30s%4d%4d %s", op, flags, ifIndex, fullname, rrtype, rrclass, rdb);
if (unknowntype) while (rd < end) printf(" %02X", *rd++);
printf("\n");
if (operation == 'C')
if (flags & kDNSServiceFlagsAdd)
DNSServiceReconfirmRecord(flags, ifIndex, fullname, rrtype, rrclass, rdlen, rdata);
}
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
//*************************************************************************************************************
// The main test function
static void HandleEvents(void)
{
int dns_sd_fd = client ? DNSServiceRefSockFD(client ) : -1;
int dns_sd_fd2 = client2 ? DNSServiceRefSockFD(client2) : -1;
int nfds = dns_sd_fd + 1;
fd_set readfds;
struct timeval tv;
int result;
if (dns_sd_fd2 > dns_sd_fd) nfds = dns_sd_fd2 + 1;
while (!stopNow)
{
// 1. Set up the fd_set as usual here.
// This example client has no file descriptors of its own,
// but a real application would call FD_SET to add them to the set here
FD_ZERO(&readfds);
// 2. Add the fd for our client(s) to the fd_set
if (client ) FD_SET(dns_sd_fd , &readfds);
if (client2) FD_SET(dns_sd_fd2, &readfds);
// 3. Set up the timeout.
tv.tv_sec = timeOut;
tv.tv_usec = 0;
result = select(nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
if (result > 0)
{
DNSServiceErrorType err = kDNSServiceErr_NoError;
if (client && FD_ISSET(dns_sd_fd , &readfds)) err = DNSServiceProcessResult(client );
else if (client2 && FD_ISSET(dns_sd_fd2, &readfds)) err = DNSServiceProcessResult(client2);
if (err) { fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); stopNow = 1; }
}
else if (result == 0)
myTimerCallBack();
else
{
printf("select() returned %d errno %d %s\n", result, errno, strerror(errno));
if (errno != EINTR) stopNow = 1;
}
}
}
static int getfirstoption( int argc, char **argv, const char *optstr, int *pOptInd)
// Return the recognized option in optstr and the option index of the next arg.
#if NOT_HAVE_GETOPT
{
int i;
for ( i=1; i < argc; i++)
{
if ( argv[i][0] == '-' && &argv[i][1] &&
NULL != strchr( optstr, argv[i][1]))
{
*pOptInd = i + 1;
return argv[i][1];
}
}
return -1;
}
#else
{
int operation = getopt(argc, (char * const *)argv, optstr);
*pOptInd = optind;
return operation;
}
#endif
static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordRef record, const DNSServiceFlags flags,
DNSServiceErrorType errorCode, void * context)
{
char *name = (char *)context;
(void)service; // Unused
(void)record; // Unused
(void)flags; // Unused
printf("Got a reply for %s: ", name);
switch (errorCode)
{
case kDNSServiceErr_NoError: printf("Name now registered and active\n"); break;
case kDNSServiceErr_NameConflict: printf("Name in use, please choose another\n"); exit(-1);
default: printf("Error %d\n", errorCode); break;
}
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
static unsigned long getip(const char *const name)
{
unsigned long ip = 0;
struct addrinfo hints;
struct addrinfo * addrs = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
if (getaddrinfo(name, NULL, &hints, &addrs) == 0)
{
ip = ((struct sockaddr_in*) addrs->ai_addr)->sin_addr.s_addr;
}
if (addrs)
{
freeaddrinfo(addrs);
}
return(ip);
}
static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef *sdRef, const char *host, const char *ip)
{
// Call getip() after the call DNSServiceCreateConnection().
// On the Win32 platform, WinSock must be initialized for getip() to succeed.
// Any DNSService* call will initialize WinSock for us, so we make sure
// DNSServiceCreateConnection() is called before getip() is.
unsigned long addr = 0;
DNSServiceErrorType err = DNSServiceCreateConnection(sdRef);
if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); }
addr = getip(ip);
return(DNSServiceRegisterRecord(*sdRef, &record, kDNSServiceFlagsUnique, kDNSServiceInterfaceIndexAny, host,
kDNSServiceType_A, kDNSServiceClass_IN, sizeof(addr), &addr, 240, MyRegisterRecordCallback, (void*)host));
// Note, should probably add support for creating proxy AAAA records too, one day
}
#define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0' ) : \
((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) : \
((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : 0)
#define HexPair(P) ((HexVal((P)[0]) << 4) | HexVal((P)[1]))
static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef,
const char *nam, const char *typ, const char *dom, const char *host, const char *port, int argc, char **argv)
{
uint16_t PortAsNumber = atoi(port);
Opaque16 registerPort = { { PortAsNumber >> 8, PortAsNumber & 0xFF } };
unsigned char txt[2048] = "";
unsigned char *ptr = txt;
int i;
if (nam[0] == '.' && nam[1] == 0) nam = ""; // We allow '.' on the command line as a synonym for empty string
if (dom[0] == '.' && dom[1] == 0) dom = ""; // We allow '.' on the command line as a synonym for empty string
printf("Registering Service %s.%s%s%s", nam[0] ? nam : "<<Default>>", typ, dom[0] ? "." : "", dom);
if (host && *host) printf(" host %s", host);
printf(" port %s\n", port);
if (argc)
{
for (i = 0; i < argc; i++)
{
const char *p = argv[i];
*ptr = 0;
while (*p && *ptr < 255 && ptr + 1 + *ptr < txt+sizeof(txt))
{
if (p[0] != '\\' || p[1] == 0) { ptr[++*ptr] = *p; p+=1; }
else if (p[1] == 'x' && isxdigit(p[2]) && isxdigit(p[3])) { ptr[++*ptr] = HexPair(p+2); p+=4; }
else { ptr[++*ptr] = p[1]; p+=2; }
}
ptr += 1 + *ptr;
}
ShowTXTRecord(ptr-txt, txt);
printf("\n");
}
return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, (uint16_t) (ptr-txt), txt, reg_reply, NULL));
}
int main(int argc, char **argv)
{
DNSServiceErrorType err;
char *dom;
int optind;
// Extract the program name from argv[0], which by convention contains the path to this executable.
// Note that this is just a voluntary convention, not enforced by the kernel --
// the process calling exec() can pass bogus data in argv[0] if it chooses to.
const char *a0 = strrchr(argv[0], kFilePathSep) + 1;
if (a0 == (const char *)1) a0 = argv[0];
if (argc > 1 && !strcmp(argv[1], "-lo"))
{
argc--;
argv++;
opinterface = kDNSServiceInterfaceIndexLocalOnly;
printf("Using LocalOnly\n");
}
if (argc > 2 && !strcmp(argv[1], "-i") && atoi(argv[2]))
{
opinterface = atoi(argv[2]);
argc -= 2;
argv += 2;
printf("Using interface %d\n", opinterface);
}
if (argc < 2) goto Fail; // Minimum command line is the command name and one argument
operation = getfirstoption( argc, argv, "EFBLRPQCAUNTMI", &optind);
if (operation == -1) goto Fail;
switch (operation)
{
case 'E': printf("Looking for recommended registration domains:\n");
err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsRegistrationDomains, opinterface, enum_reply, NULL);
break;
case 'F': printf("Looking for recommended browsing domains:\n");
err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsBrowseDomains, opinterface, enum_reply, NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "nicta.com.au.", NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "bonjour.nicta.com.au.", NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "ibm.com.", NULL);
//enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "dns-sd.ibm.com.", NULL);
break;
case 'B': if (argc < optind+1) goto Fail;
dom = (argc < optind+2) ? "" : argv[optind+1];
if (dom[0] == '.' && dom[1] == 0) dom[0] = 0; // We allow '.' on the command line as a synonym for empty string
printf("Browsing for %s%s%s\n", argv[optind+0], dom[0] ? "." : "", dom);
err = DNSServiceBrowse(&client, 0, opinterface, argv[optind+0], dom, browse_reply, NULL);
break;
case 'L': if (argc < optind+2) goto Fail;
dom = (argc < optind+3) ? "local" : argv[optind+2];
if (dom[0] == '.' && dom[1] == 0) dom = "local"; // We allow '.' on the command line as a synonym for "local"
printf("Lookup %s.%s.%s\n", argv[optind+0], argv[optind+1], dom);
err = DNSServiceResolve(&client, 0, opinterface, argv[optind+0], argv[optind+1], dom, (DNSServiceResolveReply)resolve_reply, NULL);
break;
case 'R': if (argc < optind+4) goto Fail;
err = RegisterService(&client, argv[optind+0], argv[optind+1], argv[optind+2], NULL, argv[optind+3], argc-(optind+4), argv+(optind+4));
break;
case 'P': if (argc < optind+6) goto Fail;
err = RegisterProxyAddressRecord(&client2, argv[optind+4], argv[optind+5]);
if (err) break;
err = RegisterService(&client, argv[optind+0], argv[optind+1], argv[optind+2], argv[optind+4], argv[optind+3], argc-(optind+6), argv+(optind+6));
break;
case 'Q':
case 'C': {
uint16_t rrtype, rrclass;
DNSServiceFlags flags = kDNSServiceFlagsReturnCNAME;
if (argc < optind+1) goto Fail;
rrtype = (argc <= optind+1) ? kDNSServiceType_A : GetRRType(argv[optind+1]);
rrclass = (argc <= optind+2) ? kDNSServiceClass_IN : atoi(argv[optind+2]);
if (rrtype == kDNSServiceType_TXT || rrtype == kDNSServiceType_PTR) flags |= kDNSServiceFlagsLongLivedQuery;
err = DNSServiceQueryRecord(&client, flags, opinterface, argv[optind+0], rrtype, rrclass, qr_reply, NULL);
break;
}
case 'A':
case 'U':
case 'N': {
Opaque16 registerPort = { { 0x12, 0x34 } };
static const char TXT[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
printf("Registering Service Test._testupdate._tcp.local.\n");
err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testupdate._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL);
break;
}
case 'T': {
Opaque16 registerPort = { { 0x23, 0x45 } };
char TXT[1024];
unsigned int i;
for (i=0; i<sizeof(TXT); i++)
if ((i & 0x1F) == 0) TXT[i] = 0x1F; else TXT[i] = 'A' + (i >> 5);
printf("Registering Service Test._testlargetxt._tcp.local.\n");
err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testlargetxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT), TXT, reg_reply, NULL);
break;
}
case 'M': {
pid_t pid = getpid();
Opaque16 registerPort = { { pid >> 8, pid & 0xFF } };
static const char TXT1[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
static const char TXT2[] = "\xD" "Fourth String" "\xC" "Fifth String" "\xC" "Sixth String";
printf("Registering Service Test._testdualtxt._tcp.local.\n");
err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL);
if (!err) err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_TXT, sizeof(TXT2)-1, TXT2, 0);
break;
}
case 'I': {
pid_t pid = getpid();
Opaque16 registerPort = { { pid >> 8, pid & 0xFF } };
static const char TXT[] = "\x09" "Test Data";
printf("Registering Service Test._testtxt._tcp.local.\n");
err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testtxt._tcp.", "", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
if (!err) err = DNSServiceUpdateRecord(client, NULL, 0, sizeof(TXT)-1, TXT, 0);
break;
}
default: goto Fail;
}
if (!client || err != kDNSServiceErr_NoError) { fprintf(stderr, "DNSService call failed %ld\n", (long int)err); return (-1); }
HandleEvents();
// Be sure to deallocate the DNSServiceRef when you're finished
if (client ) DNSServiceRefDeallocate(client );
if (client2) DNSServiceRefDeallocate(client2);
return 0;
Fail:
fprintf(stderr, "%s -E (Enumerate recommended registration domains)\n", a0);
fprintf(stderr, "%s -F (Enumerate recommended browsing domains)\n", a0);
fprintf(stderr, "%s -B <Type> <Domain> (Browse for services instances)\n", a0);
fprintf(stderr, "%s -L <Name> <Type> <Domain> (Look up a service instance)\n", a0);
fprintf(stderr, "%s -R <Name> <Type> <Domain> <Port> [<TXT>...] (Register a service)\n", a0);
fprintf(stderr, "%s -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...] (Proxy)\n", a0);
fprintf(stderr, "%s -Q <FQDN> <rrtype> <rrclass> (Generic query for any record type)\n", a0);
fprintf(stderr, "%s -C <FQDN> <rrtype> <rrclass> (Query; reconfirming each result)\n", a0);
fprintf(stderr, "%s -A (Test Adding/Updating/Deleting a record)\n", a0);
fprintf(stderr, "%s -U (Test updating a TXT record)\n", a0);
fprintf(stderr, "%s -N (Test adding a large NULL record)\n", a0);
fprintf(stderr, "%s -T (Test creating a large TXT record)\n", a0);
fprintf(stderr, "%s -M (Test creating a registration with multiple TXT records)\n", a0);
fprintf(stderr, "%s -I (Test registering and then immediately updating TXT record)\n", a0);
return 0;
}

View File

@ -0,0 +1,75 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2008 Apple Inc. All rights reserved.
*
* Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
* ("Apple") in consideration of your agreement to the following terms, and your
* use, installation, modification or redistribution of this Apple software
* constitutes acceptance of these terms. If you do not agree with these terms,
* please do not use, install, modify or redistribute this Apple software.
*
* In consideration of your agreement to abide by the following terms, and subject
* to these terms, Apple grants you a personal, non-exclusive license, under Apple's
* copyrights in this original Apple software (the "Apple Software"), to use,
* reproduce, modify and redistribute the Apple Software, with or without
* modifications, in source and/or binary forms; provided that if you redistribute
* the Apple Software in its entirety and without modifications, you must retain
* this notice and the following text and disclaimers in all such redistributions of
* the Apple Software. Neither the name, trademarks, service marks or logos of
* Apple Computer, Inc. may be used to endorse or promote products derived from the
* Apple Software without specific prior written permission from Apple. Except as
* expressly stated in this notice, no other rights or licenses, express or implied,
* are granted by Apple herein, including but not limited to any patent rights that
* may be infringed by your derivative works or by other works in which the Apple
* Software may be incorporated.
*
* The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
* COMBINATION WITH YOUR PRODUCTS.
*
* IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
* OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ctype.h>
#include <stdio.h> // For stdout, stderr
#include "ClientCommon.h"
const char *GetNextLabel(const char *cstr, char label[64])
{
char *ptr = label;
while (*cstr && *cstr != '.') // While we have characters in the label...
{
char c = *cstr++;
if (c == '\\' && *cstr) // If we have a backslash, and it's not the last character of the string
{
c = *cstr++;
if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
{
int v0 = cstr[-1] - '0'; // then interpret as three-digit decimal
int v1 = cstr[ 0] - '0';
int v2 = cstr[ 1] - '0';
int val = v0 * 100 + v1 * 10 + v2;
// If valid three-digit decimal value, use it
// Note that although ascii nuls are possible in DNS labels
// we're building a C string here so we have no way to represent that
if (val == 0) val = '-';
if (val <= 255) { c = (char)val; cstr += 2; }
}
}
*ptr++ = c;
if (ptr >= label+64) { label[63] = 0; return(NULL); } // Illegal label more than 63 bytes
}
*ptr = 0; // Null-terminate label text
if (ptr == label) return(NULL); // Illegal empty label
if (*cstr) cstr++; // Skip over the trailing dot (if present)
return(cstr);
}

View File

@ -0,0 +1,41 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2008 Apple Inc. All rights reserved.
*
* Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
* ("Apple") in consideration of your agreement to the following terms, and your
* use, installation, modification or redistribution of this Apple software
* constitutes acceptance of these terms. If you do not agree with these terms,
* please do not use, install, modify or redistribute this Apple software.
*
* In consideration of your agreement to abide by the following terms, and subject
* to these terms, Apple grants you a personal, non-exclusive license, under Apple's
* copyrights in this original Apple software (the "Apple Software"), to use,
* reproduce, modify and redistribute the Apple Software, with or without
* modifications, in source and/or binary forms; provided that if you redistribute
* the Apple Software in its entirety and without modifications, you must retain
* this notice and the following text and disclaimers in all such redistributions of
* the Apple Software. Neither the name, trademarks, service marks or logos of
* Apple Computer, Inc. may be used to endorse or promote products derived from the
* Apple Software without specific prior written permission from Apple. Except as
* expressly stated in this notice, no other rights or licenses, express or implied,
* are granted by Apple herein, including but not limited to any patent rights that
* may be infringed by your derivative works or by other works in which the Apple
* Software may be incorporated.
*
* The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
* COMBINATION WITH YOUR PRODUCTS.
*
* IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
* OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
extern const char *GetNextLabel(const char *cstr, char label[64]);

View File

@ -0,0 +1,47 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2016 Toomas Soome <tsoome@me.com>
#
# cmd/cmd-inet/usr.bin/dns-sd/Makefile
PROG= dns-sd
include ../../../Makefile.cmd
include ../../Makefile.cmd-inet
OBJS= ClientCommon.o dns-sd.o
SRCS= ClientCommon.c dns-sd.c
CFLAGS += $(C99_ENABLE)
LDLIBS += -lsocket -ldns_sd
.KEEP_STATE:
all: $(PROG)
ROOTPROG= $(PROG:%=$(ROOTBIN)/%)
$(PROG): $(OBJS)
$(LINK.c) $(OBJS) -o $@ $(LDLIBS)
$(POST_PROCESS)
install: all $(ROOTPROG)
clean:
$(RM) $(OBJS)
lint: lint_SRCS
include ../../../Makefile.targ

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,280 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ***************************************************************************
// CryptoAlg.c:
// Interface to DNSSEC cryptographic algorithms. The crypto support itself is
// provided by the platform and the functions in this file just provide an
// interface to access them in a more generic way.
// ***************************************************************************
#include "mDNSEmbeddedAPI.h"
#include "CryptoAlg.h"
AlgFuncs *DigestAlgFuncs[DIGEST_TYPE_MAX];
AlgFuncs *CryptoAlgFuncs[CRYPTO_ALG_MAX];
AlgFuncs *EncAlgFuncs[ENC_ALG_MAX];
mDNSexport mStatus DigestAlgInit(mDNSu8 digestType, AlgFuncs *func)
{
if (digestType >= DIGEST_TYPE_MAX)
{
LogMsg("DigestAlgInit: digestType %d exceeds bounds", digestType);
return mStatus_BadParamErr;
}
// As digestTypes may not be consecutive, check for specific digest types
// that we support
if (digestType != SHA1_DIGEST_TYPE &&
digestType != SHA256_DIGEST_TYPE)
{
LogMsg("DigestAlgInit: digestType %d not supported", digestType);
return mStatus_BadParamErr;
}
DigestAlgFuncs[digestType] = func;
return mStatus_NoError;
}
mDNSexport mStatus CryptoAlgInit(mDNSu8 alg, AlgFuncs *func)
{
if (alg >= CRYPTO_ALG_MAX)
{
LogMsg("CryptoAlgInit: alg %d exceeds bounds", alg);
return mStatus_BadParamErr;
}
// As algs may not be consecutive, check for specific algorithms
// that we support
if (alg != CRYPTO_RSA_SHA1 && alg != CRYPTO_RSA_SHA256 && alg != CRYPTO_RSA_SHA512 &&
alg != CRYPTO_DSA_NSEC3_SHA1 && alg != CRYPTO_RSA_NSEC3_SHA1)
{
LogMsg("CryptoAlgInit: alg %d not supported", alg);
return mStatus_BadParamErr;
}
CryptoAlgFuncs[alg] = func;
return mStatus_NoError;
}
mDNSexport mStatus EncAlgInit(mDNSu8 alg, AlgFuncs *func)
{
if (alg >= ENC_ALG_MAX)
{
LogMsg("EncAlgInit: alg %d exceeds bounds", alg);
return mStatus_BadParamErr;
}
// As algs may not be consecutive, check for specific algorithms
// that we support
if (alg != ENC_BASE32 && alg != ENC_BASE64)
{
LogMsg("EncAlgInit: alg %d not supported", alg);
return mStatus_BadParamErr;
}
EncAlgFuncs[alg] = func;
return mStatus_NoError;
}
mDNSexport AlgContext *AlgCreate(AlgType type, mDNSu8 alg)
{
AlgFuncs *func = mDNSNULL;
AlgContext *ctx;
if (type == CRYPTO_ALG)
{
if (alg >= CRYPTO_ALG_MAX) return mDNSNULL;
func = CryptoAlgFuncs[alg];
}
else if (type == DIGEST_ALG)
{
if (alg >= DIGEST_TYPE_MAX) return mDNSNULL;
func = DigestAlgFuncs[alg];
}
else if (type == ENC_ALG)
{
if (alg >= ENC_ALG_MAX) return mDNSNULL;
func = EncAlgFuncs[alg];
}
if (!func)
{
// If there is no support from the platform, this case can happen.
LogInfo("AlgCreate: func is NULL");
return mDNSNULL;
}
if (func->Create)
{
mStatus err;
ctx = mDNSPlatformMemAllocate(sizeof(AlgContext));
if (!ctx) return mDNSNULL;
// Create expects ctx->alg to be initialized
ctx->alg = alg;
err = func->Create(ctx);
if (err == mStatus_NoError)
{
ctx->type = type;
return ctx;
}
mDNSPlatformMemFree(ctx);
}
return mDNSNULL;
}
mDNSexport mStatus AlgDestroy(AlgContext *ctx)
{
AlgFuncs *func = mDNSNULL;
if (ctx->type == CRYPTO_ALG)
func = CryptoAlgFuncs[ctx->alg];
else if (ctx->type == DIGEST_ALG)
func = DigestAlgFuncs[ctx->alg];
else if (ctx->type == ENC_ALG)
func = EncAlgFuncs[ctx->alg];
if (!func)
{
LogMsg("AlgDestroy: ERROR!! func is NULL");
mDNSPlatformMemFree(ctx);
return mStatus_BadParamErr;
}
if (func->Destroy)
func->Destroy(ctx);
mDNSPlatformMemFree(ctx);
return mStatus_NoError;
}
mDNSexport mDNSu32 AlgLength(AlgContext *ctx)
{
AlgFuncs *func = mDNSNULL;
if (ctx->type == CRYPTO_ALG)
func = CryptoAlgFuncs[ctx->alg];
else if (ctx->type == DIGEST_ALG)
func = DigestAlgFuncs[ctx->alg];
else if (ctx->type == ENC_ALG)
func = EncAlgFuncs[ctx->alg];
// This should never happen as AlgCreate would have failed
if (!func)
{
LogMsg("AlgLength: ERROR!! func is NULL");
return 0;
}
if (func->Length)
return (func->Length(ctx));
else
return 0;
}
mDNSexport mStatus AlgAdd(AlgContext *ctx, const void *data, mDNSu32 len)
{
AlgFuncs *func = mDNSNULL;
if (ctx->type == CRYPTO_ALG)
func = CryptoAlgFuncs[ctx->alg];
else if (ctx->type == DIGEST_ALG)
func = DigestAlgFuncs[ctx->alg];
else if (ctx->type == ENC_ALG)
func = EncAlgFuncs[ctx->alg];
// This should never happen as AlgCreate would have failed
if (!func)
{
LogMsg("AlgAdd: ERROR!! func is NULL");
return mStatus_BadParamErr;
}
if (func->Add)
return (func->Add(ctx, data, len));
else
return mStatus_BadParamErr;
}
mDNSexport mStatus AlgVerify(AlgContext *ctx, mDNSu8 *key, mDNSu32 keylen, mDNSu8 *signature, mDNSu32 siglen)
{
AlgFuncs *func = mDNSNULL;
if (ctx->type == CRYPTO_ALG)
func = CryptoAlgFuncs[ctx->alg];
else if (ctx->type == DIGEST_ALG)
func = DigestAlgFuncs[ctx->alg];
else if (ctx->type == ENC_ALG)
func = EncAlgFuncs[ctx->alg];
// This should never happen as AlgCreate would have failed
if (!func)
{
LogMsg("AlgVerify: ERROR!! func is NULL");
return mStatus_BadParamErr;
}
if (func->Verify)
return (func->Verify(ctx, key, keylen, signature, siglen));
else
return mStatus_BadParamErr;
}
mDNSexport mDNSu8* AlgEncode(AlgContext *ctx)
{
AlgFuncs *func = mDNSNULL;
if (ctx->type == CRYPTO_ALG)
func = CryptoAlgFuncs[ctx->alg];
else if (ctx->type == DIGEST_ALG)
func = DigestAlgFuncs[ctx->alg];
else if (ctx->type == ENC_ALG)
func = EncAlgFuncs[ctx->alg];
// This should never happen as AlgCreate would have failed
if (!func)
{
LogMsg("AlgEncode: ERROR!! func is NULL");
return mDNSNULL;
}
if (func->Encode)
return (func->Encode(ctx));
else
return mDNSNULL;
}
mDNSexport mStatus AlgFinal(AlgContext *ctx, void *data, mDNSu32 len)
{
AlgFuncs *func = mDNSNULL;
if (ctx->type == CRYPTO_ALG)
func = CryptoAlgFuncs[ctx->alg];
else if (ctx->type == DIGEST_ALG)
func = DigestAlgFuncs[ctx->alg];
else if (ctx->type == ENC_ALG)
func = EncAlgFuncs[ctx->alg];
// This should never happen as AlgCreate would have failed
if (!func)
{
LogMsg("AlgEncode: ERROR!! func is NULL");
return mDNSNULL;
}
if (func->Final)
return (func->Final(ctx, data, len));
else
return mStatus_BadParamErr;
}

View File

@ -0,0 +1,61 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CRYPTO_ALG_H
#define __CRYPTO_ALG_H
typedef enum
{
CRYPTO_ALG,
DIGEST_ALG,
ENC_ALG,
} AlgType;
typedef struct
{
void *context;
AlgType type;
mDNSu8 alg;
} AlgContext;
typedef struct
{
mStatus (*Create)(AlgContext *ctx);
mStatus (*Destroy)(AlgContext *ctx);
mDNSu32 (*Length)(AlgContext *ctx);
mStatus (*Add)(AlgContext *ctx, const void *data, mDNSu32 len);
// Verify the ctx using the key and compare it against signature/siglen
mStatus (*Verify)(AlgContext *ctx, mDNSu8 *key, mDNSu32 keylen, mDNSu8 *signature, mDNSu32 siglen);
// Encode the data and return the encoded data
mDNSu8* (*Encode)(AlgContext *ctx);
// Return the finalized data in data whose length is len (used by hash algorithms)
mStatus (*Final)(AlgContext *ctx, void *data, mDNSu32 len);
} AlgFuncs;
mDNSexport mStatus DigestAlgInit(mDNSu8 digestType, AlgFuncs *func);
mDNSexport mStatus CryptoAlgInit(mDNSu8 algType, AlgFuncs *func);
mDNSexport mStatus EncAlgInit(mDNSu8 algType, AlgFuncs *func);
extern AlgContext *AlgCreate(AlgType type, mDNSu8 alg);
extern mStatus AlgDestroy(AlgContext *ctx);
extern mDNSu32 AlgLength(AlgContext *ctx);
extern mStatus AlgAdd(AlgContext *ctx, const void *data, mDNSu32 len);
extern mStatus AlgVerify(AlgContext *ctx, mDNSu8 *key, mDNSu32 keylen, mDNSu8 *signature, mDNSu32 siglen);
extern mDNSu8* AlgEncode(AlgContext *ctx);
extern mStatus AlgFinal(AlgContext *ctx, void *data, mDNSu32 len);
#endif // __CRYPTO_ALG_H

File diff suppressed because it is too large Load Diff

View File

@ -5,148 +5,33 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: DNSCommon.h,v $
Revision 1.34.2.1 2006/08/29 06:24:22 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.34 2006/03/18 21:47:56 cheshire
<rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
Revision 1.33 2006/03/10 21:51:41 cheshire
<rdar://problem/4111464> After record update, old record sometimes remains in cache
Split out SameRDataBody() into a separate routine so it can be called from other code
Revision 1.32 2005/03/21 00:33:51 shersche
<rdar://problem/4021486> Fix build warnings on Win32 platform
Revision 1.31 2005/02/18 00:43:11 cheshire
<rdar://problem/4010245> mDNSResponder should auto-truncate service names that are too long
Revision 1.30 2005/01/19 03:12:44 cheshire
Move LocalRecordReady() macro from mDNS.c to DNSCommon.h
Revision 1.29 2004/12/15 02:11:22 ksekar
<rdar://problem/3917317> Don't check for Dynamic DNS hostname uniqueness
Revision 1.28 2004/12/06 21:15:22 ksekar
<rdar://problem/3884386> mDNSResponder crashed in CheckServiceRegistrations
Revision 1.27 2004/12/03 07:20:50 ksekar
<rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
Revision 1.26 2004/12/03 05:18:33 ksekar
<rdar://problem/3810596> mDNSResponder needs to return more specific TSIG errors
Revision 1.25 2004/10/26 03:52:02 cheshire
Update checkin comments
Revision 1.24 2004/10/23 01:16:00 cheshire
<rdar://problem/3851677> uDNS operations not always reliable on multi-homed hosts
Revision 1.23 2004/10/03 23:18:58 cheshire
Move address comparison macros from DNSCommon.h to mDNSEmbeddedAPI.h
Revision 1.22 2004/09/30 00:24:56 ksekar
<rdar://problem/3695802> Dynamically update default registration domains on config change
Revision 1.21 2004/09/17 01:08:48 cheshire
Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
declared in that file are ONLY appropriate to single-address-space embedded applications.
For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
Revision 1.20 2004/09/17 00:49:51 cheshire
Get rid of now-unused GetResourceRecord -- the correct (safe) routine to use
is GetLargeResourceRecord
Revision 1.19 2004/09/16 21:59:15 cheshire
For consistency with zerov6Addr, rename zeroIPAddr to zerov4Addr
Revision 1.18 2004/09/16 02:29:39 cheshire
Moved mDNS_Lock/mDNS_Unlock to DNSCommon.c; Added necessary locking around
uDNS_ReceiveMsg, uDNS_StartQuery, uDNS_UpdateRecord, uDNS_RegisterService
Revision 1.17 2004/09/14 23:27:46 cheshire
Fix compile errors
Revision 1.16 2004/08/13 23:46:58 cheshire
"asyncronous" -> "asynchronous"
Revision 1.15 2004/08/10 23:19:14 ksekar
<rdar://problem/3722542>: DNS Extension daemon for Wide Area Service Discovery
Moved routines/constants to allow extern access for garbage collection daemon
Revision 1.14 2004/05/28 23:42:36 ksekar
<rdar://problem/3258021>: Feature: DNS server->client notification on record changes (#7805)
Revision 1.13 2004/05/18 23:51:25 cheshire
Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
Revision 1.12 2004/04/22 04:03:59 cheshire
Headers should use "extern" declarations, not "mDNSexport"
Revision 1.11 2004/04/14 23:09:28 ksekar
Support for TSIG signed dynamic updates.
Revision 1.10 2004/03/13 01:57:33 ksekar
<rdar://problem/3192546>: DynDNS: Dynamic update of service records
Revision 1.9 2004/02/21 08:56:58 bradley
Wrap prototypes with extern "C" for C++ builds.
Revision 1.8 2004/02/06 23:04:18 ksekar
Basic Dynamic Update support via mDNS_Register (dissabled via
UNICAST_REGISTRATION #define)
Revision 1.7 2004/02/03 19:47:36 ksekar
Added an asynchronous state machine mechanism to uDNS.c, including
calls to find the parent zone for a domain name. Changes include code
in repository previously dissabled via "#if 0 incomplete". Codepath
is currently unused, and will be called to create update records, etc.
Revision 1.6 2004/01/27 20:15:22 cheshire
<rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
Revision 1.5 2004/01/24 03:40:56 cheshire
Move mDNSAddrIsDNSMulticast() from DNSCommon.h to mDNSEmbeddedAPI.h so embedded clients can use it
Revision 1.4 2004/01/24 03:38:27 cheshire
Fix minor syntactic error: Headers should use "extern" declarations, not "mDNSexport"
Revision 1.3 2004/01/23 23:23:14 ksekar
Added TCP support for truncated unicast messages.
Revision 1.2 2004/01/21 21:12:23 cheshire
Add missing newline at end of file to make Unix tools happier
Revision 1.1 2003/12/13 03:05:27 ksekar
<rdar://problem/3192548>: DynDNS: Unicast query of service records
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef __DNSCOMMON_H_
#define __DNSCOMMON_H_
#include "mDNSEmbeddedAPI.h"
#ifdef __cplusplus
extern "C" {
#ifdef __cplusplus
extern "C" {
#endif
//*************************************************************************************************************
// Macros
// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
// To expand "version" to its value before making the string, use STRINGIFY(version) instead
#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
@ -154,51 +39,50 @@ Revision 1.1 2003/12/13 03:05:27 ksekar
#endif
typedef enum
{
kDNSFlag0_QR_Mask = 0x80, // Query or response?
kDNSFlag0_QR_Query = 0x00,
kDNSFlag0_QR_Response = 0x80,
kDNSFlag0_OP_Mask = 0x78, // Operation type
kDNSFlag0_OP_StdQuery = 0x00,
kDNSFlag0_OP_Iquery = 0x08,
kDNSFlag0_OP_Status = 0x10,
kDNSFlag0_OP_Unused3 = 0x18,
kDNSFlag0_OP_Notify = 0x20,
kDNSFlag0_OP_Update = 0x28,
kDNSFlag0_QROP_Mask = kDNSFlag0_QR_Mask | kDNSFlag0_OP_Mask,
kDNSFlag0_AA = 0x04, // Authoritative Answer?
kDNSFlag0_TC = 0x02, // Truncated?
kDNSFlag0_RD = 0x01, // Recursion Desired?
kDNSFlag1_RA = 0x80, // Recursion Available?
kDNSFlag1_Zero = 0x40, // Reserved; must be zero
kDNSFlag1_AD = 0x20, // Authentic Data [RFC 2535]
kDNSFlag1_CD = 0x10, // Checking Disabled [RFC 2535]
{
kDNSFlag0_QR_Mask = 0x80, // Query or response?
kDNSFlag0_QR_Query = 0x00,
kDNSFlag0_QR_Response = 0x80,
kDNSFlag1_RC = 0x0F, // Response code
kDNSFlag1_RC_NoErr = 0x00,
kDNSFlag1_RC_FmtErr = 0x01,
kDNSFlag1_RC_SrvErr = 0x02,
kDNSFlag1_RC_NXDomain = 0x03,
kDNSFlag1_RC_NotImpl = 0x04,
kDNSFlag1_RC_Refused = 0x05,
kDNSFlag1_RC_YXDomain = 0x06,
kDNSFlag1_RC_YXRRSet = 0x07,
kDNSFlag1_RC_NXRRSet = 0x08,
kDNSFlag1_RC_NotAuth = 0x09,
kDNSFlag1_RC_NotZone = 0x0A
} DNS_Flags;
kDNSFlag0_OP_Mask = 0x78, // Operation type
kDNSFlag0_OP_StdQuery = 0x00,
kDNSFlag0_OP_Iquery = 0x08,
kDNSFlag0_OP_Status = 0x10,
kDNSFlag0_OP_Unused3 = 0x18,
kDNSFlag0_OP_Notify = 0x20,
kDNSFlag0_OP_Update = 0x28,
kDNSFlag0_QROP_Mask = kDNSFlag0_QR_Mask | kDNSFlag0_OP_Mask,
kDNSFlag0_AA = 0x04, // Authoritative Answer?
kDNSFlag0_TC = 0x02, // Truncated?
kDNSFlag0_RD = 0x01, // Recursion Desired?
kDNSFlag1_RA = 0x80, // Recursion Available?
kDNSFlag1_Zero = 0x40, // Reserved; must be zero
kDNSFlag1_AD = 0x20, // Authentic Data [RFC 2535]
kDNSFlag1_CD = 0x10, // Checking Disabled [RFC 2535]
kDNSFlag1_RC_Mask = 0x0F, // Response code
kDNSFlag1_RC_NoErr = 0x00,
kDNSFlag1_RC_FormErr = 0x01,
kDNSFlag1_RC_ServFail = 0x02,
kDNSFlag1_RC_NXDomain = 0x03,
kDNSFlag1_RC_NotImpl = 0x04,
kDNSFlag1_RC_Refused = 0x05,
kDNSFlag1_RC_YXDomain = 0x06,
kDNSFlag1_RC_YXRRSet = 0x07,
kDNSFlag1_RC_NXRRSet = 0x08,
kDNSFlag1_RC_NotAuth = 0x09,
kDNSFlag1_RC_NotZone = 0x0A
} DNS_Flags;
typedef enum
{
TSIG_ErrBadSig = 16,
TSIG_ErrBadKey = 17,
TSIG_ErrBadTime = 18
} TSIG_ErrorCode;
{
TSIG_ErrBadSig = 16,
TSIG_ErrBadKey = 17,
TSIG_ErrBadTime = 18
} TSIG_ErrorCode;
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
@ -206,107 +90,146 @@ typedef enum
#pragma mark - General Utility Functions
#endif
extern const NetworkInterfaceInfo *GetFirstActiveInterface(const NetworkInterfaceInfo *intf);
extern NetworkInterfaceInfo *GetFirstActiveInterface(NetworkInterfaceInfo *intf);
extern mDNSInterfaceID GetNextActiveInterfaceID(const NetworkInterfaceInfo *intf);
extern mDNSu32 mDNSRandom(mDNSu32 max);
extern mDNSu32 mDNSRandomFromFixedSeed(mDNSu32 seed, mDNSu32 max);
extern mDNSu32 mDNSRandom(mDNSu32 max); // Returns pseudo-random result from zero to max inclusive
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
#pragma mark - Domain Name Utility Functions
#endif
#define mdnsIsDigit(X) ((X) >= '0' && (X) <= '9')
#define mDNSSubTypeLabel "\x04_sub"
#define mDNSIsDigit(X) ((X) >= '0' && (X) <= '9')
#define mDNSIsUpperCase(X) ((X) >= 'A' && (X) <= 'Z')
#define mDNSIsLowerCase(X) ((X) >= 'a' && (X) <= 'z')
#define mdnsIsLetter(X) (mDNSIsUpperCase(X) || mDNSIsLowerCase(X))
#define mdnsValidHostChar(X, notfirst, notlast) (mdnsIsLetter(X) || mdnsIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') )
#define mDNSIsLetter(X) (mDNSIsUpperCase(X) || mDNSIsLowerCase(X))
#define mDNSValidHostChar(X, notfirst, notlast) (mDNSIsLetter(X) || mDNSIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') )
extern mDNSu16 CompressedDomainNameLength(const domainname *const name, const domainname *parent);
extern int CountLabels(const domainname *d);
extern const domainname *SkipLeadingLabels(const domainname *d, int skip);
extern mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max);
extern mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText);
extern mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText);
extern void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichText);
extern void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
extern void AppendLabelSuffix(domainlabel *const name, mDNSu32 val, const mDNSBool RichText);
#define ValidateDomainName(N) (DomainNameLength(N) <= MAX_DOMAIN_NAME)
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
#pragma mark - Resource Record Utility Functions
#endif
extern mDNSu32 RDataHashValue(mDNSu16 const rdlength, const RDataBody *const rdb);
// IdenticalResourceRecord returns true if two resources records have
// the same name, type, class, and identical rdata (InterfaceID and TTL may differ)
extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2);
extern mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2);
// IdenticalSameNameRecord is the same, except it skips the expensive SameDomainName() check,
// which is at its most expensive and least useful in cases where we know in advance that the names match
// Note: The dominant use of IdenticalResourceRecord is from ProcessQuery(), handling known-answer lists. In this case
// it's common to have a whole bunch or records with exactly the same name (e.g. "_http._tcp.local") but different RDATA.
// The SameDomainName() check is expensive when the names match, and in this case *all* the names match, so we
// used to waste a lot of CPU time verifying that the names match, only then to find that the RDATA is different.
// We observed mDNSResponder spending 30% of its total CPU time on this single task alone.
// By swapping the checks so that we check the RDATA first, we can quickly detect when it's different
// (99% of the time) and then bail out before we waste time on the expensive SameDomainName() check.
#define IdenticalResourceRecord(r1,r2) ( \
(r1)->rrtype == (r2)->rrtype && \
(r1)->rrclass == (r2)->rrclass && \
(r1)->namehash == (r2)->namehash && \
(r1)->rdlength == (r2)->rdlength && \
(r1)->rdatahash == (r2)->rdatahash && \
SameRDataBody((r1), &(r2)->rdata->u, SameDomainName) && \
SameDomainName((r1)->name, (r2)->name))
#define IdenticalSameNameRecord(r1,r2) ( \
(r1)->rrtype == (r2)->rrtype && \
(r1)->rrclass == (r2)->rrclass && \
(r1)->rdlength == (r2)->rdlength && \
(r1)->rdatahash == (r2)->rdatahash && \
SameRDataBody((r1), &(r2)->rdata->u, SameDomainName))
// A given RRType answers a QuestionType if RRType is CNAME, or types match, or QuestionType is ANY,
// or the RRType is NSEC and positively asserts the nonexistence of the type being requested
#define RRTypeAnswersQuestionType(R,Q) ((R)->rrtype == kDNSType_CNAME || (R)->rrtype == (Q) || (Q) == kDNSQType_ANY || RRAssertsNonexistence((R),(Q)))
// Unicast NSEC records have the NSEC bit set whereas the multicast NSEC ones don't
#define UNICAST_NSEC(rr) ((rr)->rrtype == kDNSType_NSEC && RRAssertsExistence((rr), kDNSType_NSEC))
extern mDNSu32 RDataHashValue(const ResourceRecord *const rr);
extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2, DomainNameComparisonFn *samename);
extern mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
extern mDNSBool SameResourceRecord(ResourceRecord *r1, ResourceRecord *r2);
extern mDNSBool AnyTypeRecordAnswersQuestion (const ResourceRecord *const rr, const DNSQuestion *const q);
extern mDNSBool ResourceRecordAnswersUnicastResponse(const ResourceRecord *const rr, const DNSQuestion *const q);
extern mDNSBool LocalOnlyRecordAnswersQuestion(AuthRecord *const rr, const DNSQuestion *const q);
extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate);
extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
extern mStatus DNSNameToLowerCase(domainname *d, domainname *result);
#define GetRRDomainNameTarget(RR) ( \
((RR)->rrtype == kDNSType_CNAME || (RR)->rrtype == kDNSType_PTR || (RR)->rrtype == kDNSType_NS) \
? &(RR)->rdata->u.name : \
((RR)->rrtype == kDNSType_SRV ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
#define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique && (X)->resrec.RecordType != kDNSRecordTypeDeregistering)
((RR)->rrtype == kDNSType_NS || (RR)->rrtype == kDNSType_CNAME || (RR)->rrtype == kDNSType_PTR || (RR)->rrtype == kDNSType_DNAME) ? &(RR)->rdata->u.name : \
((RR)->rrtype == kDNSType_MX || (RR)->rrtype == kDNSType_AFSDB || (RR)->rrtype == kDNSType_RT || (RR)->rrtype == kDNSType_KX ) ? &(RR)->rdata->u.mx.exchange : \
((RR)->rrtype == kDNSType_SRV ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
#define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique)
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
#pragma mark -
#pragma mark - DNS Message Creation Functions
#endif
extern void InitializeDNSMessage(DNSMessageHeader *h, mDNSOpaque16 id, mDNSOpaque16 flags);
extern const mDNSu8 *FindCompressionPointer(const mDNSu8 *const base, const mDNSu8 *const end, const mDNSu8 *const domname);
extern mDNSu8 *putDomainNameAsLabels(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name);
extern mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, ResourceRecord *rr);
extern mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const ResourceRecord *const rr);
// If we have a single large record to put in the packet, then we allow the packet to be up to 9K bytes,
// but in the normal case we try to keep the packets below 1500 to avoid IP fragmentation on standard Ethernet
// but in the normal case we try to keep the packets below 1500 to avoid IP fragmentation on standard Ethernet
#define AllowedRRSpace(msg) (((msg)->h.numAnswers || (msg)->h.numAuthorities || (msg)->h.numAdditionals) ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData)
extern mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 ttl, const mDNSu8 *limit);
#define PutResourceRecordTTL(msg, ptr, count, rr, ttl) PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), \
((msg)->h.numAnswers || (msg)->h.numAuthorities || (msg)->h.numAdditionals) ? (msg)->data + NormalMaxDNSMessageData : (msg)->data + AbsoluteMaxDNSMessageData)
#define PutResourceRecordTTL(msg, ptr, count, rr, ttl) \
PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), (msg)->data + AllowedRRSpace(msg))
#define PutResourceRecordTTLJumbo(msg, ptr, count, rr, ttl) PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), \
(msg)->data + AbsoluteMaxDNSMessageData)
extern mDNSu8 *PutResourceRecordCappedTTL(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 maxttl);
#define PutResourceRecordTTLJumbo(msg, ptr, count, rr, ttl) \
PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), (msg)->data + AbsoluteMaxDNSMessageData)
extern mDNSu8 *putEmptyResourceRecord(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, mDNSu16 *count, const AuthRecord *rr);
extern mDNSu8 *putQuestion(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name, mDNSu16 rrtype, mDNSu16 rrclass);
extern mDNSu8 *putZone(DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit, const domainname *zone, mDNSOpaque16 zoneClass);
extern mDNSu8 *putPrereqNameNotInUse(domainname *name, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *end);
extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr);
extern mDNSu8 *putDeleteRRSet(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype);
extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name);
extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease);
#define PutResourceRecord(MSG, P, C, RR) PutResourceRecordTTL((MSG), (P), (C), (RR), (RR)->rroriginalttl)
// The PutRR_OS variants assume a local variable 'm', put build the packet at m->omsg,
// and assume local variables 'OwnerRecordSpace' & 'TraceRecordSpace' indicating how many bytes (if any) to reserve to add an OWNER/TRACER option at the end
#define PutRR_OS_TTL(ptr, count, rr, ttl) \
PutResourceRecordTTLWithLimit(&m->omsg, (ptr), (count), (rr), (ttl), m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace - TraceRecordSpace)
#define PutRR_OS(P, C, RR) PutRR_OS_TTL((P), (C), (RR), (RR)->rroriginalttl)
extern mDNSu8 *putQuestion(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name, mDNSu16 rrtype, mDNSu16 rrclass);
extern mDNSu8 *putZone(DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit, const domainname *zone, mDNSOpaque16 zoneClass);
extern mDNSu8 *putPrereqNameNotInUse(const domainname *const name, DNSMessage *const msg, mDNSu8 *const ptr, mDNSu8 *const end);
extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr);
extern mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit);
extern mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit);
extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name);
extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease);
extern mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit);
extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *ptr, DomainAuthInfo *authInfo, mDNSu8 *limit);
extern mDNSu8 *putDNSSECOption(DNSMessage *msg, mDNSu8 *end, mDNSu8 *limit);
extern int baseEncode(char *buffer, int blen, const mDNSu8 *data, int len, int encAlg);
extern void NSEC3Parse(const ResourceRecord *const rr, mDNSu8 **salt, int *hashLength, mDNSu8 **nxtName, int *bitmaplen, mDNSu8 **bitmap);
extern const mDNSu8 *NSEC3HashName(const domainname *name, rdataNSEC3 *nsec3, const mDNSu8 *AnonData, int AnonDataLen,
const mDNSu8 hash[NSEC3_MAX_HASH_LEN], int *dlen);
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
@ -314,43 +237,47 @@ extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease);
#pragma mark - DNS Message Parsing Functions
#endif
#define AuthHashSlot(X) (DomainNameHashValue(X) % AUTH_HASH_SLOTS)
#define HashSlot(X) (DomainNameHashValue(X) % CACHE_HASH_SLOTS)
extern mDNSu32 DomainNameHashValue(const domainname *const name);
extern void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength);
extern const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end);
extern const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end,
domainname *const name);
domainname *const name);
extern const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
extern const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage * const msg, const mDNSu8 *ptr,
const mDNSu8 * end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *largecr);
extern const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage * const msg, const mDNSu8 *ptr,
const mDNSu8 * end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *const largecr);
extern mDNSBool SetRData(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *end,
LargeCacheRecord *const largecr, mDNSu16 rdlength);
extern const mDNSu8 *skipQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
extern const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end, const mDNSInterfaceID InterfaceID,
DNSQuestion *question);
DNSQuestion *question);
extern const mDNSu8 *LocateAnswers(const DNSMessage *const msg, const mDNSu8 *const end);
extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 *const end);
extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end);
extern const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize);
extern const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end);
extern mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end);
extern void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *transport,
const mDNSAddr *srcaddr, mDNSIPPort srcport,
const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end);
extern mDNSBool RRAssertsNonexistence(const ResourceRecord *const rr, mDNSu16 type);
extern mDNSBool RRAssertsExistence(const ResourceRecord *const rr, mDNSu16 type);
extern mDNSBool BitmapTypeCheck(mDNSu8 *bmap, int bitmaplen, mDNSu16 type);
extern mDNSu16 swap16(mDNSu16 x);
extern mDNSu32 swap32(mDNSu32 x);
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
#pragma mark -
#pragma mark - Packet Sending Functions
#endif
extern mStatus mDNSSendDNSMessage(const mDNS *const m, DNSMessage *const msg, mDNSu8 *end,
mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstport, int sd, uDNS_AuthInfo *authInfo);
extern mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end,
mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo,
mDNSBool useBackgroundTrafficClass);
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
@ -358,11 +285,31 @@ extern mStatus mDNSSendDNSMessage(const mDNS *const m, DNSMessage *const msg, mD
#pragma mark - RR List Management & Task Management
#endif
extern void mDNS_Lock(mDNS *const m);
extern void mDNS_Unlock(mDNS *const m);
extern void ShowTaskSchedulingError(mDNS *const m);
extern void mDNS_Lock_(mDNS *const m, const char * const functionname);
extern void mDNS_Unlock_(mDNS *const m, const char * const functionname);
#ifdef __cplusplus
}
#if defined(_WIN32)
#define __func__ __FUNCTION__
#endif
#define mDNS_Lock(X) mDNS_Lock_((X), __func__)
#define mDNS_Unlock(X) mDNS_Unlock_((X), __func__)
#define mDNS_CheckLock(X) { if ((X)->mDNS_busy != (X)->mDNS_reentrancy+1) \
LogMsg("%s: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy); }
#define mDNS_DropLockBeforeCallback() do { m->mDNS_reentrancy++; \
if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \
} while (0)
#define mDNS_ReclaimLockAfterCallback() do { \
if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Unlocking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \
m->mDNS_reentrancy--; } while (0)
#ifdef __cplusplus
}
#endif
#endif // __DNSCOMMON_H_

File diff suppressed because it is too large Load Diff

View File

@ -5,330 +5,315 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
File: GenLinkedList.c
File: GenLinkedList.c
Contains: implementation of generic linked lists.
Contains: implementation of generic linked lists.
Version: 1.0
Tabs: 4 spaces
Change History (most recent first):
$Log: GenLinkedList.c,v $
Revision 1.4 2006/08/14 23:24:56 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.3 2004/04/22 21:14:42 cheshire
Fix comment spelling mistake
Revision 1.2 2004/02/05 07:41:08 cheshire
Add Log header
*/
#pragma ident "%Z%%M% %I% %E% SMI"
Version: 1.0
Tabs: 4 spaces
*/
#include "GenLinkedList.h"
// Return the link pointer contained within element e at offset o.
#define GETLINK( e, o) ( *(void**)((char*) (e) + (o)) )
#define GETLINK( e, o) ( *(void**)((char*) (e) + (o)) )
// Assign the link pointer l to element e at offset o.
#define ASSIGNLINK( e, l, o) ( *((void**)((char*) (e) + (o))) = (l))
#define ASSIGNLINK( e, l, o) ( *((void**)((char*) (e) + (o))) = (l))
// GenLinkedList /////////////////////////////////////////////////////////////
void InitLinkedList( GenLinkedList *pList, size_t linkOffset)
void InitLinkedList( GenLinkedList *pList, size_t linkOffset)
/* Initialize the block of memory pointed to by pList as a linked list. */
{
pList->Head = NULL;
pList->Tail = NULL;
pList->LinkOffset = linkOffset;
pList->Head = NULL;
pList->Tail = NULL;
pList->LinkOffset = linkOffset;
}
void AddToTail( GenLinkedList *pList, void *elem)
void AddToTail( GenLinkedList *pList, void *elem)
/* Add a linked list element to the tail of the list. */
{
if ( pList->Tail) {
ASSIGNLINK( pList->Tail, elem, pList->LinkOffset);
} else
pList->Head = elem;
ASSIGNLINK( elem, NULL, pList->LinkOffset);
if ( pList->Tail) {
ASSIGNLINK( pList->Tail, elem, pList->LinkOffset);
} else
pList->Head = elem;
ASSIGNLINK( elem, NULL, pList->LinkOffset);
pList->Tail = elem;
pList->Tail = elem;
}
void AddToHead( GenLinkedList *pList, void *elem)
void AddToHead( GenLinkedList *pList, void *elem)
/* Add a linked list element to the head of the list. */
{
ASSIGNLINK( elem, pList->Head, pList->LinkOffset);
if ( pList->Tail == NULL)
pList->Tail = elem;
ASSIGNLINK( elem, pList->Head, pList->LinkOffset);
if ( pList->Tail == NULL)
pList->Tail = elem;
pList->Head = elem;
pList->Head = elem;
}
int RemoveFromList( GenLinkedList *pList, void *elem)
int RemoveFromList( GenLinkedList *pList, void *elem)
/* Remove a linked list element from the list. Return 0 if it was not found. */
/* If the element is removed, its link will be set to NULL. */
{
void *iElem, *lastElem;
void *iElem, *lastElem;
for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset)) {
if ( iElem == elem) {
if ( lastElem) { // somewhere past the head
ASSIGNLINK( lastElem, GETLINK( elem, pList->LinkOffset), pList->LinkOffset);
} else { // at the head
pList->Head = GETLINK( elem, pList->LinkOffset);
}
if ( pList->Tail == elem)
pList->Tail = lastElem ? lastElem : NULL;
ASSIGNLINK( elem, NULL, pList->LinkOffset); // maybe catch a stale reference bug.
return 1;
}
lastElem = iElem;
}
return 0;
for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset)) {
if ( iElem == elem) {
if ( lastElem) { // somewhere past the head
ASSIGNLINK( lastElem, GETLINK( elem, pList->LinkOffset), pList->LinkOffset);
} else { // at the head
pList->Head = GETLINK( elem, pList->LinkOffset);
}
if ( pList->Tail == elem)
pList->Tail = lastElem ? lastElem : NULL;
ASSIGNLINK( elem, NULL, pList->LinkOffset); // maybe catch a stale reference bug.
return 1;
}
lastElem = iElem;
}
return 0;
}
int ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem)
int ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem)
/* Replace an element in the list with a new element, in the same position. */
{
void *iElem, *lastElem;
void *iElem, *lastElem;
if ( elemInList == NULL || newElem == NULL)
return 0;
if ( elemInList == NULL || newElem == NULL)
return 0;
for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset))
{
if ( iElem == elemInList)
{
ASSIGNLINK( newElem, GETLINK( elemInList, pList->LinkOffset), pList->LinkOffset);
if ( lastElem) // somewhere past the head
{
ASSIGNLINK( lastElem, newElem, pList->LinkOffset);
}
else // at the head
{
pList->Head = newElem;
}
if ( pList->Tail == elemInList)
pList->Tail = newElem;
return 1;
}
lastElem = iElem;
}
for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset))
{
if ( iElem == elemInList)
{
ASSIGNLINK( newElem, GETLINK( elemInList, pList->LinkOffset), pList->LinkOffset);
if ( lastElem) // somewhere past the head
{
ASSIGNLINK( lastElem, newElem, pList->LinkOffset);
}
else // at the head
{
pList->Head = newElem;
}
if ( pList->Tail == elemInList)
pList->Tail = newElem;
return 1;
}
lastElem = iElem;
}
return 0;
return 0;
}
// GenDoubleLinkedList /////////////////////////////////////////////////////////
void InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
size_t backLinkOffset)
void InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
size_t backLinkOffset)
/* Initialize the block of memory pointed to by pList as a double linked list. */
{
pList->Head = NULL;
pList->Tail = NULL;
pList->FwdLinkOffset = fwdLinkOffset;
pList->BackLinkOffset = backLinkOffset;
pList->Head = NULL;
pList->Tail = NULL;
pList->FwdLinkOffset = fwdLinkOffset;
pList->BackLinkOffset = backLinkOffset;
}
void DLLAddToHead( GenDoubleLinkedList *pList, void *elem)
void DLLAddToHead( GenDoubleLinkedList *pList, void *elem)
/* Add a linked list element to the head of the list. */
{
void *pNext;
void *pNext;
pNext = pList->Head;
pNext = pList->Head;
// fix up the forward links
ASSIGNLINK( elem, pList->Head, pList->FwdLinkOffset);
pList->Head = elem;
// fix up the forward links
ASSIGNLINK( elem, pList->Head, pList->FwdLinkOffset);
pList->Head = elem;
// fix up the backward links
if ( pNext) {
ASSIGNLINK( pNext, elem, pList->BackLinkOffset);
} else
pList->Tail = elem;
ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
// fix up the backward links
if ( pNext) {
ASSIGNLINK( pNext, elem, pList->BackLinkOffset);
} else
pList->Tail = elem;
ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
}
void DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem)
void DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem)
/* Remove a linked list element from the list. */
/* When the element is removed, its link will be set to NULL. */
{
void *pNext, *pPrev;
void *pNext, *pPrev;
pNext = GETLINK( elem, pList->FwdLinkOffset);
pPrev = GETLINK( elem, pList->BackLinkOffset);
pNext = GETLINK( elem, pList->FwdLinkOffset);
pPrev = GETLINK( elem, pList->BackLinkOffset);
// fix up the forward links
if ( pPrev)
ASSIGNLINK( pPrev, pNext, pList->FwdLinkOffset);
else
pList->Head = pNext;
// fix up the backward links
if ( pNext)
ASSIGNLINK( pNext, pPrev, pList->BackLinkOffset);
else
pList->Tail = pPrev;
// fix up the forward links
if ( pPrev)
ASSIGNLINK( pPrev, pNext, pList->FwdLinkOffset);
else
pList->Head = pNext;
ASSIGNLINK( elem, NULL, pList->FwdLinkOffset);
ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
// fix up the backward links
if ( pNext)
ASSIGNLINK( pNext, pPrev, pList->BackLinkOffset);
else
pList->Tail = pPrev;
ASSIGNLINK( elem, NULL, pList->FwdLinkOffset);
ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
}
// GenLinkedOffsetList /////////////////////////////////////////////////////
// Extract the Next offset from element
#define GETOFFSET( e, o) ( *(size_t*)((char*) (e) + (o)) )
#define GETOFFSET( e, o) ( *(size_t*)((char*) (e) + (o)) )
static void AssignOffsetLink( void *elem, void *link, size_t linkOffset);
static void AssignOffsetLink( void *elem, void *link, size_t linkOffset);
static void AssignOffsetLink( void *elem, void *link, size_t linkOffset)
static void AssignOffsetLink( void *elem, void *link, size_t linkOffset)
// Assign link to elem as an offset from elem. Assign 0 to elem if link is NULL.
{
GETOFFSET( elem, linkOffset) = link ? (size_t) link - (size_t) elem : 0;
GETOFFSET( elem, linkOffset) = link ? (size_t) link - (size_t) elem : 0;
}
void *GetHeadPtr( GenLinkedOffsetList *pList)
void *GetHeadPtr( GenLinkedOffsetList *pList)
/* Return a pointer to the head element of a list, or NULL if none. */
{
return pList->Head ? ( (char*) (pList) + pList->Head) : NULL;
return pList->Head ? ( (char*) (pList) + pList->Head) : NULL;
}
void *GetTailPtr( GenLinkedOffsetList *pList)
void *GetTailPtr( GenLinkedOffsetList *pList)
/* Return a pointer to the tail element of a list, or NULL if none. */
{
return pList->Tail ? ( (char*) (pList) + pList->Tail) : NULL;
return pList->Tail ? ( (char*) (pList) + pList->Tail) : NULL;
}
void *GetOffsetLink( GenLinkedOffsetList *pList, void *elem)
void *GetOffsetLink( GenLinkedOffsetList *pList, void *elem)
/* Return the link pointer contained within element e for pList, or NULL if it is 0. */
{
size_t nextOffset;
size_t nextOffset;
nextOffset = GETOFFSET( elem, pList->LinkOffset);
nextOffset = GETOFFSET( elem, pList->LinkOffset);
return nextOffset ? (char*) elem + nextOffset : NULL;
return nextOffset ? (char*) elem + nextOffset : NULL;
}
void InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset)
void InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset)
/* Initialize the block of memory pointed to by pList as a linked list. */
{
pList->Head = 0;
pList->Tail = 0;
pList->LinkOffset = linkOffset;
pList->Head = 0;
pList->Tail = 0;
pList->LinkOffset = linkOffset;
}
void OffsetAddToTail( GenLinkedOffsetList *pList, void *elem)
void OffsetAddToTail( GenLinkedOffsetList *pList, void *elem)
/* Add a linked list element to the tail of the list. */
{
if ( pList->Tail) {
AssignOffsetLink( GetTailPtr( pList), elem, pList->LinkOffset);
} else
pList->Head = (size_t) elem - (size_t) pList;
AssignOffsetLink( elem, NULL, pList->LinkOffset);
if ( pList->Tail) {
AssignOffsetLink( GetTailPtr( pList), elem, pList->LinkOffset);
} else
pList->Head = (size_t) elem - (size_t) pList;
AssignOffsetLink( elem, NULL, pList->LinkOffset);
pList->Tail = (size_t) elem - (size_t) pList;
pList->Tail = (size_t) elem - (size_t) pList;
}
void OffsetAddToHead( GenLinkedOffsetList *pList, void *elem)
void OffsetAddToHead( GenLinkedOffsetList *pList, void *elem)
/* Add a linked list element to the head of the list. */
{
AssignOffsetLink( elem, GetHeadPtr( pList), pList->LinkOffset);
if ( pList->Tail == 0)
pList->Tail = (size_t) elem - (size_t) pList;
AssignOffsetLink( elem, GetHeadPtr( pList), pList->LinkOffset);
if ( pList->Tail == 0)
pList->Tail = (size_t) elem - (size_t) pList;
pList->Head = (size_t) elem - (size_t) pList;
pList->Head = (size_t) elem - (size_t) pList;
}
int OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem)
int OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem)
/* Remove a linked list element from the list. Return 0 if it was not found. */
/* If the element is removed, its link will be set to NULL. */
{
void *iElem, *lastElem;
void *iElem, *lastElem;
for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
iElem = GetOffsetLink( pList, iElem))
{
if ( iElem == elem) {
if ( lastElem) { // somewhere past the head
AssignOffsetLink( lastElem, GetOffsetLink( pList, elem), pList->LinkOffset);
} else { // at the head
iElem = GetOffsetLink( pList, elem);
pList->Head = iElem ? (size_t) iElem - (size_t) pList : 0;
}
if ( GetTailPtr( pList) == elem)
pList->Tail = lastElem ? (size_t) lastElem - (size_t) pList : 0;
AssignOffsetLink( elem, NULL, pList->LinkOffset); // maybe catch a stale reference bug.
return 1;
}
lastElem = iElem;
}
for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
iElem = GetOffsetLink( pList, iElem))
{
if ( iElem == elem) {
if ( lastElem) { // somewhere past the head
AssignOffsetLink( lastElem, GetOffsetLink( pList, elem), pList->LinkOffset);
} else { // at the head
iElem = GetOffsetLink( pList, elem);
pList->Head = iElem ? (size_t) iElem - (size_t) pList : 0;
}
if ( GetTailPtr( pList) == elem)
pList->Tail = lastElem ? (size_t) lastElem - (size_t) pList : 0;
AssignOffsetLink( elem, NULL, pList->LinkOffset); // maybe catch a stale reference bug.
return 1;
}
lastElem = iElem;
}
return 0;
return 0;
}
int OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem)
int OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem)
/* Replace an element in the list with a new element, in the same position. */
{
void *iElem, *lastElem;
void *iElem, *lastElem;
if ( elemInList == NULL || newElem == NULL)
return 0;
if ( elemInList == NULL || newElem == NULL)
return 0;
for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
iElem = GetOffsetLink( pList, iElem))
{
if ( iElem == elemInList)
{
AssignOffsetLink( newElem, GetOffsetLink( pList, elemInList), pList->LinkOffset);
if ( lastElem) // somewhere past the head
{
AssignOffsetLink( lastElem, newElem, pList->LinkOffset);
}
else // at the head
{
pList->Head = (size_t) newElem - (size_t) pList;
}
if ( GetTailPtr( pList) == elemInList)
pList->Tail = (size_t) newElem - (size_t) pList;
return 1;
}
lastElem = iElem;
}
for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
iElem = GetOffsetLink( pList, iElem))
{
if ( iElem == elemInList)
{
AssignOffsetLink( newElem, GetOffsetLink( pList, elemInList), pList->LinkOffset);
if ( lastElem) // somewhere past the head
{
AssignOffsetLink( lastElem, newElem, pList->LinkOffset);
}
else // at the head
{
pList->Head = (size_t) newElem - (size_t) pList;
}
if ( GetTailPtr( pList) == elemInList)
pList->Tail = (size_t) newElem - (size_t) pList;
return 1;
}
lastElem = iElem;
}
return 0;
return 0;
}

View File

@ -5,34 +5,15 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
File: GenLinkedList.c
Contains: interface to generic linked lists.
Version: 1.0
Tabs: 4 spaces
Change History (most recent first):
$Log: GenLinkedList.h,v $
Revision 1.3 2006/08/14 23:24:56 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/02/05 07:41:08 cheshire
Add Log header
*/
#pragma ident "%Z%%M% %I% %E% SMI"
*/
#ifndef __GenLinkedList__
#define __GenLinkedList__
@ -41,69 +22,69 @@ Add Log header
#include <stddef.h>
struct GenLinkedList
struct GenLinkedList
{
void *Head,
*Tail;
size_t LinkOffset;
void *Head,
*Tail;
size_t LinkOffset;
};
typedef struct GenLinkedList GenLinkedList;
typedef struct GenLinkedList GenLinkedList;
void InitLinkedList( GenLinkedList *pList, size_t linkOffset);
void InitLinkedList( GenLinkedList *pList, size_t linkOffset);
void AddToHead( GenLinkedList *pList, void *elem);
void AddToTail( GenLinkedList *pList, void *elem);
void AddToHead( GenLinkedList *pList, void *elem);
void AddToTail( GenLinkedList *pList, void *elem);
int RemoveFromList( GenLinkedList *pList, void *elem);
int RemoveFromList( GenLinkedList *pList, void *elem);
int ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem);
int ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem);
struct GenDoubleLinkedList
struct GenDoubleLinkedList
{
void *Head,
*Tail;
size_t FwdLinkOffset,
BackLinkOffset;
void *Head,
*Tail;
size_t FwdLinkOffset,
BackLinkOffset;
};
typedef struct GenDoubleLinkedList GenDoubleLinkedList;
typedef struct GenDoubleLinkedList GenDoubleLinkedList;
void InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
size_t backLinkOffset);
void InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
size_t backLinkOffset);
void DLLAddToHead( GenDoubleLinkedList *pList, void *elem);
void DLLAddToHead( GenDoubleLinkedList *pList, void *elem);
void DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem);
void DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem);
/* A GenLinkedOffsetList is like a GenLinkedList that stores the *Next field as a signed */
/* offset from the address of the beginning of the element, rather than as a pointer. */
struct GenLinkedOffsetList
struct GenLinkedOffsetList
{
size_t Head,
Tail;
size_t LinkOffset;
size_t Head,
Tail;
size_t LinkOffset;
};
typedef struct GenLinkedOffsetList GenLinkedOffsetList;
typedef struct GenLinkedOffsetList GenLinkedOffsetList;
void InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset);
void InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset);
void *GetHeadPtr( GenLinkedOffsetList *pList);
void *GetTailPtr( GenLinkedOffsetList *pList);
void *GetOffsetLink( GenLinkedOffsetList *pList, void *elem);
void *GetHeadPtr( GenLinkedOffsetList *pList);
void *GetTailPtr( GenLinkedOffsetList *pList);
void *GetOffsetLink( GenLinkedOffsetList *pList, void *elem);
void OffsetAddToHead( GenLinkedOffsetList *pList, void *elem);
void OffsetAddToTail( GenLinkedOffsetList *pList, void *elem);
void OffsetAddToHead( GenLinkedOffsetList *pList, void *elem);
void OffsetAddToTail( GenLinkedOffsetList *pList, void *elem);
int OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem);
int OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem);
int OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem);
int OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem);
#endif // __GenLinkedList__

View File

@ -20,6 +20,7 @@
#
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
# Copyright 2016 Toomas Soome <tsoome@me.com>
#
PROG= mdnsd
@ -32,15 +33,15 @@ CMN_SRCS= $(CMN_OBJS:%.o=$(CMN_DIR)/%.c)
LOCAL_OBJS= DNSCommon.o DNSDigest.o GenLinkedList.o \
PlatformCommon.o PosixDaemon.o \
mDNS.o mDNSDebug.o mDNSPosix.o mDNSUNP.o \
uDNS.o uds_daemon.o
uDNS.o uds_daemon.o CryptoAlg.o anonymous.o
LOCAL_SRCS= $(LOCAL_OBJS:%.o=%.c)
SRCS= $(LOCAL_SRCS) $(CMN_SRCS)
OBJS= $(LOCAL_OBJS) $(CMN_OBJS)
MDNSFLAGS= -DNOT_HAVE_DAEMON -DNOT_HAVE_SA_LEN \
-DLOG_PERROR=0 -DHAVE_SOLARIS \
MDNSFLAGS= -DNOT_HAVE_SA_LEN \
-DLOG_PERROR=0 -DHAVE_SOLARIS -DTARGET_OS_SOLARIS \
-D_XPG4_2 -D__EXTENSIONS__ -DHAVE_BROKEN_RECVIF_NAME \
-DHAVE_IPV6=1 -Dasm=__asm -DMDNSD_NOROOT \
-DPID_FILE=\"\" -DMDNSD_USER=\"noaccess\" \

View File

@ -5,134 +5,195 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: PlatformCommon.c,v $
Revision 1.7 2006/08/14 23:24:56 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.6 2005/04/08 21:30:16 ksekar
<rdar://problem/4007457> Compiling problems with mDNSResponder-98 on Solaris/Sparc v9
Patch submitted by Bernd Kuhls
Revision 1.5 2005/02/01 19:33:30 ksekar
<rdar://problem/3985239> Keychain format too restrictive
Revision 1.4 2005/01/19 19:19:21 ksekar
<rdar://problem/3960191> Need a way to turn off domain discovery
Revision 1.3 2004/12/13 17:46:52 cheshire
Use sizeof(buf) instead of fixed constant 1024
Revision 1.2 2004/12/01 03:30:29 cheshire
<rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
Revision 1.1 2004/12/01 01:51:35 cheshire
Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h> // Needed for fopen() etc.
#include <unistd.h> // Needed for close()
#include <string.h> // Needed for strlen() etc.
#include <errno.h> // Needed for errno etc.
#include <sys/socket.h> // Needed for socket() etc.
#include <netinet/in.h> // Needed for sockaddr_in
#include <syslog.h>
#include <stdio.h> // Needed for fopen() etc.
#include <unistd.h> // Needed for close()
#include <string.h> // Needed for strlen() etc.
#include <errno.h> // Needed for errno etc.
#include <sys/socket.h> // Needed for socket() etc.
#include <netinet/in.h> // Needed for sockaddr_in
#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
#include "DNSCommon.h"
#include "PlatformCommon.h"
#ifdef NOT_HAVE_SOCKLEN_T
typedef unsigned int socklen_t;
typedef unsigned int socklen_t;
#endif
// Bind a UDP socket to a global destination to find the default route's interface address
mDNSexport void FindDefaultRouteIP(mDNSAddr *a)
{
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
int sock = socket(AF_INET,SOCK_DGRAM,0);
a->type = mDNSAddrType_None;
if (sock == -1) return;
addr.sin_family = AF_INET;
addr.sin_port = 1; // Not important, any port and public address will do
addr.sin_addr.s_addr = 0x11111111;
if ((connect(sock,(const struct sockaddr*)&addr,sizeof(addr))) == -1) { close(sock); return; }
if ((getsockname(sock,(struct sockaddr*)&addr, &len)) == -1) { close(sock); return; }
close(sock);
a->type = mDNSAddrType_IPv4;
a->ip.v4.NotAnInteger = addr.sin_addr.s_addr;
}
// Bind a UDP socket to find the source address to a destination
mDNSexport void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst)
{
union { struct sockaddr s; struct sockaddr_in a4; struct sockaddr_in6 a6; } addr;
socklen_t len = sizeof(addr);
socklen_t inner_len = 0;
int sock = socket(AF_INET, SOCK_DGRAM, 0);
src->type = mDNSAddrType_None;
if (sock == -1) return;
if (dst->type == mDNSAddrType_IPv4)
{
inner_len = sizeof(addr.a4);
#ifndef NOT_HAVE_SA_LEN
addr.a4.sin_len = inner_len;
#endif
addr.a4.sin_family = AF_INET;
addr.a4.sin_port = 1; // Not important, any port will do
addr.a4.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
}
else if (dst->type == mDNSAddrType_IPv6)
{
inner_len = sizeof(addr.a6);
#ifndef NOT_HAVE_SA_LEN
addr.a6.sin6_len = inner_len;
#endif
addr.a6.sin6_family = AF_INET6;
addr.a6.sin6_flowinfo = 0;
addr.a6.sin6_port = 1; // Not important, any port will do
addr.a6.sin6_addr = *(struct in6_addr*)&dst->ip.v6;
addr.a6.sin6_scope_id = 0;
}
else return;
if ((connect(sock, &addr.s, inner_len)) < 0)
{ if (errno != ENETUNREACH) LogMsg("mDNSPlatformSourceAddrForDest: connect %#a failed errno %d (%s)", dst, errno, strerror(errno)); goto exit; }
if ((getsockname(sock, &addr.s, &len)) < 0)
{ LogMsg("mDNSPlatformSourceAddrForDest: getsockname failed errno %d (%s)", errno, strerror(errno)); goto exit; }
src->type = dst->type;
if (dst->type == mDNSAddrType_IPv4) src->ip.v4.NotAnInteger = addr.a4.sin_addr.s_addr;
else src->ip.v6 = *(mDNSv6Addr*)&addr.a6.sin6_addr;
exit:
close(sock);
}
// dst must be at least MAX_ESCAPED_DOMAIN_NAME bytes, and option must be less than 32 bytes in length
mDNSlocal mDNSBool GetConfigOption(char *dst, const char *option, FILE *f)
{
char buf[32+1+MAX_ESCAPED_DOMAIN_NAME]; // Option name, one space, option value
unsigned int len = strlen(option);
if (len + 1 + MAX_ESCAPED_DOMAIN_NAME > sizeof(buf)-1) { LogMsg("GetConfigOption: option %s too long", option); return mDNSfalse; }
fseek(f, 0, SEEK_SET); // set position to beginning of stream
while (fgets(buf, sizeof(buf), f)) // Read at most sizeof(buf)-1 bytes from file, and append '\0' C-string terminator
{
if (!strncmp(buf, option, len))
{
strncpy(dst, buf + len + 1, MAX_ESCAPED_DOMAIN_NAME-1);
if (dst[MAX_ESCAPED_DOMAIN_NAME-1]) dst[MAX_ESCAPED_DOMAIN_NAME-1] = '\0';
len = strlen(dst);
if (len && dst[len-1] == '\n') dst[len-1] = '\0'; // chop newline
return mDNStrue;
}
}
debugf("Option %s not set", option);
return mDNSfalse;
}
{
char buf[32+1+MAX_ESCAPED_DOMAIN_NAME]; // Option name, one space, option value
unsigned int len = strlen(option);
if (len + 1 + MAX_ESCAPED_DOMAIN_NAME > sizeof(buf)-1) { LogMsg("GetConfigOption: option %s too long", option); return mDNSfalse; }
fseek(f, 0, SEEK_SET); // set position to beginning of stream
while (fgets(buf, sizeof(buf), f)) // Read at most sizeof(buf)-1 bytes from file, and append '\0' C-string terminator
{
if (!strncmp(buf, option, len))
{
strncpy(dst, buf + len + 1, MAX_ESCAPED_DOMAIN_NAME-1);
if (dst[MAX_ESCAPED_DOMAIN_NAME-1]) dst[MAX_ESCAPED_DOMAIN_NAME-1] = '\0';
len = strlen(dst);
if (len && dst[len-1] == '\n') dst[len-1] = '\0'; // chop newline
return mDNStrue;
}
}
debugf("Option %s not set", option);
return mDNSfalse;
}
mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled)
{
char buf [MAX_ESCAPED_DOMAIN_NAME];
char secret[MAX_ESCAPED_DOMAIN_NAME] = "";
mStatus err;
FILE *f = fopen(filename, "r");
{
char buf[MAX_ESCAPED_DOMAIN_NAME] = "";
mStatus err;
FILE *f = fopen(filename, "r");
if (hostname) hostname->c[0] = 0;
if (domain) domain->c[0] = 0;
if (DomainDiscoveryDisabled) *DomainDiscoveryDisabled = mDNSfalse;
if (hostname) hostname->c[0] = 0;
if (domain) domain->c[0] = 0;
if (DomainDiscoveryDisabled) *DomainDiscoveryDisabled = mDNSfalse;
if (f)
{
if (DomainDiscoveryDisabled && GetConfigOption(buf, "DomainDiscoveryDisabled", f) && !strcasecmp(buf, "true")) *DomainDiscoveryDisabled = mDNStrue;
if (hostname && GetConfigOption(buf, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, buf)) goto badf;
if (domain && GetConfigOption(buf, "zone", f) && !MakeDomainNameFromDNSNameString(domain, buf)) goto badf;
GetConfigOption(secret, "secret-64", f); // failure means no authentication
fclose(f);
f = NULL;
}
else
{
if (errno != ENOENT) LogMsg("ERROR: Config file exists, but cannot be opened.");
return;
}
if (f)
{
if (DomainDiscoveryDisabled && GetConfigOption(buf, "DomainDiscoveryDisabled", f) && !strcasecmp(buf, "true")) *DomainDiscoveryDisabled = mDNStrue;
if (hostname && GetConfigOption(buf, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, buf)) goto badf;
if (domain && GetConfigOption(buf, "zone", f) && !MakeDomainNameFromDNSNameString(domain, buf)) goto badf;
buf[0] = 0;
GetConfigOption(buf, "secret-64", f); // failure means no authentication
fclose(f);
f = NULL;
}
else
{
if (errno != ENOENT) LogMsg("ERROR: Config file exists, but cannot be opened.");
return;
}
if (domain && domain->c[0] && secret[0])
{
// for now we assume keyname = service reg domain and we use same key for service and hostname registration
err = mDNS_SetSecretForZone(m, domain, domain, secret);
if (err) LogMsg("ERROR: mDNS_SetSecretForZone returned %d for domain %##s", err, domain->c);
}
if (domain && domain->c[0] && buf[0])
{
DomainAuthInfo *info = (DomainAuthInfo*)mDNSPlatformMemAllocate(sizeof(*info));
// for now we assume keyname = service reg domain and we use same key for service and hostname registration
err = mDNS_SetSecretForDomain(m, info, domain, domain, buf, NULL, 0, mDNSfalse);
if (err) LogMsg("ERROR: mDNS_SetSecretForDomain returned %d for domain %##s", err, domain->c);
}
return;
return;
badf:
LogMsg("ERROR: malformatted config file");
if (f) fclose(f);
}
badf:
LogMsg("ERROR: malformatted config file");
if (f) fclose(f);
}
#if MDNS_DEBUGMSGS
mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
{
fprintf(stderr,"%s\n", msg);
fflush(stderr);
}
#endif
mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, mDNSLogLevel_t loglevel)
{
#if APPLE_OSX_mDNSResponder && LogTimeStamps
extern mDNS mDNSStorage;
extern mDNSu32 mDNSPlatformClockDivisor;
mDNSs32 t = mDNSStorage.timenow ? mDNSStorage.timenow : mDNSPlatformClockDivisor ? mDNS_TimeNow_NoLock(&mDNSStorage) : 0;
int ms = ((t < 0) ? -t : t) % 1000;
#endif
if (mDNS_DebugMode) // In debug mode we write to stderr
{
#if APPLE_OSX_mDNSResponder && LogTimeStamps
if (ident && ident[0] && mDNSPlatformClockDivisor)
fprintf(stderr,"%8d.%03d: %s\n", (int)(t/1000), ms, buffer);
else
#endif
fprintf(stderr,"%s\n", buffer);
fflush(stderr);
}
else // else, in production mode, we write to syslog
{
static int log_inited = 0;
int syslog_level = LOG_ERR;
switch (loglevel)
{
case MDNS_LOG_MSG: syslog_level = LOG_ERR; break;
case MDNS_LOG_OPERATION: syslog_level = LOG_WARNING; break;
case MDNS_LOG_SPS: syslog_level = LOG_NOTICE; break;
case MDNS_LOG_INFO: syslog_level = LOG_INFO; break;
case MDNS_LOG_DEBUG: syslog_level = LOG_DEBUG; break;
default:
fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel);
fflush(stderr);
}
if (!log_inited) { openlog(ident, LOG_CONS, LOG_DAEMON); log_inited++; }
#if APPLE_OSX_mDNSResponder && LogTimeStamps
if (ident && ident[0] && mDNSPlatformClockDivisor)
syslog(syslog_level, "%8d.%03d: %s", (int)(t/1000), ms, buffer);
else
#elif APPLE_OSX_mDNSResponder
mDNSPlatformLogToFile(syslog_level, buffer);
#else
syslog(syslog_level, "%s", buffer);
#endif
}
}

View File

@ -5,33 +5,14 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: PlatformCommon.h,v $
Revision 1.4 2006/08/14 23:24:56 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.3 2005/01/19 19:19:21 ksekar
<rdar://problem/3960191> Need a way to turn off domain discovery
Revision 1.2 2004/12/01 03:30:29 cheshire
<rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
Revision 1.1 2004/12/01 01:51:35 cheshire
Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
*/
#pragma ident "%Z%%M% %I% %E% SMI"
extern void FindDefaultRouteIP(mDNSAddr *a);
extern void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled);

View File

@ -5,119 +5,28 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
File: daemon.c
File: daemon.c
Contains: main & associated Application layer for mDNSResponder on Linux.
Contains: main & associated Application layer for mDNSResponder on Linux.
Change History (most recent first):
*/
$Log: PosixDaemon.c,v $
Revision 1.29.2.1 2006/08/29 06:24:34 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.29 2005/08/04 03:37:45 mkrochma
Temporary workaround to fix posix after mDNS_SetPrimaryInterfaceInfo changed
Revision 1.28 2005/07/19 11:21:09 cheshire
<rdar://problem/4170449> Unix Domain Socket leak in mdnsd
Revision 1.27 2005/02/04 00:39:59 cheshire
Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
Revision 1.26 2005/02/02 02:21:30 cheshire
Update references to "mDNSResponder" to say "mdnsd" instead
Revision 1.25 2005/01/27 20:01:50 cheshire
udsSupportRemoveFDFromEventLoop() needs to close the file descriptor as well
Revision 1.24 2005/01/19 19:20:49 ksekar
<rdar://problem/3960191> Need a way to turn off domain discovery
Revision 1.23 2004/12/16 20:17:11 cheshire
<rdar://problem/3324626> Cache memory management improvements
Revision 1.22 2004/12/10 13:12:08 cheshire
Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
Revision 1.21 2004/12/01 20:57:20 ksekar
<rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
Revision 1.20 2004/12/01 04:28:43 cheshire
<rdar://problem/3872803> Darwin patches for Solaris and Suse
Use version of daemon() provided in mDNSUNP.c instead of local copy
Revision 1.19 2004/12/01 03:30:29 cheshire
<rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
Revision 1.18 2004/11/30 22:45:59 cheshire
Minor code tidying
Revision 1.17 2004/11/30 22:18:59 cheshire
<rdar://problem/3889351> Posix needs to read the list of unicast DNS servers and set server list
Revision 1.16 2004/09/21 21:05:12 cheshire
Move duplicate code out of mDNSMacOSX/daemon.c and mDNSPosix/PosixDaemon.c,
into mDNSShared/uds_daemon.c
Revision 1.15 2004/09/17 01:08:53 cheshire
Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
declared in that file are ONLY appropriate to single-address-space embedded applications.
For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
Revision 1.14 2004/09/16 00:24:49 cheshire
<rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
Revision 1.13 2004/08/11 01:59:41 cheshire
Remove "mDNS *globalInstance" parameter from udsserver_init()
Revision 1.12 2004/06/28 23:19:19 cheshire
Fix "Daemon_Init declared but never defined" warning on Linux
Revision 1.11 2004/06/25 00:26:27 rpantos
Changes to fix the Posix build on Solaris.
Revision 1.10 2004/06/08 04:59:40 cheshire
Tidy up wording -- log messages are already prefixed with "mDNSResponder", so don't need to repeat it
Revision 1.9 2004/05/29 00:14:20 rpantos
<rdar://problem/3508093> Runtime check to disable prod mdnsd on OS X.
Revision 1.8 2004/04/07 01:19:04 cheshire
Hash slot value should be unsigned
Revision 1.7 2004/02/14 06:34:57 cheshire
Use LogMsg instead of fprintf( stderr
Revision 1.6 2004/02/14 01:10:42 rpantos
Allow daemon to run if 'nobody' is not defined, with a warning. (For Roku HD1000.)
Revision 1.5 2004/02/05 07:45:43 cheshire
Add Log header
Revision 1.4 2004/01/28 21:14:23 cheshire
Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
Revision 1.3 2004/01/19 19:51:46 cheshire
Fix compiler error (mixed declarations and code) on some versions of Linux
Revision 1.2 2003/12/11 03:03:51 rpantos
Clean up mDNSPosix so that it builds on OS X again.
Revision 1.1 2003/12/08 20:47:02 rpantos
Add support for mDNSResponder on Linux.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#if __APPLE__
// In Mac OS X 10.5 and later trying to use the daemon function gives a “daemon is deprecated”
// error, which prevents compilation because we build with "-Werror".
// Since this is supposed to be portable cross-platform code, we don't care that daemon is
// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
#endif
#include <stdio.h>
#include <string.h>
@ -129,12 +38,16 @@ Add support for mDNSResponder on Linux.
#include <pwd.h>
#include <sys/types.h>
#if __APPLE__
#undef daemon
extern int daemon(int, int);
#endif
#include "mDNSEmbeddedAPI.h"
#include "mDNSDebug.h"
#include "mDNSPosix.h"
#include "mDNSUNP.h" // For daemon()
#include "uds_daemon.h"
#include "PlatformCommon.h"
#include "mDNSUNP.h"
#ifndef MDNSD_USER
#define MDNSD_USER "nobody"
@ -146,226 +59,225 @@ static domainname DynDNSHostname;
#define RR_CACHE_SIZE 500
static CacheEntity gRRCache[RR_CACHE_SIZE];
static mDNS_PlatformSupport PlatformStorage;
extern const char mDNSResponderVersionString[];
mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
{
(void)m; // Unused
if (result == mStatus_NoError)
{
// On successful registration of dot-local mDNS host name, daemon may want to check if
// any name conflict and automatic renaming took place, and if so, record the newly negotiated
// name in persistent storage for next time. It should also inform the user of the name change.
// On Mac OS X we store the current dot-local mDNS host name in the SCPreferences store,
// and notify the user with a CFUserNotification.
}
else if (result == mStatus_ConfigChanged)
{
udsserver_handle_configchange(m);
}
else if (result == mStatus_GrowCache)
{
// Allocate another chunk of cache storage
CacheEntity *storage = malloc(sizeof(CacheEntity) * RR_CACHE_SIZE);
if (storage) mDNS_GrowCache(m, storage, RR_CACHE_SIZE);
}
}
// %%% Reconfigure() probably belongs in the platform support layer (mDNSPosix.c), not the daemon cde
// -- all client layers running on top of mDNSPosix.c need to handle network configuration changes,
// not only the Unix Domain Socket Daemon
static void Reconfigure(mDNS *m)
{
mDNSAddr DynDNSIP;
mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
mDNS_DeleteDNSServers(m);
if (ParseDNSServers(m, uDNS_SERVERS_FILE) < 0)
LogMsgNoIdent("Unable to parse DNS server list. Unicast DNS-SD unavailable");
ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &DynDNSHostname, &DynDNSZone, NULL);
FindDefaultRouteIP(&DynDNSIP);
if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
if (DynDNSIP.type) mDNS_SetPrimaryInterfaceInfo(m, &DynDNSIP, NULL, NULL);
}
{
mDNSAddr DynDNSIP;
const mDNSAddr dummy = { mDNSAddrType_IPv4, { { { 1, 1, 1, 1 } } } };;
mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
if (ParseDNSServers(m, uDNS_SERVERS_FILE) < 0)
LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &DynDNSHostname, &DynDNSZone, NULL);
mDNSPlatformSourceAddrForDest(&DynDNSIP, &dummy);
if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
if (DynDNSIP.type) mDNS_SetPrimaryInterfaceInfo(m, &DynDNSIP, NULL, NULL);
mDNS_ConfigChanged(m);
}
// Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
static void ParseCmdLinArgs(int argc, char **argv)
{
if (argc > 1)
{
if (0 == strcmp(argv[1], "-debug")) mDNS_DebugMode = mDNStrue;
else printf("Usage: %s [-debug]\n", argv[0]);
}
mDNSlocal void ParseCmdLinArgs(int argc, char **argv)
{
if (argc > 1)
{
if (0 == strcmp(argv[1], "-debug")) mDNS_DebugMode = mDNStrue;
else printf("Usage: %s [-debug]\n", argv[0]);
}
if (!mDNS_DebugMode)
{
int result = daemon(0, 0);
if (result != 0) { LogMsg("Could not run as daemon - exiting"); exit(result); }
if (!mDNS_DebugMode)
{
int result = daemon(0, 0);
if (result != 0) { LogMsg("Could not run as daemon - exiting"); exit(result); }
#if __APPLE__
LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
exit(-1);
LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
exit(-1);
#endif
}
}
}
}
static void DumpStateLog(mDNS *const m)
mDNSlocal void ToggleLog(void)
{
mDNS_LoggingEnabled = !mDNS_LoggingEnabled;
}
mDNSlocal void ToggleLogPacket(void)
{
mDNS_PacketLoggingEnabled = !mDNS_PacketLoggingEnabled;
}
mDNSlocal void DumpStateLog(mDNS *const m)
// Dump a little log of what we've been up to.
{
LogMsgIdent(mDNSResponderVersionString, "---- BEGIN STATE LOG ----");
udsserver_info(m);
LogMsgIdent(mDNSResponderVersionString, "---- END STATE LOG ----");
}
{
LogMsg("---- BEGIN STATE LOG ----");
udsserver_info(m);
LogMsg("---- END STATE LOG ----");
}
static mStatus MainLoop(mDNS *m) // Loop until we quit.
{
sigset_t signals;
mDNSBool gotData = mDNSfalse;
mDNSlocal mStatus MainLoop(mDNS *m) // Loop until we quit.
{
sigset_t signals;
mDNSBool gotData = mDNSfalse;
mDNSPosixListenForSignalInEventLoop(SIGINT);
mDNSPosixListenForSignalInEventLoop(SIGTERM);
mDNSPosixListenForSignalInEventLoop(SIGUSR1);
mDNSPosixListenForSignalInEventLoop(SIGPIPE);
mDNSPosixListenForSignalInEventLoop(SIGHUP) ;
mDNSPosixListenForSignalInEventLoop(SIGINT);
mDNSPosixListenForSignalInEventLoop(SIGTERM);
mDNSPosixListenForSignalInEventLoop(SIGUSR1);
mDNSPosixListenForSignalInEventLoop(SIGUSR2);
mDNSPosixListenForSignalInEventLoop(SIGINFO);
mDNSPosixListenForSignalInEventLoop(SIGPIPE);
mDNSPosixListenForSignalInEventLoop(SIGHUP) ;
for (; ;)
{
// Work out how long we expect to sleep before the next scheduled task
struct timeval timeout;
mDNSs32 ticks;
for (; ;)
{
// Work out how long we expect to sleep before the next scheduled task
struct timeval timeout;
mDNSs32 ticks;
// Only idle if we didn't find any data the last time around
if (!gotData)
{
mDNSs32 nextTimerEvent = mDNS_Execute(m);
nextTimerEvent = udsserver_idle(nextTimerEvent);
ticks = nextTimerEvent - mDNS_TimeNow(m);
if (ticks < 1) ticks = 1;
}
else // otherwise call EventLoop again with 0 timemout
ticks = 0;
// Only idle if we didn't find any data the last time around
if (!gotData)
{
mDNSs32 nextTimerEvent = mDNS_Execute(m);
nextTimerEvent = udsserver_idle(nextTimerEvent);
ticks = nextTimerEvent - mDNS_TimeNow(m);
if (ticks < 1) ticks = 1;
}
else // otherwise call EventLoop again with 0 timemout
ticks = 0;
timeout.tv_sec = ticks / mDNSPlatformOneSecond;
timeout.tv_usec = (ticks % mDNSPlatformOneSecond) * 1000000 / mDNSPlatformOneSecond;
timeout.tv_sec = ticks / mDNSPlatformOneSecond;
timeout.tv_usec = (ticks % mDNSPlatformOneSecond) * 1000000 / mDNSPlatformOneSecond;
(void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData);
(void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData);
if (sigismember(&signals, SIGHUP )) Reconfigure(m);
if (sigismember(&signals, SIGUSR1)) DumpStateLog(m);
// SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
if (sigismember(&signals, SIGPIPE)) LogMsg("Received SIGPIPE - ignoring");
if (sigismember(&signals, SIGINT) || sigismember(&signals, SIGTERM)) break;
}
return EINTR;
}
if (sigismember(&signals, SIGHUP )) Reconfigure(m);
if (sigismember(&signals, SIGINFO)) DumpStateLog(m);
if (sigismember(&signals, SIGUSR1)) ToggleLog();
if (sigismember(&signals, SIGUSR2)) ToggleLogPacket();
// SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
if (sigismember(&signals, SIGPIPE)) LogMsg("Received SIGPIPE - ignoring");
if (sigismember(&signals, SIGINT) || sigismember(&signals, SIGTERM)) break;
}
return EINTR;
}
int main(int argc, char **argv)
{
#define mDNSRecord mDNSStorage
mDNS_PlatformSupport platformStorage;
mStatus err;
int main(int argc, char **argv)
{
mStatus err;
bzero(&mDNSRecord, sizeof mDNSRecord);
bzero(&platformStorage, sizeof platformStorage);
ParseCmdLinArgs(argc, argv);
ParseCmdLinArgs(argc, argv);
LogInfo("%s starting", mDNSResponderVersionString);
LogMsgIdent(mDNSResponderVersionString, "starting");
err = mDNS_Init(&mDNSStorage, &PlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses,
mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
err = mDNS_Init(&mDNSRecord, &platformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses,
mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
if (mStatus_NoError == err)
err = udsserver_init(mDNSNULL, 0);
if (mStatus_NoError == err)
err = udsserver_init();
Reconfigure(&mDNSRecord);
Reconfigure(&mDNSStorage);
// Now that we're finished with anything privileged, switch over to running as "nobody"
if (mStatus_NoError == err)
{
const struct passwd *pw = getpwnam(MDNSD_USER);
if (pw != NULL)
setuid(pw->pw_uid);
else
// Now that we're finished with anything privileged, switch over to running as "nobody"
if (mStatus_NoError == err)
{
const struct passwd *pw = getpwnam(MDNSD_USER);
if (pw != NULL)
setuid(pw->pw_uid);
else
#ifdef MDNSD_NOROOT
{
LogMsg("WARNING: mdnsd exiting because user \""MDNSD_USER"\" does not exist");
err = mStatus_Invalid;
}
#else
LogMsg("WARNING: mdnsd continuing as root because user \""MDNSD_USER"\" does not exist");
#endif
}
if (mStatus_NoError == err)
err = MainLoop(&mDNSRecord);
LogMsgIdent(mDNSResponderVersionString, "stopping");
mDNS_Close(&mDNSRecord);
if (udsserver_exit() < 0)
LogMsg("ExitCallback: udsserver_exit failed");
#if MDNS_DEBUGMSGS > 0
printf("mDNSResponder exiting normally with %ld\n", err);
#endif
return err;
{
LogMsg("WARNING: mdnsd exiting because user \""MDNSD_USER"\" does not exist");
err = mStatus_Invalid;
}
#else
LogMsg("WARNING: mdnsd continuing as root because user \""MDNSD_USER"\" does not exist");
#endif
}
if (mStatus_NoError == err)
err = MainLoop(&mDNSStorage);
LogInfo("%s stopping", mDNSResponderVersionString);
mDNS_Close(&mDNSStorage);
if (udsserver_exit() < 0)
LogMsg("ExitCallback: udsserver_exit failed");
#if MDNS_DEBUGMSGS > 0
printf("mDNSResponder exiting normally with %ld\n", err);
#endif
return err;
}
// uds_daemon support ////////////////////////////////////////////////////////////
#undef LogMalloc
#if MDNS_MALLOC_DEBUGGING >= 2
#define LogMalloc LogMsg
#else
#define LogMalloc(ARGS...) ((void)0)
#endif
mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context)
mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context, void **platform_data)
/* Support routine for uds_daemon.c */
{
// Depends on the fact that udsEventCallback == mDNSPosixEventCallback
return mDNSPosixAddFDToEventLoop(fd, callback, context);
}
{
// Depends on the fact that udsEventCallback == mDNSPosixEventCallback
(void) platform_data;
return mDNSPosixAddFDToEventLoop(fd, callback, context);
}
mStatus udsSupportRemoveFDFromEventLoop(int fd) // Note: This also CLOSES the file descriptor
{
mStatus err = mDNSPosixRemoveFDFromEventLoop(fd);
close(fd);
return err;
}
int udsSupportReadFD(dnssd_sock_t fd, char *buf, int len, int flags, void *platform_data)
{
(void) platform_data;
return recv(fd, buf, len, flags);
}
mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data) // Note: This also CLOSES the file descriptor
{
mStatus err = mDNSPosixRemoveFDFromEventLoop(fd);
(void) platform_data;
close(fd);
return err;
}
mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
{
(void)m;
(void)delay;
// No-op, for now
}
{
(void)m;
(void)delay;
// No-op, for now
}
#if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
void *mallocL(char *msg, unsigned int size)
{
unsigned long *mem = malloc(size+8);
if (!mem)
{
LogMsg("malloc( %s : %d ) failed", msg, size);
return(NULL);
}
else
{
LogMalloc("malloc( %s : %lu ) = %p", msg, size, &mem[2]);
mem[0] = 0xDEAD1234;
mem[1] = size;
//bzero(&mem[2], size);
memset(&mem[2], 0xFF, size);
// validatelists(&mDNSStorage);
return(&mem[2]);
}
}
void freeL(char *msg, void *x)
{
if (!x)
LogMsg("free( %s @ NULL )!", msg);
else
{
unsigned long *mem = ((unsigned long *)x) - 2;
if (mem[0] != 0xDEAD1234)
{ LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg, &mem[2]); return; }
if (mem[1] > 8000)
{ LogMsg("free( %s : %ld @ %p) too big!", msg, mem[1], &mem[2]); return; }
LogMalloc("free( %s : %ld @ %p)", msg, mem[1], &mem[2]);
//bzero(mem, mem[1]+8);
memset(mem, 0xDD, mem[1]+8);
// validatelists(&mDNSStorage);
free(mem);
}
}
#endif // MACOSX_MDNS_MALLOC_DEBUGGING >= 1
#if _BUILDING_XCODE_PROJECT_
// If the process crashes, then this string will be magically included in the automatically-generated crash log
const char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5;
asm (".desc ___crashreporter_info__, 0x10");
#endif
// For convenience when using the "strings" command, this is the last thing in the file
#if mDNSResponderVersion > 1
mDNSexport const char mDNSResponderVersionString[] = "mDNSResponder-" STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ") ";
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder-" STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
#elif MDNS_VERSIONSTR_NODTS
mDNSexport const char mDNSResponderVersionString[] = "mDNSResponder (Engineering Build) ";
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build)";
#else
mDNSexport const char mDNSResponderVersionString[] = "mDNSResponder (Engineering Build) (" __DATE__ " " __TIME__ ") ";
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build) (" __DATE__ " " __TIME__ ")";
#endif

View File

@ -1,13 +1,13 @@
* Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
The majority of the source code in the mDNSResponder project is licensed
under the terms of the Apache License, Version 2.0, available from:
<http://www.apache.org/licenses/LICENSE-2.0>
To accommodate license compatibility with the widest possible range
of client code licenses, the shared library code, which is linked
at runtime into the same address space as the client using it, is
licensed under the terms of the "Three-Clause BSD License".
The Linux Name Service Switch code, contributed by National ICT
Australia Ltd (NICTA) is licensed under the terms of the NICTA Public
Software Licence (which is substantially similar to the "Three-Clause
BSD License", with some additional language pertaining to Australian law).

View File

@ -0,0 +1,597 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2012 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mDNSEmbeddedAPI.h"
#include "CryptoAlg.h"
#include "anonymous.h"
#include "DNSCommon.h"
// Define ANONYMOUS_DISABLED to remove all the anonymous functionality
// and use the stub functions implemented later in this file.
#ifndef ANONYMOUS_DISABLED
#define ANON_NSEC3_ITERATIONS 1
mDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonData, int len, mDNSu32 salt)
{
const mDNSu8 *ptr;
rdataNSEC3 *nsec3 = (rdataNSEC3 *)rr->rdata->u.data;
mDNSu8 *tmp, *nxt;
unsigned short iter = ANON_NSEC3_ITERATIONS;
int hlen;
const mDNSu8 hashName[NSEC3_MAX_HASH_LEN];
// Construct the RDATA first and construct the owner name based on that.
ptr = (const mDNSu8 *)&salt;
debugf("InitializeNSEC3Record: %x%x%x%x, name %##s", ptr[0], ptr[1], ptr[2], ptr[3], rr->name->c);
// Set the RDATA
nsec3->alg = SHA1_DIGEST_TYPE;
nsec3->flags = 0;
nsec3->iterations = swap16(iter);
nsec3->saltLength = 4;
tmp = (mDNSu8 *)&nsec3->salt;
*tmp++ = ptr[0];
*tmp++ = ptr[1];
*tmp++ = ptr[2];
*tmp++ = ptr[3];
// hashLength, nxt, bitmap
*tmp++ = SHA1_HASH_LENGTH; // hash length
nxt = tmp;
tmp += SHA1_HASH_LENGTH;
*tmp++ = 0; // window number
*tmp++ = NSEC_MCAST_WINDOW_SIZE; // window length
mDNSPlatformMemZero(tmp, NSEC_MCAST_WINDOW_SIZE);
tmp[kDNSType_PTR >> 3] |= 128 >> (kDNSType_PTR & 7);
// Hash the base service name + salt + AnonData
if (!NSEC3HashName(rr->name, nsec3, AnonData, len, hashName, &hlen))
{
LogMsg("InitializeNSEC3Record: NSEC3HashName failed for ##s", rr->name->c);
return mDNSfalse;
}
if (hlen != SHA1_HASH_LENGTH)
{
LogMsg("InitializeNSEC3Record: hlen wrong %d", hlen);
return mDNSfalse;
}
mDNSPlatformMemCopy(nxt, hashName, hlen);
return mDNStrue;
}
mDNSlocal ResourceRecord *ConstructNSEC3Record(const domainname *service, const mDNSu8 *AnonData, int len, mDNSu32 salt)
{
ResourceRecord *rr;
int dlen;
domainname *name;
// We are just allocating an RData which has StandardAuthRDSize
if (StandardAuthRDSize < MCAST_NSEC3_RDLENGTH)
{
LogMsg("ConstructNSEC3Record: StandardAuthRDSize %d smaller than MCAST_NSEC3_RDLENGTH %d", StandardAuthRDSize, MCAST_NSEC3_RDLENGTH);
return mDNSNULL;
}
dlen = DomainNameLength(service);
// Allocate space for the name and RData.
rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + dlen + sizeof(RData));
if (!rr)
return mDNSNULL;
name = (domainname *)((mDNSu8 *)rr + sizeof(ResourceRecord));
rr->RecordType = kDNSRecordTypePacketAuth;
rr->InterfaceID = mDNSInterface_Any;
rr->name = (const domainname *)name;
rr->rrtype = kDNSType_NSEC3;
rr->rrclass = kDNSClass_IN;
rr->rroriginalttl = kStandardTTL;
rr->rDNSServer = mDNSNULL;
rr->rdlength = MCAST_NSEC3_RDLENGTH;
rr->rdestimate = MCAST_NSEC3_RDLENGTH;
rr->rdata = (RData *)((mDNSu8 *)rr->name + dlen);
AssignDomainName(name, service);
if (!InitializeNSEC3Record(rr, AnonData, len, salt))
{
mDNSPlatformMemFree(rr);
return mDNSNULL;
}
return rr;
}
mDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const ResourceRecord *rr)
{
int len;
domainname *name;
ResourceRecord *nsec3rr;
if (rr->rdlength < MCAST_NSEC3_RDLENGTH)
{
LogMsg("CopyNSEC3ResourceRecord: rdlength %d smaller than MCAST_NSEC3_RDLENGTH %d", rr->rdlength, MCAST_NSEC3_RDLENGTH);
return mDNSNULL;
}
// Allocate space for the name and the rdata along with the ResourceRecord
len = DomainNameLength(rr->name);
nsec3rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + len + sizeof(RData));
if (!nsec3rr)
return mDNSNULL;
*nsec3rr = *rr;
name = (domainname *)((mDNSu8 *)nsec3rr + sizeof(ResourceRecord));
nsec3rr->name = (const domainname *)name;
AssignDomainName(name, rr->name);
nsec3rr->rdata = (RData *)((mDNSu8 *)nsec3rr->name + len);
mDNSPlatformMemCopy(nsec3rr->rdata->u.data, rr->rdata->u.data, rr->rdlength);
si->nsec3RR = nsec3rr;
return nsec3rr;
}
// When a service is started or a browse is started with the Anonymous data, we allocate a new random
// number and based on that allocate a new NSEC3 resource record whose hash is a function of random number (salt) and
// the anonymous data.
//
// If we receive a packet with the NSEC3 option, we need to cache that along with the resource record so that we can
// check against the question to see whether it answers them or not. In that case, we pass the "rr" that we received.
mDNSexport AnonymousInfo *AllocateAnonInfo(const domainname *service, const mDNSu8 *data, int len, const ResourceRecord *rr)
{
AnonymousInfo *ai;
ai = (AnonymousInfo *)mDNSPlatformMemAllocate(sizeof(AnonymousInfo));
if (!ai)
{
return mDNSNULL;
}
mDNSPlatformMemZero(ai, sizeof(AnonymousInfo));
if (rr)
{
if (!CopyNSEC3ResourceRecord(ai, rr))
{
mDNSPlatformMemFree(ai);
return mDNSNULL;
}
return ai;
}
ai->salt = mDNSRandom(0xFFFFFFFF);
ai->AnonData = mDNSPlatformMemAllocate(len);
if (!ai->AnonData)
{
mDNSPlatformMemFree(ai);
return mDNSNULL;
}
ai->AnonDataLen = len;
mDNSPlatformMemCopy(ai->AnonData, data, len);
ai->nsec3RR = ConstructNSEC3Record(service, data, len, ai->salt);
if (!ai->nsec3RR)
{
mDNSPlatformMemFree(ai);
return mDNSNULL;
}
return ai;
}
mDNSexport void FreeAnonInfo(AnonymousInfo *ai)
{
if (ai->nsec3RR)
mDNSPlatformMemFree(ai->nsec3RR);
if (ai->AnonData)
mDNSPlatformMemFree(ai->AnonData);
mDNSPlatformMemFree(ai);
}
mDNSexport void ReInitAnonInfo(AnonymousInfo **AnonInfo, const domainname *name)
{
if (*AnonInfo)
{
AnonymousInfo *ai = *AnonInfo;
*AnonInfo = AllocateAnonInfo(name, ai->AnonData, ai->AnonDataLen, mDNSNULL);
if (!(*AnonInfo))
*AnonInfo = ai;
else
FreeAnonInfo(ai);
}
}
// This function should be used only if you know that the question and
// the resource record belongs to the same set. The main usage is
// in ProcessQuery where we find the question to be part of the same
// set as the resource record, but it needs the AnonData to be
// initialized so that it can walk the cache records to see if they
// answer the question.
mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion)
{
if (!q->AnonInfo || !rr->AnonInfo)
{
LogMsg("SetAnonData: question %##s(%p), rr %##s(%p), NULL", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
return;
}
debugf("SetAnonData: question %##s(%p), rr %##s(%p)", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
if (ForQuestion)
{
if (!q->AnonInfo->AnonData)
{
q->AnonInfo->AnonData = mDNSPlatformMemAllocate(rr->AnonInfo->AnonDataLen);
if (!q->AnonInfo->AnonData)
return;
}
mDNSPlatformMemCopy(q->AnonInfo->AnonData, rr->AnonInfo->AnonData, rr->AnonInfo->AnonDataLen);
q->AnonInfo->AnonDataLen = rr->AnonInfo->AnonDataLen;
}
else
{
if (!rr->AnonInfo->AnonData)
{
rr->AnonInfo->AnonData = mDNSPlatformMemAllocate(q->AnonInfo->AnonDataLen);
if (!rr->AnonInfo->AnonData)
return;
}
mDNSPlatformMemCopy(rr->AnonInfo->AnonData, q->AnonInfo->AnonData, q->AnonInfo->AnonDataLen);
rr->AnonInfo->AnonDataLen = q->AnonInfo->AnonDataLen;
}
}
// returns -1 if the caller should ignore the result
// returns 1 if the record answers the question
// returns 0 if the record does not answer the question
mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
{
mDNSexport mDNS mDNSStorage;
ResourceRecord *nsec3RR;
int i;
AnonymousInfo *qai, *rai;
mDNSu8 *AnonData;
int AnonDataLen;
rdataNSEC3 *nsec3;
int hlen;
const mDNSu8 hashName[NSEC3_MAX_HASH_LEN];
int nxtLength;
mDNSu8 *nxtName;
debugf("AnonInfoAnswersQuestion: question qname %##s", q->qname.c);
// Currently only PTR records can have anonymous information
if (q->qtype != kDNSType_PTR)
{
return -1;
}
// We allow anonymous questions to be answered by both normal services (without the
// anonymous information) and anonymous services that are part of the same set. And
// normal questions discover normal services and all anonymous services.
//
// The three cases have been enumerated clearly even though they all behave the
// same way.
if (!q->AnonInfo)
{
debugf("AnonInfoAnswersQuestion: not a anonymous type question");
if (!rr->AnonInfo)
{
// case 1
return -1;
}
else
{
// case 2
debugf("AnonInfoAnswersQuestion: Question %##s not answered using anonymous record %##s", q->qname.c, rr->name->c);
return -1;
}
}
else
{
// case 3
if (!rr->AnonInfo)
{
debugf("AnonInfoAnswersQuestion: not a anonymous type record");
return -1;
}
}
// case 4: We have the anonymous information both in the question and the record. We need
// two sets of information to validate.
//
// 1) Anonymous data that identifies the set/group
// 2) NSEC3 record that contains the hash and the salt
//
// If the question is a remote one, it does not have the anonymous information to validate (just
// the NSEC3 record) and hence the anonymous data should come from the local resource record. If the
// question is local, it can come from either of them and if there is a mismatch between the
// question and record, it won't validate.
qai = q->AnonInfo;
rai = rr->AnonInfo;
if (qai->AnonData && rai->AnonData)
{
// Before a cache record is created, if there is a matching question i.e., part
// of the same set, then when the cache is created we also set the anonymous
// information. Otherwise, the cache record contains just the NSEC3 record and we
// won't be here for that case.
//
// It is also possible that a local question is matched against the local AuthRecord
// as that is also the case for which the AnonData would be non-NULL for both.
// We match questions against AuthRecords (rather than the cache) for LocalOnly case and
// to see whether a .local query should be suppressed or not. The latter never happens
// because PTR queries are never suppressed.
// If they don't belong to the same anonymous set, then no point in validating.
if ((qai->AnonDataLen != rai->AnonDataLen) ||
mDNSPlatformMemCmp(qai->AnonData, rai->AnonData, qai->AnonDataLen) != 0)
{
debugf("AnonInfoAnswersQuestion: AnonData mis-match for record %s question %##s ",
RRDisplayString(&mDNSStorage, rr), q->qname.c);
return 0;
}
// AnonData matches i.e they belong to the same group and the same service.
LogInfo("AnonInfoAnswersQuestion: Answering qname %##s, rname %##s, without validation", q->qname.c,
rr->name->c);
return 1;
}
else
{
debugf("AnonInfoAnswersQuestion: question %p, record %p", qai->AnonData, rai->AnonData);
}
if (qai->AnonData)
{
// If there is AnonData, then this is a local question. The
// NSEC3 RR comes from the resource record which could be part
// of the cache or local auth record. The cache entry could
// be from a remote host or created when we heard our own
// announcements. In any case, we use that to see if it matches
// the question.
AnonData = qai->AnonData;
AnonDataLen = qai->AnonDataLen;
nsec3RR = rai->nsec3RR;
}
else
{
// Remote question or hearing our own question back
AnonData = rai->AnonData;
AnonDataLen = rai->AnonDataLen;
nsec3RR = qai->nsec3RR;
}
if (!AnonData || !nsec3RR)
{
// AnonData can be NULL for the cache entry and if we are hearing our own question back, AnonData is NULL for
// that too and we can end up here for that case.
debugf("AnonInfoAnswersQuestion: AnonData %p or nsec3RR %p, NULL for question %##s, record %s", AnonData, nsec3RR,
q->qname.c, RRDisplayString(&mDNSStorage, rr));
return 0;
}
debugf("AnonInfoAnswersQuestion: Validating question %##s, ResourceRecord %s", q->qname.c, RRDisplayString(&mDNSStorage, nsec3RR));
nsec3 = (rdataNSEC3 *)nsec3RR->rdata->u.data;
if (!NSEC3HashName(nsec3RR->name, nsec3, AnonData, AnonDataLen, hashName, &hlen))
{
LogMsg("AnonInfoAnswersQuestion: NSEC3HashName failed for ##s", nsec3RR->name->c);
return mDNSfalse;
}
if (hlen != SHA1_HASH_LENGTH)
{
LogMsg("AnonInfoAnswersQuestion: hlen wrong %d", hlen);
return mDNSfalse;
}
NSEC3Parse(nsec3RR, mDNSNULL, &nxtLength, &nxtName, mDNSNULL, mDNSNULL);
if (hlen != nxtLength)
{
LogMsg("AnonInfoAnswersQuestion: ERROR!! hlen %d not same as nxtLength %d", hlen, nxtLength);
return mDNSfalse;
}
for (i = 0; i < nxtLength; i++)
{
if (nxtName[i] != hashName[i])
{
debugf("AnonInfoAnswersQuestion: mismatch output %x, digest %x, i %d", nxtName[i+1], hashName[i], i);
return 0;
}
}
LogInfo("AnonInfoAnswersQuestion: ResourceRecord %s matched question %##s (%s)", RRDisplayString(&mDNSStorage, nsec3RR), q->qname.c, DNSTypeName(q->qtype));
return 1;
}
// Find a matching NSEC3 record for the name. We parse the questions and the records in the packet in order.
// Similarly we also parse the NSEC3 records in order and this mapping to the questions and records
// respectively.
mDNSlocal CacheRecord *FindMatchingNSEC3ForName(mDNS *const m, CacheRecord **nsec3, const domainname *name)
{
CacheRecord *cr;
CacheRecord **prev = nsec3;
(void) m;
for (cr = *nsec3; cr; cr = cr->next)
{
if (SameDomainName(cr->resrec.name, name))
{
debugf("FindMatchingNSEC3ForName: NSEC3 record %s matched %##s", CRDisplayString(m, cr), name->c);
*prev = cr->next;
cr->next = mDNSNULL;
return cr;
}
prev = &cr->next;
}
return mDNSNULL;
}
mDNSexport void InitializeAnonInfoForQuestion(mDNS *const m, CacheRecord **McastNSEC3Records, DNSQuestion *q)
{
CacheRecord *nsec3CR;
if (q->qtype != kDNSType_PTR)
return;
nsec3CR = FindMatchingNSEC3ForName(m, McastNSEC3Records, &q->qname);
if (nsec3CR)
{
q->AnonInfo = AllocateAnonInfo(mDNSNULL, mDNSNULL, 0, &nsec3CR->resrec);
if (q->AnonInfo)
{
debugf("InitializeAnonInfoForQuestion: Found a matching NSEC3 record %s, for %##s (%s)",
RRDisplayString(m, q->AnonInfo->nsec3RR), q->qname.c, DNSTypeName(q->qtype));
}
ReleaseCacheRecord(m, nsec3CR);
}
}
mDNSexport void InitializeAnonInfoForCR(mDNS *const m, CacheRecord **McastNSEC3Records, CacheRecord *cr)
{
CacheRecord *nsec3CR;
if (!(*McastNSEC3Records))
return;
// If already initialized or not a PTR type, we don't have to do anything
if (cr->resrec.AnonInfo || cr->resrec.rrtype != kDNSType_PTR)
return;
nsec3CR = FindMatchingNSEC3ForName(m, McastNSEC3Records, cr->resrec.name);
if (nsec3CR)
{
cr->resrec.AnonInfo = AllocateAnonInfo(mDNSNULL, mDNSNULL, 0, &nsec3CR->resrec);
if (cr->resrec.AnonInfo)
{
debugf("InitializeAnonInfoForCR: Found a matching NSEC3 record %s, for %##s (%s)",
RRDisplayString(m, cr->resrec.AnonInfo->nsec3RR), cr->resrec.name->c,
DNSTypeName(cr->resrec.rrtype));
}
ReleaseCacheRecord(m, nsec3CR);
}
}
mDNSexport mDNSBool IdenticalAnonInfo(AnonymousInfo *a1, AnonymousInfo *a2)
{
// if a1 is NULL and a2 is not NULL AND vice-versa
// return false as there is a change.
if ((a1 != mDNSNULL) != (a2 != mDNSNULL))
return mDNSfalse;
// Both could be NULL or non-NULL
if (a1 && a2)
{
// The caller already verified that the owner name is the same.
// Check whether the RData is same.
if (!IdenticalSameNameRecord(a1->nsec3RR, a2->nsec3RR))
{
debugf("IdenticalAnonInfo: nsec3RR mismatch");
return mDNSfalse;
}
}
return mDNStrue;
}
mDNSexport void CopyAnonInfoForCR(mDNS *const m, CacheRecord *crto, CacheRecord *crfrom)
{
AnonymousInfo *aifrom = crfrom->resrec.AnonInfo;
AnonymousInfo *aito = crto->resrec.AnonInfo;
(void) m;
if (!aifrom)
return;
if (aito)
{
crto->resrec.AnonInfo = aifrom;
FreeAnonInfo(aito);
crfrom->resrec.AnonInfo = mDNSNULL;
}
else
{
FreeAnonInfo(aifrom);
crfrom->resrec.AnonInfo = mDNSNULL;
}
}
#else // !ANONYMOUS_DISABLED
mDNSexport void ReInitAnonInfo(AnonymousInfo **si, const domainname *name)
{
(void)si;
(void)name;
}
mDNSexport AnonymousInfo * AllocateAnonInfo(const domainname *service, const mDNSu8 *AnonData, int len, const ResourceRecord *rr)
{
(void)service;
(void)AnonData;
(void)len;
(void)rr;
return mDNSNULL;
}
mDNSexport void FreeAnonInfo(AnonymousInfo *ai)
{
(void)ai;
}
mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion)
{
(void)q;
(void)rr;
(void)ForQuestion;
}
mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
{
(void)rr;
(void)q;
return mDNSfalse;
}
mDNSexport void InitializeAnonInfoForQuestion(mDNS *const m, CacheRecord **McastNSEC3Records, DNSQuestion *q)
{
(void)m;
(void)McastNSEC3Records;
(void)q;
}
mDNSexport void InitializeAnonInfoForCR(mDNS *const m, CacheRecord **McastNSEC3Records, CacheRecord *cr)
{
(void)m;
(void)McastNSEC3Records;
(void)cr;
}
mDNSexport void CopyAnonInfoForCR(mDNS *const m, CacheRecord *crto, CacheRecord *crfrom)
{
(void)m;
(void)crto;
(void)crfrom;
}
mDNSexport mDNSBool IdenticalAnonInfo(AnonymousInfo *a1, AnonymousInfo *a2)
{
(void)a1;
(void)a2;
return mDNStrue;
}
#endif // !ANONYMOUS_DISABLED

View File

@ -0,0 +1,31 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2012 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __ANONYMOUS_H_
#define __ANONYMOUS_H_
extern void ReInitAnonInfo(AnonymousInfo **si, const domainname *name);
extern AnonymousInfo *AllocateAnonInfo(const domainname *service, const mDNSu8 *AnonData, int len, const ResourceRecord *rr);
extern void FreeAnonInfo(AnonymousInfo *ai);
extern void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion);
extern int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
extern void InitializeAnonInfoForCR(mDNS *const m, CacheRecord **McastNSEC3Records, CacheRecord *cr);
extern void InitializeAnonInfoForQuestion(mDNS *const m, CacheRecord **McastNSEC3Records, DNSQuestion *q);
extern void CopyAnonInfoForCR(mDNS *const m, CacheRecord *crto, CacheRecord *crfrom);
extern mDNSBool IdenticalAnonInfo(AnonymousInfo *a1, AnonymousInfo *a2);
#endif

View File

@ -0,0 +1,157 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __DNSSEC_H
#define __DNSSEC_H
#include "CryptoAlg.h"
#include "mDNSDebug.h"
typedef enum
{
RRVS_rr, RRVS_rrsig, RRVS_key, RRVS_rrsig_key, RRVS_ds, RRVS_done,
} RRVerifierSet;
typedef struct RRVerifier_struct RRVerifier;
typedef struct DNSSECVerifier_struct DNSSECVerifier;
typedef struct AuthChain_struct AuthChain;
typedef struct InsecureContext_struct InsecureContext;
struct RRVerifier_struct
{
RRVerifier *next;
mDNSu16 rrtype;
mDNSu16 rrclass;
mDNSu32 rroriginalttl;
mDNSu16 rdlength;
mDNSu16 found;
mDNSu32 namehash;
mDNSu32 rdatahash;
domainname name;
mDNSu8 *rdata;
};
// Each AuthChain element has one rrset (with multiple resource records of same type), rrsig and key
// that validates the rrset.
struct AuthChain_struct
{
AuthChain *next; // Next element in the chain
RRVerifier *rrset; // RRSET that is authenticated
RRVerifier *rrsig; // Signature for that RRSET
RRVerifier *key; // Public key for that RRSET
};
#define ResetAuthChain(dv) { \
(dv)->ac = mDNSNULL; \
(dv)->actail = &((dv)->ac); \
}
typedef void DNSSECVerifierCallback (mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status);
//
// When we do a validation for a question, there might be additional validations that needs to be done e.g.,
// wildcard expanded answer. It is also possible that in the case of nsec we need to prove both that a wildcard
// does not apply and the closest encloser proves that name does not exist. We identify these with the following
// flags.
//
// Note: In the following, by "marking the validation", we mean that as part of validation we need to prove
// the ones that are marked with.
//
// A wildcard may be used to answer a question. In that case, we need to verify that the right wildcard was
// used in answering the question. This is done by marking the validation with WILDCARD_PROVES_ANSWER_EXPANDED.
//
// Sometimes we get a NXDOMAIN response. In this case, we may have a wildcard where we need to prove
// that the wildcard proves that the name does not exist. This is done by marking the validation with
// WILDCARD_PROVES_NONAME_EXISTS.
//
// In the case of NODATA error, sometimes the name may exist but the query type does not exist. This is done by
// marking the validation with NSEC_PROVES_NOTYPE_EXISTS.
//
// In both NXDOMAIN and NODATA proofs, we may have to prove that the NAME does not exist. This is done by marking
// the validation with NSEC_PROVES_NONAME_EXISTS.
//
#define WILDCARD_PROVES_ANSWER_EXPANDED 0x00000001
#define WILDCARD_PROVES_NONAME_EXISTS 0x00000002
#define NSEC_PROVES_NOTYPE_EXISTS 0x00000004
#define NSEC_PROVES_NONAME_EXISTS 0x00000008
#define NSEC3_OPT_OUT 0x00000010 // OptOut was set in NSEC3
struct DNSSECVerifier_struct
{
domainname origName; // Original question name that needs verification
mDNSu16 origType; // Original question type corresponding to origName
mDNSu16 currQtype; // Current question type that is being verified
mDNSInterfaceID InterfaceID; // InterfaceID of the question
DNSQuestion q;
mDNSu8 recursed; // Number of times recursed during validation
mDNSu8 ValidationRequired; // Copy of the question's ValidationRequired status
mDNSu8 InsecureProofDone;
mDNSu8 NumPackets; // Number of packets that we send on the wire for DNSSEC verification.
mDNSs32 StartTime; // Time the DNSSEC verification starts
mDNSu32 flags;
RRVerifierSet next;
domainname *wildcardName; // set if the answer is wildcard expanded
RRVerifier *pendingNSEC;
DNSSECVerifierCallback *DVCallback;
DNSSECVerifier *parent;
RRVerifier *rrset; // rrset for which we have to verify
RRVerifier *rrsig; // RRSIG for rrset
RRVerifier *key; // DNSKEY for rrset
RRVerifier *rrsigKey; // RRSIG for DNSKEY
RRVerifier *ds; // DS for DNSKEY set in parent zone
AuthChain *saveac;
AuthChain *ac;
AuthChain **actail;
AlgContext *ctx;
};
struct InsecureContext_struct
{
DNSSECVerifier *dv; // dv for which we are doing the insecure proof
mDNSu8 skip; // labels to skip for forming the name from origName
DNSSECStatus status; // status to deliver when done
mDNSu8 triggerLabelCount; // Label count of the name that triggered the insecure proof
DNSQuestion q;
};
#define LogDNSSEC LogOperation
#define DNS_SERIAL_GT(a, b) ((int)((a) - (b)) > 0)
#define DNS_SERIAL_LT(a, b) ((int)((a) - (b)) < 0)
extern void StartDNSSECVerification(mDNS *const m, void *context);
extern RRVerifier* AllocateRRVerifier(const ResourceRecord *const rr, mStatus *status);
extern mStatus AddRRSetToVerifier(DNSSECVerifier *dv, const ResourceRecord *const rr, RRVerifier *rv, RRVerifierSet set);
extern void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q);
extern void FreeDNSSECVerifier(mDNS *const m, DNSSECVerifier *dv);
extern DNSSECVerifier *AllocateDNSSECVerifier(mDNS *const m, const domainname *name, mDNSu16 rrtype, mDNSInterfaceID InterfaceID,
mDNSu8 ValidationRequired, DNSSECVerifierCallback dvcallback, mDNSQuestionCallback qcallback);
extern void InitializeQuestion(mDNS *const m, DNSQuestion *question, mDNSInterfaceID InterfaceID, const domainname *qname,
mDNSu16 qtype, mDNSQuestionCallback *callback, void *context);
extern void ValidateRRSIG(DNSSECVerifier *dv, RRVerifierSet type, const ResourceRecord *const rr);
extern void AuthChainLink(DNSSECVerifier *dv, AuthChain *ae);
extern mStatus DNSNameToLowerCase(domainname *d, domainname *result);
extern int DNSMemCmp(const mDNSu8 *const m1, const mDNSu8 *const m2, int len);
extern int DNSSECCanonicalOrder(const domainname *const d1, const domainname *const d2, int *subdomain);
extern void ProveInsecure(mDNS *const m, DNSSECVerifier *dv, InsecureContext *ic, domainname *trigger);
extern void BumpDNSSECStats(mDNS *const m, DNSSECStatsAction action, DNSSECStatsType type, mDNSu32 value);
extern char *DNSSECStatusName(DNSSECStatus status);
// DNSSECProbe belongs in DNSSECSupport.h but then we don't want to expose yet another plaform specific dnssec file
// to other platforms where dnssec is not supported.
extern void DNSSECProbe(mDNS *const m);
#endif // __DNSSEC_H

File diff suppressed because it is too large Load Diff

View File

@ -5,70 +5,43 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
File: mDNSDebug.c
File: mDNSDebug.c
Contains: Implementation of debugging utilities. Requires a POSIX environment.
Contains: Implementation of debugging utilities. Requires a POSIX environment.
Version: 1.0
Version: 1.0
Change History (most recent first):
$Log: mDNSDebug.c,v $
Revision 1.7 2006/08/14 23:24:56 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.6 2005/01/27 22:57:56 cheshire
Fix compile errors on gcc4
Revision 1.5 2004/09/17 01:08:55 cheshire
Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
declared in that file are ONLY appropriate to single-address-space embedded applications.
For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
Revision 1.4 2004/06/11 22:36:51 cheshire
Fixes for compatibility with Windows
Revision 1.3 2004/01/28 21:14:23 cheshire
Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
Revision 1.2 2003/12/09 01:30:40 rpantos
Fix usage of ARGS... macros to build properly on Windows.
Revision 1.1 2003/12/08 21:11:42; rpantos
Changes necessary to support mDNSResponder on Linux.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
*/
#include "mDNSDebug.h"
#include <stdio.h>
#if defined(WIN32)
// Need to add Windows syslog support here
#if defined(WIN32) || defined(EFI32) || defined(EFI64) || defined(EFIX64)
// Need to add Windows/EFI syslog support here
#define LOG_PID 0x01
#define LOG_CONS 0x02
#define LOG_PERROR 0x20
#define openlog(A,B,C) (void)(A); (void)(B)
#define syslog(A,B,C)
#define closelog()
#else
#include <syslog.h>
#endif
#include "mDNSEmbeddedAPI.h"
mDNSexport int mDNS_LoggingEnabled = 0;
mDNSexport int mDNS_PacketLoggingEnabled = 0;
mDNSexport int mDNS_McastLoggingEnabled = 0;
mDNSexport int mDNS_McastTracingEnabled = 0;
#if MDNS_DEBUGMSGS
mDNSexport int mDNS_DebugMode = mDNStrue;
#else
@ -77,76 +50,46 @@ mDNSexport int mDNS_DebugMode = mDNSfalse;
// Note, this uses mDNS_vsnprintf instead of standard "vsnprintf", because mDNS_vsnprintf knows
// how to print special data types like IP addresses and length-prefixed domain names
#if MDNS_DEBUGMSGS
mDNSexport void debugf_(const char *format, ...)
{
unsigned char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
va_end(ptr);
fprintf(stderr,"%s\n", buffer);
fflush(stderr);
}
#endif
#if MDNS_DEBUGMSGS > 1
mDNSexport void verbosedebugf_(const char *format, ...)
{
unsigned char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
va_end(ptr);
fprintf(stderr,"%s\n", buffer);
fflush(stderr);
}
{
char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf(buffer, sizeof(buffer), format, ptr)] = 0;
va_end(ptr);
mDNSPlatformWriteDebugMsg(buffer);
}
#endif
mDNSlocal void WriteLogMsg(const char *ident, const char *buffer, int logoptflags, int logpriority)
{
if (mDNS_DebugMode) // In debug mode we write to stderr
{
fprintf(stderr,"%s\n", buffer);
fflush(stderr);
}
else // else, in production mode, we write to syslog
{
openlog(ident, LOG_PERROR | logoptflags, LOG_DAEMON);
syslog(logpriority, "%s", buffer);
closelog();
}
}
// Log message with default "mDNSResponder" ident string at the start
mDNSlocal void LogMsgWithLevelv(mDNSLogLevel_t logLevel, const char *format, va_list ptr)
{
char buffer[512];
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
mDNSPlatformWriteLogMsg(ProgramName, buffer, logLevel);
}
#define LOG_HELPER_BODY(L) \
{ \
va_list ptr; \
va_start(ptr,format); \
LogMsgWithLevelv(L, format, ptr); \
va_end(ptr); \
}
// see mDNSDebug.h
#if !MDNS_HAS_VA_ARG_MACROS
void LogMsg_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_MSG)
void LogOperation_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_OPERATION)
void LogSPS_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_SPS)
void LogInfo_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_INFO)
#endif
#if MDNS_DEBUGMSGS
void debugf_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_DEBUG)
#endif
// Log message with default "mDNSResponder" ident string at the start
mDNSexport void LogMsg(const char *format, ...)
{
char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
va_end(ptr);
WriteLogMsg("mDNSResponder", buffer, 0, LOG_ERR);
}
// Log message with specified ident string at the start
mDNSexport void LogMsgIdent(const char *ident, const char *format, ...)
{
char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
va_end(ptr);
WriteLogMsg(ident, buffer, ident && *ident ? LOG_PID : 0, LOG_INFO);
}
// Log message with no ident string at the start
mDNSexport void LogMsgNoIdent(const char *format, ...)
{
char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
va_end(ptr);
WriteLogMsg("", buffer, 0, LOG_INFO);
}
mDNSexport void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...)
LOG_HELPER_BODY(logLevel)

View File

@ -5,84 +5,15 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: mDNSDebug.h,v $
Revision 1.26.2.1 2006/08/29 06:24:22 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.26 2005/07/04 22:40:26 cheshire
Additional debugging code to help catch memory corruption
Revision 1.25 2004/12/14 21:34:16 cheshire
Add "#define ANSWER_REMOTE_HOSTNAME_QUERIES 0" and comment
Revision 1.24 2004/09/16 01:58:21 cheshire
Fix compiler warnings
Revision 1.23 2004/05/18 23:51:25 cheshire
Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
Revision 1.22 2004/04/22 04:27:42 cheshire
Spacing tidyup
Revision 1.21 2004/04/14 23:21:41 ksekar
Removed accidental checkin of MALLOC_DEBUGING flag in 1.20
Revision 1.20 2004/04/14 23:09:28 ksekar
Support for TSIG signed dynamic updates.
Revision 1.19 2004/03/15 18:57:59 cheshire
Undo last checkin that accidentally made verbose debugging the default for all targets
Revision 1.18 2004/03/13 01:57:33 ksekar
<rdar://problem/3192546>: DynDNS: Dynamic update of service records
Revision 1.17 2004/01/28 21:14:23 cheshire
Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
Revision 1.16 2003/12/09 01:30:06 rpantos
Fix usage of ARGS... macros to build properly on Windows.
Revision 1.15 2003/12/08 20:55:26 rpantos
Move some definitions here from mDNSMacOSX.h.
Revision 1.14 2003/08/12 19:56:24 cheshire
Update to APSL 2.0
Revision 1.13 2003/07/02 21:19:46 cheshire
<rdar://problem/3313413> Update copyright notices, etc., in source code comments
Revision 1.12 2003/05/26 03:01:27 cheshire
<rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
Revision 1.11 2003/05/21 17:48:10 cheshire
Add macro to enable GCC's printf format string checking
Revision 1.10 2003/04/26 02:32:57 cheshire
Add extern void LogMsg(const char *format, ...);
Revision 1.9 2002/09/21 20:44:49 zarzycki
Added APSL info
Revision 1.8 2002/09/19 04:20:43 cheshire
Remove high-ascii characters that confuse some systems
Revision 1.7 2002/09/16 18:41:42 cheshire
Merge in license terms from Quinn's copy, in preparation for Darwin release
*/
#pragma ident "%Z%%M% %I% %E% SMI"
*/
#ifndef __mDNSDebug_h
#define __mDNSDebug_h
@ -104,89 +35,132 @@ Merge in license terms from Quinn's copy, in preparation for Darwin release
// warning: repeated `#' flag in format (for %##s -- DNS name string format)
// warning: double format, pointer arg (arg 2) (for %.4a, %.16a, %#a -- IP address formats)
#define MDNS_CHECK_PRINTF_STYLE_FUNCTIONS 0
#if MDNS_CHECK_PRINTF_STYLE_FUNCTIONS
#define IS_A_PRINTF_STYLE_FUNCTION(F,A) __attribute__ ((format(printf,F,A)))
#else
#define IS_A_PRINTF_STYLE_FUNCTION(F,A)
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if MDNS_DEBUGMSGS
#define debugf debugf_
extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
#else // If debug breaks are off, use a preprocessor trick to optimize those calls out of the code
#if (defined(__GNUC__))
#define debugf( ARGS... ) ((void)0)
#elif (defined(__MWERKS__))
#define debugf( ... )
#else
#define debugf 1 ? ((void)0) : (void)
#endif
#endif
#if MDNS_DEBUGMSGS > 1
#define verbosedebugf verbosedebugf_
extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
#else
#if (defined(__GNUC__))
#define verbosedebugf( ARGS... ) ((void)0)
#elif (defined(__MWERKS__))
#define verbosedebugf( ... )
#else
#define verbosedebugf 1 ? ((void)0) : (void)
#endif
#endif
// LogMsg is used even in shipping code, to write truly serious error messages to syslog (or equivalent)
extern int mDNS_DebugMode; // If non-zero, LogMsg() writes to stderr instead of syslog
extern void LogMsg(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
extern void LogMsgIdent(const char *ident, const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(2,3);
extern void LogMsgNoIdent(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
typedef enum
{
MDNS_LOG_MSG,
MDNS_LOG_OPERATION,
MDNS_LOG_SPS,
MDNS_LOG_INFO,
MDNS_LOG_DEBUG,
} mDNSLogLevel_t;
// Set this symbol to 1 to answer remote queries for our Address, reverse mapping PTR, and HINFO records
#define ANSWER_REMOTE_HOSTNAME_QUERIES 0
// Set this symbol to 1 to do extra debug checks on malloc() and free()
// Set this symbol to 2 to write a log message for every malloc() and free()
#define MACOSX_MDNS_MALLOC_DEBUGGING 0
//#define MACOSX_MDNS_MALLOC_DEBUGGING 1
#if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
//#define ForceAlerts 1
//#define LogTimeStamps 1
// Developer-settings section ends here
#if MDNS_CHECK_PRINTF_STYLE_FUNCTIONS
#define IS_A_PRINTF_STYLE_FUNCTION(F,A) __attribute__ ((format(printf,F,A)))
#else
#define IS_A_PRINTF_STYLE_FUNCTION(F,A)
#endif
#ifdef __cplusplus
extern "C" {
#endif
// Variable argument macro support. Use ANSI C99 __VA_ARGS__ where possible. Otherwise, use the next best thing.
#if (defined(__GNUC__))
#if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 2)))
#define MDNS_C99_VA_ARGS 1
#define MDNS_GNU_VA_ARGS 0
#else
#define MDNS_C99_VA_ARGS 0
#define MDNS_GNU_VA_ARGS 1
#endif
#define MDNS_HAS_VA_ARG_MACROS 1
#elif (_MSC_VER >= 1400) // Visual Studio 2005 and later
#define MDNS_C99_VA_ARGS 1
#define MDNS_GNU_VA_ARGS 0
#define MDNS_HAS_VA_ARG_MACROS 1
#elif (defined(__MWERKS__))
#define MDNS_C99_VA_ARGS 1
#define MDNS_GNU_VA_ARGS 0
#define MDNS_HAS_VA_ARG_MACROS 1
#else
#define MDNS_C99_VA_ARGS 1
#define MDNS_GNU_VA_ARGS 0
#define MDNS_HAS_VA_ARG_MACROS 1
#endif
#if (MDNS_HAS_VA_ARG_MACROS)
#if (MDNS_C99_VA_ARGS)
#define debug_noop(... ) ((void)0)
#define LogMsg(... ) LogMsgWithLevel(MDNS_LOG_MSG, __VA_ARGS__)
#define LogOperation(... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_OPERATION, __VA_ARGS__);} while (0)
#define LogSPS(... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_SPS, __VA_ARGS__);} while (0)
#define LogInfo(... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_INFO, __VA_ARGS__);} while (0)
#elif (MDNS_GNU_VA_ARGS)
#define debug_noop( ARGS... ) ((void)0)
#define LogMsg( ARGS... ) LogMsgWithLevel(MDNS_LOG_MSG, ARGS)
#define LogOperation( ARGS... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_OPERATION, ARGS);} while (0)
#define LogSPS( ARGS... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_SPS, ARGS);} while (0)
#define LogInfo( ARGS... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_INFO, ARGS);} while (0)
#else
#error Unknown variadic macros
#endif
#else
// If your platform does not support variadic macros, you need to define the following variadic functions.
// See mDNSShared/mDNSDebug.c for sample implementation
#define debug_noop 1 ? (void)0 : (void)
#define LogMsg LogMsg_
#define LogOperation (mDNS_LoggingEnabled == 0) ? ((void)0) : LogOperation_
#define LogSPS (mDNS_LoggingEnabled == 0) ? ((void)0) : LogSPS_
#define LogInfo (mDNS_LoggingEnabled == 0) ? ((void)0) : LogInfo_
extern void LogMsg_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
extern void LogOperation_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
extern void LogSPS_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
extern void LogInfo_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
#endif
#if MDNS_DEBUGMSGS
#define debugf debugf_
extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
#else
#define debugf debug_noop
#endif
#if MDNS_DEBUGMSGS > 1
#define verbosedebugf verbosedebugf_
extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
#else
#define verbosedebugf debug_noop
#endif
extern int mDNS_LoggingEnabled;
extern int mDNS_PacketLoggingEnabled;
extern int mDNS_McastLoggingEnabled;
extern int mDNS_McastTracingEnabled;
extern int mDNS_DebugMode; // If non-zero, LogMsg() writes to stderr instead of syslog
extern const char ProgramName[];
extern void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(2,3);
// LogMsgNoIdent needs to be fixed so that it logs without the ident prefix like it used to
// (or completely overhauled to use the new "log to a separate file" facility)
#define LogMsgNoIdent LogMsg
#if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
extern void *mallocL(char *msg, unsigned int size);
extern void freeL(char *msg, void *x);
extern void LogMemCorruption(const char *format, ...);
extern void uds_validatelists(void);
extern void udns_validatelists(void *const v);
#else
#define mallocL(X,Y) malloc(Y)
#define freeL(X,Y) free(Y)
#endif
#if MACOSX_MDNS_MALLOC_DEBUGGING >= 2
#define LogMalloc LogMsg
#else
#if (defined( __GNUC__ ))
#define LogMalloc(ARGS...) ((void)0)
#elif (defined( __MWERKS__ ))
#define LogMalloc( ... )
#else
#define LogMalloc 1 ? ((void)0) : (void)
#endif
#endif
#define LogAllOperations 0
#if LogAllOperations
#define LogOperation LogMsg
#else
#define LogOperation debugf
#endif
#define ForceAlerts 0
#ifdef __cplusplus
}
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,77 +5,15 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: mDNSPosix.h,v $
Revision 1.18 2006/08/14 23:24:47 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.17 2005/02/04 00:39:59 cheshire
Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
Revision 1.16 2004/11/30 22:37:01 cheshire
Update copyright dates and add "Mode: C; tab-width: 4" headers
Revision 1.15 2004/02/06 01:19:51 cheshire
Conditionally exclude IPv6 code unless HAVE_IPV6 is set
Revision 1.14 2004/01/28 21:12:15 cheshire
Reconcile mDNSIPv6Support & HAVE_IPV6 into a single flag (HAVE_IPV6)
Revision 1.13 2004/01/24 05:12:03 cheshire
<rdar://problem/3534352>: Need separate socket for issuing unicast queries
Revision 1.12 2004/01/23 21:37:08 cheshire
For consistency, rename multicastSocket to multicastSocket4, and multicastSocketv6 to multicastSocket6
Revision 1.11 2003/12/11 03:03:51 rpantos
Clean up mDNSPosix so that it builds on OS X again.
Revision 1.10 2003/12/08 20:47:02 rpantos
Add support for mDNSResponder on Linux.
Revision 1.9 2003/10/30 19:25:19 cheshire
Fix warning on certain compilers
Revision 1.8 2003/08/12 19:56:26 cheshire
Update to APSL 2.0
Revision 1.7 2003/07/02 21:19:59 cheshire
<rdar://problem/3313413> Update copyright notices, etc., in source code comments
Revision 1.6 2003/03/13 03:46:21 cheshire
Fixes to make the code build on Linux
Revision 1.5 2003/03/08 00:35:56 cheshire
Switched to using new "mDNS_Execute" model (see "mDNSCore/Implementer Notes.txt")
Revision 1.4 2002/12/23 22:13:31 jgraessl
Reviewed by: Stuart Cheshire
Initial IPv6 support for mDNSResponder.
Revision 1.3 2002/09/21 20:44:53 zarzycki
Added APSL info
Revision 1.2 2002/09/19 04:20:44 cheshire
Remove high-ascii characters that confuse some systems
Revision 1.1 2002/09/17 06:24:34 cheshire
First checkin
*/
#pragma ident "%Z%%M% %I% %E% SMI"
*/
#ifndef __mDNSPlatformPosix_h
#define __mDNSPlatformPosix_h
@ -84,7 +22,7 @@ First checkin
#include <sys/time.h>
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
// PosixNetworkInterface is a record extension of the core NetworkInterfaceInfo
@ -96,32 +34,33 @@ First checkin
typedef struct PosixNetworkInterface PosixNetworkInterface;
struct PosixNetworkInterface
{
NetworkInterfaceInfo coreIntf;
const char * intfName;
PosixNetworkInterface * aliasIntf;
int index;
int multicastSocket4;
{
NetworkInterfaceInfo coreIntf; // MUST be the first element in this structure
mDNSs32 LastSeen;
const char * intfName;
PosixNetworkInterface * aliasIntf;
int index;
int multicastSocket4;
#if HAVE_IPV6
int multicastSocket6;
int multicastSocket6;
#endif
};
};
// This is a global because debugf_() needs to be able to check its value
extern int gMDNSPlatformPosixVerboseLevel;
struct mDNS_PlatformSupport_struct
{
int unicastSocket4;
{
int unicastSocket4;
#if HAVE_IPV6
int unicastSocket6;
int unicastSocket6;
#endif
};
};
#define uDNS_SERVERS_FILE "/etc/resolv.conf"
extern int ParseDNSServers(mDNS *m, const char *filePath);
extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m);
// See comment in implementation.
// See comment in implementation.
// Call mDNSPosixGetFDSet before calling select(), to update the parameters
// as may be necessary to meet the needs of the mDNSCore code.
@ -132,7 +71,7 @@ extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m);
extern void mDNSPosixGetFDSet(mDNS *m, int *nfds, fd_set *readfds, struct timeval *timeout);
extern void mDNSPosixProcessFDSet(mDNS *const m, fd_set *readfds);
typedef void (*mDNSPosixEventCallback)( void *context);
typedef void (*mDNSPosixEventCallback)(int fd, short filter, void *context);
extern mStatus mDNSPosixAddFDToEventLoop( int fd, mDNSPosixEventCallback callback, void *context);
extern mStatus mDNSPosixRemoveFDFromEventLoop( int fd);
@ -141,7 +80,7 @@ extern mStatus mDNSPosixIgnoreSignalInEventLoop( int signum);
extern mStatus mDNSPosixRunEventLoopOnce( mDNS *m, const struct timeval *pTimeout, sigset_t *pSignalsReceived, mDNSBool *pDataDispatched);
#ifdef __cplusplus
}
}
#endif
#endif

View File

@ -1,7 +1,3 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
@ -9,9 +5,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -21,14 +17,13 @@
#include "mDNSUNP.h"
#include "mDNSDebug.h"
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <sys/uio.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
@ -36,24 +31,24 @@
macro, usually defined in <sys/param.h> or someplace like that, to make sure the
CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
should be set to the name of the header to include to get the ALIGN(P) macro.
*/
*/
#ifdef NEED_ALIGN_MACRO
#include NEED_ALIGN_MACRO
#endif
/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
other platforms don't even have that include file. So,
if we haven't yet got a definition, let's try to find
/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
other platforms don't even have that include file. So,
if we haven't yet got a definition, let's try to find
<sys/sockio.h>.
*/
*/
#ifndef SIOCGIFCONF
#include <sys/sockio.h>
#endif
/* sockaddr_dl is only referenced if we're using IP_RECVIF,
/* sockaddr_dl is only referenced if we're using IP_RECVIF,
so only include the header in that case.
*/
*/
#ifdef IP_RECVIF
#include <net/if_dl.h>
@ -64,138 +59,161 @@
#include <net/if_var.h>
#else
#include <alloca.h>
#endif /* !HAVE_SOLARIS */
#endif /* !HAVE_SOLARIS */
#include <netinet/in_var.h>
// NOTE: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
// Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
#endif
#if defined(AF_INET6) && HAVE_IPV6
#if HAVE_LINUX
#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
#include <netdb.h>
#include <arpa/inet.h>
/* Converts a prefix length to IPv6 network mask */
void plen_to_mask(int plen, char *addr) {
int i;
int colons=7; /* Number of colons in IPv6 address */
int bits_in_block=16; /* Bits per IPv6 block */
for(i=0;i<=colons;i++) {
int block, ones=0xffff, ones_in_block;
if(plen>bits_in_block) ones_in_block=bits_in_block;
else ones_in_block=plen;
block = ones & (ones << (bits_in_block-ones_in_block));
i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
plen -= ones_in_block;
}
}
int i;
int colons=7; /* Number of colons in IPv6 address */
int bits_in_block=16; /* Bits per IPv6 block */
for(i=0; i<=colons; i++) {
int block, ones=0xffff, ones_in_block;
if (plen>bits_in_block) ones_in_block=bits_in_block;
else ones_in_block=plen;
block = ones & (ones << (bits_in_block-ones_in_block));
i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
plen -= ones_in_block;
}
}
/* Gets IPv6 interface information from the /proc filesystem in linux*/
struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
{
struct ifi_info *ifi, *ifihead, **ifipnext;
FILE *fp;
char addr[8][5];
int flags, myflags, index, plen, scope;
char ifname[8], lastname[IFNAMSIZ];
char addr6[32+7+1]; /* don't forget the seven ':' */
struct addrinfo hints, *res0;
struct sockaddr_in6 *sin6;
struct in6_addr *addrptr;
int err;
{
struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
FILE *fp;
char addr[8][5];
int flags, myflags, index, plen, scope;
char ifname[9], lastname[IFNAMSIZ];
char addr6[32+7+1]; /* don't forget the seven ':' */
struct addrinfo hints, *res0;
struct sockaddr_in6 *sin6;
struct in6_addr *addrptr;
int err;
int sockfd = -1;
struct ifreq ifr;
res0=NULL;
ifihead = NULL;
ifipnext = &ifihead;
lastname[0] = 0;
res0=NULL;
ifihead = NULL;
ifipnext = &ifihead;
lastname[0] = 0;
if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
while (fscanf(fp,
"%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
addr[0],addr[1],addr[2],addr[3],
addr[4],addr[5],addr[6],addr[7],
&index, &plen, &scope, &flags, ifname) != EOF) {
if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
if (sockfd < 0) {
goto gotError;
}
while (fscanf(fp,
"%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
addr[0],addr[1],addr[2],addr[3],
addr[4],addr[5],addr[6],addr[7],
&index, &plen, &scope, &flags, ifname) != EOF) {
myflags = 0;
if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
if (doaliases == 0)
continue; /* already processed this interface */
myflags = IFI_ALIAS;
}
memcpy(lastname, ifname, IFNAMSIZ);
ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
if (ifi == NULL) {
goto gotError;
}
myflags = 0;
if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
if (doaliases == 0)
continue; /* already processed this interface */
myflags = IFI_ALIAS;
}
memcpy(lastname, ifname, IFNAMSIZ);
ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
if (ifi == NULL) {
goto gotError;
}
*ifipnext = ifi; /* prev points to this new one */
ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
ifipold = *ifipnext; /* need this later */
ifiptr = ifipnext;
*ifipnext = ifi; /* prev points to this new one */
ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
addr[0],addr[1],addr[2],addr[3],
addr[4],addr[5],addr[6],addr[7]);
sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
addr[0],addr[1],addr[2],addr[3],
addr[4],addr[5],addr[6],addr[7]);
/* Add address of the interface */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_flags = AI_NUMERICHOST;
err = getaddrinfo(addr6, NULL, &hints, &res0);
if (err) {
goto gotError;
}
ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
if (ifi->ifi_addr == NULL) {
goto gotError;
}
memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
/* Add address of the interface */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_flags = AI_NUMERICHOST;
err = getaddrinfo(addr6, NULL, &hints, &res0);
if (err) {
goto gotError;
}
ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
if (ifi->ifi_addr == NULL) {
goto gotError;
}
memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
/* Add netmask of the interface */
char ipv6addr[INET6_ADDRSTRLEN];
plen_to_mask(plen, ipv6addr);
ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
if (ifi->ifi_addr == NULL) {
goto gotError;
}
sin6=calloc(1, sizeof(struct sockaddr_in6));
addrptr=calloc(1, sizeof(struct in6_addr));
inet_pton(family, ipv6addr, addrptr);
sin6->sin6_family=family;
sin6->sin6_addr=*addrptr;
sin6->sin6_scope_id=scope;
memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
free(sin6);
/* Add netmask of the interface */
char ipv6addr[INET6_ADDRSTRLEN];
plen_to_mask(plen, ipv6addr);
ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
if (ifi->ifi_addr == NULL) {
goto gotError;
}
sin6=calloc(1, sizeof(struct sockaddr_in6));
addrptr=calloc(1, sizeof(struct in6_addr));
inet_pton(family, ipv6addr, addrptr);
sin6->sin6_family=family;
sin6->sin6_addr=*addrptr;
sin6->sin6_scope_id=scope;
memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
free(sin6);
/* Add interface name */
memcpy(ifi->ifi_name, ifname, IFI_NAME);
/* Add interface name */
memcpy(ifi->ifi_name, ifname, IFI_NAME);
/* Add interface index */
ifi->ifi_index = index;
/* Add interface index */
ifi->ifi_index = index;
/* If interface is in /proc then it is up*/
ifi->ifi_flags = IFF_UP;
/* Add interface flags*/
memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
if (errno == EADDRNOTAVAIL) {
/*
* If the main interface is configured with no IP address but
* an alias interface exists with an IP address, you get
* EADDRNOTAVAIL for the main interface
*/
free(ifi->ifi_addr);
free(ifi);
ifipnext = ifiptr;
*ifipnext = ifipold;
continue;
} else {
goto gotError;
}
}
ifi->ifi_flags = ifr.ifr_flags;
freeaddrinfo(res0);
res0=NULL;
}
}
goto done;
freeaddrinfo(res0);
res0=NULL;
}
}
goto done;
gotError:
if (ifihead != NULL) {
free_ifi_info(ifihead);
ifihead = NULL;
}
if (res0 != NULL) {
freeaddrinfo(res0);
res0=NULL;
}
done:
return(ifihead); /* pointer to first structure in linked list */
}
#endif /* LINUX */
#endif /* defined(AF_INET6) && HAVE_IPV6 */
gotError:
if (ifihead != NULL) {
free_ifi_info(ifihead);
ifihead = NULL;
}
if (res0 != NULL) {
freeaddrinfo(res0);
res0=NULL;
}
done:
if (sockfd != -1) {
assert(close(sockfd) == 0);
}
return(ifihead); /* pointer to first structure in linked list */
}
#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
#if HAVE_SOLARIS
@ -230,7 +248,7 @@ select_src_ifi_info_solaris(int sockfd, int numifs,
char *chptr;
char cmpifname[LIFNAMSIZ];
int i;
uint64_t best_lifrflags;
uint64_t best_lifrflags = 0;
uint64_t ifflags;
*best_lifr = NULL;
@ -509,23 +527,23 @@ gotError:
struct ifi_info *get_ifi_info(int family, int doaliases)
{
int junk;
struct ifi_info *ifi, *ifihead, **ifipnext;
int sockfd, sockf6, len, lastlen, flags, myflags;
int junk;
struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
int sockfd, sockf6, len, lastlen, flags, myflags;
#ifdef NOT_HAVE_IF_NAMETOINDEX
int index = 200;
int index = 200;
#endif
char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
struct ifconf ifc;
struct ifconf ifc;
struct ifreq *ifr, ifrcopy;
struct sockaddr_in *sinptr;
#if defined(AF_INET6) && HAVE_IPV6
struct sockaddr_in6 *sinptr6;
#endif
#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
if(family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
#elif HAVE_SOLARIS
return get_ifi_info_solaris(family);
#endif
@ -534,7 +552,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
sockf6 = -1;
buf = NULL;
ifihead = NULL;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
goto gotError;
@ -577,7 +595,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr);
// fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
if (ifr->ifr_addr.sa_family != family)
continue; /* ignore if not desired address family */
@ -595,7 +613,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) {
goto gotError;
}
flags = ifrcopy.ifr_flags;
if ((flags & IFF_UP) == 0)
continue; /* ignore if interface not up */
@ -604,8 +622,10 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
if (ifi == NULL) {
goto gotError;
}
*ifipnext = ifi; /* prev points to this new one */
ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
ifipold = *ifipnext; /* need this later */
ifiptr = ifipnext;
*ifipnext = ifi; /* prev points to this new one */
ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
ifi->ifi_flags = flags; /* IFF_xxx values */
ifi->ifi_myflags = myflags; /* IFI_xxx values */
@ -618,7 +638,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
ifi->ifi_index = ifrcopy.ifr_index;
else
#endif
ifi->ifi_index = index++; /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
ifi->ifi_index = index++; /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
#endif
memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
ifi->ifi_name[IFI_NAME-1] = '\0';
@ -635,16 +655,32 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
#ifdef SIOCGIFNETMASK
if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) goto gotError;
ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
if (ifi->ifi_netmask == NULL) goto gotError;
sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) {
if (errno == EADDRNOTAVAIL) {
/*
* If the main interface is configured with no IP address but
* an alias interface exists with an IP address, you get
* EADDRNOTAVAIL for the main interface
*/
free(ifi->ifi_addr);
free(ifi);
ifipnext = ifiptr;
*ifipnext = ifipold;
continue;
} else {
goto gotError;
}
}
ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
if (ifi->ifi_netmask == NULL) goto gotError;
sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
#ifndef NOT_HAVE_SA_LEN
sinptr->sin_len = sizeof(struct sockaddr_in);
sinptr->sin_len = sizeof(struct sockaddr_in);
#endif
sinptr->sin_family = AF_INET;
memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
sinptr->sin_family = AF_INET;
memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
#endif
#ifdef SIOCGIFBRDADDR
@ -653,11 +689,11 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
goto gotError;
}
sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
#ifndef NOT_HAVE_SA_LEN
sinptr->sin_len = sizeof( struct sockaddr_in );
sinptr->sin_len = sizeof( struct sockaddr_in );
#endif
sinptr->sin_family = AF_INET;
sinptr->sin_family = AF_INET;
ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
if (ifi->ifi_brdaddr == NULL) {
goto gotError;
@ -674,9 +710,9 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
#ifndef NOT_HAVE_SA_LEN
sinptr->sin_len = sizeof( struct sockaddr_in );
sinptr->sin_len = sizeof( struct sockaddr_in );
#endif
sinptr->sin_family = AF_INET;
sinptr->sin_family = AF_INET;
ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
if (ifi->ifi_dstaddr == NULL) {
goto gotError;
@ -695,27 +731,42 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
if (ifi->ifi_addr == NULL) {
goto gotError;
}
/* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
/* We need to strip that out */
if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr))
sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0;
sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0;
memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
#ifdef SIOCGIFNETMASK_IN6
{
struct in6_ifreq ifr6;
if (sockf6 == -1)
sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
bzero(&ifr6, sizeof(ifr6));
memcpy(&ifr6.ifr_name, &ifr->ifr_name, sizeof(ifr6.ifr_name ));
memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) goto gotError;
ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
if (ifi->ifi_netmask == NULL) goto gotError;
sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6));
}
{
struct in6_ifreq ifr6;
if (sockf6 == -1)
sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
memset(&ifr6, 0, sizeof(ifr6));
memcpy(&ifr6.ifr_name, &ifr->ifr_name, sizeof(ifr6.ifr_name ));
memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) {
if (errno == EADDRNOTAVAIL) {
/*
* If the main interface is configured with no IP address but
* an alias interface exists with an IP address, you get
* EADDRNOTAVAIL for the main interface
*/
free(ifi->ifi_addr);
free(ifi);
ifipnext = ifiptr;
*ifipnext = ifipold;
continue;
} else {
goto gotError;
}
}
ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
if (ifi->ifi_netmask == NULL) goto gotError;
sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6));
}
#endif
}
break;
@ -726,7 +777,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
}
}
goto done;
gotError:
if (ifihead != NULL) {
free_ifi_info(ifihead);
@ -758,35 +809,35 @@ free_ifi_info(struct ifi_info *ifihead)
for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
if (ifi->ifi_addr != NULL)
free(ifi->ifi_addr);
if (ifi->ifi_netmask != NULL)
free(ifi->ifi_netmask);
if (ifi->ifi_brdaddr != NULL)
free(ifi->ifi_brdaddr);
if (ifi->ifi_dstaddr != NULL)
free(ifi->ifi_dstaddr);
if (ifi->ifi_netmask != NULL)
free(ifi->ifi_netmask);
ifinext = ifi->ifi_next; /* can't fetch ifi_next after free() */
free(ifi); /* the ifi_info{} itself */
}
}
/* end free_ifi_info */
ssize_t
ssize_t
recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)
{
struct msghdr msg;
struct iovec iov[1];
ssize_t n;
struct msghdr msg;
struct iovec iov[1];
ssize_t n;
#ifdef CMSG_FIRSTHDR
struct cmsghdr *cmptr;
union {
struct cmsghdr cm;
char control[1024];
pad64_t align8; /* ensure structure is 8-byte aligned on sparc */
struct cmsghdr cm;
char control[1024];
pad64_t align8; /* ensure structure is 8-byte aligned on sparc */
} control_un;
*ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be
*ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be
msg.msg_control = (void *) control_un.control;
msg.msg_controllen = sizeof(control_un.control);
@ -808,12 +859,12 @@ recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
*salenptr = msg.msg_namelen; /* pass back results */
if (pktp) {
/* 0.0.0.0, i/f = -1 */
/* We set the interface to -1 so that the caller can
tell whether we returned a meaningful value or
just some default. Previously this code just
set the value to 0, but I'm concerned that 0
/* We set the interface to -1 so that the caller can
tell whether we returned a meaningful value or
just some default. Previously this code just
set the value to 0, but I'm concerned that 0
might be a valid interface value.
*/
*/
memset(pktp, 0, sizeof(struct my_in_pktinfo));
pktp->ipi_ifindex = -1;
}
@ -821,7 +872,7 @@ recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
/* include recvfrom_flags2 */
#ifndef CMSG_FIRSTHDR
#warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
#warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
*flagsp = 0; /* pass back results */
return(n);
#else
@ -836,18 +887,18 @@ recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
#ifdef IP_PKTINFO
#if in_pktinfo_definition_is_missing
struct in_pktinfo
{
int ipi_ifindex;
struct in_addr ipi_spec_dst;
struct in_addr ipi_addr;
};
struct in_pktinfo
{
int ipi_ifindex;
struct in_addr ipi_spec_dst;
struct in_addr ipi_addr;
};
#endif
if (cmptr->cmsg_level == IPPROTO_IP &&
if (cmptr->cmsg_level == IPPROTO_IP &&
cmptr->cmsg_type == IP_PKTINFO) {
struct in_pktinfo *tmp;
struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
tmp = (struct in_pktinfo *) CMSG_DATA(cmptr);
sin->sin_family = AF_INET;
sin->sin_addr = tmp->ipi_addr;
@ -861,7 +912,7 @@ struct in_pktinfo
if (cmptr->cmsg_level == IPPROTO_IP &&
cmptr->cmsg_type == IP_RECVDSTADDR) {
struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
sin->sin_family = AF_INET;
sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr);
sin->sin_port = 0;
@ -877,7 +928,16 @@ struct in_pktinfo
int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1);
strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen);
#endif
(void) memcpy(&pktp->ipi_ifindex, CMSG_DATA(cmptr), sizeof(uint_t));
/*
* the is memcpy used for sparc? no idea;)
* pktp->ipi_ifindex = sdl->sdl_index;
*/
(void) memcpy(&pktp->ipi_ifindex, CMSG_DATA(cmptr), sizeof(uint_t));
#ifdef HAVE_BROKEN_RECVIF_NAME
if (sdl->sdl_index == 0) {
pktp->ipi_ifindex = *(uint_t*)sdl;
}
#endif
assert(pktp->ipi_ifname[IFI_NAME - 1] == 0);
// null terminated because of memset above
continue;
@ -887,22 +947,22 @@ struct in_pktinfo
#ifdef IP_RECVTTL
if (cmptr->cmsg_level == IPPROTO_IP &&
cmptr->cmsg_type == IP_RECVTTL) {
*ttl = *(u_char*)CMSG_DATA(cmptr);
*ttl = *(u_char*)CMSG_DATA(cmptr);
continue;
}
else if (cmptr->cmsg_level == IPPROTO_IP &&
cmptr->cmsg_type == IP_TTL) { // some implementations seem to send IP_TTL instead of IP_RECVTTL
*ttl = *(int*)CMSG_DATA(cmptr);
cmptr->cmsg_type == IP_TTL) { // some implementations seem to send IP_TTL instead of IP_RECVTTL
*ttl = *(int*)CMSG_DATA(cmptr);
continue;
}
#endif
#if defined(IPV6_PKTINFO) && HAVE_IPV6
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
cmptr->cmsg_type == IPV6_PKTINFO) {
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
cmptr->cmsg_type == IPV6_PKTINFO) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
sin6->sin6_family = AF_INET6;
#ifndef NOT_HAVE_SA_LEN
sin6->sin6_len = sizeof(*sin6);
@ -911,15 +971,15 @@ struct in_pktinfo
sin6->sin6_flowinfo = 0;
sin6->sin6_scope_id = 0;
sin6->sin6_port = 0;
pktp->ipi_ifindex = ip6_info->ipi6_ifindex;
pktp->ipi_ifindex = ip6_info->ipi6_ifindex;
continue;
}
#endif
#if defined(IPV6_HOPLIMIT) && HAVE_IPV6
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
cmptr->cmsg_type == IPV6_HOPLIMIT) {
*ttl = *(int*)CMSG_DATA(cmptr);
*ttl = *(int*)CMSG_DATA(cmptr);
continue;
}
#endif
@ -937,44 +997,44 @@ struct in_pktinfo
#ifdef NOT_HAVE_DAEMON
#include <fcntl.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/signal.h>
int daemon(int nochdir, int noclose)
{
switch (fork())
{
switch (fork())
{
case -1: return (-1); // Fork failed
case 0: break; // Child -- continue
default: _exit(0); // Parent -- exit
}
if (setsid() == -1) return(-1);
signal(SIGHUP, SIG_IGN);
switch (fork()) // Fork again, primarily for reasons of Unix trivia
{
case -1: return (-1); // Fork failed
case 0: break; // Child -- continue
default: _exit(0); // Parent -- exit
}
if (!nochdir) (void)chdir("/");
umask(0);
if (!noclose)
{
int fd = open("/dev/null", O_RDWR, 0);
if (fd != -1)
{
// Avoid unnecessarily duplicating a file descriptor to itself
if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO);
if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO);
if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO);
if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
(void)close (fd);
}
}
return (0);
case -1: return (-1); // Fork failed
case 0: break; // Child -- continue
default: _exit(0); // Parent -- exit
}
if (setsid() == -1) return(-1);
signal(SIGHUP, SIG_IGN);
switch (fork()) // Fork again, primarily for reasons of Unix trivia
{
case -1: return (-1); // Fork failed
case 0: break; // Child -- continue
default: _exit(0); // Parent -- exit
}
if (!nochdir) (void)chdir("/");
umask(0);
if (!noclose)
{
int fd = open("/dev/null", O_RDWR, 0);
if (fd != -1)
{
// Avoid unnecessarily duplicating a file descriptor to itself
if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO);
if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO);
if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO);
if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
(void)close (fd);
}
}
return (0);
}
#endif /* NOT_HAVE_DAEMON */

View File

@ -5,83 +5,15 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: mDNSUNP.h,v $
Revision 1.19 2006/08/14 23:24:47 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.18 2005/04/08 21:37:57 ksekar
<rdar://problem/3792767> get_ifi_info doesn't return IPv6 interfaces on Linux
Revision 1.17 2004/12/17 19:32:43 cheshire
Add missing semicolon
Revision 1.16 2004/12/01 04:25:05 cheshire
<rdar://problem/3872803> Darwin patches for Solaris and Suse
Provide daemon() for platforms that don't have it
Revision 1.15 2004/11/30 22:37:01 cheshire
Update copyright dates and add "Mode: C; tab-width: 4" headers
Revision 1.14 2004/10/16 00:17:01 cheshire
<rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
Revision 1.13 2004/03/20 05:37:09 cheshire
Fix contributed by Terry Lambert & Alfred Perlstein:
Don't use uint8_t -- it requires stdint.h, which doesn't exist on FreeBSD 4.x
Revision 1.12 2004/01/28 21:12:15 cheshire
Reconcile mDNSIPv6Support & HAVE_IPV6 into a single flag (HAVE_IPV6)
Revision 1.11 2003/12/13 05:43:09 bradley
Fixed non-sa_len and non-IPv6 version of GET_SA_LEN macro to cast as sockaddr to access
sa_family so it works with any sockaddr-compatible address structure (e.g. sockaddr_storage).
Revision 1.10 2003/12/11 03:03:51 rpantos
Clean up mDNSPosix so that it builds on OS X again.
Revision 1.9 2003/12/08 20:47:02 rpantos
Add support for mDNSResponder on Linux.
Revision 1.8 2003/08/12 19:56:26 cheshire
Update to APSL 2.0
Revision 1.7 2003/08/06 18:20:51 cheshire
Makefile cleanup
Revision 1.6 2003/07/02 21:19:59 cheshire
<rdar://problem/3313413> Update copyright notices, etc., in source code comments
Revision 1.5 2003/03/13 03:46:21 cheshire
Fixes to make the code build on Linux
Revision 1.4 2002/12/23 22:13:32 jgraessl
Reviewed by: Stuart Cheshire
Initial IPv6 support for mDNSResponder.
Revision 1.3 2002/09/21 20:44:53 zarzycki
Added APSL info
Revision 1.2 2002/09/19 04:20:44 cheshire
Remove high-ascii characters that confuse some systems
Revision 1.1 2002/09/17 06:24:35 cheshire
First checkin
*/
#pragma ident "%Z%%M% %I% %E% SMI"
*/
#ifndef __mDNSUNP_h
#define __mDNSUNP_h
@ -90,18 +22,26 @@ First checkin
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef HAVE_LINUX
#include <linux/socket.h>
#define IPV6_2292_PKTINFO IPV6_2292PKTINFO
#define IPV6_2292_HOPLIMIT IPV6_2292HOPLIMIT
#else
// The following are the supported non-linux posix OSes -
// netbsd, freebsd and openbsd.
#if HAVE_IPV6
#define IPV6_2292_PKTINFO 19
#define IPV6_2292_HOPLIMIT 20
#endif
#endif
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
#ifdef NOT_HAVE_SOCKLEN_T
typedef unsigned int socklen_t;
typedef unsigned int socklen_t;
#endif
#if !defined(_SS_MAXSIZE)
@ -109,7 +49,7 @@ First checkin
#define sockaddr_storage sockaddr_in6
#else
#define sockaddr_storage sockaddr
#endif // HAVE_IPV6
#endif // HAVE_IPV6
#endif // !defined(_SS_MAXSIZE)
#ifndef NOT_HAVE_SA_LEN
@ -129,8 +69,8 @@ First checkin
struct my_in_pktinfo {
struct sockaddr_storage ipi_addr;
int ipi_ifindex; /* received interface index */
char ipi_ifname[IFI_NAME]; /* received interface name */
int ipi_ifindex; /* received interface index */
char ipi_ifname[IFI_NAME]; /* received interface name */
};
/* From the text (Stevens, section 20.2): */
@ -140,33 +80,33 @@ struct my_in_pktinfo {
/* 2. the destination addres of the received datagram (from the IP_RECVDSTADDR socket option, and */
/* 3. the index of the interface on which the datagram was received (the IP_RECVIF socket option).' */
extern ssize_t recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl);
struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl);
struct ifi_info {
char ifi_name[IFI_NAME]; /* interface name, null terminated */
u_char ifi_haddr[IFI_HADDR]; /* hardware address */
u_short ifi_hlen; /* #bytes in hardware address: 0, 6, 8 */
short ifi_flags; /* IFF_xxx constants from <net/if.h> */
short ifi_myflags; /* our own IFI_xxx flags */
int ifi_index; /* interface index */
struct sockaddr *ifi_addr; /* primary address */
struct sockaddr *ifi_netmask;
struct sockaddr *ifi_brdaddr;/* broadcast address */
struct sockaddr *ifi_dstaddr;/* destination address */
struct ifi_info *ifi_next; /* next of these structures */
char ifi_name[IFI_NAME]; /* interface name, null terminated */
u_char ifi_haddr[IFI_HADDR]; /* hardware address */
u_short ifi_hlen; /* #bytes in hardware address: 0, 6, 8 */
short ifi_flags; /* IFF_xxx constants from <net/if.h> */
short ifi_myflags; /* our own IFI_xxx flags */
int ifi_index; /* interface index */
struct sockaddr *ifi_addr; /* primary address */
struct sockaddr *ifi_netmask;
struct sockaddr *ifi_brdaddr; /* broadcast address */
struct sockaddr *ifi_dstaddr; /* destination address */
struct ifi_info *ifi_next; /* next of these structures */
};
#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
#define PROC_IFINET6_PATH "/proc/net/if_inet6"
extern struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases);
#endif
#if defined(AF_INET6) && HAVE_IPV6
#define INET6_ADDRSTRLEN 46 /*Maximum length of IPv6 address */
#endif
#define IFI_ALIAS 1 /* ifi_addr is an alias */
/* From the text (Stevens, section 16.6): */
@ -184,7 +124,7 @@ extern int daemon(int nochdir, int noclose);
#endif
#ifdef __cplusplus
}
}
#endif
#endif

View File

@ -0,0 +1,33 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NSEC_H
#define __NSEC_H
#include "dnssec.h"
extern mDNSBool AddNSECSForCacheRecord(mDNS *const m, CacheRecord *crlist, CacheRecord *negcr, mDNSu8 rcode);
extern void WildcardAnswerProof(mDNS *const m, DNSSECVerifier *dv);
extern void ValidateWithNSECS(mDNS *const m, DNSSECVerifier *dv, CacheRecord *rr);
extern mDNSBool NSECAnswersDS(mDNS *const m, ResourceRecord *rr, DNSQuestion *q);
extern int CountLabelsMatch(const domainname *const d1, const domainname *const d2);
extern void NameErrorNSECCallback(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status);
extern void VerifyNSEC(mDNS *const m, ResourceRecord *rr, RRVerifier *rv, DNSSECVerifier *pdv, CacheRecord *ncr,
DNSSECVerifierCallback callback);
extern CacheRecord *NSECRecordIsDelegation(mDNS *const m, domainname *name, mDNSu16 qtype);
extern void NoDataNSECCallback(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status);
#endif // __NSEC_H

File diff suppressed because it is too large Load Diff

View File

@ -1,192 +1,151 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: uDNS.h,v $
Revision 1.32.2.1 2006/08/29 06:24:23 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.32 2005/07/29 19:46:10 ksekar
<rdar://problem/4191860> reduce polling period on failed LLQs to 15 minutes
Revision 1.31 2005/03/31 02:19:56 cheshire
<rdar://problem/4021486> Fix build warnings
Reviewed by: Scott Herscher
Revision 1.30 2005/03/04 03:00:03 ksekar
<rdar://problem/4026546> Retransmissions happen too early, causing registrations to conflict with themselves
Revision 1.29 2005/01/11 22:50:53 ksekar
Fixed constant naming (was using kLLQ_DefLease for update leases)
Revision 1.28 2004/12/22 00:13:49 ksekar
<rdar://problem/3873993> Change version, port, and polling interval for LLQ
Revision 1.27 2004/11/23 04:06:50 cheshire
Get rid of floating point constant -- in a small embedded device, bringing in all
the floating point libraries just to halve an integer value is a bit too heavyweight.
Revision 1.26 2004/11/22 17:49:15 ksekar
Changed INIT_REFRESH from fraction to decimal
Revision 1.25 2004/11/22 17:16:20 ksekar
<rdar://problem/3854298> Unicast services don't disappear when you disable all networking
Revision 1.24 2004/11/19 04:24:08 ksekar
<rdar://problem/3682609> Security: Enforce a "window" on one-shot wide-area queries
Revision 1.23 2004/11/18 18:04:21 ksekar
Add INIT_REFRESH constant
Revision 1.22 2004/11/15 20:09:24 ksekar
<rdar://problem/3719050> Wide Area support for Add/Remove record
Revision 1.21 2004/11/11 20:14:55 ksekar
<rdar://problem/3719574> Wide-Area registrations not deregistered on sleep
Revision 1.20 2004/10/16 00:16:59 cheshire
<rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
Revision 1.19 2004/09/17 01:08:49 cheshire
Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
declared in that file are ONLY appropriate to single-address-space embedded applications.
For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
Revision 1.18 2004/09/03 19:23:05 ksekar
<rdar://problem/3788460>: Need retransmission mechanism for wide-area service registrations
Revision 1.17 2004/09/01 03:59:29 ksekar
<rdar://problem/3783453>: Conditionally compile out uDNS code on Windows
Revision 1.16 2004/08/25 00:37:27 ksekar
<rdar://problem/3774635>: Cleanup DynDNS hostname registration code
Revision 1.15 2004/07/30 17:40:06 ksekar
<rdar://problem/3739115>: TXT Record updates not available for wide-area services
Revision 1.14 2004/07/29 19:27:15 ksekar
NATPMP Support - minor fixes and cleanup
Revision 1.13 2004/07/29 02:03:35 ksekar
Delete unused #define and structure field
Revision 1.12 2004/07/26 22:49:30 ksekar
<rdar://problem/3651409>: Feature #9516: Need support for NATPMP in client
Revision 1.11 2004/06/17 01:13:11 ksekar
<rdar://problem/3696616>: polling interval too short
Revision 1.10 2004/06/11 05:45:03 ksekar
<rdar://problem/3682397>: Change SRV names for LLQ/Update port lookups
Revision 1.9 2004/06/01 23:46:50 ksekar
<rdar://problem/3675149>: DynDNS: dynamically look up LLQ/Update ports
Revision 1.8 2004/05/28 23:42:37 ksekar
<rdar://problem/3258021>: Feature: DNS server->client notification on record changes (#7805)
Revision 1.7 2004/05/18 23:51:25 cheshire
Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
Revision 1.6 2004/03/13 01:57:33 ksekar
<rdar://problem/3192546>: DynDNS: Dynamic update of service records
Revision 1.5 2004/02/21 08:56:58 bradley
Wrap prototypes with extern "C" for C++ builds.
Revision 1.4 2004/02/06 23:04:19 ksekar
Basic Dynamic Update support via mDNS_Register (dissabled via
UNICAST_REGISTRATION #define)
Revision 1.3 2004/01/24 03:38:27 cheshire
Fix minor syntactic error: Headers should use "extern" declarations, not "mDNSexport"
Revision 1.2 2004/01/23 23:23:15 ksekar
Added TCP support for truncated unicast messages.
Revision 1.1 2003/12/13 03:05:27 ksekar
<rdar://problem/3192548>: DynDNS: Unicast query of service records
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef __UDNS_H_
#define __UDNS_H_
#include "mDNSEmbeddedAPI.h"
#include "DNSCommon.h"
#ifdef __cplusplus
extern "C" {
#ifdef __cplusplus
extern "C" {
#endif
#define RESTART_GOODBYE_DELAY (6 * mDNSPlatformOneSecond) // delay after restarting LLQ before nuking previous known answers (avoids flutter if we restart before we have networking up)
#define MIN_UCAST_PERIODIC_EXEC (5 * mDNSPlatformOneSecond)
#define INIT_UCAST_POLL_INTERVAL (3 * mDNSPlatformOneSecond) // this interval is used after send failures on network transitions
// which typically heal quickly, so we start agressively and exponentially back off
// which typically heal quickly, so we start agressively and exponentially back off
#define MAX_UCAST_POLL_INTERVAL (60 * 60 * mDNSPlatformOneSecond)
//#define MAX_UCAST_POLL_INTERVAL (1 * 60 * mDNSPlatformOneSecond)
#define LLQ_POLL_INTERVAL (15 * 60 * mDNSPlatformOneSecond) // Polling interval for zones w/ an advertised LLQ port (ie not static zones) if LLQ fails due to NAT, etc.
#define RESPONSE_WINDOW (60 * mDNSPlatformOneSecond) // require server responses within one minute of request
#define UPDATE_PORT_NAME "_dns-update._udp."
#define LLQ_PORT_NAME "_dns-llq._udp"
#define MAX_DNSSEC_UNANSWERED_QUERIES 1 // number of unanswered queries from any one uDNS server before turning off DNSSEC Validation
#define MAX_UCAST_UNANSWERED_QUERIES 2 // number of unanswered queries from any one uDNS server before trying another server
#define DNSSERVER_PENALTY_TIME (60 * mDNSPlatformOneSecond) // number of seconds for which new questions don't pick this server
// On some interfaces, we want to delay the first retransmission to a minimum of 2 seconds
// rather than the default (1 second).
#define MIN_UCAST_RETRANS_TIMEOUT (2 * mDNSPlatformOneSecond)
#define DEFAULT_UPDATE_LEASE 7200
#define QuestionIntervalStep 3
#define QuestionIntervalStep2 (QuestionIntervalStep*QuestionIntervalStep)
#define QuestionIntervalStep3 (QuestionIntervalStep*QuestionIntervalStep*QuestionIntervalStep)
#define InitialQuestionInterval ((mDNSPlatformOneSecond + QuestionIntervalStep-1) / QuestionIntervalStep)
#define MaxQuestionInterval (3600 * mDNSPlatformOneSecond)
// just move to MaxQuestionInterval once over this threshold
#define QuestionIntervalThreshold (QuestionIntervalStep3 * mDNSPlatformOneSecond)
// For Unicast record registrations, we initialize the interval to 1 second. When we send any query for
// the record registration e.g., GetZoneData, we always back off by QuestionIntervalStep
// so that the first retry does not happen until 3 seconds which should be enough for TCP/TLS to be done.
#define INIT_RECORD_REG_INTERVAL (1 * mDNSPlatformOneSecond)
#define MAX_RECORD_REG_INTERVAL (15 * 60 * mDNSPlatformOneSecond)
#define MERGE_DELAY_TIME (1 * mDNSPlatformOneSecond)
// If we are refreshing, we do it at least 5 times with a min update frequency of
// 5 minutes
#define MAX_UPDATE_REFRESH_COUNT 5
#define MIN_UPDATE_REFRESH_TIME (5 * 60 * mDNSPlatformOneSecond)
// For questions that use kDNSServiceFlagsTimeout and we don't have a matching resolver e.g., no dns servers,
// then use the default value of 30 seconds
#define DEFAULT_UDNS_TIMEOUT 30 // in seconds
// For questions that are validating responses (q->ValidatingResponse == 1), use 10 seconds
// which accomodates two DNS servers and two queries per DNS server.
#define DEFAULT_UDNSSEC_TIMEOUT 10 // in seconds
// If we are sending queries with EDNS0/DO option and we have no indications that the server
// is DNSSEC aware and we have already reached MAX_DNSSEC_RETRANSMISSIONS, we disable
// validation (for optional case only) for any questions that uses this server
#define MAX_DNSSEC_RETRANSMISSIONS 3
// Entry points into unicast-specific routines
extern mStatus uDNS_StartQuery(mDNS *const m, DNSQuestion *const question);
extern mDNSBool uDNS_IsActiveQuery(DNSQuestion *const question, uDNS_GlobalInfo *u); // returns true if OK to call StopQuery
extern mStatus uDNS_StopQuery(mDNS *const m, DNSQuestion *const question);
extern void uDNS_Init(mDNS *const m);
extern void uDNS_Sleep(mDNS *const m);
extern void uDNS_Wake(mDNS *const m);
#define uDNS_Close uDNS_Sleep
extern void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo);
extern void startLLQHandshake(mDNS *m, DNSQuestion *q);
extern void sendLLQRefresh(mDNS *m, DNSQuestion *q);
extern void SleepRecordRegistrations(mDNS *m);
// uDNS_UpdateRecord
// following fields must be set, and the update validated, upon entry.
// rr->NewRData
// rr->newrdlength
// rr->UpdateCallback
extern mStatus uDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra);
extern mStatus uDNS_UpdateRecord(mDNS *m, AuthRecord *rr);
extern mStatus uDNS_RegisterRecord(mDNS *const m, AuthRecord *const rr);
extern mStatus uDNS_DeregisterRecord(mDNS *const m, AuthRecord *const rr);
extern mStatus uDNS_RegisterService(mDNS *const m, ServiceRecordSet *srs);
extern mStatus uDNS_DeregisterService(mDNS *const m, ServiceRecordSet *srs);
extern void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q);
extern mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr);
extern mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt);
extern mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question);
extern mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question);
extern mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalInfo *traversal);
extern void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData);
extern mStatus uDNS_DeregisterRecord(mDNS *const m, AuthRecord *const rr);
extern const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr);
extern void uDNS_CheckCurrentQuestion(mDNS *const m);
// integer fields of msg header must be in HOST byte order before calling this routine
extern void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *const dstaddr,
const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID);
const mDNSAddr *const srcaddr, const mDNSIPPort srcport);
extern void uDNS_ReceiveNATMap(mDNS *m, mDNSu8 *pkt, mDNSu16 len);
// returns time of next scheduled event
extern void uDNS_Execute(mDNS *const m);
extern void uDNS_Tasks(mDNS *const m);
extern void UpdateAllSRVRecords(mDNS *m);
extern void CheckNATMappings(mDNS *m);
#ifdef __cplusplus
}
extern mStatus uDNS_SetupDNSConfig(mDNS *const m);
// uDNS_SetupWABQueries reads search domains from the platform layer and starts the Wide Area Bonjour
// (WAB) domain enumeration queries if necessary.
#define UDNS_WAB_BROWSE_QUERY 0x00000001 // Browse queries (b, db)
#define UDNS_WAB_LBROWSE_QUERY 0x00000002 // Browse queries (lb)
#define UDNS_WAB_REG_QUERY 0x00000004 // Registration queries (r and dr)
extern void uDNS_SetupWABQueries(mDNS *const m);
extern void uDNS_StartWABQueries(mDNS *const m, int queryType);
extern void uDNS_StopWABQueries(mDNS *const m, int queryType);
extern domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal);
typedef enum
{
uDNS_LLQ_Not = 0, // Normal uDNS answer: Flush any stale records from cache, and respect record TTL
uDNS_LLQ_Ignore, // LLQ initial challenge packet: ignore -- has no useful records for us
uDNS_LLQ_Entire, // LLQ initial set of answers: Flush any stale records from cache, but assume TTL is 2 x LLQ refresh interval
uDNS_LLQ_Events // LLQ event packet: don't flush cache; assume TTL is 2 x LLQ refresh interval
} uDNS_LLQType;
extern uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, DNSQuestion **matchQuestion);
extern DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname *const name);
extern DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *const q);
extern void DisposeTCPConn(struct tcpInfo_t *tcp);
// NAT traversal
extern void uDNS_ReceiveNATPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 *pkt, mDNSu16 len); // Called for each received PCP or NAT-PMP packet
extern void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv4Addr ExtAddr);
extern void natTraversalHandlePortMapReply(mDNS *const m, NATTraversalInfo *n, const mDNSInterfaceID InterfaceID, mDNSu16 err, mDNSIPPort extport, mDNSu32 lease, NATTProtocol protocol);
#ifdef __cplusplus
}
#endif
#endif // __UDNS_H_

File diff suppressed because it is too large Load Diff

View File

@ -5,114 +5,86 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
File: uds_daemon.h
File: uds_daemon.h
Contains: Interfaces necessary to talk to uds_daemon.c.
Contains: Interfaces necessary to talk to uds_daemon.c.
Version: 1.0
Version: 1.0
Change History (most recent first):
$Log: uds_daemon.h,v $
Revision 1.15 2006/08/14 23:24:57 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.14 2005/01/27 17:48:39 cheshire
Added comment about CFSocketInvalidate closing the underlying socket
Revision 1.13 2004/12/10 05:27:26 cheshire
<rdar://problem/3909147> Guard against multiple autoname services of the same type on the same machine
Revision 1.12 2004/12/10 04:28:28 cheshire
<rdar://problem/3914406> User not notified of name changes for services using new UDS API
Revision 1.11 2004/12/06 21:15:23 ksekar
<rdar://problem/3884386> mDNSResponder crashed in CheckServiceRegistrations
Revision 1.10 2004/10/26 04:31:44 cheshire
Rename CountSubTypes() as ChopSubTypes()
Revision 1.9 2004/09/30 00:25:00 ksekar
<rdar://problem/3695802> Dynamically update default registration domains on config change
Revision 1.8 2004/09/21 21:05:11 cheshire
Move duplicate code out of mDNSMacOSX/daemon.c and mDNSPosix/PosixDaemon.c,
into mDNSShared/uds_daemon.c
Revision 1.7 2004/09/17 01:08:55 cheshire
Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
declared in that file are ONLY appropriate to single-address-space embedded applications.
For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
Revision 1.6 2004/08/11 01:58:49 cheshire
Remove "mDNS *globalInstance" parameter from udsserver_init()
Revision 1.5 2004/06/18 04:44:58 rpantos
Use platform layer for socket types
Revision 1.4 2004/06/12 00:51:58 cheshire
Changes for Windows compatibility
Revision 1.3 2004/01/25 00:03:21 cheshire
Change to use mDNSVal16() instead of private PORT_AS_NUM() macro
Revision 1.2 2004/01/24 08:46:26 bradley
Added InterfaceID<->Index platform interfaces since they are now used by all platforms for the DNS-SD APIs.
Revision 1.1 2003/12/08 21:11:42 rpantos;
Changes necessary to support mDNSResponder on Linux.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
*/
#include "mDNSEmbeddedAPI.h"
#include "dnssd_ipc.h"
/* Client interface: */
#define SRS_PORT(S) mDNSVal16((S)->RR_SRV.resrec.rdata->u.srv.port)
extern int udsserver_init(void);
// takes the next scheduled event time, does idle work, and returns the updated nextevent time
extern int udsserver_init(dnssd_sock_t skts[], mDNSu32 count);
extern mDNSs32 udsserver_idle(mDNSs32 nextevent);
extern void udsserver_info(mDNS *const m); // print out info about current state
extern void udsserver_handle_configchange(void);
extern int udsserver_exit(void); // should be called prior to app exit
extern void udsserver_default_reg_domain_changed(const domainname *d, mDNSBool add);
extern void udsserver_default_browse_domain_changed(const domainname *d, mDNSBool add);
extern void udsserver_info(mDNS *const m); // print out info about current state
extern void udsserver_handle_configchange(mDNS *const m);
extern int udsserver_exit(void); // should be called prior to app exit
extern void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start, mDNSBool mstatelog);
#define LogMcastQ (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastQuestion
#define LogMcastS (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastService
#define LogMcast (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMsg
#define LogMcastNoIdent (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMsgNoIdent
/* Routines that uds_daemon expects to link against: */
typedef void (*udsEventCallback)(void *context);
typedef void (*udsEventCallback)(int fd, short filter, void *context);
extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback callback, void *context, void **platform_data);
extern int udsSupportReadFD(dnssd_sock_t fd, char* buf, int len, int flags, void *platform_data);
extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd, void *platform_data); // Note: This also CLOSES the file descriptor as well
extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback callback, void *context);
extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd); // Note: This also CLOSES the file descriptor as well
// RecordUpdatedNiceLabel() can be a no-op on platforms that don't care about updating the machine's
// global default service name (was OS X calls the "Computer Name") in response to name conflicts.
extern void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay);
// Globals and functions defined in uds_daemon.c and also shared with the old "daemon.c" on OS X
extern mDNS mDNSStorage;
extern mDNSs32 ChopSubTypes(char *regtype);
extern AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p);
extern DNameListElem *AutoRegistrationDomains;
extern DNameListElem *AutoBrowseDomains;
extern mDNSs32 ChopSubTypes(char *regtype, char **AnonData);
extern AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **AnonData);
extern int CountExistingRegistrations(domainname *srv, mDNSIPPort port);
extern void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result);
extern int CountPeerRegistrations(mDNS *const m, ServiceRecordSet *const srs);
#if APPLE_OSX_mDNSResponder
extern void machserver_automatic_browse_domain_changed(const domainname *d, mDNSBool add);
extern void machserver_automatic_registration_domain_changed(const domainname *d, mDNSBool add);
// D2D interface support
extern void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags);
extern void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags);
extern void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
extern void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
extern void external_start_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags);
extern void external_stop_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags);
extern void external_connection_release(const domainname *instance);
#else // APPLE_OSX_mDNSResponder
#define external_start_browsing_for_service(A,B,C,D) (void)(A)
#define external_stop_browsing_for_service(A,B,C,D) (void)(A)
#define external_start_advertising_service(A,B) (void)(A)
#define external_stop_advertising_service(A,B) (void)(A)
#define external_start_resolving_service(A,B,C) (void)(A)
#define external_stop_resolving_service(A,B,C) (void)(A)
#define external_connection_release(A) (void)(A)
#endif // APPLE_OSX_mDNSResponder
extern const char mDNSResponderVersionString_SCCS[];
#define mDNSResponderVersionString (mDNSResponderVersionString_SCCS+5)

View File

@ -20,6 +20,7 @@
#
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
# Copyright 2016 Toomas Soome <tsoome@me.com>
#
LIBRARY = libdns_sd.a
@ -33,14 +34,10 @@ $(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
SRCDIR = ../common
LDLIBS += -lsocket -lc
LDLIBS += -lsocket -lnsl -lc
C99MODE = $(C99_ENABLE)
CPPFLAGS += -I$(SRCDIR) -DNOT_HAVE_SA_LEN
CERRWARN += -erroff=E_ASSIGNMENT_TYPE_MISMATCH
CERRWARN += -_gcc=-Wno-implicit-function-declaration
CPPFLAGS += -I$(SRCDIR) -DNOT_HAVE_SA_LEN -D_XPG4_2 -D__EXTENSIONS__
.PARALLEL = $(OBJECTS)
.KEEP_STATE:

View File

@ -21,8 +21,9 @@
#
# CDDL HEADER END
#
#ident "%Z%%M% %I% %E% SMI"
# Copyright 2016 Toomas Soome <tsoome@me.com>
#
Updated from upstream version mDNSResponder-576.30.4
Multicast DNS and Service Discovery support in Solaris using the
Apple Bonjour source code (v107.6). Apple Bonjour source can be

View File

@ -1,24 +1,13 @@
* Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The majority of the source code in the mDNSResponder project is licensed
under the terms of the Apache License, Version 2.0, available from:
<http://www.apache.org/licenses/LICENSE-2.0>
To accommodate license compatibility with the widest possible range
of client code licenses, the shared library code, which is linked
at runtime into the same address space as the client using it, is
licensed under the terms of the "Three-Clause BSD License".
The Linux Name Service Switch code, contributed by National ICT
Australia Ltd (NICTA) is licensed under the terms of the NICTA Public
Software Licence (which is substantially similar to the "Three-Clause
BSD License", with some additional language pertaining to Australian law).

File diff suppressed because it is too large Load Diff

View File

@ -2,74 +2,30 @@
*
* Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Change History (most recent first):
$Log: dnssd_clientlib.c,v $
Revision 1.11 2006/08/14 23:05:53 cheshire
Added "tab-width" emacs header line
Revision 1.10 2005/04/06 02:06:56 shersche
Add DNSSD_API macro to TXTRecord API calls
Revision 1.9 2004/10/06 02:22:19 cheshire
Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
Revision 1.8 2004/10/01 22:15:55 rpantos
rdar://problem/3824265: Replace APSL in client lib with BSD license.
Revision 1.7 2004/06/26 03:16:34 shersche
clean up warning messages on Win32 platform
Submitted by: herscher
Revision 1.6 2004/06/12 01:09:45 cheshire
To be callable from the broadest range of clients on Windows (e.g. Visual Basic, C#, etc.)
API routines have to be declared as "__stdcall", instead of the C default, "__cdecl"
Revision 1.5 2004/05/25 18:29:33 cheshire
Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c,
so that it's also accessible to dnssd_clientshim.c (single address space) clients.
Revision 1.4 2004/05/25 17:08:55 cheshire
Fix compiler warning (doesn't make sense for function return type to be const)
Revision 1.3 2004/05/21 21:41:35 cheshire
Add TXT record building and parsing APIs
Revision 1.2 2004/05/20 22:22:21 cheshire
Enable code that was bracketed by "#if 0"
Revision 1.1 2004/03/12 21:30:29 cheshire
Build a System-Context Shared Library from mDNSCore, for the benefit of developers
like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <string.h>
@ -82,292 +38,329 @@ like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code
#if defined(_WIN32)
// disable warning "conversion from <data> to uint16_t"
#pragma warning(disable:4244)
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#endif
/*********************************************************************************************
*
* Supporting Functions
*
*********************************************************************************************/
*
* Supporting Functions
*
*********************************************************************************************/
#define mdnsIsDigit(X) ((X) >= '0' && (X) <= '9')
#define mDNSIsDigit(X) ((X) >= '0' && (X) <= '9')
// DomainEndsInDot returns 1 if name ends with a dot, 0 otherwise
// (DNSServiceConstructFullName depends this returning 1 for true, rather than any non-zero value meaning true)
static int DomainEndsInDot(const char *dom)
{
while (dom[0] && dom[1])
{
if (dom[0] == '\\') // advance past escaped byte sequence
{
if (mdnsIsDigit(dom[1]) && mdnsIsDigit(dom[2]) && mdnsIsDigit(dom[3]))
dom += 4; // If "\ddd" then skip four
else dom += 2; // else if "\x" then skip two
}
else dom++; // else goto next character
}
return (dom[0] == '.');
}
{
while (dom[0] && dom[1])
{
if (dom[0] == '\\') // advance past escaped byte sequence
{
if (mDNSIsDigit(dom[1]) && mDNSIsDigit(dom[2]) && mDNSIsDigit(dom[3]))
dom += 4; // If "\ddd" then skip four
else dom += 2; // else if "\x" then skip two
}
else dom++; // else goto next character
}
return (dom[0] == '.');
}
static uint8_t *InternalTXTRecordSearch
(
uint16_t txtLen,
const void *txtRecord,
const char *key,
unsigned long *keylen
)
{
uint8_t *p = (uint8_t*)txtRecord;
uint8_t *e = p + txtLen;
*keylen = (unsigned long) strlen(key);
while (p<e)
{
uint8_t *x = p;
p += 1 + p[0];
if (p <= e && *keylen <= x[0] && !strncmp(key, (char*)x+1, *keylen))
if (*keylen == x[0] || x[1+*keylen] == '=') return(x);
}
return(NULL);
}
(
uint16_t txtLen,
const void *txtRecord,
const char *key,
unsigned long *keylen
)
{
uint8_t *p = (uint8_t*)txtRecord;
uint8_t *e = p + txtLen;
*keylen = (unsigned long) strlen(key);
while (p<e)
{
uint8_t *x = p;
p += 1 + p[0];
if (p <= e && *keylen <= x[0] && !strncasecmp(key, (char*)x+1, *keylen))
if (*keylen == x[0] || x[1+*keylen] == '=') return(x);
}
return(NULL);
}
/*********************************************************************************************
*
* General Utility Functions
*
*********************************************************************************************/
*
* General Utility Functions
*
*********************************************************************************************/
int DNSSD_API DNSServiceConstructFullName
(
char *fullName,
const char *service, /* may be NULL */
const char *regtype,
const char *domain
)
{
unsigned long len;
unsigned char c;
char *fn = fullName;
const char *s = service;
const char *r = regtype;
const char *d = domain;
// Note: Need to make sure we don't write more than kDNSServiceMaxDomainName (1009) bytes to fullName
// In earlier builds this constant was defined to be 1005, so to avoid buffer overruns on clients
// compiled with that constant we'll actually limit the output to 1005 bytes.
if (service)
{
while(*s)
{
c = (unsigned char)*s++;
if (c == '.' || (c == '\\')) *fn++ = '\\'; // escape dot and backslash literals
else if (c <= ' ') // escape non-printable characters
{
*fn++ = '\\';
*fn++ = (char) ('0' + (c / 100));
*fn++ = (char) ('0' + (c / 10) % 10);
c = (unsigned char)('0' + (c % 10));
}
*fn++ = (char)c;
}
*fn++ = '.';
}
DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
(
char *const fullName,
const char *const service, // May be NULL
const char *const regtype,
const char *const domain
)
{
const size_t len = !regtype ? 0 : strlen(regtype) - DomainEndsInDot(regtype);
char *fn = fullName;
char *const lim = fullName + 1005;
const char *s = service;
const char *r = regtype;
const char *d = domain;
if (!regtype) return -1;
len = (unsigned long) strlen(regtype);
if (DomainEndsInDot(regtype)) len--;
if (len < 6) return -1; // regtype must be at least "x._udp" or "x._tcp"
if (strncmp((regtype + len - 4), "_tcp", 4) && strncmp((regtype + len - 4), "_udp", 4)) return -1;
while(*r) *fn++ = *r++;
if (!DomainEndsInDot(regtype)) *fn++ = '.';
// regtype must be at least "x._udp" or "x._tcp"
if (len < 6 || !domain || !domain[0]) return kDNSServiceErr_BadParam;
if (strncasecmp((regtype + len - 4), "_tcp", 4) && strncasecmp((regtype + len - 4), "_udp", 4)) return kDNSServiceErr_BadParam;
if (!domain || !domain[0]) return -1;
while(*d) *fn++ = *d++;
if (!DomainEndsInDot(domain)) *fn++ = '.';
*fn = '\0';
return 0;
}
if (service && *service)
{
while (*s)
{
unsigned char c = *s++; // Needs to be unsigned, or values like 0xFF will be interpreted as < 32
if (c <= ' ') // Escape non-printable characters
{
if (fn+4 >= lim) goto fail;
*fn++ = '\\';
*fn++ = '0' + (c / 100);
*fn++ = '0' + (c / 10) % 10;
c = '0' + (c ) % 10;
}
else if (c == '.' || (c == '\\')) // Escape dot and backslash literals
{
if (fn+2 >= lim) goto fail;
*fn++ = '\\';
}
else
if (fn+1 >= lim) goto fail;
*fn++ = (char)c;
}
*fn++ = '.';
}
while (*r) if (fn+1 >= lim) goto fail;else *fn++ = *r++;
if (!DomainEndsInDot(regtype)) { if (fn+1 >= lim) goto fail;else *fn++ = '.';}
while (*d) if (fn+1 >= lim) goto fail;else *fn++ = *d++;
if (!DomainEndsInDot(domain)) { if (fn+1 >= lim) goto fail;else *fn++ = '.';}
*fn = '\0';
return kDNSServiceErr_NoError;
fail:
*fn = '\0';
return kDNSServiceErr_BadParam;
}
/*********************************************************************************************
*
* TXT Record Construction Functions
*
*********************************************************************************************/
*
* TXT Record Construction Functions
*
*********************************************************************************************/
typedef struct _TXTRecordRefRealType
{
uint8_t *buffer; // Pointer to data
uint16_t buflen; // Length of buffer
uint16_t datalen; // Length currently in use
uint16_t malloced; // Non-zero if buffer was allocated via malloc()
} TXTRecordRefRealType;
{
uint8_t *buffer; // Pointer to data
uint16_t buflen; // Length of buffer
uint16_t datalen; // Length currently in use
uint16_t malloced; // Non-zero if buffer was allocated via malloc()
} TXTRecordRefRealType;
#define txtRec ((TXTRecordRefRealType*)txtRecord)
// The opaque storage defined in the public dns_sd.h header is 16 bytes;
// make sure we don't exceed that.
struct dnssd_clientlib_CompileTimeAssertionCheck
{
char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1];
};
struct CompileTimeAssertionCheck_dnssd_clientlib
{
char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1];
};
void DNSSD_API TXTRecordCreate
(
TXTRecordRef *txtRecord,
uint16_t bufferLen,
void *buffer
)
{
txtRec->buffer = buffer;
txtRec->buflen = buffer ? bufferLen : (uint16_t)0;
txtRec->datalen = 0;
txtRec->malloced = 0;
}
(
TXTRecordRef *txtRecord,
uint16_t bufferLen,
void *buffer
)
{
txtRec->buffer = buffer;
txtRec->buflen = buffer ? bufferLen : (uint16_t)0;
txtRec->datalen = 0;
txtRec->malloced = 0;
}
void DNSSD_API TXTRecordDeallocate(TXTRecordRef *txtRecord)
{
if (txtRec->malloced) free(txtRec->buffer);
}
{
if (txtRec->malloced) free(txtRec->buffer);
}
DNSServiceErrorType DNSSD_API TXTRecordSetValue
(
TXTRecordRef *txtRecord,
const char *key,
uint8_t valueSize,
const void *value
)
{
uint8_t *start, *p;
const char *k;
unsigned long keysize, keyvalsize;
(
TXTRecordRef *txtRecord,
const char *key,
uint8_t valueSize,
const void *value
)
{
uint8_t *start, *p;
const char *k;
unsigned long keysize, keyvalsize;
for (k = key; *k; k++) if (*k < 0x20 || *k > 0x7E || *k == '=') return(kDNSServiceErr_Invalid);
keysize = (unsigned long)(k - key);
keyvalsize = 1 + keysize + (value ? (1 + valueSize) : 0);
if (keysize < 1 || keyvalsize > 255) return(kDNSServiceErr_Invalid);
(void)TXTRecordRemoveValue(txtRecord, key);
if (txtRec->datalen + keyvalsize > txtRec->buflen)
{
unsigned char *newbuf;
unsigned long newlen = txtRec->datalen + keyvalsize;
if (newlen > 0xFFFF) return(kDNSServiceErr_Invalid);
newbuf = malloc((size_t)newlen);
if (!newbuf) return(kDNSServiceErr_NoMemory);
memcpy(newbuf, txtRec->buffer, txtRec->datalen);
if (txtRec->malloced) free(txtRec->buffer);
txtRec->buffer = newbuf;
txtRec->buflen = (uint16_t)(newlen);
txtRec->malloced = 1;
}
start = txtRec->buffer + txtRec->datalen;
p = start + 1;
memcpy(p, key, keysize);
p += keysize;
if (value)
{
*p++ = '=';
memcpy(p, value, valueSize);
p += valueSize;
}
*start = (uint8_t)(p - start - 1);
txtRec->datalen += p - start;
return(kDNSServiceErr_NoError);
}
for (k = key; *k; k++) if (*k < 0x20 || *k > 0x7E || *k == '=') return(kDNSServiceErr_Invalid);
keysize = (unsigned long)(k - key);
keyvalsize = 1 + keysize + (value ? (1 + valueSize) : 0);
if (keysize < 1 || keyvalsize > 255) return(kDNSServiceErr_Invalid);
(void)TXTRecordRemoveValue(txtRecord, key);
if (txtRec->datalen + keyvalsize > txtRec->buflen)
{
unsigned char *newbuf;
unsigned long newlen = txtRec->datalen + keyvalsize;
if (newlen > 0xFFFF) return(kDNSServiceErr_Invalid);
newbuf = malloc((size_t)newlen);
if (!newbuf) return(kDNSServiceErr_NoMemory);
memcpy(newbuf, txtRec->buffer, txtRec->datalen);
if (txtRec->malloced) free(txtRec->buffer);
txtRec->buffer = newbuf;
txtRec->buflen = (uint16_t)(newlen);
txtRec->malloced = 1;
}
start = txtRec->buffer + txtRec->datalen;
p = start + 1;
memcpy(p, key, keysize);
p += keysize;
if (value)
{
*p++ = '=';
memcpy(p, value, valueSize);
p += valueSize;
}
*start = (uint8_t)(p - start - 1);
txtRec->datalen += p - start;
return(kDNSServiceErr_NoError);
}
DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
(
TXTRecordRef *txtRecord,
const char *key
)
{
unsigned long keylen, itemlen, remainder;
uint8_t *item = InternalTXTRecordSearch(txtRec->datalen, txtRec->buffer, key, &keylen);
if (!item) return(kDNSServiceErr_NoSuchKey);
itemlen = (unsigned long)(1 + item[0]);
remainder = (unsigned long)((txtRec->buffer + txtRec->datalen) - (item + itemlen));
// Use memmove because memcpy behaviour is undefined for overlapping regions
memmove(item, item + itemlen, remainder);
txtRec->datalen -= itemlen;
return(kDNSServiceErr_NoError);
}
(
TXTRecordRef *txtRecord,
const char *key
)
{
unsigned long keylen, itemlen, remainder;
uint8_t *item = InternalTXTRecordSearch(txtRec->datalen, txtRec->buffer, key, &keylen);
if (!item) return(kDNSServiceErr_NoSuchKey);
itemlen = (unsigned long)(1 + item[0]);
remainder = (unsigned long)((txtRec->buffer + txtRec->datalen) - (item + itemlen));
// Use memmove because memcpy behaviour is undefined for overlapping regions
memmove(item, item + itemlen, remainder);
txtRec->datalen -= itemlen;
return(kDNSServiceErr_NoError);
}
uint16_t DNSSD_API TXTRecordGetLength (const TXTRecordRef *txtRecord) { return(txtRec->datalen); }
const void * DNSSD_API TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtRec->buffer); }
/*********************************************************************************************
*
* TXT Record Parsing Functions
*
*********************************************************************************************/
*
* TXT Record Parsing Functions
*
*********************************************************************************************/
int DNSSD_API TXTRecordContainsKey
(
uint16_t txtLen,
const void *txtRecord,
const char *key
)
{
unsigned long keylen;
return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0);
}
(
uint16_t txtLen,
const void *txtRecord,
const char *key
)
{
unsigned long keylen;
return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0);
}
const void * DNSSD_API TXTRecordGetValuePtr
(
uint16_t txtLen,
const void *txtRecord,
const char *key,
uint8_t *valueLen
)
{
unsigned long keylen;
uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen);
if (!item || item[0] <= keylen) return(NULL); // If key not found, or found with no value, return NULL
*valueLen = (uint8_t)(item[0] - (keylen + 1));
return (item + 1 + keylen + 1);
}
(
uint16_t txtLen,
const void *txtRecord,
const char *key,
uint8_t *valueLen
)
{
unsigned long keylen;
uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen);
if (!item || item[0] <= keylen) return(NULL); // If key not found, or found with no value, return NULL
*valueLen = (uint8_t)(item[0] - (keylen + 1));
return (item + 1 + keylen + 1);
}
uint16_t DNSSD_API TXTRecordGetCount
(
uint16_t txtLen,
const void *txtRecord
)
{
uint16_t count = 0;
uint8_t *p = (uint8_t*)txtRecord;
uint8_t *e = p + txtLen;
while (p<e) { p += 1 + p[0]; count++; }
return((p>e) ? (uint16_t)0 : count);
}
(
uint16_t txtLen,
const void *txtRecord
)
{
uint16_t count = 0;
uint8_t *p = (uint8_t*)txtRecord;
uint8_t *e = p + txtLen;
while (p<e) { p += 1 + p[0]; count++; }
return((p>e) ? (uint16_t)0 : count);
}
DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
(
uint16_t txtLen,
const void *txtRecord,
uint16_t index,
uint16_t keyBufLen,
char *key,
uint8_t *valueLen,
const void **value
)
{
uint16_t count = 0;
uint8_t *p = (uint8_t*)txtRecord;
uint8_t *e = p + txtLen;
while (p<e && count<index) { p += 1 + p[0]; count++; } // Find requested item
if (p<e && p + 1 + p[0] <= e) // If valid
{
uint8_t *x = p+1;
unsigned long len = 0;
e = p + 1 + p[0];
while (x+len<e && x[len] != '=') len++;
if (len >= keyBufLen) return(kDNSServiceErr_NoMemory);
memcpy(key, x, len);
key[len] = 0;
if (x+len<e) // If we found '='
{
*value = x + len + 1;
*valueLen = (uint8_t)(p[0] - (len + 1));
}
else
{
*value = NULL;
*valueLen = 0;
}
return(kDNSServiceErr_NoError);
}
return(kDNSServiceErr_Invalid);
}
(
uint16_t txtLen,
const void *txtRecord,
uint16_t itemIndex,
uint16_t keyBufLen,
char *key,
uint8_t *valueLen,
const void **value
)
{
uint16_t count = 0;
uint8_t *p = (uint8_t*)txtRecord;
uint8_t *e = p + txtLen;
while (p<e && count<itemIndex) { p += 1 + p[0]; count++; } // Find requested item
if (p<e && p + 1 + p[0] <= e) // If valid
{
uint8_t *x = p+1;
unsigned long len = 0;
e = p + 1 + p[0];
while (x+len<e && x[len] != '=') len++;
if (len >= keyBufLen) return(kDNSServiceErr_NoMemory);
memcpy(key, x, len);
key[len] = 0;
if (x+len<e) // If we found '='
{
*value = x + len + 1;
*valueLen = (uint8_t)(p[0] - (len + 1));
}
else
{
*value = NULL;
*valueLen = 0;
}
return(kDNSServiceErr_NoError);
}
return(kDNSServiceErr_Invalid);
}
/*********************************************************************************************
*
* SCCS-compatible version string
*
*********************************************************************************************/
// For convenience when using the "strings" command, this is the last thing in the file
// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
// To expand "version" to its value before making the string, use STRINGIFY(version) instead
#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
// NOT static -- otherwise the compiler may optimize it out
// The "@(#) " pattern is a special prefix the "what" command looks for
const char VersionString_SCCS_libdnssd[] = "@(#) libdns_sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";

File diff suppressed because it is too large Load Diff

View File

@ -2,134 +2,160 @@
*
* Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Change History (most recent first):
$Log: dnssd_ipc.c,v $
Revision 1.16 2006/08/14 23:05:53 cheshire
Added "tab-width" emacs header line
Revision 1.15 2005/01/27 22:57:56 cheshire
Fix compile errors on gcc4
Revision 1.14 2004/10/06 02:22:20 cheshire
Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
Revision 1.13 2004/10/01 22:15:55 rpantos
rdar://problem/3824265: Replace APSL in client lib with BSD license.
Revision 1.12 2004/09/16 23:14:24 cheshire
Changes for Windows compatibility
Revision 1.11 2004/06/18 04:56:09 rpantos
casting goodness
Revision 1.10 2004/06/12 01:08:14 cheshire
Changes for Windows compatibility
Revision 1.9 2004/05/18 23:51:27 cheshire
Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
Revision 1.8 2003/11/05 22:44:57 ksekar
<rdar://problem/3335230>: No bounds checking when reading data from client
Reviewed by: Stuart Cheshire
Revision 1.7 2003/08/12 19:56:25 cheshire
Update to APSL 2.0
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "dnssd_ipc.h"
void put_long(const uint32_t l, char **ptr)
{
(*ptr)[0] = (char)((l >> 24) & 0xFF);
(*ptr)[1] = (char)((l >> 16) & 0xFF);
(*ptr)[2] = (char)((l >> 8) & 0xFF);
(*ptr)[3] = (char)((l ) & 0xFF);
*ptr += sizeof(uint32_t);
}
#if defined(_WIN32)
uint32_t get_long(char **ptr)
{
uint8_t *p = (uint8_t*) *ptr;
*ptr += sizeof(uint32_t);
return((uint32_t) ((uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | p[3]));
}
char *win32_strerror(int inErrorCode)
{
static char buffer[1024];
DWORD n;
memset(buffer, 0, sizeof(buffer));
n = FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
(DWORD) inErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buffer,
sizeof(buffer),
NULL);
if (n > 0)
{
// Remove any trailing CR's or LF's since some messages have them.
while ((n > 0) && isspace(((unsigned char *) buffer)[n - 1]))
buffer[--n] = '\0';
}
return buffer;
}
void put_short(uint16_t s, char **ptr)
{
(*ptr)[0] = (char)((s >> 8) & 0xFF);
(*ptr)[1] = (char)((s ) & 0xFF);
*ptr += sizeof(uint16_t);
}
#endif
uint16_t get_short(char **ptr)
{
uint8_t *p = (uint8_t*) *ptr;
*ptr += sizeof(uint16_t);
return((uint16_t) ((uint16_t)p[0] << 8 | p[1]));
}
void put_uint32(const uint32_t l, char **ptr)
{
(*ptr)[0] = (char)((l >> 24) & 0xFF);
(*ptr)[1] = (char)((l >> 16) & 0xFF);
(*ptr)[2] = (char)((l >> 8) & 0xFF);
(*ptr)[3] = (char)((l ) & 0xFF);
*ptr += sizeof(uint32_t);
}
uint32_t get_uint32(const char **ptr, const char *end)
{
if (!*ptr || *ptr + sizeof(uint32_t) > end)
{
*ptr = NULL;
return(0);
}
else
{
uint8_t *p = (uint8_t*) *ptr;
*ptr += sizeof(uint32_t);
return((uint32_t) ((uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | p[3]));
}
}
void put_uint16(uint16_t s, char **ptr)
{
(*ptr)[0] = (char)((s >> 8) & 0xFF);
(*ptr)[1] = (char)((s ) & 0xFF);
*ptr += sizeof(uint16_t);
}
uint16_t get_uint16(const char **ptr, const char *end)
{
if (!*ptr || *ptr + sizeof(uint16_t) > end)
{
*ptr = NULL;
return(0);
}
else
{
uint8_t *p = (uint8_t*) *ptr;
*ptr += sizeof(uint16_t);
return((uint16_t) ((uint16_t)p[0] << 8 | p[1]));
}
}
int put_string(const char *str, char **ptr)
{
if (!str) str = "";
strcpy(*ptr, str);
*ptr += strlen(str) + 1;
return 0;
}
{
if (!str) str = "";
strcpy(*ptr, str);
*ptr += strlen(str) + 1;
return 0;
}
int get_string(char **ptr, char *buffer, int buflen)
{
int overrun = (int)strlen(*ptr) < buflen ? 0 : -1;
strncpy(buffer, *ptr, buflen - 1);
buffer[buflen - 1] = '\0';
*ptr += strlen(buffer) + 1;
return overrun;
}
int get_string(const char **ptr, const char *const end, char *buffer, int buflen)
{
if (!*ptr)
{
*buffer = 0;
return(-1);
}
else
{
char *lim = buffer + buflen; // Calculate limit
while (*ptr < end && buffer < lim)
{
char c = *buffer++ = *(*ptr)++;
if (c == 0) return(0); // Success
}
if (buffer == lim) buffer--;
*buffer = 0; // Failed, so terminate string,
*ptr = NULL; // clear pointer,
return(-1); // and return failure indication
}
}
void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr)
{
memcpy(*ptr, rdata, rdlen);
*ptr += rdlen;
}
{
memcpy(*ptr, rdata, rdlen);
*ptr += rdlen;
}
char *get_rdata(char **ptr, int rdlen)
{
char *rd = *ptr;
*ptr += rdlen;
return rd;
}
const char *get_rdata(const char **ptr, const char *end, int rdlen)
{
if (!*ptr || *ptr + rdlen > end)
{
*ptr = NULL;
return(0);
}
else
{
const char *rd = *ptr;
*ptr += rdlen;
return rd;
}
}
void ConvertHeaderBytes(ipc_msg_hdr *hdr)
{
hdr->version = htonl(hdr->version);
hdr->datalen = htonl(hdr->datalen);
hdr->flags = htonl(hdr->flags);
hdr->op = htonl(hdr->op );
hdr->reg_index = htonl(hdr->reg_index);
}
{
hdr->version = htonl(hdr->version);
hdr->datalen = htonl(hdr->datalen);
hdr->ipc_flags = htonl(hdr->ipc_flags);
hdr->op = htonl(hdr->op );
hdr->reg_index = htonl(hdr->reg_index);
}

View File

@ -2,173 +2,126 @@
*
* Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Change History (most recent first):
$Log: dnssd_ipc.h,v $
Revision 1.23 2006/08/14 23:05:53 cheshire
Added "tab-width" emacs header line
Revision 1.22 2006/06/28 08:56:26 cheshire
Added "_op" to the end of the operation code enum values,
to differentiate them from the routines with the same names
Revision 1.21 2005/09/29 06:38:13 herscher
Remove #define MSG_WAITALL on Windows. We don't use this macro anymore, and it's presence causes warnings to be emitted when compiling against the latest Microsoft Platform SDK.
Revision 1.20 2005/03/21 00:39:31 shersche
<rdar://problem/4021486> Fix build warnings on Win32 platform
Revision 1.19 2005/02/02 02:25:22 cheshire
<rdar://problem/3980388> /var/run/mDNSResponder should be /var/run/mdnsd on Linux
Revision 1.18 2005/01/27 22:57:56 cheshire
Fix compile errors on gcc4
Revision 1.17 2004/11/23 03:39:47 cheshire
Let interface name/index mapping capability live directly in JNISupport.c,
instead of having to call through to the daemon via IPC to get this information.
Revision 1.16 2004/11/12 03:21:41 rpantos
rdar://problem/3809541 Add DNSSDMapIfIndexToName, DNSSDMapNameToIfIndex.
Revision 1.15 2004/10/06 02:22:20 cheshire
Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
Revision 1.14 2004/10/01 22:15:55 rpantos
rdar://problem/3824265: Replace APSL in client lib with BSD license.
Revision 1.13 2004/09/16 23:14:25 cheshire
Changes for Windows compatibility
Revision 1.12 2004/09/16 21:46:38 ksekar
<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area domain
Revision 1.11 2004/08/10 06:24:56 cheshire
Use types with precisely defined sizes for 'op' and 'reg_index', for better
compatibility if the daemon and the client stub are built using different compilers
Revision 1.10 2004/07/07 17:39:25 shersche
Change MDNS_SERVERPORT from 5533 to 5354.
Revision 1.9 2004/06/25 00:26:27 rpantos
Changes to fix the Posix build on Solaris.
Revision 1.8 2004/06/18 04:56:51 rpantos
Add layer for platform code
Revision 1.7 2004/06/12 01:08:14 cheshire
Changes for Windows compatibility
Revision 1.6 2003/08/12 19:56:25 cheshire
Update to APSL 2.0
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef DNSSD_IPC_H
#define DNSSD_IPC_H
#include "dns_sd.h"
//
// Common cross platform services
//
#if defined(WIN32)
# include <winsock2.h>
# define dnssd_InvalidSocket INVALID_SOCKET
# define dnssd_EWOULDBLOCK WSAEWOULDBLOCK
# define dnssd_EINTR WSAEINTR
# define dnssd_sock_t SOCKET
# define dnssd_socklen_t int
# define dnssd_sockbuf_t const char*
# define dnssd_close(sock) closesocket(sock)
# define dnssd_errno() WSAGetLastError()
# define ssize_t int
# define getpid _getpid
# include <winsock2.h>
# define dnssd_InvalidSocket INVALID_SOCKET
# define dnssd_SocketValid(s) ((s) != INVALID_SOCKET)
# define dnssd_EWOULDBLOCK WSAEWOULDBLOCK
# define dnssd_EINTR WSAEINTR
# define dnssd_ECONNRESET WSAECONNRESET
# define dnssd_sock_t SOCKET
# define dnssd_socklen_t int
# define dnssd_close(sock) closesocket(sock)
# define dnssd_errno WSAGetLastError()
# define dnssd_strerror(X) win32_strerror(X)
# define ssize_t int
# define getpid _getpid
# define unlink _unlink
extern char *win32_strerror(int inErrorCode);
#else
# include <sys/types.h>
# include <unistd.h>
# include <sys/un.h>
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <sys/stat.h>
# include <sys/socket.h>
# include <netinet/in.h>
# define dnssd_InvalidSocket -1
# define dnssd_EWOULDBLOCK EWOULDBLOCK
# define dnssd_EINTR EINTR
# define dnssd_EPIPE EPIPE
# define dnssd_sock_t int
# define dnssd_socklen_t unsigned int
# define dnssd_sockbuf_t const char*
# define dnssd_close(sock) close(sock)
# define dnssd_errno() errno
# include <sys/types.h>
# include <unistd.h>
# include <sys/un.h>
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <sys/stat.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# define dnssd_InvalidSocket -1
# define dnssd_SocketValid(s) ((s) >= 0)
# define dnssd_EWOULDBLOCK EWOULDBLOCK
# define dnssd_EINTR EINTR
# define dnssd_ECONNRESET ECONNRESET
# define dnssd_EPIPE EPIPE
# define dnssd_sock_t int
# define dnssd_socklen_t unsigned int
# define dnssd_close(sock) close(sock)
# define dnssd_errno errno
# define dnssd_strerror(X) strerror(X)
#endif
#if defined(USE_TCP_LOOPBACK)
# define AF_DNSSD AF_INET
# define MDNS_TCP_SERVERADDR "127.0.0.1"
# define MDNS_TCP_SERVERPORT 5354
# define LISTENQ 5
# define dnssd_sockaddr_t struct sockaddr_in
# define AF_DNSSD AF_INET
# define MDNS_TCP_SERVERADDR "127.0.0.1"
# define MDNS_TCP_SERVERPORT 5354
# define LISTENQ 5
# define dnssd_sockaddr_t struct sockaddr_in
#else
# define AF_DNSSD AF_LOCAL
# ifndef MDNS_UDS_SERVERPATH
# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder"
# endif
# define LISTENQ 100
// longest legal control path length
# define MAX_CTLPATH 256
# define dnssd_sockaddr_t struct sockaddr_un
# define AF_DNSSD AF_LOCAL
# ifndef MDNS_UDS_SERVERPATH
# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder"
# endif
# define MDNS_UDS_SERVERPATH_ENVVAR "DNSSD_UDS_PATH"
# define LISTENQ 100
// longest legal control path length
# define MAX_CTLPATH 256
# define dnssd_sockaddr_t struct sockaddr_un
#endif
//#define UDSDEBUG // verbose debug output
// Compatibility workaround
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#define AF_LOCAL AF_UNIX
#endif
// General UDS constants
#define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record
#define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record
// IPC data encoding constants and types
#define VERSION 1
#define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client
#define IPC_FLAGS_REUSE_SOCKET 2 // set flag if synchronous errors are to be sent via the primary socket
// (if not set, first string in message buffer must be path to error socket
#define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client
// Structure packing macro. If we're not using GNUC, it's not fatal. Most compilers naturally pack the on-the-wire
// structures correctly anyway, so a plain "struct" is usually fine. In the event that structures are not packed
// correctly, our compile-time assertion checks will catch it and prevent inadvertent generation of non-working code.
#ifndef packedstruct
#if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
#define packedstruct struct __attribute__((__packed__))
#define packedunion union __attribute__((__packed__))
#else
#define packedstruct struct
#define packedunion union
#endif
#endif
typedef enum
{
connection = 1, // connected socket via DNSServiceConnect()
reg_record_request, // reg/remove record only valid for connected sockets
{
request_op_none = 0, // No request yet received on this connection
connection_request = 1, // connected socket via DNSServiceConnect()
reg_record_request, // reg/remove record only valid for connected sockets
remove_record_request,
enumeration_request,
reg_service_request,
@ -178,76 +131,96 @@ typedef enum
reconfirm_record_request,
add_record_request,
update_record_request,
setdomain_request
} request_op_t;
setdomain_request, // Up to here is in Tiger and B4W 1.0.3
getproperty_request, // New in B4W 1.0.4
port_mapping_request, // New in Leopard and B4W 2.0
addrinfo_request,
send_bpf, // New in SL
getpid_request,
release_request,
connection_delegate_request,
cancel_request = 63
} request_op_t;
typedef enum
{
{
enumeration_reply_op = 64,
reg_service_reply_op,
browse_reply_op,
resolve_reply_op,
query_reply_op,
reg_record_reply_op
} reply_op_t;
reg_record_reply_op, // Up to here is in Tiger and B4W 1.0.3
getproperty_reply_op, // New in B4W 1.0.4
port_mapping_reply_op, // New in Leopard and B4W 2.0
addrinfo_reply_op
} reply_op_t;
typedef struct ipc_msg_hdr_struct ipc_msg_hdr;
#if defined(_WIN64)
# pragma pack(push,4)
#elif !defined(__GNUC__)
# pragma pack(1)
#endif
// client stub callback to process message from server and deliver results to
// client application
typedef void (*process_reply_callback)
(
DNSServiceRef sdr,
ipc_msg_hdr *hdr,
char *msg
);
// allow 64-bit client to interoperate w/ 32-bit daemon
typedef union
{
// Define context object big enough to hold a 64-bit pointer,
// to accomodate 64-bit clients communicating with 32-bit daemon.
// There's no reason for the daemon to ever be a 64-bit process, but its clients might be
typedef packedunion
{
void *context;
uint32_t ptr64[2];
} client_context_t;
uint32_t u32[2];
} client_context_t;
typedef struct ipc_msg_hdr_struct
{
typedef packedstruct
{
uint32_t version;
uint32_t datalen;
uint32_t flags;
uint32_t op; // request_op_t or reply_op_t
uint32_t ipc_flags;
uint32_t op; // request_op_t or reply_op_t
client_context_t client_context; // context passed from client, returned by server in corresponding reply
uint32_t reg_index; // identifier for a record registered via DNSServiceRegisterRecord() on a
// socket connected by DNSServiceConnect(). Must be unique in the scope of the connection, such that and
// socket connected by DNSServiceCreateConnection(). Must be unique in the scope of the connection, such that and
// index/socket pair uniquely identifies a record. (Used to select records for removal by DNSServiceRemoveRecord())
uint32_t padbytes;
} ipc_msg_hdr_struct;
} ipc_msg_hdr;
#if defined(_WIN64)
# pragma pack(pop)
#elif !defined(__GNUC__)
# pragma pack()
#endif
// it is advanced to point to the next field, or the end of the message
// routines to write to and extract data from message buffers.
// caller responsible for bounds checking.
// ptr is the address of the pointer to the start of the field.
// it is advanced to point to the next field, or the end of the message
void put_long(const uint32_t l, char **ptr);
uint32_t get_long(char **ptr);
void put_uint32(const uint32_t l, char **ptr);
uint32_t get_uint32(const char **ptr, const char *end);
void put_short(uint16_t s, char **ptr);
uint16_t get_short(char **ptr);
void put_uint16(uint16_t s, char **ptr);
uint16_t get_uint16(const char **ptr, const char *end);
#define put_flags put_long
#define get_flags get_long
#define put_flags put_uint32
#define get_flags get_uint32
#define put_error_code put_long
#define get_error_code get_long
#define put_error_code put_uint32
#define get_error_code get_uint32
int put_string(const char *str, char **ptr);
int get_string(char **ptr, char *buffer, int buflen);
int get_string(const char **ptr, const char *const end, char *buffer, int buflen);
void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr);
char *get_rdata(char **ptr, int rdlen); // return value is rdata pointed to by *ptr -
// rdata is not copied from buffer.
const char *get_rdata(const char **ptr, const char *end, int rdlen); // return value is rdata pointed to by *ptr -
// rdata is not copied from buffer.
void ConvertHeaderBytes(ipc_msg_hdr *hdr);
struct CompileTimeAssertionChecks_dnssd_ipc
{
// Check that the compiler generated our on-the-wire packet format structure definitions
// properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
char assert0[(sizeof(client_context_t) == 8) ? 1 : -1];
char assert1[(sizeof(ipc_msg_hdr) == 28) ? 1 : -1];
};
#endif // DNSSD_IPC_H

View File

@ -18,7 +18,7 @@
#
# CDDL HEADER END
#
#
# Copyright 2016 Toomas Soome <tsoome@me.com>
# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
#
@ -38,6 +38,14 @@
$mapfile_version 2
SYMBOL_VERSION ILLUMOS_0.1 { # mDNSResponder-576.30.4
global:
DNSServiceGetAddrInfo;
DNSServiceGetProperty;
DNSServiceNATPortMappingCreate;
DNSServiceSleepKeepalive;
} SUNW_1.1;
SYMBOL_VERSION SUNW_1.1 {
global:
DNSServiceAddRecord;

View File

@ -13,21 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: BaseListener.java,v $
Revision 1.3 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/04/30 21:48:27 rpantos
Change line endings for CVS.
Revision 1.1 2004/04/30 16:29:35 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
*/

View File

@ -13,21 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: BrowseListener.java,v $
Revision 1.3 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/04/30 21:48:27 rpantos
Change line endings for CVS.
Revision 1.1 2004/04/30 16:29:35 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
*/

View File

@ -13,22 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: DNSRecord.java,v $
Revision 1.3 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/12/11 03:00:59 rpantos
<rdar://problem/3907498> Java DNSRecord API should be cleaned up
Revision 1.1 2004/04/30 16:32:34 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
*/

View File

@ -5,60 +5,20 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: DNSSD.java,v $
Revision 1.11 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.10 2006/06/20 23:05:55 rpantos
<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
Revision 1.9 2005/10/26 01:52:24 cheshire
<rdar://problem/4316286> Race condition in Java code (doesn't work at all on Linux)
Revision 1.8 2005/07/11 01:55:21 cheshire
<rdar://problem/4175511> Race condition in Java API
Revision 1.7 2005/07/05 13:01:52 cheshire
<rdar://problem/4169791> If mDNSResponder daemon is stopped, Java API spins, burning CPU time
Revision 1.6 2005/07/05 00:02:25 cheshire
Add missing comma
Revision 1.5 2005/07/04 21:13:47 cheshire
Add missing error message strings
Revision 1.4 2004/12/11 03:00:59 rpantos
<rdar://problem/3907498> Java DNSRecord API should be cleaned up
Revision 1.3 2004/11/12 03:23:08 rpantos
rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex.
Revision 1.2 2004/05/20 17:43:18 cheshire
Fix invalid UTF-8 characters in file
Revision 1.1 2004/04/30 16:32:34 rpantos
First checked in.
This file declares and implements DNSSD, the central Java factory class
for doing DNS Service Discovery. It includes the mostly-abstract public
interface, as well as the Apple* implementation subclasses.
*/
/*
* ident "%Z%%M% %I% %E% SMI"
*/
package com.apple.dnssd;
@ -67,19 +27,19 @@ package com.apple.dnssd;
DNSSD provides access to DNS Service Discovery features of ZeroConf networking.<P>
It is a factory class that is used to invoke registration and discovery-related
operations. Most operations are non-blocking; clients are called back through an interface
operations. Most operations are non-blocking; clients are called back through an interface
with the result of an operation. Callbacks are made from a separate worker thread.<P>
For example, in this program<P>
For example, in this program<P>
<PRE><CODE>
class MyClient implements BrowseListener {
void lookForWebServers() {
myBrowser = DNSSD.browse("_http_.tcp", this);
myBrowser = DNSSD.browse("_http._tcp", this);
}
public void serviceFound(DNSSDService browser, int flags, int ifIndex,
public void serviceFound(DNSSDService browser, int flags, int ifIndex,
String serviceName, String regType, String domain) {}
...
...
}</CODE></PRE>
<CODE>MyClient.serviceFound()</CODE> would be called for every HTTP server discovered in the
default browse domain(s).
@ -91,14 +51,14 @@ abstract public class DNSSD
queued. Applications should not update their UI to display browse
results if the MORE_COMING flag is set; they will be called at least once
more with the flag clear.
*/
*/
public static final int MORE_COMING = ( 1 << 0 );
/** If flag is set in a {@link DomainListener} callback, indicates that the result is the default domain. */
public static final int DEFAULT = ( 1 << 2 );
/** If flag is set, a name conflict will trigger an exception when registering non-shared records.<P>
A name must be explicitly specified when registering a service if this bit is set
/** If flag is set, a name conflict will trigger an exception when registering non-shared records.<P>
A name must be explicitly specified when registering a service if this bit is set
(i.e. the default name may not not be used).
*/
public static final int NO_AUTO_RENAME = ( 1 << 3 );
@ -117,7 +77,7 @@ abstract public class DNSSD
public static final int REGISTRATION_DOMAINS = ( 1 << 7 );
/** Maximum length, in bytes, of a domain name represented as an escaped C-String. */
public static final int MAX_DOMAIN_NAME = 1005;
public static final int MAX_DOMAIN_NAME = 1009;
/** Pass for ifIndex to specify all available interfaces. */
public static final int ALL_INTERFACES = 0;
@ -125,7 +85,7 @@ abstract public class DNSSD
/** Pass for ifIndex to specify the localhost interface. */
public static final int LOCALHOST_ONLY = -1;
/** Browse for instances of a service.<P>
/** Browse for instances of a service.<P>
Note: browsing consumes network bandwidth. Call {@link DNSSDService#stop} when you have finished browsing.<P>
@ -139,12 +99,12 @@ abstract public class DNSSD
interfaces. Pass -1 to only browse for services provided on the local host.
<P>
@param regType
The registration type being browsed for followed by the protocol, separated by a
The registration type being browsed for followed by the protocol, separated by a
dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
<P>
@param domain
If non-null, specifies the domain on which to browse for services.
Most applications will not specify a domain, instead browsing on the
Most applications will not specify a domain, instead browsing on the
default domain(s).
<P>
@param listener
@ -159,10 +119,10 @@ abstract public class DNSSD
throws DNSSDException
{ return getInstance()._makeBrowser( flags, ifIndex, regType, domain, listener); }
/** Browse for instances of a service. Use default flags, ifIndex and domain.<P>
/** Browse for instances of a service. Use default flags, ifIndex and domain.<P>
@param regType
The registration type being browsed for followed by the protocol, separated by a
The registration type being browsed for followed by the protocol, separated by a
dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
<P>
@param listener
@ -177,16 +137,16 @@ abstract public class DNSSD
throws DNSSDException
{ return browse( 0, 0, regType, "", listener); }
/** Resolve a service name discovered via browse() to a target host name, port number, and txt record.<P>
/** Resolve a service name discovered via browse() to a target host name, port number, and txt record.<P>
Note: Applications should NOT use resolve() solely for txt record monitoring - use
Note: Applications should NOT use resolve() solely for txt record monitoring - use
queryRecord() instead, as it is more efficient for this task.<P>
Note: When the desired results have been returned, the client MUST terminate the resolve by
Note: When the desired results have been returned, the client MUST terminate the resolve by
calling {@link DNSSDService#stop}.<P>
Note: resolve() behaves correctly for typical services that have a single SRV record and
a single TXT record (the TXT record may be empty.) To resolve non-standard services with
a single TXT record (the TXT record may be empty.) To resolve non-standard services with
multiple SRV or TXT records, use queryRecord().<P>
@param flags
@ -194,7 +154,7 @@ abstract public class DNSSD
<P>
@param ifIndex
The interface on which to resolve the service. The client should
pass the interface on which the serviceName was discovered (i.e.
pass the interface on which the serviceName was discovered (i.e.
the ifIndex passed to the serviceFound() callback)
or 0 to resolve the named service on all available interfaces.
<P>
@ -202,8 +162,8 @@ abstract public class DNSSD
The servicename to be resolved.
<P>
@param regType
The registration type being resolved followed by the protocol, separated by a
dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
The registration type being resolved followed by the protocol, separated by a
dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
<P>
@param domain
The domain on which the service is registered, i.e. the domain passed
@ -217,54 +177,54 @@ abstract public class DNSSD
@throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
@see RuntimePermission
*/
public static DNSSDService resolve( int flags, int ifIndex, String serviceName, String regType,
public static DNSSDService resolve( int flags, int ifIndex, String serviceName, String regType,
String domain, ResolveListener listener)
throws DNSSDException
{ return getInstance()._resolve( flags, ifIndex, serviceName, regType, domain, listener); }
/** Register a service, to be discovered via browse() and resolve() calls.<P>
/** Register a service, to be discovered via browse() and resolve() calls.<P>
@param flags
Possible values are: NO_AUTO_RENAME.
<P>
@param ifIndex
If non-zero, specifies the interface on which to register the service
(the index for a given interface is determined via the if_nametoindex()
family of calls.) Most applications will pass 0 to register on all
available interfaces. Pass -1 to register a service only on the local
family of calls.) Most applications will pass 0 to register on all
available interfaces. Pass -1 to register a service only on the local
machine (service will not be visible to remote hosts).
<P>
@param serviceName
If non-null, specifies the service name to be registered.
Applications need not specify a name, in which case the
computer name is used (this name is communicated to the client via
If non-null, specifies the service name to be registered.
Applications need not specify a name, in which case the
computer name is used (this name is communicated to the client via
the serviceRegistered() callback).
<P>
@param regType
The registration type being registered followed by the protocol, separated by a
dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
The registration type being registered followed by the protocol, separated by a
dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
<P>
@param domain
If non-null, specifies the domain on which to advertise the service.
Most applications will not specify a domain, instead automatically
Most applications will not specify a domain, instead automatically
registering in the default domain(s).
<P>
@param host
If non-null, specifies the SRV target host name. Most applications
will not specify a host, instead automatically using the machine's
default host name(s). Note that specifying a non-null host does NOT
create an address record for that host - the application is responsible
default host name(s). Note that specifying a non-null host does NOT
create an address record for that host - the application is responsible
for ensuring that the appropriate address record exists, or creating it
via {@link DNSSDRegistration#addRecord}.
<P>
@param port
The port on which the service accepts connections. Pass 0 for a
"placeholder" service (i.e. a service that will not be discovered by
browsing, but will cause a name conflict if another client tries to
The port on which the service accepts connections. Pass 0 for a
"placeholder" service (i.e. a service that will not be discovered by
browsing, but will cause a name conflict if another client tries to
register that same name.) Most clients will not use placeholder services.
<P>
@param txtRecord
The txt record rdata. May be null. Note that a non-null txtRecord
MUST be a properly formatted DNS TXT record, i.e. &lt;length byte&gt; &lt;data&gt;
The txt record rdata. May be null. Note that a non-null txtRecord
MUST be a properly formatted DNS TXT record, i.e. &lt;length byte&gt; &lt;data&gt;
&lt;length byte&gt; &lt;data&gt; ...
<P>
@param listener
@ -275,26 +235,26 @@ abstract public class DNSSD
@throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
@see RuntimePermission
*/
public static DNSSDRegistration register( int flags, int ifIndex, String serviceName, String regType,
public static DNSSDRegistration register( int flags, int ifIndex, String serviceName, String regType,
String domain, String host, int port, TXTRecord txtRecord, RegisterListener listener)
throws DNSSDException
{ return getInstance()._register( flags, ifIndex, serviceName, regType, domain, host, port, txtRecord, listener); }
/** Register a service, to be discovered via browse() and resolve() calls. Use default flags, ifIndex, domain, host and txtRecord.<P>
/** Register a service, to be discovered via browse() and resolve() calls. Use default flags, ifIndex, domain, host and txtRecord.<P>
@param serviceName
If non-null, specifies the service name to be registered.
Applications need not specify a name, in which case the
computer name is used (this name is communicated to the client via
If non-null, specifies the service name to be registered.
Applications need not specify a name, in which case the
computer name is used (this name is communicated to the client via
the serviceRegistered() callback).
<P>
@param regType
The registration type being registered followed by the protocol, separated by a
dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
The registration type being registered followed by the protocol, separated by a
dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
<P>
@param port
The port on which the service accepts connections. Pass 0 for a
"placeholder" service (i.e. a service that will not be discovered by
browsing, but will cause a name conflict if another client tries to
The port on which the service accepts connections. Pass 0 for a
"placeholder" service (i.e. a service that will not be discovered by
browsing, but will cause a name conflict if another client tries to
register that same name.) Most clients will not use placeholder services.
<P>
@param listener
@ -309,8 +269,8 @@ abstract public class DNSSD
throws DNSSDException
{ return register( 0, 0, serviceName, regType, null, null, port, null, listener); }
/** Create a {@link DNSSDRecordRegistrar} allowing efficient registration of
multiple individual records.<P>
/** Create a {@link DNSSDRecordRegistrar} allowing efficient registration of
multiple individual records.<P>
<P>
@return A {@link DNSSDRecordRegistrar} that can be used to register records.
@ -321,14 +281,14 @@ abstract public class DNSSD
throws DNSSDException
{ return getInstance()._createRecordRegistrar( listener); }
/** Query for an arbitrary DNS record.<P>
/** Query for an arbitrary DNS record.<P>
@param flags
Possible values are: MORE_COMING.
<P>
@param ifIndex
If non-zero, specifies the interface on which to issue the query
(the index for a given interface is determined via the if_nametoindex()
family of calls.) Passing 0 causes the name to be queried for on all
family of calls.) Passing 0 causes the name to be queried for on all
interfaces. Passing -1 causes the name to be queried for only on the
local host.
<P>
@ -340,7 +300,7 @@ abstract public class DNSSD
as defined in nameser.h.
<P>
@param rrclass
The class of the resource record, as defined in nameser.h
The class of the resource record, as defined in nameser.h
(usually 1 for the Internet class).
<P>
@param listener
@ -351,12 +311,12 @@ abstract public class DNSSD
@throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
@see RuntimePermission
*/
public static DNSSDService queryRecord( int flags, int ifIndex, String serviceName, int rrtype,
public static DNSSDService queryRecord( int flags, int ifIndex, String serviceName, int rrtype,
int rrclass, QueryListener listener)
throws DNSSDException
{ return getInstance()._queryRecord( flags, ifIndex, serviceName, rrtype, rrclass, listener); }
/** Asynchronously enumerate domains available for browsing and registration.<P>
/** Asynchronously enumerate domains available for browsing and registration.<P>
Currently, the only domain returned is "local.", but other domains will be returned in future.<P>
@ -368,8 +328,8 @@ abstract public class DNSSD
@param ifIndex
If non-zero, specifies the interface on which to look for domains.
(the index for a given interface is determined via the if_nametoindex()
family of calls.) Most applications will pass 0 to enumerate domains on
all interfaces.
family of calls.) Most applications will pass 0 to enumerate domains on
all interfaces.
<P>
@param listener
This object will get called when domains are found.
@ -383,15 +343,15 @@ abstract public class DNSSD
throws DNSSDException
{ return getInstance()._enumerateDomains( flags, ifIndex, listener); }
/** Concatenate a three-part domain name (as provided to the listeners) into a
properly-escaped full domain name. Note that strings passed to listeners are
ALREADY ESCAPED where necessary.<P>
/** Concatenate a three-part domain name (as provided to the listeners) into a
properly-escaped full domain name. Note that strings passed to listeners are
ALREADY ESCAPED where necessary.<P>
@param serviceName
The service name - any dots or slashes must NOT be escaped.
May be null (to construct a PTR record name, e.g. "_ftp._tcp.apple.com").
<P>
@param regType
The registration type followed by the protocol, separated by a dot (e.g. "_ftp._tcp").
The registration type followed by the protocol, separated by a dot (e.g. "_ftp._tcp").
<P>
@param domain
The domain name, e.g. "apple.com". Any literal dots or backslashes must be escaped.
@ -405,10 +365,10 @@ abstract public class DNSSD
throws DNSSDException
{ return getInstance()._constructFullName( serviceName, regType, domain); }
/** Instruct the daemon to verify the validity of a resource record that appears to
be out of date. (e.g. because tcp connection to a service's target failed.) <P>
/** Instruct the daemon to verify the validity of a resource record that appears to
be out of date. (e.g. because tcp connection to a service's target failed.) <P>
Causes the record to be flushed from the daemon's cache (as well as all other
Causes the record to be flushed from the daemon's cache (as well as all other
daemons' caches on the network) if the record is determined to be invalid.<P>
@param flags
Currently unused, reserved for future use.
@ -416,7 +376,7 @@ abstract public class DNSSD
@param ifIndex
If non-zero, specifies the interface on which to reconfirm the record
(the index for a given interface is determined via the if_nametoindex()
family of calls.) Passing 0 causes the name to be reconfirmed on all
family of calls.) Passing 0 causes the name to be reconfirmed on all
interfaces. Passing -1 causes the name to be reconfirmed only on the
local host.
<P>
@ -435,11 +395,11 @@ abstract public class DNSSD
@throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
@see RuntimePermission
*/
public static void reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
public static void reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
int rrclass, byte[] rdata)
{ getInstance()._reconfirmRecord( flags, ifIndex, fullName, rrtype, rrclass, rdata); }
/** Return the canonical name of a particular interface index.<P>
/** Return the canonical name of a particular interface index.<P>
@param ifIndex
A valid interface index. Must not be ALL_INTERFACES.
<P>
@ -451,7 +411,7 @@ abstract public class DNSSD
public static String getNameForIfIndex( int ifIndex)
{ return getInstance()._getNameForIfIndex( ifIndex); }
/** Return the index of a named interface.<P>
/** Return the index of a named interface.<P>
@param ifName
A valid interface name. An example is java.net.NetworkInterface.getName().
<P>
@ -466,29 +426,29 @@ abstract public class DNSSD
protected DNSSD() {} // prevent direct instantiation
/** Return the single instance of DNSSD. */
static protected final DNSSD getInstance()
static protected final DNSSD getInstance()
{
SecurityManager sm = System.getSecurityManager();
if ( sm != null)
sm.checkPermission( new RuntimePermission( "getDNSSDInstance"));
return fInstance;
if (sm != null)
sm.checkPermission( new RuntimePermission( "getDNSSDInstance"));
return fInstance;
}
abstract protected DNSSDService _makeBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener listener)
throws DNSSDException;
abstract protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType,
abstract protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType,
String domain, ResolveListener listener)
throws DNSSDException;
abstract protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType,
abstract protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType,
String domain, String host, int port, TXTRecord txtRecord, RegisterListener listener)
throws DNSSDException;
abstract protected DNSSDRecordRegistrar _createRecordRegistrar( RegisterRecordListener listener)
throws DNSSDException;
abstract protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype,
abstract protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype,
int rrclass, QueryListener listener)
throws DNSSDException;
@ -498,7 +458,7 @@ abstract public class DNSSD
abstract protected String _constructFullName( String serviceName, String regType, String domain)
throws DNSSDException;
abstract protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
abstract protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
int rrclass, byte[] rdata);
abstract protected String _getNameForIfIndex( int ifIndex);
@ -510,11 +470,11 @@ abstract public class DNSSD
static
{
try
{
{
String name = System.getProperty( "com.apple.dnssd.DNSSD" );
if( name == null )
if (name == null)
name = "com.apple.dnssd.AppleDNSSD"; // Fall back to Apple-provided class.
fInstance = (DNSSD) Class.forName( name ).newInstance();
fInstance = (DNSSD) Class.forName(name).newInstance();
}
catch( Exception e )
{
@ -559,10 +519,13 @@ class AppleDNSSDException extends DNSSDException
"BADTIME",
"BADSIG",
"BADKEY",
"TRANSIENT"
"TRANSIENT",
"SERVICENOTRUNNING",
"NATPORTMAPPINGUNSUPPORTED",
"NATPORTMAPPINGDISABLED"
};
if ( fErrorCode <= UNKNOWN && fErrorCode > ( UNKNOWN - kMessages.length))
if (fErrorCode <= UNKNOWN && fErrorCode > ( UNKNOWN - kMessages.length))
{
return "DNS-SD Error " + String.valueOf( fErrorCode) + ": " + kMessages[ UNKNOWN - fErrorCode];
}
@ -580,9 +543,9 @@ class AppleDNSSD extends DNSSD
{
System.loadLibrary( "jdns_sd");
int libInitResult = InitLibrary( 1);
int libInitResult = InitLibrary( 2); // Current version number (must be sync'd with jnilib version)
if ( libInitResult != DNSSDException.NO_ERROR)
if (libInitResult != DNSSDException.NO_ERROR)
throw new InternalError( "cannot instantiate DNSSD: " + new AppleDNSSDException( libInitResult).getMessage());
}
@ -594,18 +557,18 @@ class AppleDNSSD extends DNSSD
return new AppleBrowser( flags, ifIndex, regType, domain, client);
}
protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType,
protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType,
String domain, ResolveListener client)
throws DNSSDException
{
return new AppleResolver( flags, ifIndex, serviceName, regType, domain, client);
}
protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType,
protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType,
String domain, String host, int port, TXTRecord txtRecord, RegisterListener client)
throws DNSSDException
{
return new AppleRegistration( flags, ifIndex, serviceName, regType, domain, host, port,
return new AppleRegistration( flags, ifIndex, serviceName, regType, domain, host, port,
( txtRecord != null) ? txtRecord.getRawBytes() : null, client);
}
@ -615,7 +578,7 @@ class AppleDNSSD extends DNSSD
return new AppleRecordRegistrar( listener);
}
protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype,
protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype,
int rrclass, QueryListener client)
throws DNSSDException
{
@ -634,13 +597,13 @@ class AppleDNSSD extends DNSSD
String[] responseHolder = new String[1]; // lame maneuver to get around Java's lack of reference parameters
int rc = ConstructName( serviceName, regType, domain, responseHolder);
if ( rc != 0)
if (rc != 0)
throw new AppleDNSSDException( rc);
return responseHolder[0];
}
protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
int rrclass, byte[] rdata)
{
ReconfirmRecord( flags, ifIndex, fullName, rrtype, rrclass, rdata);
@ -659,7 +622,7 @@ class AppleDNSSD extends DNSSD
protected native int ConstructName( String serviceName, String regType, String domain, String[] pOut);
protected native void ReconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
protected native void ReconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
int rrclass, byte[] rdata);
protected native String GetNameForIfIndex( int ifIndex);
@ -685,7 +648,7 @@ class AppleService implements DNSSDService, Runnable
protected void ThrowOnErr( int rc) throws DNSSDException
{
if ( rc != 0)
if (rc != 0)
throw new AppleDNSSDException( rc);
}
@ -734,12 +697,12 @@ class AppleService implements DNSSDService, Runnable
class AppleBrowser extends AppleService
{
public AppleBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener client)
public AppleBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener client)
throws DNSSDException
{
{
super(client);
this.ThrowOnErr( this.CreateBrowser( flags, ifIndex, regType, domain));
if ( !AppleDNSSD.hasAutoCallbacks)
if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
@ -749,27 +712,27 @@ class AppleBrowser extends AppleService
class AppleResolver extends AppleService
{
public AppleResolver( int flags, int ifIndex, String serviceName, String regType,
String domain, ResolveListener client)
public AppleResolver( int flags, int ifIndex, String serviceName, String regType,
String domain, ResolveListener client)
throws DNSSDException
{
super(client);
{
super(client);
this.ThrowOnErr( this.CreateResolver( flags, ifIndex, serviceName, regType, domain));
if ( !AppleDNSSD.hasAutoCallbacks)
if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
// Sets fNativeContext. Returns non-zero on error.
protected native int CreateResolver( int flags, int ifIndex, String serviceName, String regType,
protected native int CreateResolver( int flags, int ifIndex, String serviceName, String regType,
String domain);
}
// An AppleDNSRecord is a simple wrapper around a dns_sd DNSRecord.
class AppleDNSRecord implements DNSRecord
{
public AppleDNSRecord( AppleService owner)
{
fOwner = owner;
public AppleDNSRecord( AppleService owner)
{
fOwner = owner;
fRecord = 0; // record always starts out empty
}
@ -785,12 +748,12 @@ class AppleDNSRecord implements DNSRecord
this.ThrowOnErr( this.Remove());
}
protected long fRecord; // Really a DNSRecord; sizeof(int) == sizeof(void*) ?
protected long fRecord; // Really a DNSRecord; sizeof(long) == sizeof(void*) ?
protected AppleService fOwner;
protected void ThrowOnErr( int rc) throws DNSSDException
{
if ( rc != 0)
if (rc != 0)
throw new AppleDNSSDException( rc);
}
@ -801,13 +764,13 @@ class AppleDNSRecord implements DNSRecord
class AppleRegistration extends AppleService implements DNSSDRegistration
{
public AppleRegistration( int flags, int ifIndex, String serviceName, String regType, String domain,
String host, int port, byte[] txtRecord, RegisterListener client)
public AppleRegistration( int flags, int ifIndex, String serviceName, String regType, String domain,
String host, int port, byte[] txtRecord, RegisterListener client)
throws DNSSDException
{
super(client);
{
super(client);
this.ThrowOnErr( this.BeginRegister( ifIndex, flags, serviceName, regType, domain, host, port, txtRecord));
if ( !AppleDNSSD.hasAutoCallbacks)
if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
@ -827,7 +790,7 @@ class AppleRegistration extends AppleService implements DNSSDRegistration
}
// Sets fNativeContext. Returns non-zero on error.
protected native int BeginRegister( int ifIndex, int flags, String serviceName, String regType,
protected native int BeginRegister( int ifIndex, int flags, String serviceName, String regType,
String domain, String host, int port, byte[] txtRecord);
// Sets fNativeContext. Returns non-zero on error.
@ -836,16 +799,16 @@ class AppleRegistration extends AppleService implements DNSSDRegistration
class AppleRecordRegistrar extends AppleService implements DNSSDRecordRegistrar
{
public AppleRecordRegistrar( RegisterRecordListener listener)
public AppleRecordRegistrar( RegisterRecordListener listener)
throws DNSSDException
{
super(listener);
{
super(listener);
this.ThrowOnErr( this.CreateConnection());
if ( !AppleDNSSD.hasAutoCallbacks)
if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype,
public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype,
int rrclass, byte[] rdata, int ttl)
throws DNSSDException
{
@ -859,19 +822,19 @@ class AppleRecordRegistrar extends AppleService implements DNSSDRecordRegistrar
protected native int CreateConnection();
// Sets fNativeContext. Returns non-zero on error.
protected native int RegisterRecord( int flags, int ifIndex, String fullname, int rrtype,
protected native int RegisterRecord( int flags, int ifIndex, String fullname, int rrtype,
int rrclass, byte[] rdata, int ttl, AppleDNSRecord destObj);
}
class AppleQuery extends AppleService
{
public AppleQuery( int flags, int ifIndex, String serviceName, int rrtype,
int rrclass, QueryListener client)
public AppleQuery( int flags, int ifIndex, String serviceName, int rrtype,
int rrclass, QueryListener client)
throws DNSSDException
{
super(client);
{
super(client);
this.ThrowOnErr( this.CreateQuery( flags, ifIndex, serviceName, rrtype, rrclass));
if ( !AppleDNSSD.hasAutoCallbacks)
if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}
@ -881,12 +844,12 @@ class AppleQuery extends AppleService
class AppleDomainEnum extends AppleService
{
public AppleDomainEnum( int flags, int ifIndex, DomainListener client)
public AppleDomainEnum( int flags, int ifIndex, DomainListener client)
throws DNSSDException
{
super(client);
{
super(client);
this.ThrowOnErr( this.BeginEnum( flags, ifIndex));
if ( !AppleDNSSD.hasAutoCallbacks)
if (!AppleDNSSD.hasAutoCallbacks)
new Thread(this).start();
}

View File

@ -13,25 +13,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: DNSSDException.java,v $
Revision 1.4 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.3 2005/07/10 22:19:01 cheshire
Add missing error codes to list of public static final ints
Revision 1.2 2004/04/30 21:48:27 rpantos
Change line endings for CVS.
Revision 1.1 2004/04/30 16:29:35 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
*/
*/
package com.apple.dnssd;
@ -42,33 +24,39 @@ package com.apple.dnssd;
abstract public class DNSSDException extends Exception
{
public static final int NO_ERROR = 0;
public static final int UNKNOWN = -65537;
public static final int NO_SUCH_NAME = -65538;
public static final int NO_MEMORY = -65539;
public static final int BAD_PARAM = -65540;
public static final int BAD_REFERENCE = -65541;
public static final int BAD_STATE = -65542;
public static final int BAD_FLAGS = -65543;
public static final int UNSUPPORTED = -65544;
public static final int NOT_INITIALIZED = -65545;
public static final int NO_CACHE = -65546;
public static final int ALREADY_REGISTERED = -65547;
public static final int NAME_CONFLICT = -65548;
public static final int INVALID = -65549;
public static final int FIREWALL = -65550;
public static final int INCOMPATIBLE = -65551;
public static final int BAD_INTERFACE_INDEX = -65552;
public static final int REFUSED = -65553;
public static final int NOSUCHRECORD = -65554;
public static final int NOAUTH = -65555;
public static final int NOSUCHKEY = -65556;
public static final int NATTRAVERSAL = -65557;
public static final int DOUBLENAT = -65558;
public static final int BADTIME = -65559;
public static final int BADSIG = -65560;
public static final int BADKEY = -65561;
public static final int TRANSIENT = -65562;
public static final int NO_ERROR = 0;
public static final int UNKNOWN = -65537;
public static final int NO_SUCH_NAME = -65538;
public static final int NO_MEMORY = -65539;
public static final int BAD_PARAM = -65540;
public static final int BAD_REFERENCE = -65541;
public static final int BAD_STATE = -65542;
public static final int BAD_FLAGS = -65543;
public static final int UNSUPPORTED = -65544;
public static final int NOT_INITIALIZED = -65545;
public static final int NO_CACHE = -65546;
public static final int ALREADY_REGISTERED = -65547;
public static final int NAME_CONFLICT = -65548;
public static final int INVALID = -65549;
public static final int FIREWALL = -65550;
public static final int INCOMPATIBLE = -65551;
public static final int BAD_INTERFACE_INDEX = -65552;
public static final int REFUSED = -65553;
public static final int NOSUCHRECORD = -65554;
public static final int NOAUTH = -65555;
public static final int NOSUCHKEY = -65556;
public static final int NATTRAVERSAL = -65557;
public static final int DOUBLENAT = -65558;
public static final int BADTIME = -65559;
public static final int BADSIG = -65560;
public static final int BADKEY = -65561;
public static final int TRANSIENT = -65562;
public static final int SERVICENOTRUNNING = -65563;
public static final int NATPORTMAPPINGUNSUPPORTED = -65564;
public static final int NATPORTMAPPINGDISABLED = -65565;
// Note: When adding new error values here, remember also
// to update the corresponding kMessages array in AppleDNSSDException (DNSSD.java)
/** Returns the sub-code that identifies the particular error. */
abstract public int getErrorCode();

View File

@ -13,21 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
This file declares the public interface to DNSSDRecordRegistrar, a DNSSDService
subclass that allows efficient registration of multiple individual records.
Change History (most recent first):
$Log: DNSSDRecordRegistrar.java,v $
Revision 1.2 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.1 2006/06/20 23:00:12 rpantos
<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
ident "%Z%%M% %I% %E% SMI"
*/
@ -58,15 +43,12 @@ public interface DNSSDRecordRegistrar extends DNSSDService
The class of the resource record, as defined in nameser.h
(usually 1 for the Internet class).
<P>
@param rData
@param rdata
The new rdata as it is to appear in the DNS record.
<P>
@param ttl
The time to live of the resource record, in seconds. Pass 0 to use a default value.
<P>
@param listener
This object will get called when the service is registered.
<P>
@return A {@link DNSSDService} that can be used to abort the record registration.
@throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.

View File

@ -13,23 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: DNSSDRegistration.java,v $
Revision 1.3 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/12/11 03:01:00 rpantos
<rdar://problem/3907498> Java DNSRecord API should be cleaned up
Revision 1.1 2004/04/30 16:32:34 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
This file declares the public interface to DNSSDRegistration, a DNSSDService
subclass that allows a client to control a service registration.
*/

View File

@ -13,21 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: DNSSDService.java,v $
Revision 1.3 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/04/30 21:48:27 rpantos
Change line endings for CVS.
Revision 1.1 2004/04/30 16:32:34 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
*/

View File

@ -13,21 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: DomainListener.java,v $
Revision 1.3 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/04/30 21:48:27 rpantos
Change line endings for CVS.
Revision 1.1 2004/04/30 16:29:35 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
*/

View File

@ -13,21 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: QueryListener.java,v $
Revision 1.3 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/04/30 21:48:27 rpantos
Change line endings for CVS.
Revision 1.1 2004/04/30 16:29:35 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
*/
@ -38,13 +23,16 @@ package com.apple.dnssd;
public interface QueryListener extends BaseListener
{
/** Called when a record query has been completed.<P>
/** Called when a record query has been completed. Inspect flags
parameter to determine nature of query event.<P>
@param query
The active query object.
<P>
@param flags
Possible values are DNSSD.MORE_COMING.
If kDNSServiceFlagsAdd bit is set, this is a newly discovered answer;
otherwise this is a previously discovered answer which has expired.
Other possible values are DNSSD.MORE_COMING.
<P>
@param ifIndex
The interface on which the query was resolved. (The index for a given

View File

@ -13,21 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: RegisterListener.java,v $
Revision 1.3 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/04/30 21:48:27 rpantos
Change line endings for CVS.
Revision 1.1 2004/04/30 16:29:35 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
*/

View File

@ -13,18 +13,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: RegisterRecordListener.java,v $
Revision 1.2 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.1 2006/06/20 23:00:12 rpantos
<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
ident "%Z%%M% %I% %E% SMI"
*/

View File

@ -13,22 +13,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: ResolveListener.java,v $
Revision 1.3 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.2 2004/04/30 21:48:27 rpantos
Change line endings for CVS.
Revision 1.1 2004/04/30 16:29:35 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
*/
*/
package com.apple.dnssd;

View File

@ -14,29 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
Change History (most recent first):
$Log: TXTRecord.java,v $
Revision 1.6 2006/08/14 23:25:08 cheshire
Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
Revision 1.5 2004/08/25 21:54:36 rpantos
<rdar://problem/3773973> Fix getValue() for values containing '='.
Revision 1.4 2004/08/04 01:04:50 rpantos
<rdar://problems/3731579&3731582> Fix set(); add remove() & toString().
Revision 1.3 2004/07/13 21:24:25 rpantos
Fix for <rdar://problem/3701120>.
Revision 1.2 2004/04/30 21:48:27 rpantos
Change line endings for CVS.
Revision 1.1 2004/04/30 16:29:35 rpantos
First checked in.
ident "%Z%%M% %I% %E% SMI"
To do:
- implement remove()
- fix set() to replace existing values
@ -126,20 +103,20 @@ public class TXTRecord
byte[] oldBytes = fBytes;
int valLen = (value != null) ? value.length : 0;
int insertion = 0;
byte newLen, avLen;
int newLen, avLen;
// locate the insertion point
for ( int i=0; i < index && insertion < fBytes.length; i++)
insertion += fBytes[ insertion] + 1;
insertion += (0xFF & (fBytes[ insertion] + 1));
avLen = (byte) ( keyBytes.length + valLen + (value != null ? 1 : 0));
newLen = (byte) ( avLen + oldBytes.length + 1);
avLen = keyBytes.length + valLen + (value != null ? 1 : 0);
newLen = avLen + oldBytes.length + 1;
fBytes = new byte[ newLen];
System.arraycopy( oldBytes, 0, fBytes, 0, insertion);
int secondHalfLen = oldBytes.length - insertion;
System.arraycopy( oldBytes, insertion, fBytes, newLen - secondHalfLen, secondHalfLen);
fBytes[ insertion] = avLen;
fBytes[ insertion] = ( byte) avLen;
System.arraycopy( keyBytes, 0, fBytes, insertion + 1, keyBytes.length);
if ( value != null)
{
@ -169,7 +146,7 @@ public class TXTRecord
return i;
}
}
avStart += avLen + 1;
avStart += (0xFF & (avLen + 1));
}
return -1;
}
@ -180,7 +157,7 @@ public class TXTRecord
int i, avStart;
for ( i=0, avStart=0; avStart < fBytes.length; i++)
avStart += fBytes[ avStart] + 1;
avStart += (0xFF & (fBytes[ avStart] + 1));
return i;
}

View File

@ -41,9 +41,6 @@
To do:
- display resolved TXTRecord
ident "%Z%%M% %I% %E% SMI"
*/
@ -57,7 +54,7 @@ import javax.swing.event.*;
import com.apple.dnssd.*;
class BrowserApp implements ListSelectionListener, ResolveListener
class BrowserApp implements ListSelectionListener, ResolveListener, Runnable
{
static BrowserApp app;
JFrame frame;
@ -66,6 +63,8 @@ class BrowserApp implements ListSelectionListener, ResolveListener
JList domainPane, servicesPane, servicePane;
DNSSDService servicesBrowser, serviceBrowser, domainBrowser;
JLabel hostLabel, portLabel;
String hostNameForUpdate;
int portForUpdate;
public BrowserApp()
{
@ -173,22 +172,43 @@ class BrowserApp implements ListSelectionListener, ResolveListener
serviceList.getNthServiceName( newSel),
serviceList.getNthRegType( newSel),
serviceList.getNthDomain( newSel),
new SwingResolveListener( this));
this);
}
}
}
catch ( Exception ex) { terminateWithException( ex); }
}
public void run()
{
hostLabel.setText( hostNameForUpdate);
portLabel.setText( String.valueOf( portForUpdate));
}
public void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName,
String hostName, int port, TXTRecord txtRecord)
{
hostLabel.setText( hostName);
portLabel.setText( String.valueOf( port));
// We want to update GUI on the AWT event dispatching thread, but we can't stop
// the resolve from that thread, since stop() is synchronized with this callback.
// So, we stop the resolve on this thread, then invokeAndWait on the AWT event thread.
resolver.stop();
hostNameForUpdate = hostName;
portForUpdate = port;
try {
SwingUtilities.invokeAndWait(this);
}
catch ( Exception e)
{
e.printStackTrace();
}
}
public void operationFailed( DNSSDService service, int errorCode)
{
service.stop();
// handle failure here
}

View File

@ -1,3 +1,2 @@
Manifest-Version: 1.0
Main-Class: BrowserApp
Class-Path: /usr/share/lib/java/dnssd.jar

View File

@ -42,9 +42,6 @@
To do:
- implement better coloring algorithm
ident "%Z%%M% %I% %E% SMI"
*/

View File

@ -1,3 +1,2 @@
Manifest-Version: 1.0
Main-Class: SimpleChat
Class-Path: /usr/share/lib/java/dnssd.jar

View File

@ -36,11 +36,9 @@
* OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ident "%Z%%M% %I% %E% SMI"
*/
import javax.swing.*;
import com.apple.dnssd.*;

View File

@ -36,9 +36,6 @@
* OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ident "%Z%%M% %I% %E% SMI"
*/

View File

@ -36,9 +36,6 @@
* OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ident "%Z%%M% %I% %E% SMI"
*/

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@
# Copyright 2011, Richard Lowe
# Copyright (c) 2012, Joyent, Inc. All rights reserved.
# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
# Copyright 2016 Toomas Soome <tsoome@me.com>
#
include $(SRC)//Makefile.master
@ -286,6 +287,7 @@ _MANFILES= 6to4relay.1m \
makedbm.1m \
makemap.1m \
mdmonitord.1m \
mdnsd.1m \
medstat.1m \
metaclear.1m \
metadb.1m \

View File

@ -1,335 +1,264 @@
'\" te
.\" Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved.
.\" Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing,
.\" software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
.\" Portions Copyright (c) 2007, Sun Microsystems, Inc. All Rights Reserved.
.TH DNS-SD 1M "Aug 21, 2007"
.SH NAME
dns-sd \- Multicast DNS (mDNS) & DNS Service Discovery (DNS-SD) Test Tool
.SH SYNOPSIS
.LP
.nf
\fBdns-sd\fR \fB-R\fR \fIname\fR \fItype\fR \fIdomain\fR \fIport\fR [\fIkey\fR=\fIvalue\fR ...]
.fi
.LP
.nf
\fBdns-sd\fR \fB-B\fR \fItype\fR \fIdomain\fR
.fi
.LP
.nf
\fBdns-sd\fR \fB-L\fR \fIname\fR \fItype\fR \fIdomain\fR
.fi
.LP
.nf
\fBdns-sd\fR \fB-Q\fR \fIFQDN\fR \fIrrtype\fR \fIrrclass\fR
.fi
.LP
.nf
\fBdns-sd\fR \fB-C\fR \fIFQDN\fR \fIrrtype\fR \fIrrclass\fR
.fi
.LP
.nf
\fBdns-sd\fR \fB-P\fR \fIname\fR \fItype\fR \fIdomain\fR \fIport\fR \fIhost\fR \fIIP\fR [\fIkey\fR=\fIvalue\fR ...]
.fi
.LP
.nf
\fBdns-sd\fR \fB-E\fR | \fB-F\fR | \fB-A\fR | \fB-U\fR | \fB-N\fR | \fB-T\fR | \fB-M\fR | \fB-I\fR
.fi
.SH DESCRIPTION
.sp
.LP
The \fBdns-sd\fR command is a network diagnostic tool, much like \fBping\fR(1M)
or \fBtraceroute\fR(1M). However, unlike those tools, most of its functionality
is not implemented in the \fBdns-sd\fR executable itself, but in library code
that is available to any application. The library \fBAPI\fR that \fBdns-sd\fR
uses is documented in \fB/usr/include/dns_sd.h\fR.
.sp
.LP
The \fBdns-sd\fR command is primarily intended for interactive use. Because its
command-line arguments and output format are subject to change, invoking it
from a shell script can be unpredictable. Additionally, the asynchronous nature
of \fBDNS\fR Service Discovery does not easily lend itself to script-oriented
programming. This style of asynchronous interaction works best with
applications that are either multi-threaded, or use a main event-handling loop
to receive keystrokes, network data, and other asynchronous event notifications
as they happen.
.SH OPTIONS
.sp
.LP
The following options are supported:
.sp
.ne 2
.na
\fB\fB-R\fR \fIname\fR \fItype\fR \fIdomain\fR \fIport\fR
[\fIkey\fR=\fIvalue\fR ...]\fR
.ad
.sp .6
.RS 4n
Register (advertise) a service in the specified domain with the given
\fIname\fR and \fItype\fR as listening (on the current machine) on the
specified \fIport\fR.
.sp
\fIname\fR can be any arbitrary unicode text, containing any legal unicode
characters (including dots, spaces, slashes, colons, and so on without any
restrictions), up to 63 \fBUTF-8\fR bytes long.
.sp
\fItype\fR must be of the form "_app-proto._tcp" or "_app-proto._udp", where
.\" -*- tab-width: 4 -*-
.\"
.\" Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
.\"
.\" Licensed under the Apache License, Version 2.0 (the "License");
.\" you may not use this file except in compliance with the License.
.\" You may obtain a copy of the License at
.\"
.\" http://www.apache.org/licenses/LICENSE-2.0
.\"
.\" Unless required by applicable law or agreed to in writing, software
.\" distributed under the License is distributed on an "AS IS" BASIS,
.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
.\" See the License for the specific language governing permissions and
.\" limitations under the License.
.\"
.\" Copyright 2016 Toomas Soome <tsoome@me.com>
.\"
.Dd Jan 28, 2016 \" Date
.Dt DNS-SD 1M \" Document Title
.Os illumos \" Operating System
.\"
.Sh NAME
.Nm dns-sd
.Nd Multicast DNS (mDNS) & DNS Service Discovery (DNS-SD) Test Tool \" For whatis
.\"
.Sh SYNOPSIS
.Nm
.Op Fl E
.Pp
.Nm
.Op Fl F
.Pp
.Nm
.Op Fl R Ar name type domain port Op Ar key=value ...
.Pp
.Nm
.Op Fl B Ar type domain
.Pp
.Nm
.Op Fl L Ar name type domain
.Pp
.Nm
.Op Fl P Ar name type domain port host IP Op Ar key=value ...
.Pp
.Nm
.Op Fl q Ar name rrtype rrclass
.Pp
.Nm
.Op Fl Z Ar type domain
.Pp
.Nm
.Op Fl G Ns \ v4/v6/v4v6 Ar name
.Pp
.Nm
.Op Fl V
.\"
.Sh DESCRIPTION
The
.Nm
command is a network diagnostic tool, much like
.Xr ping 8
or
.Xr traceroute 8 .
However, unlike those tools, most of its functionality is not implemented in the
.Nm
executable itself, but in library code that is available to any application.
The library API that
.Nm
uses is documented in
.Pa /usr/include/dns_sd.h .
The
.Nm
command replaces the older
mDNS
command.
.Pp
The
.Nm
command is primarily intended for interactive use.
Because its command-line arguments and output format are subject to change,
invoking it from a shell script will generally be fragile. Additionally,
the asynchronous nature of DNS Service Discovery does
not lend itself easily to script-oriented programming. For example,
calls like "browse" never complete; the action of performing a "browse"
sets in motion machinery to notify the client whenever instances of
that service type appear or disappear from the network. These
notifications continue to be delivered indefinitely, for minutes,
hours, or even days, as services come and go, until the client
explicitly terminates the call. This style of asynchronous interaction
works best with applications that are either multi-threaded, or use a
main event-handling loop to receive keystrokes, network data, and other
asynchronous event notifications as they happen.
.br
If you wish to perform DNS Service Discovery operations from a
scripting language, then the best way to do this is not to execute the
.Nm
command and then attempt to decipher the textual output, but instead to
directly call the DNS-SD APIs using a binding for your chosen language.
.br
For example, if you are programming in Ruby, then you can
directly call DNS-SD APIs using the dnssd package documented at
.Pa <http://rubyforge.org/projects/dnssd/> .
.br
Similar bindings for other languages are also in development.
.Bl -tag -width E
.It Nm Fl E
return a list of domains recommended for registering(advertising) services.
.It Nm Fl F
return a list of domains recommended for browsing services.
.Pp
Normally, on your home network, the only domain you are likely to see is "local".
However if your network administrator has created Domain Enumeration records,
then you may also see other recommended domains for registering and browsing.
.It Nm Fl R Ar name type domain port Op Ar key=value ...
register (advertise) a service in the specified
.Ar domain
with the given
.Ar name
and
.Ar type
as listening (on the current machine) on
.Ar port.
.Pp
.Ar name
can be arbitrary unicode text, containing any legal unicode characters
(including dots, spaces, slashes, colons, etc. without restriction),
up to 63 UTF-8 bytes long.
.Ar type
must be of the form "_app-proto._tcp" or "_app-proto._udp", where
"app-proto" is an application protocol name registered at
http://www.dns-sd.org/ServiceTypes.html.
.sp
\fIdomain\fR is the domain in which to register the service. In current
implementations, only the local multicast domain "local" is supported. In the
future, registering will be supported in any arbitrary domain that has a
working \fBDNS\fR Update server [\fBRFC\fR 2136]. The domain "." is a synonym
for "pick a sensible default", which currently means "local".
.sp
\fIport\fR is a number from 0 to 65535, and is the \fBTCP\fR or \fBUDP\fR port
number upon which the service is listening. Registering a service on port 0
allows an application to explicitly advertise the non-availability of a
service.
.sp
.Pa http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml .
.Pp
.Ar domain
is the domain in which to register the service.
In current implementations, only the local multicast domain "local" is
supported. In the future, registering will be supported in any arbitrary
domain that has a working DNS Update server [RFC 2136]. The
.Ar domain
"." is a synonym for "pick a sensible default" which today
means "local".
.Pp
.Ar port
is a number from 0 to 65535, and is the TCP or UDP port number upon
which the service is listening.
.Pp
Additional attributes of the service may optionally be described by
\fIkey/value\fR pairs, which are stored in the advertised service's \fBDNS\fR
\fBTXT\fR record. Allowable keys and values are listed with the service
registration at http://www.dns-sd.org/ServiceTypes.html
.RE
.sp
.ne 2
.na
\fB\fB-B\fR \fItype\fR \fIdomain\fR\fR
.ad
.sp .6
.RS 4n
Browse for instances of service \fItype\fR in \fIdomain\fR.
.sp
For valid types, see http://www.dns-sd.org/ServiceTypes.html. Omitting the
domain name or using "." means "pick a sensible default."
.RE
.sp
.ne 2
.na
\fB\fB-L\fR \fIname\fR \fItype\fR \fIdomain\fR\fR
.ad
.sp .6
.RS 4n
Look up and display the information necessary to contact and use the named
service. This information includes the hostname of the machine where that
service is available, the port number on which the service is listening, and
(if present) \fBTXT\fR record attributes describing properties of the service.
.sp
In a typical application, browsing happens rarely, while lookup (or
"resolving") happens every time the service is used. For example, a user does
not browse the network to pick a default printer that often, but once a default
printer has been picked, that named service is resolved to its current IP
address and port number every time the user presses Cmd-P to print.
.RE
.sp
.ne 2
.na
\fB\fB-Q\fR \fIFQDN\fR \fIrrtype\fR \fIrrclass\fR\fR
.ad
.sp .6
.RS 4n
Generic query for any resource record type and class.
.RE
.sp
.ne 2
.na
\fB\fB-C\fR \fIFQDN\fR \fIrrtype\fR \fIrrclass\fR\fR
.ad
.sp .6
.RS 4n
Generic query for any resource record type and class. This option also
reconfirms each result from the query. Reconfirming the record instructs
\fBmdnsd\fR(1M) to verify the validity of the record. If the record is not
valid \fBmdnsd\fR(1M) flushes the record from the daemon's cache and also from
other \fBmdnsd\fR(1M) caches on the network.
.RE
.sp
.ne 2
.na
\fB\fB-P\fR \fIname\fR \fItype\fR \fIdomain\fR \fIport\fR \fIhost\fR \fIIP\fR
[\fIkey\fR=\fIvalue\fR ...]\fR
.ad
.sp .6
.RS 4n
Register (advertise) a service in the specified domain with the given
\fIname\fR and \fItype\fR listening on the specified port and accessible on
another host. This option should be used to advertise by proxy a service
accessible on another host. The host name and \fBIPv4\fR address to access the
service must be specified.
.RE
.sp
.ne 2
.na
\fB\fB-E\fR\fR
.ad
.sp .6
.RS 4n
Discover recommended registration domains. This option returns the recommended
domains to register a service. The recommended registration domains are
returned by querying the name servers in \fBresolv.conf\fR(4).
.RE
.sp
.ne 2
.na
\fB\fB-F\fR\fR
.ad
.sp .6
.RS 4n
Discover recommended browsing domains. This option returns the recommended
domains for browsing services. The recommended browsing domains are returned by
querying the name servers in \fBresolv.conf\fR(4).
.RE
.sp
.ne 2
.na
\fB\fB-A\fR\fR
.ad
.sp .6
.RS 4n
Test registering service with Multicast \fBDNS\fR and test the add, update and
delete operations of \fBDNS\fR records with Multicast \fBDNS\fR.
.RE
.sp
.ne 2
.na
\fB\fB-U\fR\fR
.ad
.sp .6
.RS 4n
Test registering service with Multicast \fBDNS\fR and test updating of
\fBDNS\fR \fBTXT\fR records for a service registered with Multicast \fBDNS\fR.
.RE
.sp
.ne 2
.na
\fB\fB-N\fR\fR
.ad
.sp .6
.RS 4n
Test adding a large \fBNULL\fR record for a service registered with Multicast
\fBDNS\fR.
.RE
.sp
.ne 2
.na
\fB\fB-T\fR\fR
.ad
.sp .6
.RS 4n
Test adding a large \fBTXT\fR record for a service registered with Multicast
\fBDNS\fR.
.RE
.sp
.ne 2
.na
\fB\fB-M\fR\fR
.ad
.sp .6
.RS 4n
Test creating a registration with multiple \fBTXT\fR records.
.RE
.sp
.ne 2
.na
\fB\fB-I\fR\fR
.ad
.sp .6
.RS 4n
Test registering and then immediately updating a \fBTXT\fR record.
.RE
.SH EXAMPLES
.LP
\fBExample 1 \fRAdvertising a printing service
.sp
.LP
The following command advertises the existence of \fBLPR\fR printing service on
port 515 on this machine, so that it will be available to \fBDNS-SD\fR
compatible printing clients:
.sp
.in +2
.nf
dns-sd -R "My Test" _printer._tcp. . 515 pdl=application/postscript
.fi
.in -2
.sp
.sp
.LP
For this registration to be useful, the LPR service should be available on port
515. Advertising a service that does not exist is not very useful.
.LP
\fBExample 2 \fRAdvertising a web page
.sp
.LP
The following command advertises a web page being served by an \fBHTTP\fR
server on port 80 on this machine, so that it will appear on the Bonjour list
in Safari and other DNS-SD compatible Web clients:
.sp
.in +2
.nf
dns-sd -R "My Test" _http._tcp . 80 path=/path-to-page.html
.fi
.in -2
.sp
.LP
\fBExample 3 \fRFinding the advertised web pages on the local network
.sp
.LP
The following command finds the advertised web pages on the local network (the
same list that Safari shows):
.sp
.in +2
.nf
dns-sd -B _http._tcp
.fi
.in -2
.sp
.SH ATTRIBUTES
.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
.sp
.TS
box;
c | c
l | l .
ATTRIBUTE TYPE ATTRIBUTE VALUE
_
Interface Stability Volatile
.TE
.SH SEE ALSO
.sp
.LP
\fBmdnsd\fR(1M), \fBping\fR(1M), \fBtraceroute\fR(1M), \fBresolv.conf\fR(4),
\fBattributes\fR(5)
key/value pairs, which are stored in the advertised service's DNS TXT
record. Allowable keys and values are listed with the service
registration at
.Pa http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml .
.It Nm Fl B Ar type domain
browse for instances of service
.Ar type
in
.Ar domain .
.Pp
For valid
.Ar type Ns s
see
.Pa http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml .
as described above. Omitting the
.Ar domain
or using "." means "pick a sensible default."
.It Nm Fl L Ar name type domain
look up and display the information necessary to contact and use the
named service: the hostname of the machine where that service is
available, the port number on which the service is listening, and (if
present) TXT record attributes describing properties of the service.
.Pp
Note that in a typical application, browsing may only happen rarely, while lookup
(or "resolving") happens every time the service is used. For example, a
user browses the network to pick a default printer fairly rarely, but once
a default printer has been picked, that named service is resolved to its
current IP address and port number every time the user presses Cmd-P to
print.
.It Nm Fl P Ar name type domain port host IP Op Ar key=value ...
create a proxy advertisement for a service running on(offered by) some other machine.
The two new options are Host, a name for the device and IP, the address of it.
.Pp
The service for which you create a proxy advertisement does not necessarily have to be on your local network.
You can set up a local proxy for a website on the Internet.
.It Nm Fl q Ar name rrtype rrclass
look up any DNS name, resource record type, and resource record class,
not necessarily DNS-SD names and record types.
If rrtype is not specified, it queries for the IPv4 address of the name,
if rrclass is not specified, IN class is assumed. If the name is not a fully
qualified domain name, then search domains may be appended.
.It Nm Fl Z Ar type domain
browse for service instances and display output in zone file format.
.It Nm Fl G Ns \ v4/v6/v4v6 Ar name
look up the IP address information of the name.
If v4 is specified, the IPv4 address of the name is looked up,
if v6 is specified the IPv6 address is looked up. If v4v6 is specified both the IPv4 and IPv6
address is looked up. If the name is not a fully qualified domain name,
then search domains may be appended.
.It Nm Fl V
return the version of the currently running daemon/system service.
.El
.Sh FILES
.Pa /usr/bin/dns-sd \" Pathname
.\"
.Sh EXAMPLES
To advertise the existence of LPR printing service on port 515 on this
machine, such that it will be discovered by the Mac OS X printing software
and other DNS-SD compatible printing clients, use:
.Pp
.Dl Nm Fl R Ns \ \&"My Test\&" _printer._tcp. \&. 515 pdl=application/postscript
.Pp
For this registration to be useful, you need to actually have LPR service
available on port 515. Advertising a service that does not exist is not
very useful, and will be confusing and annoying to other people on the
network.
.Pp
Similarly, to advertise a web page being served by an HTTP
server on port 80 on this machine, such that it will show up in the
Bonjour list in Safari and other DNS-SD compatible Web clients, use:
.Pp
.Dl Nm Fl R Ns \ \&"My Test\&" _http._tcp \&. 80 path=/path-to-page.html
.Pp
To find the advertised web pages on the local network (the same list that
Safari shows), use:
.Pp
.Dl Nm Fl B Ns \ _http._tcp
.Pp
While that command is running, in another window, try the
.Nm Fl R
example given above to advertise a web page, and you should see the
"Add" event reported to the
.Nm Fl B
window. Now press Ctrl-C in the
.Nm Fl R
window and you should see the "Remove" event reported to the
.Nm Fl B
window.
.Pp
In the example below, the www.apple.com web page is advertised as a service called "apple",
running on a target host called apple.local, which resolves to 17.149.160.49.
.Pp
.Dl Nm Fl P Ns \ apple _http._tcp \&"\&"\& 80 apple.local 17.149.160.49
.Pp
The Bonjour menu in the Safari web browser will now show "apple".
The same IP address can be reached by entering apple.local in the web browser.
In either case, the request will be resolved to the IP address and browser will show
contents associated with www.apple.com.
.Pp
If a client wants to be notified of changes in server state, it can
initiate a query for the service's particular record and leave it running.
For example, to monitor the status of an iChat user you can use:
.Pp
.Dl Nm Fl q Ns \ someone@ex1._presence._tcp.local txt
.Pp
Everytime status of that user(someone) changes, you will see a new TXT record result reported.
.Pp
You can also query for a unicast name like www.apple.com and monitor its status.
.Pp
.Dl Nm Fl q Ns \ www.apple.com
.Sh INTERFACE STABILITY
.Sy Volatile .
.Sh SEE ALSO
.Xr mdnsd 1M ,
.Xr ping 1M ,
.Xr traceroute 1M ,
.Xr resolv.conf 4

108
usr/src/man/man1m/mdnsd.1m Normal file
View File

@ -0,0 +1,108 @@
.\" -*- tab-width: 4 -*-
.\"
.\" Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved.
.\"
.\" Licensed under the Apache License, Version 2.0 (the "License");
.\" you may not use this file except in compliance with the License.
.\" You may obtain a copy of the License at
.\"
.\" http://www.apache.org/licenses/LICENSE-2.0
.\"
.\" Unless required by applicable law or agreed to in writing, software
.\" distributed under the License is distributed on an "AS IS" BASIS,
.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
.\" See the License for the specific language governing permissions and
.\" limitations under the License.
.\"
.\" Copyright 2016 Toomas Soome <tsoome@me.com>
.\"
.Dd Jan 28, 2016 \" Date
.Dt MDNSD 1M \" Document Title
.Os illumos \" Operating System
.\"
.Sh NAME
.Nm mdnsd
.Nd Multicast and Unicast DNS daemon \" Name Description for whatis database
.\"
.Sh SYNOPSIS
.Nm
.\"
.Sh DESCRIPTION
.Nm
(also known as
.Nm mDNSResponder
on some systems)
is a daemon invoked at boot time to implement Multicast DNS and DNS Service Discovery.
.Pp
.Nm
listens on UDP port 5353 for Multicast DNS Query packets.
When it receives a query for which it knows an answer,
.Nm
issues the appropriate Multicast DNS Reply packet.
.Pp
.Nm
also performs Unicast and Multicast DNS Queries on behalf of client processes, and
maintains a cache of the replies.
.Pp
.Nm
has no user-specifiable command-line argument, and users should not run
.Nm
manually.
.Sh LOGGING
There are several methods with which to examine
.Nm Ns 's internal state for debugging and diagnostic purposes. The syslog(3C)
logging levels map as follows:
.Pp
.Dl Error - Error messages
.Dl Warning - Client-initiated operations
.Dl Notice - Sleep proxy operations
.Dl Info - Informational messages
.Pp
By default, only log level Error is logged.
.Pp
A SIGUSR1 signal toggles additional logging, with Warning and Notice
enabled by default:
.Pp
.Dl % sudo pkill -USR1 mdnsd
.Pp
A SIGUSR2 signal toggles packet logging:
.Pp
.Dl % sudo pkill -USR2 mdnsd
.Pp
A SIGINFO signal will dump a snapshot summary of the internal state:
.Pp
.Dl % sudo pkill -INFO mdnsd
.Sh FILES
.Pa /usr/lib/inet/mdnsd \" Pathname
.\"
.Sh INFO
For information on Multicast DNS, see
.Pa http://www.multicastdns.org/
.Pp
For information on DNS Service Discovery, see
.Pa http://www.dns-sd.org/
.Pp
For information on how to use the Multicast DNS and the
DNS Service Discovery APIs on Mac OS X and other platforms, see
.Pa http://developer.apple.com/bonjour/
.Pp
For the source code to
.Nm , see
.Pa http://developer.apple.com/darwin/projects/bonjour/
.\"
.Sh INTERFACE STABILITY
.Sy Volatile .
.Sh SEE ALSO
.Xr dns-sd 1M
.\"
.Sh NOTES
The
.Nm
service is managed by the service management facility,
\fBsmf\fR(5), under the service identifier:
.sp
.Dl svc:/network/dns/multicast:default
.sp
Administrative actions on this service, such as enabling, disabling, or
requesting restart, can be performed using \fBsvcadm\fR(1M). The service's
status can be queried using the \fBsvcs\fR(1) command.

View File

@ -22,6 +22,7 @@
#
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2012 Nexenta Systems, Inc. All rights reserved.
# Copyright 2016 Toomas Soome <tsoome@me.com>
#
set name=pkg.fmri value=pkg:/service/network/dns/mdns@$(PKGVERS)
@ -145,6 +146,7 @@ file path=usr/share/lib/java/javadoc/dnssd/api/stylesheet.css group=other
file path=usr/share/lib/java/javadoc/dnssd/examples/BrowserApp.jar group=sys
file path=usr/share/lib/java/javadoc/dnssd/examples/SimpleChat.jar group=sys
file path=usr/share/man/man1m/dns-sd.1m
file path=usr/share/man/man1m/mdnsd.1m
file path=usr/share/man/man3dns_sd/DNSServiceBrowse.3dns_sd
file path=usr/share/man/man3dns_sd/DNSServiceConstructFullName.3dns_sd
file path=usr/share/man/man3dns_sd/DNSServiceCreateConnection.3dns_sd