001package org.kuali.common.dns.util; 002 003import static com.google.common.base.Preconditions.checkArgument; 004import static org.kuali.common.util.base.Precondition.checkNotBlank; 005 006import java.util.List; 007 008import org.kuali.common.util.Ascii; 009 010import com.google.common.base.Splitter; 011 012public class DnsUtils { 013 014 private static final char DOT = '.'; 015 private static final char HYPHEN = '-'; 016 private static final int MAX_FQDN_LENGTH = 253; 017 private static final int MAX_LABEL_LENGTH = 63; 018 private static final Splitter SPLITTER = Splitter.on(DOT); 019 020 /** 021 * <p> 022 * Verify <code>fqdn</code> is a syntactically valid DNS name. 023 * </p> 024 * 025 * <p> 026 * See http://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax 027 * </p> 028 * 029 * @throws IllegalArgumentException 030 * If <code>fqdn</code> is not a syntactically valid DNS name. 031 */ 032 public static void validateFQDN(String fqdn) { 033 034 // Null, the empty string, and pure whitespace are not allowed 035 checkNotBlank(fqdn, "fqdn"); 036 037 // Max length is 253 characters 038 checkArgument(fqdn.length() <= MAX_FQDN_LENGTH, "[%s] is %s characters long. Max is %s", fqdn, fqdn.length(), MAX_FQDN_LENGTH); 039 040 // Split up the string using dot as a separator 041 List<String> labels = SPLITTER.splitToList(fqdn); 042 043 // Validate each portion of the dns name 044 for (String label : labels) { 045 validateLabel(label); 046 } 047 } 048 049 protected static void validateLabel(String label) { 050 051 // Null, the empty string, and pure whitespace are not allowed 052 checkNotBlank(label, "label"); 053 054 // Max length for an individual label is 63 characters 055 checkArgument(label.length() <= MAX_LABEL_LENGTH, "[%s] is %s characters long. Max is %s", label, label.length(), MAX_LABEL_LENGTH); 056 057 // Can't begin or end with a hyphen 058 checkArgument(label.charAt(0) != HYPHEN, "[%s] begins with %s", label, HYPHEN); 059 checkArgument(label.charAt(label.length() - 1) != HYPHEN, "[%s] ends with %s", label, HYPHEN); 060 061 // Only characters allowed are a..z, A..Z, 0..9, and the hyphen 062 checkArgument(isLetterDigitHyphen(label), "Only a..z, A..Z, 0..9, and the hyphen character are allowed"); 063 } 064 065 protected static boolean isLetterDigitHyphen(String label) { 066 char[] chars = label.toCharArray(); 067 for (char c : chars) { 068 if (!isLetterDigitHyphen(c)) { 069 return false; 070 } 071 } 072 return true; 073 } 074 075 protected static boolean isLetterDigitHyphen(char c) { 076 return Ascii.isLetter(c) || c == HYPHEN || Ascii.isDigit(c); 077 } 078 079}