#include <sys/param.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <net/if.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <stddef.h>
#include <err.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include "rtsold.h"
#ifdef RTM_IFANNOUNCE
static int rtsock_input_ifannounce(int, struct rt_msghdr *, char *);
#endif
static struct {
u_char type;
size_t minlen;
int (*func)(int, struct rt_msghdr *, char *);
} rtsock_dispatch[] = {
#ifdef RTM_IFANNOUNCE
{ RTM_IFANNOUNCE, sizeof(struct if_announcemsghdr),
rtsock_input_ifannounce },
#endif
{ 0, 0, NULL },
};
int
rtsock_open(void)
{
return socket(PF_ROUTE, SOCK_RAW, 0);
}
int
rtsock_input(int s)
{
ssize_t n;
char msg[2048];
char *lim, *next;
struct rt_msghdr *rtm;
int idx;
ssize_t len;
int ret = 0;
const ssize_t lenlim =
offsetof(struct rt_msghdr, rtm_msglen) + sizeof(rtm->rtm_msglen);
n = read(s, msg, sizeof(msg));
lim = msg + n;
for (next = msg; next < lim; next += len) {
rtm = (struct rt_msghdr *)next;
if (lim - next < lenlim)
break;
len = rtm->rtm_msglen;
if (len < lenlim)
break;
if (dflag > 1) {
warnmsg(LOG_INFO, __func__,
"rtmsg type %d, len=%lu", rtm->rtm_type,
(u_long)len);
}
for (idx = 0; rtsock_dispatch[idx].func; idx++) {
if (rtm->rtm_type != rtsock_dispatch[idx].type)
continue;
if (rtm->rtm_msglen < rtsock_dispatch[idx].minlen) {
warnmsg(LOG_INFO, __func__,
"rtmsg type %d too short!", rtm->rtm_type);
continue;
}
ret = (*rtsock_dispatch[idx].func)(s, rtm, lim);
break;
}
}
return ret;
}
#ifdef RTM_IFANNOUNCE
static int
rtsock_input_ifannounce(int s __unused, struct rt_msghdr *rtm, char *lim)
{
struct if_announcemsghdr *ifan;
struct ifinfo *ifinfo;
ifan = (struct if_announcemsghdr *)rtm;
if ((char *)(ifan + 1) > lim)
return -1;
switch (ifan->ifan_what) {
case IFAN_ARRIVAL:
warnmsg(LOG_INFO, __func__,
"interface %s inserted", ifan->ifan_name);
break;
case IFAN_DEPARTURE:
warnmsg(LOG_WARNING, __func__,
"interface %s removed", ifan->ifan_name);
ifinfo = find_ifinfo(ifan->ifan_index);
if (ifinfo) {
if (dflag > 1) {
warnmsg(LOG_INFO, __func__,
"bring interface %s to DOWN state",
ifan->ifan_name);
}
ifinfo->state = IFS_DOWN;
}
break;
}
return 0;
}
#endif