diff options
Diffstat (limited to 'mDNSResponder/mDNSMacOS9/Responder.c')
-rw-r--r-- | mDNSResponder/mDNSMacOS9/Responder.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSMacOS9/Responder.c b/mDNSResponder/mDNSMacOS9/Responder.c new file mode 100644 index 00000000..78851a62 --- /dev/null +++ b/mDNSResponder/mDNSMacOS9/Responder.c @@ -0,0 +1,183 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> // For printf() +#include <string.h> // For strcpy() + +#include <Events.h> // For WaitNextEvent() + +#include <OpenTransport.h> +#include <OpenTptInternet.h> + +#include <SIOUX.h> // For SIOUXHandleOneEvent() + +#include "dns_sd.h" + +typedef union { UInt8 b[2]; UInt16 NotAnInteger; } mDNSOpaque16; +static UInt16 mDNSVal16(mDNSOpaque16 x) { return((UInt16)(x.b[0]<<8 | x.b[1])); } +static mDNSOpaque16 mDNSOpaque16fromIntVal(UInt16 v) +{ mDNSOpaque16 x; x.b[0] = (UInt8)(v >> 8); x.b[1] = (UInt8)(v & 0xFF); return(x); } + +typedef struct RegisteredService_struct RegisteredService; +struct RegisteredService_struct +{ + RegisteredService *next; + DNSServiceRef sdRef; + Boolean gotresult; + DNSServiceErrorType errorCode; + char namestr[64]; + char typestr[kDNSServiceMaxDomainName]; + char domstr [kDNSServiceMaxDomainName]; +}; + +static RegisteredService p1, p2, afp, http, njp; +static RegisteredService *services = NULL, **nextservice = &services; + +static void RegCallback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, + const char *name, const char *regtype, const char *domain, void *context) +{ + RegisteredService *rs = (RegisteredService *)context; + (void)sdRef; // Unused + (void)flags; // Unused + rs->gotresult = true; + rs->errorCode = errorCode; + strcpy(rs->namestr, name); + strcpy(rs->typestr, regtype); + strcpy(rs->domstr, domain); +} + +static DNSServiceErrorType RegisterService(RegisteredService *rs, mDNSOpaque16 OpaquePort, + const char name[], const char type[], const char domain[], const char txtinfo[]) +{ + DNSServiceErrorType err; + unsigned char txtbuffer[257]; + strncpy((char*)txtbuffer+1, txtinfo, 255); + txtbuffer[256] = 0; + txtbuffer[0] = (unsigned char)strlen((char*)txtbuffer); + rs->gotresult = 0; + rs->errorCode = kDNSServiceErr_NoError; + err = DNSServiceRegister(&rs->sdRef, /* kDNSServiceFlagsAutoRename*/ 0, 0, + name, type, domain, NULL, OpaquePort.NotAnInteger, (unsigned short)(1+txtbuffer[0]), txtbuffer, RegCallback, rs); + if (err) + printf("RegisterService(%s %s %s) failed %d\n", name, type, domain, err); + else + { *nextservice = rs; nextservice = &rs->next; } + return(err); +} + +// RegisterFakeServiceForTesting() simulates the effect of services being registered on +// dynamically-allocated port numbers. No real service exists on that port -- this is just for testing. +static DNSServiceErrorType RegisterFakeServiceForTesting(RegisteredService *rs, + const char name[], const char type[], const char domain[], const char txtinfo[]) +{ + static UInt16 NextPort = 0xF000; + return RegisterService(rs, mDNSOpaque16fromIntVal(NextPort++), name, type, domain, txtinfo); +} + +// CreateProxyRegistrationForRealService() checks to see if the given port is currently +// in use, and if so, advertises the specified service as present on that port. +// This is useful for advertising existing real services (Personal Web Sharing, Personal +// File Sharing, etc.) that currently don't register with mDNS Service Discovery themselves. +static DNSServiceErrorType CreateProxyRegistrationForRealService(RegisteredService *rs, + const char *servicetype, UInt16 PortAsNumber, const char txtinfo[]) +{ + mDNSOpaque16 OpaquePort = mDNSOpaque16fromIntVal(PortAsNumber); + InetAddress ia; + TBind bindReq; + OSStatus err; + TEndpointInfo endpointinfo; + EndpointRef ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, &endpointinfo, &err); + if (!ep || err) { printf("OTOpenEndpoint (CreateProxyRegistrationForRealService) failed %d", err); return(err); } + + ia.fAddressType = AF_INET; + ia.fPort = OpaquePort.NotAnInteger; + ia.fHost = 0; + bindReq.addr.maxlen = sizeof(ia); + bindReq.addr.len = sizeof(ia); + bindReq.addr.buf = (UInt8*)&ia; + bindReq.qlen = 0; + err = OTBind(ep, &bindReq, NULL); + + if (err == kOTBadAddressErr) + err = RegisterService(rs, OpaquePort, "", servicetype, "local.", txtinfo); + else if (err) + printf("OTBind failed %d", err); + + OTCloseProvider(ep); + return(err); +} + +// YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS +static Boolean YieldSomeTime(UInt32 milliseconds) +{ + extern Boolean SIOUXQuitting; + EventRecord e; + WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL); + SIOUXHandleOneEvent(&e); + return(SIOUXQuitting); +} + +int main() +{ + OSStatus err; + RegisteredService *s; + + SIOUXSettings.asktosaveonclose = false; + SIOUXSettings.userwindowtitle = "\pMulticast DNS Responder"; + + printf("Multicast DNS Responder\n\n"); + printf("This software reports errors using MacsBug breaks,\n"); + printf("so if you don't have MacsBug installed your Mac may crash.\n\n"); + printf("******************************************************************************\n\n"); + + err = InitOpenTransport(); + if (err) { printf("InitOpenTransport failed %d", err); return(err); } + + printf("Advertising Services...\n"); + +#define SRSET 0 +#if SRSET==0 + RegisterFakeServiceForTesting(&p1, "Web Server One", "_http._tcp.", "local.", "path=/index.html"); + RegisterFakeServiceForTesting(&p2, "Web Server Two", "_http._tcp.", "local.", "path=/path.html"); +#elif SRSET==1 + RegisterFakeServiceForTesting(&p1, "Epson Stylus 900N", "_printer._tcp.", "local.", "rn=lpq1"); + RegisterFakeServiceForTesting(&p2, "HP LaserJet", "_printer._tcp.", "local.", "rn=lpq2"); +#else + RegisterFakeServiceForTesting(&p1, "My Printer", "_printer._tcp.", "local.", "rn=lpq3"); + RegisterFakeServiceForTesting(&p2, "My Other Printer", "_printer._tcp.", "local.", "lrn=pq4"); +#endif + + // If AFP Server is running, register a record for it + CreateProxyRegistrationForRealService(&afp, "_afpovertcp._tcp.", 548, ""); + + // If Web Server is running, register a record for it + CreateProxyRegistrationForRealService(&http, "_http._tcp.", 80, "path=/index.html"); + + while (!YieldSomeTime(35)) + for (s = services; s; s = s->next) + if (s->gotresult) + { + printf("%s %s %s registered\n", s->namestr, s->typestr, s->domstr); + s->gotresult = false; + } + + for (s = services; s; s = s->next) + if (s->sdRef) DNSServiceRefDeallocate(s->sdRef); + + CloseOpenTransport(); + return(0); +} |