]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOS9/Responder.c
mDNSResponder-161.1.tar.gz
[apple/mdnsresponder.git] / mDNSMacOS9 / Responder.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16
17 Change History (most recent first):
18
19 $Log: Responder.c,v $
20 Revision 1.3 2006/08/14 23:24:29 cheshire
21 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
22
23 Revision 1.2 2004/05/20 18:38:31 cheshire
24 Fix build broken by removal of 'kDNSServiceFlagsAutoRename' from dns_sd.h
25
26 Revision 1.1 2004/03/12 21:30:25 cheshire
27 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
28 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
29
30 */
31
32 #include <stdio.h> // For printf()
33 #include <string.h> // For strcpy()
34
35 #include <Events.h> // For WaitNextEvent()
36
37 #include <OpenTransport.h>
38 #include <OpenTptInternet.h>
39
40 #include <SIOUX.h> // For SIOUXHandleOneEvent()
41
42 #include "dns_sd.h"
43
44 typedef union { UInt8 b[2]; UInt16 NotAnInteger; } mDNSOpaque16;
45 static UInt16 mDNSVal16(mDNSOpaque16 x) { return((UInt16)(x.b[0]<<8 | x.b[1])); }
46 static mDNSOpaque16 mDNSOpaque16fromIntVal(UInt16 v)
47 { mDNSOpaque16 x; x.b[0] = (UInt8)(v >> 8); x.b[1] = (UInt8)(v & 0xFF); return(x); }
48
49 typedef struct RegisteredService_struct RegisteredService;
50 struct RegisteredService_struct
51 {
52 RegisteredService *next;
53 DNSServiceRef sdRef;
54 Boolean gotresult;
55 DNSServiceErrorType errorCode;
56 char namestr[64];
57 char typestr[kDNSServiceMaxDomainName];
58 char domstr [kDNSServiceMaxDomainName];
59 };
60
61 static RegisteredService p1, p2, afp, http, njp;
62 static RegisteredService *services = NULL, **nextservice = &services;
63
64 static void RegCallback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
65 const char *name, const char *regtype, const char *domain, void *context)
66 {
67 RegisteredService *rs = (RegisteredService *)context;
68 (void)sdRef; // Unused
69 (void)flags; // Unused
70 rs->gotresult = true;
71 rs->errorCode = errorCode;
72 strcpy(rs->namestr, name);
73 strcpy(rs->typestr, regtype);
74 strcpy(rs->domstr, domain);
75 }
76
77 static DNSServiceErrorType RegisterService(RegisteredService *rs, mDNSOpaque16 OpaquePort,
78 const char name[], const char type[], const char domain[], const char txtinfo[])
79 {
80 DNSServiceErrorType err;
81 unsigned char txtbuffer[257];
82 strncpy((char*)txtbuffer+1, txtinfo, 255);
83 txtbuffer[256] = 0;
84 txtbuffer[0] = (unsigned char)strlen((char*)txtbuffer);
85 rs->gotresult = 0;
86 rs->errorCode = kDNSServiceErr_NoError;
87 err = DNSServiceRegister(&rs->sdRef, /* kDNSServiceFlagsAutoRename*/ 0, 0,
88 name, type, domain, NULL, OpaquePort.NotAnInteger, (unsigned short)(1+txtbuffer[0]), txtbuffer, RegCallback, rs);
89 if (err)
90 printf("RegisterService(%s %s %s) failed %d\n", name, type, domain, err);
91 else
92 { *nextservice = rs; nextservice = &rs->next; }
93 return(err);
94 }
95
96 // RegisterFakeServiceForTesting() simulates the effect of services being registered on
97 // dynamically-allocated port numbers. No real service exists on that port -- this is just for testing.
98 static DNSServiceErrorType RegisterFakeServiceForTesting(RegisteredService *rs,
99 const char name[], const char type[], const char domain[], const char txtinfo[])
100 {
101 static UInt16 NextPort = 0xF000;
102 return RegisterService(rs, mDNSOpaque16fromIntVal(NextPort++), name, type, domain, txtinfo);
103 }
104
105 // CreateProxyRegistrationForRealService() checks to see if the given port is currently
106 // in use, and if so, advertises the specified service as present on that port.
107 // This is useful for advertising existing real services (Personal Web Sharing, Personal
108 // File Sharing, etc.) that currently don't register with mDNS Service Discovery themselves.
109 static DNSServiceErrorType CreateProxyRegistrationForRealService(RegisteredService *rs,
110 const char *servicetype, UInt16 PortAsNumber, const char txtinfo[])
111 {
112 mDNSOpaque16 OpaquePort = mDNSOpaque16fromIntVal(PortAsNumber);
113 InetAddress ia;
114 TBind bindReq;
115 OSStatus err;
116 TEndpointInfo endpointinfo;
117 EndpointRef ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, &endpointinfo, &err);
118 if (!ep || err) { printf("OTOpenEndpoint (CreateProxyRegistrationForRealService) failed %d", err); return(err); }
119
120 ia.fAddressType = AF_INET;
121 ia.fPort = OpaquePort.NotAnInteger;
122 ia.fHost = 0;
123 bindReq.addr.maxlen = sizeof(ia);
124 bindReq.addr.len = sizeof(ia);
125 bindReq.addr.buf = (UInt8*)&ia;
126 bindReq.qlen = 0;
127 err = OTBind(ep, &bindReq, NULL);
128
129 if (err == kOTBadAddressErr)
130 err = RegisterService(rs, OpaquePort, "", servicetype, "local.", txtinfo);
131 else if (err)
132 printf("OTBind failed %d", err);
133
134 OTCloseProvider(ep);
135 return(err);
136 }
137
138 // YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS
139 static Boolean YieldSomeTime(UInt32 milliseconds)
140 {
141 extern Boolean SIOUXQuitting;
142 EventRecord e;
143 WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL);
144 SIOUXHandleOneEvent(&e);
145 return(SIOUXQuitting);
146 }
147
148 int main()
149 {
150 OSStatus err;
151 RegisteredService *s;
152
153 SIOUXSettings.asktosaveonclose = false;
154 SIOUXSettings.userwindowtitle = "\pMulticast DNS Responder";
155
156 printf("Multicast DNS Responder\n\n");
157 printf("This software reports errors using MacsBug breaks,\n");
158 printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
159 printf("******************************************************************************\n\n");
160
161 err = InitOpenTransport();
162 if (err) { printf("InitOpenTransport failed %d", err); return(err); }
163
164 printf("Advertising Services...\n");
165
166 #define SRSET 0
167 #if SRSET==0
168 RegisterFakeServiceForTesting(&p1, "Web Server One", "_http._tcp.", "local.", "path=/index.html");
169 RegisterFakeServiceForTesting(&p2, "Web Server Two", "_http._tcp.", "local.", "path=/path.html");
170 #elif SRSET==1
171 RegisterFakeServiceForTesting(&p1, "Epson Stylus 900N", "_printer._tcp.", "local.", "rn=lpq1");
172 RegisterFakeServiceForTesting(&p2, "HP LaserJet", "_printer._tcp.", "local.", "rn=lpq2");
173 #else
174 RegisterFakeServiceForTesting(&p1, "My Printer", "_printer._tcp.", "local.", "rn=lpq3");
175 RegisterFakeServiceForTesting(&p2, "My Other Printer", "_printer._tcp.", "local.", "lrn=pq4");
176 #endif
177
178 // If AFP Server is running, register a record for it
179 CreateProxyRegistrationForRealService(&afp, "_afpovertcp._tcp.", 548, "");
180
181 // If Web Server is running, register a record for it
182 CreateProxyRegistrationForRealService(&http, "_http._tcp.", 80, "path=/index.html");
183
184 while (!YieldSomeTime(35))
185 for (s = services; s; s = s->next)
186 if (s->gotresult)
187 {
188 printf("%s %s %s registered\n", s->namestr, s->typestr, s->domstr);
189 s->gotresult = false;
190 }
191
192 for (s = services; s; s = s->next)
193 if (s->sdRef) DNSServiceRefDeallocate(s->sdRef);
194
195 CloseOpenTransport();
196 return(0);
197 }