blob: ff93a56eb30705ce9d7c30a98bd0b0819f9548cd [file] [log] [blame]
/*
*
* 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;
}