1/*	$NetBSD$	*/
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
59int     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((char *) &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 <vstream.h>
83#include <myaddrinfo.h>
84#include <inet_proto.h>
85
86static const char *myname;
87
88static NORETURN usage(void)
89{
90    msg_fatal("usage: %s hostname address", myname);
91}
92
93int     main(int argc, char **argv)
94{
95    MAI_HOSTADDR_STR hostaddr;
96    DNS_RR *rr;
97    struct addrinfo *res0;
98    struct addrinfo *res1;
99    struct addrinfo *res;
100    int     aierr;
101
102    myname = argv[0];
103
104    if (argc < 3)
105	usage();
106
107    inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
108
109    while (*++argv) {
110	if (argv[1] == 0)
111	    usage();
112
113	if ((aierr = hostaddr_to_sockaddr(argv[1], (char *) 0, 0, &res1)) != 0)
114	    msg_fatal("host address %s: %s", argv[1], MAI_STRERROR(aierr));
115	if ((rr = dns_sa_to_rr(argv[1], 0, res1->ai_addr)) == 0)
116	    msg_fatal("dns_sa_to_rr: %m");
117	freeaddrinfo(res1);
118
119	if ((aierr = hostname_to_sockaddr(argv[0], (char *) 0, 0, &res0)) != 0)
120	    msg_fatal("host name %s: %s", argv[0], MAI_STRERROR(aierr));
121	for (res = res0; res != 0; res = res->ai_next) {
122	    SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
123				 &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
124	    vstream_printf("%s =?= %s\n", hostaddr.buf, argv[1]);
125	    vstream_printf("tested by function: %s\n",
126			   dns_rr_eq_sa(rr, res->ai_addr) ?
127			   "yes" : "no");
128	    vstream_printf("tested by macro:    %s\n",
129			   DNS_RR_EQ_SA(rr, res->ai_addr) ?
130			   "yes" : "no");
131	}
132	dns_rr_free(rr);
133	freeaddrinfo(res0);
134	vstream_fflush(VSTREAM_OUT);
135	argv += 1;
136    }
137    return (0);
138}
139
140#endif
141