diff options
Diffstat (limited to 'src/dns/dns_rr_eq_sa.c')
-rw-r--r-- | src/dns/dns_rr_eq_sa.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/dns/dns_rr_eq_sa.c b/src/dns/dns_rr_eq_sa.c new file mode 100644 index 0000000..8113d6b --- /dev/null +++ b/src/dns/dns_rr_eq_sa.c @@ -0,0 +1,157 @@ +/*++ +/* NAME +/* dns_rr_eq_sa 3 +/* SUMMARY +/* compare resource record with socket address +/* SYNOPSIS +/* #include <dns.h> +/* +/* 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 <sys_defs.h> + +/* Utility library. */ + +#include <msg.h> +#include <sock_addr.h> + +/* DNS library. */ + +#include <dns.h> + +/* 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 <stdlib.h> +#include <vstream.h> +#include <myaddrinfo.h> +#include <inet_proto.h> +#include <mymalloc.h> + +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 |