#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include "net_utils.h"
const char *
get_ifname_by_sockaddr(struct sockaddr *sa, char *ifname)
{
struct ifaddrs *addr, *addr0;
struct in_addr *in4a, *in4b;
const char *ifname0 = NULL;
struct in6_addr *in6a, *in6b;
ifname0 = NULL;
getifaddrs(&addr0);
for (addr = addr0; ifname0 == NULL && addr != NULL;
addr = addr->ifa_next) {
if (addr->ifa_addr == NULL ||
addr->ifa_addr->sa_family != sa->sa_family ||
addr->ifa_addr->sa_len != sa->sa_len)
continue;
switch (addr->ifa_addr->sa_family) {
default:
continue;
case AF_INET:
in4a = &((struct sockaddr_in *)addr->ifa_addr)
->sin_addr;
in4b = &((struct sockaddr_in *)sa)->sin_addr;
if (in4a->s_addr == in4b->s_addr) {
strlcpy(ifname, addr->ifa_name, IF_NAMESIZE);
ifname0 = ifname;
}
break;
case AF_INET6:
in6a = &((struct sockaddr_in6 *)addr->ifa_addr)
->sin6_addr;
in6b = &((struct sockaddr_in6 *)sa)->sin6_addr;
if (IN6_ARE_ADDR_EQUAL(in6a, in6b)) {
strlcpy(ifname, addr->ifa_name, IF_NAMESIZE);
ifname0 = ifname;
}
break;
}
}
freeifaddrs(addr0);
return ifname0;
}
int
addrport_parse(const char *addrport, int proto, struct addrinfo **p_ai)
{
char buf[256];
char *servp, *nodep, *slash;
struct addrinfo hints;
strlcpy(buf, addrport, sizeof(buf));
if (buf[0] == '[' && (servp = strchr(buf, ']')) != NULL) {
nodep = buf + 1;
*servp++ = '\0';
if (*servp != ':')
servp = NULL;
} else {
nodep = buf;
servp = strrchr(nodep, ':');
}
if (servp != NULL) {
*servp = '\0';
servp++;
slash = strrchr(servp, '/');
if (slash != NULL) {
*slash = '\0';
slash++;
}
} else
servp = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = AF_UNSPEC;
switch (proto) {
case IPPROTO_TCP:
hints.ai_socktype = SOCK_STREAM;
break;
case IPPROTO_UDP:
hints.ai_socktype = SOCK_DGRAM;
break;
}
hints.ai_protocol = proto;
return getaddrinfo(nodep, servp, &hints, p_ai);
}
const char *
addrport_tostring(struct sockaddr *sa, socklen_t salen, char *buf, int lbuf)
{
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
if (getnameinfo(sa, salen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
NI_NUMERICHOST | NI_NUMERICSERV) != 0)
return NULL;
switch (sa->sa_family) {
case AF_INET6:
strlcpy(buf, "[", lbuf);
strlcat(buf, hbuf, lbuf);
strlcat(buf, "]:", lbuf);
strlcat(buf, sbuf, lbuf);
break;
case AF_INET:
strlcpy(buf, hbuf, lbuf);
strlcat(buf, ":", lbuf);
strlcat(buf, sbuf, lbuf);
break;
default:
return NULL;
}
return buf;
}
int
netmask2prefixlen(uint32_t mask)
{
switch(mask) {
case 0x00000000: return 0;
case 0x80000000: return 1;
case 0xC0000000: return 2;
case 0xE0000000: return 3;
case 0xF0000000: return 4;
case 0xF8000000: return 5;
case 0xFC000000: return 6;
case 0xFE000000: return 7;
case 0xFF000000: return 8;
case 0xFF800000: return 9;
case 0xFFC00000: return 10;
case 0xFFE00000: return 11;
case 0xFFF00000: return 12;
case 0xFFF80000: return 13;
case 0xFFFC0000: return 14;
case 0xFFFE0000: return 15;
case 0xFFFF0000: return 16;
case 0xFFFF8000: return 17;
case 0xFFFFC000: return 18;
case 0xFFFFE000: return 19;
case 0xFFFFF000: return 20;
case 0xFFFFF800: return 21;
case 0xFFFFFC00: return 22;
case 0xFFFFFE00: return 23;
case 0xFFFFFF00: return 24;
case 0xFFFFFF80: return 25;
case 0xFFFFFFC0: return 26;
case 0xFFFFFFE0: return 27;
case 0xFFFFFFF0: return 28;
case 0xFFFFFFF8: return 29;
case 0xFFFFFFFC: return 30;
case 0xFFFFFFFE: return 31;
case 0xFFFFFFFF: return 32;
}
return -1;
}