import of dnsmasq-2.22.tar.gz

This commit is contained in:
Simon Kelley
2005-03-31 17:48:32 +01:00
parent 0a852541d3
commit 91dccd0958
13 changed files with 350 additions and 188 deletions

View File

@@ -12,7 +12,7 @@
/* Author's email: simon@thekelleys.org.uk */
#define VERSION "2.21"
#define VERSION "2.22"
#define FTABSIZ 150 /* max number of outstanding requests */
#define MAX_PROCS 20 /* max no children for TCP requests */
@@ -207,7 +207,7 @@ NOTES:
#if defined(__uClinux__) || defined(__UCLIBC__)
#undef HAVE_LINUX_IPV6_PROC
#define HAVE_GETOPT_LONG
#undef HAVE_RTNETLINK /* headers broken */
#define HAVE_RTNETLINK
#undef HAVE_ARC4RANDOM
#define HAVE_RANDOM
#define HAVE_DEV_URANDOM

View File

@@ -206,8 +206,9 @@ void dhcp_packet(struct daemon *daemon, time_t now)
return;
}
/* unlinked contexts are marked by context->current == context */
for (context = daemon->dhcp; context; context = context->next)
context->current = NULL;
context->current = context;
#ifdef HAVE_RTNETLINK
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) &&
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->local = local;
@@ -684,6 +686,7 @@ void dhcp_read_ethers(struct daemon *daemon)
{
for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_HWADDR) &&
config->wildcard_mask == 0 &&
memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
break;
@@ -692,6 +695,7 @@ void dhcp_read_ethers(struct daemon *daemon)
if (!(config = malloc(sizeof(struct dhcp_config))))
continue;
config->flags = 0;
config->wildcard_mask = 0;
config->next = configs;
configs = config;
}

View File

@@ -321,7 +321,7 @@ struct dhcp_config {
struct dhcp_opt {
int opt, len, is_addr;
unsigned char *val;
unsigned char *val, *vendor_class;
struct dhcp_netid *netid;
struct dhcp_opt *next;
};
@@ -403,7 +403,7 @@ 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, *vendor_opts;
struct dhcp_vendor *dhcp_vendors;
struct dhcp_boot *boot_config;
struct dhcp_netid_list *dhcp_ignore;

View File

@@ -16,6 +16,7 @@
#ifdef HAVE_RTNETLINK
#include <linux/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

View File

@@ -187,13 +187,26 @@ static void add_txt(struct daemon *daemon, char *name, char *txt)
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 *daemon = safe_malloc(sizeof(struct daemon));
char *problem = NULL, *buff = safe_malloc(MAXDNAME);
int option = 0, i;
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 line_save = 0, lineno = 0;
opterr = 0;
@@ -229,10 +242,18 @@ struct daemon *read_opts (int argc, char **argv)
#else
option = getopt(argc, argv, OPTSTRING);
#endif
/* Copy optarg so that argv doesn't get changed */
if (optarg)
for (p = optarg; *p; p++)
if (*p == ',')
*p = '\001';
{
strncpy(buff, optarg, MAXDNAME);
buff[MAXDNAME-1] = 0;
arg = buff;
for (p = arg; *p; p++)
if (*p == ',')
*p = '\001';
}
else
arg = NULL;
}
else
{ /* f non-NULL, reading from conffile. */
@@ -298,11 +319,11 @@ struct daemon *read_opts (int argc, char **argv)
continue;
if ((p=strchr(buff, '=')))
{
optarg = p+1;
arg = p+1;
*p = 0;
}
else
optarg = NULL;
arg = NULL;
option = 0;
for (i=0; opts[i].name; i++)
@@ -351,14 +372,14 @@ struct daemon *read_opts (int argc, char **argv)
{
daemon->options |= optmap[i].flag;
option = 0;
if (f && optarg)
if (f && arg)
complain("extraneous parameter", lineno, conffile);
break;
}
if (option && option != '?')
{
if (f && !optarg)
if (f && !arg)
{
complain("missing parameter", lineno, conffile);
continue;
@@ -369,7 +390,7 @@ struct daemon *read_opts (int argc, char **argv)
case 'C':
if (!f)
{
conffile = safe_string_alloc(optarg);
conffile = safe_filename_alloc(arg);
conffile_set = 1;
break;
}
@@ -383,19 +404,20 @@ struct daemon *read_opts (int argc, char **argv)
file_name_save = conffile;
file_save = f;
line_save = lineno;
conffile = safe_string_alloc(optarg);
conffile = safe_filename_alloc(arg);
conffile_set = 1;
lineno = 0;
goto fileopen;
case 'x':
daemon->runfile = safe_string_alloc(optarg);
daemon->runfile = safe_filename_alloc(arg);
break;
case 'r':
{
char *name = safe_string_alloc(optarg);
char *name = safe_filename_alloc(arg);
struct resolvc *new, *list = daemon->resolv_files;
if (list && list->is_default)
{
/* replace default resolv file - possibly with nothing */
@@ -425,7 +447,7 @@ struct daemon *read_opts (int argc, char **argv)
int pref = 1;
struct mx_srv_record *new;
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
{
char *prefstr;
*(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 = '?';
problem = "bad MX name";
@@ -452,30 +474,30 @@ struct daemon *read_opts (int argc, char **argv)
new->next = daemon->mxnames;
daemon->mxnames = new;
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->weight = pref;
break;
}
case 't':
if (!canonicalise(optarg))
if (!canonicalise(arg))
{
option = '?';
problem = "bad MX target";
}
else
daemon->mxtarget = safe_string_alloc(optarg);
daemon->mxtarget = safe_string_alloc(arg);
break;
case 'l':
daemon->lease_file = safe_string_alloc(optarg);
daemon->lease_file = safe_filename_alloc(arg);
break;
case 'H':
{
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->next = daemon->addn_hosts;
daemon->addn_hosts = new;
@@ -483,57 +505,57 @@ struct daemon *read_opts (int argc, char **argv)
}
case 's':
if (strcmp (optarg, "#") == 0)
if (strcmp (arg, "#") == 0)
daemon->options |= OPT_RESOLV_DOMAIN;
else if (!canonicalise(optarg))
else if (!canonicalise(arg))
option = '?';
else
daemon->domain_suffix = safe_string_alloc(optarg);
daemon->domain_suffix = safe_string_alloc(arg);
break;
case 'u':
daemon->username = safe_string_alloc(optarg);
daemon->username = safe_string_alloc(arg);
break;
case 'g':
daemon->groupname = safe_string_alloc(optarg);
daemon->groupname = safe_string_alloc(arg);
break;
case 'i':
do {
struct iname *new = safe_malloc(sizeof(struct iname));
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
*comma++ = 0;
new->next = daemon->if_names;
daemon->if_names = new;
/* new->name may be NULL if someone does
"interface=" to disable all interfaces except loop. */
new->name = safe_string_alloc(optarg);
new->name = safe_string_alloc(arg);
new->isloop = new->used = 0;
if (strchr(optarg, ':'))
if (strchr(arg, ':'))
daemon->options |= OPT_NOWILD;
optarg = comma;
} while (optarg);
arg = comma;
} while (arg);
break;
case 'I':
do {
struct iname *new = safe_malloc(sizeof(struct iname));
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
*comma++ = 0;
new->next = daemon->if_except;
daemon->if_except = new;
new->name = safe_string_alloc(optarg);
if (strchr(optarg, ':'))
new->name = safe_string_alloc(arg);
if (strchr(arg, ':'))
daemon->options |= OPT_NOWILD;
optarg = comma;
} while (optarg);
arg = comma;
} while (arg);
break;
case 'B':
{
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));
baddr->next = daemon->bogus_addr;
@@ -548,18 +570,18 @@ struct daemon *read_opts (int argc, char **argv)
case 'a':
do {
struct iname *new = safe_malloc(sizeof(struct iname));
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
*comma++ = 0;
new->next = daemon->if_addrs;
#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;
#ifdef HAVE_SOCKADDR_SA_LEN
new->addr.in.sin_len = sizeof(struct sockaddr_in);
#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.in6.sin6_flowinfo = htonl(0);
@@ -568,7 +590,7 @@ struct daemon *read_opts (int argc, char **argv)
#endif
}
#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;
#ifdef HAVE_SOCKADDR_SA_LEN
@@ -584,8 +606,8 @@ struct daemon *read_opts (int argc, char **argv)
}
daemon->if_addrs = new;
optarg = comma;
} while (optarg);
arg = comma;
} while (arg);
break;
case 'S':
@@ -593,28 +615,28 @@ struct daemon *read_opts (int argc, char **argv)
{
struct server *serv, *newlist = NULL;
if (*optarg == '/')
if (*arg == '/')
{
char *end;
optarg++;
while ((end = strchr(optarg, '/')))
arg++;
while ((end = strchr(arg, '/')))
{
char *domain = NULL;
*end = 0;
/* # matches everything and becomes a zero length domain string */
if (strcmp(optarg, "#") == 0)
if (strcmp(arg, "#") == 0)
domain = "";
else if (!canonicalise(optarg) && strlen(optarg) != 0)
else if (!canonicalise(arg) && strlen(arg) != 0)
option = '?';
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->next = newlist;
newlist = serv;
serv->sfd = NULL;
serv->domain = domain;
serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
optarg = end+1;
arg = end+1;
}
if (!newlist)
{
@@ -639,7 +661,7 @@ struct daemon *read_opts (int argc, char **argv)
option = '?';
}
if (!*optarg)
if (!*arg)
{
newlist->flags |= SERV_NO_ADDR; /* no server */
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;
char *portno, *source;
if ((source = strchr(optarg, '@'))) /* is there a source. */
if ((source = strchr(arg, '@'))) /* is there a source. */
{
*source = 0;
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;
if (!atoi_check(portno+1, &serv_port))
@@ -675,9 +697,9 @@ struct daemon *read_opts (int argc, char **argv)
}
#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
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
{
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;
}
#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->source_addr.in6.sin6_port = htons(source_port);
@@ -752,7 +774,7 @@ struct daemon *read_opts (int argc, char **argv)
case 'c':
{
int size;
if (!atoi_check(optarg, &size))
if (!atoi_check(arg, &size))
option = '?';
else
{
@@ -769,28 +791,28 @@ struct daemon *read_opts (int argc, char **argv)
}
case 'p':
if (!atoi_check(optarg, &daemon->port))
if (!atoi_check(arg, &daemon->port))
option = '?';
break;
case 'P':
{
int i;
if (!atoi_check(optarg, &i))
if (!atoi_check(arg, &i))
option = '?';
daemon->edns_pktsz = (unsigned short)i;
break;
}
case 'Q':
if (!atoi_check(optarg, &daemon->query_port))
if (!atoi_check(arg, &daemon->query_port))
option = '?';
break;
case 'T':
{
int ttl;
if (!atoi_check(optarg, &ttl))
if (!atoi_check(arg, &ttl))
option = '?';
else
daemon->local_ttl = (unsigned long)ttl;
@@ -798,7 +820,7 @@ struct daemon *read_opts (int argc, char **argv)
}
case 'X':
if (!atoi_check(optarg, &daemon->dhcp_max))
if (!atoi_check(arg, &daemon->dhcp_max))
option = '?';
break;
@@ -819,25 +841,25 @@ struct daemon *read_opts (int argc, char **argv)
problem = "bad dhcp-range";
for (cp = optarg; *cp; cp++)
for (cp = arg; *cp; cp++)
if (!(*cp == ' ' || *cp == '.' || (*cp >='0' && *cp <= '9')))
break;
if (*cp != '\001' && (comma = strchr(optarg, '\001')))
if (*cp != '\001' && (comma = strchr(arg, '\001')))
{
*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->flags |= CONTEXT_FILTER;
}
else
new->netid.net = safe_string_alloc(optarg);
new->netid.net = safe_string_alloc(arg);
a[0] = comma + 1;
}
else
a[0] = optarg;
a[0] = arg;
for (k = 1; k < 5; k++)
@@ -940,7 +962,7 @@ struct daemon *read_opts (int argc, char **argv)
new->flags = 0;
a[0] = optarg;
a[0] = arg;
for (k = 1; k < 6; k++)
{
if (!(a[k] = strchr(a[k-1], '\001')))
@@ -1069,76 +1091,81 @@ struct daemon *read_opts (int argc, char **argv)
case 'O':
{
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;
new->next = daemon->dhcp_opts;
new->len = 0;
new->is_addr = 0;
new->netid = NULL;
new->val = NULL;
new->vendor_class = NULL;
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
{
struct dhcp_netid *np = NULL;
*comma++ = 0;
do {
for (cp = optarg; *cp; cp++)
for (cp = arg; *cp; cp++)
if (!(*cp == ' ' || (*cp >='0' && *cp <= '9')))
break;
if (!*cp)
break;
new->netid = safe_malloc(sizeof (struct dhcp_netid));
new->netid->net = safe_string_alloc(optarg);
new->netid->next = np;
np = new->netid;
optarg = comma;
if ((comma = strchr(optarg, '\001')))
if (strstr(arg, "vendor:") == arg)
new->vendor_class = safe_string_alloc(arg+7);
else
{
new->netid = safe_malloc(sizeof (struct dhcp_netid));
new->netid->net = safe_string_alloc(arg);
new->netid->next = np;
np = new->netid;
}
arg = comma;
if ((comma = strchr(arg, '\001')))
*comma++ = 0;
} while (optarg);
} while (arg);
}
if (!optarg || (new->opt = atoi(optarg)) == 0)
if (!arg || (new->opt = atoi(arg)) == 0)
{
option = '?';
problem = "bad dhcp-option";
}
else if (comma && new->opt == 119)
else if (comma && new->opt == 119 && !new->vendor_class)
{
/* dns search, RFC 3397 */
unsigned char *q, *r, *tail;
unsigned char *p = NULL;
size_t newlen, len = 0;
optarg = comma;
if ((comma = strchr(optarg, '\001')))
arg = comma;
if ((comma = strchr(arg, '\001')))
*(comma++) = 0;
while (optarg && *optarg)
while (arg && *arg)
{
if (!canonicalise(optarg))
if (!canonicalise(arg))
{
option = '?';
problem = "bad domain in dhcp-option";
break;
}
if (!(p = realloc(p, len + strlen(optarg) + 2)))
if (!(p = realloc(p, len + strlen(arg) + 2)))
die("could not get memory", NULL);
q = p + len;
/* add string on the end in RFC1035 format */
while (*optarg)
while (*arg)
{
char *cp = q++;
int j;
for (j = 0; *optarg && (*optarg != '.'); optarg++, j++)
*q++ = *optarg;
for (j = 0; *arg && (*arg != '.'); arg++, j++)
*q++ = *arg;
*cp = j;
if (*optarg)
optarg++;
if (*arg)
arg++;
}
*q++ = 0;
@@ -1155,8 +1182,8 @@ struct daemon *read_opts (int argc, char **argv)
end:
len = newlen;
optarg = comma;
if (optarg && (comma = strchr(optarg, '\001')))
arg = comma;
if (arg && (comma = strchr(arg, '\001')))
*(comma++) = 0;
}
@@ -1184,7 +1211,15 @@ struct daemon *read_opts (int argc, char **argv)
is_dec = is_hex = 0;
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') ||
(*cp >='a' && *cp <= 'f')))
is_hex = 0;
@@ -1200,19 +1235,32 @@ struct daemon *read_opts (int argc, char **argv)
{
int i, val = atoi(comma);
/* assume numeric arg is 1 byte except for
options where it is known otherwise. */
switch (new->opt)
options where it is known otherwise.
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:
new->len = 1;
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;
}
if (val & 0xffff0000)
new->len = 4;
else if (val & 0xff00)
new->len = 2;
}
else
switch (new->opt)
{
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);
for (i=0; i<new->len; i++)
new->val[i] = val>>((new->len - i - 1)*8);
@@ -1238,8 +1286,8 @@ struct daemon *read_opts (int argc, char **argv)
{
/* text arg */
new->len = strlen(comma);
new->val = safe_malloc(new->len);
memcpy(new->val, comma, new->len);
/* keep terminating zero on string */
new->val = safe_string_alloc(comma);
}
}
@@ -1255,44 +1303,53 @@ struct daemon *read_opts (int argc, char **argv)
free(new->netid);
if (new->val)
free(new->val);
if (new->vendor_class)
free(new->vendor_class);
free(new);
}
else if (new->vendor_class)
{
new->next = daemon->vendor_opts;
daemon->vendor_opts = new;
}
else
daemon->dhcp_opts = new;
{
new->next = daemon->dhcp_opts;
daemon->dhcp_opts = new;
}
break;
}
case 'M':
{
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));
newid->next = id;
id = newid;
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
*comma++ = 0;
newid->net = safe_string_alloc(optarg+4);
optarg = comma;
newid->net = safe_string_alloc(arg+4);
arg = comma;
};
if (!optarg)
if (!arg)
option = '?';
else
{
char *dhcp_file, *dhcp_sname = NULL;
struct in_addr dhcp_next_server;
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
*comma++ = 0;
dhcp_file = safe_string_alloc(optarg);
dhcp_file = safe_string_alloc(arg);
dhcp_next_server.s_addr = 0;
if (comma)
{
optarg = comma;
if ((comma = strchr(optarg, '\001')))
arg = comma;
if ((comma = strchr(arg, '\001')))
*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)
option = '?';
}
@@ -1323,13 +1380,13 @@ struct daemon *read_opts (int argc, char **argv)
case 'U':
case 'j':
{
if (!(comma = strchr(optarg, '\001')))
if (!(comma = strchr(arg, '\001')))
option = '?';
else
{
struct dhcp_vendor *new = safe_malloc(sizeof(struct dhcp_vendor));
*comma = 0;
new->netid.net = safe_string_alloc(optarg);
new->netid.net = safe_string_alloc(arg);
new->len = strlen(comma+1);
new->data = safe_malloc(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;
do {
struct dhcp_netid *member = safe_malloc(sizeof(struct dhcp_netid));
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
*comma++ = 0;
member->next = list;
list = member;
member->net = safe_string_alloc(optarg);
optarg = comma;
} while (optarg);
member->net = safe_string_alloc(arg);
arg = comma;
} while (arg);
new->list = list;
break;
@@ -1369,7 +1426,7 @@ struct daemon *read_opts (int argc, char **argv)
mask.s_addr = 0xffffffff;
a[0] = optarg;
a[0] = arg;
for (k = 1; k < 4; k++)
{
if (!(a[k] = strchr(a[k-1], '\001')))
@@ -1403,10 +1460,10 @@ struct daemon *read_opts (int argc, char **argv)
struct txt_record *new;
unsigned char *p, *q;
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
*(comma) = 0;
if (!canonicalise(optarg))
if (!canonicalise(arg))
{
option = '?';
problem = "bad TXT record";
@@ -1461,7 +1518,7 @@ struct daemon *read_opts (int argc, char **argv)
if (comma)
*comma = 0;
new->name = safe_string_alloc(optarg);
new->name = safe_string_alloc(arg);
break;
}
@@ -1471,35 +1528,35 @@ struct daemon *read_opts (int argc, char **argv)
char *name, *target = NULL;
struct mx_srv_record *new;
if ((comma = strchr(optarg, '\001')))
if ((comma = strchr(arg, '\001')))
*(comma++) = 0;
if (!canonicalise(optarg))
if (!canonicalise(arg))
{
option = '?';
problem = "bad SRV record";
break;
}
name = safe_string_alloc(optarg);
name = safe_string_alloc(arg);
if (comma)
{
optarg = comma;
if ((comma = strchr(optarg, '\001')))
arg = comma;
if ((comma = strchr(arg, '\001')))
*(comma++) = 0;
if (!canonicalise(optarg))
if (!canonicalise(arg))
{
option = '?';
problem = "bad SRV target";
break;
}
target = safe_string_alloc(optarg);
target = safe_string_alloc(arg);
if (comma)
{
optarg = comma;
if ((comma = strchr(optarg, '\001')))
arg = comma;
if ((comma = strchr(arg, '\001')))
*(comma++) = 0;
if (!atoi_check(optarg, &port))
if (!atoi_check(arg, &port))
{
option = '?';
problem = "invalid port number";
@@ -1507,10 +1564,10 @@ struct daemon *read_opts (int argc, char **argv)
}
if (comma)
{
optarg = comma;
if ((comma = strchr(optarg, '\001')))
arg = comma;
if ((comma = strchr(arg, '\001')))
*(comma++) = 0;
if (!atoi_check(optarg, &priority))
if (!atoi_check(arg, &priority))
{
option = '?';
problem = "invalid priority";
@@ -1518,10 +1575,10 @@ struct daemon *read_opts (int argc, char **argv)
}
if (comma)
{
optarg = comma;
if ((comma = strchr(optarg, '\001')))
arg = comma;
if ((comma = strchr(arg, '\001')))
*(comma++) = 0;
if (!atoi_check(optarg, &weight))
if (!atoi_check(arg, &weight))
{
option = '?';
problem = "invalid weight";
@@ -1601,11 +1658,12 @@ struct daemon *read_opts (int argc, char **argv)
if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx)
{
daemon->mxnames = safe_malloc(sizeof(struct mx_srv_record));
daemon->mxnames->next = daemon->mxnames;
daemon->mxnames->issrv = 0;
daemon->mxnames->target = NULL;
daemon->mxnames->name = safe_string_alloc(buff);
mx = safe_malloc(sizeof(struct mx_srv_record));
mx->next = daemon->mxnames;
mx->issrv = 0;
mx->target = NULL;
mx->name = safe_string_alloc(buff);
daemon->mxnames = mx;
}
if (!daemon->mxtarget)

View File

@@ -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. */
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);
for (q = 0; q < ntohs(header->qdcount); q++)

View File

@@ -29,6 +29,7 @@
#define OPTION_HOSTNAME 12
#define OPTION_DOMAINNAME 15
#define OPTION_BROADCAST 28
#define OPTION_VENDOR_CLASS_OPT 43
#define OPTION_REQUESTED_IP 50
#define OPTION_LEASE_TIME 51
#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)
{
struct dhcp_opt *tmp;
struct dhcp_opt *tmp;
for (tmp = opts; tmp; tmp = tmp->next)
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;
}
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,
unsigned char *p, unsigned char *end,
unsigned char *req_options,
@@ -833,6 +867,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
struct in_addr subnet_addr)
{
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
char *vendor_class = NULL;
if (in_list(req_options, OPTION_MAXMESSAGE))
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 ||
opt->opt == OPTION_MAXMESSAGE ||
!in_list(req_options, opt->opt) ||
opt != option_find2(netid, config_opts, opt->opt) ||
p + opt->len + 3 >= end)
opt != option_find2(netid, config_opts, opt->opt))
continue;
/* 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_DNSSERVER))
continue;
*(p++) = opt->opt;
*(p++) = opt->len;
if (opt->len == 0)
continue;
if (opt->is_addr)
/* opt->val has terminating zero */
if (opt->opt == OPTION_VENDOR_ID)
vendor_class = opt->val;
else
p = do_opt(opt, p, end, context->local);
}
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;
struct in_addr *a = (struct in_addr *)opt->val;
for (j = 0; j < opt->len; j+=INADDRSZ, a++)
p = option_put_string(p, end, OPTION_VENDOR_ID, vendor_class);
if (in_list(req_options, OPTION_VENDOR_CLASS_OPT))
{
/* zero means "self" */
if (a->s_addr == 0)
memcpy(p, &context->local, INADDRSZ);
else
memcpy(p, a, INADDRSZ);
p += INADDRSZ;
unsigned char *plen, *oend = end;
/* encapsulated options can only be 256 bytes,
even of the packet is larger */
if (p + 256 < end)
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;
}