xref: /onnv-gate/usr/src/lib/print/libhttp-core/common/http-addr.c (revision 2264:b2b9267d002d)
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