[comp.protocols.tcp-ip] Broadcast problems

kaps@orange.ucsb.edu (Vikas Kapur) (12/04/89)

I'm posting this for a friend who has no current net
access. Your help would be *very* much appreciated - he has had
no luck so far. Please reply to the address listed in the 
header. Like I said this is a *long* posting..source code
included...

^L

<* He has been trying to broadcast to 5 networked Sun 
workstations on a dedicated Ethernet *>

	I tried several variations to the basic approach outlined in
the Sun-3 IPC Manual. The basic problem is to get the correct
internet address corresponding to a broadcast, for which the
following call is suggested :

struct in_addr inet_makeaddr(net,bcast_lna)
int net, bcast_lna;

where net= the network number of the net on which the broadcast
				 is required, and
		bcast_lna= INADDR_ANY ( I also tried INADDR_BCAST ), specifies
				 the host_addr (last byte of the internet address).

One would thus expect, for a host with, for instance, the address :
"128.111.63.26" that the broadcast address on the same network
would be (either "128.111.63.0" - using INADDR_ANY, as suggested by the
IPC documentation from Sun, or) "128.111.63.255" using INADDR_BCAST.
It turns out that variations of this call (see inet(3) of manual pages),
give vastly differing return values, from "128.111.255.255" to
"255.255.255.255" (whih happens to be the *physical* ethernet 
broadcast address (4 bytes, all 1's).

Incidentally, there's a call for converting inet_addresses to the
form "a.b.c.d" : inet_ntoa() , which I used to look at the values
returned by the inet_makeaddr() and other call that I used
(viz., inet_addr()).

However, not one of these variations seemed to work. In fact,
the sendto() call using the address returned as above always
returned without error, but none of the processes doing a
receivefrom() on the appropriate UDP-port on any of the machines
on the network ever received the "broadcast". In the absence of
a LANalyser to monitor the packets appearing on the network, it's
difficult to say whether the broadcast didnot happen (error at the
sender), or the broadcast happened but was not received by any of
the machines (error at the receiver(s)). (P.S. - In all cases
the UDP-port of the sending machine & receiving machines were
also the same.)

A simple pair of test routines for 
the sending party & receiving parties is listed hereunder :

/*----------------------------------------------------------------*/
/* COMMON CODE */


#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>

#define SERVENT		struct servent
#define HOSTENT		struct hostent
#define INET_ADDR	struct sockaddr_in

#define MAX_HOST_NAMELEN		128
#define MAX_TRY	30
#define MAX_MSG	100
#define SLEEP_INT	2

char MY_HOST_NAME[MAX_HOST_NAMELEN];
INET_ADDR MY_ADDR;
int MY_SOCK;

phys_init()
{
	SERVENT *srv_ent;
	HOSTENT *hst_ent;
	int on=1;

	MY_ADDR.sin_family=AF_INET;	/* my address family */
	if((srv_ent=getservbyname("TRANS_SERVER","udp"))==(SERVENT *)0)
		err_exit(-1,"Unable to find TRANS_SERVER's port number\n");
	MY_ADDR.sin_port=srv_ent->s_port;	/* get the server's port # */
	gethostname(MY_HOST_NAME,MAX_HOST_NAMELEN); /* get my host's name */
	if((hst_ent=gethostbyname(MY_HOST_NAME))==(HOSTENT *)0)
		err_exit(-2,"Can't find my host entry\n");
	bcopy(hst_ent->h_addr,&MY_ADDR.sin_addr,hst_ent->h_length);
		/* get my internet address */

	if((MY_SOCK=socket(PF_INET,SOCK_DGRAM,0))<0)
		err_exit(-3,"Can't open datagram socket\n");
	if(setsockopt(MY_SOCK,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on))<0)
		err_exit(-1,"Can't set broadcast option on socket\n");
	/*	set broadcasting option on socket	*/
	if(bind(MY_SOCK,&MY_ADDR,sizeof(INET_ADDR))<0)
		err_exit(-1,"Error in binding name to socket\n");
		/* bind  my full internet address (including port number) to socket */

	return;
}


send_bcast()
{
	INET_ADDR BCAST_ADDR;
	struct in_addr bcast_addr;
	int i,size,nbytes;
	char *msg="Did you get this broadcast message\n";

	BCAST_ADDR.sin_family=AF_INET;
	BCAST_ADDR.sin_port=MY_ADDR.sin_port;
	bcast_addr=inet_makeaddr(inet_netof(MY_ADDR.sin_addr),INADDR_BROADCAST);
	printf("The broadcast address is %s",inet_ntoa(bcast_addr));
	bcopy(&bcast_addr,&BCAST_ADDR.sin_addr,sizeof(struct in_addr));
		/* form the broadcast socket address, preparatory to sending */

	size=strlen(msg);
	for(i=0;i<MAX_TRY;i++){
		if(sendto(MY_SOCK,msg,size,0,&BCAST_ADDR,sizeof(INET_ADDR))!=size)
			err_exit(-1,"Error in sending broadcast\n");
		delay();
	}
	printf("%d broadcast transmissions made\n", MAX_TRY);
	return;
}


recv_msg()
{
	char msgbuf[MAX_MSG];
	INET_ADDR src_addr;
	int size,nbytes;

	size=sizeof(INET_ADDR);
	if((nbytes=recvfrom(MY_SOCK,msgbuf,MAX_MSG,0,&src_addr,&size))<0)
		err_exit(-1,"Error in receive\n");
	printf("%d byte message received : %s\n",nbytes,msgbuf);
	return;
}


delay()
{
	sleep(SLEEP_INT);
	return;
}


err_exit(err,msg)
int err;
char *msg;
{
	perror("");
	printf("\nErr %d : %s",err,msg);
	exit(err);
}
/* end of common code */
/*---------------------------------------------------------------------*/

/*	This is the BROADCASTER's code */

#ifdef BROADCASTER

main()
{
	phys_init();
	send_bcast();
	exit(0);
}

#endif	BROADCASTER

/* end of Broadcaster's code */
/*---------------------------------------------------------------------*/

/* This is the RECEIVERS' code */


#ifdef RECEIVER

main()
{
	phys_init();
	recv_msg();
	exit(0);
}

#endif RECEIVER

/* end of receivers' code */
/*---------------------------------------------------------------------*/


You will notice that the "broadcast address" that the above inet_makeaddr
call returns is simply the machine internet address with the last two
bytes replaced by 255.255 (which is obviously wrong). I also
tried the inet_addr() call and directly passed to it "a.b.c.255",
but even that doesnot work.

Any advice or help that you can offer will be highly appreciated.

________________________________________________________________________

Vikas Kapur