network.sh 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. . /usr/share/libubox/jshn.sh
  2. __network_set_cache()
  3. {
  4. if [ -n "$3" ]; then
  5. eval "export -- __NETWORK_CV_$1='$3'"
  6. __NETWORK_CACHE="${__NETWORK_CACHE:+$__NETWORK_CACHE }__NETWORK_CV_$1"
  7. elif json_get_var "__NETWORK_CV_$1" "$2"; then
  8. __NETWORK_CACHE="${__NETWORK_CACHE:+$__NETWORK_CACHE }__NETWORK_CV_$1"
  9. fi
  10. }
  11. __network_export()
  12. {
  13. local __v="__NETWORK_CV_$2"
  14. eval "export -- \"$1=\${$__v:+\${$__v$4}$3}\"; [ -n \"\${$__v+x}\" ]"
  15. }
  16. __network_parse_ifstatus()
  17. {
  18. local __iface="$1"
  19. local __key="${__iface}"
  20. local __tmp
  21. local __idx
  22. local __list
  23. local __old_ns
  24. case "$__iface" in
  25. *[^a-zA-Z0-9_]*) return 1 ;;
  26. esac
  27. __network_export __tmp "${__key}__parsed" && return 0
  28. __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
  29. [ -n "$__tmp" ] || return 1
  30. json_set_namespace "network" __old_ns
  31. json_load "$__tmp"
  32. __network_set_cache "${__key}__parsed" "" "1"
  33. for __tmp in "" "_inactive"; do
  34. __key="${__key}${__tmp}"
  35. # parse addresses
  36. local __family
  37. for __family in 4 6; do
  38. __list=""
  39. if json_is_a "ipv${__family}_address" array; then
  40. json_select "ipv${__family}_address"
  41. __idx=1
  42. while json_is_a "$__idx" object; do
  43. json_select "$((__idx++))"
  44. json_get_var __tmp "address" && __list="${__list:+$__list }$__tmp"
  45. json_get_var __tmp "mask" && __list="${__list:+$__list/}$__tmp"
  46. json_select ".."
  47. done
  48. json_select ".."
  49. fi
  50. if json_is_a "ipv${__family}_prefix_assignment" array; then
  51. json_select "ipv${__family}_prefix_assignment"
  52. __idx=1
  53. while json_is_a "$__idx" object; do
  54. json_select "$((__idx++))"
  55. json_get_var __tmp "address" && __list="${__list:+$__list }${__tmp}1"
  56. json_get_var __tmp "mask" && __list="${__list:+$__list/}$__tmp"
  57. json_select ".."
  58. done
  59. json_select ".."
  60. fi
  61. if [ -n "$__list" ]; then
  62. __network_set_cache "${__key}_address${__family}" "" "$__list"
  63. fi
  64. done
  65. # parse prefixes
  66. if json_is_a "ipv6_prefix" array; then
  67. json_select "ipv6_prefix"
  68. __idx=1
  69. __list=""
  70. while json_is_a "$__idx" object; do
  71. json_select "$((__idx++))"
  72. json_get_var __tmp "address" && __list="${__list:+$__list }$__tmp"
  73. json_get_var __tmp "mask" && __list="${__list:+$__list/}$__tmp"
  74. json_select ".."
  75. done
  76. json_select ".."
  77. if [ -n "$__list" ]; then
  78. __network_set_cache "${__key}_prefix6" "" "$__list"
  79. fi
  80. fi
  81. # parse routes
  82. if json_is_a route array; then
  83. json_select "route"
  84. local __idx=1
  85. while json_is_a "$__idx" object; do
  86. json_select "$((__idx++))"
  87. json_get_var __tmp table
  88. if [ -z "$__tmp" ]; then
  89. json_get_var __tmp target
  90. case "${__tmp}" in
  91. 0.0.0.0)
  92. __network_set_cache "${__key}_gateway4" nexthop
  93. ;;
  94. ::)
  95. __network_set_cache "${__key}_gateway6" nexthop
  96. ;;
  97. esac
  98. fi
  99. json_select ".."
  100. done
  101. json_select ".."
  102. fi
  103. # parse dns info
  104. local __field
  105. for __field in "dns_server" "dns_search"; do
  106. if json_is_a "$__field" array; then
  107. json_select "$__field"
  108. __idx=1
  109. __list=""
  110. while json_is_a "$__idx" string; do
  111. json_get_var __tmp "$((__idx++))"
  112. __list="${__list:+$__list }$__tmp"
  113. done
  114. json_select ".."
  115. if [ -n "$__list" ]; then
  116. __network_set_cache "${__key}_${__field}" "" "$__list"
  117. fi
  118. fi
  119. done
  120. # parse up state, proto, device and physdev
  121. for __field in "up" "proto" "l3_device" "device"; do
  122. if json_get_type __tmp "$__field"; then
  123. __network_set_cache "${__key}_${__field}" "$__field"
  124. fi
  125. done
  126. # descend into inactive table
  127. json_is_a "inactive" object && json_select "inactive"
  128. done
  129. json_cleanup
  130. json_set_namespace "$__old_ns"
  131. return 0
  132. }
  133. __network_ipaddr()
  134. {
  135. local __var="$1"
  136. local __iface="$2"
  137. local __field="$3"
  138. local __subst="$4"
  139. local __list="$5"
  140. local __tmp=""
  141. __network_parse_ifstatus "$__iface" || return 1
  142. if [ $__list = 1 ] && [ -n "$__subst" ]; then
  143. __network_export "__list" "${__iface}_${__field}"
  144. for __list in $__list; do
  145. eval "__tmp=\"${__tmp:+$__tmp }\${__list$__subst}\""
  146. done
  147. export -- "$__var=$__tmp"; [ -n "$__tmp" ]
  148. return $?
  149. fi
  150. __network_export "$__var" "${__iface}_${__field}" "" "$__subst"
  151. return $?
  152. }
  153. # determine first IPv4 address of given logical interface
  154. # 1: destination variable
  155. # 2: interface
  156. network_get_ipaddr() { __network_ipaddr "$1" "$2" "address4" "%%/*" 0; }
  157. # determine first IPv6 address of given logical interface
  158. # 1: destination variable
  159. # 2: interface
  160. network_get_ipaddr6() { __network_ipaddr "$1" "$2" "address6" "%%/*" 0; }
  161. # determine first IPv4 subnet of given logical interface
  162. # 1: destination variable
  163. # 2: interface
  164. network_get_subnet() { __network_ipaddr "$1" "$2" "address4" "%% *" 0; }
  165. # determine first IPv6 subnet of given logical interface
  166. # 1: destination variable
  167. # 2: interface
  168. network_get_subnet6() { __network_ipaddr "$1" "$2" "address6" "%% *" 0; }
  169. # determine first IPv6 prefix of given logical interface
  170. # 1: destination variable
  171. # 2: interface
  172. network_get_prefix6() { __network_ipaddr "$1" "$2" "prefix6" "%% *" 0; }
  173. # determine all IPv4 addresses of given logical interface
  174. # 1: destination variable
  175. # 2: interface
  176. network_get_ipaddrs() { __network_ipaddr "$1" "$2" "address4" "%%/*" 1; }
  177. # determine all IPv6 addresses of given logical interface
  178. # 1: destination variable
  179. # 2: interface
  180. network_get_ipaddrs6() { __network_ipaddr "$1" "$2" "address6" "%%/*" 1; }
  181. # determine all IPv4 subnets of given logical interface
  182. # 1: destination variable
  183. # 2: interface
  184. network_get_subnets() { __network_ipaddr "$1" "$2" "address4" "" 1; }
  185. # determine all IPv6 subnets of given logical interface
  186. # 1: destination variable
  187. # 2: interface
  188. network_get_subnets6() { __network_ipaddr "$1" "$2" "address6" "" 1; }
  189. # determine all IPv6 prefixes of given logical interface
  190. # 1: destination variable
  191. # 2: interface
  192. network_get_prefixes6() { __network_ipaddr "$1" "$2" "prefix6" "" 1; }
  193. __network_gateway()
  194. {
  195. local __var="$1"
  196. local __iface="$2"
  197. local __family="$3"
  198. local __inactive="$4"
  199. __network_parse_ifstatus "$__iface" || return 1
  200. if [ "$__inactive" = 1 -o "$__inactive" = "true" ]; then
  201. __network_export "$__var" "${__iface}_inactive_gateway${__family}" && \
  202. return 0
  203. fi
  204. __network_export "$__var" "${__iface}_gateway${__family}"
  205. return $?
  206. }
  207. # determine IPv4 gateway of given logical interface
  208. # 1: destination variable
  209. # 2: interface
  210. # 3: consider inactive gateway if "true" (optional)
  211. network_get_gateway() { __network_gateway "$1" "$2" 4 "${3:-0}"; }
  212. # determine IPv6 gateway of given logical interface
  213. # 1: destination variable
  214. # 2: interface
  215. # 3: consider inactive gateway if "true" (optional)
  216. network_get_gateway6() { __network_gateway "$1" "$2" 6 "${3:-0}"; }
  217. __network_dns() {
  218. local __var="$1"
  219. local __iface="$2"
  220. local __field="$3"
  221. local __inactive="$4"
  222. __network_parse_ifstatus "$__iface" || return 1
  223. if [ "$__inactive" = 1 -o "$__inactive" = "true" ]; then
  224. __network_export "$__var" "${__iface}_inactive_${__field}" && \
  225. return 0
  226. fi
  227. __network_export "$__var" "${__iface}_${__field}"
  228. return $?
  229. }
  230. # determine the DNS servers of the given logical interface
  231. # 1: destination variable
  232. # 2: interface
  233. # 3: consider inactive servers if "true" (optional)
  234. network_get_dnsserver() { __network_dns "$1" "$2" dns_server "${3:-0}"; }
  235. # determine the domains of the given logical interface
  236. # 1: destination variable
  237. # 2: interface
  238. # 3: consider inactive domains if "true" (optional)
  239. network_get_dnssearch() { __network_dns "$1" "$2" dns_search "${3:-0}"; }
  240. __network_wan()
  241. {
  242. local __var="$1"
  243. local __family="$2"
  244. local __inactive="$3"
  245. local __iface
  246. for __iface in $(ubus list | sed -ne 's/^network\.interface\.//p'); do
  247. if [ "$__iface" != loopback ]; then
  248. if __network_gateway "$__var" "$__iface" "$__family" "$__inactive"; then
  249. eval "export -- \"$__var=$__iface\""
  250. return 0
  251. fi
  252. fi
  253. done
  254. eval "export -- \"$__var=\""
  255. return 1
  256. }
  257. # find the logical interface which holds the current IPv4 default route
  258. # 1: destination variable
  259. # 2: consider inactive default routes if "true" (optional)
  260. network_find_wan() { __network_wan "$1" 4 "${2:-0}"; }
  261. # find the logical interface which holds the current IPv6 default route
  262. # 1: destination variable
  263. # 2: consider inactive dafault routes if "true" (optional)
  264. network_find_wan6() { __network_wan "$1" 6 "${2:-0}"; }
  265. __network_device()
  266. {
  267. local __var="$1"
  268. local __iface="$2"
  269. local __field="$3"
  270. __network_parse_ifstatus "$__iface" || return 1
  271. __network_export "$__var" "${__iface}_${__field}"
  272. return $?
  273. }
  274. # test whether the given logical interface is running
  275. # 1: interface
  276. network_is_up()
  277. {
  278. local __up
  279. __network_device __up "$1" up && [ $__up -eq 1 ]
  280. }
  281. # determine the protocol of the given logical interface
  282. # 1: destination variable
  283. # 2: interface
  284. network_get_protocol() { __network_device "$1" "$2" proto; }
  285. # determine the layer 3 linux network device of the given logical interface
  286. # 1: destination variable
  287. # 2: interface
  288. network_get_device() { __network_device "$1" "$2" l3_device; }
  289. # determine the layer 2 linux network device of the given logical interface
  290. # 1: destination variable
  291. # 2: interface
  292. network_get_physdev() { __network_device "$1" "$2" device; }
  293. __network_defer()
  294. {
  295. local __device="$1"
  296. local __defer="$2"
  297. json_init
  298. json_add_string name "$__device"
  299. json_add_boolean defer "$__defer"
  300. ubus call network.device set_state "$(json_dump)" 2>/dev/null
  301. }
  302. # defer netifd actions on the given linux network device
  303. # 1: device name
  304. network_defer_device() { __network_defer "$1" 1; }
  305. # continue netifd actions on the given linux network device
  306. # 1: device name
  307. network_ready_device() { __network_defer "$1" 0; }
  308. # flush the internal value cache to force re-reading values from ubus
  309. network_flush_cache()
  310. {
  311. local __tmp
  312. for __tmp in $__NETWORK_CACHE __NETWORK_CACHE; do
  313. unset "$__tmp"
  314. done
  315. }