]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http-addr.c
Add missing file.`
[thirdparty/cups.git] / cups / http-addr.c
CommitLineData
ef416fc2 1/*
2e4ff8af 2 * "$Id: http-addr.c 6814 2007-08-20 20:09:25Z mike $"
ef416fc2 3 *
4 * HTTP address routines for the Common UNIX Printing System (CUPS).
5 *
1ff0402e 6 * Copyright 2007-2008 by Apple Inc.
ecdc0628 7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
15 * Contents:
16 *
17 * httpAddrAny() - Check for the "any" address.
18 * httpAddrEqual() - Compare two addresses.
19 * httpAddrLocalhost() - Check for the local loopback address.
20 * httpAddrLookup() - Lookup the hostname associated with the address.
1ff0402e 21 * _httpAddrPort() - Get the port number associated with an address.
ef416fc2 22 * httpAddrString() - Convert an IP address to a dotted string.
23 * httpGetHostByName() - Lookup a hostname or IP address, and return
24 * address records for the specified name.
25 * httpGetHostname() - Get the FQDN for the local system.
26 */
27
28/*
29 * Include necessary headers...
30 */
31
32#include "globals.h"
33#include "debug.h"
34#include <stdlib.h>
35#include <stddef.h>
36
37
38/*
39 * 'httpAddrAny()' - Check for the "any" address.
40 *
41 * @since CUPS 1.2@
42 */
43
44int /* O - 1 if "any", 0 otherwise */
45httpAddrAny(const http_addr_t *addr) /* I - Address to check */
46{
89d46774 47 if (!addr)
48 return (0);
49
ef416fc2 50#ifdef AF_INET6
51 if (addr->addr.sa_family == AF_INET6 &&
52 IN6_IS_ADDR_UNSPECIFIED(&(addr->ipv6.sin6_addr)))
53 return (1);
54#endif /* AF_INET6 */
55
56 if (addr->addr.sa_family == AF_INET &&
57 ntohl(addr->ipv4.sin_addr.s_addr) == 0x00000000)
58 return (1);
59
60 return (0);
61}
62
63
64/*
65 * 'httpAddrEqual()' - Compare two addresses.
66 *
67 * @since CUPS 1.2@
68 */
69
ecdc0628 70int /* O - 1 if equal, 0 if not */
ef416fc2 71httpAddrEqual(const http_addr_t *addr1, /* I - First address */
72 const http_addr_t *addr2) /* I - Second address */
73{
89d46774 74 if (!addr1 && !addr2)
75 return (1);
76
77 if (!addr1 || !addr2)
78 return (0);
79
ef416fc2 80 if (addr1->addr.sa_family != addr2->addr.sa_family)
81 return (0);
82
83#ifdef AF_LOCAL
84 if (addr1->addr.sa_family == AF_LOCAL)
85 return (!strcmp(addr1->un.sun_path, addr2->un.sun_path));
86#endif /* AF_LOCAL */
87
88#ifdef AF_INET6
89 if (addr1->addr.sa_family == AF_INET6)
90 return (!memcmp(&(addr1->ipv6.sin6_addr), &(addr2->ipv6.sin6_addr), 16));
91#endif /* AF_INET6 */
92
93 return (addr1->ipv4.sin_addr.s_addr == addr2->ipv4.sin_addr.s_addr);
94}
95
96
97/*
98 * 'httpAddrLength()' - Return the length of the address in bytes.
99 *
100 * @since CUPS 1.2@
101 */
102
103int /* O - Length in bytes */
104httpAddrLength(const http_addr_t *addr) /* I - Address */
105{
89d46774 106 if (!addr)
107 return (0);
108
ef416fc2 109#ifdef AF_INET6
110 if (addr->addr.sa_family == AF_INET6)
111 return (sizeof(addr->ipv6));
112 else
113#endif /* AF_INET6 */
114#ifdef AF_LOCAL
115 if (addr->addr.sa_family == AF_LOCAL)
116 return (offsetof(struct sockaddr_un, sun_path) +
117 strlen(addr->un.sun_path) + 1);
118 else
119#endif /* AF_LOCAL */
120 if (addr->addr.sa_family == AF_INET)
121 return (sizeof(addr->ipv4));
122 else
123 return (0);
124
125}
126
127
128/*
129 * 'httpAddrLocalhost()' - Check for the local loopback address.
130 *
131 * @since CUPS 1.2@
132 */
133
134int /* O - 1 if local host, 0 otherwise */
135httpAddrLocalhost(
136 const http_addr_t *addr) /* I - Address to check */
137{
89d46774 138 if (!addr)
139 return (1);
140
ef416fc2 141#ifdef AF_INET6
142 if (addr->addr.sa_family == AF_INET6 &&
fa73b229 143 IN6_IS_ADDR_LOOPBACK(&(addr->ipv6.sin6_addr)))
ef416fc2 144 return (1);
145#endif /* AF_INET6 */
146
147#ifdef AF_LOCAL
148 if (addr->addr.sa_family == AF_LOCAL)
149 return (1);
150#endif /* AF_LOCAL */
151
152 if (addr->addr.sa_family == AF_INET &&
153 ntohl(addr->ipv4.sin_addr.s_addr) == 0x7f000001)
154 return (1);
155
156 return (0);
157}
158
159
160#ifdef __sgi
161# define ADDR_CAST (struct sockaddr *)
162#else
163# define ADDR_CAST (char *)
164#endif /* __sgi */
165
166
167/*
168 * 'httpAddrLookup()' - Lookup the hostname associated with the address.
169 *
170 * @since CUPS 1.2@
171 */
172
ecdc0628 173char * /* O - Host name */
174httpAddrLookup(
175 const http_addr_t *addr, /* I - Address to lookup */
176 char *name, /* I - Host name buffer */
177 int namelen) /* I - Size of name buffer */
ef416fc2 178{
179 DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)\n",
180 addr, name, namelen));
181
182 /*
183 * Range check input...
184 */
185
186 if (!addr || !name || namelen <= 2)
187 {
188 if (name && namelen >= 1)
189 *name = '\0';
190
191 return (NULL);
192 }
193
194#ifdef AF_LOCAL
195 if (addr->addr.sa_family == AF_LOCAL)
196 strlcpy(name, addr->un.sun_path, namelen);
197 else
198#endif /* AF_LOCAL */
199#ifdef HAVE_GETNAMEINFO
200 {
db1f069b
MS
201 /*
202 * STR #2486: httpAddrLookup() fails when getnameinfo() returns EAI_AGAIN
203 *
204 * FWIW, I think this is really a bug in the implementation of
205 * getnameinfo(), but falling back on httpAddrString() is easy to
206 * do...
207 */
ef416fc2 208
db1f069b
MS
209 if (getnameinfo(&addr->addr, httpAddrLength(addr), name, namelen,
210 NULL, 0, 0))
211 return (httpAddrString(addr, name, namelen));
ef416fc2 212 }
213#else
214 {
215 struct hostent *host; /* Host from name service */
216
217
218# ifdef AF_INET6
219 if (addr->addr.sa_family == AF_INET6)
220 host = gethostbyaddr(ADDR_CAST &(addr->ipv6.sin6_addr),
221 sizeof(struct in_addr), AF_INET6);
222 else
223# endif /* AF_INET6 */
224 host = gethostbyaddr(ADDR_CAST &(addr->ipv4.sin_addr),
225 sizeof(struct in_addr), AF_INET);
226
227 if (host == NULL)
228 {
229 /*
230 * No hostname, so return the raw address...
231 */
232
233 httpAddrString(addr, name, namelen);
234 return (NULL);
235 }
236
237 strlcpy(name, host->h_name, namelen);
238 }
239#endif /* HAVE_GETNAMEINFO */
240
241 return (name);
242}
243
244
1ff0402e
MS
245/*
246 * '_httpAddrPort()' - Get the port number associated with an address.
247 */
248
249int /* O - Port number */
250_httpAddrPort(http_addr_t *addr) /* I - Address */
251{
252#ifdef AF_INET6
253 if (addr->addr.sa_family == AF_INET6)
254 return (ntohs(addr->ipv6.sin6_port));
255 else
256#endif /* AF_INET6 */
257 if (addr->addr.sa_family == AF_INET)
258 return (ntohs(addr->ipv4.sin_port));
259 else
260 return (ippPort());
261}
262
263
ef416fc2 264/*
ecdc0628 265 * 'httpAddrString()' - Convert an address to a numeric string.
ef416fc2 266 *
267 * @since CUPS 1.2@
268 */
269
ecdc0628 270char * /* O - Numeric address string */
271httpAddrString(const http_addr_t *addr, /* I - Address to convert */
272 char *s, /* I - String buffer */
273 int slen) /* I - Length of string */
ef416fc2 274{
275 DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)\n",
276 addr, s, slen));
277
278 /*
279 * Range check input...
280 */
281
282 if (!addr || !s || slen <= 2)
283 {
284 if (s && slen >= 1)
285 *s = '\0';
286
287 return (NULL);
288 }
289
290#ifdef AF_LOCAL
291 if (addr->addr.sa_family == AF_LOCAL)
292 strlcpy(s, addr->un.sun_path, slen);
293 else
294#endif /* AF_LOCAL */
b423cd4c 295 if (addr->addr.sa_family == AF_INET)
ef416fc2 296 {
b423cd4c 297 unsigned temp; /* Temporary address */
ef416fc2 298
299
b423cd4c 300 temp = ntohl(addr->ipv4.sin_addr.s_addr);
301
302 snprintf(s, slen, "%d.%d.%d.%d", (temp >> 24) & 255,
303 (temp >> 16) & 255, (temp >> 8) & 255, temp & 255);
304 }
305#ifdef AF_INET6
306 else if (addr->addr.sa_family == AF_INET6)
307 {
308# ifdef HAVE_GETNAMEINFO
ef416fc2 309 if (getnameinfo(&addr->addr, httpAddrLength(addr), s, slen,
b423cd4c 310 NULL, 0, NI_NUMERICHOST))
ef416fc2 311 {
312 /*
313 * If we get an error back, then the address type is not supported
314 * and we should zero out the buffer...
315 */
316
317 s[0] = '\0';
318
319 return (NULL);
320 }
b423cd4c 321# else
322 char *sptr; /* Pointer into string */
323 int i; /* Looping var */
324 unsigned temp; /* Current value */
325 const char *prefix; /* Prefix for address */
326
327
328 prefix = "";
329 for (sptr = s, i = 0; i < 4 && addr->ipv6.sin6_addr.s6_addr32[i]; i ++)
ef416fc2 330 {
b423cd4c 331 temp = ntohl(addr->ipv6.sin6_addr.s6_addr32[i]);
ef416fc2 332
b423cd4c 333 snprintf(sptr, slen, "%s%x", prefix, (temp >> 16) & 0xffff);
334 prefix = ":";
335 slen -= strlen(sptr);
336 sptr += strlen(sptr);
ef416fc2 337
b423cd4c 338 temp &= 0xffff;
ef416fc2 339
b423cd4c 340 if (temp || i == 3 || addr->ipv6.sin6_addr.s6_addr32[i + 1])
341 {
342 snprintf(sptr, slen, "%s%x", prefix, temp);
ef416fc2 343 slen -= strlen(sptr);
344 sptr += strlen(sptr);
ef416fc2 345 }
b423cd4c 346 }
347
348 if (i < 4)
349 {
350 while (i < 4 && !addr->ipv6.sin6_addr.s6_addr32[i])
351 i ++;
ef416fc2 352
353 if (i < 4)
354 {
b423cd4c 355 snprintf(sptr, slen, "%s:", prefix);
356 prefix = ":";
357 slen -= strlen(sptr);
358 sptr += strlen(sptr);
ef416fc2 359
b423cd4c 360 for (; i < 4; i ++)
ef416fc2 361 {
b423cd4c 362 temp = ntohl(addr->ipv6.sin6_addr.s6_addr32[i]);
ef416fc2 363
b423cd4c 364 if ((temp & 0xffff0000) || addr->ipv6.sin6_addr.s6_addr32[i - 1])
ef416fc2 365 {
b423cd4c 366 snprintf(sptr, slen, "%s%x", prefix, (temp >> 16) & 0xffff);
ef416fc2 367 slen -= strlen(sptr);
368 sptr += strlen(sptr);
b423cd4c 369 }
ef416fc2 370
b423cd4c 371 snprintf(sptr, slen, "%s%x", prefix, temp & 0xffff);
372 slen -= strlen(sptr);
373 sptr += strlen(sptr);
ef416fc2 374 }
375 }
b423cd4c 376 else if (sptr == s)
377 {
378 /*
379 * Empty address...
380 */
ef416fc2 381
b423cd4c 382 strlcpy(s, "::", slen);
383 sptr = s + 2;
384 slen -= 2;
385 }
386 else
387 {
388 /*
389 * Empty at end...
390 */
ef416fc2 391
b423cd4c 392 strlcpy(sptr, "::", slen);
393 sptr += 2;
394 slen -= 2;
395 }
ef416fc2 396 }
b423cd4c 397# endif /* HAVE_GETNAMEINFO */
ef416fc2 398 }
b423cd4c 399#endif /* AF_INET6 */
400 else
401 strlcpy(s, "UNKNOWN", slen);
ef416fc2 402
403 DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s));
404
405 return (s);
406}
407
408
409/*
410 * 'httpGetHostByName()' - Lookup a hostname or IPv4 address, and return
411 * address records for the specified name.
412 *
413 * @deprecated@
414 */
415
416struct hostent * /* O - Host entry */
417httpGetHostByName(const char *name) /* I - Hostname or IP address */
418{
419 const char *nameptr; /* Pointer into name */
420 unsigned ip[4]; /* IP address components */
421 _cups_globals_t *cg = _cupsGlobals();
422 /* Pointer to library globals */
423
424
425 DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name));
426
427 /*
428 * Avoid lookup delays and configuration problems when connecting
429 * to the localhost address...
430 */
431
432 if (!strcmp(name, "localhost"))
433 name = "127.0.0.1";
434
435 /*
436 * This function is needed because some operating systems have a
437 * buggy implementation of gethostbyname() that does not support
438 * IP addresses. If the first character of the name string is a
439 * number, then sscanf() is used to extract the IP components.
440 * We then pack the components into an IPv4 address manually,
441 * since the inet_aton() function is deprecated. We use the
442 * htonl() macro to get the right byte order for the address.
443 *
444 * We also support domain sockets when supported by the underlying
445 * OS...
446 */
447
448#ifdef AF_LOCAL
449 if (name[0] == '/')
450 {
451 /*
452 * A domain socket address, so make an AF_LOCAL entry and return it...
453 */
454
455 cg->hostent.h_name = (char *)name;
456 cg->hostent.h_aliases = NULL;
457 cg->hostent.h_addrtype = AF_LOCAL;
458 cg->hostent.h_length = strlen(name) + 1;
459 cg->hostent.h_addr_list = cg->ip_ptrs;
460 cg->ip_ptrs[0] = (char *)name;
461 cg->ip_ptrs[1] = NULL;
462
463 DEBUG_puts("httpGetHostByName: returning domain socket address...");
464
465 return (&cg->hostent);
466 }
467#endif /* AF_LOCAL */
468
469 for (nameptr = name; isdigit(*nameptr & 255) || *nameptr == '.'; nameptr ++);
470
471 if (!*nameptr)
472 {
473 /*
474 * We have an IPv4 address; break it up and provide the host entry
475 * to the caller.
476 */
477
478 if (sscanf(name, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) != 4)
479 return (NULL); /* Must have 4 numbers */
480
481 if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255)
482 return (NULL); /* Invalid byte ranges! */
483
484 cg->ip_addr = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) |
485 ip[3]));
486
487 /*
488 * Fill in the host entry and return it...
489 */
490
491 cg->hostent.h_name = (char *)name;
492 cg->hostent.h_aliases = NULL;
493 cg->hostent.h_addrtype = AF_INET;
494 cg->hostent.h_length = 4;
495 cg->hostent.h_addr_list = cg->ip_ptrs;
496 cg->ip_ptrs[0] = (char *)&(cg->ip_addr);
497 cg->ip_ptrs[1] = NULL;
498
499 DEBUG_puts("httpGetHostByName: returning IPv4 address...");
500
501 return (&cg->hostent);
502 }
503 else
504 {
505 /*
506 * Use the gethostbyname() function to get the IPv4 address for
507 * the name...
508 */
509
510 DEBUG_puts("httpGetHostByName: returning domain lookup address(es)...");
511
512 return (gethostbyname(name));
513 }
514}
515
516
517/*
757d2cad 518 * 'httpGetHostname()' - Get the FQDN for the connection or local system.
ef416fc2 519 *
757d2cad 520 * When "http" points to a connected socket, return the hostname or
521 * address that was used in the call to httpConnect() or httpConnectEncrypt().
522 * Otherwise, return the FQDN for the local system using both gethostname()
523 * and gethostbyname() to get the local hostname with domain.
ef416fc2 524 *
525 * @since CUPS 1.2@
526 */
527
757d2cad 528const char * /* O - FQDN for connection or system */
529httpGetHostname(http_t *http, /* I - HTTP connection or NULL */
530 char *s, /* I - String buffer for name */
531 int slen) /* I - Size of buffer */
ef416fc2 532{
533 struct hostent *host; /* Host entry to get FQDN */
534
535
89d46774 536 if (!s || slen <= 1)
537 return (NULL);
538
757d2cad 539 if (http)
480ef0fe 540 {
541 if (http->hostname[0] == '/')
542 strlcpy(s, "localhost", slen);
543 else
544 strlcpy(s, http->hostname, slen);
545 }
757d2cad 546 else
ef416fc2 547 {
548 /*
757d2cad 549 * Get the hostname...
ef416fc2 550 */
551
89d46774 552 if (gethostname(s, slen) < 0)
553 strlcpy(s, "localhost", slen);
757d2cad 554
555 if (!strchr(s, '.'))
556 {
557 /*
558 * The hostname is not a FQDN, so look it up...
559 */
560
89d46774 561 if ((host = gethostbyname(s)) != NULL && host->h_name)
757d2cad 562 strlcpy(s, host->h_name, slen);
563 }
ef416fc2 564 }
565
566 /*
567 * Return the hostname with as much domain info as we have...
568 */
569
570 return (s);
571}
572
573
574/*
2e4ff8af 575 * End of "$Id: http-addr.c 6814 2007-08-20 20:09:25Z mike $".
ef416fc2 576 */