15e01956fSGlenn Barry /*
25e01956fSGlenn Barry  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
35e01956fSGlenn Barry  */
47c478bd9Sstevel@tonic-gate /*
57c478bd9Sstevel@tonic-gate  * lib/krb5/os/hostaddr.c
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
87c478bd9Sstevel@tonic-gate  * All Rights Reserved.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
117c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
127c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
137c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
14*55fea89dSDan Cross  *
157c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
167c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
177c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
187c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
197c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
207c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
217c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
227c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
237c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
247c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
257c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
267c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
277c478bd9Sstevel@tonic-gate  * or implied warranty.
28*55fea89dSDan Cross  *
297c478bd9Sstevel@tonic-gate  * This routine returns a list of krb5 addresses given a hostname.
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
33159d09a2SMark Phalan #include "k5-int.h"
345e01956fSGlenn Barry #include <locale.h>
35159d09a2SMark Phalan #include "fake-addrinfo.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate krb5_error_code
krb5_os_hostaddr(krb5_context context,const char * name,krb5_address *** ret_addrs)38159d09a2SMark Phalan krb5_os_hostaddr(krb5_context context, const char *name, krb5_address ***ret_addrs)
397c478bd9Sstevel@tonic-gate {
407c478bd9Sstevel@tonic-gate     krb5_error_code 	retval;
417c478bd9Sstevel@tonic-gate     krb5_address 	**addrs;
427c478bd9Sstevel@tonic-gate     int			i, j, r;
437c478bd9Sstevel@tonic-gate     struct addrinfo hints, *ai, *aip;
447c478bd9Sstevel@tonic-gate 
455e01956fSGlenn Barry     if (!name) {
467c478bd9Sstevel@tonic-gate 	return KRB5_ERR_BAD_HOSTNAME;
475e01956fSGlenn Barry     }
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate     memset (&hints, 0, sizeof (hints));
507c478bd9Sstevel@tonic-gate     hints.ai_flags = AI_NUMERICHOST;
517c478bd9Sstevel@tonic-gate     /* We don't care what kind at this point, really, but without
527c478bd9Sstevel@tonic-gate        this, we can get back multiple sockaddrs per address, for
537c478bd9Sstevel@tonic-gate        SOCK_DGRAM, SOCK_STREAM, and SOCK_RAW.  I haven't checked if
547c478bd9Sstevel@tonic-gate        that's what the spec indicates.  */
557c478bd9Sstevel@tonic-gate     hints.ai_socktype = SOCK_DGRAM;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate     r = getaddrinfo (name, 0, &hints, &ai);
587c478bd9Sstevel@tonic-gate     if (r && AI_NUMERICHOST != 0) {
597c478bd9Sstevel@tonic-gate 	hints.ai_flags &= ~AI_NUMERICHOST;
607c478bd9Sstevel@tonic-gate 	r = getaddrinfo (name, 0, &hints, &ai);
617c478bd9Sstevel@tonic-gate     }
625e01956fSGlenn Barry     if (r) {
635e01956fSGlenn Barry         krb5_set_error_message(context, KRB5_ERR_BAD_HOSTNAME,
645e01956fSGlenn Barry 			    dgettext(TEXT_DOMAIN,
655e01956fSGlenn Barry 				    "Hostname cannot be canonicalized for '%s': %s"),
665e01956fSGlenn Barry 			    name, strerror(r));
677c478bd9Sstevel@tonic-gate 	return KRB5_ERR_BAD_HOSTNAME;
685e01956fSGlenn Barry     }
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate     for (i = 0, aip = ai; aip; aip = aip->ai_next) {
717c478bd9Sstevel@tonic-gate 	switch (aip->ai_addr->sa_family) {
727c478bd9Sstevel@tonic-gate 	case AF_INET:
737c478bd9Sstevel@tonic-gate #ifdef KRB5_USE_INET6
747c478bd9Sstevel@tonic-gate 	case AF_INET6:
757c478bd9Sstevel@tonic-gate #endif
767c478bd9Sstevel@tonic-gate 	    i++;
777c478bd9Sstevel@tonic-gate 	default:
787c478bd9Sstevel@tonic-gate 	    /* Ignore addresses of unknown families.  */
797c478bd9Sstevel@tonic-gate 	    ;
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate     }
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate     addrs = malloc ((i+1) * sizeof(*addrs));
847c478bd9Sstevel@tonic-gate     if (!addrs)
857c478bd9Sstevel@tonic-gate 	return errno;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate     for (j = 0; j < i + 1; j++)
887c478bd9Sstevel@tonic-gate 	addrs[j] = 0;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate     for (i = 0, aip = ai; aip; aip = aip->ai_next) {
917c478bd9Sstevel@tonic-gate 	void *ptr;
927c478bd9Sstevel@tonic-gate 	size_t addrlen;
937c478bd9Sstevel@tonic-gate 	int atype;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	switch (aip->ai_addr->sa_family) {
967c478bd9Sstevel@tonic-gate 	case AF_INET:
977c478bd9Sstevel@tonic-gate 	    addrlen = sizeof (struct in_addr);
987c478bd9Sstevel@tonic-gate 	    /*LINTED*/
997c478bd9Sstevel@tonic-gate 	    ptr = &sa2sin(aip->ai_addr)->sin_addr;
1007c478bd9Sstevel@tonic-gate 	    atype = ADDRTYPE_INET;
1017c478bd9Sstevel@tonic-gate 	    break;
1027c478bd9Sstevel@tonic-gate #ifdef KRB5_USE_INET6
1037c478bd9Sstevel@tonic-gate 	case AF_INET6:
1047c478bd9Sstevel@tonic-gate 	    addrlen = sizeof (struct in6_addr);
1057c478bd9Sstevel@tonic-gate 	    /*LINTED*/
1067c478bd9Sstevel@tonic-gate 	    ptr = &sa2sin6(aip->ai_addr)->sin6_addr;
1077c478bd9Sstevel@tonic-gate 	    atype = ADDRTYPE_INET6;
1087c478bd9Sstevel@tonic-gate 	    break;
1097c478bd9Sstevel@tonic-gate #endif
1107c478bd9Sstevel@tonic-gate 	default:
1117c478bd9Sstevel@tonic-gate 	    continue;
1127c478bd9Sstevel@tonic-gate 	}
1137c478bd9Sstevel@tonic-gate 	addrs[i] = (krb5_address *) malloc(sizeof(krb5_address));
1147c478bd9Sstevel@tonic-gate 	if (!addrs[i]) {
1157c478bd9Sstevel@tonic-gate 	    retval = ENOMEM;
1167c478bd9Sstevel@tonic-gate 	    goto errout;
1177c478bd9Sstevel@tonic-gate 	}
1187c478bd9Sstevel@tonic-gate 	addrs[i]->magic = KV5M_ADDRESS;
1197c478bd9Sstevel@tonic-gate 	addrs[i]->addrtype = atype;
1207c478bd9Sstevel@tonic-gate 	addrs[i]->length = addrlen;
1217c478bd9Sstevel@tonic-gate 	addrs[i]->contents = malloc(addrs[i]->length);
1227c478bd9Sstevel@tonic-gate 	if (!addrs[i]->contents) {
1237c478bd9Sstevel@tonic-gate 	    retval = ENOMEM;
1247c478bd9Sstevel@tonic-gate 	    goto errout;
1257c478bd9Sstevel@tonic-gate 	}
1267c478bd9Sstevel@tonic-gate 	memcpy (addrs[i]->contents, ptr, addrs[i]->length);
1277c478bd9Sstevel@tonic-gate 	i++;
1287c478bd9Sstevel@tonic-gate     }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate     *ret_addrs = addrs;
1317c478bd9Sstevel@tonic-gate     if (ai)
1327c478bd9Sstevel@tonic-gate 	freeaddrinfo(ai);
1337c478bd9Sstevel@tonic-gate     return 0;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate errout:
13635ea52c6SMark Phalan     /* Solaris Kerberos */
13735ea52c6SMark Phalan     if (addrs)
1387c478bd9Sstevel@tonic-gate 	krb5_free_addresses(context, addrs);
1397c478bd9Sstevel@tonic-gate     if (ai)
1407c478bd9Sstevel@tonic-gate 	freeaddrinfo(ai);
1417c478bd9Sstevel@tonic-gate     return retval;
142*55fea89dSDan Cross 
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
145