xref: /netbsd-src/external/ibm-public/postfix/dist/src/dns/dns_rr_eq_sa.c (revision c48c605c14fd8622b523d1d6a3f0c0bad133ea89)
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 
dns_rr_eq_sa(DNS_RR * rr,struct sockaddr * sa)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 
usage(void)90 static NORETURN usage(void)
91 {
92     msg_fatal("usage: %s hostname address", myname);
93 }
94 
compare_family(const void * a,const void * b)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 
main(int argc,char ** argv)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