Re: bootpd again
Re: bootpd again
- Subject: Re: bootpd again
- From: Quinn <email@hidden>
- Date: Mon, 21 Jul 2003 17:15:39 +0100
At 11:33 -0400 21/7/03, Matt Mashyna wrote:
>
Last time I asked everyone was at WWDC, so here I go again:
Did you catch my previous reply? I've included a copy at the end of
this email.
>
Porting the unix code for it to OT looks like a headache. I'm
>
running into problems with arp. Bootpd uses arp so that when the
>
server sends back a udp response it doesn't have to broadcast.
>
>
Any clues at all would be much appreciated.
I could probably walk you through the steps necessary to get ARP to
work, but you have to evaluate the cost vs the benefit. IMHO, the
benefit is very small (how much bootp traffic do you expect on the
network?). Moreover, it's not like your server will stand out from
the crowd; plenty of servers just broadcast the response. The cost,
OTOH, is US$195 for a DTS tech support incident (-;
<
http://developer.apple.com/products/techsupport/>
S+E
--
Quinn "The Eskimo!" <
http://www.apple.com/developer/>
Apple Developer Technical Support * Networking, Communications, Hardware
At 10:47 +0100 9/7/03, Quinn wrote:
>
I don't know of any official UDP broadcast send/received samples.
>
However, my experience is that this isn't particularly tricky. The
>
most common gotchas associated with UDP broadcast reception are
>
covered by DTS Q&A NW 53.
>
>
<http://developer.apple.com/qa/nw/nw53.html>
>
>
I also dug through my archive of snippets written for developers and
>
found some code that might be useful. It contains too many ugly
>
experiments to post as a whole, but I've included some relevant
>
routines at the end of this email.
>
>
Note that this was written for traditional Mac OS (pre-Carbon). I
>
decided not to update it for Carbon because we're no longer
>
encouraging developers to use the OT API for new code.
>
>
S+E
>
--
>
Quinn "The Eskimo!" <http://www.apple.com/developer/>
>
Apple Developer Technical Support * Networking, Communications, Hardware
>
>
>
static OSStatus BindEndpoint(EndpointRef ep, InetHost host, InetPort port)
>
{
>
OSStatus err;
>
TBind bindRequest;
>
InetAddress requestAddr;
>
TBind bindResponse;
>
InetAddress responseAddr;
>
>
// Set up to bind the endpoint. Because we're listening for broadcasts,
>
// we have to request kOTAnyInetAddress.
>
>
OTInitInetAddress(&requestAddr, port, host);
>
>
OTMemzero(&bindRequest, sizeof(TBind));
>
bindRequest.addr.buf = (UInt8 *) &requestAddr;
>
bindRequest.addr.len = sizeof(InetAddress);
>
>
// Because the port might be in use, we have to check that XTI
>
// has not given us another port (XTI is kinda lame in this respect).
>
// So we set up bindResponse to collect the bound address.
>
>
OTMemzero(&bindResponse, sizeof(TBind));
>
bindResponse.addr.buf = (UInt8 *) &responseAddr;
>
bindResponse.addr.maxlen = sizeof(InetAddress);
>
>
// Do the bind and check that we got what we wanted.
>
>
err = OTBind(ep, &bindRequest, &bindResponse);
>
if (err == noErr) {
>
if ( requestAddr.fPort != responseAddr.fPort ) {
>
err = kEADDRINUSEErr;
>
}
>
}
>
return err;
>
}
>
>
static pascal OSStatus EchoThread(void *junkParam)
>
{
>
#pragma unused(junkParam)
>
OSStatus err;
>
OSStatus junk;
>
OTResult result;
>
EndpointRef ep;
>
TEndpointInfo epInfo;
>
UInt8 *dataBuffer;
>
UInt8 *addrBuffer;
>
TUnitData rcvRequest;
>
OTFlags junkFlags;
>
InetAddress *sourceAddr;
>
>
dataBuffer = nil;
>
addrBuffer = nil;
>
>
ep = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, nil, &err);
>
>
// If the endpoint opens successfully...
>
>
if (err == noErr) {
>
SetupEndpointForThreads(ep);
>
>
junk = OTGetEndpointInfo(ep, &epInfo);
>
OTAssert("EchoThread: OTGetEndpointInfo failed", junk == noErr);
>
>
dataBuffer = OTAllocMem(epInfo.tsdu);
>
if (dataBuffer == nil) {
>
err = kENOMEMErr;
>
}
>
addrBuffer = OTAllocMem(epInfo.addr);
>
if (dataBuffer == nil) {
>
err = kENOMEMErr;
>
}
>
}
>
>
// Now bind the endpoint.
>
>
if (err == noErr) {
>
result = SetFourByteOption(ep, INET_IP, IP_REUSEADDR, 1);
>
if (result > 0) {
>
err = kENXIOErr;
>
} else {
>
err = result;
>
}
>
}
>
if (err == noErr) {
>
err = BindEndpoint(ep, kOTAnyInetAddress, kTestPort);
>
}
>
>
if (err == noErr) {
>
>
// Tell the sending thread that we're bound and waiting for
>
// packets to echo. We do this because we want to make sure
>
// that we bind before it does.
>
>
gEchoThreadBound = true;
>
>
// Repeatedly get data from the endpoint and echo it to
>
// stdout.
>
>
do {
>
OTMemzero(&rcvRequest, sizeof(TUnitData));
>
rcvRequest.addr.buf = addrBuffer;
>
rcvRequest.addr.maxlen = epInfo.addr;
>
rcvRequest.udata.buf = dataBuffer;
>
rcvRequest.udata.maxlen = epInfo.tsdu;
>
>
err = OTRcvUData(ep, &rcvRequest, &junkFlags);
>
if (err == noErr) {
>
sourceAddr = (InetAddress *) addrBuffer;
>
>
printf("EchoThread: Got a packet!\n");
>
printf(" size = %ld.\n", rcvRequest.addr.len);
>
if ( sourceAddr->fAddressType == AF_INET ) {
>
printf(" source addr = %d.%d.%d.%d, source port = %d\n",
>
(int) ((sourceAddr->fHost >> 24) & 0x00FF),
>
(int) ((sourceAddr->fHost >> 16) & 0x00FF),
>
(int) ((sourceAddr->fHost >> 8) & 0x00FF),
>
(int) ((sourceAddr->fHost >> 0) & 0x00FF),
>
sourceAddr->fPort);
>
} else {
>
printf(" unknown (fAddressType = %d)\n",
>
((InetAddress *) addrBuffer)->fAddressType);
>
}
>
} else if (err == kOTLookErr) {
>
OTResult look;
>
>
look = OTLook(ep);
>
switch ( look ) {
>
case T_UDERR:
>
err = OTRcvUDErr(ep, nil);
>
break;
>
default:
>
printf("EchoThread: Got a kOTLookErr, look =
>
%ld\n", look);
>
// leave err set to kOTLookErr
>
break;
>
}
>
}
>
// fflush(stdout);
>
} while (err == noErr);
>
}
>
>
// Clean up.
>
>
if (addrBuffer != nil) {
>
OTFreeMem(dataBuffer);
>
}
>
if (dataBuffer != nil) {
>
OTFreeMem(addrBuffer);
>
}
>
if (ep != kOTInvalidEndpointRef) {
>
junk = OTCloseProvider(ep);
>
OTAssert("EchoThread: OTCloseProvider failed", junk == noErr);
>
}
>
>
if (err == noErr || err == userCanceledErr) {
>
printf("EchoThread: Successful termination.\n");
>
} else {
>
printf("EchoThread: Terminated with error %d.\n", err);
>
}
>
return noErr;
>
}
>
>
static UInt32 gPacketsToSend = 0;
>
>
static UInt32 gCurrentPacketNumber = 0;
>
>
static pascal OSStatus SendThread(void *junkParam)
>
{
>
#pragma unused(junkParam)
>
OSStatus err;
>
OSStatus junk;
>
EndpointRef ep;
>
OTResult result;
>
TUnitData sndRequest;
>
InetAddress destAddr;
>
OTResult look;
>
char dataString[256];
>
>
ep = kOTInvalidEndpointRef;
>
>
// Start by waiting for the echo thread to start up successfully.
>
>
err = noErr;
>
while ( err == noErr && ! gEchoThreadBound ) {
>
err = MyYieldToAnyThread();
>
}
>
>
// Create the endpoint, set it up for threaded execution, set
>
// up the IP_REUSEADDR option, and then bind it to one of the
>
// interfaces.
>
>
if (err == noErr) {
>
ep = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, nil, &err);
>
}
>
if (err == noErr) {
>
SetupEndpointForThreads(ep);
>
>
result = SetFourByteOption(ep, INET_IP, IP_REUSEADDR, 1);
>
if (result > 0) {
>
err = kENXIOErr;
>
} else {
>
err = result;
>
}
>
}
>
if (err == noErr) {
>
err = BindEndpoint(ep, kOTAnyInetAddress, kTestPort);
>
}
>
if (err == noErr) {
>
do {
>
if (gPacketsToSend == 0) {
>
err = MyYieldToAnyThread();
>
} else {
>
OTInitInetAddress(&destAddr, kTestPort, 0xFFFFFFFF);
>
>
gCurrentPacketNumber += 1;
>
sprintf(dataString, "Broadcast Message %ld",
>
gCurrentPacketNumber);
>
>
OTMemzero(&sndRequest, sizeof(TUnitData));
>
sndRequest.addr.buf = (UInt8 *) &destAddr;
>
sndRequest.addr.len = sizeof(InetAddress);
>
sndRequest.udata.buf = (UInt8 *) dataString;
>
sndRequest.udata.len = OTStrLength(dataString);
>
>
err = OTSndUData(ep, &sndRequest);
>
if (err == kOTLookErr) {
>
look = OTLook(ep);
>
switch ( look ) {
>
case T_UDERR:
>
err = OTRcvUDErr(ep, nil);
>
break;
>
case T_DATA:
>
printf("SendThread: Got a T_DATA\n");
>
// leave err set to kOTLookErr
>
break;
>
default:
>
printf("SendThread: Got a kOTLookErr,
>
look = %ld\n", look);
>
// leave err set to kOTLookErr
>
break;
>
}
>
}
>
// fflush(stdout);
>
gPacketsToSend -= 1;
>
}
>
} while (err == noErr);
>
}
>
>
// Clean up.
>
>
if (ep != kOTInvalidEndpointRef) {
>
junk = OTCloseProvider(ep);
>
OTAssert("SendThread: OTCloseProvider failed", junk == noErr);
>
}
>
>
if (err == noErr || err == userCanceledErr) {
>
printf("SendThread: Successful termination.\n");
>
} else {
>
printf("SendThread: Terminated with error %d.\n", err);
>
}
>
return noErr;
>
}
_______________________________________________
macnetworkprog mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/macnetworkprog
Do not post admin requests to the list. They will be ignored.
References: | |
| >bootpd again (From: Matt Mashyna <email@hidden>) |