147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* -*- Mode: C; tab-width: 4 -*- 247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. 447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License"); 647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * you may not use this file except in compliance with the License. 747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * You may obtain a copy of the License at 847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * http://www.apache.org/licenses/LICENSE-2.0 1047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 1147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Unless required by applicable law or agreed to in writing, software 1247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS, 1347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * See the License for the specific language governing permissions and 1547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * limitations under the License. 1647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */ 1747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 1847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if __APPLE__ 1947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated” 2047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// error, which prevents compilation because we build with "-Werror". 2147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Since this is supposed to be portable cross-platform code, we don't care that daemon is 2247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message. 2347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou 2447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 2547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 2647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <signal.h> 2747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <pthread.h> 2847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdlib.h> 2947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <unistd.h> 3047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/types.h> 3147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/socket.h> 3247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netinet/in.h> 3347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <arpa/inet.h> 3447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdio.h> 3547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <syslog.h> 3647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <string.h> 3747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/time.h> 3847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/resource.h> 3947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <time.h> 4047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <errno.h> 4147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 4247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if __APPLE__ 4347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#undef daemon 4447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltextern int daemon(int, int); 4547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 4647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 4747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Solaris doesn't have daemon(), so we define it here 4847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef NOT_HAVE_DAEMON 4947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "../mDNSPosix/mDNSUNP.h" // For daemon() 5047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif // NOT_HAVE_DAEMON 5147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 5247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "dnsextd.h" 5347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "../mDNSShared/uds_daemon.h" 5447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "../mDNSShared/dnssd_ipc.h" 5547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "../mDNSCore/uDNS.h" 5647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "../mDNSShared/DebugServices.h" 5747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 5847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Compatibility workaround 5947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef AF_LOCAL 6047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define AF_LOCAL AF_UNIX 6147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 6247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 6347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 6447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Constants 6547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 6647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport const char ProgramName[] = "dnsextd"; 6747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 6847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define LOOPBACK "127.0.0.1" 6947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if !defined(LISTENQ) 7047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt# define LISTENQ 128 // tcp connection backlog 7147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 7247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define RECV_BUFLEN 9000 7347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define LEASETABLE_INIT_NBUCKETS 256 // initial hashtable size (doubles as table fills) 7447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define EXPIRATION_INTERVAL 300 // check for expired records every 5 minutes 7547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define SRV_TTL 7200 // TTL For _dns-update SRV records 7647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define CONFIG_FILE "/etc/dnsextd.conf" 7747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define TCP_SOCKET_FLAGS kTCPSocketFlags_UseTLS 7847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 7947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// LLQ Lease bounds (seconds) 8047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define LLQ_MIN_LEASE (15 * 60) 8147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define LLQ_MAX_LEASE (120 * 60) 8247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define LLQ_LEASE_FUDGE 60 8347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 8447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// LLQ SOA poll interval (microseconds) 8547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define LLQ_MONITOR_ERR_INTERVAL (60 * 1000000) 8647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define LLQ_MONITOR_INTERVAL 250000 8747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef SIGINFO 8847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define INFO_SIGNAL SIGINFO 8947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#else 9047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define INFO_SIGNAL SIGUSR1 9147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 9247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 9347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define SAME_INADDR(x,y) (*((mDNSu32 *)&x) == *((mDNSu32 *)&y)) 9447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 9547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 9647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Data Structures 9747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Structs/fields that must be locked for thread safety are explicitly commented 9847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 9947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 10047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// args passed to UDP request handler thread as void* 10147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 10247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct 10347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 10447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg pkt; 10547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct sockaddr_in cliaddr; 10647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo *d; 10747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int sd; 10847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } UDPContext; 10947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 11047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// args passed to TCP request handler thread as void* 11147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct 11247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 11347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg pkt; 11447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct sockaddr_in cliaddr; 11547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPSocket *sock; // socket connected to client 11647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo *d; 11747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } TCPContext; 11847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 11947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// args passed to UpdateAnswerList thread as void* 12047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct 12147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 12247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo *d; 12347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerListElem *a; 12447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } UpdateAnswerListArgs; 12547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 12647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 12747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Global Variables 12847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 12947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 13047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// booleans to determine runtime output 13147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// read-only after initialization (no mutex protection) 13247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool foreground = 0; 13347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool verbose = 0; 13447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 13547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// globals set via signal handler (accessed exclusively by main select loop and signal handler) 13647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool terminate = 0; 13747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool dumptable = 0; 13847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool hangup = 0; 13947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 14047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// global for config file location 14147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char * cfgfile = NULL; 14247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 14347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 14447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Logging Routines 14547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Log messages are delivered to syslog unless -f option specified 14647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 14747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 14847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// common message logging subroutine 14947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void PrintLog(const char *buffer) 15047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 15147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (foreground) 15247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 15347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr,"%s\n", buffer); 15447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fflush(stderr); 15547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 15647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 15747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 15847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt openlog("dnsextd", LOG_CONS, LOG_DAEMON); 15947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt syslog(LOG_ERR, "%s", buffer); 16047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt closelog(); 16147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 16247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 16347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 16447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Verbose Logging (conditional on -v option) 16547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void VLog(const char *format, ...) 16647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 16747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer[512]; 16847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt va_list ptr; 16947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 17047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!verbose) return; 17147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt va_start(ptr,format); 17247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; 17347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt va_end(ptr); 17447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintLog(buffer); 17547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 17647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 17747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Unconditional Logging 17847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void Log(const char *format, ...) 17947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 18047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer[512]; 18147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt va_list ptr; 18247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 18347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt va_start(ptr,format); 18447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; 18547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt va_end(ptr); 18647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintLog(buffer); 18747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 18847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 18947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Error Logging 19047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// prints message "dnsextd <function>: <operation> - <error message>" 19147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// must be compiled w/ -D_REENTRANT for thread-safe errno usage 19247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void LogErr(const char *fn, const char *operation) 19347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 19447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buf[512], errbuf[256]; 19547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strerror_r(errno, errbuf, sizeof(errbuf)); 19647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt snprintf(buf, sizeof(buf), "%s: %s - %s", fn, operation, errbuf); 19747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintLog(buf); 19847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 19947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 20047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 20147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Networking Utility Routines 20247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 20347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 20447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Convert DNS Message Header from Network to Host byte order 20547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void HdrNToH(PktMsg *pkt) 20647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 20747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Read the integer parts which are in IETF byte-order (MSB first, LSB second) 20847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions; 20947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->msg.h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]); 21047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->msg.h.numAnswers = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]); 21147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->msg.h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]); 21247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->msg.h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]); 21347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 21447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 21547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Convert DNS Message Header from Host to Network byte order 21647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void HdrHToN(PktMsg *pkt) 21747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 21847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 numQuestions = pkt->msg.h.numQuestions; 21947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 numAnswers = pkt->msg.h.numAnswers; 22047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 numAuthorities = pkt->msg.h.numAuthorities; 22147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 numAdditionals = pkt->msg.h.numAdditionals; 22247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions; 22347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 22447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Put all the integer values in IETF byte-order (MSB first, LSB second) 22547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr++ = (mDNSu8)(numQuestions >> 8); 22647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr++ = (mDNSu8)(numQuestions & 0xFF); 22747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr++ = (mDNSu8)(numAnswers >> 8); 22847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr++ = (mDNSu8)(numAnswers & 0xFF); 22947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr++ = (mDNSu8)(numAuthorities >> 8); 23047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr++ = (mDNSu8)(numAuthorities & 0xFF); 23147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr++ = (mDNSu8)(numAdditionals >> 8); 23247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr++ = (mDNSu8)(numAdditionals & 0xFF); 23347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 23447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 23547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 23647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Add socket to event loop 23747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 23847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mStatus AddSourceToEventLoop( DaemonInfo * self, TCPSocket *sock, EventCallback callback, void *context ) 23947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 24047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt EventSource * newSource; 24147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err = mStatus_NoError; 24247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 24347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( self->eventSources.LinkOffset == 0 ) 24447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 24547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitLinkedList( &self->eventSources, offsetof( EventSource, next)); 24647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 24747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 24847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt newSource = ( EventSource*) malloc( sizeof *newSource ); 24947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( newSource == NULL ) 25047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 25147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = mStatus_NoMemoryErr; 25247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto exit; 25347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 25447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 25547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt newSource->callback = callback; 25647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt newSource->context = context; 25747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt newSource->sock = sock; 25847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt newSource->fd = mDNSPlatformTCPGetFD( sock ); 25947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AddToTail( &self->eventSources, newSource ); 26147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 26347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 26547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 26647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Remove socket from event loop 26947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 27047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mStatus RemoveSourceFromEventLoop( DaemonInfo * self, TCPSocket *sock ) 27147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 27247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt EventSource * source; 27347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err; 27447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 27547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( source = ( EventSource* ) self->eventSources.Head; source; source = source->next ) 27647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 27747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( source->sock == sock ) 27847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 27947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RemoveFromList( &self->eventSources, source ); 28047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 28147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free( source ); 28247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = mStatus_NoError; 28347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto exit; 28447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 28547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 28647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 28747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = mStatus_NoSuchNameErr; 28847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 28947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 29047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 29147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 29247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 29347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 29447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// create a socket connected to nameserver 29547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// caller terminates connection via close() 29647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal TCPSocket *ConnectToServer(DaemonInfo *d) 29747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 29847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int ntries = 0, retry = 0; 29947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 30047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (1) 30147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 30247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSIPPort port = zeroIPPort; 30347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int fd; 30447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 30547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPSocket *sock = mDNSPlatformTCPSocket( NULL, 0, &port ); 30647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( !sock ) { LogErr("ConnectToServer", "socket"); return NULL; } 30747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd = mDNSPlatformTCPGetFD( sock ); 30847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!connect( fd, (struct sockaddr *)&d->ns_addr, sizeof(d->ns_addr))) return sock; 30947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformTCPCloseConnection( sock ); 31047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (++ntries < 10) 31147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 31247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr("ConnectToServer", "connect"); 31347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("ConnectToServer - retrying connection"); 31447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!retry) retry = 500000 + random() % 500000; 31547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt usleep(retry); 31647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt retry *= 2; 31747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 31847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else { Log("ConnectToServer - %d failed attempts. Aborting.", ntries); return NULL; } 31947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 32047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 32147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 32247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// send an entire block of data over a connected socket 32347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int MySend(TCPSocket *sock, const void *msg, int len) 32447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 32547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int selectval, n, nsent = 0; 32647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd_set wset; 32747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short 32847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 32947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (nsent < len) 33047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 33147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int fd; 33247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 33347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_ZERO(&wset); 33447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 33547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd = mDNSPlatformTCPGetFD( sock ); 33647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 33747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET( fd, &wset ); 33847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt selectval = select( fd+1, NULL, &wset, NULL, &timeout); 33947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (selectval < 0) { LogErr("MySend", "select"); return -1; } 34047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!selectval || !FD_ISSET(fd, &wset)) { Log("MySend - timeout"); return -1; } 34147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 34247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt n = mDNSPlatformWriteTCP( sock, ( char* ) msg + nsent, len - nsent); 34347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 34447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (n < 0) { LogErr("MySend", "send"); return -1; } 34547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt nsent += n; 34647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 34747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return 0; 34847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 34947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 35047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Transmit a DNS message, prefixed by its length, over TCP, blocking if necessary 35147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int SendPacket(TCPSocket *sock, PktMsg *pkt) 35247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 35347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // send the lenth, in network byte order 35447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 len = htons((mDNSu16)pkt->len); 35547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (MySend(sock, &len, sizeof(len)) < 0) return -1; 35647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 35747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // send the message 35847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("SendPacket Q:%d A:%d A:%d A:%d ", 35947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ntohs(pkt->msg.h.numQuestions), 36047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ntohs(pkt->msg.h.numAnswers), 36147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ntohs(pkt->msg.h.numAuthorities), 36247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ntohs(pkt->msg.h.numAdditionals)); 36347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return MySend(sock, &pkt->msg, pkt->len); 36447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 36547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 36647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Receive len bytes, waiting until we have all of them. 36747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Returns number of bytes read (which should always be the number asked for). 36847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int my_recv(TCPSocket *sock, void *const buf, const int len, mDNSBool * closed) 36947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 37047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; 37147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // use an explicit while() loop instead. 37247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Also, don't try to do '+=' arithmetic on the original "void *" pointer -- 37347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // arithmetic on "void *" pointers is compiler-dependent. 37447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 37547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd_set rset; 37647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short 37747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int selectval, remaining = len; 37847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char *ptr = (char *)buf; 37947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ssize_t num_read; 38047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 38147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (remaining) 38247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 38347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int fd; 38447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 38547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd = mDNSPlatformTCPGetFD( sock ); 38647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 38747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_ZERO(&rset); 38847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET(fd, &rset); 38947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt selectval = select(fd+1, &rset, NULL, NULL, &timeout); 39047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (selectval < 0) { LogErr("my_recv", "select"); return -1; } 39147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!selectval || !FD_ISSET(fd, &rset)) 39247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 39347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("my_recv - timeout"); 39447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return -1; 39547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 39647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 39747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt num_read = mDNSPlatformReadTCP( sock, ptr, remaining, closed ); 39847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 39947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (((num_read == 0) && *closed) || (num_read < 0) || (num_read > remaining)) return -1; 40047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (num_read == 0) return 0; 40147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr += num_read; 40247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt remaining -= num_read; 40347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 40447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(len); 40547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 40647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 40747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Return a DNS Message read off of a TCP socket, or NULL on failure 40847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// If storage is non-null, result is placed in that buffer. Otherwise, 40947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// returned value is allocated with Malloc, and contains sufficient extra 41047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// storage for a Lease OPT RR 41147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 41247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal PktMsg* 41347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltRecvPacket 41447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 41547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPSocket * sock, 41647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * storage, 41747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool * closed 41847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 41947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 42047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int nread; 42147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int allocsize; 42247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 msglen = 0; 42347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * pkt = NULL; 42447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt unsigned int srclen; 42547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int fd; 42647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err = 0; 42747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 42847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd = mDNSPlatformTCPGetFD( sock ); 42947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 43047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt nread = my_recv( sock, &msglen, sizeof( msglen ), closed ); 43147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 43247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( nread != -1, exit, err = mStatus_UnknownErr ); 43347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( nread > 0, exit, err = mStatus_NoError ); 43447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 43547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt msglen = ntohs( msglen ); 43647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( nread == sizeof( msglen ), exit, err = mStatus_UnknownErr; Log( "Could not read length field of message") ); 43747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 43847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( storage ) 43947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 44047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( msglen <= sizeof( storage->msg ), exit, err = mStatus_UnknownErr; Log( "RecvPacket: provided buffer too small." ) ); 44147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt = storage; 44247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 44347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 44447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 44547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // buffer extra space to add an OPT RR 44647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 44747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( msglen > sizeof(DNSMessage)) 44847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 44947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt allocsize = sizeof(PktMsg) - sizeof(DNSMessage) + msglen; 45047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 45147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 45247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 45347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt allocsize = sizeof(PktMsg); 45447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 45547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 45647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt = malloc(allocsize); 45747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( pkt, exit, err = mStatus_NoMemoryErr; LogErr( "RecvPacket", "malloc" ) ); 45847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero( pkt, sizeof( *pkt ) ); 45947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 46047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 46147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->len = msglen; 46247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt srclen = sizeof(pkt->src); 46347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 46447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( getpeername( fd, ( struct sockaddr* ) &pkt->src, &srclen ) || ( srclen != sizeof( pkt->src ) ) ) 46547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 46647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr("RecvPacket", "getpeername"); 46747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(&pkt->src, sizeof(pkt->src)); 46847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 46947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 47047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt nread = my_recv(sock, &pkt->msg, msglen, closed ); 47147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( nread >= 0, exit, err = mStatus_UnknownErr ; LogErr( "RecvPacket", "recv" ) ); 47247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( nread == msglen, exit, err = mStatus_UnknownErr ; Log( "Could not read entire message" ) ); 47347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( pkt->len >= sizeof( DNSMessageHeader ), exit, err = mStatus_UnknownErr ; Log( "RecvPacket: Message too short (%d bytes)", pkt->len ) ); 47447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 47547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 47647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 47747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( err && pkt ) 47847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 47947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( pkt != storage ) 48047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 48147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(pkt); 48247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 48347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 48447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt = NULL; 48547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 48647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 48747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return pkt; 48847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 48947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 49047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 49147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal DNSZone* 49247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltFindZone 49347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 49447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo * self, 49547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainname * name 49647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 49747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 49847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSZone * zone; 49947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 50047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( zone = self->zones; zone; zone = zone->next ) 50147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 50247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( SameDomainName( &zone->name, name ) ) 50347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 50447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 50547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 50647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 50747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 50847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return zone; 50947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 51047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 51147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 51247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool 51347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltZoneHandlesName 51447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 51547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const domainname * zname, 51647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const domainname * dname 51747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 51847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 51947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 i = DomainNameLength( zname ); 52047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 j = DomainNameLength( dname ); 52147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 52247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( ( i == ( MAX_DOMAIN_NAME + 1 ) ) || ( j == ( MAX_DOMAIN_NAME + 1 ) ) || ( i > j ) || ( memcmp( zname->c, dname->c + ( j - i ), i ) != 0 ) ) 52347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 52447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return mDNSfalse; 52547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 52647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 52747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return mDNStrue; 52847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 52947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 53047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 53147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool IsQuery( PktMsg * pkt ) 53247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 53347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery ); 53447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 53547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 53647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 53747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool IsUpdate( PktMsg * pkt ) 53847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 53947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_OP_Update ); 54047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 54147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 54247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 54347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool IsNotify(PktMsg *pkt) 54447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 54547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == ( mDNSu8) ( kDNSFlag0_OP_Notify ); 54647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 54747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 54847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 54947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool IsLLQRequest(PktMsg *pkt) 55047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 55147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 *ptr = NULL, *end = (mDNSu8 *)&pkt->msg + pkt->len; 55247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LargeCacheRecord lcr; 55347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i; 55447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool result = mDNSfalse; 55547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 55647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrNToH(pkt); 55747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((mDNSu8)(pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (mDNSu8)(kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery)) goto end; 55847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 55947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!pkt->msg.h.numAdditionals) goto end; 56047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = LocateAdditionals(&pkt->msg, end); 56147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) goto end; 56247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 56347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // find last Additional info. 56447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < pkt->msg.h.numAdditionals; i++) 56547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 56647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); 56747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) { Log("Unable to read additional record"); goto end; } 56847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 56947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 57047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( lcr.r.resrec.rrtype == kDNSType_OPT && lcr.r.resrec.rdlength >= DNSOpt_LLQData_Space && lcr.r.resrec.rdata->u.opt[0].opt == kDNSOpt_LLQ ) 57147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 57247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = mDNStrue; 57347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 57447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 57547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end: 57647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(pkt); 57747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return result; 57847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 57947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 58047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// !!!KRS implement properly 58147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool IsLLQAck(PktMsg *pkt) 58247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 58347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery ) && 58447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->msg.h.numQuestions && !pkt->msg.h.numAnswers && !pkt->msg.h.numAuthorities) return mDNStrue; 58547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return mDNSfalse; 58647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 58747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 58847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 58947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool 59047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltIsPublicSRV 59147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 59247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo * self, 59347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSQuestion * q 59447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 59547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 59647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNameListElem * elem; 59747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool ret = mDNSfalse; 59847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i = ( int ) DomainNameLength( &q->qname ) - 1; 59947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 60047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( elem = self->public_names; elem; elem = elem->next ) 60147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 60247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int j = ( int ) DomainNameLength( &elem->name ) - 1; 60347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 60447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( i > j ) 60547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 60647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( ; i >= 0; i--, j-- ) 60747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 60847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( q->qname.c[ i ] != elem->name.c[ j ] ) 60947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 61047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ret = mDNStrue; 61147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto exit; 61247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 61347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 61447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 61547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 61647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 61747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 61847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 61947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return ret; 62047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 62147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 62247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 62347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void 62447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltSetZone 62547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 62647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo * self, 62747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * pkt 62847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 62947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 63047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainname zname; 63147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 QR_OP; 63247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 * ptr = pkt->msg.data; 63347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool exception = mDNSfalse; 63447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 63547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Initialize 63647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 63747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->zone = NULL; 63847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->isZonePublic = mDNStrue; 63947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt zname.c[0] = '\0'; 64047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 64147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Figure out what type of packet this is 64247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 64347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt QR_OP = ( mDNSu8 ) ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ); 64447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 64547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( IsQuery( pkt ) ) 64647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 64747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSQuestion question; 64847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 64947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // It's a query 65047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 65147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = getQuestion( &pkt->msg, ptr, ( ( mDNSu8* ) &pkt->msg ) + pkt->len, NULL, &question ); 65247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 65347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AppendDomainName( &zname, &question.qname ); 65447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 65547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exception = ( ( question.qtype == kDNSType_SOA ) || ( question.qtype == kDNSType_NS ) || ( ( question.qtype == kDNSType_SRV ) && IsPublicSRV( self, &question ) ) ); 65647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 65747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if ( IsUpdate( pkt ) ) 65847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 65947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSQuestion question; 66047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 66147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // It's an update. The format of the zone section is the same as the format for the question section 66247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // according to RFC 2136, so we'll just treat this as a question so we can get at the zone. 66347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 66447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = getQuestion( &pkt->msg, ptr, ( ( mDNSu8* ) &pkt->msg ) + pkt->len, NULL, &question ); 66547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 66647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AppendDomainName( &zname, &question.qname ); 66747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 66847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exception = mDNSfalse; 66947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 67047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 67147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( zname.c[0] != '\0' ) 67247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 67347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Find the right zone 67447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 67547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( pkt->zone = self->zones; pkt->zone; pkt->zone = pkt->zone->next ) 67647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 67747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( ZoneHandlesName( &pkt->zone->name, &zname ) ) 67847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 67947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog( "found correct zone %##s for query", pkt->zone->name.c ); 68047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 68147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->isZonePublic = ( ( pkt->zone->type == kDNSZonePublic ) || exception ); 68247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 68347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog( "zone %##s is %s", pkt->zone->name.c, ( pkt->isZonePublic ) ? "public" : "private" ); 68447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 68547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 68647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 68747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 68847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 68947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 69047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 69147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 69247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int 69347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltUDPServerTransaction(const DaemonInfo *d, const PktMsg *request, PktMsg *reply, mDNSBool *trunc) 69447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 69547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd_set rset; 69647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short 69747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int sd; 69847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int res; 69947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err = mStatus_NoError; 70047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 70147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Initialize 70247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 70347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *trunc = mDNSfalse; 70447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 70547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Create a socket 70647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 70747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt sd = socket( AF_INET, SOCK_DGRAM, 0 ); 70847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( sd >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "socket" ) ); 70947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 71047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Send the packet to the nameserver 71147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 71247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("UDPServerTransaction Q:%d A:%d A:%d A:%d ", 71347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ntohs(request->msg.h.numQuestions), 71447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ntohs(request->msg.h.numAnswers), 71547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ntohs(request->msg.h.numAuthorities), 71647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ntohs(request->msg.h.numAdditionals)); 71747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt res = sendto( sd, (char *)&request->msg, request->len, 0, ( struct sockaddr* ) &d->ns_addr, sizeof( d->ns_addr ) ); 71847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( res == (int) request->len, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "sendto" ) ); 71947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 72047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Wait for reply 72147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 72247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_ZERO( &rset ); 72347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET( sd, &rset ); 72447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt res = select( sd + 1, &rset, NULL, NULL, &timeout ); 72547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( res >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "select" ) ); 72647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ( res > 0 ) && FD_ISSET( sd, &rset ), exit, err = mStatus_UnknownErr; Log( "UDPServerTransaction - timeout" ) ); 72747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 72847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Receive reply 72947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 73047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply->len = recvfrom( sd, &reply->msg, sizeof(reply->msg), 0, NULL, NULL ); 73147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ( ( int ) reply->len ) >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "recvfrom" ) ); 73247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( reply->len >= sizeof( DNSMessageHeader ), exit, err = mStatus_UnknownErr; Log( "UDPServerTransaction - Message too short (%d bytes)", reply->len ) ); 73347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 73447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Check for truncation bit 73547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 73647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( reply->msg.h.flags.b[0] & kDNSFlag0_TC ) 73747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 73847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *trunc = mDNStrue; 73947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 74047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 74147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 74247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 74347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( sd >= 0 ) 74447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 74547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt close( sd ); 74647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 74747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 74847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 74947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 75047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 75147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 75247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Dynamic Update Utility Routines 75347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 75447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 75547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// check if a request and server response complete a successful dynamic update 75647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool SuccessfulUpdateTransaction(PktMsg *request, PktMsg *reply) 75747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 75847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buf[32]; 75947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char *vlogmsg = NULL; 76047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 76147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // check messages 76247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!request || !reply) { vlogmsg = "NULL message"; goto failure; } 76347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (request->len < sizeof(DNSMessageHeader) || reply->len < sizeof(DNSMessageHeader)) { vlogmsg = "Malformatted message"; goto failure; } 76447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 76547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // check request operation 76647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask)) 76747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { vlogmsg = "Request opcode not an update"; goto failure; } 76847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 76947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // check result 77047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask)) { vlogmsg = "Reply contains non-zero rcode"; goto failure; } 77147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_OP_Update | kDNSFlag0_QR_Response)) 77247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { vlogmsg = "Reply opcode not an update response"; goto failure; } 77347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 77447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Successful update from %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32)); 77547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return mDNStrue; 77647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 77747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt failure: 77847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Request %s: %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32), vlogmsg); 77947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return mDNSfalse; 78047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 78147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 78247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Allocate an appropriately sized CacheRecord and copy data from original. 78347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Name pointer in CacheRecord object is set to point to the name specified 78447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 78547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal CacheRecord *CopyCacheRecord(const CacheRecord *orig, domainname *name) 78647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 78747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheRecord *cr; 78847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt size_t size = sizeof(*cr); 78947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (orig->resrec.rdlength > InlineCacheRDSize) size += orig->resrec.rdlength - InlineCacheRDSize; 79047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr = malloc(size); 79147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!cr) { LogErr("CopyCacheRecord", "malloc"); return NULL; } 79247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt memcpy(cr, orig, size); 79347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr->resrec.rdata = (RData*)&cr->smallrdatastorage; 79447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr->resrec.name = name; 79547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 79647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return cr; 79747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 79847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 79947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 80047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 80147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Lease Hashtable Utility Routines 80247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 80347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 80447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// double hash table size 80547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// caller must lock table prior to invocation 80647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void RehashTable(DaemonInfo *d) 80747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 80847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RRTableElem *ptr, *tmp, **new; 80947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i, bucket, newnbuckets = d->nbuckets * 2; 81047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 81147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Rehashing lease table (new size %d buckets)", newnbuckets); 81247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt new = malloc(sizeof(RRTableElem *) * newnbuckets); 81347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!new) { LogErr("RehashTable", "malloc"); return; } 81447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(new, newnbuckets * sizeof(RRTableElem *)); 81547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 81647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < d->nbuckets; i++) 81747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 81847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = d->table[i]; 81947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (ptr) 82047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 82147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt bucket = ptr->rr.resrec.namehash % newnbuckets; 82247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp = ptr; 82347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = ptr->next; 82447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp->next = new[bucket]; 82547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt new[bucket] = tmp; 82647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 82747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 82847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->nbuckets = newnbuckets; 82947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(d->table); 83047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->table = new; 83147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 83247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 83347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// print entire contents of hashtable, invoked via SIGINFO 83447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void PrintLeaseTable(DaemonInfo *d) 83547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 83647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i; 83747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RRTableElem *ptr; 83847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char rrbuf[MaxMsg], addrbuf[16]; 83947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval now; 84047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int hr, min, sec; 84147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 84247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gettimeofday(&now, NULL)) { LogErr("PrintTable", "gettimeofday"); return; } 84347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (pthread_mutex_lock(&d->tablelock)) { LogErr("PrintTable", "pthread_mutex_lock"); return; } 84447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 84547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Dumping Lease Table Contents (table contains %d resource records)", d->nelems); 84647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < d->nbuckets; i++) 84747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 84847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (ptr = d->table[i]; ptr; ptr = ptr->next) 84947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 85047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hr = ((ptr->expire - now.tv_sec) / 60) / 60; 85147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt min = ((ptr->expire - now.tv_sec) / 60) % 60; 85247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt sec = (ptr->expire - now.tv_sec) % 60; 85347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Update from %s, Expires in %d:%d:%d\n\t%s", inet_ntop(AF_INET, &ptr->cli.sin_addr, addrbuf, 16), hr, min, sec, 85447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt GetRRDisplayString_rdb(&ptr->rr.resrec, &ptr->rr.resrec.rdata->u, rrbuf)); 85547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 85647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 85747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pthread_mutex_unlock(&d->tablelock); 85847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 85947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 86047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 86147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Startup SRV Registration Routines 86247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Register _dns-update._udp/_tcp.<zone> SRV records indicating the port on which 86347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// the daemon accepts requests 86447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 86547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 86647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// delete all RRS of a given name/type 86747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSu8 *putRRSetDeletion(DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit, ResourceRecord *rr) 86847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 86947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name); 87047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr || ptr + 10 >= limit) return NULL; // out of space 87147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr[0] = (mDNSu8)(rr->rrtype >> 8); 87247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr[1] = (mDNSu8)(rr->rrtype & 0xFF); 87347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr[2] = (mDNSu8)((mDNSu16)kDNSQClass_ANY >> 8); 87447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr[3] = (mDNSu8)((mDNSu16)kDNSQClass_ANY & 0xFF); 87547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(ptr+4, sizeof(rr->rroriginalttl) + sizeof(rr->rdlength)); // zero ttl/rdata 87647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt msg->h.mDNS_numUpdates++; 87747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return ptr + 10; 87847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 87947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 88047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSu8 *PutUpdateSRV(DaemonInfo *d, DNSZone * zone, PktMsg *pkt, mDNSu8 *ptr, char *regtype, mDNSIPPort port, mDNSBool registration) 88147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 88247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AuthRecord rr; 88347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char hostname[1024], buf[MaxMsg]; 88447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *end = (mDNSu8 *)&pkt->msg + sizeof(DNSMessage); 88547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 88647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( void ) d; 88747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 88847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_SetupResourceRecord(&rr, NULL, 0, kDNSType_SRV, SRV_TTL, kDNSRecordTypeUnique, AuthRecordAny, NULL, NULL); 88947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rr.resrec.rrclass = kDNSClass_IN; 89047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rr.resrec.rdata->u.srv.priority = 0; 89147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rr.resrec.rdata->u.srv.weight = 0; 89247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rr.resrec.rdata->u.srv.port = port; 89347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gethostname(hostname, 1024) < 0 || !MakeDomainNameFromDNSNameString(&rr.resrec.rdata->u.srv.target, hostname)) 89447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rr.resrec.rdata->u.srv.target.c[0] = '\0'; 89547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 89647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainNameFromDNSNameString(&rr.namestorage, regtype); 89747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AppendDomainName(&rr.namestorage, &zone->name); 89847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("%s %s", registration ? "Registering SRV record" : "Deleting existing RRSet", 89947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt GetRRDisplayString_rdb(&rr.resrec, &rr.resrec.rdata->u, buf)); 90047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (registration) ptr = PutResourceRecord(&pkt->msg, ptr, &pkt->msg.h.mDNS_numUpdates, &rr.resrec); 90147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else ptr = putRRSetDeletion(&pkt->msg, ptr, end, &rr.resrec); 90247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return ptr; 90347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 90447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 90547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 90647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// perform dynamic update. 90747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// specify deletion by passing false for the register parameter, otherwise register the records. 90847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int UpdateSRV(DaemonInfo *d, mDNSBool registration) 90947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 91047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPSocket *sock = NULL; 91147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSZone * zone; 91247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int err = mStatus_NoError; 91347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 91447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt sock = ConnectToServer( d ); 91547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( sock, exit, err = mStatus_UnknownErr; Log( "UpdateSRV: ConnectToServer failed" ) ); 91647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 91747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( zone = d->zones; zone; zone = zone->next ) 91847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 91947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg pkt; 92047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *ptr = pkt.msg.data; 92147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage); 92247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg *reply = NULL; 92347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool closed; 92447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool ok; 92547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 92647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Initialize message 92747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitializeDNSMessage(&pkt.msg.h, zeroID, UpdateReqFlags); 92847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt.src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // address field set solely for verbose logging in subroutines 92947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt.src.sin_family = AF_INET; 93047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 93147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // format message body 93247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = putZone(&pkt.msg, ptr, end, &zone->name, mDNSOpaque16fromIntVal(kDNSClass_IN)); 93347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 93447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 93547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( zone->type == kDNSZonePrivate ) 93647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 93747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update-tls._tcp.", d->private_port, registration); 93847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 93947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-query-tls._tcp.", d->private_port, registration); 94047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 94147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq-tls._tcp.", d->private_port, registration); 94247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 94347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 94447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( !registration ) 94547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 94647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update._udp.", d->llq_port, registration); 94747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 94847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq._udp.", d->llq_port, registration); 94947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 95047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 95147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 95247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 95347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 95447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( !registration ) 95547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 95647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update-tls.", d->private_port, registration); 95747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 95847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-query-tls.", d->private_port, registration); 95947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 96047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq-tls.", d->private_port, registration); 96147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 96247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 96347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 96447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update._udp.", d->llq_port, registration); 96547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 96647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq._udp.", d->llq_port, registration); 96747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) ); 96847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 96947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 97047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(&pkt); 97147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 97247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( zone->updateKeys ) 97347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 97447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSDigest_SignMessage( &pkt.msg, &ptr, zone->updateKeys, 0 ); 97547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ptr, exit, Log("UpdateSRV: Error constructing lease expiration update" ) ); 97647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 97747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 97847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt.len = ptr - (mDNSu8 *)&pkt.msg; 97947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 98047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // send message, receive reply 98147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 98247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = SendPacket( sock, &pkt ); 98347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, Log( "UpdateSRV: SendPacket failed" ) ); 98447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 98547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = RecvPacket( sock, NULL, &closed ); 98647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( reply, exit, err = mStatus_UnknownErr; Log( "UpdateSRV: RecvPacket returned NULL" ) ); 98747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 98847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ok = SuccessfulUpdateTransaction( &pkt, reply ); 98947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 99047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( !ok ) 99147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 99247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("SRV record registration failed with rcode %d", reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask); 99347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 99447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 99547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free( reply ); 99647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 99747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 99847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 99947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 100047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( sock ) 100147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 100247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformTCPCloseConnection( sock ); 100347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 100447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 100547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 100647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 100747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 100847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// wrapper routines/macros 100947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define ClearUpdateSRV(d) UpdateSRV(d, 0) 101047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 101147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// clear any existing records prior to registration 101247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int SetUpdateSRV(DaemonInfo *d) 101347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 101447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int err; 101547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 101647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = ClearUpdateSRV(d); // clear any existing record 101747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!err) err = UpdateSRV(d, 1); 101847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 101947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 102047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 102147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 102247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Argument Parsing and Configuration 102347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 102447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 102547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void PrintUsage(void) 102647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 102747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "Usage: dnsextd [-f <config file>] [-vhd] ...\n" 102847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "Use \"dnsextd -h\" for help\n"); 102947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 103047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 103147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void PrintHelp(void) 103247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 103347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "\n\n"); 103447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintUsage(); 103547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 103647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, 103747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "dnsextd is a daemon that implements DNS extensions supporting Dynamic DNS Update Leases\n" 103847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "and Long Lived Queries, used in Wide-Area DNS Service Discovery, on behalf of name servers\n" 103947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "that do not natively support these extensions. (See dns-sd.org for more info on DNS Service\n" 104047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "Discovery, Update Leases, and Long Lived Queries.)\n\n" 104147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 104247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "dnsextd requires one argument,the zone, which is the domain for which Update Leases\n" 104347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "and Long Lived Queries are to be administered. dnsextd communicates directly with the\n" 104447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "primary master server for this zone.\n\n" 104547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 104647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "The options are as follows:\n\n" 104747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 104847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "-f Specify configuration file. The default is /etc/dnsextd.conf.\n\n" 104947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 105047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "-d Run daemon in foreground.\n\n" 105147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 105247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "-h Print help.\n\n" 105347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 105447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "-v Verbose output.\n\n" 105547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ); 105647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 105747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 105847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 105947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Note: ProcessArgs called before process is daemonized, and therefore must open no descriptors 106047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// returns 0 (success) if program is to continue execution 106147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// output control arguments (-f, -v) do not affect this routine 106247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d) 106347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 106447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSZone * zone; 106547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int opt; 106647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int err = 0; 106747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 106847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cfgfile = strdup( CONFIG_FILE ); 106947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( cfgfile, arg_error, err = mStatus_NoMemoryErr ); 107047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 107147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // defaults, may be overriden by command option 107247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 107347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // setup our sockaddr 107447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 107547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero( &d->addr, sizeof( d->addr ) ); 107647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->addr.sin_addr.s_addr = zerov4Addr.NotAnInteger; 107747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->addr.sin_port = UnicastDNSPort.NotAnInteger; 107847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->addr.sin_family = AF_INET; 107947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN 108047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->addr.sin_len = sizeof( d->addr ); 108147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 108247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 108347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // setup nameserver's sockaddr 108447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 108547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(&d->ns_addr, sizeof(d->ns_addr)); 108647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->ns_addr.sin_family = AF_INET; 108747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt inet_pton( AF_INET, LOOPBACK, &d->ns_addr.sin_addr ); 108847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->ns_addr.sin_port = NSIPCPort.NotAnInteger; 108947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN 109047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->ns_addr.sin_len = sizeof( d->ns_addr ); 109147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 109247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 109347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // setup our ports 109447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 109547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->private_port = PrivateDNSPort; 109647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->llq_port = DNSEXTPort; 109747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 109847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while ((opt = getopt(argc, argv, "f:hdv")) != -1) 109947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 110047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt switch(opt) 110147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 110247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'f': free( cfgfile ); cfgfile = strdup( optarg ); require_action( cfgfile, arg_error, err = mStatus_NoMemoryErr ); break; 110347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'h': PrintHelp(); return -1; 110447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'd': foreground = 1; break; // Also used when launched via OS X's launchd mechanism 110547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'v': verbose = 1; break; 110647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt default: goto arg_error; 110747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 110847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 110947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 111047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = ParseConfig( d, cfgfile ); 111147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_noerr( err, arg_error ); 111247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 111347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Make sure we've specified some zones 111447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 111547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( d->zones, arg_error, err = mStatus_UnknownErr ); 111647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 111747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // if we have a shared secret, use it for the entire zone 111847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 111947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( zone = d->zones; zone; zone = zone->next ) 112047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 112147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( zone->updateKeys ) 112247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 112347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AssignDomainName( &zone->updateKeys->domain, &zone->name ); 112447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 112547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 112647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 112747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return 0; 112847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 112947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltarg_error: 113047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 113147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintUsage(); 113247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return -1; 113347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 113447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 113547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 113647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 113747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Initialization Routines 113847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 113947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 114047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Allocate memory, initialize locks and bookkeeping variables 114147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int InitLeaseTable(DaemonInfo *d) 114247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 114347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (pthread_mutex_init(&d->tablelock, NULL)) { LogErr("InitLeaseTable", "pthread_mutex_init"); return -1; } 114447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->nbuckets = LEASETABLE_INIT_NBUCKETS; 114547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->nelems = 0; 114647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->table = malloc(sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS); 114747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!d->table) { LogErr("InitLeaseTable", "malloc"); return -1; } 114847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(d->table, sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS); 114947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return 0; 115047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 115147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 115247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 115347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int 115447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltSetupSockets 115547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 115647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo * self 115747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 115847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 115947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt static const int kOn = 1; 116047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int sockpair[2]; 116147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool private = mDNSfalse; 116247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct sockaddr_in daddr; 116347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSZone * zone; 116447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err = 0; 116547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 116647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // set up sockets on which we all ns requests 116747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 116847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->tcpsd = socket( AF_INET, SOCK_STREAM, 0 ); 116947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( dnssd_SocketValid(self->tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 117047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 117147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(SO_REUSEADDR) 117247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = setsockopt(self->tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 117347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->tcpsd" ) ); 117447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 117547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 117647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = bind( self->tcpsd, ( struct sockaddr* ) &self->addr, sizeof( self->addr ) ); 117747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "bind self->tcpsd" ) ); 117847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 117947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = listen( self->tcpsd, LISTENQ ); 118047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "listen" ) ); 118147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 118247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->udpsd = socket( AF_INET, SOCK_DGRAM, 0 ); 118347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( dnssd_SocketValid(self->udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 118447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 118547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(SO_REUSEADDR) 118647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = setsockopt(self->udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 118747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->udpsd" ) ); 118847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 118947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 119047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = bind( self->udpsd, ( struct sockaddr* ) &self->addr, sizeof( self->addr ) ); 119147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "bind self->udpsd" ) ); 119247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 119347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // set up sockets on which we receive llq requests 119447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 119547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(&self->llq_addr, sizeof(self->llq_addr)); 119647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->llq_addr.sin_family = AF_INET; 119747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->llq_addr.sin_addr.s_addr = zerov4Addr.NotAnInteger; 119847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->llq_addr.sin_port = ( self->llq_port.NotAnInteger ) ? self->llq_port.NotAnInteger : DNSEXTPort.NotAnInteger; 119947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 120047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (self->llq_addr.sin_port == self->addr.sin_port) 120147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 120247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->llq_tcpsd = self->tcpsd; 120347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->llq_udpsd = self->udpsd; 120447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 120547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 120647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 120747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 ); 120847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( dnssd_SocketValid(self->llq_tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 120947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 121047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(SO_REUSEADDR) 121147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = setsockopt(self->llq_tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 121247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_tcpsd" ) ); 121347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 121447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 121547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = bind( self->llq_tcpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) ); 121647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_tcpsd" ) ); 121747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 121847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = listen( self->llq_tcpsd, LISTENQ ); 121947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "listen" ) ); 122047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 122147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->llq_udpsd = socket( AF_INET, SOCK_DGRAM, 0 ); 122247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( dnssd_SocketValid(self->llq_udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 122347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 122447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(SO_REUSEADDR) 122547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = setsockopt(self->llq_udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 122647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_udpsd" ) ); 122747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 122847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 122947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = bind(self->llq_udpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) ); 123047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_udpsd" ) ); 123147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 123247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 123347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // set up Unix domain socket pair for LLQ polling thread to signal main thread that a change to the zone occurred 123447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 123547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = socketpair( AF_LOCAL, SOCK_STREAM, 0, sockpair ); 123647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "socketpair" ) ); 123747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 123847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->LLQEventListenSock = sockpair[0]; 123947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->LLQEventNotifySock = sockpair[1]; 124047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 124147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // set up socket on which we receive private requests 124247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 124347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 ); 124447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( dnssd_SocketValid(self->tlssd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 124547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(&daddr, sizeof(daddr)); 124647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt daddr.sin_family = AF_INET; 124747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt daddr.sin_addr.s_addr = zerov4Addr.NotAnInteger; 124847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt daddr.sin_port = ( self->private_port.NotAnInteger ) ? self->private_port.NotAnInteger : PrivateDNSPort.NotAnInteger; 124947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 125047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt self->tlssd = socket( AF_INET, SOCK_STREAM, 0 ); 125147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( dnssd_SocketValid(self->tlssd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) ); 125247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 125347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(SO_REUSEADDR) 125447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = setsockopt(self->tlssd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); 125547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->tlssd" ) ); 125647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 125747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 125847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = bind( self->tlssd, ( struct sockaddr* ) &daddr, sizeof( daddr ) ); 125947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "bind self->tlssd" ) ); 126047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 126147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = listen( self->tlssd, LISTENQ ); 126247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "listen" ) ); 126347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 126447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Do we have any private zones? 126547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 126647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( zone = self->zones; zone; zone = zone->next ) 126747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 126847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( zone->type == kDNSZonePrivate ) 126947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 127047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt private = mDNStrue; 127147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 127247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 127347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 127447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 127547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( private ) 127647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 127747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = mDNSPlatformTLSSetupCerts(); 127847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "SetupSockets", "mDNSPlatformTLSSetupCerts" ) ); 127947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 128047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 128147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 128247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 128347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 128447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 128547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 128647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 128747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// periodic table updates 128847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 128947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 129047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Delete a resource record from the nameserver via a dynamic update 129147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// sd is a socket already connected to the server 129247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void DeleteOneRecord(DaemonInfo *d, CacheRecord *rr, domainname *zname, TCPSocket *sock) 129347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 129447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSZone * zone; 129547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg pkt; 129647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *ptr = pkt.msg.data; 129747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage); 129847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buf[MaxMsg]; 129947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool closed; 130047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg *reply = NULL; 130147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 130247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Expiring record %s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, buf)); 130347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 130447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitializeDNSMessage(&pkt.msg.h, zeroID, UpdateReqFlags); 130547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 130647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = putZone(&pkt.msg, ptr, end, zname, mDNSOpaque16fromIntVal(rr->resrec.rrclass)); 130747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) goto end; 130847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = putDeletionRecord(&pkt.msg, ptr, &rr->resrec); 130947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) goto end; 131047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 131147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(&pkt); 131247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 131347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt zone = FindZone( d, zname ); 131447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 131547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( zone && zone->updateKeys) 131647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 131747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSDigest_SignMessage(&pkt.msg, &ptr, zone->updateKeys, 0 ); 131847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) goto end; 131947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 132047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 132147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt.len = ptr - (mDNSu8 *)&pkt.msg; 132247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt.src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // address field set solely for verbose logging in subroutines 132347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt.src.sin_family = AF_INET; 132447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (SendPacket( sock, &pkt)) { Log("DeleteOneRecord: SendPacket failed"); } 132547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = RecvPacket( sock, NULL, &closed ); 132647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (reply) HdrNToH(reply); 132747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( reply, end, Log( "DeleteOneRecord: RecvPacket returned NULL" ) ); 132847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 132947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!SuccessfulUpdateTransaction(&pkt, reply)) 133047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Expiration update failed with rcode %d", reply ? reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask : -1); 133147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 133247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end: 133347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) { Log("DeleteOneRecord: Error constructing lease expiration update"); } 133447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (reply) free(reply); 133547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 133647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 133747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// iterate over table, deleting expired records (or all records if DeleteAll is true) 133847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void DeleteRecords(DaemonInfo *d, mDNSBool DeleteAll) 133947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 134047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval now; 134147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i; 134247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPSocket *sock = ConnectToServer(d); 134347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!sock) { Log("DeleteRecords: ConnectToServer failed"); return; } 134447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gettimeofday(&now, NULL)) { LogErr("DeleteRecords ", "gettimeofday"); return; } 134547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteRecords", "pthread_mutex_lock"); return; } 134647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 134747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < d->nbuckets; i++) 134847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 134947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RRTableElem **ptr = &d->table[i]; 135047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (*ptr) 135147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 135247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (DeleteAll || (*ptr)->expire - now.tv_sec < 0) 135347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 135447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RRTableElem *fptr; 135547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // delete record from server 135647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DeleteOneRecord(d, &(*ptr)->rr, &(*ptr)->zone, sock); 135747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fptr = *ptr; 135847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr = (*ptr)->next; 135947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(fptr); 136047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->nelems--; 136147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 136247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else ptr = &(*ptr)->next; 136347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 136447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 136547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pthread_mutex_unlock(&d->tablelock); 136647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformTCPCloseConnection( sock ); 136747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 136847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 136947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 137047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// main update request handling 137147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 137247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 137347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Add, delete, or refresh records in table based on contents of a successfully completed dynamic update 137447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease) 137547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 137647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RRTableElem **rptr, *tmp; 137747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i, allocsize, bucket; 137847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LargeCacheRecord lcr; 137947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ResourceRecord *rr = &lcr.r.resrec; 138047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 *ptr, *end; 138147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval tv; 138247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSQuestion zone; 138347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buf[MaxMsg]; 138447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 138547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (pthread_mutex_lock(&d->tablelock)) { LogErr("UpdateLeaseTable", "pthread_mutex_lock"); return; } 138647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrNToH(pkt); 138747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = pkt->msg.data; 138847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = (mDNSu8 *)&pkt->msg + pkt->len; 138947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = getQuestion(&pkt->msg, ptr, end, 0, &zone); 139047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) { Log("UpdateLeaseTable: cannot read zone"); goto cleanup; } 139147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = LocateAuthorities(&pkt->msg, end); 139247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) { Log("UpdateLeaseTable: Format error"); goto cleanup; } 139347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 139447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < pkt->msg.h.mDNS_numUpdates; i++) 139547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 139647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool DeleteAllRRSets = mDNSfalse, DeleteOneRRSet = mDNSfalse, DeleteOneRR = mDNSfalse; 139747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 139847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); 139947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr || lcr.r.resrec.RecordType == kDNSRecordTypePacketNegative) { Log("UpdateLeaseTable: GetLargeResourceRecord failed"); goto cleanup; } 140047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt bucket = rr->namehash % d->nbuckets; 140147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rptr = &d->table[bucket]; 140247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 140347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // handle deletions 140447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (rr->rrtype == kDNSQType_ANY && !rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength) 140547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DeleteAllRRSets = mDNStrue; // delete all rrsets for a name 140647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (!rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength) 140747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DeleteOneRRSet = mDNStrue; 140847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (!rr->rroriginalttl && rr->rrclass == kDNSClass_NONE) 140947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DeleteOneRR = mDNStrue; 141047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 141147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (DeleteAllRRSets || DeleteOneRRSet || DeleteOneRR) 141247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 141347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (*rptr) 141447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 141547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (SameDomainName((*rptr)->rr.resrec.name, rr->name) && 141647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (DeleteAllRRSets || 141747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (DeleteOneRRSet && (*rptr)->rr.resrec.rrtype == rr->rrtype) || 141847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (DeleteOneRR && IdenticalResourceRecord(&(*rptr)->rr.resrec, rr)))) 141947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 142047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp = *rptr; 142147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Received deletion update for %s", GetRRDisplayString_rdb(&tmp->rr.resrec, &tmp->rr.resrec.rdata->u, buf)); 142247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *rptr = (*rptr)->next; 142347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(tmp); 142447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->nelems--; 142547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 142647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else rptr = &(*rptr)->next; 142747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 142847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 142947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (lease > 0) 143047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 143147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // see if add or refresh 143247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (*rptr && !IdenticalResourceRecord(&(*rptr)->rr.resrec, rr)) rptr = &(*rptr)->next; 143347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (*rptr) 143447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 143547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // refresh 143647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } 143747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (*rptr)->expire = tv.tv_sec + (unsigned)lease; 143847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); 143947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 144047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 144147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 144247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // New record - add to table 144347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (d->nelems > d->nbuckets) 144447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 144547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RehashTable(d); 144647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt bucket = rr->namehash % d->nbuckets; 144747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rptr = &d->table[bucket]; 144847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 144947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } 145047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt allocsize = sizeof(RRTableElem); 145147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (rr->rdlength > InlineCacheRDSize) allocsize += (rr->rdlength - InlineCacheRDSize); 145247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp = malloc(allocsize); 145347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!tmp) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; } 145447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt memcpy(&tmp->rr, &lcr.r, sizeof(CacheRecord) + rr->rdlength - InlineCacheRDSize); 145547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp->rr.resrec.rdata = (RData *)&tmp->rr.smallrdatastorage; 145647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AssignDomainName(&tmp->name, rr->name); 145747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp->rr.resrec.name = &tmp->name; 145847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp->expire = tv.tv_sec + (unsigned)lease; 145947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp->cli.sin_addr = pkt->src.sin_addr; 146047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AssignDomainName(&tmp->zone, &zone.qname); 146147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp->next = d->table[bucket]; 146247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->table[bucket] = tmp; 146347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->nelems++; 146447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Adding update for %s to lease table", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); 146547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 146647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 146747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 146847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 146947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cleanup: 147047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pthread_mutex_unlock(&d->tablelock); 147147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(pkt); 147247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 147347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 147447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Given a successful reply from a server, create a new reply that contains lease information 147547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Replies are currently not signed !!!KRS change this 147647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal PktMsg *FormatLeaseReply(DaemonInfo *d, PktMsg *orig, mDNSu32 lease) 147747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 147847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg *reply; 147947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *ptr, *end; 148047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSOpaque16 flags; 148147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 148247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)d; //unused 148347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = malloc(sizeof(*reply)); 148447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!reply) { LogErr("FormatLeaseReply", "malloc"); return NULL; } 148547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update; 148647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt flags.b[1] = 0; 148747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 148847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitializeDNSMessage(&reply->msg.h, orig->msg.h.id, flags); 148947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply->src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // unused except for log messages 149047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply->src.sin_family = AF_INET; 149147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = reply->msg.data; 149247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = (mDNSu8 *)&reply->msg + sizeof(DNSMessage); 149347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = putUpdateLease(&reply->msg, ptr, lease); 149447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) { Log("FormatLeaseReply: putUpdateLease failed"); free(reply); return NULL; } 149547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply->len = ptr - (mDNSu8 *)&reply->msg; 149647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(reply); 149747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return reply; 149847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 149947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 150047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 150147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// pkt is thread-local, not requiring locking 150247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 150347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal PktMsg* 150447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltHandleRequest 150547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 150647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo * self, 150747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * request 150847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 150947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 151047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * reply = NULL; 151147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * leaseReply; 151247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg buf; 151347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char addrbuf[32]; 151447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPSocket * sock = NULL; 151547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err; 151647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSs32 lease = 0; 151747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) == kDNSFlag0_OP_Update) 151847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 151947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i, adds = 0, dels = 0; 152047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 *ptr, *end = (mDNSu8 *)&request->msg + request->len; 152147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrNToH(request); 152247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt lease = GetPktLease(&mDNSStorage, &request->msg, end); 152347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = LocateAuthorities(&request->msg, end); 152447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < request->msg.h.mDNS_numUpdates; i++) 152547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 152647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LargeCacheRecord lcr; 152747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = GetLargeResourceRecord(NULL, &request->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); 152847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rroriginalttl) adds++; else dels++; 152947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 153047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(request); 153147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (adds && !lease) 153247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 153347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt static const mDNSOpaque16 UpdateRefused = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update, kDNSFlag1_RC_Refused } }; 153447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Rejecting Update Request with %d additions but no lease", adds); 153547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = malloc(sizeof(*reply)); 153647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(&reply->src, sizeof(reply->src)); 153747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply->len = sizeof(DNSMessageHeader); 153847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply->zone = NULL; 153947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply->isZonePublic = 0; 154047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitializeDNSMessage(&reply->msg.h, request->msg.h.id, UpdateRefused); 154147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(reply); 154247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 154347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (lease > 7200) // Don't allow lease greater than two hours; typically 90-minute renewal period 154447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt lease = 7200; 154547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 154647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Send msg to server, read reply 154747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 154847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( request->len <= 512 ) 154947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 155047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool trunc; 155147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 155247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( UDPServerTransaction( self, request, &buf, &trunc) < 0 ) 155347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 155447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("HandleRequest - UDPServerTransaction failed. Trying TCP"); 155547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 155647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if ( trunc ) 155747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 155847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("HandleRequest - answer truncated. Using TCP"); 155947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 156047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 156147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 156247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = &buf; // success 156347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 156447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 156547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 156647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( !reply ) 156747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 156847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool closed; 156947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int res; 157047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 157147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt sock = ConnectToServer( self ); 157247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( sock, exit, err = mStatus_UnknownErr ; Log( "Discarding request from %s due to connection errors", inet_ntop( AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) ); 157347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 157447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt res = SendPacket( sock, request ); 157547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( res >= 0, exit, err = mStatus_UnknownErr ; Log( "Couldn't relay message from %s to server. Discarding.", inet_ntop(AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) ); 157647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 157747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = RecvPacket( sock, &buf, &closed ); 157847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 157947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 158047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // IMPORTANT: reply is in network byte order at this point in the code 158147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // We keep it this way because we send it back to the client in the same form 158247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 158347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Is it an update? 158447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 158547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( reply && ( ( reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == ( kDNSFlag0_OP_Update | kDNSFlag0_QR_Response ) ) ) 158647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 158747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char pingmsg[4]; 158847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool ok = SuccessfulUpdateTransaction( request, reply ); 158947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( ok, exit, err = mStatus_UnknownErr; VLog( "Message from %s not a successful update.", inet_ntop(AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) ); 159047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 159147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt UpdateLeaseTable( request, self, lease ); 159247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 159347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( lease > 0 ) 159447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 159547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt leaseReply = FormatLeaseReply( self, reply, lease ); 159647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 159747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( !leaseReply ) 159847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 159947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("HandleRequest - unable to format lease reply"); 160047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 160147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 160247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // %%% Looks like a potential memory leak -- who frees the original reply? 160347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = leaseReply; 160447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 160547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 160647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // tell the main thread there was an update so it can send LLQs 160747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 160847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( send( self->LLQEventNotifySock, pingmsg, sizeof( pingmsg ), 0 ) != sizeof( pingmsg ) ) 160947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 161047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr("HandleRequest", "send"); 161147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 161247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 161347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 161447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 161547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 161647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( sock ) 161747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 161847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformTCPCloseConnection( sock ); 161947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 162047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 162147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( reply == &buf ) 162247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 162347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = malloc( sizeof( *reply ) ); 162447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 162547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( reply ) 162647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 162747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply->len = buf.len; 162847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt memcpy(&reply->msg, &buf.msg, buf.len); 162947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 163047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 163147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 163247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr("HandleRequest", "malloc"); 163347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 163447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 163547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 163647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return reply; 163747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 163847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 163947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 164047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 164147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// LLQ Support Routines 164247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 164347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 164447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Set fields of an LLQ OPT Resource Record 164547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void FormatLLQOpt(AuthRecord *opt, int opcode, const mDNSOpaque64 *const id, mDNSs32 lease) 164647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 164747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(opt, sizeof(*opt)); 164847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_SetupResourceRecord(opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); 164947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt opt->resrec.rrclass = NormalMaxDNSMessageData; 165047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt opt->resrec.rdlength = sizeof(rdataOPT); // One option in this OPT record 165147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt opt->resrec.rdestimate = sizeof(rdataOPT); 165247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt opt->resrec.rdata->u.opt[0].opt = kDNSOpt_LLQ; 165347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt opt->resrec.rdata->u.opt[0].u.llq.vers = kLLQ_Vers; 165447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt opt->resrec.rdata->u.opt[0].u.llq.llqOp = opcode; 165547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt opt->resrec.rdata->u.opt[0].u.llq.err = LLQErr_NoError; 165647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt opt->resrec.rdata->u.opt[0].u.llq.id = *id; 165747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt opt->resrec.rdata->u.opt[0].u.llq.llqlease = lease; 165847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 165947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 166047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Calculate effective remaining lease of an LLQ 166147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSu32 LLQLease(LLQEntry *e) 166247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 166347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval t; 166447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 166547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gettimeofday(&t, NULL); 166647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (e->expire < t.tv_sec) return 0; 166747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else return e->expire - t.tv_sec; 166847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 166947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 167047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e) 167147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 167247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE; 167347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQEntry **ptr = &d->LLQTable[bucket]; 167447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerListElem *a = e->AnswerList; 167547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char addr[32]; 167647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 167747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); 167847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Deleting LLQ table entry for %##s client %s", e->qname.c, addr); 167947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 168047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (a && !(--a->refcount) && d->AnswerTableCount >= LLQ_TABLESIZE) 168147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 168247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // currently, generating initial answers blocks the main thread, so we keep the answer list 168347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // even if the ref count drops to zero. To prevent unbounded table growth, we free shared answers 168447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // if the ref count drops to zero AND there are more table elements than buckets 168547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // !!!KRS update this when we make the table dynamically growable 168647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 168747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheRecord *cr = a->KnownAnswers, *tmp; 168847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerListElem **tbl = &d->AnswerTable[bucket]; 168947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 169047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (cr) 169147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 169247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp = cr; 169347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr = cr->next; 169447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(tmp); 169547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 169647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 169747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (*tbl && *tbl != a) tbl = &(*tbl)->next; 169847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (*tbl) { *tbl = (*tbl)->next; free(a); d->AnswerTableCount--; } 169947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else Log("Error: DeleteLLQ - AnswerList not found in table"); 170047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 170147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 170247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // remove LLQ from table, free memory 170347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while(*ptr && *ptr != e) ptr = &(*ptr)->next; 170447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!*ptr) { Log("Error: DeleteLLQ - LLQ not in table"); return; } 170547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ptr = (*ptr)->next; 170647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(e); 170747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 170847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 170947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst, TCPSocket *sock) 171047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 171147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char addr[32]; 171247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int err = -1; 171347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 171447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(pkt); 171547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 171647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( sock ) 171747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 171847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( SendPacket( sock, pkt ) != 0 ) 171947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 172047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr("DaemonInfo", "MySend"); 172147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Could not send response to client %s", inet_ntop(AF_INET, &dst.sin_addr, addr, 32)); 172247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 172347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 172447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 172547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 172647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (sendto(d->llq_udpsd, &pkt->msg, pkt->len, 0, (struct sockaddr *)&dst, sizeof(dst)) != (int)pkt->len) 172747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 172847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr("DaemonInfo", "sendto"); 172947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Could not send response to client %s", inet_ntop(AF_INET, &dst.sin_addr, addr, 32)); 173047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 173147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 173247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 173347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = 0; 173447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrNToH(pkt); 173547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 173647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 173747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 173847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e) 173947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 174047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg q; 174147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i; 174247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPSocket *sock = NULL; 174347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 *ansptr; 174447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *end = q.msg.data; 174547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg buf, *reply = NULL; 174647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LargeCacheRecord lcr; 174747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheRecord *AnswerList = NULL; 174847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 rcode; 174947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 175047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Querying server for %##s type %d", e->name.c, e->type); 175147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 175247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitializeDNSMessage(&q.msg.h, zeroID, uQueryFlags); 175347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 175447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->name, e->type, kDNSClass_IN); 175547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: AnswerQuestion - putQuestion returned NULL"); goto end; } 175647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q.len = (int)(end - (mDNSu8 *)&q.msg); 175747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 175847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(&q); 175947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 176047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!e->UseTCP) 176147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 176247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool trunc; 176347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 176447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (UDPServerTransaction(d, &q, &buf, &trunc) < 0) 176547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("AnswerQuestion %##s - UDPServerTransaction failed. Trying TCP", e->name.c); 176647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (trunc) 176747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { VLog("AnswerQuestion %##s - answer truncated. Using TCP", e->name.c); e->UseTCP = mDNStrue; } 176847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else reply = &buf; // success 176947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 177047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 177147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!reply) 177247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 177347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool closed; 177447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 177547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt sock = ConnectToServer(d); 177647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!sock) { Log("AnswerQuestion: ConnectToServer failed"); goto end; } 177747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (SendPacket( sock, &q)) { Log("AnswerQuestion: SendPacket failed"); mDNSPlatformTCPCloseConnection( sock ); goto end; } 177847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = RecvPacket( sock, NULL, &closed ); 177947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformTCPCloseConnection( sock ); 178047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( reply, end, Log( "AnswerQuestion: RecvPacket returned NULL" ) ); 178147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 178247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 178347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrNToH(&q); 178447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (reply) HdrNToH(reply); 178547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 178647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery)) 178747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { Log("AnswerQuestion: %##s type %d - Invalid response flags from server"); goto end; } 178847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rcode = (mDNSu8)(reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask); 178947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (rcode && rcode != kDNSFlag1_RC_NXDomain) { Log("AnswerQuestion: %##s type %d - non-zero rcode %d from server", e->name.c, e->type, rcode); goto end; } 179047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 179147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = (mDNSu8 *)&reply->msg + reply->len; 179247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ansptr = LocateAnswers(&reply->msg, end); 179347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ansptr) { Log("Error: AnswerQuestion - LocateAnswers returned NULL"); goto end; } 179447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 179547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < reply->msg.h.numAnswers; i++) 179647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 179747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ansptr = GetLargeResourceRecord(NULL, &reply->msg, ansptr, end, 0, kDNSRecordTypePacketAns, &lcr); 179847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ansptr) { Log("AnswerQuestions: GetLargeResourceRecord returned NULL"); goto end; } 179947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative) 180047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 180147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (lcr.r.resrec.rrtype != e->type || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->name)) 180247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 180347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d. Discarding", 180447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->name.c, e->type); 180547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 180647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 180747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 180847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->name); 180947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; } 181047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr->next = AnswerList; 181147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerList = cr; 181247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 181347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 181447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 181547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 181647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end: 181747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (reply && reply != &buf) free(reply); 181847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return AnswerList; 181947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 182047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 182147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Routine forks a thread to set EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list 182247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void *UpdateAnswerList(void *args) 182347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 182447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheRecord *cr, *NewAnswers, **na, **ka; // "new answer", "known answer" 182547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo *d = ((UpdateAnswerListArgs *)args)->d; 182647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerListElem *a = ((UpdateAnswerListArgs *)args)->a; 182747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 182847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(args); 182947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt args = NULL; 183047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 183147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // get up to date answers 183247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NewAnswers = AnswerQuestion(d, a); 183347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 183447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // first pass - mark all answers for deletion 183547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) 183647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (*ka)->resrec.rroriginalttl = (unsigned)-1; // -1 means delete 183747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 183847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // second pass - mark answers pre-existent 183947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) 184047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 184147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (na = &NewAnswers; *na; na = &(*na)->next) 184247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 184347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec)) 184447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { (*ka)->resrec.rroriginalttl = 0; break; } // 0 means no change 184547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 184647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 184747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 184847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // third pass - add new records to Event list 184947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt na = &NewAnswers; 185047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (*na) 185147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 185247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) 185347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec)) break; 185447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!*ka) 185547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 185647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // answer is not in list - splice from NewAnswers list, add to Event list 185747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr = *na; 185847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *na = (*na)->next; // splice from list 185947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr->next = a->EventList; // add spliced record to event list 186047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->EventList = cr; 186147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr->resrec.rroriginalttl = 1; // 1 means add 186247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 186347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else na = &(*na)->next; 186447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 186547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 186647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // move all the removes from the answer list to the event list 186747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ka = &a->KnownAnswers; 186847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (*ka) 186947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 187047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((*ka)->resrec.rroriginalttl == (unsigned)-1) 187147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 187247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr = *ka; 187347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *ka = (*ka)->next; 187447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr->next = a->EventList; 187547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->EventList = cr; 187647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 187747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else ka = &(*ka)->next; 187847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 187947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 188047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // lastly, free the remaining records (known answers) in NewAnswers list 188147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (NewAnswers) 188247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 188347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr = NewAnswers; 188447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NewAnswers = NewAnswers->next; 188547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(cr); 188647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 188747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 188847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return NULL; 188947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 189047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 189147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e) 189247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 189347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg response; 189447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheRecord *cr; 189547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *end = (mDNSu8 *)&response.msg.data; 189647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSOpaque16 msgID; 189747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char rrbuf[MaxMsg], addrbuf[32]; 189847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AuthRecord opt; 189947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 190047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Should this really be random? Do we use the msgID on the receiving end? 190147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt msgID.NotAnInteger = random(); 190247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32); 190347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitializeDNSMessage(&response.msg.h, msgID, ResponseFlags); 190447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = putQuestion(&response.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); 190547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: SendEvents - putQuestion returned NULL"); return; } 190647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 190747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // put adds/removes in packet 190847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (cr = e->AnswerList->EventList; cr; cr = cr->next) 190947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 191047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (verbose) GetRRDisplayString_rdb(&cr->resrec, &cr->resrec.rdata->u, rrbuf); 191147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("%s (%s): %s", addrbuf, (mDNSs32)cr->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf); 191247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &cr->resrec, cr->resrec.rroriginalttl); 191347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo returned NULL"); return; } 191447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 191547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 191647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FormatLLQOpt(&opt, kLLQOp_Event, &e->id, LLQLease(e)); 191747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAdditionals, &opt.resrec, 0); 191847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo"); return; } 191947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 192047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt response.len = (int)(end - (mDNSu8 *)&response.msg); 192147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (SendLLQ(d, &response, e->cli, NULL ) < 0) LogMsg("Error: SendEvents - SendLLQ"); 192247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 192347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 192447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void PrintLLQAnswers(DaemonInfo *d) 192547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 192647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i; 192747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char rrbuf[MaxMsg]; 192847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 192947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Printing LLQ Answer Table contents"); 193047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 193147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < LLQ_TABLESIZE; i++) 193247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 193347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerListElem *a = d->AnswerTable[i]; 193447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while(a) 193547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 193647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int ancount = 0; 193747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const CacheRecord *rr = a->KnownAnswers; 193847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (rr) { ancount++; rr = rr->next; } 193947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("%p : Question %##s; type %d; referenced by %d LLQs; %d answers:", a, a->name.c, a->type, a->refcount, ancount); 194047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (rr = a->KnownAnswers; rr; rr = rr->next) Log("\t%s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, rrbuf)); 194147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a = a->next; 194247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 194347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 194447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 194547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 194647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void PrintLLQTable(DaemonInfo *d) 194747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 194847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQEntry *e; 194947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char addr[32]; 195047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i; 195147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 195247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Printing LLQ table contents"); 195347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 195447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < LLQ_TABLESIZE; i++) 195547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 195647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e = d->LLQTable[i]; 195747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while(e) 195847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 195947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char *state; 196047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 196147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt switch (e->state) 196247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 196347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case RequestReceived: state = "RequestReceived"; break; 196447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case ChallengeSent: state = "ChallengeSent"; break; 196547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case Established: state = "Established"; break; 196647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt default: state = "unknown"; 196747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 196847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); 196947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 197047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("LLQ from %s in state %s; %##s; type %d; orig lease %d; remaining lease %d; AnswerList %p)", 197147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt addr, state, e->qname.c, e->qtype, e->lease, LLQLease(e), e->AnswerList); 197247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e = e->next; 197347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 197447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 197547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 197647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 197747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Send events to clients as a result of a change in the zone 197847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void GenLLQEvents(DaemonInfo *d) 197947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 198047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQEntry **e; 198147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i; 198247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval t; 198347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt UpdateAnswerListArgs *args; 198447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 198547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Generating LLQ Events"); 198647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 198747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gettimeofday(&t, NULL); 198847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 198947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // get all answers up to date 199047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < LLQ_TABLESIZE; i++) 199147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 199247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerListElem *a = d->AnswerTable[i]; 199347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while(a) 199447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 199547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt args = malloc(sizeof(*args)); 199647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!args) { LogErr("GenLLQEvents", "malloc"); return; } 199747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt args->d = d; 199847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt args->a = a; 199947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (pthread_create(&a->tid, NULL, UpdateAnswerList, args) < 0) { LogErr("GenLLQEvents", "pthread_create"); return; } 200047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt usleep(1); 200147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a = a->next; 200247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 200347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 200447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 200547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < LLQ_TABLESIZE; i++) 200647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 200747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerListElem *a = d->AnswerTable[i]; 200847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while(a) 200947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 201047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (pthread_join(a->tid, NULL)) LogErr("GenLLQEvents", "pthread_join"); 201147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a = a->next; 201247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 201347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 201447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 201547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // for each established LLQ, send events 201647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < LLQ_TABLESIZE; i++) 201747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 201847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e = &d->LLQTable[i]; 201947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while(*e) 202047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 202147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((*e)->expire < t.tv_sec) DeleteLLQ(d, *e); 202247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 202347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 202447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((*e)->state == Established && (*e)->AnswerList->EventList) SendEvents(d, *e); 202547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e = &(*e)->next; 202647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 202747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 202847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 202947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 203047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // now that all LLQs are updated, we move Add events from the Event list to the Known Answer list, and free Removes 203147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < LLQ_TABLESIZE; i++) 203247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 203347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerListElem *a = d->AnswerTable[i]; 203447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while(a) 203547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 203647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (a->EventList) 203747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 203847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheRecord *cr = a->EventList, *tmp; 203947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (cr) 204047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 204147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp = cr; 204247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cr = cr->next; 204347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ((signed)tmp->resrec.rroriginalttl < 0) free(tmp); 204447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 204547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 204647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp->next = a->KnownAnswers; 204747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->KnownAnswers = tmp; 204847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt tmp->resrec.rroriginalttl = 0; 204947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 205047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 205147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->EventList = NULL; 205247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 205347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a = a->next; 205447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 205547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 205647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 205747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 205847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e) 205947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 206047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE; 206147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AnswerListElem *a = d->AnswerTable[bucket]; 206247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (a && (a->type != e->qtype ||!SameDomainName(&a->name, &e->qname))) a = a->next; 206347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!a) 206447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 206547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a = malloc(sizeof(*a)); 206647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!a) { LogErr("SetAnswerList", "malloc"); return; } 206747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AssignDomainName(&a->name, &e->qname); 206847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->type = e->qtype; 206947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->refcount = 0; 207047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->EventList = NULL; 207147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->UseTCP = mDNSfalse; 207247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->next = d->AnswerTable[bucket]; 207347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->AnswerTable[bucket] = a; 207447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->AnswerTableCount++; 207547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->KnownAnswers = AnswerQuestion(d, a); 207647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 207747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 207847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->AnswerList = a; 207947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt a->refcount ++; 208047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 208147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 208247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Allocate LLQ entry, insert into table 208347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, mDNSu32 lease ) 208447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 208547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char addr[32]; 208647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval t; 208747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE; 208847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQEntry *e; 208947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 209047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e = malloc(sizeof(*e)); 209147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!e) { LogErr("NewLLQ", "malloc"); return NULL; } 209247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 209347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt inet_ntop(AF_INET, &cli.sin_addr, addr, 32); 209447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Allocating LLQ entry for client %s question %##s type %d", addr, qname->c, qtype); 209547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 209647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // initialize structure 209747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->cli = cli; 209847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AssignDomainName(&e->qname, qname); 209947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->qtype = qtype; 210047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->id = zeroOpaque64; 210147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->state = RequestReceived; 210247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->AnswerList = NULL; 210347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 210447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (lease < LLQ_MIN_LEASE) lease = LLQ_MIN_LEASE; 210547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (lease > LLQ_MAX_LEASE) lease = LLQ_MAX_LEASE; 210647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 210747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gettimeofday(&t, NULL); 210847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->expire = t.tv_sec + (int)lease; 210947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->lease = lease; 211047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 211147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // add to table 211247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->next = d->LLQTable[bucket]; 211347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->LLQTable[bucket] = e; 211447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 211547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return e; 211647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 211747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 211847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Handle a refresh request from client 211947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void LLQRefresh(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock ) 212047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 212147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AuthRecord opt; 212247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg ack; 212347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *end = (mDNSu8 *)&ack.msg.data; 212447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char addr[32]; 212547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 212647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); 212747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("%s LLQ for %##s from %s", llq->llqlease ? "Refreshing" : "Deleting", e->qname.c, addr); 212847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 212947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (llq->llqlease) 213047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 213147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval t; 213247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (llq->llqlease < LLQ_MIN_LEASE) llq->llqlease = LLQ_MIN_LEASE; 213347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (llq->llqlease > LLQ_MAX_LEASE) llq->llqlease = LLQ_MIN_LEASE; 213447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gettimeofday(&t, NULL); 213547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->expire = t.tv_sec + llq->llqlease; 213647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 213747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 213847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ack.src.sin_addr.s_addr = 0; // unused 213947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags); 214047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); 214147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: putQuestion"); return; } 214247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 214347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FormatLLQOpt(&opt, kLLQOp_Refresh, &e->id, llq->llqlease ? LLQLease(e) : 0); 214447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0); 214547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } 214647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 214747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ack.len = (int)(end - (mDNSu8 *)&ack.msg); 214847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (SendLLQ(d, &ack, e->cli, sock)) Log("Error: LLQRefresh"); 214947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 215047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (llq->llqlease) e->state = Established; 215147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else DeleteLLQ(d, e); 215247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 215347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 215447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Complete handshake with Ack an initial answers 215547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void LLQCompleteHandshake(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock) 215647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 215747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char addr[32]; 215847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheRecord *ptr; 215947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AuthRecord opt; 216047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg ack; 216147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *end = (mDNSu8 *)&ack.msg.data; 216247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char rrbuf[MaxMsg], addrbuf[32]; 216347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 216447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); 216547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 216647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!mDNSSameOpaque64(&llq->id, &e->id) || 216747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt llq->vers != kLLQ_Vers || 216847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt llq->llqOp != kLLQOp_Setup || 216947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt llq->err != LLQErr_NoError || 217047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt llq->llqlease > e->lease + LLQ_LEASE_FUDGE || 217147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt llq->llqlease < e->lease - LLQ_LEASE_FUDGE) 217247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 217347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Incorrect challenge response from %s", addr); 217447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return; 217547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 217647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 217747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (e->state == Established) VLog("Retransmitting LLQ ack + answers for %##s", e->qname.c); 217847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else VLog("Delivering LLQ ack + answers for %##s", e->qname.c); 217947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 218047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // format ack + answers 218147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ack.src.sin_addr.s_addr = 0; // unused 218247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags); 218347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); 218447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: putQuestion"); return; } 218547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 218647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (e->state != Established) { SetAnswerList(d, e); e->state = Established; } 218747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 218847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32); 218947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (ptr = e->AnswerList->KnownAnswers; ptr; ptr = ptr->next) 219047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 219147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (verbose) GetRRDisplayString_rdb(&ptr->resrec, &ptr->resrec.rdata->u, rrbuf); 219247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("%s Intitial Answer - %s", addr, rrbuf); 219347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAnswers, &ptr->resrec, 1); 219447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } 219547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 219647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 219747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FormatLLQOpt(&opt, kLLQOp_Setup, &e->id, LLQLease(e)); 219847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0); 219947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } 220047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 220147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ack.len = (int)(end - (mDNSu8 *)&ack.msg); 220247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (SendLLQ(d, &ack, e->cli, sock)) Log("Error: LLQCompleteHandshake"); 220347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 220447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 220547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void LLQSetupChallenge(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID) 220647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 220747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval t; 220847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg challenge; 220947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *end = challenge.msg.data; 221047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AuthRecord opt; 221147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 221247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (e->state == ChallengeSent) VLog("Retransmitting LLQ setup challenge for %##s", e->qname.c); 221347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else VLog("Sending LLQ setup challenge for %##s", e->qname.c); 221447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 221547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!mDNSOpaque64IsZero(&llq->id)) { Log("Error: LLQSetupChallenge - nonzero ID"); return; } // server bug 221647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (llq->llqOp != kLLQOp_Setup) { Log("LLQSetupChallenge - incorrrect operation from client"); return; } // client error 221747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 221847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (mDNSOpaque64IsZero(&e->id)) // don't regenerate random ID for retransmissions 221947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 222047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // construct ID <time><random> 222147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gettimeofday(&t, NULL); 222247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->id.l[0] = t.tv_sec; 222347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->id.l[1] = random(); 222447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 222547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 222647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // format response (query + LLQ opt rr) 222747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt challenge.src.sin_addr.s_addr = 0; // unused 222847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt InitializeDNSMessage(&challenge.msg.h, msgID, ResponseFlags); 222947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = putQuestion(&challenge.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); 223047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: putQuestion"); return; } 223147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FormatLLQOpt(&opt, kLLQOp_Setup, &e->id, LLQLease(e)); 223247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end = PutResourceRecordTTLJumbo(&challenge.msg, end, &challenge.msg.h.numAdditionals, &opt.resrec, 0); 223347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } 223447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt challenge.len = (int)(end - (mDNSu8 *)&challenge.msg); 223547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (SendLLQ(d, &challenge, e->cli, NULL)) { Log("Error: LLQSetupChallenge"); return; } 223647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->state = ChallengeSent; 223747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 223847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 223947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Take action on an LLQ message from client. Entry must be initialized and in table 224047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void UpdateLLQ(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock ) 224147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 224247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt switch(e->state) 224347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 224447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case RequestReceived: 224547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( sock ) 224647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 224747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval t; 224847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gettimeofday(&t, NULL); 224947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->id.l[0] = t.tv_sec; // construct ID <time><random> 225047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->id.l[1] = random(); 225147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt llq->id = e->id; 225247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQCompleteHandshake( d, e, llq, msgID, sock ); 225347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 225447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Set the state to established because we've just set the LLQ up using TCP 225547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e->state = Established; 225647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 225747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 225847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 225947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQSetupChallenge(d, e, llq, msgID); 226047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 226147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return; 226247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case ChallengeSent: 226347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (mDNSOpaque64IsZero(&llq->id)) LLQSetupChallenge(d, e, llq, msgID); // challenge sent and lost 226447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else LLQCompleteHandshake(d, e, llq, msgID, sock ); 226547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return; 226647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case Established: 226747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (mDNSOpaque64IsZero(&llq->id)) 226847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 226947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // client started over. reset state. 227047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQEntry *newe = NewLLQ(d, e->cli, &e->qname, e->qtype, llq->llqlease ); 227147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!newe) return; 227247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DeleteLLQ(d, e); 227347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQSetupChallenge(d, newe, llq, msgID); 227447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return; 227547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 227647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (llq->llqOp == kLLQOp_Setup) 227747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { LLQCompleteHandshake(d, e, llq, msgID, sock); return; } // Ack lost 227847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (llq->llqOp == kLLQOp_Refresh) 227947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { LLQRefresh(d, e, llq, msgID, sock); return; } 228047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else { Log("Unhandled message for established LLQ"); return; } 228147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 228247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 228347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 228447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal LLQEntry *LookupLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, const mDNSOpaque64 *const id) 228547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 228647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int bucket = bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE; 228747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQEntry *ptr = d->LLQTable[bucket]; 228847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 228947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while(ptr) 229047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 229147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (((ptr->state == ChallengeSent && mDNSOpaque64IsZero(id) && (cli.sin_port == ptr->cli.sin_port)) || // zero-id due to packet loss OK in state ChallengeSent 229247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSSameOpaque64(id, &ptr->id)) && // id match 229347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (cli.sin_addr.s_addr == ptr->cli.sin_addr.s_addr) && (qtype == ptr->qtype) && SameDomainName(&ptr->qname, qname)) // same source, type, qname 229447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return ptr; 229547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = ptr->next; 229647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 229747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return NULL; 229847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 229947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 230047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int 230147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltRecvNotify 230247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 230347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo * d, 230447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * pkt 230547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 230647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 230747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int res; 230847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int err = 0; 230947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 231047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->msg.h.flags.b[0] |= kDNSFlag0_QR_Response; 231147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 231247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt res = sendto( d->udpsd, &pkt->msg, pkt->len, 0, ( struct sockaddr* ) &pkt->src, sizeof( pkt->src ) ); 231347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( res == ( int ) pkt->len, exit, err = mStatus_UnknownErr; LogErr( "RecvNotify", "sendto" ) ); 231447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 231547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 231647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 231747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 231847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 231947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 232047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 232147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int RecvLLQ( DaemonInfo *d, PktMsg *pkt, TCPSocket *sock ) 232247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 232347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSQuestion q; 232447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LargeCacheRecord opt; 232547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i, err = -1; 232647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char addr[32]; 232747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 *qptr = pkt->msg.data; 232847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 *end = (mDNSu8 *)&pkt->msg + pkt->len; 232947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 *aptr; 233047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQOptData *llq = NULL; 233147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LLQEntry *e = NULL; 233247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 233347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrNToH(pkt); 233447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt aptr = LocateAdditionals(&pkt->msg, end); // Can't do this until after HdrNToH(pkt); 233547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt inet_ntop(AF_INET, &pkt->src.sin_addr, addr, 32); 233647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 233747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Received LLQ msg from %s", addr); 233847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // sanity-check packet 233947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!pkt->msg.h.numQuestions || !pkt->msg.h.numAdditionals) 234047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 234147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Malformatted LLQ from %s with %d questions, %d additionals", addr, pkt->msg.h.numQuestions, pkt->msg.h.numAdditionals); 234247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto end; 234347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 234447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 234547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Locate the OPT record. 234647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // According to RFC 2671, "One OPT pseudo-RR can be added to the additional data section of either a request or a response." 234747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // This implies that there may be *at most* one OPT record per DNS message, in the Additional Section, 234847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // but not necessarily the *last* entry in the Additional Section. 234947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < pkt->msg.h.numAdditionals; i++) 235047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 235147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt aptr = GetLargeResourceRecord(NULL, &pkt->msg, aptr, end, 0, kDNSRecordTypePacketAdd, &opt); 235247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!aptr) { Log("Malformatted LLQ from %s: could not get Additional record %d", addr, i); goto end; } 235347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (opt.r.resrec.RecordType != kDNSRecordTypePacketNegative && opt.r.resrec.rrtype == kDNSType_OPT) break; 235447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 235547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 235647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // validate OPT 235747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (opt.r.resrec.rrtype != kDNSType_OPT) { Log("Malformatted LLQ from %s: last Additional not an OPT RR", addr); goto end; } 235847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (opt.r.resrec.rdlength < pkt->msg.h.numQuestions * DNSOpt_LLQData_Space) { Log("Malformatted LLQ from %s: OPT RR to small (%d bytes for %d questions)", addr, opt.r.resrec.rdlength, pkt->msg.h.numQuestions); } 235947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 236047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // dispatch each question 236147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < pkt->msg.h.numQuestions; i++) 236247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 236347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt qptr = getQuestion(&pkt->msg, qptr, end, 0, &q); 236447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!qptr) { Log("Malformatted LLQ from %s: cannot read question %d", addr, i); goto end; } 236547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt llq = (LLQOptData *)&opt.r.resrec.rdata->u.opt[0].u.llq + i; // point into OptData at index i 236647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (llq->vers != kLLQ_Vers) { Log("LLQ from %s contains bad version %d (expected %d)", addr, llq->vers, kLLQ_Vers); goto end; } 236747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 236847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e = LookupLLQ(d, pkt->src, &q.qname, q.qtype, &llq->id); 236947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!e) 237047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 237147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // no entry - if zero ID, create new 237247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e = NewLLQ(d, pkt->src, &q.qname, q.qtype, llq->llqlease ); 237347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!e) goto end; 237447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 237547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt UpdateLLQ(d, e, llq, pkt->msg.h.id, sock); 237647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 237747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = 0; 237847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 237947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end: 238047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(pkt); 238147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 238247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 238347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 238447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 238547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSBool IsAuthorized( DaemonInfo * d, PktMsg * pkt, DomainAuthInfo ** key, mDNSu16 * rcode, mDNSu16 * tcode ) 238647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 238747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 * lastPtr = NULL; 238847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 * ptr = NULL; 238947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DomainAuthInfo * keys; 239047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 * end = ( mDNSu8* ) &pkt->msg + pkt->len; 239147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LargeCacheRecord lcr; 239247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool hasTSIG = mDNSfalse; 239347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool strip = mDNSfalse; 239447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool ok = mDNSfalse; 239547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i; 239647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 239747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Unused parameters 239847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 239947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( void ) d; 240047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 240147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrNToH(pkt); 240247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 240347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *key = NULL; 240447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 240547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( pkt->msg.h.numAdditionals ) 240647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 240747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = LocateAdditionals(&pkt->msg, end); 240847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (ptr) 240947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 241047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < pkt->msg.h.numAdditionals; i++) 241147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 241247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt lastPtr = ptr; 241347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); 241447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ptr) 241547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 241647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Unable to read additional record"); 241747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt lastPtr = NULL; 241847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 241947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 242047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 242147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 242247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hasTSIG = ( ptr && lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rrtype == kDNSType_TSIG ); 242347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 242447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 242547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 242647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogMsg( "IsAuthorized: unable to find Additional section" ); 242747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 242847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 242947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 243047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // If we don't know what zone this is, then it's authorized. 243147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 243247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( !pkt->zone ) 243347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 243447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ok = mDNStrue; 243547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strip = mDNSfalse; 243647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto exit; 243747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 243847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 243947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( IsQuery( pkt ) ) 244047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 244147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt keys = pkt->zone->queryKeys; 244247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strip = mDNStrue; 244347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 244447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if ( IsUpdate( pkt ) ) 244547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 244647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt keys = pkt->zone->updateKeys; 244747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strip = mDNSfalse; 244847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 244947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 245047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 245147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ok = mDNStrue; 245247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strip = mDNSfalse; 245347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto exit; 245447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 245547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 245647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( pkt->isZonePublic ) 245747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 245847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ok = mDNStrue; 245947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto exit; 246047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 246147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 246247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // If there are no keys, then we're authorized 246347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 246447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( ( hasTSIG && !keys ) || ( !hasTSIG && keys ) ) 246547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 246647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log( "Invalid TSIG spec %##s for zone %##s", lcr.r.resrec.name->c, pkt->zone->name.c ); 246747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *rcode = kDNSFlag1_RC_NotAuth; 246847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *tcode = TSIG_ErrBadKey; 246947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strip = mDNStrue; 247047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ok = mDNSfalse; 247147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto exit; 247247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 247347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 247447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Find the right key 247547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 247647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( *key = keys; *key; *key = (*key)->next ) 247747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 247847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( SameDomainName( lcr.r.resrec.name, &(*key)->keyname ) ) 247947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 248047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 248147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 248247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 248347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 248447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( !(*key) ) 248547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 248647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log( "Invalid TSIG name %##s for zone %##s", lcr.r.resrec.name->c, pkt->zone->name.c ); 248747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *rcode = kDNSFlag1_RC_NotAuth; 248847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *tcode = TSIG_ErrBadKey; 248947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strip = mDNStrue; 249047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ok = mDNSfalse; 249147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto exit; 249247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 249347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 249447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Okay, we have the correct key and a TSIG record. DNSDigest_VerifyMessage does the heavy 249547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // lifting of message verification 249647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 249747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->msg.h.numAdditionals--; 249847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 249947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN( pkt ); 250047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 250147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ok = DNSDigest_VerifyMessage( &pkt->msg, ( mDNSu8* ) lastPtr, &lcr, (*key), rcode, tcode ); 250247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 250347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrNToH( pkt ); 250447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 250547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->msg.h.numAdditionals++; 250647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 250747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 250847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 250947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( hasTSIG && strip ) 251047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 251147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Strip the TSIG from the message 251247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 251347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->msg.h.numAdditionals--; 251447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt->len = lastPtr - ( mDNSu8* ) ( &pkt->msg ); 251547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 251647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 251747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt HdrHToN(pkt); 251847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 251947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return ok; 252047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 252147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 252247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// request handler wrappers for TCP and UDP requests 252347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// (read message off socket, fork thread that invokes main processing routine and handles cleanup) 252447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 252547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void* 252647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltUDPMessageHandler 252747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 252847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt void * vptr 252947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 253047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 253147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt UDPContext * context = ( UDPContext* ) vptr; 253247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * reply = NULL; 253347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int res; 253447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err; 253547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 253647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // !!!KRS strictly speaking, we shouldn't use TCP for a UDP request because the server 253747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // may give us a long answer that would require truncation for UDP delivery to client 253847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 253947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = HandleRequest( context->d, &context->pkt ); 254047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( reply, exit, err = mStatus_UnknownErr ); 254147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 254247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt res = sendto( context->sd, &reply->msg, reply->len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) ); 254347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( res == ( int ) reply->len, exit, LogErr( "UDPMessageHandler", "sendto" ) ); 254447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 254547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 254647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 254747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( reply ) 254847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 254947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free( reply ); 255047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 255147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 255247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free( context ); 255347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 255447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pthread_exit( NULL ); 255547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 255647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return NULL; 255747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 255847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 255947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 256047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int 256147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltRecvUDPMessage 256247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 256347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo * self, 256447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int sd 256547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 256647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 256747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt UDPContext * context = NULL; 256847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pthread_t tid; 256947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 rcode; 257047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 tcode; 257147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DomainAuthInfo * key; 257247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt unsigned int clisize = sizeof( context->cliaddr ); 257347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int res; 257447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err = mStatus_NoError; 257547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 257647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt context = malloc( sizeof( UDPContext ) ); 257747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( context, exit, err = mStatus_NoMemoryErr ; LogErr( "RecvUDPMessage", "malloc" ) ); 257847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 257947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero( context, sizeof( *context ) ); 258047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt context->d = self; 258147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt context->sd = sd; 258247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 258347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt res = recvfrom(sd, &context->pkt.msg, sizeof(context->pkt.msg), 0, (struct sockaddr *)&context->cliaddr, &clisize); 258447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 258547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( res >= 0, exit, err = mStatus_UnknownErr ; LogErr( "RecvUDPMessage", "recvfrom" ) ); 258647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt context->pkt.len = res; 258747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( clisize == sizeof( context->cliaddr ), exit, err = mStatus_UnknownErr ; Log( "Client address of unknown size %d", clisize ) ); 258847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt context->pkt.src = context->cliaddr; 258947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 259047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Set the zone in the packet 259147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 259247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt SetZone( context->d, &context->pkt ); 259347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 259447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Notify messages handled by main thread 259547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 259647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( IsNotify( &context->pkt ) ) 259747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 259847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int e = RecvNotify( self, &context->pkt ); 259947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(context); 260047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return e; 260147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 260247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) ) 260347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 260447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( IsLLQRequest( &context->pkt ) ) 260547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 260647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // LLQ messages handled by main thread 260747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int e = RecvLLQ( self, &context->pkt, NULL ); 260847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(context); 260947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return e; 261047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 261147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 261247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( IsLLQAck(&context->pkt ) ) 261347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 261447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // !!!KRS need to do acks + retrans 261547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 261647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(context); 261747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return 0; 261847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 261947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 262047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = pthread_create( &tid, NULL, UDPMessageHandler, context ); 262147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "RecvUDPMessage", "pthread_create" ) ); 262247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 262347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pthread_detach(tid); 262447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 262547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 262647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 262747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg reply; 262847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int e; 262947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 263047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt memcpy( &reply, &context->pkt, sizeof( PktMsg ) ); 263147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 263247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply.msg.h.flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD; 263347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply.msg.h.flags.b[1] = kDNSFlag1_RA | kDNSFlag1_RC_NXDomain; 263447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 263547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt e = sendto( sd, &reply.msg, reply.len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) ); 263647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( e == ( int ) reply.len, exit, LogErr( "RecvUDPMessage", "sendto" ) ); 263747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 263847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = mStatus_NoAuth; 263947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 264047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 264147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 264247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 264347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( err && context ) 264447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 264547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free( context ); 264647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 264747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 264847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 264947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 265047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 265147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 265247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void 265347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltFreeTCPContext 265447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 265547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPContext * context 265647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 265747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 265847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( context ) 265947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 266047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( context->sock ) 266147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 266247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformTCPCloseConnection( context->sock ); 266347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 266447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 266547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free( context ); 266647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 266747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 266847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 266947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 267047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void* 267147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltTCPMessageHandler 267247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 267347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt void * vptr 267447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 267547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 267647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPContext * context = ( TCPContext* ) vptr; 267747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * reply = NULL; 267847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int res; 267947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buf[32]; 268047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 268147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt //!!!KRS if this read blocks indefinitely, we can run out of threads 268247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // read the request 268347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 268447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply = HandleRequest( context->d, &context->pkt ); 268547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action_quiet( reply, exit, LogMsg( "TCPMessageHandler: No reply for client %s", inet_ntop( AF_INET, &context->cliaddr.sin_addr, buf, 32 ) ) ); 268647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 268747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // deliver reply to client 268847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 268947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt res = SendPacket( context->sock, reply ); 269047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( res >= 0, exit, LogMsg("TCPMessageHandler: Unable to send reply to client %s", inet_ntop(AF_INET, &context->cliaddr.sin_addr, buf, 32 ) ) ); 269147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 269247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 269347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 269447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FreeTCPContext( context ); 269547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 269647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( reply ) 269747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 269847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free( reply ); 269947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 270047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 270147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pthread_exit(NULL); 270247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 270347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 270447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 270547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void 270647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltRecvTCPMessage 270747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 270847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt void * param 270947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 271047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 271147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPContext * context = ( TCPContext* ) param; 271247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 rcode; 271347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 tcode; 271447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pthread_t tid; 271547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DomainAuthInfo * key; 271647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg * pkt; 271747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool closed; 271847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool freeContext = mDNStrue; 271947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err = mStatus_NoError; 272047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 272147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Receive a packet. It's okay if we don't actually read a packet, as long as the closed flag is 272247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // set to false. This is because SSL/TLS layer might gobble up the first packet that we read off the 272347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // wire. We'll let it do that, and wait for the next packet which will be ours. 272447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 272547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pkt = RecvPacket( context->sock, &context->pkt, &closed ); 272647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (pkt) HdrNToH(pkt); 272747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( pkt || !closed, exit, err = mStatus_UnknownErr; LogMsg( "client disconnected" ) ); 272847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 272947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( pkt ) 273047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 273147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Always do this, regardless of what kind of packet it is. If we wanted LLQ events to be sent over TCP, 273247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // we would change this line of code. As it is now, we will reply to an LLQ via TCP, but then events 273347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // are sent over UDP 273447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 273547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RemoveSourceFromEventLoop( context->d, context->sock ); 273647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 273747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Set's the DNS Zone that is associated with this message 273847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 273947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt SetZone( context->d, &context->pkt ); 274047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 274147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // IsAuthorized will make sure the message is authorized for the designated zone. 274247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // After verifying the signature, it will strip the TSIG from the message 274347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 274447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) ) 274547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 274647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( IsLLQRequest( &context->pkt ) ) 274747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 274847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // LLQ messages handled by main thread 274947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RecvLLQ( context->d, &context->pkt, context->sock); 275047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 275147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 275247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 275347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = pthread_create( &tid, NULL, TCPMessageHandler, context ); 275447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 275547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( err ) 275647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 275747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr( "RecvTCPMessage", "pthread_create" ); 275847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = mStatus_NoError; 275947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto exit; 276047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 276147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 276247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Let the thread free the context 276347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 276447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt freeContext = mDNSfalse; 276547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 276647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt pthread_detach(tid); 276747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 276847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 276947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 277047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 277147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PktMsg reply; 277247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 277347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogMsg( "Client %s Not authorized for zone %##s", inet_ntoa( context->pkt.src.sin_addr ), pkt->zone->name.c ); 277447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 277547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt memcpy( &reply, &context->pkt, sizeof( PktMsg ) ); 277647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 277747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply.msg.h.flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD; 277847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt reply.msg.h.flags.b[1] = kDNSFlag1_RA | kDNSFlag1_RC_Refused; 277947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 278047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt SendPacket( context->sock, &reply ); 278147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 278247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 278347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 278447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 278547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt freeContext = mDNSfalse; 278647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 278747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 278847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 278947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 279047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( err ) 279147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 279247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RemoveSourceFromEventLoop( context->d, context->sock ); 279347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 279447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 279547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( freeContext ) 279647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 279747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FreeTCPContext( context ); 279847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 279947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 280047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 280147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 280247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int 280347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltAcceptTCPConnection 280447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 280547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo * self, 280647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int sd, 280747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPSocketFlags flags 280847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 280947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 281047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt TCPContext * context = NULL; 281147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt unsigned int clilen = sizeof( context->cliaddr); 281247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int newSock; 281347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err = mStatus_NoError; 281447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 281547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt context = ( TCPContext* ) malloc( sizeof( TCPContext ) ); 281647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( context, exit, err = mStatus_NoMemoryErr; LogErr( "AcceptTCPConnection", "malloc" ) ); 281747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero( context, sizeof( sizeof( TCPContext ) ) ); 281847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt context->d = self; 281947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt newSock = accept( sd, ( struct sockaddr* ) &context->cliaddr, &clilen ); 282047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( newSock != -1, exit, err = mStatus_UnknownErr; LogErr( "AcceptTCPConnection", "accept" ) ); 282147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 282247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt context->sock = mDNSPlatformTCPAccept( flags, newSock ); 282347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( context->sock, exit, err = mStatus_UnknownErr; LogErr( "AcceptTCPConnection", "mDNSPlatformTCPAccept" ) ); 282447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 282547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = AddSourceToEventLoop( self, context->sock, RecvTCPMessage, context ); 282647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( !err, exit, LogErr( "AcceptTCPConnection", "AddSourceToEventLoop" ) ); 282747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 282847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 282947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 283047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( err && context ) 283147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 283247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free( context ); 283347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt context = NULL; 283447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 283547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 283647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 283747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 283847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 283947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 284047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// main event loop 284147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// listen for incoming requests, periodically check table for expired records, respond to signals 284247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int Run(DaemonInfo *d) 284347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 284447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int staticMaxFD, nfds; 284547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd_set rset; 284647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval timenow, timeout, EventTS, tablecheck = { 0, 0 }; 284747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool EventsPending = mDNSfalse; 284847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 284947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt VLog("Listening for requests..."); 285047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 285147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt staticMaxFD = 0; 285247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 285347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( d->tcpsd + 1 > staticMaxFD ) staticMaxFD = d->tcpsd + 1; 285447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( d->udpsd + 1 > staticMaxFD ) staticMaxFD = d->udpsd + 1; 285547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( d->tlssd + 1 > staticMaxFD ) staticMaxFD = d->tlssd + 1; 285647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( d->llq_tcpsd + 1 > staticMaxFD ) staticMaxFD = d->llq_tcpsd + 1; 285747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( d->llq_udpsd + 1 > staticMaxFD ) staticMaxFD = d->llq_udpsd + 1; 285847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( d->LLQEventListenSock + 1 > staticMaxFD ) staticMaxFD = d->LLQEventListenSock + 1; 285947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 286047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while(1) 286147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 286247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt EventSource * source; 286347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int maxFD; 286447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 286547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // set timeout 286647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt timeout.tv_sec = timeout.tv_usec = 0; 286747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gettimeofday(&timenow, NULL)) { LogErr("Run", "gettimeofday"); return -1; } 286847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 286947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (EventsPending) 287047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 287147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (timenow.tv_sec - EventTS.tv_sec >= 5) // if we've been waiting 5 seconds for a "quiet" period to send 287247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { GenLLQEvents(d); EventsPending = mDNSfalse; } // events, we go ahead and do it now 287347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else timeout.tv_usec = 500000; // else do events after 1/2 second with no new events or LLQs 287447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 287547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!EventsPending) 287647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 287747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // if no pending events, timeout when we need to check for expired records 287847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (tablecheck.tv_sec && timenow.tv_sec - tablecheck.tv_sec >= 0) 287947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; } // table check overdue 288047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!tablecheck.tv_sec) tablecheck.tv_sec = timenow.tv_sec + EXPIRATION_INTERVAL; 288147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt timeout.tv_sec = tablecheck.tv_sec - timenow.tv_sec; 288247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 288347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 288447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_ZERO(&rset); 288547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET( d->tcpsd, &rset ); 288647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET( d->udpsd, &rset ); 288747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET( d->tlssd, &rset ); 288847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET( d->llq_tcpsd, &rset ); 288947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET( d->llq_udpsd, &rset ); 289047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET( d->LLQEventListenSock, &rset ); 289147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 289247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt maxFD = staticMaxFD; 289347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 289447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( source = ( EventSource* ) d->eventSources.Head; source; source = source->next ) 289547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 289647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_SET( source->fd, &rset ); 289747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 289847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( source->fd > maxFD ) 289947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 290047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt maxFD = source->fd; 290147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 290247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 290347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 290447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt nfds = select( maxFD + 1, &rset, NULL, NULL, &timeout); 290547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (nfds < 0) 290647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 290747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (errno == EINTR) 290847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 290947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (terminate) 291047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 291147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // close sockets to prevent clients from making new requests during shutdown 291247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt close( d->tcpsd ); 291347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt close( d->udpsd ); 291447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt close( d->tlssd ); 291547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt close( d->llq_tcpsd ); 291647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt close( d->llq_udpsd ); 291747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->tcpsd = d->udpsd = d->tlssd = d->llq_tcpsd = d->llq_udpsd = -1; 291847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DeleteRecords(d, mDNStrue); 291947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return 0; 292047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 292147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (dumptable) 292247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 292347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log( "Received SIGINFO" ); 292447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 292547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintLeaseTable(d); 292647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintLLQTable(d); 292747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintLLQAnswers(d); 292847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt dumptable = 0; 292947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 293047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (hangup) 293147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 293247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int err; 293347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 293447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log( "Received SIGHUP" ); 293547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 293647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt err = ParseConfig( d, cfgfile ); 293747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 293847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( err ) 293947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 294047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr( "Run", "ParseConfig" ); 294147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return -1; 294247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 294347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 294447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hangup = 0; 294547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 294647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 294747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 294847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Received unhandled signal - continuing"); 294947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 295047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 295147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 295247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 295347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr("Run", "select"); return -1; 295447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 295547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 295647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (nfds) 295747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 295847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (FD_ISSET(d->udpsd, &rset)) RecvUDPMessage( d, d->udpsd ); 295947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (FD_ISSET(d->llq_udpsd, &rset)) RecvUDPMessage( d, d->llq_udpsd ); 296047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (FD_ISSET(d->tcpsd, &rset)) AcceptTCPConnection( d, d->tcpsd, 0 ); 296147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (FD_ISSET(d->llq_tcpsd, &rset)) AcceptTCPConnection( d, d->llq_tcpsd, 0 ); 296247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (FD_ISSET(d->tlssd, &rset)) AcceptTCPConnection( d, d->tlssd, TCP_SOCKET_FLAGS ); 296347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (FD_ISSET(d->LLQEventListenSock, &rset)) 296447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 296547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // clear signalling data off socket 296647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buf[256]; 296747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt recv(d->LLQEventListenSock, buf, 256, 0); 296847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!EventsPending) 296947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 297047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt EventsPending = mDNStrue; 297147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gettimeofday(&EventTS, NULL)) { LogErr("Run", "gettimeofday"); return -1; } 297247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 297347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 297447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 297547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for ( source = ( EventSource* ) d->eventSources.Head; source; source = source->next ) 297647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 297747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( FD_ISSET( source->fd, &rset ) ) 297847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 297947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt source->callback( source->context ); 298047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; // in case we removed this guy from the event loop 298147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 298247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 298347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 298447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 298547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 298647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // timeout 298747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (EventsPending) { GenLLQEvents(d); EventsPending = mDNSfalse; } 298847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; } 298947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 299047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 299147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return 0; 299247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 299347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 299447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// signal handler sets global variables, which are inspected by main event loop 299547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// (select automatically returns due to the handled signal) 299647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void HndlSignal(int sig) 299747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 299847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (sig == SIGTERM || sig == SIGINT ) { terminate = 1; return; } 299947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (sig == INFO_SIGNAL) { dumptable = 1; return; } 300047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (sig == SIGHUP) { hangup = 1; return; } 300147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 300247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 300347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mStatus 300447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltSetPublicSRV 300547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ( 300647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo * d, 300747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const char * name 300847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ) 300947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 301047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNameListElem * elem; 301147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus err = mStatus_NoError; 301247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 301347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt elem = ( DNameListElem* ) malloc( sizeof( DNameListElem ) ); 301447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt require_action( elem, exit, err = mStatus_NoMemoryErr ); 301547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainNameFromDNSNameString( &elem->name, name ); 301647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt elem->next = d->public_names; 301747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d->public_names = elem; 301847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 301947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltexit: 302047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 302147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return err; 302247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 302347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 302447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 302547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint main(int argc, char *argv[]) 302647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 302747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int started_via_launchd = 0; 302847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DaemonInfo *d; 302947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct rlimit rlim; 303047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 303147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("dnsextd starting"); 303247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 303347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt d = malloc(sizeof(*d)); 303447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!d) { LogErr("main", "malloc"); exit(1); } 303547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemZero(d, sizeof(DaemonInfo)); 303647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 303747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Setup the public SRV record names 303847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 303947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt SetPublicSRV(d, "_dns-update._udp."); 304047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt SetPublicSRV(d, "_dns-llq._udp."); 304147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt SetPublicSRV(d, "_dns-update-tls._tcp."); 304247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt SetPublicSRV(d, "_dns-query-tls._tcp."); 304347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt SetPublicSRV(d, "_dns-llq-tls._tcp."); 304447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 304547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Setup signal handling 304647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 304747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (signal(SIGHUP, HndlSignal) == SIG_ERR) perror("Can't catch SIGHUP"); 304847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (signal(SIGTERM, HndlSignal) == SIG_ERR) perror("Can't catch SIGTERM"); 304947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (signal(INFO_SIGNAL, HndlSignal) == SIG_ERR) perror("Can't catch SIGINFO"); 305047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (signal(SIGINT, HndlSignal) == SIG_ERR) perror("Can't catch SIGINT"); 305147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (signal(SIGPIPE, SIG_IGN ) == SIG_ERR) perror("Can't ignore SIGPIPE"); 305247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 305347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // remove open file limit 305447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rlim.rlim_max = RLIM_INFINITY; 305547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt rlim.rlim_cur = RLIM_INFINITY; 305647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) 305747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 305847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr("main", "setrlimit"); 305947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("Using default file descriptor resource limit"); 306047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 306147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 306247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (argc > 1 && !strcasecmp(argv[1], "-launchd")) 306347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 306447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("started_via_launchd"); 306547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt started_via_launchd = 1; 306647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt argv++; 306747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt argc--; 306847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 306947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (ProcessArgs(argc, argv, d) < 0) { LogErr("main", "ProcessArgs"); exit(1); } 307047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 307147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!foreground && !started_via_launchd) 307247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 307347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (daemon(0,0)) 307447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 307547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt LogErr("main", "daemon"); 307647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt foreground = 1; 307747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 307847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 307947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 308047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (InitLeaseTable(d) < 0) { LogErr("main", "InitLeaseTable"); exit(1); } 308147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (SetupSockets(d) < 0) { LogErr("main", "SetupSockets"); exit(1); } 308247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (SetUpdateSRV(d) < 0) { LogErr("main", "SetUpdateSRV"); exit(1); } 308347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 308447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Run(d); 308547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 308647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt Log("dnsextd stopping"); 308747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 308847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (ClearUpdateSRV(d) < 0) { LogErr("main", "ClearUpdateSRV"); exit(1); } // clear update srv's even if Run or pthread_create returns an error 308947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(d); 309047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(0); 309147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 309247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 309347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 309447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// These are stubbed out implementations of up-call routines that the various platform support layers 309547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// call. These routines are fully implemented in both mDNS.c and uDNS.c, but dnsextd doesn't 309647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// link this code in. 309747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 309847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// It's an error for these routines to actually be called, so perhaps we should log any call 309947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// to them. 310047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNSCoreInitComplete( mDNS * const m, mStatus result) { ( void ) m; ( void ) result; } 310147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNS_ConfigChanged(mDNS *const m) { ( void ) m; } 310247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNSCoreMachineSleep(mDNS * const m, mDNSBool wake) { ( void ) m; ( void ) wake; } 310347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end, 310447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSAddr *const srcaddr, const mDNSIPPort srcport, 310547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSAddr *const dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID iid) 310647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { ( void ) m; ( void ) msg; ( void ) end; ( void ) srcaddr; ( void ) srcport; ( void ) dstaddr; ( void ) dstport; ( void ) iid; } 310747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltDNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped, mDNSu32 timeout) 310847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { ( void ) m; ( void ) d; ( void ) interface; ( void ) addr; ( void ) port; ( void ) scoped; ( void ) timeout; return(NULL); } 310947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID) { (void)domain; (void) InterfaceID;} 311047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext) 311147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { ( void ) m; ( void ) fqdn; ( void ) StatusCallback; ( void ) StatusContext; } 311247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSs32 mDNS_Execute (mDNS *const m) { ( void ) m; return 0; } 311347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSs32 mDNS_TimeNow(const mDNS *const m) { ( void ) m; return 0; } 311447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr) { ( void ) m; ( void ) rr; return 0; } 311547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) 311647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { ( void ) m; ( void ) set; ( void ) flapping; } 311747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char * const mDNS_DomainTypeNames[1] = {}; 311847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom, 311947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context) 312047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { ( void ) m; ( void ) question; ( void ) DomainType; ( void ) dom; ( void ) InterfaceID; ( void ) Callback; ( void ) Context; return 0; } 312147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNS_Register(mDNS *const m, AuthRecord *const rr) { ( void ) m; ( void ) rr; return 0; } 312247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) 312347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { ( void ) m; ( void ) set; ( void ) flapping; return 0; } 312447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn) { ( void ) m; ( void ) fqdn; } 312547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNS_SetFQDN(mDNS * const m) { ( void ) m; } 312647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router) 312747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { ( void ) m; ( void ) v4addr; ( void ) v6addr; ( void ) router; } 312847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus uDNS_SetupDNSConfig( mDNS *const m ) { ( void ) m; return 0; } 312947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info, 313047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port, const char *autoTunnelPrefix) 313147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { ( void ) m; ( void ) info; ( void ) domain; ( void ) keyname; ( void ) b64keydata; ( void ) hostname; (void) port; ( void ) autoTunnelPrefix; return 0; } 313247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question) { ( void ) m; ( void ) question; return 0; } 313347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid TriggerEventCompletion(void); 313447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid TriggerEventCompletion() {} 313547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNS mDNSStorage; 313647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 313747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 313847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// For convenience when using the "strings" command, this is the last thing in the file 313947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// The "@(#) " pattern is a special prefix the "what" command looks for 314047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char mDNSResponderVersionString_SCCS[] = "@(#) dnsextd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")"; 314147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 314247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if _BUILDING_XCODE_PROJECT_ 314347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// If the process crashes, then this string will be magically included in the automatically-generated crash log 314447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5; 314547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltasm(".desc ___crashreporter_info__, 0x10"); 314647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 3147