diff options
Diffstat (limited to 'sbin/ipf/ifaddr.c')
-rw-r--r-- | sbin/ipf/ifaddr.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/sbin/ipf/ifaddr.c b/sbin/ipf/ifaddr.c new file mode 100644 index 00000000000..300e3e27f3e --- /dev/null +++ b/sbin/ipf/ifaddr.c @@ -0,0 +1,75 @@ +/* $OpenBSD: ifaddr.c,v 1.1 1999/12/16 07:38:45 kjell Exp $ */ +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <err.h> +#include <stdlib.h> +#include "ifaddr.h" + + +/* + * if_addr(): + * given a string containing an interface name (e.g. "ppp0") + * return the IP address it represents + * + * The OpenBSD community considers this feature to be quite useful and + * suggests inclusion into other platforms. The closest alternative is + * to define /etc/networks with suitable values. + */ +int if_addr(name, ap) +char *name; +struct in_addr *ap; +{ + struct ifconf ifc; + struct ifreq ifreq, *ifr; + char *inbuf = NULL; + int s, i, len = 8192; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + warn("socket"); + return 0; + } + + while (1) { + ifc.ifc_len = len; + ifc.ifc_buf = inbuf = realloc(inbuf, len); + if (inbuf == NULL) + err(1, "malloc"); + if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { + warn("SIOCGIFCONF"); + goto if_addr_lose; + } + if (ifc.ifc_len + sizeof(ifreq) < len) + break; + len *= 2; + } + ifr = ifc.ifc_req; + ifreq.ifr_name[0] = '\0'; + for (i = 0; i < ifc.ifc_len; ) { + ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i); + i += sizeof(ifr->ifr_name) + + (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) + ? ifr->ifr_addr.sa_len + : sizeof(struct sockaddr)); + ifreq = *ifr; + if (ioctl(s, SIOCGIFADDR, (caddr_t)ifr) < 0) + continue; + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + if (!strcmp(name, ifr->ifr_name)) { + struct sockaddr_in *sin; + close(s); + free(inbuf); + sin = (struct sockaddr_in *)&ifr->ifr_addr; + *ap = sin->sin_addr; + return (1); + } + } + +if_addr_lose: + close(s); + free(inbuf); + return 0; +} |