Skip to content

Commit ac500d5

Browse files
authored
Merge pull request #2232 from pi-hole/development
Pi-hole FTL v6.0.2
2 parents 62904ae + bdbe30a commit ac500d5

10 files changed

+141
-87
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ set(CMAKE_C_STANDARD 17)
1616

1717
project(PIHOLE_FTL C)
1818

19-
set(DNSMASQ_VERSION pi-hole-v2.91rc4)
19+
set(DNSMASQ_VERSION pi-hole-v2.91rc5)
2020

2121
add_subdirectory(src)

src/config/dnsmasq_config.c

+22-31
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
#include "log.h"
1515
// get_blocking_mode_str()
1616
#include "datastructure.h"
17-
// flock(), LOCK_SH
18-
#include <sys/file.h>
1917
// struct config
2018
#include "config/config.h"
2119
// JSON array functions
@@ -116,11 +114,21 @@ static bool test_dnsmasq_config(char errbuf[ERRBUF_SIZE])
116114
// We can ignore EINTR as it just means that the wait
117115
// was interrupted, so we just try again. All other
118116
// errors are fatal and we break out of the loop
119-
if(err != EINTR)
117+
if(err != EINTR && err != EAGAIN && err != ECHILD)
120118
{
121119
log_err("Cannot wait for dnsmasq test: %s", strerror(err));
122120
break;
123121
}
122+
123+
// Check if the child exited too quickly for waitpid to
124+
// catch it. We cannot get the return code in this case
125+
// and have to check the pipe content instead
126+
if(errno == ECHILD)
127+
{
128+
log_debug(DEBUG_CONFIG, "dnsmasq test exited too quickly for waitpid");
129+
code = strstr(errbuf, "syntax check OK") != NULL ? EXIT_SUCCESS : EXIT_FAILURE;
130+
goto check_return;
131+
}
124132
}
125133

126134
// Get return code if child exited normally
@@ -136,11 +144,12 @@ static bool test_dnsmasq_config(char errbuf[ERRBUF_SIZE])
136144
WCOREDUMP(status) ? "(core dumped)" : "");
137145
}
138146

147+
check_return:
139148
// Check if the error message contains a line number. If so, we
140149
// can append the offending line to the error message
141150
if(code != EXIT_SUCCESS)
142151
{
143-
int lineno = get_lineno_from_string(errbuf);
152+
const int lineno = get_lineno_from_string(errbuf);
144153
if(lineno > 0)
145154
{
146155
const size_t errbuf_size = strlen(errbuf);
@@ -314,12 +323,7 @@ bool __attribute__((const)) write_dnsmasq_config(struct config *conf, bool test_
314323
}
315324

316325
// Lock file, may block if the file is currently opened
317-
if(flock(fileno(pihole_conf), LOCK_EX) != 0)
318-
{
319-
log_err("Cannot open "DNSMASQ_TEMP_CONF" in exclusive mode: %s", strerror(errno));
320-
fclose(pihole_conf);
321-
return false;
322-
}
326+
const bool locked = lock_file(pihole_conf, DNSMASQ_TEMP_CONF);
323327

324328
write_config_header(pihole_conf, "Dnsmasq config for Pi-hole's FTLDNS");
325329
fputs("hostsdir="DNSMASQ_HOSTSDIR"\n", pihole_conf);
@@ -500,9 +504,9 @@ bool __attribute__((const)) write_dnsmasq_config(struct config *conf, bool test_
500504
continue;
501505
}
502506

503-
if(active == NULL || cidr == NULL || target == NULL || domain == NULL)
507+
if(active == NULL || cidr == NULL || target == NULL)
504508
{
505-
log_err("Skipped invalid dns.revServers[%u]: %s", i, revServer->valuestring);
509+
log_err("Skipped invalid dns.revServers[%u]: %s (not fully defined)", i, revServer->valuestring);
506510
free(copy);
507511
continue;
508512
}
@@ -513,7 +517,7 @@ bool __attribute__((const)) write_dnsmasq_config(struct config *conf, bool test_
513517

514518
// If we have a reverse domain, we forward all queries to this domain to
515519
// the same destination
516-
if(strlen(domain) > 0)
520+
if(domain != NULL && strlen(domain) > 0)
517521
{
518522
fprintf(pihole_conf, "server=/%s/%s\n", domain, target);
519523

@@ -757,12 +761,8 @@ bool __attribute__((const)) write_dnsmasq_config(struct config *conf, bool test_
757761
fflush(pihole_conf);
758762

759763
// Unlock file
760-
if(flock(fileno(pihole_conf), LOCK_UN) != 0)
761-
{
762-
log_err("Cannot release lock on dnsmasq config file: %s", strerror(errno));
763-
fclose(pihole_conf);
764-
return false;
765-
}
764+
if(locked)
765+
unlock_file(pihole_conf, DNSMASQ_TEMP_CONF);
766766

767767
// Close file
768768
if(fclose(pihole_conf) != 0)
@@ -1026,12 +1026,7 @@ bool write_custom_list(void)
10261026
}
10271027

10281028
// Lock file, may block if the file is currently opened
1029-
if(flock(fileno(custom_list), LOCK_EX) != 0)
1030-
{
1031-
log_err("Cannot open "DNSMASQ_CUSTOM_LIST_LEGACY".tmp in exclusive mode: %s", strerror(errno));
1032-
fclose(custom_list);
1033-
return false;
1034-
}
1029+
const bool locked = lock_file(custom_list, DNSMASQ_CUSTOM_LIST_LEGACY".tmp");
10351030

10361031
write_config_header(custom_list, "Custom DNS entries (HOSTS file)");
10371032
fputc('\n', custom_list);
@@ -1056,12 +1051,8 @@ bool write_custom_list(void)
10561051
fputs("\n# There are currently no entries in this file\n", custom_list);
10571052

10581053
// Unlock file
1059-
if(flock(fileno(custom_list), LOCK_UN) != 0)
1060-
{
1061-
log_err("Cannot release lock on custom.list: %s", strerror(errno));
1062-
fclose(custom_list);
1063-
return false;
1064-
}
1054+
if(locked)
1055+
unlock_file(custom_list, DNSMASQ_CUSTOM_LIST_LEGACY".tmp");
10651056

10661057
// Close file
10671058
if(fclose(custom_list) != 0)

src/config/env.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,9 @@ cJSON *read_forced_vars(const unsigned int version)
633633
cJSON *env_vars = cJSON_CreateArray();
634634

635635
// Try to open default config file. Use fallback if not found
636-
FILE *fp;
637-
if((fp = openFTLtoml("r", version)) == NULL)
636+
bool locked = false;
637+
FILE *fp = openFTLtoml("r", version, &locked);
638+
if(fp == NULL)
638639
{
639640
// Return empty cJSON array
640641
return env_vars;
@@ -672,7 +673,7 @@ cJSON *read_forced_vars(const unsigned int version)
672673
}
673674

674675
// Close file and release exclusive lock
675-
closeFTLtoml(fp);
676+
closeFTLtoml(fp, locked);
676677

677678
// Return cJSON array
678679
return env_vars;

src/config/toml_helper.c

+6-16
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#include "config/config.h"
1414
// get_refresh_hostnames_str()
1515
#include "datastructure.h"
16-
// flock(), LOCK_SH
17-
#include <sys/file.h>
1816
// fcntl(), O_ACCMODE, O_RDONLY
1917
#include <fcntl.h>
2018
// rotate_files()
@@ -29,7 +27,7 @@
2927
#include "files.h"
3028

3129
// Open the TOML file for reading or writing
32-
FILE * __attribute((malloc)) __attribute((nonnull(1))) openFTLtoml(const char *mode, const unsigned int version)
30+
FILE * __attribute((malloc)) __attribute((nonnull(1))) openFTLtoml(const char *mode, const unsigned int version, bool *locked)
3331
{
3432
// This should not happen, install a safeguard anyway to unveil
3533
// possible future coding issues early on
@@ -69,15 +67,7 @@ FILE * __attribute((malloc)) __attribute((nonnull(1))) openFTLtoml(const char *m
6967
}
7068

7169
// Lock file, may block if the file is currently opened
72-
if(flock(fileno(fp), LOCK_EX) != 0)
73-
{
74-
const int _e = errno;
75-
log_err("Cannot open config file %s in exclusive mode (%s): %s",
76-
filename, mode, strerror(errno));
77-
fclose(fp);
78-
errno = _e;
79-
return NULL;
80-
}
70+
*locked = lock_file(fp, filename);
8171

8272
// Log if we are using a backup file
8373
if(version > 0)
@@ -88,14 +78,14 @@ FILE * __attribute((malloc)) __attribute((nonnull(1))) openFTLtoml(const char *m
8878
}
8979

9080
// Open the TOML file for reading or writing
91-
void closeFTLtoml(FILE *fp)
81+
void closeFTLtoml(FILE *fp, const bool locked)
9282
{
9383
// Release file lock
94-
const int fn = fileno(fp);
95-
if(flock(fn, LOCK_UN) != 0)
96-
log_err("Cannot release lock on FTL's config file: %s", strerror(errno));
84+
if(locked)
85+
unlock_file(fp, NULL);
9786

9887
// Get access mode
88+
const int fn = fileno(fp);
9989
const int mode = fcntl(fn, F_GETFL);
10090
if (mode == -1)
10191
log_err("Cannot get access mode for FTL's config file: %s", strerror(errno));

src/config/toml_helper.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
#include "tomlc99/toml.h"
1818

1919
void indentTOML(FILE *fp, const unsigned int indent);
20-
FILE *openFTLtoml(const char *mode, const unsigned int version) __attribute((malloc)) __attribute((nonnull(1)));
21-
void closeFTLtoml(FILE *fp);
20+
FILE *openFTLtoml(const char *mode, const unsigned int version, bool *locked) __attribute((malloc)) __attribute((nonnull(1)));
21+
void closeFTLtoml(FILE *fp, const bool locked);
2222
void print_comment(FILE *fp, const char *str, const char *intro, const unsigned int width, const unsigned int indent);
2323
void print_toml_allowed_values(cJSON *allowed_values, FILE *fp, const unsigned int width, const unsigned int indent);
2424
void writeTOMLvalue(FILE * fp, const int indent, const enum conf_type t, union conf_value *v);

src/config/toml_reader.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -228,16 +228,17 @@ bool readFTLtoml(struct config *oldconf, struct config *newconf,
228228
static toml_table_t *parseTOML(const unsigned int version)
229229
{
230230
// Try to open default config file. Use fallback if not found
231-
FILE *fp;
232-
if((fp = openFTLtoml("r", version)) == NULL)
231+
bool locked = false;
232+
FILE *fp = openFTLtoml("r", version, &locked);
233+
if(fp == NULL)
233234
return NULL;
234235

235236
// Parse lines in the config file
236237
char errbuf[200];
237238
toml_table_t *conf = toml_parse_file(fp, errbuf, sizeof(errbuf));
238239

239240
// Close file and release exclusive lock
240-
closeFTLtoml(fp);
241+
closeFTLtoml(fp, locked);
241242

242243
// Check for errors
243244
if(conf == NULL)

src/config/toml_writer.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ bool writeFTLtoml(const bool verbose)
4141
}
4242

4343
// Try to open a temporary config file for writing
44-
FILE *fp;
45-
if((fp = openFTLtoml("w", 0)) == NULL)
44+
bool locked = false;
45+
FILE *fp = openFTLtoml("w", 0, &locked);
46+
if(fp == NULL)
4647
return false;
4748

4849
// Write header
@@ -163,7 +164,7 @@ bool writeFTLtoml(const bool verbose)
163164
cJSON_Delete(env_vars);
164165

165166
// Close file and release exclusive lock
166-
closeFTLtoml(fp);
167+
closeFTLtoml(fp, locked);
167168

168169
// Move temporary file to the final location if it is different
169170
// We skip the first 8 lines as they contain the header and will always

src/dnsmasq/forward.c

+21-28
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,9 @@ static void forward_query(int udpfd, union mysockaddr *udpaddr,
301301

302302
if (gobig && !bitvector)
303303
{
304-
casediff = (i/BITS_IN_INT) + 1; /* length of array */
305-
if ((bitvector = whine_malloc(casediff)))
304+
casediff = ((i - 1)/BITS_IN_INT) + 1; /* length of array */
305+
/* whine_malloc() zeros memory */
306+
if ((bitvector = whine_malloc(casediff * sizeof(unsigned int))))
306307
goto big_redo;
307308
}
308309
}
@@ -402,6 +403,7 @@ static void forward_query(int udpfd, union mysockaddr *udpaddr,
402403
header->id = ntohs(forward->new_id);
403404

404405
forward->frec_src.encode_bitmap = option_bool(OPT_NO_0x20) ? 0 : rand32();
406+
forward->frec_src.encode_bigmap = NULL;
405407
p = (unsigned char *)(header+1);
406408
if (!extract_name(header, plen, &p, (char *)&forward->frec_src.encode_bitmap, EXTR_NAME_FLIP, 1))
407409
goto reply;
@@ -721,7 +723,6 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
721723
unsigned int rcode = RCODE(header);
722724
size_t plen;
723725
/******** Pi-hole modification ********/
724-
unsigned char *pheader_copy = NULL;
725726
unsigned char ede_data[MAX_EDE_DATA] = { 0 };
726727
size_t ede_len = 0;
727728
/**************************************/
@@ -874,16 +875,6 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
874875
if(rc == 99)
875876
{
876877
cache_secure = 0;
877-
// Make a private copy of the pheader to ensure
878-
// we are not accidentially rewriting what is in
879-
// the pheader when we're creating a crafted reply
880-
// further below (when a query is to be blocked)
881-
if (pheader)
882-
{
883-
pheader_copy = calloc(1, plen);
884-
memcpy(pheader_copy, pheader, plen);
885-
}
886-
887878
// Generate DNS packet for reply, a possibly existing pseudo header
888879
// will be restored later inside resize_packet()
889880
n = FTL_make_answer(header, ((char *) header) + 65536, n, ede_data, &ede_len);
@@ -919,22 +910,17 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
919910

920911
/* the code above can elide sections of the packet. Find the new length here
921912
and put back pseudoheader if it was removed. */
922-
n = resize_packet(header, n, pheader_copy ? pheader_copy : pheader, plen);
913+
n = resize_packet(header, n, pheader, plen);
923914
/******** Pi-hole modification ********/
924-
// The line above was modified to use
925-
// pheader_copy instead of pheader
926-
if(pheader_copy)
927-
free(pheader_copy);
928-
929915
if (pheader && (ede != EDE_UNSET || ede_len > 0))
930916
{
931917
if (ede_len > 0)
932-
n = add_pseudoheader(header, n, limit, EDNS0_OPTION_EDE, ede_data, ede_len, do_bit, 1);
933-
else
934-
{
935-
u16 swap = htons((u16)ede);
936-
n = add_pseudoheader(header, n, limit, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 1);
937-
}
918+
n = add_pseudoheader(header, n, limit, EDNS0_OPTION_EDE, ede_data, ede_len, do_bit, 1);
919+
else
920+
{
921+
u16 swap = htons((u16)ede);
922+
n = add_pseudoheader(header, n, limit, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 1);
923+
}
938924
}
939925
/**************************************/
940926

@@ -1100,6 +1086,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
11001086
new->flags |= flags;
11011087
new->forwardall = 0;
11021088
new->frec_src.encode_bitmap = 0;
1089+
new->frec_src.encode_bigmap = NULL;
11031090

11041091
forward->next_dependent = NULL;
11051092
new->dependent = forward; /* to find query awaiting new one. */
@@ -1555,13 +1542,13 @@ void return_reply(time_t now, struct frec *forward, struct dns_header *header, s
15551542
int first_ID = -1;
15561543

15571544
/* This gets the name back to the state it was in when we started. */
1558-
flip_queryname(header, nn, prev, &forward->frec_src);
1545+
flip_queryname(header, new, prev, &forward->frec_src);
15591546

15601547
for (src = &forward->frec_src, prev = NULL; src; prev = src, src = src->next)
15611548
{
15621549
/* If you didn't undertand this above, you won't understand it here either. */
15631550
if (prev)
1564-
flip_queryname(header, nn, prev, src);
1551+
flip_queryname(header, new, prev, src);
15651552

15661553
if (src->fd != -1 && nn > src->udp_pkt_size)
15671554
{
@@ -3200,7 +3187,7 @@ static void free_frec(struct frec *f)
32003187
struct frec_src *last;
32013188

32023189
/* add back to freelist if not the record builtin to every frec,
3203-
also free any bigmaps they's been decorated with. */
3190+
also free any bigmaps they've been decorated with. */
32043191
for (last = f->frec_src.next; last && last->next; last = last->next)
32053192
if (last->encode_bigmap)
32063193
{
@@ -3210,6 +3197,12 @@ static void free_frec(struct frec *f)
32103197

32113198
if (last)
32123199
{
3200+
/* final link in the chain loses bigmap too. */
3201+
if (last->encode_bigmap)
3202+
{
3203+
free(last->encode_bigmap);
3204+
last->encode_bigmap = NULL;
3205+
}
32133206
last->next = daemon->free_frec_src;
32143207
daemon->free_frec_src = f->frec_src.next;
32153208
}

0 commit comments

Comments
 (0)