From 87e9839293534bf13dc3d1bf4fc285914770cd12 Mon Sep 17 00:00:00 2001 From: msweet Date: Thu, 17 Oct 2013 00:23:06 +0000 Subject: [PATCH] Use httpAddrListen and new httpAddrClose in cupsd and other places that need it. git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@11337 a1ca3aef-8c08-0410-bb20-df032aa958be --- backend/lpd.c | 6 +- cups/file.c | 4 +- cups/http-addr.c | 98 ++++++++++++++++++++++++- cups/http-addrlist.c | 12 +-- cups/http-private.h | 1 - cups/http.c | 36 ++------- cups/http.h | 1 + cups/snmp.c | 63 +++------------- scheduler/listen.c | 170 ++++--------------------------------------- test/ippfind.c | 6 +- 10 files changed, 133 insertions(+), 264 deletions(-) diff --git a/backend/lpd.c b/backend/lpd.c index d73d1bcf0..37fa5a1d2 100644 --- a/backend/lpd.c +++ b/backend/lpd.c @@ -1285,11 +1285,7 @@ rresvport_af(int *port, /* IO - Port number to bind to */ if (errno != EADDRINUSE) { -# ifdef WIN32 - closesocket(fd); -# else - close(fd); -# endif /* WIN32 */ + httpAddrClose(NULL, fd); return (-1); } diff --git a/cups/file.c b/cups/file.c index d5e8f8b29..ef8c77209 100644 --- a/cups/file.c +++ b/cups/file.c @@ -468,7 +468,7 @@ cupsFileClose(cups_file_t *fp) /* I - CUPS file */ if (mode == 's') { - if (closesocket(fd) < 0) + if (httpAddrClose(NULL, fd) < 0) status = -1; } else if (!is_stdio) @@ -1170,7 +1170,7 @@ cupsFileOpen(const char *filename, /* I - Name of file */ if ((fp = cupsFileOpenFd(fd, mode)) == NULL) { if (*mode == 's') - closesocket(fd); + httpAddrClose(NULL, fd); else close(fd); } diff --git a/cups/http-addr.c b/cups/http-addr.c index ad74f083f..e5c3791cf 100644 --- a/cups/http-addr.c +++ b/cups/http-addr.c @@ -18,6 +18,7 @@ */ #include "cups-private.h" +#include #ifdef HAVE_RESOLV_H # include #endif /* HAVE_RESOLV_H */ @@ -53,6 +54,37 @@ httpAddrAny(const http_addr_t *addr) /* I - Address to check */ } +/* + * 'httpAddrClose()' - Close a socket created by @link httpAddrConnect@ or + * @link httpAddrListen@. + * + * Pass @code NULL@ for sockets created with @link httpAddrConnect@ and the + * listen address for sockets created with @link httpAddrListen@. This will + * ensure that domain sockets are removed when closed. + * + * @since CUPS 2.0@ + */ + +int /* O - 0 on success, -1 on failure */ +httpAddrClose(http_addr_t *addr, /* I - Listen address or @code NULL@ */ + int fd) /* I - Socket file descriptor */ +{ +#ifdef WIN32 + if (closesocket(fd)) +#else + if (close(fd)) +#endif /* WIN32 */ + return (-1); + +#ifdef AF_LOCAL + if (addr && addr->addr.sa_family == AF_LOCAL) + return (unlink(addr->un.sun_path)); +#endif /* AF_LOCAL */ + + return (0); +} + + /* * 'httpAddrEqual()' - Compare two addresses. * @@ -129,16 +161,21 @@ httpAddrListen(http_addr_t *addr, /* I - Address to bind to */ int port) /* I - Port number to bind to */ { int fd = -1, /* Socket */ - val; /* Socket value */ + val, /* Socket value */ + status; /* Bind status */ /* * Range check input... */ - if (!addr || port <= 0) + if (!addr || port < 0) return (-1); + /* + * Create the socket and set options... + */ + if ((fd = socket(addr->addr.sa_family, SOCK_STREAM, 0)) < 0) { _cupsSetHTTPError(HTTP_STATUS_ERROR); @@ -153,9 +190,50 @@ httpAddrListen(http_addr_t *addr, /* I - Address to bind to */ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, CUPS_SOCAST &val, sizeof(val)); #endif /* IPV6_V6ONLY */ - _httpAddrSetPort(addr, port); + /* + * Bind the socket... + */ + +#ifdef AF_LOCAL + if (addr->addr.sa_family == AF_LOCAL) + { + mode_t mask; /* Umask setting */ + + /* + * Remove any existing domain socket file... + */ + + unlink(addr->un.sun_path); + + /* + * Save the current umask and set it to 0 so that all users can access + * the domain socket... + */ + + mask = umask(0); + + /* + * Bind the domain socket... + */ + + status = bind(fd, (struct sockaddr *)addr, httpAddrLength(addr)); + + /* + * Restore the umask and fix permissions... + */ - if (bind(fd, (struct sockaddr *)addr, httpAddrLength(addr))) + umask(mask); + chmod(addr->un.sun_path, 0140777); + } + else +#endif /* AF_LOCAL */ + { + _httpAddrSetPort(addr, port); + + status = bind(fd, (struct sockaddr *)addr, httpAddrLength(addr)); + } + + if (status) { _cupsSetHTTPError(HTTP_STATUS_ERROR); @@ -164,6 +242,10 @@ httpAddrListen(http_addr_t *addr, /* I - Address to bind to */ return (-1); } + /* + * Listen... + */ + if (listen(fd, 5)) { _cupsSetHTTPError(HTTP_STATUS_ERROR); @@ -173,6 +255,14 @@ httpAddrListen(http_addr_t *addr, /* I - Address to bind to */ return (-1); } + /* + * Close on exec... + */ + +#ifndef WIN32 + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); +#endif /* !WIN32 */ + #ifdef SO_NOSIGPIPE /* * Disable SIGPIPE for this socket. diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c index 0b7e24359..b6cbc1f3f 100644 --- a/cups/http-addrlist.c +++ b/cups/http-addrlist.c @@ -225,11 +225,7 @@ httpAddrConnect2( DEBUG_puts("1httpAddrConnect2: Canceled connect()"); -# ifdef WIN32 - closesocket(*sock); -# else - close(*sock); -# endif /* WIN32 */ + httpAddrClose(NULL, *sock); *sock = -1; @@ -297,11 +293,7 @@ httpAddrConnect2( * Close this socket and move to the next address... */ -#ifdef WIN32 - closesocket(*sock); -#else - close(*sock); -#endif /* WIN32 */ + httpAddrClose(NULL, *sock); *sock = -1; addrlist = addrlist->next; diff --git a/cups/http-private.h b/cups/http-private.h index 43285b3c5..d768c84af 100644 --- a/cups/http-private.h +++ b/cups/http-private.h @@ -40,7 +40,6 @@ # include # include # include -# define closesocket(f) close(f) # define CUPS_SOCAST # endif /* WIN32 */ diff --git a/cups/http.c b/cups/http.c index 0e1ff5864..3db98fca2 100644 --- a/cups/http.c +++ b/cups/http.c @@ -678,11 +678,7 @@ _httpDisconnect(http_t *http) /* I - HTTP connection */ http_shutdown_ssl(http); #endif /* HAVE_SSL */ -#ifdef WIN32 - closesocket(http->fd); -#else - close(http->fd); -#endif /* WIN32 */ + httpAddrClose(NULL, http->fd); http->fd = -1; } @@ -817,11 +813,7 @@ httpFlush(http_t *http) /* I - HTTP connection */ http_shutdown_ssl(http); #endif /* HAVE_SSL */ -#ifdef WIN32 - closesocket(http->fd); -#else - close(http->fd); -#endif /* WIN32 */ + httpAddrClose(NULL, http->fd); http->fd = -1; } @@ -2727,11 +2719,7 @@ httpReconnect2(http_t *http, /* I - HTTP connection */ { DEBUG_printf(("2httpReconnect2: Closing socket %d...", http->fd)); -#ifdef WIN32 - closesocket(http->fd); -#else - close(http->fd); -#endif /* WIN32 */ + httpAddrClose(NULL, http->fd); http->fd = -1; } @@ -2799,11 +2787,7 @@ httpReconnect2(http_t *http, /* I - HTTP connection */ if (http_setup_ssl(http) != 0) { -# ifdef WIN32 - closesocket(http->fd); -# else - close(http->fd); -# endif /* WIN32 */ + httpAddrClose(NULL, http->fd); return (-1); } @@ -3270,11 +3254,7 @@ _httpUpdate(http_t *http, /* I - HTTP connection */ { if (http_setup_ssl(http) != 0) { -# ifdef WIN32 - closesocket(http->fd); -# else - close(http->fd); -# endif /* WIN32 */ + httpAddrClose(NULL, http->fd); *status = http->status = HTTP_STATUS_ERROR; return (0); @@ -5742,11 +5722,7 @@ http_upgrade(http_t *http) /* I - HTTP connection */ DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!"); -# ifdef WIN32 - closesocket(http->fd); -# else - close(http->fd); -# endif + httpAddrClose(NULL, http->fd); http->fd = -1; diff --git a/cups/http.h b/cups/http.h index 510b9763b..b1fbb37b0 100644 --- a/cups/http.h +++ b/cups/http.h @@ -614,6 +614,7 @@ extern http_state_t httpWriteResponse(http_t *http, /**** New in CUPS 2.0 ****/ +extern int httpAddrClose(http_addr_t *addr, int fd) _CUPS_API_2_0; extern int httpAddrFamily(http_addr_t *addr) _CUPS_API_2_0; extern http_field_t httpFieldValue(const char *name) _CUPS_API_2_0; extern time_t httpGetActivity(http_t *http) _CUPS_API_2_0; diff --git a/cups/snmp.c b/cups/snmp.c index 034db89a9..143563ef4 100644 --- a/cups/snmp.c +++ b/cups/snmp.c @@ -1,57 +1,18 @@ /* * "$Id$" * - * SNMP functions for CUPS. + * SNMP functions for CUPS. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 2006-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2013 by Apple Inc. + * Copyright 2006-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * "LICENSE" which should have been included with this file. If this - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged, see the license at "http://www.cups.org/". * - * This file is subject to the Apple OS-Developed Software exception. - * - * Contents: - * - * _cupsSNMPClose() - Close a SNMP socket. - * _cupsSNMPCopyOID() - Copy an OID. - * _cupsSNMPDefaultCommunity() - Get the default SNMP community name. - * _cupsSNMPIsOID() - Test whether a SNMP response contains the - * specified OID. - * _cupsSNMPIsOIDPrefixed() - Test whether a SNMP response uses the - * specified OID prefix. - * _cupsSNMPOIDToString() - Convert an OID to a string. - * _cupsSNMPOpen() - Open a SNMP socket. - * _cupsSNMPRead() - Read and parse a SNMP response. - * _cupsSNMPSetDebug() - Enable/disable debug logging to stderr. - * _cupsSNMPStringToOID() - Convert a numeric OID string to an OID array. - * _cupsSNMPWalk() - Enumerate a group of OIDs. - * _cupsSNMPWrite() - Send an SNMP query packet. - * asn1_debug() - Decode an ASN1-encoded message. - * asn1_decode_snmp() - Decode a SNMP packet. - * asn1_encode_snmp() - Encode a SNMP packet. - * asn1_get_integer() - Get an integer value. - * asn1_get_length() - Get a value length. - * asn1_get_oid() - Get an OID value. - * asn1_get_packed() - Get a packed integer value. - * asn1_get_string() - Get a string value. - * asn1_get_type() - Get a value type. - * asn1_set_integer() - Set an integer value. - * asn1_set_length() - Set a value length. - * asn1_set_oid() - Set an OID value. - * asn1_set_packed() - Set a packed integer value. - * asn1_size_integer() - Figure out the number of bytes needed for an - * integer value. - * asn1_size_length() - Figure out the number of bytes needed for a - * length value. - * asn1_size_oid() - Figure out the numebr of bytes needed for an - * OID value. - * asn1_size_packed() - Figure out the number of bytes needed for a - * packed integer value. - * snmp_set_error() - Set the localized error for a packet. + * This file is subject to the Apple OS-Developed Software exception. */ /* @@ -116,11 +77,7 @@ _cupsSNMPClose(int fd) /* I - SNMP socket file descriptor */ { DEBUG_printf(("4_cupsSNMPClose(fd=%d)", fd)); -#ifdef WIN32 - closesocket(fd); -#else - close(fd); -#endif /* WIN32 */ + httpAddrClose(NULL, fd); } diff --git a/scheduler/listen.c b/scheduler/listen.c index fe5e9faff..7ef4a3c92 100644 --- a/scheduler/listen.c +++ b/scheduler/listen.c @@ -1,24 +1,16 @@ /* * "$Id$" * - * Server listening routines for the CUPS scheduler. + * Server listening routines for the CUPS scheduler. * - * Copyright 2007-2010 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2013 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdDeleteAllListeners() - Delete all listeners. - * cupsdPauseListening() - Clear input polling on all listening sockets... - * cupsdResumeListening() - Set input polling on all listening sockets... - * cupsdStartListening() - Create all listening sockets... - * cupsdStopListening() - Close all listening sockets... + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -123,9 +115,7 @@ cupsdResumeListening(void) void cupsdStartListening(void) { - int status; /* Bind result */ - int p, /* Port number */ - val; /* Parameter value */ + int p; /* Port number */ cupsd_listener_t *lis; /* Current listening socket */ char s[256]; /* String addresss */ const char *have_domain; /* Have a domain socket? */ @@ -163,7 +153,7 @@ cupsdStartListening(void) * Create a socket for listening... */ - lis->fd = socket(lis->address.addr.sa_family, SOCK_STREAM, 0); + lis->fd = httpAddrListen(&(lis->address), p); if (lis->fd == -1) { @@ -186,132 +176,15 @@ cupsdStartListening(void) continue; } - - /* - * Set things up to reuse the local address for this port. - */ - - val = 1; -#ifdef __sun - setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); -#else - setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); -#endif /* __sun */ - - /* - * Bind to the port we found... - */ - -#ifdef AF_INET6 - if (lis->address.addr.sa_family == AF_INET6) - { -# ifdef IPV6_V6ONLY - /* - * Accept only IPv6 connections on this socket, to avoid - * potential security issues and to make all platforms behave - * the same. - */ - - val = 1; -# ifdef __sun - setsockopt(lis->fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val)); -# else - setsockopt(lis->fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)); -# endif /* __sun */ -# endif /* IPV6_V6ONLY */ - - status = bind(lis->fd, (struct sockaddr *)&(lis->address), - httpAddrLength(&(lis->address))); - } - else -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - if (lis->address.addr.sa_family == AF_LOCAL) - { - mode_t mask; /* Umask setting */ - - - /* - * Remove any existing domain socket file... - */ - - unlink(lis->address.un.sun_path); - - /* - * Save the current umask and set it to 0 so that all users can access - * the domain socket... - */ - - mask = umask(0); - - /* - * Bind the domain socket... - */ - - status = bind(lis->fd, (struct sockaddr *)&(lis->address), - httpAddrLength(&(lis->address))); - - /* - * Restore the umask... - */ - - umask(mask); - } - else -#endif /* AF_LOCAL */ - status = bind(lis->fd, (struct sockaddr *)&(lis->address), - sizeof(lis->address.ipv4)); - - if (status < 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to bind socket for address %s:%d - %s.", - s, p, strerror(errno)); - close(lis->fd); - lis->fd = -1; - - if (FatalErrors & CUPSD_FATAL_LISTEN) - cupsdEndProcess(getpid(), 0); - - continue; - } - - /* - * Listen for new clients. - */ - - if (listen(lis->fd, ListenBackLog) < 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to listen for clients on address %s:%d - %s.", - s, p, strerror(errno)); - - close(lis->fd); - lis->fd = -1; - - if (FatalErrors & CUPSD_FATAL_LISTEN) - cupsdEndProcess(getpid(), 0); - - continue; - } } - fcntl(lis->fd, F_SETFD, fcntl(lis->fd, F_GETFD) | FD_CLOEXEC); - if (p) cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d on fd %d...", s, p, lis->fd); else - { cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s on fd %d...", s, lis->fd); - if (chmod(s, 0140777)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to change permisssions on domain socket " - "\"%s\" - %s", s, strerror(errno)); - } - /* * Save the first port that is bound to the local loopback or * "any" address... @@ -339,7 +212,7 @@ cupsdStartListening(void) { cupsdLogMessage(CUPSD_LOG_EMERG, "No Listen or Port lines were found to allow access via " - "localhost!"); + "localhost."); if (FatalErrors & (CUPSD_FATAL_CONFIG | CUPSD_FATAL_LISTEN)) cupsdEndProcess(getpid(), 0); @@ -403,24 +276,13 @@ cupsdStopListening(void) { if (lis->fd != -1) { -#ifdef WIN32 - closesocket(lis->fd); +#ifdef HAVE_LAUNCH_H + httpAddrClose(NULL, lis->fd); #else - close(lis->fd); -#endif /* WIN32 */ + httpAddrClose(&(lis->address), lis->fd); +#endif /* HAVE_LAUNCH */ -#ifdef AF_LOCAL - /* - * Remove domain sockets... - */ - -# ifdef HAVE_LAUNCH_H - if (lis->address.addr.sa_family == AF_LOCAL && !Launchd) -# else - if (lis->address.addr.sa_family == AF_LOCAL) -# endif /* HAVE_LAUNCH_H */ - unlink(lis->address.un.sun_path); -#endif /* AF_LOCAL */ + lis->fd = -1; } } } diff --git a/test/ippfind.c b/test/ippfind.c index 8a7c2015c..2331222bf 100644 --- a/test/ippfind.c +++ b/test/ippfind.c @@ -2385,11 +2385,7 @@ list_service(ippfind_srv_t *service) /* I - Service */ _cupsLangPrintf(stdout, "%s available", service->uri); httpAddrFreeList(addrlist); -#ifdef WIN32 - closesocket(sock); -#else - close(sock); -#endif /* WIN32 */ + httpAddrClose(NULL, sock); } else { -- 2.39.2