Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F165156575
D29824.id87709.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D29824.id87709.diff
View Options
Index: sbin/rtsol/Makefile
===================================================================
--- sbin/rtsol/Makefile
+++ sbin/rtsol/Makefile
@@ -18,7 +18,7 @@
PACKAGE=runtime
PROG= rtsol
-SRCS= cap_llflags.c \
+SRCS= cap_if.c \
cap_script.c \
cap_sendmsg.c \
dump.c \
Index: usr.sbin/rtsold/Makefile
===================================================================
--- usr.sbin/rtsold/Makefile
+++ usr.sbin/rtsold/Makefile
@@ -17,7 +17,7 @@
PROG= rtsold
MAN= rtsold.8
MLINKS= rtsold.8 rtsol.8
-SRCS= cap_llflags.c \
+SRCS= cap_if.c \
cap_script.c \
cap_sendmsg.c \
dump.c \
Index: usr.sbin/rtsold/cap_llflags.c
===================================================================
--- usr.sbin/rtsold/cap_llflags.c
+++ usr.sbin/rtsold/cap_llflags.c
@@ -40,6 +40,7 @@
#include <net/if.h>
#include <netinet/in.h>
#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
#include <errno.h>
#include <ifaddrs.h>
@@ -52,14 +53,75 @@
#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.
+ * A service providing access to network interfaces. Currently this is
+ * restricted to fetching interface info and bringing an interface up.
*/
+#ifdef WITH_CASPER
+#define CMD_IFFLAGS_GET "ifflags_get"
+#define CMD_IFMEDIA_GET "ifmedia_get"
+#define CMD_LLFLAGS_GET "llflags_get"
+#define CMD_IF_UP "if_up"
+
+static const char *const *ifnames;
+static size_t ifcnt;
+#endif
+
+static int
+return_errno(int error)
+{
+ if (error != 0) {
+ errno = error;
+ error = -1;
+ }
+ return (error);
+}
+
+/* Fetch interface flags for the specified interface. */
+static int
+ifflags_get(const char *ifname, int *flagsp)
+{
+ struct ifreq ifr;
+ int error, s;
+
+ error = 0;
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (s < 0)
+ return (-1);
+ memset(&ifr, 0, sizeof(ifr));
+ (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0)
+ *flagsp = ifr.ifr_flags;
+ else
+ error = errno;
+
+ (void)close(s);
+ return (return_errno(error));
+}
+
+/* Fetch media info for the specified interface. */
+static int
+ifmedia_get(const char *ifname, struct ifmediareq *ifmr)
+{
+ int error, s;
+
+ error = 0;
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (s < 0)
+ return (-1);
+ memset(ifmr, 0, sizeof(*ifmr));
+ (void)strlcpy(ifmr->ifm_name, ifname, sizeof(ifmr->ifm_name));
+ if (ioctl(s, SIOCGIFMEDIA, ifmr) != 0)
+ error = errno;
+
+ (void)close(s);
+ return (return_errno(error));
+}
+
+/*
+ * Fetch interface address flags for the first link-local address assigned to
+ * the specified interface.
+ */
static int
llflags_get(const char *ifname, int *flagsp)
{
@@ -108,12 +170,156 @@
(void)close(s);
if (ifap != NULL)
freeifaddrs(ifap);
+ return (return_errno(error));
+}
+
+/*
+ * Bring the interface up, and optionally enable IPv6 networking and proccessing
+ * of router advertisements.
+ */
+static int
+if_up(const char *ifname, bool in6en)
+{
+ struct ifreq ifr;
+ struct in6_ndireq nd;
+ int error, ndflags, s;
+
+ error = 0;
+
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (s < 0)
+ return (-1);
+
+ memset(&ifr, 0, sizeof(ifr));
+ (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) != 0) {
+ error = errno;
+ goto out;
+ }
+ if ((ifr.ifr_flags & IFF_UP) == 0) {
+ memset(&ifr, 0, sizeof(ifr));
+ (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_flags = IFF_UP;
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) != 0) {
+ error = errno;
+ goto out;
+ }
+ }
+
+ memset(&nd, 0, sizeof(nd));
+ strlcpy(nd.ifname, ifname, sizeof(nd.ifname));
+ if (ioctl(s, SIOCGIFINFO_IN6, &nd) != 0) {
+ error = errno;
+ goto out;
+ }
+
+ ndflags = nd.ndi.flags;
+ memset(&nd, 0, sizeof(nd));
+ strlcpy(nd.ifname, ifname, sizeof(nd.ifname));
+ if ((ndflags & ND6_IFF_IFDISABLED) != 0) {
+ if (in6en) {
+ nd.ndi.flags &= ~ND6_IFF_IFDISABLED;
+ if (ioctl(s, SIOCSIFINFO_IN6, &nd) != 0) {
+ error = errno;
+ goto out;
+ }
+ } else {
+ error = ENETDOWN;
+ goto out;
+ }
+ }
+ if ((ndflags & ND6_IFF_ACCEPT_RTADV) == 0) {
+ if (in6en) {
+ nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV;
+ if (ioctl(s, SIOCSIFINFO_IN6, &nd) != 0) {
+ error = errno;
+ goto out;
+ }
+ } else {
+ error = EHOSTDOWN;
+ goto out;
+ }
+ }
+
+out:
+ (void)close(s);
+ return (return_errno(error));
+}
+
+#ifdef WITH_CASPER
+static nvlist_t *
+cap_if_op(cap_channel_t *cap, const char *cmd, const char *ifname, int *errorp)
+{
+ nvlist_t *nvl;
+ int error;
+
+ nvl = nvlist_create(0);
+ nvlist_add_string(nvl, "cmd", cmd);
+ nvlist_add_string(nvl, "ifname", ifname);
+ nvl = cap_xfer_nvlist(cap, nvl);
+ if (nvl == NULL) {
+ *errorp = errno;
+ return (NULL);
+ }
+ error = (int)dnvlist_get_number(nvl, "error", 0);
if (error != 0) {
+ *errorp = error;
+ nvlist_destroy(nvl);
+ nvl = NULL;
+ }
+ return (nvl);
+}
+#endif
+
+int
+cap_ifflags_get(cap_channel_t *cap, const char *ifname, int *flagsp)
+{
+#ifdef WITH_CASPER
+ nvlist_t *nvl;
+ int error;
+
+ nvl = cap_if_op(cap, CMD_IFFLAGS_GET, ifname, &error);
+ if (nvl == NULL) {
errno = error;
return (-1);
- } else {
- return (0);
}
+ *flagsp = (int)nvlist_get_number(nvl, "flags");
+ nvlist_destroy(nvl);
+ return (0);
+#else
+ (void)cap;
+ return (ifflags_get(ifname, flagsp));
+#endif
+}
+
+int
+cap_ifmedia_get(cap_channel_t *cap, const char *ifname, struct ifmediareq *ifmr)
+{
+#ifdef WITH_CASPER
+ struct ifmediareq *ret;
+ nvlist_t *nvl;
+ size_t sz;
+ int error;
+
+ nvl = cap_if_op(cap, CMD_IFMEDIA_GET, ifname, &error);
+ if (nvl == NULL) {
+ errno = error;
+ return (-1);
+ }
+ ret = nvlist_take_binary(nvl, "ifmedia", &sz);
+ nvlist_destroy(nvl);
+ if (sz != sizeof(*ifmr)) {
+ free(ret);
+ errno = EINVAL;
+ return (-1);
+ }
+ memcpy(ifmr, ret, sizeof(*ifmr));
+ free(ret);
+ return (0);
+#else
+ (void)cap;
+ return (ifmedia_get(ifname, ifmr));
+#endif
}
int
@@ -123,41 +329,106 @@
nvlist_t *nvl;
int error;
+ nvl = cap_if_op(cap, CMD_LLFLAGS_GET, ifname, &error);
+ if (nvl == NULL) {
+ errno = error;
+ return (-1);
+ }
+ *flagsp = (int)nvlist_get_number(nvl, "flags");
+ nvlist_destroy(nvl);
+ return (0);
+#else
+ (void)cap;
+ return (llflags_get(ifname, flagsp));
+#endif
+}
+
+int
+cap_if_up(cap_channel_t *cap, const char *ifname, bool in6en)
+{
+#ifdef WITH_CASPER
+ nvlist_t *nvl;
+ int error;
+
nvl = nvlist_create(0);
- nvlist_add_string(nvl, "cmd", "get");
+ nvlist_add_string(nvl, "cmd", CMD_IF_UP);
nvlist_add_string(nvl, "ifname", ifname);
+ nvlist_add_bool(nvl, "in6en", in6en);
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)
+ if (error != 0) {
errno = error;
- return (error == 0 ? 0 : -1);
+ error = -1;
+ }
+ nvlist_destroy(nvl);
+ return (error);
#else
(void)cap;
- return (llflags_get(ifname, flagsp));
+ return (if_up(ifname, in6en));
#endif
}
#ifdef WITH_CASPER
static int
-llflags_command(const char *cmd, const nvlist_t *limits __unused,
+if_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits)
+{
+ if (oldlimits != NULL)
+ return (ENOTCAPABLE);
+ ifnames = nvlist_get_string_array(newlimits, "ifnames", &ifcnt);
+ return (0);
+}
+
+static int
+if_command(const char *cmd, const nvlist_t *limits __unused,
nvlist_t *nvlin, nvlist_t *nvlout)
{
const char *ifname;
- int flags;
+ size_t i;
+ int error, flags;
- if (strcmp(cmd, "get") != 0)
- return (EINVAL);
+ /*
+ * Check whether the specified interface belongs to the allowed list.
+ */
ifname = nvlist_get_string(nvlin, "ifname");
- if (llflags_get(ifname, &flags) != 0)
- return (errno);
- nvlist_add_number(nvlout, "flags", flags);
- return (0);
+ for (i = 0; i < ifcnt; i++)
+ if (strcmp(ifnames[i], ifname) == 0)
+ break;
+ if (i == ifcnt)
+ return (ENOTCAPABLE);
+
+ error = 0;
+ if (strcmp(cmd, CMD_IFFLAGS_GET) == 0) {
+ if (ifflags_get(ifname, &flags) != 0)
+ error = errno;
+ else
+ nvlist_add_number(nvlout, "flags", flags);
+ } else if (strcmp(cmd, CMD_IFMEDIA_GET) == 0) {
+ struct ifmediareq ifmr;
+
+ if (ifmedia_get(ifname, &ifmr) != 0)
+ error = errno;
+ else
+ nvlist_add_binary(nvlout, "ifmedia", &ifmr,
+ sizeof(ifmr));
+ } else if (strcmp(cmd, CMD_LLFLAGS_GET) == 0) {
+ if (llflags_get(ifname, &flags) != 0)
+ error = errno;
+ else
+ nvlist_add_number(nvlout, "flags", flags);
+ } else if (strcmp(cmd, CMD_IF_UP) == 0) {
+ bool in6en;
+
+ in6en = nvlist_get_bool(nvlin, "in6en");
+ if (if_up(ifname, in6en) != 0)
+ error = errno;
+ } else {
+ error = EINVAL;
+ }
+
+ return (error);
}
-CREATE_SERVICE("rtsold.llflags", NULL, llflags_command, 0);
+CREATE_SERVICE("rtsold.if", if_limit, if_command, 0);
#endif /* WITH_CASPER */
Index: usr.sbin/rtsold/if.c
===================================================================
--- usr.sbin/rtsold/if.c
+++ usr.sbin/rtsold/if.c
@@ -64,122 +64,35 @@
#include <ifaddrs.h>
#include "rtsold.h"
-static int ifsock;
static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
-int
-ifinit(void)
-{
- cap_rights_t rights;
- int sock;
-
- 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
interface_up(char *name)
{
- struct ifreq ifr;
- struct in6_ndireq nd;
- int llflag;
- int s;
+ int llflags;
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- memset(&nd, 0, sizeof(nd));
- strlcpy(nd.ifname, name, sizeof(nd.ifname));
-
- if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
- warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFFLAGS): %s",
- strerror(errno));
- return (-1);
- }
- if (!(ifr.ifr_flags & IFF_UP)) {
- ifr.ifr_flags |= IFF_UP;
- if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
- warnmsg(LOG_ERR, __func__,
- "ioctl(SIOCSIFFLAGS): %s", strerror(errno));
- return (-1);
- }
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- warnmsg(LOG_WARNING, __func__, "socket(AF_INET6, SOCK_DGRAM): %s",
- strerror(errno));
- return (-1);
- }
- if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) {
- warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFINFO_IN6): %s",
+ if (cap_if_up(capif, name, Fflag != 0) != 0) {
+ warnmsg(LOG_WARNING, __func__, "cap_ifflags_get(): %s",
strerror(errno));
- close(s);
return (-1);
}
- warnmsg(LOG_DEBUG, __func__, "checking if %s is ready...", name);
-
- if (nd.ndi.flags & ND6_IFF_IFDISABLED) {
- if (Fflag) {
- nd.ndi.flags &= ~ND6_IFF_IFDISABLED;
- if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) {
- warnmsg(LOG_WARNING, __func__,
- "ioctl(SIOCSIFINFO_IN6): %s",
- strerror(errno));
- close(s);
- return (-1);
- }
- } else {
- warnmsg(LOG_WARNING, __func__,
- "%s is disabled.", name);
- close(s);
- return (-1);
- }
- }
- if (!(nd.ndi.flags & ND6_IFF_ACCEPT_RTADV)) {
- if (Fflag) {
- nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV;
- if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) {
- warnmsg(LOG_WARNING, __func__,
- "ioctl(SIOCSIFINFO_IN6): %s",
- strerror(errno));
- close(s);
- return (-1);
- }
- } else {
- warnmsg(LOG_WARNING, __func__,
- "%s does not accept Router Advertisement.", name);
- close(s);
- return (-1);
- }
- }
- close(s);
-
- if (cap_llflags_get(capllflags, name, &llflag) != 0) {
+ if (cap_llflags_get(capif, name, &llflags) != 0) {
warnmsg(LOG_WARNING, __func__,
"cap_llflags_get() failed, anyway I'll try");
return (0);
}
- if (!(llflag & IN6_IFF_NOTREADY)) {
+ if ((llflags & IN6_IFF_NOTREADY) == 0) {
warnmsg(LOG_DEBUG, __func__, "%s is ready", name);
return (0);
} else {
- if (llflag & IN6_IFF_TENTATIVE) {
+ if (llflags & IN6_IFF_TENTATIVE) {
warnmsg(LOG_DEBUG, __func__, "%s is tentative",
name);
return (IFS_TENTATIVE);
}
- if (llflag & IN6_IFF_DUPLICATED)
+ if (llflags & IN6_IFF_DUPLICATED)
warnmsg(LOG_DEBUG, __func__, "%s is duplicated",
name);
return (-1);
@@ -190,14 +103,12 @@
interface_status(struct ifinfo *ifinfo)
{
char *ifname = ifinfo->ifname;
- struct ifreq ifr;
struct ifmediareq ifmr;
+ int ifflags;
/* get interface flags */
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) {
- warnmsg(LOG_ERR, __func__, "ioctl(SIOCGIFFLAGS) on %s: %s",
+ if (cap_ifflags_get(capif, ifname, &ifflags) != 0) {
+ warnmsg(LOG_ERR, __func__, "cap_ifflags_get() on %s: %s",
ifname, strerror(errno));
return (-1);
}
@@ -205,21 +116,20 @@
* if one of UP and RUNNING flags is dropped,
* the interface is not active.
*/
- if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+ if ((ifflags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
goto inactive;
/* Next, check carrier on the interface, if possible */
if (!ifinfo->mediareqok)
goto active;
- memset(&ifmr, 0, sizeof(ifmr));
- strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
- if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+ if (cap_ifmedia_get(capif, ifname, &ifmr) != 0) {
if (errno != EINVAL) {
warnmsg(LOG_DEBUG, __func__,
- "ioctl(SIOCGIFMEDIA) on %s: %s",
+ "cap_ifmedia_get() on %s: %s",
ifname, strerror(errno));
return(-1);
}
+
/*
* EINVAL simply means that the interface does not support
* the SIOCGIFMEDIA ioctl. We regard it alive.
Index: usr.sbin/rtsold/rtsold.h
===================================================================
--- usr.sbin/rtsold/rtsold.h
+++ usr.sbin/rtsold/rtsold.h
@@ -161,7 +161,7 @@
extern const char *managedconf_script;
extern const char *otherconf_script;
extern const char *resolvconf_script;
-extern struct cap_channel *capllflags, *capscript, *capsendmsg, *capsyslog;
+extern struct cap_channel *capif, *capscript, *capsendmsg, *capsyslog;
struct ifinfo *find_ifinfo(int);
struct rainfo *find_rainfo(struct ifinfo *, struct sockaddr_in6 *);
@@ -172,7 +172,6 @@
/* if.c */
struct nd_opt_hdr;
-extern int ifinit(void);
extern int interface_up(char *);
extern int interface_status(struct ifinfo *);
extern int lladdropt_length(struct sockaddr_dl *);
@@ -183,8 +182,13 @@
extern int recvsockopen(void);
extern void rtsol_input(int);
-/* cap_llflags.c */
+/* cap_if.c */
+struct ifmediareq;
+extern int cap_ifflags_get(struct cap_channel *, const char *, int *);
+extern int cap_ifmedia_get(struct cap_channel *, const char *,
+ struct ifmediareq *);
extern int cap_llflags_get(struct cap_channel *, const char *, int *);
+extern int cap_if_up(struct cap_channel *, const char *, bool);
/* cap_script.c */
extern int cap_script_run(struct cap_channel *, const char *const *);
Index: usr.sbin/rtsold/rtsold.c
===================================================================
--- usr.sbin/rtsold/rtsold.c
+++ usr.sbin/rtsold/rtsold.c
@@ -84,7 +84,7 @@
const char *otherconf_script;
const char *resolvconf_script = "/sbin/resolvconf";
-cap_channel_t *capllflags, *capscript, *capsendmsg, *capsyslog;
+cap_channel_t *capif, *capscript, *capsendmsg, *capsyslog;
/* protocol constants */
#define MAX_RTR_SOLICITATION_DELAY 1 /* second */
@@ -106,6 +106,7 @@
static char **autoifprobe(void);
static int ifconfig(char *ifname);
static int init_capabilities(void);
+static int limit_capabilities(char *const *);
static int make_packet(struct ifinfo *);
static struct timespec *rtsol_check_timer(void);
@@ -251,12 +252,12 @@
}
/* Probe network interfaces and set up tracking info. */
- if (ifinit() != 0) {
- warnmsg(LOG_ERR, __func__, "failed to initialize interfaces");
- exit(1);
- }
if (aflag)
argv = autoifprobe();
+
+ /* Limit the interface service to the specified interfaces. */
+ limit_capabilities(argv);
+
while (argv && *argv) {
if (ifconfig(*argv)) {
warnmsg(LOG_ERR, __func__,
@@ -340,8 +341,8 @@
if (capcasper == NULL)
return (-1);
- capllflags = cap_service_open(capcasper, "rtsold.llflags");
- if (capllflags == NULL)
+ capif = cap_service_open(capcasper, "rtsold.if");
+ if (capif == NULL)
return (-1);
capscript = cap_service_open(capcasper, "rtsold.script");
@@ -370,6 +371,24 @@
return (0);
}
+static int
+limit_capabilities(char *const *ifs)
+{
+#ifdef WITH_CASPER
+ nvlist_t *limits;
+
+ limits = nvlist_create(0);
+ for (int i = 0; ifs[i] != NULL; i++)
+ nvlist_append_string_array(limits, "ifnames", ifs[i]);
+ if (cap_limit_set(capif, limits) != 0)
+ return (-1);
+ return (0);
+#else
+ (void)ifs;
+ return (0);
+#endif
+}
+
static int
ifconfig(char *ifname)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 7, 11:14 AM (7 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36167794
Default Alt Text
D29824.id87709.diff (16 KB)
Attached To
Mode
D29824: rtsold: Extend casper to support various interface operations
Attached
Detach File
Event Timeline
Log In to Comment