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