Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142777296
D17572.id52589.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
59 KB
Referenced Files
None
Subscribers
None
D17572.id52589.diff
View Options
Index: head/sbin/rtsol/Makefile
===================================================================
--- head/sbin/rtsol/Makefile
+++ head/sbin/rtsol/Makefile
@@ -18,10 +18,24 @@
PACKAGE=runtime
PROG= rtsol
-SRCS= rtsold.c rtsol.c if.c probe.c dump.c rtsock.c
+SRCS= cap_llflags.c \
+ cap_script.c \
+ cap_sendmsg.c \
+ dump.c \
+ if.c \
+ rtsol.c \
+ rtsold.c \
+ rtsock.c
MAN=
+LIBADD= util
-WARNS?= 3
-CFLAGS+= -DSMALL
+.include <src.opts.mk>
+
+.if ${MK_DYNAMICROOT} == "no"
+.warning ${PROG} built without libcasper support
+.elif ${MK_CASPER} != "no" && !defined(RESCUE)
+CFLAGS+= -DWITH_CASPER
+LIBADD+= cap_syslog casper nv
+.endif
.include <bsd.prog.mk>
Index: head/usr.sbin/rtsold/Makefile
===================================================================
--- head/usr.sbin/rtsold/Makefile
+++ head/usr.sbin/rtsold/Makefile
@@ -17,8 +17,22 @@
PROG= rtsold
MAN= rtsold.8
MLINKS= rtsold.8 rtsol.8
-SRCS= rtsold.c rtsol.c if.c probe.c dump.c rtsock.c
+SRCS= cap_llflags.c \
+ cap_script.c \
+ cap_sendmsg.c \
+ dump.c \
+ if.c \
+ rtsock.c \
+ rtsol.c \
+ rtsold.c
-WARNS?= 3
+LIBADD= util
+
+.include <src.opts.mk>
+
+.if ${MK_CASPER} != "no"
+CFLAGS+= -DWITH_CASPER
+LIBADD+= casper cap_syslog nv
+.endif
.include <bsd.prog.mk>
Index: head/usr.sbin/rtsold/cap_llflags.c
===================================================================
--- head/usr.sbin/rtsold/cap_llflags.c
+++ head/usr.sbin/rtsold/cap_llflags.c
@@ -0,0 +1,157 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2018 The FreeBSD Foundation
+ *
+ * This software was developed by Mark Johnston under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/dnv.h>
+#include <sys/ioctl.h>
+#include <sys/nv.h>
+#include <sys/queue.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <string.h>
+
+#include <libcasper.h>
+#include <libcasper_service.h>
+
+#include "rtsold.h"
+
+/*
+ * A service to fetch the flags for the link-local IPv6 address on the specified
+ * interface. This cannot easily be done in capability mode because we need to
+ * use the routing socket sysctl API to find the link-local address of a
+ * particular interface. The SIOCGIFCONF ioctl is one other option, but as
+ * currently implemented it is less flexible (it cannot report the required
+ * buffer length), and hard-codes a buffer length limit.
+ */
+
+static int
+llflags_get(const char *ifname, int *flagsp)
+{
+ struct in6_ifreq ifr6;
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr_in6 *sin6;
+ int error, s;
+
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (s < 0)
+ return (-1);
+
+ if (getifaddrs(&ifap) != 0)
+ return (-1);
+ error = -1;
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ if (strcmp(ifa->ifa_name, ifname) != 0)
+ continue;
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+
+ sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr;
+ if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+ continue;
+
+ memset(&ifr6, 0, sizeof(ifr6));
+ if (strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)) >=
+ sizeof(ifr6.ifr_name)) {
+ freeifaddrs(ifap);
+ errno = EINVAL;
+ return (-1);
+ }
+ memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
+ if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
+ error = errno;
+ freeifaddrs(ifap);
+ errno = error;
+ return (-1);
+ }
+
+ *flagsp = ifr6.ifr_ifru.ifru_flags6;
+ error = 0;
+ break;
+ }
+ (void)close(s);
+ freeifaddrs(ifap);
+ if (error == -1)
+ errno = ENOENT;
+ return (error);
+}
+
+int
+cap_llflags_get(cap_channel_t *cap, const char *ifname, int *flagsp)
+{
+#ifdef WITH_CASPER
+ nvlist_t *nvl;
+ int error;
+
+ nvl = nvlist_create(0);
+ nvlist_add_string(nvl, "cmd", "get");
+ nvlist_add_string(nvl, "ifname", ifname);
+ nvl = cap_xfer_nvlist(cap, nvl);
+ if (nvl == NULL)
+ return (-1);
+ error = (int)dnvlist_get_number(nvl, "error", 0);
+ if (error == 0)
+ *flagsp = (int)nvlist_get_number(nvl, "flags");
+ nvlist_destroy(nvl);
+ if (error != 0)
+ errno = error;
+ return (error == 0 ? 0 : -1);
+#else
+ (void)cap;
+ return (llflags_get(ifname, flagsp));
+#endif
+}
+
+#ifdef WITH_CASPER
+static int
+llflags_command(const char *cmd, const nvlist_t *limits __unused,
+ nvlist_t *nvlin, nvlist_t *nvlout)
+{
+ const char *ifname;
+ int flags;
+
+ if (strcmp(cmd, "get") != 0)
+ return (EINVAL);
+ ifname = nvlist_get_string(nvlin, "ifname");
+ if (llflags_get(ifname, &flags) != 0)
+ return (errno);
+ nvlist_add_number(nvlout, "flags", flags);
+ return (0);
+}
+
+CREATE_SERVICE("rtsold.llflags", NULL, llflags_command, 0);
+#endif /* WITH_CASPER */
Index: head/usr.sbin/rtsold/cap_script.c
===================================================================
--- head/usr.sbin/rtsold/cap_script.c
+++ head/usr.sbin/rtsold/cap_script.c
@@ -0,0 +1,236 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2018 The FreeBSD Foundation
+ *
+ * This software was developed by Mark Johnston under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/capsicum.h>
+#include <sys/dnv.h>
+#include <sys/nv.h>
+#include <sys/queue.h>
+#include <sys/wait.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <capsicum_helpers.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+#include <libcasper_service.h>
+
+#include "rtsold.h"
+
+/*
+ * Run the script and return the write end of a pipe to the main process.
+ * Return -1 and set errno on error.
+ */
+static int
+script_run(char **argv)
+{
+ pid_t pid;
+ int fd[2], null;
+
+ if (pipe(fd) != 0)
+ return (-1);
+ if ((pid = fork()) < 0)
+ return (-1);
+ if (pid == 0) {
+ (void)close(fd[1]);
+ null = open("/dev/null", O_RDWR);
+ if (null < 0)
+ _exit(1);
+ if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
+ _exit(1);
+
+ closefrom(3);
+ (void)execve(argv[0], argv, NULL);
+ _exit(1);
+ } else
+ (void)close(fd[0]);
+
+ return (fd[1]);
+}
+
+int
+cap_script_run(cap_channel_t *cap, const char *const *argv)
+{
+#ifdef WITH_CASPER
+ nvlist_t *nvl;
+ size_t argc;
+ int error, wfd;
+
+ for (argc = 0; argv[argc] != NULL; argc++)
+ ;
+
+ nvl = nvlist_create(0);
+ nvlist_add_string(nvl, "cmd", "script_run");
+ nvlist_add_string_array(nvl, "argv", argv, argc);
+ nvl = cap_xfer_nvlist(cap, nvl);
+ if (nvl == NULL)
+ return (-1);
+
+ error = (int)dnvlist_get_number(nvl, "error", 0);
+ if (error == 0)
+ wfd = nvlist_take_descriptor(nvl, "fd");
+ nvlist_destroy(nvl);
+ if (error != 0)
+ errno = error;
+ return (error == 0 ? wfd : -1);
+#else
+ (void)cap;
+ return (script_run(__DECONST(char **, argv)));
+#endif
+}
+
+/*
+ * Wait for a child process to exit, and return its status.
+ * Return -1 and set errno upon error.
+ */
+static int
+script_wait(int *statusp)
+{
+ int error;
+
+ error = wait(statusp);
+ return (error >= 0 ? 0 : -1);
+}
+
+int
+cap_script_wait(cap_channel_t *cap, int *statusp)
+{
+#ifdef WITH_CASPER
+ nvlist_t *nvl;
+ int error;
+
+ nvl = nvlist_create(0);
+ nvlist_add_string(nvl, "cmd", "script_wait");
+ nvl = cap_xfer_nvlist(cap, nvl);
+ if (nvl == NULL)
+ return (-1);
+
+ error = (int)dnvlist_get_number(nvl, "error", 0);
+ if (error == 0)
+ *statusp = (int)nvlist_get_number(nvl, "status");
+ nvlist_destroy(nvl);
+ if (error != 0)
+ errno = error;
+ return (error == 0 ? 0 : -1);
+#else
+ (void)cap;
+ return (script_wait(statusp));
+#endif
+}
+
+#ifdef WITH_CASPER
+static int
+script_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
+ nvlist_t *nvlout)
+{
+ cap_rights_t rights;
+ const char *const *iargv, *const *scripts;
+ char **argv;
+ size_t argc, i, nscripts;
+ int fd, status;
+
+ if (strcmp(cmd, "script_wait") == 0) {
+ /* Wait for the result of a previous "script_run" command. */
+ if (script_wait(&status) == -1)
+ return (errno);
+ nvlist_add_number(nvlout, "status", status);
+ return (0);
+ }
+ if (strcmp(cmd, "script_run") != 0)
+ return (EINVAL);
+
+ /*
+ * Validate the argv against the limits specified at initialization
+ * time.
+ */
+ iargv = nvlist_get_string_array(nvlin, "argv", &argc);
+ if (argc == 0)
+ return (EINVAL);
+ scripts = nvlist_get_string_array(limits, "scripts", &nscripts);
+ for (i = 0; i < nscripts; i++)
+ if (strcmp(iargv[0], scripts[i]) == 0)
+ break;
+ if (i == nscripts)
+ return (EINVAL);
+
+ /*
+ * The nvlist API does not permit NULL pointers in an array, so we have
+ * to add the nul terminator ourselves. Yuck.
+ */
+ argv = calloc(argc + 1, sizeof(*argv));
+ if (argv == NULL)
+ return (errno);
+ memcpy(argv, iargv, sizeof(*argv) * argc);
+
+ fd = script_run(argv);
+ if (fd < 0)
+ return (errno);
+
+ (void)caph_rights_limit(fd, cap_rights_init(&rights, CAP_WRITE));
+ nvlist_move_descriptor(nvlout, "fd", fd);
+ return (0);
+}
+
+static int
+script_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits __unused)
+{
+ const char *name;
+ void *cookie;
+ int nvtype;
+ bool hasscripts;
+
+ /* Limits may only be set once. */
+ if (oldlimits != NULL)
+ return (ENOTCAPABLE);
+
+ cookie = NULL;
+ hasscripts = false;
+ while ((name = nvlist_next(newlimits, &nvtype, &cookie)) != NULL) {
+ if (nvtype == NV_TYPE_STRING_ARRAY &&
+ strcmp(name, "scripts") == 0)
+ hasscripts = true;
+ else
+ return (EINVAL);
+ }
+ if (!hasscripts)
+ return (EINVAL);
+ return (0);
+}
+
+CREATE_SERVICE("rtsold.script", script_limit, script_command, 0);
+#endif /* WITH_CASPER */
Index: head/usr.sbin/rtsold/cap_sendmsg.c
===================================================================
--- head/usr.sbin/rtsold/cap_sendmsg.c
+++ head/usr.sbin/rtsold/cap_sendmsg.c
@@ -0,0 +1,282 @@
+/* $KAME: probe.c,v 1.17 2003/10/05 00:09:36 itojun Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (C) 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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$
+ */
+
+#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/dnv.h>
+#include <sys/nv.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+#include <netinet/icmp6.h>
+#include <netinet6/nd6.h>
+
+#include <arpa/inet.h>
+
+#include <capsicum_helpers.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+#include <libcasper_service.h>
+
+#include "rtsold.h"
+
+static int
+getsocket(int *sockp, int proto)
+{
+ cap_rights_t rights;
+ int sock;
+
+ if (*sockp >= 0)
+ return (0);
+
+ if ((sock = socket(AF_INET6, SOCK_RAW, proto)) < 0)
+ return (-1);
+ cap_rights_init(&rights, CAP_CONNECT, CAP_SEND);
+ if (caph_rights_limit(sock, &rights) != 0)
+ return (-1);
+ *sockp = sock;
+
+ return (0);
+}
+
+static ssize_t
+sendpacket(int sock, struct sockaddr_in6 *dst, uint32_t ifindex, int hoplimit,
+ const void *data, size_t len)
+{
+ uint8_t cmsg[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
+ CMSG_SPACE(sizeof(int))];
+ struct msghdr hdr;
+ struct iovec iov;
+ struct in6_pktinfo *pi;
+ struct cmsghdr *cm;
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.msg_name = dst;
+ hdr.msg_namelen = sizeof(*dst);
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+ hdr.msg_control = cmsg;
+ hdr.msg_controllen = sizeof(cmsg);
+
+ iov.iov_base = __DECONST(void *, data);
+ iov.iov_len = len;
+
+ /* Specify the outbound interface. */
+ cm = CMSG_FIRSTHDR(&hdr);
+ cm->cmsg_level = IPPROTO_IPV6;
+ cm->cmsg_type = IPV6_PKTINFO;
+ cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ pi = (struct in6_pktinfo *)(void *)CMSG_DATA(cm);
+ memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/
+ pi->ipi6_ifindex = ifindex;
+
+ /* Specify the hop limit of the packet for safety. */
+ cm = CMSG_NXTHDR(&hdr, cm);
+ cm->cmsg_level = IPPROTO_IPV6;
+ cm->cmsg_type = IPV6_HOPLIMIT;
+ cm->cmsg_len = CMSG_LEN(sizeof(int));
+ memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
+
+ return (sendmsg(sock, &hdr, 0));
+}
+
+static int
+probe_defrouters(uint32_t ifindex, uint32_t linkid)
+{
+ static int probesock = -1;
+ struct sockaddr_in6 dst;
+ struct in6_defrouter *p, *ep;
+ char *buf;
+ size_t len;
+ int mib[4];
+
+ if (ifindex == 0)
+ return (0);
+ if (getsocket(&probesock, IPPROTO_NONE) != 0)
+ return (-1);
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET6;
+ mib[2] = IPPROTO_ICMPV6;
+ mib[3] = ICMPV6CTL_ND6_DRLIST;
+ if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) < 0)
+ return (-1);
+ if (len == 0)
+ return (0);
+
+ memset(&dst, 0, sizeof(dst));
+ dst.sin6_family = AF_INET6;
+ dst.sin6_len = sizeof(dst);
+
+ buf = malloc(len);
+ if (buf == NULL)
+ return (-1);
+ if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) < 0)
+ return (-1);
+ ep = (struct in6_defrouter *)(void *)(buf + len);
+ for (p = (struct in6_defrouter *)(void *)buf; p < ep; p++) {
+ if (ifindex != p->if_index)
+ continue;
+ if (!IN6_IS_ADDR_LINKLOCAL(&p->rtaddr.sin6_addr))
+ continue;
+ dst.sin6_addr = p->rtaddr.sin6_addr;
+ dst.sin6_scope_id = linkid;
+ (void)sendpacket(probesock, &dst, ifindex, 1, NULL, 0);
+ }
+ free(buf);
+
+ return (0);
+}
+
+static int
+rssend(uint32_t ifindex, uint32_t linkid, const void *data, size_t len)
+{
+ static int rssock = -1;
+ struct sockaddr_in6 dst;
+ ssize_t n;
+
+ if (getsocket(&rssock, IPPROTO_ICMPV6) != 0)
+ return (-1);
+
+ memset(&dst, 0, sizeof(dst));
+ dst.sin6_family = AF_INET6;
+ dst.sin6_len = sizeof(dst);
+ dst.sin6_addr = (struct in6_addr)IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
+ dst.sin6_scope_id = linkid;
+
+ n = sendpacket(rssock, &dst, ifindex, 255, data, len);
+ if (n < 0 || (size_t)n != len)
+ return (-1);
+ return (0);
+}
+
+int
+cap_probe_defrouters(cap_channel_t *cap, struct ifinfo *ifinfo)
+{
+#ifdef WITH_CASPER
+ nvlist_t *nvl;
+ int error;
+
+ nvl = nvlist_create(0);
+ nvlist_add_string(nvl, "cmd", "probe_defrouters");
+ nvlist_add_number(nvl, "ifindex", ifinfo->sdl->sdl_index);
+ nvlist_add_number(nvl, "linkid", ifinfo->linkid);
+
+ nvl = cap_xfer_nvlist(cap, nvl);
+ if (nvl == NULL)
+ return (errno);
+ error = (int)dnvlist_get_number(nvl, "error", 0);
+ nvlist_destroy(nvl);
+ errno = error;
+ return (error == 0 ? 0 : -1);
+#else
+ (void)cap;
+ return (probe_defrouters(ifinfo->sdl->sdl_index, ifinfo->linkid));
+#endif
+}
+
+int
+cap_rssend(cap_channel_t *cap, struct ifinfo *ifinfo)
+{
+ int error;
+
+#ifdef WITH_CASPER
+ nvlist_t *nvl = nvlist_create(0);
+ nvlist_add_string(nvl, "cmd", "rssend");
+ nvlist_add_number(nvl, "ifindex", ifinfo->sdl->sdl_index);
+ nvlist_add_number(nvl, "linkid", ifinfo->linkid);
+ nvlist_add_binary(nvl, "data", ifinfo->rs_data, ifinfo->rs_datalen);
+
+ nvl = cap_xfer_nvlist(cap, nvl);
+ if (nvl == NULL)
+ return (errno);
+ error = (int)dnvlist_get_number(nvl, "error", 0);
+ nvlist_destroy(nvl);
+ errno = error;
+#else
+ (void)cap;
+ error = rssend(ifinfo->sdl->sdl_index, ifinfo->linkid, ifinfo->rs_data,
+ ifinfo->rs_datalen);
+#endif
+
+ ifinfo->probes++;
+ if (error != 0 && (errno != ENETDOWN || dflag > 0)) {
+ error = errno;
+ warnmsg(LOG_ERR, __func__, "sendmsg on %s: %s",
+ ifinfo->ifname, strerror(errno));
+ errno = error;
+ }
+ return (error == 0 ? 0 : -1);
+}
+
+#ifdef WITH_CASPER
+static int
+sendmsg_command(const char *cmd, const nvlist_t *limits __unused, nvlist_t *nvlin,
+ nvlist_t *nvlout __unused)
+{
+ const void *data;
+ size_t len;
+ uint32_t ifindex, linkid;
+ int error;
+
+ if (strcmp(cmd, "probe_defrouters") != 0 &&
+ strcmp(cmd, "rssend") != 0)
+ return (EINVAL);
+
+ ifindex = (uint32_t)nvlist_get_number(nvlin, "ifindex");
+ linkid = (uint32_t)nvlist_get_number(nvlin, "linkid");
+ if (strcmp(cmd, "probe_defrouters") == 0) {
+ error = probe_defrouters(ifindex, linkid);
+ } else {
+ data = nvlist_get_binary(nvlin, "data", &len);
+ error = rssend(ifindex, linkid, data, len);
+ }
+ if (error != 0)
+ return (errno);
+ return (0);
+}
+
+CREATE_SERVICE("rtsold.sendmsg", NULL, sendmsg_command, 0);
+#endif /* WITH_CASPER */
Index: head/usr.sbin/rtsold/dump.c
===================================================================
--- head/usr.sbin/rtsold/dump.c
+++ head/usr.sbin/rtsold/dump.c
@@ -34,6 +34,7 @@
*/
#include <sys/types.h>
+#include <sys/capsicum.h>
#include <sys/socket.h>
#include <sys/queue.h>
@@ -42,21 +43,20 @@
#include <netinet/icmp6.h>
#include <arpa/inet.h>
-#include <syslog.h>
-#include <time.h>
+#include <capsicum_helpers.h>
+#include <errno.h>
#include <stdio.h>
#include <string.h>
-#include <errno.h>
+#include <syslog.h>
+#include <time.h>
#include "rtsold.h"
-static FILE *fp;
+static const char * const ifstatstr[] =
+ { "IDLE", "DELAY", "PROBE", "DOWN", "TENTATIVE" };
-static void dump_interface_status(void);
-static const char * const ifstatstr[] = {"IDLE", "DELAY", "PROBE", "DOWN", "TENTATIVE"};
-
-static void
-dump_interface_status(void)
+void
+rtsold_dump(FILE *fp)
{
struct ifinfo *ifi;
struct rainfo *rai;
@@ -64,8 +64,14 @@
struct timespec now;
char ntopbuf[INET6_ADDRSTRLEN];
- clock_gettime(CLOCK_MONOTONIC_FAST, &now);
+ if (fseek(fp, 0, SEEK_SET) != 0) {
+ warnmsg(LOG_ERR, __func__, "fseek(): %s", strerror(errno));
+ return;
+ }
+ (void)ftruncate(fileno(fp), 0);
+ (void)clock_gettime(CLOCK_MONOTONIC_FAST, &now);
+
TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) {
fprintf(fp, "Interface %s\n", ifi->ifname);
fprintf(fp, " probe interval: ");
@@ -121,18 +127,28 @@
fprintf(fp, "\n");
}
}
+ fflush(fp);
}
-void
-rtsold_dump_file(const char *dumpfile)
+FILE *
+rtsold_init_dumpfile(const char *dumpfile)
{
+ cap_rights_t rights;
+ FILE *fp;
+
if ((fp = fopen(dumpfile, "w")) == NULL) {
- warnmsg(LOG_WARNING, __func__, "open a dump file(%s): %s",
+ warnmsg(LOG_WARNING, __func__, "opening a dump file(%s): %s",
dumpfile, strerror(errno));
- return;
+ return (NULL);
}
- dump_interface_status();
- fclose(fp);
+
+ cap_rights_init(&rights, CAP_FSTAT, CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
+ if (caph_rights_limit(fileno(fp), &rights) != 0) {
+ warnmsg(LOG_WARNING, __func__, "caph_rights_limit(%s): %s",
+ dumpfile, strerror(errno));
+ return (NULL);
+ }
+ return (fp);
}
const char *
Index: head/usr.sbin/rtsold/if.c
===================================================================
--- head/usr.sbin/rtsold/if.c
+++ head/usr.sbin/rtsold/if.c
@@ -34,10 +34,11 @@
*/
#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
+#include <sys/capsicum.h>
#include <sys/ioctl.h>
#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_types.h>
@@ -51,6 +52,7 @@
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h>
+#include <capsicum_helpers.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@@ -63,16 +65,28 @@
#include "rtsold.h"
static int ifsock;
-
-static int get_llflag(const char *);
static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
int
ifinit(void)
{
- ifsock = rssock;
+ cap_rights_t rights;
+ int sock;
- return(0);
+ sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ if (sock < 0) {
+ warnmsg(LOG_ERR, __func__, "socket(): %s",
+ strerror(errno));
+ return (-1);
+ }
+ if (caph_rights_limit(sock, cap_rights_init(&rights, CAP_IOCTL)) < 0) {
+ warnmsg(LOG_ERR, __func__, "caph_rights_limit(): %s",
+ strerror(errno));
+ (void)close(sock);
+ return (-1);
+ }
+ ifsock = sock;
+ return (0);
}
int
@@ -150,10 +164,9 @@
}
close(s);
- llflag = get_llflag(name);
- if (llflag < 0) {
+ if (cap_llflags_get(capllflags, name, &llflag) != 0) {
warnmsg(LOG_WARNING, __func__,
- "get_llflag() failed, anyway I'll try");
+ "cap_llflags_get() failed, anyway I'll try");
return (0);
}
@@ -273,8 +286,6 @@
"unsupported link type(%d)", sdl->sdl_type);
exit(1);
}
-
- return;
}
struct sockaddr_dl *
@@ -331,58 +342,6 @@
free(buf);
return (ret_sdl);
}
-
-/*------------------------------------------------------------*/
-
-/* get ia6_flags for link-local addr on if. returns -1 on error. */
-static int
-get_llflag(const char *name)
-{
- struct ifaddrs *ifap, *ifa;
- struct in6_ifreq ifr6;
- struct sockaddr_in6 *sin6;
- int s;
-
- if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) {
- warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s",
- strerror(errno));
- exit(1);
- }
- if (getifaddrs(&ifap) != 0) {
- warnmsg(LOG_ERR, __func__, "getifaddrs: %s",
- strerror(errno));
- exit(1);
- }
-
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if (strlen(ifa->ifa_name) != strlen(name) ||
- strncmp(ifa->ifa_name, name, strlen(name)) != 0)
- continue;
- if (ifa->ifa_addr->sa_family != AF_INET6)
- continue;
- sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr;
- if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
- continue;
-
- memset(&ifr6, 0, sizeof(ifr6));
- strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
- memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
- if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
- warnmsg(LOG_ERR, __func__,
- "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno));
- exit(1);
- }
-
- freeifaddrs(ifap);
- close(s);
- return (ifr6.ifr_ifru.ifru_flags6);
- }
-
- freeifaddrs(ifap);
- close(s);
- return (-1);
-}
-
static void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
Index: head/usr.sbin/rtsold/probe.c
===================================================================
--- head/usr.sbin/rtsold/probe.c
+++ head/usr.sbin/rtsold/probe.c
@@ -1,191 +0,0 @@
-/* $KAME: probe.c,v 1.17 2003/10/05 00:09:36 itojun Exp $ */
-
-/*-
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Copyright (C) 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * 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$
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/uio.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/if_dl.h>
-
-#include <netinet/in.h>
-#include <netinet6/in6_var.h>
-#include <netinet/icmp6.h>
-#include <netinet6/nd6.h>
-
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <syslog.h>
-#include <stdlib.h>
-
-#include "rtsold.h"
-
-static struct msghdr sndmhdr;
-static struct iovec sndiov[2];
-static int probesock;
-static void sendprobe(struct in6_addr *, struct ifinfo *);
-
-int
-probe_init(void)
-{
- int scmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
- CMSG_SPACE(sizeof(int));
- static u_char *sndcmsgbuf = NULL;
-
- if (sndcmsgbuf == NULL &&
- (sndcmsgbuf = (u_char *)malloc(scmsglen)) == NULL) {
- warnmsg(LOG_ERR, __func__, "malloc failed");
- return (-1);
- }
-
- if ((probesock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) {
- warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
- return (-1);
- }
-
- /* initialize msghdr for sending packets */
- sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
- sndmhdr.msg_iov = sndiov;
- sndmhdr.msg_iovlen = 1;
- sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
- sndmhdr.msg_controllen = scmsglen;
-
- return (0);
-}
-
-/*
- * Probe if each router in the default router list is still alive.
- */
-void
-defrouter_probe(struct ifinfo *ifinfo)
-{
- struct in6_defrouter *p, *ep;
- int ifindex, mib[4];
- char *buf, ntopbuf[INET6_ADDRSTRLEN];
- size_t l;
-
- ifindex = ifinfo->sdl->sdl_index;
- if (ifindex == 0)
- return;
- mib[0] = CTL_NET;
- mib[1] = PF_INET6;
- mib[2] = IPPROTO_ICMPV6;
- mib[3] = ICMPV6CTL_ND6_DRLIST;
- if (sysctl(mib, nitems(mib), NULL, &l, NULL, 0) < 0) {
- warnmsg(LOG_ERR, __func__, "sysctl(ICMPV6CTL_ND6_DRLIST): %s",
- strerror(errno));
- return;
- }
- if (l == 0)
- return;
- buf = malloc(l);
- if (buf == NULL) {
- warnmsg(LOG_ERR, __func__, "malloc(): %s", strerror(errno));
- return;
- }
- if (sysctl(mib, nitems(mib), buf, &l, NULL, 0) < 0) {
- warnmsg(LOG_ERR, __func__, "sysctl(ICMPV6CTL_ND6_DRLIST): %s",
- strerror(errno));
- free(buf);
- return;
- }
- ep = (struct in6_defrouter *)(void *)(buf + l);
- for (p = (struct in6_defrouter *)(void *)buf; p < ep; p++) {
- if (ifindex != p->if_index)
- continue;
- if (!IN6_IS_ADDR_LINKLOCAL(&p->rtaddr.sin6_addr)) {
- warnmsg(LOG_ERR, __func__,
- "default router list contains a "
- "non-link-local address(%s)",
- inet_ntop(AF_INET6, &p->rtaddr.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN));
- continue; /* ignore the address */
- }
- sendprobe(&p->rtaddr.sin6_addr, ifinfo);
- }
- free(buf);
-}
-
-static void
-sendprobe(struct in6_addr *addr, struct ifinfo *ifinfo)
-{
- u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
- struct sockaddr_in6 sa6_probe;
- struct in6_pktinfo *pi;
- struct cmsghdr *cm;
- u_int32_t ifindex = ifinfo->sdl->sdl_index;
- int hoplimit = 1;
-
- memset(&sa6_probe, 0, sizeof(sa6_probe));
- sa6_probe.sin6_family = AF_INET6;
- sa6_probe.sin6_len = sizeof(sa6_probe);
- sa6_probe.sin6_addr = *addr;
- sa6_probe.sin6_scope_id = ifinfo->linkid;
-
- sndmhdr.msg_name = (caddr_t)&sa6_probe;
- sndmhdr.msg_iov[0].iov_base = NULL;
- sndmhdr.msg_iov[0].iov_len = 0;
-
- cm = CMSG_FIRSTHDR(&sndmhdr);
- /* specify the outgoing interface */
- cm->cmsg_level = IPPROTO_IPV6;
- cm->cmsg_type = IPV6_PKTINFO;
- cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
- pi = (struct in6_pktinfo *)(void *)CMSG_DATA(cm);
- memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/
- pi->ipi6_ifindex = ifindex;
-
- /* specify the hop limit of the packet for safety */
- cm = CMSG_NXTHDR(&sndmhdr, cm);
- cm->cmsg_level = IPPROTO_IPV6;
- cm->cmsg_type = IPV6_HOPLIMIT;
- cm->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
-
- warnmsg(LOG_DEBUG, __func__, "probe a router %s on %s",
- inet_ntop(AF_INET6, addr, ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(ifindex, ifnamebuf));
-
- if (sendmsg(probesock, &sndmhdr, 0))
- warnmsg(LOG_ERR, __func__, "sendmsg on %s: %s",
- if_indextoname(ifindex, ifnamebuf), strerror(errno));
-}
Index: head/usr.sbin/rtsold/rtsock.c
===================================================================
--- head/usr.sbin/rtsold/rtsock.c
+++ head/usr.sbin/rtsold/rtsock.c
@@ -33,10 +33,11 @@
*/
#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/queue.h>
#include <sys/socket.h>
-#include <sys/uio.h>
#include <sys/time.h>
-#include <sys/queue.h>
+#include <sys/uio.h>
#include <net/if.h>
#include <net/route.h>
@@ -46,6 +47,7 @@
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
+#include <capsicum_helpers.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>
@@ -72,8 +74,20 @@
int
rtsock_open(void)
{
+ cap_rights_t rights;
+ int error, s;
- return (socket(PF_ROUTE, SOCK_RAW, 0));
+ s = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (s < 0)
+ return (s);
+ cap_rights_init(&rights, CAP_EVENT, CAP_READ);
+ if (caph_rights_limit(s, &rights) != 0) {
+ error = errno;
+ (void)close(s);
+ errno = errno;
+ return (-1);
+ }
+ return (s);
}
int
Index: head/usr.sbin/rtsold/rtsol.c
===================================================================
--- head/usr.sbin/rtsold/rtsol.c
+++ head/usr.sbin/rtsold/rtsol.c
@@ -35,11 +35,12 @@
*/
#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/queue.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/uio.h>
-#include <sys/queue.h>
#include <sys/wait.h>
-#include <sys/stat.h>
#include <net/if.h>
#include <net/route.h>
@@ -54,6 +55,7 @@
#include <arpa/inet.h>
+#include <capsicum_helpers.h>
#include <netdb.h>
#include <time.h>
#include <fcntl.h>
@@ -67,28 +69,11 @@
#include <syslog.h>
#include "rtsold.h"
-static struct msghdr rcvmhdr;
-static struct msghdr sndmhdr;
-static struct iovec rcviov[2];
-static struct iovec sndiov[2];
-static struct sockaddr_in6 from;
-static int rcvcmsglen;
-
-int rssock;
static char rsid[IFNAMSIZ + 1 + sizeof(DNSINFO_ORIGIN_LABEL) + 1 + NI_MAXHOST];
-struct ifinfo_head_t ifinfo_head =
- TAILQ_HEAD_INITIALIZER(ifinfo_head);
+struct ifinfo_head_t ifinfo_head = TAILQ_HEAD_INITIALIZER(ifinfo_head);
-static const struct sockaddr_in6 sin6_allrouters = {
- .sin6_len = sizeof(sin6_allrouters),
- .sin6_family = AF_INET6,
- .sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT,
-};
-
-static void call_script(const int, const char *const *,
- struct script_msg_head_t *);
+static void call_script(const char *const *, struct script_msg_head_t *);
static size_t dname_labeldec(char *, size_t, const char *);
-static int safefile(const char *);
static struct ra_opt *find_raopt(struct rainfo *, int, void *, size_t);
static int ra_opt_rdnss_dispatch(struct ifinfo *, struct rainfo *,
struct script_msg_head_t *, struct script_msg_head_t *);
@@ -100,7 +85,7 @@
#define CALL_SCRIPT(name, sm_head) do { \
const char *const sarg[] = { _ARGS_##name, NULL }; \
- call_script(sizeof(sarg), sarg, sm_head); \
+ call_script(sarg, sm_head); \
} while (0)
#define ELM_MALLOC(p, error_action) do { \
@@ -114,130 +99,69 @@
} while (0)
int
-sockopen(void)
+recvsockopen(void)
{
- static u_char *rcvcmsgbuf = NULL, *sndcmsgbuf = NULL;
- int sndcmsglen, on;
- static u_char answer[1500];
struct icmp6_filter filt;
+ cap_rights_t rights;
+ int on, sock;
- sndcmsglen = rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
- CMSG_SPACE(sizeof(int));
- if (rcvcmsgbuf == NULL && (rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
- warnmsg(LOG_ERR, __func__,
- "malloc for receive msghdr failed");
- return (-1);
- }
- if (sndcmsgbuf == NULL && (sndcmsgbuf = malloc(sndcmsglen)) == NULL) {
- warnmsg(LOG_ERR, __func__,
- "malloc for send msghdr failed");
- return (-1);
- }
- if ((rssock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
+ if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
- return (-1);
+ goto fail;
}
- /* specify to tell receiving interface */
+ /* Provide info about the receiving interface. */
on = 1;
- if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
sizeof(on)) < 0) {
- warnmsg(LOG_ERR, __func__, "IPV6_RECVPKTINFO: %s",
+ warnmsg(LOG_ERR, __func__, "setsockopt(IPV6_RECVPKTINFO): %s",
strerror(errno));
- exit(1);
+ goto fail;
}
- /* specify to tell value of hoplimit field of received IP6 hdr */
+ /* Include the hop limit from the received header. */
on = 1;
- if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
sizeof(on)) < 0) {
- warnmsg(LOG_ERR, __func__, "IPV6_RECVHOPLIMIT: %s",
+ warnmsg(LOG_ERR, __func__, "setsockopt(IPV6_RECVHOPLIMIT): %s",
strerror(errno));
- exit(1);
+ goto fail;
}
- /* specfiy to accept only router advertisements on the socket */
+ /* Filter out everything except for Router Advertisements. */
ICMP6_FILTER_SETBLOCKALL(&filt);
ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
- if (setsockopt(rssock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
+ if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
sizeof(filt)) == -1) {
warnmsg(LOG_ERR, __func__, "setsockopt(ICMP6_FILTER): %s",
strerror(errno));
- return(-1);
+ goto fail;
}
- /* initialize msghdr for receiving packets */
- rcviov[0].iov_base = (caddr_t)answer;
- rcviov[0].iov_len = sizeof(answer);
- rcvmhdr.msg_name = (caddr_t)&from;
- rcvmhdr.msg_iov = rcviov;
- rcvmhdr.msg_iovlen = 1;
- rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
+ cap_rights_init(&rights, CAP_EVENT, CAP_RECV);
+ if (caph_rights_limit(sock, &rights) < 0) {
+ warnmsg(LOG_ERR, __func__, "caph_rights_limit(): %s",
+ strerror(errno));
+ goto fail;
+ }
- /* initialize msghdr for sending packets */
- sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
- sndmhdr.msg_iov = sndiov;
- sndmhdr.msg_iovlen = 1;
- sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
- sndmhdr.msg_controllen = sndcmsglen;
+ return (sock);
- return (rssock);
+fail:
+ if (sock >= 0)
+ (void)close(sock);
+ return (-1);
}
void
-sendpacket(struct ifinfo *ifi)
+rtsol_input(int sock)
{
- struct in6_pktinfo *pi;
- struct cmsghdr *cm;
- int hoplimit = 255;
- ssize_t i;
- struct sockaddr_in6 dst;
-
- dst = sin6_allrouters;
- dst.sin6_scope_id = ifi->linkid;
-
- sndmhdr.msg_name = (caddr_t)&dst;
- sndmhdr.msg_iov[0].iov_base = (caddr_t)ifi->rs_data;
- sndmhdr.msg_iov[0].iov_len = ifi->rs_datalen;
-
- cm = CMSG_FIRSTHDR(&sndmhdr);
- /* specify the outgoing interface */
- cm->cmsg_level = IPPROTO_IPV6;
- cm->cmsg_type = IPV6_PKTINFO;
- cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
- pi = (struct in6_pktinfo *)(void *)CMSG_DATA(cm);
- memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/
- pi->ipi6_ifindex = ifi->sdl->sdl_index;
-
- /* specify the hop limit of the packet */
- cm = CMSG_NXTHDR(&sndmhdr, cm);
- cm->cmsg_level = IPPROTO_IPV6;
- cm->cmsg_type = IPV6_HOPLIMIT;
- cm->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
-
- warnmsg(LOG_DEBUG, __func__,
- "send RS on %s, whose state is %d",
- ifi->ifname, ifi->state);
- i = sendmsg(rssock, &sndmhdr, 0);
- if (i < 0 || (size_t)i != ifi->rs_datalen) {
- /*
- * ENETDOWN is not so serious, especially when using several
- * network cards on a mobile node. We ignore it.
- */
- if (errno != ENETDOWN || dflag > 0)
- warnmsg(LOG_ERR, __func__, "sendmsg on %s: %s",
- ifi->ifname, strerror(errno));
- }
-
- /* update counter */
- ifi->probes++;
-}
-
-void
-rtsol_input(int s)
-{
- char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
+ uint8_t cmsg[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
+ CMSG_SPACE(sizeof(int))];
+ struct iovec iov;
+ struct msghdr hdr;
+ struct sockaddr_in6 from;
+ char answer[1500], ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
int l, ifindex = 0, *hlimp = NULL;
ssize_t msglen;
struct in6_pktinfo *pi = NULL;
@@ -247,8 +171,7 @@
struct nd_router_advert *nd_ra;
struct cmsghdr *cm;
struct rainfo *rai;
- char *raoptp;
- char *p;
+ char *p, *raoptp;
struct in6_addr *addr;
struct nd_opt_hdr *ndo;
struct nd_opt_rdnss *rdnss;
@@ -256,22 +179,28 @@
size_t len;
char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1];
char dname[NI_MAXHOST];
- struct timespec now;
- struct timespec lifetime;
- int newent_rai;
- int newent_rao;
+ struct timespec lifetime, now;
+ int newent_rai, newent_rao;
- /* get message. namelen and controllen must always be initialized. */
- rcvmhdr.msg_namelen = sizeof(from);
- rcvmhdr.msg_controllen = rcvcmsglen;
- if ((msglen = recvmsg(s, &rcvmhdr, 0)) < 0) {
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+ hdr.msg_name = &from;
+ hdr.msg_namelen = sizeof(from);
+ hdr.msg_control = cmsg;
+ hdr.msg_controllen = sizeof(cmsg);
+
+ iov.iov_base = (caddr_t)answer;
+ iov.iov_len = sizeof(answer);
+
+ if ((msglen = recvmsg(sock, &hdr, 0)) < 0) {
warnmsg(LOG_ERR, __func__, "recvmsg: %s", strerror(errno));
return;
}
- /* extract optional information via Advanced API */
- for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmhdr); cm;
- cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmhdr, cm)) {
+ /* Extract control message info. */
+ for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&hdr); cm != NULL;
+ cm = (struct cmsghdr *)CMSG_NXTHDR(&hdr, cm)) {
if (cm->cmsg_level == IPPROTO_IPV6 &&
cm->cmsg_type == IPV6_PKTINFO &&
cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
@@ -301,8 +230,7 @@
return;
}
- icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;
-
+ icp = (struct icmp6_hdr *)iov.iov_base;
if (icp->icmp6_type != ND_ROUTER_ADVERT) {
/*
* this should not happen because we configured a filter
@@ -761,154 +689,43 @@
}
static void
-call_script(const int argc, const char *const argv[],
- struct script_msg_head_t *sm_head)
+call_script(const char *const argv[], struct script_msg_head_t *sm_head)
{
- const char *scriptpath;
- int fd[2];
- int error;
- pid_t pid, wpid;
+ struct script_msg *smp;
+ ssize_t len;
+ int status, wfd;
- if ((scriptpath = argv[0]) == NULL)
+ if (argv[0] == NULL)
return;
- fd[0] = fd[1] = -1;
- if (sm_head != NULL && !TAILQ_EMPTY(sm_head)) {
- error = pipe(fd);
- if (error) {
- warnmsg(LOG_ERR, __func__,
- "failed to create a pipe: %s", strerror(errno));
- return;
- }
- }
-
- /* launch the script */
- pid = fork();
- if (pid < 0) {
+ wfd = cap_script_run(capscript, argv);
+ if (wfd == -1) {
warnmsg(LOG_ERR, __func__,
- "failed to fork: %s", strerror(errno));
+ "failed to run %s: %s", argv[0], strerror(errno));
return;
- } else if (pid) { /* parent */
- int wstatus;
+ }
- if (fd[0] != -1) { /* Send message to the child if any. */
- ssize_t len;
- struct script_msg *smp;
-
- close(fd[0]);
- TAILQ_FOREACH(smp, sm_head, sm_next) {
- len = strlen(smp->sm_msg);
- warnmsg(LOG_DEBUG, __func__,
- "write to child = %s(%zd)",
- smp->sm_msg, len);
- if (write(fd[1], smp->sm_msg, len) != len) {
- warnmsg(LOG_ERR, __func__,
- "write to child failed: %s",
- strerror(errno));
- break;
- }
+ if (sm_head != NULL) {
+ TAILQ_FOREACH(smp, sm_head, sm_next) {
+ len = strlen(smp->sm_msg);
+ warnmsg(LOG_DEBUG, __func__, "write to child = %s(%zd)",
+ smp->sm_msg, len);
+ if (write(wfd, smp->sm_msg, len) != len) {
+ warnmsg(LOG_ERR, __func__,
+ "write to child failed: %s",
+ strerror(errno));
+ break;
}
- close(fd[1]);
}
- do {
- wpid = wait(&wstatus);
- } while (wpid != pid && wpid > 0);
-
- if (wpid < 0)
- warnmsg(LOG_ERR, __func__,
- "wait: %s", strerror(errno));
- else
- warnmsg(LOG_DEBUG, __func__,
- "script \"%s\" terminated", scriptpath);
- } else { /* child */
- int nullfd;
- char **_argv;
-
- if (safefile(scriptpath)) {
- warnmsg(LOG_ERR, __func__,
- "script \"%s\" cannot be executed safely",
- scriptpath);
- exit(1);
- }
- nullfd = open("/dev/null", O_RDWR);
- if (nullfd < 0) {
- warnmsg(LOG_ERR, __func__,
- "open /dev/null: %s", strerror(errno));
- exit(1);
- }
- if (fd[0] != -1) { /* Receive message from STDIN if any. */
- close(fd[1]);
- if (fd[0] != STDIN_FILENO) {
- /* Connect a pipe read-end to child's STDIN. */
- if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) {
- warnmsg(LOG_ERR, __func__,
- "dup2 STDIN: %s", strerror(errno));
- exit(1);
- }
- close(fd[0]);
- }
- } else
- dup2(nullfd, STDIN_FILENO);
-
- dup2(nullfd, STDOUT_FILENO);
- dup2(nullfd, STDERR_FILENO);
- if (nullfd > STDERR_FILENO)
- close(nullfd);
-
- _argv = malloc(sizeof(*_argv) * argc);
- if (_argv == NULL) {
- warnmsg(LOG_ERR, __func__,
- "malloc: %s", strerror(errno));
- exit(1);
- }
- memcpy(_argv, argv, (size_t)argc);
- execv(scriptpath, (char *const *)_argv);
- warnmsg(LOG_ERR, __func__, "child: exec failed: %s",
- strerror(errno));
- exit(1);
}
- return;
-}
+ (void)close(wfd);
-static int
-safefile(const char *path)
-{
- struct stat s;
- uid_t myuid;
-
- /* no setuid */
- if (getuid() != geteuid()) {
- warnmsg(LOG_NOTICE, __func__,
- "setuid'ed execution not allowed\n");
- return (-1);
- }
-
- if (lstat(path, &s) != 0) {
- warnmsg(LOG_NOTICE, __func__, "lstat failed: %s",
- strerror(errno));
- return (-1);
- }
-
- /* the file must be owned by the running uid */
- myuid = getuid();
- if (s.st_uid != myuid) {
- warnmsg(LOG_NOTICE, __func__,
- "%s has invalid owner uid\n", path);
- return (-1);
- }
-
- switch (s.st_mode & S_IFMT) {
- case S_IFREG:
- break;
- default:
- warnmsg(LOG_NOTICE, __func__,
- "%s is an invalid file type 0x%o\n",
- path, (s.st_mode & S_IFMT));
- return (-1);
- }
-
- return (0);
+ if (cap_script_wait(capscript, &status) != 0)
+ warnmsg(LOG_ERR, __func__, "wait(): %s", strerror(errno));
+ else
+ warnmsg(LOG_DEBUG, __func__, "script \"%s\" status %d",
+ argv[0], status);
}
/* Decode domain name label encoding in RFC 1035 Section 3.1 */
Index: head/usr.sbin/rtsold/rtsold.h
===================================================================
--- head/usr.sbin/rtsold/rtsold.h
+++ head/usr.sbin/rtsold/rtsold.h
@@ -60,12 +60,13 @@
TAILQ_HEAD(, ra_opt) rai_ra_opt;
};
+/* Per-interface tracking info. */
struct ifinfo {
- TAILQ_ENTRY(ifinfo) ifi_next; /* pointer to the next interface */
+ TAILQ_ENTRY(ifinfo) ifi_next; /* pointer to the next interface */
struct sockaddr_dl *sdl; /* link-layer address */
char ifname[IFNAMSIZ]; /* interface name */
- u_int32_t linkid; /* link ID of this interface */
+ uint32_t linkid; /* link ID of this interface */
int active; /* interface status */
int probeinterval; /* interval of probe timer (if necessary) */
int probetimer; /* rest of probe timer */
@@ -77,7 +78,6 @@
int dadcount;
struct timespec timer;
struct timespec expire;
- int errors; /* # of errors we've got - detect wedge */
#define IFI_DNSOPT_STATE_NOINFO 0
#define IFI_DNSOPT_STATE_RECEIVED 1
int ifi_rdnss; /* RDNSS option state */
@@ -150,6 +150,7 @@
} while (0)
/* rtsold.c */
+struct cap_channel;
extern struct timespec tm_max;
extern int dflag;
extern int aflag;
@@ -157,6 +158,8 @@
extern int uflag;
extern const char *otherconf_script;
extern const char *resolvconf_script;
+extern struct cap_channel *capllflags, *capscript, *capsendmsg, *capsyslog;
+
struct ifinfo *find_ifinfo(int);
struct rainfo *find_rainfo(struct ifinfo *, struct sockaddr_in6 *);
void rtsol_timer_update(struct ifinfo *);
@@ -165,6 +168,7 @@
extern int ra_opt_handler(struct ifinfo *);
/* if.c */
+struct nd_opt_hdr;
extern int ifinit(void);
extern int interface_up(char *);
extern int interface_status(struct ifinfo *);
@@ -173,17 +177,23 @@
extern struct sockaddr_dl *if_nametosdl(char *);
/* rtsol.c */
-extern int rssock;
-extern int sockopen(void);
-extern void sendpacket(struct ifinfo *);
+extern int recvsockopen(void);
extern void rtsol_input(int);
-/* probe.c */
-extern int probe_init(void);
-extern void defrouter_probe(struct ifinfo *);
+/* cap_llflags.c */
+extern int cap_llflags_get(struct cap_channel *, const char *, int *);
+/* cap_script.c */
+extern int cap_script_run(struct cap_channel *, const char *const *);
+extern int cap_script_wait(struct cap_channel *, int *);
+
+/* cap_sendmsg.c */
+extern int cap_probe_defrouters(struct cap_channel *, struct ifinfo *);
+extern int cap_rssend(struct cap_channel *, struct ifinfo *);
+
/* dump.c */
-extern void rtsold_dump_file(const char *);
+extern FILE *rtsold_init_dumpfile(const char *);
+extern void rtsold_dump(FILE *);
extern const char *sec2str(const struct timespec *);
/* rtsock.c */
Index: head/usr.sbin/rtsold/rtsold.c
===================================================================
--- head/usr.sbin/rtsold/rtsold.c
+++ head/usr.sbin/rtsold/rtsold.c
@@ -34,6 +34,8 @@
*/
#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/event.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -47,23 +49,27 @@
#include <netinet6/nd6.h>
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <ifaddrs.h>
+#include <libgen.h>
#include <signal.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <string.h>
-#include <stdlib.h>
+#include <stdarg.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
#include <time.h>
-#include <errno.h>
-#include <err.h>
-#include <stdarg.h>
-#include <ifaddrs.h>
-#include <poll.h>
+#include <unistd.h>
+#include <libcasper.h>
+#include <casper/cap_syslog.h>
+#include <libutil.h>
+
#include "rtsold.h"
-#define RTSOL_DUMPFILE "/var/run/rtsold.dump";
-#define RTSOL_PIDFILE "/var/run/rtsold.pid";
+#define RTSOL_DUMPFILE "/var/run/rtsold.dump"
struct timespec tm_max;
static int log_upto = 999;
@@ -77,6 +83,8 @@
const char *otherconf_script;
const char *resolvconf_script = "/sbin/resolvconf";
+cap_channel_t *capllflags, *capscript, *capsendmsg, *capsyslog;
+
/* protocol constants */
#define MAX_RTR_SOLICITATION_DELAY 1 /* second */
#define RTR_SOLICITATION_INTERVAL 4 /* seconds */
@@ -90,43 +98,40 @@
/* static variables and functions */
static int mobile_node = 0;
-static const char *pidfilename = RTSOL_PIDFILE;
-#ifndef SMALL
-static int do_dump;
-static const char *dumpfilename = RTSOL_DUMPFILE;
-#endif
+static sig_atomic_t do_dump, do_exit;
+static struct pidfh *pfh;
static char **autoifprobe(void);
static int ifconfig(char *ifname);
+static int init_capabilities(void);
static int make_packet(struct ifinfo *);
static struct timespec *rtsol_check_timer(void);
-#ifndef SMALL
-static void rtsold_set_dump_file(int);
-#endif
-static void usage(void);
+static void set_dumpfile(int);
+static void set_exit(int);
+static void usage(const char *progname);
int
main(int argc, char **argv)
{
- int s, ch, once = 0;
+ struct kevent events[2];
+ FILE *dumpfp;
+ struct ifinfo *ifi;
struct timespec *timeout;
- const char *opts;
- struct pollfd set[2];
- int rtsock;
- char *argv0;
+ const char *opts, *pidfilepath, *progname;
+ int ch, error, kq, once, rcvsock, rtsock;
-#ifndef SMALL
- /* rtsold */
- opts = "adDfFm1O:p:R:u";
-#else
- /* rtsol */
- opts = "adDFO:R:u";
- fflag = 1;
- once = 1;
-#endif
- argv0 = argv[0];
+ progname = basename(argv[0]);
+ if (strcmp(progname, "rtsold") == 0) {
+ opts = "adDfFm1O:p:R:u";
+ once = 0;
+ pidfilepath = NULL;
+ } else {
+ opts = "adDFO:R:u";
+ fflag = 1;
+ once = 1;
+ }
while ((ch = getopt(argc, argv, opts)) != -1) {
switch (ch) {
@@ -155,7 +160,7 @@
otherconf_script = optarg;
break;
case 'p':
- pidfilename = optarg;
+ pidfilepath = optarg;
break;
case 'R':
resolvconf_script = optarg;
@@ -164,17 +169,14 @@
uflag = 1;
break;
default:
- usage();
- exit(1);
+ usage(progname);
}
}
argc -= optind;
argv += optind;
- if ((!aflag && argc == 0) || (aflag && argc != 0)) {
- usage();
- exit(1);
- }
+ if ((!aflag && argc == 0) || (aflag && argc != 0))
+ usage(progname);
/* Generate maximum time in timespec. */
tm_max.tv_sec = (-1) & ~((time_t)1 << ((sizeof(tm_max.tv_sec) * 8) - 1));
@@ -188,64 +190,62 @@
else
log_upto = LOG_NOTICE;
- if (!fflag) {
- char *ident;
-
- ident = strrchr(argv0, '/');
- if (!ident)
- ident = argv0;
- else
- ident++;
- openlog(ident, LOG_NDELAY|LOG_PID, LOG_DAEMON);
- if (log_upto >= 0)
- setlogmask(LOG_UPTO(log_upto));
- }
-
- if (otherconf_script && *otherconf_script != '/') {
+ if (otherconf_script != NULL && *otherconf_script != '/')
errx(1, "configuration script (%s) must be an absolute path",
otherconf_script);
- }
- if (resolvconf_script && *resolvconf_script != '/') {
+ if (*resolvconf_script != '/')
errx(1, "configuration script (%s) must be an absolute path",
resolvconf_script);
+
+ if (!fflag) {
+ pfh = pidfile_open(pidfilepath, 0644, NULL);
+ if (pfh == NULL)
+ errx(1, "failed to open pidfile: %s", strerror(errno));
+ if (daemon(0, 0) != 0)
+ errx(1, "failed to daemonize");
}
- if (pidfilename && *pidfilename != '/') {
- errx(1, "pid filename (%s) must be an absolute path",
- pidfilename);
- }
-#ifndef SMALL
- /* initialization to dump internal status to a file */
- signal(SIGUSR1, rtsold_set_dump_file);
-#endif
+ if ((error = init_capabilities()) != 0)
+ err(1, "failed to initialize capabilities");
- if (!fflag)
- daemon(0, 0); /* act as a daemon */
+ if (!fflag) {
+ cap_openlog(capsyslog, progname, LOG_NDELAY | LOG_PID,
+ LOG_DAEMON);
+ if (log_upto >= 0)
+ (void)cap_setlogmask(capsyslog, LOG_UPTO(log_upto));
+ (void)signal(SIGTERM, set_exit);
+ (void)signal(SIGINT, set_exit);
+ (void)signal(SIGUSR1, set_dumpfile);
+ dumpfp = rtsold_init_dumpfile(RTSOL_DUMPFILE);
+ } else
+ dumpfp = NULL;
- /*
- * Open a socket for sending RS and receiving RA.
- * This should be done before calling ifinit(), since the function
- * uses the socket.
- */
- if ((s = sockopen()) < 0) {
- warnmsg(LOG_ERR, __func__, "failed to open a socket");
+ kq = kqueue();
+ if (kq < 0) {
+ warnmsg(LOG_ERR, __func__, "failed to create a kqueue: %s",
+ strerror(errno));
exit(1);
}
- set[0].fd = s;
- set[0].events = POLLIN;
- set[1].fd = -1;
+ /* Open global sockets and register for read events. */
if ((rtsock = rtsock_open()) < 0) {
- warnmsg(LOG_ERR, __func__, "failed to open a socket");
+ warnmsg(LOG_ERR, __func__, "failed to open routing socket");
exit(1);
}
- set[1].fd = rtsock;
- set[1].events = POLLIN;
+ if ((rcvsock = recvsockopen()) < 0) {
+ warnmsg(LOG_ERR, __func__, "failed to open receive socket");
+ exit(1);
+ }
+ EV_SET(&events[0], rtsock, EVFILT_READ, EV_ADD, 0, 0, NULL);
+ EV_SET(&events[1], rcvsock, EVFILT_READ, EV_ADD, 0, 0, NULL);
+ if (kevent(kq, events, 2, NULL, 0, NULL) < 0) {
+ warnmsg(LOG_ERR, __func__, "kevent(): %s", strerror(errno));
+ exit(1);
+ }
- /* configuration per interface */
- if (ifinit()) {
- warnmsg(LOG_ERR, __func__,
- "failed to initialize interfaces");
+ /* Probe network interfaces and set up tracking info. */
+ if (ifinit() != 0) {
+ warnmsg(LOG_ERR, __func__, "failed to initialize interfaces");
exit(1);
}
if (aflag)
@@ -259,42 +259,37 @@
argv++;
}
- /* setup for probing default routers */
- if (probe_init()) {
+ /* Write to our pidfile. */
+ if (pfh != NULL && pidfile_write(pfh) != 0) {
warnmsg(LOG_ERR, __func__,
- "failed to setup for probing routers");
+ "failed to open pidfile: %s", strerror(errno));
exit(1);
- /*NOTREACHED*/
}
- /* dump the current pid */
- if (!once) {
- pid_t pid = getpid();
- FILE *fp;
+ /* Enter capability mode. */
+ caph_cache_catpages();
+ if (caph_enter_casper() != 0) {
+ warnmsg(LOG_ERR, __func__, "caph_enter(): %s", strerror(errno));
+ exit(1);
+ }
- if ((fp = fopen(pidfilename, "w")) == NULL)
- warnmsg(LOG_ERR, __func__,
- "failed to open a pid log file(%s): %s",
- pidfilename, strerror(errno));
- else {
- fprintf(fp, "%d\n", pid);
- fclose(fp);
+ for (;;) {
+ if (do_exit) {
+ /* Handle SIGTERM, SIGINT. */
+ if (pfh != NULL)
+ pidfile_remove(pfh);
+ break;
}
- }
- while (1) { /* main loop */
- int e;
-#ifndef SMALL
- if (do_dump) { /* SIGUSR1 */
+ if (do_dump) {
+ /* Handle SIGUSR1. */
do_dump = 0;
- rtsold_dump_file(dumpfilename);
+ if (dumpfp != NULL)
+ rtsold_dump(dumpfp);
}
-#endif
timeout = rtsol_check_timer();
if (once) {
- struct ifinfo *ifi;
-
/* if we have no timeout, we are done (or failed) */
if (timeout == NULL)
break;
@@ -307,27 +302,65 @@
if (ifi == NULL)
break;
}
- e = poll(set, 2, timeout ? (timeout->tv_sec * 1000 + timeout->tv_nsec / 1000 / 1000) : INFTIM);
- if (e < 1) {
- if (e < 0 && errno != EINTR) {
- warnmsg(LOG_ERR, __func__, "select: %s",
+
+ error = kevent(kq, NULL, 0, &events[0], 1, timeout);
+ if (error < 1) {
+ if (error < 0 && errno != EINTR)
+ warnmsg(LOG_ERR, __func__, "kevent(): %s",
strerror(errno));
- }
continue;
}
- /* packet reception */
- if (set[1].revents & POLLIN)
+ if (events[0].ident == (uintptr_t)rtsock)
rtsock_input(rtsock);
- if (set[0].revents & POLLIN)
- rtsol_input(s);
+ else
+ rtsol_input(rcvsock);
}
- /* NOTREACHED */
return (0);
}
static int
+init_capabilities(void)
+{
+#ifdef WITH_CASPER
+ const char *const scripts[2] = { resolvconf_script, otherconf_script };
+ cap_channel_t *capcasper;
+ nvlist_t *limits;
+
+ capcasper = cap_init();
+ if (capcasper == NULL)
+ return (-1);
+
+ capllflags = cap_service_open(capcasper, "rtsold.llflags");
+ if (capllflags == NULL)
+ return (-1);
+
+ capscript = cap_service_open(capcasper, "rtsold.script");
+ if (capscript == NULL)
+ return (-1);
+ limits = nvlist_create(0);
+ nvlist_add_string_array(limits, "scripts", scripts,
+ otherconf_script != NULL ? 2 : 1);
+ if (cap_limit_set(capscript, limits) != 0)
+ return (-1);
+
+ capsendmsg = cap_service_open(capcasper, "rtsold.sendmsg");
+ if (capsendmsg == NULL)
+ return (-1);
+
+ if (!fflag) {
+ capsyslog = cap_service_open(capcasper, "system.syslog");
+ if (capsyslog == NULL)
+ return (-1);
+ }
+
+ cap_close(capcasper);
+#endif /* WITH_CASPER */
+ return (0);
+}
+
+static int
ifconfig(char *ifname)
{
struct ifinfo *ifi;
@@ -501,7 +534,7 @@
struct ifinfo *ifi;
struct rainfo *rai;
struct ra_opt *rao, *raotmp;
- int flags;
+ int error, flags;
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
@@ -568,18 +601,23 @@
*/
if (probe)
ifi->otherconfig = 0;
-
- if (probe && mobile_node)
- defrouter_probe(ifi);
+ if (probe && mobile_node) {
+ error = cap_probe_defrouters(capsendmsg,
+ ifi);
+ if (error != 0)
+ warnmsg(LOG_DEBUG, __func__,
+ "failed to probe routers: %d",
+ error);
+ }
break;
}
case IFS_DELAY:
ifi->state = IFS_PROBE;
- sendpacket(ifi);
+ (void)cap_rssend(capsendmsg, ifi);
break;
case IFS_PROBE:
if (ifi->probes < MAX_RTR_SOLICITATIONS)
- sendpacket(ifi);
+ (void)cap_rssend(capsendmsg, ifi);
else {
warnmsg(LOG_INFO, __func__,
"No answer after sending %d RSs",
@@ -660,10 +698,9 @@
ifi->timer.tv_sec = 1;
break;
case IFS_IDLE:
- if (mobile_node) {
+ if (mobile_node)
/* XXX should be configurable */
ifi->timer.tv_sec = 3;
- }
else
ifi->timer = tm_max; /* stop timer(valid?) */
break;
@@ -675,7 +712,7 @@
case IFS_PROBE:
if (ifi->probes < MAX_RTR_SOLICITATIONS)
ifi->timer.tv_sec = RTR_SOLICITATION_INTERVAL;
- else {
+ else
/*
* After sending MAX_RTR_SOLICITATIONS solicitations,
* we're just waiting for possible replies; there
@@ -684,7 +721,6 @@
* on RFC 2461, Section 6.3.7.
*/
ifi->timer.tv_sec = MAX_RTR_SOLICITATION_DELAY;
- }
break;
default:
warnmsg(LOG_ERR, __func__,
@@ -711,30 +747,38 @@
#undef MILLION
}
-#ifndef SMALL
static void
-rtsold_set_dump_file(int sig __unused)
+set_dumpfile(int sig __unused)
{
+
do_dump = 1;
}
-#endif
static void
-usage(void)
+set_exit(int sig __unused)
{
-#ifndef SMALL
- fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] "
- "[-p pidfile] [-R script-name] interface ...\n");
- fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] "
- "[-p pidfile] [-R script-name] -a\n");
-#else
- fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] "
- "[-p pidfile] [-R script-name] interface ...\n");
- fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] "
- "[-p pidfile] [-R script-name] -a\n");
-#endif
+
+ do_exit = 1;
}
+static void
+usage(const char *progname)
+{
+
+ if (strcmp(progname, "rtsold") == 0) {
+ fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] "
+ "[-p pidfile] [-R script-name] interface ...\n");
+ fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] "
+ "[-p pidfile] [-R script-name] -a\n");
+ } else {
+ fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] "
+ "[-p pidfile] [-R script-name] interface ...\n");
+ fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] "
+ "[-p pidfile] [-R script-name] -a\n");
+ }
+ exit(1);
+}
+
void
warnmsg(int priority, const char *func, const char *msg, ...)
{
@@ -750,7 +794,7 @@
} else {
snprintf(buf, sizeof(buf), "<%s> %s", func, msg);
msg = buf;
- vsyslog(priority, msg, ap);
+ cap_vsyslog(capsyslog, priority, msg, ap);
}
va_end(ap);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 24, 11:51 AM (1 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27896619
Default Alt Text
D17572.id52589.diff (59 KB)
Attached To
Mode
D17572: Run most of rtsold(8) and rtsol(8) in capability mode.
Attached
Detach File
Event Timeline
Log In to Comment