mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a222641cb0 | ||
|
|
a84fa1d085 |
No files matched your search
@@ -917,11 +917,89 @@ release 2.6
|
|||||||
line or preceded by whitespace. Thanks to Christian
|
line or preceded by whitespace. Thanks to Christian
|
||||||
Haggstrom for the bug report.
|
Haggstrom for the bug report.
|
||||||
|
|
||||||
|
release 2.7
|
||||||
|
Allow the dhcp-host specification of id:* which makes
|
||||||
|
dnsmasq ignore any client-id. This is useful to ensure
|
||||||
|
that a dual-boot machine sees the same lease when one OS
|
||||||
|
gives a client-id and the other doesn't. It's also useful
|
||||||
|
when PXE boot DHCP does not use client IDs but the OS it boots
|
||||||
|
does. Thanks to Grzegorz Nosek for suggesting this enhancement.
|
||||||
|
|
||||||
|
No longer assume that ciaddr is zero in received DHCPDISCOVER
|
||||||
|
messages, just for security against broken clients.
|
||||||
|
|
||||||
|
Set default of siaddr field to the address of the machine running
|
||||||
|
dnsmasq when not explicitly set using dhcp-boot
|
||||||
|
option. This is the ISC dhcpd behaviour.
|
||||||
|
|
||||||
|
Send T1 and T2 options in DHCPOFFER packets. This is required
|
||||||
|
by the DHCP client in some JetDirect printers. Thanks
|
||||||
|
to Paul Mattal for work on this.
|
||||||
|
|
||||||
|
Fixed bug with DHCP on OpenBSD reported by Dominique Jacquel.
|
||||||
|
The code which added loopback interfaces to the list
|
||||||
|
was confusing the DHCP code, which expected one interface only.
|
||||||
|
Solved by adding loopback interfaces to address list instead.
|
||||||
|
|
||||||
|
Add dhcp-vendorclass option to allow options to be sent only
|
||||||
|
to certain classes of clients.
|
||||||
|
|
||||||
|
Tweaked option search code so that if a netid-qualified
|
||||||
|
option is used, any unqualified option is ignored.
|
||||||
|
|
||||||
|
Changed the method of picking new dynamic IP
|
||||||
|
addresses. This used to use the next consecutive
|
||||||
|
address as long it was free, now it uses a hash
|
||||||
|
from the client hardware address. This reduces the amount
|
||||||
|
of address movement for clients which let their lease
|
||||||
|
expire and allows consecutive DHCPOFFERS to the same host
|
||||||
|
to (almost always) be for the same address, without
|
||||||
|
storing state before a lease is granted.
|
||||||
|
|
||||||
|
Tweaked option handling code to return all possible
|
||||||
|
options rather than none when DHCP "requested options"
|
||||||
|
field is missing. This fixes interoperability with
|
||||||
|
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.
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.6
|
Version: 2.8
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.6
|
Version: 2.8
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: Productivity/Networking/DNS/Servers
|
Group: Productivity/Networking/DNS/Servers
|
||||||
|
|||||||
@@ -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.
|
both IPv4 and IPv6 addresses for a domain, use repeated -A flags.
|
||||||
Note that /etc/hosts and DHCP leases override this for individual
|
Note that /etc/hosts and DHCP leases override this for individual
|
||||||
names. A common use of this is to redirect the entire doubleclick.net
|
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
|
.TP
|
||||||
.B \-m, --mx-host=<mx name>
|
.B \-m, --mx-host=<mx name>
|
||||||
Return an MX record named <mx name> pointing to the host specified in the --mx-target switch
|
Return an MX record named <mx name> pointing to the host specified in the --mx-target switch
|
||||||
@@ -283,7 +288,7 @@ addresses given via
|
|||||||
.B dhcp-host
|
.B dhcp-host
|
||||||
or from /etc/ethers will be served.
|
or from /etc/ethers will be served.
|
||||||
.TP
|
.TP
|
||||||
.B \-G, --dhcp-host=[[<hwaddr>]|[id:<client_id>]][net:<netid>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
.B \-G, --dhcp-host=[[<hwaddr>]|[id:[<client_id>][*]]][net:<netid>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||||
Specify per host parameters for the DHCP server. This allows a machine
|
Specify per host parameters for the DHCP server. This allows a machine
|
||||||
with a particular hardware address to be always allocated the same
|
with a particular hardware address to be always allocated the same
|
||||||
hostname, IP address and lease time. A hostname specified like this
|
hostname, IP address and lease time. A hostname specified like this
|
||||||
@@ -306,6 +311,9 @@ hardware addresses to identify hosts by prefixing with 'id:'. Thus:
|
|||||||
refers to the host with client identifier 01:02:03:04. It is also
|
refers to the host with client identifier 01:02:03:04. It is also
|
||||||
allowed to specify the client ID as text, like this:
|
allowed to specify the client ID as text, like this:
|
||||||
.B --dhcp-host=id:clientidastext,.....
|
.B --dhcp-host=id:clientidastext,.....
|
||||||
|
The special option id:* means "ignore any client-id
|
||||||
|
and use MAC addresses only." This is useful when a client presents a client-id sometimes
|
||||||
|
but not others.
|
||||||
If a name appears in /etc/hosts, the associated address can be
|
If a name appears in /etc/hosts, the associated address can be
|
||||||
allocated to a DHCP lease, but only if a
|
allocated to a DHCP lease, but only if a
|
||||||
.B --dhcp-host
|
.B --dhcp-host
|
||||||
@@ -340,7 +348,7 @@ specfied in RFC2132. For example, to set the default route option to
|
|||||||
192.168.4.4, do
|
192.168.4.4, do
|
||||||
.B --dhcp-option=3,192.168.4.4
|
.B --dhcp-option=3,192.168.4.4
|
||||||
and to set the time-server address to 192.168.0.4, do
|
and to set the time-server address to 192.168.0.4, do
|
||||||
.B dhcp-option=42,192.168.0.4
|
.B --dhcp-option=42,192.168.0.4
|
||||||
The special address 0.0.0.0 is taken to mean "the address of the
|
The special address 0.0.0.0 is taken to mean "the address of the
|
||||||
machine running dnsmasq". Data types allowed are comma seperated
|
machine running dnsmasq". Data types allowed are comma seperated
|
||||||
dotted-quad IP addresses, a decimal number, colon-seperated hex digits
|
dotted-quad IP addresses, a decimal number, colon-seperated hex digits
|
||||||
@@ -353,6 +361,27 @@ possible to generate the correct data type; 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.
|
||||||
.TP
|
.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 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>]]
|
.B \-M, --dhcp-boot=<filename>,[<servername>[,<server address>]]
|
||||||
Set BOOTP options to be returned by the DHCP server. These are needed
|
Set BOOTP options to be returned by the DHCP server. These are needed
|
||||||
for machines which network boot, and tell the machine where to collect
|
for machines which network boot, and tell the machine where to collect
|
||||||
|
|||||||
@@ -161,10 +161,24 @@ filterwin2k
|
|||||||
# address is 11:22:33:44:55:66
|
# address is 11:22:33:44:55:66
|
||||||
#dhcp-host=11:22:33:44:55:66,ignore
|
#dhcp-host=11:22:33:44:55:66,ignore
|
||||||
|
|
||||||
|
# Ignore any client-id presented by the machine with ethernet
|
||||||
|
# address 11:22:33:44:55:66. This is useful to prevent a machine
|
||||||
|
# being treated differently when running under different OS's or
|
||||||
|
# between PXE boot and OS boot.
|
||||||
|
#dhcp-host=11:22:33:44:55:66,id:*
|
||||||
|
|
||||||
# Send extra options which are tagged as "red" to
|
# Send extra options which are tagged as "red" to
|
||||||
# the machine with ethernet address 11:22:33:44:55:66
|
# the machine with ethernet address 11:22:33:44:55:66
|
||||||
#dhcp-host=11:22:33:44:55:66,net:red
|
#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
|
# 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
|
# on the ethernet-address/IP pairs found there just as if they had
|
||||||
# been given as --dhcp-host options. Useful if you keep
|
# been given as --dhcp-host options. Useful if you keep
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
/* Author's email: simon@thekelleys.org.uk */
|
/* Author's email: simon@thekelleys.org.uk */
|
||||||
|
|
||||||
#define VERSION "2.6"
|
#define VERSION "2.8"
|
||||||
|
|
||||||
#define FTABSIZ 150 /* max number of outstanding requests */
|
#define FTABSIZ 150 /* max number of outstanding requests */
|
||||||
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */
|
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */
|
||||||
|
|||||||
+26
-17
@@ -61,6 +61,7 @@ void dhcp_init(int *fdp, int* rfdp)
|
|||||||
|
|
||||||
void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
||||||
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
||||||
|
struct dhcp_vendor *vendors,
|
||||||
time_t now, char *namebuff, char *domain_suffix,
|
time_t now, char *namebuff, char *domain_suffix,
|
||||||
char *dhcp_file, char *dhcp_sname,
|
char *dhcp_file, char *dhcp_sname,
|
||||||
struct in_addr dhcp_next_server, int dhcp_fd, int raw_fd,
|
struct in_addr dhcp_next_server, int dhcp_fd, int raw_fd,
|
||||||
@@ -181,7 +182,7 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
/* we can use the interface netmask if either the packet came direct,
|
/* we can use the interface netmask if either the packet came direct,
|
||||||
or it came via a relay listening on the same network. This sounds unlikely,
|
or it came via a relay listening on the same network. This sounds unlikely,
|
||||||
but it happens with win4lin. */
|
but it happens with win4lin. */
|
||||||
if ((source.s_addr & iface_netmask.s_addr) != (iface_addr.s_addr & iface_netmask.s_addr))
|
if (!is_same_net(source, iface_addr, iface_netmask))
|
||||||
iface_netmask.s_addr = 0;
|
iface_netmask.s_addr = 0;
|
||||||
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
|
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
|
||||||
iface_broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
iface_broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||||
@@ -193,8 +194,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
struct in_addr netmask = context->netmask.s_addr ? context->netmask : iface_netmask;
|
struct in_addr netmask = context->netmask.s_addr ? context->netmask : iface_netmask;
|
||||||
|
|
||||||
if (netmask.s_addr &&
|
if (netmask.s_addr &&
|
||||||
(source.s_addr & netmask.s_addr) == (context->start.s_addr & netmask.s_addr) &&
|
is_same_net(source, context->start, netmask) &&
|
||||||
(source.s_addr & netmask.s_addr) == (context->end.s_addr & netmask.s_addr))
|
is_same_net(source, context->end, netmask))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +226,7 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
DHCP broadcast, either this machine or a relay. In the special case that the relay
|
DHCP broadcast, either this machine or a relay. In the special case that the relay
|
||||||
is on the same network as us, we set the default route to us, not the relay.
|
is on the same network as us, we set the default route to us, not the relay.
|
||||||
This is the win4lin scenario again. */
|
This is the win4lin scenario again. */
|
||||||
if ((source.s_addr & context->netmask.s_addr) == (iface_addr.s_addr & context->netmask.s_addr))
|
if (is_same_net(source, iface_addr, context->netmask))
|
||||||
router = iface_addr;
|
router = iface_addr;
|
||||||
else
|
else
|
||||||
router = source;
|
router = source;
|
||||||
@@ -233,8 +234,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
lease_prune(NULL, now); /* lose any expired leases */
|
lease_prune(NULL, now); /* lose any expired leases */
|
||||||
newlen = dhcp_reply(context, iface_addr, ifr.ifr_name, ifr.ifr_mtu,
|
newlen = dhcp_reply(context, iface_addr, ifr.ifr_name, ifr.ifr_mtu,
|
||||||
rawpacket, sz, now, namebuff,
|
rawpacket, sz, now, namebuff,
|
||||||
dhcp_opts, dhcp_configs, domain_suffix, dhcp_file,
|
dhcp_opts, dhcp_configs, vendors, domain_suffix,
|
||||||
dhcp_sname, dhcp_next_server, router);
|
dhcp_file, dhcp_sname, dhcp_next_server, router);
|
||||||
lease_update_file(0, now);
|
lease_update_file(0, now);
|
||||||
lease_update_dns();
|
lease_update_dns();
|
||||||
|
|
||||||
@@ -350,7 +351,6 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int address_available(struct dhcp_context *context, struct in_addr taddr)
|
int address_available(struct dhcp_context *context, struct in_addr taddr)
|
||||||
{
|
{
|
||||||
/* Check is an address is OK for this network, ie
|
/* Check is an address is OK for this network, ie
|
||||||
@@ -379,38 +379,47 @@ int address_available(struct dhcp_context *context, struct in_addr taddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
||||||
struct in_addr *addrp)
|
struct in_addr *addrp, unsigned char *hwaddr)
|
||||||
{
|
{
|
||||||
/* Find a free address: exlude anything in use and anything allocated to
|
/* Find a free address: exlude anything in use and anything allocated to
|
||||||
a particular hwaddr/clientid/hostname in our configuration */
|
a particular hwaddr/clientid/hostname in our configuration */
|
||||||
|
|
||||||
struct dhcp_config *config;
|
struct dhcp_config *config;
|
||||||
struct in_addr start = context->last;
|
struct in_addr start, addr ;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
/* start == end means no dynamic leases. */
|
/* start == end means no dynamic leases. */
|
||||||
if (context->end.s_addr == context->start.s_addr)
|
if (context->end.s_addr == context->start.s_addr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* pick a seed based on hwaddr then iterate until we find a free address. */
|
||||||
|
for (j = 0, i = 0; i < ETHER_ADDR_LEN; i++)
|
||||||
|
j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
|
||||||
|
|
||||||
|
start.s_addr = addr.s_addr =
|
||||||
|
htonl(ntohl(context->start.s_addr) +
|
||||||
|
(j % (ntohl(context->end.s_addr) - ntohl(context->start.s_addr))));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (context->last.s_addr == context->end.s_addr)
|
if (addr.s_addr == context->end.s_addr)
|
||||||
context->last = context->start;
|
addr = context->start;
|
||||||
else
|
else
|
||||||
context->last.s_addr = htonl(ntohl(context->last.s_addr) + 1);
|
addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
|
||||||
|
|
||||||
|
|
||||||
if (!lease_find_by_addr(context->last))
|
if (!lease_find_by_addr(addr))
|
||||||
{
|
{
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == context->last.s_addr)
|
if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!config)
|
if (!config)
|
||||||
{
|
{
|
||||||
*addrp = context->last;
|
*addrp = addr;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (context->last.s_addr != start.s_addr);
|
} while (addr.s_addr != start.s_addr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -421,7 +430,7 @@ static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *
|
|||||||
return 1;
|
return 1;
|
||||||
if (!(config->flags & CONFIG_ADDR))
|
if (!(config->flags & CONFIG_ADDR))
|
||||||
return 1;
|
return 1;
|
||||||
if ((config->addr.s_addr & context->netmask.s_addr) == (context->start.s_addr & context->netmask.s_addr))
|
if (is_same_net(config->addr, context->start, context->netmask))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+10
-9
@@ -66,6 +66,7 @@ int main (int argc, char **argv)
|
|||||||
struct dhcp_context *dhcp_tmp, *dhcp = NULL;
|
struct dhcp_context *dhcp_tmp, *dhcp = NULL;
|
||||||
struct dhcp_config *dhcp_configs = NULL;
|
struct dhcp_config *dhcp_configs = NULL;
|
||||||
struct dhcp_opt *dhcp_options = NULL;
|
struct dhcp_opt *dhcp_options = NULL;
|
||||||
|
struct dhcp_vendor *dhcp_vendors = NULL;
|
||||||
char *dhcp_file = NULL, *dhcp_sname = NULL;
|
char *dhcp_file = NULL, *dhcp_sname = NULL;
|
||||||
struct in_addr dhcp_next_server;
|
struct in_addr dhcp_next_server;
|
||||||
int leasefd = -1, dhcpfd = -1, dhcp_raw_fd = -1;
|
int leasefd = -1, dhcpfd = -1, dhcp_raw_fd = -1;
|
||||||
@@ -109,16 +110,10 @@ int main (int argc, char **argv)
|
|||||||
&username, &groupname, &domain_suffix, &runfile,
|
&username, &groupname, &domain_suffix, &runfile,
|
||||||
&if_names, &if_addrs, &if_except, &bogus_addr,
|
&if_names, &if_addrs, &if_except, &bogus_addr,
|
||||||
&serv_addrs, &cachesize, &port, &query_port, &local_ttl, &addn_hosts,
|
&serv_addrs, &cachesize, &port, &query_port, &local_ttl, &addn_hosts,
|
||||||
&dhcp, &dhcp_configs, &dhcp_options,
|
&dhcp, &dhcp_configs, &dhcp_options, &dhcp_vendors,
|
||||||
&dhcp_file, &dhcp_sname, &dhcp_next_server, &maxleases, &min_leasetime,
|
&dhcp_file, &dhcp_sname, &dhcp_next_server, &maxleases, &min_leasetime,
|
||||||
&doctors);
|
&doctors);
|
||||||
|
|
||||||
/* if we cannot support binding the wildcard address, set the "bind only
|
|
||||||
interfaces in use" option */
|
|
||||||
#ifndef HAVE_UDP_SRC_DST
|
|
||||||
options |= OPT_NOWILD;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!lease_file)
|
if (!lease_file)
|
||||||
{
|
{
|
||||||
if (dhcp)
|
if (dhcp)
|
||||||
@@ -129,7 +124,13 @@ int main (int argc, char **argv)
|
|||||||
die("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h", NULL);
|
die("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h", NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
interfaces = enumerate_interfaces(if_names, if_addrs, if_except, port);
|
#ifndef HAVE_UDP_SRC_DST
|
||||||
|
/* if we cannot support binding the wildcard address, set the "bind only
|
||||||
|
interfaces in use" option */
|
||||||
|
options |= OPT_NOWILD;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
interfaces = enumerate_interfaces(&if_names, &if_addrs, if_except, port);
|
||||||
if (options & OPT_NOWILD)
|
if (options & OPT_NOWILD)
|
||||||
listeners = create_bound_listeners(interfaces);
|
listeners = create_bound_listeners(interfaces);
|
||||||
else
|
else
|
||||||
@@ -397,7 +398,7 @@ int main (int argc, char **argv)
|
|||||||
dnamebuff, last_server, bogus_addr, doctors);
|
dnamebuff, last_server, bogus_addr, doctors);
|
||||||
|
|
||||||
if (dhcp && FD_ISSET(dhcpfd, &rset))
|
if (dhcp && FD_ISSET(dhcpfd, &rset))
|
||||||
dhcp_packet(dhcp, packet, dhcp_options, dhcp_configs,
|
dhcp_packet(dhcp, packet, dhcp_options, dhcp_configs, dhcp_vendors,
|
||||||
now, dnamebuff, domain_suffix, dhcp_file,
|
now, dnamebuff, domain_suffix, dhcp_file,
|
||||||
dhcp_sname, dhcp_next_server, dhcpfd, dhcp_raw_fd,
|
dhcp_sname, dhcp_next_server, dhcpfd, dhcp_raw_fd,
|
||||||
if_names, if_addrs, if_except);
|
if_names, if_addrs, if_except);
|
||||||
|
|||||||
+31
-9
@@ -130,7 +130,7 @@ struct crec {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define F_IMMORTAL 1
|
#define F_IMMORTAL 1
|
||||||
#define F_CONFIG 2
|
#define F_CONFIG 2
|
||||||
#define F_REVERSE 4
|
#define F_REVERSE 4
|
||||||
#define F_FORWARD 8
|
#define F_FORWARD 8
|
||||||
#define F_DHCP 16
|
#define F_DHCP 16
|
||||||
@@ -237,12 +237,18 @@ struct dhcp_lease {
|
|||||||
struct dhcp_lease *next;
|
struct dhcp_lease *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dhcp_netid {
|
||||||
|
char *net;
|
||||||
|
struct dhcp_netid *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct dhcp_config {
|
struct dhcp_config {
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int clid_len; /* length of client identifier */
|
int clid_len; /* length of client identifier */
|
||||||
unsigned char *clid; /* clientid */
|
unsigned char *clid; /* clientid */
|
||||||
unsigned char hwaddr[ETHER_ADDR_LEN];
|
unsigned char hwaddr[ETHER_ADDR_LEN];
|
||||||
char *hostname, *netid;
|
char *hostname;
|
||||||
|
struct dhcp_netid netid;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
unsigned int lease_time;
|
unsigned int lease_time;
|
||||||
struct dhcp_config *next;
|
struct dhcp_config *next;
|
||||||
@@ -255,19 +261,27 @@ struct dhcp_config {
|
|||||||
#define CONFIG_NAME 16
|
#define CONFIG_NAME 16
|
||||||
#define CONFIG_ADDR 32
|
#define CONFIG_ADDR 32
|
||||||
#define CONFIG_NETID 64
|
#define CONFIG_NETID 64
|
||||||
|
#define CONFIG_NOCLID 128
|
||||||
|
|
||||||
struct dhcp_opt {
|
struct dhcp_opt {
|
||||||
int opt, len, is_addr;
|
int opt, len, is_addr;
|
||||||
unsigned char *val;
|
unsigned char *val;
|
||||||
char *netid;
|
char *netid;
|
||||||
struct dhcp_opt *next;
|
struct dhcp_opt *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dhcp_vendor {
|
||||||
|
int len, is_vendor, used;
|
||||||
|
char *data;
|
||||||
|
struct dhcp_netid netid;
|
||||||
|
struct dhcp_vendor *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct dhcp_context {
|
struct dhcp_context {
|
||||||
unsigned int lease_time;
|
unsigned int lease_time;
|
||||||
struct in_addr netmask, broadcast;
|
struct in_addr netmask, broadcast;
|
||||||
struct in_addr start, end, last; /* range of available addresses */
|
struct in_addr start, end; /* range of available addresses */
|
||||||
char *netid;
|
struct dhcp_netid netid;
|
||||||
struct dhcp_context *next;
|
struct dhcp_context *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -333,6 +347,7 @@ int check_for_bogus_wildcard(HEADER *header, unsigned int qlen, char *name,
|
|||||||
unsigned short rand16(void);
|
unsigned short rand16(void);
|
||||||
int legal_char(char c);
|
int legal_char(char c);
|
||||||
int canonicalise(char *s);
|
int canonicalise(char *s);
|
||||||
|
int atoi_check(char *a, int *res);
|
||||||
void die(char *message, char *arg1);
|
void die(char *message, char *arg1);
|
||||||
void complain(char *message, char *arg1);
|
void complain(char *message, char *arg1);
|
||||||
void *safe_malloc(int size);
|
void *safe_malloc(int size);
|
||||||
@@ -341,6 +356,8 @@ int sa_len(union mysockaddr *addr);
|
|||||||
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
||||||
int hostname_isequal(unsigned char *a, unsigned char *b);
|
int hostname_isequal(unsigned char *a, unsigned char *b);
|
||||||
time_t dnsmasq_time(int fd);
|
time_t dnsmasq_time(int fd);
|
||||||
|
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
|
||||||
|
|
||||||
/* option.c */
|
/* option.c */
|
||||||
unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resolv_file,
|
unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resolv_file,
|
||||||
char **mxname, char **mxtarget, char **lease_file,
|
char **mxname, char **mxtarget, char **lease_file,
|
||||||
@@ -349,7 +366,8 @@ unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resol
|
|||||||
struct iname **if_names, struct iname **if_addrs, struct iname **if_except,
|
struct iname **if_names, struct iname **if_addrs, struct iname **if_except,
|
||||||
struct bogus_addr **bogus_addr, struct server **serv_addrs, int *cachesize,
|
struct bogus_addr **bogus_addr, struct server **serv_addrs, int *cachesize,
|
||||||
int *port, int *query_port, unsigned long *local_ttl, char **addn_hosts,
|
int *port, int *query_port, unsigned long *local_ttl, char **addn_hosts,
|
||||||
struct dhcp_context **dhcp, struct dhcp_config **dhcp_conf, struct dhcp_opt **opts,
|
struct dhcp_context **dhcp, struct dhcp_config **dhcp_conf,
|
||||||
|
struct dhcp_opt **opts, struct dhcp_vendor **dhcp_vendors,
|
||||||
char **dhcp_file, char **dhcp_sname, struct in_addr *dhcp_next_server,
|
char **dhcp_file, char **dhcp_sname, struct in_addr *dhcp_next_server,
|
||||||
int *maxleases, unsigned int *min_leasetime, struct doctor **doctors);
|
int *maxleases, unsigned int *min_leasetime, struct doctor **doctors);
|
||||||
|
|
||||||
@@ -367,8 +385,8 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
|
|||||||
/* network.c */
|
/* network.c */
|
||||||
struct server *reload_servers(char *fname, char *buff, struct server *servers, int query_port);
|
struct server *reload_servers(char *fname, char *buff, struct server *servers, int query_port);
|
||||||
struct server *check_servers(struct server *new, struct irec *interfaces, struct serverfd **sfds);
|
struct server *check_servers(struct server *new, struct irec *interfaces, struct serverfd **sfds);
|
||||||
struct irec *enumerate_interfaces(struct iname *names,
|
struct irec *enumerate_interfaces(struct iname **names,
|
||||||
struct iname *addrs,
|
struct iname **addrs,
|
||||||
struct iname *except,
|
struct iname *except,
|
||||||
int port);
|
int port);
|
||||||
struct listener *create_wildcard_listeners(int port);
|
struct listener *create_wildcard_listeners(int port);
|
||||||
@@ -377,13 +395,14 @@ struct listener *create_bound_listeners(struct irec *interfaces);
|
|||||||
void dhcp_init(int *fdp, int* rfdp);
|
void dhcp_init(int *fdp, int* rfdp);
|
||||||
void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
||||||
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
||||||
|
struct dhcp_vendor *vendors,
|
||||||
time_t now, char *namebuff, char *domain_suffix,
|
time_t now, char *namebuff, char *domain_suffix,
|
||||||
char *dhcp_file, char *dhcp_sname,
|
char *dhcp_file, char *dhcp_sname,
|
||||||
struct in_addr dhcp_next_server, int dhcp_fd, int raw_fd,
|
struct in_addr dhcp_next_server, int dhcp_fd, int raw_fd,
|
||||||
struct iname *names, struct iname *addrs, struct iname *except);
|
struct iname *names, struct iname *addrs, struct iname *except);
|
||||||
int address_available(struct dhcp_context *context, struct in_addr addr);
|
int address_available(struct dhcp_context *context, struct in_addr addr);
|
||||||
int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
||||||
struct in_addr *addrp);
|
struct in_addr *addrp, unsigned char *hwaddr);
|
||||||
struct dhcp_config *find_config(struct dhcp_config *configs,
|
struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||||
struct dhcp_context *context,
|
struct dhcp_context *context,
|
||||||
unsigned char *clid, int clid_len,
|
unsigned char *clid, int clid_len,
|
||||||
@@ -391,6 +410,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
struct dhcp_config *read_ethers(struct dhcp_config *configs, char *buff);
|
struct dhcp_config *read_ethers(struct dhcp_config *configs, char *buff);
|
||||||
void dhcp_update_configs(struct dhcp_config *configs);
|
void dhcp_update_configs(struct dhcp_config *configs);
|
||||||
struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff);
|
struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff);
|
||||||
|
|
||||||
/* lease.c */
|
/* lease.c */
|
||||||
void lease_update_file(int force, time_t now);
|
void lease_update_file(int force, time_t now);
|
||||||
void lease_update_dns(void);
|
void lease_update_dns(void);
|
||||||
@@ -404,6 +424,7 @@ struct dhcp_lease *lease_find_by_client(unsigned char *clid, int clid_len);
|
|||||||
struct dhcp_lease *lease_find_by_addr(struct in_addr addr);
|
struct dhcp_lease *lease_find_by_addr(struct in_addr addr);
|
||||||
void lease_prune(struct dhcp_lease *target, time_t now);
|
void lease_prune(struct dhcp_lease *target, time_t now);
|
||||||
void lease_update_from_configs(struct dhcp_config *dhcp_configs, char *domain);
|
void lease_update_from_configs(struct dhcp_config *dhcp_configs, char *domain);
|
||||||
|
|
||||||
/* rfc2131.c */
|
/* rfc2131.c */
|
||||||
int dhcp_reply(struct dhcp_context *context,
|
int dhcp_reply(struct dhcp_context *context,
|
||||||
struct in_addr iface_addr,
|
struct in_addr iface_addr,
|
||||||
@@ -412,6 +433,7 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
struct udp_dhcp_packet *rawpacket,
|
struct udp_dhcp_packet *rawpacket,
|
||||||
unsigned int sz, time_t now, char *namebuff,
|
unsigned int sz, time_t now, char *namebuff,
|
||||||
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
||||||
|
struct dhcp_vendor *vendors,
|
||||||
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
|
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
|
||||||
struct in_addr dhcp_next_server, struct in_addr router);
|
struct in_addr dhcp_next_server, struct in_addr router);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -177,7 +177,7 @@ static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
unsigned int domainlen = strlen(serv->domain);
|
unsigned int domainlen = strlen(serv->domain);
|
||||||
if (namelen >= domainlen &&
|
if (namelen >= domainlen &&
|
||||||
hostname_isequal(dnamebuff + namelen - domainlen, serv->domain) &&
|
hostname_isequal(dnamebuff + namelen - domainlen, serv->domain) &&
|
||||||
domainlen > matchlen)
|
domainlen >= matchlen)
|
||||||
{
|
{
|
||||||
if (serv->flags & SERV_LITERAL_ADDRESS)
|
if (serv->flags & SERV_LITERAL_ADDRESS)
|
||||||
{ /* flags gets set if server is in fact an answer */
|
{ /* flags gets set if server is in fact an answer */
|
||||||
|
|||||||
+3
-3
@@ -109,7 +109,7 @@ void lease_update_from_configs(struct dhcp_config *dhcp_configs, char *domain)
|
|||||||
|
|
||||||
for (lease = leases; lease; lease = lease->next)
|
for (lease = leases; lease; lease = lease->next)
|
||||||
if ((config = find_config(dhcp_configs, NULL, lease->clid, lease->clid_len, lease->hwaddr, NULL)) &&
|
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);
|
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],
|
expires, lease->hwaddr[0], lease->hwaddr[1],
|
||||||
lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
|
lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
|
||||||
lease->hwaddr[5], inet_ntoa(lease->addr),
|
lease->hwaddr[5], inet_ntoa(lease->addr),
|
||||||
lease->hostname ? lease->hostname : "*");
|
lease->hostname && strlen(lease->hostname) != 0 ? lease->hostname : "*");
|
||||||
|
|
||||||
if (lease->clid_len)
|
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;
|
struct dhcp_lease *lease_tmp;
|
||||||
char *new_name = NULL, *new_fqdn = NULL;
|
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;
|
return;
|
||||||
|
|
||||||
if (!name && !lease->hostname)
|
if (!name && !lease->hostname)
|
||||||
|
|||||||
+28
-25
@@ -25,7 +25,7 @@ static struct irec *add_iface(struct irec *list, char *name, union mysockaddr *a
|
|||||||
if (except)
|
if (except)
|
||||||
for (tmp = except; tmp; tmp = tmp->next)
|
for (tmp = except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && strcmp(tmp->name, name) == 0)
|
if (tmp->name && strcmp(tmp->name, name) == 0)
|
||||||
return NULL;
|
return list;
|
||||||
|
|
||||||
/* we may need to check the whitelist */
|
/* we may need to check the whitelist */
|
||||||
if (names || addrs)
|
if (names || addrs)
|
||||||
@@ -38,31 +38,31 @@ static struct irec *add_iface(struct irec *list, char *name, union mysockaddr *a
|
|||||||
if (sockaddr_isequal(&tmp->addr, addr))
|
if (sockaddr_isequal(&tmp->addr, addr))
|
||||||
break;
|
break;
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return NULL;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check whether the interface IP has been added already
|
/* check whether the interface IP has been added already
|
||||||
it is possible to have multiple interfaces with the same address */
|
it is possible to have multiple interfaces with the same address */
|
||||||
for (; list; list = list->next)
|
for (iface = list; iface; iface = iface->next)
|
||||||
if (sockaddr_isequal(&list->addr, addr))
|
if (sockaddr_isequal(&iface->addr, addr))
|
||||||
break;
|
break;
|
||||||
if (list)
|
if (iface)
|
||||||
return NULL;
|
return list;
|
||||||
|
|
||||||
/* If OK, add it to the head of the list */
|
/* If OK, add it to the head of the list */
|
||||||
iface = safe_malloc(sizeof(struct irec));
|
iface = safe_malloc(sizeof(struct irec));
|
||||||
iface->addr = *addr;
|
iface->addr = *addr;
|
||||||
|
iface->next = list;
|
||||||
return iface;
|
return iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct irec *enumerate_interfaces(struct iname *names,
|
struct irec *enumerate_interfaces(struct iname **names,
|
||||||
struct iname *addrs,
|
struct iname **addrs,
|
||||||
struct iname *except,
|
struct iname *except,
|
||||||
int port)
|
int port)
|
||||||
{
|
{
|
||||||
struct irec *iface = NULL, *new;
|
struct irec *iface = NULL;
|
||||||
char *buf, *ptr;
|
char *buf, *ptr;
|
||||||
struct ifreq *ifr = NULL;
|
struct ifreq *ifr = NULL;
|
||||||
struct ifconf ifc;
|
struct ifconf ifc;
|
||||||
@@ -137,21 +137,18 @@ struct irec *enumerate_interfaces(struct iname *names,
|
|||||||
die("ioctl error getting interface flags: %m", NULL);
|
die("ioctl error getting interface flags: %m", NULL);
|
||||||
|
|
||||||
/* If we are restricting the set of interfaces to use, make
|
/* If we are restricting the set of interfaces to use, make
|
||||||
sure that loopback interfaces are in that set. */
|
sure that loopback interfaces are in that set. Note that
|
||||||
if (names && (ifr->ifr_flags & IFF_LOOPBACK))
|
this is done as addresses rather than interface names so
|
||||||
|
as not to confuse the no-IPRECVIF workaround on the DHCP code */
|
||||||
|
if (*names && (ifr->ifr_flags & IFF_LOOPBACK))
|
||||||
{
|
{
|
||||||
struct iname *lo = safe_malloc(sizeof(struct iname));
|
struct iname *lo = safe_malloc(sizeof(struct iname));
|
||||||
lo->name = safe_string_alloc(ifr->ifr_name);
|
lo->addr = addr;
|
||||||
lo->next = names->next;
|
lo->next = *addrs;
|
||||||
names->next = lo;
|
*addrs = lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((new = add_iface(iface, ifr->ifr_name,
|
iface = add_iface(iface, ifr->ifr_name, &addr, *names, *addrs, except);
|
||||||
&addr, names, addrs, except)))
|
|
||||||
{
|
|
||||||
new->next = iface;
|
|
||||||
iface = new;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
|
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
|
||||||
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
|
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
|
||||||
@@ -194,11 +191,17 @@ struct irec *enumerate_interfaces(struct iname *names,
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found && (new = add_iface(iface, ifr->ifr_name,
|
if (found)
|
||||||
&addr6, names, addrs, except)))
|
|
||||||
{
|
{
|
||||||
new->next = iface;
|
if (*names && (ifr->ifr_flags & IFF_LOOPBACK))
|
||||||
iface = new;
|
{
|
||||||
|
struct iname *lo = safe_malloc(sizeof(struct iname));
|
||||||
|
lo->addr = addr6;
|
||||||
|
lo->next = *addrs;
|
||||||
|
*addrs = lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = add_iface(iface, ifr->ifr_name, &addr6, *names, *addrs, except);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* LINUX */
|
#endif /* LINUX */
|
||||||
|
|||||||
+110
-58
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000 - 2003 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000 - 2004 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -21,7 +21,7 @@ struct myoption {
|
|||||||
int val;
|
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:"
|
#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[] = {
|
static struct myoption opts[] = {
|
||||||
{"version", 0, 0, 'v'},
|
{"version", 0, 0, 'v'},
|
||||||
@@ -70,6 +70,8 @@ static struct myoption opts[] = {
|
|||||||
{"bind-interfaces", 0, 0, 'z'},
|
{"bind-interfaces", 0, 0, 'z'},
|
||||||
{"read-ethers", 0, 0, 'Z' },
|
{"read-ethers", 0, 0, 'Z' },
|
||||||
{"alias", 1, 0, 'V' },
|
{"alias", 1, 0, 'V' },
|
||||||
|
{"dhcp-vendorclass", 1, 0, 'U'},
|
||||||
|
{"dhcp-userclass", 1, 0, 'j'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -120,6 +122,7 @@ static char *usage =
|
|||||||
"-H, --addn-hosts=path Specify a hosts file to be read in addition to " HOSTSFILE ".\n"
|
"-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, --interface=interface Specify interface(s) to listen on.\n"
|
||||||
"-I, --except-interface=int Specify interface(s) NOT 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, --dhcp-leasefile=path Specify where to store DHCP leases (defaults to " LEASEFILE ").\n"
|
||||||
"-L, --localmx Return MX records for local hosts.\n"
|
"-L, --localmx Return MX records for local hosts.\n"
|
||||||
"-m, --mx-host=host_name Specify the MX name to reply to.\n"
|
"-m, --mx-host=host_name Specify the MX name to reply to.\n"
|
||||||
@@ -139,6 +142,7 @@ static char *usage =
|
|||||||
"-t, --mx-target=host_name Specify the host in an MX reply.\n"
|
"-t, --mx-target=host_name Specify the host in an MX reply.\n"
|
||||||
"-T, --local-ttl=time Specify time-to-live in seconds for replies from /etc/hosts.\n"
|
"-T, --local-ttl=time Specify time-to-live in seconds for replies from /etc/hosts.\n"
|
||||||
"-u, --user=username Change to this user after startup. (defaults to " CHUSER ").\n"
|
"-u, --user=username Change to this user after startup. (defaults to " CHUSER ").\n"
|
||||||
|
"-U, --dhcp-vendorclass=<id>,<class> Map DHCP vendor class to option set.\n"
|
||||||
"-v, --version Display dnsmasq version.\n"
|
"-v, --version Display dnsmasq version.\n"
|
||||||
"-V, --alias=addr,addr,mask Translate IPv4 addresses from upstream servers.\n"
|
"-V, --alias=addr,addr,mask Translate IPv4 addresses from upstream servers.\n"
|
||||||
"-w, --help Display this message.\n"
|
"-w, --help Display this message.\n"
|
||||||
@@ -155,7 +159,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
struct iname **if_names, struct iname **if_addrs, struct iname **if_except,
|
struct iname **if_names, struct iname **if_addrs, struct iname **if_except,
|
||||||
struct bogus_addr **bogus_addr, struct server **serv_addrs, int *cachesize, int *port,
|
struct bogus_addr **bogus_addr, struct server **serv_addrs, int *cachesize, int *port,
|
||||||
int *query_port, unsigned long *local_ttl, char **addn_hosts, struct dhcp_context **dhcp,
|
int *query_port, unsigned long *local_ttl, char **addn_hosts, struct dhcp_context **dhcp,
|
||||||
struct dhcp_config **dhcp_conf, struct dhcp_opt **dhcp_opts, char **dhcp_file,
|
struct dhcp_config **dhcp_conf, struct dhcp_opt **dhcp_opts, struct dhcp_vendor **dhcp_vendors, char **dhcp_file,
|
||||||
char **dhcp_sname, struct in_addr *dhcp_next_server, int *dhcp_max,
|
char **dhcp_sname, struct in_addr *dhcp_next_server, int *dhcp_max,
|
||||||
unsigned int *min_leasetime, struct doctor **doctors)
|
unsigned int *min_leasetime, struct doctor **doctors)
|
||||||
{
|
{
|
||||||
@@ -472,11 +476,15 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
optarg++;
|
optarg++;
|
||||||
while ((end = strchr(optarg, '/')))
|
while ((end = strchr(optarg, '/')))
|
||||||
{
|
{
|
||||||
char *domain;
|
char *domain = NULL;
|
||||||
*end = 0;
|
*end = 0;
|
||||||
if (!canonicalise(optarg))
|
/* # matches everything and becomes a zero length domain string */
|
||||||
|
if (strcmp(optarg, "#") == 0)
|
||||||
|
domain = "";
|
||||||
|
else if (!canonicalise(optarg))
|
||||||
option = '?';
|
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 = safe_malloc(sizeof(struct server));
|
||||||
serv->next = newlist;
|
serv->next = newlist;
|
||||||
newlist = serv;
|
newlist = serv;
|
||||||
@@ -525,14 +533,16 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
if ((portno = strchr(source+1, '#')))
|
if ((portno = strchr(source+1, '#')))
|
||||||
{
|
{
|
||||||
*portno = 0;
|
*portno = 0;
|
||||||
source_port = atoi(portno+1);
|
if (!atoi_check(portno+1, &source_port))
|
||||||
|
option = '?';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((portno = strchr(optarg, '#'))) /* is there a port no. */
|
if ((portno = strchr(optarg, '#'))) /* is there a port no. */
|
||||||
{
|
{
|
||||||
*portno = 0;
|
*portno = 0;
|
||||||
serv_port = atoi(portno+1);
|
if (!atoi_check(portno+1, &serv_port))
|
||||||
|
option = '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
@@ -612,32 +622,46 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
{
|
{
|
||||||
int size = atoi(optarg);
|
int size;
|
||||||
/* zero is OK, and means no caching. */
|
if (!atoi_check(optarg, &size))
|
||||||
|
option = '?';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* zero is OK, and means no caching. */
|
||||||
|
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
size = 0;
|
size = 0;
|
||||||
else if (size > 10000)
|
else if (size > 10000)
|
||||||
size = 10000;
|
size = 10000;
|
||||||
|
|
||||||
*cachesize = size;
|
*cachesize = size;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
*port = atoi(optarg);
|
if (!atoi_check(optarg, port))
|
||||||
|
option = '?';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'Q':
|
case 'Q':
|
||||||
*query_port = atoi(optarg);
|
if (!atoi_check(optarg, query_port))
|
||||||
|
option = '?';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T':
|
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':
|
case 'X':
|
||||||
*dhcp_max = atoi(optarg);
|
if (!atoi_check(optarg, dhcp_max))
|
||||||
|
option = '?';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
@@ -650,7 +674,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
new->lease_time = DEFLEASE;
|
new->lease_time = DEFLEASE;
|
||||||
new->netmask.s_addr = 0;
|
new->netmask.s_addr = 0;
|
||||||
new->broadcast.s_addr = 0;
|
new->broadcast.s_addr = 0;
|
||||||
new->netid = NULL;
|
new->netid.net = NULL;
|
||||||
|
|
||||||
|
|
||||||
for (cp = optarg; *cp; cp++)
|
for (cp = optarg; *cp; cp++)
|
||||||
@@ -660,7 +684,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
if (*cp != ',' && (comma = strchr(optarg, ',')))
|
if (*cp != ',' && (comma = strchr(optarg, ',')))
|
||||||
{
|
{
|
||||||
*comma = 0;
|
*comma = 0;
|
||||||
new->netid = safe_string_alloc(optarg);
|
new->netid.net = safe_string_alloc(optarg);
|
||||||
a[0] = comma + 1;
|
a[0] = comma + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -726,7 +750,6 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new->last = new->start;
|
|
||||||
if (new->lease_time < *min_leasetime)
|
if (new->lease_time < *min_leasetime)
|
||||||
*min_leasetime = new->lease_time;
|
*min_leasetime = new->lease_time;
|
||||||
break;
|
break;
|
||||||
@@ -760,40 +783,45 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
(arg[1] == 'd' || arg[1] == 'D') &&
|
(arg[1] == 'd' || arg[1] == 'D') &&
|
||||||
arg[2] == ':')
|
arg[2] == ':')
|
||||||
{
|
{
|
||||||
int len;
|
if (arg[3] == '*')
|
||||||
arg += 3; /* dump id: */
|
new->flags |= CONFIG_NOCLID;
|
||||||
if (strchr(arg, ':'))
|
|
||||||
{
|
|
||||||
/* decode hex in place */
|
|
||||||
char *p = arg, *q = arg, *r;
|
|
||||||
while (*p)
|
|
||||||
{
|
|
||||||
for (r = p; *r && *r != ':'; r++);
|
|
||||||
if (*r)
|
|
||||||
{
|
|
||||||
if (r != p)
|
|
||||||
{
|
|
||||||
*r = 0;
|
|
||||||
*(q++) = strtol(p, NULL, 16);
|
|
||||||
}
|
|
||||||
p = r+1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (*p)
|
|
||||||
*(q++) = strtol(p, NULL, 16);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
len = q - arg;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
len = strlen(arg);
|
{
|
||||||
|
int len;
|
||||||
|
arg += 3; /* dump id: */
|
||||||
|
if (strchr(arg, ':'))
|
||||||
|
{
|
||||||
|
/* decode hex in place */
|
||||||
|
char *p = arg, *q = arg, *r;
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
for (r = p; *r && *r != ':'; r++);
|
||||||
|
if (*r)
|
||||||
|
{
|
||||||
|
if (r != p)
|
||||||
|
{
|
||||||
|
*r = 0;
|
||||||
|
*(q++) = strtol(p, NULL, 16);
|
||||||
|
}
|
||||||
|
p = r+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*p)
|
||||||
|
*(q++) = strtol(p, NULL, 16);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len = q - arg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
len = strlen(arg);
|
||||||
|
|
||||||
new->flags |= CONFIG_CLID;
|
new->flags |= CONFIG_CLID;
|
||||||
new->clid_len = len;
|
new->clid_len = len;
|
||||||
new->clid = safe_malloc(len);
|
new->clid = safe_malloc(len);
|
||||||
memcpy(new->clid, arg, len);
|
memcpy(new->clid, arg, len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ((arg[0] == 'n' || arg[0] == 'N') &&
|
else if ((arg[0] == 'n' || arg[0] == 'N') &&
|
||||||
(arg[1] == 'e' || arg[1] == 'E') &&
|
(arg[1] == 'e' || arg[1] == 'E') &&
|
||||||
@@ -801,7 +829,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
arg[3] == ':')
|
arg[3] == ':')
|
||||||
{
|
{
|
||||||
new->flags |= CONFIG_NETID;
|
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",
|
else if (sscanf(a[j], "%x:%x:%x:%x:%x:%x",
|
||||||
&e0, &e1, &e2, &e3, &e4, &e5) == 6)
|
&e0, &e1, &e2, &e3, &e4, &e5) == 6)
|
||||||
@@ -882,7 +910,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
if (new->flags & CONFIG_CLID)
|
if (new->flags & CONFIG_CLID)
|
||||||
free(new->clid);
|
free(new->clid);
|
||||||
if (new->flags & CONFIG_NETID)
|
if (new->flags & CONFIG_NETID)
|
||||||
free(new->netid);
|
free(new->netid.net);
|
||||||
free(new);
|
free(new);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -925,6 +953,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
if ((new->opt = atoi(optarg)) == 0)
|
if ((new->opt = atoi(optarg)) == 0)
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
|
if (new->netid)
|
||||||
|
free(new->netid);
|
||||||
free(new);
|
free(new);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -954,7 +984,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
{
|
{
|
||||||
is_dec = is_addr = 0;
|
is_dec = is_addr = 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1057,6 +1087,28 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'U':
|
||||||
|
case 'j':
|
||||||
|
{
|
||||||
|
char *comma;
|
||||||
|
|
||||||
|
if (!(comma = strchr(optarg, ',')))
|
||||||
|
option = '?';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct dhcp_vendor *new = safe_malloc(sizeof(struct dhcp_vendor));
|
||||||
|
*comma = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
{
|
{
|
||||||
char *a[3] = { NULL, NULL, NULL };
|
char *a[3] = { NULL, NULL, NULL };
|
||||||
|
|||||||
+1
-1
@@ -443,7 +443,7 @@ void extract_neg_addrs(HEADER *header, unsigned int qlen, char *name, time_t now
|
|||||||
static void dns_doctor(struct doctor *doctor, struct in_addr *addr)
|
static void dns_doctor(struct doctor *doctor, struct in_addr *addr)
|
||||||
{
|
{
|
||||||
for (; doctor; doctor = doctor->next)
|
for (; doctor; doctor = doctor->next)
|
||||||
if ((doctor->in.s_addr & doctor->mask.s_addr) == (addr->s_addr & doctor->mask.s_addr))
|
if (is_same_net(doctor->in, *addr, doctor->mask))
|
||||||
{
|
{
|
||||||
addr->s_addr &= ~doctor->mask.s_addr;
|
addr->s_addr &= ~doctor->mask.s_addr;
|
||||||
addr->s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
|
addr->s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
|
||||||
|
|||||||
+172
-71
@@ -18,6 +18,10 @@
|
|||||||
#define BOOTREPLY 2
|
#define BOOTREPLY 2
|
||||||
#define DHCP_COOKIE 0x63825363
|
#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_PAD 0
|
||||||
#define OPTION_NETMASK 1
|
#define OPTION_NETMASK 1
|
||||||
#define OPTION_ROUTER 3
|
#define OPTION_ROUTER 3
|
||||||
@@ -35,7 +39,9 @@
|
|||||||
#define OPTION_MAXMESSAGE 57
|
#define OPTION_MAXMESSAGE 57
|
||||||
#define OPTION_T1 58
|
#define OPTION_T1 58
|
||||||
#define OPTION_T2 59
|
#define OPTION_T2 59
|
||||||
|
#define OPTION_VENDOR_ID 60
|
||||||
#define OPTION_CLIENT_ID 61
|
#define OPTION_CLIENT_ID 61
|
||||||
|
#define OPTION_USER_CLASS 77
|
||||||
#define OPTION_END 255
|
#define OPTION_END 255
|
||||||
|
|
||||||
#define DHCPDISCOVER 1
|
#define DHCPDISCOVER 1
|
||||||
@@ -48,6 +54,7 @@
|
|||||||
#define DHCPINFORM 8
|
#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_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 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 void bootp_option_put(struct dhcp_packet *mess, char *filename, char *sname);
|
||||||
static int option_len(unsigned char *opt);
|
static int option_len(unsigned char *opt);
|
||||||
@@ -63,7 +70,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
char *domainname, char *hostname,
|
char *domainname, char *hostname,
|
||||||
struct in_addr router,
|
struct in_addr router,
|
||||||
struct in_addr iface_addr,
|
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)
|
static int have_config(struct dhcp_config *config, unsigned int mask)
|
||||||
{
|
{
|
||||||
@@ -77,11 +84,13 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
struct udp_dhcp_packet *rawpacket,
|
struct udp_dhcp_packet *rawpacket,
|
||||||
unsigned int sz, time_t now, char *namebuff,
|
unsigned int sz, time_t now, char *namebuff,
|
||||||
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
||||||
|
struct dhcp_vendor *vendors,
|
||||||
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
|
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
|
||||||
struct in_addr dhcp_next_server, struct in_addr router)
|
struct in_addr dhcp_next_server, struct in_addr router)
|
||||||
{
|
{
|
||||||
unsigned char *opt, *clid;
|
unsigned char *opt, *clid;
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
struct dhcp_vendor *vendor;
|
||||||
int clid_len;
|
int clid_len;
|
||||||
struct dhcp_packet *mess = &rawpacket->data;
|
struct dhcp_packet *mess = &rawpacket->data;
|
||||||
unsigned char *p = mess->options;
|
unsigned char *p = mess->options;
|
||||||
@@ -92,7 +101,9 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
unsigned int renewal_time, expires_time, def_time;
|
unsigned int renewal_time, expires_time, def_time;
|
||||||
struct dhcp_config *config;
|
struct dhcp_config *config;
|
||||||
char *netid;
|
struct dhcp_netid *netid = NULL;
|
||||||
|
struct in_addr addr;
|
||||||
|
unsigned short fuzz = 0;
|
||||||
|
|
||||||
if (mess->op != BOOTREQUEST ||
|
if (mess->op != BOOTREQUEST ||
|
||||||
mess->hlen != ETHER_ADDR_LEN ||
|
mess->hlen != ETHER_ADDR_LEN ||
|
||||||
@@ -138,17 +149,6 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
clid_len = 0;
|
clid_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do we have a lease in store? */
|
|
||||||
lease = lease_find_by_client(clid, clid_len);
|
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS)))
|
|
||||||
{
|
|
||||||
int len = option_len(opt);
|
|
||||||
req_options = namebuff;
|
|
||||||
memcpy(req_options, option_ptr(opt), len);
|
|
||||||
req_options[len] = OPTION_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, NULL)) &&
|
if ((config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, NULL)) &&
|
||||||
have_config(config, CONFIG_NAME))
|
have_config(config, CONFIG_NAME))
|
||||||
hostname = config->hostname;
|
hostname = config->hostname;
|
||||||
@@ -175,15 +175,80 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
hostname = NULL;
|
hostname = NULL;
|
||||||
}
|
}
|
||||||
else
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* search again now we have a hostname */
|
|
||||||
config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, hostname);
|
|
||||||
def_time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
def_time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
||||||
netid = have_config(config, CONFIG_NETID) ? config->netid : context->netid;
|
|
||||||
|
if (context->netid.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 */
|
||||||
|
if (have_config(config, CONFIG_NOCLID))
|
||||||
|
{
|
||||||
|
clid = mess->chaddr;
|
||||||
|
clid_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do we have a lease in store? */
|
||||||
|
lease = lease_find_by_client(clid, clid_len);
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
||||||
{
|
{
|
||||||
@@ -204,10 +269,18 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
expires_time = def_time;
|
expires_time = def_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS)))
|
||||||
|
{
|
||||||
|
int len = option_len(opt);
|
||||||
|
req_options = namebuff;
|
||||||
|
memcpy(req_options, option_ptr(opt), len);
|
||||||
|
req_options[len] = OPTION_END;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(opt = option_find(mess, sz, OPTION_MESSAGE_TYPE)))
|
if (!(opt = option_find(mess, sz, OPTION_MESSAGE_TYPE)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (opt[2])
|
switch (option_uint(opt, 1))
|
||||||
{
|
{
|
||||||
case DHCPDECLINE:
|
case DHCPDECLINE:
|
||||||
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER)) ||
|
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER)) ||
|
||||||
@@ -261,39 +334,48 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
|
|
||||||
case DHCPDISCOVER:
|
case DHCPDISCOVER:
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
||||||
mess->yiaddr = option_addr(opt);
|
addr = option_addr(opt);
|
||||||
|
|
||||||
if (have_config(config, CONFIG_DISABLE))
|
if (have_config(config, CONFIG_DISABLE))
|
||||||
message = "ignored";
|
message = "ignored";
|
||||||
else if (have_config(config, CONFIG_ADDR) && !lease_find_by_addr(config->addr))
|
else if (have_config(config, CONFIG_ADDR) && !lease_find_by_addr(config->addr))
|
||||||
mess->yiaddr = config->addr;
|
mess->yiaddr = config->addr;
|
||||||
else if (lease &&
|
else if (lease && is_same_net(lease->addr, context->start, context->netmask))
|
||||||
((lease->addr.s_addr & context->netmask.s_addr) ==
|
|
||||||
(context->start.s_addr & context->netmask.s_addr)))
|
|
||||||
mess->yiaddr = lease->addr;
|
mess->yiaddr = lease->addr;
|
||||||
else if ((!opt || !address_available(context, mess->yiaddr)) &&
|
else if (opt && address_available(context, addr))
|
||||||
!address_allocate(context, dhcp_configs, &mess->yiaddr))
|
mess->yiaddr = addr;
|
||||||
|
else if (!address_allocate(context, dhcp_configs, &mess->yiaddr, mess->chaddr))
|
||||||
message = "no address available";
|
message = "no address available";
|
||||||
|
|
||||||
log_packet("DISCOVER", opt ? &mess->yiaddr : NULL, mess->chaddr, iface_name, message);
|
log_packet("DISCOVER", opt ? &addr : NULL, mess->chaddr, iface_name, message);
|
||||||
|
|
||||||
if (message)
|
if (message)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* ensure that we send the reply by steam even if a buggy client sets this. */
|
||||||
|
mess->ciaddr.s_addr = 0;
|
||||||
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
||||||
mess->siaddr = dhcp_next_server;
|
mess->siaddr = dhcp_next_server.s_addr ? dhcp_next_server : iface_addr;
|
||||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
|
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
|
||||||
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
||||||
p = option_put(p, end, OPTION_LEASE_TIME, 4, expires_time);
|
p = option_put(p, end, OPTION_LEASE_TIME, 4, expires_time);
|
||||||
|
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
|
||||||
|
if (expires_time != 0xffffffff)
|
||||||
|
{
|
||||||
|
p = option_put(p, end, OPTION_T1, 4, (expires_time/2));
|
||||||
|
p = option_put(p, end, OPTION_T2, 4, ((expires_time * 7)/8));
|
||||||
|
}
|
||||||
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||||
NULL, router, iface_addr, iface_mtu, netid);
|
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);
|
log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
||||||
return p - (unsigned char *)mess;
|
return p - (unsigned char *)mess;
|
||||||
|
|
||||||
|
|
||||||
case DHCPREQUEST:
|
case DHCPREQUEST:
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
if (have_config(config, CONFIG_DISABLE))
|
||||||
|
message = "disabled";
|
||||||
|
else if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
||||||
{
|
{
|
||||||
/* SELECTING or INIT_REBOOT */
|
/* SELECTING or INIT_REBOOT */
|
||||||
mess->yiaddr = option_addr(opt);
|
mess->yiaddr = option_addr(opt);
|
||||||
@@ -333,15 +415,17 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
mess->yiaddr = mess->ciaddr;
|
mess->yiaddr = mess->ciaddr;
|
||||||
if (!lease || mess->ciaddr.s_addr != lease->addr.s_addr)
|
if (!lease || mess->ciaddr.s_addr != lease->addr.s_addr)
|
||||||
message = "lease not found";
|
message = "lease not found";
|
||||||
|
|
||||||
|
/* desynchronise renewals */
|
||||||
|
fuzz = rand16();
|
||||||
|
while (fuzz > (renewal_time/16))
|
||||||
|
fuzz = fuzz/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a machine moves networks whilst it has a lease, we catch that here. */
|
/* If a machine moves networks whilst it has a lease, we catch that here. */
|
||||||
if ((mess->yiaddr.s_addr & context->netmask.s_addr) != (context->start.s_addr & context->netmask.s_addr))
|
if (!message && !is_same_net(mess->yiaddr, context->start, context->netmask))
|
||||||
message = "wrong network";
|
message = "wrong network";
|
||||||
|
|
||||||
if (have_config(config, CONFIG_DISABLE))
|
|
||||||
message = "disabled";
|
|
||||||
|
|
||||||
log_packet("REQUEST", &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
log_packet("REQUEST", &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
||||||
|
|
||||||
if (message)
|
if (message)
|
||||||
@@ -352,7 +436,7 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
bootp_option_put(mess, NULL, NULL);
|
bootp_option_put(mess, NULL, NULL);
|
||||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
|
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
|
||||||
p = option_put_string(p, end, OPTION_MESSAGE, message);
|
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 */
|
mess->flags |= htons(0x8000); /* broadcast */
|
||||||
return p - (unsigned char *)mess;
|
return p - (unsigned char *)mess;
|
||||||
}
|
}
|
||||||
@@ -360,41 +444,39 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
log_packet("ACK", &mess->yiaddr, mess->chaddr, iface_name, hostname);
|
log_packet("ACK", &mess->yiaddr, mess->chaddr, iface_name, hostname);
|
||||||
|
|
||||||
lease_set_hwaddr(lease, mess->chaddr);
|
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);
|
lease_set_expires(lease, renewal_time == 0xffffffff ? 0 : now + (time_t)renewal_time);
|
||||||
|
|
||||||
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
||||||
mess->siaddr = dhcp_next_server;
|
mess->siaddr = dhcp_next_server.s_addr ? dhcp_next_server : iface_addr;
|
||||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||||
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
||||||
p = option_put(p, end, OPTION_LEASE_TIME, 4, renewal_time);
|
p = option_put(p, end, OPTION_LEASE_TIME, 4, renewal_time);
|
||||||
if (renewal_time != 0xffffffff)
|
if (renewal_time != 0xffffffff)
|
||||||
{
|
{
|
||||||
unsigned short fuzz = rand16();
|
|
||||||
while (fuzz > (renewal_time/16))
|
|
||||||
fuzz = fuzz/2;
|
|
||||||
p = option_put(p, end, OPTION_T1, 4, (renewal_time/2) - fuzz);
|
p = option_put(p, end, OPTION_T1, 4, (renewal_time/2) - fuzz);
|
||||||
p = option_put(p, end, OPTION_T2, 4, ((renewal_time * 7)/8) - fuzz);
|
p = option_put(p, end, OPTION_T2, 4, ((renewal_time * 7)/8) - fuzz);
|
||||||
}
|
}
|
||||||
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||||
hostname, router, iface_addr, iface_mtu, netid);
|
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;
|
return p - (unsigned char *)mess;
|
||||||
|
|
||||||
case DHCPINFORM:
|
case DHCPINFORM:
|
||||||
if (have_config(config, CONFIG_DISABLE))
|
if (have_config(config, CONFIG_DISABLE))
|
||||||
{
|
message = "ignored";
|
||||||
log_packet("INFORM", &mess->ciaddr, mess->chaddr, iface_name, "ignored");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_packet("INFORM", &mess->ciaddr, mess->chaddr, iface_name, NULL);
|
log_packet("INFORM", &mess->ciaddr, mess->chaddr, iface_name, message);
|
||||||
|
|
||||||
|
if (message || mess->ciaddr.s_addr == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||||
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
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,
|
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||||
hostname, router, iface_addr, iface_mtu, netid);
|
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);
|
log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname);
|
||||||
return p - (unsigned char *)mess;
|
return p - (unsigned char *)mess;
|
||||||
@@ -464,20 +546,26 @@ static unsigned char *option_put(unsigned char *p, unsigned char *end, int opt,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* always keep one octet space for the END option. */
|
/* always keep one octet space for the END option. */
|
||||||
if ((opt == OPTION_END) || (p + len + 3 < end))
|
if (p + len + 3 < end)
|
||||||
{
|
{
|
||||||
*(p++) = opt;
|
*(p++) = opt;
|
||||||
if (opt != OPTION_END)
|
*(p++) = len;
|
||||||
{
|
|
||||||
*(p++) = len;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
*(p++) = val >> (8 * (len - (i + 1)));
|
*(p++) = val >> (8 * (len - (i + 1)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return p;
|
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)
|
static unsigned char *option_put_string(unsigned char *p, unsigned char *end, int opt, char *string)
|
||||||
{
|
{
|
||||||
if (p + strlen(string) + 3 < end)
|
if (p + strlen(string) + 3 < end)
|
||||||
@@ -546,6 +634,10 @@ static int in_list(unsigned char *list, int opt)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* If no requested options, send everything, not nothing. */
|
||||||
|
if (!list)
|
||||||
|
return 1;
|
||||||
|
|
||||||
for (i = 0; list[i] != OPTION_END; i++)
|
for (i = 0; list[i] != OPTION_END; i++)
|
||||||
if (opt == list[i])
|
if (opt == list[i])
|
||||||
return 1;
|
return 1;
|
||||||
@@ -553,13 +645,26 @@ static int in_list(unsigned char *list, int opt)
|
|||||||
return 0;
|
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)
|
||||||
{
|
{
|
||||||
for (; opts; opts = opts->next)
|
struct dhcp_opt *tmp;
|
||||||
if (opts->opt == opt &&
|
struct dhcp_netid *tmp1;
|
||||||
(!opts->netid || (netid && strcmp(opts->netid, netid) == 0)))
|
|
||||||
return opts;
|
for (tmp = opts; tmp; tmp = tmp->next)
|
||||||
return NULL;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *do_req_options(struct dhcp_context *context,
|
static unsigned char *do_req_options(struct dhcp_context *context,
|
||||||
@@ -569,12 +674,9 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
char *domainname, char *hostname,
|
char *domainname, char *hostname,
|
||||||
struct in_addr router,
|
struct in_addr router,
|
||||||
struct in_addr iface_addr,
|
struct in_addr iface_addr,
|
||||||
int iface_mtu, char *netid)
|
int iface_mtu, struct dhcp_netid *netid)
|
||||||
{
|
{
|
||||||
int i;
|
struct dhcp_opt *opt;
|
||||||
|
|
||||||
if (!req_options)
|
|
||||||
return p;
|
|
||||||
|
|
||||||
if (in_list(req_options, OPTION_MAXMESSAGE))
|
if (in_list(req_options, OPTION_MAXMESSAGE))
|
||||||
p = option_put(p, end, OPTION_MAXMESSAGE, 2,
|
p = option_put(p, end, OPTION_MAXMESSAGE, 2,
|
||||||
@@ -607,14 +709,13 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
if (hostname && in_list(req_options, OPTION_HOSTNAME))
|
if (hostname && in_list(req_options, OPTION_HOSTNAME))
|
||||||
p = option_put_string(p, end, OPTION_HOSTNAME, hostname);
|
p = option_put_string(p, end, OPTION_HOSTNAME, hostname);
|
||||||
|
|
||||||
for (i = 0; req_options[i] != OPTION_END; i++)
|
for (opt=config_opts; opt; opt = opt->next)
|
||||||
{
|
{
|
||||||
struct dhcp_opt *opt;
|
if (opt->opt == OPTION_HOSTNAME ||
|
||||||
|
opt->opt == OPTION_MAXMESSAGE ||
|
||||||
if (req_options[i] == OPTION_HOSTNAME ||
|
!in_list(req_options, opt->opt) ||
|
||||||
req_options[i] == OPTION_MAXMESSAGE ||
|
opt != option_find2(netid, config_opts, opt->opt) ||
|
||||||
!(opt = option_find2(netid, config_opts, req_options[i])) ||
|
p + opt->len + 3 >= end)
|
||||||
(p + opt->len + 3 >= end))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* For the options we have default values on
|
/* For the options we have default values on
|
||||||
|
|||||||
+27
-4
@@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Code in this file contributed by Rob Funk. */
|
/* Some code in this file contributed by Rob Funk. */
|
||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
@@ -85,6 +85,18 @@ unsigned short rand16(void)
|
|||||||
return( (unsigned short) (rand() >> 15) );
|
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)
|
int legal_char(char c)
|
||||||
{
|
{
|
||||||
/* check for legal char a-z A-Z 0-9 -
|
/* check for legal char a-z A-Z 0-9 -
|
||||||
@@ -100,12 +112,18 @@ int legal_char(char c)
|
|||||||
|
|
||||||
int canonicalise(char *s)
|
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);
|
int l = strlen(s);
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if (l>0 && s[l-1] == '.')
|
if (l == 0) return 0;
|
||||||
s[l-1] = 0;
|
|
||||||
|
if (s[l-1] == '.')
|
||||||
|
{
|
||||||
|
if (l == 1) return 0;
|
||||||
|
s[l-1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
while ((c = *s++))
|
while ((c = *s++))
|
||||||
if (c != '.' && !legal_char(c))
|
if (c != '.' && !legal_char(c))
|
||||||
@@ -228,3 +246,8 @@ time_t dnsmasq_time(int fd)
|
|||||||
return time(NULL);
|
return time(NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
|
||||||
|
{
|
||||||
|
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user