Compare commits

..

2 Commits
v2.3 ... v2.5

Author SHA1 Message Date
Simon Kelley
8a911ccc75 import of dnsmasq-2.5.tar.gz 2012-01-05 17:31:10 +00:00
Simon Kelley
1cff166d37 import of dnsmasq-2.4.tar.gz 2012-01-05 17:31:10 +00:00
17 changed files with 296 additions and 113 deletions

View File

@@ -821,5 +821,43 @@ release 2.3
embedded systems without a stable RTC. Oleg Vdovikin
helped work out how to make that work.
release 2.4
Fixed inability to start when the lease file doesn't
already exist. Thanks to Dag Wieers for reporting that.
Fixed problem were dhcp-host configuration options did
not play well with entries in /etc/ethers for the same
host. Thanks again to Dag Wieers.
Tweaked DHCP code to favour moving to a newly-configured
static IP address rather than an old lease when doing
DHCP allocation.
Added --alias configuration option. This provides IPv4
rewrite facilities like Cisco "DNS doctoring". Suggested
by Chad Skeeters.
Fixed bug in /etc/ethers parsing code triggered by tab
characters. Qudos to Dag Wieers for hepling to nail that
one.
Added "bind-interfaces" option correctly.
release 2.5
Made "where are we allocating addresses?" code in DHCP
server cope with requests via a relay which is on a
directly connected network for which there is not a
configured netmask. This strange state of affairs occurs
with win4lin. Thanks to Alex Melt and Jim Horner for bug
reports and testing with this.
Fixed trivial-but-irritating missing #include which broke
compilation on *BSD.
Force --bind-interfaces if IP-aliased interface
specifications are used, since the sockets API provides
no other sane way to determine which alias of an
interface a packet was sent to. Thanks to Javier Kohen
for the bug report.

View File

@@ -5,7 +5,7 @@
###############################################################################
Name: dnsmasq
Version: 2.3
Version: 2.5
Release: 1
Copyright: GPL
Group: System Environment/Daemons

View File

@@ -5,7 +5,7 @@
###############################################################################
Name: dnsmasq
Version: 2.3
Version: 2.5
Release: 1
Copyright: GPL
Group: System Environment/Daemons

View File

@@ -5,7 +5,7 @@
###############################################################################
Name: dnsmasq
Version: 2.3
Version: 2.5
Release: 1
Copyright: GPL
Group: Productivity/Networking/DNS/Servers

View File

@@ -82,7 +82,14 @@ flags are given, dnsmasq listens on all available interfaces unless overridden b
.B \-a
or
.B \-I
flags.
flags. If IP alias interfaces (eg "eth1:0") are used with
.B --interface
or
.B --except-interface
options, then the
.B --bind-interfaces
option will be automatically set. This is required for deeply boring
sockets-API reasons.
.TP
.B \-I, --except-interface=<interface name>
Do not listen on the specified interface.
@@ -108,12 +115,22 @@ requests that it shouldn't reply to. This has the advantage of
working even when interfaces come and go and change address. This
option forces dnsmasq to really bind only the interfaces it is
listening on. About the only time when this is useful is when
running another nameserver on the same machine.
running another nameserver on the same machine or using IP
alias. Specifying interfaces with IP alias automatically turns this
option on.
.TP
.B \-b, --bogus-priv
Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc)
which are not found in /etc/hosts or the DHCP leases file are resolved to the IP address in dotted-quad form.
.TP
.B \-V, --alias=<old-ip>,<new-ip>[,<mask>]
Modify IPv4 addresses returned from upstream nameservers; old-ip is
replaced by new-ip. If the optional mask is given then any address
which matches the masked old-ip will be re-written. So, for instance
.B --alias=1.2.3.0,6.7.8.0,255.255.255.0
will map 1.2.3.56 to 6.7.8.56 and 1.2.3.67 to 6.7.8.67. This is what
Cisco PIX routers call "DNS doctoring".
.TP
.B \-B, --bogus-nxdomain=<ipaddr>
Transform replies which contain the IP address given into "No such
domain" replies. This is intended to counteract a devious move made by

View File

@@ -243,6 +243,15 @@ filterwin2k
# registries which have implemented wildcard A records.
#bogus-nxdomain=64.94.110.11
# If you want to fix up DNS results from upstream servers, use the
# alias option. This only works for IPv4.
# This alias makes a result of 1.2.3.4 appear as 5.6.7.8
#alias=1.2.3.4,5.6.7.8
# and this maps 1.2.3.x to 5.6.7.x
#alias=1.2.3.0,5.6.7.0,255.255.255.0
# For debugging purposes, log each DNS query as it passes through
# dnsmasq.
#log-queries

View File

@@ -641,7 +641,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
if (crec->flags & F_HOSTS)
{
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);
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))
{
@@ -653,7 +653,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
goto newrec;
}
else
syslog(LOG_WARNING, "Not naming 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;
}
@@ -686,7 +686,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
void dump_cache(int debug, int cache_size)
{
syslog(LOG_INFO, "Cache size %d, %d/%d cache insertions re-used unexpired cache entries.",
syslog(LOG_INFO, "cache size %d, %d/%d cache insertions re-used unexpired cache entries.",
cache_size, cache_live_freed, cache_inserted);
if (debug)

View File

@@ -12,7 +12,7 @@
/* Author's email: simon@thekelleys.org.uk */
#define VERSION "2.3"
#define VERSION "2.5"
#define FTABSIZ 150 /* max number of outstanding requests */
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */

View File

@@ -21,7 +21,7 @@ void dhcp_init(int *fdp, int* rfdp)
int opt = 1;
if (fd == -1)
die ("Cannot create DHCP socket : %s", NULL);
die ("cannot create DHCP socket : %s", NULL);
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
#if defined(IP_PKTINFO)
@@ -49,11 +49,11 @@ void dhcp_init(int *fdp, int* rfdp)
if ((fd = open(filename, O_RDWR, 0)) != -1)
break;
if (errno != EBUSY)
die("Cannot create DHCP BPF socket: %s", NULL);
die("cannot create DHCP BPF socket: %s", NULL);
}
#else
if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_IP))) == -1)
die("Cannot create DHCP packet socket: %s", NULL);
die("cannot create DHCP packet socket: %s", NULL);
#endif
*rfdp = fd;
@@ -75,7 +75,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
struct iovec iov[2];
struct cmsghdr *cmptr;
int sz, newlen, iface_index = 0;
struct in_addr source, real_netmask, iface_addr, netmask_save, broadcast_save;
struct in_addr source, iface_netmask, iface_addr, iface_broadcast;
struct in_addr netmask_save, broadcast_save, router;
#ifdef HAVE_BPF
unsigned char iface_hwaddr[ETHER_ADDR_LEN];
#endif
@@ -112,7 +113,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
if (!iface_index || !if_indextoname(iface_index, ifr.ifr_name))
if (!(ifr.ifr_ifindex = iface_index) ||
ioctl(dhcp_fd, SIOCGIFNAME, &ifr) == -1)
return;
#elif defined(IP_RECVIF)
@@ -169,17 +171,30 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
/* If the packet came via a relay, use that address to look up the context,
else use the address of the interface is arrived on. */
source = mess->giaddr.s_addr ? mess->giaddr : iface_addr;
iface_netmask.s_addr = 0;
iface_broadcast.s_addr = 0;
if (ioctl(dhcp_fd, SIOCGIFNETMASK, &ifr) != -1)
{
iface_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
/* 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,
but it happens with win4lin. */
if ((source.s_addr & iface_netmask.s_addr) != (iface_addr.s_addr & iface_netmask.s_addr))
iface_netmask.s_addr = 0;
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
iface_broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
for (context = contexts; context; context = context->next)
{
if (!context->netmask.s_addr && !mess->giaddr.s_addr && ioctl(dhcp_fd, SIOCGIFNETMASK, &ifr) != -1)
real_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
else
real_netmask = context->netmask;
if (real_netmask.s_addr &&
(source.s_addr & real_netmask.s_addr) == (context->start.s_addr & real_netmask.s_addr) &&
(source.s_addr & real_netmask.s_addr) == (context->end.s_addr & real_netmask.s_addr))
struct in_addr netmask = context->netmask.s_addr ? context->netmask : iface_netmask;
if (netmask.s_addr &&
(source.s_addr & netmask.s_addr) == (context->start.s_addr & netmask.s_addr) &&
(source.s_addr & netmask.s_addr) == (context->end.s_addr & netmask.s_addr))
break;
}
@@ -192,26 +207,34 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
netmask_save = context->netmask;
broadcast_save = context->broadcast;
context->netmask = real_netmask;
if (!context->netmask.s_addr)
context->netmask = iface_netmask;
if (!context->broadcast.s_addr)
{
if (mess->giaddr.s_addr)
context->broadcast.s_addr = (mess->giaddr.s_addr & real_netmask.s_addr) | ~real_netmask.s_addr;
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
context->broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
if (iface_broadcast.s_addr)
context->broadcast = iface_broadcast;
else
context->broadcast.s_addr = (iface_addr.s_addr & real_netmask.s_addr) | ~real_netmask.s_addr;
context->broadcast.s_addr = (source.s_addr & context->netmask.s_addr) | ~context->netmask.s_addr;
}
if (ioctl(dhcp_fd, SIOCGIFMTU, &ifr) == -1)
ifr.ifr_mtu = ETHERMTU;
/* Normally, we set the default route to point to the machine which is getting the
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.
This is the win4lin scenario again. */
if ((source.s_addr & context->netmask.s_addr) == (iface_addr.s_addr & context->netmask.s_addr))
router = iface_addr;
else
router = source;
lease_prune(NULL, now); /* lose any expired leases */
newlen = dhcp_reply(context, iface_addr, ifr.ifr_name, ifr.ifr_mtu,
rawpacket, sz, now, namebuff,
dhcp_opts, dhcp_configs, domain_suffix, dhcp_file,
dhcp_sname, dhcp_next_server);
dhcp_sname, dhcp_next_server, router);
lease_update_file(0, now);
lease_update_dns();
@@ -426,7 +449,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
if (hostname)
for (config = configs; config; config = config->next)
if (config->hostname && strcmp(config->hostname, hostname) == 0 &&
if (config->hostname && hostname_isequal(config->hostname, hostname) &&
is_addr_in_context(context, config))
return config;
@@ -439,24 +462,25 @@ struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
unsigned int e0, e1, e2, e3, e4, e5;
char *ip, *cp, *name;
struct in_addr addr;
struct dhcp_config *new;
struct dhcp_config *config;
if (!f)
die("Failed to open " ETHERSFILE ":%s", NULL);
die("failed to open " ETHERSFILE ":%s", NULL);
while (fgets(buff, MAXDNAME, f))
{
while (strlen(buff) > 0 &&
(buff[strlen(buff)-1] == '\n' ||
buff[strlen(buff)-1] == ' ' ||
buff[strlen(buff)-1] == '\r' ||
buff[strlen(buff)-1] == '\t'))
buff[strlen(buff)-1] = 0;
if ((*buff == '#') || (*buff == '+'))
continue;
for (ip = buff; *ip && *ip != ' '; ip++);
for(; *ip && *ip == ' '; ip++)
for (ip = buff; *ip && *ip != ' ' && *ip != '\t'; ip++);
for(; *ip && (*ip == ' ' || *ip == '\t'); ip++)
*ip = 0;
if (!*ip)
continue;
@@ -473,29 +497,42 @@ struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
{
name = NULL;
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
continue;
continue;
for (config = configs; config; config = config->next)
if (config->addr.s_addr == addr.s_addr)
break;
}
else
{
name = safe_string_alloc(ip);
if (!canonicalise(ip))
continue;
name = ip;
addr.s_addr = 0;
for (config = configs; config; config = config->next)
if (config->hostname && hostname_isequal(config->hostname, name))
break;
}
new = safe_malloc(sizeof(struct dhcp_config));
new->clid_len = 0;
new->clid = NULL;
new->hwaddr[0] = e0;
new->hwaddr[1] = e1;
new->hwaddr[2] = e2;
new->hwaddr[3] = e3;
new->hwaddr[4] = e4;
new->hwaddr[5] = e5;
new->hostname = name;
new->addr = addr;
new->lease_time = 0;
new->next = configs;
configs = new;
if (!config)
{
config = safe_malloc(sizeof(struct dhcp_config));
config->clid_len = 0;
config->clid = NULL;
config->lease_time = 0;
config->hostname = safe_string_alloc(name);
config->addr = addr;
config->next = configs;
configs = config;
}
config->hwaddr[0] = e0;
config->hwaddr[1] = e1;
config->hwaddr[2] = e2;
config->hwaddr[3] = e3;
config->hwaddr[4] = e4;
config->hwaddr[5] = e5;
}
fclose(f);

View File

@@ -44,6 +44,7 @@ int main (int argc, char **argv)
time_t now, last = 0;
struct irec *interfaces = NULL;
struct listener *listener, *listeners;
struct doctor *doctors = NULL;
char *mxname = NULL;
char *mxtarget = NULL;
char *lease_file = NULL;
@@ -109,7 +110,8 @@ int main (int argc, char **argv)
&if_names, &if_addrs, &if_except, &bogus_addr,
&serv_addrs, &cachesize, &port, &query_port, &local_ttl, &addn_hosts,
&dhcp, &dhcp_configs, &dhcp_options,
&dhcp_file, &dhcp_sname, &dhcp_next_server, &maxleases, &min_leasetime);
&dhcp_file, &dhcp_sname, &dhcp_next_server, &maxleases, &min_leasetime,
&doctors);
/* if we cannot support binding the wildcard address, set the "bind only
interfaces in use" option */
@@ -152,7 +154,6 @@ int main (int argc, char **argv)
leasefd = lease_init(lease_file, domain_suffix, dnamebuff, packet, now, maxleases);
if (options & OPT_ETHERS)
dhcp_configs = dhcp_read_ethers(dhcp_configs, dnamebuff);
dhcp_update_configs(dhcp_configs);
lease_update_from_configs(dhcp_configs, domain_suffix); /* must follow cache_init and lease_init */
lease_update_file(0, now);
lease_update_dns();
@@ -390,7 +391,7 @@ int main (int argc, char **argv)
for (serverfdp = sfds; serverfdp; serverfdp = serverfdp->next)
if (FD_ISSET(serverfdp->fd, &rset))
last_server = reply_query(serverfdp->fd, options, packet, now,
dnamebuff, last_server, bogus_addr);
dnamebuff, last_server, bogus_addr, doctors);
if (dhcp && FD_ISSET(dhcpfd, &rset))
dhcp_packet(dhcp, packet, dhcp_options, dhcp_configs,

View File

@@ -40,6 +40,7 @@
# include <sys/sockio.h>
#endif
#include <sys/time.h>
#include <limits.h>
#include <net/if.h>
#include <unistd.h>
#include <stdio.h>
@@ -105,6 +106,12 @@ struct bogus_addr {
struct bogus_addr *next;
};
/* dns doctor param */
struct doctor {
struct in_addr in, out, mask;
struct doctor *next;
};
union bigname {
char name[MAXDNAME];
union bigname *next; /* freelist */
@@ -304,7 +311,8 @@ unsigned short extract_request(HEADER *header, unsigned int qlen, char *name);
int setup_reply(HEADER *header, unsigned int qlen,
struct all_addr *addrp, unsigned short flags,
unsigned long local_ttl);
void extract_addresses(HEADER *header, unsigned int qlen, char *namebuff, time_t now);
void extract_addresses(HEADER *header, unsigned int qlen, char *namebuff,
time_t now, struct doctor *doctors);
void extract_neg_addrs(HEADER *header, unsigned int qlen, char *namebuff, time_t now);
int answer_request(HEADER *header, char *limit, unsigned int qlen, char *mxname,
char *mxtarget, unsigned int options, time_t now, unsigned long local_ttl,
@@ -334,13 +342,13 @@ unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resol
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,
char **dhcp_file, char **dhcp_sname, struct in_addr *dhcp_next_server,
int *maxleases, unsigned int *min_leasetime);
int *maxleases, unsigned int *min_leasetime, struct doctor **doctors);
/* forward.c */
void forward_init(int first);
struct server *reply_query(int fd, int options, char *packet, time_t now,
char *dnamebuff, struct server *last_server,
struct bogus_addr *bogus_nxdomain);
struct bogus_addr *bogus_nxdomain, struct doctor *doctors);
struct server *receive_query(struct listener *listen, char *packet, char *mxname,
char *mxtarget, unsigned int options, time_t now,
@@ -396,5 +404,5 @@ int dhcp_reply(struct dhcp_context *context,
unsigned int sz, time_t now, char *namebuff,
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
struct in_addr dhcp_next_server);
struct in_addr dhcp_next_server, struct in_addr router);

View File

@@ -104,7 +104,6 @@ static void send_from(int fd, int nowild, char *packet, int len,
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmptr->cmsg_type = IPV6_PKTINFO;
cmptr->cmsg_level = IPV6_LEVEL;
cmptr->cmsg_level = IPPROTO_IPV6;
}
#endif
@@ -314,7 +313,8 @@ static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
/* returns new last_server */
struct server *reply_query(int fd, int options, char *packet, time_t now,
char *dnamebuff, struct server *last_server, struct bogus_addr *bogus_nxdomain)
char *dnamebuff, struct server *last_server,
struct bogus_addr *bogus_nxdomain, struct doctor *doctors)
{
/* packet from peer server, extract data for cache, and send to
original requester */
@@ -338,7 +338,7 @@ struct server *reply_query(int fd, int options, char *packet, time_t now,
check_for_bogus_wildcard(header, (unsigned int)n, dnamebuff, bogus_nxdomain, now)))
{
if (header->rcode == NOERROR && ntohs(header->ancount) != 0)
extract_addresses(header, (unsigned int)n, dnamebuff, now);
extract_addresses(header, (unsigned int)n, dnamebuff, now, doctors);
else if (!(options & OPT_NO_NEG))
extract_neg_addrs(header, (unsigned int)n, dnamebuff, now);
}
@@ -367,11 +367,10 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
union mysockaddr source_addr;
struct iname *tmp;
struct all_addr dst_addr;
int m, n, gotit = 0;
int m, n, if_index = 0;
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmptr;
char if_name[IF_NAMESIZE];
union {
struct cmsghdr align; /* this ensures alignment */
#ifdef HAVE_IPV6
@@ -413,20 +412,16 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
{
dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
if_indextoname(((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex, if_name);
gotit = 1;
if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
}
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
if (!(options & OPT_NOWILD) && listen->family == AF_INET)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
{
dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
gotit = 1;
}
dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
if_indextoname(((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index, if_name);
if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
}
#endif
@@ -437,8 +432,7 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO)
{
dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
if_indextoname(((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex, if_name);
gotit = 1;
if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex;
}
}
#endif
@@ -449,17 +443,31 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
/* enforce available interface configuration */
if (!(options & OPT_NOWILD))
{
if (!gotit)
struct ifreq ifr;
if (if_index == 0)
return last_server;
if (except || names)
{
#ifdef SIOCGIFNAME
ifr.ifr_ifindex = if_index;
if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
return last_server;
#else
if (!if_indextoname(if_index, ifr.ifr_name))
return last_server;
#endif
}
for (tmp = except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, if_name) == 0))
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return last_server;
if (names || addrs)
{
for (tmp = names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, if_name) == 0))
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
break;
if (!tmp)
for (tmp = addrs; tmp; tmp = tmp->next)

View File

@@ -34,9 +34,13 @@ int lease_init(char *filename, char *domain, char *buff,
leases = NULL;
leases_left = maxleases;
if (!(lease_file = fopen(filename, "r+")))
/* NOTE: need a+ mode to create file if it doesn't exist */
if (!(lease_file = fopen(filename, "a+")))
die("cannot open or create leases file: %s", NULL);
/* a+ mode lease pointer at end. */
rewind(lease_file);
while (fscanf(lease_file, "%lu %x:%x:%x:%x:%x:%x %d.%d.%d.%d %256s %500s",
&ei, &e0, &e1, &e2, &e3, &e4, &e5, &a0, &a1, &a2, &a3, buff, buff2) == 13)
{

View File

@@ -33,12 +33,10 @@ static struct irec *add_iface(struct irec *list, char *name, union mysockaddr *a
for (tmp = names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
break;
if (!tmp && !addrs)
return NULL;
for (tmp = addrs; tmp; tmp = tmp->next)
if (sockaddr_isequal(&tmp->addr, addr))
break;
if (!tmp)
for (tmp = addrs; tmp; tmp = tmp->next)
if (sockaddr_isequal(&tmp->addr, addr))
break;
if (!tmp)
return NULL;
}
@@ -147,7 +145,7 @@ struct irec *enumerate_interfaces(struct iname *names,
lo->next = names->next;
names->next = lo;
}
if ((new = add_iface(iface, ifr->ifr_name,
&addr, names, addrs, except)))
{

View File

@@ -21,7 +21,7 @@ struct myoption {
int val;
};
#define OPTSTRING "ZDNLERzowefnbvhdqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:"
#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:"
static struct myoption opts[] = {
{"version", 0, 0, 'v'},
@@ -67,7 +67,9 @@ static struct myoption opts[] = {
{"except-interface", 1, 0, 'I'},
{"domain-needed", 0, 0, 'D'},
{"dhcp-lease-max", 1, 0, 'X' },
{"bind-interfaces", 0, 0, 'z'},
{"read-ethers", 0, 0, 'Z' },
{"alias", 1, 0, 'V' },
{0, 0, 0, 0}
};
@@ -138,6 +140,7 @@ static char *usage =
"-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"
"-v, --version Display dnsmasq version.\n"
"-V, --alias=addr,addr,mask Translate IPv4 addresses from upstream servers.\n"
"-w, --help Display this message.\n"
"-x, --pid-file=path Specify path of PID file. (defaults to " RUNFILE ").\n"
"-X, --dhcp-lease-max=number Specify maximum number of DHCP leases (defaults to %d).\n"
@@ -154,7 +157,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
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,
char **dhcp_sname, struct in_addr *dhcp_next_server, int *dhcp_max,
unsigned int *min_leasetime)
unsigned int *min_leasetime, struct doctor **doctors)
{
int option = 0, i;
unsigned int flags = 0;
@@ -162,7 +165,6 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
char *conffile = CONFFILE;
int conffile_set = 0;
int lineno = 0;
opterr = 0;
*min_leasetime = UINT_MAX;
@@ -194,7 +196,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
/* fgets gets end of line char too. */
while (strlen(buff) > 0 &&
(buff[strlen(buff)-1] == '\n' ||
buff[strlen(buff)-1] == ' ' ||
buff[strlen(buff)-1] == ' ' ||
buff[strlen(buff)-1] == '\r' ||
buff[strlen(buff)-1] == '\t'))
buff[strlen(buff)-1] = 0;
if (*buff == 0)
@@ -355,6 +358,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
/* new->name may be NULL if someone does
"interface=" to disable all interfaces except loop. */
new->name = safe_string_alloc(optarg);
if (strchr(optarg, ':'))
flags |= OPT_NOWILD;
break;
}
@@ -364,6 +369,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
new->next = *if_except;
*if_except = new;
new->name = safe_string_alloc(optarg);
if (strchr(optarg, ':'))
flags |= OPT_NOWILD;
break;
}
@@ -680,14 +687,13 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
}
new->lease_time = atoi(a[leasepos]) * fac;
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
}
}
}
new->last = new->start;
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
break;
}
@@ -799,17 +805,17 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
new->hostname = safe_string_alloc(a[j]);
}
else
{
new->lease_time = atoi(a[j]) * fac;
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
}
new->lease_time = atoi(a[j]) * fac;
}
if (option == '?')
free(new);
else
*dhcp_conf = new;
{
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
*dhcp_conf = new;
}
break;
}
@@ -920,6 +926,44 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
}
break;
}
case 'V':
{
char *a[3] = { NULL, NULL, NULL };
int k;
struct in_addr in, out, mask;
struct doctor *new;
mask.s_addr = 0xffffffff;
a[0] = optarg;
for (k = 1; k < 4; k++)
{
if (!(a[k] = strchr(a[k-1], ',')))
break;
*(a[k]++) = 0;
}
if ((k < 2) ||
((in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
((out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
{
option = '?';
break;
}
if (k == 3)
mask.s_addr = inet_addr(a[2]);
new = safe_malloc(sizeof(struct doctor));
new->in = in;
new->out = out;
new->mask = mask;
new->next = *doctors;
*doctors = new;
break;
}
}
}
@@ -981,7 +1025,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
*resolv_files = 0;
else if (*resolv_files && (*resolv_files)->next && (flags & OPT_NO_POLL))
die("only one resolv.conf file allowed in no-poll mode.", NULL);
return flags;
}

View File

@@ -440,7 +440,19 @@ void extract_neg_addrs(HEADER *header, unsigned int qlen, char *name, time_t now
cache_end_insert();
}
void extract_addresses(HEADER *header, unsigned int qlen, char *name, time_t now)
static void dns_doctor(struct doctor *doctor, struct in_addr *addr)
{
for (; doctor; doctor = doctor->next)
if ((doctor->in.s_addr & doctor->mask.s_addr) == (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);
break;
}
}
void extract_addresses(HEADER *header, unsigned int qlen, char *name,
time_t now, struct doctor *doctors)
{
unsigned char *p, *psave, *endrr;
int qtype, qclass, rdlen;
@@ -477,8 +489,11 @@ void extract_addresses(HEADER *header, unsigned int qlen, char *name, time_t now
}
if (qtype == T_A) /* A record. */
cache_insert(name, (struct all_addr *)p, now,
ttl, F_IPV4 | F_FORWARD);
{
dns_doctor(doctors, (struct in_addr *)p);
cache_insert(name, (struct all_addr *)p, now,
ttl, F_IPV4 | F_FORWARD);
}
#ifdef HAVE_IPV6
else if (qtype == T_AAAA) /* IPV6 address record. */
cache_insert(name, (struct all_addr *)p, now,
@@ -546,8 +561,11 @@ void extract_addresses(HEADER *header, unsigned int qlen, char *name, time_t now
return;
if (qtype == T_A) /* A record. */
cache_insert(name, (struct all_addr *)p, now,
cttl, F_IPV4 | F_FORWARD);
{
dns_doctor(doctors, (struct in_addr *)p);
cache_insert(name, (struct all_addr *)p, now,
cttl, F_IPV4 | F_FORWARD);
}
#ifdef HAVE_IPV6
else if (qtype == T_AAAA) /* IPV6 address record. */
cache_insert(name, (struct all_addr *)p, now,

View File

@@ -61,7 +61,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
unsigned char *req_options,
struct dhcp_opt *config_opts,
char *domainname, char *hostname,
struct in_addr relay,
struct in_addr router,
struct in_addr iface_addr,
int iface_mtu);
@@ -74,7 +74,7 @@ int dhcp_reply(struct dhcp_context *context,
unsigned int sz, time_t now, char *namebuff,
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
struct in_addr dhcp_next_server)
struct in_addr dhcp_next_server, struct in_addr router)
{
unsigned char *opt, *clid;
struct dhcp_lease *lease;
@@ -246,11 +246,12 @@ int dhcp_reply(struct dhcp_context *context,
log_packet("DISCOVER", opt ? &mess->yiaddr : NULL, mess->chaddr, iface_name, NULL);
if (lease &&
((lease->addr.s_addr & context->netmask.s_addr) == (context->start.s_addr & context->netmask.s_addr)))
mess->yiaddr = lease->addr;
else if (config && config->addr.s_addr && !lease_find_by_addr(config->addr))
if (config && config->addr.s_addr && !lease_find_by_addr(config->addr))
mess->yiaddr = config->addr;
else if (lease &&
((lease->addr.s_addr & context->netmask.s_addr) ==
(context->start.s_addr & context->netmask.s_addr)))
mess->yiaddr = lease->addr;
else if ((!opt || !address_available(context, mess->yiaddr)) &&
!address_allocate(context, dhcp_configs, &mess->yiaddr))
{
@@ -264,7 +265,7 @@ int dhcp_reply(struct dhcp_context *context,
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 = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
NULL, mess->giaddr, iface_addr, iface_mtu);
NULL, router, iface_addr, iface_mtu);
p = option_put(p, end, OPTION_END, 0, 0);
log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL);
@@ -353,7 +354,7 @@ int dhcp_reply(struct dhcp_context *context,
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,
hostname, mess->giaddr, iface_addr, iface_mtu);
hostname, router, iface_addr, iface_mtu);
p = option_put(p, end, OPTION_END, 0, 0);
return p - (unsigned char *)mess;
@@ -363,7 +364,7 @@ int dhcp_reply(struct dhcp_context *context,
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 = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
hostname, mess->giaddr, iface_addr, iface_mtu);
hostname, router, iface_addr, iface_mtu);
p = option_put(p, end, OPTION_END, 0, 0);
log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname);
@@ -537,7 +538,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
unsigned char *req_options,
struct dhcp_opt *config_opts,
char *domainname, char *hostname,
struct in_addr relay,
struct in_addr router,
struct in_addr iface_addr,
int iface_mtu)
{
@@ -562,7 +563,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
if (in_list(req_options, OPTION_ROUTER) &&
!option_find2(context, config_opts, OPTION_ROUTER))
p = option_put(p, end, OPTION_ROUTER, INADDRSZ,
ntohl(relay.s_addr ? relay.s_addr : iface_addr.s_addr ));
ntohl(router.s_addr));
if (in_list(req_options, OPTION_DNSSERVER) &&
!option_find2(context, config_opts, OPTION_DNSSERVER))