| /* |
| * |
| * Connection Manager |
| * |
| * Copyright (C) 2007-2009 Intel Corporation. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| * |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <syslog.h> |
| |
| #include <gdbus.h> |
| |
| #include "connman.h" |
| |
| #ifndef VCSID |
| #define VCSID "<not set>" |
| #endif |
| |
| static volatile unsigned debug_enabled = 0; |
| |
| /* A non-NULL sentinel pointer used as a value in masked_key_hash. */ |
| static gpointer *sentinel_pointer = (gpointer)~0; |
| /* |
| * A hash table, used as a set, to look up for keys whose value should be |
| * masked out from the log |
| */ |
| static GHashTable *masked_key_hash = NULL; |
| /* |
| * This string is printed to the log instead of the actual value of keys |
| * being masked out |
| */ |
| static const char kMaskedValue[] = "[***]"; |
| |
| #define DBGTAG(tag) {#tag, DBG_##tag} |
| |
| /* |
| * N.B. The following must be kept in sync with the enum |
| * of debug tag values in log.h. |
| */ |
| static struct _debugtag { |
| const char *tagname; |
| unsigned int mask; |
| } debugtags[] = { |
| DBGTAG(AGENT), |
| DBGTAG(CONNECTION), |
| DBGTAG(DEVICE), |
| DBGTAG(ELEMENT), |
| DBGTAG(INET), |
| DBGTAG(MANAGER), |
| DBGTAG(NETWORK), |
| DBGTAG(NOTIFIER), |
| DBGTAG(PROFILE), |
| DBGTAG(RESOLV), |
| DBGTAG(RFKILL), |
| DBGTAG(RTNL), |
| DBGTAG(SECURITY), |
| DBGTAG(SERVICE), |
| DBGTAG(STORAGE), |
| DBGTAG(TASK), |
| DBGTAG(TEST), |
| DBGTAG(UDEV), |
| DBGTAG(METRICS), |
| DBGTAG(CRYPTO), |
| DBGTAG(PLUGIN), |
| DBGTAG(BLUETOOTH), |
| DBGTAG(DHCLIENT), |
| DBGTAG(DNSPROXY), |
| DBGTAG(ETHERNET), |
| DBGTAG(HOSTROUTE), |
| DBGTAG(PPPD), |
| DBGTAG(VPN), |
| DBGTAG(WIFI), |
| DBGTAG(MODEM), |
| DBGTAG(RESOLVFILES), |
| DBGTAG(PORTAL), |
| /* pseudo-tags */ |
| DBGTAG(ANY) |
| }; |
| |
| /** |
| * connman_vinfo: |
| * @format: format string |
| * @ap: varags list of arguments |
| * |
| * Output general information |
| */ |
| void connman_vinfo(const char *format, va_list ap) |
| { |
| vsyslog(LOG_INFO, format, ap); |
| } |
| |
| /** |
| * connman_info: |
| * @format: format string |
| * @Varargs: list of arguments |
| * |
| * Output general information |
| */ |
| void connman_info(const char *format, ...) |
| { |
| va_list ap; |
| |
| va_start(ap, format); |
| connman_vinfo(format, ap); |
| va_end(ap); |
| } |
| |
| |
| /** |
| * connman_vwarn: |
| * @format: format string |
| * @ap: varargs list of arguments |
| * |
| * Output warning messages |
| */ |
| void connman_vwarn(const char *format, va_list ap) |
| { |
| vsyslog(LOG_WARNING, format, ap); |
| } |
| |
| /** |
| * connman_warn: |
| * @format: format string |
| * @Varargs: list of arguments |
| * |
| * Output warning messages |
| */ |
| void connman_warn(const char *format, ...) |
| { |
| va_list ap; |
| |
| va_start(ap, format); |
| connman_vwarn(format, ap); |
| va_end(ap); |
| } |
| |
| /** |
| * connman_verror: |
| * @format: format string |
| * @ap: varargs list of arguments |
| * |
| * Output error messages |
| */ |
| void connman_verror(const char *format, va_list ap) |
| { |
| vsyslog(LOG_ERR, format, ap); |
| } |
| |
| /** |
| * connman_error: |
| * @format: format string |
| * @varargs: list of arguments |
| * |
| * Output error messages |
| */ |
| void connman_error(const char *format, ...) |
| { |
| va_list ap; |
| |
| va_start(ap, format); |
| connman_verror(format, ap); |
| va_end(ap); |
| } |
| |
| /** |
| * connman_vdebug: |
| * @mask: debug message mask |
| * @format: format string |
| * @ap: varargs list of arguments |
| * |
| * Output debug message |
| * |
| * The actual output of the debug message is controlled via a command line |
| * switch. If not enabled, these messages will be ignored. |
| */ |
| void connman_vdebug(unsigned mask, const char *format, va_list ap) |
| { |
| if ((debug_enabled & mask) != 0) |
| vsyslog(LOG_DEBUG, format, ap); |
| } |
| |
| /** |
| * connman_debug: |
| * @mask: debug message mask |
| * @format: format string |
| * @varargs: list of arguments |
| * |
| * Output debug message |
| * |
| * The actual output of the debug message is controlled via a command line |
| * switch. If not enabled, these messages will be ignored. |
| */ |
| void connman_debug(unsigned mask, const char *format, ...) |
| { |
| va_list ap; |
| |
| va_start(ap, format); |
| connman_vdebug(mask, format, ap); |
| va_end(ap); |
| } |
| |
| unsigned __connman_debug_setmask(unsigned debugmask) |
| { |
| unsigned omask = debug_enabled; |
| |
| debug_enabled = debugmask; |
| |
| return omask; |
| } |
| |
| unsigned __connman_debug_getmask(void) |
| { |
| return debug_enabled; |
| } |
| |
| unsigned __connman_debug_tags_to_mask(const char *tags, GError **error) |
| { |
| gchar **taglist = g_strsplit(tags, "+", 0); |
| gchar **tagp; |
| gchar *tag; |
| unsigned int debugmask = 0; |
| int j; |
| |
| for (tagp = taglist; (tag = *tagp) != NULL; tagp++) { |
| struct _debugtag *dtag = NULL; |
| for (j = 0; j < G_N_ELEMENTS(debugtags); j++) { |
| if (g_ascii_strcasecmp(tag, debugtags[j].tagname) |
| == 0) { |
| dtag = &debugtags[j]; |
| debugmask |= dtag->mask; |
| break; |
| } |
| } |
| if (dtag == NULL) { |
| g_set_error(error, |
| G_OPTION_ERROR, |
| G_OPTION_ERROR_BAD_VALUE, |
| "Unknown debug tag \"%s\"", tag); |
| break; |
| } |
| } |
| |
| g_strfreev(taglist); |
| return debugmask; |
| } |
| |
| connman_bool_t connman_debug_enabled(unsigned debugmask) |
| { |
| return (debug_enabled & debugmask) ? TRUE : FALSE; |
| } |
| |
| gchar *__connman_debug_get_tag_list(unsigned int debugmask) |
| { |
| int i; |
| unsigned int val = debugmask; |
| unsigned int numbits; |
| int vecind; |
| gchar **tagvec; |
| gchar *taglist; |
| gchar *cp; |
| |
| if (debugmask == 0) |
| return g_strdup(""); |
| |
| /* |
| * Use Kernighan's method for counting number of bits set. See |
| * http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan |
| * The number of iteration is equal to the number of set bits. |
| */ |
| for (numbits = 0; val != 0; numbits++) { |
| val &= val - 1; |
| } |
| |
| tagvec = g_new(gchar *, numbits+1); |
| if (tagvec == NULL) |
| return NULL; |
| |
| for (i = 0, vecind = 0; i < G_N_ELEMENTS(debugtags); i++) { |
| struct _debugtag *dtag = &debugtags[i]; |
| if ((debugmask & dtag->mask) == dtag->mask && |
| dtag->mask != DBG_ANY) |
| tagvec[vecind++] = (gchar *)dtag->tagname; |
| } |
| tagvec[vecind] = NULL; |
| taglist = g_strjoinv("+", tagvec); |
| for (cp = taglist; *cp != '\0'; ++cp) |
| *cp = g_ascii_tolower(*cp); |
| g_free(tagvec); |
| return taglist; |
| } |
| |
| gchar *__connman_debug_get_tags() |
| { |
| return __connman_debug_get_tag_list(__connman_debug_getmask()); |
| } |
| |
| gchar *__connman_debug_get_all_tags() |
| { |
| return __connman_debug_get_tag_list(DBG_ANY); |
| } |
| |
| gboolean __connman_debug_set_tags(char *taglist) |
| { |
| GError *error = NULL; |
| unsigned int debugmask; |
| |
| debugmask = __connman_debug_tags_to_mask(taglist, &error); |
| if (error != NULL) |
| return FALSE; |
| __connman_debug_setmask(debugmask); |
| return TRUE; |
| |
| } |
| |
| int __connman_log_init(gboolean detach, unsigned debugmask) |
| { |
| int option = LOG_NDELAY | LOG_PID; |
| |
| if (detach == FALSE) |
| option |= LOG_PERROR; |
| |
| openlog("flimflamd", option, LOG_DAEMON); |
| |
| syslog(LOG_INFO, "vcsid %s", VCSID); |
| |
| __connman_debug_setmask(debugmask); |
| |
| masked_key_hash = g_hash_table_new_full(g_str_hash, g_str_equal, |
| g_free, NULL); |
| |
| return 0; |
| } |
| |
| void __connman_log_cleanup(void) |
| { |
| g_hash_table_destroy(masked_key_hash); |
| |
| syslog(LOG_INFO, "Exit"); |
| |
| closelog(); |
| } |
| |
| /** |
| * connman_log_mask_value_of_key: |
| * @key: key whose value to be masked out |
| * |
| * Mask out the value of the provided key in the log. |
| */ |
| void connman_log_mask_value_of_key(const char *key) |
| { |
| g_hash_table_insert(masked_key_hash, g_strdup(key), sentinel_pointer); |
| } |
| |
| /** |
| * connman_log_get_masked_value: |
| * @key: key associated with the value |
| * @value: value to be printed to the log |
| * |
| * Return kMaskedValue if @key is in masked_key_hash, or @value otherwise. |
| */ |
| const char *connman_log_get_masked_value(const char *key, const char *value) |
| { |
| if (g_hash_table_lookup(masked_key_hash, key) != NULL) |
| return kMaskedValue; |
| |
| return value; |
| } |