mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f4dc5c6ca | ||
|
|
2ae195f5a7 | ||
|
|
393415597c | ||
|
|
ae4624bf46 | ||
|
|
5e321739db | ||
|
|
9f79ee4ae3 | ||
|
|
28de38768e | ||
|
|
25cf5e373e |
No files matched your search
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user