1 /* $NetBSD: dns_rr_to_sa.c,v 1.1.1.1 2009/06/23 10:08:43 tron 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 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((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); 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((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); 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 120 static NORETURN usage(void) 121 { 122 msg_fatal("usage: %s dnsaddrtype hostname portnumber", myname); 123 } 124 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