diff options
Diffstat (limited to 'dhcpcd/dhcpcd-hooks/30-hostname')
-rw-r--r-- | dhcpcd/dhcpcd-hooks/30-hostname | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/dhcpcd/dhcpcd-hooks/30-hostname b/dhcpcd/dhcpcd-hooks/30-hostname new file mode 100644 index 00000000..616fb82a --- /dev/null +++ b/dhcpcd/dhcpcd-hooks/30-hostname @@ -0,0 +1,154 @@ +# Set the hostname from DHCP data if required + +# A hostname can either be a short hostname or a FQDN. +# hostname_fqdn=true +# hostname_fqdn=false +# hostname_fqdn=server + +# A value of server means just what the server says, don't manipulate it. +# This could lead to an inconsistent hostname on a DHCPv4 and DHCPv6 network +# where the DHCPv4 hostname is short and the DHCPv6 has an FQDN. +# DHCPv6 has no hostname option. +# RFC4702 section 3.1 says FQDN should be prefered over hostname. +# +# As such, the default is hostname_fqdn=true so that a consistent hostname +# is always assigned. +: ${hostname_fqdn:=true} + +# Some systems don't have hostname(1) +_hostname() +{ + local name= + + if [ -z "$1" ]; then + if type hostname >/dev/null 2>&1; then + hostname + elif [ -r /proc/sys/kernel/hostname ]; then + read name </proc/sys/kernel/hostname && echo "$name" + elif sysctl kern.hostname >/dev/null 2>&1; then + sysctl -n kern.hostname + elif sysctl kernel.hostname >/dev/null 2>&1; then + sysctl -n kernel.hostname + else + return 1 + fi + return $? + fi + + # Always prefer hostname(1) if we have it + if type hostname >/dev/null 2>&1; then + hostname "$1" + elif [ -w /proc/sys/kernel/hostname ]; then + echo "$1" >/proc/sys/kernel/hostname + elif sysctl kern.hostname >/dev/null 2>&1; then + sysctl -w "kern.hostname=$1" + elif sysctl kernel.hostname >/dev/null 2>&1; then + sysctl -w "kernel.hostname=$1" + else + # We know this will fail, but it will now fail + # with an error to stdout + hostname "$1" + fi +} + +need_hostname() +{ + local hostname hfqdn=false hshort=false + + case "$force_hostname" in + [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1) return 0;; + esac + + hostname="$(_hostname)" + case "$hostname" in + ""|"(none)"|localhost|localhost.localdomain) return 0;; + esac + + case "$hostname_fqdn" in + [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1) hfqdn=true;; + [Ss][Ee][Rr][Vv][Ee][Rr]) ;; + *) hshort=true;; + esac + + if [ -n "$old_fqdn" ]; then + if ${hfqdn} || ! ${hsort}; then + [ "$hostname" = "$old_fqdn" ] + else + [ "$hostname" = "${old_fqdn%%.*}" ] + fi + elif [ -n "$old_host_name" ]; then + if ${hfqdn}; then + if [ -n "$old_domain_name" -a \ + "$old_host_name" = "${old_host_name#*.}" ] + then + [ "$hostname" = \ + "$old_host_name.$old_domain_name" ] + else + [ "$hostname" = "$old_host_name" ] + fi + elif ${hshort}; then + [ "$hostname" = "${old_host_name%%.*}" ] + else + [ "$hostname" = "$old_host_name" ] + fi + else + # No old hostname + false + fi +} + +try_hostname() +{ + + if valid_domainname "$1"; then + _hostname "$1" + else + syslog err "Invalid hostname: $1" + fi +} + +set_hostname() +{ + local hfqdn=false hshort=false + + need_hostname || return + + case "$hostname_fqdn" in + [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1) hfqdn=true;; + "") ;; + *) hshort=true;; + esac + + if [ -n "$new_fqdn" ]; then + if ${hfqdn} || ! ${hshort}; then + try_hostname "$new_fqdn" + else + try_hostname "${new_fqdn%%.*}" + fi + elif [ -n "$new_host_name" ]; then + if ${hfqdn}; then + if [ -n "$new_domain_name" -a \ + "$new_host_name" = "${new_host_name#*.}" ] + then + try_hostname "$new_host_name.$new_domain_name" + else + try_hostname "$new_host_name" + fi + elif ${hshort}; then + try_hostname "${new_host_name%%.*}" + else + try_hostname "$new_host_name" + fi + fi +} + +# For ease of use, map DHCP6 names onto our DHCP4 names +case "$reason" in +BOUND6|RENEW6|REBIND6|REBOOT6|INFORM6) + new_fqdn="$new_dhcp6_fqdn" + ;; +esac + +if $if_up; then + set_hostname +fi |