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