In case this turns out to be useful for unlocking work in the kernel.
It's a minimum diff, if we want to go this way we probably want to move
init_soiikey() to the engine process and stop bouncing through the main
process when an interface changes.
This changes behaviour: in -current we can change the sysctl and down/up
an interface to read the new value, with this diff that no longer
works. slaacd will (and can) only read the file on startup.
This has consequences for the installer: slaacd starts before
/mnt/etc/soii.key is available in the upgrade case. Which in turn means
that we get a different IPv6 address in the installer than in the
running system. I don't know how big of an issue that is.
diff --git distrib/miniroot/install.sub distrib/miniroot/install.sub
index d3d944bf2ca..aa84e4808f2 100644
--- distrib/miniroot/install.sub
+++ distrib/miniroot/install.sub
@@ -2620,9 +2620,6 @@ enable_network() {
echo "127.0.0.1\tlocalhost" >/tmp/i/hosts
echo "::1\t\tlocalhost" >>/tmp/i/hosts
- _f=/mnt/etc/soii.key
- [[ -f $_f ]] && sysctl "net.inet6.ip6.soiikey=$(<$_f)"
-
enable_ifs
}
diff --git distrib/special/sysctl/sysctl.c distrib/special/sysctl/sysctl.c
index 9156d5f455c..7aedb6dd55b 100644
--- distrib/special/sysctl/sysctl.c
+++ distrib/special/sysctl/sysctl.c
@@ -99,39 +99,6 @@ pstring(struct var *v)
return (1);
}
-int
-parse_hex_char(char ch)
-{
- if (ch >= '0' && ch <= '9')
- return (ch - '0');
-
- ch = tolower((unsigned char)ch);
- if (ch >= 'a' && ch <= 'f')
- return (ch - 'a' + 10);
-
- return (-1);
-}
-
-int
-set_soii_key(char *src)
-{
- uint8_t key[SOIIKEY_LEN];
- int mib[4] = {CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_SOIIKEY};
- int i, c;
-
- for(i = 0; i < SOIIKEY_LEN; i++) {
- if ((c = parse_hex_char(src[2 * i])) == -1)
- return (-1);
- key[i] = c << 4;
- if ((c = parse_hex_char(src[2 * i + 1])) == -1)
- return (-1);
- key[i] |= c;
- }
-
- return sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, NULL, key,
- SOIIKEY_LEN);
-}
-
int
main(int argc, char *argv[])
{
@@ -159,17 +126,6 @@ main(int argc, char *argv[])
while (argc--) {
name = *argv++;
- /*
- * strlen("net.inet6.ip6.soiikey="
- * "00000000000000000000000000000000") == 54
- * strlen("net.inet6.ip6.soiikey=") == 22
- */
- if (strlen(name) == 54 && strncmp(name,
- "net.inet6.ip6.soiikey=", 22) == 0) {
- set_soii_key(name + 22);
- continue;
- }
-
for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
if (strcmp(name, vars[i].name) == 0) {
(vars[i].print)(&vars[i]);
diff --git etc/netstart etc/netstart
index af4866f909e..105d5a977cf 100644
--- etc/netstart
+++ etc/netstart
@@ -360,13 +360,6 @@ if ifconfig lo0 inet6 >/dev/null 2>&1; then
IP6KERNEL=true
fi
-# Load key material for the generation of IPv6 Semantically Opaque Interface
-# Identifiers (SOII) used for SLAAC addresses.
-if $IP6KERNEL && ! $PRINT_ONLY; then
- [[ -f /etc/soii.key ]] &&
- sysctl -q "net.inet6.ip6.soiikey=$(</etc/soii.key)"
-fi
-
# If we were invoked with a list of interface names, just reconfigure these
# interfaces (or bridges), add default routes and return.
# Create virtual interfaces upfront to make ifconfig commands depending on
diff --git etc/rc etc/rc
index ea30a76aec4..78d82c81cd5 100644
--- etc/rc
+++ etc/rc
@@ -164,11 +164,6 @@ make_keys() {
ssh-keygen -A
- if [[ ! -f /etc/soii.key ]]; then
- openssl rand -hex 16 > /etc/soii.key &&
- chmod 600 /etc/soii.key && sysctl -q \
- "net.inet6.ip6.soiikey=$(</etc/soii.key)"
- fi
}
# Re-link libraries, placing the objects in a random order.
diff --git sbin/slaacd/slaacd.c sbin/slaacd/slaacd.c
index 4d1786361f7..3187af8740b 100644
--- sbin/slaacd/slaacd.c
+++ sbin/slaacd/slaacd.c
@@ -22,8 +22,8 @@
#include <sys/ioctl.h>
#include <sys/queue.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/syslog.h>
-#include <sys/sysctl.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -34,6 +34,7 @@
#include <netinet6/in6_var.h>
#include <netinet/icmp6.h>
+#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -76,7 +77,8 @@ void configure_gateway(struct imsg_configure_dfr *, uint8_t);
void add_gateway(struct imsg_configure_dfr *);
void delete_gateway(struct imsg_configure_dfr *);
void send_rdns_proposal(struct imsg_propose_rdns *);
-int get_soiikey(uint8_t *);
+int parse_hex_char(char);
+void init_soiikey(void);
static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *);
int main_imsg_compose_frontend(int, int, void *, uint16_t);
@@ -89,6 +91,7 @@ pid_t frontend_pid;
pid_t engine_pid;
int routesock, ioctl_sock, rtm_seq = 0;
+uint8_t soiikey[SLAACD_SOIIKEY_LEN];
void
main_sig_handler(int sig, short event, void *arg)
@@ -189,6 +192,10 @@ main(int argc, char *argv[])
if (getpwnam(SLAACD_USER) == NULL)
errx(1, "unknown user %s", SLAACD_USER);
+#ifndef SMALL
+ init_soiikey();
+#endif /* SMALL */
+
log_init(debug, LOG_DAEMON);
log_setverbose(verbose);
@@ -431,11 +438,9 @@ main_dispatch_frontend(int fd, short event, void *bula)
fatalx("%s: IMSG_UPDATE_IF wrong length: %lu",
__func__, IMSG_DATA_SIZE(imsg));
memcpy(&imsg_ifinfo, imsg.data, sizeof(imsg_ifinfo));
- if (get_soiikey(imsg_ifinfo.soiikey) == -1)
- log_warn("get_soiikey");
- else
- main_imsg_compose_engine(IMSG_UPDATE_IF, 0,
- &imsg_ifinfo, sizeof(imsg_ifinfo));
+ memcpy(imsg_ifinfo.soiikey, soiikey, sizeof(soiikey));
+ main_imsg_compose_engine(IMSG_UPDATE_IF, 0,
+ &imsg_ifinfo, sizeof(imsg_ifinfo));
break;
default:
log_debug("%s: error handling imsg %d", __func__,
@@ -856,16 +861,56 @@ sin6_to_str(struct sockaddr_in6 *sin6)
}
return hbuf;
}
-#endif /* SMALL */
int
-get_soiikey(uint8_t *key)
+parse_hex_char(char ch)
{
- int mib[4] = {CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_SOIIKEY};
- size_t size = SLAACD_SOIIKEY_LEN;
+ if (ch >= '0' && ch <= '9')
+ return (ch - '0');
+
+ ch = tolower((unsigned char)ch);
+ if (ch >= 'a' && ch <= 'f')
+ return (ch - 'a' + 10);
+
+ return (-1);
+}
- return sysctl(mib, sizeof(mib) / sizeof(mib[0]), key, &size, NULL, 0);
+void
+init_soiikey(void)
+{
+ int fd, i;
+ char buf[SLAACD_SOIIKEY_LEN * 2 + 1];
+
+ memset(buf, 0, sizeof(buf));
+ if ((fd = open(_PATH_SOIIKEY, O_RDONLY)) == -1) {
+ arc4random_buf(soiikey, SLAACD_SOIIKEY_LEN);
+ for (i = 0; i < SLAACD_SOIIKEY_LEN; i++)
+ snprintf(&buf[2 * i], sizeof(buf) - 2 * i, "%02x",
+ soiikey[i]);
+ buf[sizeof(buf) - 1] = '\n';
+ if ((fd = open(_PATH_SOIIKEY, O_WRONLY | O_CREAT,
+ S_IRUSR | S_IWUSR)) != -1) {
+ write(fd, buf, sizeof(buf));
+ close(fd);
+ }
+ } else {
+ if (read(fd, buf, sizeof(buf)) == -1)
+ arc4random_buf(soiikey, SLAACD_SOIIKEY_LEN);
+ else {
+ for (i = 0; i < SLAACD_SOIIKEY_LEN; i++) {
+ int c;
+ if ((c = parse_hex_char(buf[2 * i])) == -1)
+ break;
+ soiikey[i] = c << 4;
+ if ((c = parse_hex_char(buf[2 * i + 1])) == -1)
+ break;
+ soiikey[i] |= c;
+ }
+ }
+ close(fd);
+ }
}
+#endif /* SMALL */
void
open_icmp6sock(int rdomain)
diff --git sbin/slaacd/slaacd.h sbin/slaacd/slaacd.h
index 2844f4a63b7..9ee028247a8 100644
--- sbin/slaacd/slaacd.h
+++ sbin/slaacd/slaacd.h
@@ -20,6 +20,7 @@
#define _PATH_LOCKFILE "/dev/slaacd.lock"
#define _PATH_SLAACD_SOCKET "/dev/slaacd.sock"
+#define _PATH_SOIIKEY "/etc/soii.key"
#define SLAACD_USER "_slaacd"
#define SLAACD_RTA_LABEL "slaacd"
--
In my defence, I have been left unsupervised.