libreswan.chart.sh 5.3 KB

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