summaryrefslogtreecommitdiffstats
path: root/src/dns/dns_rr_eq_sa.c
blob: 8113d6b26d6b258f2356fb567a1ad2697ad56fb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*++
/* NAME
/*	dns_rr_eq_sa 3
/* SUMMARY
/*	compare resource record with socket address
/* SYNOPSIS
/*	#include <dns.h>
/*
/*	int	dns_rr_eq_sa(DNS_RR *rr, struct sockaddr *sa)
/*	DNS_RR	*rr;
/*	struct sockaddr *sa;
/*
/*	int	DNS_RR_EQ_SA(DNS_RR *rr, struct sockaddr *sa)
/*	DNS_RR	*rr;
/*	struct sockaddr *sa;
/* DESCRIPTION
/*	dns_rr_eq_sa() compares a DNS resource record with a socket
/*	address.  The result is non-zero when the resource type
/*	matches the socket address family, and when the network
/*	address information is identical.
/*
/*	DNS_RR_EQ_SA() is an unsafe macro version for those who live fast.
/*
/*	Arguments:
/* .IP rr
/*	DNS resource record pointer.
/* .IP sa
/*	Binary address pointer.
/* DIAGNOSTICS
/*	Panic: unknown socket address family.
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

/* System libraries. */

#include <sys_defs.h>

/* Utility library. */

#include <msg.h>
#include <sock_addr.h>

/* DNS library. */

#include <dns.h>

/* dns_rr_eq_sa - compare resource record with socket address */

int     dns_rr_eq_sa(DNS_RR *rr, struct sockaddr *sa)
{
    const char *myname = "dns_rr_eq_sa";

    if (sa->sa_family == AF_INET) {
	return (rr->type == T_A
		&& SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR(rr->data).s_addr);
#ifdef HAS_IPV6
    } else if (sa->sa_family == AF_INET6) {
	return (rr->type == T_AAAA
		&& memcmp((void *) &SOCK_ADDR_IN6_ADDR(sa),
			  rr->data, rr->data_len) == 0);
#endif
    } else {
	msg_panic("%s: unsupported socket address family type: %d",
		  myname, sa->sa_family);
    }
}

 /*
  * Stand-alone test program.
  */
#ifdef TEST
#include <stdlib.h>
#include <vstream.h>
#include <myaddrinfo.h>
#include <inet_proto.h>
#include <mymalloc.h>

static const char *myname;

static NORETURN usage(void)
{
    msg_fatal("usage: %s hostname address", myname);
}

static int compare_family(const void *a, const void *b)
{
    struct addrinfo *resa = *(struct addrinfo **) a;
    struct addrinfo *resb = *(struct addrinfo **) b;

    return (resa->ai_family - resb->ai_family);
}

int     main(int argc, char **argv)
{
    MAI_HOSTADDR_STR hostaddr;
    DNS_RR *rr;
    struct addrinfo *res0;
    struct addrinfo *res1;
    struct addrinfo *res;
    struct addrinfo **resv;
    size_t  len, n;
    int     aierr;

    myname = argv[0];

    if (argc < 3)
	usage();

    inet_proto_init(argv[0], INET_PROTO_NAME_ALL);

    while (*++argv) {
	if (argv[1] == 0)
	    usage();

	if ((aierr = hostaddr_to_sockaddr(argv[1], (char *) 0, 0, &res1)) != 0)
	    msg_fatal("host address %s: %s", argv[1], MAI_STRERROR(aierr));
	if ((rr = dns_sa_to_rr(argv[1], 0, res1->ai_addr)) == 0)
	    msg_fatal("dns_sa_to_rr: %m");
	freeaddrinfo(res1);

	if ((aierr = hostname_to_sockaddr(argv[0], (char *) 0, 0, &res0)) != 0)
	    msg_fatal("host name %s: %s", argv[0], MAI_STRERROR(aierr));
	for (len = 0, res = res0; res != 0; res = res->ai_next)
	    len += 1;
	resv = (struct addrinfo **) mymalloc(len * sizeof(*resv));
	for (len = 0, res = res0; res != 0; res = res->ai_next)
	    resv[len++] = res;
	qsort((void *) resv, len, sizeof(*resv), compare_family);
	for (n = 0; n < len; n++) {
	    SOCKADDR_TO_HOSTADDR(resv[n]->ai_addr, resv[n]->ai_addrlen,
				 &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
	    vstream_printf("%s =?= %s\n", hostaddr.buf, argv[1]);
	    vstream_printf("tested by function: %s\n",
			   dns_rr_eq_sa(rr, resv[n]->ai_addr) ?
			   "yes" : "no");
	    vstream_printf("tested by macro:    %s\n",
			   DNS_RR_EQ_SA(rr, resv[n]->ai_addr) ?
			   "yes" : "no");
	}
	dns_rr_free(rr);
	freeaddrinfo(res0);
	myfree((void *) resv);
	vstream_fflush(VSTREAM_OUT);
	argv += 1;
    }
    return (0);
}

#endif