1 #!/bin/sh /etc/rc.common
10 lease_file
=/tmp
/dhcpd.leases
11 config_file
=/tmp
/run
/dhcpd.conf
14 conf_local_file
=$dyndir/named.conf.
local
16 session_key_name
=local-ddns
17 session_key_file
=/var
/run
/named
/session.key
21 local multiplier number suffix
23 suffix
="${timestring//[0-9 ]}"
24 number
="${timestring%%$suffix}"
25 [ "$number$suffix" != "$timestring" ] && return 1
46 echo $
(( number
* multiplier
))
52 echo "$arg" |
sed -e 's/^ *//' -e 's/ *$//'
56 local octets
="$(echo "${1%%/*}" | cut -d. -f1)"
58 [ "$octets" = "10" ] && { echo "$octets"; return; }
60 octets
="$(echo "${1%%/*}" | cut -d. -f1-2)"
63 172.1[6789]|
172.2[0-9]|
172.3[01]|
192.168)
70 [ -n "$(named-checkconf -px \
71 | sed -r -ne '1N; N; /^\tlisten-on-v6 ?\{\n\t\t"none
";\n\t\};$/{ p; q; }; D')" ]
74 # duplicated from dnsmasq init script
77 local hex
="${2#0x}" # strip optional "0x" prefix
79 if [ -n "${hex//[0-9a-fA-F]/}" ]; then
80 # is invalid hex literal
84 # convert into host id
87 $(((0x$hex >> 16) % 65536)) \
96 /^\d+\.\d+\.\d+\.\d+$/ { print "ip\n"; next; }
97 /^(true|false)$/ { print "bool\n"; next; }
98 /^\d+$/ { print "integer\n"; next; }
99 /^"[^"]*"$/ { print "string\n"; next; }
100 /^[0-9a-fA-F]{2,2}(:[0-9a-fA-F]{2,2})*$/ { print "string\n"; next; }
101 { print "other\n"; next; }
106 local lhs
="$1" family
="$2" type="$3"
109 [ $dynamicdns -eq 1 ] && \
110 echo -e "$PREFIX" "$lhs $family $type $@\nsend" >> $dyn_file
116 echo "$arg" |
sed -e 's/\./, /g'
120 local str
="$1" delim
="$2"
121 local frag result
="" IFS
="$delim"
124 result
="$frag${result:+$delim}$result"
130 create_empty_zone
() {
133 if [ ! -f $dyndir/db.
"$zone" ]; then
134 cp -p /etc
/bind
/db.empty
$dyndir/db.
"$zone"
135 chmod g
+w
$dyndir/db.
"$zone"
136 chgrp
bind $dyndir/db.
"$zone"
141 local tuple tuple
="$(trim "$1")"
142 local network prefix router save octets compacted
145 router
="$(trim "${tuple#${save} }")"
147 network
="$(trim "${save%/[0-9]*}")"
149 prefix
="$(trim "${save##${network}/}")"
151 octets
=$
((($prefix + 7) / 8))
152 compacted
="$(echo "$network" | cut -d. -f1-$octets)"
154 routes
="$routes${routes:+, }$(explode "$prefix${compacted:+.$compacted}.
$router")"
157 append_dhcp_options
() {
160 # strip redundant "option:" prefix
161 tuple
="${tuple#option:}"
163 local tag
="${tuple%%,*}"
164 local values
="${tuple#$tag,}"
166 local formatted value
168 for value
in $values; do
169 # detect type of $value and quote if necessary
170 case $
(typeof
"$value") in
171 ip|bool|integer|string
)
177 formatted
="$formatted${formatted:+, }$value"
179 echo " option $tag $formatted;"
186 config_get cname
"$cfg" "cname"
187 [ -n "$cname" ] ||
return 0
188 config_get target
"$cfg" "target"
189 [ -n "$target" ] ||
return 0
191 update
"$cname.$domain." IN CNAME
"$target.$domain."
195 config_foreach static_cname_add cname
"$@"
198 static_domain_add
() {
200 local name ip ips revip
202 config_get name
"$cfg" "name"
203 [ -n "$name" ] ||
return 0
204 config_get ip
"$cfg" "ip"
205 [ -n "$ip" ] ||
return 0
209 revip
="$(rev_str "$ip" ".
")"
211 update
"$name.$domain." IN A
"$ip"
212 [ -n "$(rfc1918_prefix "$ip")" ] && \
213 update
"$revip.in-addr.arpa." IN PTR
"$name.$domain."
218 config_foreach static_domain_add domain
"$@"
221 static_mxhost_add
() {
223 local domain2 relay pref
225 config_get domain2
"$cfg" "domain"
226 [ -n "$domain2" ] ||
return 0
227 config_get relay
"$cfg" "relay"
228 [ -n "$relay" ] ||
return 0
229 config_get pref
"$cfg" "pref"
230 [ -n "$pref" ] ||
return 0
232 if [ "$domain2" = "@" ]; then
233 update
"$domain." IN MX
"$pref" "$relay.$domain."
235 update
"$domain2.$domain." IN MX
"$pref" "$relay.$domain."
240 config_foreach static_mxhost_add mxhost
"$@"
243 static_srvhost_add
() {
245 local srv target port priority weight
247 config_get srv
"$cfg" "srv"
248 [ -n "$srv" ] ||
return 0
249 config_get target
"$cfg" "target"
250 [ -n "$target" ] ||
return 0
251 config_get port
"$cfg" "port"
252 [ -n "$port" ] ||
return 0
253 config_get priority
"$cfg" "priority"
254 [ -n "$priority" ] ||
return 0
255 config_get weight
"$cfg" "weight"
256 [ -n "$weight" ] ||
return 0
258 update
"$srv.$domain." IN SRV
"$priority" "$weight" "$port" "$target.$domain"
262 config_foreach static_srvhost_add srvhost
"$@"
267 local broadcast hostid macn macs mac name ip ips revip leasetime
268 local force_send extra_options option
270 config_get macs
"$cfg" "mac"
271 [ -n "$macs" ] ||
return 0
272 config_get name
"$cfg" "name"
273 [ -n "$name" ] ||
return 0
274 config_get ip
"$cfg" "ip"
275 [ -n "$ip" ] ||
return 0
277 config_get_bool broadcast
"$cfg" "broadcast" 0
278 config_get dns
"$cfg" "dns"
279 config_get gateway
"$cfg" "gateway"
280 config_get leasetime
"$cfg" "leasetime"
281 if [ -n "$leasetime" ] ; then
282 leasetime
="$(time2seconds "$leasetime")"
283 [ "$?" -ne 0 ] && return 1
286 config_get hostid
"$cfg" "hostid"
287 if [ -n "$hostid" ] ; then
288 hex_to_hostid hostid
"$hostid" ||
return 1
291 config_get force_send
"$cfg" "force_send"
293 local _IFS
="$IFS" IFS
=','
294 for option
in $force_send; do
297 extra_options
="$extra_options${extra_options:+,}0c" ;;
299 extra_options
="$extra_options${extra_options:+,}0f" ;;
301 extra_options
="$extra_options${extra_options:+,}3a" ;;
303 extra_options
="$extra_options${extra_options:+,}3b" ;;
305 extra_options
="$extra_options${extra_options:+,}51" ;;
307 extra_options
="$extra_options${extra_options:+,}79" ;;
309 echo "unknown option: $option" >&2 ;;
320 local secname
="$name"
321 if [ $macn -gt 1 ] ; then
322 secname
="${name}-${mac//:}"
324 echo "host $secname {"
325 echo " hardware ethernet $mac;"
326 echo " fixed-address $ip;"
327 echo " option host-name \"$name\";"
328 if [ "$broadcast" -eq 1 ] ; then
329 echo " always-broadcast true;"
331 if [ -n "$leasetime" ] ; then
332 echo " default-lease-time $leasetime;"
333 echo " max-lease-time $leasetime;"
335 if [ -n "$hostid" ] ; then
336 echo " option dhcp-client-identifier $hostid;"
338 if [ -n "$dns" ] ; then
339 echo " option domain-name-servers $dns;"
341 if [ -n "$gateway" ] ; then
342 echo " option routers $gateway;"
346 config_list_foreach
"$cfg" "routes" append_routes
347 [ -n "$routes" ] && echo " option classless-ipv4-route $routes;"
349 config_list_foreach
"$cfg" "dhcp_option" append_dhcp_options
350 if [ -n "$extra_options" ]; then
351 echo -e " if exists dhcp-parameter-request-list {\n option dhcp-parameter-request-list = concat(option dhcp-parameter-request-list, $extra_options);\n }"
358 revip
="$(rev_str "$ip" ".
")"
360 update
"$name.$domain." IN A
"$ip"
361 update
"$revip.in-addr.arpa." IN PTR
"$name.$domain."
366 config_foreach static_host_add
host "$@"
372 echo "subnet $NETWORK netmask $NETMASK {"
373 if [ -n "$START" ] && [ -n "$END" ]; then
374 echo " range $START $END;"
376 echo " option subnet-mask $netmask;"
377 if [ "$BROADCAST" != "0.0.0.0" ] ; then
378 echo " option broadcast-address $BROADCAST;"
380 if [ "$dynamicdhcp" -eq 0 ] ; then
381 if [ "$authoritative" -eq 1 ] ; then
382 echo " deny unknown-clients;"
384 echo " ignore unknown-clients;"
387 if [ -n "$leasetime" ] ; then
388 echo " default-lease-time $leasetime;"
389 echo " max-lease-time $leasetime;"
391 if [ "$defaultroute" -eq 1 ] ; then
392 echo " option routers $gateway;"
394 echo " option domain-name-servers $DNS;"
397 config_list_foreach
"$cfg" "routes" append_routes
398 [ -n "$routes" ] && echo " option classless-ipv4-route $routes;"
400 config_list_foreach
"$cfg" "dhcp_option" append_dhcp_options
405 local cfg
="$1" synthesize
="$2"
406 local dhcp6range
="::"
407 local dynamicdhcp defaultroute end gateway ifname ignore leasetime limit net netmask
408 local proto networkid start subnet
409 local IP NETMASK BROADCAST NETWORK PREFIX DNS START END
411 config_get_bool ignore
"$cfg" "ignore" 0
412 [ "$ignore" = "0" ] ||
return 0
414 config_get net
"$cfg" "interface"
415 [ -n "$net" ] ||
return 0
417 config_get start
"$cfg" "start"
418 config_get limit
"$cfg" "limit"
420 case "$start:$limit" in
422 echo "dhcpd: start/limit must be used together in $cfg" >&2
426 network_get_subnet subnet
"$net" ||
return 0
427 network_get_device ifname
"$net" ||
return 0
428 network_get_protocol proto
"$net" ||
return 0
430 [ static
= "$proto" ] ||
return 0
432 local octets
="$(rfc1918_prefix "$subnet")"
434 [ -n "$octets" ] && rfc1918_nets
="$rfc1918_nets${rfc1918_nets:+ }$octets"
436 [ $synthesize -eq 0 ] && return
438 config_get_bool dynamicdhcp
"$cfg" "dynamicdhcp" 1
440 config_get_bool defaultroute
"$cfg" "default_route" 1
442 dhcp_ifs
="$dhcp_ifs $ifname"
444 eval "$(ipcalc.sh $subnet $start $limit)"
446 config_get netmask
"$cfg" "netmask" "$NETMASK"
447 config_get leasetime
"$cfg" "leasetime"
448 if [ -n "$leasetime" ] ; then
449 leasetime
="$(time2seconds "$leasetime")"
450 [ "$?" -ne 0 ] && return 1
453 if network_get_dnsserver dnsserver
"$net" ; then
454 for dnsserv
in $dnsserver ; do
455 DNS
="$DNS${DNS:+, }$dnsserv"
461 if ! network_get_gateway gateway
"$net" ; then
465 gen_dhcp_subnet
"$cfg"
469 local always_broadcast boot_unknown_clients log_facility
470 local default_lease_time max_lease_time
472 config_get_bool always_broadcast
"isc_dhcpd" "always_broadcast" 0
473 config_get_bool authoritative
"isc_dhcpd" "authoritative" 1
474 config_get_bool boot_unknown_clients
"isc_dhcpd" "boot_unknown_clients" 1
475 config_get default_lease_time
"isc_dhcpd" "default_lease_time" 3600
476 config_get max_lease_time
"isc_dhcpd" "max_lease_time" 86400
477 config_get log_facility
"isc_dhcpd" "log_facility"
479 config_get domain
"isc_dhcpd" "domain"
480 config_get_bool dynamicdns
"isc_dhcpd" dynamicdns
0
482 [ $always_broadcast -eq 1 ] && echo "always-broadcast true;"
483 [ $authoritative -eq 1 ] && echo "authoritative;"
484 [ $boot_unknown_clients -eq 0 ] && echo "boot-unknown-clients false;"
486 default_lease_time
="$(time2seconds "$default_lease_time")"
487 [ "$?" -ne 0 ] && return 1
488 max_lease_time
="$(time2seconds "$max_lease_time")"
489 [ "$?" -ne 0 ] && return 1
491 if [ $dynamicdns -eq 1 ]; then
492 create_empty_zone
"$domain"
496 for mynet
in $rfc1918_nets; do
497 mynet
="$(rev_str "$mynet" ".
")"
498 create_empty_zone
"$mynet.in-addr.arpa"
503 cp -p $conf_local_file ${conf_local_file}_
505 cat <<EOF > $conf_local_file
508 file "$dyndir/db.$domain";
510 grant $session_key_name zonesub any;
516 for mynet
in $rfc1918_nets; do
517 mynet
="$(rev_str "$mynet" ".
")"
518 cat <<EOF >> $conf_local_file
519 zone "$mynet.in-addr.arpa" {
521 file "$dyndir/db.$mynet.in-addr.arpa";
523 grant $session_key_name zonesub any;
530 cmp -s $conf_local_file ${conf_local_file}_ || need_reload
=1
531 rm -f ${conf_local_file}_
533 [ -n "$need_reload" ] && /etc
/init.d
/named reload
537 ddns-domainname "$domain.";
538 ddns-update-style standard;
540 ignore client-updates;
542 update-static-leases on;
543 use-host-decl-names on;
544 update-conflict-detection off;
545 update-optimization off;
547 include "$session_key_file";
551 key $session_key_name;
556 for mynet
in $rfc1918_nets; do
557 mynet
="$(rev_str "$mynet" ".
")"
559 zone $mynet.in-addr.arpa. {
561 key $session_key_name;
568 if [ -n "$log_facility" ] ; then
569 echo "log-facility $log_facility;"
571 echo "default-lease-time $default_lease_time;"
572 echo "max-lease-time $max_lease_time;"
574 [ -n "$domain" ] && echo "option domain-name \"$domain\";"
576 echo -e "\n# additional codes\noption classless-ipv4-route code 121 = array of { unsigned integer 8 };\n"
578 rm -f /tmp
/resolv.conf
579 echo "# This file is generated by the DHCPD service" > /tmp
/resolv.conf
580 [ -n "$domain" ] && echo "domain $domain" >> /tmp
/resolv.conf
581 echo "nameserver 127.0.0.1" >> /tmp
/resolv.conf
592 local domain dhcp_ifs authoritative dynamicdns
594 if [ -n "$DHCPD_BOOT" ] ; then
598 if [ ! -e $lease_file ] ; then
602 if [ -e "/etc/dhcpd.conf" ] ; then
603 config_file
="/etc/dhcpd.conf"
605 .
/lib
/functions
/network.sh
607 local dyn_file
=$
(mktemp
-u /tmp
/dhcpd.XXXXXX
)
611 local rfc1918_nets
=""
613 # alas we have to make 2 passes...
614 config_foreach dhcpd_add dhcp
0
616 rfc1918_nets
="$(echo "$rfc1918_nets" | tr ' ' $'\n' | sort | uniq | tr $'\n' ' ')"
618 general_config
> $config_file
620 if [ $dynamicdns -eq 1 ]; then
621 cat <<EOF > $dyn_file
622 ; Generated by /etc/init.d/dhcpd at $(date)
631 config_foreach dhcpd_add dhcp
1 >> $config_file
633 static_hosts
>> $config_file
635 static_cnames
>> $config_file
637 static_domains
>> $config_file
639 static_mxhosts
>> $config_file
641 static_srvhosts
>> $config_file
643 if [ $dynamicdns -eq 1 ]; then
648 nsupdate
-l -v $args $dyn_file
654 [ -z "$dhcp_ifs" ] && return 0
658 procd_set_param
command $PROG -q -f -cf $config_file -lf $lease_file $dhcp_ifs
663 rc_procd start_service
"$@"
664 procd_send_signal dhcpd
"$@"
667 add_interface_trigger
() {
671 config_get trigger
"$cfg" interface
672 config_get_bool ignore
"$cfg" ignore
0
674 if [ -n "$trigger" -a $ignore -eq 0 ] ; then
675 procd_add_reload_interface_trigger
"$trigger"
680 if [ -n "$DHCPD_BOOT" ] ; then
681 # Make the first start robust to slow interfaces; wait a while
682 procd_add_raw_trigger
"interface.*.up" 5000 /etc
/init.d
/dhcpd restart
685 # reload with normal parameters
686 procd_add_reload_trigger
"network" "dhcp"
688 config_foreach add_interface_trigger dhcp