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;
|
static int resolv_conf_fd = -1;
|
||||||
/* int ntp_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. */
|
/* If true, allow HOSTNAME changes from dhcp server. */
|
||||||
int allow_hostname = 0;
|
int allow_hostname = 0;
|
||||||
@ -75,6 +77,38 @@ static void writeordie(int fd, const char buf[static 1], size_t len)
|
|||||||
__func__, r);
|
__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. */
|
/* Writes a new resolv.conf based on the information we have received. */
|
||||||
static int write_resolve_conf(void)
|
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)
|
if (lseek(resolv_conf_fd, 0, SEEK_SET) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
write_append_fd(resolv_conf_fd, resolv_conf_head_fd, "prepending resolv_conf head");
|
||||||
|
|
||||||
char *p = cl.namesvrs;
|
char *p = cl.namesvrs;
|
||||||
while (p && (*p != '\0')) {
|
while (p && (*p != '\0')) {
|
||||||
char *q = strchr(p, ',');
|
char *q = strchr(p, ',');
|
||||||
@ -147,6 +183,8 @@ static int write_resolve_conf(void)
|
|||||||
}
|
}
|
||||||
writeordie(resolv_conf_fd, "\n", 1);
|
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);
|
off = lseek(resolv_conf_fd, 0, SEEK_CUR);
|
||||||
if (off < 0) {
|
if (off < 0) {
|
||||||
log_line("write_resolve_conf: lseek returned error: %s",
|
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)
|
void ifch_main(void)
|
||||||
{
|
{
|
||||||
prctl(PR_SET_NAME, "ndhc: ifch");
|
prctl(PR_SET_NAME, "ndhc: ifch");
|
||||||
umask(077);
|
umask(077);
|
||||||
signalFd = setup_signals_subprocess();
|
signalFd = setup_signals_subprocess();
|
||||||
|
setup_resolv_conf();
|
||||||
// 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);
|
|
||||||
|
|
||||||
nk_set_chroot(chroot_dir);
|
nk_set_chroot(chroot_dir);
|
||||||
memset(chroot_dir, '\0', sizeof chroot_dir);
|
memset(chroot_dir, '\0', sizeof chroot_dir);
|
||||||
|
Loading…
Reference in New Issue
Block a user