blob: a0ba385bf92f282e2160dfbe608a285dc8fca2ef [file] [log] [blame]
/*
* dhcpcd-dbus
* Copyright 2009 Roy Marples <roy@marples.name>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <arpa/inet.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <dbus/dbus.h>
#include "config.h"
#include "dbus-dict.h"
#define S_EINVAL DHCPCD_SERVICE ".InvalidArgument"
static dbus_bool_t
append_sanitized_string(DBusMessageIter *iter, const char *value)
{
dbus_bool_t ret;
int len = strlen(value);
char *sanitized_value = malloc(len + 1);
dbus_bool_t sanitize_was_invoked = FALSE;
if (sanitized_value != NULL) {
int i;
for (i = 0; i < len; i++) {
if (isascii(value[i]) || isprint(value[i]))
sanitized_value[i] = value[i];
else {
sanitize_was_invoked = TRUE;
sanitized_value[i] = '?';
}
}
sanitized_value[i] = '\0';
if (sanitize_was_invoked)
syslog(LOG_ERR, "DBus string parameter sanitization"
" was invoked");
} else {
/*
* Whoops! malloc failed. We could give up right now, but we
* could also just pass the un-sanitized value on the
* off-chance that we succeed. If we don't we'll just crash
* in dbus_message_iter_append_basic().
*/
sanitized_value = value;
}
ret = dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
&sanitized_value);
if (sanitized_value != value)
free(sanitized_value);
return ret;
}
static int
append_config_value(DBusMessageIter *entry, int type,
const char *data)
{
int retval;
DBusMessageIter var;
unsigned char byte;
dbus_uint16_t u16;
dbus_uint32_t u32;
dbus_int16_t i16;
dbus_int32_t i32;
struct in_addr in;
retval = -1;
switch (type) {
case DBUS_TYPE_BOOLEAN:
if (*data == '0' || *data == '\0')
u32 = 0;
else
u32 = 1;
dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
DBUS_TYPE_BOOLEAN_AS_STRING, &var);
if (dbus_message_iter_append_basic(&var,
DBUS_TYPE_BOOLEAN, &u32))
retval = 0;
break;
case DBUS_TYPE_BYTE:
byte = strtoul(data, NULL, 0);
dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
DBUS_TYPE_BYTE_AS_STRING, &var);
if (dbus_message_iter_append_basic(&var, DBUS_TYPE_BYTE,
&byte))
retval = 0;
break;
case DBUS_TYPE_STRING:
dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
DBUS_TYPE_STRING_AS_STRING, &var);
if (append_sanitized_string(&var, data))
retval = 0;
break;
case DBUS_TYPE_INT16:
i16 = strtol(data, NULL, 0);
dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
DBUS_TYPE_INT16_AS_STRING, &var);
if (dbus_message_iter_append_basic(&var,
DBUS_TYPE_INT16, &i16))
retval = 0;
break;
case DBUS_TYPE_UINT16:
u16 = strtoul(data, NULL, 0);
dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
DBUS_TYPE_UINT16_AS_STRING, &var);
if (dbus_message_iter_append_basic(&var,
DBUS_TYPE_UINT16, &u16))
retval = 0;
break;
case DBUS_TYPE_INT32:
i32 = strtol(data, NULL, 0);
dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
DBUS_TYPE_INT32_AS_STRING, &var);
if (dbus_message_iter_append_basic(&var,
DBUS_TYPE_INT32, &i32))
retval = 0;
break;
case DBUS_TYPE_UINT32:
if (strchr(data, '.') != NULL && inet_aton(data, &in) == 1)
u32 = in.s_addr;
else
u32 = strtoul(data, NULL, 0);
dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
DBUS_TYPE_UINT32_AS_STRING, &var);
if (dbus_message_iter_append_basic(&var,
DBUS_TYPE_UINT32, &u32))
retval = 0;
break;
default:
retval = 1;
break;
}
if (retval == 0)
dbus_message_iter_close_container(entry, &var);
else if (retval == 1)
retval = 0;
return retval;
}
static int
append_config_array(DBusMessageIter *entry, int type, const char *data)
{
int retval;
char *ns, *p, *tok;
const char *tsa, *ts;
DBusMessageIter var, array;
dbus_bool_t ok;
dbus_uint32_t u32;
struct in_addr in;
switch (type) {
case DBUS_TYPE_STRING:
tsa = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING;
ts = DBUS_TYPE_STRING_AS_STRING;
break;
case DBUS_TYPE_UINT32:
tsa = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_UINT32_AS_STRING;
ts = DBUS_TYPE_UINT32_AS_STRING;
break;
default:
return -1;
}
ns = p = strdup(data);
if (ns == NULL)
return -1;
retval = 0;
dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, tsa, &var);
dbus_message_iter_open_container(&var, DBUS_TYPE_ARRAY, ts, &array);
while ((tok = strsep(&p, " ")) != NULL) {
if (*tok == '\0')
continue;
switch(type) {
case DBUS_TYPE_STRING:
ok = append_sanitized_string(&array, tok);
break;
case DBUS_TYPE_UINT32:
if (strchr(tok, '.') != NULL &&
inet_aton(tok, &in) == 1)
u32 = in.s_addr;
else
u32 = strtoul(tok, NULL, 0);
ok = dbus_message_iter_append_basic(&array,
DBUS_TYPE_UINT32, &u32);
break;
default:
ok = FALSE;
break;
}
if (!ok)
break;
}
dbus_message_iter_close_container(&var, &array);
dbus_message_iter_close_container(entry, &var);
free(ns);
return retval;
}
int
dict_append_config_item(DBusMessageIter *iter, const struct o_dbus *op,
const char *data)
{
int retval;
DBusMessageIter entry;
retval = 0;
if (*data == '\0')
return retval;
dbus_message_iter_open_container(iter,
DBUS_TYPE_DICT_ENTRY,
NULL,
&entry);
append_sanitized_string(&entry, op->name);
if (op->type == DBUS_TYPE_ARRAY)
retval = append_config_array(&entry, op->sub_type, data);
else
retval = append_config_value(&entry, op->type, data);
dbus_message_iter_close_container(iter, &entry);
return retval;
}