14b22b933Srs /* -*- Mode: C; tab-width: 4 -*- 24b22b933Srs * 3cda73f64SToomas Soome * Copyright (c) 2004-2015 Apple Inc. All rights reserved. 44b22b933Srs * 54b22b933Srs * Licensed under the Apache License, Version 2.0 (the "License"); 64b22b933Srs * you may not use this file except in compliance with the License. 74b22b933Srs * You may obtain a copy of the License at 85ffb0c9bSToomas Soome * 94b22b933Srs * http://www.apache.org/licenses/LICENSE-2.0 105ffb0c9bSToomas Soome * 114b22b933Srs * Unless required by applicable law or agreed to in writing, software 124b22b933Srs * distributed under the License is distributed on an "AS IS" BASIS, 134b22b933Srs * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144b22b933Srs * See the License for the specific language governing permissions and 154b22b933Srs * limitations under the License. 164b22b933Srs */ 174b22b933Srs 185ffb0c9bSToomas Soome #include <stdio.h> // Needed for fopen() etc. 195ffb0c9bSToomas Soome #include <unistd.h> // Needed for close() 205ffb0c9bSToomas Soome #include <string.h> // Needed for strlen() etc. 215ffb0c9bSToomas Soome #include <errno.h> // Needed for errno etc. 225ffb0c9bSToomas Soome #include <sys/socket.h> // Needed for socket() etc. 235ffb0c9bSToomas Soome #include <netinet/in.h> // Needed for sockaddr_in 245ffb0c9bSToomas Soome #include <syslog.h> 254b22b933Srs 26c65ebfc7SToomas Soome #if APPLE_OSX_mDNSResponder 27c65ebfc7SToomas Soome #include <os/log.h> 28c65ebfc7SToomas Soome #endif 29c65ebfc7SToomas Soome 305ffb0c9bSToomas Soome #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above 315ffb0c9bSToomas Soome #include "DNSCommon.h" 324b22b933Srs #include "PlatformCommon.h" 334b22b933Srs 344b22b933Srs #ifdef NOT_HAVE_SOCKLEN_T 355ffb0c9bSToomas Soome typedef unsigned int socklen_t; 364b22b933Srs #endif 374b22b933Srs 385ffb0c9bSToomas Soome // Bind a UDP socket to find the source address to a destination 395ffb0c9bSToomas Soome mDNSexport void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst) 405ffb0c9bSToomas Soome { 415ffb0c9bSToomas Soome union { struct sockaddr s; struct sockaddr_in a4; struct sockaddr_in6 a6; } addr; 425ffb0c9bSToomas Soome socklen_t len = sizeof(addr); 435ffb0c9bSToomas Soome socklen_t inner_len = 0; 445ffb0c9bSToomas Soome int sock = socket(AF_INET, SOCK_DGRAM, 0); 455ffb0c9bSToomas Soome src->type = mDNSAddrType_None; 465ffb0c9bSToomas Soome if (sock == -1) return; 475ffb0c9bSToomas Soome if (dst->type == mDNSAddrType_IPv4) 485ffb0c9bSToomas Soome { 495ffb0c9bSToomas Soome inner_len = sizeof(addr.a4); 505ffb0c9bSToomas Soome #ifndef NOT_HAVE_SA_LEN 515ffb0c9bSToomas Soome addr.a4.sin_len = inner_len; 525ffb0c9bSToomas Soome #endif 535ffb0c9bSToomas Soome addr.a4.sin_family = AF_INET; 545ffb0c9bSToomas Soome addr.a4.sin_port = 1; // Not important, any port will do 555ffb0c9bSToomas Soome addr.a4.sin_addr.s_addr = dst->ip.v4.NotAnInteger; 565ffb0c9bSToomas Soome } 575ffb0c9bSToomas Soome else if (dst->type == mDNSAddrType_IPv6) 585ffb0c9bSToomas Soome { 595ffb0c9bSToomas Soome inner_len = sizeof(addr.a6); 605ffb0c9bSToomas Soome #ifndef NOT_HAVE_SA_LEN 615ffb0c9bSToomas Soome addr.a6.sin6_len = inner_len; 625ffb0c9bSToomas Soome #endif 635ffb0c9bSToomas Soome addr.a6.sin6_family = AF_INET6; 645ffb0c9bSToomas Soome addr.a6.sin6_flowinfo = 0; 655ffb0c9bSToomas Soome addr.a6.sin6_port = 1; // Not important, any port will do 665ffb0c9bSToomas Soome addr.a6.sin6_addr = *(struct in6_addr*)&dst->ip.v6; 675ffb0c9bSToomas Soome addr.a6.sin6_scope_id = 0; 685ffb0c9bSToomas Soome } 695ffb0c9bSToomas Soome else return; 705ffb0c9bSToomas Soome 71cda73f64SToomas Soome if ((connect(sock, &addr.s, inner_len)) < 0) { 72*3b436d06SToomas Soome if (errno != ENETUNREACH) 73*3b436d06SToomas Soome LogMsg("mDNSPlatformSourceAddrForDest: connect %#a failed errno %d (%s)", dst, errno, 74*3b436d06SToomas Soome strerror(errno)); 75cda73f64SToomas Soome goto exit; 76cda73f64SToomas Soome } 775ffb0c9bSToomas Soome 785ffb0c9bSToomas Soome if ((getsockname(sock, &addr.s, &len)) < 0) 795ffb0c9bSToomas Soome { LogMsg("mDNSPlatformSourceAddrForDest: getsockname failed errno %d (%s)", errno, strerror(errno)); goto exit; } 805ffb0c9bSToomas Soome 815ffb0c9bSToomas Soome src->type = dst->type; 825ffb0c9bSToomas Soome if (dst->type == mDNSAddrType_IPv4) src->ip.v4.NotAnInteger = addr.a4.sin_addr.s_addr; 835ffb0c9bSToomas Soome else src->ip.v6 = *(mDNSv6Addr*)&addr.a6.sin6_addr; 845ffb0c9bSToomas Soome exit: 855ffb0c9bSToomas Soome close(sock); 865ffb0c9bSToomas Soome } 874b22b933Srs 884b22b933Srs // dst must be at least MAX_ESCAPED_DOMAIN_NAME bytes, and option must be less than 32 bytes in length 894b22b933Srs mDNSlocal mDNSBool GetConfigOption(char *dst, const char *option, FILE *f) 905ffb0c9bSToomas Soome { 915ffb0c9bSToomas Soome char buf[32+1+MAX_ESCAPED_DOMAIN_NAME]; // Option name, one space, option value 925ffb0c9bSToomas Soome unsigned int len = strlen(option); 935ffb0c9bSToomas Soome if (len + 1 + MAX_ESCAPED_DOMAIN_NAME > sizeof(buf)-1) { LogMsg("GetConfigOption: option %s too long", option); return mDNSfalse; } 945ffb0c9bSToomas Soome fseek(f, 0, SEEK_SET); // set position to beginning of stream 955ffb0c9bSToomas Soome while (fgets(buf, sizeof(buf), f)) // Read at most sizeof(buf)-1 bytes from file, and append '\0' C-string terminator 965ffb0c9bSToomas Soome { 975ffb0c9bSToomas Soome if (!strncmp(buf, option, len)) 985ffb0c9bSToomas Soome { 995ffb0c9bSToomas Soome strncpy(dst, buf + len + 1, MAX_ESCAPED_DOMAIN_NAME-1); 1005ffb0c9bSToomas Soome if (dst[MAX_ESCAPED_DOMAIN_NAME-1]) dst[MAX_ESCAPED_DOMAIN_NAME-1] = '\0'; 1015ffb0c9bSToomas Soome len = strlen(dst); 1025ffb0c9bSToomas Soome if (len && dst[len-1] == '\n') dst[len-1] = '\0'; // chop newline 1035ffb0c9bSToomas Soome return mDNStrue; 1045ffb0c9bSToomas Soome } 1055ffb0c9bSToomas Soome } 1065ffb0c9bSToomas Soome debugf("Option %s not set", option); 1075ffb0c9bSToomas Soome return mDNSfalse; 1085ffb0c9bSToomas Soome } 1094b22b933Srs 1104b22b933Srs mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled) 1115ffb0c9bSToomas Soome { 1125ffb0c9bSToomas Soome char buf[MAX_ESCAPED_DOMAIN_NAME] = ""; 1135ffb0c9bSToomas Soome mStatus err; 1145ffb0c9bSToomas Soome FILE *f = fopen(filename, "r"); 1155ffb0c9bSToomas Soome 1165ffb0c9bSToomas Soome if (hostname) hostname->c[0] = 0; 1175ffb0c9bSToomas Soome if (domain) domain->c[0] = 0; 1185ffb0c9bSToomas Soome if (DomainDiscoveryDisabled) *DomainDiscoveryDisabled = mDNSfalse; 1195ffb0c9bSToomas Soome 1205ffb0c9bSToomas Soome if (f) 1215ffb0c9bSToomas Soome { 1225ffb0c9bSToomas Soome if (DomainDiscoveryDisabled && GetConfigOption(buf, "DomainDiscoveryDisabled", f) && !strcasecmp(buf, "true")) *DomainDiscoveryDisabled = mDNStrue; 1235ffb0c9bSToomas Soome if (hostname && GetConfigOption(buf, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, buf)) goto badf; 1245ffb0c9bSToomas Soome if (domain && GetConfigOption(buf, "zone", f) && !MakeDomainNameFromDNSNameString(domain, buf)) goto badf; 1255ffb0c9bSToomas Soome buf[0] = 0; 1265ffb0c9bSToomas Soome GetConfigOption(buf, "secret-64", f); // failure means no authentication 1275ffb0c9bSToomas Soome fclose(f); 1285ffb0c9bSToomas Soome f = NULL; 1295ffb0c9bSToomas Soome } 1305ffb0c9bSToomas Soome else 1315ffb0c9bSToomas Soome { 1325ffb0c9bSToomas Soome if (errno != ENOENT) LogMsg("ERROR: Config file exists, but cannot be opened."); 1335ffb0c9bSToomas Soome return; 1345ffb0c9bSToomas Soome } 1355ffb0c9bSToomas Soome 1365ffb0c9bSToomas Soome if (domain && domain->c[0] && buf[0]) 1375ffb0c9bSToomas Soome { 1385ffb0c9bSToomas Soome DomainAuthInfo *info = (DomainAuthInfo*)mDNSPlatformMemAllocate(sizeof(*info)); 1395ffb0c9bSToomas Soome // for now we assume keyname = service reg domain and we use same key for service and hostname registration 1405ffb0c9bSToomas Soome err = mDNS_SetSecretForDomain(m, info, domain, domain, buf, NULL, 0, mDNSfalse); 1415ffb0c9bSToomas Soome if (err) LogMsg("ERROR: mDNS_SetSecretForDomain returned %d for domain %##s", err, domain->c); 1425ffb0c9bSToomas Soome } 1435ffb0c9bSToomas Soome 1445ffb0c9bSToomas Soome return; 1455ffb0c9bSToomas Soome 1465ffb0c9bSToomas Soome badf: 1475ffb0c9bSToomas Soome LogMsg("ERROR: malformatted config file"); 1485ffb0c9bSToomas Soome if (f) fclose(f); 1495ffb0c9bSToomas Soome } 1505ffb0c9bSToomas Soome 1515ffb0c9bSToomas Soome #if MDNS_DEBUGMSGS 1525ffb0c9bSToomas Soome mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg) 1535ffb0c9bSToomas Soome { 1545ffb0c9bSToomas Soome fprintf(stderr,"%s\n", msg); 1555ffb0c9bSToomas Soome fflush(stderr); 1565ffb0c9bSToomas Soome } 1575ffb0c9bSToomas Soome #endif 1585ffb0c9bSToomas Soome 1595ffb0c9bSToomas Soome mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, mDNSLogLevel_t loglevel) 1605ffb0c9bSToomas Soome { 1615ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder && LogTimeStamps 1625ffb0c9bSToomas Soome extern mDNS mDNSStorage; 1635ffb0c9bSToomas Soome extern mDNSu32 mDNSPlatformClockDivisor; 1645ffb0c9bSToomas Soome mDNSs32 t = mDNSStorage.timenow ? mDNSStorage.timenow : mDNSPlatformClockDivisor ? mDNS_TimeNow_NoLock(&mDNSStorage) : 0; 1655ffb0c9bSToomas Soome int ms = ((t < 0) ? -t : t) % 1000; 1665ffb0c9bSToomas Soome #endif 1675ffb0c9bSToomas Soome 1685ffb0c9bSToomas Soome if (mDNS_DebugMode) // In debug mode we write to stderr 1695ffb0c9bSToomas Soome { 1705ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder && LogTimeStamps 1715ffb0c9bSToomas Soome if (ident && ident[0] && mDNSPlatformClockDivisor) 1725ffb0c9bSToomas Soome fprintf(stderr,"%8d.%03d: %s\n", (int)(t/1000), ms, buffer); 1735ffb0c9bSToomas Soome else 1745ffb0c9bSToomas Soome #endif 1755ffb0c9bSToomas Soome fprintf(stderr,"%s\n", buffer); 1765ffb0c9bSToomas Soome fflush(stderr); 1775ffb0c9bSToomas Soome } 1785ffb0c9bSToomas Soome else // else, in production mode, we write to syslog 1795ffb0c9bSToomas Soome { 1805ffb0c9bSToomas Soome static int log_inited = 0; 1815ffb0c9bSToomas Soome 1825ffb0c9bSToomas Soome int syslog_level = LOG_ERR; 1835ffb0c9bSToomas Soome switch (loglevel) 1845ffb0c9bSToomas Soome { 185c65ebfc7SToomas Soome #if APPLE_OSX_mDNSResponder 186c65ebfc7SToomas Soome case MDNS_LOG_MSG: syslog_level = OS_LOG_TYPE_DEFAULT; break; 187c65ebfc7SToomas Soome case MDNS_LOG_OPERATION: syslog_level = OS_LOG_TYPE_INFO; break; 188c65ebfc7SToomas Soome case MDNS_LOG_SPS: syslog_level = OS_LOG_TYPE_INFO; break; 189c65ebfc7SToomas Soome case MDNS_LOG_INFO: syslog_level = OS_LOG_TYPE_INFO; break; 190c65ebfc7SToomas Soome case MDNS_LOG_DEBUG: syslog_level = OS_LOG_TYPE_DEBUG; break; 191c65ebfc7SToomas Soome default: syslog_level = OS_LOG_TYPE_DEFAULT; break; 192c65ebfc7SToomas Soome #else 1935ffb0c9bSToomas Soome case MDNS_LOG_MSG: syslog_level = LOG_ERR; break; 1945ffb0c9bSToomas Soome case MDNS_LOG_OPERATION: syslog_level = LOG_WARNING; break; 1955ffb0c9bSToomas Soome case MDNS_LOG_SPS: syslog_level = LOG_NOTICE; break; 1965ffb0c9bSToomas Soome case MDNS_LOG_INFO: syslog_level = LOG_INFO; break; 1975ffb0c9bSToomas Soome case MDNS_LOG_DEBUG: syslog_level = LOG_DEBUG; break; 1985ffb0c9bSToomas Soome default: 1995ffb0c9bSToomas Soome fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel); 2005ffb0c9bSToomas Soome fflush(stderr); 201c65ebfc7SToomas Soome #endif 2025ffb0c9bSToomas Soome } 2035ffb0c9bSToomas Soome 2045ffb0c9bSToomas Soome if (!log_inited) { openlog(ident, LOG_CONS, LOG_DAEMON); log_inited++; } 2055ffb0c9bSToomas Soome 2065ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder && LogTimeStamps 2075ffb0c9bSToomas Soome if (ident && ident[0] && mDNSPlatformClockDivisor) 2085ffb0c9bSToomas Soome syslog(syslog_level, "%8d.%03d: %s", (int)(t/1000), ms, buffer); 2095ffb0c9bSToomas Soome else 210cda73f64SToomas Soome #endif 211cda73f64SToomas Soome { 212cda73f64SToomas Soome #if APPLE_OSX_mDNSResponder 213cda73f64SToomas Soome mDNSPlatformLogToFile(syslog_level, buffer); 2145ffb0c9bSToomas Soome #else 215cda73f64SToomas Soome syslog(syslog_level, "%s", buffer); 2165ffb0c9bSToomas Soome #endif 217cda73f64SToomas Soome } 2185ffb0c9bSToomas Soome } 2195ffb0c9bSToomas Soome } 220