Support resolv_conf.head and resolv_conf.tail.
These will be used if they exist at initialization. Operations are all done by acting on pre-opened fds.
This commit is contained in:
parent
313da14518
commit
a47a2feea1
83
src/ifchd.c
83
src/ifchd.c
@ -60,6 +60,8 @@ static struct epoll_event events[2];
|
||||
|
||||
static int resolv_conf_fd = -1;
|
||||
/* int ntp_conf_fd = -1; */
|
||||
static int resolv_conf_head_fd = -1;
|
||||
static int resolv_conf_tail_fd = -1;
|
||||
|
||||
/* If true, allow HOSTNAME changes from dhcp server. */
|
||||
int allow_hostname = 0;
|
||||
@ -75,6 +77,38 @@ static void writeordie(int fd, const char buf[static 1], size_t len)
|
||||
__func__, r);
|
||||
}
|
||||
|
||||
static int write_append_fd(int to_fd, int from_fd, const char descr[static 1])
|
||||
{
|
||||
if (from_fd < 0) return 0;
|
||||
if (to_fd < 0) return -1;
|
||||
|
||||
const off_t lse = lseek(from_fd, 0, SEEK_END);
|
||||
if (lse < 0) {
|
||||
log_warning("%s: (%s) lseek(SEEK_END) failed %s",
|
||||
client_config.interface, __func__, descr);
|
||||
return -2;
|
||||
}
|
||||
if (lseek(from_fd, 0, SEEK_SET) < 0) {
|
||||
log_warning("%s: (%s) lseek(SEEK_SET) failed %s",
|
||||
client_config.interface, __func__, descr);
|
||||
return -2;
|
||||
}
|
||||
|
||||
char buf[4096];
|
||||
size_t from_fd_len = lse;
|
||||
while (from_fd_len > 0) {
|
||||
const size_t to_read = from_fd_len <= sizeof buf ? from_fd_len : sizeof buf;
|
||||
ssize_t r = safe_read(from_fd, buf, to_read);
|
||||
if (r < 0 || (size_t)r != to_read)
|
||||
suicide("%s: (%s) read failed %s", client_config.interface, __func__, descr);
|
||||
r = safe_write(to_fd, buf, to_read);
|
||||
if (r < 0 || (size_t)r != to_read)
|
||||
suicide("%s: (%s) write failed %s", client_config.interface, __func__, descr);
|
||||
from_fd_len -= to_read;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Writes a new resolv.conf based on the information we have received. */
|
||||
static int write_resolve_conf(void)
|
||||
{
|
||||
@ -92,6 +126,8 @@ static int write_resolve_conf(void)
|
||||
if (lseek(resolv_conf_fd, 0, SEEK_SET) < 0)
|
||||
return -1;
|
||||
|
||||
write_append_fd(resolv_conf_fd, resolv_conf_head_fd, "prepending resolv_conf head");
|
||||
|
||||
char *p = cl.namesvrs;
|
||||
while (p && (*p != '\0')) {
|
||||
char *q = strchr(p, ',');
|
||||
@ -147,6 +183,8 @@ static int write_resolve_conf(void)
|
||||
}
|
||||
writeordie(resolv_conf_fd, "\n", 1);
|
||||
|
||||
write_append_fd(resolv_conf_fd, resolv_conf_tail_fd, "appending resolv_conf tail");
|
||||
|
||||
off = lseek(resolv_conf_fd, 0, SEEK_CUR);
|
||||
if (off < 0) {
|
||||
log_line("write_resolve_conf: lseek returned error: %s",
|
||||
@ -345,24 +383,43 @@ static void do_ifch_work(void)
|
||||
}
|
||||
}
|
||||
|
||||
// If we are requested to update resolv.conf, preopen the fd before
|
||||
// we drop root privileges, making sure that if we create
|
||||
// resolv.conf, it will be world-readable.
|
||||
static void setup_resolv_conf(void)
|
||||
{
|
||||
if (strncmp(resolv_conf_d, "", sizeof resolv_conf_d)) {
|
||||
umask(022);
|
||||
resolv_conf_fd = open(resolv_conf_d, O_RDWR|O_CREAT|O_CLOEXEC, 644);
|
||||
umask(077);
|
||||
if (resolv_conf_fd < 0) {
|
||||
suicide("FATAL - unable to open resolv.conf");
|
||||
}
|
||||
char buf[PATH_MAX];
|
||||
|
||||
ssize_t sl = snprintf(buf, sizeof buf, "%s.head", resolv_conf_d);
|
||||
if (sl < 0 || (size_t)sl >= sizeof buf)
|
||||
log_warning("snprintf failed appending resolv_conf_head; path too long?");
|
||||
else
|
||||
resolv_conf_head_fd = open(buf, O_RDONLY|O_CLOEXEC, 0);
|
||||
|
||||
sl = snprintf(buf, sizeof buf, "%s.tail", resolv_conf_d);
|
||||
if (sl < 0 || (size_t)sl >= sizeof buf)
|
||||
log_warning("snprintf failed appending resolv_conf_tail; path too long?");
|
||||
else
|
||||
resolv_conf_tail_fd = open(buf, O_RDONLY|O_CLOEXEC, 0);
|
||||
|
||||
memset(buf, '\0', sizeof buf);
|
||||
}
|
||||
memset(resolv_conf_d, '\0', sizeof resolv_conf_d);
|
||||
}
|
||||
|
||||
void ifch_main(void)
|
||||
{
|
||||
prctl(PR_SET_NAME, "ndhc: ifch");
|
||||
umask(077);
|
||||
signalFd = setup_signals_subprocess();
|
||||
|
||||
// If we are requested to update resolv.conf, preopen the fd before
|
||||
// we drop root privileges, making sure that if we create
|
||||
// resolv.conf, it will be world-readable.
|
||||
if (strncmp(resolv_conf_d, "", sizeof resolv_conf_d)) {
|
||||
umask(022);
|
||||
resolv_conf_fd = open(resolv_conf_d, O_RDWR | O_CREAT, 644);
|
||||
umask(077);
|
||||
if (resolv_conf_fd < 0) {
|
||||
suicide("FATAL - unable to open resolv.conf");
|
||||
}
|
||||
}
|
||||
memset(resolv_conf_d, '\0', sizeof resolv_conf_d);
|
||||
setup_resolv_conf();
|
||||
|
||||
nk_set_chroot(chroot_dir);
|
||||
memset(chroot_dir, '\0', sizeof chroot_dir);
|
||||
|
Loading…
Reference in New Issue
Block a user