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