diff --git a/activity_monitor.c b/activity_monitor.c index 4377c89e..51eeb0a2 100644 --- a/activity_monitor.c +++ b/activity_monitor.c @@ -265,9 +265,9 @@ void activity_monitor_start() { void activity_monitor_stop() { if (activity_monitor_running) { - debug(1, "activity_monitor_stop start..."); + debug(3, "activity_monitor_stop start..."); pthread_cancel(activity_monitor_thread); pthread_join(activity_monitor_thread, NULL); - debug(1, "activity_monitor_stop complete"); + debug(2, "activity_monitor_stop complete"); } } diff --git a/audio_alsa.c b/audio_alsa.c index a683f060..4e2fefda 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -1059,9 +1059,9 @@ static void deinit(void) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable // debug(2,"audio_alsa deinit called."); stop(); - debug(1, "Cancel buffer monitor thread."); + debug(2, "Cancel buffer monitor thread."); pthread_cancel(alsa_buffer_monitor_thread); - debug(1, "Join buffer monitor thread."); + debug(3, "Join buffer monitor thread."); pthread_join(alsa_buffer_monitor_thread, NULL); pthread_setcancelstate(oldState, NULL); } diff --git a/common.c b/common.c index 6bd31524..cf5c0730 100644 --- a/common.c +++ b/common.c @@ -91,6 +91,28 @@ void set_alsa_out_dev(char *); static volatile int requested_connection_state_to_output = 1; +// this stuff is to direct logging to syslog via libdaemon or directly +// alternatively you can direct it to stderr using a command line option + +#ifdef CONFIG_LIBDAEMON +static void (*sps_log)(int prio, const char *t, ...) = daemon_log; +#else +static void (*sps_log)(int prio, const char *t, ...) = syslog; +#endif + +void do_sps_log(__attribute__((unused)) int prio, const char *t, ...) { + char s[1024]; + va_list args; + va_start(args, t); + vsnprintf(s, sizeof(s), t, args); + va_end(args); + fprintf(stderr,"%s\n",s); +} + +void log_to_stderr() { + sps_log = do_sps_log; +} + shairport_cfg config; volatile int debuglev = 0; @@ -146,24 +168,13 @@ void die(const char *format, ...) { va_end(args); if ((debuglev) && (config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - - #ifdef CONFIG_LIBDAEMON - daemon_log(LOG_ERR, "|% 20.9f|% 20.9f|*fatal error: %s", tss, tsl, s); + sps_log(LOG_ERR, "|% 20.9f|% 20.9f|*fatal error: %s", tss, tsl, s); else if ((debuglev) && (config.debugger_show_relative_time)) - daemon_log(LOG_ERR, "% 20.9f|*fatal error: %s", tsl, s); + sps_log(LOG_ERR, "% 20.9f|*fatal error: %s", tsl, s); else if ((debuglev) && (config.debugger_show_elapsed_time)) - daemon_log(LOG_ERR, "% 20.9f|*fatal error: %s", tss, s); + sps_log(LOG_ERR, "% 20.9f|*fatal error: %s", tss, s); else - daemon_log(LOG_ERR, "fatal error: %s", s); - #else - syslog(LOG_ERR, "|% 20.9f|% 20.9f|*fatal error: %s", tss, tsl, s); - else if ((debuglev) && (config.debugger_show_relative_time)) - syslog(LOG_ERR, "% 20.9f|*fatal error: %s", tsl, s); - else if ((debuglev) && (config.debugger_show_elapsed_time)) - syslog(LOG_ERR, "% 20.9f|*fatal error: %s", tss, s); - else - syslog(LOG_ERR, "fatal error: %s", s); - #endif + sps_log(LOG_ERR, "fatal error: %s", s); pthread_setcancelstate(oldState, NULL); exit(1); } @@ -184,25 +195,14 @@ void warn(const char *format, ...) { va_start(args, format); vsnprintf(s, sizeof(s), format, args); va_end(args); -#ifdef CONFIG_LIBDAEMON if ((debuglev) && (config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - daemon_log(LOG_WARNING, "|% 20.9f|% 20.9f|*warning: %s", tss, tsl, s); + sps_log(LOG_WARNING, "|% 20.9f|% 20.9f|*warning: %s", tss, tsl, s); else if ((debuglev) && (config.debugger_show_relative_time)) - daemon_log(LOG_WARNING, "% 20.9f|*warning: %s", tsl, s); + sps_log(LOG_WARNING, "% 20.9f|*warning: %s", tsl, s); else if ((debuglev) && (config.debugger_show_elapsed_time)) - daemon_log(LOG_WARNING, "% 20.9f|*warning: %s", tss, s); + sps_log(LOG_WARNING, "% 20.9f|*warning: %s", tss, s); else - daemon_log(LOG_WARNING, "%s", s); -#else - if ((debuglev) && (config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - syslog(LOG_WARNING, "|% 20.9f|% 20.9f|*warning: %s", tss, tsl, s); - else if ((debuglev) && (config.debugger_show_relative_time)) - syslog(LOG_WARNING, "% 20.9f|*warning: %s", tsl, s); - else if ((debuglev) && (config.debugger_show_elapsed_time)) - syslog(LOG_WARNING, "% 20.9f|*warning: %s", tss, s); - else - syslog(LOG_WARNING, "%s", s); -#endif + sps_log(LOG_WARNING, "%s", s); pthread_setcancelstate(oldState, NULL); } @@ -224,25 +224,14 @@ void debug(int level, const char *format, ...) { va_start(args, format); vsnprintf(s, sizeof(s), format, args); va_end(args); -#ifdef CONFIG_LIBDAEMON if ((config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - daemon_log(LOG_DEBUG, "|% 20.9f|% 20.9f|%s", tss, tsl, s); + sps_log(LOG_DEBUG, "|% 20.9f|% 20.9f|%s", tss, tsl, s); else if (config.debugger_show_relative_time) - daemon_log(LOG_DEBUG, "% 20.9f|%s", tsl, s); + sps_log(LOG_DEBUG, "% 20.9f|%s", tsl, s); else if (config.debugger_show_elapsed_time) - daemon_log(LOG_DEBUG, "% 20.9f|%s", tss, s); + sps_log(LOG_DEBUG, "% 20.9f|%s", tss, s); else - daemon_log(LOG_DEBUG, "%s", s); -#else - if ((config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - syslog(LOG_DEBUG, "|% 20.9f|% 20.9f|%s", tss, tsl, s); - else if (config.debugger_show_relative_time) - syslog(LOG_DEBUG, "% 20.9f|%s", tsl, s); - else if (config.debugger_show_elapsed_time) - syslog(LOG_DEBUG, "% 20.9f|%s", tss, s); - else - syslog(LOG_DEBUG, "%s", s); -#endif + sps_log(LOG_DEBUG, "%s", s); pthread_setcancelstate(oldState, NULL); } @@ -262,26 +251,14 @@ void inform(const char *format, ...) { va_start(args, format); vsnprintf(s, sizeof(s), format, args); va_end(args); -#ifdef CONFIG_LIBDAEMON if ((debuglev) && (config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - daemon_log(LOG_INFO, "|% 20.9f|% 20.9f|%s", tss, tsl, s); + sps_log(LOG_INFO, "|% 20.9f|% 20.9f|%s", tss, tsl, s); else if ((debuglev) && (config.debugger_show_relative_time)) - daemon_log(LOG_INFO, "% 20.9f|%s", tsl, s); + sps_log(LOG_INFO, "% 20.9f|%s", tsl, s); else if ((debuglev) && (config.debugger_show_elapsed_time)) - daemon_log(LOG_INFO, "% 20.9f|%s", tss, s); + sps_log(LOG_INFO, "% 20.9f|%s", tss, s); else - daemon_log(LOG_INFO, "%s", s); -#else - if ((debuglev) && (config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - syslog(LOG_INFO, "|% 20.9f|% 20.9f|%s", tss, tsl, s); - else if ((debuglev) && (config.debugger_show_relative_time)) - syslog(LOG_INFO, "% 20.9f|%s", tsl, s); - else if ((debuglev) && (config.debugger_show_elapsed_time)) - syslog(LOG_INFO, "% 20.9f|%s", tss, s); - else - syslog(LOG_INFO, "%s", s); - -#endif + sps_log(LOG_INFO, "%s", s); pthread_setcancelstate(oldState, NULL); } diff --git a/common.h b/common.h index 78c9ddda..9dceabb3 100644 --- a/common.h +++ b/common.h @@ -245,6 +245,8 @@ uint16_t nctohs(const uint8_t *p); // read 2 characters from *p and do ntohs on void memory_barrier(); +void log_to_stderr(); // call this to director logging to stderr; + // true if Shairport Sync is supposed to be sending output to the output device, false otherwise int get_requested_connection_state_to_output(); diff --git a/dacp.c b/dacp.c index 4f40e2d0..f5797554 100644 --- a/dacp.c +++ b/dacp.c @@ -894,11 +894,11 @@ void dacp_monitor_start() { void dacp_monitor_stop() { if (dacp_monitor_initialised) { // only if it's been started and initialised - debug(1, "dacp_monitor_stop"); + debug(2, "dacp_monitor_stop"); pthread_cancel(dacp_monitor_thread); pthread_join(dacp_monitor_thread, NULL); pthread_mutex_destroy(&dacp_server_information_lock); - debug(1, "DACP Conversation Lock Mutex Destroyed"); + debug(3, "DACP Conversation Lock Mutex Destroyed"); pthread_mutex_destroy(&dacp_conversation_lock); } } diff --git a/dbus-service.c b/dbus-service.c index 2ed17d0a..a1cde3fd 100644 --- a/dbus-service.c +++ b/dbus-service.c @@ -885,7 +885,7 @@ int start_dbus_service() { } void stop_dbus_service() { - debug(1, "stopping dbus service"); + debug(2, "stopping dbus service"); if (ownerID) g_bus_unown_name(ownerID); else diff --git a/metadata_hub.c b/metadata_hub.c index f116f272..4d7def38 100644 --- a/metadata_hub.c +++ b/metadata_hub.c @@ -107,7 +107,7 @@ void metadata_hub_init(void) { void metadata_hub_stop(void) { if (metadata_hub_initialised) { - debug(1, "metadata_hub_stop."); + debug(2, "metadata_hub_stop."); metadata_hub_release_track_artwork(); if (metadata_store.track_metadata) { metadata_hub_release_track_metadata(metadata_store.track_metadata); diff --git a/rtsp.c b/rtsp.c index 9aff0e65..4e5062d3 100644 --- a/rtsp.c +++ b/rtsp.c @@ -291,6 +291,7 @@ void *player_watchdog_thread_code(void *arg) { if (time_since_last_bark >= ct) { conn->watchdog_barks++; if (conn->watchdog_barks == 1) { + debuglev = 3; // tell us everything. debug(1, "Connection %d: As Yeats almost said, \"Too long a silence / can make a stone " "of the heart\".", @@ -1410,7 +1411,7 @@ void metadata_process(uint32_t type, uint32_t code, char *data, uint32_t length) } void metadata_thread_cleanup_function(__attribute__((unused)) void *arg) { - debug(1, "metadata_thread_cleanup_function called"); + debug(2, "metadata_thread_cleanup_function called"); metadata_delete_multicast_socket(); metadata_close(); pc_queue_delete(&metadata_queue); @@ -1461,7 +1462,7 @@ void metadata_init(void) { void metadata_stop(void) { if (metadata_running) { - debug(1, "metadata_stop called."); + debug(2, "metadata_stop called."); pthread_cancel(metadata_thread); pthread_join(metadata_thread, NULL); } diff --git a/shairport.c b/shairport.c index 0959e5f2..4cb316e1 100644 --- a/shairport.c +++ b/shairport.c @@ -107,7 +107,7 @@ static void sig_ignore(__attribute__((unused)) int foo, __attribute__((unused)) __attribute__((unused)) void *baz) {} static void sig_shutdown(__attribute__((unused)) int foo, __attribute__((unused)) siginfo_t *bar, __attribute__((unused)) void *baz) { - debug(1, "shutdown requested..."); + debug(2, "shutdown requested..."); #ifdef CONFIG_LIBDAEMON daemon_retval_send(255); daemon_pid_file_remove(); @@ -156,9 +156,9 @@ void usage(char *progname) { #ifdef CONFIG_LIBDAEMON printf(" -d, --daemon daemonise.\n"); printf(" -j, --justDaemoniseNoPIDFile daemonise without a PID file.\n"); + printf(" -k, --kill kill the existing shairport daemon.\n"); #endif printf(" -V, --version show version information.\n"); - printf(" -k, --kill kill the existing shairport daemon.\n"); printf(" -c, --configfile=FILE read configuration settings from FILE. Default is " "/etc/shairport-sync.conf.\n"); @@ -171,7 +171,6 @@ void usage(char *progname) { printf(" -L, --latency=FRAMES [Deprecated] Set the latency for audio sent from an unknown " "device.\n"); printf(" The default is to set it automatically.\n"); - printf(" The default is to set it automatically.\n"); printf(" -S, --stuffing=MODE set how to adjust current latency to match desired latency, " "where \n"); printf(" \"basic\" (default) inserts or deletes audio frames from " @@ -213,6 +212,7 @@ void usage(char *progname) { printf(" The default is /tmp/shairport-sync-metadata.\n"); printf(" --get-coverart send cover art through the metadata pipe.\n"); #endif + printf(" -u, --use-stderr log messages through STDERR rather than syslog.\n"); printf("\n"); mdns_ls_backends(); printf("\n"); @@ -229,15 +229,17 @@ int parse_options(int argc, char **argv) { int fResyncthreshold = (int)(config.resyncthreshold * 44100); int fTolerance = (int)(config.tolerance * 44100); poptContext optCon; /* context for parsing command-line options */ +#if CONFIG_LIBDAEMON int daemonisewith = 0; int daemonisewithout = 0; +#endif struct poptOption optionsTable[] = { {"verbose", 'v', POPT_ARG_NONE, NULL, 'v', NULL, NULL}, - {"disconnectFromOutput", 'D', POPT_ARG_NONE, NULL, 0, NULL, NULL}, - {"reconnectToOutput", 'R', POPT_ARG_NONE, NULL, 0, NULL, NULL}, +#if CONFIG_LIBDAEMON {"kill", 'k', POPT_ARG_NONE, NULL, 0, NULL, NULL}, {"daemon", 'd', POPT_ARG_NONE, &daemonisewith, 0, NULL, NULL}, {"justDaemoniseNoPIDFile", 'j', POPT_ARG_NONE, &daemonisewithout, 0, NULL, NULL}, +#endif {"configfile", 'c', POPT_ARG_STRING, &config.configfile, 0, NULL, NULL}, {"statistics", 0, POPT_ARG_NONE, &config.statistics_requested, 0, NULL, NULL}, {"logOutputLevel", 0, POPT_ARG_NONE, &config.logOutputLevel, 0, NULL, NULL}, @@ -255,6 +257,7 @@ int parse_options(int argc, char **argv) { {"timeout", 't', POPT_ARG_INT, &config.timeout, 't', NULL, NULL}, {"password", 0, POPT_ARG_STRING, &config.password, 0, NULL, NULL}, {"tolerance", 'z', POPT_ARG_INT, &fTolerance, 0, NULL, NULL}, + {"use-stderr", 'u', POPT_ARG_NONE, NULL, 'u', NULL, NULL}, #ifdef CONFIG_METADATA {"metadata-pipename", 'M', POPT_ARG_STRING, &config.metadata_pipename, 'M', NULL, NULL}, {"get-coverart", 'g', POPT_ARG_NONE, &config.get_coverart, 'g', NULL, NULL}, @@ -281,6 +284,9 @@ int parse_options(int argc, char **argv) { case 'v': debuglev++; break; + case 'u': + log_to_stderr(); + break; case 'D': inform("Warning: the option -D or --disconnectFromOutput is deprecated."); break; @@ -1081,7 +1087,7 @@ pthread_t dbus_thread; void *dbus_thread_func(__attribute__((unused)) void *arg) { g_main_loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(g_main_loop); - debug(1, "g_main_loop thread exit"); + debug(2, "g_main_loop thread exit"); pthread_exit(NULL); } #endif @@ -1139,7 +1145,7 @@ const char *pid_file_proc(void) { void main_cleanup_handler(__attribute__((unused)) void *arg) { // it doesn't look like this is called when the main function is cancelled eith a pthread cancel. - debug(1, "main cleanup handler called."); + debug(2, "main cleanup handler called."); #ifdef CONFIG_MQTT if (config.mqtt_enabled) { // terminate_mqtt(); @@ -1154,19 +1160,19 @@ void main_cleanup_handler(__attribute__((unused)) void *arg) { stop_dbus_service(); #endif if (g_main_loop) { - debug(1, "Stopping DBUS Loop Thread"); + debug(2, "Stopping DBUS Loop Thread"); g_main_loop_quit(g_main_loop); pthread_join(dbus_thread, NULL); } #endif #ifdef CONFIG_DACP_CLIENT - debug(1, "Stopping DACP Monitor"); + debug(2, "Stopping DACP Monitor"); dacp_monitor_stop(); #endif #ifdef CONFIG_METADATA_HUB - debug(1, "Stopping metadata hub"); + debug(2, "Stopping metadata hub"); metadata_hub_stop(); #endif @@ -1177,7 +1183,7 @@ void main_cleanup_handler(__attribute__((unused)) void *arg) { activity_monitor_stop(0); if ((config.output) && (config.output->deinit)) { - debug(1, "Deinitialise the audio backend."); + debug(2, "Deinitialise the audio backend."); config.output->deinit(); } #ifdef CONFIG_LIBDAEMON @@ -1185,12 +1191,12 @@ void main_cleanup_handler(__attribute__((unused)) void *arg) { daemon_pid_file_remove(); daemon_signal_done(); #endif - debug(1, "Exit..."); + debug(2, "Exit..."); exit(0); } void exit_function() { - debug(1, "exit function called..."); + debug(2, "exit function called..."); main_cleanup_handler(NULL); if (conns) free(conns); // make sure the connections have been deleted first diff --git a/tinysvcmdns.c b/tinysvcmdns.c index d0cbebb8..f0c03187 100644 --- a/tinysvcmdns.c +++ b/tinysvcmdns.c @@ -6,6 +6,8 @@ * tinysvcmdns - a tiny MDNS implementation for publishing services * Copyright (C) 2011 Darell Tan * All rights reserved. + * Updated many times by Mike Brady (c) 2014 -- 2019 + * Includes fixes for CVE-12087 and CVE-2017-12130 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -81,6 +83,8 @@ struct name_comp { // duplicates a name inline uint8_t *dup_nlabel(const uint8_t *n) { + if (n == NULL) + return NULL; assert(n[0] <= 63); // prevent mis-use return (uint8_t *)strdup((char *)n); } @@ -126,7 +130,8 @@ char *nlabel_to_str(const uint8_t *name) { size_t buf_len = 256; assert(name != NULL); - + if (name == NULL) + return NULL; label = labelp = malloc(buf_len); if (label) { @@ -186,7 +191,9 @@ uint8_t *create_label(const char *txt) { int len; uint8_t *s; - assert(txt != NULL); + // assert(txt != NULL); + if (txt == NULL) + return NULL; len = strlen(txt); if (len > 63) return NULL; @@ -678,9 +685,12 @@ static size_t mdns_parse_qn(uint8_t *pkt_buf, size_t pkt_len, size_t off, struct if (rr) memset(rr, 0, sizeof(struct rr_entry)); else - die("could not allocate memory for \"rr\" in tinysvcmdns"); + goto err; name = uncompress_nlabel(pkt_buf, pkt_len, off); + if (name == NULL) + goto err; + p += label_len(pkt_buf, pkt_len, off); rr->name = name; @@ -694,6 +704,10 @@ static size_t mdns_parse_qn(uint8_t *pkt_buf, size_t pkt_len, size_t off, struct rr_list_append(&pkt->rr_qn, rr); return p - (pkt_buf + off); + +err: + free(rr); + return 0; } // parse the MDNS RR section @@ -716,10 +730,13 @@ static size_t mdns_parse_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, struct if (rr) memset(rr, 0, sizeof(struct rr_entry)); else - die("could not allocate memory for \"rr (2)\" in tinysvcmdns"); + goto err; name = uncompress_nlabel(pkt_buf, pkt_len, off); - p += label_len(pkt_buf, pkt_len, off); + if (name == NULL) + goto err; + + // parse the MDNS RR section p += label_len(pkt_buf, pkt_len, off); rr->name = name; rr->type = mdns_read_u16(p); @@ -822,6 +839,10 @@ static size_t mdns_parse_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off, struct rr_list_append(&pkt->rr_ans, rr); return p - (pkt_buf + off); + +err: + free(rr); + return 0; } // parse a MDNS packet into an mdns_pkt struct @@ -1716,8 +1737,7 @@ void mdnsd_stop(struct mdnsd *s) { assert(s != NULL); struct timeval tv = { - .tv_sec = 0, - .tv_usec = 500 * 1000, + .tv_sec = 0, .tv_usec = 500 * 1000, }; s->stop_flag = 1;