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