mirror of
https://github.com/Silicondust/libhdhomerun
synced 2025-08-21 14:03:25 -07:00
Network Interface Detection Bug Fix
It appears that the socket ioctl command SIOCGIFCONF can return invalid objects. When the socket ioctl command SIOCGIFFLAGS was called on the network interfaces returned by SIOCGIFCONF, the function can return in error with errno ENODEV (19) "No such device." Specifically, this affected running the software on my DD-WRT ARM based linux distrobution. According to "http://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/baselib-sockio-2.html", "The SIOCGIFCONF interface is superceded by the if_nameindex() family of functions (see ISO POSIX (2003))." After switching to use if_nameindex(), the hdhomerun_local_ip_info() function is now successfully is able to lookup network interfaces on DD-WRT's ARM implementation. Additionally, I have tested this on my Macbook and it appears to work with no problems. Testing was done by running the command "./hdhomerun_config discover"
This commit is contained in:
parent
0d3b72c1cc
commit
e1d847772b
1 changed files with 21 additions and 37 deletions
58
hdhomerun_sock_posix.c
Normal file → Executable file
58
hdhomerun_sock_posix.c
Normal file → Executable file
|
@ -20,13 +20,11 @@
|
|||
|
||||
#include "hdhomerun.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifndef SIOCGIFCONF
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
|
||||
#ifndef _SIZEOF_ADDR_IFREQ
|
||||
#define _SIZEOF_ADDR_IFREQ(x) sizeof(x)
|
||||
#endif
|
||||
|
@ -35,54 +33,39 @@
|
|||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
|
||||
struct hdhomerun_sock_t {
|
||||
int sock;
|
||||
};
|
||||
|
||||
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
|
||||
{
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (sock == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ifconf ifc;
|
||||
size_t ifreq_buffer_size = 1024;
|
||||
|
||||
while (1) {
|
||||
ifc.ifc_len = (int)ifreq_buffer_size;
|
||||
ifc.ifc_buf = (char *)malloc(ifreq_buffer_size);
|
||||
if (!ifc.ifc_buf) {
|
||||
close(sock);
|
||||
return -1;
|
||||
/*
|
||||
* Retrieve network interfaces from OS. if_nameindex() dynamically allocates a list of
|
||||
* network interface names and indexs.
|
||||
*/
|
||||
struct if_nameindex *if_ni, *iter;
|
||||
if_ni = if_nameindex();
|
||||
if (if_ni == NULL) {
|
||||
perror("if_nameindex");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(ifc.ifc_buf, 0, ifreq_buffer_size);
|
||||
|
||||
if (ioctl(sock, SIOCGIFCONF, &ifc) != 0) {
|
||||
free(ifc.ifc_buf);
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ifc.ifc_len < (int)ifreq_buffer_size) {
|
||||
break;
|
||||
}
|
||||
|
||||
free(ifc.ifc_buf);
|
||||
ifreq_buffer_size += 1024;
|
||||
}
|
||||
|
||||
char *ptr = ifc.ifc_buf;
|
||||
char *end = ifc.ifc_buf + ifc.ifc_len;
|
||||
|
||||
struct ifreq *ifr = malloc(sizeof(struct ifreq));
|
||||
int count = 0;
|
||||
while (ptr < end) {
|
||||
struct ifreq *ifr = (struct ifreq *)ptr;
|
||||
ptr += _SIZEOF_ADDR_IFREQ(*ifr);
|
||||
for (iter = if_ni; ! (iter->if_index == 0 && iter->if_name == NULL); ++iter) {
|
||||
|
||||
/* Set interface's name for flag lookup. */
|
||||
strncpy(ifr->ifr_name, iter->if_name, IF_NAMESIZE);
|
||||
|
||||
/* Flags. */
|
||||
if (ioctl(sock, SIOCGIFFLAGS, ifr) != 0) {
|
||||
fprintf(stderr, "ioctl: flags SIOCGIFFLAGS errno %d/%s\n", errno, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -122,7 +105,8 @@ int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int
|
|||
count++;
|
||||
}
|
||||
|
||||
free(ifc.ifc_buf);
|
||||
if_freenameindex(if_ni);
|
||||
free(ifr);
|
||||
close(sock);
|
||||
return count;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue