Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: dns_rr_eq_sa.c,v 1.3 2023/12/23 20:30:43 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	dns_rr_eq_sa 3
      6 /* SUMMARY
      7 /*	compare resource record with socket address
      8 /* SYNOPSIS
      9 /*	#include <dns.h>
     10 /*
     11 /*	int	dns_rr_eq_sa(DNS_RR *rr, struct sockaddr *sa)
     12 /*	DNS_RR	*rr;
     13 /*	struct sockaddr *sa;
     14 /*
     15 /*	int	DNS_RR_EQ_SA(DNS_RR *rr, struct sockaddr *sa)
     16 /*	DNS_RR	*rr;
     17 /*	struct sockaddr *sa;
     18 /* DESCRIPTION
     19 /*	dns_rr_eq_sa() compares a DNS resource record with a socket
     20 /*	address.  The result is non-zero when the resource type
     21 /*	matches the socket address family, and when the network
     22 /*	address information is identical.
     23 /*
     24 /*	DNS_RR_EQ_SA() is an unsafe macro version for those who live fast.
     25 /*
     26 /*	Arguments:
     27 /* .IP rr
     28 /*	DNS resource record pointer.
     29 /* .IP sa
     30 /*	Binary address pointer.
     31 /* DIAGNOSTICS
     32 /*	Panic: unknown socket address family.
     33 /* LICENSE
     34 /* .ad
     35 /* .fi
     36 /*	The Secure Mailer license must be distributed with this software.
     37 /* AUTHOR(S)
     38 /*	Wietse Venema
     39 /*	IBM T.J. Watson Research
     40 /*	P.O. Box 704
     41 /*	Yorktown Heights, NY 10598, USA
     42 /*--*/
     43 
     44 /* System libraries. */
     45 
     46 #include <sys_defs.h>
     47 
     48 /* Utility library. */
     49 
     50 #include <msg.h>
     51 #include <sock_addr.h>
     52 
     53 /* DNS library. */
     54 
     55 #include <dns.h>
     56 
     57 /* dns_rr_eq_sa - compare resource record with socket address */
     58 
     59 int     dns_rr_eq_sa(DNS_RR *rr, struct sockaddr *sa)
     60 {
     61     const char *myname = "dns_rr_eq_sa";
     62 
     63     if (sa->sa_family == AF_INET) {
     64 	return (rr->type == T_A
     65 		&& SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR(rr->data).s_addr);
     66 #ifdef HAS_IPV6
     67     } else if (sa->sa_family == AF_INET6) {
     68 	return (rr->type == T_AAAA
     69 		&& memcmp((void *) &SOCK_ADDR_IN6_ADDR(sa),
     70 			  rr->data, rr->data_len) == 0);
     71 #endif
     72     } else {
     73 	msg_panic("%s: unsupported socket address family type: %d",
     74 		  myname, sa->sa_family);
     75     }
     76 }
     77 
     78  /*
     79   * Stand-alone test program.
     80   */
     81 #ifdef TEST
     82 #include <stdlib.h>
     83 #include <vstream.h>
     84 #include <myaddrinfo.h>
     85 #include <inet_proto.h>
     86 #include <mymalloc.h>
     87 
     88 static const char *myname;
     89 
     90 static NORETURN usage(void)
     91 {
     92     msg_fatal("usage: %s hostname address", myname);
     93 }
     94 
     95 static int compare_family(const void *a, const void *b)
     96 {
     97     struct addrinfo *resa = *(struct addrinfo **) a;
     98     struct addrinfo *resb = *(struct addrinfo **) b;
     99 
    100     return (resa->ai_family - resb->ai_family);
    101 }
    102 
    103 int     main(int argc, char **argv)
    104 {
    105     MAI_HOSTADDR_STR hostaddr;
    106     DNS_RR *rr;
    107     struct addrinfo *res0;
    108     struct addrinfo *res1;
    109     struct addrinfo *res;
    110     struct addrinfo **resv;
    111     size_t  len, n;
    112     int     aierr;
    113 
    114     myname = argv[0];
    115 
    116     if (argc < 3)
    117 	usage();
    118 
    119     inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
    120 
    121     while (*++argv) {
    122 	if (argv[1] == 0)
    123 	    usage();
    124 
    125 	if ((aierr = hostaddr_to_sockaddr(argv[1], (char *) 0, 0, &res1)) != 0)
    126 	    msg_fatal("host address %s: %s", argv[1], MAI_STRERROR(aierr));
    127 	if ((rr = dns_sa_to_rr(argv[1], DNS_RR_NOPREF, res1->ai_addr)) == 0)
    128 	    msg_fatal("dns_sa_to_rr: %m");
    129 	freeaddrinfo(res1);
    130 
    131 	if ((aierr = hostname_to_sockaddr(argv[0], (char *) 0, 0, &res0)) != 0)
    132 	    msg_fatal("host name %s: %s", argv[0], MAI_STRERROR(aierr));
    133 	for (len = 0, res = res0; res != 0; res = res->ai_next)
    134 	    len += 1;
    135 	resv = (struct addrinfo **) mymalloc(len * sizeof(*resv));
    136 	for (len = 0, res = res0; res != 0; res = res->ai_next)
    137 	    resv[len++] = res;
    138 	qsort((void *) resv, len, sizeof(*resv), compare_family);
    139 	for (n = 0; n < len; n++) {
    140 	    SOCKADDR_TO_HOSTADDR(resv[n]->ai_addr, resv[n]->ai_addrlen,
    141 				 &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
    142 	    vstream_printf("%s =?= %s\n", hostaddr.buf, argv[1]);
    143 	    vstream_printf("tested by function: %s\n",
    144 			   dns_rr_eq_sa(rr, resv[n]->ai_addr) ?
    145 			   "yes" : "no");
    146 	    vstream_printf("tested by macro:    %s\n",
    147 			   DNS_RR_EQ_SA(rr, resv[n]->ai_addr) ?
    148 			   "yes" : "no");
    149 	}
    150 	dns_rr_free(rr);
    151 	freeaddrinfo(res0);
    152 	myfree((void *) resv);
    153 	vstream_fflush(VSTREAM_OUT);
    154 	argv += 1;
    155     }
    156     return (0);
    157 }
    158 
    159 #endif
    160