
1: /* Host name canonicalization 2: 3: Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. 4: 5: Written by Derek Price <derek@ximbiot.com>. 6: 7: This program is free software; you can redistribute it and/or 8: modify it under the terms of the GNU General Public License as 9: published by the Free Software Foundation; either version 2, or (at 10: your option) any later version. 11: 12: This program is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with this program; if not, write to the Free Software Foundation, 19: Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 20: 21: #include <config.h> 22: 23: #include "canon-host.h" 24: 25: #include <string.h> 26: 27: #include "getaddrinfo.h" 28: 29: /* Store the last error for the single-threaded version of this function. */ 30: static int last_cherror; 31: 32: /* Single-threaded of wrapper for canon_host_r. After a NULL return, error 33: messages may be retrieved via ch_strerror(). */ 34: char * 35: canon_host (const char *host) 36: { 37: return canon_host_r (host, &last_cherror); 38: } 39: 40: /* Return a malloc'd string containing the canonical hostname associated with 41: HOST, or NULL if a canonical name cannot be determined. On NULL return, 42: if CHERROR is not NULL, set *CHERROR to an error code as returned by 43: getaddrinfo(). Use ch_strerror_r() or gai_strerror() to convert a *CHERROR 44: value to a string suitable for error messages. 45: 46: WARNINGS 47: HOST must be a string representation of a resolvable name for this host. 48: Strings containing an IP address in dotted decimal notation will be 49: returned as-is, without further resolution. 50: 51: The use of the word "canonical" in this context is unfortunate but 52: entrenched. The value returned by this function will be the end result 53: of the resolution of any CNAME chains in the DNS. There may only be one 54: such value for any given hostname, though the actual IP address 55: referenced by this value and the device using that IP address may each 56: actually have any number of such "canonical" hostnames. See the POSIX 57: getaddrinfo spec <http://www.opengroup.org/susv3xsh/getaddrinfo.html">, 58: RFC 1034 <http://www.faqs.org/rfcs/rfc1034.html>, & RFC 2181 59: <http://www.faqs.org/rfcs/rfc2181.html> for more on what this confusing 60: term really refers to. */ 61: char * 62: canon_host_r (char const *host, int *cherror) 63: { 64: char *retval = NULL; 65: static struct addrinfo hints; 66: struct addrinfo *res = NULL; 67: int status; 68: 69: hints.ai_flags = AI_CANONNAME; 70: status = getaddrinfo (host, NULL, &hints, &res); 71: if (!status) 72: { 73: /* http://lists.gnu.org/archive/html/bug-coreutils/2006-09/msg00300.html 74: says Darwin 7.9.0 getaddrinfo returns 0 but sets 75: res->ai_canonname to NULL. */ 76: retval = strdup (res->ai_canonname ? res->ai_canonname : host); 77: if (!retval && cherror) 78: *cherror = EAI_MEMORY; 79: freeaddrinfo (res); 80: } 81: else if (cherror) 82: *cherror = status; 83: 84: return retval; 85: } 86: 87: /* Return a string describing the last error encountered by canon_host. */ 88: const char * 89: ch_strerror (void) 90: { 91: return gai_strerror (last_cherror); 92: }