You need to sign in or sign up before continuing.
Commit 19c51cfa authored by Simon Kelley's avatar Simon Kelley

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.
parent d5082158
...@@ -79,7 +79,7 @@ static unsigned int next_uid(void) ...@@ -79,7 +79,7 @@ static unsigned int next_uid(void)
uid++; uid++;
/* uid == 0 used to indicate CNAME to interface name. */ /* uid == 0 used to indicate CNAME to interface name. */
if (uid == 0) if (uid == SRC_INTERFACE)
uid++; uid++;
return uid; return uid;
...@@ -265,7 +265,7 @@ char *cache_get_name(struct crec *crecp) ...@@ -265,7 +265,7 @@ char *cache_get_name(struct crec *crecp)
char *cache_get_cname_target(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 cache_get_name(crecp->addr.cname.target.cache);
return crecp->addr.cname.target.int_name->name; return crecp->addr.cname.target.int_name->name;
...@@ -783,13 +783,14 @@ static void add_hosts_cname(struct crec *target) ...@@ -783,13 +783,14 @@ static void add_hosts_cname(struct crec *target)
crec->name.namep = a->alias; crec->name.namep = a->alias;
crec->addr.cname.target.cache = target; crec->addr.cname.target.cache = target;
crec->addr.cname.uid = target->uid; crec->addr.cname.uid = target->uid;
crec->uid = next_uid();
cache_hash(crec); cache_hash(crec);
add_hosts_cname(crec); /* handle chains */ add_hosts_cname(crec); /* handle chains */
} }
} }
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen, 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)); struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
int i, nameexists = 0; int i, nameexists = 0;
...@@ -893,7 +894,7 @@ static int gettok(FILE *f, char *token) ...@@ -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"); FILE *f = fopen(filename, "r");
char *token = daemon->namebuff, *domain_suffix = NULL; char *token = daemon->namebuff, *domain_suffix = NULL;
...@@ -1043,7 +1044,8 @@ void cache_reload(void) ...@@ -1043,7 +1044,8 @@ void cache_reload(void)
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG; cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
cache->name.namep = a->alias; cache->name.namep = a->alias;
cache->addr.cname.target.int_name = intr; 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); cache_hash(cache);
add_hosts_cname(cache); /* handle chains */ add_hosts_cname(cache); /* handle chains */
} }
...@@ -1079,7 +1081,7 @@ void cache_reload(void) ...@@ -1079,7 +1081,7 @@ void cache_reload(void)
{ {
cache->name.namep = nl->name; cache->name.namep = nl->name;
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG; 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 #ifdef HAVE_IPV6
if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) && if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
...@@ -1087,7 +1089,7 @@ void cache_reload(void) ...@@ -1087,7 +1089,7 @@ void cache_reload(void)
{ {
cache->name.namep = nl->name; cache->name.namep = nl->name;
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG; 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 #endif
} }
...@@ -1100,7 +1102,7 @@ void cache_reload(void) ...@@ -1100,7 +1102,7 @@ void cache_reload(void)
} }
if (!option_bool(OPT_NO_HOSTS)) 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); daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
for (ah = daemon->addn_hosts; ah; ah = ah->next) for (ah = daemon->addn_hosts; ah; ah = ah->next)
...@@ -1164,6 +1166,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd) ...@@ -1164,6 +1166,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
aliasc->name.namep = a->alias; aliasc->name.namep = a->alias;
aliasc->addr.cname.target.cache = target; aliasc->addr.cname.target.cache = target;
aliasc->addr.cname.uid = target->uid; aliasc->addr.cname.uid = target->uid;
aliasc->uid = next_uid();
cache_hash(aliasc); cache_hash(aliasc);
add_dhcp_cname(aliasc, ttd); add_dhcp_cname(aliasc, ttd);
} }
...@@ -1377,11 +1380,13 @@ void dump_cache(time_t now) ...@@ -1377,11 +1380,13 @@ void dump_cache(time_t now)
} }
} }
char *record_source(int index) char *record_source(unsigned int index)
{ {
struct hostsfile *ah; struct hostsfile *ah;
if (index == 0) if (index == SRC_CONFIG)
return "config";
else if (index == SRC_HOSTS)
return HOSTSFILE; return HOSTSFILE;
for (ah = daemon->addn_hosts; ah; ah = ah->next) for (ah = daemon->addn_hosts; ah; ah = ah->next)
......
...@@ -427,6 +427,12 @@ struct crec { ...@@ -427,6 +427,12 @@ struct crec {
#define F_SECSTAT (1u<<24) #define F_SECSTAT (1u<<24)
#define F_NO_RR (1u<<25) #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, /* struct sockaddr is not large enough to hold any address,
and specifically not big enough to hold an IPv6 address. and specifically not big enough to hold an IPv6 address.
...@@ -525,7 +531,7 @@ struct hostsfile { ...@@ -525,7 +531,7 @@ struct hostsfile {
struct hostsfile *next; struct hostsfile *next;
int flags; int flags;
char *fname; 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 { ...@@ -1005,7 +1011,7 @@ extern struct daemon {
/* cache.c */ /* cache.c */
void cache_init(void); void cache_init(void);
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg); 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); char *querystr(char *desc, unsigned short type);
struct crec *cache_find_by_addr(struct crec *crecp, struct crec *cache_find_by_addr(struct crec *crecp,
struct all_addr *addr, time_t now, struct all_addr *addr, time_t now,
......
...@@ -1664,7 +1664,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -1664,7 +1664,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case 'H': /* --addn-hosts */ case 'H': /* --addn-hosts */
{ {
struct hostsfile *new = opt_malloc(sizeof(struct hostsfile)); 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->fname = opt_string_alloc(arg);
new->index = hosts_index++; new->index = hosts_index++;
new->flags = 0; new->flags = 0;
...@@ -4020,10 +4020,11 @@ static int one_file(char *file, int hard_opt) ...@@ -4020,10 +4020,11 @@ static int one_file(char *file, int hard_opt)
/* expand any name which is a directory */ /* expand any name which is a directory */
struct hostsfile *expand_filelist(struct hostsfile *list) struct hostsfile *expand_filelist(struct hostsfile *list)
{ {
int i; unsigned int i;
struct hostsfile *ah; 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) if (i <= ah->index)
i = ah->index + 1; i = ah->index + 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment