1 /* 2 * lib/krb5/os/hostaddr.c 3 * 4 * Copyright 1990,1991 by the Massachusetts Institute of Technology. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 * 26 * This routine returns a list of krb5 addresses given a hostname. 27 * 28 */ 29 30 #include "k5-int.h" 31 32 #include "fake-addrinfo.h" 33 34 krb5_error_code 35 krb5_os_hostaddr(krb5_context context, const char *name, krb5_address ***ret_addrs) 36 { 37 krb5_error_code retval; 38 krb5_address **addrs; 39 int i, j, r; 40 struct addrinfo hints, *ai, *aip; 41 42 if (!name) 43 return KRB5_ERR_BAD_HOSTNAME; 44 45 memset (&hints, 0, sizeof (hints)); 46 hints.ai_flags = AI_NUMERICHOST; 47 /* We don't care what kind at this point, really, but without 48 this, we can get back multiple sockaddrs per address, for 49 SOCK_DGRAM, SOCK_STREAM, and SOCK_RAW. I haven't checked if 50 that's what the spec indicates. */ 51 hints.ai_socktype = SOCK_DGRAM; 52 53 r = getaddrinfo (name, 0, &hints, &ai); 54 if (r && AI_NUMERICHOST != 0) { 55 hints.ai_flags &= ~AI_NUMERICHOST; 56 r = getaddrinfo (name, 0, &hints, &ai); 57 } 58 if (r) 59 return KRB5_ERR_BAD_HOSTNAME; 60 61 for (i = 0, aip = ai; aip; aip = aip->ai_next) { 62 switch (aip->ai_addr->sa_family) { 63 case AF_INET: 64 #ifdef KRB5_USE_INET6 65 case AF_INET6: 66 #endif 67 i++; 68 default: 69 /* Ignore addresses of unknown families. */ 70 ; 71 } 72 } 73 74 addrs = malloc ((i+1) * sizeof(*addrs)); 75 if (!addrs) 76 return errno; 77 78 for (j = 0; j < i + 1; j++) 79 addrs[j] = 0; 80 81 for (i = 0, aip = ai; aip; aip = aip->ai_next) { 82 void *ptr; 83 size_t addrlen; 84 int atype; 85 86 switch (aip->ai_addr->sa_family) { 87 case AF_INET: 88 addrlen = sizeof (struct in_addr); 89 /*LINTED*/ 90 ptr = &sa2sin(aip->ai_addr)->sin_addr; 91 atype = ADDRTYPE_INET; 92 break; 93 #ifdef KRB5_USE_INET6 94 case AF_INET6: 95 addrlen = sizeof (struct in6_addr); 96 /*LINTED*/ 97 ptr = &sa2sin6(aip->ai_addr)->sin6_addr; 98 atype = ADDRTYPE_INET6; 99 break; 100 #endif 101 default: 102 continue; 103 } 104 addrs[i] = (krb5_address *) malloc(sizeof(krb5_address)); 105 if (!addrs[i]) { 106 retval = ENOMEM; 107 goto errout; 108 } 109 addrs[i]->magic = KV5M_ADDRESS; 110 addrs[i]->addrtype = atype; 111 addrs[i]->length = addrlen; 112 addrs[i]->contents = malloc(addrs[i]->length); 113 if (!addrs[i]->contents) { 114 retval = ENOMEM; 115 goto errout; 116 } 117 memcpy (addrs[i]->contents, ptr, addrs[i]->length); 118 i++; 119 } 120 121 *ret_addrs = addrs; 122 if (ai) 123 freeaddrinfo(ai); 124 return 0; 125 126 errout: 127 /* Solaris Kerberos */ 128 if (addrs) 129 krb5_free_addresses(context, addrs); 130 if (ai) 131 freeaddrinfo(ai); 132 return retval; 133 134 } 135 136