Re: Porting Winsock DHCP Server; is OS/X ignoring Broadcast UDP in recvall()?
Re: Porting Winsock DHCP Server; is OS/X ignoring Broadcast UDP in recvall()?
- Subject: Re: Porting Winsock DHCP Server; is OS/X ignoring Broadcast UDP in recvall()?
- From: "Hostile Fork" <email@hidden>
- Date: Fri, 1 Feb 2008 14:46:28 -0800
On Jan 31, 2008 6:38 AM, Peter Sichel <email@hidden> wrote:
> There's a good example of using bpftransmit in the Darwin "bootp"
> project. That's where I cribbed mine from.
Wow Peter, copying that worked! I had no idea I'd be going that deep
to port socket code from one platform to another. From doing further
research I can't really find a published standard about what the
"correct" behavior would be. The only thing I see mentioning how
255.255.255.255 should work is in RFC1700:
"The "limited broadcast" destination address 255.255.255.255 should
never be forwarded outside the (sub-)net of the source."
[RFC1700, page 4]
Without a formal specification I guess it's hard to say that the BSD
way of not broadcasting to all adapters is "wrong"... it's just that
it leaves no option but to go underneath the socket layer if one
wishes to write a DHCP server. Probably a good idea anyway as it's
sort of a meta-protocol, handing out addresses and such. But it would
be nice if all socket layers were consistent in that case, treating
255.255.255.255 as an invalid address for outgoing sends.
I was little troubled by the use of bpf functions directly, since
they're not available on all platforms and I don't really want to
#ifdef MACOSX in this code. Then I noticed that there are now
cross-platform implementations of pcap_inject() and
pcap_sendpacket()...
http://winpcap.mirror.ethereal.com/301a/docs/group__wpcap__tut8.html
So I decided to use that instead of bpf_write. It did not work at
first, but after packet sniffing I realized that's because pcap_inject
wasn't filling in the ethernet address of the source hardware.
Darwin's BOOTP expects that, note the comment in this code:
/* set ethernet dest and type, source is inserted automatically */
if (ntohl(dest_ip.s_addr) == INADDR_BROADCAST) {
bcopy(ðer_broadcast, eh_p->ether_dhost, sizeof(ether_broadcast));
}
else {
bcopy(hwaddr, eh_p->ether_dhost, sizeof(eh_p->ether_dhost));
}
eh_p->ether_type = htons(ETHERTYPE_IP);
So by hacking the eh_p->ether_shost with the hardcoded address of the
adapter I'm servicing, I was able to replace:
status = bpf_write(bpf_fd, sendbuf, sizeof(*eh_p) + sizeof(*ip_udp) + len);
with:
status = pcap_inject(pcap_handle,
reinterpret_cast<const u_char*>(sendbuf),
sizeof(*eh_p)+sizeof(*ip_udp) + len);
That let me pull out a lot of bpf dependencies, and I hope the
resulting code will run on Linux and Windows without modification.
Though I'll need to figure out a good cross-platform way to get the
hardware ethernet address from pcap's device handle. I suppose I
could send my own IP address a packet, capture it, and then read the
data out of the header...but that seems roundabout! Better ideas
appreciated...
Thanks again for your help on this issue, I'm happy to be unblocked!
---
http://hostilefork.com
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden