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