Commit 91dccd09 authored by Simon Kelley's avatar Simon Kelley

import of dnsmasq-2.22.tar.gz

parent 0a852541
...@@ -1422,3 +1422,25 @@ version 2.21 ...@@ -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 @@ ...@@ -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 @@ ...@@ -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
......
...@@ -408,7 +408,7 @@ have exactly the same effect as ...@@ -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 ...@@ -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 ...@@ -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 @@ ...@@ -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 @@ ...@@ -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: ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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>
......
This diff is collapsed.
...@@ -340,7 +340,8 @@ static unsigned char *skip_section(unsigned char *ansp, int count, HEADER *heade ...@@ -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++)
......
...@@ -29,6 +29,7 @@ ...@@ -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
...@@ -808,7 +809,6 @@ static int in_list(unsigned char *list, int opt) ...@@ -808,7 +809,6 @@ 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 * ...@@ -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, ...@@ -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, ...@@ -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
...@@ -891,31 +925,53 @@ static unsigned char *do_req_options(struct dhcp_context *context, ...@@ -891,31 +925,53 @@ static unsigned char *do_req_options(struct dhcp_context *context,
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))
{ {
int j; for (opt = daemon->vendor_opts; opt; opt = opt->next)
struct in_addr *a = (struct in_addr *)opt->val; if (!opt->netid || match_netid(opt->netid, netid))
for (j = 0; j < opt->len; j+=INADDRSZ, a++)
{ {
/* zero means "self" */ if (vendor_class && strcmp(vendor_class, opt->vendor_class) != 0)
if (a->s_addr == 0) syslog(LOG_WARNING, "More than one vendor class matches, using %s", vendor_class);
memcpy(p, &context->local, INADDRSZ);
else else
memcpy(p, a, INADDRSZ); vendor_class = opt->vendor_class;
p += INADDRSZ;
}
} }
else
if (vendor_class)
{ {
memcpy(p, opt->val, opt->len); p = option_put_string(p, end, OPTION_VENDOR_ID, vendor_class);
p += opt->len;
if (in_list(req_options, OPTION_VENDOR_CLASS_OPT))
{
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;
}
} }
} }
return p; return p;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment