/*++ /* NAME /* dns_sa_to_rr 3 /* SUMMARY /* socket address to resource record /* SYNOPSIS /* #include /* /* DNS_RR *dns_sa_to_rr(hostname, pref, sa) /* const char *hostname; /* unsigned pref; /* struct sockaddr *sa; /* DESCRIPTION /* dns_sa_to_rr() converts a socket address into a DNS resource record. /* /* Arguments: /* .IP hostname /* The resource record host name. This will be both the qname /* and the rname in the synthetic DNS resource record. /* .IP pref /* The resource record MX host preference, if applicable. /* .IP sa /* Binary address. /* DIAGNOSTICS /* The result is a null pointer in case of problems, with the /* errno variable set to indicate the problem type. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System libraries. */ #include #include /* Utility library. */ #include /* DNS library. */ #include /* dns_sa_to_rr - socket address to resource record */ DNS_RR *dns_sa_to_rr(const char *hostname, unsigned pref, struct sockaddr *sa) { #define DUMMY_TTL 0 if (sa->sa_family == AF_INET) { return (dns_rr_create(hostname, hostname, T_A, C_IN, DUMMY_TTL, pref, (char *) &SOCK_ADDR_IN_ADDR(sa), sizeof(SOCK_ADDR_IN_ADDR(sa)))); #ifdef HAS_IPV6 } else if (sa->sa_family == AF_INET6) { return (dns_rr_create(hostname, hostname, T_AAAA, C_IN, DUMMY_TTL, pref, (char *) &SOCK_ADDR_IN6_ADDR(sa), sizeof(SOCK_ADDR_IN6_ADDR(sa)))); #endif } else { errno = EAFNOSUPPORT; return (0); } } /* * Stand-alone test program. */ #ifdef TEST #include #include #include #include #include static const char *myname; static NORETURN usage(void) { msg_fatal("usage: %s hostname", myname); } static int compare_family(const void *a, const void *b) { struct addrinfo *resa = *(struct addrinfo **) a; struct addrinfo *resb = *(struct addrinfo **) b; return (resa->ai_family - resb->ai_family); } int main(int argc, char **argv) { MAI_HOSTADDR_STR hostaddr; struct addrinfo *res0; struct addrinfo *res; struct addrinfo **resv; size_t len, n; DNS_RR *rr; int aierr; myname = argv[0]; if (argc < 2) usage(); inet_proto_init(argv[0], INET_PROTO_NAME_ALL); while (*++argv) { if ((aierr = hostname_to_sockaddr(argv[0], (char *) 0, 0, &res0)) != 0) msg_fatal("%s: %s", argv[0], MAI_STRERROR(aierr)); for (len = 0, res = res0; res != 0; res = res->ai_next) len += 1; resv = (struct addrinfo **) mymalloc(len * sizeof(*resv)); for (len = 0, res = res0; res != 0; res = res->ai_next) resv[len++] = res; qsort((void *) resv, len, sizeof(*resv), compare_family); for (n = 0; n < len; n++) { if ((rr = dns_sa_to_rr(argv[0], 0, resv[n]->ai_addr)) == 0) msg_fatal("dns_sa_to_rr: %m"); if (dns_rr_to_pa(rr, &hostaddr) == 0) msg_fatal("dns_rr_to_pa: %m"); vstream_printf("%s -> %s\n", argv[0], hostaddr.buf); vstream_fflush(VSTREAM_OUT); dns_rr_free(rr); } freeaddrinfo(res0); myfree((void *) resv); } return (0); } #endif