/* -*- Mode: C; 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.
 */

#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 "mDNSEmbeddedAPI.h"	// Defines the interface provided to the client layer above
#include "DNSCommon.h"
#include "PlatformCommon.h"

#ifdef __ANDROID__
#include <android/log.h>
#endif

#ifdef NOT_HAVE_SOCKLEN_T
    typedef unsigned int socklen_t;
#endif

// 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)
		{ 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;
	}

mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled)
	{
	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 (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] && 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, NULL);
		if (err) LogMsg("ERROR: mDNS_SetSecretForDomain returned %d for domain %##s", err, domain->c);
		}

	return;

	badf:
	LogMsg("ERROR: malformatted config file");
	if (f) fclose(f);
	}

#if MDNS_DEBUGMSGS
mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
	{
#ifdef __ANDROID__
	__android_log_print(ANDROID_LOG_DEBUG, "mdns", "%s", msg);
#else
	fprintf(stderr,"%s\n", msg);
	fflush(stderr);
#endif
	}
#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
#endif
#ifdef __ANDROID__
		switch (loglevel)
			{
			case MDNS_LOG_DEBUG:     syslog_level = ANDROID_LOG_DEBUG;  break;
#if MDNS_DEBUGMSGS > 0
			case MDNS_LOG_OPERATION: syslog_level = ANDROID_LOG_WARN;   break;
			case MDNS_LOG_SPS:       syslog_level = ANDROID_LOG_DEBUG;  break;
			case MDNS_LOG_INFO:      syslog_level = ANDROID_LOG_INFO;   break;
			default:                 syslog_level = ANDROID_LOG_ERROR;  break;
#else
			default:		return;
#endif
			}
		__android_log_print(syslog_level, "mdns", "%s", buffer);
#else
			syslog(syslog_level, "%s", buffer);
#endif
		}
	}
