1 /* $NetBSD: dns_rr_to_sa.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */
2
3 /*++
4 /* NAME
5 /* dns_rr_to_sa 3
6 /* SUMMARY
7 /* resource record to socket address
8 /* SYNOPSIS
9 /* #include <dns.h>
10 /*
11 /* int dns_rr_to_sa(rr, port, sa, sa_length)
12 /* DNS_RR *rr;
13 /* unsigned port;
14 /* struct sockaddr *sa;
15 /* SOCKADDR_SIZE *sa_length;
16 /* DESCRIPTION
17 /* dns_rr_to_sa() converts the address in a DNS resource record into
18 /* a socket address of the corresponding type.
19 /*
20 /* Arguments:
21 /* .IP rr
22 /* DNS resource record pointer.
23 /* .IP port
24 /* TCP or UDP port, network byte order.
25 /* .IP sa
26 /* Socket address pointer.
27 /* .IP sa_length
28 /* On input, the available socket address storage space.
29 /* On output, the amount of space actually used.
30 /* DIAGNOSTICS
31 /* The result is non-zero in case of problems, with the
32 /* error type returned via the errno variable.
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 #include <errno.h>
48
49 /* Utility library. */
50
51 #include <msg.h>
52
53 /* DNS library. */
54
55 #include <dns.h>
56
57 /* dns_rr_to_sa - resource record to socket address */
58
dns_rr_to_sa(DNS_RR * rr,unsigned port,struct sockaddr * sa,SOCKADDR_SIZE * sa_length)59 int dns_rr_to_sa(DNS_RR *rr, unsigned port, struct sockaddr *sa,
60 SOCKADDR_SIZE *sa_length)
61 {
62 SOCKADDR_SIZE sock_addr_len;
63
64 if (rr->type == T_A) {
65 if (rr->data_len != sizeof(SOCK_ADDR_IN_ADDR(sa))) {
66 errno = EINVAL;
67 return (-1);
68 } else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN_PTR(sa))) > *sa_length) {
69 errno = ENOSPC;
70 return (-1);
71 } else {
72 memset((void *) SOCK_ADDR_IN_PTR(sa), 0, sock_addr_len);
73 SOCK_ADDR_IN_FAMILY(sa) = AF_INET;
74 SOCK_ADDR_IN_PORT(sa) = port;
75 SOCK_ADDR_IN_ADDR(sa) = IN_ADDR(rr->data);
76 #ifdef HAS_SA_LEN
77 sa->sa_len = sock_addr_len;
78 #endif
79 *sa_length = sock_addr_len;
80 return (0);
81 }
82 #ifdef HAS_IPV6
83 } else if (rr->type == T_AAAA) {
84 if (rr->data_len != sizeof(SOCK_ADDR_IN6_ADDR(sa))) {
85 errno = EINVAL;
86 return (-1);
87 } else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN6_PTR(sa))) > *sa_length) {
88 errno = ENOSPC;
89 return (-1);
90 } else {
91 memset((void *) SOCK_ADDR_IN6_PTR(sa), 0, sock_addr_len);
92 SOCK_ADDR_IN6_FAMILY(sa) = AF_INET6;
93 SOCK_ADDR_IN6_PORT(sa) = port;
94 SOCK_ADDR_IN6_ADDR(sa) = IN6_ADDR(rr->data);
95 #ifdef HAS_SA_LEN
96 sa->sa_len = sock_addr_len;
97 #endif
98 *sa_length = sock_addr_len;
99 return (0);
100 }
101 #endif
102 } else {
103 errno = EAFNOSUPPORT;
104 return (-1);
105 }
106 }
107
108 /*
109 * Stand-alone test program.
110 */
111 #ifdef TEST
112 #include <stdlib.h>
113
114 #include <stringops.h>
115 #include <vstream.h>
116 #include <myaddrinfo.h>
117
118 static const char *myname;
119
usage(void)120 static NORETURN usage(void)
121 {
122 msg_fatal("usage: %s dnsaddrtype hostname portnumber", myname);
123 }
124
main(int argc,char ** argv)125 int main(int argc, char **argv)
126 {
127 DNS_RR *rr;
128 MAI_HOSTADDR_STR hostaddr;
129 MAI_SERVPORT_STR portnum;
130 struct sockaddr_storage ss;
131 struct sockaddr *sa = (struct sockaddr *) &ss;
132 SOCKADDR_SIZE sa_length = sizeof(ss);
133 VSTRING *why;
134 int type;
135 int port;
136
137 myname = argv[0];
138 if (argc < 4)
139 usage();
140 why = vstring_alloc(1);
141
142 while (*++argv) {
143 if (argv[1] == 0 || argv[2] == 0)
144 usage();
145 if ((type = dns_type(argv[0])) == 0)
146 usage();
147 if (!alldig(argv[2]) || (port = atoi(argv[2])) > 65535)
148 usage();
149 if (dns_lookup(argv[1], type, 0, &rr, (VSTRING *) 0, why) != DNS_OK)
150 msg_fatal("%s: %s", argv[1], vstring_str(why));
151 sa_length = sizeof(ss);
152 if (dns_rr_to_sa(rr, htons(port), sa, &sa_length) != 0)
153 msg_fatal("dns_rr_to_sa: %m");
154 SOCKADDR_TO_HOSTADDR(sa, sa_length, &hostaddr, &portnum, 0);
155 vstream_printf("%s %s -> %s %s\n",
156 argv[1], argv[2], hostaddr.buf, portnum.buf);
157 vstream_fflush(VSTREAM_OUT);
158 argv += 2;
159 dns_rr_free(rr);
160 }
161 vstring_free(why);
162 return (0);
163 }
164
165 #endif
166