#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"
#define ROUNDUP(a, size) \
(((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
#define NEXT_SA(ap) (ap) = (struct sockaddr *) \
((caddr_t)(ap) + \
((ap)->sa_len ? ROUNDUP((ap)->sa_len, sizeof(uint32_t)) \
: sizeof(uint32_t)))
#ifdef RTM_IFANNOUNCE
static int rtsock_input_ifannounce __P((int, struct rt_msghdr *, char *));
#endif
static struct {
u_char type;
size_t minlen;
int (*func) __P((int, struct rt_msghdr *, char *));
} rtsock_dispatch[] = {
#ifdef RTM_IFANNOUNCE
{ RTM_IFANNOUNCE, sizeof(struct if_announcemsghdr),
rtsock_input_ifannounce },
#endif
{ 0, 0UL, NULL },
};
int
rtsock_open()
{
return socket(PF_ROUTE, SOCK_RAW, 0);
}
int
rtsock_input(s)
int s;
{
ssize_t n;
char msg[2048];
char *lim, *next;
struct rt_msghdr *rtm;
int idx;
size_t len;
int ret = 0;
const size_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, __FUNCTION__,
"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, __FUNCTION__,
"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(s, rtm, lim)
int s;
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, __FUNCTION__,
"interface %s inserted", ifan->ifan_name);
break;
case IFAN_DEPARTURE:
warnmsg(LOG_WARNING, __FUNCTION__,
"interface %s removed", ifan->ifan_name);
ifinfo = find_ifinfo(ifan->ifan_index);
if (ifinfo) {
if (dflag > 1) {
warnmsg(LOG_INFO, __FUNCTION__,
"bring interface %s to DOWN state",
ifan->ifan_name);
}
ifinfo->state = IFS_DOWN;
}
break;
}
return 0;
}
#endif