mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.42.tar.gz
This commit is contained in:
44
CHANGELOG
44
CHANGELOG
@@ -2459,10 +2459,50 @@ version 2.41
|
||||
SIP, XMPP and Google-talk to the example config file.
|
||||
|
||||
Fix va_list abuse in log.c. This fixes crashes on powerpc
|
||||
when debug mode is set. Thanks to cedric Duval for the
|
||||
when debug mode is set. Thanks to Cedric Duval for the
|
||||
patch.
|
||||
|
||||
version 2.42
|
||||
Define _GNU_SOURCE to avoid problems with later glibc
|
||||
headers. Thanks to Jima for spotting the problem.
|
||||
|
||||
|
||||
Add --dhcp-alternate-port option. Thanks to Jan Psota for
|
||||
the suggestion.
|
||||
|
||||
Fix typo in code which is only used on BSD, when Dbus and
|
||||
IPv6 support is enabled. Thanks to Roy Marples.
|
||||
|
||||
Updated Polish translations - thank to Jan Psota.
|
||||
|
||||
Fix OS detection logic to cope with GNU/FreeBSD.
|
||||
|
||||
Fix unitialised variable in DBus code - thanks to Roy
|
||||
Marples.
|
||||
|
||||
Fix network enumeration code to work on later NetBSD -
|
||||
thanks to Roy Marples.
|
||||
|
||||
Provide --dhcp-bridge on all BSD variants.
|
||||
|
||||
Define _LARGEFILE_SOURCE which removes an arbitrary 2GB
|
||||
limit on logfiles. Thanks to Paul Chambers for spotting
|
||||
the problem.
|
||||
|
||||
Fix RFC3046 agent-id echo code, broken for many
|
||||
releases. Thanks to Jeremy Laine for spotting the problem
|
||||
and providing a patch.
|
||||
|
||||
Added Solaris 10 service manifest from David Connelly in
|
||||
contrib/Solaris10
|
||||
|
||||
Add --dhcp-scriptuser option.
|
||||
|
||||
Support new capability interface on suitable Linux
|
||||
kernels, removes "legacy support in use" messages. Thanks
|
||||
to Jorge Bastos for pointing this out.
|
||||
|
||||
Fix subtle bug in cache code which could cause dnsmasq to
|
||||
lock spinning CPU in rare circumstances. Thanks to Alex
|
||||
Chekholko for bug reports and help debugging.
|
||||
|
||||
Support netascii transfer mode for TFTP.
|
||||
|
||||
2
FAQ
2
FAQ
@@ -226,7 +226,7 @@ A: What is happening is this: The boot process sends a DHCP
|
||||
Q: What network types are supported by the DHCP server?
|
||||
|
||||
A: Ethernet (and 802.11 wireless) are supported on all platforms. On
|
||||
Linux Token Ring is also supported.
|
||||
Linux all network types (including FireWire) are supported.
|
||||
|
||||
Q: What is this strange "bind-interface" option?
|
||||
|
||||
|
||||
28
contrib/Solaris10/README
Normal file
28
contrib/Solaris10/README
Normal file
@@ -0,0 +1,28 @@
|
||||
From: David Connelly <dconnelly@gmail.com>
|
||||
Date: Mon, Apr 7, 2008 at 3:31 AM
|
||||
Subject: Solaris 10 service manifest
|
||||
To: dnsmasq-discuss@lists.thekelleys.org.uk
|
||||
|
||||
|
||||
I've found dnsmasq much easier to set up on my home server running Solaris
|
||||
10 than the stock dhcp/dns server, which is probably overkill anyway for my
|
||||
simple home network needs. Since Solaris now uses SMF (Service Management
|
||||
Facility) to manage services I thought I'd create a simple service manifest
|
||||
for the dnsmasq service. The manifest currently assumes that dnsmasq has
|
||||
been installed in '/usr/local/sbin/dnsmasq' and the configuration file in
|
||||
'/usr/local/etc/dnsmasq.conf', so you may have to adjust these paths for
|
||||
your local installation. Here are the steps I followed to install and enable
|
||||
the dnsmasq service:
|
||||
# svccfg import dnsmasq.xml
|
||||
# svcadm enable dnsmasq
|
||||
|
||||
To confirm that the service is enabled and online:
|
||||
|
||||
# svcs -l dnsmasq
|
||||
|
||||
I've just started learning about SMF so if anyone has any
|
||||
corrections/feedback they are more than welcome.
|
||||
|
||||
Thanks,
|
||||
David
|
||||
|
||||
65
contrib/Solaris10/dnsmasq.xml
Normal file
65
contrib/Solaris10/dnsmasq.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
|
||||
|
||||
<!-- Service manifest for dnsmasq -->
|
||||
|
||||
<service_bundle type='manifest' name='dnsmasq'>
|
||||
<service name='network/dnsmasq' type='service' version='1'>
|
||||
|
||||
<create_default_instance enabled='false'/>
|
||||
<single_instance/>
|
||||
|
||||
<dependency name='multi-user'
|
||||
grouping='require_all'
|
||||
restart_on='refresh'
|
||||
type='service'>
|
||||
<service_fmri value='svc:/milestone/multi-user'/>
|
||||
</dependency>
|
||||
|
||||
<dependency name='config'
|
||||
grouping='require_all'
|
||||
restart_on='restart'
|
||||
type='path'>
|
||||
<service_fmri value='file:///usr/local/etc/dnsmasq.conf'/>
|
||||
</dependency>
|
||||
|
||||
<dependent name='dnsmasq_multi-user-server'
|
||||
grouping='optional_all'
|
||||
restart_on='none'>
|
||||
<service_fmri value='svc:/milestone/multi-user-server' />
|
||||
</dependent>
|
||||
|
||||
<exec_method type='method' name='start'
|
||||
exec='/usr/local/sbin/dnsmasq -C /usr/local/etc/dnsmasq.conf'
|
||||
timeout_seconds='60' >
|
||||
<method_context>
|
||||
<method_credential user='root' group='root' privileges='all'/>
|
||||
</method_context>
|
||||
</exec_method>
|
||||
|
||||
<exec_method type='method'
|
||||
name='stop'
|
||||
exec=':kill'
|
||||
timeout_seconds='60'/>
|
||||
|
||||
<exec_method type='method'
|
||||
name='refresh'
|
||||
exec=':kill -HUP'
|
||||
timeout_seconds='60' />
|
||||
|
||||
<template>
|
||||
<common_name>
|
||||
<loctext xml:lang='C'>dnsmasq server</loctext>
|
||||
</common_name>
|
||||
<description>
|
||||
<loctext xml:lang='C'>
|
||||
dnsmasq - A lightweight DHCP and caching DNS server.
|
||||
</loctext>
|
||||
</description>
|
||||
<documentation>
|
||||
<manpage title='dnsmasq' section='8' manpath='/usr/local/man'/>
|
||||
</documentation>
|
||||
</template>
|
||||
|
||||
</service>
|
||||
</service_bundle>
|
||||
@@ -77,7 +77,7 @@ Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on r
|
||||
.B \-8, --log-facility=<facility>
|
||||
Set the facility to which dnsmasq will send syslog entries, this
|
||||
defaults to DAEMON, and to LOCAL0 when debug mode is in operation. If
|
||||
the facilty given contains at least one '/' character, it is taken to
|
||||
the facility given contains at least one '/' character, it is taken to
|
||||
be a filename, and dnsmasq logs to the given file, instead of
|
||||
syslog. (Errors whilst reading configuration will still go to syslog,
|
||||
but all output from a successful startup, and all output whilst
|
||||
@@ -378,7 +378,7 @@ Return a DNS record associating the name with the primary address on
|
||||
the given interface. This flag specifies an A record for the given
|
||||
name in the same way as an /etc/hosts line, except that the address is
|
||||
not constant, but taken from the given interface. If the interface is
|
||||
down, not configured or non-existant, an empty record is returned. The
|
||||
down, not configured or non-existent, an empty record is returned. The
|
||||
matching PTR record is also created, mapping the interface address to
|
||||
the name. More than one name may be associated with an interface
|
||||
address by repeating the flag; in that case the first instance is used
|
||||
@@ -406,7 +406,7 @@ in
|
||||
options. If the lease time is given, then leases
|
||||
will be given for that length of time. The lease time is in seconds,
|
||||
or minutes (eg 45m) or hours (eg 1h) or the literal "infinite". The
|
||||
minimum lease time is two minutres. This
|
||||
minimum lease time is two minutes. This
|
||||
option may be repeated, with different addresses, to enable DHCP
|
||||
service to more than one network. For directly connected networks (ie,
|
||||
networks on which the machine running dnsmasq has an interface) the
|
||||
@@ -635,7 +635,7 @@ not allocate it a DHCP lease.
|
||||
.B --dhcp-ignore-names[=<network-id>[,<network-id>]]
|
||||
When all the given network-ids match the set of network-ids derived
|
||||
from the net, host, vendor and user classes, ignore any hostname
|
||||
provided by the host. Note that, unlike dhcp-ignore, it is permissable
|
||||
provided by the host. Note that, unlike dhcp-ignore, it is permissible
|
||||
to supply no netid tags, in which case DHCP-client supplied hostnames
|
||||
are always ignored, and DHCP hosts are added to the DNS using only
|
||||
dhcp-host configuration in dnsmasq and the contents of /etc/hosts and
|
||||
@@ -671,7 +671,15 @@ It changes the behaviour from strict RFC compliance so that DHCP requests on
|
||||
unknown leases from unknown hosts are not ignored. This allows new hosts
|
||||
to get a lease without a tedious timeout under all circumstances. It also
|
||||
allows dnsmasq to rebuild its lease database without each client needing to
|
||||
reaquire a lease, if the database is lost.
|
||||
reacquire a lease, if the database is lost.
|
||||
.TP
|
||||
.B --dhcp-alternate-port[=<server port>[,<client port>]]
|
||||
Change the ports used for DHCP from the default. If this option is
|
||||
given alone, without arguments, it changes the ports used for DHCP
|
||||
from 67 and 68 to 1067 and 1068. If a single argument is given, that
|
||||
port number is used for the server and the port number plus one used
|
||||
for the client. Finally, two port numbers allows arbitrary
|
||||
specification of both server and client ports for DHCP.
|
||||
.TP
|
||||
.B \-3, --bootp-dynamic
|
||||
Enable dynamic allocation of IP addresses to BOOTP clients. Use this
|
||||
@@ -728,9 +736,9 @@ If a lease used to have a hostname, which is
|
||||
removed, an "old" event is generated with the new state of the lease,
|
||||
ie no name, and the former name is provided in the environment
|
||||
variable DNSMASQ_OLD_HOSTNAME. DNSMASQ_INTERFACE stores the name of
|
||||
the interface on which the reuest arrived; this is not set for "old"
|
||||
the interface on which the request arrived; this is not set for "old"
|
||||
actions when dnsmasq restarts.
|
||||
All file decriptors are
|
||||
All file descriptors are
|
||||
closed except stdin, stdout and stderr which are open to /dev/null
|
||||
(except in debug mode).
|
||||
The script is not invoked concurrently: if subsequent lease
|
||||
@@ -740,7 +748,10 @@ all existing leases as they are read from the lease file. Expired
|
||||
leases will be called with "del" and others with "old". <path>
|
||||
must be an absolute pathname, no PATH search occurs. When dnsmasq
|
||||
receives a HUP signal, the script will be invoked for existing leases
|
||||
with an "old " event.
|
||||
with an "old " event.
|
||||
.TP
|
||||
.B --dhcp-scriptuser
|
||||
Specify the user as which to run the lease-change script. This defaults to root, but can be changed to another user using this flag.
|
||||
.TP
|
||||
.B \-9, --leasefile-ro
|
||||
Completely suppress use of the lease database file. The file will not
|
||||
@@ -759,7 +770,7 @@ to the client-id and lease length and expiry time.
|
||||
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
||||
Treat DHCP request packets arriving at any of the <alias> interfaces
|
||||
as if they had arrived at <interface>. This option is only available
|
||||
on FreeBSD and Dragonfly BSD, and is necessary when using "old style" bridging, since
|
||||
on BSD platforms, and is necessary when using "old style" bridging, since
|
||||
packets arrive at tap interfaces which don't have an IP address.
|
||||
.TP
|
||||
.B \-s, --domain=<domain>
|
||||
@@ -784,8 +795,8 @@ in /etc/resolv.conf (or equivalent).
|
||||
.TP
|
||||
.B --enable-tftp
|
||||
Enable the TFTP server function. This is deliberately limited to that
|
||||
needed to net-boot a client: Only reading is allowed, and only in
|
||||
binary/octet mode. The tsize and blksize extensions are supported.
|
||||
needed to net-boot a client. Only reading is allowed; the tsize and
|
||||
blksize extensions are supported (tsize is only supported in octet mode).
|
||||
.TP
|
||||
.B --tftp-root=<directory>
|
||||
Look for files to transfer using TFTP relative to the given
|
||||
@@ -902,7 +913,7 @@ will close and reopen the log file. Note that during this operation,
|
||||
dnsmasq will not be running as root. When it first creates the logfile
|
||||
dnsmasq changes the ownership of the file to the non-root user it will run
|
||||
as. Logrotate should be configured to create a new log file with
|
||||
the ownership which matches the exising one before sending SIGUSR2.
|
||||
the ownership which matches the existing one before sending SIGUSR2.
|
||||
If TCP DNS queries are in progress, the old logfile will remain open in
|
||||
child processes which are handling TCP queries and may continue to be
|
||||
written. There is a limit of 150 seconds, after which all existing TCP
|
||||
@@ -1027,7 +1038,7 @@ normally if backgrounding is not enabled.
|
||||
2 - A problem with network access occurred (address in use, attempt
|
||||
to use privileged ports without permission).
|
||||
.PP
|
||||
3 - A problem occured with a filesystem operation (missing
|
||||
3 - A problem occurred with a filesystem operation (missing
|
||||
file/directory, permissions).
|
||||
.PP
|
||||
4 - Memory allocation failure.
|
||||
|
||||
581
po/pt_BR.po
581
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
|
||||
an aligned buffer to avoid nasty complaints about
|
||||
unaligned accesses. */
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
|
||||
len = ((struct ifreq *)ptr)->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru);
|
||||
#else
|
||||
len = sizeof(struct ifreq);
|
||||
#endif
|
||||
@@ -212,8 +212,8 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
udp.uh_sport = htons(DHCP_SERVER_PORT);
|
||||
udp.uh_dport = htons(DHCP_CLIENT_PORT);
|
||||
udp.uh_sport = htons(daemon->dhcp_server_port);
|
||||
udp.uh_dport = htons(daemon->dhcp_client_port);
|
||||
if (len & 1)
|
||||
((char *)mess)[len] = 0; /* for checksum, in case length is odd. */
|
||||
udp.uh_sum = 0;
|
||||
|
||||
34
src/cache.c
34
src/cache.c
@@ -359,6 +359,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
struct crec *new;
|
||||
union bigname *big_name = NULL;
|
||||
int freed_all = flags & F_REVERSE;
|
||||
int free_avail = 0;
|
||||
|
||||
log_query(flags | F_UPSTREAM, name, addr, 0, NULL, 0);
|
||||
|
||||
@@ -392,8 +393,24 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
|
||||
if (new->flags & (F_FORWARD | F_REVERSE))
|
||||
{
|
||||
/* If free_avail set, we believe that an entry has been freed.
|
||||
Bugs have been known to make this not true, resulting in
|
||||
a tight loop here. If that happens, log a warning and abandon the
|
||||
insert. Once in this state, all inserts will probably fail. */
|
||||
|
||||
if (free_avail)
|
||||
{
|
||||
static int warned = 0;
|
||||
|
||||
if (!warned)
|
||||
my_syslog(LOG_ERR, "BUG in cache detected. Please mail simon@thekelleys.org.uk");
|
||||
warned = insert_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (freed_all)
|
||||
{
|
||||
free_avail = 1; /* Must be free space now. */
|
||||
cache_scan_free(cache_get_name(new), &new->addr.addr, now, new->flags);
|
||||
cache_live_freed++;
|
||||
}
|
||||
@@ -516,19 +533,22 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
|
||||
Make sure that re-ordering doesn't break the hash-chain
|
||||
order invariants.
|
||||
*/
|
||||
if (!insert)
|
||||
{
|
||||
insert = up;
|
||||
ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
|
||||
up = &crecp->hash_next;
|
||||
}
|
||||
else if ((crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
|
||||
if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
|
||||
{
|
||||
*up = crecp->hash_next;
|
||||
crecp->hash_next = *insert;
|
||||
*insert = crecp;
|
||||
insert = &crecp->hash_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!insert)
|
||||
{
|
||||
insert = up;
|
||||
ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
|
||||
}
|
||||
up = &crecp->hash_next;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* case : not expired, incorrect entry. */
|
||||
|
||||
24
src/config.h
24
src/config.h
@@ -14,7 +14,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define VERSION "2.41"
|
||||
#define VERSION "2.42"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
@@ -54,6 +54,8 @@
|
||||
#define CHGRP "dip"
|
||||
#define DHCP_SERVER_PORT 67
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
#define DHCP_SERVER_ALTPORT 1067
|
||||
#define DHCP_CLIENT_ALTPORT 1068
|
||||
#define TFTP_PORT 69
|
||||
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
|
||||
#define LOG_MAX 5 /* log-queue length */
|
||||
@@ -85,13 +87,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Get linux C library versions. */
|
||||
#if defined(__linux__) && !defined(__UCLIBC__) && !defined(__uClinux__)
|
||||
/*# include <libio.h> */
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Follows system specific switches. If you run on a
|
||||
new system, you may want to edit these.
|
||||
May replace this with Autoconf one day.
|
||||
@@ -153,6 +148,10 @@ HAVE_DBUS
|
||||
define some methods to allow (re)configuration of the upstream DNS
|
||||
servers via DBus.
|
||||
|
||||
HAVE_BSD_BRIDGE
|
||||
Define this to enable the --bridge-interface option, useful on some
|
||||
BSD systems.
|
||||
|
||||
NOTES:
|
||||
For Linux you should define
|
||||
HAVE_LINUX_NETWORK
|
||||
@@ -188,7 +187,7 @@ NOTES:
|
||||
# error HAVE_ISC_READER is not compatible with HAVE_BROKEN_RTC
|
||||
#endif
|
||||
|
||||
/* Allow TFTP to be disabled with COPT=-DNO_TFTP */
|
||||
/* Allow TFTP to be disabled with COPTS=-DNO_TFTP */
|
||||
#ifdef NO_TFTP
|
||||
#undef HAVE_TFTP
|
||||
#endif
|
||||
@@ -249,7 +248,10 @@ typedef unsigned long in_addr_t;
|
||||
# define HAVE_BROKEN_SOCKADDR_IN6
|
||||
#endif
|
||||
|
||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#elif defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined (__FreeBSD_kernel__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
/* Later verions of FreeBSD have getopt_long() */
|
||||
#if defined(optional_argument) && defined(required_argument)
|
||||
@@ -261,6 +263,7 @@ typedef unsigned long in_addr_t;
|
||||
#define HAVE_RANDOM
|
||||
#define HAVE_DEV_URANDOM
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
#define HAVE_BSD_BRIDGE
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
@@ -282,6 +285,7 @@ typedef unsigned long in_addr_t;
|
||||
#define HAVE_DEV_URANDOM
|
||||
#define HAVE_DEV_RANDOM
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
#define HAVE_BSD_BRIDGE
|
||||
|
||||
#elif defined(__sun) || defined(__sun__)
|
||||
#define HAVE_SOLARIS_NETWORK
|
||||
|
||||
@@ -118,7 +118,7 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
{
|
||||
memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(stuct sockaddr_in6);
|
||||
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
|
||||
addr.in6.sin6_port = htons(NAMESERVER_PORT);
|
||||
@@ -167,8 +167,11 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
if (!serv && (serv = whine_malloc(sizeof (struct server))))
|
||||
{
|
||||
/* Not found, create a new one. */
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
|
||||
if (domain)
|
||||
serv->domain = whine_malloc(strlen(domain)+1);
|
||||
|
||||
if (domain && !serv->domain)
|
||||
{
|
||||
free(serv);
|
||||
@@ -179,7 +182,6 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
serv->flags = SERV_FROM_DBUS;
|
||||
serv->sfd = NULL;
|
||||
if (domain)
|
||||
{
|
||||
strcpy(serv->domain, domain);
|
||||
|
||||
14
src/dhcp.c
14
src/dhcp.c
@@ -71,7 +71,7 @@ void dhcp_init(void)
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(DHCP_SERVER_PORT);
|
||||
saddr.sin_port = htons(daemon->dhcp_server_port);
|
||||
saddr.sin_addr.s_addr = INADDR_ANY;
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
saddr.sin_len = sizeof(struct sockaddr_in);
|
||||
@@ -264,7 +264,7 @@ void dhcp_packet(time_t now)
|
||||
if (mess->giaddr.s_addr)
|
||||
{
|
||||
/* Send to BOOTP relay */
|
||||
dest.sin_port = htons(DHCP_SERVER_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_server_port);
|
||||
dest.sin_addr = mess->giaddr;
|
||||
}
|
||||
else if (mess->ciaddr.s_addr)
|
||||
@@ -276,7 +276,7 @@ void dhcp_packet(time_t now)
|
||||
if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) ||
|
||||
dest.sin_port == 0 || dest.sin_addr.s_addr == 0)
|
||||
{
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
dest.sin_addr = mess->ciaddr;
|
||||
}
|
||||
}
|
||||
@@ -296,7 +296,7 @@ void dhcp_packet(time_t now)
|
||||
cmptr->cmsg_level = SOL_IP;
|
||||
cmptr->cmsg_type = IP_PKTINFO;
|
||||
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -304,7 +304,7 @@ void dhcp_packet(time_t now)
|
||||
struct sockaddr limits size to 14 bytes. */
|
||||
struct arpreq req;
|
||||
dest.sin_addr = mess->yiaddr;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
*((struct sockaddr_in *)&req.arp_pa) = dest;
|
||||
req.arp_ha.sa_family = mess->htype;
|
||||
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
|
||||
@@ -317,7 +317,7 @@ void dhcp_packet(time_t now)
|
||||
{
|
||||
/* broadcast to 255.255.255.255 (or mac address invalid) */
|
||||
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
/* note that we don't specify the interface here: that's done by the
|
||||
IP_XMIT_IF sockopt lower down. */
|
||||
}
|
||||
@@ -329,7 +329,7 @@ void dhcp_packet(time_t now)
|
||||
mysteriously. Bah. Fall back to broadcast for other net types. */
|
||||
struct arpreq req;
|
||||
dest.sin_addr = mess->yiaddr;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
*((struct sockaddr_in *)&req.arp_pa) = dest;
|
||||
req.arp_ha.sa_family = AF_UNSPEC;
|
||||
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
|
||||
|
||||
@@ -33,6 +33,9 @@ static char *compile_opts =
|
||||
#ifdef NO_FORK
|
||||
"no-MMU "
|
||||
#endif
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
"BSD-bridge "
|
||||
#endif
|
||||
#ifndef HAVE_ISC_READER
|
||||
"no-"
|
||||
#endif
|
||||
@@ -216,6 +219,9 @@ int main (int argc, char **argv)
|
||||
/* The following code "daemonizes" the process.
|
||||
See Stevens section 12.4 */
|
||||
|
||||
if (chdir("/") != 0)
|
||||
die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
|
||||
|
||||
#ifndef NO_FORK
|
||||
if (!(daemon->options & OPT_NO_FORK))
|
||||
{
|
||||
@@ -223,7 +229,9 @@ int main (int argc, char **argv)
|
||||
|
||||
if ((pid = fork()) == -1 )
|
||||
die(_("cannot fork into background: %s"), NULL, EC_MISC);
|
||||
|
||||
|
||||
/* NO calls to die() from here on. */
|
||||
|
||||
if (pid != 0)
|
||||
_exit(EC_GOOD);
|
||||
|
||||
@@ -234,10 +242,7 @@ int main (int argc, char **argv)
|
||||
_exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (chdir("/") != 0)
|
||||
die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
|
||||
|
||||
|
||||
/* write pidfile _after_ forking ! */
|
||||
if (daemon->runfile && (pidfile = fopen(daemon->runfile, "w")))
|
||||
{
|
||||
@@ -259,8 +264,6 @@ int main (int argc, char **argv)
|
||||
#endif
|
||||
|
||||
ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
|
||||
|
||||
/* before here, we should only call die(), after here, only call syslog() */
|
||||
log_start(ent_pw);
|
||||
|
||||
if (!(daemon->options & OPT_DEBUG))
|
||||
@@ -287,9 +290,20 @@ int main (int argc, char **argv)
|
||||
/* On linux, we keep CAP_NETADMIN (for ARP-injection) and
|
||||
CAP_NET_RAW (for icmp) if we're doing dhcp */
|
||||
cap_user_header_t hdr = safe_malloc(sizeof(*hdr));
|
||||
cap_user_data_t data = safe_malloc(sizeof(*data));
|
||||
hdr->version = _LINUX_CAPABILITY_VERSION;
|
||||
cap_user_data_t data;
|
||||
int capsize = 1; /* for header version 1 */
|
||||
hdr->version = 0;
|
||||
/* find version supported by kernel */
|
||||
capget(hdr, NULL);
|
||||
if (hdr->version != LINUX_CAPABILITY_VERSION_1)
|
||||
{
|
||||
/* if not version 1, use version 2 */
|
||||
hdr->version = LINUX_CAPABILITY_VERSION_2;
|
||||
capsize = 2;
|
||||
}
|
||||
hdr->pid = 0; /* this process */
|
||||
data = safe_malloc(sizeof(*data) * capsize);
|
||||
memset(hdr, sizeof(*data) * capsize, 0);
|
||||
data->effective = data->permitted = data->inheritable =
|
||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
|
||||
(1 << CAP_SETGID) | (1 << CAP_SETUID);
|
||||
@@ -688,13 +702,21 @@ static void async_event(int pipe, time_t now)
|
||||
break;
|
||||
|
||||
case EVENT_EXEC_ERR:
|
||||
my_syslog(LOG_ERR, _("failed to execute %s: %s"), daemon->lease_change_command, strerror(ev.data));
|
||||
my_syslog(LOG_ERR, _("failed to execute %s: %s"),
|
||||
daemon->lease_change_command, strerror(ev.data));
|
||||
break;
|
||||
|
||||
case EVENT_PIPE_ERR:
|
||||
my_syslog(LOG_ERR, _("failed to create helper: %s"), strerror(ev.data));
|
||||
break;
|
||||
|
||||
case EVENT_USER_ERR:
|
||||
my_syslog(LOG_ERR, _("cannot change to user %s for script execution%s%s"),
|
||||
daemon->scriptuser,
|
||||
ev.data != 0 ? ": " : "",
|
||||
ev.data != 0 ? strerror(ev.data) : "");
|
||||
break;
|
||||
|
||||
case EVENT_REOPEN:
|
||||
/* Note: this may leave TCP-handling processes with the old file still open.
|
||||
Since any such process will die in CHILD_LIFETIME or probably much sooner,
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
|
||||
#define COPYRIGHT "Copyright (C) 2000-2008 Simon Kelley"
|
||||
|
||||
/* Ensure we can use files >2GB (log files may grow this big) */
|
||||
#define _LARGEFILE_SOURCE 1
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
/* Get linux C library versions. */
|
||||
#ifdef __linux__
|
||||
# define _GNU_SOURCE
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
/* get these before config.h for IPv6 stuff... */
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -60,6 +70,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
@@ -84,8 +95,12 @@
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
#include <linux/capability.h>
|
||||
/* There doesn't seem to be a universally-available
|
||||
userpace header for this. */
|
||||
userpace header for these. */
|
||||
extern int capset(cap_user_header_t header, cap_user_data_t data);
|
||||
extern int capget(cap_user_header_t header, cap_user_data_t data);
|
||||
#define LINUX_CAPABILITY_VERSION_1 0x19980330
|
||||
#define LINUX_CAPABILITY_VERSION_2 0x20071026
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#elif defined(HAVE_SOLARIS_PRIVS)
|
||||
#include <priv.h>
|
||||
@@ -109,6 +124,7 @@ struct event_desc {
|
||||
#define EVENT_KILLED 8
|
||||
#define EVENT_EXEC_ERR 9
|
||||
#define EVENT_PIPE_ERR 10
|
||||
#define EVENT_USER_ERR 11
|
||||
|
||||
/* Exit codes. */
|
||||
#define EC_GOOD 0
|
||||
@@ -455,7 +471,7 @@ struct dhcp_mac {
|
||||
struct dhcp_mac *next;
|
||||
};
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
struct dhcp_bridge {
|
||||
char iface[IF_NAMESIZE];
|
||||
struct dhcp_bridge *alias, *next;
|
||||
@@ -509,9 +525,10 @@ struct tftp_transfer {
|
||||
int sockfd;
|
||||
time_t timeout;
|
||||
int backoff;
|
||||
unsigned int block, blocksize;
|
||||
unsigned int block, blocksize, expansion;
|
||||
off_t offset;
|
||||
struct sockaddr_in peer;
|
||||
char opt_blocksize, opt_transize;
|
||||
char opt_blocksize, opt_transize, netascii, carrylf;
|
||||
struct tftp_file *file;
|
||||
struct tftp_transfer *next;
|
||||
};
|
||||
@@ -529,7 +546,7 @@ extern struct daemon {
|
||||
struct interface_name *int_names;
|
||||
char *mxtarget;
|
||||
char *lease_file;
|
||||
char *username, *groupname;
|
||||
char *username, *groupname, *scriptuser;
|
||||
char *domain_suffix;
|
||||
char *runfile;
|
||||
char *lease_change_command;
|
||||
@@ -552,6 +569,7 @@ extern struct daemon {
|
||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast;
|
||||
char *dhcp_hosts_file, *dhcp_opts_file;
|
||||
int dhcp_max, tftp_max;
|
||||
int dhcp_server_port, dhcp_client_port;
|
||||
int start_tftp_port, end_tftp_port;
|
||||
unsigned int min_leasetime;
|
||||
struct doctor *doctors;
|
||||
@@ -582,7 +600,7 @@ extern struct daemon {
|
||||
char *dhcp_buff, *dhcp_buff2;
|
||||
struct ping_result *ping_results;
|
||||
FILE *lease_stream;
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
struct dhcp_bridge *bridges;
|
||||
#endif
|
||||
|
||||
|
||||
22
src/helper.c
22
src/helper.c
@@ -55,10 +55,18 @@ int create_helper(int event_fd, long max_fd)
|
||||
pid_t pid;
|
||||
int i, pipefd[2];
|
||||
struct sigaction sigact;
|
||||
struct passwd *ent_pw = NULL;
|
||||
|
||||
if (!daemon->dhcp || !daemon->lease_change_command)
|
||||
return -1;
|
||||
|
||||
if (daemon->scriptuser && !(ent_pw = getpwnam(daemon->scriptuser)))
|
||||
{
|
||||
/* too late to die() */
|
||||
send_event(event_fd, EVENT_USER_ERR, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* create the pipe through which the main program sends us commands,
|
||||
then fork our process. By now it's too late to die(), we just log
|
||||
any failure via the main process. */
|
||||
@@ -173,6 +181,20 @@ int create_helper(int event_fd, long max_fd)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Change ownership of child, if this fails, log and ditch,
|
||||
rather than running wrong user */
|
||||
if (ent_pw)
|
||||
{
|
||||
gid_t dummy;
|
||||
if (setgroups(0, &dummy) == -1 ||
|
||||
setgid(ent_pw->pw_gid) == -1 ||
|
||||
setuid(ent_pw->pw_uid) == -1)
|
||||
{
|
||||
send_event(event_fd, EVENT_USER_ERR, errno);
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.clid_len != 0)
|
||||
my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err);
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ int iface_check(int family, struct all_addr *addr,
|
||||
|
||||
if (indexp)
|
||||
{
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
/* One form of bridging on FreeBSD has the property that packets
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
/* One form of bridging on BSD has the property that packets
|
||||
can be recieved on bridge interfaces which do not have an IP address.
|
||||
We allow these to be treated as aliases of another interface which does have
|
||||
an IP address with --dhcp-bridge=interface,alias,alias */
|
||||
|
||||
39
src/option.c
39
src/option.c
@@ -91,6 +91,8 @@ struct myoption {
|
||||
#define LOPT_MATCH 281
|
||||
#define LOPT_BROADCAST 282
|
||||
#define LOPT_NEGTTL 283
|
||||
#define LOPT_ALTPORT 284
|
||||
#define LOPT_SCRIPTUSR 285
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -171,7 +173,7 @@ static const struct myoption opts[] =
|
||||
{"tftp-root", 1, 0, LOPT_PREFIX },
|
||||
{"tftp-max", 1, 0, LOPT_TFTP_MAX },
|
||||
{"ptr-record", 1, 0, LOPT_PTR },
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
{"bridge-interface", 1, 0 , LOPT_BRIDGE },
|
||||
#endif
|
||||
{"dhcp-option-force", 1, 0, LOPT_FORCE },
|
||||
@@ -191,6 +193,8 @@ static const struct myoption opts[] =
|
||||
{"dhcp-match", 1, 0, LOPT_MATCH },
|
||||
{"dhcp-broadcast", 1, 0, LOPT_BROADCAST },
|
||||
{"neg-ttl", 1, 0, LOPT_NEGTTL },
|
||||
{"dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
|
||||
{"dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -308,7 +312,7 @@ static const struct {
|
||||
{ "-2, --no-dhcp-interface=interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
|
||||
{ "-3, --bootp-dynamic", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
|
||||
{ "-4, --dhcp-mac=<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
{ " --bridge-interface=iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
|
||||
#endif
|
||||
{ "-5, --no-ping", gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
|
||||
@@ -332,6 +336,8 @@ static const struct {
|
||||
{ " --stop-dns-rebind", gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
|
||||
{ " --all-servers", gettext_noop("Always perform DNS queries to all servers."), NULL },
|
||||
{ " --dhcp-match=<netid>,<opt-no>", gettext_noop("Set tag if client includes option in request."), NULL },
|
||||
{ " --dhcp-alternate-port[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
|
||||
{ " --dhcp-scriptuser=<username>", gettext_noop("Run lease-change script as this user."), NULL },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -396,8 +402,8 @@ static const struct {
|
||||
{ "client-id", 61,OT_INTERNAL },
|
||||
{ "nis-domain", 64, 0 },
|
||||
{ "nis-server", 65, OT_ADDR_LIST },
|
||||
{ "tftp-server", 66, OT_INTERNAL },
|
||||
{ "bootfile-name", 67, OT_INTERNAL },
|
||||
{ "tftp-server", 66, 0 },
|
||||
{ "bootfile-name", 67, 0 },
|
||||
{ "mobile-ip-home", 68, OT_ADDR_LIST },
|
||||
{ "smtp-server", 69, OT_ADDR_LIST },
|
||||
{ "pop3-server", 70, OT_ADDR_LIST },
|
||||
@@ -1108,6 +1114,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
case 'g': /* --group */
|
||||
daemon->groupname = opt_string_alloc(arg);
|
||||
break;
|
||||
|
||||
case LOPT_SCRIPTUSR: /* --scriptuser */
|
||||
daemon->scriptuser = opt_string_alloc(arg);
|
||||
break;
|
||||
|
||||
case 'i': /* --interface */
|
||||
do {
|
||||
@@ -1435,7 +1445,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
break;
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
case LOPT_BRIDGE: /* --bridge-interface */
|
||||
{
|
||||
struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
|
||||
@@ -1876,6 +1886,23 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_ALTPORT: /* --dhcp-alternate-port */
|
||||
if (!arg)
|
||||
{
|
||||
daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
|
||||
daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
comma = split(arg);
|
||||
if (!atoi_check(arg, &daemon->dhcp_server_port) ||
|
||||
(comma && !atoi_check(comma, &daemon->dhcp_client_port)))
|
||||
problem = _("invalid port number");
|
||||
if (!comma)
|
||||
daemon->dhcp_client_port = daemon->dhcp_server_port+1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'J': /* --dhcp-ignore */
|
||||
case LOPT_NO_NAMES: /* --dhcp-ignore-names */
|
||||
case LOPT_BROADCAST: /* --dhcp-broadcast */
|
||||
@@ -2351,6 +2378,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
daemon->cachesize = CACHESIZ;
|
||||
daemon->ftabsize = FTABSIZ;
|
||||
daemon->port = NAMESERVER_PORT;
|
||||
daemon->dhcp_client_port = DHCP_CLIENT_PORT;
|
||||
daemon->dhcp_server_port = DHCP_SERVER_PORT;
|
||||
daemon->default_resolv.is_default = 1;
|
||||
daemon->default_resolv.name = RESOLVFILE;
|
||||
daemon->resolv_files = &daemon->default_resolv;
|
||||
|
||||
@@ -227,7 +227,7 @@ static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
|
||||
if (*name == '\\' && *(name+1) == '[' &&
|
||||
(*(name+2) == 'x' || *(name+2) == 'X'))
|
||||
{
|
||||
for (j = 0, cp1 = name+3; *cp1 && isxdigit(*cp1) && j < 32; cp1++, j++)
|
||||
for (j = 0, cp1 = name+3; *cp1 && isxdigit((int) *cp1) && j < 32; cp1++, j++)
|
||||
{
|
||||
char xdig[2];
|
||||
xdig[0] = *cp1;
|
||||
|
||||
@@ -82,7 +82,8 @@ static void log_packet(char *type, void *addr,
|
||||
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
|
||||
static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
|
||||
static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid);
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end, unsigned char *agent_id);
|
||||
static void restore_agent_id(unsigned char *agent_id, struct dhcp_packet *mess, unsigned char *real_end);
|
||||
static void do_options(struct dhcp_context *context,
|
||||
struct dhcp_packet *mess,
|
||||
unsigned char *real_end,
|
||||
@@ -436,7 +437,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
lease_set_expires(lease, 0xffffffff, now); /* infinite lease */
|
||||
lease_set_interface(lease, int_index);
|
||||
|
||||
clear_packet(mess, end);
|
||||
clear_packet(mess, end, NULL);
|
||||
do_options(context, mess, end, NULL,
|
||||
hostname, netid, subnet_addr, 0, 0, NULL);
|
||||
}
|
||||
@@ -750,7 +751,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
}
|
||||
|
||||
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
|
||||
clear_packet(mess, end);
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||
@@ -889,11 +890,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
log_packet("NAK", &mess->yiaddr, emac, emac_len, iface_name, message);
|
||||
|
||||
mess->yiaddr.s_addr = 0;
|
||||
clear_packet(mess, end);
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ,
|
||||
ntohl(context ? context->local.s_addr : fallback.s_addr));
|
||||
option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
|
||||
/* DHCPNAK gets agent-id too */
|
||||
restore_agent_id(agent_id, mess, end);
|
||||
/* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
|
||||
a distant subnet which unicast a REQ to us won't work. */
|
||||
if (!unicast_dest || mess->giaddr.s_addr != 0 ||
|
||||
@@ -970,7 +973,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
log_packet("ACK", &mess->yiaddr, emac, emac_len, iface_name, hostname);
|
||||
|
||||
clear_packet(mess, end);
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||
@@ -1015,7 +1018,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
netid = &context->netid;
|
||||
}
|
||||
|
||||
clear_packet(mess, end);
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
|
||||
@@ -1462,14 +1465,29 @@ static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end, unsigned char *agent_id)
|
||||
{
|
||||
/* don't clear agent_id */
|
||||
if (agent_id)
|
||||
end = agent_id;
|
||||
|
||||
memset(mess->sname, 0, sizeof(mess->sname));
|
||||
memset(mess->file, 0, sizeof(mess->file));
|
||||
memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
|
||||
mess->siaddr.s_addr = 0;
|
||||
}
|
||||
|
||||
static void restore_agent_id(unsigned char *agent_id, struct dhcp_packet *mess, unsigned char *real_end)
|
||||
{
|
||||
if (agent_id)
|
||||
{
|
||||
unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
|
||||
memmove(p, agent_id, real_end - agent_id);
|
||||
p += real_end - agent_id;
|
||||
memset(p, 0, real_end - p); /* in case of overlap */
|
||||
}
|
||||
}
|
||||
|
||||
static void do_options(struct dhcp_context *context,
|
||||
struct dhcp_packet *mess,
|
||||
unsigned char *real_end,
|
||||
@@ -1784,13 +1802,7 @@ static void do_options(struct dhcp_context *context,
|
||||
}
|
||||
|
||||
/* move agent_id back down to the end of the packet */
|
||||
if (agent_id)
|
||||
{
|
||||
p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
|
||||
memmove(p, agent_id, real_end - agent_id);
|
||||
p += real_end - agent_id;
|
||||
memset(p, 0, real_end - p); /* in case of overlap */
|
||||
}
|
||||
restore_agent_id(agent_id, mess, real_end);
|
||||
|
||||
/* restore BOOTP anti-overload hack */
|
||||
if (!req_options || (daemon->options & OPT_NO_OVERRIDE))
|
||||
|
||||
56
src/tftp.c
56
src/tftp.c
@@ -151,8 +151,10 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
transfer->backoff = 1;
|
||||
transfer->block = 1;
|
||||
transfer->blocksize = 512;
|
||||
transfer->offset = 0;
|
||||
transfer->file = NULL;
|
||||
transfer->opt_blocksize = transfer->opt_transize = 0;
|
||||
transfer->netascii = transfer->carrylf = 0;
|
||||
|
||||
/* if we have a nailed-down range, iterate until we find a free one. */
|
||||
while (1)
|
||||
@@ -184,10 +186,13 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
|
||||
!(filename = next(&p, end)) ||
|
||||
!(mode = next(&p, end)) ||
|
||||
strcasecmp(mode, "octet") != 0)
|
||||
(strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
|
||||
len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), inet_ntoa(peer.sin_addr));
|
||||
else
|
||||
{
|
||||
if (strcasecmp(mode, "netascii") == 0)
|
||||
transfer->netascii = 1;
|
||||
|
||||
while ((opt = next(&p, end)))
|
||||
{
|
||||
if (strcasecmp(opt, "blksize") == 0 &&
|
||||
@@ -203,7 +208,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
transfer->block = 0;
|
||||
}
|
||||
|
||||
if (strcasecmp(opt, "tsize") == 0 && next(&p, end))
|
||||
if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
|
||||
{
|
||||
transfer->opt_transize = 1;
|
||||
transfer->block = 0;
|
||||
@@ -378,7 +383,8 @@ void check_tftp_listeners(fd_set *rset, time_t now)
|
||||
/* Got ack, ensure we take the (re)transmit path */
|
||||
transfer->timeout = now;
|
||||
transfer->backoff = 0;
|
||||
transfer->block++;
|
||||
if (transfer->block++ != 0)
|
||||
transfer->offset += transfer->blocksize - transfer->expansion;
|
||||
}
|
||||
else if (ntohs(mess->op) == OP_ERR)
|
||||
{
|
||||
@@ -532,24 +538,52 @@ static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
|
||||
unsigned char data[];
|
||||
} *mess = (struct datamess *)packet;
|
||||
|
||||
off_t offset = transfer->blocksize * (transfer->block - 1);
|
||||
size_t size = transfer->file->size - offset;
|
||||
size_t size = transfer->file->size - transfer->offset;
|
||||
|
||||
if (offset > transfer->file->size)
|
||||
if (transfer->offset > transfer->file->size)
|
||||
return 0; /* finished */
|
||||
|
||||
if (size > transfer->blocksize)
|
||||
size = transfer->blocksize;
|
||||
|
||||
lseek(transfer->file->fd, offset, SEEK_SET);
|
||||
|
||||
mess->op = htons(OP_DATA);
|
||||
mess->block = htons((unsigned short)(transfer->block));
|
||||
|
||||
if (!read_write(transfer->file->fd, mess->data, size, 1))
|
||||
if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
|
||||
!read_write(transfer->file->fd, mess->data, size, 1))
|
||||
return -1;
|
||||
else
|
||||
return size + 4;
|
||||
|
||||
transfer->expansion = 0;
|
||||
|
||||
/* Map '\n' to CR-LF in netascii mode */
|
||||
if (transfer->netascii)
|
||||
{
|
||||
size_t i;
|
||||
int newcarrylf;
|
||||
|
||||
for (i = 0, newcarrylf = 0; i < size; i++)
|
||||
if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
|
||||
{
|
||||
if (size == transfer->blocksize)
|
||||
{
|
||||
transfer->expansion++;
|
||||
if (i == size - 1)
|
||||
newcarrylf = 1; /* don't expand LF again if it moves to the next block */
|
||||
}
|
||||
else
|
||||
size++; /* room in this block */
|
||||
|
||||
/* make space and insert CR */
|
||||
memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
|
||||
mess->data[i] = '\r';
|
||||
|
||||
i++;
|
||||
}
|
||||
transfer->carrylf = newcarrylf;
|
||||
|
||||
}
|
||||
|
||||
return size + 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user