ip.sh 12 KB

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