You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

341 lines
7.5 KiB

  1. #!/bin/sh /etc/rc.common
  2. START=19
  3. USE_PROCD=1
  4. PROG=/usr/sbin/dhcpd
  5. lease_file=/tmp/dhcpd.leases
  6. config_file=/tmp/run/dhcpd.conf
  7. time2seconds() {
  8. local timestring=$1
  9. local multiplier number suffix
  10. suffix="${timestring//[0-9 ]}"
  11. number="${timestring%%$suffix}"
  12. [ "$number$suffix" != "$timestring" ] && return 1
  13. case "$suffix" in
  14. "" | s)
  15. multiplier=1
  16. ;;
  17. m)
  18. multiplier=60
  19. ;;
  20. h)
  21. multiplier=3600
  22. ;;
  23. d)
  24. multiplier=86400
  25. ;;
  26. w)
  27. multiplier=604800
  28. ;;
  29. *)
  30. return 1
  31. ;;
  32. esac
  33. echo $(( number * multiplier ))
  34. }
  35. # duplicated from dnsmasq init script
  36. hex_to_hostid() {
  37. local var="$1"
  38. local hex="${2#0x}" # strip optional "0x" prefix
  39. if [ -n "${hex//[0-9a-fA-F]/}" ]; then
  40. # is invalid hex literal
  41. return 1
  42. fi
  43. # convert into host id
  44. export "$var=$(
  45. printf "%0x:%0x" \
  46. $(((0x$hex >> 16) % 65536)) \
  47. $(( 0x$hex % 65536))
  48. )"
  49. return 0
  50. }
  51. static_host_add() {
  52. local cfg="$1"
  53. local broadcast hostid macn macs mac name ip leasetime
  54. config_get macs "$cfg" "mac"
  55. [ -n "$macs" ] || return 0
  56. config_get name "$cfg" "name"
  57. [ -n "$name" ] || return 0
  58. config_get ip "$cfg" "ip"
  59. [ -n "$ip" ] || return 0
  60. config_get_bool broadcast "$cfg" "broadcast" 0
  61. config_get dns "$cfg" "dns"
  62. config_get gateway "$cfg" "gateway"
  63. config_get leasetime "$cfg" "leasetime"
  64. if [ -n "$leasetime" ] ; then
  65. leasetime="$(time2seconds "$leasetime")"
  66. [ "$?" -ne 0 ] && return 1
  67. fi
  68. config_get hostid "$cfg" "hostid"
  69. if [ -n "$hostid" ] ; then
  70. hex_to_hostid hostid "$hostid" || return 1
  71. fi
  72. macn=0
  73. for mac in $macs; do
  74. macn=$(( macn + 1 ))
  75. done
  76. for mac in $macs; do
  77. local secname="$name"
  78. if [ $macn -gt 1 ] ; then
  79. secname="${name}-${mac//:}"
  80. fi
  81. echo "host $secname {"
  82. echo " hardware ethernet $mac;"
  83. echo " fixed-address $ip;"
  84. echo " option host-name \"$name\";"
  85. if [ "$broadcast" -eq 1 ] ; then
  86. echo " always-broadcast true;"
  87. fi
  88. if [ -n "$leasetime" ] ; then
  89. echo " default-lease-time $leasetime;"
  90. echo " max-lease-time $leasetime;"
  91. fi
  92. if [ -n "$hostid" ] ; then
  93. echo " option dhcp-client-identifier $hostid;"
  94. fi
  95. if [ -n "$dns" ] ; then
  96. echo " option domain-name-servers $dns;"
  97. fi
  98. if [ -n "$gateway" ] ; then
  99. echo " option routers $gateway;"
  100. fi
  101. config_list_foreach "$cfg" "dhcp_option" append_dhcp_options
  102. echo "}"
  103. done
  104. }
  105. static_hosts() {
  106. config_foreach static_host_add host "$@"
  107. }
  108. typeof() {
  109. echo "$1" | awk '
  110. /^\d+\.\d+\.\d+\.\d+$/ { print "ip\n"; next; }
  111. /^(true|false)$/ { print "bool\n"; next; }
  112. /^\d+$/ { print "integer\n"; next; }
  113. /^"[^"]*"$/ { print "string\n"; next; }
  114. { print "other\n"; next; }
  115. '
  116. }
  117. append_dhcp_options() {
  118. local tuple="$1"
  119. # strip redundant "option:" prefix
  120. tuple="${tuple#option:}"
  121. local tag="${tuple%%,*}"
  122. local values="${tuple#$tag,}"
  123. local formatted value
  124. local IFS=$', \n'
  125. for value in $values; do
  126. # detect type of $value and quote if necessary
  127. case $(typeof "$value") in
  128. ip|bool|integer|string)
  129. ;;
  130. other)
  131. value="\"$value\""
  132. ;;
  133. esac
  134. formatted="$formatted${formatted:+, }$value"
  135. done
  136. echo " option $tag $formatted;"
  137. }
  138. gen_dhcp_subnet() {
  139. local cfg="$1"
  140. echo "subnet $NETWORK netmask $NETMASK {"
  141. echo " range $START $END;"
  142. echo " option subnet-mask $netmask;"
  143. if [ "$BROADCAST" != "0.0.0.0" ] ; then
  144. echo " option broadcast-address $BROADCAST;"
  145. fi
  146. if [ "$dynamicdhcp" -eq 0 ] ; then
  147. if [ "$authoritative" -eq 1 ] ; then
  148. echo " deny unknown-clients;"
  149. else
  150. echo " ignore unknown-clients;"
  151. fi
  152. fi
  153. if [ -n "$leasetime" ] ; then
  154. echo " default-lease-time $leasetime;"
  155. echo " max-lease-time $leasetime;"
  156. fi
  157. echo " option routers $gateway;"
  158. echo " option domain-name-servers $DNS;"
  159. config_list_foreach "$cfg" "dhcp_option" append_dhcp_options
  160. echo "}"
  161. }
  162. dhcpd_add() {
  163. local cfg="$1"
  164. local dhcp6range="::"
  165. local dynamicdhcp end gateway ifname ignore leasetime limit net netmask
  166. local proto networkid start subnet
  167. local IP NETMASK BROADCAST NETWORK PREFIX DNS START END
  168. config_get_bool ignore "$cfg" "ignore" 0
  169. [ "$ignore" = "0" ] || return 0
  170. config_get net "$cfg" "interface"
  171. [ -n "$net" ] || return 0
  172. config_get start "$cfg" "start"
  173. [ -n "$start" ] || return 0
  174. config_get limit "$cfg" "limit"
  175. [ -n "$limit" ] || return 0
  176. network_get_subnet subnet "$net" || return 0
  177. network_get_device ifname "$net" || return 0
  178. network_get_protocol proto "$net" || return 0
  179. [ static = "$proto" ] || return 0
  180. config_get_bool dynamicdhcp "$cfg" "dynamicdhcp" 1
  181. dhcp_ifs="$dhcp_ifs $ifname"
  182. eval "$(ipcalc.sh $subnet $start $limit)"
  183. config_get netmask "$cfg" "netmask" "$NETMASK"
  184. config_get leasetime "$cfg" "leasetime"
  185. if [ -n "$leasetime" ] ; then
  186. leasetime="$(time2seconds "$leasetime")"
  187. [ "$?" -ne 0 ] && return 1
  188. fi
  189. if network_get_dnsserver dnsserver "$net" ; then
  190. for dnsserv in $dnsserver ; do
  191. DNS="$DNS${DNS:+, }$dnsserv"
  192. done
  193. else
  194. DNS="$IP"
  195. fi
  196. if ! network_get_gateway gateway "$net" ; then
  197. gateway="$IP"
  198. fi
  199. gen_dhcp_subnet "$cfg" >> $config_file
  200. }
  201. general_config() {
  202. local always_broadcast boot_unknown_clients log_facility
  203. local default_lease_time max_lease_time
  204. config_get_bool always_broadcast "isc_dhcpd" "always_broadcast" 0
  205. config_get_bool authoritative "isc_dhcpd" "authoritative" 1
  206. config_get_bool boot_unknown_clients "isc_dhcpd" "boot_unknown_clients" 1
  207. config_get default_lease_time "isc_dhcpd" "default_lease_time" 3600
  208. config_get max_lease_time "isc_dhcpd" "max_lease_time" 86400
  209. config_get log_facility "isc_dhcpd" "log_facility"
  210. config_get domain "isc_dhcpd" "domain"
  211. [ $always_broadcast -eq 1 ] && echo "always-broadcast true;"
  212. [ $authoritative -eq 1 ] && echo "authoritative;"
  213. [ $boot_unknown_clients -eq 0 ] && echo "boot-unknown-clients false;"
  214. default_lease_time="$(time2seconds "$default_lease_time")"
  215. [ "$?" -ne 0 ] && return 1
  216. max_lease_time="$(time2seconds "$max_lease_time")"
  217. [ "$?" -ne 0 ] && return 1
  218. if [ -n "$log_facility" ] ; then
  219. echo "log-facility $log_facility;"
  220. fi
  221. echo "default-lease-time $default_lease_time;"
  222. echo "max-lease-time $max_lease_time;"
  223. [ -n "$domain" ] && echo "option domain-name \"$domain\";"
  224. rm -f /tmp/resolv.conf
  225. echo "# This file is generated by the DHCPD service" > /tmp/resolv.conf
  226. [ -n "$domain" ] && echo "domain $domain" >> /tmp/resolv.conf
  227. echo "nameserver 127.0.0.1" >> /tmp/resolv.conf
  228. }
  229. # base procd hooks
  230. boot() {
  231. DHCPD_BOOT=1
  232. start "$@"
  233. }
  234. start_service() {
  235. local domain dhcp_ifs authoritative
  236. if [ -n "$DHCPD_BOOT" ] ; then
  237. return 0
  238. fi
  239. if [ ! -e $lease_file ] ; then
  240. touch $lease_file
  241. fi
  242. if [ -e "/etc/dhcpd.conf" ] ; then
  243. config_file="/etc/dhcpd.conf"
  244. else
  245. . /lib/functions/network.sh
  246. config_load dhcp
  247. general_config > $config_file
  248. config_foreach dhcpd_add dhcp
  249. static_hosts >> $config_file
  250. [ -z "$dhcp_ifs" ] && return 0
  251. fi
  252. procd_open_instance
  253. procd_set_param command $PROG -q -f -cf $config_file -lf $lease_file $dhcp_ifs
  254. procd_close_instance
  255. }
  256. reload_service() {
  257. rc_procd start_service "$@"
  258. prodcd_send_signal dhcpd "$@"
  259. }
  260. add_interface_trigger() {
  261. local cfg=$1
  262. local trigger ignore
  263. config_get trigger "$cfg" interface
  264. config_get_bool ignore "$cfg" ignore 0
  265. if [ -n "$trigger" -a $ignore -eq 0 ] ; then
  266. procd_add_reload_interface_trigger "$trigger"
  267. fi
  268. }
  269. service_triggers() {
  270. if [ -n "$DHCPD_BOOT" ] ; then
  271. # Make the first start robust to slow interfaces; wait a while
  272. procd_add_raw_trigger "interface.*.up" 5000 /etc/init.d/dhcpd restart
  273. else
  274. # reload with normal parameters
  275. procd_add_reload_trigger "network" "dhcp"
  276. config_load dhcp
  277. config_foreach add_interface_trigger dhcp
  278. fi
  279. }