mirror of
https://github.com/Silicondust/libhdhomerun
synced 2025-08-20 21:43:27 -07:00
support multiple ip addresses on same interface
This commit is contained in:
parent
b1ca457584
commit
3c60a84adb
1 changed files with 68 additions and 80 deletions
|
@ -20,8 +20,13 @@
|
||||||
|
|
||||||
#include "hdhomerun.h"
|
#include "hdhomerun.h"
|
||||||
|
|
||||||
#include <net/if.h>
|
#if defined(LIBHDHOMERUN_USE_LEGACY_SIOCGIFCONF)
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#else
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
#ifndef MSG_NOSIGNAL
|
#ifndef MSG_NOSIGNAL
|
||||||
#define MSG_NOSIGNAL 0
|
#define MSG_NOSIGNAL 0
|
||||||
|
@ -31,48 +36,6 @@ struct hdhomerun_sock_t {
|
||||||
int sock;
|
int sock;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool hdhomerun_local_ip_info_add(struct hdhomerun_local_ip_info_t *ip_info, int sock, struct ifreq *ifr)
|
|
||||||
{
|
|
||||||
/* Flags. */
|
|
||||||
if (ioctl(sock, SIOCGIFFLAGS, ifr) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ifr->ifr_flags & IFF_UP) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((ifr->ifr_flags & IFF_RUNNING) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Local IP address. */
|
|
||||||
if (ioctl(sock, SIOCGIFADDR, ifr) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in *ip_addr_in = (struct sockaddr_in *)&ifr->ifr_addr;
|
|
||||||
uint32_t ip_addr = ntohl(ip_addr_in->sin_addr.s_addr);
|
|
||||||
if (ip_addr == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Subnet mask. */
|
|
||||||
if (ioctl(sock, SIOCGIFNETMASK, ifr) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in *subnet_mask_in = (struct sockaddr_in *)&ifr->ifr_addr;
|
|
||||||
uint32_t subnet_mask = ntohl(subnet_mask_in->sin_addr.s_addr);
|
|
||||||
|
|
||||||
/* Result. */
|
|
||||||
if (ip_info) {
|
|
||||||
ip_info->ip_addr = ip_addr;
|
|
||||||
ip_info->subnet_mask = subnet_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(LIBHDHOMERUN_USE_LEGACY_SIOCGIFCONF)
|
#if defined(LIBHDHOMERUN_USE_LEGACY_SIOCGIFCONF)
|
||||||
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
|
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +76,7 @@ int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hdhomerun_local_ip_info_t *ip_info = (max_count > 0) ? ip_info_list : NULL;
|
struct hdhomerun_local_ip_info_t *ip_info = ip_info_list;
|
||||||
char *ptr = ifc.ifc_buf;
|
char *ptr = ifc.ifc_buf;
|
||||||
char *end = ifc.ifc_buf + ifc.ifc_len;
|
char *end = ifc.ifc_buf + ifc.ifc_len;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -122,17 +85,43 @@ int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int
|
||||||
struct ifreq *ifr = (struct ifreq *)ptr;
|
struct ifreq *ifr = (struct ifreq *)ptr;
|
||||||
ptr += sizeof(struct ifreq);
|
ptr += sizeof(struct ifreq);
|
||||||
|
|
||||||
if (!hdhomerun_local_ip_info_add(ip_info, sock, ifr)) {
|
/* Flags. */
|
||||||
|
if (ioctl(sock, SIOCGIFFLAGS, ifr) != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
unsigned int flags = ifr->ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_UP | IFF_RUNNING);
|
||||||
|
if (flags != (IFF_UP | IFF_RUNNING)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (count >= max_count) {
|
/* Local IP address. */
|
||||||
ip_info = NULL;
|
if (ioctl(sock, SIOCGIFADDR, ifr) != 0) {
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in *ip_addr_in = (struct sockaddr_in *)&ifr->ifr_addr;
|
||||||
|
uint32_t ip_addr = ntohl(ip_addr_in->sin_addr.s_addr);
|
||||||
|
if (ip_addr == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subnet mask. */
|
||||||
|
if (ioctl(sock, SIOCGIFNETMASK, ifr) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in *subnet_mask_in = (struct sockaddr_in *)&ifr->ifr_addr;
|
||||||
|
uint32_t subnet_mask = ntohl(subnet_mask_in->sin_addr.s_addr);
|
||||||
|
|
||||||
|
/* Result. */
|
||||||
|
if (count < max_count) {
|
||||||
|
ip_info->ip_addr = ip_addr;
|
||||||
|
ip_info->subnet_mask = subnet_mask;
|
||||||
ip_info++;
|
ip_info++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ifreq_buffer);
|
free(ifreq_buffer);
|
||||||
|
@ -142,51 +131,50 @@ int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int
|
||||||
#else
|
#else
|
||||||
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
|
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
|
||||||
{
|
{
|
||||||
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
struct ifaddrs *ifaddrs;
|
||||||
if (sock == -1) {
|
if (getifaddrs(&ifaddrs) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct if_nameindex *ni = if_nameindex();
|
struct hdhomerun_local_ip_info_t *ip_info = ip_info_list;
|
||||||
if (!ni) {
|
struct ifaddrs *ifa = ifaddrs;
|
||||||
close(sock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct hdhomerun_local_ip_info_t *ip_info = (max_count > 0) ? ip_info_list : NULL;
|
|
||||||
struct if_nameindex *iter = ni;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
while (1) {
|
while (ifa) {
|
||||||
if (!iter->if_name) {
|
if (ifa->ifa_addr == NULL) {
|
||||||
if (iter->if_index == 0) {
|
ifa = ifa->ifa_next;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
iter++;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ifreq ifr;
|
if (ifa->ifa_addr->sa_family != AF_INET) {
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
ifa = ifa->ifa_next;
|
||||||
strncpy(ifr.ifr_name, iter->if_name, IF_NAMESIZE);
|
|
||||||
iter++;
|
|
||||||
|
|
||||||
if (!hdhomerun_local_ip_info_add(ip_info, sock, &ifr)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int flags = ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_UP | IFF_RUNNING);
|
||||||
|
if (flags != (IFF_UP | IFF_RUNNING)) {
|
||||||
|
ifa = ifa->ifa_next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in *addr_in = (struct sockaddr_in *)ifa->ifa_addr;
|
||||||
|
uint32_t ip_addr = ntohl(addr_in->sin_addr.s_addr);
|
||||||
|
|
||||||
|
struct sockaddr_in *netmask_in = (struct sockaddr_in *)ifa->ifa_netmask;
|
||||||
|
uint32_t subnet_mask = ntohl(netmask_in->sin_addr.s_addr);
|
||||||
|
|
||||||
|
ifa = ifa->ifa_next;
|
||||||
|
|
||||||
|
if (count < max_count) {
|
||||||
|
ip_info->ip_addr = ip_addr;
|
||||||
|
ip_info->subnet_mask = subnet_mask;
|
||||||
|
ip_info++;
|
||||||
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (count >= max_count) {
|
|
||||||
ip_info = NULL;
|
|
||||||
} else {
|
|
||||||
ip_info++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if_freenameindex(ni);
|
freeifaddrs(ifaddrs);
|
||||||
close(sock);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue