Compare commits

...
8 Commits
13 changed files with 296 additions and 43 deletions

No files matched your search

+19
View File
@@ -40,6 +40,25 @@ version 2.73
nameservers in the unsigned parts of the DNS tree
which don't respond well to DNSSEC queries.
Add --log-queries=extra option, which makes logs easier
to search automatically.
Add --min-cache-ttl option. I've resisted this for a long
time, on the grounds that disbelieving TTLs is never a
good idea, but I've been persuaded that there are
sometimes reasons to do it. (Step forward, GFW).
To avoid misuse, there's a hard limit on the TTL
floor of one hour. Thansk to RinSatsuki for the patch.
Cope with multiple interfaces with the same link-local
address. (IPv6 addresses are scoped, so this is allowed.)
Thanks to Cory Benfield for help with this.
Add --dhcp-hostsdir. This allows addition of new host
configurations to a running dnsmasq instance much more
cheaply than having dnsmasq re-read all its existing
configuration each time.
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
+19 -1
View File
@@ -81,6 +81,12 @@ the upstream DNS servers.
.B --max-cache-ttl=<time>
Set a maximum TTL value for entries in the cache.
.TP
.B --min-cache-ttl=<time>
Extend short TTL values to the time given when caching them. Note that
artificially extending TTL values is in general a bad idea, do not do it
unless you have a good reason, and understand what you are doing.
Dnsmasq limits the value of this option to one hour, unless recompiled.
.TP
.B --auth-ttl=<time>
Set the TTL value returned in answers from the authoritative server.
.TP
@@ -98,7 +104,10 @@ only, to stop dnsmasq daemonising in production, use
.B -k.
.TP
.B \-q, --log-queries
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1.
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1. If the argument "extra" is supplied, ie
.B --log-queries=extra
then the log has extra information at the start of each line.
This consists of a serial number which ties together the log lines associated with an individual query, and the IP address of the requestor.
.TP
.B \-8, --log-facility=<facility>
Set the facility to which dnsmasq will send syslog entries, this
@@ -968,6 +977,15 @@ is given, then read all the files contained in that directory. The advantage of
using this option is the same as for --dhcp-hostsfile: the
dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
it is possible to encode the information in a
.TP
.B --dhcp-hostsdir=<path>
This is exactly equivalent to dhcp-hostfile, except for the following. The path MUST be a
directory, and not an individual file. Changed or new files within
the directory are read automatically, without the need to send SIGHUP.
If a file is deleted for changed after it has been read by dnsmasq, then the
host record it contained will remain until dnsmasq recieves a SIGHUP, or
is restarted; ie host records are only added dynamically.
.TP
.B --dhcp-boot
flag as DHCP options, using the options names bootfile-name,
server-ip-address and tftp-server. This allows these to be included
+4 -1
View File
@@ -413,7 +413,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
peer_addr->in.sin_port = 0;
#ifdef HAVE_IPV6
else
peer_addr->in6.sin6_port = 0;
{
peer_addr->in6.sin6_port = 0;
peer_addr->in6.sin6_scope_id = 0;
}
#endif
for (peers = daemon->auth_peers; peers; peers = peers->next)
+13 -2
View File
@@ -461,9 +461,11 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
{
log_query(flags | F_UPSTREAM, name, addr, NULL);
/* Don;t mess with TTL for DNSSEC records. */
/* Don't mess with TTL for DNSSEC records. */
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
ttl = daemon->max_cache_ttl;
if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
ttl = daemon->min_cache_ttl;
}
/* if previous insertion failed give up now. */
@@ -1638,7 +1640,16 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
if (strlen(name) == 0)
name = ".";
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
if (option_bool(OPT_EXTRALOG))
{
int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
if (flags & F_NOEXTRA)
my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest);
else
my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest);
}
else
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
}
+2
View File
@@ -17,6 +17,7 @@
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
@@ -26,6 +27,7 @@
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
#define CACHESIZ 150 /* default cache size */
#define TTL_FLOOR_LIMIT 3600 /* don't allow --min-cache-ttl to raise TTL above this under any circumstances */
#define MAXLEASES 1000 /* maximum number of DHCP leases */
#define PING_WAIT 3 /* wait for ping address-in-use test */
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
+25 -8
View File
@@ -93,6 +93,8 @@ int main (int argc, char **argv)
daemon->packet = safe_malloc(daemon->packet_buff_sz);
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
if (option_bool(OPT_EXTRALOG))
daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
@@ -140,6 +142,9 @@ int main (int argc, char **argv)
set_option_bool(OPT_NOWILD);
reset_option_bool(OPT_CLEVERBIND);
}
if (daemon->inotify_hosts)
die(_("dhcp-hostsdir not supported on this platform"), NULL, EC_BADCONF);
#endif
if (option_bool(OPT_DNSSEC_VALID))
@@ -314,13 +319,16 @@ int main (int argc, char **argv)
#ifdef HAVE_DNSSEC
blockdata_init();
#endif
}
#ifdef HAVE_LINUX_NETWORK
if (!option_bool(OPT_NO_POLL))
inotify_dnsmasq_init();
if ((!option_bool(OPT_NO_POLL) && daemon->port != 0) ||
daemon->dhcp || daemon->doing_dhcp6)
inotify_dnsmasq_init();
else
daemon->inotifyfd = -1;
#endif
}
if (option_bool(OPT_DBUS))
#ifdef HAVE_DBUS
{
@@ -743,7 +751,7 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_TFTP
if (option_bool(OPT_TFTP))
if (option_bool(OPT_TFTP))
{
#ifdef FD_SETSIZE
if (FD_SETSIZE < (unsigned)max_fd)
@@ -868,7 +876,7 @@ int main (int argc, char **argv)
#if defined(HAVE_LINUX_NETWORK)
FD_SET(daemon->netlinkfd, &rset);
bump_maxfd(daemon->netlinkfd, &maxfd);
if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
if (daemon->inotifyfd != -1)
{
FD_SET(daemon->inotifyfd, &rset);
bump_maxfd(daemon->inotifyfd, &maxfd);
@@ -941,8 +949,11 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_LINUX_NETWORK
if (daemon->port != 0 && !option_bool(OPT_NO_POLL) && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check())
poll_resolv(1, 1, now);
if (daemon->inotifyfd != -1 && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check(now))
{
if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
poll_resolv(1, 1, now);
}
#else
/* Check for changes to resolv files once per second max. */
/* Don't go silent for long periods if the clock goes backwards. */
@@ -1383,6 +1394,9 @@ void clear_cache_and_reload(time_t now)
if (option_bool(OPT_ETHERS))
dhcp_read_ethers();
reread_dhcp();
#ifdef HAVE_LINUX_NETWORK
set_dhcp_inotify();
#endif
dhcp_update_configs(daemon->dhcp_conf);
lease_update_from_configs();
lease_update_file(now);
@@ -1587,6 +1601,9 @@ static void check_dns_listeners(fd_set *set, time_t now)
}
}
close(confd);
/* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
daemon->log_id += TCP_MAX_QUERIES;
}
#endif
else
+19 -7
View File
@@ -238,7 +238,8 @@ struct event_desc {
#define OPT_DNSSEC_NO_SIGN 48
#define OPT_LOCAL_SERVICE 49
#define OPT_LOOP_DETECT 50
#define OPT_LAST 51
#define OPT_EXTRALOG 51
#define OPT_LAST 52
/* extra flags for my_syslog, we use a couple of facilities since they are known
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
@@ -442,6 +443,7 @@ struct crec {
#define F_NO_RR (1u<<25)
#define F_IPSET (1u<<26)
#define F_NSIGMATCH (1u<<27)
#define F_NOEXTRA (1u<<28)
/* Values of uid in crecs with F_CONFIG bit set. */
#define SRC_INTERFACE 0
@@ -548,13 +550,17 @@ struct resolvc {
#endif
};
/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */
/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile and dhcp-hostsdir*/
#define AH_DIR 1
#define AH_INACTIVE 2
#define AH_WD_DONE 4
struct hostsfile {
struct hostsfile *next;
int flags;
char *fname;
#ifdef HAVE_LINUX_NETWORK
int wd; /* inotify watch descriptor */
#endif
unsigned int index; /* matches to cache entries for logging */
};
@@ -599,7 +605,7 @@ struct frec {
#endif
unsigned int iface;
unsigned short orig_id, new_id;
int fd, forwardall, flags;
int log_id, fd, forwardall, flags;
time_t time;
unsigned char *hash[HASH_SIZE];
#ifdef HAVE_DNSSEC
@@ -941,7 +947,7 @@ extern struct daemon {
int max_logs; /* queue limit */
int cachesize, ftabsize;
int port, query_port, min_port;
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl;
struct hostsfile *addn_hosts;
struct dhcp_context *dhcp, *dhcp6;
struct ra_interface *ra_interfaces;
@@ -959,7 +965,7 @@ extern struct daemon {
int doing_ra, doing_dhcp6;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *inotify_hosts;
int dhcp_max, tftp_max;
int dhcp_server_port, dhcp_client_port;
int start_tftp_port, end_tftp_port;
@@ -1002,6 +1008,8 @@ extern struct daemon {
struct randfd randomsocks[RANDOM_SOCKS];
int v6pktinfo;
struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */
int log_id, log_display_id; /* ids of transactions for logging */
union mysockaddr *log_source_addr;
/* DHCP state */
int dhcpfd, helperfd, pxefd;
@@ -1033,6 +1041,7 @@ extern struct daemon {
/* utility string buffer, hold max sized IP address as string */
char *addrbuff;
char *addrbuff2; /* only allocated when OPT_EXTRALOG */
} *daemon;
@@ -1192,7 +1201,7 @@ void reset_option_bool(unsigned int opt);
struct hostsfile *expand_filelist(struct hostsfile *list);
char *parse_server(char *arg, union mysockaddr *addr,
union mysockaddr *source_addr, char *interface, int *flags);
int option_read_hostsfile(char *file);
/* forward.c */
void reply_query(int fd, int family, time_t now);
void receive_query(struct listener *listen, time_t now);
@@ -1481,5 +1490,8 @@ int detect_loop(char *query, int type);
/* inotify.c */
#ifdef HAVE_LINUX_NETWORK
void inotify_dnsmasq_init();
int inotify_check(void);
int inotify_check(time_t now);
# ifdef HAVE_DHCP
void set_dhcp_inotify(void);
# endif
#endif
+15 -8
View File
@@ -1038,7 +1038,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
else
{
a.addr.keytag = keytag;
log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u");
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u");
recp1->addr.key.keylen = rdlen - 4;
recp1->addr.key.keydata = key;
@@ -1092,7 +1092,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
return STAT_SECURE;
}
log_query(F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
return STAT_BOGUS;
}
@@ -1136,7 +1136,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
if (val == STAT_BOGUS)
{
log_query(F_UPSTREAM, name, NULL, "BOGUS DS");
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS");
return STAT_BOGUS;
}
@@ -1201,7 +1201,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
cache_end_insert();
log_query(F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS");
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS");
}
return nons ? STAT_NO_NS : STAT_NO_DS;
@@ -1818,11 +1818,14 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
struct blockdata *key;
struct crec *crecp;
char *wildname;
int have_wildcard = 0;
rc = validate_rrset(now, header, plen, class1, type1, name, keyname, &wildname, NULL, 0, 0, 0);
if (rc == STAT_SECURE_WILDCARD)
{
have_wildcard = 1;
/* An attacker replay a wildcard answer with a different
answer and overlay a genuine RR. To prove this
hasn't happened, the answer must prove that
@@ -1885,7 +1888,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
else
{
a.addr.keytag = keytag;
log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
crecp->addr.ds.digest = digest;
crecp->addr.ds.keydata = key;
crecp->addr.ds.algo = algo;
@@ -1913,7 +1916,11 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
p2 += 13; /* labels, orig_ttl, expiration, inception */
GETSHORT(keytag, p2);
if ((key = blockdata_alloc((char*)psave, rdlen2)))
/* We don't cache sigs for wildcard answers, because to reproduce the
answer from the cache will require one or more NSEC/NSEC3 records
which we don't cache. The lack of the RRSIG ensures that a query for
this RRset asking for a secure answer will always be forwarded. */
if (!have_wildcard && (key = blockdata_alloc((char*)psave, rdlen2)))
{
if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
blockdata_free(key);
@@ -2058,10 +2065,10 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i
char *types = querystr("dnssec-query", type);
if (addr->sa.sa_family == AF_INET)
log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
#ifdef HAVE_IPV6
else
log_query(F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types);
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types);
#endif
header->qdcount = htons(1);
+27 -5
View File
@@ -279,10 +279,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
plen = forward->stash_len;
if (forward->sentto->addr.sa.sa_family == AF_INET)
log_query(F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
#ifdef HAVE_IPV6
else
log_query(F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
#endif
if (forward->sentto->sfd)
@@ -389,6 +389,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
struct server *firstsentto = start;
int forwarded = 0;
/* If a query is retried, use the log_id for the retry when logging the answer. */
forward->log_id = daemon->log_id;
if (option_bool(OPT_ADD_MAC))
plen = add_mac(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source);
@@ -725,11 +728,16 @@ void reply_query(int fd, int family, time_t now)
if (!(forward = lookup_frec(ntohs(header->id), hash)))
return;
/* log_query gets called indirectly all over the place, so
pass these in global variables - sorry. */
daemon->log_display_id = forward->log_id;
daemon->log_source_addr = &forward->source;
if (daemon->ignore_addr && RCODE(header) == NOERROR &&
check_for_ignored_address(header, n, daemon->ignore_addr))
return;
if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
if (RCODE(header) == REFUSED &&
!option_bool(OPT_ORDER) &&
forward->forwardall == 0)
/* for broken servers, attempt to send to another one. */
@@ -1258,6 +1266,11 @@ void receive_query(struct listener *listen, time_t now)
dst_addr_4.s_addr = 0;
}
}
/* log_query gets called indirectly all over the place, so
pass these in global variables - sorry. */
daemon->log_display_id = ++daemon->log_id;
daemon->log_source_addr = &source_addr;
if (extract_request(header, (size_t)n, daemon->namebuff, &type))
{
@@ -1675,7 +1688,8 @@ unsigned char *tcp_request(int confd, time_t now,
struct in_addr dst_addr_4;
union mysockaddr peer_addr;
socklen_t peer_len = sizeof(union mysockaddr);
int query_count = 0;
if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
return packet;
@@ -1712,7 +1726,8 @@ unsigned char *tcp_request(int confd, time_t now,
while (1)
{
if (!packet ||
if (query_count == TCP_MAX_QUERIES ||
!packet ||
!read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
!(size = c1 << 8 | c2) ||
!read_write(confd, payload, size, 1))
@@ -1721,6 +1736,13 @@ unsigned char *tcp_request(int confd, time_t now,
if (size < (int)sizeof(struct dns_header))
continue;
query_count++;
/* log_query gets called indirectly all over the place, so
pass these in global variables - sorry. */
daemon->log_display_id = ++daemon->log_id;
daemon->log_source_addr = &peer_addr;
check_subnet = 0;
/* save state of "cd" flag in query */
+113 -6
View File
@@ -19,6 +19,11 @@
#include <sys/inotify.h>
#ifdef HAVE_DHCP
static void check_for_dhcp_inotify(struct inotify_event *in, time_t now);
#endif
/* the strategy is to set a inotify on the directories containing
resolv files, for any files in the directory which are close-write
or moved into the directory.
@@ -40,8 +45,6 @@ void inotify_dnsmasq_init()
struct resolvc *res;
inotify_buffer = safe_malloc(INOTIFY_SZ);
daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
if (daemon->inotifyfd == -1)
@@ -66,6 +69,7 @@ void inotify_dnsmasq_init()
{
*d = 0; /* make path just directory */
res->wd = inotify_add_watch(daemon->inotifyfd, path, IN_CLOSE_WRITE | IN_MOVED_TO);
res->file = d+1; /* pointer to filename */
*d = '/';
@@ -78,7 +82,7 @@ void inotify_dnsmasq_init()
}
}
int inotify_check(void)
int inotify_check(time_t now)
{
int hit = 0;
@@ -101,13 +105,116 @@ int inotify_check(void)
for (res = daemon->resolv_files; res; res = res->next)
if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0)
hit = 1;
#ifdef HAVE_DHCP
if (daemon->dhcp || daemon->doing_dhcp6)
check_for_dhcp_inotify(in, now);
#endif
}
}
return hit;
}
#endif
#ifdef HAVE_DHCP
/* initialisation for dhcp-hostdir. Set inotify watch for each directory, and read pre-existing files */
void set_dhcp_inotify(void)
{
struct hostsfile *ah;
for (ah = daemon->inotify_hosts; ah; ah = ah->next)
{
DIR *dir_stream = NULL;
struct dirent *ent;
struct stat buf;
if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode)))
{
my_syslog(LOG_ERR, _("bad directory in dhcp-hostsdir %s"), ah->fname);
continue;
}
if (!(ah->flags & AH_WD_DONE))
{
ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
ah->flags |= AH_WD_DONE;
}
/* Read contents of dir _after_ calling add_watch, in the ho[e of avoiding
a race which misses files being added as we start */
if (ah->wd == -1 || !(dir_stream = opendir(ah->fname)))
{
my_syslog(LOG_ERR, _("failed to create inotify for %s"), ah->fname);
continue;
}
while ((ent = readdir(dir_stream)))
{
size_t lendir = strlen(ah->fname);
size_t lenfile = strlen(ent->d_name);
char *path;
/* ignore emacs backups and dotfiles */
if (lenfile == 0 ||
ent->d_name[lenfile - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
ent->d_name[0] == '.')
continue;
if ((path = whine_malloc(lendir + lenfile + 2)))
{
strcpy(path, ah->fname);
strcat(path, "/");
strcat(path, ent->d_name);
/* ignore non-regular files */
if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))
option_read_hostsfile(path);
free(path);
}
}
}
}
static void check_for_dhcp_inotify(struct inotify_event *in, time_t now)
{
struct hostsfile *ah;
/* ignore emacs backups and dotfiles */
if (in->len == 0 ||
in->name[in->len - 1] == '~' ||
(in->name[0] == '#' && in->name[in->len - 1] == '#') ||
in->name[0] == '.')
return;
for (ah = daemon->inotify_hosts; ah; ah = ah->next)
if (ah->wd == in->wd)
{
size_t lendir = strlen(ah->fname);
char *path;
if ((path = whine_malloc(lendir + in->len + 2)))
{
strcpy(path, ah->fname);
strcat(path, "/");
strcat(path, in->name);
if (option_read_hostsfile(path))
{
/* Propogate the consequences of loading a new dhcp-host */
dhcp_update_configs(daemon->dhcp_conf);
lease_update_from_configs();
lease_update_file(now);
lease_update_dns(1);
}
free(path);
}
return;
}
}
#endif /* DHCP */
#endif /* LINUX_NETWORK */
+38 -4
View File
@@ -148,6 +148,8 @@ struct myoption {
#define LOPT_DNSSEC_TIME 336
#define LOPT_LOOP_DETECT 337
#define LOPT_IGNORE_ADDR 338
#define LOPT_MINCTTL 339
#define LOPT_DHCP_INOTIFY 340
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -160,7 +162,7 @@ static const struct myoption opts[] =
{ "no-poll", 0, 0, 'n' },
{ "help", 0, 0, 'w' },
{ "no-daemon", 0, 0, 'd' },
{ "log-queries", 0, 0, 'q' },
{ "log-queries", 2, 0, 'q' },
{ "user", 2, 0, 'u' },
{ "group", 2, 0, 'g' },
{ "resolv-file", 2, 0, 'r' },
@@ -246,6 +248,7 @@ static const struct myoption opts[] =
{ "interface-name", 1, 0, LOPT_INTNAME },
{ "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
{ "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
{ "dhcp-hostsdir", 1, 0, LOPT_DHCP_INOTIFY },
{ "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
{ "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
{ "stop-dns-rebind", 0, 0, LOPT_REBIND },
@@ -255,6 +258,7 @@ static const struct myoption opts[] =
{ "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
{ "neg-ttl", 1, 0, LOPT_NEGTTL },
{ "max-ttl", 1, 0, LOPT_MAXTTL },
{ "min-cache-ttl", 1, 0, LOPT_MINCTTL },
{ "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
{ "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
{ "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
@@ -333,6 +337,7 @@ static struct {
{ 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
{ LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
{ LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
{ LOPT_DHCP_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from a directory."), NULL },
{ LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
{ 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
{ 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
@@ -357,7 +362,7 @@ static struct {
{ LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
{ 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
{ 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
{ 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
{ 'q', ARG_DUP, NULL, gettext_noop("Log DNS queries."), NULL },
{ 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
{ 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
{ 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
@@ -370,6 +375,8 @@ static struct {
{ 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
{ LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
{ LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
{ LOPT_MAXCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live ceiling for cache."), NULL },
{ LOPT_MINCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live floor for cache."), NULL },
{ 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
{ 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
{ 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
@@ -1705,8 +1712,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break;
#endif /* HAVE_DHCP */
case LOPT_DHCP_HOST: /* --dhcp-hostfile */
case LOPT_DHCP_HOST: /* --dhcp-hostsfile */
case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
case LOPT_DHCP_INOTIFY: /* dhcp-hostsdir */
case 'H': /* --addn-hosts */
{
struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
@@ -1729,6 +1737,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->next = daemon->dhcp_opts_file;
daemon->dhcp_opts_file = new;
}
else if (option == LOPT_DHCP_INOTIFY)
{
new->next = daemon->inotify_hosts;
daemon->inotify_hosts = new;
}
break;
}
@@ -2421,6 +2435,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
ret_err(gen_err);
break;
case 'q': /* --log-queries */
set_option_bool(OPT_LOG);
if (arg && strcmp(arg, "extra") == 0)
set_option_bool(OPT_EXTRALOG);
break;
case LOPT_MAX_LOGS: /* --log-async */
daemon->max_logs = LOG_MAX; /* default */
if (arg && !atoi_check(arg, &daemon->max_logs))
@@ -2450,6 +2470,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case 'T': /* --local-ttl */
case LOPT_NEGTTL: /* --neg-ttl */
case LOPT_MAXTTL: /* --max-ttl */
case LOPT_MINCTTL: /* --min-cache-ttl */
case LOPT_MAXCTTL: /* --max-cache-ttl */
case LOPT_AUTHTTL: /* --auth-ttl */
{
@@ -2460,6 +2481,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
daemon->neg_ttl = (unsigned long)ttl;
else if (option == LOPT_MAXTTL)
daemon->max_ttl = (unsigned long)ttl;
else if (option == LOPT_MINCTTL)
{
if (ttl > TTL_FLOOR_LIMIT)
ttl = TTL_FLOOR_LIMIT;
daemon->min_cache_ttl = (unsigned long)ttl;
}
else if (option == LOPT_MAXCTTL)
daemon->max_cache_ttl = (unsigned long)ttl;
else if (option == LOPT_AUTHTTL)
@@ -4024,6 +4051,13 @@ static void read_file(char *file, FILE *f, int hard_opt)
fclose(f);
}
#ifdef HAVE_DHCP
int option_read_hostsfile(char *file)
{
return one_file(file, LOPT_BANK);
}
#endif
static int one_file(char *file, int hard_opt)
{
FILE *f;
@@ -4121,7 +4155,7 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
/* don't read this as a file */
ah->flags |= AH_INACTIVE;
if (!(dir_stream = opendir(ah->fname)))
my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
ah->fname, strerror(errno));
+1 -1
View File
@@ -1643,7 +1643,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
{
if (crecp->flags & F_NXDOMAIN)
nxdomain = 1;
log_query(F_UPSTREAM, name, NULL, "secure no DS");
log_query(F_UPSTREAM, name, NULL, "no DS");
}
else if ((keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
{
+1
View File
@@ -274,6 +274,7 @@ int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
#ifdef HAVE_IPV6
if (s1->sa.sa_family == AF_INET6 &&
s1->in6.sin6_port == s2->in6.sin6_port &&
s1->in6.sin6_scope_id == s2->in6.sin6_scope_id &&
IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
return 1;
#endif