X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=cups%2Fhttp-addr.c;h=86749c84856ad7f56a86e601e1522c3ef10e8614;hb=87030afb3aa8735848c66a0526d06af69d7010c6;hp=0bc71f6fa711f08e172bd68cfd5a0127bef06672;hpb=5f64df29828e9ca71164342efd357e9debfb6e44;p=thirdparty%2Fcups.git diff --git a/cups/http-addr.c b/cups/http-addr.c index 0bc71f6fa..86749c848 100644 --- a/cups/http-addr.c +++ b/cups/http-addr.c @@ -1,44 +1,35 @@ /* - * "$Id: http-addr.c 6814 2007-08-20 20:09:25Z mike $" + * HTTP address routines for CUPS. * - * HTTP address routines for the Common UNIX Printing System (CUPS). + * Copyright 2007-2019 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * Copyright 2007-2008 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * httpAddrAny() - Check for the "any" address. - * httpAddrEqual() - Compare two addresses. - * httpAddrLocalhost() - Check for the local loopback address. - * httpAddrLookup() - Lookup the hostname associated with the address. - * _httpAddrPort() - Get the port number associated with an address. - * httpAddrString() - Convert an IP address to a dotted string. - * httpGetHostByName() - Lookup a hostname or IP address, and return - * address records for the specified name. - * httpGetHostname() - Get the FQDN for the local system. + * Licensed under Apache License v2.0. See the file "LICENSE" for more + * information. */ /* * Include necessary headers... */ -#include "globals.h" -#include "debug.h" -#include -#include +#include "cups-private.h" +#include "debug-internal.h" +#include +#ifdef HAVE_RESOLV_H +# include +#endif /* HAVE_RESOLV_H */ +#ifdef __APPLE__ +# include +# ifdef HAVE_SCDYNAMICSTORECOPYCOMPUTERNAME +# include +# endif /* HAVE_SCDYNAMICSTORECOPYCOMPUTERNAME */ +#endif /* __APPLE__ */ /* * 'httpAddrAny()' - Check for the "any" address. * - * @since CUPS 1.2@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 1 if "any", 0 otherwise */ @@ -61,10 +52,41 @@ httpAddrAny(const http_addr_t *addr) /* I - Address to check */ } +/* + * 'httpAddrClose()' - Close a socket created by @link httpAddrConnect@ or + * @link httpAddrListen@. + * + * Pass @code NULL@ for sockets created with @link httpAddrConnect2@ and the + * listen address for sockets created with @link httpAddrListen@. This function + * ensures that domain sockets are removed when closed. + * + * @since CUPS 2.0/OS 10.10@ + */ + +int /* O - 0 on success, -1 on failure */ +httpAddrClose(http_addr_t *addr, /* I - Listen address or @code NULL@ */ + int fd) /* I - Socket file descriptor */ +{ +#ifdef _WIN32 + if (closesocket(fd)) +#else + if (close(fd)) +#endif /* _WIN32 */ + return (-1); + +#ifdef AF_LOCAL + if (addr && addr->addr.sa_family == AF_LOCAL) + return (unlink(addr->un.sun_path)); +#endif /* AF_LOCAL */ + + return (0); +} + + /* * 'httpAddrEqual()' - Compare two addresses. * - * @since CUPS 1.2@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 1 if equal, 0 if not */ @@ -97,7 +119,7 @@ httpAddrEqual(const http_addr_t *addr1, /* I - First address */ /* * 'httpAddrLength()' - Return the length of the address in bytes. * - * @since CUPS 1.2@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - Length in bytes */ @@ -113,8 +135,7 @@ httpAddrLength(const http_addr_t *addr) /* I - Address */ #endif /* AF_INET6 */ #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) - return (offsetof(struct sockaddr_un, sun_path) + - strlen(addr->un.sun_path) + 1); + return ((int)(offsetof(struct sockaddr_un, sun_path) + strlen(addr->un.sun_path) + 1)); else #endif /* AF_LOCAL */ if (addr->addr.sa_family == AF_INET) @@ -125,10 +146,137 @@ httpAddrLength(const http_addr_t *addr) /* I - Address */ } +/* + * 'httpAddrListen()' - Create a listening socket bound to the specified + * address and port. + * + * @since CUPS 1.7/macOS 10.9@ + */ + +int /* O - Socket or -1 on error */ +httpAddrListen(http_addr_t *addr, /* I - Address to bind to */ + int port) /* I - Port number to bind to */ +{ + int fd = -1, /* Socket */ + val, /* Socket value */ + status; /* Bind status */ + + + /* + * Range check input... + */ + + if (!addr || port < 0) + return (-1); + + /* + * Create the socket and set options... + */ + + if ((fd = socket(addr->addr.sa_family, SOCK_STREAM, 0)) < 0) + { + _cupsSetHTTPError(HTTP_STATUS_ERROR); + return (-1); + } + + val = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, CUPS_SOCAST &val, sizeof(val)); + +#ifdef IPV6_V6ONLY + if (addr->addr.sa_family == AF_INET6) + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, CUPS_SOCAST &val, sizeof(val)); +#endif /* IPV6_V6ONLY */ + + /* + * Bind the socket... + */ + +#ifdef AF_LOCAL + if (addr->addr.sa_family == AF_LOCAL) + { + mode_t mask; /* Umask setting */ + + /* + * Remove any existing domain socket file... + */ + + unlink(addr->un.sun_path); + + /* + * Save the current umask and set it to 0 so that all users can access + * the domain socket... + */ + + mask = umask(0); + + /* + * Bind the domain socket... + */ + + status = bind(fd, (struct sockaddr *)addr, (socklen_t)httpAddrLength(addr)); + + /* + * Restore the umask and fix permissions... + */ + + umask(mask); + chmod(addr->un.sun_path, 0140777); + } + else +#endif /* AF_LOCAL */ + { + _httpAddrSetPort(addr, port); + + status = bind(fd, (struct sockaddr *)addr, (socklen_t)httpAddrLength(addr)); + } + + if (status) + { + _cupsSetHTTPError(HTTP_STATUS_ERROR); + + close(fd); + + return (-1); + } + + /* + * Listen... + */ + + if (listen(fd, 5)) + { + _cupsSetHTTPError(HTTP_STATUS_ERROR); + + close(fd); + + return (-1); + } + + /* + * Close on exec... + */ + +#ifndef _WIN32 + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); +#endif /* !_WIN32 */ + +#ifdef SO_NOSIGPIPE + /* + * Disable SIGPIPE for this socket. + */ + + val = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val)); +#endif /* SO_NOSIGPIPE */ + + return (fd); +} + + /* * 'httpAddrLocalhost()' - Check for the local loopback address. * - * @since CUPS 1.2@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 1 if local host, 0 otherwise */ @@ -150,24 +298,17 @@ httpAddrLocalhost( #endif /* AF_LOCAL */ if (addr->addr.sa_family == AF_INET && - ntohl(addr->ipv4.sin_addr.s_addr) == 0x7f000001) + (ntohl(addr->ipv4.sin_addr.s_addr) & 0xff000000) == 0x7f000000) return (1); return (0); } -#ifdef __sgi -# define ADDR_CAST (struct sockaddr *) -#else -# define ADDR_CAST (char *) -#endif /* __sgi */ - - /* * 'httpAddrLookup()' - Lookup the hostname associated with the address. * - * @since CUPS 1.2@ + * @since CUPS 1.2/macOS 10.5@ */ char * /* O - Host name */ @@ -176,8 +317,11 @@ httpAddrLookup( char *name, /* I - Host name buffer */ int namelen) /* I - Size of name buffer */ { - DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)\n", - addr, name, namelen)); + _cups_globals_t *cg = _cupsGlobals(); + /* Global data */ + + + DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)", (void *)addr, (void *)name, namelen)); /* * Range check input... @@ -193,9 +337,43 @@ httpAddrLookup( #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) - strlcpy(name, addr->un.sun_path, namelen); - else + { + strlcpy(name, addr->un.sun_path, (size_t)namelen); + return (name); + } #endif /* AF_LOCAL */ + + /* + * Optimize lookups for localhost/loopback addresses... + */ + + if (httpAddrLocalhost(addr)) + { + strlcpy(name, "localhost", (size_t)namelen); + return (name); + } + +#ifdef HAVE_RES_INIT + /* + * STR #2920: Initialize resolver after failure in cups-polld + * + * If the previous lookup failed, re-initialize the resolver to prevent + * temporary network errors from persisting. This *should* be handled by + * the resolver libraries, but apparently the glibc folks do not agree. + * + * We set a flag at the end of this function if we encounter an error that + * requires reinitialization of the resolver functions. We then call + * res_init() if the flag is set on the next call here or in httpAddrLookup(). + */ + + if (cg->need_res_init) + { + res_init(); + + cg->need_res_init = 0; + } +#endif /* HAVE_RES_INIT */ + #ifdef HAVE_GETNAMEINFO { /* @@ -206,9 +384,15 @@ httpAddrLookup( * do... */ - if (getnameinfo(&addr->addr, httpAddrLength(addr), name, namelen, - NULL, 0, 0)) + int error = getnameinfo(&addr->addr, (socklen_t)httpAddrLength(addr), name, (socklen_t)namelen, NULL, 0, 0); + + if (error) + { + if (error == EAI_FAIL) + cg->need_res_init = 1; + return (httpAddrString(addr, name, namelen)); + } } #else { @@ -217,11 +401,11 @@ httpAddrLookup( # ifdef AF_INET6 if (addr->addr.sa_family == AF_INET6) - host = gethostbyaddr(ADDR_CAST &(addr->ipv6.sin6_addr), + host = gethostbyaddr((char *)&(addr->ipv6.sin6_addr), sizeof(struct in_addr), AF_INET6); else # endif /* AF_INET6 */ - host = gethostbyaddr(ADDR_CAST &(addr->ipv4.sin_addr), + host = gethostbyaddr((char *)&(addr->ipv4.sin_addr), sizeof(struct in_addr), AF_INET); if (host == NULL) @@ -230,27 +414,47 @@ httpAddrLookup( * No hostname, so return the raw address... */ - httpAddrString(addr, name, namelen); - return (NULL); + if (h_errno == NO_RECOVERY) + cg->need_res_init = 1; + + return (httpAddrString(addr, name, namelen)); } - strlcpy(name, host->h_name, namelen); + strlcpy(name, host->h_name, (size_t)namelen); } #endif /* HAVE_GETNAMEINFO */ + DEBUG_printf(("1httpAddrLookup: returning \"%s\"...", name)); + return (name); } /* - * '_httpAddrPort()' - Get the port number associated with an address. + * 'httpAddrFamily()' - Get the address family of an address. + */ + +int /* O - Address family */ +httpAddrFamily(http_addr_t *addr) /* I - Address */ +{ + if (addr) + return (addr->addr.sa_family); + else + return (0); +} + + +/* + * 'httpAddrPort()' - Get the port number associated with an address. + * + * @since CUPS 1.7/macOS 10.9@ */ int /* O - Port number */ -_httpAddrPort(http_addr_t *addr) /* I - Address */ +httpAddrPort(http_addr_t *addr) /* I - Address */ { if (!addr) - return (ippPort()); + return (-1); #ifdef AF_INET6 else if (addr->addr.sa_family == AF_INET6) return (ntohs(addr->ipv6.sin6_port)); @@ -258,14 +462,35 @@ _httpAddrPort(http_addr_t *addr) /* I - Address */ else if (addr->addr.sa_family == AF_INET) return (ntohs(addr->ipv4.sin_port)); else - return (ippPort()); + return (0); +} + + +/* + * '_httpAddrSetPort()' - Set the port number associated with an address. + */ + +void +_httpAddrSetPort(http_addr_t *addr, /* I - Address */ + int port) /* I - Port */ +{ + if (!addr || port <= 0) + return; + +#ifdef AF_INET6 + if (addr->addr.sa_family == AF_INET6) + addr->ipv6.sin6_port = htons(port); + else +#endif /* AF_INET6 */ + if (addr->addr.sa_family == AF_INET) + addr->ipv4.sin_port = htons(port); } /* * 'httpAddrString()' - Convert an address to a numeric string. * - * @since CUPS 1.2@ + * @since CUPS 1.2/macOS 10.5@ */ char * /* O - Numeric address string */ @@ -273,8 +498,7 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ char *s, /* I - String buffer */ int slen) /* I - Length of string */ { - DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)\n", - addr, s, slen)); + DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)", (void *)addr, (void *)s, slen)); /* * Range check input... @@ -290,25 +514,31 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) - strlcpy(s, addr->un.sun_path, slen); + { + if (addr->un.sun_path[0] == '/') + strlcpy(s, addr->un.sun_path, (size_t)slen); + else + strlcpy(s, "localhost", (size_t)slen); + } else #endif /* AF_LOCAL */ if (addr->addr.sa_family == AF_INET) { unsigned temp; /* Temporary address */ - temp = ntohl(addr->ipv4.sin_addr.s_addr); - snprintf(s, slen, "%d.%d.%d.%d", (temp >> 24) & 255, + snprintf(s, (size_t)slen, "%d.%d.%d.%d", (temp >> 24) & 255, (temp >> 16) & 255, (temp >> 8) & 255, temp & 255); } #ifdef AF_INET6 else if (addr->addr.sa_family == AF_INET6) { + char *sptr, /* Pointer into string */ + temps[64]; /* Temporary string for address */ + # ifdef HAVE_GETNAMEINFO - if (getnameinfo(&addr->addr, httpAddrLength(addr), s, slen, - NULL, 0, NI_NUMERICHOST)) + if (getnameinfo(&addr->addr, (socklen_t)httpAddrLength(addr), temps, sizeof(temps), NULL, 0, NI_NUMERICHOST)) { /* * If we get an error back, then the address type is not supported @@ -319,29 +549,35 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ return (NULL); } + else if ((sptr = strchr(temps, '%')) != NULL) + { + /* + * Convert "%zone" to "+zone" to match URI form... + */ + + *sptr = '+'; + } + # else - char *sptr; /* Pointer into string */ int i; /* Looping var */ unsigned temp; /* Current value */ const char *prefix; /* Prefix for address */ prefix = ""; - for (sptr = s, i = 0; i < 4 && addr->ipv6.sin6_addr.s6_addr32[i]; i ++) + for (sptr = temps, i = 0; i < 4 && addr->ipv6.sin6_addr.s6_addr32[i]; i ++) { temp = ntohl(addr->ipv6.sin6_addr.s6_addr32[i]); - snprintf(sptr, slen, "%s%x", prefix, (temp >> 16) & 0xffff); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s%x", prefix, (temp >> 16) & 0xffff); prefix = ":"; - slen -= strlen(sptr); sptr += strlen(sptr); temp &= 0xffff; if (temp || i == 3 || addr->ipv6.sin6_addr.s6_addr32[i + 1]) { - snprintf(sptr, slen, "%s%x", prefix, temp); - slen -= strlen(sptr); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s%x", prefix, temp); sptr += strlen(sptr); } } @@ -353,24 +589,22 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ if (i < 4) { - snprintf(sptr, slen, "%s:", prefix); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s:", prefix); prefix = ":"; - slen -= strlen(sptr); sptr += strlen(sptr); for (; i < 4; i ++) { temp = ntohl(addr->ipv6.sin6_addr.s6_addr32[i]); - if ((temp & 0xffff0000) || addr->ipv6.sin6_addr.s6_addr32[i - 1]) + if ((temp & 0xffff0000) || + (i > 0 && addr->ipv6.sin6_addr.s6_addr32[i - 1])) { - snprintf(sptr, slen, "%s%x", prefix, (temp >> 16) & 0xffff); - slen -= strlen(sptr); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s%x", prefix, (temp >> 16) & 0xffff); sptr += strlen(sptr); } - snprintf(sptr, slen, "%s%x", prefix, temp & 0xffff); - slen -= strlen(sptr); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s%x", prefix, temp & 0xffff); sptr += strlen(sptr); } } @@ -380,9 +614,7 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ * Empty address... */ - strlcpy(s, "::", slen); - sptr = s + 2; - slen -= 2; + strlcpy(temps, "::", sizeof(temps)); } else { @@ -390,28 +622,54 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ * Empty at end... */ - strlcpy(sptr, "::", slen); - sptr += 2; - slen -= 2; + strlcpy(sptr, "::", sizeof(temps) - (size_t)(sptr - temps)); } } # endif /* HAVE_GETNAMEINFO */ + + /* + * Add "[v1." and "]" around IPv6 address to convert to URI form. + */ + + snprintf(s, (size_t)slen, "[v1.%s]", temps); } #endif /* AF_INET6 */ else - strlcpy(s, "UNKNOWN", slen); + strlcpy(s, "UNKNOWN", (size_t)slen); - DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s)); + DEBUG_printf(("1httpAddrString: returning \"%s\"...", s)); return (s); } +/* + * 'httpGetAddress()' - Get the address of the connected peer of a connection. + * + * For connections created with @link httpConnect2@, the address is for the + * server. For connections created with @link httpAccept@, the address is for + * the client. + * + * Returns @code NULL@ if the socket is currently unconnected. + * + * @since CUPS 2.0/OS 10.10@ + */ + +http_addr_t * /* O - Connected address or @code NULL@ */ +httpGetAddress(http_t *http) /* I - HTTP connection */ +{ + if (http) + return (http->hostaddr); + else + return (NULL); +} + + /* * 'httpGetHostByName()' - Lookup a hostname or IPv4 address, and return * address records for the specified name. * - * @deprecated@ + * @deprecated@ @exclude all@ */ struct hostent * /* O - Host entry */ @@ -423,7 +681,7 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */ /* Pointer to library globals */ - DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name)); + DEBUG_printf(("httpGetHostByName(name=\"%s\")", name)); /* * Avoid lookup delays and configuration problems when connecting @@ -456,12 +714,12 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */ cg->hostent.h_name = (char *)name; cg->hostent.h_aliases = NULL; cg->hostent.h_addrtype = AF_LOCAL; - cg->hostent.h_length = strlen(name) + 1; + cg->hostent.h_length = (int)strlen(name) + 1; cg->hostent.h_addr_list = cg->ip_ptrs; cg->ip_ptrs[0] = (char *)name; cg->ip_ptrs[1] = NULL; - DEBUG_puts("httpGetHostByName: returning domain socket address..."); + DEBUG_puts("1httpGetHostByName: returning domain socket address..."); return (&cg->hostent); } @@ -482,8 +740,9 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */ if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255) return (NULL); /* Invalid byte ranges! */ - cg->ip_addr = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | - ip[3])); + cg->ip_addr = htonl((((((((unsigned)ip[0] << 8) | (unsigned)ip[1]) << 8) | + (unsigned)ip[2]) << 8) | + (unsigned)ip[3])); /* * Fill in the host entry and return it... @@ -497,7 +756,7 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */ cg->ip_ptrs[0] = (char *)&(cg->ip_addr); cg->ip_ptrs[1] = NULL; - DEBUG_puts("httpGetHostByName: returning IPv4 address..."); + DEBUG_puts("1httpGetHostByName: returning IPv4 address..."); return (&cg->hostent); } @@ -508,7 +767,7 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */ * the name... */ - DEBUG_puts("httpGetHostByName: returning domain lookup address(es)..."); + DEBUG_puts("1httpGetHostByName: returning domain lookup address(es)..."); return (gethostbyname(name)); } @@ -519,11 +778,12 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */ * 'httpGetHostname()' - Get the FQDN for the connection or local system. * * When "http" points to a connected socket, return the hostname or - * address that was used in the call to httpConnect() or httpConnectEncrypt(). + * address that was used in the call to httpConnect() or httpConnectEncrypt(), + * or the address of the client for the connection from httpAcceptConnection(). * Otherwise, return the FQDN for the local system using both gethostname() * and gethostbyname() to get the local hostname with domain. * - * @since CUPS 1.2@ + * @since CUPS 1.2/macOS 10.5@ */ const char * /* O - FQDN for connection or system */ @@ -531,18 +791,19 @@ httpGetHostname(http_t *http, /* I - HTTP connection or NULL */ char *s, /* I - String buffer for name */ int slen) /* I - Size of buffer */ { - struct hostent *host; /* Host entry to get FQDN */ - - - if (!s || slen <= 1) - return (NULL); - if (http) { - if (http->hostname[0] == '/') - strlcpy(s, "localhost", slen); + if (!s || slen <= 1) + { + if (http->hostname[0] == '/') + return ("localhost"); + else + return (http->hostname); + } + else if (http->hostname[0] == '/') + strlcpy(s, "localhost", (size_t)slen); else - strlcpy(s, http->hostname, slen); + strlcpy(s, http->hostname, (size_t)slen); } else { @@ -550,18 +811,78 @@ httpGetHostname(http_t *http, /* I - HTTP connection or NULL */ * Get the hostname... */ - if (gethostname(s, slen) < 0) - strlcpy(s, "localhost", slen); + if (!s || slen <= 1) + return (NULL); + + if (gethostname(s, (size_t)slen) < 0) + strlcpy(s, "localhost", (size_t)slen); if (!strchr(s, '.')) { +#ifdef HAVE_SCDYNAMICSTORECOPYCOMPUTERNAME + /* + * The hostname is not a FQDN, so use the local hostname from the + * SystemConfiguration framework... + */ + + SCDynamicStoreRef sc = SCDynamicStoreCreate(kCFAllocatorDefault, + CFSTR("libcups"), NULL, NULL); + /* System configuration data */ + CFStringRef local = sc ? SCDynamicStoreCopyLocalHostName(sc) : NULL; + /* Local host name */ + char localStr[1024]; /* Local host name C string */ + + if (local && CFStringGetCString(local, localStr, sizeof(localStr), + kCFStringEncodingUTF8)) + { + /* + * Append ".local." to the hostname we get... + */ + + snprintf(s, (size_t)slen, "%s.local.", localStr); + } + + if (local) + CFRelease(local); + if (sc) + CFRelease(sc); + +#else /* * The hostname is not a FQDN, so look it up... */ + struct hostent *host; /* Host entry to get FQDN */ + if ((host = gethostbyname(s)) != NULL && host->h_name) - strlcpy(s, host->h_name, slen); + { + /* + * Use the resolved hostname... + */ + + strlcpy(s, host->h_name, (size_t)slen); + } +#endif /* HAVE_SCDYNAMICSTORECOPYCOMPUTERNAME */ } + + /* + * Make sure .local hostnames end with a period... + */ + + if (strlen(s) > 6 && !strcmp(s + strlen(s) - 6, ".local")) + strlcat(s, ".", (size_t)slen); + } + + /* + * Convert the hostname to lowercase as needed... + */ + + if (s[0] != '/') + { + char *ptr; /* Pointer into string */ + + for (ptr = s; *ptr; ptr ++) + *ptr = (char)_cups_tolower((int)*ptr); } /* @@ -573,5 +894,41 @@ httpGetHostname(http_t *http, /* I - HTTP connection or NULL */ /* - * End of "$Id: http-addr.c 6814 2007-08-20 20:09:25Z mike $". + * 'httpResolveHostname()' - Resolve the hostname of the HTTP connection + * address. + * + * @since CUPS 2.0/OS 10.10@ */ + +const char * /* O - Resolved hostname or @code NULL@ */ +httpResolveHostname(http_t *http, /* I - HTTP connection */ + char *buffer, /* I - Hostname buffer */ + size_t bufsize) /* I - Size of buffer */ +{ + if (!http) + return (NULL); + + if (isdigit(http->hostname[0] & 255) || http->hostname[0] == '[') + { + char temp[1024]; /* Temporary string */ + + if (httpAddrLookup(http->hostaddr, temp, sizeof(temp))) + strlcpy(http->hostname, temp, sizeof(http->hostname)); + else + return (NULL); + } + + if (buffer) + { + if (http->hostname[0] == '/') + strlcpy(buffer, "localhost", bufsize); + else + strlcpy(buffer, http->hostname, bufsize); + + return (buffer); + } + else if (http->hostname[0] == '/') + return ("localhost"); + else + return (http->hostname); +}