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