config.sh 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #!/bin/sh
  2. # Copyright (C) 2006 OpenWrt.org
  3. # DEBUG="echo"
  4. find_config() {
  5. local iftype device iface ifaces ifn
  6. for ifn in $interfaces; do
  7. config_get iftype "$ifn" type
  8. config_get iface "$ifn" ifname
  9. case "$iftype" in
  10. bridge) config_get ifaces "$ifn" ifnames;;
  11. esac
  12. config_get device "$ifn" device
  13. for ifc in $device $iface $ifaces; do
  14. [ ."$ifc" = ."$1" ] && {
  15. echo "$ifn"
  16. return 0
  17. }
  18. done
  19. done
  20. return 1;
  21. }
  22. scan_interfaces() {
  23. local cfgfile="$1"
  24. local mode iftype iface ifname device
  25. interfaces=
  26. config_cb() {
  27. case "$1" in
  28. interface)
  29. config_set "$2" auto 1
  30. ;;
  31. esac
  32. config_get iftype "$CONFIG_SECTION" TYPE
  33. case "$iftype" in
  34. interface)
  35. config_get proto "$CONFIG_SECTION" proto
  36. append interfaces "$CONFIG_SECTION"
  37. config_get iftype "$CONFIG_SECTION" type
  38. config_get ifname "$CONFIG_SECTION" ifname
  39. config_get device "$CONFIG_SECTION" device
  40. config_set "$CONFIG_SECTION" device "${device:-$ifname}"
  41. case "$iftype" in
  42. bridge)
  43. config_set "$CONFIG_SECTION" ifnames "${device:-$ifname}"
  44. config_set "$CONFIG_SECTION" ifname br-"$CONFIG_SECTION"
  45. ;;
  46. esac
  47. ( type "scan_$proto" ) >/dev/null 2>/dev/null && eval "scan_$proto '$CONFIG_SECTION'"
  48. ;;
  49. esac
  50. }
  51. config_load "${cfgfile:-network}"
  52. }
  53. add_vlan() {
  54. local vif="${1%\.*}"
  55. [ "$1" = "$vif" ] || ifconfig "$1" >/dev/null 2>/dev/null || {
  56. ifconfig "$vif" up 2>/dev/null >/dev/null || add_vlan "$vif"
  57. $DEBUG vconfig add "$vif" "${1##*\.}"
  58. return 0
  59. }
  60. return 1
  61. }
  62. # sort the device list, drop duplicates
  63. sort_list() {
  64. local arg="$*"
  65. (
  66. for item in $arg; do
  67. echo "$item"
  68. done
  69. ) | sort -u
  70. }
  71. # Create the interface, if necessary.
  72. # Return status 0 indicates that the setup_interface() call should continue
  73. # Return status 1 means that everything is set up already.
  74. prepare_interface() {
  75. local iface="$1"
  76. local config="$2"
  77. # if we're called for the bridge interface itself, don't bother trying
  78. # to create any interfaces here. The scripts have already done that, otherwise
  79. # the bridge interface wouldn't exist.
  80. [ "br-$config" = "$iface" -o -e "$iface" ] && return 0;
  81. ifconfig "$iface" 2>/dev/null >/dev/null && {
  82. # make sure the interface is removed from any existing bridge and deconfigured
  83. ifconfig "$iface" 0.0.0.0
  84. unbridge "$iface"
  85. }
  86. # Setup VLAN interfaces
  87. add_vlan "$iface" && return 1
  88. ifconfig "$iface" 2>/dev/null >/dev/null || return 0
  89. # Setup bridging
  90. config_get iftype "$config" type
  91. config_get stp "$config" stp
  92. case "$iftype" in
  93. bridge)
  94. [ -x /usr/sbin/brctl ] && {
  95. ifconfig "br-$config" 2>/dev/null >/dev/null && {
  96. local newdevs=
  97. config_get devices "$config" device
  98. for dev in $(sort_list "$devices" "$iface"); do
  99. append newdevs "$dev"
  100. done
  101. uci_set_state network "$config" device "$newdevs"
  102. $DEBUG brctl addif "br-$config" "$iface"
  103. # Bridge existed already. No further processing necesary
  104. } || {
  105. $DEBUG brctl addbr "br-$config"
  106. $DEBUG brctl setfd "br-$config" 0
  107. $DEBUG ifconfig "br-$config" up
  108. $DEBUG brctl addif "br-$config" "$iface"
  109. $DEBUG brctl stp "br-$config" ${stp:-0}
  110. # Creating the bridge here will have triggered a hotplug event, which will
  111. # result in another setup_interface() call, so we simply stop processing
  112. # the current event at this point.
  113. }
  114. ifconfig "$iface" up 2>/dev/null >/dev/null
  115. return 1
  116. }
  117. ;;
  118. esac
  119. return 0
  120. }
  121. set_interface_ifname() {
  122. local config="$1"
  123. local ifname="$2"
  124. config_get device "$1" device
  125. uci_set_state network "$config" ifname "$ifname"
  126. uci_set_state network "$config" device "$device"
  127. }
  128. setup_interface_none() {
  129. env -i ACTION="ifup" INTERFACE="$2" DEVICE="$1" PROTO=none /sbin/hotplug-call "iface" &
  130. }
  131. setup_interface_static() {
  132. local iface="$1"
  133. local config="$2"
  134. config_get ipaddr "$config" ipaddr
  135. config_get netmask "$config" netmask
  136. config_get ip6addr "$config" ip6addr
  137. [ -z "$ipaddr" -o -z "$netmask" ] && [ -z "$ip6addr" ] && return 1
  138. config_get gateway "$config" gateway
  139. config_get ip6gw "$config" ip6gw
  140. config_get dns "$config" dns
  141. config_get bcast "$config" broadcast
  142. [ -z "$ipaddr" ] || $DEBUG ifconfig "$iface" "$ipaddr" netmask "$netmask" broadcast "${bcast:-+}"
  143. [ -z "$ip6addr" ] || $DEBUG ifconfig "$iface" add "$ip6addr"
  144. [ -z "$gateway" ] || $DEBUG route add default gw "$gateway" dev "$iface"
  145. [ -z "$ip6gw" ] || $DEBUG route -A inet6 add default gw "$ip6gw" dev "$iface"
  146. [ -z "$dns" ] || {
  147. for ns in $dns; do
  148. grep "$ns" /tmp/resolv.conf.auto 2>/dev/null >/dev/null || {
  149. echo "nameserver $ns" >> /tmp/resolv.conf.auto
  150. }
  151. done
  152. }
  153. env -i ACTION="ifup" INTERFACE="$config" DEVICE="$iface" PROTO=static /sbin/hotplug-call "iface" &
  154. }
  155. setup_interface_alias() {
  156. local config="$1"
  157. local parent="$2"
  158. local iface="$3"
  159. config_get cfg "$config" interface
  160. [ "$parent" == "$cfg" ] || return 0
  161. # alias counter
  162. config_get ctr "$parent" alias_count
  163. ctr="$(($ctr + 1))"
  164. config_set "$parent" alias_count "$ctr"
  165. # alias list
  166. config_get list "$parent" aliases
  167. append list "$config"
  168. config_set "$parent" aliases "$list"
  169. set_interface_ifname "$config" "$iface:$ctr"
  170. config_get proto "$config" proto
  171. case "${proto:-static}" in
  172. static)
  173. setup_interface_static "$iface:$ctr" "$config"
  174. ;;
  175. *)
  176. echo "Unsupported type '$proto' for alias config '$config'"
  177. return 1
  178. ;;
  179. esac
  180. }
  181. setup_interface() {
  182. local iface="$1"
  183. local config="$2"
  184. local proto
  185. local macaddr
  186. [ -n "$config" ] || {
  187. config=$(find_config "$iface")
  188. [ "$?" = 0 ] || return 1
  189. }
  190. proto="${3:-$(config_get "$config" proto)}"
  191. prepare_interface "$iface" "$config" || return 0
  192. [ "$iface" = "br-$config" ] && {
  193. # need to bring up the bridge and wait a second for
  194. # it to switch to the 'forwarding' state, otherwise
  195. # it will lose its routes...
  196. ifconfig "$iface" up
  197. sleep 1
  198. }
  199. # Interface settings
  200. config_get mtu "$config" mtu
  201. config_get macaddr "$config" macaddr
  202. grep "$iface:" /proc/net/dev > /dev/null && \
  203. $DEBUG ifconfig "$iface" down && \
  204. $DEBUG ifconfig "$iface" ${macaddr:+hw ether "$macaddr"} ${mtu:+mtu $mtu} up
  205. set_interface_ifname "$config" "$iface"
  206. pidfile="/var/run/$iface.pid"
  207. case "$proto" in
  208. static)
  209. setup_interface_static "$iface" "$config"
  210. ;;
  211. dhcp)
  212. # prevent udhcpc from starting more than once
  213. lock "/var/lock/dhcp-$iface"
  214. pid="$(cat "$pidfile" 2>/dev/null)"
  215. if [ -d "/proc/$pid" ] && grep udhcpc "/proc/${pid}/cmdline" >/dev/null 2>/dev/null; then
  216. lock -u "/var/lock/dhcp-$iface"
  217. else
  218. config_get ipaddr "$config" ipaddr
  219. config_get netmask "$config" netmask
  220. config_get hostname "$config" hostname
  221. config_get proto1 "$config" proto
  222. config_get clientid "$config" clientid
  223. [ -z "$ipaddr" ] || \
  224. $DEBUG ifconfig "$iface" "$ipaddr" ${netmask:+netmask "$netmask"}
  225. # don't stay running in background if dhcp is not the main proto on the interface (e.g. when using pptp)
  226. [ ."$proto1" != ."$proto" ] && dhcpopts="-n -q"
  227. $DEBUG eval udhcpc -t 0 -i "$iface" ${ipaddr:+-r $ipaddr} ${hostname:+-H $hostname} ${clientid:+-c $clientid} -b -p "$pidfile" ${dhcpopts:- -R &}
  228. lock -u "/var/lock/dhcp-$iface"
  229. fi
  230. ;;
  231. none)
  232. setup_interface_none "$iface" "$config"
  233. ;;
  234. *)
  235. if ( eval "type setup_interface_$proto" ) >/dev/null 2>/dev/null; then
  236. eval "setup_interface_$proto '$iface' '$config' '$proto'"
  237. else
  238. echo "Interface type $proto not supported."
  239. return 1
  240. fi
  241. ;;
  242. esac
  243. config_set "$config" aliases ""
  244. config_set "$config" alias_count 0
  245. config_foreach setup_interface_alias alias "$config" "$iface"
  246. config_get aliases "$config" aliases
  247. [ -z "$aliases" ] || uci_set_state network "$config" aliases "$aliases"
  248. }
  249. unbridge() {
  250. local dev="$1"
  251. local brdev
  252. [ -x /usr/sbin/brctl ] || return 0
  253. brctl show | grep "$dev" >/dev/null && {
  254. # interface is still part of a bridge, correct that
  255. for brdev in $(brctl show | awk '$2 ~ /^[0-9].*\./ { print $1 }'); do
  256. brctl delif "$brdev" "$dev" 2>/dev/null >/dev/null
  257. done
  258. }
  259. }