PDA

View Full Version : Fedora 8 socket INADDR_BROADCAST flag incompatible with RHEL4 and RHEL5


Ed Leaver
17th November 2007, 10:21 PM
Hi. I'm developing a client-server application, targeted at RHEL4 and RHEL5. I'd
*like* for it to run on Fedora 8 as well, but there appears to be an incompatibility
-- some would say bug -- between the values sendto() accepts for the broadcast address
between the three operating systems. Basically, this is what I've got thusfar:
1. CentOS 4 (sorry, its what I've got) *requires* INADDR_BROADCAST
2. Fedora 8 *requires* INADDR_ANY
3. CentOS 5 (yeah, yeah, yeah, I know) can use either INADDR_BROADCAST or INADDR_ANY

I'd like to know if this INADDR_BROADCAST vs. INADDR_ANY is a known issue, a known
upgrade requirment, ignorance on my part :-), or an oversight somewhere probably not too
deep in Fedora 8's libc. Either way, I doubt I'm the only one who will stumble over it.
If its any help, the Fedora 8 ip man page alludes:

"There are several special addresses: INADDR_LOOPBACK (127.0.0.1) always
refers to the local host via the loopback device; INADDR_ANY (0.0.0.0)
means any address for binding; INADDR_BROADCAST (255.255.255.255) means
any host and has the same effect on bind as INADDR_ANY for historical
reasons."

Here's a fragment of my server-side code that sets up a broadcast socket to get info
on all running clients, each of which has its own response server that replies to this
request on a connected socket (client-side code not shown):
/// Reference: Stevens pg 288
bool PingAllClients(){
int sockfd;
sockaddr_in serv_addr;
memset(&serv_addr, '\0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
#ifdef FEDORA8
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Works on F8 and CentOS-5, but not CentOS-4
#else
serv_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); // works on CentOS-4 and 5, but not Fedora 8
#endif
serv_addr.sin_port = htons(CLIENT_PINGSERVER_UDP_PORT); // Common port number for all clients (40002)

// get a socket to send ping request to remote client ping servers
if( (sockfd=socket(PF_INET, SOCK_DGRAM, 0)) < 0){
perror("socket");
exit(1);
}
// tell the socket we want to broadcast on it
int bcast = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) < 0){
perror("setsockopt");
}
// tell the socket not to let the datagram live too long, since our clients'
// ping-echo servers might only peek at the datagram, not actually receive it
int TimeToLive = 1; // set larger only if you want packet to leave local network
if(setsockopt(sockfd, IPPROTO_IP, IP_TTL, &TimeToLive, sizeof(TimeToLive)) < 0){
perror("setsockopt IP_TTL");
}
TimeToLive = 1; // set larger only if you want packet to leave local network
if(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &TimeToLive, sizeof(TimeToLive)) < 0){
perror("setsockopt IP_MULTICAST_TTL");
}
(place about 100 bytes of stuff in buffer, set buflen appropriately)
// broadcast ping request:
if(sendto(sockfd, buffer, buflen, 0, (sockaddr*)&serv_addr, sizeof(serv_addr)) != buflen){
perror("sendto");
}
(etc)
}

Thanks!

tashirosgt
19th November 2007, 11:47 PM
I think the proper way to state the compatibility problem is that the the versions of glibc shipped with the various distributions are incompatible with respect to the socket parameters. So the problem could exist in the one distribution if the user had updated his glibc library to a later version.

This could be verifed if I could find a page with release notes for glibc. There are pages with relase notes for the GNU C compiler with no problem ( http://gcc.gnu.org/gcc-3.4/changes.html). But I haven't found one for glibc. Does anybody know of such documentation?