mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.8.tar.gz
This commit is contained in:
41
CHANGELOG
41
CHANGELOG
@@ -962,3 +962,44 @@ release 2.7
|
||||
ancient IBM LANMAN DHCP clients. Thanks to Jim Louvau for
|
||||
help with this.
|
||||
|
||||
release 2.8
|
||||
Pad DHCP packets to a minimum size of 300 bytes. This
|
||||
fixes interoperability problems with the Linux in-kernel
|
||||
DHCP/BOOTP client. Thanks to Richard Musil for
|
||||
diagnosing this and supplying a patch.
|
||||
|
||||
Fixed option-parsing bug and potential memory leak. Patch
|
||||
from Richard Musil.
|
||||
|
||||
Improved vendor class configuration and added user class
|
||||
configuration. Specifically: (1) options are matched on
|
||||
the netids from dhcp-range, dhcp-host, vendor class and
|
||||
user class(es). Multiple net-ids are allowed and options
|
||||
are searched on them all. (2) matches agains vendor class
|
||||
and user class are now on a substring, if the given
|
||||
string is a substring of the vendor/user class, then a
|
||||
match occurs. Thanks again to Richard Musil for prompting
|
||||
this.
|
||||
|
||||
Make "#" match any domain on --address and --server
|
||||
flags. --address=/#/1.2.3.4 will return 1.2.3.4 for _any_
|
||||
domain not otherwise matched. Of course
|
||||
--server=/#/1.2.3.4 is exactly equivalent to
|
||||
--server=1.2.3.4. Special request from Josh Howlett.
|
||||
|
||||
Fixed a nasty bug which would cause dnsmasq to lose track
|
||||
of leases for hosts which had a --dhcp-host flag without
|
||||
a name specification. The mechanism for this was that
|
||||
the hostname could get erroneously set as a zero-length
|
||||
string and then written to the leases file as a
|
||||
mal-formed line. Restarting dnsmasq would then lose the lease.
|
||||
Alex Hermann's work helped chase down this problem.
|
||||
|
||||
Add checks against DHCP clients which return zero-length
|
||||
hostnames. This avoids the potential lease-loss problems
|
||||
reffered to above. Also, if a client sends a hostname when
|
||||
it creates a lease but subsequently sends no or a
|
||||
zero-length hostname whilst renewing, continue to use the
|
||||
existing hostname, don't wipe it out.
|
||||
|
||||
Tweaked option parsing to flag some parameter errors.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
###############################################################################
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.7
|
||||
Version: 2.8
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: System Environment/Daemons
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
###############################################################################
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.7
|
||||
Version: 2.8
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Productivity/Networking/DNS/Servers
|
||||
|
||||
21
dnsmasq.8
21
dnsmasq.8
@@ -223,7 +223,12 @@ with the specified IP address which may be IPv4 or IPv6. To give
|
||||
both IPv4 and IPv6 addresses for a domain, use repeated -A flags.
|
||||
Note that /etc/hosts and DHCP leases override this for individual
|
||||
names. A common use of this is to redirect the entire doubleclick.net
|
||||
domain to some friendly local web server to avoid banner ads.
|
||||
domain to some friendly local web server to avoid banner ads. The
|
||||
domain specification works in the same was as for --server, with the
|
||||
additional facility that /#/ matches any domain. Thus
|
||||
--address=/#/1.2.3.4 will always return 1.2.3.4 for any query not
|
||||
answered from /etc/hosts or DHCP and not sent to an upstream
|
||||
nameserver by a more specific --server directive.
|
||||
.TP
|
||||
.B \-m, --mx-host=<mx name>
|
||||
Return an MX record named <mx name> pointing to the host specified in the --mx-target switch
|
||||
@@ -358,12 +363,24 @@ of this flag.
|
||||
.TP
|
||||
.B \-U, --dhcp-vendorclass=<network-id>,<vendor-class>
|
||||
Map from a vendor-class string to a network id. Most DHCP clients provide a
|
||||
"vendor class" which represents, in some sense, the type of host. This options
|
||||
"vendor class" which represents, in some sense, the type of host. This option
|
||||
maps vendor classes to network ids, so that DHCP options may be selectively delivered
|
||||
to different classes of hosts. For example
|
||||
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
|
||||
will allow options to be set only for HP printers like so:
|
||||
.B --dhcp-option=printers,3,192.168.4.4
|
||||
The vendor-class string is
|
||||
substring matched against the vendor-class supplied by the client, to
|
||||
allow fuzzy matching.
|
||||
.TP
|
||||
.B \-j, --dhcp-userclass=<network-id>,<user-class>
|
||||
Map from a user-class string to a network id (with substring
|
||||
matching, like vendor classes). Most DHCP clients provide a
|
||||
"user class" which is configurable. This option
|
||||
maps user classes to network ids, so that DHCP options may be selectively delivered
|
||||
to different classes of hosts. It is possible, for instance to use
|
||||
this to set a different printer server for hosts in the class
|
||||
"accounts" than for hosts in the class "engineering".
|
||||
.TP
|
||||
.B \-M, --dhcp-boot=<filename>,[<servername>[,<server address>]]
|
||||
Set BOOTP options to be returned by the DHCP server. These are needed
|
||||
|
||||
@@ -171,6 +171,14 @@ filterwin2k
|
||||
# the machine with ethernet address 11:22:33:44:55:66
|
||||
#dhcp-host=11:22:33:44:55:66,net:red
|
||||
|
||||
# Send extra options which are tagged as "red" to any machine whose
|
||||
# DHCP vendorclass string includes the substring "Linux"
|
||||
#dhcp-vendorclass=red,Linux
|
||||
|
||||
# Send extra options which are tagged as "red" to any machine one
|
||||
# of whose DHCP userclass strings includes the substring "accounts"
|
||||
#dhcp-userclass=red,accounts
|
||||
|
||||
# If this line is uncommented, dnsmasq will read /etc/ethers and act
|
||||
# on the ethernet-address/IP pairs found there just as if they had
|
||||
# been given as --dhcp-host options. Useful if you keep
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
/* Author's email: simon@thekelleys.org.uk */
|
||||
|
||||
#define VERSION "2.7"
|
||||
#define VERSION "2.8"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests */
|
||||
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */
|
||||
|
||||
@@ -237,12 +237,18 @@ struct dhcp_lease {
|
||||
struct dhcp_lease *next;
|
||||
};
|
||||
|
||||
struct dhcp_netid {
|
||||
char *net;
|
||||
struct dhcp_netid *next;
|
||||
};
|
||||
|
||||
struct dhcp_config {
|
||||
unsigned int flags;
|
||||
int clid_len; /* length of client identifier */
|
||||
unsigned char *clid; /* clientid */
|
||||
unsigned char hwaddr[ETHER_ADDR_LEN];
|
||||
char *hostname, *netid;
|
||||
char *hostname;
|
||||
struct dhcp_netid netid;
|
||||
struct in_addr addr;
|
||||
unsigned int lease_time;
|
||||
struct dhcp_config *next;
|
||||
@@ -265,8 +271,9 @@ struct dhcp_opt {
|
||||
};
|
||||
|
||||
struct dhcp_vendor {
|
||||
int len;
|
||||
char *data, *net;
|
||||
int len, is_vendor, used;
|
||||
char *data;
|
||||
struct dhcp_netid netid;
|
||||
struct dhcp_vendor *next;
|
||||
};
|
||||
|
||||
@@ -274,7 +281,7 @@ struct dhcp_context {
|
||||
unsigned int lease_time;
|
||||
struct in_addr netmask, broadcast;
|
||||
struct in_addr start, end; /* range of available addresses */
|
||||
char *netid;
|
||||
struct dhcp_netid netid;
|
||||
struct dhcp_context *next;
|
||||
};
|
||||
|
||||
@@ -340,6 +347,7 @@ int check_for_bogus_wildcard(HEADER *header, unsigned int qlen, char *name,
|
||||
unsigned short rand16(void);
|
||||
int legal_char(char c);
|
||||
int canonicalise(char *s);
|
||||
int atoi_check(char *a, int *res);
|
||||
void die(char *message, char *arg1);
|
||||
void complain(char *message, char *arg1);
|
||||
void *safe_malloc(int size);
|
||||
|
||||
@@ -177,7 +177,7 @@ static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
unsigned int domainlen = strlen(serv->domain);
|
||||
if (namelen >= domainlen &&
|
||||
hostname_isequal(dnamebuff + namelen - domainlen, serv->domain) &&
|
||||
domainlen > matchlen)
|
||||
domainlen >= matchlen)
|
||||
{
|
||||
if (serv->flags & SERV_LITERAL_ADDRESS)
|
||||
{ /* flags gets set if server is in fact an answer */
|
||||
|
||||
@@ -109,7 +109,7 @@ void lease_update_from_configs(struct dhcp_config *dhcp_configs, char *domain)
|
||||
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
if ((config = find_config(dhcp_configs, NULL, lease->clid, lease->clid_len, lease->hwaddr, NULL)) &&
|
||||
(config->hostname))
|
||||
(config->flags & CONFIG_NAME))
|
||||
lease_set_hostname(lease, config->hostname, domain);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ void lease_update_file(int force, time_t now)
|
||||
expires, lease->hwaddr[0], lease->hwaddr[1],
|
||||
lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
|
||||
lease->hwaddr[5], inet_ntoa(lease->addr),
|
||||
lease->hostname ? lease->hostname : "*");
|
||||
lease->hostname && strlen(lease->hostname) != 0 ? lease->hostname : "*");
|
||||
|
||||
if (lease->clid_len)
|
||||
{
|
||||
@@ -311,7 +311,7 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix)
|
||||
struct dhcp_lease *lease_tmp;
|
||||
char *new_name = NULL, *new_fqdn = NULL;
|
||||
|
||||
if (lease->hostname && name && strcmp(lease->hostname, name) == 0)
|
||||
if (lease->hostname && name && hostname_isequal(lease->hostname, name))
|
||||
return;
|
||||
|
||||
if (!name && !lease->hostname)
|
||||
|
||||
74
src/option.c
74
src/option.c
@@ -21,7 +21,7 @@ struct myoption {
|
||||
int val;
|
||||
};
|
||||
|
||||
#define OPTSTRING "ZDNLERzowefnbvhdqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:"
|
||||
#define OPTSTRING "ZDNLERzowefnbvhdqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:"
|
||||
|
||||
static struct myoption opts[] = {
|
||||
{"version", 0, 0, 'v'},
|
||||
@@ -71,6 +71,7 @@ static struct myoption opts[] = {
|
||||
{"read-ethers", 0, 0, 'Z' },
|
||||
{"alias", 1, 0, 'V' },
|
||||
{"dhcp-vendorclass", 1, 0, 'U'},
|
||||
{"dhcp-userclass", 1, 0, 'j'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -121,6 +122,7 @@ static char *usage =
|
||||
"-H, --addn-hosts=path Specify a hosts file to be read in addition to " HOSTSFILE ".\n"
|
||||
"-i, --interface=interface Specify interface(s) to listen on.\n"
|
||||
"-I, --except-interface=int Specify interface(s) NOT to listen on.\n"
|
||||
"-j, --dhcp-userclass=<id>,<class> Map DHCP user class to option set.\n"
|
||||
"-l, --dhcp-leasefile=path Specify where to store DHCP leases (defaults to " LEASEFILE ").\n"
|
||||
"-L, --localmx Return MX records for local hosts.\n"
|
||||
"-m, --mx-host=host_name Specify the MX name to reply to.\n"
|
||||
@@ -474,11 +476,15 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
optarg++;
|
||||
while ((end = strchr(optarg, '/')))
|
||||
{
|
||||
char *domain;
|
||||
char *domain = NULL;
|
||||
*end = 0;
|
||||
if (!canonicalise(optarg))
|
||||
/* # matches everything and becomes a zero length domain string */
|
||||
if (strcmp(optarg, "#") == 0)
|
||||
domain = "";
|
||||
else if (!canonicalise(optarg))
|
||||
option = '?';
|
||||
domain = safe_string_alloc(optarg); /* NULL if strlen is zero */
|
||||
else
|
||||
domain = safe_string_alloc(optarg); /* NULL if strlen is zero */
|
||||
serv = safe_malloc(sizeof(struct server));
|
||||
serv->next = newlist;
|
||||
newlist = serv;
|
||||
@@ -527,14 +533,16 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
if ((portno = strchr(source+1, '#')))
|
||||
{
|
||||
*portno = 0;
|
||||
source_port = atoi(portno+1);
|
||||
if (!atoi_check(portno+1, &source_port))
|
||||
option = '?';
|
||||
}
|
||||
}
|
||||
|
||||
if ((portno = strchr(optarg, '#'))) /* is there a port no. */
|
||||
{
|
||||
*portno = 0;
|
||||
serv_port = atoi(portno+1);
|
||||
if (!atoi_check(portno+1, &serv_port))
|
||||
option = '?';
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -614,32 +622,46 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
|
||||
case 'c':
|
||||
{
|
||||
int size = atoi(optarg);
|
||||
/* zero is OK, and means no caching. */
|
||||
int size;
|
||||
if (!atoi_check(optarg, &size))
|
||||
option = '?';
|
||||
else
|
||||
{
|
||||
/* zero is OK, and means no caching. */
|
||||
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
else if (size > 10000)
|
||||
size = 10000;
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
else if (size > 10000)
|
||||
size = 10000;
|
||||
|
||||
*cachesize = size;
|
||||
*cachesize = size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
*port = atoi(optarg);
|
||||
if (!atoi_check(optarg, port))
|
||||
option = '?';
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
*query_port = atoi(optarg);
|
||||
if (!atoi_check(optarg, query_port))
|
||||
option = '?';
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
*local_ttl = (unsigned long)atoi(optarg);
|
||||
break;
|
||||
{
|
||||
int ttl;
|
||||
if (!atoi_check(optarg, &ttl))
|
||||
option = '?';
|
||||
else
|
||||
*local_ttl = (unsigned long)ttl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'X':
|
||||
*dhcp_max = atoi(optarg);
|
||||
if (!atoi_check(optarg, dhcp_max))
|
||||
option = '?';
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
@@ -652,7 +674,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
new->lease_time = DEFLEASE;
|
||||
new->netmask.s_addr = 0;
|
||||
new->broadcast.s_addr = 0;
|
||||
new->netid = NULL;
|
||||
new->netid.net = NULL;
|
||||
|
||||
|
||||
for (cp = optarg; *cp; cp++)
|
||||
@@ -662,7 +684,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
if (*cp != ',' && (comma = strchr(optarg, ',')))
|
||||
{
|
||||
*comma = 0;
|
||||
new->netid = safe_string_alloc(optarg);
|
||||
new->netid.net = safe_string_alloc(optarg);
|
||||
a[0] = comma + 1;
|
||||
}
|
||||
else
|
||||
@@ -807,7 +829,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
arg[3] == ':')
|
||||
{
|
||||
new->flags |= CONFIG_NETID;
|
||||
new->netid = safe_string_alloc(arg+4);
|
||||
new->netid.net = safe_string_alloc(arg+4);
|
||||
}
|
||||
else if (sscanf(a[j], "%x:%x:%x:%x:%x:%x",
|
||||
&e0, &e1, &e2, &e3, &e4, &e5) == 6)
|
||||
@@ -888,7 +910,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
if (new->flags & CONFIG_CLID)
|
||||
free(new->clid);
|
||||
if (new->flags & CONFIG_NETID)
|
||||
free(new->netid);
|
||||
free(new->netid.net);
|
||||
free(new);
|
||||
}
|
||||
else
|
||||
@@ -931,6 +953,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
if ((new->opt = atoi(optarg)) == 0)
|
||||
{
|
||||
option = '?';
|
||||
if (new->netid)
|
||||
free(new->netid);
|
||||
free(new);
|
||||
break;
|
||||
}
|
||||
@@ -960,7 +984,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
{
|
||||
is_dec = is_addr = 0;
|
||||
if (!((*cp >='A' && *cp <= 'F') ||
|
||||
(*cp >='a' && *cp <= 'F')))
|
||||
(*cp >='a' && *cp <= 'f')))
|
||||
is_hex = 0;
|
||||
}
|
||||
|
||||
@@ -1064,6 +1088,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
}
|
||||
|
||||
case 'U':
|
||||
case 'j':
|
||||
{
|
||||
char *comma;
|
||||
|
||||
@@ -1073,10 +1098,11 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
{
|
||||
struct dhcp_vendor *new = safe_malloc(sizeof(struct dhcp_vendor));
|
||||
*comma = 0;
|
||||
new->net = safe_string_alloc(optarg);
|
||||
new->netid.net = safe_string_alloc(optarg);
|
||||
new->len = strlen(comma+1);
|
||||
new->data = safe_malloc(new->len);
|
||||
memcpy(new->data, comma+1, new->len);
|
||||
new->is_vendor = (option == 'U');
|
||||
new->next = *dhcp_vendors;
|
||||
*dhcp_vendors = new;
|
||||
}
|
||||
|
||||
127
src/rfc2131.c
127
src/rfc2131.c
@@ -18,6 +18,10 @@
|
||||
#define BOOTREPLY 2
|
||||
#define DHCP_COOKIE 0x63825363
|
||||
|
||||
/* The Linux in-kernel DHCP client silently ignores any packet
|
||||
smaller than this. Sigh........... */
|
||||
#define MIN_PACKETSZ 300
|
||||
|
||||
#define OPTION_PAD 0
|
||||
#define OPTION_NETMASK 1
|
||||
#define OPTION_ROUTER 3
|
||||
@@ -37,6 +41,7 @@
|
||||
#define OPTION_T2 59
|
||||
#define OPTION_VENDOR_ID 60
|
||||
#define OPTION_CLIENT_ID 61
|
||||
#define OPTION_USER_CLASS 77
|
||||
#define OPTION_END 255
|
||||
|
||||
#define DHCPDISCOVER 1
|
||||
@@ -49,6 +54,7 @@
|
||||
#define DHCPINFORM 8
|
||||
|
||||
static unsigned char *option_put(unsigned char *p, unsigned char *end, int opt, int len, unsigned int val);
|
||||
static unsigned char *option_end(unsigned char *p, unsigned char *end, struct dhcp_packet *start);
|
||||
static unsigned char *option_put_string(unsigned char *p, unsigned char *end, int opt, char *string);
|
||||
static void bootp_option_put(struct dhcp_packet *mess, char *filename, char *sname);
|
||||
static int option_len(unsigned char *opt);
|
||||
@@ -64,7 +70,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
char *domainname, char *hostname,
|
||||
struct in_addr router,
|
||||
struct in_addr iface_addr,
|
||||
int iface_mtu, char *netid);
|
||||
int iface_mtu, struct dhcp_netid *netid);
|
||||
|
||||
static int have_config(struct dhcp_config *config, unsigned int mask)
|
||||
{
|
||||
@@ -84,6 +90,7 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
{
|
||||
unsigned char *opt, *clid;
|
||||
struct dhcp_lease *lease;
|
||||
struct dhcp_vendor *vendor;
|
||||
int clid_len;
|
||||
struct dhcp_packet *mess = &rawpacket->data;
|
||||
unsigned char *p = mess->options;
|
||||
@@ -94,7 +101,7 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
char *message = NULL;
|
||||
unsigned int renewal_time, expires_time, def_time;
|
||||
struct dhcp_config *config;
|
||||
char *netid;
|
||||
struct dhcp_netid *netid = NULL;
|
||||
struct in_addr addr;
|
||||
unsigned short fuzz = 0;
|
||||
|
||||
@@ -168,7 +175,11 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
hostname = NULL;
|
||||
}
|
||||
else
|
||||
*dot = 0; /* truncate */
|
||||
{
|
||||
*dot = 0; /* truncate */
|
||||
if (strlen(hostname) == 0)
|
||||
hostname = NULL; /* nothing left */
|
||||
}
|
||||
}
|
||||
/* search again now we have a hostname */
|
||||
config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, hostname);
|
||||
@@ -177,16 +188,56 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
|
||||
def_time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
||||
|
||||
netid = context->netid;
|
||||
if (have_config(config, CONFIG_NETID))
|
||||
netid = config->netid;
|
||||
else if ((opt = option_find(mess, sz, OPTION_VENDOR_ID)))
|
||||
if (context->netid.net)
|
||||
{
|
||||
struct dhcp_vendor *vendor;
|
||||
for (vendor = vendors; vendor; vendor = vendor->next)
|
||||
if (vendor->len == option_len(opt) &&
|
||||
memcmp(vendor->data, option_ptr(opt), vendor->len) == 0)
|
||||
netid = vendor->net;
|
||||
context->netid.next = netid;
|
||||
netid = &context->netid;
|
||||
}
|
||||
|
||||
if (have_config(config, CONFIG_NETID))
|
||||
{
|
||||
config->netid.next = netid;
|
||||
netid = &config->netid;
|
||||
}
|
||||
|
||||
/* Theres a chance that carefully chosen data could match the same
|
||||
vendor/user option twice and make a loop in the netid chain. */
|
||||
for (vendor = vendors; vendor; vendor = vendor->next)
|
||||
vendor->used = 0;
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_VENDOR_ID)))
|
||||
for (vendor = vendors; vendor; vendor = vendor->next)
|
||||
if (vendor->is_vendor && !vendor->used)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= (option_len(opt) - vendor->len); i++)
|
||||
if (memcmp(vendor->data, option_ptr(opt)+i, vendor->len) == 0)
|
||||
{
|
||||
vendor->used = 1;
|
||||
vendor->netid.next = netid;
|
||||
netid = &vendor->netid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_USER_CLASS)))
|
||||
{
|
||||
unsigned char *ucp = option_ptr(opt);
|
||||
int j;
|
||||
for (j = 0; j < option_len(opt); j += ucp[j] + 1)
|
||||
for (vendor = vendors; vendor; vendor = vendor->next)
|
||||
if (!vendor->is_vendor && !vendor->used)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= (ucp[j] - vendor->len); i++)
|
||||
if (memcmp(vendor->data, &ucp[j+i+1], vendor->len) == 0)
|
||||
{
|
||||
vendor->used = 1;
|
||||
vendor->netid.next = netid;
|
||||
netid = &vendor->netid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Can have setting to ignore the client ID for a particular MAC address or hostname */
|
||||
@@ -316,7 +367,7 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
}
|
||||
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||
NULL, router, iface_addr, iface_mtu, netid);
|
||||
p = option_put(p, end, OPTION_END, 0, 0);
|
||||
p = option_end(p, end, mess);
|
||||
|
||||
log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
||||
return p - (unsigned char *)mess;
|
||||
@@ -385,7 +436,7 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
bootp_option_put(mess, NULL, NULL);
|
||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
|
||||
p = option_put_string(p, end, OPTION_MESSAGE, message);
|
||||
p = option_put(p, end, OPTION_END, 0, 0);
|
||||
p = option_end(p, end, mess);
|
||||
mess->flags |= htons(0x8000); /* broadcast */
|
||||
return p - (unsigned char *)mess;
|
||||
}
|
||||
@@ -393,7 +444,8 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
log_packet("ACK", &mess->yiaddr, mess->chaddr, iface_name, hostname);
|
||||
|
||||
lease_set_hwaddr(lease, mess->chaddr);
|
||||
lease_set_hostname(lease, hostname, domain_suffix);
|
||||
if (hostname)
|
||||
lease_set_hostname(lease, hostname, domain_suffix);
|
||||
lease_set_expires(lease, renewal_time == 0xffffffff ? 0 : now + (time_t)renewal_time);
|
||||
|
||||
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
||||
@@ -408,7 +460,7 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
}
|
||||
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||
hostname, router, iface_addr, iface_mtu, netid);
|
||||
p = option_put(p, end, OPTION_END, 0, 0);
|
||||
p = option_end(p, end, mess);
|
||||
return p - (unsigned char *)mess;
|
||||
|
||||
case DHCPINFORM:
|
||||
@@ -424,7 +476,7 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
||||
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||
hostname, router, iface_addr, iface_mtu, netid);
|
||||
p = option_put(p, end, OPTION_END, 0, 0);
|
||||
p = option_end(p, end, mess);
|
||||
|
||||
log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname);
|
||||
return p - (unsigned char *)mess;
|
||||
@@ -494,20 +546,26 @@ static unsigned char *option_put(unsigned char *p, unsigned char *end, int opt,
|
||||
int i;
|
||||
|
||||
/* always keep one octet space for the END option. */
|
||||
if ((opt == OPTION_END) || (p + len + 3 < end))
|
||||
if (p + len + 3 < end)
|
||||
{
|
||||
*(p++) = opt;
|
||||
if (opt != OPTION_END)
|
||||
{
|
||||
*(p++) = len;
|
||||
*(p++) = len;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
*(p++) = val >> (8 * (len - (i + 1)));
|
||||
}
|
||||
for (i = 0; i < len; i++)
|
||||
*(p++) = val >> (8 * (len - (i + 1)));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static unsigned char *option_end(unsigned char *p, unsigned char *end, struct dhcp_packet *start)
|
||||
{
|
||||
*(p++) = OPTION_END;
|
||||
while ((p < end) && (p - ((unsigned char *)start) < MIN_PACKETSZ))
|
||||
*p++ = 0;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static unsigned char *option_put_string(unsigned char *p, unsigned char *end, int opt, char *string)
|
||||
{
|
||||
if (p + strlen(string) + 3 < end)
|
||||
@@ -587,15 +645,24 @@ static int in_list(unsigned char *list, int opt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dhcp_opt *option_find2(char *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_netid *tmp1;
|
||||
|
||||
for (tmp = opts; tmp; tmp = tmp->next)
|
||||
if (tmp->opt == opt &&
|
||||
((!netid && !tmp->netid) ||
|
||||
(netid && tmp->netid && strcmp(tmp->netid, netid) == 0)))
|
||||
return tmp;
|
||||
if (tmp->opt == opt)
|
||||
{
|
||||
if (netid)
|
||||
{
|
||||
if (tmp->netid)
|
||||
for (tmp1 = netid; tmp1; tmp1 = tmp1->next)
|
||||
if (strcmp(tmp->netid, tmp1->net) == 0)
|
||||
return tmp;
|
||||
}
|
||||
else if (!tmp->netid)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
return netid ? option_find2(NULL, opts, opt) : NULL;
|
||||
}
|
||||
@@ -607,7 +674,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
char *domainname, char *hostname,
|
||||
struct in_addr router,
|
||||
struct in_addr iface_addr,
|
||||
int iface_mtu, char *netid)
|
||||
int iface_mtu, struct dhcp_netid *netid)
|
||||
{
|
||||
struct dhcp_opt *opt;
|
||||
|
||||
|
||||
26
src/util.c
26
src/util.c
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
|
||||
/* Code in this file contributed by Rob Funk. */
|
||||
/* Some code in this file contributed by Rob Funk. */
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
@@ -85,6 +85,18 @@ unsigned short rand16(void)
|
||||
return( (unsigned short) (rand() >> 15) );
|
||||
}
|
||||
|
||||
int atoi_check(char *a, int *res)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = a; *p; p++)
|
||||
if (*p < '0' || *p > '9')
|
||||
return 0;
|
||||
|
||||
*res = atoi(a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int legal_char(char c)
|
||||
{
|
||||
/* check for legal char a-z A-Z 0-9 -
|
||||
@@ -100,12 +112,18 @@ int legal_char(char c)
|
||||
|
||||
int canonicalise(char *s)
|
||||
{
|
||||
/* check for legal chars ans remove trailing . */
|
||||
/* check for legal chars and remove trailing .
|
||||
also fail empty string. */
|
||||
int l = strlen(s);
|
||||
char c;
|
||||
|
||||
if (l>0 && s[l-1] == '.')
|
||||
s[l-1] = 0;
|
||||
if (l == 0) return 0;
|
||||
|
||||
if (s[l-1] == '.')
|
||||
{
|
||||
if (l == 1) return 0;
|
||||
s[l-1] = 0;
|
||||
}
|
||||
|
||||
while ((c = *s++))
|
||||
if (c != '.' && !legal_char(c))
|
||||
|
||||
Reference in New Issue
Block a user