xref: /titanic_52/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.c (revision 5ffb0c9b03b5149ff4f5821a62be4a52408ada2a)
14b22b933Srs200217 /* -*- Mode: C; tab-width: 4 -*-
24b22b933Srs200217  *
34b22b933Srs200217  * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
44b22b933Srs200217  *
54b22b933Srs200217  * Licensed under the Apache License, Version 2.0 (the "License");
64b22b933Srs200217  * you may not use this file except in compliance with the License.
74b22b933Srs200217  * You may obtain a copy of the License at
84b22b933Srs200217  *
94b22b933Srs200217  *     http://www.apache.org/licenses/LICENSE-2.0
104b22b933Srs200217  *
114b22b933Srs200217  * Unless required by applicable law or agreed to in writing, software
124b22b933Srs200217  * distributed under the License is distributed on an "AS IS" BASIS,
134b22b933Srs200217  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144b22b933Srs200217  * See the License for the specific language governing permissions and
154b22b933Srs200217  * limitations under the License.
164b22b933Srs200217  */
174b22b933Srs200217 
184b22b933Srs200217 #include <stdio.h>              // Needed for fopen() etc.
194b22b933Srs200217 #include <unistd.h>             // Needed for close()
204b22b933Srs200217 #include <string.h>             // Needed for strlen() etc.
214b22b933Srs200217 #include <errno.h>              // Needed for errno etc.
224b22b933Srs200217 #include <sys/socket.h>         // Needed for socket() etc.
234b22b933Srs200217 #include <netinet/in.h>         // Needed for sockaddr_in
24*5ffb0c9bSToomas Soome #include <syslog.h>
254b22b933Srs200217 
264b22b933Srs200217 #include "mDNSEmbeddedAPI.h"    // Defines the interface provided to the client layer above
27*5ffb0c9bSToomas Soome #include "DNSCommon.h"
284b22b933Srs200217 #include "PlatformCommon.h"
294b22b933Srs200217 
304b22b933Srs200217 #ifdef NOT_HAVE_SOCKLEN_T
314b22b933Srs200217 typedef unsigned int socklen_t;
324b22b933Srs200217 #endif
334b22b933Srs200217 
34*5ffb0c9bSToomas Soome // Bind a UDP socket to find the source address to a destination
35*5ffb0c9bSToomas Soome mDNSexport void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst)
364b22b933Srs200217 {
37*5ffb0c9bSToomas Soome     union { struct sockaddr s; struct sockaddr_in a4; struct sockaddr_in6 a6; } addr;
384b22b933Srs200217     socklen_t len = sizeof(addr);
39*5ffb0c9bSToomas Soome     socklen_t inner_len = 0;
404b22b933Srs200217     int sock = socket(AF_INET, SOCK_DGRAM, 0);
41*5ffb0c9bSToomas Soome     src->type = mDNSAddrType_None;
424b22b933Srs200217     if (sock == -1) return;
43*5ffb0c9bSToomas Soome     if (dst->type == mDNSAddrType_IPv4)
44*5ffb0c9bSToomas Soome     {
45*5ffb0c9bSToomas Soome         inner_len = sizeof(addr.a4);
46*5ffb0c9bSToomas Soome         #ifndef NOT_HAVE_SA_LEN
47*5ffb0c9bSToomas Soome         addr.a4.sin_len         = inner_len;
48*5ffb0c9bSToomas Soome         #endif
49*5ffb0c9bSToomas Soome         addr.a4.sin_family      = AF_INET;
50*5ffb0c9bSToomas Soome         addr.a4.sin_port        = 1;    // Not important, any port will do
51*5ffb0c9bSToomas Soome         addr.a4.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
52*5ffb0c9bSToomas Soome     }
53*5ffb0c9bSToomas Soome     else if (dst->type == mDNSAddrType_IPv6)
54*5ffb0c9bSToomas Soome     {
55*5ffb0c9bSToomas Soome         inner_len = sizeof(addr.a6);
56*5ffb0c9bSToomas Soome         #ifndef NOT_HAVE_SA_LEN
57*5ffb0c9bSToomas Soome         addr.a6.sin6_len      = inner_len;
58*5ffb0c9bSToomas Soome         #endif
59*5ffb0c9bSToomas Soome         addr.a6.sin6_family   = AF_INET6;
60*5ffb0c9bSToomas Soome         addr.a6.sin6_flowinfo = 0;
61*5ffb0c9bSToomas Soome         addr.a6.sin6_port     = 1;  // Not important, any port will do
62*5ffb0c9bSToomas Soome         addr.a6.sin6_addr     = *(struct in6_addr*)&dst->ip.v6;
63*5ffb0c9bSToomas Soome         addr.a6.sin6_scope_id = 0;
64*5ffb0c9bSToomas Soome     }
65*5ffb0c9bSToomas Soome     else return;
66*5ffb0c9bSToomas Soome 
67*5ffb0c9bSToomas Soome     if ((connect(sock, &addr.s, inner_len)) < 0)
68*5ffb0c9bSToomas Soome     { if (errno != ENETUNREACH) LogMsg("mDNSPlatformSourceAddrForDest: connect %#a failed errno %d (%s)", dst, errno, strerror(errno)); goto exit; }
69*5ffb0c9bSToomas Soome 
70*5ffb0c9bSToomas Soome     if ((getsockname(sock, &addr.s, &len)) < 0)
71*5ffb0c9bSToomas Soome     { LogMsg("mDNSPlatformSourceAddrForDest: getsockname failed errno %d (%s)", errno, strerror(errno)); goto exit; }
72*5ffb0c9bSToomas Soome 
73*5ffb0c9bSToomas Soome     src->type = dst->type;
74*5ffb0c9bSToomas Soome     if (dst->type == mDNSAddrType_IPv4) src->ip.v4.NotAnInteger = addr.a4.sin_addr.s_addr;
75*5ffb0c9bSToomas Soome     else src->ip.v6 = *(mDNSv6Addr*)&addr.a6.sin6_addr;
76*5ffb0c9bSToomas Soome exit:
774b22b933Srs200217     close(sock);
784b22b933Srs200217 }
794b22b933Srs200217 
804b22b933Srs200217 // dst must be at least MAX_ESCAPED_DOMAIN_NAME bytes, and option must be less than 32 bytes in length
814b22b933Srs200217 mDNSlocal mDNSBool GetConfigOption(char *dst, const char *option, FILE *f)
824b22b933Srs200217 {
834b22b933Srs200217     char buf[32+1+MAX_ESCAPED_DOMAIN_NAME]; // Option name, one space, option value
844b22b933Srs200217     unsigned int len = strlen(option);
854b22b933Srs200217     if (len + 1 + MAX_ESCAPED_DOMAIN_NAME > sizeof(buf)-1) { LogMsg("GetConfigOption: option %s too long", option); return mDNSfalse; }
864b22b933Srs200217     fseek(f, 0, SEEK_SET);  // set position to beginning of stream
874b22b933Srs200217     while (fgets(buf, sizeof(buf), f))      // Read at most sizeof(buf)-1 bytes from file, and append '\0' C-string terminator
884b22b933Srs200217     {
894b22b933Srs200217         if (!strncmp(buf, option, len))
904b22b933Srs200217         {
914b22b933Srs200217             strncpy(dst, buf + len + 1, MAX_ESCAPED_DOMAIN_NAME-1);
924b22b933Srs200217             if (dst[MAX_ESCAPED_DOMAIN_NAME-1]) dst[MAX_ESCAPED_DOMAIN_NAME-1] = '\0';
934b22b933Srs200217             len = strlen(dst);
944b22b933Srs200217             if (len && dst[len-1] == '\n') dst[len-1] = '\0';  // chop newline
954b22b933Srs200217             return mDNStrue;
964b22b933Srs200217         }
974b22b933Srs200217     }
984b22b933Srs200217     debugf("Option %s not set", option);
994b22b933Srs200217     return mDNSfalse;
1004b22b933Srs200217 }
1014b22b933Srs200217 
1024b22b933Srs200217 mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled)
1034b22b933Srs200217 {
104*5ffb0c9bSToomas Soome     char buf[MAX_ESCAPED_DOMAIN_NAME] = "";
1054b22b933Srs200217     mStatus err;
1064b22b933Srs200217     FILE *f = fopen(filename, "r");
1074b22b933Srs200217 
1084b22b933Srs200217     if (hostname) hostname->c[0] = 0;
1094b22b933Srs200217     if (domain) domain->c[0] = 0;
1104b22b933Srs200217     if (DomainDiscoveryDisabled) *DomainDiscoveryDisabled = mDNSfalse;
1114b22b933Srs200217 
1124b22b933Srs200217     if (f)
1134b22b933Srs200217     {
1144b22b933Srs200217         if (DomainDiscoveryDisabled && GetConfigOption(buf, "DomainDiscoveryDisabled", f) && !strcasecmp(buf, "true")) *DomainDiscoveryDisabled = mDNStrue;
1154b22b933Srs200217         if (hostname && GetConfigOption(buf, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, buf)) goto badf;
1164b22b933Srs200217         if (domain && GetConfigOption(buf, "zone", f) && !MakeDomainNameFromDNSNameString(domain, buf)) goto badf;
117*5ffb0c9bSToomas Soome         buf[0] = 0;
118*5ffb0c9bSToomas Soome         GetConfigOption(buf, "secret-64", f);  // failure means no authentication
1194b22b933Srs200217         fclose(f);
1204b22b933Srs200217         f = NULL;
1214b22b933Srs200217     }
1224b22b933Srs200217     else
1234b22b933Srs200217     {
1244b22b933Srs200217         if (errno != ENOENT) LogMsg("ERROR: Config file exists, but cannot be opened.");
1254b22b933Srs200217         return;
1264b22b933Srs200217     }
1274b22b933Srs200217 
128*5ffb0c9bSToomas Soome     if (domain && domain->c[0] && buf[0])
1294b22b933Srs200217     {
130*5ffb0c9bSToomas Soome         DomainAuthInfo *info = (DomainAuthInfo*)mDNSPlatformMemAllocate(sizeof(*info));
1314b22b933Srs200217         // for now we assume keyname = service reg domain and we use same key for service and hostname registration
132*5ffb0c9bSToomas Soome         err = mDNS_SetSecretForDomain(m, info, domain, domain, buf, NULL, 0, mDNSfalse);
133*5ffb0c9bSToomas Soome         if (err) LogMsg("ERROR: mDNS_SetSecretForDomain returned %d for domain %##s", err, domain->c);
1344b22b933Srs200217     }
1354b22b933Srs200217 
1364b22b933Srs200217     return;
1374b22b933Srs200217 
1384b22b933Srs200217 badf:
1394b22b933Srs200217     LogMsg("ERROR: malformatted config file");
1404b22b933Srs200217     if (f) fclose(f);
1414b22b933Srs200217 }
142*5ffb0c9bSToomas Soome 
143*5ffb0c9bSToomas Soome #if MDNS_DEBUGMSGS
144*5ffb0c9bSToomas Soome mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
145*5ffb0c9bSToomas Soome {
146*5ffb0c9bSToomas Soome     fprintf(stderr,"%s\n", msg);
147*5ffb0c9bSToomas Soome     fflush(stderr);
148*5ffb0c9bSToomas Soome }
149*5ffb0c9bSToomas Soome #endif
150*5ffb0c9bSToomas Soome 
151*5ffb0c9bSToomas Soome mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, mDNSLogLevel_t loglevel)
152*5ffb0c9bSToomas Soome {
153*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder && LogTimeStamps
154*5ffb0c9bSToomas Soome     extern mDNS mDNSStorage;
155*5ffb0c9bSToomas Soome     extern mDNSu32 mDNSPlatformClockDivisor;
156*5ffb0c9bSToomas Soome     mDNSs32 t = mDNSStorage.timenow ? mDNSStorage.timenow : mDNSPlatformClockDivisor ? mDNS_TimeNow_NoLock(&mDNSStorage) : 0;
157*5ffb0c9bSToomas Soome     int ms = ((t < 0) ? -t : t) % 1000;
158*5ffb0c9bSToomas Soome #endif
159*5ffb0c9bSToomas Soome 
160*5ffb0c9bSToomas Soome     if (mDNS_DebugMode) // In debug mode we write to stderr
161*5ffb0c9bSToomas Soome     {
162*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder && LogTimeStamps
163*5ffb0c9bSToomas Soome         if (ident && ident[0] && mDNSPlatformClockDivisor)
164*5ffb0c9bSToomas Soome             fprintf(stderr,"%8d.%03d: %s\n", (int)(t/1000), ms, buffer);
165*5ffb0c9bSToomas Soome         else
166*5ffb0c9bSToomas Soome #endif
167*5ffb0c9bSToomas Soome         fprintf(stderr,"%s\n", buffer);
168*5ffb0c9bSToomas Soome         fflush(stderr);
169*5ffb0c9bSToomas Soome     }
170*5ffb0c9bSToomas Soome     else                // else, in production mode, we write to syslog
171*5ffb0c9bSToomas Soome     {
172*5ffb0c9bSToomas Soome         static int log_inited = 0;
173*5ffb0c9bSToomas Soome 
174*5ffb0c9bSToomas Soome         int syslog_level = LOG_ERR;
175*5ffb0c9bSToomas Soome         switch (loglevel)
176*5ffb0c9bSToomas Soome         {
177*5ffb0c9bSToomas Soome         case MDNS_LOG_MSG:       syslog_level = LOG_ERR;     break;
178*5ffb0c9bSToomas Soome         case MDNS_LOG_OPERATION: syslog_level = LOG_WARNING; break;
179*5ffb0c9bSToomas Soome         case MDNS_LOG_SPS:       syslog_level = LOG_NOTICE;  break;
180*5ffb0c9bSToomas Soome         case MDNS_LOG_INFO:      syslog_level = LOG_INFO;    break;
181*5ffb0c9bSToomas Soome         case MDNS_LOG_DEBUG:     syslog_level = LOG_DEBUG;   break;
182*5ffb0c9bSToomas Soome         default:
183*5ffb0c9bSToomas Soome             fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel);
184*5ffb0c9bSToomas Soome             fflush(stderr);
185*5ffb0c9bSToomas Soome         }
186*5ffb0c9bSToomas Soome 
187*5ffb0c9bSToomas Soome         if (!log_inited) { openlog(ident, LOG_CONS, LOG_DAEMON); log_inited++; }
188*5ffb0c9bSToomas Soome 
189*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder && LogTimeStamps
190*5ffb0c9bSToomas Soome         if (ident && ident[0] && mDNSPlatformClockDivisor)
191*5ffb0c9bSToomas Soome             syslog(syslog_level, "%8d.%03d: %s", (int)(t/1000), ms, buffer);
192*5ffb0c9bSToomas Soome         else
193*5ffb0c9bSToomas Soome #elif APPLE_OSX_mDNSResponder
194*5ffb0c9bSToomas Soome         mDNSPlatformLogToFile(syslog_level, buffer);
195*5ffb0c9bSToomas Soome #else
196*5ffb0c9bSToomas Soome         syslog(syslog_level, "%s", buffer);
197*5ffb0c9bSToomas Soome #endif
198*5ffb0c9bSToomas Soome     }
199*5ffb0c9bSToomas Soome }
200