mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Add SetServersEX method in DBus interface.
This commit is contained in:
@@ -19,6 +19,9 @@ 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
|
||||
Williams for the patch.
|
||||
|
||||
|
||||
version 2.63
|
||||
Do duplicate dhcp-host address check in --test mode.
|
||||
|
||||
@@ -95,6 +95,48 @@ Each call to SetServers 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.
|
||||
|
||||
SetServersEx
|
||||
------------
|
||||
|
||||
This function is more flexible and the SetServers function, in that it can
|
||||
handle address scoping, port numbers, and is easier for clients to use.
|
||||
|
||||
Returns nothing. Takes a set of arguments representing the new
|
||||
upstream DNS servers to be used by dnsmasq. All addresses (both IPv4 and IPv6)
|
||||
are represented as STRINGS. Each server address may be followed by one or more
|
||||
STRINGS, which are the domains for which the preceding server should be used.
|
||||
|
||||
This function takes an array of STRING arrays, where each inner array represents
|
||||
a set of DNS servers and domains for which those servers may be used. Each
|
||||
string represents a list of upstream DNS servers first, and domains second.
|
||||
Mixing of domains and servers within a the string array is not allowed.
|
||||
|
||||
Examples.
|
||||
|
||||
[
|
||||
["1.2.3.4", "foobar.com"],
|
||||
["1003:1234:abcd::1%eth0", "eng.mycorp.com", "lab.mycorp.com"]
|
||||
]
|
||||
|
||||
is equivalent to
|
||||
|
||||
--server=/foobar.com/1.2.3.4 \
|
||||
--server=/eng.mycorp.com/lab.mycorp.com/1003:1234:abcd::1%eth0
|
||||
|
||||
An IPv4 address of 0.0.0.0 is interpreted as "no address, local only",
|
||||
so
|
||||
|
||||
[ ["0.0.0.0", "local.domain"] ]
|
||||
|
||||
is equivalent to
|
||||
|
||||
--local=/local.domain/
|
||||
|
||||
|
||||
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.
|
||||
|
||||
2. SIGNALS
|
||||
----------
|
||||
|
||||
|
||||
314
src/dbus.c
314
src/dbus.c
@@ -38,6 +38,9 @@ const char* introspection_xml_template =
|
||||
" <method name=\"SetServers\">\n"
|
||||
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetServersEx\">\n"
|
||||
" <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"
|
||||
" </method>\n"
|
||||
" <signal name=\"DhcpLeaseAdded\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
@@ -99,19 +102,117 @@ static void remove_watch(DBusWatch *watch, void *data)
|
||||
w = data; /* no warning */
|
||||
}
|
||||
|
||||
static void dbus_read_servers(DBusMessage *message)
|
||||
static void add_update_server(union mysockaddr *addr,
|
||||
union mysockaddr *source_addr,
|
||||
const char *interface,
|
||||
const char *domain)
|
||||
{
|
||||
struct server *serv;
|
||||
|
||||
/* See if there is a suitable candidate, and unmark */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if ((serv->flags & SERV_FROM_DBUS) &&
|
||||
(serv->flags & SERV_MARK))
|
||||
{
|
||||
if (domain)
|
||||
{
|
||||
if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serv->flags & SERV_HAS_DOMAIN)
|
||||
continue;
|
||||
}
|
||||
|
||||
serv->flags &= ~SERV_MARK;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!serv && (serv = whine_malloc(sizeof (struct server))))
|
||||
{
|
||||
/* Not found, create a new one. */
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
|
||||
if (domain && !(serv->domain = whine_malloc(strlen(domain)+1)))
|
||||
{
|
||||
free(serv);
|
||||
serv = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
serv->flags = SERV_FROM_DBUS;
|
||||
if (domain)
|
||||
{
|
||||
strcpy(serv->domain, domain);
|
||||
serv->flags |= SERV_HAS_DOMAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serv)
|
||||
{
|
||||
if (interface)
|
||||
strcpy(serv->interface, interface);
|
||||
else
|
||||
serv->interface[0] = 0;
|
||||
|
||||
if (source_addr->in.sin_family == AF_INET &&
|
||||
addr->in.sin_addr.s_addr == 0 &&
|
||||
serv->domain)
|
||||
serv->flags |= SERV_NO_ADDR;
|
||||
else
|
||||
{
|
||||
serv->flags &= ~SERV_NO_ADDR;
|
||||
serv->addr = *addr;
|
||||
serv->source_addr = *source_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_dbus(void)
|
||||
{
|
||||
struct server *serv;
|
||||
|
||||
/* mark everything from DBUS */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if (serv->flags & SERV_FROM_DBUS)
|
||||
serv->flags |= SERV_MARK;
|
||||
}
|
||||
|
||||
static void cleanup_dbus()
|
||||
{
|
||||
struct server *serv, *tmp, **up;
|
||||
|
||||
/* unlink and free anything still marked. */
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
{
|
||||
tmp = serv->next;
|
||||
if (serv->flags & SERV_MARK)
|
||||
{
|
||||
server_gone(serv);
|
||||
*up = serv->next;
|
||||
if (serv->domain)
|
||||
free(serv->domain);
|
||||
free(serv);
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void dbus_read_servers(DBusMessage *message)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
union mysockaddr addr, source_addr;
|
||||
char *domain;
|
||||
|
||||
dbus_message_iter_init(message, &iter);
|
||||
|
||||
/* mark everything from DBUS */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if (serv->flags & SERV_FROM_DBUS)
|
||||
serv->flags |= SERV_MARK;
|
||||
mark_dbus();
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -171,6 +272,7 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
/* At the end */
|
||||
break;
|
||||
|
||||
/* process each domain */
|
||||
do {
|
||||
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING)
|
||||
{
|
||||
@@ -181,83 +283,118 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
domain = NULL;
|
||||
|
||||
if (!skip)
|
||||
{
|
||||
/* See if this is already there, and unmark */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if ((serv->flags & SERV_FROM_DBUS) &&
|
||||
(serv->flags & SERV_MARK))
|
||||
{
|
||||
if (!(serv->flags & SERV_HAS_DOMAIN) && !domain)
|
||||
{
|
||||
serv->flags &= ~SERV_MARK;
|
||||
break;
|
||||
}
|
||||
if ((serv->flags & SERV_HAS_DOMAIN) &&
|
||||
domain &&
|
||||
hostname_isequal(domain, serv->domain))
|
||||
{
|
||||
serv->flags &= ~SERV_MARK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
add_update_server(&addr, &source_addr, NULL, domain);
|
||||
|
||||
if (!serv && (serv = whine_malloc(sizeof (struct server))))
|
||||
{
|
||||
/* Not found, create a new one. */
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
|
||||
if (domain)
|
||||
serv->domain = whine_malloc(strlen(domain)+1);
|
||||
|
||||
if (domain && !serv->domain)
|
||||
{
|
||||
free(serv);
|
||||
serv = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
serv->flags = SERV_FROM_DBUS;
|
||||
if (domain)
|
||||
{
|
||||
strcpy(serv->domain, domain);
|
||||
serv->flags |= SERV_HAS_DOMAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serv)
|
||||
{
|
||||
if (source_addr.in.sin_family == AF_INET &&
|
||||
addr.in.sin_addr.s_addr == 0 &&
|
||||
serv->domain)
|
||||
serv->flags |= SERV_NO_ADDR;
|
||||
else
|
||||
{
|
||||
serv->flags &= ~SERV_NO_ADDR;
|
||||
serv->addr = addr;
|
||||
serv->source_addr = source_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
|
||||
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
|
||||
}
|
||||
|
||||
/* unlink and free anything still marked. */
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
cleanup_dbus();
|
||||
}
|
||||
|
||||
static DBusMessage* dbus_read_servers_ex(DBusMessage *message)
|
||||
{
|
||||
DBusMessageIter iter, array_iter, string_iter;
|
||||
DBusMessage *error = NULL;
|
||||
const char *addr_err;
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
{
|
||||
tmp = serv->next;
|
||||
if (serv->flags & SERV_MARK)
|
||||
{
|
||||
server_gone(serv);
|
||||
*up = serv->next;
|
||||
free(serv);
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Failed to initialize dbus message iter");
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected array of string arrays");
|
||||
}
|
||||
|
||||
mark_dbus();
|
||||
|
||||
/* array_iter points to each "as" element in the outer array */
|
||||
dbus_message_iter_recurse(&iter, &array_iter);
|
||||
while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID)
|
||||
{
|
||||
const char *str = NULL;
|
||||
union mysockaddr addr, source_addr;
|
||||
char interface[IF_NAMESIZE];
|
||||
char *str_addr;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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, &interface, NULL);
|
||||
free(str_addr);
|
||||
|
||||
if (addr_err)
|
||||
{
|
||||
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s': %s",
|
||||
str, addr_err);
|
||||
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);
|
||||
|
||||
/* jump to next element in outer array */
|
||||
dbus_message_iter_next(&array_iter);
|
||||
}
|
||||
|
||||
cleanup_dbus();
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
@@ -265,11 +402,10 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
void *user_data)
|
||||
{
|
||||
char *method = (char *)dbus_message_get_member(message);
|
||||
DBusMessage *reply = NULL;
|
||||
|
||||
if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
|
||||
{
|
||||
DBusMessage *reply;
|
||||
|
||||
/* string length: "%s" provides space for termination zero */
|
||||
if (!introspection_xml &&
|
||||
(introspection_xml = whine_malloc(strlen(introspection_xml_template) + strlen(daemon->dbus_name))))
|
||||
@@ -278,20 +414,15 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
if (introspection_xml)
|
||||
{
|
||||
reply = dbus_message_new_method_return(message);
|
||||
|
||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
|
||||
dbus_connection_send (connection, reply, NULL);
|
||||
dbus_message_unref (reply);
|
||||
}
|
||||
}
|
||||
else if (strcmp(method, "GetVersion") == 0)
|
||||
{
|
||||
char *v = VERSION;
|
||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||
reply = dbus_message_new_method_return(message);
|
||||
|
||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
|
||||
dbus_connection_send (connection, reply, NULL);
|
||||
dbus_message_unref (reply);
|
||||
}
|
||||
else if (strcmp(method, "SetServers") == 0)
|
||||
{
|
||||
@@ -299,6 +430,12 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
dbus_read_servers(message);
|
||||
check_servers();
|
||||
}
|
||||
else if (strcmp(method, "SetServersEx") == 0)
|
||||
{
|
||||
my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
|
||||
reply = dbus_read_servers_ex(message);
|
||||
check_servers();
|
||||
}
|
||||
else if (strcmp(method, "ClearCache") == 0)
|
||||
clear_cache_and_reload(dnsmasq_time());
|
||||
else
|
||||
@@ -306,8 +443,17 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
|
||||
method = user_data; /* no warning */
|
||||
|
||||
return (DBUS_HANDLER_RESULT_HANDLED);
|
||||
/* If no reply or no error, return nothing */
|
||||
if (!reply)
|
||||
reply = dbus_message_new_method_return(message);
|
||||
|
||||
if (reply)
|
||||
{
|
||||
dbus_connection_send (connection, reply, NULL);
|
||||
dbus_message_unref (reply);
|
||||
}
|
||||
|
||||
return (DBUS_HANDLER_RESULT_HANDLED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -928,6 +928,8 @@ void reread_dhcp(void);
|
||||
void set_option_bool(unsigned int opt);
|
||||
void reset_option_bool(unsigned int opt);
|
||||
struct hostsfile *expand_filelist(struct hostsfile *list);
|
||||
char *parse_server(char *arg, union mysockaddr *addr,
|
||||
union mysockaddr *source_addr, char *interface, int *flags);
|
||||
|
||||
/* forward.c */
|
||||
void reply_query(int fd, int family, time_t now);
|
||||
|
||||
169
src/option.c
169
src/option.c
@@ -621,6 +621,93 @@ static char *set_prefix(char *arg)
|
||||
return arg;
|
||||
}
|
||||
|
||||
char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
|
||||
{
|
||||
int source_port = 0, serv_port = NAMESERVER_PORT;
|
||||
char *portno, *source;
|
||||
#ifdef HAVE_IPV6
|
||||
int scope_index = 0;
|
||||
char *scope_id;
|
||||
#endif
|
||||
|
||||
if ((source = split_chr(arg, '@')) && /* is there a source. */
|
||||
(portno = split_chr(source, '#')) &&
|
||||
!atoi_check16(portno, &source_port))
|
||||
return _("bad port");
|
||||
|
||||
if ((portno = split_chr(arg, '#')) && /* is there a port no. */
|
||||
!atoi_check16(portno, &serv_port))
|
||||
return _("bad port");
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
scope_id = split_chr(arg, '%');
|
||||
#endif
|
||||
|
||||
if ((addr->in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
|
||||
{
|
||||
addr->in.sin_port = htons(serv_port);
|
||||
addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
source_addr->in.sin_addr.s_addr = INADDR_ANY;
|
||||
source_addr->in.sin_port = htons(daemon->query_port);
|
||||
|
||||
if (source)
|
||||
{
|
||||
if (flags)
|
||||
*flags |= SERV_HAS_SOURCE;
|
||||
source_addr->in.sin_port = htons(source_port);
|
||||
if ((source_addr->in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
source_addr->in.sin_addr.s_addr = INADDR_ANY;
|
||||
strncpy(interface, source, IF_NAMESIZE - 1);
|
||||
#else
|
||||
return _("interface binding not supported");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
|
||||
{
|
||||
if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
|
||||
return _("bad interface name");
|
||||
|
||||
addr->in6.sin6_port = htons(serv_port);
|
||||
addr->in6.sin6_scope_id = scope_index;
|
||||
source_addr->in6.sin6_addr = in6addr_any;
|
||||
source_addr->in6.sin6_port = htons(daemon->query_port);
|
||||
source_addr->in6.sin6_scope_id = 0;
|
||||
addr->sa.sa_family = source_addr->sa.sa_family = AF_INET6;
|
||||
addr->in6.sin6_flowinfo = source_addr->in6.sin6_flowinfo = 0;
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr->in6.sin6_len = source_addr->in6.sin6_len = sizeof(addr->in6);
|
||||
#endif
|
||||
if (source)
|
||||
{
|
||||
if (flags)
|
||||
*flags |= SERV_HAS_SOURCE;
|
||||
source_addr->in6.sin6_port = htons(source_port);
|
||||
if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
source_addr->in6.sin6_addr = in6addr_any;
|
||||
strncpy(interface, source, IF_NAMESIZE - 1);
|
||||
#else
|
||||
return _("interface binding not supported");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return _("bad address");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This is too insanely large to keep in-line in the switch */
|
||||
static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||
{
|
||||
@@ -1760,84 +1847,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
}
|
||||
else
|
||||
{
|
||||
int source_port = 0, serv_port = NAMESERVER_PORT;
|
||||
char *portno, *source;
|
||||
#ifdef HAVE_IPV6
|
||||
int scope_index = 0;
|
||||
char *scope_id;
|
||||
#endif
|
||||
|
||||
if ((source = split_chr(arg, '@')) && /* is there a source. */
|
||||
(portno = split_chr(source, '#')) &&
|
||||
!atoi_check16(portno, &source_port))
|
||||
ret_err(_("bad port"));
|
||||
|
||||
if ((portno = split_chr(arg, '#')) && /* is there a port no. */
|
||||
!atoi_check16(portno, &serv_port))
|
||||
ret_err(_("bad port"));
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
scope_id = split_chr(arg, '%');
|
||||
#endif
|
||||
|
||||
if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
|
||||
{
|
||||
newlist->addr.in.sin_port = htons(serv_port);
|
||||
newlist->source_addr.in.sin_port = htons(source_port);
|
||||
newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET;
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
if (source)
|
||||
{
|
||||
newlist->flags |= SERV_HAS_SOURCE;
|
||||
if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
strncpy(newlist->interface, source, IF_NAMESIZE - 1);
|
||||
#else
|
||||
ret_err(_("interface binding not supported"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr) > 0)
|
||||
{
|
||||
if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
|
||||
ret_err(_("bad interface name"));
|
||||
|
||||
newlist->addr.in6.sin6_port = htons(serv_port);
|
||||
newlist->addr.in6.sin6_scope_id = scope_index;
|
||||
newlist->source_addr.in6.sin6_port = htons(source_port);
|
||||
newlist->source_addr.in6.sin6_scope_id = 0;
|
||||
newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6;
|
||||
newlist->addr.in6.sin6_flowinfo = newlist->source_addr.in6.sin6_flowinfo = 0;
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(newlist->addr.in6);
|
||||
#endif
|
||||
if (source)
|
||||
{
|
||||
newlist->flags |= SERV_HAS_SOURCE;
|
||||
if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
newlist->source_addr.in6.sin6_addr = in6addr_any;
|
||||
strncpy(newlist->interface, source, IF_NAMESIZE - 1);
|
||||
#else
|
||||
ret_err(_("interface binding not supported"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
newlist->source_addr.in6.sin6_addr = in6addr_any;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ret_err(gen_err);
|
||||
char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
|
||||
if (err)
|
||||
ret_err(err);
|
||||
}
|
||||
|
||||
serv = newlist;
|
||||
@@ -1846,6 +1858,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
serv->next->flags = serv->flags;
|
||||
serv->next->addr = serv->addr;
|
||||
serv->next->source_addr = serv->source_addr;
|
||||
strcpy(serv->next->interface, serv->interface);
|
||||
serv = serv->next;
|
||||
}
|
||||
serv->next = daemon->servers;
|
||||
|
||||
Reference in New Issue
Block a user