import of dnsmasq-2.4.tar.gz

This commit is contained in:
Simon Kelley
2004-03-12 08:12:58 +00:00
parent 44a2a3165c
commit 1cff166d37
17 changed files with 184 additions and 59 deletions

View File

@@ -821,5 +821,27 @@ release 2.3
embedded systems without a stable RTC. Oleg Vdovikin embedded systems without a stable RTC. Oleg Vdovikin
helped work out how to make that work. 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.

View File

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

View File

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

View File

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

View File

@@ -114,6 +114,14 @@ running another nameserver on the same machine.
Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc) 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. which are not found in /etc/hosts or the DHCP leases file are resolved to the IP address in dotted-quad form.
.TP .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> .B \-B, --bogus-nxdomain=<ipaddr>
Transform replies which contain the IP address given into "No such Transform replies which contain the IP address given into "No such
domain" replies. This is intended to counteract a devious move made by 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. # registries which have implemented wildcard A records.
#bogus-nxdomain=64.94.110.11 #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 # For debugging purposes, log each DNS query as it passes through
# dnsmasq. # dnsmasq.
#log-queries #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->flags & F_HOSTS)
{ {
if (crec->addr.addr.addr4.s_addr != host_address->s_addr) 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)) 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; goto newrec;
} }
else 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; 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) 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); cache_size, cache_live_freed, cache_inserted);
if (debug) if (debug)

View File

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

View File

@@ -21,7 +21,7 @@ void dhcp_init(int *fdp, int* rfdp)
int opt = 1; int opt = 1;
if (fd == -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 (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
#if defined(IP_PKTINFO) #if defined(IP_PKTINFO)
@@ -49,11 +49,11 @@ void dhcp_init(int *fdp, int* rfdp)
if ((fd = open(filename, O_RDWR, 0)) != -1) if ((fd = open(filename, O_RDWR, 0)) != -1)
break; break;
if (errno != EBUSY) if (errno != EBUSY)
die("Cannot create DHCP BPF socket: %s", NULL); die("cannot create DHCP BPF socket: %s", NULL);
} }
#else #else
if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_IP))) == -1) 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 #endif
*rfdp = fd; *rfdp = fd;
@@ -426,7 +426,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
if (hostname) if (hostname)
for (config = configs; config; config = config->next) 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)) is_addr_in_context(context, config))
return config; return config;
@@ -439,24 +439,25 @@ struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
unsigned int e0, e1, e2, e3, e4, e5; unsigned int e0, e1, e2, e3, e4, e5;
char *ip, *cp, *name; char *ip, *cp, *name;
struct in_addr addr; struct in_addr addr;
struct dhcp_config *new; struct dhcp_config *config;
if (!f) if (!f)
die("Failed to open " ETHERSFILE ":%s", NULL); die("failed to open " ETHERSFILE ":%s", NULL);
while (fgets(buff, MAXDNAME, f)) while (fgets(buff, MAXDNAME, f))
{ {
while (strlen(buff) > 0 && while (strlen(buff) > 0 &&
(buff[strlen(buff)-1] == '\n' || (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] == '\t'))
buff[strlen(buff)-1] = 0; buff[strlen(buff)-1] = 0;
if ((*buff == '#') || (*buff == '+')) if ((*buff == '#') || (*buff == '+'))
continue; continue;
for (ip = buff; *ip && *ip != ' '; ip++); for (ip = buff; *ip && *ip != ' ' && *ip != '\t'; ip++);
for(; *ip && *ip == ' '; ip++) for(; *ip && (*ip == ' ' || *ip == '\t'); ip++)
*ip = 0; *ip = 0;
if (!*ip) if (!*ip)
continue; continue;
@@ -473,29 +474,42 @@ struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
{ {
name = NULL; name = NULL;
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1) 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 else
{ {
name = safe_string_alloc(ip); if (!canonicalise(ip))
continue;
name = ip;
addr.s_addr = 0; 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)); if (!config)
new->clid_len = 0; {
new->clid = NULL; config = safe_malloc(sizeof(struct dhcp_config));
new->hwaddr[0] = e0; config->clid_len = 0;
new->hwaddr[1] = e1; config->clid = NULL;
new->hwaddr[2] = e2; config->lease_time = 0;
new->hwaddr[3] = e3; config->hostname = safe_string_alloc(name);
new->hwaddr[4] = e4; config->addr = addr;
new->hwaddr[5] = e5; config->next = configs;
new->hostname = name; configs = config;
new->addr = addr; }
new->lease_time = 0;
new->next = configs;
configs = new; 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); fclose(f);

View File

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

View File

@@ -105,6 +105,12 @@ struct bogus_addr {
struct bogus_addr *next; struct bogus_addr *next;
}; };
/* dns doctor param */
struct doctor {
struct in_addr in, out, mask;
struct doctor *next;
};
union bigname { union bigname {
char name[MAXDNAME]; char name[MAXDNAME];
union bigname *next; /* freelist */ union bigname *next; /* freelist */
@@ -304,7 +310,8 @@ unsigned short extract_request(HEADER *header, unsigned int qlen, char *name);
int setup_reply(HEADER *header, unsigned int qlen, int setup_reply(HEADER *header, unsigned int qlen,
struct all_addr *addrp, unsigned short flags, struct all_addr *addrp, unsigned short flags,
unsigned long local_ttl); 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); 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, int answer_request(HEADER *header, char *limit, unsigned int qlen, char *mxname,
char *mxtarget, unsigned int options, time_t now, unsigned long local_ttl, char *mxtarget, unsigned int options, time_t now, unsigned long local_ttl,
@@ -334,13 +341,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, int *port, int *query_port, unsigned long *local_ttl, char **addn_hosts,
struct dhcp_context **dhcp, struct dhcp_config **dhcp_conf, struct dhcp_opt **opts, struct dhcp_context **dhcp, struct dhcp_config **dhcp_conf, struct dhcp_opt **opts,
char **dhcp_file, char **dhcp_sname, struct in_addr *dhcp_next_server, char **dhcp_file, char **dhcp_sname, struct in_addr *dhcp_next_server,
int *maxleases, unsigned int *min_leasetime); int *maxleases, unsigned int *min_leasetime, struct doctor **doctors);
/* forward.c */ /* forward.c */
void forward_init(int first); void forward_init(int first);
struct server *reply_query(int fd, int options, char *packet, time_t now, struct server *reply_query(int fd, int options, char *packet, time_t now,
char *dnamebuff, struct server *last_server, 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, struct server *receive_query(struct listener *listen, char *packet, char *mxname,
char *mxtarget, unsigned int options, time_t now, char *mxtarget, unsigned int options, time_t now,

View File

@@ -314,7 +314,8 @@ static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
/* returns new last_server */ /* returns new last_server */
struct server *reply_query(int fd, int options, char *packet, time_t now, 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 /* packet from peer server, extract data for cache, and send to
original requester */ original requester */
@@ -338,7 +339,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))) check_for_bogus_wildcard(header, (unsigned int)n, dnamebuff, bogus_nxdomain, now)))
{ {
if (header->rcode == NOERROR && ntohs(header->ancount) != 0) 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)) else if (!(options & OPT_NO_NEG))
extract_neg_addrs(header, (unsigned int)n, dnamebuff, now); extract_neg_addrs(header, (unsigned int)n, dnamebuff, now);
} }

View File

@@ -34,9 +34,13 @@ int lease_init(char *filename, char *domain, char *buff,
leases = NULL; leases = NULL;
leases_left = maxleases; 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); 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", 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) &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) for (tmp = names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0)) if (tmp->name && (strcmp(tmp->name, name) == 0))
break; break;
if (!tmp && !addrs) if (!tmp)
return NULL; for (tmp = addrs; tmp; tmp = tmp->next)
if (sockaddr_isequal(&tmp->addr, addr))
for (tmp = addrs; tmp; tmp = tmp->next) break;
if (sockaddr_isequal(&tmp->addr, addr))
break;
if (!tmp) if (!tmp)
return NULL; return NULL;
} }

View File

@@ -21,7 +21,7 @@ struct myoption {
int val; int val;
}; };
#define OPTSTRING "ZDNLERzowefnbvhdqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:" #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[] = { static struct myoption opts[] = {
{"version", 0, 0, 'v'}, {"version", 0, 0, 'v'},
@@ -67,7 +67,9 @@ static struct myoption opts[] = {
{"except-interface", 1, 0, 'I'}, {"except-interface", 1, 0, 'I'},
{"domain-needed", 0, 0, 'D'}, {"domain-needed", 0, 0, 'D'},
{"dhcp-lease-max", 1, 0, 'X' }, {"dhcp-lease-max", 1, 0, 'X' },
{"bind-interfaces", 0, 0, 'z'},
{"read-ethers", 0, 0, 'Z' }, {"read-ethers", 0, 0, 'Z' },
{"alias", 1, 0, 'V' },
{0, 0, 0, 0} {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" "-T, --local-ttl=time Specify time-to-live in seconds for replies from /etc/hosts.\n"
"-u, --user=username Change to this user after startup. (defaults to " CHUSER ").\n" "-u, --user=username Change to this user after startup. (defaults to " CHUSER ").\n"
"-v, --version Display dnsmasq version.\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" "-w, --help Display this message.\n"
"-x, --pid-file=path Specify path of PID file. (defaults to " RUNFILE ").\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" "-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, int *query_port, unsigned long *local_ttl, char **addn_hosts, struct dhcp_context **dhcp,
struct dhcp_config **dhcp_conf, struct dhcp_opt **dhcp_opts, char **dhcp_file, struct dhcp_config **dhcp_conf, struct dhcp_opt **dhcp_opts, char **dhcp_file,
char **dhcp_sname, struct in_addr *dhcp_next_server, int *dhcp_max, char **dhcp_sname, struct in_addr *dhcp_next_server, int *dhcp_max,
unsigned int *min_leasetime) unsigned int *min_leasetime, struct doctor **doctors)
{ {
int option = 0, i; int option = 0, i;
unsigned int flags = 0; unsigned int flags = 0;
@@ -195,6 +198,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
while (strlen(buff) > 0 && while (strlen(buff) > 0 &&
(buff[strlen(buff)-1] == '\n' || (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] == '\t'))
buff[strlen(buff)-1] = 0; buff[strlen(buff)-1] = 0;
if (*buff == 0) if (*buff == 0)
@@ -920,6 +924,44 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
} }
break; 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;
}
} }
} }

View File

@@ -440,7 +440,19 @@ void extract_neg_addrs(HEADER *header, unsigned int qlen, char *name, time_t now
cache_end_insert(); 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; unsigned char *p, *psave, *endrr;
int qtype, qclass, rdlen; 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. */ 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 #ifdef HAVE_IPV6
else if (qtype == T_AAAA) /* IPV6 address record. */ else if (qtype == T_AAAA) /* IPV6 address record. */
cache_insert(name, (struct all_addr *)p, now, 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; return;
if (qtype == T_A) /* A record. */ 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 #ifdef HAVE_IPV6
else if (qtype == T_AAAA) /* IPV6 address record. */ else if (qtype == T_AAAA) /* IPV6 address record. */
cache_insert(name, (struct all_addr *)p, now, cache_insert(name, (struct all_addr *)p, now,

View File

@@ -246,11 +246,12 @@ int dhcp_reply(struct dhcp_context *context,
log_packet("DISCOVER", opt ? &mess->yiaddr : NULL, mess->chaddr, iface_name, NULL); log_packet("DISCOVER", opt ? &mess->yiaddr : NULL, mess->chaddr, iface_name, NULL);
if (lease && if (config && config->addr.s_addr && !lease_find_by_addr(config->addr))
((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))
mess->yiaddr = 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)) && else if ((!opt || !address_available(context, mess->yiaddr)) &&
!address_allocate(context, dhcp_configs, &mess->yiaddr)) !address_allocate(context, dhcp_configs, &mess->yiaddr))
{ {