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