]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/http-addr.c
Drop old private APIs that are no longer used/supported.
[thirdparty/cups.git] / cups / http-addr.c
1 /*
2 * "$Id$"
3 *
4 * HTTP address routines for CUPS.
5 *
6 * Copyright 2007-2013 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
8 *
9 * These coded instructions, statements, and computer programs are the
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/".
14 */
15
16 /*
17 * Include necessary headers...
18 */
19
20 #include "cups-private.h"
21 #include <sys/stat.h>
22 #ifdef HAVE_RESOLV_H
23 # include <resolv.h>
24 #endif /* HAVE_RESOLV_H */
25 #ifdef __APPLE__
26 # include <CoreFoundation/CoreFoundation.h>
27 # include <SystemConfiguration/SystemConfiguration.h>
28 #endif /* __APPLE__ */
29
30
31 /*
32 * 'httpAddrAny()' - Check for the "any" address.
33 *
34 * @since CUPS 1.2/OS X 10.5@
35 */
36
37 int /* O - 1 if "any", 0 otherwise */
38 httpAddrAny(const http_addr_t *addr) /* I - Address to check */
39 {
40 if (!addr)
41 return (0);
42
43 #ifdef AF_INET6
44 if (addr->addr.sa_family == AF_INET6 &&
45 IN6_IS_ADDR_UNSPECIFIED(&(addr->ipv6.sin6_addr)))
46 return (1);
47 #endif /* AF_INET6 */
48
49 if (addr->addr.sa_family == AF_INET &&
50 ntohl(addr->ipv4.sin_addr.s_addr) == 0x00000000)
51 return (1);
52
53 return (0);
54 }
55
56
57 /*
58 * 'httpAddrClose()' - Close a socket created by @link httpAddrConnect@ or
59 * @link httpAddrListen@.
60 *
61 * Pass @code NULL@ for sockets created with @link httpAddrConnect@ and the
62 * listen address for sockets created with @link httpAddrListen@. This will
63 * ensure that domain sockets are removed when closed.
64 *
65 * @since CUPS 2.0@
66 */
67
68 int /* O - 0 on success, -1 on failure */
69 httpAddrClose(http_addr_t *addr, /* I - Listen address or @code NULL@ */
70 int fd) /* I - Socket file descriptor */
71 {
72 #ifdef WIN32
73 if (closesocket(fd))
74 #else
75 if (close(fd))
76 #endif /* WIN32 */
77 return (-1);
78
79 #ifdef AF_LOCAL
80 if (addr && addr->addr.sa_family == AF_LOCAL)
81 return (unlink(addr->un.sun_path));
82 #endif /* AF_LOCAL */
83
84 return (0);
85 }
86
87
88 /*
89 * 'httpAddrEqual()' - Compare two addresses.
90 *
91 * @since CUPS 1.2/OS X 10.5@
92 */
93
94 int /* O - 1 if equal, 0 if not */
95 httpAddrEqual(const http_addr_t *addr1, /* I - First address */
96 const http_addr_t *addr2) /* I - Second address */
97 {
98 if (!addr1 && !addr2)
99 return (1);
100
101 if (!addr1 || !addr2)
102 return (0);
103
104 if (addr1->addr.sa_family != addr2->addr.sa_family)
105 return (0);
106
107 #ifdef AF_LOCAL
108 if (addr1->addr.sa_family == AF_LOCAL)
109 return (!strcmp(addr1->un.sun_path, addr2->un.sun_path));
110 #endif /* AF_LOCAL */
111
112 #ifdef AF_INET6
113 if (addr1->addr.sa_family == AF_INET6)
114 return (!memcmp(&(addr1->ipv6.sin6_addr), &(addr2->ipv6.sin6_addr), 16));
115 #endif /* AF_INET6 */
116
117 return (addr1->ipv4.sin_addr.s_addr == addr2->ipv4.sin_addr.s_addr);
118 }
119
120
121 /*
122 * 'httpAddrLength()' - Return the length of the address in bytes.
123 *
124 * @since CUPS 1.2/OS X 10.5@
125 */
126
127 int /* O - Length in bytes */
128 httpAddrLength(const http_addr_t *addr) /* I - Address */
129 {
130 if (!addr)
131 return (0);
132
133 #ifdef AF_INET6
134 if (addr->addr.sa_family == AF_INET6)
135 return (sizeof(addr->ipv6));
136 else
137 #endif /* AF_INET6 */
138 #ifdef AF_LOCAL
139 if (addr->addr.sa_family == AF_LOCAL)
140 return (offsetof(struct sockaddr_un, sun_path) +
141 strlen(addr->un.sun_path) + 1);
142 else
143 #endif /* AF_LOCAL */
144 if (addr->addr.sa_family == AF_INET)
145 return (sizeof(addr->ipv4));
146 else
147 return (0);
148
149 }
150
151
152 /*
153 * 'httpAddrListen()' - Create a listening socket bound to the specified
154 * address and port.
155 *
156 * @since CUPS 1.7/OS X 10.9@
157 */
158
159 int /* O - Socket or -1 on error */
160 httpAddrListen(http_addr_t *addr, /* I - Address to bind to */
161 int port) /* I - Port number to bind to */
162 {
163 int fd = -1, /* Socket */
164 val, /* Socket value */
165 status; /* Bind status */
166
167
168 /*
169 * Range check input...
170 */
171
172 if (!addr || port < 0)
173 return (-1);
174
175 /*
176 * Create the socket and set options...
177 */
178
179 if ((fd = socket(addr->addr.sa_family, SOCK_STREAM, 0)) < 0)
180 {
181 _cupsSetHTTPError(HTTP_STATUS_ERROR);
182 return (-1);
183 }
184
185 val = 1;
186 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, CUPS_SOCAST &val, sizeof(val));
187
188 #ifdef IPV6_V6ONLY
189 if (addr->addr.sa_family == AF_INET6)
190 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, CUPS_SOCAST &val, sizeof(val));
191 #endif /* IPV6_V6ONLY */
192
193 /*
194 * Bind the socket...
195 */
196
197 #ifdef AF_LOCAL
198 if (addr->addr.sa_family == AF_LOCAL)
199 {
200 mode_t mask; /* Umask setting */
201
202 /*
203 * Remove any existing domain socket file...
204 */
205
206 unlink(addr->un.sun_path);
207
208 /*
209 * Save the current umask and set it to 0 so that all users can access
210 * the domain socket...
211 */
212
213 mask = umask(0);
214
215 /*
216 * Bind the domain socket...
217 */
218
219 status = bind(fd, (struct sockaddr *)addr, httpAddrLength(addr));
220
221 /*
222 * Restore the umask and fix permissions...
223 */
224
225 umask(mask);
226 chmod(addr->un.sun_path, 0140777);
227 }
228 else
229 #endif /* AF_LOCAL */
230 {
231 _httpAddrSetPort(addr, port);
232
233 status = bind(fd, (struct sockaddr *)addr, httpAddrLength(addr));
234 }
235
236 if (status)
237 {
238 _cupsSetHTTPError(HTTP_STATUS_ERROR);
239
240 close(fd);
241
242 return (-1);
243 }
244
245 /*
246 * Listen...
247 */
248
249 if (listen(fd, 5))
250 {
251 _cupsSetHTTPError(HTTP_STATUS_ERROR);
252
253 close(fd);
254
255 return (-1);
256 }
257
258 /*
259 * Close on exec...
260 */
261
262 #ifndef WIN32
263 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
264 #endif /* !WIN32 */
265
266 #ifdef SO_NOSIGPIPE
267 /*
268 * Disable SIGPIPE for this socket.
269 */
270
271 val = 1;
272 setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val));
273 #endif /* SO_NOSIGPIPE */
274
275 return (fd);
276 }
277
278
279 /*
280 * 'httpAddrLocalhost()' - Check for the local loopback address.
281 *
282 * @since CUPS 1.2/OS X 10.5@
283 */
284
285 int /* O - 1 if local host, 0 otherwise */
286 httpAddrLocalhost(
287 const http_addr_t *addr) /* I - Address to check */
288 {
289 if (!addr)
290 return (1);
291
292 #ifdef AF_INET6
293 if (addr->addr.sa_family == AF_INET6 &&
294 IN6_IS_ADDR_LOOPBACK(&(addr->ipv6.sin6_addr)))
295 return (1);
296 #endif /* AF_INET6 */
297
298 #ifdef AF_LOCAL
299 if (addr->addr.sa_family == AF_LOCAL)
300 return (1);
301 #endif /* AF_LOCAL */
302
303 if (addr->addr.sa_family == AF_INET &&
304 (ntohl(addr->ipv4.sin_addr.s_addr) & 0xff000000) == 0x7f000000)
305 return (1);
306
307 return (0);
308 }
309
310
311 /*
312 * 'httpAddrLookup()' - Lookup the hostname associated with the address.
313 *
314 * @since CUPS 1.2/OS X 10.5@
315 */
316
317 char * /* O - Host name */
318 httpAddrLookup(
319 const http_addr_t *addr, /* I - Address to lookup */
320 char *name, /* I - Host name buffer */
321 int namelen) /* I - Size of name buffer */
322 {
323 _cups_globals_t *cg = _cupsGlobals();
324 /* Global data */
325
326
327 DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)", addr, name,
328 namelen));
329
330 /*
331 * Range check input...
332 */
333
334 if (!addr || !name || namelen <= 2)
335 {
336 if (name && namelen >= 1)
337 *name = '\0';
338
339 return (NULL);
340 }
341
342 #ifdef AF_LOCAL
343 if (addr->addr.sa_family == AF_LOCAL)
344 {
345 strlcpy(name, addr->un.sun_path, namelen);
346 return (name);
347 }
348 #endif /* AF_LOCAL */
349
350 /*
351 * Optimize lookups for localhost/loopback addresses...
352 */
353
354 if (httpAddrLocalhost(addr))
355 {
356 strlcpy(name, "localhost", namelen);
357 return (name);
358 }
359
360 #ifdef HAVE_RES_INIT
361 /*
362 * STR #2920: Initialize resolver after failure in cups-polld
363 *
364 * If the previous lookup failed, re-initialize the resolver to prevent
365 * temporary network errors from persisting. This *should* be handled by
366 * the resolver libraries, but apparently the glibc folks do not agree.
367 *
368 * We set a flag at the end of this function if we encounter an error that
369 * requires reinitialization of the resolver functions. We then call
370 * res_init() if the flag is set on the next call here or in httpAddrLookup().
371 */
372
373 if (cg->need_res_init)
374 {
375 res_init();
376
377 cg->need_res_init = 0;
378 }
379 #endif /* HAVE_RES_INIT */
380
381 #ifdef HAVE_GETNAMEINFO
382 {
383 /*
384 * STR #2486: httpAddrLookup() fails when getnameinfo() returns EAI_AGAIN
385 *
386 * FWIW, I think this is really a bug in the implementation of
387 * getnameinfo(), but falling back on httpAddrString() is easy to
388 * do...
389 */
390
391 int error = getnameinfo(&addr->addr, httpAddrLength(addr), name, namelen,
392 NULL, 0, 0);
393
394 if (error)
395 {
396 if (error == EAI_FAIL)
397 cg->need_res_init = 1;
398
399 return (httpAddrString(addr, name, namelen));
400 }
401 }
402 #else
403 {
404 struct hostent *host; /* Host from name service */
405
406
407 # ifdef AF_INET6
408 if (addr->addr.sa_family == AF_INET6)
409 host = gethostbyaddr((char *)&(addr->ipv6.sin6_addr),
410 sizeof(struct in_addr), AF_INET6);
411 else
412 # endif /* AF_INET6 */
413 host = gethostbyaddr((char *)&(addr->ipv4.sin_addr),
414 sizeof(struct in_addr), AF_INET);
415
416 if (host == NULL)
417 {
418 /*
419 * No hostname, so return the raw address...
420 */
421
422 if (h_errno == NO_RECOVERY)
423 cg->need_res_init = 1;
424
425 return (httpAddrString(addr, name, namelen));
426 }
427
428 strlcpy(name, host->h_name, namelen);
429 }
430 #endif /* HAVE_GETNAMEINFO */
431
432 DEBUG_printf(("1httpAddrLookup: returning \"%s\"...", name));
433
434 return (name);
435 }
436
437
438 /*
439 * 'httpAddrFamily()' - Get the address family of an address.
440 */
441
442 int /* O - Address family */
443 httpAddrFamily(http_addr_t *addr) /* I - Address */
444 {
445 if (addr)
446 return (addr->addr.sa_family);
447 else
448 return (0);
449 }
450
451
452 /*
453 * 'httpAddrPort()' - Get the port number associated with an address.
454 *
455 * @since CUPS 1.7/OS X 10.9@
456 */
457
458 int /* O - Port number */
459 httpAddrPort(http_addr_t *addr) /* I - Address */
460 {
461 if (!addr)
462 return (-1);
463 #ifdef AF_INET6
464 else if (addr->addr.sa_family == AF_INET6)
465 return (ntohs(addr->ipv6.sin6_port));
466 #endif /* AF_INET6 */
467 else if (addr->addr.sa_family == AF_INET)
468 return (ntohs(addr->ipv4.sin_port));
469 else
470 return (0);
471 }
472
473
474 /*
475 * '_httpAddrSetPort()' - Set the port number associated with an address.
476 */
477
478 void
479 _httpAddrSetPort(http_addr_t *addr, /* I - Address */
480 int port) /* I - Port */
481 {
482 if (!addr || port <= 0)
483 return;
484
485 #ifdef AF_INET6
486 if (addr->addr.sa_family == AF_INET6)
487 addr->ipv6.sin6_port = htons(port);
488 else
489 #endif /* AF_INET6 */
490 if (addr->addr.sa_family == AF_INET)
491 addr->ipv4.sin_port = htons(port);
492 }
493
494
495 /*
496 * 'httpAddrString()' - Convert an address to a numeric string.
497 *
498 * @since CUPS 1.2/OS X 10.5@
499 */
500
501 char * /* O - Numeric address string */
502 httpAddrString(const http_addr_t *addr, /* I - Address to convert */
503 char *s, /* I - String buffer */
504 int slen) /* I - Length of string */
505 {
506 DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)", addr, s, slen));
507
508 /*
509 * Range check input...
510 */
511
512 if (!addr || !s || slen <= 2)
513 {
514 if (s && slen >= 1)
515 *s = '\0';
516
517 return (NULL);
518 }
519
520 #ifdef AF_LOCAL
521 if (addr->addr.sa_family == AF_LOCAL)
522 {
523 if (addr->un.sun_path[0] == '/')
524 strlcpy(s, addr->un.sun_path, slen);
525 else
526 strlcpy(s, "localhost", slen);
527 }
528 else
529 #endif /* AF_LOCAL */
530 if (addr->addr.sa_family == AF_INET)
531 {
532 unsigned temp; /* Temporary address */
533
534
535 temp = ntohl(addr->ipv4.sin_addr.s_addr);
536
537 snprintf(s, slen, "%d.%d.%d.%d", (temp >> 24) & 255,
538 (temp >> 16) & 255, (temp >> 8) & 255, temp & 255);
539 }
540 #ifdef AF_INET6
541 else if (addr->addr.sa_family == AF_INET6)
542 {
543 char *sptr, /* Pointer into string */
544 temps[64]; /* Temporary string for address */
545
546 # ifdef HAVE_GETNAMEINFO
547 if (getnameinfo(&addr->addr, httpAddrLength(addr), temps, sizeof(temps),
548 NULL, 0, NI_NUMERICHOST))
549 {
550 /*
551 * If we get an error back, then the address type is not supported
552 * and we should zero out the buffer...
553 */
554
555 s[0] = '\0';
556
557 return (NULL);
558 }
559 else if ((sptr = strchr(temps, '%')) != NULL)
560 {
561 /*
562 * Convert "%zone" to "+zone" to match URI form...
563 */
564
565 *sptr = '+';
566 }
567
568 # else
569 int i; /* Looping var */
570 unsigned temp; /* Current value */
571 const char *prefix; /* Prefix for address */
572
573
574 prefix = "";
575 for (sptr = temps, i = 0; i < 4 && addr->ipv6.sin6_addr.s6_addr32[i]; i ++)
576 {
577 temp = ntohl(addr->ipv6.sin6_addr.s6_addr32[i]);
578
579 snprintf(sptr, sizeof(temps) - (sptr - temps), "%s%x", prefix,
580 (temp >> 16) & 0xffff);
581 prefix = ":";
582 sptr += strlen(sptr);
583
584 temp &= 0xffff;
585
586 if (temp || i == 3 || addr->ipv6.sin6_addr.s6_addr32[i + 1])
587 {
588 snprintf(sptr, sizeof(temps) - (sptr - temps), "%s%x", prefix, temp);
589 sptr += strlen(sptr);
590 }
591 }
592
593 if (i < 4)
594 {
595 while (i < 4 && !addr->ipv6.sin6_addr.s6_addr32[i])
596 i ++;
597
598 if (i < 4)
599 {
600 snprintf(sptr, sizeof(temps) - (sptr - temps), "%s:", prefix);
601 prefix = ":";
602 sptr += strlen(sptr);
603
604 for (; i < 4; i ++)
605 {
606 temp = ntohl(addr->ipv6.sin6_addr.s6_addr32[i]);
607
608 if ((temp & 0xffff0000) ||
609 (i > 0 && addr->ipv6.sin6_addr.s6_addr32[i - 1]))
610 {
611 snprintf(sptr, sizeof(temps) - (sptr - temps), "%s%x", prefix,
612 (temp >> 16) & 0xffff);
613 sptr += strlen(sptr);
614 }
615
616 snprintf(sptr, sizeof(temps) - (sptr - temps), "%s%x", prefix,
617 temp & 0xffff);
618 sptr += strlen(sptr);
619 }
620 }
621 else if (sptr == s)
622 {
623 /*
624 * Empty address...
625 */
626
627 strlcpy(temps, "::", sizeof(temps));
628 }
629 else
630 {
631 /*
632 * Empty at end...
633 */
634
635 strlcpy(sptr, "::", sizeof(temps) - (sptr - temps));
636 }
637 }
638 # endif /* HAVE_GETNAMEINFO */
639
640 /*
641 * Add "[v1." and "]" around IPv6 address to convert to URI form.
642 */
643
644 snprintf(s, slen, "[v1.%s]", temps);
645 }
646 #endif /* AF_INET6 */
647 else
648 strlcpy(s, "UNKNOWN", slen);
649
650 DEBUG_printf(("1httpAddrString: returning \"%s\"...", s));
651
652 return (s);
653 }
654
655
656 /*
657 * 'httpGetAddress()' - Get the address of the connected peer of a connection.
658 *
659 * Returns @code NULL@ if the socket is currently unconnected.
660 *
661 * @since CUPS 2.0@
662 */
663
664 http_addr_t * /* O - Connected address or @code NULL@ */
665 httpGetAddress(http_t *http) /* I - HTTP connection */
666 {
667 if (http)
668 return (http->hostaddr);
669 else
670 return (NULL);
671 }
672
673
674 /*
675 * 'httpGetHostByName()' - Lookup a hostname or IPv4 address, and return
676 * address records for the specified name.
677 *
678 * @deprecated@
679 */
680
681 struct hostent * /* O - Host entry */
682 httpGetHostByName(const char *name) /* I - Hostname or IP address */
683 {
684 const char *nameptr; /* Pointer into name */
685 unsigned ip[4]; /* IP address components */
686 _cups_globals_t *cg = _cupsGlobals();
687 /* Pointer to library globals */
688
689
690 DEBUG_printf(("httpGetHostByName(name=\"%s\")", name));
691
692 /*
693 * Avoid lookup delays and configuration problems when connecting
694 * to the localhost address...
695 */
696
697 if (!strcmp(name, "localhost"))
698 name = "127.0.0.1";
699
700 /*
701 * This function is needed because some operating systems have a
702 * buggy implementation of gethostbyname() that does not support
703 * IP addresses. If the first character of the name string is a
704 * number, then sscanf() is used to extract the IP components.
705 * We then pack the components into an IPv4 address manually,
706 * since the inet_aton() function is deprecated. We use the
707 * htonl() macro to get the right byte order for the address.
708 *
709 * We also support domain sockets when supported by the underlying
710 * OS...
711 */
712
713 #ifdef AF_LOCAL
714 if (name[0] == '/')
715 {
716 /*
717 * A domain socket address, so make an AF_LOCAL entry and return it...
718 */
719
720 cg->hostent.h_name = (char *)name;
721 cg->hostent.h_aliases = NULL;
722 cg->hostent.h_addrtype = AF_LOCAL;
723 cg->hostent.h_length = strlen(name) + 1;
724 cg->hostent.h_addr_list = cg->ip_ptrs;
725 cg->ip_ptrs[0] = (char *)name;
726 cg->ip_ptrs[1] = NULL;
727
728 DEBUG_puts("1httpGetHostByName: returning domain socket address...");
729
730 return (&cg->hostent);
731 }
732 #endif /* AF_LOCAL */
733
734 for (nameptr = name; isdigit(*nameptr & 255) || *nameptr == '.'; nameptr ++);
735
736 if (!*nameptr)
737 {
738 /*
739 * We have an IPv4 address; break it up and provide the host entry
740 * to the caller.
741 */
742
743 if (sscanf(name, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) != 4)
744 return (NULL); /* Must have 4 numbers */
745
746 if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255)
747 return (NULL); /* Invalid byte ranges! */
748
749 cg->ip_addr = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) |
750 ip[3]));
751
752 /*
753 * Fill in the host entry and return it...
754 */
755
756 cg->hostent.h_name = (char *)name;
757 cg->hostent.h_aliases = NULL;
758 cg->hostent.h_addrtype = AF_INET;
759 cg->hostent.h_length = 4;
760 cg->hostent.h_addr_list = cg->ip_ptrs;
761 cg->ip_ptrs[0] = (char *)&(cg->ip_addr);
762 cg->ip_ptrs[1] = NULL;
763
764 DEBUG_puts("1httpGetHostByName: returning IPv4 address...");
765
766 return (&cg->hostent);
767 }
768 else
769 {
770 /*
771 * Use the gethostbyname() function to get the IPv4 address for
772 * the name...
773 */
774
775 DEBUG_puts("1httpGetHostByName: returning domain lookup address(es)...");
776
777 return (gethostbyname(name));
778 }
779 }
780
781
782 /*
783 * 'httpGetHostname()' - Get the FQDN for the connection or local system.
784 *
785 * When "http" points to a connected socket, return the hostname or
786 * address that was used in the call to httpConnect() or httpConnectEncrypt(),
787 * or the address of the client for the connection from httpAcceptConnection().
788 * Otherwise, return the FQDN for the local system using both gethostname()
789 * and gethostbyname() to get the local hostname with domain.
790 *
791 * @since CUPS 1.2/OS X 10.5@
792 */
793
794 const char * /* O - FQDN for connection or system */
795 httpGetHostname(http_t *http, /* I - HTTP connection or NULL */
796 char *s, /* I - String buffer for name */
797 int slen) /* I - Size of buffer */
798 {
799 if (http)
800 {
801 if (!s || slen <= 1)
802 {
803 if (http->hostname[0] == '/')
804 return ("localhost");
805 else
806 return (http->hostname);
807 }
808 else if (http->hostname[0] == '/')
809 strlcpy(s, "localhost", slen);
810 else
811 strlcpy(s, http->hostname, slen);
812 }
813 else
814 {
815 /*
816 * Get the hostname...
817 */
818
819 if (!s || slen <= 1)
820 return (NULL);
821
822 if (gethostname(s, slen) < 0)
823 strlcpy(s, "localhost", slen);
824
825 if (!strchr(s, '.'))
826 {
827 #ifdef HAVE_SCDYNAMICSTORECOPYCOMPUTERNAME
828 /*
829 * The hostname is not a FQDN, so use the local hostname from the
830 * SystemConfiguration framework...
831 */
832
833 SCDynamicStoreRef sc = SCDynamicStoreCreate(kCFAllocatorDefault,
834 CFSTR("libcups"), NULL, NULL);
835 /* System configuration data */
836 CFStringRef local = sc ? SCDynamicStoreCopyLocalHostName(sc) : NULL;
837 /* Local host name */
838 char localStr[1024]; /* Local host name C string */
839
840 if (local && CFStringGetCString(local, localStr, sizeof(localStr),
841 kCFStringEncodingUTF8))
842 {
843 /*
844 * Append ".local." to the hostname we get...
845 */
846
847 snprintf(s, slen, "%s.local.", localStr);
848 }
849
850 if (local)
851 CFRelease(local);
852 if (sc)
853 CFRelease(sc);
854
855 #else
856 /*
857 * The hostname is not a FQDN, so look it up...
858 */
859
860 struct hostent *host; /* Host entry to get FQDN */
861
862 if ((host = gethostbyname(s)) != NULL && host->h_name)
863 {
864 /*
865 * Use the resolved hostname...
866 */
867
868 strlcpy(s, host->h_name, slen);
869 }
870 #endif /* HAVE_SCDYNAMICSTORECOPYCOMPUTERNAME */
871 }
872 }
873
874 /*
875 * Return the hostname with as much domain info as we have...
876 */
877
878 return (s);
879 }
880
881
882 /*
883 * 'httpResolveHostname()' - Resolve the hostname of the HTTP connection
884 * address.
885 *
886 * @since CUPS 2.0@
887 */
888
889 const char * /* O - Resolved hostname or @code NULL@ */
890 httpResolveHostname(http_t *http, /* I - HTTP connection */
891 char *buffer, /* I - Hostname buffer */
892 size_t bufsize) /* I - Size of buffer */
893 {
894 if (!http)
895 return (NULL);
896
897 if (isdigit(http->hostname[0] & 255) || http->hostname[0] == '[')
898 {
899 char temp[1024]; /* Temporary string */
900
901 if (httpAddrLookup(http->hostaddr, temp, sizeof(temp)))
902 strlcpy(http->hostname, temp, sizeof(http->hostname));
903 else
904 return (NULL);
905 }
906
907 if (buffer)
908 {
909 if (http->hostname[0] == '/')
910 strlcpy(buffer, "localhost", bufsize);
911 else
912 strlcpy(buffer, http->hostname, bufsize);
913
914 return (buffer);
915 }
916 else if (http->hostname[0] == '/')
917 return ("localhost");
918 else
919 return (http->hostname);
920 }
921
922
923 /*
924 * End of "$Id$".
925 */