mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-06-12 19:33:44 +08:00

The sources can be obtained via: http://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-544.tar.gz
184 lines
7.2 KiB
C
184 lines
7.2 KiB
C
/* -*- 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);
|
|
}
|