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