34c8c54
diff -up ./contrib/systemd/cjdns-loadmodules.service.sbin ./contrib/systemd/cjdns-loadmodules.service
da4d7ba
--- ./contrib/systemd/cjdns-loadmodules.service.sbin	2017-01-13 21:43:05.413731242 -0500
da4d7ba
+++ ./contrib/systemd/cjdns-loadmodules.service	2017-01-13 21:43:05.413731242 -0500
34c8c54
@@ -0,0 +1,13 @@
34c8c54
+[Unit]
34c8c54
+Description=Load cjdns kernel modules
34c8c54
+# Load kernel modules needed by cjdns so that it doesn't need the privilege
34c8c54
+Before=cjdns.service
34c8c54
+# Do not try to load modules in containers like openvz
34c8c54
+ConditionVirtualization=!container
34c8c54
+
34c8c54
+[Service]
34c8c54
+Type=oneshot
34c8c54
+ExecStart=/usr/sbin/modprobe tun
34c8c54
+
34c8c54
+[Install]
34c8c54
+WantedBy=multi-user.target
2f8dfd1
diff -up ./contrib/systemd/cjdns-online.sh.sbin ./contrib/systemd/cjdns-online.sh
da4d7ba
--- ./contrib/systemd/cjdns-online.sh.sbin	2017-01-13 21:43:05.414731254 -0500
da4d7ba
+++ ./contrib/systemd/cjdns-online.sh	2017-01-13 21:43:05.414731254 -0500
a92f077
@@ -0,0 +1,90 @@
2f8dfd1
+#!/bin/sh
2f8dfd1
+#   Check whether cjdns IPs are available
2f8dfd1
+#   Copyright (C) 2016  Stuart D. Gathman <stuart@gathman.org>
2f8dfd1
+#
2f8dfd1
+#   This program is free software: you can redistribute it and/or modify
2f8dfd1
+#   it under the terms of the GNU General Public License as published by
2f8dfd1
+#   the Free Software Foundation, either version 3 of the License, or
2f8dfd1
+#   (at your option) any later version.
2f8dfd1
+#
2f8dfd1
+#   This program is distributed in the hope that it will be useful,
2f8dfd1
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
2f8dfd1
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2f8dfd1
+#   GNU General Public License for more details.
2f8dfd1
+#
2f8dfd1
+#   You should have received a copy of the GNU General Public License
2f8dfd1
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
2f8dfd1
+
2f8dfd1
+cjdns_ips() {
2f8dfd1
+  ip -6 -o addr | while read i dev fam ip rem; do
2f8dfd1
+    case "$ip" in
2f8dfd1
+    fc*:*/8) echo "${ip%/8}";;
2f8dfd1
+    esac
2f8dfd1
+  done
2f8dfd1
+}
2f8dfd1
+
a92f077
+cjdns_dev() {
a92f077
+  ip -6 -o addr | while read i dev fam ip rem; do
a92f077
+    case "$ip" in
a92f077
+    fc*:*/8) echo "${dev}";;
a92f077
+    esac
a92f077
+  done
a92f077
+}
a92f077
+
2f8dfd1
+die() {
2f8dfd1
+  echo "$1" >&2
2f8dfd1
+  exit 1
2f8dfd1
+}
2f8dfd1
+
2f8dfd1
+PROGRAM_NAME="/usr/bin/cjdns-online"
2f8dfd1
+
a92f077
+ARGS=$(getopt -n $PROGRAM_NAME -o t:xiqsh \
a92f077
+	--long timeout:,exit,interface,quiet,wait-for-startup,help -- "$@")
2f8dfd1
+
2f8dfd1
+# Die if they fat finger arguments, this program may be run as root
2f8dfd1
+[ $? = 0 ] || die "Error parsing arguments. Try $PROGRAM_NAME --help"
2f8dfd1
+
2f8dfd1
+help() {
2f8dfd1
+        cat <
2f8dfd1
+Usage: $PROGRAM_NAME [options]
2f8dfd1
+        -t, --timeout <timeout_value>	time to wait in seconds, default 30
a92f077
+        -i, --interface 	output interface name instead of ip
2f8dfd1
+        -x, --exit		exit immediately if cjdns is not online
2f8dfd1
+        -q, --quiet		don't print anything
2f8dfd1
+        -s, --wait-for-startup	wait for full startup instead of just tun dev
2f8dfd1
+EOH
2f8dfd1
+        exit 2
2f8dfd1
+}
2f8dfd1
+
2f8dfd1
+let timeout="30"
2f8dfd1
+let nowait="0"
2f8dfd1
+let quiet="0"
2f8dfd1
+let startup="0"
a92f077
+let interface="0"
2f8dfd1
+
2f8dfd1
+eval set -- "$ARGS"
2f8dfd1
+while true; do
2f8dfd1
+  case "$1" in
2f8dfd1
+    -t|--timeout)	   let timeout="$2" || help; shift 2; continue;;
a92f077
+    -i|--interface)	   let interface="1"; shift;;
2f8dfd1
+    -x|--exit)		   let nowait="1"; shift;;
2f8dfd1
+    -q|--quiet)		   let quiet="1"; shift;;
2f8dfd1
+    -s|--wait-for-startup) let startup="1"; shift;;
2f8dfd1
+    --) shift; break;;
2f8dfd1
+    *)	help;;
2f8dfd1
+  esac
2f8dfd1
+done
2f8dfd1
+
2f8dfd1
+let started="$(date +%s)"
2f8dfd1
+while test -z "$(cjdns_ips)"; do
2f8dfd1
+  let elapsed="$(date +%s) - $started"
2f8dfd1
+  [ $elapsed -gt $timeout ] && exit 1
2f8dfd1
+  sleep 2
2f8dfd1
+done
2f8dfd1
+if [ "$quiet" -eq 0 ]; then
a92f077
+  if [ "$interface" -eq 0 ]; then
a92f077
+    cjdns_ips
a92f077
+  else
a92f077
+    cjdns_dev
a92f077
+  fi
2f8dfd1
+fi
2f8dfd1
diff -up ./contrib/systemd/cjdns.service.sbin ./contrib/systemd/cjdns.service
da4d7ba
--- ./contrib/systemd/cjdns.service.sbin	2016-10-11 17:39:44.000000000 -0400
da4d7ba
+++ ./contrib/systemd/cjdns.service	2017-01-13 22:07:35.128118775 -0500
da4d7ba
@@ -1,18 +1,21 @@
34c8c54
 [Unit]
34c8c54
 Description=cjdns: routing engine designed for security, scalability, speed and ease of use
34c8c54
 Wants=network.target
34c8c54
-After=network.target
34c8c54
+After=network.target cjdns-loadmodules.service
34c8c54
+Requires=cjdns-loadmodules.service
34c8c54
 
34c8c54
 [Service]
35161c4
 ProtectHome=true
35161c4
 ProtectSystem=true
2f8dfd1
 SyslogIdentifier=cjdroute
b56859a
+CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_SYS_CHROOT CAP_AUDIT_CONTROL
2f8dfd1
 ExecStartPre=/bin/sh -ec "if ! test -s /etc/cjdroute.conf; \
2f8dfd1
                 then umask 077; \
2f8dfd1
-                /usr/bin/cjdroute --genconf > /etc/cjdroute.conf; \
2f8dfd1
+                /usr/sbin/cjdroute --genconf | cat > /etc/cjdroute.conf; \
2f8dfd1
                 echo 'WARNING: A new /etc/cjdroute.conf file has been generated.'; \
34c8c54
             fi"
2f8dfd1
-ExecStart=/bin/sh -c "exec cjdroute --nobg < /etc/cjdroute.conf"
2f8dfd1
+ExecStart=/bin/sh -c "exec /usr/sbin/cjdroute --nobg < /etc/cjdroute.conf"
da4d7ba
+ExecStartPost=/bin/sh /usr/libexec/cjdns/cjdns-up
2f8dfd1
 Restart=always
2f8dfd1
 
2f8dfd1
 [Install]
2f8dfd1
diff -up ./contrib/systemd/cjdns-wait-online.service.sbin ./contrib/systemd/cjdns-wait-online.service
da4d7ba
--- ./contrib/systemd/cjdns-wait-online.service.sbin	2017-01-13 21:43:05.414731254 -0500
da4d7ba
+++ ./contrib/systemd/cjdns-wait-online.service	2017-01-13 21:43:05.414731254 -0500
2f8dfd1
@@ -0,0 +1,13 @@
2f8dfd1
+[Unit]
2f8dfd1
+Description=CJDNS Wait Online
2f8dfd1
+Requisite=cjdns.service
2f8dfd1
+After=cjdns.service
2f8dfd1
+Wants=network.target
2f8dfd1
+Before=network-online.target
2f8dfd1
+
2f8dfd1
+[Service]
2f8dfd1
+Type=oneshot
2f8dfd1
+ExecStart=/usr/bin/cjdns-online -s -q --timeout=30
2f8dfd1
+
2f8dfd1
+[Install]
2f8dfd1
+WantedBy=multi-user.target
2f8dfd1
diff -up ./contrib/upstart/cjdns.conf.sbin ./contrib/upstart/cjdns.conf
da4d7ba
--- ./contrib/upstart/cjdns.conf.sbin	2016-10-11 17:39:44.000000000 -0400
da4d7ba
+++ ./contrib/upstart/cjdns.conf	2017-01-13 21:45:35.268491363 -0500
8431b66
@@ -13,10 +13,16 @@ pre-start script
2f8dfd1
     if ! [ -s /etc/cjdroute.conf ]; then
2f8dfd1
         ( # start a subshell to avoid side effects of umask later on
2f8dfd1
             umask 077 # to create the file with 600 permissions without races
2f8dfd1
-            /usr/bin/cjdroute --genconf > /etc/cjdroute.conf
2f8dfd1
+	    # use cat because cjdroute can't write directly to /etc
2f8dfd1
+            /usr/sbin/cjdroute --genconf | cat > /etc/cjdroute.conf
2f8dfd1
         ) # exit subshell; umask no longer applies
2f8dfd1
         echo 'WARNING: A new cjdns cjdroute.conf file has been generated.'
2f8dfd1
     fi
2f8dfd1
+    # preload tun driver, since we prevent module_request
8431b66
+    case $(wc -c /proc/modules) in
8431b66
+    0*) ;;
8431b66
+    *) /sbin/modprobe tun;;
8431b66
+    esac
2f8dfd1
 
2f8dfd1
     # If you need a non-standard setup, as described in
2f8dfd1
     # https://github.com/cjdelisle/cjdns#non-standard-setups,
da4d7ba
@@ -25,4 +31,10 @@ pre-start script
2f8dfd1
     # see http://upstart.ubuntu.com/cookbook/#setuid
2f8dfd1
 end script
2f8dfd1
 
2f8dfd1
-exec /usr/bin/cjdroute --nobg < /etc/cjdroute.conf
da4d7ba
+script
da4d7ba
+  exec /usr/sbin/cjdroute --nobg < /etc/cjdroute.conf
da4d7ba
+end script
da4d7ba
+
da4d7ba
+post-start script
da4d7ba
+  . /usr/libexec/cjdns/cjdns-up
da4d7ba
+end script