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
21 changes: 16 additions & 5 deletions src/dhcpcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,10 @@ static void
dhcpcd_initstate(struct interface *ifp, unsigned long long options)
{

dhcpcd_initstate1(ifp, ifp->ctx->argc, ifp->ctx->argv, options);
dhcpcd_initstate1(ifp,
ifp->argc ?: ifp->ctx->argc,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ?: a valid ternary operator in standard C?

ifp->argv ?: ifp->ctx->argv,
options);
}

static void
Expand Down Expand Up @@ -1315,7 +1318,7 @@ if_reboot(struct interface *ifp, int argc, char **argv)
oldopts = ifp->options->options;
#endif
script_runreason(ifp, "RECONFIGURE");
dhcpcd_initstate1(ifp, argc, argv, 0);
dhcpcd_initstate1(ifp, argc, argv, 0); // control or main argv
#ifdef INET
if (ifp->options->options & DHCPCD_DHCP)
dhcp_reboot_newopts(ifp, oldopts);
Expand Down Expand Up @@ -1370,8 +1373,16 @@ reconf_reboot(struct dhcpcd_ctx *ctx, int action, int argc, char **argv, int oi)
ipv4_applyaddr(ifp);
#endif
} else if (i != argc) {
/* iface wasnt found above -> it's new. start it. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is misleading as the interface is not new, it's already been allocated.
The interface however is not active which is clearly noted above. Just remove the comment please.

ifp->active = IF_ACTIVE_USER;
dhcpcd_initstate1(ifp, argc, argv, 0);
dhcpcd_initstate1(ifp, argc, argv, 0); // control cmd args

if (ifp->argv)
free_argv_copy(ifp->argv);
ifp->argv = copy_argv(argc, argv);
if (ifp->argv)
ifp->argc = argc;

run_preinit(ifp);
dhcpcd_prestartinterface(ifp);
}
Expand Down Expand Up @@ -1715,7 +1726,7 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
}

reload_config(ctx);
/* XXX: Respect initial commandline options? */
/* Respect control cmd options! */
reconf_reboot(ctx, do_reboot, argc, argv, oifind);
return 0;
}
Expand Down Expand Up @@ -2605,7 +2616,7 @@ main(int argc, char **argv, char **envp)

TAILQ_FOREACH(ifp, ctx.ifaces, next) {
if (ifp->active)
dhcpcd_initstate1(ifp, argc, argv, 0);
dhcpcd_initstate1(ifp, argc, argv, 0); // main argv
}
if_learnaddrs(&ctx, ctx.ifaces, &ifaddrs);
if_freeifaddrs(&ctx, &ifaddrs);
Expand Down
3 changes: 3 additions & 0 deletions src/dhcpcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ struct interface {
uint8_t ssid[IF_SSIDLEN];
unsigned int ssid_len;

int argc;
char **argv;

char profile[PROFILE_LEN];
struct if_options *options;
void *if_data[IF_DATA_MAX];
Expand Down
60 changes: 60 additions & 0 deletions src/if-options.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <assert.h>

#include "config.h"
#include "common.h"
Expand Down Expand Up @@ -2986,6 +2987,65 @@ add_options(struct dhcpcd_ctx *ctx, const char *ifname,
return r;
}

#define ARGV_COPY_MAGIC ((char *)0x5a54292d273f3d34)
/*^ intentional truncation on 32bit arches */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is scary.
Why do we need a sentinel here? The scope of the variable isn't going outside any process so we can just malloc and free which makes the below code easier.


char **copy_argv(int argc, char **argv)
{
int i;
size_t strslen = 0;
for (i = 0; i < argc; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace between declaration and code please.

strslen += strlen(argv[i]) + 1;
}
if (strslen == 0) // also handles argc < 0
return NULL;

unsigned nptrs = 1 + (unsigned)argc + 1;
size_t ptrslen = nptrs * sizeof(char *);
void *buf = malloc(ptrslen + strslen);
char **ptrs = buf;
if (!buf)
return NULL;

ptrs[0] = ARGV_COPY_MAGIC;
ptrs[nptrs - 1] = NULL;

if (argc == 0)
goto out;

char *strsp = (char *)&ptrs[nptrs];
for (i = 0; i < argc; i++) {
size_t len = strlcpy(strsp, argv[i], strslen);
if (len >= strslen) // truncated
goto err;

ptrs[1 + i] = strsp;

strsp += len + 1;
if (strslen < len + 1)
goto err;
strslen -= len + 1;
}

assert(strslen == 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it interesting that you assert this error but allow impossible errors to pass with a failure in the loop.
Please pick one and be consistent.

assert(ptrs[nptrs - 1] == NULL);
out:
return &ptrs[1];

err:
free(buf);
return NULL;
}

void free_argv_copy(char **argv)
{
assert(argv[-1] == ARGV_COPY_MAGIC);
if (argv[-1] != ARGV_COPY_MAGIC) {
logerrx("%s: invalid argv", __func__);
} else
free(&argv[-1]);
}

void
free_options(struct dhcpcd_ctx *ctx, struct if_options *ifo)
{
Expand Down
3 changes: 3 additions & 0 deletions src/if-options.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,7 @@ int add_options(struct dhcpcd_ctx *, const char *,
void free_dhcp_opt_embenc(struct dhcp_opt *);
void free_options(struct dhcpcd_ctx *, struct if_options *);

char **copy_argv(int argc, char **argv);
void free_argv_copy(char **argv);

#endif
2 changes: 2 additions & 0 deletions src/if.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ if_free(struct interface *ifp)
#endif
rt_freeif(ifp);
free_options(ifp->ctx, ifp->options);
if (ifp->argv)
free_argv_copy(ifp->argv);
free(ifp);
}

Expand Down
Loading