/*++ /* NAME /* dns_rr_eq_sa 3 /* SUMMARY /* compare resource record with socket address /* SYNOPSIS /* #include /* /* int dns_rr_eq_sa(DNS_RR *rr, struct sockaddr *sa) /* DNS_RR *rr; /* struct sockaddr *sa; /* /* int DNS_RR_EQ_SA(DNS_RR *rr, struct sockaddr *sa) /* DNS_RR *rr; /* struct sockaddr *sa; /* DESCRIPTION /* dns_rr_eq_sa() compares a DNS resource record with a socket /* address. The result is non-zero when the resource type /* matches the socket address family, and when the network /* address information is identical. /* /* DNS_RR_EQ_SA() is an unsafe macro version for those who live fast. /* /* Arguments: /* .IP rr /* DNS resource record pointer. /* .IP sa /* Binary address pointer. /* DIAGNOSTICS /* Panic: unknown socket address family. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System libraries. */ #include /* Utility library. */ #include #include /* DNS library. */ #include /* dns_rr_eq_sa - compare resource record with socket address */ int dns_rr_eq_sa(DNS_RR *rr, struct sockaddr *sa) { const char *myname = "dns_rr_eq_sa"; if (sa->sa_family == AF_INET) { return (rr->type == T_A && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR(rr->data).s_addr); #ifdef HAS_IPV6 } else if (sa->sa_family == AF_INET6) { return (rr->type == T_AAAA && memcmp((void *) &SOCK_ADDR_IN6_ADDR(sa), rr->data, rr->data_len) == 0); #endif } else { msg_panic("%s: unsupported socket address family type: %d", myname, sa->sa_family); } } /* * Stand-alone test program. */ #ifdef TEST #include #include #include #include #include static const char *myname; static NORETURN usage(void) { msg_fatal("usage: %s hostname address", myname); } static int compare_family(const void *a, const void *b) { struct addrinfo *resa = *(struct addrinfo **) a; struct addrinfo *resb = *(struct addrinfo **) b; return (resa->ai_family - resb->ai_family); } int main(int argc, char **argv) { MAI_HOSTADDR_STR hostaddr; DNS_RR *rr; struct addrinfo *res0; struct addrinfo *res1; struct addrinfo *res; struct addrinfo **resv; size_t len, n; int aierr; myname = argv[0]; if (argc < 3) usage(); inet_proto_init(argv[0], INET_PROTO_NAME_ALL); while (*++argv) { if (argv[1] == 0) usage(); if ((aierr = hostaddr_to_sockaddr(argv[1], (char *) 0, 0, &res1)) != 0) msg_fatal("host address %s: %s", argv[1], MAI_STRERROR(aierr)); if ((rr = dns_sa_to_rr(argv[1], 0, res1->ai_addr)) == 0) msg_fatal("dns_sa_to_rr: %m"); freeaddrinfo(res1); if ((aierr = hostname_to_sockaddr(argv[0], (char *) 0, 0, &res0)) != 0) msg_fatal("host name %s: %s", argv[0], MAI_STRERROR(aierr)); for (len = 0, res = res0; res != 0; res = res->ai_next) len += 1; resv = (struct addrinfo **) mymalloc(len * sizeof(*resv)); for (len = 0, res = res0; res != 0; res = res->ai_next) resv[len++] = res; qsort((void *) resv, len, sizeof(*resv), compare_family); for (n = 0; n < len; n++) { SOCKADDR_TO_HOSTADDR(resv[n]->ai_addr, resv[n]->ai_addrlen, &hostaddr, (MAI_SERVPORT_STR *) 0, 0); vstream_printf("%s =?= %s\n", hostaddr.buf, argv[1]); vstream_printf("tested by function: %s\n", dns_rr_eq_sa(rr, resv[n]->ai_addr) ? "yes" : "no"); vstream_printf("tested by macro: %s\n", DNS_RR_EQ_SA(rr, resv[n]->ai_addr) ? "yes" : "no"); } dns_rr_free(rr); freeaddrinfo(res0); myfree((void *) resv); vstream_fflush(VSTREAM_OUT); argv += 1; } return (0); } #endif