mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.47.tar.gz
This commit is contained in:
18
src/bpf.c
18
src/bpf.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -63,16 +63,20 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
|
||||
}
|
||||
}
|
||||
|
||||
for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len; ptr += len )
|
||||
for (ptr = ifc.ifc_buf; ptr < (char *)(ifc.ifc_buf + ifc.ifc_len); ptr += len)
|
||||
{
|
||||
/* subsequent entries may not be aligned, so copy into
|
||||
an aligned buffer to avoid nasty complaints about
|
||||
unaligned accesses. */
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
len = ((struct ifreq *)ptr)->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru);
|
||||
#else
|
||||
|
||||
len = sizeof(struct ifreq);
|
||||
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
ifr = (struct ifreq *)ptr;
|
||||
if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru))
|
||||
len = ifr->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru);
|
||||
#endif
|
||||
|
||||
if (!expand_buf(&ifreq, len))
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
36
src/config.h
36
src/config.h
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,11 +10,11 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define VERSION "2.46"
|
||||
#define VERSION "2.47"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
@@ -38,18 +38,25 @@
|
||||
# define RESOLVFILE "/etc/resolv.conf"
|
||||
#endif
|
||||
#define RUNFILE "/var/run/dnsmasq.pid"
|
||||
#if defined(__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__)
|
||||
# define LEASEFILE "/var/db/dnsmasq.leases"
|
||||
#elif defined(__sun__) || defined (__sun)
|
||||
# define LEASEFILE "/var/cache/dnsmasq.leases"
|
||||
#else
|
||||
# define LEASEFILE "/var/lib/misc/dnsmasq.leases"
|
||||
|
||||
#ifndef LEASEFILE
|
||||
# if defined(__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
|
||||
# define LEASEFILE "/var/db/dnsmasq.leases"
|
||||
# elif defined(__sun__) || defined (__sun)
|
||||
# define LEASEFILE "/var/cache/dnsmasq.leases"
|
||||
# else
|
||||
# define LEASEFILE "/var/lib/misc/dnsmasq.leases"
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
# define CONFFILE "/usr/local/etc/dnsmasq.conf"
|
||||
#else
|
||||
# define CONFFILE "/etc/dnsmasq.conf"
|
||||
|
||||
#ifndef CONFFILE
|
||||
# if defined(__FreeBSD__)
|
||||
# define CONFFILE "/usr/local/etc/dnsmasq.conf"
|
||||
# else
|
||||
# define CONFFILE "/etc/dnsmasq.conf"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
||||
#define CHUSER "nobody"
|
||||
#define CHGRP "dip"
|
||||
@@ -61,6 +68,7 @@
|
||||
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
|
||||
#define LOG_MAX 5 /* log-queue length */
|
||||
#define RANDFILE "/dev/urandom"
|
||||
#define DAD_WAIT 20 /* retry binding IPv6 sockets for this long */
|
||||
|
||||
/* DBUS interface specifics */
|
||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
|
||||
|
||||
52
src/dbus.c
52
src/dbus.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -21,6 +21,42 @@
|
||||
#define DBUS_API_SUBJECT_TO_CHANGE
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
const char* introspection_xml =
|
||||
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
|
||||
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
||||
"<node name=\"" DNSMASQ_PATH "\">\n"
|
||||
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
|
||||
" <method name=\"Introspect\">\n"
|
||||
" <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
|
||||
" </method>\n"
|
||||
" </interface>\n"
|
||||
" <interface name=\"" DNSMASQ_SERVICE "\">\n"
|
||||
" <method name=\"ClearCache\">\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetVersion\">\n"
|
||||
" <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetServers\">\n"
|
||||
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
|
||||
" </method>\n"
|
||||
" <signal name=\"DhcpLeaseAdded\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"s\"/>\n"
|
||||
" </signal>\n"
|
||||
" <signal name=\"DhcpLeaseDeleted\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"s\"/>\n"
|
||||
" </signal>\n"
|
||||
" <signal name=\"DhcpLeaseUpdated\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"s\"/>\n"
|
||||
" </signal>\n"
|
||||
" </interface>\n"
|
||||
"</node>\n";
|
||||
|
||||
struct watch {
|
||||
DBusWatch *watch;
|
||||
struct watch *next;
|
||||
@@ -229,7 +265,15 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
{
|
||||
char *method = (char *)dbus_message_get_member(message);
|
||||
|
||||
if (strcmp(method, "GetVersion") == 0)
|
||||
if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
|
||||
{
|
||||
DBusMessage *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);
|
||||
|
||||
22
src/dhcp.c
22
src/dhcp.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -345,7 +345,12 @@ void dhcp_packet(time_t now)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SOLARIS_NETWORK
|
||||
/* OpenSolaris eliminates IP_XMIT_IF */
|
||||
# ifdef IP_XMIT_IF
|
||||
setsockopt(daemon->dhcpfd, IPPROTO_IP, IP_XMIT_IF, &iface_index, sizeof(iface_index));
|
||||
# else
|
||||
setsockopt(daemon->dhcpfd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
while(sendmsg(daemon->dhcpfd, &msg, 0) == -1 && retry_send());
|
||||
@@ -560,9 +565,16 @@ int address_allocate(struct dhcp_context *context,
|
||||
if (addr.s_addr == d->router.s_addr)
|
||||
break;
|
||||
|
||||
/* Addresses which end in .255 and .0 are broken in Windows even when using
|
||||
supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0
|
||||
then 192.168.0.255 is a valid IP address, but not for Windows as it's
|
||||
in the class C range. See KB281579. We therefore don't allocate these
|
||||
addresses to avoid hard-to-diagnose problems. Thanks Bill. */
|
||||
if (!d &&
|
||||
!lease_find_by_addr(addr) &&
|
||||
!config_find_by_address(daemon->dhcp_conf, addr))
|
||||
!config_find_by_address(daemon->dhcp_conf, addr) &&
|
||||
(!IN_CLASSC(ntohl(addr.s_addr)) ||
|
||||
((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
|
||||
{
|
||||
struct ping_result *r, *victim = NULL;
|
||||
int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
|
||||
@@ -744,7 +756,7 @@ void dhcp_read_ethers(void)
|
||||
while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
|
||||
buff[strlen(buff)-1] = 0;
|
||||
|
||||
if ((*buff == '#') || (*buff == '+'))
|
||||
if ((*buff == '#') || (*buff == '+') || (*buff == 0))
|
||||
continue;
|
||||
|
||||
for (ip = buff; *ip && !isspace((int)*ip); ip++);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -856,6 +856,9 @@ static void async_event(int pipe, time_t now)
|
||||
|
||||
if (daemon->lease_stream)
|
||||
fclose(daemon->lease_stream);
|
||||
|
||||
if (daemon->runfile)
|
||||
unlink(daemon->runfile);
|
||||
|
||||
my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
|
||||
flush_log();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,11 +10,11 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define COPYRIGHT "Copyright (C) 2000-2008 Simon Kelley"
|
||||
#define COPYRIGHT "Copyright (C) 2000-2009 Simon Kelley"
|
||||
|
||||
#ifndef NO_LARGEFILE
|
||||
/* Ensure we can use files >2GB (log files may grow this big) */
|
||||
@@ -201,7 +201,7 @@ struct bogus_addr {
|
||||
|
||||
/* dns doctor param */
|
||||
struct doctor {
|
||||
struct in_addr in, out, mask;
|
||||
struct in_addr in, end, out, mask;
|
||||
struct doctor *next;
|
||||
};
|
||||
|
||||
@@ -464,7 +464,12 @@ struct dhcp_config {
|
||||
|
||||
struct dhcp_opt {
|
||||
int opt, len, flags;
|
||||
unsigned char *val, *vendor_class;
|
||||
union {
|
||||
int encap;
|
||||
unsigned int wildcard_mask;
|
||||
unsigned char *vendor_class;
|
||||
} u;
|
||||
unsigned char *val;
|
||||
struct dhcp_netid *netid;
|
||||
struct dhcp_opt *next;
|
||||
};
|
||||
@@ -472,9 +477,13 @@ struct dhcp_opt {
|
||||
#define DHOPT_ADDR 1
|
||||
#define DHOPT_STRING 2
|
||||
#define DHOPT_ENCAPSULATE 4
|
||||
#define DHOPT_VENDOR_MATCH 8
|
||||
#define DHOPT_ENCAP_MATCH 8
|
||||
#define DHOPT_FORCE 16
|
||||
#define DHOPT_BANK 32
|
||||
#define DHOPT_ENCAP_DONE 64
|
||||
#define DHOPT_MATCH 128
|
||||
#define DHOPT_VENDOR 256
|
||||
#define DHOPT_HEX 512
|
||||
|
||||
struct dhcp_boot {
|
||||
char *file, *sname;
|
||||
@@ -488,7 +497,6 @@ struct dhcp_boot {
|
||||
#define MATCH_CIRCUIT 3
|
||||
#define MATCH_REMOTE 4
|
||||
#define MATCH_SUBSCRIBER 5
|
||||
#define MATCH_OPTION 6
|
||||
|
||||
/* vendorclass, userclass, remote-id or cicuit-id */
|
||||
struct dhcp_vendor {
|
||||
@@ -608,7 +616,7 @@ extern struct daemon {
|
||||
struct hostsfile *addn_hosts;
|
||||
struct dhcp_context *dhcp;
|
||||
struct dhcp_config *dhcp_conf;
|
||||
struct dhcp_opt *dhcp_opts;
|
||||
struct dhcp_opt *dhcp_opts, *dhcp_match;
|
||||
struct dhcp_vendor *dhcp_vendors;
|
||||
struct dhcp_mac *dhcp_macs;
|
||||
struct dhcp_boot *boot_config;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -93,7 +93,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
/* kill daemon */
|
||||
send_event(event_fd, EVENT_DIE, 0);
|
||||
/* return error */
|
||||
send_event(err_fd, EVENT_HUSER_ERR, errno);;
|
||||
send_event(err_fd, EVENT_HUSER_ERR, errno);
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -366,8 +366,11 @@ struct listener *create_bound_listeners(void)
|
||||
{
|
||||
struct listener *listeners = NULL;
|
||||
struct irec *iface;
|
||||
int opt = 1;
|
||||
|
||||
int rc, opt = 1;
|
||||
#ifdef HAVE_IPV6
|
||||
static int dad_count = 0;
|
||||
#endif
|
||||
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
{
|
||||
struct listener *new = safe_malloc(sizeof(struct listener));
|
||||
@@ -377,6 +380,7 @@ struct listener *create_bound_listeners(void)
|
||||
new->tftpfd = -1;
|
||||
new->tcpfd = -1;
|
||||
new->fd = -1;
|
||||
listeners = new;
|
||||
|
||||
if (daemon->port != 0)
|
||||
{
|
||||
@@ -396,27 +400,34 @@ struct listener *create_bound_listeners(void)
|
||||
die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
|
||||
bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
|
||||
|
||||
while(1)
|
||||
{
|
||||
if ((rc = bind(new->fd, &iface->addr.sa, sa_len(&iface->addr))) != -1)
|
||||
break;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL))
|
||||
/* An interface may have an IPv6 address which is still undergoing DAD.
|
||||
If so, the bind will fail until the DAD completes, so we try over 20 seconds
|
||||
before failing. */
|
||||
if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL) &&
|
||||
dad_count++ < DAD_WAIT)
|
||||
{
|
||||
close(new->tcpfd);
|
||||
close(new->fd);
|
||||
free(new);
|
||||
new = NULL;
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
prettyprint_addr(&iface->addr, daemon->namebuff);
|
||||
die(_("failed to bind listening socket for %s: %s"),
|
||||
daemon->namebuff, EC_BADNET);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (listen(new->tcpfd, 5) == -1)
|
||||
|
||||
if (rc == -1 || bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
|
||||
{
|
||||
prettyprint_addr(&iface->addr, daemon->namebuff);
|
||||
die(_("failed to bind listening socket for %s: %s"),
|
||||
daemon->namebuff, EC_BADNET);
|
||||
}
|
||||
|
||||
if (listen(new->tcpfd, 5) == -1)
|
||||
die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
|
||||
@@ -434,8 +445,6 @@ struct listener *create_bound_listeners(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (new)
|
||||
listeners = new;
|
||||
}
|
||||
|
||||
return listeners;
|
||||
@@ -519,7 +528,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
||||
return 0;
|
||||
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
if (strlen(intname) != 0 &&
|
||||
if (intname[0] != 0 &&
|
||||
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, sizeof(intname)) == -1)
|
||||
return 0;
|
||||
#endif
|
||||
@@ -534,7 +543,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
||||
|
||||
/* when using random ports, servers which would otherwise use
|
||||
the INADDR_ANY/port0 socket have sfd set to NULL */
|
||||
if (!daemon->osport)
|
||||
if (!daemon->osport && intname[0] == 0)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
@@ -620,7 +629,7 @@ void pre_allocate_sfds(void)
|
||||
(daemon->options & OPT_NOWILD))
|
||||
{
|
||||
prettyprint_addr(&srv->addr, daemon->namebuff);
|
||||
if (strlen(srv->interface) != 0)
|
||||
if (srv->interface[0] != 0)
|
||||
{
|
||||
strcat(daemon->namebuff, " ");
|
||||
strcat(daemon->namebuff, srv->interface);
|
||||
@@ -695,7 +704,7 @@ void check_servers(void)
|
||||
else if (!(new->flags & SERV_LITERAL_ADDRESS))
|
||||
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
|
||||
}
|
||||
else if (strlen(new->interface) != 0)
|
||||
else if (new->interface[0] != 0)
|
||||
my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
|
||||
else
|
||||
my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
|
||||
|
||||
158
src/option.c
158
src/option.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* define this to get facilitynames */
|
||||
@@ -310,7 +310,7 @@ static struct {
|
||||
{ LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
|
||||
{ LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
|
||||
{ LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
|
||||
{ LOPT_MATCH, ARG_DUP, "<netid>,<opt-no>", gettext_noop("Set tag if client includes option in request."), NULL },
|
||||
{ LOPT_MATCH, ARG_DUP, "<netid>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
|
||||
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
|
||||
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
|
||||
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
|
||||
@@ -391,6 +391,9 @@ static const struct {
|
||||
{ "user-class", 77, 0 },
|
||||
{ "FQDN", 81, OT_INTERNAL },
|
||||
{ "agent-id", 82, OT_INTERNAL },
|
||||
{ "client-arch", 93, 2 },
|
||||
{ "client-interface-id", 94, 0 },
|
||||
{ "client-machine-id", 97, 0 },
|
||||
{ "subnet-select", 118, OT_INTERNAL },
|
||||
{ "domain-search", 119, 0 },
|
||||
{ "sip-server", 120, 0 },
|
||||
@@ -491,11 +494,12 @@ static char *opt_string_alloc(char *cp)
|
||||
|
||||
/* find next comma, split string with zero and eliminate spaces.
|
||||
return start of string following comma */
|
||||
static char *split(char *s)
|
||||
|
||||
static char *split_chr(char *s, char c)
|
||||
{
|
||||
char *comma, *p;
|
||||
|
||||
if (!s || !(comma = strchr(s, ',')))
|
||||
if (!s || !(comma = strchr(s, c)))
|
||||
return NULL;
|
||||
|
||||
p = comma;
|
||||
@@ -509,6 +513,11 @@ static char *split(char *s)
|
||||
return comma;
|
||||
}
|
||||
|
||||
static char *split(char *s)
|
||||
{
|
||||
return split_chr(s, ',');
|
||||
}
|
||||
|
||||
static int canonicalise_opt(char *s)
|
||||
{
|
||||
if (!s)
|
||||
@@ -642,7 +651,6 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
new->flags = flags;
|
||||
new->netid = NULL;
|
||||
new->val = NULL;
|
||||
new->vendor_class = NULL;
|
||||
new->opt = 0;
|
||||
|
||||
while (arg)
|
||||
@@ -675,7 +683,12 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
}
|
||||
else if (strstr(arg, "vendor:") == arg)
|
||||
{
|
||||
new->vendor_class = (unsigned char *)opt_string_alloc(arg+7);
|
||||
new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
|
||||
new->flags |= DHOPT_VENDOR;
|
||||
}
|
||||
else if (strstr(arg, "encap:") == arg)
|
||||
{
|
||||
new->u.encap = atoi(arg+6);
|
||||
new->flags |= DHOPT_ENCAPSULATE;
|
||||
}
|
||||
else
|
||||
@@ -740,7 +753,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
else
|
||||
is_dec = 0;
|
||||
if (!((c >='A' && c <= 'F') ||
|
||||
(c >='a' && c <= 'f')))
|
||||
(c >='a' && c <= 'f') ||
|
||||
(c == '*' && (flags & DHOPT_MATCH))))
|
||||
is_hex = 0;
|
||||
}
|
||||
|
||||
@@ -757,7 +771,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
{
|
||||
new->len = digs;
|
||||
new->val = opt_malloc(new->len);
|
||||
parse_hex(comma, new->val, digs, NULL, NULL);
|
||||
parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
|
||||
new->flags |= DHOPT_HEX;
|
||||
}
|
||||
else if (is_dec)
|
||||
{
|
||||
@@ -804,8 +819,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
{
|
||||
cp = comma;
|
||||
comma = split(cp);
|
||||
if ((slash = strchr(cp, '/')))
|
||||
*slash++ = 0;
|
||||
slash = split_chr(cp, '/');
|
||||
in.s_addr = inet_addr(cp);
|
||||
if (!slash)
|
||||
{
|
||||
@@ -910,8 +924,23 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
|
||||
if (!problem)
|
||||
{
|
||||
new->next = daemon->dhcp_opts;
|
||||
daemon->dhcp_opts = new;
|
||||
if (flags == DHOPT_MATCH)
|
||||
{
|
||||
if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
|
||||
!new->netid ||
|
||||
new->netid->next)
|
||||
problem = _("illegal dhcp-match");
|
||||
else
|
||||
{
|
||||
new->next = daemon->dhcp_match;
|
||||
daemon->dhcp_match = new;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new->next = daemon->dhcp_opts;
|
||||
daemon->dhcp_opts = new;
|
||||
}
|
||||
}
|
||||
|
||||
return problem;
|
||||
@@ -1149,10 +1178,9 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
{
|
||||
struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
|
||||
unhide_metas(comma);
|
||||
if ((arg = strchr(comma, '/')))
|
||||
if ((arg = split_chr(comma, '/')))
|
||||
{
|
||||
int mask;
|
||||
*arg++ = 0;
|
||||
if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
|
||||
!atoi_check(arg, &mask))
|
||||
option = '?';
|
||||
@@ -1292,10 +1320,9 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
{
|
||||
char *end;
|
||||
arg++;
|
||||
while ((end = strchr(arg, '/')))
|
||||
while ((end = split_chr(arg, '/')))
|
||||
{
|
||||
char *domain = NULL;
|
||||
*end = 0;
|
||||
/* # matches everything and becomes a zero length domain string */
|
||||
if (strcmp(arg, "#") == 0)
|
||||
domain = "";
|
||||
@@ -1309,7 +1336,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
newlist = serv;
|
||||
serv->domain = domain;
|
||||
serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
|
||||
arg = end+1;
|
||||
arg = end;
|
||||
}
|
||||
if (!newlist)
|
||||
{
|
||||
@@ -1342,23 +1369,14 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
int source_port = 0, serv_port = NAMESERVER_PORT;
|
||||
char *portno, *source;
|
||||
|
||||
if ((source = strchr(arg, '@'))) /* is there a source. */
|
||||
{
|
||||
*source = 0;
|
||||
if ((portno = strchr(source+1, '#')))
|
||||
{
|
||||
*portno = 0;
|
||||
if (!atoi_check16(portno+1, &source_port))
|
||||
problem = _("bad port");
|
||||
}
|
||||
}
|
||||
|
||||
if ((portno = strchr(arg, '#'))) /* is there a port no. */
|
||||
{
|
||||
*portno = 0;
|
||||
if (!atoi_check16(portno+1, &serv_port))
|
||||
problem = _("bad port");
|
||||
}
|
||||
if ((source = split_chr(arg, '@')) && /* is there a source. */
|
||||
(portno = split_chr(source, '#')) &&
|
||||
!atoi_check16(portno, &source_port))
|
||||
problem = _("bad port");
|
||||
|
||||
if ((portno = split_chr(arg, '#')) && /* is there a port no. */
|
||||
!atoi_check16(portno, &serv_port))
|
||||
problem = _("bad port");
|
||||
|
||||
if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
|
||||
{
|
||||
@@ -1371,11 +1389,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
if (source)
|
||||
{
|
||||
newlist->flags |= SERV_HAS_SOURCE;
|
||||
if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source+1)) == (in_addr_t) -1)
|
||||
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+1, IF_NAMESIZE);
|
||||
strncpy(newlist->interface, source, IF_NAMESIZE);
|
||||
#else
|
||||
problem = _("interface binding not supported");
|
||||
#endif
|
||||
@@ -1396,11 +1414,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
if (source)
|
||||
{
|
||||
newlist->flags |= SERV_HAS_SOURCE;
|
||||
if (inet_pton(AF_INET6, source+1, &newlist->source_addr.in6.sin6_addr) == 0)
|
||||
if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE) || defined(HAVE_SOLARIS_NETWORK)
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
newlist->source_addr.in6.sin6_addr = in6addr_any;
|
||||
strncpy(newlist->interface, source+1, IF_NAMESIZE);
|
||||
strncpy(newlist->interface, source, IF_NAMESIZE);
|
||||
#else
|
||||
problem = _("interface binding not supported");
|
||||
#endif
|
||||
@@ -1455,7 +1473,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
case LOPT_MINPORT: /* --min-port */
|
||||
if (!atoi_check16(arg, &daemon->min_port))
|
||||
option = '?';
|
||||
option = '?';
|
||||
break;
|
||||
|
||||
case '0': /* --dns-forward-max */
|
||||
@@ -1840,12 +1858,14 @@ option = '?';
|
||||
break;
|
||||
}
|
||||
|
||||
case 'O':
|
||||
case LOPT_FORCE:
|
||||
case 'O': /* --dhcp-option */
|
||||
case LOPT_FORCE: /* --dhcp-option-force */
|
||||
case LOPT_OPTS:
|
||||
case LOPT_MATCH: /* --dhcp-match */
|
||||
problem = parse_dhcp_opt(arg,
|
||||
option == LOPT_FORCE ? DHOPT_FORCE :
|
||||
(option == LOPT_OPTS ? DHOPT_BANK : 0));
|
||||
(option == LOPT_MATCH ? DHOPT_MATCH :
|
||||
(option == LOPT_OPTS ? DHOPT_BANK : 0)));
|
||||
break;
|
||||
|
||||
case 'M': /* --dhcp-boot */
|
||||
@@ -1921,7 +1941,6 @@ option = '?';
|
||||
case LOPT_CIRCUIT: /* --dhcp-circuitid */
|
||||
case LOPT_REMOTE: /* --dhcp-remoteid */
|
||||
case LOPT_SUBSCR: /* --dhcp-subscrid */
|
||||
case LOPT_MATCH: /* --dhcp-match */
|
||||
{
|
||||
if (!(comma = split(arg)))
|
||||
option = '?';
|
||||
@@ -1942,9 +1961,7 @@ option = '?';
|
||||
else if (*p != ':')
|
||||
break;
|
||||
unhide_metas(comma);
|
||||
if (option == LOPT_MATCH)
|
||||
new->option = atoi(comma);
|
||||
else if (option == 'U' || option == 'j' || *p || !dig)
|
||||
if (option == 'U' || option == 'j' || *p || !dig)
|
||||
{
|
||||
new->len = strlen(comma);
|
||||
new->data = opt_malloc(new->len);
|
||||
@@ -1974,9 +1991,6 @@ option = '?';
|
||||
case LOPT_SUBSCR:
|
||||
new->match_type = MATCH_SUBSCRIBER;
|
||||
break;
|
||||
case LOPT_MATCH:
|
||||
new->match_type = MATCH_OPTION;
|
||||
break;
|
||||
}
|
||||
new->next = daemon->dhcp_vendors;
|
||||
daemon->dhcp_vendors = new;
|
||||
@@ -2047,13 +2061,14 @@ option = '?';
|
||||
|
||||
case 'V': /* --alias */
|
||||
{
|
||||
char *a[3] = { NULL, NULL, NULL };
|
||||
char *dash, *a[3] = { NULL, NULL, NULL };
|
||||
int k = 0;
|
||||
struct in_addr in, out, mask;
|
||||
struct doctor *new;
|
||||
|
||||
mask.s_addr = 0xffffffff;
|
||||
|
||||
struct doctor *new = opt_malloc(sizeof(struct doctor));
|
||||
new->next = daemon->doctors;
|
||||
daemon->doctors = new;
|
||||
new->mask.s_addr = 0xffffffff;
|
||||
new->end.s_addr = 0;
|
||||
|
||||
if ((a[0] = arg))
|
||||
for (k = 1; k < 3; k++)
|
||||
{
|
||||
@@ -2062,23 +2077,21 @@ option = '?';
|
||||
unhide_metas(a[k]);
|
||||
}
|
||||
|
||||
dash = split_chr(a[0], '-');
|
||||
|
||||
if ((k < 2) ||
|
||||
((in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
|
||||
((out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
|
||||
{
|
||||
option = '?';
|
||||
break;
|
||||
}
|
||||
((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
|
||||
((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
|
||||
option = '?';
|
||||
|
||||
if (k == 3)
|
||||
mask.s_addr = inet_addr(a[2]);
|
||||
new->mask.s_addr = inet_addr(a[2]);
|
||||
|
||||
new = opt_malloc(sizeof(struct doctor));
|
||||
new->in = in;
|
||||
new->out = out;
|
||||
new->mask = mask;
|
||||
new->next = daemon->doctors;
|
||||
daemon->doctors = new;
|
||||
if (dash &&
|
||||
((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
|
||||
!is_same_net(new->in, new->end, new->mask) ||
|
||||
ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
|
||||
problem = _("invalid alias range");
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2513,7 +2526,8 @@ void reread_dhcp(void)
|
||||
|
||||
if (opts->flags & DHOPT_BANK)
|
||||
{
|
||||
free(opts->vendor_class);
|
||||
if ((opts->flags & DHOPT_VENDOR))
|
||||
free(opts->u.vendor_class);
|
||||
free(opts->val);
|
||||
for (id = opts->netid; id; id = next)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -25,7 +25,7 @@ static int add_resource_record(HEADER *header, char *limit, int *truncp,
|
||||
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
|
||||
|
||||
#define ADD_RDLEN(header, pp, plen, len) \
|
||||
(!CHECK_LEN(header, pp, plen, len) ? 0 : (int)((pp) += (len)), 1)
|
||||
(!CHECK_LEN(header, pp, plen, len) ? 0 : (long)((pp) += (len)), 1)
|
||||
|
||||
static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
char *name, int isExtract, int extrabytes)
|
||||
@@ -551,15 +551,23 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
|
||||
memcpy(&addr, p, INADDRSZ);
|
||||
|
||||
for (doctor = daemon->doctors; doctor; doctor = doctor->next)
|
||||
if (is_same_net(doctor->in, addr, doctor->mask))
|
||||
{
|
||||
addr.s_addr &= ~doctor->mask.s_addr;
|
||||
addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
|
||||
/* Since we munged the data, the server it came from is no longer authoritative */
|
||||
header->aa = 0;
|
||||
memcpy(p, &addr, INADDRSZ);
|
||||
break;
|
||||
}
|
||||
{
|
||||
if (doctor->end.s_addr == 0)
|
||||
{
|
||||
if (!is_same_net(doctor->in, addr, doctor->mask))
|
||||
continue;
|
||||
}
|
||||
else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) ||
|
||||
ntohl(doctor->end.s_addr) < ntohl(addr.s_addr))
|
||||
continue;
|
||||
|
||||
addr.s_addr &= ~doctor->mask.s_addr;
|
||||
addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
|
||||
/* Since we munged the data, the server it came from is no longer authoritative */
|
||||
header->aa = 0;
|
||||
memcpy(p, &addr, INADDRSZ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ADD_RDLEN(header, p, qlen, rdlen))
|
||||
|
||||
282
src/rfc2131.c
282
src/rfc2131.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -72,7 +72,7 @@
|
||||
#define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
|
||||
|
||||
static int sanitise(unsigned char *opt, char *buf);
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override);
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback);
|
||||
static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
|
||||
static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
|
||||
static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
|
||||
@@ -99,7 +99,7 @@ static void do_options(struct dhcp_context *context,
|
||||
unsigned char *agent_id);
|
||||
|
||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
||||
|
||||
static void do_encap_opts(int encap, struct dhcp_packet *mess, unsigned char *end, int null_term);
|
||||
|
||||
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
size_t sz, time_t now, int unicast_dest, int *is_inform)
|
||||
@@ -127,6 +127,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
unsigned char *emac = NULL;
|
||||
int emac_len = 0;
|
||||
struct dhcp_netid known_id, iface_id;
|
||||
struct dhcp_opt *o;
|
||||
|
||||
subnet_addr.s_addr = override.s_addr = 0;
|
||||
|
||||
@@ -574,6 +575,46 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
netid = &config->netid;
|
||||
}
|
||||
|
||||
/* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
|
||||
Otherwise assume the option is an array, and look for a matching element.
|
||||
If no data given, existance of the option is enough. */
|
||||
for (o = daemon->dhcp_match; o; o = o->next)
|
||||
{
|
||||
int i, matched = 0;
|
||||
|
||||
if (!(opt = option_find(mess, sz, o->opt, 1)) ||
|
||||
o->len > option_len(opt))
|
||||
continue;
|
||||
|
||||
if (o->len == 0)
|
||||
matched = 1;
|
||||
else if (o->flags & DHOPT_HEX)
|
||||
{
|
||||
if (memcmp_masked(o->val, option_ptr(opt, 0), o->len, o->u.wildcard_mask))
|
||||
matched = 1;
|
||||
}
|
||||
else
|
||||
for (i = 0; i <= (option_len(opt) - o->len); )
|
||||
{
|
||||
if (memcmp(o->val, option_ptr(opt, i), o->len) == 0)
|
||||
{
|
||||
matched = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (o->flags & DHOPT_STRING)
|
||||
i++;
|
||||
else
|
||||
i += o->len;
|
||||
}
|
||||
|
||||
if (matched)
|
||||
{
|
||||
o->netid->next = netid;
|
||||
netid = o->netid;
|
||||
}
|
||||
}
|
||||
|
||||
/* user-class options are, according to RFC3004, supposed to contain
|
||||
a set of counted strings. Here we check that this is so (by seeing
|
||||
if the counts are consistent with the overall option length) and if
|
||||
@@ -597,7 +638,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
ucp[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
||||
{
|
||||
int mopt;
|
||||
@@ -606,15 +647,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
mopt = OPTION_VENDOR_ID;
|
||||
else if (vendor->match_type == MATCH_USER)
|
||||
mopt = OPTION_USER_CLASS;
|
||||
else if (vendor->match_type == MATCH_OPTION)
|
||||
{
|
||||
if (option_find(mess, sz, vendor->option, 1))
|
||||
{
|
||||
vendor->netid.next = netid;
|
||||
netid = &vendor->netid;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
@@ -662,7 +694,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
{
|
||||
case DHCPDECLINE:
|
||||
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
|
||||
option_addr(opt).s_addr != server_id(context, override).s_addr)
|
||||
option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
|
||||
return 0;
|
||||
|
||||
/* sanitise any message. Paranoid? Moi? */
|
||||
@@ -695,7 +727,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
case DHCPRELEASE:
|
||||
if (!(context = narrow_context(context, mess->ciaddr, netid)) ||
|
||||
!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
|
||||
option_addr(opt).s_addr != server_id(context, override).s_addr)
|
||||
option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
|
||||
return 0;
|
||||
|
||||
if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
|
||||
@@ -781,7 +813,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override).s_addr));
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
|
||||
if (time != 0xffffffff)
|
||||
@@ -950,8 +982,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
mess->yiaddr.s_addr = 0;
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ,
|
||||
ntohl(server_id(context, override).s_addr ? server_id(context, override).s_addr : fallback.s_addr));
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||
option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
|
||||
/* DHCPNAK gets agent-id too */
|
||||
restore_agent_id(agent_id, mess, end);
|
||||
@@ -1038,7 +1069,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override).s_addr));
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||
if (time != 0xffffffff)
|
||||
{
|
||||
@@ -1059,9 +1090,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
log_packet("INFORM", &mess->ciaddr, emac, emac_len, iface_name, message);
|
||||
|
||||
if (message || mess->ciaddr.s_addr == 0 ||
|
||||
!(context = narrow_context(context, mess->ciaddr, netid)))
|
||||
if (message || mess->ciaddr.s_addr == 0)
|
||||
return 0;
|
||||
|
||||
/* For DHCPINFORM only, cope without a valid context */
|
||||
context = narrow_context(context, mess->ciaddr, netid);
|
||||
|
||||
/* Find a least based on IP address if we didn't
|
||||
get one from MAC address/client-d */
|
||||
@@ -1075,7 +1108,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
log_packet("ACK", &mess->ciaddr, emac, emac_len, iface_name, hostname);
|
||||
|
||||
if (context->netid.net)
|
||||
if (context && context->netid.net)
|
||||
{
|
||||
context->netid.next = netid;
|
||||
netid = &context->netid;
|
||||
@@ -1091,8 +1124,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override).s_addr));
|
||||
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||
|
||||
if (lease)
|
||||
{
|
||||
if (lease->expires == 0)
|
||||
@@ -1164,12 +1197,14 @@ static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *
|
||||
return time;
|
||||
}
|
||||
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override)
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
|
||||
{
|
||||
if (override.s_addr != 0 || !context)
|
||||
if (override.s_addr != 0)
|
||||
return override;
|
||||
else
|
||||
else if (context)
|
||||
return context->local;
|
||||
else
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static int sanitise(unsigned char *opt, char *buf)
|
||||
@@ -1476,7 +1511,7 @@ static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int
|
||||
}
|
||||
|
||||
/* return length, note this only does the data part */
|
||||
static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct in_addr local, int null_term)
|
||||
static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
|
||||
{
|
||||
int len = opt->len;
|
||||
|
||||
@@ -1485,7 +1520,7 @@ static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct in_addr local,
|
||||
|
||||
if (p && len != 0)
|
||||
{
|
||||
if ((opt->flags & DHOPT_ADDR) && !(opt->flags & DHOPT_ENCAPSULATE))
|
||||
if (context && (opt->flags & DHOPT_ADDR))
|
||||
{
|
||||
int j;
|
||||
struct in_addr *a = (struct in_addr *)opt->val;
|
||||
@@ -1493,7 +1528,7 @@ static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct in_addr local,
|
||||
{
|
||||
/* zero means "self" (but not in vendorclass options.) */
|
||||
if (a->s_addr == 0)
|
||||
memcpy(p, &local, INADDRSZ);
|
||||
memcpy(p, &context->local, INADDRSZ);
|
||||
else
|
||||
memcpy(p, a, INADDRSZ);
|
||||
p += INADDRSZ;
|
||||
@@ -1524,7 +1559,7 @@ static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *
|
||||
{
|
||||
struct dhcp_opt *tmp;
|
||||
for (tmp = opts; tmp; tmp = tmp->next)
|
||||
if (tmp->opt == opt && !(tmp->flags & DHOPT_ENCAPSULATE))
|
||||
if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)))
|
||||
if (match_netid(tmp->netid, netid, 1) || match_netid(tmp->netid, netid, 0))
|
||||
return tmp;
|
||||
|
||||
@@ -1537,22 +1572,66 @@ static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
|
||||
{
|
||||
for (; dopt; dopt = dopt->next)
|
||||
{
|
||||
dopt->flags &= ~DHOPT_VENDOR_MATCH;
|
||||
if (opt && (dopt->flags & DHOPT_ENCAPSULATE))
|
||||
dopt->flags &= ~(DHOPT_ENCAP_MATCH | DHOPT_ENCAP_DONE);
|
||||
if (opt && (dopt->flags & DHOPT_VENDOR))
|
||||
{
|
||||
int i, len = 0;
|
||||
if (dopt->vendor_class)
|
||||
len = strlen((char *)dopt->vendor_class);
|
||||
if (dopt->u.vendor_class)
|
||||
len = strlen((char *)dopt->u.vendor_class);
|
||||
for (i = 0; i <= (option_len(opt) - len); i++)
|
||||
if (len == 0 || memcmp(dopt->vendor_class, option_ptr(opt, i), len) == 0)
|
||||
if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0)
|
||||
{
|
||||
dopt->flags |= DHOPT_VENDOR_MATCH;
|
||||
dopt->flags |= DHOPT_ENCAP_MATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void do_encap_opts(int encap, struct dhcp_packet *mess, unsigned char *end, int null_term)
|
||||
{
|
||||
int len, enc_len;
|
||||
struct dhcp_opt *opt, *start;
|
||||
unsigned char *p;
|
||||
|
||||
/* find size in advance */
|
||||
for (enc_len = 0, start = opt = daemon->dhcp_opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_ENCAP_MATCH)
|
||||
{
|
||||
int new = do_opt(opt, NULL, NULL, null_term) + 2;
|
||||
if (enc_len + new <= 255)
|
||||
enc_len += new;
|
||||
else
|
||||
{
|
||||
p = free_space(mess, end, encap, enc_len);
|
||||
for (; start && start != opt; start = start->next)
|
||||
if (p && (start->flags & DHOPT_ENCAP_MATCH))
|
||||
{
|
||||
len = do_opt(start, p + 2, NULL, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
enc_len = new;
|
||||
start = opt;
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_len != 0 &&
|
||||
(p = free_space(mess, end, encap, enc_len + 1)))
|
||||
{
|
||||
for (; start; start = start->next)
|
||||
if (start->flags & DHOPT_ENCAP_MATCH)
|
||||
{
|
||||
len = do_opt(start, p + 2, NULL, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
*p = OPTION_END;
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end, unsigned char *agent_id)
|
||||
{
|
||||
/* don't clear agent_id */
|
||||
@@ -1629,7 +1708,8 @@ static void do_options(struct dhcp_context *context,
|
||||
if (match_netid(boot->netid, netid, 1))
|
||||
break;
|
||||
|
||||
mess->siaddr = context->local;
|
||||
if (context)
|
||||
mess->siaddr = context->local;
|
||||
|
||||
/* See if we can send the boot stuff as options.
|
||||
To do this we need a requested option list, BOOTP
|
||||
@@ -1713,27 +1793,31 @@ static void do_options(struct dhcp_context *context,
|
||||
/* rfc3011 says this doesn't need to be in the requested options list. */
|
||||
if (subnet_addr.s_addr)
|
||||
option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
|
||||
|
||||
/* replies to DHCPINFORM may not have a valid context */
|
||||
if (context)
|
||||
{
|
||||
if (!option_find2(netid, config_opts, OPTION_NETMASK))
|
||||
option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
|
||||
|
||||
/* May not have a "guessed" broadcast address if we got no packets via a relay
|
||||
from this net yet (ie just unicast renewals after a restart */
|
||||
if (context->broadcast.s_addr &&
|
||||
!option_find2(netid, config_opts, OPTION_BROADCAST))
|
||||
option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
|
||||
|
||||
/* Same comments as broadcast apply, and also may not be able to get a sensible
|
||||
default when using subnet select. User must configure by steam in that case. */
|
||||
if (context->router.s_addr &&
|
||||
in_list(req_options, OPTION_ROUTER) &&
|
||||
!option_find2(netid, config_opts, OPTION_ROUTER))
|
||||
option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
|
||||
|
||||
if (in_list(req_options, OPTION_DNSSERVER) &&
|
||||
!option_find2(netid, config_opts, OPTION_DNSSERVER))
|
||||
option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
}
|
||||
|
||||
if (!option_find2(netid, config_opts, OPTION_NETMASK))
|
||||
option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
|
||||
|
||||
/* May not have a "guessed" broadcast address if we got no packets via a relay
|
||||
from this net yet (ie just unicast renewals after a restart */
|
||||
if (context->broadcast.s_addr &&
|
||||
!option_find2(netid, config_opts, OPTION_BROADCAST))
|
||||
option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
|
||||
|
||||
/* Same comments as broadcast apply, and also may not be able to get a sensible
|
||||
default when using subnet select. User must configure by steam in that case. */
|
||||
if (context->router.s_addr &&
|
||||
in_list(req_options, OPTION_ROUTER) &&
|
||||
!option_find2(netid, config_opts, OPTION_ROUTER))
|
||||
option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
|
||||
|
||||
if (in_list(req_options, OPTION_DNSSERVER) &&
|
||||
!option_find2(netid, config_opts, OPTION_DNSSERVER))
|
||||
option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
|
||||
if (domain && in_list(req_options, OPTION_DOMAINNAME) &&
|
||||
!option_find2(netid, config_opts, OPTION_DOMAINNAME))
|
||||
option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
|
||||
@@ -1747,7 +1831,8 @@ static void do_options(struct dhcp_context *context,
|
||||
|
||||
if (fqdn_flags != 0)
|
||||
{
|
||||
int len = strlen(hostname) + 3;
|
||||
len = strlen(hostname) + 3;
|
||||
|
||||
if (fqdn_flags & 0x04)
|
||||
len += 2;
|
||||
else if (null_term)
|
||||
@@ -1825,12 +1910,12 @@ static void do_options(struct dhcp_context *context,
|
||||
continue;
|
||||
|
||||
/* always force null-term for filename ans servername - buggy PXE again. */
|
||||
len = do_opt(opt, NULL, context->local,
|
||||
len = do_opt(opt, NULL, context,
|
||||
(optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
|
||||
|
||||
if ((p = free_space(mess, end, optno, len)))
|
||||
{
|
||||
do_opt(opt, p, context->local,
|
||||
do_opt(opt, p, context,
|
||||
(optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
|
||||
|
||||
/* If we send a vendor-id, revisit which vendor-ops we consider
|
||||
@@ -1840,59 +1925,48 @@ static void do_options(struct dhcp_context *context,
|
||||
}
|
||||
}
|
||||
|
||||
/* prune encapsulated options based on netid, and look if we're forcing them to be sent */
|
||||
/* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
|
||||
for (opt = config_opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_VENDOR_MATCH)
|
||||
if (opt->flags & DHOPT_ENCAP_MATCH)
|
||||
{
|
||||
if (!match_netid(opt->netid, netid, 1) && !match_netid(opt->netid, netid, 0))
|
||||
opt->flags &= ~DHOPT_VENDOR_MATCH;
|
||||
opt->flags &= ~DHOPT_ENCAP_MATCH;
|
||||
else if (opt->flags & DHOPT_FORCE)
|
||||
force_encap = 1;
|
||||
}
|
||||
|
||||
if (force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT))
|
||||
{
|
||||
int enc_len = 0;
|
||||
struct dhcp_opt *start;
|
||||
|
||||
/* find size in advance */
|
||||
for (start = opt = config_opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_VENDOR_MATCH)
|
||||
do_encap_opts(OPTION_VENDOR_CLASS_OPT, mess, end, null_term);
|
||||
|
||||
/* Now send options to be encapsulated in arbitrary options,
|
||||
eg dhcp-option=encap:172,17,.......
|
||||
The may be more that one "outer" to do, so group
|
||||
all the options which match each outer in turn. */
|
||||
for (opt = config_opts; opt; opt = opt->next)
|
||||
if ((opt->flags & (DHOPT_ENCAPSULATE | DHOPT_ENCAP_DONE)) == DHOPT_ENCAPSULATE)
|
||||
{
|
||||
struct dhcp_opt *o;
|
||||
int found = 0;
|
||||
|
||||
for (o = config_opts; o; o = o->next)
|
||||
{
|
||||
int new = do_opt(opt, NULL, context->local, null_term) + 2;
|
||||
if (enc_len + new <= 255)
|
||||
enc_len += new;
|
||||
else
|
||||
o->flags &= ~DHOPT_ENCAP_MATCH;
|
||||
if ((o->flags & DHOPT_ENCAPSULATE) && opt->u.encap == o->u.encap)
|
||||
{
|
||||
p = free_space(mess, end, OPTION_VENDOR_CLASS_OPT, enc_len);
|
||||
for (; start && start != opt; start = start->next)
|
||||
if (p && (start->flags & DHOPT_VENDOR_MATCH))
|
||||
{
|
||||
len = do_opt(start, p + 2, context->local, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
enc_len = new;
|
||||
start = opt;
|
||||
o->flags |= DHOPT_ENCAP_DONE;
|
||||
if ((match_netid(o->netid, netid, 1) || match_netid(o->netid, netid, 0)) &&
|
||||
(o->flags & DHOPT_FORCE || in_list(req_options, o->u.encap)))
|
||||
{
|
||||
o->flags |= DHOPT_ENCAP_MATCH;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_len != 0 &&
|
||||
(p = free_space(mess, end, OPTION_VENDOR_CLASS_OPT, enc_len + 1)))
|
||||
{
|
||||
for (; start; start = start->next)
|
||||
if (start->flags & DHOPT_VENDOR_MATCH)
|
||||
{
|
||||
len = do_opt(start, p + 2, context->local, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
*p = OPTION_END;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (found)
|
||||
do_encap_opts(opt->u.encap, mess, end, null_term);
|
||||
}
|
||||
|
||||
/* move agent_id back down to the end of the packet */
|
||||
restore_agent_id(agent_id, mess, real_end);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
10
src/util.c
10
src/util.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -9,13 +9,11 @@
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Some code in this file contributed by Rob Funk. */
|
||||
|
||||
/* The SURF random number generator was taken from djbdns-1.05, by
|
||||
Daniel J Berstein, which is public domain. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user