Merge pull request #580 from wigyori/cc-libpcap
[15.05/openwrt.git] / package / network / services / wireguard / files / wireguard.sh
1 #!/bin/sh
2 # Copyright 2016-2017 Dan Luedtke <mail@danrl.com>
3 # Licensed to the public under the Apache License 2.0.
4
5
6 WG=/usr/bin/wg
7 if [ ! -x $WG ]; then
8   logger -t "wireguard" "error: missing wireguard-tools (${WG})"
9   exit 0
10 fi
11
12
13 [ -n "$INCLUDE_ONLY" ] || {
14   . /lib/functions.sh
15   . ../netifd-proto.sh
16   init_proto "$@"
17 }
18
19
20 proto_wireguard_init_config() {
21   proto_config_add_string "private_key"
22   proto_config_add_int    "listen_port"
23   proto_config_add_int    "mtu"
24   proto_config_add_string "fwmark"
25   available=1
26   no_proto_task=1
27 }
28
29
30 proto_wireguard_setup_peer() {
31   local peer_config="$1"
32
33   local public_key
34   local preshared_key
35   local allowed_ips
36   local route_allowed_ips
37   local endpoint_host
38   local endpoint_port
39   local persistent_keepalive
40
41   config_get      public_key           "${peer_config}" "public_key"
42   config_get      preshared_key        "${peer_config}" "preshared_key"
43   config_get      allowed_ips          "${peer_config}" "allowed_ips"
44   config_get_bool route_allowed_ips    "${peer_config}" "route_allowed_ips" 0
45   config_get      endpoint_host        "${peer_config}" "endpoint_host"
46   config_get      endpoint_port        "${peer_config}" "endpoint_port"
47   config_get      persistent_keepalive "${peer_config}" "persistent_keepalive"
48
49   # peer configuration
50   echo "[Peer]"                                         >> "${wg_cfg}"
51   echo "PublicKey=${public_key}"                        >> "${wg_cfg}"
52   if [ "${preshared_key}" ]; then
53     echo "PresharedKey=${preshared_key}"                >> "${wg_cfg}"
54   fi
55   for allowed_ip in $allowed_ips; do
56     echo "AllowedIPs=${allowed_ip}"                     >> "${wg_cfg}"
57   done
58   if [ "${endpoint_host}" ]; then
59     case "${endpoint_host}" in
60       *:*)
61         endpoint="[${endpoint_host}]"
62       ;;
63       *)
64         endpoint="${endpoint_host}"
65       ;;
66     esac
67     if [ "${endpoint_port}" ]; then
68       endpoint="${endpoint}:${endpoint_port}"
69     else
70       endpoint="${endpoint}:51820"
71     fi
72     echo "Endpoint=${endpoint}"                         >> "${wg_cfg}"
73   fi
74   if [ "${persistent_keepalive}" ]; then
75     echo "PersistentKeepalive=${persistent_keepalive}"  >> "${wg_cfg}"
76   fi
77
78   # add routes for allowed ips
79   if [ ${route_allowed_ips} -ne 0 ]; then
80     for allowed_ip in ${allowed_ips}; do
81       case "${allowed_ip}" in
82         *:*/*)
83           proto_add_ipv6_route "${allowed_ip%%/*}" "${allowed_ip##*/}"
84         ;;
85         *.*/*)
86           proto_add_ipv4_route "${allowed_ip%%/*}" "${allowed_ip##*/}"
87         ;;
88         *:*)
89           proto_add_ipv6_route "${allowed_ip%%/*}" "128"
90         ;;
91         *.*)
92           proto_add_ipv4_route "${allowed_ip%%/*}" "32"
93         ;;
94       esac
95     done
96   fi
97 }
98
99
100 proto_wireguard_setup() {
101   local config="$1"
102   local wg_dir="/tmp/wireguard"
103   local wg_cfg="${wg_dir}/${config}"
104
105   local private_key
106   local listen_port
107   local mtu
108
109   # load configuration
110   config_load network
111   config_get private_key   "${config}" "private_key"
112   config_get listen_port   "${config}" "listen_port"
113   config_get addresses     "${config}" "addresses"
114   config_get mtu           "${config}" "mtu"
115   config_get fwmark        "${config}" "fwmark"
116
117   # create interface
118   ip link del dev "${config}" 2>/dev/null
119   ip link add dev "${config}" type wireguard
120
121   if [ "${mtu}" ]; then
122     ip link set mtu "${mtu}" dev "${config}"
123   fi
124
125   proto_init_update "${config}" 1
126
127   # generate configuration file
128   umask 077
129   mkdir -p "${wg_dir}"
130   echo "[Interface]"                     >  "${wg_cfg}"
131   echo "PrivateKey=${private_key}"       >> "${wg_cfg}"
132   if [ "${listen_port}" ]; then
133     echo "ListenPort=${listen_port}"     >> "${wg_cfg}"
134   fi
135   if [ "${fwmark}" ]; then
136     echo "FwMark=${fwmark}" >> "${wg_cfg}"
137   fi
138   config_foreach proto_wireguard_setup_peer "wireguard_${config}"
139
140   # apply configuration file
141   ${WG} setconf ${config} "${wg_cfg}"
142   WG_RETURN=$?
143
144   # delete configuration file
145   rm -f "${wg_cfg}"
146
147   # check status
148   if [ ${WG_RETURN} -ne 0 ]; then
149     sleep 5
150     proto_setup_failed "${config}"
151     exit 1
152   fi
153
154   # add ip addresses
155   for address in ${addresses}; do
156     case "${address}" in
157       *:*/*)
158         proto_add_ipv6_address "${address%%/*}" "${address##*/}"
159       ;;
160       *.*/*)
161         proto_add_ipv4_address "${address%%/*}" "${address##*/}"
162       ;;
163       *:*)
164         proto_add_ipv6_address "${address%%/*}" "128"
165       ;;
166       *.*)
167         proto_add_ipv4_address "${address%%/*}" "32"
168       ;;
169     esac
170   done
171
172   # endpoint dependency
173   wg show "${config}" endpoints | \
174     sed -E 's/\[?([0-9.:a-f]+)\]?:([0-9]+)/\1 \2/' | \
175     while IFS=$'\t ' read -r key address port; do
176     [ -n "${port}" ] || continue
177     proto_add_host_dependency "${config}" "${address}"
178   done
179
180   proto_send_update "${config}"
181 }
182
183
184 proto_wireguard_teardown() {
185   local config="$1"
186   ip link del dev "${config}" >/dev/null 2>&1
187 }
188
189
190 [ -n "$INCLUDE_ONLY" ] || {
191   add_protocol wireguard
192 }