Compare commits

..
11 Commits
15 changed files with 471 additions and 196 deletions

No files matched your search

+15
View File
@@ -13,7 +13,22 @@ version 2.64
Fix broken vendor-option processing for BOOTP. Thanks to
Hans-Joachim Baader for the bug report.
Don't report spurious netlink errors, regression in
2.63. Thanks to Vladislav Grishenko for the patch.
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.
Fix build with later Lua libraries. Thansk to Cristian
Rodriguez for the patch.
Add --max-cache-ttl option. Thanks to Dennis Kaarsemaker
for the patch.
version 2.63
Do duplicate dhcp-host address check in --test mode.
+42
View File
@@ -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
----------
+7 -1
View File
@@ -2,7 +2,13 @@ dnsmasq (2.64-1) unstable; urgency=low
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 4 Sep 2012 21:50:22 +0000
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 21 Sep 2012 17:17:22 +0000
dnsmasq (2.63-4) unstable; urgency=low
* Make pid-file creation immune to symlink attacks. (closes: #686484)
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 21 Sep 2012 17:16:34 +0000
dnsmasq (2.63-3) unstable; urgency=low
+3
View File
@@ -71,6 +71,9 @@ maximum TTL will be given to clients instead of the true TTL value if it is
lower. The true TTL value is however kept in the cache to avoid flooding
the upstream DNS servers.
.TP
.B --max-cache-ttl=<time>
Set a maximum TTL value for entries in the cache.
.TP
.B \-k, --keep-in-foreground
Do not go into the background at startup but otherwise run as
normal. This is intended for use when dnsmasq is run under daemontools
+3
View File
@@ -371,6 +371,9 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
int freed_all = flags & F_REVERSE;
int free_avail = 0;
if(daemon->max_cache_ttl < ttl)
ttl = daemon->max_cache_ttl;
/* Don't log keys */
if (flags & (F_IPV4 | F_IPV6))
log_query(flags | F_UPSTREAM, name, addr, NULL);
+234 -88
View File
@@ -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,20 +102,118 @@ 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)
{
int skip = 0;
@@ -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;
}
}
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);
add_update_server(&addr, &source_addr, NULL, domain);
} 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 */
/* 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);
}
+5 -3
View File
@@ -255,7 +255,7 @@ void dhcp_update_configs(struct dhcp_config *configs)
in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
restore the status-quo ante first. */
struct dhcp_config *config;
struct dhcp_config *config, *conf_tmp;
struct crec *crec;
int prot = AF_INET;
@@ -297,7 +297,8 @@ void dhcp_update_configs(struct dhcp_config *configs)
config->hostname, daemon->addrbuff);
}
if (prot == AF_INET && !config_find_by_address(configs, crec->addr.addr.addr.addr4))
if (prot == AF_INET &&
(!(conf_tmp = config_find_by_address(configs, crec->addr.addr.addr.addr4)) || conf_tmp == config))
{
config->addr = crec->addr.addr.addr.addr4;
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
@@ -305,7 +306,8 @@ void dhcp_update_configs(struct dhcp_config *configs)
}
#ifdef HAVE_DHCP6
if (prot == AF_INET6 && !config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0))
if (prot == AF_INET6 &&
(!(conf_tmp = config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0)) || conf_tmp == config))
{
memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
+12 -5
View File
@@ -323,14 +323,21 @@ struct dhcp_context *narrow_context6(struct dhcp_context *context,
return tmp;
}
static int is_addr_in_context6(struct dhcp_context *context, struct dhcp_config *config)
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config)
{
if (!context) /* called via find_config() from lease_update_from_configs() */
return 1;
if (!(config->flags & CONFIG_ADDR6))
if (!(config->flags & CONFIG_ADDR6) || is_addr_in_context6(context, &config->addr6))
return 1;
return 0;
}
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr)
{
for (; context; context = context->current)
if (is_same_net6(&config->addr6, &context->start6, context->prefix))
if (is_same_net6(addr, &context->start6, context->prefix))
return 1;
return 0;
@@ -350,7 +357,7 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
{
if (config->clid_len == duid_len &&
memcmp(config->clid, duid, duid_len) == 0 &&
is_addr_in_context6(context, config))
is_config_in_context6(context, config))
return config;
}
@@ -358,7 +365,7 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_NAME) &&
hostname_isequal(config->hostname, hostname) &&
is_addr_in_context6(context, config))
is_config_in_context6(context, config))
return config;
return NULL;
+5 -4
View File
@@ -658,12 +658,13 @@ int main (int argc, char **argv)
if ((dhcp_tmp->flags & CONTEXT_DHCP) || family == AF_INET)
my_syslog(MS_DHCP | LOG_INFO,
(dhcp_tmp->flags & CONTEXT_RA_STATELESS) ?
_("stateless DHCPv6 on %s%.0s%.0s") :
_("%s stateless on %s%.0s%.0s") :
(dhcp_tmp->flags & CONTEXT_STATIC) ?
_("DHCP, static leases only on %.0s%s, %s") :
_("%s, static leases only on %.0s%s, %s") :
(dhcp_tmp->flags & CONTEXT_PROXY) ?
_("DHCP, proxy on subnet %.0s%s%.0s") :
_("DHCP, IP range %s -- %s, %s"),
_("%s, proxy on subnet %.0s%s%.0s") :
_("%s, IP range %s -- %s, %s"),
(family != AF_INET) ? "DHCPv6" : "DHCP",
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff);
if (dhcp_tmp->flags & CONTEXT_RA_NAME)
+5 -1
View File
@@ -751,7 +751,7 @@ extern struct daemon {
int max_logs; /* queue limit */
int cachesize, ftabsize;
int port, query_port, min_port;
unsigned long local_ttl, neg_ttl, max_ttl;
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl;
struct hostsfile *addn_hosts;
struct dhcp_context *dhcp, *dhcp6, *ra_contexts;
struct dhcp_config *dhcp_conf;
@@ -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);
@@ -992,6 +994,7 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr);
struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type);
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
int lease_type, int iaid, struct in6_addr *addr);
void lease6_filter(int lease_type, int iaid, struct dhcp_context *context);
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr);
u64 lease_find_max_addr6(struct dhcp_context *context);
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
@@ -1091,6 +1094,7 @@ void dhcp6_init(void);
void dhcp6_packet(time_t now);
int address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
int serial, struct dhcp_netid *netids, struct in6_addr *ans);
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr);
struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids);
+5
View File
@@ -34,10 +34,15 @@ static void my_setenv(const char *name, const char *value, int *error);
static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end, char *env, int *err);
#ifdef HAVE_LUASCRIPT
#define LUA_COMPAT_ALL
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#ifndef lua_open
#define lua_open() luaL_newstate()
#endif
lua_State *lua;
static unsigned char *grab_extradata_lua(unsigned char *buf, unsigned char *end, char *field);
+20 -7
View File
@@ -562,18 +562,31 @@ struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
memcmp(clid, lease->clid, clid_len) != 0))
continue;
if (clid || addr)
{
lease->flags |= LEASE_USED;
return lease;
}
else
lease->flags &= ~LEASE_USED;
lease->flags |= LEASE_USED;
return lease;
}
return NULL;
}
void lease6_filter(int lease_type, int iaid, struct dhcp_context *context)
{
struct dhcp_lease *lease;
for (lease = leases; lease; lease = lease->next)
{
/* reset "USED flag */
lease->flags &= ~LEASE_USED;
if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
continue;
/* leases on the wrong interface get filtered out here */
if (!is_addr_in_context6(context, (struct in6_addr *)&lease->hwaddr))
lease->flags |= LEASE_USED;
}
}
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
{
struct dhcp_lease *lease;
+2 -1
View File
@@ -336,7 +336,8 @@ static int nl_async(struct nlmsghdr *h)
if (h->nlmsg_type == NLMSG_ERROR)
{
struct nlmsgerr *err = NLMSG_DATA(h);
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
if (err->error != 0)
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
return 0;
}
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
+96 -78
View File
@@ -120,6 +120,7 @@ struct myoption {
#define LOPT_TFTP_LC 309
#define LOPT_RR 310
#define LOPT_CLVERBIND 311
#define LOPT_MAXCTTL 312
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -223,6 +224,7 @@ static const struct myoption opts[] =
{ "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
{ "neg-ttl", 1, 0, LOPT_NEGTTL },
{ "max-ttl", 1, 0, LOPT_MAXTTL },
{ "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
{ "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
{ "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
{ "min-port", 1, 0, LOPT_MINPORT },
@@ -621,6 +623,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 +1849,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 +1860,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;
@@ -1917,6 +1932,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case 'T': /* --local-ttl */
case LOPT_NEGTTL: /* --neg-ttl */
case LOPT_MAXTTL: /* --max-ttl */
case LOPT_MAXCTTL: /* --max-cache-ttl */
{
int ttl;
if (!atoi_check(arg, &ttl))
@@ -1925,6 +1941,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
daemon->neg_ttl = (unsigned long)ttl;
else if (option == LOPT_MAXTTL)
daemon->max_ttl = (unsigned long)ttl;
else if (option == LOPT_MAXCTTL)
daemon->max_cache_ttl = (unsigned long)ttl;
else
daemon->local_ttl = (unsigned long)ttl;
break;
+17 -8
View File
@@ -180,7 +180,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
char *client_hostname= NULL, *hostname = NULL;
char *domain = NULL, *send_domain = NULL;
struct dhcp_config *config = NULL;
struct dhcp_netid known_id, iface_id;
struct dhcp_netid known_id, iface_id, v6_id;
int done_dns = 0, hostname_auth = 0, do_encap = 0;
unsigned char *outmsgtypep;
struct dhcp_opt *opt_cfg;
@@ -194,6 +194,11 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
iface_id.next = tags;
tags = &iface_id;
/* set tag "DHCPv6" */
v6_id.net = "DHCPv6";
v6_id.next = tags;
tags = &v6_id;
/* copy over transaction-id, and save pointer to message type */
outmsgtypep = put_opt6(inbuff, 4);
start_opts = save_counter(-1);
@@ -497,7 +502,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
ia_option = opt6_find(opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4), ia_end, OPTION6_IAADDR, 24);
/* reset "USED" flags on leases */
lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
o = new_opt6(ia_type);
put_opt6_long(iaid);
@@ -570,14 +575,18 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
daemon->addrbuff);
else
addrp = &config->addr6;
{
addrp = &config->addr6;
/* may have existing lease for this address */
lease = lease6_find(clid, clid_len,
ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, addrp);
}
}
/* existing lease */
if (!addrp &&
(lease = lease6_find(clid, clid_len,
ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL)) &&
address6_available(context, (struct in6_addr *)&lease->hwaddr, tags) &&
!config_find_by_address6(daemon->dhcp_conf, (struct in6_addr *)&lease->hwaddr, 128, 0))
addrp = (struct in6_addr *)&lease->hwaddr;
@@ -832,7 +841,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
iacntr = save_counter(-1);
/* reset "USED" flags on leases */
lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
ia_end = opt6_ptr(opt, opt6_len(opt));
@@ -1001,10 +1010,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
case DHCP6IREQ:
{
log6_packet("DHCPINFORMATION-REQUEST", clid, clid_len, NULL, xid, iface_name, ignore ? "ignored" : hostname);
if (ignore)
return 0;
*outmsgtypep = DHCP6REPLY;
log6_packet("DHCPINFORMATION-REQUEST", clid, clid_len, NULL, xid, iface_name, hostname);
break;
}
@@ -1036,7 +1045,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
/* reset "USED" flags on leases */
lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
ia_option;
@@ -1115,7 +1124,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
/* reset "USED" flags on leases */
lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
ia_option;