1#!/bin/sh -- 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22 23# Check hostname configuration as per the sendmail code. 24# 25# See http://www.sendmail.org/sun-specific/migration.html#FQHN for details. 26# 27# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 28# Use is subject to license terms. 29# 30 31PATH=/bin:/usr/sbin 32 33# If $1 has a ".", accept it and exit. 34 35accept_if_fully_qualified() { 36 case $1 in 37 *.*) 38 echo "Hostname $myhostname OK: fully qualified as $1" 39 exit 0 40 ;; 41 esac 42} 43 44# Check the `getent hosts $1` output, skipping the 1st entry (IP address). 45 46check_gethostbyname() { 47 for host in `getent hosts $1 | awk '{for (f=2; f <= NF; f++) print $f}'` 48 do 49 accept_if_fully_qualified $host 50 done 51} 52 53# Parse /etc/hosts, looking for $1 as an entry by itself, and try to find 54# a long name on the same line. First kill all comments, then check for 55# $1 as a word by itself, then take just the first such line, then skip 56# its first entry (IP address). 57 58check_hosts_file() { 59 for entry in `sed -e 's/#.*$//' /etc/hosts | \ 60 awk '/[ ]'$1'([ ]|$)/ \ 61 {for (f=2; f <= NF; f++) print $f; exit}'` 62 do 63 accept_if_fully_qualified $entry 64 done 65} 66 67# Parse the output of `nslookup $1`, checking the Name and Aliases. 68 69check_dns() { 70 for host in `nslookup $1 2>/dev/null | \ 71 awk '$1 == "Name:" || $1 == "Aliases:"{print $2}'` 72 do 73 accept_if_fully_qualified $host 74 done 75} 76 77# Check the `ypmatch $1 hosts` output, skipping the 1st entry (IP address). 78 79check_nis() { 80 for hst in `ypmatch $1 hosts | awk '{for (f=2; f <= NF; f++) print $f}'` 81 do 82 accept_if_fully_qualified $hst 83 done 84} 85 86# Recommend how to reconfigure to get $1.$2 as the FQHN. 87# $3 is the first entry for hosts in /etc/nsswitch.conf . 88 89suggest_fix_and_exit() { 90 myhost=$1 91 suggested_domain=$2 92 fhe=$3 93 myipaddr=`getent hosts $myhost | head -1 | awk '{print $1}'` 94 95 # aliases: skip the 1st & 2nd entries: IP address & canonical name 96 97 set -- '' '' '[ aliases ... ]' 98 set -- `grep "^$myipaddr[ ]" /etc/hosts 2>/dev/null` 99 result=$? 100 shift 2 101 echo "We recommend \c" 102 if [ "x$fhe" != "xfiles" ] ; then 103 echo "listing files first for hosts in /etc/nsswitch.conf" 104 echo "and then \c" 105 fi 106 if [ $result = 0 ] ; then 107 echo "changing the /etc/hosts entry:\n" 108 echo "$myipaddr $myhost $*\n" 109 echo "to:\n" 110 else 111 echo "adding the /etc/hosts entry:\n" 112 fi 113 echo "$myipaddr $myhost $myhost.$suggested_domain $*" 114 exit 0 115} 116 117# Fall back to the NIS domain, minus the first label. If it is non-null, 118# use it but recommend against it. $2 is just informative, indicating whether 119# we're checking the NIS domain. $3 is to pass on. 120 121check_nis_domain() { 122 nisdomain=`domainname` 123 realdomain=`echo $nisdomain | sed 's/[^.]*\.//'` 124 if [ "x$realdomain" != "x" ] ; then 125 echo "Hostname $1 can be fully qualified using NIS$2 domain" 126 echo " $nisdomain" 127 echo "resulting in the name" 128 echo " $1.$realdomain" 129 echo "but this is bad practice.\n" 130 suggest_fix_and_exit $1 $realdomain $3 131 fi 132} 133 134# Goal: try to fully qualify `hostname` as sendmail would. 135# Algorithm (stop as soon as a name with a dot is found): 136# 1. gethostbyname (simulate with getent hosts) 137# 2. fall back to individual hosts: methods in nsswitch.conf, using 138# only those that are configured, in their configured order 139# * files (parse /etc/hosts directly) 140# * dns (parse nslookup output) 141# * nis (parse ypmatch output) 142# 3. fall back to the NIS domain name. 143# If none of the above succeed, give up. Recommend: 144# a. the domain entry in /etc/resolv.conf, if one exists 145# b. "pick.some.domain" 146 147myhostname=`hostname` 148 149check_gethostbyname $myhostname 150 151hosts_line=`sed -n -e 's/^hosts:\([^#]*\).*/\1/p' /etc/nsswitch.conf` 152first_hosts_entry=`echo $hosts_line | awk '{print $1}'` 153nis_domains="" 154 155for entry in $hosts_line 156do 157 case $entry in 158 files) 159 check_hosts_file $myhostname 160 ;; 161 dns) 162 check_dns $myhostname 163 ;; 164 nis) 165 check_nis $myhostname 166 nis_domains="$nis_domains nis" 167 ;; 168 esac 169done 170 171for entry in $nis_domains 172do 173 case $entry in 174 nis) 175 check_nis_domain $myhostname "" $first_hosts_entry 176 ;; 177 esac 178done 179 180realdomain=`awk '$1 ~ /^domain/ {print $2}' 2>/dev/null < /etc/resolv.conf` 181case $realdomain in 182*.*) 183 # OK 184 ;; 185*) 186 realdomain="pick.some.domain" 187 ;; 188esac 189 190echo "Hostname $myhostname could not be fully qualified." 191suggest_fix_and_exit $myhostname $realdomain $first_hosts_entry 192