Check for valid hostnames

Hello,

I am trying to develop a script to check for valid hostnames. Below are the prerequisites for a valid hostname which I got from wiki :

Hostnames are composed of series of labels concatenated with dots, as are all domain names. For example, "en.wikipedia.org" is a hostname. Each label must be between 1 and 63 characters long, and the entire hostname (including the delimiting dots but not a trailing dot) has a maximum of 253 ASCII characters.

The Internet standards (Requests for Comments) for protocols mandate that component hostname labels may contain only the ASCII letters 'a' through 'z' (in a case-insensitive manner), the digits '0' through '9', and the hyphen ('-'). The original specification of hostnames in RFC 952, mandated that labels could not start with a digit or with a hyphen, and must not end with a hyphen. However, a subsequent specification (RFC 1123) permitted hostname labels to start with digits. No other symbols, punctuation characters, or white space are permitted.

Could someone please help.

Thanks
Rahul

Hello Rahul,

Good to see you in forums :b:. Regarding above query I would like to say it completely depends on the organization like they are really following the mentioned rules/guidelines or not. Why not do a ping test for each host and find out(means--> if a host is valid it will pass the test), please do let me know your thoughts on same.

Thanks,
R. Singh

Hello Ravinder,

Thanks for your reply. :slight_smile: I am actually developing a script to configure hostname. The script which will ask the user for the hostname. It will check for all the conditions mentioned in my previous mail and validate if the user has entered hostname as per the correct naming convention. If the user has not adhered to the valid hostname convention then script will echo error else script will proceed and make changes specific to the hostname in the RedHat configuration files.

Thanks
Rahul

Hello rahul2662,

Could you please try following and let me know if this helps and covers your conditions, though I haven't tested it.

 echo "Please enter the name:"
read NAME
ONE=1
 VALUE=`echo $NAME | awk -F"." '{if(length($0)<=63 && NF==3 && $0 !~ /\.$/ && $0 !~ /^[[:digit:]]/ && $0 !~ /^-/ && $0 !~ /-$/ && $0 !~ /[[:space:]]/ && $0 !~ /[[:punct:]]/ && $0 !~ /[[:cntrl:]]/){print 1}}'`
 if [[ $VALUE == $ONE ]]
then
        echo "You have entered correct name as " $NAME
else
        echo "Please enter correct name as it is matching the standards."
fi
 

It is taking care of following conditions too.
i- length should be 63 char long.
ii- 3 dots.
iii- NO trailing dot at last of variable.
iv- should not start with a digit and hyphen, should not end with hyphen too.
v- no other symbols, punctuations, white spaces.
Could you please more elaborate about following point.

Thanks,
R. Singh

Hello Ravinder,

Below conditions should be satisfied for a valid hostname :

1) Maximum 3 dots ( can have zero dots as well)
2) maximum 63 characters within each dot

for example below should be a valid hostname

]$ksh hostnamecheck.ksh
Please enter the name:
newhost
Please enter correct name as it is matching the standards.

Thanks
Rahul

Hello rahul2662,

Could you please try following and let me know how it goes then.

echo "Please enter the name:"
read NAME
ONE=1
VALUE=`echo $NAME | awk '{if(length($0)<=253 && $0 !~ /\.$/ && $0 !~ /^[[:digit:]]/ && $0 !~ /^-/ && $0 !~ /-$/ && $0 !~ /[[:space:]]/ && $0 !~ /[[:punct:]]/ && $0 !~ /[[:cntrl:]]/){num=split($0, A,".");if(num==1){print 1}} else {for(i=1;i<=num;i++){if(length(A)<=63){k++}}};if(k==num){print 1}}'`
if [[ $VALUE == $ONE ]]
then
        echo "You have entered correct name as " $NAME
else
        echo "Please enter correct name as it is NOT matching the standards."
fi

You should check all permutations and combinations for above example too. Please let me know if you have any queries on same.

EDIT: I have added logic to check 0 occurrences for DOT too now in above code. Adding a more clarifying one liner form of awk within script.

echo "Please enter the name:"
read NAME
ONE=1
VALUE=`echo $NAME | awk '{
                                if(length($0)<=253 && $0 !~ /\.$/ && $0 !~ /^[[:digit:]]/ && $0 !~ /^-/ && $0 !~ /-$/ && $0 !~ /[[:space:]]/ && $0 !~ /[[:punct:]]/ && $0 !~ /[[:cntrl:]]/)      {
                                num=split($0, A,".");
                                if(num==1){
                                                print 1
                                          }
                                else      {
                                                for(i=1;i<=num;i++){
                                                                        if(length(A)<=63){
                                                                                                k++
                                                                                          }
                                                                   };
                                                                   }
                                          }
                                if(k==num){
                                                print 1
                                          }
                          }
                        '`
if [[ $VALUE == $ONE ]]
then
        echo "You have entered correct name as " $NAME
else
        echo "Please enter corect name as it is NOT matching the standards."
fi

Thanks,
R. Singh

How about (pure recent bash ):

read NAME
IFS="."; NARR=($NAME)
ST=1
for i in ${!NARR[@]}; do [ ${#NARR[$i]} -gt 63 ] && { ST=0; break; }; done
[ ${#NAME} -le 253 ] && [ ${#NARR[@]} -le 4 ] && [[ ! "$NAME" =~ [^[:alnum:].-] ]] && [ $ST -eq 1 ] && echo good || echo bad

Hello RudiC,

The following points also needs to be satisfied by the script for a valid hostname naming convention :

1) The hostname cannot start or end with a hyphen.

In the below example output should be bad :

$ ./hostchk.sh
Enter hostname
deda23-
good

$ ./hostchk.sh
Enter hostname
-dwedr
good


2) Hostnames are composed of series of labels concatenated with dots. Each label must be between 1 and 63 characters long. Hence we cannot have two dots together in the hostname ( ".." ) .Also we cannot have a dot in the beginning ( since each label must be between 1-63 characters).

In the below example output should be bad :

$ ./hostchk.sh
Enter hostname
deda1x..
good

$ ./hostchk_rudic.sh
Enter hostname
.deda
good

Hello rahul2662,

Could you please try following.

echo "Please enter the name:"
read NAME
ONE=1
VALUE=`echo $NAME | awk '{if($0 !~ /^\./ &&  $0 !~ /\.$/ && $0 !~ /^[[:digit:]]/ && $0 !~ /^-/ && $0 !~ /-$/ && $0 !~ /[[:space:]]/ && $0 !~ /[[:cntrl:]]/){num=split($0, A,".");if(num<=3){for(i=1;i<=num;i++){if(length(A)>63){exit};Q=Q?Q+length(A):length(A)};if(length(Q)<=189){print 1}}}}'`
 if [[ $VALUE == $ONE ]]
then
        echo "You have entered correct name as " $NAME
else
        echo "Please enter correct name as it is NOT matching the standards."
fi

Following are few tests which I ran for above code too.

##### Digit starting TEST.
./script.ksh
Please enter the name:
12334ewfwfwffw.defwfwwfw
Please enter correct name as it is NOT matching the standards.
  
##### DOT ending TEST.
./script.ksh
Please enter the name:
dwqfwfweffwfe.
Please enter correct name as it is NOT matching the standards.
  
##### Length of a field is more than 63 TEST.
./script.ksh
Please enter the name:
qdqeewfweffew.fwefwfewf.fweffwfwfwfwfwfwfwfwfwfwfwfwqcwdcwcwvwfwcwdvfdwgfeqseqrwqfw
Please enter correct name as it is NOT matching the standards.
  
##### Ending entry with an hyphen TEST.
./script.ksh
Please enter the name:
fefewfwefd-
Please enter correct name as it is NOT matching the standards.
  
##### starting with hyphen of entry TEST.
./script.ksh
Please enter the name:
-dwqwfwffwwv2131241.sqcwdwdcw
Please enter correct name as it is NOT matching the standards.

EDIT: Adding a non-one liner form of solution too now.

 echo "Please enter the name:"
read NAME
ONE=1
 VALUE=`echo $NAME | awk '{if($0 !~ /^\./ &&  $0 !~ /\.$/ && $0 !~ /^[[:digit:]]/ && $0 !~ /^-/ && $0 !~ /-$/ && $0 !~ /[[:space:]]/ && $0 !~ /[[:cntrl:]]/){
                          num=split($0, A,".");
                          if(num<=3){
                                        for(i=1;i<=num;i++){
                                                                if(length(A)>63){exit}
                                                                Q=Q?Q+length(A):length(A)
                                                           };
                                        if(length(Q)<=189) {
                                                                print 1
                                                           }
                                    }
                                                                                                                                           }
                          }'`
 if [[ $VALUE == $ONE ]]
then
        echo "You have entered correct name as " $NAME
else
        echo "Please enter corect name as it is NOT matching the standards."
fi
 

Also adding a working example too following.

 ./script.ksh
Please enter the name:
dqdqfdq.213124.wrgfrewge
You have entered correct name as  dqdqfdq.213124.wrgfrewge
 

Thanks,
R. Singh