mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.22.tar.gz
This commit is contained in:
22
CHANGELOG
22
CHANGELOG
@@ -1422,3 +1422,25 @@ version 2.21
|
|||||||
Added wildcard matching for MAC addresses in dhcp-host
|
Added wildcard matching for MAC addresses in dhcp-host
|
||||||
options. A sensible suggestion by Nathaniel McCallum.
|
options. A sensible suggestion by Nathaniel McCallum.
|
||||||
|
|
||||||
|
version 2.22
|
||||||
|
Fixed build problems on (many) systems with older libc
|
||||||
|
headers where <linux/types.h> is required before
|
||||||
|
<linux/netlink.h>. Enabled HAVE_RTNETLINK under uclibc now
|
||||||
|
that this fix is in place.
|
||||||
|
|
||||||
|
Added support for encapsulated vendor-class-specific DHCP
|
||||||
|
options. Thanks to Eric Shattow for help with this.
|
||||||
|
|
||||||
|
Fix regression in 2.21 which broke commas in filenames and
|
||||||
|
corrupted argv. Thanks to Eric Scott for the bugreport.
|
||||||
|
|
||||||
|
Fixed stupid thinko which caused dnsmasq to wedge during
|
||||||
|
startup with certain MX-record options. Another 2.21 regression.
|
||||||
|
|
||||||
|
Fixed broken-ness when reading /etc/ethers. 2.21 broke
|
||||||
|
this too.
|
||||||
|
|
||||||
|
Fixed wedge with certain DHCP options. Yet another 2.21
|
||||||
|
regression. Rob Holland and Roy Marples chased this one
|
||||||
|
down.
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.21
|
Version: 2.22
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.21
|
Version: 2.22
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: Productivity/Networking/DNS/Servers
|
Group: Productivity/Networking/DNS/Servers
|
||||||
|
|||||||
17
dnsmasq.8
17
dnsmasq.8
@@ -408,7 +408,7 @@ have exactly the same effect as
|
|||||||
.B --dhcp-host
|
.B --dhcp-host
|
||||||
options containing the same information.
|
options containing the same information.
|
||||||
.TP
|
.TP
|
||||||
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]]<opt>,[<value>[,<value>]]
|
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]][vendor:<vendor-class>]<opt>,[<value>[,<value>]]
|
||||||
Specfify different or extra options to DHCP clients. By default,
|
Specfify different or extra options to DHCP clients. By default,
|
||||||
dnsmasq sends some standard options to DHCP clients, the netmask and
|
dnsmasq sends some standard options to DHCP clients, the netmask and
|
||||||
broadcast address are set to the same as the host running dnsmasq, and
|
broadcast address are set to the same as the host running dnsmasq, and
|
||||||
@@ -426,10 +426,23 @@ machine running dnsmasq". Data types allowed are comma separated
|
|||||||
dotted-quad IP addresses, a decimal number, colon-separated hex digits
|
dotted-quad IP addresses, a decimal number, colon-separated hex digits
|
||||||
and a text string. If the optional network-ids are given then
|
and a text string. If the optional network-ids are given then
|
||||||
this option is only sent when all the network-ids are matched.
|
this option is only sent when all the network-ids are matched.
|
||||||
|
|
||||||
Be careful: no checking is done that the correct type of data for the
|
Be careful: no checking is done that the correct type of data for the
|
||||||
option number is sent, it is quite possible to
|
option number is sent, it is quite possible to
|
||||||
persuade dnsmasq to generate illegal DHCP packets with injudicious use
|
persuade dnsmasq to generate illegal DHCP packets with injudicious use
|
||||||
of this flag.
|
of this flag. When the value is a decimal number, dnsmasq must determine how
|
||||||
|
large the data item is. It does this by examining the option number and/or the
|
||||||
|
value, but can be overriden by appending a single letter flag as follows:
|
||||||
|
b = one byte, s = two bytes, i = four bytes. This is mainly useful with
|
||||||
|
encapsulated vendor class options (see below) where dnsmasq cannot determine data size from the option number.
|
||||||
|
|
||||||
|
Encapsulated Vendor-class options may also be specified using
|
||||||
|
--dhcp-option: for instance
|
||||||
|
.B --dhcp-option=vendor:PXEClient,1,0.0.0.0
|
||||||
|
sends the vendor class "PXEClient" and the encapsulated vendor class-specific option "mftp-address=0.0.0.0" Only one vendor class is allowed for any
|
||||||
|
host, but multiple options are allowed, provided they all have
|
||||||
|
the same vendor class. The address 0.0.0.0 is not treated specially in
|
||||||
|
encapsulated vendor class options.
|
||||||
.TP
|
.TP
|
||||||
.B \-U, --dhcp-vendorclass=<network-id>,<vendor-class>
|
.B \-U, --dhcp-vendorclass=<network-id>,<vendor-class>
|
||||||
Map from a vendor-class string to a network id. Most DHCP clients provide a
|
Map from a vendor-class string to a network id. Most DHCP clients provide a
|
||||||
|
|||||||
@@ -239,6 +239,13 @@ bogus-priv
|
|||||||
# probably doesn't support this......
|
# probably doesn't support this......
|
||||||
#dhcp-option=119,eng.apple.com,marketing.apple.com
|
#dhcp-option=119,eng.apple.com,marketing.apple.com
|
||||||
|
|
||||||
|
# Send encapsulated vendor-class specific options. The vendor-class
|
||||||
|
# is sent as DHCP option 60, and all the options marked with the
|
||||||
|
# vendor class are send encapsulated in DHCP option 43. The meaning of
|
||||||
|
# the options is defined by the vendor-class. This example sets the
|
||||||
|
# mtftp address to 0.0.0.0 for PXEClients
|
||||||
|
#dhcp-option=vendor:PXEClient,1,0.0.0.0
|
||||||
|
|
||||||
# Set the boot filename and tftpd server name and address
|
# Set the boot filename and tftpd server name and address
|
||||||
# for BOOTP. You will only need this is you want to
|
# for BOOTP. You will only need this is you want to
|
||||||
# boot machines over the network.
|
# boot machines over the network.
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#define IP6INTERFACES "/proc/net/if_inet6"
|
#define IP6INTERFACES "/proc/net/if_inet6"
|
||||||
#define UPTIME "/proc/uptime"
|
#define UPTIME "/proc/uptime"
|
||||||
#define DHCP_SERVER_PORT 67
|
#define DHCP_SERVER_PORT 67
|
||||||
@@ -187,7 +187,7 @@
|
@@ -195,7 +195,7 @@
|
||||||
|
|
||||||
/* platform independent options. */
|
/* platform independent options. */
|
||||||
#undef HAVE_BROKEN_RTC
|
#undef HAVE_BROKEN_RTC
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
/* Author's email: simon@thekelleys.org.uk */
|
/* Author's email: simon@thekelleys.org.uk */
|
||||||
|
|
||||||
#define VERSION "2.21"
|
#define VERSION "2.22"
|
||||||
|
|
||||||
#define FTABSIZ 150 /* max number of outstanding requests */
|
#define FTABSIZ 150 /* max number of outstanding requests */
|
||||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||||
@@ -207,7 +207,7 @@ NOTES:
|
|||||||
#if defined(__uClinux__) || defined(__UCLIBC__)
|
#if defined(__uClinux__) || defined(__UCLIBC__)
|
||||||
#undef HAVE_LINUX_IPV6_PROC
|
#undef HAVE_LINUX_IPV6_PROC
|
||||||
#define HAVE_GETOPT_LONG
|
#define HAVE_GETOPT_LONG
|
||||||
#undef HAVE_RTNETLINK /* headers broken */
|
#define HAVE_RTNETLINK
|
||||||
#undef HAVE_ARC4RANDOM
|
#undef HAVE_ARC4RANDOM
|
||||||
#define HAVE_RANDOM
|
#define HAVE_RANDOM
|
||||||
#define HAVE_DEV_URANDOM
|
#define HAVE_DEV_URANDOM
|
||||||
|
|||||||
@@ -206,8 +206,9 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* unlinked contexts are marked by context->current == context */
|
||||||
for (context = daemon->dhcp; context; context = context->next)
|
for (context = daemon->dhcp; context; context = context->next)
|
||||||
context->current = NULL;
|
context->current = context;
|
||||||
|
|
||||||
#ifdef HAVE_RTNETLINK
|
#ifdef HAVE_RTNETLINK
|
||||||
if (!netlink_process(daemon, iface_index, mess->giaddr, iface_addr, &context))
|
if (!netlink_process(daemon, iface_index, mess->giaddr, iface_addr, &context))
|
||||||
@@ -381,7 +382,8 @@ struct dhcp_context *complete_context(struct daemon *daemon, struct in_addr loca
|
|||||||
if (is_same_net(local, context->start, context->netmask) &&
|
if (is_same_net(local, context->start, context->netmask) &&
|
||||||
is_same_net(local, context->end, context->netmask))
|
is_same_net(local, context->end, context->netmask))
|
||||||
{
|
{
|
||||||
if (!context->current)
|
/* link it onto the current chain if we've not seen it before */
|
||||||
|
if (context->current == context)
|
||||||
{
|
{
|
||||||
context->router = local;
|
context->router = local;
|
||||||
context->local = local;
|
context->local = local;
|
||||||
@@ -684,6 +686,7 @@ void dhcp_read_ethers(struct daemon *daemon)
|
|||||||
{
|
{
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if ((config->flags & CONFIG_HWADDR) &&
|
if ((config->flags & CONFIG_HWADDR) &&
|
||||||
|
config->wildcard_mask == 0 &&
|
||||||
memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
|
memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -692,6 +695,7 @@ void dhcp_read_ethers(struct daemon *daemon)
|
|||||||
if (!(config = malloc(sizeof(struct dhcp_config))))
|
if (!(config = malloc(sizeof(struct dhcp_config))))
|
||||||
continue;
|
continue;
|
||||||
config->flags = 0;
|
config->flags = 0;
|
||||||
|
config->wildcard_mask = 0;
|
||||||
config->next = configs;
|
config->next = configs;
|
||||||
configs = config;
|
configs = config;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ struct dhcp_config {
|
|||||||
|
|
||||||
struct dhcp_opt {
|
struct dhcp_opt {
|
||||||
int opt, len, is_addr;
|
int opt, len, is_addr;
|
||||||
unsigned char *val;
|
unsigned char *val, *vendor_class;
|
||||||
struct dhcp_netid *netid;
|
struct dhcp_netid *netid;
|
||||||
struct dhcp_opt *next;
|
struct dhcp_opt *next;
|
||||||
};
|
};
|
||||||
@@ -403,7 +403,7 @@ struct daemon {
|
|||||||
struct hostsfile *addn_hosts;
|
struct hostsfile *addn_hosts;
|
||||||
struct dhcp_context *dhcp;
|
struct dhcp_context *dhcp;
|
||||||
struct dhcp_config *dhcp_conf;
|
struct dhcp_config *dhcp_conf;
|
||||||
struct dhcp_opt *dhcp_opts;
|
struct dhcp_opt *dhcp_opts, *vendor_opts;
|
||||||
struct dhcp_vendor *dhcp_vendors;
|
struct dhcp_vendor *dhcp_vendors;
|
||||||
struct dhcp_boot *boot_config;
|
struct dhcp_boot *boot_config;
|
||||||
struct dhcp_netid_list *dhcp_ignore;
|
struct dhcp_netid_list *dhcp_ignore;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_RTNETLINK
|
#ifdef HAVE_RTNETLINK
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
|||||||
358
src/option.c
358
src/option.c
@@ -187,13 +187,26 @@ static void add_txt(struct daemon *daemon, char *name, char *txt)
|
|||||||
memcpy((r->txt)+1, txt, len);
|
memcpy((r->txt)+1, txt, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* filenames are OK with unquoted commas, restore them here. */
|
||||||
|
static char *safe_filename_alloc(char *filename)
|
||||||
|
{
|
||||||
|
char *p, *ret = safe_string_alloc(filename);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
for (p = ret; *p; p++)
|
||||||
|
if (*p == '\001')
|
||||||
|
*p = ',';
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
struct daemon *read_opts (int argc, char **argv)
|
struct daemon *read_opts (int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct daemon *daemon = safe_malloc(sizeof(struct daemon));
|
struct daemon *daemon = safe_malloc(sizeof(struct daemon));
|
||||||
char *problem = NULL, *buff = safe_malloc(MAXDNAME);
|
char *problem = NULL, *buff = safe_malloc(MAXDNAME);
|
||||||
int option = 0, i;
|
int option = 0, i;
|
||||||
FILE *file_save = NULL, *f = NULL;
|
FILE *file_save = NULL, *f = NULL;
|
||||||
char *p, *comma, *file_name_save = NULL, *conffile = CONFFILE;
|
char *p, *arg, *comma, *file_name_save = NULL, *conffile = CONFFILE;
|
||||||
int hosts_index = 1, conffile_set = 0;
|
int hosts_index = 1, conffile_set = 0;
|
||||||
int line_save = 0, lineno = 0;
|
int line_save = 0, lineno = 0;
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
@@ -229,10 +242,18 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
#else
|
#else
|
||||||
option = getopt(argc, argv, OPTSTRING);
|
option = getopt(argc, argv, OPTSTRING);
|
||||||
#endif
|
#endif
|
||||||
|
/* Copy optarg so that argv doesn't get changed */
|
||||||
if (optarg)
|
if (optarg)
|
||||||
for (p = optarg; *p; p++)
|
{
|
||||||
if (*p == ',')
|
strncpy(buff, optarg, MAXDNAME);
|
||||||
*p = '\001';
|
buff[MAXDNAME-1] = 0;
|
||||||
|
arg = buff;
|
||||||
|
for (p = arg; *p; p++)
|
||||||
|
if (*p == ',')
|
||||||
|
*p = '\001';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
arg = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* f non-NULL, reading from conffile. */
|
{ /* f non-NULL, reading from conffile. */
|
||||||
@@ -298,11 +319,11 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
continue;
|
continue;
|
||||||
if ((p=strchr(buff, '=')))
|
if ((p=strchr(buff, '=')))
|
||||||
{
|
{
|
||||||
optarg = p+1;
|
arg = p+1;
|
||||||
*p = 0;
|
*p = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
optarg = NULL;
|
arg = NULL;
|
||||||
|
|
||||||
option = 0;
|
option = 0;
|
||||||
for (i=0; opts[i].name; i++)
|
for (i=0; opts[i].name; i++)
|
||||||
@@ -351,14 +372,14 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
daemon->options |= optmap[i].flag;
|
daemon->options |= optmap[i].flag;
|
||||||
option = 0;
|
option = 0;
|
||||||
if (f && optarg)
|
if (f && arg)
|
||||||
complain("extraneous parameter", lineno, conffile);
|
complain("extraneous parameter", lineno, conffile);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option && option != '?')
|
if (option && option != '?')
|
||||||
{
|
{
|
||||||
if (f && !optarg)
|
if (f && !arg)
|
||||||
{
|
{
|
||||||
complain("missing parameter", lineno, conffile);
|
complain("missing parameter", lineno, conffile);
|
||||||
continue;
|
continue;
|
||||||
@@ -369,7 +390,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
case 'C':
|
case 'C':
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
conffile = safe_string_alloc(optarg);
|
conffile = safe_filename_alloc(arg);
|
||||||
conffile_set = 1;
|
conffile_set = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -383,19 +404,20 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
file_name_save = conffile;
|
file_name_save = conffile;
|
||||||
file_save = f;
|
file_save = f;
|
||||||
line_save = lineno;
|
line_save = lineno;
|
||||||
conffile = safe_string_alloc(optarg);
|
conffile = safe_filename_alloc(arg);
|
||||||
conffile_set = 1;
|
conffile_set = 1;
|
||||||
lineno = 0;
|
lineno = 0;
|
||||||
goto fileopen;
|
goto fileopen;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
daemon->runfile = safe_string_alloc(optarg);
|
daemon->runfile = safe_filename_alloc(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
{
|
{
|
||||||
char *name = safe_string_alloc(optarg);
|
char *name = safe_filename_alloc(arg);
|
||||||
struct resolvc *new, *list = daemon->resolv_files;
|
struct resolvc *new, *list = daemon->resolv_files;
|
||||||
|
|
||||||
if (list && list->is_default)
|
if (list && list->is_default)
|
||||||
{
|
{
|
||||||
/* replace default resolv file - possibly with nothing */
|
/* replace default resolv file - possibly with nothing */
|
||||||
@@ -425,7 +447,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
int pref = 1;
|
int pref = 1;
|
||||||
struct mx_srv_record *new;
|
struct mx_srv_record *new;
|
||||||
|
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
{
|
{
|
||||||
char *prefstr;
|
char *prefstr;
|
||||||
*(comma++) = 0;
|
*(comma++) = 0;
|
||||||
@@ -441,7 +463,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!canonicalise(optarg) || (comma && !canonicalise(comma)))
|
if (!canonicalise(arg) || (comma && !canonicalise(comma)))
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "bad MX name";
|
problem = "bad MX name";
|
||||||
@@ -452,30 +474,30 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
new->next = daemon->mxnames;
|
new->next = daemon->mxnames;
|
||||||
daemon->mxnames = new;
|
daemon->mxnames = new;
|
||||||
new->issrv = 0;
|
new->issrv = 0;
|
||||||
new->name = safe_string_alloc(optarg);
|
new->name = safe_string_alloc(arg);
|
||||||
new->target = safe_string_alloc(comma); /* may be NULL */
|
new->target = safe_string_alloc(comma); /* may be NULL */
|
||||||
new->weight = pref;
|
new->weight = pref;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
if (!canonicalise(optarg))
|
if (!canonicalise(arg))
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "bad MX target";
|
problem = "bad MX target";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
daemon->mxtarget = safe_string_alloc(optarg);
|
daemon->mxtarget = safe_string_alloc(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
daemon->lease_file = safe_string_alloc(optarg);
|
daemon->lease_file = safe_filename_alloc(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'H':
|
case 'H':
|
||||||
{
|
{
|
||||||
struct hostsfile *new = safe_malloc(sizeof(struct hostsfile));
|
struct hostsfile *new = safe_malloc(sizeof(struct hostsfile));
|
||||||
new->fname = safe_string_alloc(optarg);
|
new->fname = safe_filename_alloc(arg);
|
||||||
new->index = hosts_index++;
|
new->index = hosts_index++;
|
||||||
new->next = daemon->addn_hosts;
|
new->next = daemon->addn_hosts;
|
||||||
daemon->addn_hosts = new;
|
daemon->addn_hosts = new;
|
||||||
@@ -483,57 +505,57 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
if (strcmp (optarg, "#") == 0)
|
if (strcmp (arg, "#") == 0)
|
||||||
daemon->options |= OPT_RESOLV_DOMAIN;
|
daemon->options |= OPT_RESOLV_DOMAIN;
|
||||||
else if (!canonicalise(optarg))
|
else if (!canonicalise(arg))
|
||||||
option = '?';
|
option = '?';
|
||||||
else
|
else
|
||||||
daemon->domain_suffix = safe_string_alloc(optarg);
|
daemon->domain_suffix = safe_string_alloc(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
daemon->username = safe_string_alloc(optarg);
|
daemon->username = safe_string_alloc(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
daemon->groupname = safe_string_alloc(optarg);
|
daemon->groupname = safe_string_alloc(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
do {
|
do {
|
||||||
struct iname *new = safe_malloc(sizeof(struct iname));
|
struct iname *new = safe_malloc(sizeof(struct iname));
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
new->next = daemon->if_names;
|
new->next = daemon->if_names;
|
||||||
daemon->if_names = new;
|
daemon->if_names = new;
|
||||||
/* new->name may be NULL if someone does
|
/* new->name may be NULL if someone does
|
||||||
"interface=" to disable all interfaces except loop. */
|
"interface=" to disable all interfaces except loop. */
|
||||||
new->name = safe_string_alloc(optarg);
|
new->name = safe_string_alloc(arg);
|
||||||
new->isloop = new->used = 0;
|
new->isloop = new->used = 0;
|
||||||
if (strchr(optarg, ':'))
|
if (strchr(arg, ':'))
|
||||||
daemon->options |= OPT_NOWILD;
|
daemon->options |= OPT_NOWILD;
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
} while (optarg);
|
} while (arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
do {
|
do {
|
||||||
struct iname *new = safe_malloc(sizeof(struct iname));
|
struct iname *new = safe_malloc(sizeof(struct iname));
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
new->next = daemon->if_except;
|
new->next = daemon->if_except;
|
||||||
daemon->if_except = new;
|
daemon->if_except = new;
|
||||||
new->name = safe_string_alloc(optarg);
|
new->name = safe_string_alloc(arg);
|
||||||
if (strchr(optarg, ':'))
|
if (strchr(arg, ':'))
|
||||||
daemon->options |= OPT_NOWILD;
|
daemon->options |= OPT_NOWILD;
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
} while (optarg);
|
} while (arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'B':
|
case 'B':
|
||||||
{
|
{
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
if ((addr.s_addr = inet_addr(optarg)) != (in_addr_t)-1)
|
if ((addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
|
||||||
{
|
{
|
||||||
struct bogus_addr *baddr = safe_malloc(sizeof(struct bogus_addr));
|
struct bogus_addr *baddr = safe_malloc(sizeof(struct bogus_addr));
|
||||||
baddr->next = daemon->bogus_addr;
|
baddr->next = daemon->bogus_addr;
|
||||||
@@ -548,18 +570,18 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
case 'a':
|
case 'a':
|
||||||
do {
|
do {
|
||||||
struct iname *new = safe_malloc(sizeof(struct iname));
|
struct iname *new = safe_malloc(sizeof(struct iname));
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
new->next = daemon->if_addrs;
|
new->next = daemon->if_addrs;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (inet_pton(AF_INET, optarg, &new->addr.in.sin_addr))
|
if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr))
|
||||||
{
|
{
|
||||||
new->addr.sa.sa_family = AF_INET;
|
new->addr.sa.sa_family = AF_INET;
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
new->addr.in.sin_len = sizeof(struct sockaddr_in);
|
new->addr.in.sin_len = sizeof(struct sockaddr_in);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (inet_pton(AF_INET6, optarg, &new->addr.in6.sin6_addr))
|
else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr))
|
||||||
{
|
{
|
||||||
new->addr.sa.sa_family = AF_INET6;
|
new->addr.sa.sa_family = AF_INET6;
|
||||||
new->addr.in6.sin6_flowinfo = htonl(0);
|
new->addr.in6.sin6_flowinfo = htonl(0);
|
||||||
@@ -568,7 +590,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if ((new->addr.in.sin_addr.s_addr = inet_addr(optarg)) != (in_addr_t)-1)
|
if ((new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
|
||||||
{
|
{
|
||||||
new->addr.sa.sa_family = AF_INET;
|
new->addr.sa.sa_family = AF_INET;
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
@@ -584,8 +606,8 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
daemon->if_addrs = new;
|
daemon->if_addrs = new;
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
} while (optarg);
|
} while (arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
@@ -593,28 +615,28 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
struct server *serv, *newlist = NULL;
|
struct server *serv, *newlist = NULL;
|
||||||
|
|
||||||
if (*optarg == '/')
|
if (*arg == '/')
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
optarg++;
|
arg++;
|
||||||
while ((end = strchr(optarg, '/')))
|
while ((end = strchr(arg, '/')))
|
||||||
{
|
{
|
||||||
char *domain = NULL;
|
char *domain = NULL;
|
||||||
*end = 0;
|
*end = 0;
|
||||||
/* # matches everything and becomes a zero length domain string */
|
/* # matches everything and becomes a zero length domain string */
|
||||||
if (strcmp(optarg, "#") == 0)
|
if (strcmp(arg, "#") == 0)
|
||||||
domain = "";
|
domain = "";
|
||||||
else if (!canonicalise(optarg) && strlen(optarg) != 0)
|
else if (!canonicalise(arg) && strlen(arg) != 0)
|
||||||
option = '?';
|
option = '?';
|
||||||
else
|
else
|
||||||
domain = safe_string_alloc(optarg); /* NULL if strlen is zero */
|
domain = safe_string_alloc(arg); /* NULL if strlen is zero */
|
||||||
serv = safe_malloc(sizeof(struct server));
|
serv = safe_malloc(sizeof(struct server));
|
||||||
serv->next = newlist;
|
serv->next = newlist;
|
||||||
newlist = serv;
|
newlist = serv;
|
||||||
serv->sfd = NULL;
|
serv->sfd = NULL;
|
||||||
serv->domain = domain;
|
serv->domain = domain;
|
||||||
serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
|
serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
|
||||||
optarg = end+1;
|
arg = end+1;
|
||||||
}
|
}
|
||||||
if (!newlist)
|
if (!newlist)
|
||||||
{
|
{
|
||||||
@@ -639,7 +661,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
option = '?';
|
option = '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*optarg)
|
if (!*arg)
|
||||||
{
|
{
|
||||||
newlist->flags |= SERV_NO_ADDR; /* no server */
|
newlist->flags |= SERV_NO_ADDR; /* no server */
|
||||||
if (newlist->flags & SERV_LITERAL_ADDRESS)
|
if (newlist->flags & SERV_LITERAL_ADDRESS)
|
||||||
@@ -650,7 +672,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
int source_port = 0, serv_port = NAMESERVER_PORT;
|
int source_port = 0, serv_port = NAMESERVER_PORT;
|
||||||
char *portno, *source;
|
char *portno, *source;
|
||||||
|
|
||||||
if ((source = strchr(optarg, '@'))) /* is there a source. */
|
if ((source = strchr(arg, '@'))) /* is there a source. */
|
||||||
{
|
{
|
||||||
*source = 0;
|
*source = 0;
|
||||||
if ((portno = strchr(source+1, '#')))
|
if ((portno = strchr(source+1, '#')))
|
||||||
@@ -664,7 +686,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((portno = strchr(optarg, '#'))) /* is there a port no. */
|
if ((portno = strchr(arg, '#'))) /* is there a port no. */
|
||||||
{
|
{
|
||||||
*portno = 0;
|
*portno = 0;
|
||||||
if (!atoi_check(portno+1, &serv_port))
|
if (!atoi_check(portno+1, &serv_port))
|
||||||
@@ -675,9 +697,9 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (inet_pton(AF_INET, optarg, &newlist->addr.in.sin_addr))
|
if (inet_pton(AF_INET, arg, &newlist->addr.in.sin_addr))
|
||||||
#else
|
#else
|
||||||
if ((newlist->addr.in.sin_addr.s_addr = inet_addr(optarg)) != (in_addr_t) -1)
|
if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
newlist->addr.in.sin_port = htons(serv_port);
|
newlist->addr.in.sin_port = htons(serv_port);
|
||||||
@@ -701,7 +723,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
|
newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else if (inet_pton(AF_INET6, optarg, &newlist->addr.in6.sin6_addr))
|
else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr))
|
||||||
{
|
{
|
||||||
newlist->addr.in6.sin6_port = htons(serv_port);
|
newlist->addr.in6.sin6_port = htons(serv_port);
|
||||||
newlist->source_addr.in6.sin6_port = htons(source_port);
|
newlist->source_addr.in6.sin6_port = htons(source_port);
|
||||||
@@ -752,7 +774,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
case 'c':
|
case 'c':
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
if (!atoi_check(optarg, &size))
|
if (!atoi_check(arg, &size))
|
||||||
option = '?';
|
option = '?';
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -769,28 +791,28 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (!atoi_check(optarg, &daemon->port))
|
if (!atoi_check(arg, &daemon->port))
|
||||||
option = '?';
|
option = '?';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (!atoi_check(optarg, &i))
|
if (!atoi_check(arg, &i))
|
||||||
option = '?';
|
option = '?';
|
||||||
daemon->edns_pktsz = (unsigned short)i;
|
daemon->edns_pktsz = (unsigned short)i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'Q':
|
case 'Q':
|
||||||
if (!atoi_check(optarg, &daemon->query_port))
|
if (!atoi_check(arg, &daemon->query_port))
|
||||||
option = '?';
|
option = '?';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
{
|
{
|
||||||
int ttl;
|
int ttl;
|
||||||
if (!atoi_check(optarg, &ttl))
|
if (!atoi_check(arg, &ttl))
|
||||||
option = '?';
|
option = '?';
|
||||||
else
|
else
|
||||||
daemon->local_ttl = (unsigned long)ttl;
|
daemon->local_ttl = (unsigned long)ttl;
|
||||||
@@ -798,7 +820,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'X':
|
case 'X':
|
||||||
if (!atoi_check(optarg, &daemon->dhcp_max))
|
if (!atoi_check(arg, &daemon->dhcp_max))
|
||||||
option = '?';
|
option = '?';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -819,25 +841,25 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
|
|
||||||
problem = "bad dhcp-range";
|
problem = "bad dhcp-range";
|
||||||
|
|
||||||
for (cp = optarg; *cp; cp++)
|
for (cp = arg; *cp; cp++)
|
||||||
if (!(*cp == ' ' || *cp == '.' || (*cp >='0' && *cp <= '9')))
|
if (!(*cp == ' ' || *cp == '.' || (*cp >='0' && *cp <= '9')))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (*cp != '\001' && (comma = strchr(optarg, '\001')))
|
if (*cp != '\001' && (comma = strchr(arg, '\001')))
|
||||||
{
|
{
|
||||||
*comma = 0;
|
*comma = 0;
|
||||||
if (strstr(optarg, "net:") == optarg)
|
if (strstr(arg, "net:") == arg)
|
||||||
{
|
{
|
||||||
new->netid.net = safe_string_alloc(optarg+4);
|
new->netid.net = safe_string_alloc(arg+4);
|
||||||
new->netid.next = NULL;
|
new->netid.next = NULL;
|
||||||
new->flags |= CONTEXT_FILTER;
|
new->flags |= CONTEXT_FILTER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
new->netid.net = safe_string_alloc(optarg);
|
new->netid.net = safe_string_alloc(arg);
|
||||||
a[0] = comma + 1;
|
a[0] = comma + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
a[0] = optarg;
|
a[0] = arg;
|
||||||
|
|
||||||
|
|
||||||
for (k = 1; k < 5; k++)
|
for (k = 1; k < 5; k++)
|
||||||
@@ -940,7 +962,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
new->flags = 0;
|
new->flags = 0;
|
||||||
|
|
||||||
|
|
||||||
a[0] = optarg;
|
a[0] = arg;
|
||||||
for (k = 1; k < 6; k++)
|
for (k = 1; k < 6; k++)
|
||||||
{
|
{
|
||||||
if (!(a[k] = strchr(a[k-1], '\001')))
|
if (!(a[k] = strchr(a[k-1], '\001')))
|
||||||
@@ -1069,76 +1091,81 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
case 'O':
|
case 'O':
|
||||||
{
|
{
|
||||||
struct dhcp_opt *new = safe_malloc(sizeof(struct dhcp_opt));
|
struct dhcp_opt *new = safe_malloc(sizeof(struct dhcp_opt));
|
||||||
char *cp;
|
char lenchar = 0, *cp;
|
||||||
int addrs, digs, is_addr, is_hex, is_dec;
|
int addrs, digs, is_addr, is_hex, is_dec;
|
||||||
|
|
||||||
new->next = daemon->dhcp_opts;
|
|
||||||
new->len = 0;
|
new->len = 0;
|
||||||
new->is_addr = 0;
|
new->is_addr = 0;
|
||||||
new->netid = NULL;
|
new->netid = NULL;
|
||||||
new->val = NULL;
|
new->val = NULL;
|
||||||
|
new->vendor_class = NULL;
|
||||||
|
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
{
|
{
|
||||||
struct dhcp_netid *np = NULL;
|
struct dhcp_netid *np = NULL;
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
for (cp = optarg; *cp; cp++)
|
for (cp = arg; *cp; cp++)
|
||||||
if (!(*cp == ' ' || (*cp >='0' && *cp <= '9')))
|
if (!(*cp == ' ' || (*cp >='0' && *cp <= '9')))
|
||||||
break;
|
break;
|
||||||
if (!*cp)
|
if (!*cp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
new->netid = safe_malloc(sizeof (struct dhcp_netid));
|
if (strstr(arg, "vendor:") == arg)
|
||||||
new->netid->net = safe_string_alloc(optarg);
|
new->vendor_class = safe_string_alloc(arg+7);
|
||||||
new->netid->next = np;
|
else
|
||||||
np = new->netid;
|
{
|
||||||
optarg = comma;
|
new->netid = safe_malloc(sizeof (struct dhcp_netid));
|
||||||
if ((comma = strchr(optarg, '\001')))
|
new->netid->net = safe_string_alloc(arg);
|
||||||
|
new->netid->next = np;
|
||||||
|
np = new->netid;
|
||||||
|
}
|
||||||
|
arg = comma;
|
||||||
|
if ((comma = strchr(arg, '\001')))
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
} while (optarg);
|
} while (arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!optarg || (new->opt = atoi(optarg)) == 0)
|
if (!arg || (new->opt = atoi(arg)) == 0)
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "bad dhcp-option";
|
problem = "bad dhcp-option";
|
||||||
}
|
}
|
||||||
else if (comma && new->opt == 119)
|
else if (comma && new->opt == 119 && !new->vendor_class)
|
||||||
{
|
{
|
||||||
/* dns search, RFC 3397 */
|
/* dns search, RFC 3397 */
|
||||||
unsigned char *q, *r, *tail;
|
unsigned char *q, *r, *tail;
|
||||||
unsigned char *p = NULL;
|
unsigned char *p = NULL;
|
||||||
size_t newlen, len = 0;
|
size_t newlen, len = 0;
|
||||||
|
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*(comma++) = 0;
|
*(comma++) = 0;
|
||||||
|
|
||||||
while (optarg && *optarg)
|
while (arg && *arg)
|
||||||
{
|
{
|
||||||
if (!canonicalise(optarg))
|
if (!canonicalise(arg))
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "bad domain in dhcp-option";
|
problem = "bad domain in dhcp-option";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(p = realloc(p, len + strlen(optarg) + 2)))
|
if (!(p = realloc(p, len + strlen(arg) + 2)))
|
||||||
die("could not get memory", NULL);
|
die("could not get memory", NULL);
|
||||||
q = p + len;
|
q = p + len;
|
||||||
|
|
||||||
/* add string on the end in RFC1035 format */
|
/* add string on the end in RFC1035 format */
|
||||||
while (*optarg)
|
while (*arg)
|
||||||
{
|
{
|
||||||
char *cp = q++;
|
char *cp = q++;
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; *optarg && (*optarg != '.'); optarg++, j++)
|
for (j = 0; *arg && (*arg != '.'); arg++, j++)
|
||||||
*q++ = *optarg;
|
*q++ = *arg;
|
||||||
*cp = j;
|
*cp = j;
|
||||||
if (*optarg)
|
if (*arg)
|
||||||
optarg++;
|
arg++;
|
||||||
}
|
}
|
||||||
*q++ = 0;
|
*q++ = 0;
|
||||||
|
|
||||||
@@ -1155,8 +1182,8 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
end:
|
end:
|
||||||
len = newlen;
|
len = newlen;
|
||||||
|
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
if (optarg && (comma = strchr(optarg, '\001')))
|
if (arg && (comma = strchr(arg, '\001')))
|
||||||
*(comma++) = 0;
|
*(comma++) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1184,7 +1211,15 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
is_dec = is_hex = 0;
|
is_dec = is_hex = 0;
|
||||||
else if (!((*cp >='0' && *cp <= '9') || *cp == '-'))
|
else if (!((*cp >='0' && *cp <= '9') || *cp == '-'))
|
||||||
{
|
{
|
||||||
is_dec = is_addr = 0;
|
is_addr = 0;
|
||||||
|
if (cp[1] == 0 && is_dec &&
|
||||||
|
(*cp == 'b' || *cp == 's' || *cp == 'i'))
|
||||||
|
{
|
||||||
|
lenchar = *cp;
|
||||||
|
*cp = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
is_dec = 0;
|
||||||
if (!((*cp >='A' && *cp <= 'F') ||
|
if (!((*cp >='A' && *cp <= 'F') ||
|
||||||
(*cp >='a' && *cp <= 'f')))
|
(*cp >='a' && *cp <= 'f')))
|
||||||
is_hex = 0;
|
is_hex = 0;
|
||||||
@@ -1200,19 +1235,32 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int i, val = atoi(comma);
|
int i, val = atoi(comma);
|
||||||
/* assume numeric arg is 1 byte except for
|
/* assume numeric arg is 1 byte except for
|
||||||
options where it is known otherwise. */
|
options where it is known otherwise.
|
||||||
switch (new->opt)
|
For vendor class option, we have to hack. */
|
||||||
|
new->len = 1;
|
||||||
|
if (lenchar == 'b')
|
||||||
|
new->len = 1;
|
||||||
|
else if (lenchar == 's')
|
||||||
|
new->len = 2;
|
||||||
|
else if (lenchar == 'i')
|
||||||
|
new->len = 4;
|
||||||
|
else if (new->vendor_class)
|
||||||
{
|
{
|
||||||
default:
|
if (val & 0xffff0000)
|
||||||
new->len = 1;
|
new->len = 4;
|
||||||
break;
|
else if (val & 0xff00)
|
||||||
case 13: case 22: case 25: case 26:
|
new->len = 2;
|
||||||
new->len = 2;
|
}
|
||||||
break;
|
else
|
||||||
case 2: case 24: case 35: case 38:
|
switch (new->opt)
|
||||||
new->len = 4;
|
{
|
||||||
break;
|
case 13: case 22: case 25: case 26:
|
||||||
}
|
new->len = 2;
|
||||||
|
break;
|
||||||
|
case 2: case 24: case 35: case 38:
|
||||||
|
new->len = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
new->val = safe_malloc(new->len);
|
new->val = safe_malloc(new->len);
|
||||||
for (i=0; i<new->len; i++)
|
for (i=0; i<new->len; i++)
|
||||||
new->val[i] = val>>((new->len - i - 1)*8);
|
new->val[i] = val>>((new->len - i - 1)*8);
|
||||||
@@ -1238,8 +1286,8 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
/* text arg */
|
/* text arg */
|
||||||
new->len = strlen(comma);
|
new->len = strlen(comma);
|
||||||
new->val = safe_malloc(new->len);
|
/* keep terminating zero on string */
|
||||||
memcpy(new->val, comma, new->len);
|
new->val = safe_string_alloc(comma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1255,44 +1303,53 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
free(new->netid);
|
free(new->netid);
|
||||||
if (new->val)
|
if (new->val)
|
||||||
free(new->val);
|
free(new->val);
|
||||||
|
if (new->vendor_class)
|
||||||
|
free(new->vendor_class);
|
||||||
free(new);
|
free(new);
|
||||||
}
|
}
|
||||||
|
else if (new->vendor_class)
|
||||||
|
{
|
||||||
|
new->next = daemon->vendor_opts;
|
||||||
|
daemon->vendor_opts = new;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
daemon->dhcp_opts = new;
|
{
|
||||||
|
new->next = daemon->dhcp_opts;
|
||||||
|
daemon->dhcp_opts = new;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'M':
|
case 'M':
|
||||||
{
|
{
|
||||||
struct dhcp_netid *id = NULL;
|
struct dhcp_netid *id = NULL;
|
||||||
while (optarg && strstr(optarg, "net:") == optarg)
|
while (arg && strstr(arg, "net:") == arg)
|
||||||
{
|
{
|
||||||
struct dhcp_netid *newid = safe_malloc(sizeof(struct dhcp_netid));
|
struct dhcp_netid *newid = safe_malloc(sizeof(struct dhcp_netid));
|
||||||
newid->next = id;
|
newid->next = id;
|
||||||
id = newid;
|
id = newid;
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
newid->net = safe_string_alloc(optarg+4);
|
newid->net = safe_string_alloc(arg+4);
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!optarg)
|
if (!arg)
|
||||||
option = '?';
|
option = '?';
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *dhcp_file, *dhcp_sname = NULL;
|
char *dhcp_file, *dhcp_sname = NULL;
|
||||||
struct in_addr dhcp_next_server;
|
struct in_addr dhcp_next_server;
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
dhcp_file = safe_string_alloc(optarg);
|
dhcp_file = safe_string_alloc(arg);
|
||||||
dhcp_next_server.s_addr = 0;
|
dhcp_next_server.s_addr = 0;
|
||||||
if (comma)
|
if (comma)
|
||||||
{
|
{
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
dhcp_sname = safe_string_alloc(optarg);
|
dhcp_sname = safe_string_alloc(arg);
|
||||||
if (comma && (dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
|
if (comma && (dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
|
||||||
option = '?';
|
option = '?';
|
||||||
}
|
}
|
||||||
@@ -1323,13 +1380,13 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
case 'U':
|
case 'U':
|
||||||
case 'j':
|
case 'j':
|
||||||
{
|
{
|
||||||
if (!(comma = strchr(optarg, '\001')))
|
if (!(comma = strchr(arg, '\001')))
|
||||||
option = '?';
|
option = '?';
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct dhcp_vendor *new = safe_malloc(sizeof(struct dhcp_vendor));
|
struct dhcp_vendor *new = safe_malloc(sizeof(struct dhcp_vendor));
|
||||||
*comma = 0;
|
*comma = 0;
|
||||||
new->netid.net = safe_string_alloc(optarg);
|
new->netid.net = safe_string_alloc(arg);
|
||||||
new->len = strlen(comma+1);
|
new->len = strlen(comma+1);
|
||||||
new->data = safe_malloc(new->len);
|
new->data = safe_malloc(new->len);
|
||||||
memcpy(new->data, comma+1, new->len);
|
memcpy(new->data, comma+1, new->len);
|
||||||
@@ -1348,13 +1405,13 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
daemon->dhcp_ignore = new;
|
daemon->dhcp_ignore = new;
|
||||||
do {
|
do {
|
||||||
struct dhcp_netid *member = safe_malloc(sizeof(struct dhcp_netid));
|
struct dhcp_netid *member = safe_malloc(sizeof(struct dhcp_netid));
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
member->next = list;
|
member->next = list;
|
||||||
list = member;
|
list = member;
|
||||||
member->net = safe_string_alloc(optarg);
|
member->net = safe_string_alloc(arg);
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
} while (optarg);
|
} while (arg);
|
||||||
|
|
||||||
new->list = list;
|
new->list = list;
|
||||||
break;
|
break;
|
||||||
@@ -1369,7 +1426,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
|
|
||||||
mask.s_addr = 0xffffffff;
|
mask.s_addr = 0xffffffff;
|
||||||
|
|
||||||
a[0] = optarg;
|
a[0] = arg;
|
||||||
for (k = 1; k < 4; k++)
|
for (k = 1; k < 4; k++)
|
||||||
{
|
{
|
||||||
if (!(a[k] = strchr(a[k-1], '\001')))
|
if (!(a[k] = strchr(a[k-1], '\001')))
|
||||||
@@ -1403,10 +1460,10 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
struct txt_record *new;
|
struct txt_record *new;
|
||||||
unsigned char *p, *q;
|
unsigned char *p, *q;
|
||||||
|
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*(comma) = 0;
|
*(comma) = 0;
|
||||||
|
|
||||||
if (!canonicalise(optarg))
|
if (!canonicalise(arg))
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "bad TXT record";
|
problem = "bad TXT record";
|
||||||
@@ -1461,7 +1518,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
|
|
||||||
if (comma)
|
if (comma)
|
||||||
*comma = 0;
|
*comma = 0;
|
||||||
new->name = safe_string_alloc(optarg);
|
new->name = safe_string_alloc(arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1471,35 +1528,35 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
char *name, *target = NULL;
|
char *name, *target = NULL;
|
||||||
struct mx_srv_record *new;
|
struct mx_srv_record *new;
|
||||||
|
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*(comma++) = 0;
|
*(comma++) = 0;
|
||||||
|
|
||||||
if (!canonicalise(optarg))
|
if (!canonicalise(arg))
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "bad SRV record";
|
problem = "bad SRV record";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
name = safe_string_alloc(optarg);
|
name = safe_string_alloc(arg);
|
||||||
|
|
||||||
if (comma)
|
if (comma)
|
||||||
{
|
{
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*(comma++) = 0;
|
*(comma++) = 0;
|
||||||
if (!canonicalise(optarg))
|
if (!canonicalise(arg))
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "bad SRV target";
|
problem = "bad SRV target";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
target = safe_string_alloc(optarg);
|
target = safe_string_alloc(arg);
|
||||||
if (comma)
|
if (comma)
|
||||||
{
|
{
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*(comma++) = 0;
|
*(comma++) = 0;
|
||||||
if (!atoi_check(optarg, &port))
|
if (!atoi_check(arg, &port))
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "invalid port number";
|
problem = "invalid port number";
|
||||||
@@ -1507,10 +1564,10 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (comma)
|
if (comma)
|
||||||
{
|
{
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*(comma++) = 0;
|
*(comma++) = 0;
|
||||||
if (!atoi_check(optarg, &priority))
|
if (!atoi_check(arg, &priority))
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "invalid priority";
|
problem = "invalid priority";
|
||||||
@@ -1518,10 +1575,10 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (comma)
|
if (comma)
|
||||||
{
|
{
|
||||||
optarg = comma;
|
arg = comma;
|
||||||
if ((comma = strchr(optarg, '\001')))
|
if ((comma = strchr(arg, '\001')))
|
||||||
*(comma++) = 0;
|
*(comma++) = 0;
|
||||||
if (!atoi_check(optarg, &weight))
|
if (!atoi_check(arg, &weight))
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
problem = "invalid weight";
|
problem = "invalid weight";
|
||||||
@@ -1601,11 +1658,12 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
|
|
||||||
if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx)
|
if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx)
|
||||||
{
|
{
|
||||||
daemon->mxnames = safe_malloc(sizeof(struct mx_srv_record));
|
mx = safe_malloc(sizeof(struct mx_srv_record));
|
||||||
daemon->mxnames->next = daemon->mxnames;
|
mx->next = daemon->mxnames;
|
||||||
daemon->mxnames->issrv = 0;
|
mx->issrv = 0;
|
||||||
daemon->mxnames->target = NULL;
|
mx->target = NULL;
|
||||||
daemon->mxnames->name = safe_string_alloc(buff);
|
mx->name = safe_string_alloc(buff);
|
||||||
|
daemon->mxnames = mx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!daemon->mxtarget)
|
if (!daemon->mxtarget)
|
||||||
|
|||||||
@@ -340,7 +340,8 @@ static unsigned char *skip_section(unsigned char *ansp, int count, HEADER *heade
|
|||||||
We ignore case in the names for the same reason. */
|
We ignore case in the names for the same reason. */
|
||||||
unsigned int questions_crc(HEADER *header, unsigned int plen, char *name)
|
unsigned int questions_crc(HEADER *header, unsigned int plen, char *name)
|
||||||
{
|
{
|
||||||
unsigned int q, crc = 0xffffffff;
|
int q;
|
||||||
|
unsigned int crc = 0xffffffff;
|
||||||
unsigned char *p1, *p = (unsigned char *)(header+1);
|
unsigned char *p1, *p = (unsigned char *)(header+1);
|
||||||
|
|
||||||
for (q = 0; q < ntohs(header->qdcount); q++)
|
for (q = 0; q < ntohs(header->qdcount); q++)
|
||||||
|
|||||||
108
src/rfc2131.c
108
src/rfc2131.c
@@ -29,6 +29,7 @@
|
|||||||
#define OPTION_HOSTNAME 12
|
#define OPTION_HOSTNAME 12
|
||||||
#define OPTION_DOMAINNAME 15
|
#define OPTION_DOMAINNAME 15
|
||||||
#define OPTION_BROADCAST 28
|
#define OPTION_BROADCAST 28
|
||||||
|
#define OPTION_VENDOR_CLASS_OPT 43
|
||||||
#define OPTION_REQUESTED_IP 50
|
#define OPTION_REQUESTED_IP 50
|
||||||
#define OPTION_LEASE_TIME 51
|
#define OPTION_LEASE_TIME 51
|
||||||
#define OPTION_OVERLOAD 52
|
#define OPTION_OVERLOAD 52
|
||||||
@@ -807,8 +808,7 @@ static int in_list(unsigned char *list, int opt)
|
|||||||
|
|
||||||
static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *opts, int opt)
|
static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *opts, int opt)
|
||||||
{
|
{
|
||||||
struct dhcp_opt *tmp;
|
struct dhcp_opt *tmp;
|
||||||
|
|
||||||
for (tmp = opts; tmp; tmp = tmp->next)
|
for (tmp = opts; tmp; tmp = tmp->next)
|
||||||
if (tmp->opt == opt)
|
if (tmp->opt == opt)
|
||||||
{
|
{
|
||||||
@@ -824,6 +824,40 @@ static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *
|
|||||||
return netid ? option_find2(NULL, opts, opt) : NULL;
|
return netid ? option_find2(NULL, opts, opt) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned char *do_opt(struct dhcp_opt *opt, unsigned char *p, unsigned char *end, struct in_addr local)
|
||||||
|
{
|
||||||
|
if (p + opt->len + 3 >= end)
|
||||||
|
return p;
|
||||||
|
|
||||||
|
*(p++) = opt->opt;
|
||||||
|
*(p++) = opt->len;
|
||||||
|
|
||||||
|
if (opt->len == 0)
|
||||||
|
return p;
|
||||||
|
|
||||||
|
if (opt->is_addr && !opt->vendor_class)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
struct in_addr *a = (struct in_addr *)opt->val;
|
||||||
|
for (j = 0; j < opt->len; j+=INADDRSZ, a++)
|
||||||
|
{
|
||||||
|
/* zero means "self" (but not in vendorclass options.) */
|
||||||
|
if (a->s_addr == 0)
|
||||||
|
memcpy(p, &local, INADDRSZ);
|
||||||
|
else
|
||||||
|
memcpy(p, a, INADDRSZ);
|
||||||
|
p += INADDRSZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(p, opt->val, opt->len);
|
||||||
|
p += opt->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned char *do_req_options(struct dhcp_context *context,
|
static unsigned char *do_req_options(struct dhcp_context *context,
|
||||||
unsigned char *p, unsigned char *end,
|
unsigned char *p, unsigned char *end,
|
||||||
unsigned char *req_options,
|
unsigned char *req_options,
|
||||||
@@ -833,6 +867,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
struct in_addr subnet_addr)
|
struct in_addr subnet_addr)
|
||||||
{
|
{
|
||||||
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
|
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
|
||||||
|
char *vendor_class = NULL;
|
||||||
|
|
||||||
if (in_list(req_options, OPTION_MAXMESSAGE))
|
if (in_list(req_options, OPTION_MAXMESSAGE))
|
||||||
p = option_put(p, end, OPTION_MAXMESSAGE, 2, end - (unsigned char *)daemon->dhcp_packet);
|
p = option_put(p, end, OPTION_MAXMESSAGE, 2, end - (unsigned char *)daemon->dhcp_packet);
|
||||||
@@ -877,8 +912,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
if (opt->opt == OPTION_HOSTNAME ||
|
if (opt->opt == OPTION_HOSTNAME ||
|
||||||
opt->opt == OPTION_MAXMESSAGE ||
|
opt->opt == OPTION_MAXMESSAGE ||
|
||||||
!in_list(req_options, opt->opt) ||
|
!in_list(req_options, opt->opt) ||
|
||||||
opt != option_find2(netid, config_opts, opt->opt) ||
|
opt != option_find2(netid, config_opts, opt->opt))
|
||||||
p + opt->len + 3 >= end)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* For the options we have default values on
|
/* For the options we have default values on
|
||||||
@@ -890,32 +924,54 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
opt->opt == OPTION_ROUTER ||
|
opt->opt == OPTION_ROUTER ||
|
||||||
opt->opt == OPTION_DNSSERVER))
|
opt->opt == OPTION_DNSSERVER))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
*(p++) = opt->opt;
|
/* opt->val has terminating zero */
|
||||||
*(p++) = opt->len;
|
if (opt->opt == OPTION_VENDOR_ID)
|
||||||
if (opt->len == 0)
|
vendor_class = opt->val;
|
||||||
continue;
|
else
|
||||||
|
p = do_opt(opt, p, end, context->local);
|
||||||
if (opt->is_addr)
|
}
|
||||||
|
|
||||||
|
if (in_list(req_options, OPTION_VENDOR_ID))
|
||||||
|
{
|
||||||
|
for (opt = daemon->vendor_opts; opt; opt = opt->next)
|
||||||
|
if (!opt->netid || match_netid(opt->netid, netid))
|
||||||
|
{
|
||||||
|
if (vendor_class && strcmp(vendor_class, opt->vendor_class) != 0)
|
||||||
|
syslog(LOG_WARNING, "More than one vendor class matches, using %s", vendor_class);
|
||||||
|
else
|
||||||
|
vendor_class = opt->vendor_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vendor_class)
|
||||||
{
|
{
|
||||||
int j;
|
p = option_put_string(p, end, OPTION_VENDOR_ID, vendor_class);
|
||||||
struct in_addr *a = (struct in_addr *)opt->val;
|
|
||||||
for (j = 0; j < opt->len; j+=INADDRSZ, a++)
|
if (in_list(req_options, OPTION_VENDOR_CLASS_OPT))
|
||||||
{
|
{
|
||||||
/* zero means "self" */
|
unsigned char *plen, *oend = end;
|
||||||
if (a->s_addr == 0)
|
|
||||||
memcpy(p, &context->local, INADDRSZ);
|
/* encapsulated options can only be 256 bytes,
|
||||||
else
|
even of the packet is larger */
|
||||||
memcpy(p, a, INADDRSZ);
|
if (p + 256 < end)
|
||||||
p += INADDRSZ;
|
oend = p + 256;
|
||||||
|
|
||||||
|
if (p + 3 >= oend)
|
||||||
|
return p;
|
||||||
|
|
||||||
|
*(p++) = OPTION_VENDOR_CLASS_OPT;
|
||||||
|
plen = p++; /* fill in later */
|
||||||
|
|
||||||
|
for (opt = daemon->vendor_opts; opt; opt = opt->next)
|
||||||
|
if ((!opt->netid || match_netid(opt->netid, netid)) &&
|
||||||
|
strcmp(vendor_class, opt->vendor_class) == 0)
|
||||||
|
p = do_opt(opt, p, oend, context->local);
|
||||||
|
|
||||||
|
*plen = p - plen - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
memcpy(p, opt->val, opt->len);
|
|
||||||
p += opt->len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user