From 77fe670bf171fdedd05232f7cfabefd7b2c6d743 Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Wed, 22 May 2024 15:30:42 -0400 Subject: [PATCH] Merge Coverity fixes. --- cups/debug.c | 32 +- cups/dest.c | 6 +- cups/dnssd.c | 752 +++++++++++++++++++++++---------------------- cups/string.c | 18 +- cups/tls-gnutls.c | 7 +- cups/tls-openssl.c | 14 +- 6 files changed, 416 insertions(+), 413 deletions(-) diff --git a/cups/debug.c b/cups/debug.c index 3143780cd3..8151cc8966 100644 --- a/cups/debug.c +++ b/cups/debug.c @@ -82,6 +82,7 @@ void _cups_debug_printf(const char *format, /* I - Printf-style format string */ ...) /* I - Additional arguments as needed */ { + int result = 0; /* Filter result */ va_list ap; /* Pointer to arguments */ struct timeval curtime; /* Current time */ char buffer[2048]; /* Output buffer */ @@ -94,8 +95,7 @@ _cups_debug_printf(const char *format, /* I - Printf-style format string */ */ if (!debug_init) - _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"), - getenv("CUPS_DEBUG_FILTER"), 0); + _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"), getenv("CUPS_DEBUG_FILTER"), 0); if (_cups_debug_fd < 0) return; @@ -112,17 +112,13 @@ _cups_debug_printf(const char *format, /* I - Printf-style format string */ if (level > _cups_debug_level) return; + cupsMutexLock(&debug_init_mutex); if (debug_filter) - { - int result; /* Filter result */ - - cupsMutexLock(&debug_init_mutex); result = regexec(debug_filter, format, 0, NULL, 0); - cupsMutexUnlock(&debug_init_mutex); + cupsMutexUnlock(&debug_init_mutex); - if (result) - return; - } + if (result) + return; /* * Format the message... @@ -166,6 +162,7 @@ _cups_debug_printf(const char *format, /* I - Printf-style format string */ void _cups_debug_puts(const char *s) /* I - String to output */ { + int result = 0; /* Filter result */ struct timeval curtime; /* Current time */ char buffer[2048]; /* Output buffer */ ssize_t bytes; /* Number of bytes in buffer */ @@ -177,8 +174,7 @@ _cups_debug_puts(const char *s) /* I - String to output */ */ if (!debug_init) - _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"), - getenv("CUPS_DEBUG_FILTER"), 0); + _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"), getenv("CUPS_DEBUG_FILTER"), 0); if (_cups_debug_fd < 0) return; @@ -195,17 +191,13 @@ _cups_debug_puts(const char *s) /* I - String to output */ if (level > _cups_debug_level) return; + cupsMutexLock(&debug_init_mutex); if (debug_filter) - { - int result; /* Filter result */ - - cupsMutexLock(&debug_init_mutex); result = regexec(debug_filter, s, 0, NULL, 0); - cupsMutexUnlock(&debug_init_mutex); + cupsMutexUnlock(&debug_init_mutex); - if (result) - return; - } + if (result) + return; /* * Format the message... diff --git a/cups/dest.c b/cups/dest.c index 021caf7a5a..8e0713f4ed 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -2697,7 +2697,11 @@ cups_dest_query_cb( dkey.dest.name = name; - if ((device = cupsArrayFind(data->devices, &dkey)) != NULL && device->state == _CUPS_DNSSD_NEW) + cupsRWLockRead(&data->rwlock); + device = cupsArrayFind(data->devices, &dkey); + cupsRWUnlock(&data->rwlock); + + if (device && device->state == _CUPS_DNSSD_NEW) { // Found it, pull out the make and model from the TXT record and save it... const uint8_t *txt, // Pointer into data diff --git a/cups/dnssd.c b/cups/dnssd.c index ae042619d7..f124c32afd 100644 --- a/cups/dnssd.c +++ b/cups/dnssd.c @@ -8,7 +8,6 @@ // #include "cups-private.h" -#include "debug-internal.h" #include "dnssd.h" #ifdef __APPLE__ @@ -209,6 +208,182 @@ cupsDNSSDAssembleFullName( } +// +// 'cupsDNSSDBrowseDelete()' - Cancel and delete a browse request. +// + +void +cupsDNSSDBrowseDelete( + cups_dnssd_browse_t *browse) // I - Browse request +{ + if (browse) + { + cups_dnssd_t *dnssd = browse->dnssd; + + DEBUG_puts("2cupsDNSSDBrowseDelete: Write locking rwlock."); + cupsRWLockWrite(&dnssd->rwlock); + + cupsArrayRemove(dnssd->browses, browse); + + DEBUG_puts("2cupsDNSSDBrowseDelete: Unlocking rwlock."); + cupsRWUnlock(&dnssd->rwlock); + } +} + + +// +// 'cupsDNSSDBrowseGetContext()' - Get the DNS-SD context for the browse request. +// + +cups_dnssd_t * // O - Context or `NULL` +cupsDNSSDBrowseGetContext( + cups_dnssd_browse_t *browse) // I - Browse request +{ + return (browse ? browse->dnssd : NULL); +} + + +// +// 'cupsDNSSDBrowseNew()' - Create a new DNS-SD browse request. +// +// This function creates a new DNS-SD browse request for the specified service +// types and optional domain and interface index. The "types" argument can be a +// single service type ("_ipp._tcp") or a service type and comma-delimited list +// of sub-types ("_ipp._tcp,_print,_universal"). +// +// Newly discovered services are reported using the required browse callback +// function, with the "flags" argument set to `CUPS_DNSSD_FLAGS_ADD` for newly +// discovered services, `CUPS_DNSSD_FLAGS_NONE` for removed services, or +// `CUPS_DNSSD_FLAGS_ERROR` on an error: +// +// ``` +// void +// browse_cb( +// cups_dnssd_browse_t *browse, +// void *cb_data, +// cups_dnssd_flags_t flags, +// uint32_t if_index, +// const char *name, +// const char *regtype, +// const char *domain) +// { +// // Process added/removed service +// } +// ``` +// + +cups_dnssd_browse_t * // O - Browse request or `NULL` on error +cupsDNSSDBrowseNew( + cups_dnssd_t *dnssd, // I - DNS-SD context + uint32_t if_index, // I - Interface index, `CUPS_DNSSD_IF_INDEX_ANY`, or `CUPS_DNSSD_IF_INDEX_LOCAL` + const char *types, // I - Service types + const char *domain, // I - Domain name or `NULL` for default + cups_dnssd_browse_cb_t browse_cb, // I - Browse callback function + void *cb_data) // I - Browse callback data +{ + cups_dnssd_browse_t *browse; // Browse request + + + // Range check input... + if (!dnssd || !types || !browse_cb) + return (NULL); + + // Allocate memory for the browser... + if ((browse = (cups_dnssd_browse_t *)calloc(1, sizeof(cups_dnssd_browse_t))) == NULL) + return (NULL); + + browse->dnssd = dnssd; + browse->cb = browse_cb; + browse->cb_data = cb_data; + + DEBUG_puts("2cupsDNSSDBrowseNew: Write locking rwlock."); + cupsRWLockWrite(&dnssd->rwlock); + + if (!dnssd->browses) + { + // Create an array of browsers... + if ((dnssd->browses = cupsArrayNew3(NULL, NULL, NULL, 0, NULL, (cups_afree_cb_t)delete_browse)) == NULL) + { + // Unable to create... + free(browse); + browse = NULL; + goto done; + } + } + +#ifdef HAVE_MDNSRESPONDER + DNSServiceErrorType error; // Error, if any + + browse->ref = dnssd->ref; + if ((error = DNSServiceBrowse(&browse->ref, kDNSServiceFlagsShareConnection, if_index, types, domain, (DNSServiceBrowseReply)mdns_browse_cb, browse)) != kDNSServiceErr_NoError) + { + report_error(dnssd, "Unable to create DNS-SD browse request: %s", mdns_strerror(error)); + free(browse); + browse = NULL; + goto done; + } + +#elif _WIN32 + +#else // HAVE_AVAHI + if (!dnssd->in_callback) + { + DEBUG_puts("2cupsDNSSDBrowseNew: Locking mutex."); + cupsMutexLock(&dnssd->mutex); + } + + browse->num_browsers = 1; + browse->browsers[0] = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, types, /*domain*/NULL, /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse); + + if (!browse->browsers[0]) + { + report_error(dnssd, "Unable to create DNS-SD browse request: %s", avahi_strerror(avahi_client_errno(dnssd->client))); + free(browse); + browse = NULL; + + if (!dnssd->in_callback) + { + DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex."); + cupsMutexUnlock(&dnssd->mutex); + } + + goto done; + } + + if (!domain && dnssd->num_domains > 0) + { + // Add browsers for all domains... + size_t i; // Looping var + + for (i = 0; i < dnssd->num_domains; i ++) + { + if ((browse->browsers[browse->num_browsers] = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, types, dnssd->domains[i], /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse)) != NULL) + browse->num_browsers ++; + } + } + + if (!dnssd->in_callback) + { + DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex."); + cupsMutexUnlock(&dnssd->mutex); + + avahi_simple_poll_wakeup(dnssd->poll); + } +#endif // HAVE_MDNSRESPONDER + + DEBUG_printf("2cupsDNSSDBrowseNew: Adding browse=%p", (void *)browse); + cupsArrayAdd(dnssd->browses, browse); + + done: + + DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking rwlock."); + cupsRWUnlock(&dnssd->rwlock); + + return (browse); +} + + + // // 'cupsDNSSDCopyComputerName()' - Copy the current human-readable name for the system. // @@ -377,127 +552,6 @@ cupsDNSSDDecodeTXT( } -// -// 'cupsDNSSDSeparateFullName()' - Separate a full service name into an instance -// name, registration type, and domain. -// -// This function separates a full service name such as -// "Example\032Name._ipp._tcp.local.") into its instance name ("Example Name"), -// registration type ("_ipp._tcp"), and domain ("local."). -// - -bool // O - `true` on success, `false` on error -cupsDNSSDSeparateFullName( - const char *fullname, // I - Full service name - char *name, // I - Instance name buffer - size_t namesize, // I - Size of instance name buffer - char *type, // I - Registration type buffer - size_t typesize, // I - Size of registration type buffer - char *domain, // I - Domain name buffer - size_t domainsize) // I - Size of domain name buffer -{ - // Range check input.. - if (!fullname || !name || !namesize || !type || !typesize || !domain || !domainsize) - { - if (name) - *name = '\0'; - if (type) - *type = '\0'; - if (domain) - *domain = '\0'; - - return (false); - } - -#if _WIN32 || defined(HAVE_MDNSRESPONDER) - bool ret = true; // Return value - char *ptr, // Pointer into name/type/domain - *end; // Pointer to end of name/type/domain - - // Get the service name... - for (ptr = name, end = name + namesize - 1; *fullname; fullname ++) - { - if (*fullname == '.') - { - // Service type separator... - break; - } - else if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255)) - { - // Escaped character - if (ptr < end) - *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0'; - else - ret = false; - - fullname += 3; - } - else if (ptr < end) - *ptr++ = *fullname; - else - ret = false; - } - *ptr = '\0'; - - if (*fullname) - fullname ++; - - // Get the type... - for (ptr = type, end = type + typesize - 1; *fullname; fullname ++) - { - if (*fullname == '.' && fullname[1] != '_') - { - // Service type separator... - break; - } - else if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255)) - { - // Escaped character - if (ptr < end) - *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0'; - else - ret = false; - - fullname += 3; - } - else if (ptr < end) - *ptr++ = *fullname; - else - ret = false; - } - *ptr = '\0'; - - if (*fullname) - fullname ++; - - // Get the domain... - for (ptr = domain, end = domain + domainsize - 1; *fullname; fullname ++) - { - if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255)) - { - // Escaped character - if (ptr < end) - *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0'; - else - ret = false; - - fullname += 3; - } - else if (ptr < end) - *ptr++ = *fullname; - else - ret = false; - } - *ptr = '\0'; - - return (ret); - -#else // HAVE_AVAHI - return (!avahi_service_name_split(fullname, name, namesize, type, typesize, domain, domainsize)); -#endif // _WIN32 || HAVE_MDNSRESPONDER -} - - // // 'cupsDNSSDDelete()' - Delete a DNS-SD context and all its requests. // @@ -556,7 +610,17 @@ size_t // O - Number of host name changes cupsDNSSDGetConfigChanges( cups_dnssd_t *dnssd) // I - DNS-SD context { - return (dnssd ? dnssd->config_changes : 0); + size_t config_changes = 0; + + + if (dnssd) + { + cupsRWLockRead(&dnssd->rwlock); + config_changes = dnssd->config_changes; + cupsRWUnlock(&dnssd->rwlock); + } + + return (config_changes); } @@ -584,277 +648,101 @@ cupsDNSSDNew( { DEBUG_puts("2cupsDNSSDNew: Unable to allocate memory, returning NULL."); return (NULL); - } - - // Save the error callback... - dnssd->cb = error_cb; - dnssd->cb_data = cb_data; - - // Initialize the rwlock... - cupsRWInit(&dnssd->rwlock); - - // Setup the DNS-SD connection and monitor thread... -#ifdef HAVE_MDNSRESPONDER - DNSServiceErrorType error; // Error code - - if ((error = DNSServiceCreateConnection(&dnssd->ref)) != kDNSServiceErr_NoError) - { - // Unable to create connection... - report_error(dnssd, "Unable to initialize DNS-SD: %s", mdns_strerror(error)); - cupsDNSSDDelete(dnssd); - DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL."); - return (NULL); - } - - // Monitor for hostname changes... - httpGetHostname(NULL, dnssd->hostname, sizeof(dnssd->hostname)); - dnssd->hostname_ref = dnssd->ref; - if ((error = DNSServiceQueryRecord(&dnssd->hostname_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "1.0.0.127.in-addr.arpa.", kDNSServiceType_PTR, kDNSServiceClass_IN, (DNSServiceQueryRecordReply)mdns_hostname_cb, dnssd)) != kDNSServiceErr_NoError) - { - report_error(dnssd, "Unable to query PTR record for local hostname: %s", mdns_strerror(error)); - dnssd->hostname_ref = NULL; - } - - // Start the background monitoring thread... - if ((dnssd->monitor = cupsThreadCreate((void *(*)(void *))mdns_monitor, dnssd)) == 0) - { - report_error(dnssd, "Unable to create DNS-SD thread: %s", strerror(errno)); - cupsDNSSDDelete(dnssd); - DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL."); - return (NULL); - } - - DEBUG_printf("2cupsDNSSDNew: dnssd->monitor=%p", (void *)dnssd->monitor); - -#elif _WIN32 - -#else // HAVE_AVAHI - int error; // Error code - - // Initialize the mutex used to control access to the socket - cupsMutexInit(&dnssd->mutex); - - // Create a polled interface for Avahi requests... - if ((dnssd->poll = avahi_simple_poll_new()) == NULL) - { - // Unable to create the background thread... - report_error(dnssd, "Unable to initialize DNS-SD: %s", strerror(errno)); - cupsDNSSDDelete(dnssd); - DEBUG_puts("2cupsDNSSDNew: Unable to create simple poll - returning NULL."); - return (NULL); - } - - avahi_simple_poll_set_func(dnssd->poll, (AvahiPollFunc)avahi_poll_cb, dnssd); - - DEBUG_printf("2cupsDNSSDNew: dnssd->poll=%p", (void *)dnssd->poll); - - if ((dnssd->client = avahi_client_new(avahi_simple_poll_get(dnssd->poll), AVAHI_CLIENT_NO_FAIL, (AvahiClientCallback)avahi_client_cb, dnssd, &error)) == NULL) - { - // Unable to create the client... - report_error(dnssd, "Unable to initialize DNS-SD: %s", avahi_strerror(error)); - avahi_simple_poll_free(dnssd->poll); - cupsDNSSDDelete(dnssd); - DEBUG_puts("2cupsDNSSDNew: Unable to create Avahi client - returning NULL."); - return (NULL); - } - - DEBUG_printf("2cupsDNSSDNew: dnssd->client=%p", (void *)dnssd->client); - - if ((dnssd->monitor = cupsThreadCreate((void *(*)(void *))avahi_monitor, dnssd)) == 0) - { - report_error(dnssd, "Unable to create DNS-SD thread: %s", strerror(errno)); - cupsDNSSDDelete(dnssd); - DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL."); - return (NULL); - } - - DEBUG_printf("2cupsDNSSDNew: dnssd->monitor=%p", (void *)dnssd->monitor); - - dnssd->dbrowser = avahi_domain_browser_new(dnssd->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, /*domain*/NULL, AVAHI_DOMAIN_BROWSER_BROWSE, /*flags*/0, (AvahiDomainBrowserCallback)avahi_domain_cb, dnssd); -#endif // HAVE_MDNSRESPONDER - - DEBUG_printf("2cupsDNSSDNew: Returning %p.", (void *)dnssd); - - return (dnssd); -} - - -// -// 'cupsDNSSDBrowseDelete()' - Cancel and delete a browse request. -// - -void -cupsDNSSDBrowseDelete( - cups_dnssd_browse_t *browse) // I - Browse request -{ - if (browse) - { - cups_dnssd_t *dnssd = browse->dnssd; - - DEBUG_puts("2cupsDNSSDBrowseDelete: Write locking rwlock."); - cupsRWLockWrite(&dnssd->rwlock); - - cupsArrayRemove(dnssd->browses, browse); - - DEBUG_puts("2cupsDNSSDBrowseDelete: Unlocking rwlock."); - cupsRWUnlock(&dnssd->rwlock); - } -} - - -// -// 'cupsDNSSDBrowseGetContext()' - Get the DNS-SD context for the browse request. -// - -cups_dnssd_t * // O - Context or `NULL` -cupsDNSSDBrowseGetContext( - cups_dnssd_browse_t *browse) // I - Browse request -{ - return (browse ? browse->dnssd : NULL); -} - - -// -// 'cupsDNSSDBrowseNew()' - Create a new DNS-SD browse request. -// -// This function creates a new DNS-SD browse request for the specified service -// types and optional domain and interface index. The "types" argument can be a -// single service type ("_ipp._tcp") or a service type and comma-delimited list -// of sub-types ("_ipp._tcp,_print,_universal"). -// -// Newly discovered services are reported using the required browse callback -// function, with the "flags" argument set to `CUPS_DNSSD_FLAGS_ADD` for newly -// discovered services, `CUPS_DNSSD_FLAGS_NONE` for removed services, or -// `CUPS_DNSSD_FLAGS_ERROR` on an error: -// -// ``` -// void -// browse_cb( -// cups_dnssd_browse_t *browse, -// void *cb_data, -// cups_dnssd_flags_t flags, -// uint32_t if_index, -// const char *name, -// const char *regtype, -// const char *domain) -// { -// // Process added/removed service -// } -// ``` -// - -cups_dnssd_browse_t * // O - Browse request or `NULL` on error -cupsDNSSDBrowseNew( - cups_dnssd_t *dnssd, // I - DNS-SD context - uint32_t if_index, // I - Interface index, `CUPS_DNSSD_IF_INDEX_ANY`, or `CUPS_DNSSD_IF_INDEX_LOCAL` - const char *types, // I - Service types - const char *domain, // I - Domain name or `NULL` for default - cups_dnssd_browse_cb_t browse_cb, // I - Browse callback function - void *cb_data) // I - Browse callback data -{ - cups_dnssd_browse_t *browse; // Browse request - - - // Range check input... - if (!dnssd || !types || !browse_cb) - return (NULL); - - // Allocate memory for the browser... - if ((browse = (cups_dnssd_browse_t *)calloc(1, sizeof(cups_dnssd_browse_t))) == NULL) - return (NULL); + } - browse->dnssd = dnssd; - browse->cb = browse_cb; - browse->cb_data = cb_data; + // Save the error callback... + dnssd->cb = error_cb; + dnssd->cb_data = cb_data; - DEBUG_puts("2cupsDNSSDBrowseNew: Write locking rwlock."); - cupsRWLockWrite(&dnssd->rwlock); + // Initialize the rwlock... + cupsRWInit(&dnssd->rwlock); - if (!dnssd->browses) + // Setup the DNS-SD connection and monitor thread... +#ifdef HAVE_MDNSRESPONDER + DNSServiceErrorType error; // Error code + + if ((error = DNSServiceCreateConnection(&dnssd->ref)) != kDNSServiceErr_NoError) { - // Create an array of browsers... - if ((dnssd->browses = cupsArrayNew3(NULL, NULL, NULL, 0, NULL, (cups_afree_cb_t)delete_browse)) == NULL) - { - // Unable to create... - free(browse); - browse = NULL; - goto done; - } + // Unable to create connection... + report_error(dnssd, "Unable to initialize DNS-SD: %s", mdns_strerror(error)); + cupsDNSSDDelete(dnssd); + DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL."); + return (NULL); } -#ifdef HAVE_MDNSRESPONDER - DNSServiceErrorType error; // Error, if any + // Monitor for hostname changes... + httpGetHostname(NULL, dnssd->hostname, sizeof(dnssd->hostname)); + dnssd->hostname_ref = dnssd->ref; + if ((error = DNSServiceQueryRecord(&dnssd->hostname_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "1.0.0.127.in-addr.arpa.", kDNSServiceType_PTR, kDNSServiceClass_IN, (DNSServiceQueryRecordReply)mdns_hostname_cb, dnssd)) != kDNSServiceErr_NoError) + { + report_error(dnssd, "Unable to query PTR record for local hostname: %s", mdns_strerror(error)); + dnssd->hostname_ref = NULL; + } - browse->ref = dnssd->ref; - if ((error = DNSServiceBrowse(&browse->ref, kDNSServiceFlagsShareConnection, if_index, types, domain, (DNSServiceBrowseReply)mdns_browse_cb, browse)) != kDNSServiceErr_NoError) + // Start the background monitoring thread... + if ((dnssd->monitor = cupsThreadCreate((void *(*)(void *))mdns_monitor, dnssd)) == 0) { - report_error(dnssd, "Unable to create DNS-SD browse request: %s", mdns_strerror(error)); - free(browse); - browse = NULL; - goto done; + report_error(dnssd, "Unable to create DNS-SD thread: %s", strerror(errno)); + cupsDNSSDDelete(dnssd); + DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL."); + return (NULL); } + DEBUG_printf("2cupsDNSSDNew: dnssd->monitor=%p", (void *)dnssd->monitor); + #elif _WIN32 #else // HAVE_AVAHI - if (!dnssd->in_callback) - { - DEBUG_puts("2cupsDNSSDBrowseNew: Locking mutex."); - cupsMutexLock(&dnssd->mutex); - } + int error; // Error code - browse->num_browsers = 1; - browse->browsers[0] = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, types, /*domain*/NULL, /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse); + // Initialize the mutex used to control access to the socket + cupsMutexInit(&dnssd->mutex); - if (!browse->browsers[0]) + // Create a polled interface for Avahi requests... + if ((dnssd->poll = avahi_simple_poll_new()) == NULL) { - report_error(dnssd, "Unable to create DNS-SD browse request: %s", avahi_strerror(avahi_client_errno(dnssd->client))); - free(browse); - browse = NULL; + // Unable to create the background thread... + report_error(dnssd, "Unable to initialize DNS-SD: %s", strerror(errno)); + cupsDNSSDDelete(dnssd); + DEBUG_puts("2cupsDNSSDNew: Unable to create simple poll - returning NULL."); + return (NULL); + } - if (!dnssd->in_callback) - { - DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex."); - cupsMutexUnlock(&dnssd->mutex); - } + avahi_simple_poll_set_func(dnssd->poll, (AvahiPollFunc)avahi_poll_cb, dnssd); - goto done; - } + DEBUG_printf("2cupsDNSSDNew: dnssd->poll=%p", (void *)dnssd->poll); - if (!domain && dnssd->num_domains > 0) + if ((dnssd->client = avahi_client_new(avahi_simple_poll_get(dnssd->poll), AVAHI_CLIENT_NO_FAIL, (AvahiClientCallback)avahi_client_cb, dnssd, &error)) == NULL) { - // Add browsers for all domains... - size_t i; // Looping var - - for (i = 0; i < dnssd->num_domains; i ++) - { - if ((browse->browsers[browse->num_browsers] = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, types, dnssd->domains[i], /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse)) != NULL) - browse->num_browsers ++; - } + // Unable to create the client... + report_error(dnssd, "Unable to initialize DNS-SD: %s", avahi_strerror(error)); + avahi_simple_poll_free(dnssd->poll); + cupsDNSSDDelete(dnssd); + DEBUG_puts("2cupsDNSSDNew: Unable to create Avahi client - returning NULL."); + return (NULL); } - if (!dnssd->in_callback) - { - DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex."); - cupsMutexUnlock(&dnssd->mutex); + DEBUG_printf("2cupsDNSSDNew: dnssd->client=%p", (void *)dnssd->client); - avahi_simple_poll_wakeup(dnssd->poll); + if ((dnssd->monitor = cupsThreadCreate((void *(*)(void *))avahi_monitor, dnssd)) == 0) + { + report_error(dnssd, "Unable to create DNS-SD thread: %s", strerror(errno)); + cupsDNSSDDelete(dnssd); + DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL."); + return (NULL); } -#endif // HAVE_MDNSRESPONDER - DEBUG_printf("2cupsDNSSDBrowseNew: Adding browse=%p", (void *)browse); - cupsArrayAdd(dnssd->browses, browse); + DEBUG_printf("2cupsDNSSDNew: dnssd->monitor=%p", (void *)dnssd->monitor); - done: + dnssd->dbrowser = avahi_domain_browser_new(dnssd->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, /*domain*/NULL, AVAHI_DOMAIN_BROWSER_BROWSE, /*flags*/0, (AvahiDomainBrowserCallback)avahi_domain_cb, dnssd); +#endif // HAVE_MDNSRESPONDER - DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking rwlock."); - cupsRWUnlock(&dnssd->rwlock); + DEBUG_printf("2cupsDNSSDNew: Returning %p.", (void *)dnssd); - return (browse); + return (dnssd); } - // // 'cupsDNSSDQueryDelete()' - Cancel and delete a query request. // @@ -929,7 +817,7 @@ cupsDNSSDQueryNew( cups_dnssd_query_t *query; // Query request - DEBUG_printf("cupsDNSSDQueryNew(dnssd=%p, if_index=%u, fullname=\"%s\", rrtype=%u, query_cb=%p, cb_data=%p)", (void *)dnssd, if_index, fullname, rrtype, query_cb, cb_data); + DEBUG_printf("cupsDNSSDQueryNew(dnssd=%p, if_index=%u, fullname=\"%s\", rrtype=%u, query_cb=%p, cb_data=%p)", (void *)dnssd, if_index, fullname, rrtype, (void *)query_cb, cb_data); // Range check input... if (!dnssd || !fullname || !query_cb) @@ -1066,7 +954,7 @@ cupsDNSSDResolveGetContext( // const char *fullname, // const char *host, // uint16_t port, -// int num_txt, +// size_t num_txt, // cups_option_t *txt) // { // // Process resolved service @@ -1115,8 +1003,7 @@ cupsDNSSDResolveNew( { report_error(dnssd, "Unable to create DNS-SD query request: %s", mdns_strerror(error)); free(resolve); - resolve = NULL; - goto done; + return (NULL); } #elif _WIN32 @@ -1142,8 +1029,7 @@ cupsDNSSDResolveNew( { report_error(dnssd, "Unable to create DNS-SD resolve request: %s", avahi_strerror(avahi_client_errno(dnssd->client))); free(resolve); - resolve = NULL; - goto done; + return (NULL); } #endif // HAVE_MDNSRESPONDER @@ -1160,6 +1046,7 @@ cupsDNSSDResolveNew( DEBUG_printf("2cupsDNSSDResolveNew: Unable to allocate memory: %s", strerror(errno)); free(resolve); resolve = NULL; + goto done; } } @@ -1167,15 +1054,136 @@ cupsDNSSDResolveNew( DEBUG_printf("2cupsDNSSDResolveNew: Adding resolver %p.", (void *)resolve); cupsArrayAdd(dnssd->resolves, resolve); + done: + DEBUG_puts("2cupsDNSSDResolveNew: Unlocking rwlock."); cupsRWUnlock(&dnssd->rwlock); - done: - return (resolve); } +// +// 'cupsDNSSDSeparateFullName()' - Separate a full service name into an instance +// name, registration type, and domain. +// +// This function separates a full service name such as +// "Example\032Name._ipp._tcp.local.") into its instance name ("Example Name"), +// registration type ("_ipp._tcp"), and domain ("local."). +// + +bool // O - `true` on success, `false` on error +cupsDNSSDSeparateFullName( + const char *fullname, // I - Full service name + char *name, // I - Instance name buffer + size_t namesize, // I - Size of instance name buffer + char *type, // I - Registration type buffer + size_t typesize, // I - Size of registration type buffer + char *domain, // I - Domain name buffer + size_t domainsize) // I - Size of domain name buffer +{ + // Range check input.. + if (!fullname || !name || !namesize || !type || !typesize || !domain || !domainsize) + { + if (name) + *name = '\0'; + if (type) + *type = '\0'; + if (domain) + *domain = '\0'; + + return (false); + } + +#if _WIN32 || defined(HAVE_MDNSRESPONDER) + bool ret = true; // Return value + char *ptr, // Pointer into name/type/domain + *end; // Pointer to end of name/type/domain + + // Get the service name... + for (ptr = name, end = name + namesize - 1; *fullname; fullname ++) + { + if (*fullname == '.') + { + // Service type separator... + break; + } + else if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255)) + { + // Escaped character + if (ptr < end) + *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0'; + else + ret = false; + + fullname += 3; + } + else if (ptr < end) + *ptr++ = *fullname; + else + ret = false; + } + *ptr = '\0'; + + if (*fullname) + fullname ++; + + // Get the type... + for (ptr = type, end = type + typesize - 1; *fullname; fullname ++) + { + if (*fullname == '.' && fullname[1] != '_') + { + // Service type separator... + break; + } + else if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255)) + { + // Escaped character + if (ptr < end) + *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0'; + else + ret = false; + + fullname += 3; + } + else if (ptr < end) + *ptr++ = *fullname; + else + ret = false; + } + *ptr = '\0'; + + if (*fullname) + fullname ++; + + // Get the domain... + for (ptr = domain, end = domain + domainsize - 1; *fullname; fullname ++) + { + if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255)) + { + // Escaped character + if (ptr < end) + *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0'; + else + ret = false; + + fullname += 3; + } + else if (ptr < end) + *ptr++ = *fullname; + else + ret = false; + } + *ptr = '\0'; + + return (ret); + +#else // HAVE_AVAHI + return (!avahi_service_name_split(fullname, name, namesize, type, typesize, domain, domainsize)); +#endif // _WIN32 || HAVE_MDNSRESPONDER +} + + // // 'cupsDNSSDServiceAdd()' - Add a service instance. // @@ -2389,7 +2397,7 @@ avahi_resolve_cb( cups_dnssd_resolve_t *resolve) // I - Resolve request { AvahiStringList *txtpair; // Current pair - int num_txt = 0; // Number of TXT key/value pairs + size_t num_txt = 0; // Number of TXT key/value pairs cups_option_t *txt = NULL; // TXT key/value pairs char fullname[1024]; // Full service name diff --git a/cups/string.c b/cups/string.c index fac91560fe..4d5e09172d 100644 --- a/cups/string.c +++ b/cups/string.c @@ -753,17 +753,6 @@ _cupsStrFree(const char *s) /* I - String to free */ if (!s) return; - /* - * Check the string pool... - * - * We don't need to lock the mutex yet, as we only want to know if - * the stringpool is initialized. The rest of the code will still - * work if it is initialized before we lock... - */ - - if (!stringpool) - return; - /* * See if the string is already in the pool... */ @@ -772,8 +761,7 @@ _cupsStrFree(const char *s) /* I - String to free */ key = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str)); - if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL && - item == key) + if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL && item == key) { /* * Found it, dereference... @@ -823,6 +811,8 @@ _cupsStrRetain(const char *s) /* I - String to retain */ { item = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str)); + cupsMutexLock(&sp_mutex); + #ifdef DEBUG_GUARDS if (item->guard != _CUPS_STR_GUARD) { @@ -831,8 +821,6 @@ _cupsStrRetain(const char *s) /* I - String to retain */ } #endif /* DEBUG_GUARDS */ - cupsMutexLock(&sp_mutex); - item->ref_count ++; cupsMutexUnlock(&sp_mutex); diff --git a/cups/tls-gnutls.c b/cups/tls-gnutls.c index b161bfea49..87d493b1ec 100644 --- a/cups/tls-gnutls.c +++ b/cups/tls-gnutls.c @@ -1473,6 +1473,7 @@ _httpTLSRead(http_t *http, // I - Connection to server bool // O - `true` on success, `false` on failure _httpTLSStart(http_t *http) // I - Connection to server { + const char *keypath; // Certificate store path char hostname[256], // Hostname *hostptr; // Pointer into hostname int status; // Status of handshake @@ -1505,7 +1506,11 @@ _httpTLSStart(http_t *http) // I - Connection to server DEBUG_printf("4_httpTLSStart: tls_options=%x", tls_options); } - if (http->mode == _HTTP_MODE_SERVER && !tls_keypath) + cupsMutexLock(&tls_mutex); + keypath = tls_keypath; + cupsMutexUnlock(&tls_mutex); + + if (http->mode == _HTTP_MODE_SERVER && !keypath) { DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called."); http->error = errno = EINVAL; diff --git a/cups/tls-openssl.c b/cups/tls-openssl.c index 67493a19b6..bf5819dc01 100644 --- a/cups/tls-openssl.c +++ b/cups/tls-openssl.c @@ -1496,6 +1496,7 @@ _httpTLSRead(http_t *http, // I - Connection to server bool // O - `true` on success, `false` on failure _httpTLSStart(http_t *http) // I - Connection to server { + const char *keypath; // Certificate store path BIO *bio; // Basic input/output context SSL_CTX *context; // Encryption context char hostname[256], // Hostname @@ -1526,7 +1527,11 @@ _httpTLSStart(http_t *http) // I - Connection to server DEBUG_printf("4_httpTLSStart: tls_options=%x", tls_options); } - if (http->mode == _HTTP_MODE_SERVER && !tls_keypath) + cupsMutexLock(&tls_mutex); + keypath = tls_keypath; + cupsMutexUnlock(&tls_mutex); + + if (http->mode == _HTTP_MODE_SERVER && !keypath) { DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called."); http->error = errno = EINVAL; @@ -1600,13 +1605,13 @@ _httpTLSStart(http_t *http) // I - Connection to server if (isdigit(hostname[0] & 255) || hostname[0] == '[') hostname[0] = '\0'; // Don't allow numeric addresses + cupsMutexLock(&tls_mutex); + if (hostname[0]) cn = hostname; else cn = tls_common_name; - cupsMutexLock(&tls_mutex); - if (cn) { // First look in the CUPS keystore... @@ -1709,9 +1714,10 @@ _httpTLSStart(http_t *http) // I - Connection to server BIO_meth_set_puts(tls_bio_method, http_bio_puts); BIO_meth_set_write(tls_bio_method, http_bio_write); } - cupsMutexUnlock(&tls_mutex); bio = BIO_new(tls_bio_method); + cupsMutexUnlock(&tls_mutex); + BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http); http->tls = SSL_new(context); -- 2.47.2