Network Addressing Programatically

Network addresses have always been a massive pain in the ass for programmers since the dawn of time, but it doesn't necessarily have to be that way. Here you'll find some interesting tips and tricks to get you up to speed on how to deal with them like a pro!

Getting Network Interface Information

It's very common to have to get information on the network interfaces of a device in order to get more information about the network or just to be capable of talking to all devices on all the networks that you may have available. This can be a bit tricky and might involve a lot of platform-dependent code since most of the functions surrounding network interfaces are not portable and are deeply tied to the operating system.

According to this very comprehensive piece of code there are four ways of fetching the network interfaces of a device, two involve system functions and the other two involve ioctls:

Broadcast Address

The broadcast address of a network is essential when dealing with device discovery (unless you can use proper multicast), you can get away with using INADDR_BROADCAST, but that's very hacky and not recommended for devices that already have an IP address on the network. The correct way to broadcast a packet on a network is to get a list of all the network interfaces of the device and then get the broadcast address of each one of them.

Here are a couple of ways that you can get the broadcast address of interfaces on various platforms:

Using ioctls

This interesting bit of code shows how to use ioctls under most UNIX operating systems to get a list of the interfaces and their respective broadcast addresses:

getbroadaddr.c
#include <net/if.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
 
static void show_interface_broadaddr(int fd, const char *name) {
	struct ifreq ifreq;
	char host[128];
	memset(&ifreq, 0, sizeof ifreq);
	strncpy(ifreq.ifr_name, name, IFNAMSIZ);
 
	if (ioctl(fd, SIOCGIFBRDADDR, &ifreq) != 0) {
		fprintf(stderr, "Could not find interface named %s\n", name);
		return; /* ignore */
	}
 
	getnameinfo(&ifreq.ifr_broadaddr, sizeof(ifreq.ifr_broadaddr), host, sizeof(host), 0, 0, NI_NUMERICHOST);
	printf("%-24s%s\n", name, host);
}
 
static void list_interfaces(int fd) {
	struct ifreq *ifreq;
	struct ifconf ifconf;
	char buf[16384];
	unsigned i;
	size_t len;
 
	ifconf.ifc_len = sizeof(buf);
	ifconf.ifc_buf = buf;
 
	if (ioctl(fd, SIOCGIFCONF, &ifconf) != 0) {
		perror("ioctl(SIOCGIFCONF)");
		exit(EXIT_FAILURE);
	}
 
	printf("Listing all interfaces:\n");
	ifreq = ifconf.ifc_req;
	i = 0;
	while (i < ifconf.ifc_len) {
#ifndef linux
		len = IFNAMSIZ + ifreq->ifr_addr.sa_len;
#else
		len = sizeof(struct ifreq);
#endif
 
		printf("%s\n", ifreq->ifr_name);
 
		ifreq = (struct ifreq *)((char *)ifreq + len);
		i += len;
	}
}
 
int main(int argc, char **argv) {
	int sock;
 
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) {
		perror("socket()");
		exit(EXIT_FAILURE);
	}
 
	if (argc == 1) {
		list_interfaces(sock);
	} else if (argc == 2) {
		show_interface_broadaddr(sock, argv[1]);
	}
 
	close(sock);
 
	return EXIT_SUCCESS;
}
devnotes/netaddr.txt · Last modified: by nathanpc
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 4.0 International
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki