Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / dns / dns_rr_to_sa.c
blob974d6357efdab2f1f3f9f9a23d39bd26678c4d0d
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* dns_rr_to_sa 3
6 /* SUMMARY
7 /* resource record to socket address
8 /* SYNOPSIS
9 /* #include <dns.h>
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.
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 /*--*/
44 /* System libraries. */
46 #include <sys_defs.h>
47 #include <errno.h>
49 /* Utility library. */
51 #include <msg.h>
53 /* DNS library. */
55 #include <dns.h>
57 /* dns_rr_to_sa - resource record to socket address */
59 int dns_rr_to_sa(DNS_RR *rr, unsigned port, struct sockaddr * sa,
60 SOCKADDR_SIZE *sa_length)
62 SOCKADDR_SIZE sock_addr_len;
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((char *) 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);
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((char *) 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);
101 #endif
102 } else {
103 errno = EAFNOSUPPORT;
104 return (-1);
109 * Stand-alone test program.
111 #ifdef TEST
112 #include <stdlib.h>
114 #include <stringops.h>
115 #include <vstream.h>
116 #include <myaddrinfo.h>
118 static const char *myname;
120 static NORETURN usage(void)
122 msg_fatal("usage: %s dnsaddrtype hostname portnumber", myname);
125 int main(int argc, char **argv)
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;
137 myname = argv[0];
138 if (argc < 4)
139 usage();
140 why = vstring_alloc(1);
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);
161 vstring_free(why);
162 return (0);
165 #endif