"""Regexes used in the DNS protocol""" def grpm(regex): """Make a matching group""" return grp(regex, matching=True) def grp(regex, matching=False): """Make a group""" return r'(' + (r'' if matching else r'?:') + regex + r')' def opt(regex): """Make an optional group""" return grp(grp(regex) + r'?') def regex_opt_r(*regexes): """Make a group that matches one of the given regexes""" return grp(r'|'.join(regexes)) DIGIT = r'\d' LETTER = r'[a-zA-Z]' LETDIG = grp(regex_opt_r(DIGIT, LETTER)) LETDIGHYP = grp(regex_opt_r(LETDIG, r'-')) LDHSTR = grp(LETDIGHYP + r'+') LABEL = grp(LETTER + opt(opt(LDHSTR) + LETDIG)) SUBDOMAIN = grp(grpm(grp(LABEL + r'\.') + r'*') + grpm(LABEL)) DOMAIN = regex_opt_r(SUBDOMAIN, r' ') # Fast, non-matching domain _DOMAIN = r'(?:(?:[a-zA-Z](?:[a-zA-Z\d\-]*[a-zA-Z\d])?\.)*)?' IP = r'(?:(?:\d{1,3}\.){3}\d{1,3})' CLASS = regex_opt_r(r'IN', r'CH') TYPE = regex_opt_r(r'A', r'CNAME', r'HINFO', r'MX', r'NS', r'PTR', r'SOA') TTL = r'\d+' RDATA = r'.*?' RR = regex_opt_r( grp(grpm(TTL) + r'\s+' + opt(grpm(CLASS))), grp(grpm(CLASS) + r'\s+' + opt(grpm(TTL))) ) + r'\s+' + grpm(TYPE) + r'\s+' + grpm(RDATA) + r'\s*(?:(?