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