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