diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2014-03-18 22:38:30 +0000 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2014-03-18 22:38:30 +0000 |
commit | 19c51cfa493563628e07f09008e56c04555e29bb (patch) | |
tree | 38c78b4690a891668b28fe720edf5f499c92b3d9 | |
parent | d5082158ee55db893aeafb0f8392ae6b5e2d1354 (diff) | |
download | dnsmasq-19c51cfa493563628e07f09008e56c04555e29bb.tar.gz |
Tidy and fix cache->uid handling.
Some CNAMES left the value of ->uid undefined.
Since there are now special values if this, for CNAMES
to interface names, that could cause a crash
if the undefined value hit the special value.
Also ensure that the special value can't arise
when the uid is encoding the source of an F_CONFIG
record, in case there's a CNAME to it.
-rw-r--r-- | src/cache.c | 25 | ||||
-rw-r--r-- | src/dnsmasq.h | 10 | ||||
-rw-r--r-- | src/option.c | 7 |
3 files changed, 27 insertions, 15 deletions
diff --git a/src/cache.c b/src/cache.c index a3f9c3a..8c99e6c 100644 --- a/src/cache.c +++ b/src/cache.c @@ -79,7 +79,7 @@ static unsigned int next_uid(void) uid++; /* uid == 0 used to indicate CNAME to interface name. */ - if (uid == 0) + if (uid == SRC_INTERFACE) uid++; return uid; @@ -265,7 +265,7 @@ char *cache_get_name(struct crec *crecp) char *cache_get_cname_target(struct crec *crecp) { - if (crecp->addr.cname.uid != 0) + if (crecp->addr.cname.uid != SRC_INTERFACE) return cache_get_name(crecp->addr.cname.target.cache); return crecp->addr.cname.target.int_name->name; @@ -783,13 +783,14 @@ static void add_hosts_cname(struct crec *target) crec->name.namep = a->alias; crec->addr.cname.target.cache = target; crec->addr.cname.uid = target->uid; + crec->uid = next_uid(); cache_hash(crec); add_hosts_cname(crec); /* handle chains */ } } static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen, - int index, struct crec **rhash, int hashsz) + unsigned int index, struct crec **rhash, int hashsz) { struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6)); int i, nameexists = 0; @@ -893,7 +894,7 @@ static int gettok(FILE *f, char *token) } } -static int read_hostsfile(char *filename, int index, int cache_size, struct crec **rhash, int hashsz) +static int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz) { FILE *f = fopen(filename, "r"); char *token = daemon->namebuff, *domain_suffix = NULL; @@ -1043,7 +1044,8 @@ void cache_reload(void) cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG; cache->name.namep = a->alias; cache->addr.cname.target.int_name = intr; - cache->addr.cname.uid = 0; + cache->addr.cname.uid = SRC_INTERFACE; + cache->uid = next_uid(); cache_hash(cache); add_hosts_cname(cache); /* handle chains */ } @@ -1079,7 +1081,7 @@ void cache_reload(void) { cache->name.namep = nl->name; cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG; - add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, 0, (struct crec **)daemon->packet, revhashsz); + add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz); } #ifdef HAVE_IPV6 if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) && @@ -1087,7 +1089,7 @@ void cache_reload(void) { cache->name.namep = nl->name; cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG; - add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, 0, (struct crec **)daemon->packet, revhashsz); + add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz); } #endif } @@ -1100,7 +1102,7 @@ void cache_reload(void) } if (!option_bool(OPT_NO_HOSTS)) - total_size = read_hostsfile(HOSTSFILE, 0, total_size, (struct crec **)daemon->packet, revhashsz); + total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz); daemon->addn_hosts = expand_filelist(daemon->addn_hosts); for (ah = daemon->addn_hosts; ah; ah = ah->next) @@ -1164,6 +1166,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd) aliasc->name.namep = a->alias; aliasc->addr.cname.target.cache = target; aliasc->addr.cname.uid = target->uid; + aliasc->uid = next_uid(); cache_hash(aliasc); add_dhcp_cname(aliasc, ttd); } @@ -1377,11 +1380,13 @@ void dump_cache(time_t now) } } -char *record_source(int index) +char *record_source(unsigned int index) { struct hostsfile *ah; - if (index == 0) + if (index == SRC_CONFIG) + return "config"; + else if (index == SRC_HOSTS) return HOSTSFILE; for (ah = daemon->addn_hosts; ah; ah = ah->next) diff --git a/src/dnsmasq.h b/src/dnsmasq.h index e7097bd..4ee3c49 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -427,6 +427,12 @@ struct crec { #define F_SECSTAT (1u<<24) #define F_NO_RR (1u<<25) +/* Values of uid in crecs with F_CONFIG bit set. */ +#define SRC_INTERFACE 0 +#define SRC_CONFIG 1 +#define SRC_HOSTS 2 +#define SRC_AH 3 + /* struct sockaddr is not large enough to hold any address, and specifically not big enough to hold an IPv6 address. @@ -525,7 +531,7 @@ struct hostsfile { struct hostsfile *next; int flags; char *fname; - int index; /* matches to cache entries for logging */ + unsigned int index; /* matches to cache entries for logging */ }; @@ -1005,7 +1011,7 @@ extern struct daemon { /* cache.c */ void cache_init(void); void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg); -char *record_source(int index); +char *record_source(unsigned int index); char *querystr(char *desc, unsigned short type); struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr, time_t now, diff --git a/src/option.c b/src/option.c index e8ef5fa..8484513 100644 --- a/src/option.c +++ b/src/option.c @@ -1664,7 +1664,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma case 'H': /* --addn-hosts */ { struct hostsfile *new = opt_malloc(sizeof(struct hostsfile)); - static int hosts_index = 1; + static unsigned int hosts_index = SRC_AH; new->fname = opt_string_alloc(arg); new->index = hosts_index++; new->flags = 0; @@ -4020,10 +4020,11 @@ static int one_file(char *file, int hard_opt) /* expand any name which is a directory */ struct hostsfile *expand_filelist(struct hostsfile *list) { - int i; + unsigned int i; struct hostsfile *ah; - for (i = 0, ah = list; ah; ah = ah->next) + /* find largest used index */ + for (i = SRC_AH, ah = list; ah; ah = ah->next) { if (i <= ah->index) i = ah->index + 1; |