ip.sh 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #!/bin/bash
  2. #===========================================================================#
  3. # #
  4. # Hestia Control Panel - IP/Network Function Library #
  5. # #
  6. #===========================================================================#
  7. # === Global definitions ===
  8. REGEX_IPV4="^((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])$"
  9. # === IPV4 specific functions ===
  10. # Check ip ownership
  11. is_ip_owner() {
  12. # ip address (ipv4/ipv6) as first parameter, otherwise $ip (ipv4)
  13. ip_for_test="${1-$ip}"
  14. owner=$(grep 'OWNER=' $HESTIA/data/ips/$ip_for_test | cut -f 2 -d \')
  15. if [ "$owner" != "$user" ]; then
  16. check_result "$E_FORBIDEN" "$ip_for_test is not owned by $user"
  17. fi
  18. }
  19. # Check if ip address is free
  20. is_ip_free() {
  21. ip_for_test="${1-$ip}" # ip address (ipv4/ipv6) as first parameter, otherwise $ip (ipv4)
  22. if [ -e "$HESTIA/data/ips/$ip_for_test" ]; then
  23. check_result "$E_EXISTS" "$ip_for_test is already exists"
  24. fi
  25. }
  26. # Check ip address specific value
  27. is_ip_key_empty() {
  28. key="$1"
  29. ip_for_test="${2-$ip}" # ip address (ipv4/ipv6) as second parameter, otherwise $ip (ipv4)
  30. if [ -n "$ip_for_test" ]; then
  31. string=$(cat $HESTIA/data/ips/$ip_for_test)
  32. eval $string
  33. eval value="$key"
  34. if [ -n "$value" ] && [ "$value" != '0' ]; then
  35. key="$(echo $key | sed -e "s/\$U_//")"
  36. check_result "$E_EXISTS" "IP is in use / $key = $value"
  37. fi
  38. else
  39. check_result 1 "is_ip_key_empty(): IP address is empty!"
  40. fi
  41. }
  42. is_ip_rdns_valid() {
  43. local ip="$1"
  44. local network_ip=$(echo $ip | cut -d"." -f1-3)
  45. local awk_ip=$(echo $network_ip | sed 's|\.|/\&\&/|g')
  46. local rev_awk_ip=$(echo $awk_ip | rev)
  47. if [ -z "$rdns" ]; then
  48. local rdns=$(dig +short -x "$ip" | head -n 1 | sed 's/.$//') || unset rdns
  49. fi
  50. if [ -n "$rdns" ] && [ ! $(echo $rdns | awk "/$awk_ip/ || /$rev_awk_ip/") ]; then
  51. echo $rdns
  52. return 0 # True
  53. fi
  54. return 1 # False
  55. }
  56. # Update ip address value
  57. update_ip_value() {
  58. key="$1"
  59. value="$2"
  60. ip_for_update="${3-$ip}" # ip address (ipv4/ipv6) as third parameter, otherwise $ip (ipv4)
  61. if [ -n "$ip_for_update" ]; then
  62. conf="$HESTIA/data/ips/$ip_for_update"
  63. str=$(cat $conf)
  64. eval $str
  65. c_key=$(echo "${key//$/}")
  66. eval old="${key}"
  67. old=$(echo "$old" | sed -e 's/\\/\\\\/g' -e 's/&/\\&/g' -e 's/\//\\\//g')
  68. new=$(echo "$value" | sed -e 's/\\/\\\\/g' -e 's/&/\\&/g' -e 's/\//\\\//g')
  69. sed -i "$str_number s/$c_key='${old//\*/\\*}'/$c_key='${new//\*/\\*}'/g" \
  70. $conf
  71. else
  72. check_result 1 "is_ip_key_empty(): IP address is empty!"
  73. fi
  74. }
  75. # New method that is improved on a later date we need to check if we can improve it for other locations
  76. update_ip_value_new() {
  77. key="$1"
  78. value="$2"
  79. conf="$HESTIA/data/ips/$ip"
  80. check_ckey=$(grep "^$key='" $conf)
  81. if [ -z "$check_ckey" ]; then
  82. echo "$key='$value'" >> $conf
  83. else
  84. sed -i "s|^$key=.*|$key='$value'|g" $conf
  85. fi
  86. }
  87. # Get ip name
  88. get_ip_alias() {
  89. # ip address (ipv4/ipv6) as second parameter, otherwise $local_ip (ipv4)
  90. ip_for_test="${2-$local_ip}"
  91. if [ -n "$ip_for_test" ]; then
  92. ip_name=$(grep "NAME=" $HESTIA/data/ips/${ip_for_test} | cut -f 2 -d \')
  93. if [ -n "$ip_name" ]; then
  94. echo "${1//./-}.$ip_name"
  95. fi
  96. else
  97. ip_name=""
  98. fi
  99. }
  100. # Increase ip value
  101. increase_ip_value() {
  102. sip=${1-ip}
  103. USER=${2-$user}
  104. web_key='U_WEB_DOMAINS'
  105. usr_key='U_SYS_USERS'
  106. current_web=$(grep "$web_key=" $HESTIA/data/ips/$sip | cut -f 2 -d \')
  107. current_usr=$(grep "$usr_key=" $HESTIA/data/ips/$sip | cut -f 2 -d \')
  108. if [ -z "$current_web" ]; then
  109. echo "Error: Parsing error"
  110. log_event "$E_PARSING" "$ARGUMENTS"
  111. exit "$E_PARSING"
  112. fi
  113. if (($current_web <= 0)); then
  114. new_web=1
  115. else
  116. new_web=$((current_web + 1))
  117. fi
  118. if [ -z "$current_usr" ]; then
  119. new_usr="$USER"
  120. else
  121. check_usr=$(echo -e "${current_usr//,/\\n}" | grep -x "$USER")
  122. if [ -z "$check_usr" ]; then
  123. new_usr="$current_usr,$USER"
  124. else
  125. new_usr="$current_usr"
  126. fi
  127. fi
  128. # Make sure users list does not contain duplicates
  129. new_usr=$(echo "$new_usr" \
  130. | sed "s/,/\n/g" \
  131. | sort -u \
  132. | sed ':a;N;$!ba;s/\n/,/g')
  133. sed -i "s/$web_key='$current_web'/$web_key='$new_web'/g" \
  134. $HESTIA/data/ips/$sip
  135. sed -i "s/$usr_key='$current_usr'/$usr_key='$new_usr'/g" \
  136. $HESTIA/data/ips/$sip
  137. }
  138. # Decrease ip value
  139. decrease_ip_value() {
  140. sip=${1-ip}
  141. local user=${2-$user}
  142. web_key='U_WEB_DOMAINS'
  143. usr_key='U_SYS_USERS'
  144. current_web=$(grep "$web_key=" $HESTIA/data/ips/$sip | cut -f 2 -d \')
  145. current_usr=$(grep "$usr_key=" $HESTIA/data/ips/$sip | cut -f 2 -d \')
  146. if [ -z "$current_web" ]; then
  147. check_result $E_PARSING "Parsing error"
  148. fi
  149. if (($current_web <= 0)); then
  150. new_web=0
  151. else
  152. new_web=$((current_web - 1))
  153. fi
  154. check_ip=$(grep $sip $USER_DATA/web.conf | wc -l)
  155. if [[ $check_ip = 0 ]]; then
  156. new_usr=$(echo "$current_usr" \
  157. | sed "s/,/\n/g" \
  158. | sed "s/^$user$//g" \
  159. | sed "/^$/d" \
  160. | sort -u \
  161. | sed ':a;N;$!ba;s/\n/,/g')
  162. else
  163. new_usr="$current_usr"
  164. fi
  165. sed -i "s/$web_key='$current_web'/$web_key='$new_web'/g" \
  166. $HESTIA/data/ips/$sip
  167. sed -i "s/$usr_key='$current_usr'/$usr_key='$new_usr'/g" \
  168. $HESTIA/data/ips/$sip
  169. }
  170. # Get ip address value
  171. get_ip_value() {
  172. key="$1"
  173. string=$(cat $HESTIA/data/ips/$ip)
  174. eval $string
  175. eval value="$key"
  176. echo "$value"
  177. }
  178. # Get real ip address
  179. get_real_ip() {
  180. if [ -e "$HESTIA/data/ips/$1" ]; then
  181. echo "$1"
  182. else
  183. nat=$(grep -H "^NAT='$1'" $HESTIA/data/ips/* | head -n1)
  184. if [ -n "$nat" ]; then
  185. echo "$nat" | cut -f 1 -d : | cut -f 7 -d /
  186. fi
  187. fi
  188. }
  189. # Convert CIDR to netmask
  190. convert_cidr() {
  191. # CIDR can be defined as /32 (with leading /) or as 32 (number without leading /)
  192. # please check the value range of cidr before converting!
  193. set ${1#/} # allow to use cidr format with leading /
  194. set -- $((5 - ($1 / 8))) 255 255 255 255 \
  195. $(((255 << (8 - ($1 % 8))) & 255)) 0 0 0
  196. if [[ $1 -gt 1 ]]; then
  197. shift $1
  198. else
  199. shift
  200. fi
  201. echo ${1-0}.${2-0}.${3-0}.${4-0}
  202. }
  203. # Convert netmask to CIDR
  204. convert_netmask() {
  205. nbits=0
  206. IFS=.
  207. for dec in $1; do
  208. case $dec in
  209. 255) let nbits+=8 ;;
  210. 254) let nbits+=7 ;;
  211. 252) let nbits+=6 ;;
  212. 248) let nbits+=5 ;;
  213. 240) let nbits+=4 ;;
  214. 224) let nbits+=3 ;;
  215. 192) let nbits+=2 ;;
  216. 128) let nbits+=1 ;;
  217. 0) ;;
  218. esac
  219. done
  220. echo "/$nbits"
  221. }
  222. # Calculate broadcast address
  223. get_broadcast() {
  224. OLD_IFS=$IFS
  225. IFS=.
  226. typeset -a I=($1)
  227. typeset -a N=($2)
  228. IFS=$OLD_IFS
  229. echo "$((${I[0]} | (255 ^ ${N[0]}))).$((${I[1]} | (255 ^ ${N[1]}))).$((${I[2]} | (255 ^ ${N[2]}))).$((${I[3]} | (255 ^ ${N[3]})))"
  230. }
  231. # Get user ips
  232. get_user_ips() {
  233. dedicated=$(grep -H "OWNER='$user'" $HESTIA/data/ips/*)
  234. dedicated=$(echo "$dedicated" | cut -f 1 -d : | sed 's=.*/==' | grep -E ${REGEX_IPV4})
  235. shared=$(grep -H -A1 "OWNER='admin'" $HESTIA/data/ips/* | grep shared)
  236. shared=$(echo "$shared" | cut -f 1 -d : | sed 's=.*/==' | cut -f 1 -d \- | grep -E ${REGEX_IPV4})
  237. for dedicated_ip in $dedicated; do
  238. shared=$(echo "$shared" | grep -v $dedicated_ip)
  239. done
  240. echo -e "$dedicated\n$shared" | sed "/^$/d"
  241. }
  242. # Get user ip
  243. get_user_ip() {
  244. ip=$(get_user_ips | head -n1)
  245. if [ -z "$ip" ]; then
  246. check_result $E_NOTEXIST "no IP is available"
  247. fi
  248. local_ip=$ip
  249. nat=$(grep "^NAT" $HESTIA/data/ips/$ip | cut -f 2 -d \')
  250. if [ -n "$nat" ]; then
  251. ip=$nat
  252. fi
  253. }
  254. # Validate ip address
  255. is_ip_valid() {
  256. local_ip="$1"
  257. if [ ! -e "$HESTIA/data/ips/$1" ]; then
  258. nat=$(grep -H "^NAT='$1'" $HESTIA/data/ips/*)
  259. if [ -z "$nat" ]; then
  260. check_result "$E_NOTEXIST" "IP $1 doesn't exist"
  261. else
  262. nat=$(echo "$nat" | cut -f1 -d: | cut -f7 -d/)
  263. local_ip=$nat
  264. fi
  265. fi
  266. if [ -n "$2" ]; then
  267. if [ -z "$nat" ]; then
  268. ip_data=$(cat $HESTIA/data/ips/$1)
  269. else
  270. ip_data=$(cat $HESTIA/data/ips/$nat)
  271. fi
  272. ip_owner=$(echo "$ip_data" | grep OWNER= | cut -f2 -d \')
  273. ip_status=$(echo "$ip_data" | grep STATUS= | cut -f2 -d \')
  274. if [ "$ip_owner" != "$user" ] && [ "$ip_status" = 'dedicated' ]; then
  275. check_result "$E_FORBIDEN" "$user user can't use IP $1"
  276. fi
  277. get_user_owner
  278. if [ "$ip_owner" != "$user" ] && [ "$ip_owner" != "$owner" ]; then
  279. check_result "$E_FORBIDEN" "$user user can't use IP $1"
  280. fi
  281. fi
  282. }
  283. # === IPV6 specific functions ===
  284. # Get full interface name
  285. get_ipv6_iface() {
  286. i=$(/sbin/ip addr | grep -w $interface \
  287. | awk '{print $NF}' | tail -n 1 | cut -f 2 -d :)
  288. if [ "$i" = "$interface" ]; then
  289. n=0
  290. else
  291. n=$((i + 1))
  292. fi
  293. echo "$interface:$n"
  294. }
  295. # Get user ip6s
  296. get_user_ip6s() {
  297. dedicated=$(grep -H -A10 "OWNER='$user'" $HESTIA/data/ips/* | grep "VERSION='6'")
  298. dedicated=$(echo "$dedicated" | cut -f 1 -d '-' | sed 's=.*/==')
  299. shared=$(grep -H -A10 "OWNER='admin'" $HESTIA/data/ips/* | grep -A10 shared | grep "VERSION='6'")
  300. shared=$(echo "$shared" | cut -f 1 -d '-' | sed 's=.*/==' | cut -f 1 -d \-)
  301. for dedicated_ip in $dedicated; do
  302. shared=$(echo "$shared" | grep -v $dedicated_ip)
  303. done
  304. echo -e "$dedicated\n$shared" | sed "/^$/d"
  305. }
  306. # Get user ipv6
  307. get_user_ipv6() {
  308. ipv6=$(get_user_ip6s | head -n1)
  309. local_ipv6="$ipv6"
  310. }
  311. # Validate ipv6 address
  312. is_ipv6_valid() {
  313. local_ipv6="$1"
  314. if [ -z "$local_ipv6" ]; then
  315. check_result $E_NOTEXIST "IPV6 address is empty"
  316. fi
  317. if [ ! -e "$HESTIA/data/ips/$1" ]; then
  318. check_result $E_NOTEXIST "IPV6 $1 doesn't exist"
  319. fi
  320. if [ ! -z $2 ]; then
  321. ip_data=$(cat $HESTIA/data/ips/$1)
  322. ip_owner=$(echo "$ip_data" | grep OWNER= | cut -f2 -d \')
  323. ip_status=$(echo "$ip_data" | grep STATUS= | cut -f2 -d \')
  324. if [ "$ip_owner" != "$user" ] && [ "$ip_status" = 'dedicated' ]; then
  325. check_result $E_FORBIDEN "$user user can't use IPV6 $1"
  326. fi
  327. get_user_owner
  328. if [ "$ip_owner" != "$user" ] && [ "$ip_owner" != "$owner" ]; then
  329. check_result $E_FORBIDEN "$user user can't use IPV6 $1"
  330. fi
  331. fi
  332. }