Broadcasting and Determining Network Configuration
Broadcasting is not supported in IPv6. Broadcasting is supported only in IPv4.
Messages sent by datagram sockets can be broadcast to reach all of the hosts on an attached network. The network must support broadcast because the system provides no simulation of broadcast in software. Broadcast messages can place a high load on a network because broadcast messages force every host on the network to service the broadcast messages. Broadcasting is usually used for either of two reasons:
-
To find a resource on a local network without having its address
-
For functions that require information to be sent to all accessible neighbors
To send a broadcast message, create an Internet datagram socket:
s = socket(AF_INET, SOCK_DGRAM, 0);
Bind a port number to the socket:
sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(MYPORT); bind(s, (struct sockaddr *) &sin, sizeof sin);
The datagram can be broadcast on only one network by sending to the
network's broadcast address. A datagram can also be broadcast on all attached
networks by sending to the special address INADDR_BROADCAST
,
which is defined in netinet/in.h
.
The system provides a mechanism to determine a number of pieces of information about the
network interfaces on the system. This information includes the IP address and
broadcast address. The SIOCGIFCONF
ioctl
()
call returns the interface configuration of a host in a
single ifconf
structure. This structure contains an array of
ifreq
structures. Every address family supported by every
network interface to which the host is connected has its own
ifreq
structure. For more information, see the
ioctl
(2) man page.
The following example shows the
ifreq
structures defined in
net/if.h
.
Example 7-14 Showing the Contents of net/if.h
struct ifreq { #define IFNAMSIZ 16 char ifr_name[IFNAMSIZ]; /* if name, e.g., "en0" */ union { struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; char ifru_oname[IFNAMSIZ]; /* other if name */ struct sockaddr ifru_broadaddr; short ifru_flags; int ifru_metric; char ifru_data[1]; /* interface dependent data */ char ifru_enaddr[6]; } ifr_ifru; #define ifr_addr ifr_ifru.ifru_addr #define ifr_dstaddr ifr_ifru.ifru_dstaddr #define ifr_oname ifr_ifru.ifru_oname #define ifr_broadaddr ifr_ifru.ifru_broadaddr #define ifr_flags ifr_ifru.ifru_flags #define ifr_metric ifr_ifru.ifru_metric #define ifr_data ifr_ifru.ifru_data #define ifr_enaddr ifr_ifru.ifru_enaddr };
The call that obtains the interface configuration is:
/* * Do SIOCGIFNUM ioctl to find the number of interfaces * * Allocate space for number of interfaces found * * Do SIOCGIFCONF with allocated buffer * */ if (ioctl(s, SIOCGIFNUM, (char *)&numifs) == -1) { numifs = MAXIFS; } bufsize = numifs * sizeof(struct ifreq); reqbuf = (struct ifreq *)malloc(bufsize); if (reqbuf == NULL) { fprintf(stderr, "out of memory\n"); exit(1); } ifc.ifc_buf = (caddr_t)&reqbuf[0]; ifc.ifc_len = bufsize; if (ioctl(s, SIOCGIFCONF, (char *)&ifc) == -1) { perror("ioctl(SIOCGIFCONF)"); exit(1); }
After this call, buf contains an array of ifreq
structures. Every network to which the host connects has an
associated ifreq
structure. The sort order these structures
appear in is:
-
Alphabetical by interface name
-
Numerical by supported address families
The value of ifc.ifc_len
is set to the number of
bytes used by the ifreq
structures.
Each structure has a set of interface flags that indicate
whether the corresponding network is up or down, point-to-point or
broadcast, and so on. The following example shows
ioctl
()
returning the SIOCGIFFLAGS
flags for an interface specified by an ifreq
structure.
Example 7-15 Obtaining Interface Flags
struct ifreq *ifr; ifr = ifc.ifc_req; for (n = ifc.ifc_len/sizeof (struct ifreq); --n >= 0; ifr++) { /* * Be careful not to use an interface devoted to an address * family other than those intended. */ if (ifr->ifr_addr.sa_family != AF_INET) continue; if (ioctl(s, SIOCGIFFLAGS, (char *) ifr) < 0) { ... } /* Skip boring cases */ if ((ifr->ifr_flags & IFF_UP) == 0 || (ifr->ifr_flags & IFF_LOOPBACK) || (ifr->ifr_flags & (IFF_BROADCAST | IFF_POINTOPOINT)) == 0) continue; }
The following example uses the SIOGGIFBRDADDR
ioctl
command to obtain the broadcast address of an
interface.
Example 7-16 Obtaining the Broadcast Address of an Interface
if (ioctl(s, SIOCGIFBRDADDR, (char *) ifr) < 0) { ... } memcpy((char *) &dst, (char *) &ifr->ifr_broadaddr, sizeof ifr->ifr_broadaddr);
You can also use SIOGGIFBRDADDR
ioctl
to get the destination address of a point-to-point
interface. For more information, see the
ioctl
(2) man page.
After the interface broadcast address is obtained, transmit the broadcast datagram with
sendto
:
sendto(s, buf, buflen, 0, (struct sockaddr *)&dst, sizeof dst);
Use one sendto
for each interface to which the host is connected, if that
interface supports the broadcast or point-to-point addressing. For more information,
see the
sendto
(3C) man page.