package config import ( "fmt" "strings" "unicode" ) // ValidateName checks that a name follows shorewall naming conventions: // starts with a letter, composed of letters, digits, and underscores. func ValidateName(name, kind string) error { if len(name) == 0 { return fmt.Errorf("%s name is empty", kind) } if !unicode.IsLetter(rune(name[0])) { return fmt.Errorf("%s name %q must start with a letter", kind, name) } for _, r := range name { if !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != '_' { return fmt.Errorf("%s name %q contains invalid character %q", kind, name, r) } } return nil } // ValidateInterfaceRef checks that an interface reference is valid. // Strips any @suffix (e.g. "sit1@NONE" -> "sit1"), allows trailing + for wildcards. func ValidateInterfaceRef(name string) string { if idx := strings.IndexByte(name, '@'); idx >= 0 { name = name[:idx] } return name } // IsWildcardInterface returns true if the interface name is a wildcard (ends with +). func IsWildcardInterface(name string) bool { return strings.HasSuffix(name, "+") } // ValidateDNSName checks shorewall's DNS name rules: fully qualified, // minimum two periods. Returns an error if the name looks like a DNS name // but doesn't meet the requirements. func ValidateDNSName(name string) error { if !strings.Contains(name, ".") { return nil } count := strings.Count(name, ".") if count < 2 { trimmed := strings.TrimSuffix(name, ".") if strings.Count(trimmed, ".") < 1 { return fmt.Errorf("DNS name %q must be fully qualified with at least two periods", name) } } return nil }