Home | History | Annotate | Line # | Download | only in dns
      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 
     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 
    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