/* * hostname-like (A, MX, WKS) owners can have "*" as their first label * but must otherwise be as a host name. */ int res_ownok(const char *dn) { if (asterchar(dn[0])) { if (periodchar(dn[1])) return (res_hnok(dn+2)); if (dn[1] == '\0') return (1); } return (res_hnok(dn)); }
/* * SOA RNAMEs and RP RNAMEs can have any printable character in their first * label, but the rest of the name has to look like a host name. */ int res_mailok( const char *dn ) { int ch, escaped = 0; /* "." is a valid missing representation */ if (*dn == '\0') return (1); /* otherwise <label>.<hostname> */ while ((ch = *dn++) != '\0') { if (!domainchar(ch)) return (0); if (!escaped && periodchar(ch)) break; if (escaped) escaped = 0; else if (bslashchar(ch)) escaped = 1; } if (periodchar(ch)) return (res_hnok(dn)); return (0); }
int valid_domainpart(const char *s) { struct in_addr ina; struct in6_addr ina6; char *c, domain[SMTPD_MAXDOMAINPARTSIZE]; const char *p; if (*s == '[') { if (strncasecmp("[IPv6:", s, 6) == 0) p = s + 6; else p = s + 1; if (strlcpy(domain, p, sizeof domain) >= sizeof domain) return 0; c = strchr(domain, (int)']'); if (!c || c[1] != '\0') return 0; *c = '\0'; if (inet_pton(AF_INET6, domain, &ina6) == 1) return 1; if (inet_pton(AF_INET, domain, &ina) == 1) return 1; return 0; } return res_hnok(s); }
static int hostent_add_alias(struct hostent_ext *h, const char *name, int isdname) { char buf[MAXDNAME]; size_t i, n; for (i = 0; i < MAXALIASES; i++) if (h->aliases[i] == NULL) break; if (i == MAXALIASES) return (0); if (isdname) { _asr_strdname(name, buf, sizeof buf); buf[strlen(buf)-1] = '\0'; if (!res_hnok(buf)) return (-1); name = buf; } n = strlen(name) + 1; if (h->pos + n >= h->end) return (0); h->aliases[i] = h->pos; memmove(h->pos, name, n); h->pos += n; return (0); }
static int hostent_set_cname(struct hostent_ext *h, const char *name, int isdname) { char buf[MAXDNAME]; size_t n; if (h->h.h_name) return (-1); if (isdname) { _asr_strdname(name, buf, sizeof buf); buf[strlen(buf) - 1] = '\0'; if (!res_hnok(buf)) return (-1); name = buf; } n = strlen(name) + 1; if (h->pos + n >= h->end) return (-1); h->h.h_name = h->pos; memmove(h->pos, name, n); h->pos += n; return (0); }
static int addrinfo_from_pkt(struct asr_query *as, char *pkt, size_t pktlen) { struct asr_unpack p; struct asr_dns_header h; struct asr_dns_query q; struct asr_dns_rr rr; int i; union { struct sockaddr sa; struct sockaddr_in sain; struct sockaddr_in6 sain6; } u; char buf[MAXDNAME], *c; _asr_unpack_init(&p, pkt, pktlen); _asr_unpack_header(&p, &h); for (; h.qdcount; h.qdcount--) _asr_unpack_query(&p, &q); for (i = 0; i < h.ancount; i++) { _asr_unpack_rr(&p, &rr); if (rr.rr_type != q.q_type || rr.rr_class != q.q_class) continue; memset(&u, 0, sizeof u); if (rr.rr_type == T_A) { #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN u.sain.sin_len = sizeof u.sain; #endif u.sain.sin_family = AF_INET; u.sain.sin_addr = rr.rr.in_a.addr; u.sain.sin_port = 0; } else if (rr.rr_type == T_AAAA) { #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN u.sain6.sin6_len = sizeof u.sain6; #endif u.sain6.sin6_family = AF_INET6; u.sain6.sin6_addr = rr.rr.in_aaaa.addr6; u.sain6.sin6_port = 0; } else continue; if (as->as.ai.hints.ai_flags & AI_CANONNAME) { _asr_strdname(rr.rr_dname, buf, sizeof buf); buf[strlen(buf) - 1] = '\0'; c = res_hnok(buf) ? buf : NULL; } else if (as->as.ai.hints.ai_flags & AI_FQDN) c = as->as.ai.fqdn; else c = NULL; if (addrinfo_add(as, &u.sa, c)) return (-1); /* errno set */ } return (0); }