298 lines
7.8 KiB
C
298 lines
7.8 KiB
C
/*
|
|
* dhcpcd - DHCP client daemon
|
|
* Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
|
|
* All rights reserved
|
|
|
|
* 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 <stdio.h>
|
|
#include <string.h>
|
|
#include <syslog.h>
|
|
|
|
#include <dbus/dbus.h>
|
|
|
|
#include "../config.h"
|
|
#include "dbus-dict.h"
|
|
|
|
static dbus_bool_t
|
|
append_sanitized_string(DBusMessageIter *iter, const char *value)
|
|
{
|
|
dbus_bool_t ret;
|
|
int len = strlen(value);
|
|
char *sanitized_value = NULL;
|
|
int i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (isascii(value[i]) || isprint(value[i])) {
|
|
if (sanitized_value)
|
|
sanitized_value[i] = value[i];
|
|
} else {
|
|
if (sanitized_value == NULL) {
|
|
sanitized_value = malloc(len + 1);
|
|
if (sanitized_value == NULL) {
|
|
syslog(LOG_ERR, "DBus string parameter "
|
|
"sanitization failed due to "
|
|
"malloc failure");
|
|
return FALSE;
|
|
}
|
|
memcpy(sanitized_value, value, i);
|
|
}
|
|
sanitized_value[i] = '?';
|
|
}
|
|
}
|
|
if (sanitized_value) {
|
|
syslog(LOG_ERR, "DBus string parameter sanitization"
|
|
" was invoked");
|
|
sanitized_value[i] = '\0';
|
|
ret = dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
|
|
&sanitized_value);
|
|
|
|
free(sanitized_value);
|
|
} else {
|
|
ret = dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
|
|
&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_byte_array(DBusMessageIter *entry, const char *data)
|
|
{
|
|
DBusMessageIter var, array;
|
|
dbus_bool_t ok = TRUE;
|
|
uint8_t u8, u8_2;
|
|
size_t len;
|
|
const char *it, *end;
|
|
const char *tsa, *ts;
|
|
|
|
tsa = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
|
|
ts = DBUS_TYPE_BYTE_AS_STRING;
|
|
|
|
dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, tsa, &var);
|
|
dbus_message_iter_open_container(&var, DBUS_TYPE_ARRAY, ts, &array);
|
|
|
|
len = strlen(data);
|
|
it = data;
|
|
end = data + len;
|
|
|
|
/* "a12" is treated as "0a12" */
|
|
if (len & 1) {
|
|
ok = (sscanf(it++, "%1hhx", &u8) == 1) &&
|
|
dbus_message_iter_append_basic(&array, DBUS_TYPE_BYTE,
|
|
&u8);
|
|
}
|
|
|
|
while (ok && it < end) {
|
|
/* sscanf("1z", "%2hhx", &u8) will store 0x01 in u8 and
|
|
* will return 1 */
|
|
ok = (sscanf(it++, "%1hhx", &u8) == 1) &&
|
|
(sscanf(it++, "%1hhx", &u8_2) == 1);
|
|
if (!ok)
|
|
break;
|
|
|
|
u8 = (u8 << 4) | u8_2;
|
|
ok = dbus_message_iter_append_basic(&array, DBUS_TYPE_BYTE, &u8);
|
|
}
|
|
|
|
dbus_message_iter_close_container(&var, &array);
|
|
dbus_message_iter_close_container(entry, &var);
|
|
return ok ? 0 : -1;
|
|
}
|
|
|
|
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;
|
|
|
|
if (type == DBUS_TYPE_BYTE)
|
|
return append_config_byte_array(entry, data);
|
|
|
|
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;
|
|
}
|