Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

#include "config.h"
#include "auth.h"
#include "common.h"
#include "dhcp.h"
#include "dhcp6.h"
#include "dhcpcd.h"
Expand Down Expand Up @@ -437,16 +438,17 @@ auth_get_rdm_monotonic(uint64_t *rdm)
int flocked;
#endif

fp = fopen(RDM_MONOFILE, "r+");
ensure_dir(dhcpcd_rdm_monofile, 0750);
fp = fopen(dhcpcd_rdm_monofile, "r+");
if (fp == NULL) {
if (errno != ENOENT)
return -1;
fp = fopen(RDM_MONOFILE, "w");
fp = fopen(dhcpcd_rdm_monofile, "w");
if (fp == NULL)
return -1;
if (chmod(RDM_MONOFILE, 0400) == -1) {
if (chmod(dhcpcd_rdm_monofile, 0400) == -1) {
(void)fclose(fp);
unlink(RDM_MONOFILE);
unlink(dhcpcd_rdm_monofile);
return -1;
}
#ifdef LOCK_EX
Expand Down
84 changes: 84 additions & 0 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,96 @@ readfile(const char *file, void **data, size_t *len)
return bytes;
}

/* Return a copy of s with every '%' doubled so it is safe to use as a
* literal within a printf-style format string. Returns NULL on failure. */
char *
escape_percent(const char *s)
{
const char *p;
char *r, *d;
size_t extra = 0;

if (s == NULL)
s = "";
for (p = s; *p != '\0'; p++)
if (*p == '%')
extra++;
r = malloc(strlen(s) + extra + 1);
if (r == NULL)
return NULL;
for (p = s, d = r; *p != '\0'; p++) {
if (*p == '%')
*d++ = '%';
*d++ = *p;
}
*d = '\0';
return r;
}

/* Create a directory and any missing parents, like mkdir -p. */
int
mkdirs(const char *dir, mode_t mode)
{
char *d, *p;
int r = 0;

if (dir == NULL || dir[0] == '\0') {
errno = EINVAL;
return -1;
}
d = strdup(dir);
if (d == NULL)
return -1;
for (p = d + 1; *p != '\0'; p++) {
if (*p != '/')
continue;
*p = '\0';
if (mkdir(d, mode) == -1 && errno != EEXIST)
r = -1;
*p = '/';
}
if (mkdir(d, mode) == -1 && errno != EEXIST)
r = -1;
free(d);
return r;
}

/* Ensure the directory part of a file path exists. */
int
ensure_dir(const char *file, mode_t mode)
{
char *d, *p;
int r;

if (file == NULL) {
errno = EINVAL;
return -1;
}
d = strdup(file);
if (d == NULL)
return -1;
p = strrchr(d, '/');
if (p == NULL) {
free(d);
return 0;
}
if (p == d)
*(p + 1) = '\0';
else
*p = '\0';
r = mkdirs(d, mode);
free(d);
return r;
}

ssize_t
writefile(const char *file, mode_t mode, const void *data, size_t len)
{
int fd;
ssize_t bytes;

if (ensure_dir(file, 0750) == -1)
return -1;
fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (fd == -1)
return -1;
Expand Down
3 changes: 3 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ const char *hwaddr_ntoa(const void *, size_t, char *, size_t);
size_t hwaddr_aton(uint8_t *, const char *);
ssize_t readfile(const char *, void **, size_t *);
ssize_t writefile(const char *, mode_t, const void *, size_t);
char *escape_percent(const char *);
int mkdirs(const char *, mode_t);
int ensure_dir(const char *, mode_t);
int filemtime(const char *, time_t *);
char *get_line(char **__restrict, size_t *__restrict);
int is_root_local(void);
Expand Down
4 changes: 3 additions & 1 deletion src/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ make_path(char *path, size_t len, const char *ifname, sa_family_t family)
per = "";
break;
}
return snprintf(path, len, CONTROLSOCKET, ifname ? ifname : "",
return snprintf(path, len, dhcpcd_controlsock, ifname ? ifname : "",
ifname ? per : "", "", ifname ? "." : "");
}

Expand Down Expand Up @@ -521,6 +521,8 @@ control_start1(struct dhcpcd_ctx *ctx, const char *ifname, sa_family_t family)
if (fd == -1)
return -1;

ensure_dir(sa.sun_path, 0755);

len = (socklen_t)SUN_LEN(&sa);
if (GID_SET(ctx->control_group) && GID_SET(ctx->read_group)) {
if (ctx->control_group == ctx->read_group) {
Expand Down
26 changes: 26 additions & 0 deletions src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,32 @@
#define RDM_MONOFILE DBDIR "/rdm_monotonic"
#endif

/*
* Runtime configurable paths.
* These default to the compiled in values but can be overridden at runtime
* with the corresponding command line options (--instance, --dbdir, --rundir,
* --devdir). The individual file paths are derived from these and rebuilt
* whenever a base directory is changed (see dhcpcd_paths_update()).
*/
extern const char *dhcpcd_dbdir;
extern const char *dhcpcd_rundir;
extern const char *dhcpcd_devdir;
extern const char *dhcpcd_instance;
extern const char *dhcpcd_duidfile;
extern const char *dhcpcd_secretfile;
extern const char *dhcpcd_rdm_monofile;
extern const char *dhcpcd_leasefile;
extern const char *dhcpcd_leasefile6;
extern const char *dhcpcd_pidfile;
extern const char *dhcpcd_controlsock;

void dhcpcd_paths_init(void);
void dhcpcd_paths_update(void);
void dhcpcd_paths_set_dbdir(const char *);
void dhcpcd_paths_set_rundir(const char *);
void dhcpcd_paths_set_devdir(const char *);
void dhcpcd_paths_set_instance(const char *);

#ifndef NO_SIGNALS
#define USE_SIGNALS
#endif
Expand Down
6 changes: 3 additions & 3 deletions src/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ dev_start2(struct dhcpcd_ctx *ctx, const struct dev_dhcpcd *dev_dhcpcd,
void (*fptr)(struct dev *, const struct dev_dhcpcd *);
int r;

snprintf(file, sizeof(file), DEVDIR "/%s", name);
snprintf(file, sizeof(file), "%s/%s", dhcpcd_devdir, name);
h = dlopen(file, RTLD_LAZY);
if (h == NULL) {
logerrx("dlopen: %s", dlerror());
Expand Down Expand Up @@ -143,9 +143,9 @@ dev_start1(struct dhcpcd_ctx *ctx, const struct dev_dhcpcd *dev_dhcpcd)
if (ctx->dev_load)
return dev_start2(ctx, dev_dhcpcd, ctx->dev_load);

dp = opendir(DEVDIR);
dp = opendir(dhcpcd_devdir);
if (dp == NULL) {
logdebug("dev: %s", DEVDIR);
logdebug("dev: %s", dhcpcd_devdir);
return -1;
}

Expand Down
3 changes: 2 additions & 1 deletion src/dhcp-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,8 @@ dhcp_set_leasefile(char *leasefile, size_t len, int family,
} else
ssid[0] = '\0';
return snprintf(leasefile, len,
family == AF_INET ? LEASEFILE : LEASEFILE6, ifname, ssid);
family == AF_INET ? dhcpcd_leasefile : dhcpcd_leasefile6, ifname,
ssid);
}

void
Expand Down
73 changes: 67 additions & 6 deletions src/dhcpcd.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
.Op Fl Z , Fl Fl denyinterfaces Ar pattern
.Op Fl z , Fl Fl allowinterfaces Ar pattern
.Op Fl Fl inactive
.Op Fl Fl instance Ar instance
.Op Fl Fl dbdir Ar dir
.Op Fl Fl rundir Ar dir
.Op Fl Fl devdir Ar dir
.Op Fl Fl configure
.Op Fl Fl noconfigure
.Op interface
Expand Down Expand Up @@ -271,9 +275,9 @@ Use a DHCP Unique Identifier.
If persistent storage is available then a DUID-LLT
(link local address + time) is generated,
otherwise DUID-LL is generated (link local address).
The DUID type can be hinted as an optional parameter if the file
.Pa @DBDIR@/duid
does not exist.
The DUID type can be hinted as an optional parameter if the default DUID file
.Pa @DBDIR@/duid
does not exist.
If not
.Va ll ,
.Va lt
Expand All @@ -284,9 +288,9 @@ then
will be converted from 00:11:22:33 format.
This, plus the IAID will be used as the
.Fl I , Fl Fl clientid .
The DUID generated will be held in
.Pa @DBDIR@/duid
and should not be copied to other hosts.
The DUID generated will be held in the default DUID file
.Pa @DBDIR@/duid
and should not be copied to other hosts.
This file also takes precedence over the above rules except for setting a value.
.It Fl d , Fl Fl debug
Echo debug messages to the stderr and syslog.
Expand Down Expand Up @@ -778,6 +782,51 @@ addition of
Don't load any
.Pa /dev
management modules.
.It Fl Fl instance Ar instance
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Prefix the state and runtime files that
.Nm
writes, namely the DUID, secret, lease, RDM, PID and control socket files,
with the
.Ar instance
name inside the state and runtime directories.
.Ar instance
must be a single path component and must not contain a
.Sq / .
For example,
.Fl Fl instance=foo
will cause the DUID file to be written to
.Pa @DBDIR@/ Ns Pa foo Ns .duid
and the PID file to
.Pa @RUNDIR@/ Ns Pa foo Ns .pid .
The base directories remain unchanged.
.It Fl Fl dbdir Ar dir
Specify the base directory where
.Nm
stores its lease and state database.
This overrides the compiled in default
.Pa @DBDIR@ .
Without
.Fl Fl instance
the DUID, secret, lease and RDM files are created directly here, otherwise
they are created here under the file name prefixed with the instance name.
.It Fl Fl rundir Ar dir
Specify the base directory where
.Nm
stores its runtime files, such as the PID file and control socket.
This overrides the compiled in default
.Pa @RUNDIR@ .
Without
.Fl Fl instance
the PID file and control socket are created directly here, otherwise they
are created here under the file name prefixed with the instance name.
.It Fl Fl devdir Ar dir
Specify the directory from which
.Nm
loads
.Pa /dev
management modules.
This overrides the compiled in default
.Pa @LIBDIR@/dhcpcd/dev .
.El
.Sh 3RDPARTY LINK MANAGEMENT
Some interfaces require configuration by 3rd parties, such as PPP or VPN.
Expand Down Expand Up @@ -818,6 +867,18 @@ sends to match.
If using a DUID in place of the ClientID, edit
.Pa @DBDIR@/duid
accordingly.
.Pp
The file paths shown in this manual, such as
.Pa @DBDIR@/duid ,
are the compiled in defaults.
The effective path used by
.Nm
can be changed with the
.Fl Fl dbdir ,
.Fl Fl rundir
and
.Fl Fl instance
options described above.
.Sh FILES
.Bl -ohang
.It Pa @SYSCONFDIR@/dhcpcd.conf
Expand Down
Loading