mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.1.tar.gz
This commit is contained in:
@@ -639,7 +639,10 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
|
||||
if ((crec = cache_find_by_name(NULL, host_name, 0, F_IPV4)))
|
||||
{
|
||||
if (crec->flags & F_HOSTS)
|
||||
syslog(LOG_WARNING, "Ignoring DHCP lease for %s because it clashes with an /etc/hosts entry.", host_name);
|
||||
{
|
||||
if (crec->addr.addr.addr4.s_addr != host_address->s_addr)
|
||||
syslog(LOG_WARNING, "Not naming DHCP lease for %s because it clashes with an /etc/hosts entry.", host_name);
|
||||
}
|
||||
else if (!(crec->flags & F_DHCP))
|
||||
{
|
||||
if (crec->flags & F_NEG)
|
||||
@@ -650,7 +653,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
|
||||
goto newrec;
|
||||
}
|
||||
else
|
||||
syslog(LOG_WARNING, "Ignoring DHCP lease for %s because it clashes with a cached name.", cache_get_name(crec));
|
||||
syslog(LOG_WARNING, "Not naming DHCP lease for %s because it clashes with a cached name.", cache_get_name(crec));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -671,7 +674,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
|
||||
crec->flags |= F_IMMORTAL;
|
||||
else
|
||||
crec->ttd = ttd;
|
||||
memcpy(&crec->addr, host_address, INADDRSZ);
|
||||
crec->addr.addr.addr4 = *host_address;
|
||||
crec->name.namep = host_name;
|
||||
crec->prev = dhcp_inuse;
|
||||
dhcp_inuse = crec;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
/* Author's email: simon@thekelleys.org.uk */
|
||||
|
||||
#define VERSION "2.0"
|
||||
#define VERSION "2.1"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests */
|
||||
#define TIMEOUT 40 /* drop queries after TIMEOUT seconds */
|
||||
|
||||
15
src/dhcp.c
15
src/dhcp.c
@@ -269,5 +269,18 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void set_configs_from_cache(struct dhcp_config *configs)
|
||||
/* Some people like to keep all static IP addresses in /etc/hosts.
|
||||
This goes through /etc/hosts and sets static addresses for any DHCP config
|
||||
records which don't have an address and whose name matches. */
|
||||
{
|
||||
struct dhcp_config *config;
|
||||
struct crec *crec;
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
if (config->addr.s_addr == 0 && config->hostname &&
|
||||
(crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
|
||||
(crec->flags & F_HOSTS))
|
||||
config->addr = crec->addr.addr.addr4;
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,7 @@ int main (int argc, char **argv)
|
||||
if (!dhcp_tmp->iface)
|
||||
die("No suitable interface for DHCP service at address %s", inet_ntoa(dhcp_tmp->start));
|
||||
|
||||
set_configs_from_cache(dhcp_configs);
|
||||
leasefd = lease_init(lease_file, domain_suffix, dnamebuff, packet, time(NULL), dhcp_configs);
|
||||
lease_update_dns(1); /* must follow cache_init and lease_init */
|
||||
}
|
||||
@@ -270,6 +271,7 @@ int main (int argc, char **argv)
|
||||
if (sighup)
|
||||
{
|
||||
cache_reload(options, dnamebuff, domain_suffix, addn_hosts);
|
||||
set_configs_from_cache(dhcp_configs);
|
||||
lease_update_dns(1);
|
||||
if (resolv && (options & OPT_NO_POLL))
|
||||
servers = last_server =
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#define _XOPEN_SOURCE 600
|
||||
/* but then DNS headers don't compile without.... */
|
||||
#define _BSD_SOURCE
|
||||
/* and also, on FreeBSD 5.0 ..... */
|
||||
#define __BSD_VISIBLE 1
|
||||
|
||||
/* get these before config.h for IPv6 stuff... */
|
||||
#include <sys/types.h>
|
||||
@@ -26,7 +28,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -229,8 +230,7 @@ struct dhcp_config {
|
||||
};
|
||||
|
||||
struct dhcp_opt {
|
||||
unsigned char opt;
|
||||
unsigned char len;
|
||||
int opt, len, is_addr;
|
||||
unsigned char *val;
|
||||
struct dhcp_opt *next;
|
||||
};
|
||||
@@ -360,6 +360,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
unsigned char *clid, int clid_len,
|
||||
unsigned char *hwaddr, char *hostname);
|
||||
|
||||
void set_configs_from_cache(struct dhcp_config *configs);
|
||||
/* lease.c */
|
||||
void lease_update_dns(int force_dns);
|
||||
int lease_init(char *lease_file, char *domain, char *buff,
|
||||
|
||||
@@ -132,6 +132,7 @@ struct server *forward_query(int udpfd, union mysockaddr *udpaddr, HEADER *heade
|
||||
flags = 0; /* may be better match from previous literal */
|
||||
domain = serv->domain;
|
||||
matchlen = domainlen;
|
||||
type = SERV_HAS_DOMAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
143
src/network.c
143
src/network.c
@@ -76,12 +76,14 @@ static char *add_iface(struct irec **list, unsigned int flags,
|
||||
specific addresses even if BIND is running and has bound *:53 */
|
||||
opt = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
|
||||
bind(fd, &addr->sa, sa_len(addr)))
|
||||
bind(fd, &addr->sa, sa_len(addr)) == -1)
|
||||
{
|
||||
int errsave = errno;
|
||||
close(fd);
|
||||
errno = errsave;
|
||||
return "failed to bind socket: %s";
|
||||
/* IPv6 interfaces sometimes return ENODEV to bind() for unknown
|
||||
(to me) reasons. Don't treat that as fatal. */
|
||||
return errno == ENODEV ? NULL : "failed to bind socket: %s";
|
||||
}
|
||||
|
||||
/* If OK, add it to the head of the list */
|
||||
@@ -119,6 +121,7 @@ char *enumerate_interfaces(struct irec **interfacep,
|
||||
struct irec *iface, *prev;
|
||||
char *buf, *ptr, *err = NULL;
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr = NULL;
|
||||
int fd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
int rawfd = -1;
|
||||
|
||||
@@ -158,12 +161,22 @@ char *enumerate_interfaces(struct irec **interfacep,
|
||||
|
||||
for (ptr = buf; ptr < buf + ifc.ifc_len; )
|
||||
{
|
||||
struct ifreq *ifr = (struct ifreq *) ptr;
|
||||
union mysockaddr addr;
|
||||
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
ptr += ifr->ifr_addr.sa_len + IF_NAMESIZE;
|
||||
/* subsequent entries may not be aligned, so copy into
|
||||
an aligned buffer to avoid nasty complaints about
|
||||
unaligned accesses. */
|
||||
int ifr_len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
|
||||
if (!(ifr = realloc(ifr, ifr_len)))
|
||||
{
|
||||
err = "cannot allocate buffer";
|
||||
goto end;
|
||||
}
|
||||
|
||||
memcpy(ifr, ptr, ifr_len);
|
||||
ptr += ifr_len;
|
||||
#else
|
||||
ifr = (struct ifreq *)ptr;
|
||||
ptr += sizeof(struct ifreq);
|
||||
#endif
|
||||
|
||||
@@ -198,6 +211,54 @@ char *enumerate_interfaces(struct irec **interfacep,
|
||||
&addr, names, addrs, except)))
|
||||
goto end;
|
||||
|
||||
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
|
||||
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
|
||||
/* This code snarfed from net-tools 1.60 and certainly linux specific, though
|
||||
it shouldn't break on other Unices, and their SIOGIFCONF might work. */
|
||||
{
|
||||
FILE *f = fopen(IP6INTERFACES, "r");
|
||||
int found = 0;
|
||||
|
||||
if (f)
|
||||
{
|
||||
unsigned int plen, scope, flags, if_idx;
|
||||
char devname[20], addrstring[32];
|
||||
|
||||
while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
|
||||
addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
|
||||
{
|
||||
if (strcmp(devname, ifr->ifr_name) == 0)
|
||||
{
|
||||
int i;
|
||||
unsigned char *addr6p = (unsigned char *) &addr.in6.sin6_addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sa.sa_family = AF_INET6;
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
unsigned int byte;
|
||||
sscanf(addrstring+i+i, "%02x", &byte);
|
||||
addr6p[i] = byte;
|
||||
}
|
||||
addr.in6.sin6_port = htons(port);
|
||||
addr.in6.sin6_flowinfo = htonl(0);
|
||||
addr.in6.sin6_scope_id = htonl(scope);
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (found &&
|
||||
(err = add_iface(interfacep, ifr->ifr_flags, ifr->ifr_name,
|
||||
&addr, names, addrs, except)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
#endif /* LINUX */
|
||||
|
||||
/* dhcp is non-null only on the first call: set up the relevant
|
||||
interface-related DHCP stuff here. DHCP is IPv4 only.
|
||||
Because errors here are ultimately fatal we can return directly and not bother
|
||||
@@ -289,32 +350,48 @@ char *enumerate_interfaces(struct irec **interfacep,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_BPF
|
||||
/* now go through the interfaces again, looking for AF_LINK records
|
||||
to get hardware addresses from */
|
||||
for (ptr = buf; ptr < buf + ifc.ifc_len; )
|
||||
{
|
||||
struct ifreq *ifr = (struct ifreq *) ptr;
|
||||
struct dhcp_context *context;
|
||||
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
ptr += ifr->ifr_addr.sa_len + IF_NAMESIZE;
|
||||
/* subsequent entries may not be aligned, so copy into
|
||||
an aligned buffer to avoid nasty complaints about
|
||||
unaligned accesses. */
|
||||
int ifr_len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
|
||||
if (!(ifr = realloc(ifr, ifr_len)))
|
||||
{
|
||||
err = "cannot allocate buffer";
|
||||
goto end;
|
||||
}
|
||||
|
||||
memcpy(ifr, ptr, ifr_len);
|
||||
ptr += ifr_len;
|
||||
#else
|
||||
ifr = (struct ifreq *)ptr;
|
||||
ptr += sizeof(struct ifreq);
|
||||
#endif
|
||||
|
||||
if (ifr->ifr_addr.sa_family == AF_LINK)
|
||||
for (context = dhcp; context; context = context->next)
|
||||
if (context->iface && strcmp(context->iface, ifr->ifr_name) == 0)
|
||||
memcpy(context->hwaddr, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
end:
|
||||
errsave = errno; /* since errno gets overwritten by close */
|
||||
if (buf)
|
||||
free(buf);
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
if (ifr)
|
||||
free(ifr);
|
||||
#endif
|
||||
close(fd);
|
||||
if (err)
|
||||
{
|
||||
@@ -322,54 +399,6 @@ char *enumerate_interfaces(struct irec **interfacep,
|
||||
return err;
|
||||
}
|
||||
|
||||
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
|
||||
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
|
||||
/* This code snarfed from net-tools 1.60 and certainly linux specific, though
|
||||
it shouldn't break on other Unices, and their SIOGIFCONF might work. */
|
||||
{
|
||||
FILE *f = fopen(IP6INTERFACES, "r");
|
||||
|
||||
if (f)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
unsigned int plen, scope, flags, if_idx;
|
||||
char devname[20], addrstring[32];
|
||||
|
||||
while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
|
||||
addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
|
||||
{
|
||||
int i;
|
||||
unsigned char *addr6p = (unsigned char *) &addr.in6.sin6_addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sa.sa_family = AF_INET6;
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
unsigned int byte;
|
||||
sscanf(addrstring+i+i, "%02x", &byte);
|
||||
addr6p[i] = byte;
|
||||
}
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
/* For completeness - should never be defined on Linux. */
|
||||
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
addr.in6.sin6_port = htons(port);
|
||||
addr.in6.sin6_flowinfo = htonl(0);
|
||||
addr.in6.sin6_scope_id = htonl(scope);
|
||||
|
||||
if ((err = add_iface(interfacep, flags, devname, &addr, names, addrs, except)))
|
||||
{
|
||||
errsave = errno;
|
||||
fclose(f);
|
||||
errno = errsave;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
#endif /* LINUX */
|
||||
|
||||
/* now remove interfaces which were not found on this scan */
|
||||
for(prev = NULL, iface = *interfacep; iface; )
|
||||
{
|
||||
|
||||
64
src/option.c
64
src/option.c
@@ -175,14 +175,18 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
else
|
||||
{
|
||||
char *p;
|
||||
/* dump comments */
|
||||
for (p = buff; *p; p++)
|
||||
if (*p == '#')
|
||||
*p = 0;
|
||||
/* fgets gets end of line char too. */
|
||||
while (strlen(buff) > 0 &&
|
||||
(buff[strlen(buff)-1] == '\n' ||
|
||||
buff[strlen(buff)-1] == ' ' ||
|
||||
buff[strlen(buff)-1] == '\t'))
|
||||
buff[strlen(buff)-1] = 0;
|
||||
if (*buff == '#' || *buff == 0)
|
||||
continue; /* comment */
|
||||
if (*buff == 0)
|
||||
continue;
|
||||
if ((p=strchr(buff, '=')))
|
||||
{
|
||||
optarg = p+1;
|
||||
@@ -639,7 +643,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
new->clid = NULL;
|
||||
new->hostname = NULL;
|
||||
new->addr.s_addr = 0;
|
||||
new->lease_time = DEFLEASE;
|
||||
new->lease_time = 0;
|
||||
|
||||
a[0] = optarg;
|
||||
for (k = 1; k < 4; k++)
|
||||
@@ -706,8 +710,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
{
|
||||
case 'h':
|
||||
case 'H':
|
||||
fac *= 60;
|
||||
/* fall through */
|
||||
fac *= 60;
|
||||
/* fall through */
|
||||
case 'm':
|
||||
case 'M':
|
||||
fac *= 60;
|
||||
@@ -717,7 +721,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
}
|
||||
|
||||
for (cp = a[j]; *cp; cp++)
|
||||
if (!isdigit(*cp))
|
||||
if (!isdigit(*cp) && *cp != ' ')
|
||||
break;
|
||||
|
||||
if (*cp)
|
||||
@@ -739,24 +743,33 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
{
|
||||
struct dhcp_opt *new = safe_malloc(sizeof(struct dhcp_opt));
|
||||
char *cp, *comma = strchr(optarg, ',');
|
||||
int addrs;
|
||||
int addrs, is_addr;
|
||||
|
||||
new->next = *dhcp_opts;
|
||||
new->len = 0;
|
||||
new->is_addr = 0;
|
||||
*dhcp_opts = new;
|
||||
|
||||
if (!comma || (*comma = 0) || (new->opt = atoi(optarg)) == 0)
|
||||
if ((new->opt = atoi(optarg)) == 0)
|
||||
{
|
||||
option = '?';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!comma)
|
||||
break;
|
||||
|
||||
*comma = 0;
|
||||
|
||||
/* check for non-address list characters */
|
||||
for (addrs = 1, cp = comma+1; *cp; cp++)
|
||||
for (addrs = 1, is_addr = 0, cp = comma+1; *cp; cp++)
|
||||
if (*cp == ',')
|
||||
addrs++;
|
||||
else if (!(*cp == '.' || *cp == ' ' || (*cp >='0' && *cp <= '9')))
|
||||
break;
|
||||
|
||||
else if (*cp == '.')
|
||||
is_addr = 1;
|
||||
|
||||
if (*cp)
|
||||
{
|
||||
/* text arg */
|
||||
@@ -768,17 +781,28 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
{
|
||||
struct in_addr in;
|
||||
unsigned char *op;
|
||||
new->len = INADDRSZ * addrs;
|
||||
new->val = op = safe_malloc(new->len);
|
||||
while (addrs--)
|
||||
|
||||
if (addrs == 1 && !is_addr)
|
||||
{
|
||||
cp = comma;
|
||||
if (cp && (comma = strchr(cp+1, ',')))
|
||||
*comma = 0;
|
||||
if (cp && (in.s_addr = inet_addr(cp+1)) == (in_addr_t)-1)
|
||||
option = '?';
|
||||
memcpy(op, &in, INADDRSZ);
|
||||
op += INADDRSZ;
|
||||
new->len = 1;
|
||||
new->val = safe_malloc(1);
|
||||
*(new->val) = atoi(comma+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
new->len = INADDRSZ * addrs;
|
||||
new->val = op = safe_malloc(new->len);
|
||||
new->is_addr = 1;
|
||||
while (addrs--)
|
||||
{
|
||||
cp = comma;
|
||||
if (cp && (comma = strchr(cp+1, ',')))
|
||||
*comma = 0;
|
||||
if (cp && (in.s_addr = inet_addr(cp+1)) == (in_addr_t)-1)
|
||||
option = '?';
|
||||
memcpy(op, &in, INADDRSZ);
|
||||
op += INADDRSZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -139,7 +139,7 @@ int dhcp_reply(struct dhcp_context *context, struct dhcp_packet *mess,
|
||||
|
||||
/* search again now we have a hostname */
|
||||
config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, hostname);
|
||||
def_time = config ? config->lease_time : context->lease_time;
|
||||
def_time = config && config->lease_time ? config->lease_time : context->lease_time;
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
||||
{
|
||||
@@ -444,6 +444,9 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
if (!req_options)
|
||||
return p;
|
||||
|
||||
if (in_list(req_options, OPTION_MAXMESSAGE))
|
||||
p = option_put(p, end, OPTION_MAXMESSAGE, 2, sizeof(struct udp_dhcp_packet));
|
||||
|
||||
if (in_list(req_options, OPTION_NETMASK) &&
|
||||
!option_find2(config_opts, OPTION_NETMASK))
|
||||
p = option_put(p, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
|
||||
@@ -484,12 +487,34 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
for (i = 0; req_options[i] != OPTION_END; i++)
|
||||
{
|
||||
struct dhcp_opt *opt = option_find2(config_opts, req_options[i]);
|
||||
if (req_options[i] != OPTION_HOSTNAME && opt && (p + opt->len + 2 < end))
|
||||
if (req_options[i] != OPTION_HOSTNAME &&
|
||||
req_options[i] != OPTION_MAXMESSAGE &&
|
||||
opt && (p + opt->len + 2 < end))
|
||||
{
|
||||
*(p++) = opt->opt;
|
||||
*(p++) = opt->len;
|
||||
memcpy(p, opt->val, opt->len);
|
||||
p += opt->len;
|
||||
if (opt->len != 0)
|
||||
{
|
||||
if (opt->is_addr)
|
||||
{
|
||||
int j;
|
||||
struct in_addr *a = (struct in_addr *)opt->val;
|
||||
for (j = 0; j < opt->len; j+=INADDRSZ, a++)
|
||||
{
|
||||
/* zero means "self" */
|
||||
if (a->s_addr == 0)
|
||||
memcpy(p, &context->serv_addr, INADDRSZ);
|
||||
else
|
||||
memcpy(p, a, INADDRSZ);
|
||||
p += INADDRSZ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(p, opt->val, opt->len);
|
||||
p += opt->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user