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#include <stdio.h> // For printf() 1947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdlib.h> // For exit() etc. 2047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <string.h> // For strlen() etc. 2147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <unistd.h> // For select() 2247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <signal.h> // For SIGINT, SIGTERM 2347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <errno.h> // For errno, EINTR 2447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netinet/in.h> // For INADDR_NONE 2547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <arpa/inet.h> // For inet_addr() 2647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netdb.h> // For gethostbyname() 2747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 2847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSEmbeddedAPI.h" // Defines the interface to the client layer above 2947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform 3047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "ExampleClientApp.h" 3147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 3247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Compatibility workaround: Solaris 2.5 has no INADDR_NONE 3347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef INADDR_NONE 3447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define INADDR_NONE (mDNSu32)0xffffffff 3547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 3647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 3747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 3847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Globals 3947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNS mDNSStorage; // mDNS core uses this to store its globals 4047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals 4147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport const char ProgramName[] = "mDNSProxyResponderPosix"; 4247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 4347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 4447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Proxy Host Registration 4547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 4647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct 4747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 4847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSv4Addr ip; 4947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainlabel hostlabel; // Conforms to standard DNS letter-digit-hyphen host name rules 5047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AuthRecord RR_A; // 'A' (address) record for our ".local" name 5147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AuthRecord RR_PTR; // PTR (reverse lookup) record 5247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } ProxyHost; 5347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 5447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result) 5547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 5647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ProxyHost *f = (ProxyHost*)rr->RecordContext; 5747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result == mStatus_NoError) 5847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("Host name successfully registered: %##s", rr->resrec.name->c); 5947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 6047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 6147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("Host name conflict for %##s", rr->resrec.name->c); 6247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Deregister(m, &f->RR_A); 6347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Deregister(m, &f->RR_PTR); 6447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(-1); 6547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 6647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 6747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 6847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mStatus mDNS_RegisterProxyHost(mDNS *m, ProxyHost *p) 6947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 7047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer[32]; 7147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 7247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_SetupResourceRecord(&p->RR_A, mDNSNULL, mDNSInterface_Any, kDNSType_A, 60, kDNSRecordTypeUnique, AuthRecordAny, HostNameCallback, p); 7347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_SetupResourceRecord(&p->RR_PTR, mDNSNULL, mDNSInterface_Any, kDNSType_PTR, 60, kDNSRecordTypeKnownUnique, AuthRecordAny, HostNameCallback, p); 7447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 7547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt p->RR_A.namestorage.c[0] = 0; 7647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AppendDomainLabel(&p->RR_A.namestorage, &p->hostlabel); 7747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AppendLiteralLabelString(&p->RR_A.namestorage, "local"); 7847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 7947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code 8047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p->ip.b[3], p->ip.b[2], p->ip.b[1], p->ip.b[0]); 8147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainNameFromDNSNameString(&p->RR_PTR.namestorage, buffer); 8247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt p->RR_PTR.ForceMCast = mDNStrue; // This PTR points to our dot-local name, so don't ever try to write it into a uDNS server 8347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 8447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt p->RR_A. resrec.rdata->u.ipv4 = p->ip; 8547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AssignDomainName(&p->RR_PTR.resrec.rdata->u.name, p->RR_A.resrec.name); 8647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 8747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Register(m, &p->RR_A); 8847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Register(m, &p->RR_PTR); 8947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 9047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("Made Proxy Host Records for %##s", p->RR_A.resrec.name->c); 9147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 9247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(mStatus_NoError); 9347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 9447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 9547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 9647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Service Registration 9747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 9847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// This sample ServiceCallback just calls mDNS_RenameAndReregisterService to automatically pick a new 9947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// unique name for the service. For a device such as a printer, this may be appropriate. 10047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// For a device with a user interface, and a screen, and a keyboard, the appropriate 10147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// response may be to prompt the user and ask them to choose a new name for the service. 10247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void ServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result) 10347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 10447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt switch (result) 10547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 10647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case mStatus_NoError: debugf("Callback: %##s Name Registered", sr->RR_SRV.resrec.name->c); break; 10747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", sr->RR_SRV.resrec.name->c); break; 10847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case mStatus_MemFree: debugf("Callback: %##s Memory Free", sr->RR_SRV.resrec.name->c); break; 10947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt default: debugf("Callback: %##s Unknown Result %ld", sr->RR_SRV.resrec.name->c, result); break; 11047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 11147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 11247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result == mStatus_NoError) 11347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 11447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer[MAX_ESCAPED_DOMAIN_NAME]; 11547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer); 11647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("Service %s now registered and active\n", buffer); 11747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 11847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 11947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result == mStatus_NameConflict) 12047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 12147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer1[MAX_ESCAPED_DOMAIN_NAME], buffer2[MAX_ESCAPED_DOMAIN_NAME]; 12247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer1); 12347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_RenameAndReregisterService(m, sr, mDNSNULL); 12447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer2); 12547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("Name Conflict! %s renamed as %s\n", buffer1, buffer2); 12647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 12747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 12847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 12947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// RegisterService() is a simple wrapper function which takes C string 13047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// parameters, converts them to domainname parameters, and calls mDNS_RegisterService() 13147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void RegisterService(mDNS *m, ServiceRecordSet *recordset, 13247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const char name[], const char type[], const char domain[], 13347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const domainname *host, mDNSu16 PortAsNumber, int argc, char **argv) 13447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 13547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainlabel n; 13647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainname t, d; 13747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt unsigned char txtbuffer[1024], *bptr = txtbuffer; 13847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer[MAX_ESCAPED_DOMAIN_NAME]; 13947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 14047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainLabelFromLiteralString(&n, name); 14147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainNameFromDNSNameString(&t, type); 14247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainNameFromDNSNameString(&d, domain); 14347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (argc) 14447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 14547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int len = strlen(argv[0]); 14647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (len > 255 || bptr + 1 + len >= txtbuffer + sizeof(txtbuffer)) break; 14747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("STR: %s\n", argv[0]); 14847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt bptr[0] = len; 14947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strcpy((char*)(bptr+1), argv[0]); 15047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt bptr += 1 + len; 15147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt argc--; 15247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt argv++; 15347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 15447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 15547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_RegisterService(m, recordset, 15647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt &n, &t, &d, // Name, type, domain 15747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt host, mDNSOpaque16fromIntVal(PortAsNumber), 15847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt txtbuffer, bptr-txtbuffer, // TXT data, length 15947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSNULL, 0, // Subtypes 16047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSInterface_Any, // Interface ID 16147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ServiceCallback, mDNSNULL, 0); // Callback, context, flags 16247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 16347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ConvertDomainNameToCString(recordset->RR_SRV.resrec.name, buffer); 16447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("Made Service Records for %s\n", buffer); 16547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 16647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 16747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 16847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Service non-existence assertion 16947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// (claiming a service name without actually providing a service at that name, to prevent anyone else using that name) 17047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// This is useful to avoid confusion between similar services 17147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// e.g. A printer that implements IPP printing service using the name "My Printer", but doesn't implement LPR service, 17247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// should also claim the LPR service name "My Printer" to stop a different printer offering LPR service under the same name, 17347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// since it would be confusing to users to have two equivalent services with the same name. 17447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 17547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void NoSuchServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus result) 17647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 17747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const domainname *proxyhostname = (const domainname *)rr->RecordContext; 17847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt switch (result) 17947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 18047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case mStatus_NoError: debugf("Callback: %##s Name Registered", rr->resrec.name->c); break; 18147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", rr->resrec.name->c); break; 18247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case mStatus_MemFree: debugf("Callback: %##s Memory Free", rr->resrec.name->c); break; 18347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt default: debugf("Callback: %##s Unknown Result %ld", rr->resrec.name->c, result); break; 18447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 18547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 18647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result == mStatus_NoError) 18747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 18847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer[MAX_ESCAPED_DOMAIN_NAME]; 18947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ConvertDomainNameToCString(rr->resrec.name, buffer); 19047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("Non-existence assertion %s now registered and active\n", buffer); 19147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 19247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 19347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result == mStatus_NameConflict) 19447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 19547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainlabel n; 19647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainname t, d; 19747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer1[MAX_ESCAPED_DOMAIN_NAME], buffer2[MAX_ESCAPED_DOMAIN_NAME]; 19847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ConvertDomainNameToCString(rr->resrec.name, buffer1); 19947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DeconstructServiceName(rr->resrec.name, &n, &t, &d); 20047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt IncrementLabelSuffix(&n, mDNStrue); 20147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_RegisterNoSuchService(m, rr, &n, &t, &d, proxyhostname, mDNSInterface_Any, NoSuchServiceCallback, mDNSNULL, mDNSfalse); 20247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ConvertDomainNameToCString(rr->resrec.name, buffer2); 20347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("Name Conflict! %s renamed as %s\n", buffer1, buffer2); 20447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 20547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 20647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 20747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void RegisterNoSuchService(mDNS *m, AuthRecord *const rr, domainname *proxyhostname, 20847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const char name[], const char type[], const char domain[]) 20947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 21047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainlabel n; 21147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainname t, d; 21247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer[MAX_ESCAPED_DOMAIN_NAME]; 21347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainLabelFromLiteralString(&n, name); 21447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainNameFromDNSNameString(&t, type); 21547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainNameFromDNSNameString(&d, domain); 21647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_RegisterNoSuchService(m, rr, &n, &t, &d, proxyhostname, mDNSInterface_Any, NoSuchServiceCallback, proxyhostname, mDNSfalse); 21747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ConvertDomainNameToCString(rr->resrec.name, buffer); 21847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("Made Non-existence Record for %s\n", buffer); 21947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 22047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 22147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 22247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Main 22347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 22447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport int main(int argc, char **argv) 22547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 22647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus status; 22747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt sigset_t signals; 22847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 22947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (argc < 3) goto usage; 23047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 23147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mDNS_Init(&mDNSStorage, &PlatformStorage, 23247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize, 23347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Init_DontAdvertiseLocalAddresses, 23447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); 23547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); } 23647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 23747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPosixListenForSignalInEventLoop(SIGINT); 23847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPosixListenForSignalInEventLoop(SIGTERM); 23947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 24047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!strcmp(argv[1], "-")) 24147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 24247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainname proxyhostname; 24347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AuthRecord proxyrecord; 24447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (argc < 5) goto usage; 24547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt proxyhostname.c[0] = 0; 24647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AppendLiteralLabelString(&proxyhostname, argv[2]); 24747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt AppendLiteralLabelString(&proxyhostname, "local"); 24847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RegisterNoSuchService(&mDNSStorage, &proxyrecord, &proxyhostname, argv[3], argv[4], "local."); 24947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 25047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 25147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 25247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ProxyHost proxyhost; 25347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ServiceRecordSet proxyservice; 25447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 25547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt proxyhost.ip.NotAnInteger = inet_addr(argv[1]); 25647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (proxyhost.ip.NotAnInteger == INADDR_NONE) // INADDR_NONE is 0xFFFFFFFF 25747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 25847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct hostent *h = gethostbyname(argv[1]); 25947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (h) proxyhost.ip.NotAnInteger = *(long*)h->h_addr; 26047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 26147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (proxyhost.ip.NotAnInteger == INADDR_NONE) // INADDR_NONE is 0xFFFFFFFF 26247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 26347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s is not valid host address\n", argv[1]); 26447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(-1); 26547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 26647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainLabelFromLiteralString(&proxyhost.hostlabel, argv[2]); 26847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_RegisterProxyHost(&mDNSStorage, &proxyhost); 27047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 27147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (argc >=6) 27247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RegisterService(&mDNSStorage, &proxyservice, argv[3], argv[4], "local.", 27347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt proxyhost.RR_A.resrec.name, atoi(argv[5]), argc-6, &argv[6]); 27447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 27547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 27647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt do 27747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 27847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval timeout = { 0x3FFFFFFF, 0 }; // wait until SIGINT or SIGTERM 27947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool gotSomething; 28047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPosixRunEventLoopOnce(&mDNSStorage, &timeout, &signals, &gotSomething); 28147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 28247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while ( !( sigismember( &signals, SIGINT) || sigismember( &signals, SIGTERM))); 28347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 28447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Close(&mDNSStorage); 28547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 28647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(0); 28747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 28847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltusage: 28947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s ip hostlabel [srvname srvtype port txt [txt ...]]\n", argv[0]); 29047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "ip Real IP address (or valid host name) of the host where the service actually resides\n"); 29147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "hostlabel First label of the dot-local host name to create for this host, e.g. \"foo\" for \"foo.local.\"\n"); 29247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "srvname Descriptive name of service, e.g. \"Stuart's Ink Jet Printer\"\n"); 29347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "srvtype IANA service type, e.g. \"_ipp._tcp\" or \"_ssh._tcp\", etc.\n"); 29447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "port Port number where the service resides (1-65535)\n"); 29547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "txt Additional name/value pairs specified in service definition, e.g. \"pdl=application/postscript\"\n"); 29647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "e.g. %s 169.254.12.34 thehost (just create a dot-local host name)\n", argv[0]); 29747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "or %s 169.254.12.34 thehost \"My Printer\" _printer._tcp. 515 rp=lpt1 pdl=application/postscript\n", argv[0]); 29847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "or %s - thehost \"My Printer\" _printer._tcp. (assertion of non-existence)\n", argv[0]); 29947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(-1); 30047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 301