1*355b4669Sjacobs /* 2*355b4669Sjacobs * "$Id: http-addr.c 148 2006-04-25 16:54:17Z njacobs $" 3*355b4669Sjacobs * 4*355b4669Sjacobs * HTTP address routines for the Common UNIX Printing System (CUPS). 5*355b4669Sjacobs * 6*355b4669Sjacobs * Copyright 1997-2005 by Easy Software Products, all rights reserved. 7*355b4669Sjacobs * 8*355b4669Sjacobs * These coded instructions, statements, and computer programs are the 9*355b4669Sjacobs * property of Easy Software Products and are protected by Federal 10*355b4669Sjacobs * copyright law. Distribution and use rights are outlined in the file 11*355b4669Sjacobs * "LICENSE.txt" which should have been included with this file. If this 12*355b4669Sjacobs * file is missing or damaged please contact Easy Software Products 13*355b4669Sjacobs * at: 14*355b4669Sjacobs * 15*355b4669Sjacobs * Attn: CUPS Licensing Information 16*355b4669Sjacobs * Easy Software Products 17*355b4669Sjacobs * 44141 Airport View Drive, Suite 204 18*355b4669Sjacobs * Hollywood, Maryland 20636 USA 19*355b4669Sjacobs * 20*355b4669Sjacobs * Voice: (301) 373-9600 21*355b4669Sjacobs * EMail: cups-info@cups.org 22*355b4669Sjacobs * WWW: http://www.cups.org 23*355b4669Sjacobs * 24*355b4669Sjacobs * Contents: 25*355b4669Sjacobs * 26*355b4669Sjacobs * httpAddrAny() - Check for the "any" address. 27*355b4669Sjacobs * httpAddrEqual() - Compare two addresses. 28*355b4669Sjacobs * httpAddrLoad() - Load a host entry address into an HTTP address. 29*355b4669Sjacobs * httpAddrLocalhost() - Check for the local loopback address. 30*355b4669Sjacobs * httpAddrLookup() - Lookup the hostname associated with the address. 31*355b4669Sjacobs * httpAddrString() - Convert an IP address to a dotted string. 32*355b4669Sjacobs * httpGetHostByName() - Lookup a hostname or IP address, and return 33*355b4669Sjacobs * address records for the specified name. 34*355b4669Sjacobs */ 35*355b4669Sjacobs 36*355b4669Sjacobs /* 37*355b4669Sjacobs * Include necessary headers... 38*355b4669Sjacobs */ 39*355b4669Sjacobs 40*355b4669Sjacobs #pragma ident "%Z%%M% %I% %E% SMI" 41*355b4669Sjacobs 42*355b4669Sjacobs #include "http.h" 43*355b4669Sjacobs #include "debug.h" 44*355b4669Sjacobs #include "string.h" 45*355b4669Sjacobs #include <ctype.h> 46*355b4669Sjacobs 47*355b4669Sjacobs 48*355b4669Sjacobs /* 49*355b4669Sjacobs * 'httpAddrAny()' - Check for the "any" address. 50*355b4669Sjacobs */ 51*355b4669Sjacobs 52*355b4669Sjacobs int /* O - 1 if "any", 0 otherwise */ 53*355b4669Sjacobs httpAddrAny(const http_addr_t *addr) /* I - Address to check */ 54*355b4669Sjacobs { 55*355b4669Sjacobs #ifdef AF_INET6 56*355b4669Sjacobs if (addr->addr.sa_family == AF_INET6 && 57*355b4669Sjacobs IN6_IS_ADDR_UNSPECIFIED(&(addr->ipv6.sin6_addr))) 58*355b4669Sjacobs return (1); 59*355b4669Sjacobs #endif /* AF_INET6 */ 60*355b4669Sjacobs 61*355b4669Sjacobs if (addr->addr.sa_family == AF_INET && 62*355b4669Sjacobs ntohl(addr->ipv4.sin_addr.s_addr) == 0x00000000) 63*355b4669Sjacobs return (1); 64*355b4669Sjacobs 65*355b4669Sjacobs return (0); 66*355b4669Sjacobs } 67*355b4669Sjacobs 68*355b4669Sjacobs 69*355b4669Sjacobs /* 70*355b4669Sjacobs * 'httpAddrEqual()' - Compare two addresses. 71*355b4669Sjacobs */ 72*355b4669Sjacobs 73*355b4669Sjacobs int /* O - 1 if equal, 0 if != */ 74*355b4669Sjacobs httpAddrEqual(const http_addr_t *addr1, /* I - First address */ 75*355b4669Sjacobs const http_addr_t *addr2) /* I - Second address */ 76*355b4669Sjacobs { 77*355b4669Sjacobs if (addr1->addr.sa_family != addr2->addr.sa_family) 78*355b4669Sjacobs return (0); 79*355b4669Sjacobs 80*355b4669Sjacobs #ifdef AF_INET6 81*355b4669Sjacobs if (addr1->addr.sa_family == AF_INET6) 82*355b4669Sjacobs return (memcmp(&(addr1->ipv6.sin6_addr), &(addr2->ipv6.sin6_addr), 16) == 0); 83*355b4669Sjacobs #endif /* AF_INET6 */ 84*355b4669Sjacobs 85*355b4669Sjacobs return (addr1->ipv4.sin_addr.s_addr == addr2->ipv4.sin_addr.s_addr); 86*355b4669Sjacobs } 87*355b4669Sjacobs 88*355b4669Sjacobs 89*355b4669Sjacobs /* 90*355b4669Sjacobs * 'httpAddrLoad()' - Load a host entry address into an HTTP address. 91*355b4669Sjacobs */ 92*355b4669Sjacobs 93*355b4669Sjacobs void 94*355b4669Sjacobs httpAddrLoad(const struct hostent *host, /* I - Host entry */ 95*355b4669Sjacobs int port, /* I - Port number */ 96*355b4669Sjacobs int n, /* I - Index into host entry */ 97*355b4669Sjacobs http_addr_t *addr) /* O - Address to load */ 98*355b4669Sjacobs { 99*355b4669Sjacobs #ifdef AF_INET6 100*355b4669Sjacobs if (host->h_addrtype == AF_INET6) 101*355b4669Sjacobs { 102*355b4669Sjacobs # ifdef WIN32 103*355b4669Sjacobs addr->ipv6.sin6_port = htons((u_short)port); 104*355b4669Sjacobs # else 105*355b4669Sjacobs addr->ipv6.sin6_port = htons(port); 106*355b4669Sjacobs # endif /* WIN32 */ 107*355b4669Sjacobs 108*355b4669Sjacobs memcpy((char *)&(addr->ipv6.sin6_addr), host->h_addr_list[n], 109*355b4669Sjacobs host->h_length); 110*355b4669Sjacobs addr->ipv6.sin6_family = AF_INET6; 111*355b4669Sjacobs } 112*355b4669Sjacobs else 113*355b4669Sjacobs #endif /* AF_INET6 */ 114*355b4669Sjacobs #ifdef AF_LOCAL 115*355b4669Sjacobs if (host->h_addrtype == AF_LOCAL) 116*355b4669Sjacobs { 117*355b4669Sjacobs addr->un.sun_family = AF_LOCAL; 118*355b4669Sjacobs strlcpy(addr->un.sun_path, host->h_addr_list[n], sizeof(addr->un.sun_path)); 119*355b4669Sjacobs } 120*355b4669Sjacobs else 121*355b4669Sjacobs #endif /* AF_LOCAL */ 122*355b4669Sjacobs if (host->h_addrtype == AF_INET) 123*355b4669Sjacobs { 124*355b4669Sjacobs # ifdef WIN32 125*355b4669Sjacobs addr->ipv4.sin_port = htons((u_short)port); 126*355b4669Sjacobs # else 127*355b4669Sjacobs addr->ipv4.sin_port = htons(port); 128*355b4669Sjacobs # endif /* WIN32 */ 129*355b4669Sjacobs 130*355b4669Sjacobs memcpy((char *)&(addr->ipv4.sin_addr), host->h_addr_list[n], 131*355b4669Sjacobs host->h_length); 132*355b4669Sjacobs addr->ipv4.sin_family = AF_INET; 133*355b4669Sjacobs } 134*355b4669Sjacobs } 135*355b4669Sjacobs 136*355b4669Sjacobs 137*355b4669Sjacobs /* 138*355b4669Sjacobs * 'httpAddrLocalhost()' - Check for the local loopback address. 139*355b4669Sjacobs */ 140*355b4669Sjacobs 141*355b4669Sjacobs int /* O - 1 if local host, 0 otherwise */ 142*355b4669Sjacobs httpAddrLocalhost(const http_addr_t *addr) 143*355b4669Sjacobs /* I - Address to check */ 144*355b4669Sjacobs { 145*355b4669Sjacobs #ifdef AF_INET6 146*355b4669Sjacobs if (addr->addr.sa_family == AF_INET6 && 147*355b4669Sjacobs IN6_IS_ADDR_LOOPBACK(&(addr->ipv6.sin6_addr))) 148*355b4669Sjacobs return (1); 149*355b4669Sjacobs #endif /* AF_INET6 */ 150*355b4669Sjacobs 151*355b4669Sjacobs #ifdef AF_LOCAL 152*355b4669Sjacobs if (addr->addr.sa_family == AF_LOCAL) 153*355b4669Sjacobs return (1); 154*355b4669Sjacobs #endif /* AF_LOCAL */ 155*355b4669Sjacobs 156*355b4669Sjacobs if (addr->addr.sa_family == AF_INET && 157*355b4669Sjacobs ntohl(addr->ipv4.sin_addr.s_addr) == 0x7f000001) 158*355b4669Sjacobs return (1); 159*355b4669Sjacobs 160*355b4669Sjacobs return (0); 161*355b4669Sjacobs } 162*355b4669Sjacobs 163*355b4669Sjacobs 164*355b4669Sjacobs #ifdef __sgi 165*355b4669Sjacobs # define ADDR_CAST (struct sockaddr *) 166*355b4669Sjacobs #else 167*355b4669Sjacobs # define ADDR_CAST (char *) 168*355b4669Sjacobs #endif /* __sgi */ 169*355b4669Sjacobs 170*355b4669Sjacobs 171*355b4669Sjacobs /* 172*355b4669Sjacobs * 'httpAddrLookup()' - Lookup the hostname associated with the address. 173*355b4669Sjacobs */ 174*355b4669Sjacobs 175*355b4669Sjacobs char * /* O - Host name */ 176*355b4669Sjacobs httpAddrLookup(const http_addr_t *addr, /* I - Address to lookup */ 177*355b4669Sjacobs char *name, /* I - Host name buffer */ 178*355b4669Sjacobs int namelen) /* I - Size of name buffer */ 179*355b4669Sjacobs { 180*355b4669Sjacobs struct hostent *host; /* Host from name service */ 181*355b4669Sjacobs 182*355b4669Sjacobs 183*355b4669Sjacobs DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)\n", 184*355b4669Sjacobs addr, name, namelen)); 185*355b4669Sjacobs 186*355b4669Sjacobs #ifdef AF_INET6 187*355b4669Sjacobs if (addr->addr.sa_family == AF_INET6) 188*355b4669Sjacobs host = gethostbyaddr(ADDR_CAST &(addr->ipv6.sin6_addr), 189*355b4669Sjacobs sizeof(struct in6_addr), AF_INET6); 190*355b4669Sjacobs else 191*355b4669Sjacobs #endif /* AF_INET6 */ 192*355b4669Sjacobs #ifdef AF_LOCAL 193*355b4669Sjacobs if (addr->addr.sa_family == AF_LOCAL) 194*355b4669Sjacobs { 195*355b4669Sjacobs strlcpy(name, addr->un.sun_path, namelen); 196*355b4669Sjacobs return (name); 197*355b4669Sjacobs } 198*355b4669Sjacobs else 199*355b4669Sjacobs #endif /* AF_LOCAL */ 200*355b4669Sjacobs if (addr->addr.sa_family == AF_INET) 201*355b4669Sjacobs host = gethostbyaddr(ADDR_CAST &(addr->ipv4.sin_addr), 202*355b4669Sjacobs sizeof(struct in_addr), AF_INET); 203*355b4669Sjacobs else 204*355b4669Sjacobs host = NULL; 205*355b4669Sjacobs 206*355b4669Sjacobs if (host == NULL) 207*355b4669Sjacobs { 208*355b4669Sjacobs httpAddrString(addr, name, namelen); 209*355b4669Sjacobs return (NULL); 210*355b4669Sjacobs } 211*355b4669Sjacobs 212*355b4669Sjacobs strlcpy(name, host->h_name, namelen); 213*355b4669Sjacobs 214*355b4669Sjacobs return (name); 215*355b4669Sjacobs } 216*355b4669Sjacobs 217*355b4669Sjacobs 218*355b4669Sjacobs /* 219*355b4669Sjacobs * 'httpAddrString()' - Convert an IP address to a dotted string. 220*355b4669Sjacobs */ 221*355b4669Sjacobs 222*355b4669Sjacobs char * /* O - IP string */ 223*355b4669Sjacobs httpAddrString(const http_addr_t *addr, /* I - Address to convert */ 224*355b4669Sjacobs char *s, /* I - String buffer */ 225*355b4669Sjacobs int slen) /* I - Length of string */ 226*355b4669Sjacobs { 227*355b4669Sjacobs DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)\n", 228*355b4669Sjacobs addr, s, slen)); 229*355b4669Sjacobs 230*355b4669Sjacobs #ifdef AF_INET6 231*355b4669Sjacobs if (addr->addr.sa_family == AF_INET6) 232*355b4669Sjacobs snprintf(s, slen, "%u.%u.%u.%u", 233*355b4669Sjacobs ntohl(addr->ipv6.sin6_addr.s6_addr32[0]), 234*355b4669Sjacobs ntohl(addr->ipv6.sin6_addr.s6_addr32[1]), 235*355b4669Sjacobs ntohl(addr->ipv6.sin6_addr.s6_addr32[2]), 236*355b4669Sjacobs ntohl(addr->ipv6.sin6_addr.s6_addr32[3])); 237*355b4669Sjacobs else 238*355b4669Sjacobs #endif /* AF_INET6 */ 239*355b4669Sjacobs #ifdef AF_LOCAL 240*355b4669Sjacobs if (addr->addr.sa_family == AF_LOCAL) 241*355b4669Sjacobs strlcpy(s, addr->un.sun_path, slen); 242*355b4669Sjacobs else 243*355b4669Sjacobs #endif /* AF_LOCAL */ 244*355b4669Sjacobs if (addr->addr.sa_family == AF_INET) 245*355b4669Sjacobs { 246*355b4669Sjacobs unsigned temp; /* Temporary address */ 247*355b4669Sjacobs 248*355b4669Sjacobs 249*355b4669Sjacobs temp = ntohl(addr->ipv4.sin_addr.s_addr); 250*355b4669Sjacobs 251*355b4669Sjacobs snprintf(s, slen, "%d.%d.%d.%d", (temp >> 24) & 255, 252*355b4669Sjacobs (temp >> 16) & 255, (temp >> 8) & 255, temp & 255); 253*355b4669Sjacobs } 254*355b4669Sjacobs else 255*355b4669Sjacobs strlcpy(s, "UNKNOWN", slen); 256*355b4669Sjacobs 257*355b4669Sjacobs DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s)); 258*355b4669Sjacobs 259*355b4669Sjacobs return (s); 260*355b4669Sjacobs } 261*355b4669Sjacobs 262*355b4669Sjacobs 263*355b4669Sjacobs /* 264*355b4669Sjacobs * 'httpGetHostByName()' - Lookup a hostname or IP address, and return 265*355b4669Sjacobs * address records for the specified name. 266*355b4669Sjacobs */ 267*355b4669Sjacobs 268*355b4669Sjacobs struct hostent * /* O - Host entry */ 269*355b4669Sjacobs httpGetHostByName(const char *name) /* I - Hostname or IP address */ 270*355b4669Sjacobs { 271*355b4669Sjacobs const char *nameptr; /* Pointer into name */ 272*355b4669Sjacobs unsigned ip[4]; /* IP address components */ 273*355b4669Sjacobs static unsigned packed_ip; /* Packed IPv4 address */ 274*355b4669Sjacobs static char *packed_ptr[2]; /* Pointer to packed address */ 275*355b4669Sjacobs static struct hostent host_ip; /* Host entry for IP/domain address */ 276*355b4669Sjacobs 277*355b4669Sjacobs 278*355b4669Sjacobs DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name)); 279*355b4669Sjacobs 280*355b4669Sjacobs #if defined(__APPLE__) 281*355b4669Sjacobs /* OS X hack to avoid it's ocassional long delay in lookupd */ 282*355b4669Sjacobs static const char sLoopback[] = "127.0.0.1"; 283*355b4669Sjacobs if (strcmp(name, "localhost") == 0) 284*355b4669Sjacobs name = sLoopback; 285*355b4669Sjacobs #endif /* __APPLE__ */ 286*355b4669Sjacobs 287*355b4669Sjacobs /* 288*355b4669Sjacobs * This function is needed because some operating systems have a 289*355b4669Sjacobs * buggy implementation of gethostbyname() that does not support 290*355b4669Sjacobs * IP addresses. If the first character of the name string is a 291*355b4669Sjacobs * number, then sscanf() is used to extract the IP components. 292*355b4669Sjacobs * We then pack the components into an IPv4 address manually, 293*355b4669Sjacobs * since the inet_aton() function is deprecated. We use the 294*355b4669Sjacobs * htonl() macro to get the right byte order for the address. 295*355b4669Sjacobs * 296*355b4669Sjacobs * We also support domain sockets when supported by the underlying 297*355b4669Sjacobs * OS... 298*355b4669Sjacobs */ 299*355b4669Sjacobs 300*355b4669Sjacobs #ifdef AF_LOCAL 301*355b4669Sjacobs if (name[0] == '/') 302*355b4669Sjacobs { 303*355b4669Sjacobs /* 304*355b4669Sjacobs * A domain socket address, so make an AF_LOCAL entry and return it... 305*355b4669Sjacobs */ 306*355b4669Sjacobs 307*355b4669Sjacobs host_ip.h_name = (char *)name; 308*355b4669Sjacobs host_ip.h_aliases = NULL; 309*355b4669Sjacobs host_ip.h_addrtype = AF_LOCAL; 310*355b4669Sjacobs host_ip.h_length = strlen(name) + 1; 311*355b4669Sjacobs host_ip.h_addr_list = packed_ptr; 312*355b4669Sjacobs packed_ptr[0] = (char *)name; 313*355b4669Sjacobs packed_ptr[1] = NULL; 314*355b4669Sjacobs 315*355b4669Sjacobs DEBUG_puts("httpGetHostByName: returning domain socket address..."); 316*355b4669Sjacobs 317*355b4669Sjacobs return (&host_ip); 318*355b4669Sjacobs } 319*355b4669Sjacobs #endif /* AF_LOCAL */ 320*355b4669Sjacobs 321*355b4669Sjacobs for (nameptr = name; isdigit(*nameptr & 255) || *nameptr == '.'; nameptr ++); 322*355b4669Sjacobs 323*355b4669Sjacobs if (!*nameptr) 324*355b4669Sjacobs { 325*355b4669Sjacobs /* 326*355b4669Sjacobs * We have an IP address; break it up and provide the host entry 327*355b4669Sjacobs * to the caller. Currently only supports IPv4 addresses, although 328*355b4669Sjacobs * it should be trivial to support IPv6 in CUPS 1.2. 329*355b4669Sjacobs */ 330*355b4669Sjacobs 331*355b4669Sjacobs if (sscanf(name, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) != 4) 332*355b4669Sjacobs return (NULL); /* Must have 4 numbers */ 333*355b4669Sjacobs 334*355b4669Sjacobs if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255) 335*355b4669Sjacobs return (NULL); /* Invalid byte ranges! */ 336*355b4669Sjacobs 337*355b4669Sjacobs packed_ip = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | ip[3])); 338*355b4669Sjacobs 339*355b4669Sjacobs /* 340*355b4669Sjacobs * Fill in the host entry and return it... 341*355b4669Sjacobs */ 342*355b4669Sjacobs 343*355b4669Sjacobs host_ip.h_name = (char *)name; 344*355b4669Sjacobs host_ip.h_aliases = NULL; 345*355b4669Sjacobs host_ip.h_addrtype = AF_INET; 346*355b4669Sjacobs host_ip.h_length = 4; 347*355b4669Sjacobs host_ip.h_addr_list = packed_ptr; 348*355b4669Sjacobs packed_ptr[0] = (char *)(&packed_ip); 349*355b4669Sjacobs packed_ptr[1] = NULL; 350*355b4669Sjacobs 351*355b4669Sjacobs DEBUG_puts("httpGetHostByName: returning IPv4 address..."); 352*355b4669Sjacobs 353*355b4669Sjacobs return (&host_ip); 354*355b4669Sjacobs } 355*355b4669Sjacobs else 356*355b4669Sjacobs { 357*355b4669Sjacobs /* 358*355b4669Sjacobs * Use the gethostbyname() function to get the IP address for 359*355b4669Sjacobs * the name... 360*355b4669Sjacobs */ 361*355b4669Sjacobs 362*355b4669Sjacobs DEBUG_puts("httpGetHostByName: returning domain lookup address(es)..."); 363*355b4669Sjacobs 364*355b4669Sjacobs return (gethostbyname(name)); 365*355b4669Sjacobs } 366*355b4669Sjacobs } 367*355b4669Sjacobs 368*355b4669Sjacobs 369*355b4669Sjacobs /* 370*355b4669Sjacobs * End of "$Id: http-addr.c 148 2006-04-25 16:54:17Z njacobs $". 371*355b4669Sjacobs */ 372