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