]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/http-addrlist.c
Fix clang-reported issues (<rdar://problem/15936066>)
[thirdparty/cups.git] / cups / http-addrlist.c
1 /*
2 * "$Id$"
3 *
4 * HTTP address list routines for CUPS.
5 *
6 * Copyright 2007-2013 by Apple Inc.
7 * Copyright 1997-2007 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 #ifdef HAVE_RESOLV_H
22 # include <resolv.h>
23 #endif /* HAVE_RESOLV_H */
24 #ifdef HAVE_POLL
25 # include <poll.h>
26 #endif /* HAVE_POLL */
27 #ifndef WIN32
28 # include <fcntl.h>
29 #endif /* WIN32 */
30
31
32 /*
33 * 'httpAddrConnect()' - Connect to any of the addresses in the list.
34 *
35 * @since CUPS 1.2/OS X 10.5@
36 */
37
38 http_addrlist_t * /* O - Connected address or NULL on failure */
39 httpAddrConnect(
40 http_addrlist_t *addrlist, /* I - List of potential addresses */
41 int *sock) /* O - Socket */
42 {
43 DEBUG_printf(("httpAddrConnect(addrlist=%p, sock=%p)", addrlist, sock));
44
45 return (httpAddrConnect2(addrlist, sock, 30000, NULL));
46 }
47
48
49 /*
50 * 'httpAddrConnect2()' - Connect to any of the addresses in the list with a
51 * timeout and optional cancel.
52 *
53 * @since CUPS 1.7/OS X 10.9@
54 */
55
56 http_addrlist_t * /* O - Connected address or NULL on failure */
57 httpAddrConnect2(
58 http_addrlist_t *addrlist, /* I - List of potential addresses */
59 int *sock, /* O - Socket */
60 int msec, /* I - Timeout in milliseconds */
61 int *cancel) /* I - Pointer to "cancel" variable */
62 {
63 int val; /* Socket option value */
64 #ifdef O_NONBLOCK
65 socklen_t len; /* Length of value */
66 http_addr_t peer; /* Peer address */
67 int flags, /* Socket flags */
68 remaining; /* Remaining timeout */
69 # ifdef HAVE_POLL
70 struct pollfd pfd; /* Polled file descriptor */
71 # else
72 fd_set input_set, /* select() input set */
73 output_set; /* select() output set */
74 struct timeval timeout; /* Timeout */
75 # endif /* HAVE_POLL */
76 int nfds; /* Result from select()/poll() */
77 #endif /* O_NONBLOCK */
78 #ifdef DEBUG
79 char temp[256]; /* Temporary address string */
80 #endif /* DEBUG */
81
82
83 DEBUG_printf(("httpAddrConnect2(addrlist=%p, sock=%p, msec=%d, cancel=%p)",
84 addrlist, sock, msec, cancel));
85
86 if (!sock)
87 {
88 errno = EINVAL;
89 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
90 return (NULL);
91 }
92
93 if (cancel && *cancel)
94 return (NULL);
95
96 if (msec <= 0 || getenv("CUPS_DISABLE_ASYNC_CONNECT"))
97 msec = INT_MAX;
98
99 /*
100 * Loop through each address until we connect or run out of addresses...
101 */
102
103 while (addrlist)
104 {
105 if (cancel && *cancel)
106 return (NULL);
107
108 /*
109 * Create the socket...
110 */
111
112 DEBUG_printf(("2httpAddrConnect2: Trying %s:%d...",
113 httpAddrString(&(addrlist->addr), temp, sizeof(temp)),
114 httpAddrPort(&(addrlist->addr))));
115
116 if ((*sock = (int)socket(httpAddrFamily(&(addrlist->addr)), SOCK_STREAM,
117 0)) < 0)
118 {
119 /*
120 * Don't abort yet, as this could just be an issue with the local
121 * system not being configured with IPv4/IPv6/domain socket enabled...
122 */
123
124 addrlist = addrlist->next;
125 continue;
126 }
127
128 /*
129 * Set options...
130 */
131
132 val = 1;
133 setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, CUPS_SOCAST &val, sizeof(val));
134
135 #ifdef SO_REUSEPORT
136 val = 1;
137 setsockopt(*sock, SOL_SOCKET, SO_REUSEPORT, CUPS_SOCAST &val, sizeof(val));
138 #endif /* SO_REUSEPORT */
139
140 #ifdef SO_NOSIGPIPE
141 val = 1;
142 setsockopt(*sock, SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val));
143 #endif /* SO_NOSIGPIPE */
144
145 /*
146 * Using TCP_NODELAY improves responsiveness, especially on systems
147 * with a slow loopback interface...
148 */
149
150 val = 1;
151 setsockopt(*sock, IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val));
152
153 #ifdef FD_CLOEXEC
154 /*
155 * Close this socket when starting another process...
156 */
157
158 fcntl(*sock, F_SETFD, FD_CLOEXEC);
159 #endif /* FD_CLOEXEC */
160
161 #ifdef O_NONBLOCK
162 /*
163 * Do an asynchronous connect by setting the socket non-blocking...
164 */
165
166 DEBUG_printf(("httpAddrConnect2: Setting non-blocking connect()"));
167
168 flags = fcntl(*sock, F_GETFL, 0);
169 if (msec != INT_MAX)
170 {
171 DEBUG_puts("httpAddrConnect2: Setting non-blocking connect()");
172
173 fcntl(*sock, F_SETFL, flags | O_NONBLOCK);
174 }
175 #endif /* O_NONBLOCK */
176
177 /*
178 * Then connect...
179 */
180
181 if (!connect(*sock, &(addrlist->addr.addr),
182 httpAddrLength(&(addrlist->addr))))
183 {
184 DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...",
185 httpAddrString(&(addrlist->addr), temp, sizeof(temp)),
186 httpAddrPort(&(addrlist->addr))));
187
188 #ifdef O_NONBLOCK
189 fcntl(*sock, F_SETFL, flags);
190 #endif /* O_NONBLOCK */
191
192 return (addrlist);
193 }
194
195 #ifdef O_NONBLOCK
196 # ifdef WIN32
197 if (WSAGetLastError() == WSAEINPROGRESS ||
198 WSAGetLastError() == WSAEWOULDBLOCK)
199 # else
200 if (errno == EINPROGRESS || errno == EWOULDBLOCK)
201 # endif /* WIN32 */
202 {
203 DEBUG_puts("1httpAddrConnect2: Finishing async connect()");
204
205 fcntl(*sock, F_SETFL, flags);
206
207 for (remaining = msec; remaining > 0; remaining -= 250)
208 {
209 do
210 {
211 if (cancel && *cancel)
212 {
213 /*
214 * Close this socket and return...
215 */
216
217 DEBUG_puts("1httpAddrConnect2: Canceled connect()");
218
219 httpAddrClose(NULL, *sock);
220
221 *sock = -1;
222
223 return (NULL);
224 }
225
226 # ifdef HAVE_POLL
227 pfd.fd = *sock;
228 pfd.events = POLLIN | POLLOUT;
229
230 nfds = poll(&pfd, 1, remaining > 250 ? 250 : remaining);
231
232 DEBUG_printf(("1httpAddrConnect2: poll() returned %d (%d)", nfds,
233 errno));
234
235 # else
236 FD_ZERO(&input_set);
237 FD_SET(*sock, &input_set);
238 output_set = input_set;
239
240 timeout.tv_sec = 0;
241 timeout.tv_usec = (remaining > 250 ? 250 : remaining) * 1000;
242
243 nfds = select(*sock + 1, &input_set, &output_set, NULL, &timeout);
244
245 DEBUG_printf(("1httpAddrConnect2: select() returned %d (%d)", nfds,
246 errno));
247 # endif /* HAVE_POLL */
248 }
249 # ifdef WIN32
250 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
251 WSAGetLastError() == WSAEWOULDBLOCK));
252 # else
253 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
254 # endif /* WIN32 */
255
256 if (nfds > 0)
257 {
258 len = sizeof(peer);
259 if (!getpeername(*sock, (struct sockaddr *)&peer, &len))
260 {
261 DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...",
262 httpAddrString(&peer, temp, sizeof(temp)),
263 httpAddrPort(&peer)));
264
265 return (addrlist);
266 }
267
268 break;
269 }
270 }
271 }
272 #endif /* O_NONBLOCK */
273
274 DEBUG_printf(("1httpAddrConnect2: Unable to connect to %s:%d: %s",
275 httpAddrString(&(addrlist->addr), temp, sizeof(temp)),
276 httpAddrPort(&(addrlist->addr)), strerror(errno)));
277
278 #ifndef WIN32
279 if (errno == EINPROGRESS)
280 errno = ETIMEDOUT;
281 #endif /* !WIN32 */
282
283 /*
284 * Close this socket and move to the next address...
285 */
286
287 httpAddrClose(NULL, *sock);
288
289 *sock = -1;
290 addrlist = addrlist->next;
291 }
292
293 if (!addrlist)
294 #ifdef WIN32
295 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, "Connection failed", 0);
296 #else
297 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, strerror(errno), 0);
298 #endif /* WIN32 */
299
300 return (addrlist);
301 }
302
303
304
305 /*
306 * 'httpAddrCopyList()' - Copy an address list.
307 *
308 * @since CUPS 1.7/OS X 10.9@
309 */
310
311 http_addrlist_t * /* O - New address list or @code NULL@ on error */
312 httpAddrCopyList(
313 http_addrlist_t *src) /* I - Source address list */
314 {
315 http_addrlist_t *dst = NULL, /* First list entry */
316 *prev = NULL, /* Previous list entry */
317 *current = NULL;/* Current list entry */
318
319
320 while (src)
321 {
322 if ((current = malloc(sizeof(http_addrlist_t))) == NULL)
323 {
324 current = dst;
325
326 while (current)
327 {
328 prev = current;
329 current = current->next;
330
331 free(prev);
332 }
333
334 return (NULL);
335 }
336
337 memcpy(current, src, sizeof(http_addrlist_t));
338
339 current->next = NULL;
340
341 if (prev)
342 prev->next = current;
343 else
344 dst = current;
345
346 prev = current;
347 src = src->next;
348 }
349
350 return (dst);
351 }
352
353
354 /*
355 * 'httpAddrFreeList()' - Free an address list.
356 *
357 * @since CUPS 1.2/OS X 10.5@
358 */
359
360 void
361 httpAddrFreeList(
362 http_addrlist_t *addrlist) /* I - Address list to free */
363 {
364 http_addrlist_t *next; /* Next address in list */
365
366
367 /*
368 * Free each address in the list...
369 */
370
371 while (addrlist)
372 {
373 next = addrlist->next;
374
375 free(addrlist);
376
377 addrlist = next;
378 }
379 }
380
381
382 /*
383 * 'httpAddrGetList()' - Get a list of addresses for a hostname.
384 *
385 * @since CUPS 1.2/OS X 10.5@
386 */
387
388 http_addrlist_t * /* O - List of addresses or NULL */
389 httpAddrGetList(const char *hostname, /* I - Hostname, IP address, or NULL for passive listen address */
390 int family, /* I - Address family or AF_UNSPEC */
391 const char *service) /* I - Service name or port number */
392 {
393 http_addrlist_t *first, /* First address in list */
394 *addr, /* Current address in list */
395 *temp; /* New address */
396 _cups_globals_t *cg = _cupsGlobals();
397 /* Global data */
398
399
400 #ifdef DEBUG
401 _cups_debug_printf("httpAddrGetList(hostname=\"%s\", family=AF_%s, "
402 "service=\"%s\")\n",
403 hostname ? hostname : "(nil)",
404 family == AF_UNSPEC ? "UNSPEC" :
405 # ifdef AF_LOCAL
406 family == AF_LOCAL ? "LOCAL" :
407 # endif /* AF_LOCAL */
408 # ifdef AF_INET6
409 family == AF_INET6 ? "INET6" :
410 # endif /* AF_INET6 */
411 family == AF_INET ? "INET" : "???", service);
412 #endif /* DEBUG */
413
414 #ifdef HAVE_RES_INIT
415 /*
416 * STR #2920: Initialize resolver after failure in cups-polld
417 *
418 * If the previous lookup failed, re-initialize the resolver to prevent
419 * temporary network errors from persisting. This *should* be handled by
420 * the resolver libraries, but apparently the glibc folks do not agree.
421 *
422 * We set a flag at the end of this function if we encounter an error that
423 * requires reinitialization of the resolver functions. We then call
424 * res_init() if the flag is set on the next call here or in httpAddrLookup().
425 */
426
427 if (cg->need_res_init)
428 {
429 res_init();
430
431 cg->need_res_init = 0;
432 }
433 #endif /* HAVE_RES_INIT */
434
435 /*
436 * Lookup the address the best way we can...
437 */
438
439 first = addr = NULL;
440
441 #ifdef AF_LOCAL
442 if (hostname && hostname[0] == '/')
443 {
444 /*
445 * Domain socket address...
446 */
447
448 if ((first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t))) != NULL)
449 {
450 addr = first;
451 first->addr.un.sun_family = AF_LOCAL;
452 strlcpy(first->addr.un.sun_path, hostname, sizeof(first->addr.un.sun_path));
453 }
454 }
455 else
456 #endif /* AF_LOCAL */
457 if (!hostname || _cups_strcasecmp(hostname, "localhost"))
458 {
459 #ifdef HAVE_GETADDRINFO
460 struct addrinfo hints, /* Address lookup hints */
461 *results, /* Address lookup results */
462 *current; /* Current result */
463 char ipv6[64], /* IPv6 address */
464 *ipv6zone; /* Pointer to zone separator */
465 int ipv6len; /* Length of IPv6 address */
466 int error; /* getaddrinfo() error */
467
468
469 /*
470 * Lookup the address as needed...
471 */
472
473 memset(&hints, 0, sizeof(hints));
474 hints.ai_family = family;
475 hints.ai_flags = hostname ? 0 : AI_PASSIVE;
476 hints.ai_socktype = SOCK_STREAM;
477
478 if (hostname && *hostname == '[')
479 {
480 /*
481 * Remove brackets from numeric IPv6 address...
482 */
483
484 if (!strncmp(hostname, "[v1.", 4))
485 {
486 /*
487 * Copy the newer address format which supports link-local addresses...
488 */
489
490 strlcpy(ipv6, hostname + 4, sizeof(ipv6));
491 if ((ipv6len = (int)strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']')
492 {
493 ipv6[ipv6len] = '\0';
494 hostname = ipv6;
495
496 /*
497 * Convert "+zone" in address to "%zone"...
498 */
499
500 if ((ipv6zone = strrchr(ipv6, '+')) != NULL)
501 *ipv6zone = '%';
502 }
503 }
504 else
505 {
506 /*
507 * Copy the regular non-link-local IPv6 address...
508 */
509
510 strlcpy(ipv6, hostname + 1, sizeof(ipv6));
511 if ((ipv6len = (int)strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']')
512 {
513 ipv6[ipv6len] = '\0';
514 hostname = ipv6;
515 }
516 }
517 }
518
519 if ((error = getaddrinfo(hostname, service, &hints, &results)) == 0)
520 {
521 /*
522 * Copy the results to our own address list structure...
523 */
524
525 for (current = results; current; current = current->ai_next)
526 if (current->ai_family == AF_INET || current->ai_family == AF_INET6)
527 {
528 /*
529 * Copy the address over...
530 */
531
532 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
533 if (!temp)
534 {
535 httpAddrFreeList(first);
536 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
537 return (NULL);
538 }
539
540 if (current->ai_family == AF_INET6)
541 memcpy(&(temp->addr.ipv6), current->ai_addr,
542 sizeof(temp->addr.ipv6));
543 else
544 memcpy(&(temp->addr.ipv4), current->ai_addr,
545 sizeof(temp->addr.ipv4));
546
547 /*
548 * Append the address to the list...
549 */
550
551 if (!first)
552 first = temp;
553
554 if (addr)
555 addr->next = temp;
556
557 addr = temp;
558 }
559
560 /*
561 * Free the results from getaddrinfo()...
562 */
563
564 freeaddrinfo(results);
565 }
566 else
567 {
568 if (error == EAI_FAIL)
569 cg->need_res_init = 1;
570
571 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, gai_strerror(error), 0);
572 }
573
574 #else
575 if (hostname)
576 {
577 int i; /* Looping vars */
578 unsigned ip[4]; /* IPv4 address components */
579 const char *ptr; /* Pointer into hostname */
580 struct hostent *host; /* Result of lookup */
581 struct servent *port; /* Port number for service */
582 int portnum; /* Port number */
583
584
585 /*
586 * Lookup the service...
587 */
588
589 if (!service)
590 portnum = 0;
591 else if (isdigit(*service & 255))
592 portnum = atoi(service);
593 else if ((port = getservbyname(service, NULL)) != NULL)
594 portnum = ntohs(port->s_port);
595 else if (!strcmp(service, "http"))
596 portnum = 80;
597 else if (!strcmp(service, "https"))
598 portnum = 443;
599 else if (!strcmp(service, "ipp") || !strcmp(service, "ipps"))
600 portnum = 631;
601 else if (!strcmp(service, "lpd"))
602 portnum = 515;
603 else if (!strcmp(service, "socket"))
604 portnum = 9100;
605 else
606 return (NULL);
607
608 /*
609 * This code is needed because some operating systems have a
610 * buggy implementation of gethostbyname() that does not support
611 * IPv4 addresses. If the hostname string is an IPv4 address, then
612 * sscanf() is used to extract the IPv4 components. We then pack
613 * the components into an IPv4 address manually, since the
614 * inet_aton() function is deprecated. We use the htonl() macro
615 * to get the right byte order for the address.
616 */
617
618 for (ptr = hostname; isdigit(*ptr & 255) || *ptr == '.'; ptr ++);
619
620 if (!*ptr)
621 {
622 /*
623 * We have an IPv4 address; break it up and create an IPv4 address...
624 */
625
626 if (sscanf(hostname, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) == 4 &&
627 ip[0] <= 255 && ip[1] <= 255 && ip[2] <= 255 && ip[3] <= 255)
628 {
629 first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
630 if (!first)
631 return (NULL);
632
633 first->addr.ipv4.sin_family = AF_INET;
634 first->addr.ipv4.sin_addr.s_addr = htonl((((((((unsigned)ip[0] << 8) |
635 (unsigned)ip[1]) << 8) |
636 (unsigned)ip[2]) << 8) |
637 (unsigned)ip[3]));
638 first->addr.ipv4.sin_port = htons(portnum);
639 }
640 }
641 else if ((host = gethostbyname(hostname)) != NULL &&
642 # ifdef AF_INET6
643 (host->h_addrtype == AF_INET || host->h_addrtype == AF_INET6))
644 # else
645 host->h_addrtype == AF_INET)
646 # endif /* AF_INET6 */
647 {
648 for (i = 0; host->h_addr_list[i]; i ++)
649 {
650 /*
651 * Copy the address over...
652 */
653
654 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
655 if (!temp)
656 {
657 httpAddrFreeList(first);
658 return (NULL);
659 }
660
661 # ifdef AF_INET6
662 if (host->h_addrtype == AF_INET6)
663 {
664 temp->addr.ipv6.sin6_family = AF_INET6;
665 memcpy(&(temp->addr.ipv6.sin6_addr), host->h_addr_list[i],
666 sizeof(temp->addr.ipv6));
667 temp->addr.ipv6.sin6_port = htons(portnum);
668 }
669 else
670 # endif /* AF_INET6 */
671 {
672 temp->addr.ipv4.sin_family = AF_INET;
673 memcpy(&(temp->addr.ipv4.sin_addr), host->h_addr_list[i],
674 sizeof(temp->addr.ipv4));
675 temp->addr.ipv4.sin_port = htons(portnum);
676 }
677
678 /*
679 * Append the address to the list...
680 */
681
682 if (!first)
683 first = temp;
684
685 if (addr)
686 addr->next = temp;
687
688 addr = temp;
689 }
690 }
691 else
692 {
693 if (h_errno == NO_RECOVERY)
694 cg->need_res_init = 1;
695
696 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, hstrerror(h_errno), 0);
697 }
698 }
699 #endif /* HAVE_GETADDRINFO */
700 }
701
702 /*
703 * Detect some common errors and handle them sanely...
704 */
705
706 if (!addr && (!hostname || !_cups_strcasecmp(hostname, "localhost")))
707 {
708 struct servent *port; /* Port number for service */
709 int portnum; /* Port number */
710
711
712 /*
713 * Lookup the service...
714 */
715
716 if (!service)
717 portnum = 0;
718 else if (isdigit(*service & 255))
719 portnum = atoi(service);
720 else if ((port = getservbyname(service, NULL)) != NULL)
721 portnum = ntohs(port->s_port);
722 else if (!strcmp(service, "http"))
723 portnum = 80;
724 else if (!strcmp(service, "https"))
725 portnum = 443;
726 else if (!strcmp(service, "ipp") || !strcmp(service, "ipps"))
727 portnum = 631;
728 else if (!strcmp(service, "lpd"))
729 portnum = 515;
730 else if (!strcmp(service, "socket"))
731 portnum = 9100;
732 else
733 {
734 httpAddrFreeList(first);
735
736 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown service name."), 1);
737 return (NULL);
738 }
739
740 if (hostname && !_cups_strcasecmp(hostname, "localhost"))
741 {
742 /*
743 * Unfortunately, some users ignore all of the warnings in the
744 * /etc/hosts file and delete "localhost" from it. If we get here
745 * then we were unable to resolve the name, so use the IPv6 and/or
746 * IPv4 loopback interface addresses...
747 */
748
749 #ifdef AF_INET6
750 if (family != AF_INET)
751 {
752 /*
753 * Add [::1] to the address list...
754 */
755
756 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
757 if (!temp)
758 {
759 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
760 httpAddrFreeList(first);
761 return (NULL);
762 }
763
764 temp->addr.ipv6.sin6_family = AF_INET6;
765 temp->addr.ipv6.sin6_port = htons(portnum);
766 # ifdef WIN32
767 temp->addr.ipv6.sin6_addr.u.Byte[15] = 1;
768 # else
769 temp->addr.ipv6.sin6_addr.s6_addr32[3] = htonl(1);
770 # endif /* WIN32 */
771
772 if (!first)
773 first = temp;
774
775 addr = temp;
776 }
777
778 if (family != AF_INET6)
779 #endif /* AF_INET6 */
780 {
781 /*
782 * Add 127.0.0.1 to the address list...
783 */
784
785 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
786 if (!temp)
787 {
788 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
789 httpAddrFreeList(first);
790 return (NULL);
791 }
792
793 temp->addr.ipv4.sin_family = AF_INET;
794 temp->addr.ipv4.sin_port = htons(portnum);
795 temp->addr.ipv4.sin_addr.s_addr = htonl(0x7f000001);
796
797 if (!first)
798 first = temp;
799
800 if (addr)
801 addr->next = temp;
802 }
803 }
804 else if (!hostname)
805 {
806 /*
807 * Provide one or more passive listening addresses...
808 */
809
810 #ifdef AF_INET6
811 if (family != AF_INET)
812 {
813 /*
814 * Add [::] to the address list...
815 */
816
817 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
818 if (!temp)
819 {
820 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
821 httpAddrFreeList(first);
822 return (NULL);
823 }
824
825 temp->addr.ipv6.sin6_family = AF_INET6;
826 temp->addr.ipv6.sin6_port = htons(portnum);
827
828 if (!first)
829 first = temp;
830
831 addr = temp;
832 }
833
834 if (family != AF_INET6)
835 #endif /* AF_INET6 */
836 {
837 /*
838 * Add 0.0.0.0 to the address list...
839 */
840
841 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
842 if (!temp)
843 {
844 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
845 httpAddrFreeList(first);
846 return (NULL);
847 }
848
849 temp->addr.ipv4.sin_family = AF_INET;
850 temp->addr.ipv4.sin_port = htons(portnum);
851
852 if (!first)
853 first = temp;
854
855 if (addr)
856 addr->next = temp;
857 }
858 }
859 }
860
861 /*
862 * Return the address list...
863 */
864
865 return (first);
866 }
867
868
869 /*
870 * End of "$Id$".
871 */