Remove the .info file and now set environment vars in the same vein as dhclient. This allows similar scripts to be used.

This commit is contained in:
Roy Marples 2008-04-16 09:51:20 +00:00
parent 2cb85d9bb2
commit dcab79de5e
12 changed files with 433 additions and 741 deletions

View File

@ -9,13 +9,13 @@ SRCS+= ${SRC_IF} ${SRC_SOCKET}
SCRIPT= dhcpcd.sh
MAN= dhcpcd.8
VERSION= 3.3.0-alpha1
CLEANFILES= dhcpcd.8
VERSION= 4.0.0-alpha1
CLEANFILES= dhcpcd.sh dhcpcd.8
BINDIR= ${PREFIX}/sbin
SYSCONFDIR?= ${PREFIX}/etc
.SUFFIXES: .in
.SUFFIXES: .in .sh.in
MK= mk
include ${MK}/prog.mk
@ -27,3 +27,7 @@ LDADD+= ${LIBRT}
.in:
${SED} 's:@SYSCONFDIR@:${SYSCONFDIR}:g; s:@DBDIR@:${DBDIR}:g' $< > $@
.sh.in.sh:
${SED} 's:@SYSCONFDIR@:${SYSCONFDIR}:g' $< > $@

224
client.c
View File

@ -95,6 +95,7 @@ struct if_state {
int options;
struct interface *interface;
struct dhcp_message *dhcp;
struct dhcp_message *old_dhcp;
struct dhcp_lease lease;
time_t start;
time_t last_sent;
@ -139,8 +140,8 @@ get_dhcp_op(uint8_t type)
return NULL;
}
static pid_t
daemonise(int *pidfd)
static int
daemonise(struct if_state *state, const struct options *options)
{
pid_t pid;
sigset_t full;
@ -150,6 +151,10 @@ daemonise(int *pidfd)
int i;
#endif
if (state->options & DHCPCD_DAEMONISED ||
!(options->options & DHCPCD_DAEMONISE))
return 0;
sigfillset(&full);
sigprocmask(SIG_SETMASK, &full, &old);
@ -202,13 +207,21 @@ daemonise(int *pidfd)
/* Done with the fd now */
if (pid != 0) {
writepid(*pidfd, pid);
close(*pidfd);
*pidfd = -1;
writepid(*state->pidfd, pid);
close(*state->pidfd);
*state->pidfd = -1;
}
sigprocmask(SIG_SETMASK, &old, NULL);
return pid;
state->state = STATE_BOUND;
if (pid == 0) {
state->options |= DHCPCD_DAEMONISED;
return 0;
}
state->options |= DHCPCD_PERSISTENT | DHCPCD_FORKED;
return -1;
}
@ -316,7 +329,7 @@ static void
get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp)
{
lease->addr.s_addr = dhcp->yiaddr;
if (get_option_addr(&lease->net.s_addr, dhcp, DHCP_NETMASK) == -1)
if (get_option_addr(&lease->net.s_addr, dhcp, DHCP_SUBNETMASK) == -1)
lease->net.s_addr = get_netmask(dhcp->yiaddr);
if (get_option_uint32(&lease->leasetime, dhcp, DHCP_LEASETIME) != 0)
lease->leasetime = DEFAULT_LEASETIME;
@ -372,7 +385,8 @@ get_old_lease(struct if_state *state, const struct options *options)
/* Ok, lets use this */
if (IN_LINKLOCAL(dhcp->yiaddr)) {
free(state->dhcp);
free(state->old_dhcp);
state->old_dhcp = state->dhcp;
state->dhcp = dhcp;
return 0;
}
@ -399,7 +413,8 @@ get_old_lease(struct if_state *state, const struct options *options)
offset = 0;
state->timeout = lease->renewaltime - offset;
iface->start_uptime = uptime();
free(state->dhcp);
free(state->old_dhcp);
state->old_dhcp = state->dhcp;
state->dhcp = dhcp;
return 0;
}
@ -611,11 +626,14 @@ send_message(struct if_state *state, int type, const struct options *options)
}
static void
drop_config(struct if_state *state, const struct options *options)
drop_config(struct if_state *state, const char *reason, const struct options *options)
{
if (!(state->options & DHCPCD_PERSISTENT))
configure(state->interface, state->dhcp,
&state->lease, options, 0);
configure(state->interface, reason, NULL, state->dhcp,
&state->lease, options, 0);
free(state->old_dhcp);
state->old_dhcp = NULL;
free(state->dhcp);
state->dhcp = NULL;
state->lease.addr.s_addr = 0;
}
@ -715,9 +733,11 @@ handle_signal(int sig, struct if_state *state, const struct options *options)
switch (sig) {
case SIGINT:
logger(LOG_INFO, "received SIGINT, stopping");
drop_config(state, "STOP", options);
return -1;
case SIGTERM:
logger(LOG_INFO, "received SIGTERM, stopping");
drop_config(state, "STOP", options);
return -1;
case SIGALRM:
@ -750,13 +770,13 @@ handle_signal(int sig, struct if_state *state, const struct options *options)
logger (LOG_INFO, "received SIGHUP, releasing lease");
if (!IN_LINKLOCAL(ntohl(lease->addr.s_addr))) {
do_socket(state, SOCKET_OPEN);
state->xid = (uint32_t)random();
send_message(state, DHCP_RELEASE, options);
do_socket(state, SOCKET_CLOSED);
}
unlink(state->interface->infofile);
return -1;
do_socket(state, SOCKET_OPEN);
state->xid = (uint32_t)random();
send_message(state, DHCP_RELEASE, options);
do_socket(state, SOCKET_CLOSED);
}
drop_config(state, "RELEASE", options);
return -1;
default:
logger (LOG_ERR,
@ -772,96 +792,80 @@ handle_timeout(struct if_state *state, const struct options *options)
{
struct dhcp_lease *lease = &state->lease;
struct interface *iface = state->interface;
int gotlease = -1;
char *reason = NULL;
/* No NAK, so reset the backoff */
state->nakoff = 1;
if (state->state == STATE_INIT && state->xid != 0) {
if (iface->addr.s_addr != 0 &&
!IN_LINKLOCAL(ntohl(iface->addr.s_addr)) &&
!(state->options & DHCPCD_INFORM))
{
logger(LOG_ERR, "lost lease");
if (!(state->options & DHCPCD_PERSISTENT))
drop_config(state, options);
} else if (!IN_LINKLOCAL(ntohl(iface->addr.s_addr)))
logger(LOG_ERR, "timed out");
if (!IN_LINKLOCAL(ntohl(iface->addr.s_addr))) {
if (iface->addr.s_addr != 0 &&
!(state->options & DHCPCD_INFORM))
logger(LOG_ERR, "lost lease");
else
logger(LOG_ERR, "timed out");
}
do_socket(state, SOCKET_CLOSED);
if (options->options & DHCPCD_INFORM)
return -1;
if (!(state->options & DHCPCD_TEST) &&
(state->options & DHCPCD_IPV4LL ||
state->options & DHCPCD_LASTLEASE))
if (state->options & DHCPCD_IPV4LL ||
state->options & DHCPCD_LASTLEASE)
{
errno = 0;
if (get_old_lease(state, options) != 0) {
if (errno == EINTR)
return 0;
if (state->options & DHCPCD_LASTLEASE)
return -1;
gotlease = get_old_lease(state, options);
if (gotlease == 0) {
if (!(state->options & DHCPCD_DAEMONISED))
reason = "REBOOT";
} else if (errno == EINTR)
return 0;
}
#ifdef ENABLE_IPV4LL
if (!(state->options & DHCPCD_TEST) &&
state->options & DHCPCD_IPV4LL &&
(!lease->addr.s_addr ||
(!IN_LINKLOCAL(ntohl(lease->addr.s_addr)) &&
!(state->options & DHCPCD_LASTLEASE))))
{
if (state->options & DHCPCD_IPV4LL && gotlease != -1) {
logger(LOG_INFO, "probing for an IPV4LL address");
if (ipv4ll_get_address(iface, lease) == -1) {
if (!(state->options & DHCPCD_DAEMONISED))
return -1;
/* start over */
state->xid = 0;
return 0;
}
state->timeout = lease->renewaltime;
if (!state->dhcp)
errno = 0;
gotlease = ipv4ll_get_address(iface, lease);
if (gotlease != 0) {
if (errno == EINTR)
return 0;
} else {
free(state->old_dhcp);
state->old_dhcp = state->dhcp;
state->dhcp = xmalloc(sizeof(*state->dhcp));
memset(state->dhcp, 0, sizeof(*state->dhcp));
state->dhcp->yiaddr = lease->addr.s_addr;
state->dhcp->options[0] = DHCP_END;
memset(state->dhcp, 0, sizeof(*state->dhcp));
state->dhcp->yiaddr = lease->addr.s_addr;
state->dhcp->options[0] = DHCP_END;
reason = "IPV4LL";
}
}
#endif
if (lease->addr.s_addr) {
if (!(state->options & DHCPCD_DAEMONISED) &&
IN_LINKLOCAL(ntohl(lease->addr.s_addr)))
logger(LOG_WARNING, "using IPV4LL address %s",
inet_ntoa(lease->addr));
if (configure(iface, state->dhcp, lease, options, 1) != 0 &&
!(state->options & DHCPCD_DAEMONISED))
return -1;
state->state = STATE_BOUND;
if (!(state->options & DHCPCD_DAEMONISED) &&
options->options & DHCPCD_DAEMONISE) {
switch (daemonise(state->pidfd)) {
case -1:
return -1;
case 0:
state->options |= DHCPCD_DAEMONISED;
return 0;
default:
state->options |= DHCPCD_PERSISTENT | DHCPCD_FORKED;
return -1;
}
}
state->timeout = lease->renewaltime;
state->xid = 0;
return 0;
if (gotlease != 0) {
if (state->dhcp && !IN_LINKLOCAL(state->dhcp->yiaddr))
reason = "EXPIRE";
if (!reason)
reason = "FAIL";
drop_config(state, reason, options);
if (!(state->options & DHCPCD_DAEMONISED))
return -1;
}
if (!(state->options & DHCPCD_DAEMONISED))
return -1;
if (!(state->options & DHCPCD_DAEMONISED) &&
IN_LINKLOCAL(ntohl(lease->addr.s_addr)))
logger(LOG_WARNING, "using IPV4LL address %s",
inet_ntoa(lease->addr));
if (!reason)
reason = "TIMEOUT";
if (configure(iface, reason,
state->dhcp, state->old_dhcp,
lease, options, 1) == 0)
daemonise(state, options);
state->timeout = lease->renewaltime;
state->xid = 0;
return 0;
}
switch (state->state) {
@ -942,6 +946,7 @@ handle_dhcp(struct if_state *state, struct dhcp_message **dhcpp, const struct op
uint8_t type;
struct timeval tv;
int r;
const char *reason = NULL;
if (get_option_uint8(&type, dhcp, DHCP_MESSAGETYPE) == -1) {
logger(LOG_ERR, "no DHCP type in message");
@ -991,9 +996,9 @@ handle_dhcp(struct if_state *state, struct dhcp_message **dhcpp, const struct op
logger(LOG_INFO, "offered %s", addr);
free(addr);
if (options->options & DHCPCD_TEST) {
write_info(iface, dhcp, lease, options, 0);
errno = 0;
if (state->options & DHCPCD_TEST) {
exec_script(options->script, iface->name,
"TEST", dhcp, NULL);
return -1;
}
@ -1061,11 +1066,11 @@ handle_dhcp(struct if_state *state, struct dhcp_message **dhcpp, const struct op
}
#endif
if (state->dhcp)
free(state->dhcp);
free(state->old_dhcp);
state->old_dhcp = state->dhcp;
state->dhcp = dhcp;
*dhcpp = NULL;
if (options->options & DHCPCD_INFORM) {
if (options->request_address.s_addr != 0)
lease->addr.s_addr = options->request_address.s_addr;
@ -1078,6 +1083,7 @@ handle_dhcp(struct if_state *state, struct dhcp_message **dhcpp, const struct op
if (state->timeout == 0)
state->timeout = DEFAULT_LEASETIME;
state->state = STATE_INIT;
reason = "INFORM";
} else {
if (gettimeofday(&tv, NULL) == 0)
lease->leasedfrom = tv.tv_sec;
@ -1135,25 +1141,21 @@ handle_dhcp(struct if_state *state, struct dhcp_message **dhcpp, const struct op
}
state->xid = 0;
if (configure(iface, dhcp, &state->lease, options, 1) != 0)
if (!reason) {
if (state->old_dhcp) {
if (state->old_dhcp->yiaddr == dhcp->yiaddr &&
lease->server.s_addr)
reason = "RENEW";
else
reason = "REBIND";
} else
reason = "BOUND";
}
r = configure(iface, reason, dhcp, state->old_dhcp,
&state->lease, options, 1);
if (r != 0)
return -1;
if (!(state->options & DHCPCD_DAEMONISED) &&
state->options & DHCPCD_DAEMONISE)
{
switch (daemonise(state->pidfd)) {
case 0:
state->options |= DHCPCD_DAEMONISED;
return 0;
case -1:
return -1;
default:
state->options |= DHCPCD_PERSISTENT | DHCPCD_FORKED;
return -1;
}
}
return 0;
return daemonise(state, options);
}
static int
@ -1261,7 +1263,6 @@ dhcp_run(const struct options *options, int *pidfd)
eexit:
if (iface) {
do_socket(state, SOCKET_CLOSED);
drop_config(state, options);
free_routes(iface->routes);
free(iface->clientid);
free(iface);
@ -1274,6 +1275,7 @@ eexit:
unlink(options->pidfile);
free(state->buffer);
free(state->dhcp);
free(state->old_dhcp);
free(state);
}

View File

@ -64,7 +64,6 @@
# define DBDIR "/var/db"
#endif
#define LEASEFILE DBDIR "/" PACKAGE "-%s.lease"
#define INFOFILE DBDIR "/" PACKAGE "-%s.info"
#define DUIDFILE DBDIR "/" PACKAGE ".duid"
#endif

View File

@ -45,10 +45,11 @@
#include "net.h"
#include "signal.h"
static int
exec_script(const char *cmd, const char *arg1, const char *arg2)
int
exec_script(const char *script, const char *iface, const char *reason,
const struct dhcp_message *dhcpn, const struct dhcp_message *dhcpo)
{
char *const argv[4] = { (char *)cmd, (char *)arg1, (char *)arg2, NULL};
char *const argv[2] = { (char *)script, NULL };
int ret = 0;
pid_t pid;
pid_t wpid;
@ -56,7 +57,7 @@ exec_script(const char *cmd, const char *arg1, const char *arg2)
sigset_t full;
sigset_t old;
logger(LOG_DEBUG, "exec `%s' `%s' `%s'", cmd, arg1, arg2);
logger(LOG_DEBUG, "exec `%s'", script);
/* OK, we need to block signals */
sigfillset(&full);
@ -79,8 +80,14 @@ exec_script(const char *cmd, const char *arg1, const char *arg2)
signal_reset();
#endif
sigprocmask(SIG_SETMASK, &old, NULL);
execvp(cmd, argv);
logger(LOG_ERR, "%s: %s", cmd, strerror(errno));
if (dhcpo)
configure_env("old", dhcpo);
if (dhcpn)
configure_env("new", dhcpn);
setenv("interface", iface, 1);
setenv("reason", reason, 1);
execvp(script, argv);
logger(LOG_ERR, "%s: %s", script, strerror(errno));
_exit(111);
/* NOTREACHED */
}
@ -99,6 +106,8 @@ exec_script(const char *cmd, const char *arg1, const char *arg2)
logger(LOG_ERR, "waitpid: %s", strerror(errno));
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
if (WIFSIGNALED(status))
logger(LOG_ERR, "script signaled");
if (WIFEXITED(status))
ret = WEXITSTATUS(status);
else
@ -336,116 +345,9 @@ configure_routes(struct interface *iface, const struct dhcp_message *dhcp,
return retval;
}
static void
print_clean(FILE *f, const char *name, const char *value)
{
fprintf(f, "%s=", name);
if (value)
write_string(f, (const uint8_t*)value, strlen(value));
fputc('\n', f);
}
int
write_info(const struct interface *iface, const struct dhcp_message *dhcp,
const struct dhcp_lease *lease, const struct options *options,
int overwrite)
{
FILE *f;
struct rt *rt, *ort;
struct stat sb;
struct in_addr addr;
int doneone;
if (options->options & DHCPCD_TEST)
f = stdout;
else {
if (!overwrite && stat(iface->infofile, &sb) == 0)
return 0;
if ((f = fopen(iface->infofile, "w")) == NULL)
return -1;
}
if (dhcp->yiaddr) {
fprintf(f, "IPADDR=%s\n", inet_ntoa(iface->addr));
fprintf(f, "NETMASK=%s\n", inet_ntoa(iface->net));
addr.s_addr = dhcp->yiaddr & iface->net.s_addr;
fprintf(f, "NETWORK=%s\n", inet_ntoa(addr));
if (get_option_addr(&addr.s_addr, dhcp, DHCP_BROADCAST) == -1)
addr.s_addr = dhcp->yiaddr | ~iface->net.s_addr;
fprintf(f, "BROADCAST=%s\n", inet_ntoa(addr));
ort = get_option_routes(dhcp);
doneone = 0;
fprintf(f, "ROUTES=");
for (rt = ort; rt; rt = rt->next) {
if (rt->dest.s_addr == 0)
continue;
if (doneone)
fprintf(f, "\\ ");
else
doneone = 1;
fprintf(f, "%s", inet_ntoa(rt->dest));
fprintf(f, ",%s", inet_ntoa(rt->net));
fprintf(f, ",%s", inet_ntoa(rt->gate));
}
fputc('\n', f);
doneone = 0;
fprintf(f, "GATEWAYS=");
for (rt = ort; rt; rt = rt->next) {
if (rt->dest.s_addr != 0)
continue;
if (doneone)
fprintf(f, "\\ ");
else
doneone = 1;
fprintf(f, "%s", inet_ntoa(rt->gate));
}
fputc('\n', f);
free_routes(ort);
}
write_options(f, dhcp);
/* FIXME
if (dhcp->fqdn) {
fprintf(f, "FQDNFLAGS='%u'\n", dhcp->fqdn->flags);
fprintf(f, "FQDNRCODE1='%u'\n", dhcp->fqdn->r1);
fprintf(f, "FQDNRCODE2='%u'\n", dhcp->fqdn->r2);
print_clean(f, "FQDNHOSTNAME", dhcp->fqdn->name);
}
*/
if (dhcp->siaddr) {
addr.s_addr = dhcp->siaddr;
fprintf(f, "DHCPSID=%s\n", inet_ntoa(addr));
}
if (dhcp->servername[0])
print_clean(f, "DHCPSNAME", (const char *)dhcp->servername);
if (!(options->options & DHCPCD_INFORM) && dhcp->yiaddr) {
if (!(options->options & DHCPCD_TEST))
fprintf(f, "LEASEDFROM=%u\n", lease->leasedfrom);
fprintf(f, "LEASETIME=%u\n", lease->leasetime);
fprintf(f, "RENEWALTIME=%u\n", lease->renewaltime);
fprintf(f, "REBINDTIME=%u\n", lease->rebindtime);
}
print_clean(f, "INTERFACE", iface->name);
print_clean(f, "CLASSID", options->classid);
if (iface->clientid_len > 0) {
fprintf(f, "CLIENTID=%s\n",
hwaddr_ntoa(iface->clientid, iface->clientid_len));
}
fprintf(f, "DHCPCHADDR=%s\n",
hwaddr_ntoa(iface->hwaddr, iface->hwlen));
if (!(options->options & DHCPCD_TEST))
fclose(f);
return 0;
}
int
configure(struct interface *iface, const struct dhcp_message *dhcp,
configure(struct interface *iface, const char *reason,
const struct dhcp_message *dhcp, const struct dhcp_message *old,
const struct dhcp_lease *lease, const struct options *options,
int up)
{
@ -463,7 +365,7 @@ configure(struct interface *iface, const struct dhcp_message *dhcp,
else {
addr.s_addr = dhcp->yiaddr;
/* Ensure we have all the needed values */
if (get_option_addr(&net.s_addr, dhcp, DHCP_NETMASK) == -1)
if (get_option_addr(&net.s_addr, dhcp, DHCP_SUBNETMASK) == -1)
net.s_addr = get_netmask(addr.s_addr);
if (get_option_addr(&brd.s_addr, dhcp, DHCP_BROADCAST) == -1)
brd.s_addr = addr.s_addr | ~net.s_addr;
@ -471,13 +373,6 @@ configure(struct interface *iface, const struct dhcp_message *dhcp,
/* If we aren't up, then reset the interface as much as we can */
if (!up) {
/* If we haven't created an info file, do so now */
if (!lease->frominfo) {
if (write_info(iface, dhcp, lease, options, 0) == -1)
logger(LOG_ERR, "write_info: %s",
strerror(errno));
}
/* Only reset things if we had set them before */
if (iface->addr.s_addr != 0) {
if (!(options->options & DHCPCD_KEEPADDRESS)) {
@ -495,7 +390,7 @@ configure(struct interface *iface, const struct dhcp_message *dhcp,
}
}
exec_script(options->script, iface->infofile, "down");
exec_script(options->script, iface->name, reason, NULL, old);
return 0;
}
@ -537,10 +432,9 @@ configure(struct interface *iface, const struct dhcp_message *dhcp,
iface->net.s_addr = net.s_addr;
if (!lease->frominfo)
write_info(iface, dhcp, lease, options, 1);
if (write_lease(iface, dhcp) == -1)
logger(LOG_ERR, "write_lease: %s", strerror(errno));
exec_script(options->script, iface->infofile, up ? "new" : "up");
exec_script(options->script, iface->name, reason, dhcp, old);
return 0;
}

View File

@ -32,9 +32,10 @@
#include "dhcp.h"
#include "net.h"
int write_info(const struct interface *, const struct dhcp_message *,
const struct dhcp_lease *, const struct options *, int);
int configure(struct interface *, const struct dhcp_message *,
const struct dhcp_lease *, const struct options *, int);
int exec_script(const char *, const char *, const char *,
const struct dhcp_message *, const struct dhcp_message *);
int configure(struct interface *, const char *,
const struct dhcp_message *, const struct dhcp_message *,
const struct dhcp_lease *, const struct options *, int);
#endif

431
dhcp.c
View File

@ -39,12 +39,16 @@
#define REQUEST (1 << 0)
#define UINT8 (1 << 1)
#define UINT16 (1 << 2)
#define UINT32 (1 << 3)
#define IPV4 (1 << 4)
#define STRING (1 << 5)
#define ARRAY (1 << 6)
#define RFC3361 (1 << 7)
#define RFC3397 (1 << 8)
#define SINT16 (1 << 3)
#define UINT32 (1 << 4)
#define SINT32 (1 << 5)
#define IPV4 (1 << 6)
#define STRING (1 << 7)
#define PAIR (1 << 8)
#define ARRAY (1 << 9)
#define RFC3361 (1 << 10)
#define RFC3397 (1 << 11)
#define RFC3442 (1 << 12)
#define IPV4R IPV4 | REQUEST
@ -55,80 +59,93 @@ struct dhcp_option {
};
const struct dhcp_option dhcp_options[] = {
{ DHCP_NETMASK, IPV4R, NULL },
{ DHCP_TIMEOFFSET, UINT32, "TIMEOFFSET" },
{ DHCP_ROUTER, IPV4R, NULL },
{ DHCP_TIMESERVER, IPV4, "TIMESERVER" },
{ DHCP_NAMESERVER, IPV4, "NAMESERVER" },
{ DHCP_DNSSERVER, IPV4, "DNSSERVER" },
{ DHCP_LOGSERVER, IPV4, "LOGSERVER" },
{ DHCP_COOKIESERVER, IPV4, "COOKIESERVER" },
{ DHCP_LPRSERVER, IPV4, "LPRSERVER" },
{ DHCP_IMPRESSSERVER, IPV4, "IMPRESSSERVER" },
{ DHCP_RESOURCELOCATIONSERVER, IPV4, "RESOURCELOCATIONSERVER" },
{ DHCP_HOSTNAME, STRING, "HOSTNAME" },
{ DHCP_BOOTFILESIZE, UINT16, "BOOTFILESIZE" },
{ DHCP_MERITDUMPFILE, STRING, "MERITDUMPFILE" },
{ DHCP_DNSDOMAIN, STRING, "DNSDOMAIN" },
{ DHCP_SWAPSERVER, IPV4, "SWAPSERVER" },
{ DHCP_ROOTPATH, STRING, "ROOTPATH" },
{ DHCP_EXTENSIONSPATH, STRING, "EXTENSIONSPATH" },
{ DHCP_IPFORWARDING, UINT8, "IPFORWARDING" },
{ DHCP_NONLOCALSOURCEROUTING, UINT8, "NONLOCALSOURCEROUTING" },
{ DHCP_POLICYFILTER, IPV4, "POLICYFILTER" },
{ DHCP_MAXDGRAMSIZE, UINT16, "MAXDGRAMSIZE" },
{ DHCP_DEFAULTIPTTL, UINT16, "DEFAULTIPTTL" },
{ DHCP_PATHMTUAGINGTIMEOUT, UINT32, "PATHMTUAGINGTIMEOUT" },
{ DHCP_PATHMTUPLATEAUTABLE, UINT16 | ARRAY, "PATHMTUPLATEAUTABLE" },
{ DHCP_MTU, UINT16, "MTU" },
{ DHCP_ALLSUBNETSLOCAL, UINT8, "ALLSUBNETSLOCAL" },
{ DHCP_BROADCAST, IPV4R, NULL },
{ DHCP_MASKDISCOVERY, UINT8, "MASKDISCOVERY" },
{ DHCP_MASKSUPPLIER, UINT8, "MASKSUPPLIER" },
{ DHCP_ROUTERDISCOVERY, UINT8, "ROUTERDISCOVERY" },
{ DHCP_ROUTERSOLICITATIONADDR, UINT8, "ROUTERSOLICITATIONADDR" },
{ DHCP_STATICROUTE, IPV4R, NULL },
{ DHCP_TRAILERENCAPSULATION, UINT8, "TRAILERENCAPSULATION" },
{ DHCP_ARPCACHETIMEOUT, UINT32, "ARPCACHETIMEOUT" },
{ DHCP_ETHERNETENCAPSULATION, UINT8, "ETHERNETENCAPSULATION" },
{ DHCP_TCPDEFAULTTTL, UINT8, "TCPDEFAULTTTL" },
{ DHCP_TCPKEEPALIVEINTERVAL, UINT32, "TCPKEEPALIVEINTERVAL" },
{ DHCP_TCPKEEPALIVEGARBAGE, UINT8, "TCPKEEPALIVEGARBAGE" },
{ DHCP_NISDOMAIN, IPV4, "NISDOMAIN" },
{ DHCP_NISSERVER, IPV4, "NISSERVER" },
{ DHCP_NTPSERVER, IPV4, "NTPSERVER" },
{ DHCP_VENDORSPECIFICINFO, STRING, "VENDORSPECIFICINFO" },
{ DHCP_NETBIOSNAMESERVER, IPV4, "NETBIOSNAMESERVER" },
{ DHCP_NETBIOSDGRAMSERVER, IPV4, "NETBIOSDGRAMSERVER" },
{ DHCP_NETBIOSNODETYPE, UINT8, "NETBIOSNODETYPE" },
{ DHCP_NETBIOSSCOPE, STRING, "NETBIOSSCOPE" },
{ DHCP_XFONTSERVER, IPV4, "XFONTSERVER" },
{ DHCP_XDISPLAYMANAGER, IPV4, "XDISPLAYMANAGER" },
{ DHCP_NISPLUSDOMAIN, IPV4, "NISPLUSDOMAIN" },
{ DHCP_NISPLUSSERVER, IPV4, "NISPLUSSERVER" },
{ DHCP_MOBILEIPHOMEAGENT, IPV4, "MOBILEIPHOMEAGENT" },
{ DHCP_SMTPSERVER, IPV4, "SMTPSERVER" },
{ DHCP_POP3SERVER, IPV4, "POP3SERVER" },
{ DHCP_NNTPSERVER, IPV4, "NNTPSERVER" },
{ DHCP_WWWSERVER, IPV4, "WWWSERVER" },
{ DHCP_FINGERSERVER, IPV4, "FINGERSERVER" },
{ DHCP_IRCSERVER, IPV4, "IRCSERVER" },
{ DHCP_STREETTALKSERVER, IPV4, "STREETTALKSERVER" },
{ DHCP_STREETTALKDASERVER, IPV4, "STREETTALKDASERVER" },
{ DHCP_LEASETIME, UINT32, NULL },
{ DHCP_SERVERID, IPV4, "SERVERID" },
{ DHCP_RENEWALTIME, UINT32 | REQUEST, NULL },
{ DHCP_REBINDTIME, UINT32 | REQUEST, NULL },
{ DHCP_MESSAGE, STRING, NULL},
{ DHCP_DNSSEARCH, STRING | RFC3397, "DNSSEARCH" },
{ DHCP_SIPSERVER, STRING | RFC3361, "SIPSERVER" },
{ 1, IPV4 | REQUEST, "subnet_mask" },
{ 2, UINT32, "time_offset" },
{ 3, IPV4 | ARRAY | REQUEST, "routers" },
{ 4, IPV4 | ARRAY, "time_servers" },
{ 5, IPV4 | ARRAY, "ien116_name_servers" },
{ 6, IPV4 | ARRAY, "domain_name_servers" },
{ 7, IPV4 | ARRAY, "log_servers" },
{ 8, IPV4 | ARRAY, "cookie_servers" },
{ 9, IPV4 | ARRAY, "lpr_servers" },
{ 10, IPV4 | ARRAY, "impress_servers" },
{ 11, IPV4 | ARRAY, "resource_location_servers" },
{ 12, STRING, "host_name" },
{ 13, UINT16, "boot_size" },
{ 14, STRING, "merit_dump" },
{ 15, STRING, "domain_name" },
{ 16, IPV4, "swap_server" },
{ 17, STRING, "root_path" },
{ 18, STRING, "extensions_path" },
{ 19, UINT8, "ip_forwarding" },
{ 20, UINT8, "non_local_source_routing" },
{ 21, IPV4 | ARRAY, "policy_filter" },
{ 22, SINT16, "max_dgram_reassembly" },
{ 23, UINT16, "default_ip_ttl" },
{ 24, UINT32, "path_mtu_aging_timeout" },
{ 25, UINT16 | ARRAY, "path_mtu_plateau_table" },
{ 26, UINT16, "interface_mtu" },
{ 27, UINT8, "all_subnets_local" },
{ 28, IPV4 | REQUEST, "broadcast_address" },
{ 29, UINT8, "perform_mask_discovery" },
{ 30, UINT8, "mask_supplier" },
{ 31, UINT8, "router_discovery" },
{ 32, IPV4, "router_solicitation_address" },
{ 33, IPV4 | ARRAY | REQUEST, "static_routes" },
{ 34, UINT8, "trailer_encapsulation" },
{ 35, UINT32, "arp_cache_timeout" },
{ 36, UINT16, "ieee802_3_encapsulation" },
{ 37, UINT8, "default_tcp_ttl" },
{ 38, UINT32, "tcp_keepalive_interval" },
{ 39, UINT8, "tcp_keepalive_garbage" },
{ 30, STRING, "nis_domain" },
{ 31, IPV4 | ARRAY, "nis_servers" },
{ 32, IPV4 | ARRAY, "ntp_servers" },
{ 43, STRING, "vendor_encapsulated_options" },
{ 44, IPV4 | ARRAY, "netbios_name_servers" },
{ 45, IPV4, "netbios_dd_server" },
{ 46, UINT8, "netbios_node_type" },
{ 47, STRING, "netbios_scope" },
{ 48, IPV4 | ARRAY, "font_servers" },
{ 49, IPV4 | ARRAY, "x_display_manager" },
{ 50, IPV4, "dhcp_requested_address" },
{ 51, UINT32 | REQUEST, "dhcp_lease_time" },
{ 52, UINT8, "dhcp_option_overload" },
{ 53, UINT8, "dhcp_message_type" },
{ 54, IPV4, "dhcp_server_identifier" },
{ 55, UINT8 | ARRAY, "dhcp_parameter_request_list" },
{ 56, STRING, "dhcp_message" },
{ 57, UINT16, "dhcp_max_message_size" },
{ 58, UINT32 | REQUEST, "dhcp_renewal_time" },
{ 59, UINT32 | REQUEST, "dhcp_rebinding_time" },
{ 64, STRING, "nisplus_domain" },
{ 65, IPV4 | ARRAY, "nisplus_servers" },
{ 66, STRING, "tftp_server_name" },
{ 67, STRING, "bootfile_name" },
{ 68, IPV4 | ARRAY, "mobile_ip_home_agent" },
{ 69, IPV4 | ARRAY, "smtp_server" },
{ 70, IPV4 | ARRAY, "pop_server" },
{ 71, IPV4 | ARRAY, "nntp_server" },
{ 72, IPV4 | ARRAY, "www_server" },
{ 73, IPV4 | ARRAY, "finger_server" },
{ 74, IPV4 | ARRAY, "irc_server" },
{ 75, IPV4 | ARRAY, "streettalk_server" },
{ 76, IPV4 | ARRAY, "streettalk_directory_assistance_server" },
{ 77, STRING, "user_class" },
{ 85, IPV4 | ARRAY, "nds_servers" },
{ 86, STRING, "nds_tree_name" },
{ 87, STRING, "nds_context" },
{ 88, STRING | RFC3397, "bcms_controller_names" },
{ 89, IPV4 | ARRAY, "bcms_controller_address" },
{ 91, UINT32, "client_last_transaction_time" },
{ 92, IPV4 | ARRAY, "associated_ip" },
{ 98, STRING, "uap_servers" },
{ 112, IPV4 | ARRAY, "netinfo_server_address" },
{ 113, STRING, "netinfo_server_tag" },
{ 114, STRING, "default_url" },
{ 118, IPV4, "subnet_selection" },
{ 119, STRING | RFC3397, "domain_search" },
{ 121, RFC3442, "classless_static_routes" },
{ 0, 0, NULL }
};
@ -693,7 +710,7 @@ make_message(struct dhcp_message **message,
lease->addr.s_addr != iface->addr.s_addr &&
!IN_LINKLOCAL(ntohl(lease->addr.s_addr)))
{
PUTADDR(DHCP_ADDRESS, lease->addr);
PUTADDR(DHCP_IPADDRESS, lease->addr);
if (lease->server.s_addr)
PUTADDR(DHCP_SERVERID, lease->server);
}
@ -832,19 +849,29 @@ read_lease(const struct interface *iface)
}
ssize_t
write_string(FILE *f, const uint8_t *data, ssize_t len)
print_string(char *s, const uint8_t *data, ssize_t len)
{
uint8_t c;
const uint8_t *e;
ssize_t bytes = 0;
ssize_t r;
if (!len)
len = *data++;
e = data + len;
c = *data++;
e = data + c;
while (data < e) {
c = *data++;
if (!isascii(c) || !isprint(c)) {
bytes += fprintf(f, "\\%03o", c);
if (s) {
if (len < 5) {
errno = ENOBUFS;
return -1;
}
r = snprintf(s, len, "\\%03o", c);
len -= r;
bytes += r;
s += r;
} else
bytes += 4;
continue;
}
switch (c) {
@ -853,88 +880,184 @@ write_string(FILE *f, const uint8_t *data, ssize_t len)
case '$': /* FALLTHROUGH */
case '`': /* FALLTHROUGH */
case '\\': /* FALLTHROUGH */
case ' ': /* FALLTHROUGH */
if (fputc('\\', f))
bytes++;
if (s) {
if (len < 3) {
errno = ENOBUFS;
return -1;
}
*s++ = '\\';
len--;
}
bytes++;
break;
}
if (fputc(c, f))
bytes++;
if (s) {
*s++ = c;
len--;
}
bytes++;
}
/* NULL */
if (s)
*s = '\0';
bytes++;
return bytes;
}
ssize_t
write_options(FILE *f, const struct dhcp_message *dhcp)
static ssize_t
print_option(char *s, int type, const uint8_t *data, ssize_t len)
{
uint8_t i;
const uint8_t *e, *t;
uint8_t u8;
uint16_t u16;
int16_t s16;
uint32_t u32;
int32_t s32;
struct in_addr addr;
ssize_t bytes = 0;
ssize_t l;
if (!type || type & STRING)
return print_string(s, data, len);
if (!s) {
if (type & UINT8)
l = 3;
else if (type & UINT16)
l = 5;
else if (type & SINT16)
l = 6;
else if (type & UINT32)
l = 10;
else if (type & SINT32)
l = 11;
else if (type & IPV4)
l = 16;
else {
errno = EINVAL;
return -1;
}
return (l + 1) * *data;
}
l = *data++;
t = data;
e = data + l;
while (data < e) {
if (data != t) {
*s++ = ' ';
bytes++;
len--;
}
if (type & UINT8) {
l = snprintf(s, len, "%d", *data);
data++;
} else if (type & UINT16) {
memcpy(&u16, data, sizeof(u16));
u16 = ntohs(u16);
l = snprintf(s, len, "%d", u16);
data += sizeof(u16);
} else if (type & SINT16) {
memcpy(&s16, data, sizeof(s16));
s16 = ntohs(s16);
l = snprintf(s, len, "%d", s16);
data += sizeof(s16);
} else if (type & UINT32) {
memcpy(&u32, data, sizeof(u32));
u32 = ntohl(u32);
l = snprintf(s, len, "%d", u32);
data += sizeof(u32);
} else if (type & SINT32) {
memcpy(&s32, data, sizeof(s32));
s32 = ntohl(s32);
l = snprintf(s, len, "%d", s32);
data += sizeof(s32);
} else if (type & IPV4) {
memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
l = snprintf(s, len, "%s", inet_ntoa(addr));
data += sizeof(addr.s_addr);
}
len -= l;
bytes += l;
s += l;
}
return bytes;
}
static int
_setenv(const char *prefix, const char *var, const char *value)
{
size_t len = strlen(prefix) + strlen(var) + 3;
char *name = xmalloc(len);
int r;
snprintf(name, len, "%s_%s", prefix, var);
if (value)
r = setenv(name, value, 1);
else
r = unsetenv(name);
free(name);
return r;
}
int
configure_env(const char *prefix, const struct dhcp_message *dhcp)
{
int i;
const uint8_t *p, *e, *t;
uint32_t u32;
uint16_t u16;
uint8_t u8;
struct in_addr addr;
ssize_t retval = 0;
struct in_addr net;
struct in_addr brd;
char *val;
const struct dhcp_option *opt;
ssize_t len;
char cidr[4];
if (dhcp->yiaddr) {
/* Set some useful variables that we drive from the DHCP
* message but are not necessarily in the options */
addr.s_addr = dhcp->yiaddr;
_setenv(prefix, "ip_address", inet_ntoa(addr));
if (get_option_addr(&net.s_addr, dhcp, DHCP_SUBNETMASK) == -1) {
net.s_addr = get_netmask(addr.s_addr);
_setenv(prefix, "subnet_mask", inet_ntoa(net));
}
i = inet_ntocidr(net);
snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net));
_setenv(prefix, "subnet_cidr", cidr);
if (get_option_addr(&brd.s_addr, dhcp, DHCP_BROADCAST) == -1) {
brd.s_addr = addr.s_addr | ~net.s_addr;
_setenv(prefix, "broadcast_address", inet_ntoa(net));
}
addr.s_addr = dhcp->yiaddr & net.s_addr;
_setenv(prefix, "network_address", inet_ntoa(addr));
} else {
_setenv(prefix, "ip_address", NULL);
_setenv(prefix, "subnet_cidr", NULL);
_setenv(prefix, "network_address", NULL);
}
for (i = 0; i < sizeof(dhcp_options) / sizeof(dhcp_options[0]); i++) {
if (!dhcp_options[i].var)
opt = &dhcp_options[i];
if (!opt->var)
continue;
retval += fprintf(f, "%s=", dhcp_options[i].var);
/* Unknown type, so just print escape codes */
if (dhcp_options[i].type == STRING) {
p = get_option(dhcp, dhcp_options[i].option);
if (p)
retval += write_string(f, p, 0);
val = NULL;
p = get_option(dhcp, opt->option);
if (p) {
len = print_option(NULL, opt->type, p, 0);
if (len < 0)
return -1;
val = xmalloc(len);
print_option(val, opt->type, p, len);
}
if ((dhcp_options[i].type & IPV4 ||
dhcp_options[i].type & ARRAY) &&
(p = get_option(dhcp, dhcp_options[i].option)))
{
u8 = *p++;
t = p;
e = p + u8;
while (p < e) {
if (p != t)
retval += fprintf(f, "\\ ");
if (dhcp_options[i].type & UINT8) {
retval += fprintf(f, "%d", *p);
p++;
} else if (dhcp_options[i].type & UINT16) {
memcpy(&u16, p, sizeof(u16));
u16 = ntohs(u16);
retval += fprintf(f, "%d", *p);
p += sizeof(u16);
} else if (dhcp_options[i].type & UINT32) {
memcpy(&u32, p, sizeof(u32));
u32 = ntohl(u32);
retval += fprintf(f, "%d", *p);
p += sizeof(u32);
} else if (dhcp_options[i].type & IPV4) {
memcpy(&addr.s_addr, p,
sizeof(addr.s_addr));
retval += fprintf(f, "%s",
inet_ntoa(addr));
p += sizeof(addr.s_addr);
} else
/* Sanity check */
p = e;
}
}
if (dhcp_options[i].type & UINT32) {
if (get_option_uint32(&u32, dhcp,
dhcp_options[i].option) == 0)
retval += fprintf(f, "%d", u32);
}
if (dhcp_options[i].type & UINT16) {
if (get_option_uint16(&u16, dhcp,
dhcp_options[i].option) == 0)
retval += fprintf(f, "%d", u16);
}
retval += fprintf(f, "\n");
_setenv(prefix, opt->var, val);
free(val);
}
return retval;
return 0;
}

60
dhcp.h
View File

@ -65,56 +65,17 @@
enum DHCP_OPTIONS
{
DHCP_PAD = 0,
DHCP_NETMASK = 1,
DHCP_TIMEOFFSET = 2,
DHCP_SUBNETMASK = 1,
DHCP_ROUTER = 3,
DHCP_TIMESERVER = 4,
DHCP_NAMESERVER = 5,
DHCP_DNSSERVER = 6,
DHCP_LOGSERVER = 7,
DHCP_COOKIESERVER = 8,
DHCP_LPRSERVER = 9,
DHCP_IMPRESSSERVER = 10,
DHCP_RESOURCELOCATIONSERVER = 11,
DHCP_HOSTNAME = 12,
DHCP_BOOTFILESIZE = 13,
DHCP_MERITDUMPFILE = 14,
DHCP_DNSDOMAIN = 15,
DHCP_SWAPSERVER = 16,
DHCP_ROOTPATH = 17,
DHCP_EXTENSIONSPATH = 18,
DHCP_IPFORWARDING = 19,
DHCP_NONLOCALSOURCEROUTING = 20,
DHCP_POLICYFILTER = 21,
DHCP_MAXDGRAMSIZE = 22,
DHCP_DEFAULTIPTTL = 23,
DHCP_PATHMTUAGINGTIMEOUT = 24,
DHCP_PATHMTUPLATEAUTABLE = 25,
DHCP_MTU = 26,
DHCP_ALLSUBNETSLOCAL = 27,
DHCP_BROADCAST = 28,
DHCP_MASKDISCOVERY = 29,
DHCP_MASKSUPPLIER = 30,
DHCP_ROUTERDISCOVERY = 31,
DHCP_ROUTERSOLICITATIONADDR = 32,
DHCP_STATICROUTE = 33,
DHCP_TRAILERENCAPSULATION = 34,
DHCP_ARPCACHETIMEOUT = 35,
DHCP_ETHERNETENCAPSULATION = 36,
DHCP_TCPDEFAULTTTL = 37,
DHCP_TCPKEEPALIVEINTERVAL = 38,
DHCP_TCPKEEPALIVEGARBAGE = 39,
DHCP_NISDOMAIN = 40,
DHCP_NISSERVER = 41,
DHCP_NTPSERVER = 42,
DHCP_VENDORSPECIFICINFO = 43,
DHCP_NETBIOSNAMESERVER = 44,
DHCP_NETBIOSDGRAMSERVER = 45,
DHCP_NETBIOSNODETYPE = 46,
DHCP_NETBIOSSCOPE = 47,
DHCP_XFONTSERVER = 48,
DHCP_XDISPLAYMANAGER = 49,
DHCP_ADDRESS = 50,
DHCP_IPADDRESS = 50,
DHCP_LEASETIME = 51,
DHCP_OPTIONSOVERLOADED = 52,
DHCP_MESSAGETYPE = 53,
@ -126,21 +87,9 @@ enum DHCP_OPTIONS
DHCP_REBINDTIME = 59,
DHCP_CLASSID = 60,
DHCP_CLIENTID = 61,
DHCP_NISPLUSDOMAIN = 64,
DHCP_NISPLUSSERVER = 65,
DHCP_MOBILEIPHOMEAGENT = 68,
DHCP_SMTPSERVER = 69,
DHCP_POP3SERVER = 70,
DHCP_NNTPSERVER = 71,
DHCP_WWWSERVER = 72,
DHCP_FINGERSERVER = 73,
DHCP_IRCSERVER = 74,
DHCP_STREETTALKSERVER = 75,
DHCP_STREETTALKDASERVER = 76,
DHCP_USERCLASS = 77, /* RFC 3004 */
DHCP_FQDN = 81,
DHCP_DNSSEARCH = 119, /* RFC 3397 */
DHCP_SIPSERVER = 120, /* RFC 3361 */
DHCP_CSR = 121, /* RFC 3442 */
DHCP_MSCSR = 249, /* MS code for RFC 3442 */
DHCP_END = 255
@ -221,6 +170,8 @@ int get_option_uint16(uint16_t *, const struct dhcp_message *, uint8_t);
int get_option_uint8(uint8_t *, const struct dhcp_message *, uint8_t);
struct rt *get_option_routes(const struct dhcp_message *);
struct rt *decode_rfc3442(const uint8_t *);
int configure_env(const char *, const struct dhcp_message *);
ssize_t make_message(struct dhcp_message **,
const struct interface *, const struct dhcp_lease *,
uint32_t, uint8_t, const struct options *);
@ -228,7 +179,4 @@ int valid_dhcp_packet(unsigned char *);
ssize_t write_lease(const struct interface *, const struct dhcp_message *);
struct dhcp_message *read_lease(const struct interface *iface);
ssize_t write_string(FILE *f, const uint8_t *, ssize_t);
ssize_t write_options(FILE *f, const struct dhcp_message *);
#endif

View File

@ -284,13 +284,11 @@ Don't request any options beyond what is needed to configure the interface.
.It Fl R , -nodns
Don't send DNS information to resolvconf or touch
.Pa /etc/resolv.conf .
.It Fl T , -test
On receipt of discover messages, simply print the contents of the DHCP
message to the console.
.Nm
will not configure the
.Ar interface ,
touch any files or restart any services.
.It Fl T, -test
On receipt of discover messages we just call @SYSCONFDIR@/dhcpcd.sh with the
reason of TEST which echo's the DHCP variables found in the message to the
console. The interface configuration isn't touched and neither are any
configuration files.
.It Fl Y , -nonis
Don't touch
.Pa /etc/yp.conf
@ -331,10 +329,6 @@ Linux Socket Filter, or LPF device on Linux based systems.
Bourne shell script that is run when we configure or deconfigure an interface.
.It Pa @DBDIR@/dhcpcd.duid
Text file that holds the DUID used to identify the host.
.It Pa @DBDIR@/dhcpcd- Ns Ar interface Ns .info
Bourne shell file that holds the DHCP values used in configuring the interface.
This path is passed as the first argument to
.Pa @SYSCONFDIR@/dhcpcd.sh .
.It Pa @DBDIR@/dhcpcd- Ns Ar interface Ns .lease
The actual DHCP message send by the server. We use this when reading the last
lease and use the files mtime as when it was issued.

271
dhcpcd.sh
View File

@ -1,271 +0,0 @@
#!/bin/sh
# dhcpcd - DHCP client daemon
# Copyright 2006-2008 Roy Marples <roy@marples.name>
# All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
info="$1"
state="$2"
[ -e "${info}" ] && . "${info}"
do_hooks()
{
local x= retval=0
for x in /etc/dhcpcd/"$1"-hook /etc/dhcpcd/"$1"-hook.d/*; do
if [ -e "${x}" ]; then
. "${x}"
retval=$((${retval} + $?))
fi
done
return ${retval}
}
# Try and locate a service pidfile
service_pid()
{
local service="$1" x=
for x in "${service}".pid \
"${service}"/pid \
"${service}"/"${service}".pid;
do
if [ -s "/var/run/${x}" ]; then
echo "/var/run/${x}"
return 0
fi
done
return 1
}
# Try and detect how to handle services so we're pretty
# platform independant
do_service()
{
local service="$1" action="$2"
shift; shift
# If restarting check if service is running or not if we can
if [ "${action}" = "restart" ]; then
pidfile=$(service_pid "${service}")
[ -s "${pidfile}" ] || return 0
kill -0 $(cat "${pidfile}") 2>/dev/null || return 0
fi
if type rc-service >/dev/null 2>/dev/null; then
rc-service "${service}" -- --nodeps "${action}" "$@"
elif [ -x /sbin/service ]; then
service "${service}" "${action}" "$@"
elif [ -x /etc/init.d/"${service}" -a -x /sbin/runscript ]; then
/etc/init.d/"${service}" --quiet --nodeps "${action}" "$@"
elif [ -x /etc/init.d/"${service}" ]; then
/etc/init.d/"${service}" "${action}" "$@"
elif [ -x /etc/rc.d/"${service}" ]; then
/etc/rc.d/"${service}" "${action}" "$@"
elif [ -x /etc/rc.d/rc."${service}" ]; then
/etc/rc.d/rc."${service}" "${action}" "$@"
else
echo "Don't know how to interact with services on this platform" >&2
return 1
fi
}
yesno()
{
[ -z "$1" ] && return 2
case "$1" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0;;
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1;;
esac
return 2
}
save_conf()
{
if [ -e "$1" ]; then
rm -f "$1"-pre."${INTERFACE}"
mv -f "$1" "$1"-pre."${INTERFACE}"
fi
}
restore_conf()
{
[ -e "$1"-pre."${INTERFACE}" ] || return 1
rm -f "$1"
mv -f "$1"-pre."${INTERFACE}" "$1"
}
make_mtu()
{
if [ -n "${MTU}" ]; then
ifconfig "${INTERFACE}" mtu "${MTU}"
fi
}
make_nis_conf() {
[ -z "${NISDOMAIN}" -a -z "${NISSERVER}" ] && return 0
local cf=/etc/yp.conf."${INTERFACE}" prefix= x= pidfile=
echo "# Generated by dhcpcd for interface ${INTERFACE}" > "${cf}"
if [ -n "${NISDOMAIN}" ]; then
domainname "${NISDOMAIN}"
if [ -n "${NISSERVER}" ]; then
prefix="domain ${NISDOMAIN} server "
else
echo "domain ${NISDOMAIN} broadcast" >> "${cf}"
fi
else
prefix="ypserver "
fi
for x in ${NISSERVER}; do
echo "${prefix}${x}" >> "${cf}"
done
save_conf /etc/yp.conf
mv -f "${cf}" /etc/yp.conf
pidfile="$(service_pidfile ypbind)"
if [ -s "${pidfile}" ]; then
kill -HUP "${pidfile}"
fi
}
restore_nis_conf()
{
restore_conf /etc/yp.conf || return 0
pidfile="$(service_pidfile ypbind)"
if [ -s "${pidfile}" ]; then
kill -HUP "${pidfile}"
fi
}
make_ntp_conf()
{
[ -z "${NTPSERVER}" ] && return 0
local cf=/etc/ntp.conf."${INTERFACE}" x=
echo "# Generated by dhcpcd for interface ${INTERFACE}" > "${cf}"
echo "restrict default noquery notrust nomodify" >> "${cf}"
echo "restrict 127.0.0.1" >> "${cf}"
for x in ${NTPSERVER}; do
echo "restrict ${x} nomodify notrap noquery" >> "${cf}"
echo "server ${x}" >> "${cf}"
done
if [ ! -e /etc/ntp.conf ]; then
true
elif type cmp >/dev/null 2>&1; then
cmp -s /etc/ntp.conf "${cf}"
elif type diff >/dev/null 2>&1; then
diff -q /etc/ntp.conf "${cf}" >/dev/null
else
false
fi
if [ $? = 0 ]; then
rm -f "${cf}"
else
save_conf /etc/ntp.conf
mv -f "${cf}" /etc/ntp.conf
do_service ntp restart
fi
}
restore_ntp_conf()
{
restore_conf /etc/ntp.conf || return 0
do_service ntp restart
}
make_resolv_conf()
{
if [ -z "${DNSSERVER}" -a -z "${DNSDOMAIN}" -a -z "${DNSSEARCH}" ]; then
return 0
fi
local x= conf="# Generated by dhcpcd for interface ${INTERFACE}\n"
if [ -n "${DNSSEARCH}" ]; then
conf="${conf}search ${DNSSEARCH}\n"
elif [ -n "${DNSDOMAIN}" ]; then
conf="${conf}search ${DNSDOMAIN}\n"
fi
for x in ${DNSSERVER}; do
conf="${conf}nameserver ${x}\n"
done
if type resolvconf >/dev/null 2>&1; then
printf "${conf}" | resolvconf -a "${INTERFACE}"
else
save_conf /etc/resolv.conf
printf "${conf}" > /etc/resolv.conf
do_service nscd restart
fi
}
restore_resolv_conf()
{
if type resolvconf >/dev/null 2>&1; then
resolvconf -d "${INTERFACE}"
else
restore_conf /etc/resolv.conf || return 0
do_service nscd restart
fi
}
need_hostname()
{
case "$(hostname)" in
""|"(none)"|localhost) return 0;;
esac
return 1
}
lookup_hostname()
{
if type host >/dev/null 2>&1; then
host "${IPADDR}" | sed 's/.* domain name pointer \(.*\)./\1/'
elif type dig >/dev/null 2>&1; then
dig +short -x "${IPADDR}" | sed 's/\.$//'
else
return 1
fi
}
make_hostname()
{
if need_hostname; then
local name="${HOSTNAME}"
[ -z "${name}" ] && name="$(lookup_hostname)"
[ -n "${name}" ] && hostname "${name}"
fi
}
do_hooks enter
# Don't do anything by default when we go down
if [ "${state}" = "down" ]; then
restore_resolv_conf
restore_nis_conf
restore_ntp_conf
exit $?
fi
make_mtu
make_resolv_conf
make_hostname
make_nis_conf
make_ntp_conf
do_hooks exit

View File

@ -15,9 +15,9 @@ SYSCONFDIR?= ${PREFIX}/etc
INSTALL?= install
SED?= sed
all: ${PROG} ${MAN}
all: ${PROG} ${SCRIPT} ${MAN}
${PROG}: ${SCRIPTS} ${OBJS}
${PROG}: ${OBJS}
${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD}
# We could save about 600 bytes by building it like this

1
net.c
View File

@ -358,7 +358,6 @@ read_interface(const char *ifname, _unused int metric)
iface = xzalloc(sizeof(*iface));
strlcpy(iface->name, ifname, IF_NAMESIZE);
snprintf(iface->leasefile, PATH_MAX, LEASEFILE, ifname);
snprintf(iface->infofile, PATH_MAX, INFOFILE, ifname);
memcpy(&iface->hwaddr, hwaddr, hwlen);
iface->hwlen = hwlen;

1
net.h
View File

@ -112,7 +112,6 @@ struct interface
#endif
char leasefile[PATH_MAX];
char infofile[PATH_MAX];
struct in_addr addr;
struct in_addr net;