101
113
servparm_array servers=NULL;
103
void lex_set_io(FILE *in, FILE *out); /* defined in conf.l */
104
int yyparse (void); /* from yacc/bison output */
115
static void free_zones(zone_array za);
116
static void free_server_data(servparm_array sa);
105
117
static int report_server_stat(int f,int i);
109
* Read a configuration file and save the result. This uses the parser generated by yacc/bison
110
* from conf.y, which in turn uses the lexer generated lex/flex from conf.l
121
* Read a configuration file and save the result.
122
* Return 1 on success, 0 on failure.
123
* In case of failure, **errstr will refer to a newly allocated string containing an error message.
124
* If we are multi-threaded, call with locks applied.
112
void read_config_file(char *nm)
126
int read_config_file(const char *nm, globparm_t *global, servparm_array *servers, char **errstr)
117
nm=CONFDIR"/pdnsd.conf";
119
if (stat(nm,&sb)!=0) {
120
fprintf(stderr,"Error: Could not stat conf file %s: %s\n",nm,strerror(errno));
123
if (sb.st_uid!=getuid()) {
124
fprintf(stderr,"Error: You must own the config file.\n");
127
if ((sb.st_mode&(S_IWGRP|S_IWOTH))) {
128
fprintf(stderr,"Error: Bad config file permissions: the file must be only writeable by the user.\n");
131
135
if (!(in=fopen(nm,"r"))) {
132
fprintf(stderr,"Error: Could not open conf file %s: %s\n",nm,strerror(errno));
136
if(asprintf(errstr,"Error: Could not open config file %s: %s",nm,strerror(errno))<0)
141
/* Note by Paul Rombouts: I am using fstat() instead of stat() here to
142
prevent a possible exploitable race condition */
143
if (fd==-1 || fstat(fd,&sb)!=0) {
144
if(asprintf(errstr, "Error: Could not stat config file %s: %s",nm,strerror(errno))<0)
147
else if (sb.st_uid!=init_uid) {
148
/* Note by Paul Rombouts:
149
Perhaps we should use getpwuid_r() instead of getpwuid(), which is not necessarily thread safe.
150
As long as getpwuid() is only used by only one thread, it should be OK,
151
but it is something to keep in mind.
154
char owner[24],user[24];
155
if((pws=getpwuid(sb.st_uid)))
156
strncp(owner,pws->pw_name,sizeof(owner));
158
sprintf(owner,"%i",sb.st_uid);
159
if((pws=getpwuid(init_uid)))
160
strncp(user,pws->pw_name,sizeof(user));
162
sprintf(user,"%i",init_uid);
164
"Error: Config file %s is owned by '%s', but pdnsd was started as user '%s'.",
168
else if ((sb.st_mode&(S_IWGRP|S_IWOTH))) {
170
"Error: Bad config file permissions: file %s must be only writeable by the user.",nm)<0)
174
retval=confparse(in,global,servers,errstr);
176
if(fclose(in) && retval) {
177
if(asprintf(errstr,"Error: Could not close config file %s: %s",nm,strerror(errno))<0)
185
* Re-Read the configuration file.
186
* Return 1 on success, 0 on failure.
187
* In case of failure, the old configuration will be unchanged (although the cache may not) and
188
* **errstr will refer to a newly allocated string containing an error message.
190
int reload_config_file(const char *nm, char **errstr)
192
globparm_t global_new;
193
servparm_array servers_new;
196
global_new.cache_dir=NULL;
197
global_new.pidfile=NULL;
198
global_new.scheme_file=NULL;
199
global_new.deleg_only_zones=NULL;
200
global_new.onquery=0;
202
if(read_config_file(nm,&global_new,&servers_new,errstr)) {
203
if(global_new.cache_dir && strcmp(global_new.cache_dir,global.cache_dir)) {
204
*errstr=strdup("Cannot reload config file: the specified cache_dir directory has changed.\n"
205
"Try restarting pdnsd instead.");
208
if(global_new.pidfile && (!global.pidfile || strcmp(global_new.pidfile,global.pidfile))) {
209
*errstr=strdup("Cannot reload config file: the specified pid_file has changed.\n"
210
"Try restarting pdnsd instead.");
213
if(global_new.scheme_file && strcmp(global_new.scheme_file,global.scheme_file)) {
214
*errstr=strdup("Cannot reload config file: the specified scheme_file has changed.\n"
215
"Try restarting pdnsd instead.");
218
if(global_new.port!=global.port) {
219
*errstr=strdup("Cannot reload config file: the specified server_port has changed.\n"
220
"Try restarting pdnsd instead.");
223
if(!ADDR_EQUIV(&global_new.a,&global.a)) {
224
*errstr=strdup("Cannot reload config file: the specified interface address (server_ip) has changed.\n"
225
"Try restarting pdnsd instead.");
229
if(!IN6_ARE_ADDR_EQUAL(&global_new.ipv4_6_prefix,&global.ipv4_6_prefix)) {
230
*errstr=strdup("Cannot reload config file: the specified ipv4_6_prefix has changed.\n"
231
"Try restarting pdnsd instead.");
235
if(strcmp(global_new.run_as,global.run_as)) {
236
*errstr=strdup("Cannot reload config file: the specified run_as id has changed.\n"
237
"Try restarting pdnsd instead.");
240
if(global_new.daemon!=global.daemon) {
241
*errstr=strdup("Cannot reload config file: the daemon option has changed.\n"
242
"Try restarting pdnsd instead.");
245
if(global_new.debug!=global.debug) {
246
*errstr=strdup("Cannot reload config file: the debug option has changed.\n"
247
"Try restarting pdnsd instead.");
250
if(global_new.stat_pipe!=global.stat_pipe) {
251
*errstr=strdup("Cannot reload config file: the status_ctl option has changed.\n"
252
"Try restarting pdnsd instead.");
255
if(global_new.notcp!=global.notcp) {
256
*errstr=strdup("Cannot reload config file: the tcp_server option has changed.\n"
257
"Try restarting pdnsd instead.");
260
if(global_new.strict_suid!=global.strict_suid) {
261
*errstr=strdup("Cannot reload config file: the strict_setuid option has changed.\n"
262
"Try restarting pdnsd instead.");
265
if(global_new.ctl_perms!=global.ctl_perms) {
266
*errstr=strdup("Cannot reload config file: the specified ctl_perms has changed.\n"
267
"Try restarting pdnsd instead.");
275
int i,n=DA_NEL(servers_new);
277
if (DA_INDEX(servers_new,i).uptest==C_PING) {
278
if(asprintf(errstr,"Cannot reload config file: the ping socket is not initialized"
279
" and the new config contains uptest=ping in server section %i.\n"
280
"Try restarting pdnsd instead.",i)<0)
287
/* we need exclusive access to the server data to make the changes */
288
/* Wait at most 60 seconds to obtain a lock. */
289
if(!exclusive_lock_server_data(60)) {
290
*errstr=strdup("Cannot reload config file: Timed out while waiting for access to config data.");
293
free(global_new.cache_dir); global_new.cache_dir=global.cache_dir;
294
free(global_new.pidfile); global_new.pidfile=global.pidfile;
295
free(global_new.scheme_file); global_new.scheme_file=global.scheme_file;
296
free_zones(global.deleg_only_zones);
299
free_server_data(servers);
301
/* schedule a retest to check which servers are up,
302
and free the lock. */
303
exclusive_unlock_server_data(1);
309
free(global_new.cache_dir);
310
free(global_new.pidfile);
311
free(global_new.scheme_file);
312
free_zones(global_new.deleg_only_zones);
313
free_server_data(servers_new);
317
void free_zone(void *ptr)
319
free(*((unsigned char **)ptr));
322
static void free_zones(zone_array za)
326
free(DA_INDEX(za,i));
331
void free_slist_domain(void *ptr)
333
free(((slist_t *)ptr)->domain);
336
void free_slist_array(slist_array sla)
340
free(DA_INDEX(sla,j).domain);
345
void free_servparm(servparm_t *serv)
347
free(serv->uptest_cmd);
349
da_free(serv->atup_a);
350
free_slist_array(serv->alist);
353
static void free_server_data(servparm_array sa)
357
free_servparm(&DA_INDEX(sa,i));
141
361
/* Report the current configuration to the file descriptor f (for the status fifo, see status.c) */
173
393
fsprintf_or_return(f,"\tGlobal timeout setting: %li\n",(long)global.timeout);
174
394
fsprintf_or_return(f,"\tParallel queries increment: %i\n",global.par_queries);
175
395
fsprintf_or_return(f,"\tRandomize records in answer: %s\n",global.rnd_recs?"on":"off");
176
fsprintf_or_return(f,"\tQuery method: %s\n",const_name(query_method));
396
fsprintf_or_return(f,"\tQuery method: %s\n",const_name(global.query_method));
177
397
fsprintf_or_return(f,"\tQuery port start: %i\n",global.query_port_start);
178
398
fsprintf_or_return(f,"\tQuery port end: %i\n",global.query_port_end);
179
399
#ifndef NO_TCP_SERVER
180
fsprintf_or_return(f,"\tTCP server thread: %s\n",notcp?"off":"on");
400
fsprintf_or_return(f,"\tTCP server thread: %s\n",global.notcp?"off":"on");
182
402
{fsprintf_or_return(f,"\tTCP query timeout: %li\n",(long)global.tcp_qtimeout);}
184
fsprintf_or_return(f,"\tDelegation-only zones: ");
407
int rv=fsprintf(f,"\tDelegation-only zones: ");
408
if(rv<0) {retval=rv; goto unlock_return;}
185
410
if(global.deleg_only_zones==NULL) {
186
fsprintf_or_return(f,"(none)\n");
411
int rv=fsprintf(f,"(none)\n");
412
if(rv<0) {retval=rv; goto unlock_return;}
189
416
for(i=0;i<DA_NEL(global.deleg_only_zones);++i) {
190
unsigned char zstr[256];
191
rhn2str(DA_INDEX(global.deleg_only_zones,i),zstr);
192
fsprintf_or_return(f,i==0?"%s":", %s",zstr);
417
unsigned char buf[256];
418
rv=fsprintf(f,i==0?"%s":", %s",
419
rhn2str(DA_INDEX(global.deleg_only_zones,i),buf,sizeof(buf)));
420
if(rv<0) {retval=rv; goto unlock_return;}
194
fsprintf_or_return(f,"\n");
423
if(rv<0) {retval=rv; goto unlock_return;}
198
426
for(i=0;i<DA_NEL(servers);i++) {
199
427
int rv=report_server_stat(f,i);
428
if(rv<0) {retval=rv; goto unlock_return;}
205
431
unlock_server_data();