#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <syslog.h>
#include "rtadvd.h"
#include "if.h"
sizeof(uint32_t)) :\
sizeof(uint32_t)))
-struct if_msghdr **iflist;
-int iflist_init_ok;
+/* Interface list */
+TAILQ_HEAD(ifilist_head_t, ifinfo);
+struct ifilist_head_t ifilist = TAILQ_HEAD_INITIALIZER(ifilist);
size_t ifblock_size;
char *ifblock;
static void get_iflist(char **buf, size_t *size);
-static void parse_iflist(struct if_msghdr ***ifmlist_p, char *buf,
- size_t bufsize);
+static void parse_iflist(char *buf, size_t bufsize);
+static void purge_iflist();
static void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
int s;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "<%s> socket: %s", __func__,
+ errorlog("<%s> socket: %s", __func__,
strerror(errno));
return (oifflags & ~IFF_UP);
}
if_indextoname(ifindex, ifr.ifr_name);
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
- syslog(LOG_ERR, "<%s> ioctl:SIOCGIFFLAGS: failed for %s",
+ errorlog("<%s> ioctl:SIOCGIFFLAGS: failed for %s",
__func__, ifr.ifr_name);
close(s);
return (oifflags & ~IFF_UP);
memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
break;
default:
- syslog(LOG_ERR, "<%s> unsupported link type(%d)",
+ errorlog("<%s> unsupported link type(%d)",
__func__, sdl->sdl_type);
exit(1);
}
rtm = (struct rt_msghdr *)(((char *)rtm) + rtm->rtm_msglen)) {
/* just for safety */
if (!rtm->rtm_msglen) {
- syslog(LOG_WARNING, "<%s> rtm_msglen is 0 "
+ errorlog("<%s> rtm_msglen is 0 "
"(buf=%p lim=%p rtm=%p)", __func__,
buf, lim, rtm);
break;
mib[5] = 0;
if (sysctl(mib, 6, NULL, size, NULL, 0) < 0) {
- syslog(LOG_ERR, "<%s> sysctl: iflist size get failed",
+ errorlog("<%s> sysctl: iflist size get failed",
__func__);
exit(1);
}
if ((*buf = malloc(*size)) == NULL) {
- syslog(LOG_ERR, "<%s> malloc failed", __func__);
+ errorlog("<%s> malloc failed", __func__);
exit(1);
}
if (sysctl(mib, 6, *buf, size, NULL, 0) < 0) {
- syslog(LOG_ERR, "<%s> sysctl: iflist get failed",
+ errorlog("<%s> sysctl: iflist get failed",
__func__);
exit(1);
}
return;
}
+struct if_msghdr *
+get_interface_entry(int if_index)
+{
+ struct ifinfo *ifi = NULL;
+ struct if_msghdr *ifm = NULL;
+
+ TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
+ if (if_index == ifi->ifm->ifm_index) {
+ ifm = ifi->ifm;
+ break;
+ }
+ }
+ return ifm;
+}
+
/*
* alloc buffer and parse if_msghdrs block passed as arg,
* and init the buffer as list of pointers ot each of the if_msghdr.
*/
static void
-parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize)
+parse_iflist(char *buf, size_t bufsize)
{
- int iflentry_size, malloc_size;
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
char *lim;
- /*
- * Estimate least size of an iflist entry, to be obtained from kernel.
- * Should add sizeof(sockaddr) ??
- */
- iflentry_size = sizeof(struct if_msghdr);
- /* roughly estimate max list size of pointers to each if_msghdr */
- malloc_size = (bufsize/iflentry_size) * sizeof(size_t);
- if ((*ifmlist_p = (struct if_msghdr **)malloc(malloc_size)) == NULL) {
- syslog(LOG_ERR, "<%s> malloc failed", __func__);
- exit(1);
- }
-
lim = buf + bufsize;
for (ifm = (struct if_msghdr *)buf; ifm < (struct if_msghdr *)lim;) {
if (ifm->ifm_msglen == 0) {
- syslog(LOG_WARNING, "<%s> ifm_msglen is 0 "
+ errorlog("<%s> ifm_msglen is 0 "
"(buf=%p lim=%p ifm=%p)", __func__,
buf, lim, ifm);
return;
}
if (ifm->ifm_type == RTM_IFINFO) {
- (*ifmlist_p)[ifm->ifm_index] = ifm;
+ struct ifinfo *ifi = NULL;
+
+ if (get_interface_entry(ifm->ifm_index) != NULL) {
+ debuglog("Interface entry is already present for "
+ "interface index: %d. Skipping.", ifm->ifm_index);
+ continue;
+ }
+
+ ELM_MALLOC(ifi, exit(1));
+ ifi->ifm = ifm;
+ TAILQ_INSERT_TAIL(&ifilist, ifi, ifi_next);
} else {
- syslog(LOG_ERR, "out of sync parsing NET_RT_IFLIST\n"
+ errorlog("out of sync parsing NET_RT_IFLIST\n"
"expected %d, got %d\n msglen = %d\n"
"buf:%p, ifm:%p, lim:%p\n",
RTM_IFINFO, ifm->ifm_type, ifm->ifm_msglen,
((char *)ifam + ifam->ifam_msglen)) {
/* just for safety */
if (!ifam->ifam_msglen) {
- syslog(LOG_WARNING, "<%s> ifa_msglen is 0 "
+ errorlog("<%s> ifa_msglen is 0 "
"(buf=%p lim=%p ifam=%p)", __func__,
buf, lim, ifam);
return;
}
}
+static void
+purge_iflist()
+{
+ struct ifinfo *ifi = NULL;
+ if (!TAILQ_EMPTY(&ifilist)) {
+ while ((ifi = TAILQ_FIRST(&ifilist)) != NULL) {
+ TAILQ_REMOVE(&ifilist, ifi, ifi_next);
+ free(ifi);
+ }
+ }
+}
+
void
init_iflist()
{
+ purge_iflist();
+
if (ifblock) {
free(ifblock);
ifblock_size = 0;
}
- if (iflist)
- free(iflist);
+
/* get iflist block from kernel */
get_iflist(&ifblock, &ifblock_size);
/* make list of pointers to each if_msghdr */
- parse_iflist(&iflist, ifblock, ifblock_size);
+ parse_iflist(ifblock, ifblock_size);
}