master
sh 182 lines 5.14 KB
Raw
1 # no need for shebang - this file is loaded from charts.d.plugin
2 # SPDX-License-Identifier: GPL-3.0-or-later
3 # shellcheck shell=bash disable=SC1117
4 #
5 # _update_every is a special variable - it holds the number of seconds
6 # between the calls of the _update() function
7 libreswan_update_every=1
8
9 # the priority is used to sort the charts on the dashboard
10 # 1 = the first chart
11 libreswan_priority=90000
12
13 # set to 1, to run ipsec with sudo
14 libreswan_sudo=1
15
16 # global variables to store our collected data
17
18 # [TUNNELID] = TUNNELNAME
19 # here we track the *latest* established tunnels
20 # as detected by: ipsec whack --status
21 declare -A libreswan_connected_tunnels=()
22
23 # [TUNNELID] = VALUE
24 # here we track values of all established tunnels (not only the latest)
25 # as detected by: ipsec whack --trafficstatus
26 declare -A libreswan_traffic_in=()
27 declare -A libreswan_traffic_out=()
28 declare -A libreswan_established_add_time=()
29
30 # [TUNNELNAME] = CHARTID
31 # here we remember CHARTIDs of all tunnels
32 # we need this to avoid converting tunnel names to chart IDs on every iteration
33 declare -A libreswan_tunnel_charts=()
34
35 is_able_sudo_ipsec() {
36 if ! sudo -n -l "${IPSEC_CMD}" whack --status > /dev/null 2>&1; then
37 return 1
38 fi
39 if ! sudo -n -l "${IPSEC_CMD}" whack --trafficstatus > /dev/null 2>&1; then
40 return 1
41 fi
42 return 0
43 }
44
45 # run the ipsec command
46 libreswan_ipsec() {
47 if [ ${libreswan_sudo} -ne 0 ]; then
48 sudo -n "${IPSEC_CMD}" "${@}"
49 return $?
50 else
51 "${IPSEC_CMD}" "${@}"
52 return $?
53 fi
54 }
55
56 # fetch latest values - fill the arrays
57 libreswan_get() {
58 # do all the work to collect / calculate the values
59 # for each dimension
60
61 # empty the variables
62 libreswan_traffic_in=()
63 libreswan_traffic_out=()
64 libreswan_established_add_time=()
65 libreswan_connected_tunnels=()
66
67 # convert the ipsec command output to a shell script
68 # and source it to get the values
69 # shellcheck disable=SC1090
70 source <(
71 {
72 libreswan_ipsec whack --status
73 libreswan_ipsec whack --trafficstatus
74 } | sed -n \
75 -e "s|[0-9]\+ #\([0-9]\+\): \"\(.*\)\".*IPsec SA established.*newest IPSEC.*|libreswan_connected_tunnels[\"\1\"]=\"\2\"|p" \
76 -e "s|[0-9]\+ #\([0-9]\+\): \"\(.*\)\",\{0,1\}.* add_time=\([0-9]\+\),.* inBytes=\([0-9]\+\),.* outBytes=\([0-9]\+\).*|libreswan_traffic_in[\"\1\"]=\"\4\"; libreswan_traffic_out[\"\1\"]=\"\5\"; libreswan_established_add_time[\"\1\"]=\"\3\";|p"
77 ) || return 1
78
79 # check we got some data
80 [ ${#libreswan_connected_tunnels[@]} -eq 0 ] && return 1
81
82 return 0
83 }
84
85 # _check is called once, to find out if this chart should be enabled or not
86 libreswan_check() {
87 # this should return:
88 # - 0 to enable the chart
89 # - 1 to disable the chart
90
91 require_cmd ipsec || return 1
92
93 # make sure it is libreswan
94 # shellcheck disable=SC2143
95 if [ -z "$(ipsec --version | grep -i libreswan)" ]; then
96 error "ipsec command is not Libreswan. Disabling Libreswan plugin."
97 return 1
98 fi
99
100 if [ ${libreswan_sudo} -ne 0 ] && ! is_able_sudo_ipsec; then
101 error "not enough permissions to execute ipsec with sudo. Disabling Libreswan plugin."
102 return 1
103 fi
104
105 # check that we can collect data
106 libreswan_get || return 1
107
108 return 0
109 }
110
111 # create the charts for an ipsec tunnel
112 libreswan_create_one() {
113 local n="${1}" name
114
115 name="${libreswan_connected_tunnels[${n}]}"
116
117 [ -n "${libreswan_tunnel_charts[${name}]}" ] && return 0
118
119 libreswan_tunnel_charts[${name}]="$(fixid "${name}")"
120
121 cat << EOF
122 CHART libreswan.${libreswan_tunnel_charts[${name}]}_net '${name}_net' "LibreSWAN Tunnel ${name} Traffic" "kilobits/s" "${name}" libreswan.net area $((libreswan_priority)) $libreswan_update_every '' '' 'libreswan'
123 DIMENSION in '' incremental 8 1000
124 DIMENSION out '' incremental -8 1000
125 CHART libreswan.${libreswan_tunnel_charts[${name}]}_uptime '${name}_uptime' "LibreSWAN Tunnel ${name} Uptime" "seconds" "${name}" libreswan.uptime line $((libreswan_priority + 1)) $libreswan_update_every '' '' 'libreswan'
126 DIMENSION uptime '' absolute 1 1
127 EOF
128
129 return 0
130
131 }
132
133 # _create is called once, to create the charts
134 libreswan_create() {
135 local n
136 for n in "${!libreswan_connected_tunnels[@]}"; do
137 libreswan_create_one "${n}"
138 done
139 return 0
140 }
141
142 libreswan_now=$(date +%s)
143
144 # send the values to netdata for an ipsec tunnel
145 libreswan_update_one() {
146 local n="${1}" microseconds="${2}" name id uptime
147
148 name="${libreswan_connected_tunnels[${n}]}"
149 id="${libreswan_tunnel_charts[${name}]}"
150
151 [ -z "${id}" ] && libreswan_create_one "${name}"
152
153 uptime=$((libreswan_now - libreswan_established_add_time[${n}]))
154 [ ${uptime} -lt 0 ] && uptime=0
155
156 # write the result of the work.
157 cat << VALUESEOF
158 BEGIN libreswan.${id}_net ${microseconds}
159 SET in = ${libreswan_traffic_in[${n}]}
160 SET out = ${libreswan_traffic_out[${n}]}
161 END
162 BEGIN libreswan.${id}_uptime ${microseconds}
163 SET uptime = ${uptime}
164 END
165 VALUESEOF
166 }
167
168 # _update is called continuously, to collect the values
169 libreswan_update() {
170 # the first argument to this function is the microseconds since last update
171 # pass this parameter to the BEGIN statement (see below).
172
173 libreswan_get || return 1
174 libreswan_now=$(date +%s)
175
176 local n
177 for n in "${!libreswan_connected_tunnels[@]}"; do
178 libreswan_update_one "${n}" "${@}"
179 done
180
181 return 0
182 }