* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/if.c,v 1.2.2.3 2001/07/03 11:02:14 ume Exp $
*/
#include <sys/param.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_types.h>
-#if defined(__FreeBSD__) || defined (__APPLE__)
-# include <net/ethernet.h>
-#endif
+#include <net/ethernet.h>
#include <ifaddrs.h>
-#ifdef __NetBSD__
-#include <net/if_ether.h>
-#endif
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
-#ifdef __bsdi__
-# include <netinet/if_ether.h>
-#endif
-#ifdef __OpenBSD__
-#include <netinet/if_ether.h>
-#endif
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <syslog.h>
#include "rtadvd.h"
#include "if.h"
#define NEXT_SA(ap) (ap) = (struct sockaddr *) \
((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\
- sizeof(u_long)) :\
- sizeof(u_long)))
+ 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 __P((char **buf, size_t *size));
-static void parse_iflist __P((struct if_msghdr ***ifmlist_p, char *buf,
- size_t bufsize));
+static void get_iflist(char **buf, size_t *size);
+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)
return(NULL);
if ((buf = malloc(len)) == NULL)
return(NULL);
- if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
- goto end;
+ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+ free(buf);
+ return(NULL);
+ }
lim = buf + len;
for (next = buf; next < lim; next += ifm->ifm_msglen) {
}
if (next == lim) {
/* search failed */
- goto end;
+ free(buf);
+ return(NULL);
}
- if ((ret_sdl = malloc(sdl->sdl_len)) == NULL)
+ if (sdl == NULL || (ret_sdl = malloc(sdl->sdl_len)) == NULL)
goto end;
memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len);
end:
free(buf);
- return (ret_sdl);
+ return(ret_sdl);
}
int
{
struct ifaddrs *ifap, *ifa;
struct if_data *ifd;
- u_long mtu = 0;
+ int mtu = 0;
if (getifaddrs(&ifap) < 0)
return(0);
int s;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "<%s> socket: %s", __FUNCTION__,
+ 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",
- __FUNCTION__, ifr.ifr_name);
+ errorlog("<%s> ioctl:SIOCGIFFLAGS: failed for %s",
+ __func__, ifr.ifr_name);
close(s);
return (oifflags & ~IFF_UP);
}
int
lladdropt_length(struct sockaddr_dl *sdl)
{
- switch(sdl->sdl_type) {
- case IFT_ETHER:
- return(ROUNDUP8(ETHER_ADDR_LEN + 2));
- default:
- return(0);
+ switch (sdl->sdl_type) {
+ case IFT_ETHER:
+ return(ROUNDUP8(ETHER_ADDR_LEN + 2));
+ default:
+ return(0);
}
}
ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */
- switch(sdl->sdl_type) {
- case IFT_ETHER:
- ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
- addr = (char *)(ndopt + 1);
- memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
- break;
- default:
- syslog(LOG_ERR,
- "<%s> unsupported link type(%d)",
- __FUNCTION__, sdl->sdl_type);
- exit(1);
+ switch (sdl->sdl_type) {
+ case IFT_ETHER:
+ ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
+ addr = (char *)(ndopt + 1);
+ memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
+ break;
+ default:
+ errorlog("<%s> unsupported link type(%d)",
+ __func__, sdl->sdl_type);
+ exit(1);
}
return;
rtm = (struct rt_msghdr *)(((char *)rtm) + rtm->rtm_msglen)) {
/* just for safety */
if (!rtm->rtm_msglen) {
- syslog(LOG_WARNING, "<%s> rtm_msglen is 0 "
- "(buf=%p lim=%p rtm=%p)", __FUNCTION__,
+ 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",
- __FUNCTION__);
+ errorlog("<%s> sysctl: iflist size get failed",
+ __func__);
exit(1);
}
if ((*buf = malloc(*size)) == NULL) {
- syslog(LOG_ERR, "<%s> malloc failed", __FUNCTION__);
+ errorlog("<%s> malloc failed", __func__);
exit(1);
}
if (sysctl(mib, 6, *buf, size, NULL, 0) < 0) {
- syslog(LOG_ERR, "<%s> sysctl: iflist get failed",
- __FUNCTION__);
+ 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", __FUNCTION__);
- 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 "
- "(buf=%p lim=%p ifm=%p)", __FUNCTION__,
+ 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 "
- "(buf=%p lim=%p ifam=%p)", __FUNCTION__,
+ 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);
}