1#!/bin/sh /etc/rc.common 2# Copyright (C) 2007-2012 OpenWrt.org 3 4START=60 5 6USE_PROCD=1 7PROG=/usr/sbin/dnsmasq 8 9DNS_SERVERS="" 10DOMAIN="" 11 12ADD_LOCAL_DOMAIN=1 13ADD_LOCAL_HOSTNAME=1 14 15CONFIGFILE="/var/etc/dnsmasq.conf" 16HOSTFILE="/tmp/hosts/dhcp" 17TRUSTANCHORSFILE="/usr/share/dnsmasq/trust-anchors.conf" 18TIMESTAMPFILE="/etc/dnsmasq.time" 19 20xappend() { 21 local value="$1" 22 23 echo "${value#--}" >> $CONFIGFILE 24} 25 26dhcp_calc() { 27 local ip="$1" 28 local res=0 29 30 while [ -n "$ip" ]; do 31 part="${ip%%.*}" 32 res="$(($res * 256))" 33 res="$(($res + $part))" 34 [ "${ip%.*}" != "$ip" ] && ip="${ip#*.}" || ip= 35 done 36 echo "$res" 37} 38 39dhcp_check() { 40 local ifname="$1" 41 local stamp="/var/run/dnsmasq.$ifname.dhcp" 42 local rv=0 43 44 [ -s "$stamp" ] && return $(cat "$stamp") 45 46 udhcpc -n -q -s /bin/true -t 1 -i "$ifname" >&- && rv=1 || rv=0 47 48 [ $rv -eq 1 ] && \ 49 logger -t dnsmasq \ 50 "found already running DHCP-server on interface '$ifname'" \ 51 "refusing to start, use 'option force 1' to override" 52 53 echo $rv > "$stamp" 54 return $rv 55} 56 57log_once() { 58 pidof dnsmasq >/dev/null || \ 59 logger -t dnsmasq "$@" 60} 61 62append_bool() { 63 local section="$1" 64 local option="$2" 65 local value="$3" 66 local _loctmp 67 config_get_bool _loctmp "$section" "$option" 0 68 [ $_loctmp -gt 0 ] && xappend "$value" 69} 70 71append_parm() { 72 local section="$1" 73 local option="$2" 74 local switch="$3" 75 local _loctmp 76 config_get _loctmp "$section" "$option" 77 [ -z "$_loctmp" ] && return 0 78 xappend "$switch=$_loctmp" 79} 80 81append_server() { 82 xappend "--server=$1" 83} 84 85append_address() { 86 xappend "--address=$1" 87} 88 89append_ipset() { 90 xappend "--ipset=$1" 91} 92 93append_interface() { 94 local ifname=$(uci_get_state network "$1" ifname "$1") 95 xappend "--interface=$ifname" 96} 97 98append_notinterface() { 99 local ifname=$(uci_get_state network "$1" ifname "$1") 100 xappend "--except-interface=$ifname" 101} 102 103append_addnhosts() { 104 xappend "--addn-hosts=$1" 105} 106 107append_bogusnxdomain() { 108 xappend "--bogus-nxdomain=$1" 109} 110 111append_pxe_service() { 112 xappend "--pxe-service=$1" 113} 114 115dnsmasq() { 116 local cfg="$1" 117 append_bool "$cfg" authoritative "--dhcp-authoritative" 118 append_bool "$cfg" nodaemon "--no-daemon" 119 append_bool "$cfg" domainneeded "--domain-needed" 120 append_bool "$cfg" filterwin2k "--filterwin2k" 121 append_bool "$cfg" nohosts "--no-hosts" 122 append_bool "$cfg" nonegcache "--no-negcache" 123 append_bool "$cfg" strictorder "--strict-order" 124 append_bool "$cfg" logqueries "--log-queries=extra" 125 append_bool "$cfg" noresolv "--no-resolv" 126 append_bool "$cfg" localise_queries "--localise-queries" 127 append_bool "$cfg" readethers "--read-ethers" 128 append_bool "$cfg" dbus "--enable-dbus" 129 append_bool "$cfg" boguspriv "--bogus-priv" 130 append_bool "$cfg" expandhosts "--expand-hosts" 131 config_get tftp_root "$cfg" "tftp_root" 132 [ -d "$tftp_root" ] && append_bool "$cfg" enable_tftp "--enable-tftp" 133 append_bool "$cfg" tftp_no_fail "--tftp-no-fail" 134 append_bool "$cfg" nonwildcard "--bind-dynamic" 135 append_bool "$cfg" fqdn "--dhcp-fqdn" 136 append_bool "$cfg" proxydnssec "--proxy-dnssec" 137 append_bool "$cfg" localservice "--local-service" 138 append_bool "$cfg" quietdhcp "--quiet-dhcp" 139 append_bool "$cfg" sequential_ip "--dhcp-sequential-ip" 140 append_bool "$cfg" allservers "--all-servers" 141 append_bool "$cfg" noping "--no-ping" 142 143 append_parm "$cfg" dhcpscript "--dhcp-script" 144 append_parm "$cfg" cachesize "--cache-size" 145 append_parm "$cfg" dnsforwardmax "--dns-forward-max" 146 append_parm "$cfg" port "--port" 147 append_parm "$cfg" ednspacket_max "--edns-packet-max" 148 append_parm "$cfg" dhcpleasemax "--dhcp-lease-max" 149 append_parm "$cfg" "queryport" "--query-port" 150 append_parm "$cfg" "minport" "--min-port" 151 append_parm "$cfg" "domain" "--domain" 152 append_parm "$cfg" "local" "--server" 153 config_list_foreach "$cfg" "server" append_server 154 config_list_foreach "$cfg" "address" append_address 155 config_list_foreach "$cfg" "ipset" append_ipset 156 config_list_foreach "$cfg" "interface" append_interface 157 config_list_foreach "$cfg" "notinterface" append_notinterface 158 config_list_foreach "$cfg" "addnhosts" append_addnhosts 159 config_list_foreach "$cfg" "bogusnxdomain" append_bogusnxdomain 160 append_parm "$cfg" "leasefile" "--dhcp-leasefile" 161 append_parm "$cfg" "resolvfile" "--resolv-file" 162 append_parm "$cfg" "serversfile" "--servers-file" 163 append_parm "$cfg" "tftp_root" "--tftp-root" 164 append_parm "$cfg" "dhcp_boot" "--dhcp-boot" 165 append_parm "$cfg" "local_ttl" "--local-ttl" 166 append_parm "$cfg" "pxe_prompt" "--pxe-prompt" 167 config_list_foreach "$cfg" "pxe_service" append_pxe_service 168 config_get DOMAIN "$cfg" domain 169 170 config_get_bool ADD_LOCAL_DOMAIN "$cfg" add_local_domain 1 171 config_get_bool ADD_LOCAL_HOSTNAME "$cfg" add_local_hostname 1 172 173 config_get_bool readethers "$cfg" readethers 174 [ "$readethers" = "1" -a \! -e "/etc/ethers" ] && touch /etc/ethers 175 176 config_get leasefile $cfg leasefile 177 [ -n "$leasefile" -a \! -e "$leasefile" ] && touch "$leasefile" 178 config_get_bool cachelocal "$cfg" cachelocal 1 179 180 config_get hostsfile "$cfg" dhcphostsfile 181 [ -e "$hostsfile" ] && xappend "--dhcp-hostsfile=$hostsfile" 182 183 local rebind 184 config_get_bool rebind "$cfg" rebind_protection 1 185 [ $rebind -gt 0 ] && { 186 log_once \ 187 "DNS rebinding protection is active," \ 188 "will discard upstream RFC1918 responses!" 189 xappend "--stop-dns-rebind" 190 191 local rebind_localhost 192 config_get_bool rebind_localhost "$cfg" rebind_localhost 0 193 [ $rebind_localhost -gt 0 ] && { 194 log_once "Allowing 127.0.0.0/8 responses" 195 xappend "--rebind-localhost-ok" 196 } 197 198 append_rebind_domain() { 199 log_once "Allowing RFC1918 responses for domain $1" 200 xappend "--rebind-domain-ok=$1" 201 } 202 203 config_list_foreach "$cfg" rebind_domain append_rebind_domain 204 } 205 206 config_get_bool dnssec "$cfg" dnssec 0 207 [ "$dnssec" -gt 0 ] && { 208 xappend "--conf-file=$TRUSTANCHORSFILE" 209 xappend "--dnssec" 210 xappend "--dnssec-timestamp=$TIMESTAMPFILE" 211 append_bool "$cfg" dnsseccheckunsigned "--dnssec-check-unsigned" 212 } 213 214 dhcp_option_add "$cfg" "" 0 215 216 xappend "--dhcp-broadcast=tag:needs-broadcast" 217 218 mkdir -p /tmp/hosts /tmp/dnsmasq.d 219 xappend "--addn-hosts=/tmp/hosts" 220 xappend "--conf-dir=/tmp/dnsmasq.d" 221 xappend "--user=dnsmasq" 222 xappend "--group=dnsmasq" 223 224 echo >> $CONFIGFILE 225 226 config_get_bool enable_tftp "$cfg" enable_tftp 0 227 [ "$enable_tftp" -gt 0 ] && { 228 config_get tftp_root "$cfg" tftp_root 229 append EXTRA_MOUNT $tftp_root 230 } 231} 232 233dhcp_subscrid_add() { 234 local cfg="$1" 235 236 config_get networkid "$cfg" networkid 237 [ -n "$networkid" ] || return 0 238 239 config_get subscriberid "$cfg" subscriberid 240 [ -n "$subscriberid" ] || return 0 241 242 xappend "--dhcp-subscrid=$networkid,$subscriberid" 243 244 config_get_bool force "$cfg" force 0 245 246 dhcp_option_add "$cfg" "$networkid" "$force" 247} 248 249dhcp_remoteid_add() { 250 local cfg="$1" 251 252 config_get networkid "$cfg" networkid 253 [ -n "$networkid" ] || return 0 254 255 config_get remoteid "$cfg" remoteid 256 [ -n "$remoteid" ] || return 0 257 258 xappend "--dhcp-remoteid=$networkid,$remoteid" 259 260 config_get_bool force "$cfg" force 0 261 262 dhcp_option_add "$cfg" "$networkid" "$force" 263} 264 265dhcp_circuitid_add() { 266 local cfg="$1" 267 268 config_get networkid "$cfg" networkid 269 [ -n "$networkid" ] || return 0 270 271 config_get circuitid "$cfg" circuitid 272 [ -n "$circuitid" ] || return 0 273 274 xappend "--dhcp-circuitid=$networkid,$circuitid" 275 276 config_get_bool force "$cfg" force 0 277 278 dhcp_option_add "$cfg" "$networkid" "$force" 279} 280 281dhcp_userclass_add() { 282 local cfg="$1" 283 284 config_get networkid "$cfg" networkid 285 [ -n "$networkid" ] || return 0 286 287 config_get userclass "$cfg" userclass 288 [ -n "$userclass" ] || return 0 289 290 xappend "--dhcp-userclass=$networkid,$userclass" 291 292 config_get_bool force "$cfg" force 0 293 294 dhcp_option_add "$cfg" "$networkid" "$force" 295} 296 297dhcp_vendorclass_add() { 298 local cfg="$1" 299 300 config_get networkid "$cfg" networkid 301 [ -n "$networkid" ] || return 0 302 303 config_get vendorclass "$cfg" vendorclass 304 [ -n "$vendorclass" ] || return 0 305 306 xappend "--dhcp-vendorclass=$networkid,$vendorclass" 307 308 config_get_bool force "$cfg" force 0 309 310 dhcp_option_add "$cfg" "$networkid" "$force" 311} 312 313dhcp_host_add() { 314 local cfg="$1" 315 316 config_get_bool force "$cfg" force 0 317 318 config_get networkid "$cfg" networkid 319 [ -n "$networkid" ] && dhcp_option_add "$cfg" "$networkid" "$force" 320 321 config_get_bool enable "$cfg" enable 1 322 [ "$enable" = "0" ] && return 0 323 324 config_get name "$cfg" name 325 config_get ip "$cfg" ip 326 [ -n "$ip" -o -n "$name" ] || return 0 327 328 config_get_bool dns "$cfg" dns 0 329 [ "$dns" = "1" -a -n "$ip" -a -n "$name" ] && { 330 echo "$ip $name${DOMAIN:+.$DOMAIN}" >> $HOSTFILE 331 } 332 333 config_get mac "$cfg" mac 334 if [ -n "$mac" ]; then 335 # --dhcp-host=00:20:e0:3b:13:af,192.168.0.199,lap 336 macs="" 337 for m in $mac; do append macs "$m" ","; done 338 else 339 # --dhcp-host=lap,192.168.0.199 340 [ -n "$name" ] || return 0 341 macs="$name" 342 name="" 343 fi 344 345 config_get tag "$cfg" tag 346 347 config_get_bool broadcast "$cfg" broadcast 0 348 [ "$broadcast" = "0" ] && broadcast= 349 350 config_get leasetime "$cfg" leasetime 351 352 xappend "--dhcp-host=$macs${networkid:+,net:$networkid}${broadcast:+,set:needs-broadcast}${tag:+,set:$tag}${ip:+,$ip}${name:+,$name}${leasetime:+,$leasetime}" 353} 354 355dhcp_tag_add() { 356 local cfg="$1" 357 358 tag="$cfg" 359 360 [ -n "$tag" ] || return 0 361 362 config_get_bool force "$cfg" force 0 363 [ "$force" = "0" ] && force= 364 365 config_get option "$cfg" dhcp_option 366 for o in $option; do 367 xappend "--dhcp-option${force:+-force}=tag:$tag,$o" 368 done 369} 370 371dhcp_mac_add() { 372 local cfg="$1" 373 374 config_get networkid "$cfg" networkid 375 [ -n "$networkid" ] || return 0 376 377 config_get mac "$cfg" mac 378 [ -n "$mac" ] || return 0 379 380 xappend "--dhcp-mac=$networkid,$mac" 381 382 dhcp_option_add "$cfg" "$networkid" 383} 384 385dhcp_boot_add() { 386 local cfg="$1" 387 388 config_get networkid "$cfg" networkid 389 390 config_get filename "$cfg" filename 391 [ -n "$filename" ] || return 0 392 393 config_get servername "$cfg" servername 394 config_get serveraddress "$cfg" serveraddress 395 396 [ -n "$serveraddress" -a ! -n "$servername" ] && return 0 397 398 xappend "--dhcp-boot=${networkid:+net:$networkid,}${filename}${servername:+,$servername}${serveraddress:+,$serveraddress}" 399 400 config_get_bool force "$cfg" force 0 401 402 dhcp_option_add "$cfg" "$networkid" "$force" 403} 404 405 406dhcp_add() { 407 local cfg="$1" 408 config_get net "$cfg" interface 409 [ -n "$net" ] || return 0 410 411 config_get dhcpv4 "$cfg" dhcpv4 412 [ "$dhcpv4" != "disabled" ] || return 0 413 414 config_get networkid "$cfg" networkid 415 [ -n "$networkid" ] || networkid="$net" 416 417 network_get_subnet subnet "$net" || return 0 418 network_get_device ifname "$net" || return 0 419 network_get_protocol proto "$net" || return 0 420 421 [ "$cachelocal" = "0" ] && network_get_dnsserver dnsserver "$net" && { 422 DNS_SERVERS="$DNS_SERVERS $dnsserver" 423 } 424 425 append_bool "$cfg" ignore "--no-dhcp-interface=$ifname" && return 0 426 427 # Do not support non-static interfaces for now 428 [ static = "$proto" ] || return 0 429 430 # Override interface netmask with dhcp config if applicable 431 config_get netmask "$cfg" netmask "${subnet##*/}" 432 433 #check for an already active dhcp server on the interface, unless 'force' is set 434 config_get_bool force "$cfg" force 0 435 [ $force -gt 0 ] || dhcp_check "$ifname" || return 0 436 437 config_get start "$cfg" start 438 config_get limit "$cfg" limit 439 config_get leasetime "$cfg" leasetime 440 config_get options "$cfg" options 441 config_get_bool dynamicdhcp "$cfg" dynamicdhcp 1 442 443 leasetime="${leasetime:-12h}" 444 start="$(dhcp_calc "${start:-100}")" 445 limit="${limit:-150}" 446 [ "$limit" -gt 0 ] && limit=$((limit-1)) 447 eval "$(ipcalc.sh "${subnet%%/*}" $netmask $start $limit)" 448 if [ "$dynamicdhcp" = "0" ]; then END="static"; fi 449 xappend "--dhcp-range=$networkid,$START,$END,$NETMASK,$leasetime${options:+ $options}" 450 451 dhcp_option_add "$cfg" "$networkid" 452} 453 454dhcp_option_add() { 455 local cfg="$1" 456 local networkid="$2" 457 local force="$3" 458 459 [ "$force" = "0" ] && force= 460 461 config_get dhcp_option "$cfg" dhcp_option 462 for o in $dhcp_option; do 463 xappend "--dhcp-option${force:+-force}=${networkid:+$networkid,}$o" 464 done 465 466} 467 468dhcp_domain_add() { 469 local cfg="$1" 470 local ip name names record 471 472 config_get names "$cfg" name "$2" 473 [ -n "$names" ] || return 0 474 475 config_get ip "$cfg" ip "$3" 476 [ -n "$ip" ] || return 0 477 478 for name in $names; do 479 record="${record:+$record }$name" 480 done 481 482 echo "$ip $record" >> $HOSTFILE 483} 484 485dhcp_srv_add() { 486 local cfg="$1" 487 488 config_get srv "$cfg" srv 489 [ -n "$srv" ] || return 0 490 491 config_get target "$cfg" target 492 [ -n "$target" ] || return 0 493 494 config_get port "$cfg" port 495 [ -n "$port" ] || return 0 496 497 config_get class "$cfg" class 498 config_get weight "$cfg" weight 499 500 local service="$srv,$target,$port${class:+,$class${weight:+,$weight}}" 501 502 xappend "--srv-host=$service" 503} 504 505dhcp_mx_add() { 506 local cfg="$1" 507 local domain relay pref 508 509 config_get domain "$cfg" domain 510 [ -n "$domain" ] || return 0 511 512 config_get relay "$cfg" relay 513 [ -n "$relay" ] || return 0 514 515 config_get pref "$cfg" pref 0 516 517 local service="$domain,$relay,$pref" 518 519 xappend "--mx-host=$service" 520} 521 522dhcp_cname_add() { 523 local cfg="$1" 524 local cname target 525 526 config_get cname "$cfg" cname 527 [ -n "$cname" ] || return 0 528 529 config_get target "$cfg" target 530 [ -n "$target" ] || return 0 531 532 xappend "--cname=${cname},${target}" 533} 534 535dhcp_hostrecord_add() { 536 local cfg="$1" 537 local names addresses record val 538 539 config_get names "$cfg" name "$2" 540 if [ -z "$names" ]; then 541 return 0 542 fi 543 544 config_get addresses "$cfg" ip "$3" 545 if [ -z "$addresses" ]; then 546 return 0 547 fi 548 549 for val in $names $addresses; do 550 record="${record:+$record,}$val" 551 done 552 553 xappend "--host-record=$record" 554} 555 556dhcp_relay_add() { 557 local cfg="$1" 558 local local_addr server_addr interface 559 560 config_get local_addr "$cfg" local_addr 561 [ -n "$local_addr" ] || return 0 562 563 config_get server_addr "$cfg" server_addr 564 [ -n "$server_addr" ] || return 0 565 566 config_get interface "$cfg" interface 567 if [ -z "$interface" ]; then 568 xappend "--dhcp-relay=$local_addr,$server_addr" 569 else 570 xappend "--dhcp-relay=$local_addr,$server_addr,$interface" 571 fi 572} 573 574service_triggers() 575{ 576 procd_add_reload_trigger "dhcp" 577} 578 579boot() { 580 # Will be launched through hotplug 581 return 0 582} 583 584start_service() { 585 include /lib/functions 586 587 config_load dhcp 588 589 # before we can call xappend 590 mkdir -p /var/run/dnsmasq/ 591 mkdir -p $(dirname $CONFIGFILE) 592 mkdir -p /var/lib/misc 593 touch /tmp/dhcp.leases 594 595 if [ ! -f "$TIMESTAMPFILE" ]; then 596 touch "$TIMESTAMPFILE" 597 chown dnsmasq.dnsmasq "$TIMESTAMPFILE" 598 fi 599 600 echo "# auto-generated config file from /etc/config/dhcp" > $CONFIGFILE 601 echo "# auto-generated config file from /etc/config/dhcp" > $HOSTFILE 602 603 # if we did this last, we could override auto-generated config 604 [ -f /etc/dnsmasq.conf ] && { 605 xappend "--conf-file=/etc/dnsmasq.conf" 606 } 607 608 args="" 609 config_foreach dnsmasq dnsmasq 610 config_foreach dhcp_host_add host 611 echo >> $CONFIGFILE 612 config_foreach dhcp_boot_add boot 613 config_foreach dhcp_mac_add mac 614 config_foreach dhcp_tag_add tag 615 config_foreach dhcp_vendorclass_add vendorclass 616 config_foreach dhcp_userclass_add userclass 617 config_foreach dhcp_circuitid_add circuitid 618 config_foreach dhcp_remoteid_add remoteid 619 config_foreach dhcp_subscrid_add subscrid 620 config_foreach dhcp_domain_add domain 621 config_foreach dhcp_hostrecord_add hostrecord 622 config_foreach dhcp_relay_add relay 623 624 # add own hostname 625 [ $ADD_LOCAL_HOSTNAME -eq 1 ] && { 626 local lanaddr lanaddr6 627 local ulaprefix="$(uci_get network @globals[0] ula_prefix)" 628 local hostname="$(uci_get system @system[0] hostname OpenWrt)" 629 630 network_get_ipaddr lanaddr "lan" && { 631 dhcp_domain_add "" "$hostname" "$lanaddr" 632 } 633 634 [ -n "$ulaprefix" ] && network_get_ipaddrs6 lanaddr6 "lan" && { 635 for lanaddr6 in $lanaddr6; do 636 case "$lanaddr6" in 637 "${ulaprefix%%:/*}"*) 638 dhcp_domain_add "" "$hostname" "$lanaddr6" 639 ;; 640 esac 641 done 642 } 643 } 644 645 echo >> $CONFIGFILE 646 config_foreach dhcp_srv_add srvhost 647 config_foreach dhcp_mx_add mxhost 648 echo >> $CONFIGFILE 649 650 config_get odhcpd_is_active odhcpd maindhcp 651 if [ "$odhcpd_is_active" != "1" ]; then 652 config_foreach dhcp_add dhcp 653 fi 654 655 echo >> $CONFIGFILE 656 config_foreach dhcp_cname_add cname 657 echo >> $CONFIGFILE 658 659 rm -f /tmp/resolv.conf 660 [ $ADD_LOCAL_DOMAIN -eq 1 ] && [ -n "$DOMAIN" ] && { 661 echo "search $DOMAIN" >> /tmp/resolv.conf 662 } 663 DNS_SERVERS="$DNS_SERVERS 127.0.0.1" 664 for DNS_SERVER in $DNS_SERVERS ; do 665 echo "nameserver $DNS_SERVER" >> /tmp/resolv.conf 666 done 667 668 procd_open_instance 669 procd_set_param command $PROG -C $CONFIGFILE -k -x /var/run/dnsmasq/dnsmasq.pid 670 procd_set_param file $CONFIGFILE 671 procd_set_param respawn 672 673 procd_add_jail dnsmasq ubus log 674 procd_add_jail_mount $CONFIGFILE $TRUSTANCHORSFILE $HOSTFILE /etc/passwd /etc/group /etc/TZ /dev/null /dev/urandom /etc/dnsmasq.conf /tmp/dnsmasq.d /tmp/resolv.conf.auto /etc/hosts /etc/ethers $EXTRA_MOUNT 675 procd_add_jail_mount_rw /var/run/dnsmasq/ /tmp/dhcp.leases $TIMESTAMPFILE 676 677 procd_close_instance 678} 679 680reload_service() { 681 rc_procd start_service "$@" 682 return 0 683} 684 685stop_service() { 686 [ -f /tmp/resolv.conf ] && { 687 rm -f /tmp/resolv.conf 688 ln -s /tmp/resolv.conf.auto /tmp/resolv.conf 689 } 690 rm -f /var/run/dnsmasq.*.dhcp 691} 692