/* * "$Id: http-addr.c 148 2006-04-25 16:54:17Z njacobs $" * * HTTP address routines for the Common UNIX Printing System (CUPS). * * Copyright 1997-2005 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products 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 missing or damaged please contact Easy Software Products * at: * * Attn: CUPS Licensing Information * Easy Software Products * 44141 Airport View Drive, Suite 204 * Hollywood, Maryland 20636 USA * * Voice: (301) 373-9600 * EMail: cups-info@cups.org * WWW: http://www.cups.org * * Contents: * * httpAddrAny() - Check for the "any" address. * httpAddrEqual() - Compare two addresses. * httpAddrLoad() - Load a host entry address into an HTTP address. * httpAddrLocalhost() - Check for the local loopback address. * httpAddrLookup() - Lookup the hostname associated with the 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. */ /* * Include necessary headers... */ #include "http.h" #include "debug.h" #include "string.h" #include /* * 'httpAddrAny()' - Check for the "any" address. */ int /* O - 1 if "any", 0 otherwise */ httpAddrAny(const http_addr_t *addr) /* I - Address to check */ { #ifdef AF_INET6 if (addr->addr.sa_family == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&(addr->ipv6.sin6_addr))) return (1); #endif /* AF_INET6 */ if (addr->addr.sa_family == AF_INET && ntohl(addr->ipv4.sin_addr.s_addr) == 0x00000000) return (1); return (0); } /* * 'httpAddrEqual()' - Compare two addresses. */ int /* O - 1 if equal, 0 if != */ httpAddrEqual(const http_addr_t *addr1, /* I - First address */ const http_addr_t *addr2) /* I - Second address */ { if (addr1->addr.sa_family != addr2->addr.sa_family) return (0); #ifdef AF_INET6 if (addr1->addr.sa_family == AF_INET6) return (memcmp(&(addr1->ipv6.sin6_addr), &(addr2->ipv6.sin6_addr), 16) == 0); #endif /* AF_INET6 */ return (addr1->ipv4.sin_addr.s_addr == addr2->ipv4.sin_addr.s_addr); } /* * 'httpAddrLoad()' - Load a host entry address into an HTTP address. */ void httpAddrLoad(const struct hostent *host, /* I - Host entry */ int port, /* I - Port number */ int n, /* I - Index into host entry */ http_addr_t *addr) /* O - Address to load */ { #ifdef AF_INET6 if (host->h_addrtype == AF_INET6) { # ifdef WIN32 addr->ipv6.sin6_port = htons((u_short)port); # else addr->ipv6.sin6_port = htons(port); # endif /* WIN32 */ memcpy((char *)&(addr->ipv6.sin6_addr), host->h_addr_list[n], host->h_length); addr->ipv6.sin6_family = AF_INET6; } else #endif /* AF_INET6 */ #ifdef AF_LOCAL if (host->h_addrtype == AF_LOCAL) { addr->un.sun_family = AF_LOCAL; strlcpy(addr->un.sun_path, host->h_addr_list[n], sizeof(addr->un.sun_path)); } else #endif /* AF_LOCAL */ if (host->h_addrtype == AF_INET) { # ifdef WIN32 addr->ipv4.sin_port = htons((u_short)port); # else addr->ipv4.sin_port = htons(port); # endif /* WIN32 */ memcpy((char *)&(addr->ipv4.sin_addr), host->h_addr_list[n], host->h_length); addr->ipv4.sin_family = AF_INET; } } /* * 'httpAddrLocalhost()' - Check for the local loopback address. */ int /* O - 1 if local host, 0 otherwise */ httpAddrLocalhost(const http_addr_t *addr) /* I - Address to check */ { #ifdef AF_INET6 if (addr->addr.sa_family == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&(addr->ipv6.sin6_addr))) return (1); #endif /* AF_INET6 */ #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) return (1); #endif /* AF_LOCAL */ if (addr->addr.sa_family == AF_INET && ntohl(addr->ipv4.sin_addr.s_addr) == 0x7f000001) 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. */ char * /* O - Host name */ httpAddrLookup(const http_addr_t *addr, /* I - Address to lookup */ char *name, /* I - Host name buffer */ int namelen) /* I - Size of name buffer */ { struct hostent *host; /* Host from name service */ DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)\n", addr, name, namelen)); #ifdef AF_INET6 if (addr->addr.sa_family == AF_INET6) host = gethostbyaddr(ADDR_CAST &(addr->ipv6.sin6_addr), sizeof(struct in6_addr), AF_INET6); else #endif /* AF_INET6 */ #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) { strlcpy(name, addr->un.sun_path, namelen); return (name); } else #endif /* AF_LOCAL */ if (addr->addr.sa_family == AF_INET) host = gethostbyaddr(ADDR_CAST &(addr->ipv4.sin_addr), sizeof(struct in_addr), AF_INET); else host = NULL; if (host == NULL) { httpAddrString(addr, name, namelen); return (NULL); } strlcpy(name, host->h_name, namelen); return (name); } /* * 'httpAddrString()' - Convert an IP address to a dotted string. */ char * /* O - IP string */ 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)); #ifdef AF_INET6 if (addr->addr.sa_family == AF_INET6) snprintf(s, slen, "%u.%u.%u.%u", ntohl(addr->ipv6.sin6_addr.s6_addr32[0]), ntohl(addr->ipv6.sin6_addr.s6_addr32[1]), ntohl(addr->ipv6.sin6_addr.s6_addr32[2]), ntohl(addr->ipv6.sin6_addr.s6_addr32[3])); else #endif /* AF_INET6 */ #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) strlcpy(s, addr->un.sun_path, 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, (temp >> 16) & 255, (temp >> 8) & 255, temp & 255); } else strlcpy(s, "UNKNOWN", slen); DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s)); return (s); } /* * 'httpGetHostByName()' - Lookup a hostname or IP address, and return * address records for the specified name. */ struct hostent * /* O - Host entry */ httpGetHostByName(const char *name) /* I - Hostname or IP address */ { const char *nameptr; /* Pointer into name */ unsigned ip[4]; /* IP address components */ static unsigned packed_ip; /* Packed IPv4 address */ static char *packed_ptr[2]; /* Pointer to packed address */ static struct hostent host_ip; /* Host entry for IP/domain address */ DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name)); #if defined(__APPLE__) /* OS X hack to avoid it's ocassional long delay in lookupd */ static const char sLoopback[] = "127.0.0.1"; if (strcmp(name, "localhost") == 0) name = sLoopback; #endif /* __APPLE__ */ /* * This function is needed because some operating systems have a * buggy implementation of gethostbyname() that does not support * IP addresses. If the first character of the name string is a * number, then sscanf() is used to extract the IP components. * We then pack the components into an IPv4 address manually, * since the inet_aton() function is deprecated. We use the * htonl() macro to get the right byte order for the address. * * We also support domain sockets when supported by the underlying * OS... */ #ifdef AF_LOCAL if (name[0] == '/') { /* * A domain socket address, so make an AF_LOCAL entry and return it... */ host_ip.h_name = (char *)name; host_ip.h_aliases = NULL; host_ip.h_addrtype = AF_LOCAL; host_ip.h_length = strlen(name) + 1; host_ip.h_addr_list = packed_ptr; packed_ptr[0] = (char *)name; packed_ptr[1] = NULL; DEBUG_puts("httpGetHostByName: returning domain socket address..."); return (&host_ip); } #endif /* AF_LOCAL */ for (nameptr = name; isdigit(*nameptr & 255) || *nameptr == '.'; nameptr ++); if (!*nameptr) { /* * We have an IP address; break it up and provide the host entry * to the caller. Currently only supports IPv4 addresses, although * it should be trivial to support IPv6 in CUPS 1.2. */ if (sscanf(name, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) != 4) return (NULL); /* Must have 4 numbers */ if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255) return (NULL); /* Invalid byte ranges! */ packed_ip = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | ip[3])); /* * Fill in the host entry and return it... */ host_ip.h_name = (char *)name; host_ip.h_aliases = NULL; host_ip.h_addrtype = AF_INET; host_ip.h_length = 4; host_ip.h_addr_list = packed_ptr; packed_ptr[0] = (char *)(&packed_ip); packed_ptr[1] = NULL; DEBUG_puts("httpGetHostByName: returning IPv4 address..."); return (&host_ip); } else { /* * Use the gethostbyname() function to get the IP address for * the name... */ DEBUG_puts("httpGetHostByName: returning domain lookup address(es)..."); return (gethostbyname(name)); } } /* * End of "$Id: http-addr.c 148 2006-04-25 16:54:17Z njacobs $". */