summaryrefslogtreecommitdiffstats
path: root/usr.sbin/rtadvd/rtadvd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/rtadvd/rtadvd.c')
-rw-r--r--usr.sbin/rtadvd/rtadvd.c84
1 files changed, 80 insertions, 4 deletions
diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c
index d76be75..bd31f49 100644
--- a/usr.sbin/rtadvd/rtadvd.c
+++ b/usr.sbin/rtadvd/rtadvd.c
@@ -90,6 +90,8 @@ int sock;
int rtsock = -1;
int accept_rr = 0;
int dflag = 0, sflag = 0;
+static int ifl_len;
+static char **ifl_names;
struct railist_head_t railist =
TAILQ_HEAD_INITIALIZER(railist);
@@ -171,6 +173,7 @@ static void ra_output(struct rainfo *);
static void rtmsg_input(void);
static void rtadvd_set_dump_file(int);
static void set_short_delay(struct rainfo *);
+static int ifl_lookup(char *, char **, int);
int
main(int argc, char *argv[])
@@ -186,6 +189,7 @@ main(int argc, char *argv[])
int i, ch;
int fflag = 0, logopt;
pid_t pid, otherpid;
+ int error;
/* get command line options and arguments */
while ((ch = getopt(argc, argv, "c:dDfF:M:p:Rs")) != -1) {
@@ -258,9 +262,25 @@ main(int argc, char *argv[])
#endif
/* get iflist block from kernel */
init_iflist();
+ ifl_names = argv;
+ ifl_len = argc;
+
+ for (i = 0; i < ifl_len; i++) {
+ int idx;
- while (argc--)
- getconfig(*argv++);
+ idx = if_nametoindex(ifl_names[i]);
+ if (idx == 0) {
+ syslog(LOG_INFO,
+ "<%s> interface %s not found."
+ "Ignored at this moment.", __func__, ifl_names[i]);
+ continue;
+ }
+ error = getconfig(idx);
+ if (error)
+ syslog(LOG_INFO,
+ "<%s> invalid configuration for %s."
+ "Ignored at this moment.", __func__, ifl_names[i]);
+ }
pfh = pidfile_open(pidfilename, 0600, &otherpid);
if (pfh == NULL) {
@@ -376,6 +396,15 @@ main(int argc, char *argv[])
exit(0); /* NOTREACHED */
}
+static int
+ifl_lookup(char *ifn, char **names, int len)
+{
+ while (len--)
+ if (strncmp(names[len], ifn, IFNAMSIZ) == 0)
+ return (0);
+ return (-1);
+}
+
static void
rtadvd_set_dump_file(int sig __unused)
{
@@ -426,12 +455,14 @@ rtmsg_input(void)
int n, type, ifindex = 0, plen;
size_t len;
char msg[2048], *next, *lim;
- u_char ifname[IF_NAMESIZE];
+ u_char ifname[IFNAMSIZ];
+ struct if_announcemsghdr *ifan;
struct prefix *pfx;
struct rainfo *rai;
struct in6_addr *addr;
char addrbuf[INET6_ADDRSTRLEN];
int prefixchange = 0;
+ int error;
n = read(rtsock, msg, sizeof(msg));
syslog(LOG_DEBUG, "<%s> received a routing message "
@@ -462,7 +493,8 @@ rtmsg_input(void)
RTADV_TYPE2BITMASK(RTM_DELETE) |
RTADV_TYPE2BITMASK(RTM_NEWADDR) |
RTADV_TYPE2BITMASK(RTM_DELADDR) |
- RTADV_TYPE2BITMASK(RTM_IFINFO));
+ RTADV_TYPE2BITMASK(RTM_IFINFO) |
+ RTADV_TYPE2BITMASK(RTM_IFANNOUNCE));
if (len == 0)
break;
type = rtmsg_type(next);
@@ -478,6 +510,50 @@ rtmsg_input(void)
case RTM_IFINFO:
ifindex = get_ifm_ifindex(next);
break;
+ case RTM_IFANNOUNCE:
+ ifan = (struct if_announcemsghdr *)next;
+ switch (ifan->ifan_what) {
+ case IFAN_ARRIVAL:
+ case IFAN_DEPARTURE:
+ break;
+ default:
+ syslog(LOG_DEBUG,
+ "<%s:%d> unknown ifan msg (ifan_what=%d)",
+ __func__, __LINE__, ifan->ifan_what);
+ continue;
+ }
+
+ syslog(LOG_INFO, "<%s>: if_announcemsg (idx=%d:%d)",
+ __func__, ifan->ifan_index, ifan->ifan_what);
+ init_iflist();
+ error = ifl_lookup(ifan->ifan_name,
+ ifl_names, ifl_len);
+ if (error) {
+ syslog(LOG_INFO, "<%s>: not a target "
+ "interface (idx=%d)", __func__,
+ ifan->ifan_index);
+ continue;
+ }
+
+ switch (ifan->ifan_what) {
+ case IFAN_ARRIVAL:
+ error = getconfig(ifan->ifan_index);
+ if (error)
+ syslog(LOG_ERR,
+ "<%s>: getconfig failed (idx=%d)"
+ " Ignored.", __func__,
+ ifan->ifan_index);
+ break;
+ case IFAN_DEPARTURE:
+ error = rmconfig(ifan->ifan_index);
+ if (error)
+ syslog(LOG_ERR,
+ "<%s>: rmconfig failed (idx=%d)"
+ " Ignored.", __func__,
+ ifan->ifan_index);
+ break;
+ }
+ continue;
default:
/* should not reach here */
syslog(LOG_DEBUG,
OpenPOWER on IntegriCloud