[PATCH 4/4] dhcp6c: DHCPv6 client
Denys Vlasenko
vda.linux at googlemail.com
Mon Oct 17 23:06:56 UTC 2011
On Saturday 01 October 2011 18:12, Leonid Lisovskiy wrote:
> This patch contains ported DHCPv6 client. Due to patch is huge
> (230Kb), attach is gzipped.
>
> With all options enabled applet increases size of bb code approx. to
> 36Kb on x86.
It looks WAY too big.
There are planty of places to shrink the code.
For example, let's look at dhcp6c_script.c:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include "common.h"
common.h includes libbb.h, which in turn includes most of system includes.
You can remove almost all includes above this line.
const char reason[] = "REASON=NBI";
...
*curr = xstrdup(reason);
Why reason[] exists?
elen = strlen(client6_envp_list[i].name) + 1 + elens[i];
*curr = xzalloc(elen);
snprintf(*curr, elen, "%s=", client6_envp_list[i].name);
^^^^^^^^^^^^
Can use sprintf: we know we won't overflow.
TAILQ_FOREACH(v, &optinfo->ad_list, link) {
if (v->dh6optype != client6_envp_list[i].type)
continue;
/* since we count total length above, it is safely to use strcat() */
switch (v->lvtype) {
case DHCP6_LISTVAL_VBUF:
strcat(*curr, v->val_vbuf.dv_buf);
strcat(*curr, " ");
strcat is inefficient. strcat(" ") doubly so:
can use *p++ = ' ' instead.
break;
case DHCP6_LISTVAL_ADDR6:
sprint_nip6(a, (const uint8_t *)&v->val_addr6);
strcat(*curr, a);
strcat(*curr, " ");
break;
default:
break;
}
}
static int safefile(const char *path)
{
struct stat s;
uid_t myuid = getuid();
/* no setuid */
if (myuid != geteuid()) {
bb_info_msg("setuid'ed execution not allowed");
return -1;
}
if (access(path, X_OK) || lstat(path, &s)) {
return -1;
}
if (!S_ISREG(s.st_mode) && !S_ISLNK(s.st_mode)) {
return -1;
}
/* the file must be owned by the running uid */
if (s.st_uid != myuid) {
bb_info_msg("script has invalid owner");
return -1;
}
return 0;
}
int dhcp6_script(const char *scriptpath, char **envp)
{
char *argv[2];
/* if a script is not specified, do nothing */
if (strlen(scriptpath) == 0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use if (!scriptpath[0]) ... instead
return -2;
if (safefile(scriptpath)) {
bb_error_msg("script \"%s\" cannot be executed safely", scriptpath);
return -2;
}
Nuke safefile altogether, it's bloat. We never do such checks
in other applets.
dhcp6_script() is called exactly one, this way:
dhcp6_script(ifp->scriptpath, fill_envp_client6(optinfo, ifp->ifname));
which is also the only callsite of fill_envp_client6.
Therefore, fill_envp_client6 can be made static to dhcp6c_script.c
and called *from within* dhcp6_script() (which, by the way,
is better be renamed to dhcp6_run_script()...)
Elsewhere, random observations:
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
error = getaddrinfo(DH6ADDR_ALLAGENT, DH6PORT_UPSTREAM, &hints, &res);
if (error) {
bb_error_msg_and_die("getaddrinfo: %s", gai_strerror(error));
}
memcpy(&G.sa6_allagent, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
???! This is a fixed IPv6 address, [ff02::1:2]:547, it can be just a constant struct,
right?
argv += optind;
argc -= optind;
if (argc < 1) {
bb_show_usage();
}
if (!(opt & OPT_FOREGROUND) && !(opt & OPT_i)) {
bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
BUG: would re-execute (on NOMMU) with wrong argv: argv += optind
is done too early.
Need documentation for /etc/dhcp6c.conf format.
Patch does not compile with uclibc:
networking/udhcp/lib.a(if6.o): In function `gethwid':
if6.c:(.text.gethwid+0xf): undefined reference to `getifaddrs'
if6.c:(.text.gethwid+0x9a): undefined reference to `freeifaddrs'
networking/udhcp/lib.a(if6.o): In function `if6init':
if6.c:(.text.if6init+0x88): undefined reference to `getifaddrs'
if6.c:(.text.if6init+0x10d): undefined reference to `freeifaddrs'
networking/udhcp/lib.a(common6.o): In function `duidstr':
common6.c:(.text.duidstr+0x9): undefined reference to `BUG_dhcp6c_globals_too_big'
collect2: ld returned 1 exit status
make: *** [busybox_unstripped] Error 1
--
vda
More information about the busybox
mailing list