blob: 17e93abc3320d11e997eda29fb663d888b51a821 [file] [log] [blame]
/**
* @file posix/pif.c POSIX network interface code
*
* Copyright (C) 2010 Creytiv.com
*/
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#define __USE_POSIX 1 /**< Use POSIX code */
#define __USE_XOPEN2K 1/**< Use POSIX.1:2001 code */
#include <netdb.h>
#define __USE_MISC 1 /**< Use MISC code */
#include <net/if.h>
#include <arpa/inet.h>
/*#include <net/if_arp.h>*/
#ifdef __sun
#include <sys/sockio.h>
#endif
#include <re_types.h>
#include <re_fmt.h>
#include <re_mbuf.h>
#include <re_sa.h>
#include <re_net.h>
#define DEBUG_MODULE "posixif"
#define DEBUG_LEVEL 5
#include <re_dbg.h>
/**
* Get IP address for a given network interface
*
* @param ifname Network interface name
* @param af Address Family
* @param ip Returned IP address
*
* @return 0 if success, otherwise errorcode
*
* @deprecated Works for IPv4 only
*/
int net_if_getaddr4(const char *ifname, int af, struct sa *ip)
{
struct addrinfo hints, *res, *r;
int error, err;
if (AF_INET != af)
return EAFNOSUPPORT;
memset(&hints, 0, sizeof(hints));
/* set-up hints structure */
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_DGRAM;
error = getaddrinfo(NULL, "0", &hints, &res);
if (error) {
DEBUG_WARNING("get_ifaddr: getaddrinfo(): %s\n",
gai_strerror(error));
return EADDRNOTAVAIL;
}
err = ENOENT;
for (r = res; r; r = r->ai_next) {
struct ifreq ifrr;
int fd = -1;
fd = socket(r->ai_family, SOCK_DGRAM, 0);
if (fd < 0) {
continue;
}
ifrr.ifr_addr.sa_family = r->ai_family;
str_ncpy(ifrr.ifr_name, ifname, sizeof(ifrr.ifr_name));
if (ioctl(fd, SIOCGIFADDR, &ifrr) < 0) {
err = errno;
goto next;
}
err = sa_set_sa(ip, &ifrr.ifr_ifru.ifru_addr);
next:
(void)close(fd);
}
freeaddrinfo(res);
return err;
}
/**
* Enumerate all network interfaces
*
* @param ifh Interface handler
* @param arg Handler argument
*
* @return 0 if success, otherwise errorcode
*
* @deprecated Works for IPv4 only
*/
int net_if_list(net_ifaddr_h *ifh, void *arg)
{
struct ifreq ifrv[32], *ifr;
struct ifconf ifc;
int sockfd = -1;
int err = 0;
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
err = errno;
DEBUG_WARNING("interface list: socket(): (%m)\n", err);
goto out;
}
ifc.ifc_len = sizeof(ifrv);
ifc.ifc_req = ifrv;
if (0 != ioctl(sockfd, SIOCGIFCONF, &ifc)) {
err = errno;
DEBUG_WARNING("interface list: ioctl SIOCFIFCONF: %m\n", err);
goto out;
}
for (ifr = ifc.ifc_req;
(char *)ifr < ((char *)ifc.ifc_buf + ifc.ifc_len);
++ifr) {
struct ifreq ifrr;
struct sa sa;
if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data)
continue; /* duplicate, skip it */
if (ioctl(sockfd, SIOCGIFFLAGS, ifr))
continue; /* failed to get flags, skip it */
#if 0
if (ifr->ifr_flags & IFF_LOOPBACK)
continue;
#endif
if (!(ifr->ifr_flags & IFF_UP))
continue;
ifrr.ifr_addr.sa_family = AF_INET;
str_ncpy(ifrr.ifr_name, ifr->ifr_name, sizeof(ifrr.ifr_name));
if (ioctl(sockfd, SIOCGIFADDR, &ifrr) < 0) {
err = errno;
continue;
}
err = sa_set_sa(&sa, &ifrr.ifr_ifru.ifru_addr);
if (err) {
DEBUG_WARNING("if_list: sa_set_sa %m\n", err);
break;
}
if (ifh && ifh(ifr->ifr_name, &sa, arg))
break;
}
out:
if (sockfd >= 0)
(void)close(sockfd);
return err;
}