diff --git a/CHANGELOG b/CHANGELOG index 9013579..a39b178 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,9 +19,12 @@ version 2.64 Flag DHCP or DHCPv6 in starup logging. Thanks to Vladislav Grishenko for the patch. - Add SetServersEX method in DBus interface. Thanks to Dan + Add SetServersEx method in DBus interface. Thanks to Dan Williams for the patch. + Add SetDomainServers method in DBus interface. Thanks to + Roy Marples for the patch. + Fix build with later Lua libraries. Thansk to Cristian Rodriguez for the patch. diff --git a/dbus/DBus-interface b/dbus/DBus-interface index 58ae03c..cbb6e82 100644 --- a/dbus/DBus-interface +++ b/dbus/DBus-interface @@ -137,6 +137,23 @@ Each call to SetServersEx completely replaces the set of servers specified by via the DBus, but it leaves any servers specified via the command line or /etc/dnsmasq.conf or /etc/resolv.conf alone. + +SetDomainServers +---------------- + +Yes another variation for setting DNS servers, with the capability of +SetServersEx, but without using arrays of arrays, which are not +sendable with dbus-send. The arguments are an array of strings which +are identical to the equivalent arguments --server, so the example +for SetServersEx is represented as + +[ + "/foobar.com/1.2.3.4" + "/eng.mycorp.com/lab.mycorp.com/1003:1234:abcd::1%eth0" +] + + + 2. SIGNALS ---------- diff --git a/src/dbus.c b/src/dbus.c index d835270..cbcc91a 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -38,6 +38,9 @@ const char* introspection_xml_template = " \n" " \n" " \n" +" \n" +" \n" +" \n" " \n" " \n" " \n" @@ -292,12 +295,15 @@ static void dbus_read_servers(DBusMessage *message) cleanup_dbus(); } -static DBusMessage* dbus_read_servers_ex(DBusMessage *message) +static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings) { DBusMessageIter iter, array_iter, string_iter; DBusMessage *error = NULL; const char *addr_err; - + char *dup = NULL; + + my_syslog(LOG_INFO, _("setting upstream servers from DBus")); + if (!dbus_message_iter_init(message, &iter)) { return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, @@ -306,10 +312,10 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message) /* check that the message contains an array of arrays */ if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) || - (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)) + (dbus_message_iter_get_element_type(&iter) != (strings ? DBUS_TYPE_STRING : DBUS_TYPE_ARRAY))) { return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, - "Expected array of string arrays"); + strings ? "Expected array of string" : "Expected array of string arrays"); } mark_dbus(); @@ -321,51 +327,91 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message) const char *str = NULL; union mysockaddr addr, source_addr; char interface[IF_NAMESIZE]; - char *str_addr; + char *str_addr, *str_domain; - /* check the types of the struct and its elements */ - if ((dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY) || - (dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_STRING)) - { - error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, - "Expected inner array of strings"); - break; - } + if (strings) + { + dbus_message_iter_get_basic(&array_iter, &str); + if (!str || !strlen (str)) + { + error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, + "Empty string"); + break; + } + + /* dup the string because it gets modified during parsing */ + if (!(dup = str_domain = whine_malloc(strlen(str)+1))) + break; - /* string_iter points to each "s" element in the inner array */ - dbus_message_iter_recurse(&array_iter, &string_iter); - if (dbus_message_iter_get_arg_type(&string_iter) != DBUS_TYPE_STRING) - { - /* no IP address given */ - error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, - "Expected IP address"); - break; - } + strcpy(str_domain, str); - dbus_message_iter_get_basic(&string_iter, &str); - if (!str || !strlen (str)) - { - error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, - "Empty IP address"); - break; - } + /* point to address part of old string for error message */ + if ((str_addr = strrchr(str, '/'))) + str = str_addr+1; + + if ((str_addr = strrchr(str_domain, '/'))) + { + if (*str_domain != '/' || str_addr == str_domain) + { + error = dbus_message_new_error_printf(message, + DBUS_ERROR_INVALID_ARGS, + "No domain terminator '%s'", + str); + break; + } + *str_addr++ = 0; + str_domain++; + } + else + { + str_addr = str_domain; + str_domain = NULL; + } + + + } + else + { + /* check the types of the struct and its elements */ + if ((dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY) || + (dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_STRING)) + { + error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, + "Expected inner array of strings"); + break; + } + + /* string_iter points to each "s" element in the inner array */ + dbus_message_iter_recurse(&array_iter, &string_iter); + if (dbus_message_iter_get_arg_type(&string_iter) != DBUS_TYPE_STRING) + { + /* no IP address given */ + error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, + "Expected IP address"); + break; + } + + dbus_message_iter_get_basic(&string_iter, &str); + if (!str || !strlen (str)) + { + error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, + "Empty IP address"); + break; + } + + /* dup the string because it gets modified during parsing */ + if (!(dup = str_addr = whine_malloc(strlen(str)+1))) + break; + + strcpy(str_addr, str); + } memset(&addr, 0, sizeof(addr)); memset(&source_addr, 0, sizeof(source_addr)); memset(&interface, 0, sizeof(interface)); - /* dup the string because it gets modified during parsing */ - str_addr = strdup(str); - if (!str_addr) - { - error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, - "Out of memory parsing IP address"); - break; - } - /* parse the IP address */ addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, NULL); - free(str_addr); if (addr_err) { @@ -375,25 +421,47 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message) break; } - /* jump past the address to the domain list (if any) */ - dbus_message_iter_next (&string_iter); - - /* parse domains and add each server/domain pair to the list */ - do { - str = NULL; - if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING) - dbus_message_iter_get_basic(&string_iter, &str); - dbus_message_iter_next (&string_iter); - - add_update_server(&addr, &source_addr, interface, str); - } while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING); - + if (strings) + { + char *p; + + do { + if (str_domain) + { + if ((p = strchr(str_domain, '/'))) + *p++ = 0; + } + else + p = NULL; + + add_update_server(&addr, &source_addr, interface, str_domain); + } while ((str_domain = p)); + } + else + { + /* jump past the address to the domain list (if any) */ + dbus_message_iter_next (&string_iter); + + /* parse domains and add each server/domain pair to the list */ + do { + str = NULL; + if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING) + dbus_message_iter_get_basic(&string_iter, &str); + dbus_message_iter_next (&string_iter); + + add_update_server(&addr, &source_addr, interface, str); + } while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING); + } + /* jump to next element in outer array */ dbus_message_iter_next(&array_iter); } cleanup_dbus(); + if (dup) + free(dup); + return error; } @@ -403,7 +471,7 @@ DBusHandlerResult message_handler(DBusConnection *connection, { char *method = (char *)dbus_message_get_member(message); DBusMessage *reply = NULL; - + if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) { /* string length: "%s" provides space for termination zero */ @@ -432,8 +500,12 @@ DBusHandlerResult message_handler(DBusConnection *connection, } else if (strcmp(method, "SetServersEx") == 0) { - my_syslog(LOG_INFO, _("setting upstream servers from DBus")); - reply = dbus_read_servers_ex(message); + reply = dbus_read_servers_ex(message, 0); + check_servers(); + } + else if (strcmp(method, "SetDomainServers") == 0) + { + reply = dbus_read_servers_ex(message, 1); check_servers(); } else if (strcmp(method, "ClearCache") == 0)