SRCS= common.c dhcp.c dhcpcd.c logger.c net.c signal.c
SRCS+= configure.c client.c
SRCS+= ${SRC_IF} ${SRC_SOCKET}
+SCRIPT= dhcpcd.sh
MAN= dhcpcd.8
VERSION= 3.3.0-alpha1
CLEANFILES= dhcpcd.8
BINDIR= ${PREFIX}/sbin
+SCRIPTDIR= ${PREFIX}/etc
.SUFFIXES: .in
include ${MK}/prog.mk
CFLAGS+= -DVERSION=\"${VERSION}\"
-
-# Work out how to restart services
-_RC_SH= if test -n "${HAVE_INIT}"; then \
- test "${HAVE_INIT}" = "no" || echo "-DENABLE_${HAVE_INIT}"; \
- elif test -x /sbin/runscript; then echo "-DENABLE_OPENRC"; \
- elif test -x /sbin/service; then echo "-DENABLE_SERVICE"; \
- elif test -x /etc/rc.d/rc.S -a -x /etc/rc.d/rc.M; then echo "-DENABLE_SLACKRC"; \
- elif test -d /etc/rc.d; then echo "-DENABLE_BSDRC"; \
- elif test -d /etc/init.d; then echo "-DENABLE_SYSV"; \
- fi
-_RC!= ${_RC_SH}
-CFLAGS+= ${_RC}$(shell ${_RC_SH})
-
CFLAGS+= -DINFODIR=\"${INFODIR}\"
-LDADD+= ${LIBRESOLV} ${LIBRT}
+LDADD+= ${LIBRT}
.in:
${SED} 's:@PREFIX@:${PREFIX}:g; s:@INFODIR@:${INFODIR}:g' $< > $@
#include "logger.h"
#include "signal.h"
-#ifdef THERE_IS_NO_FORK
-# ifndef ENABLE_INFO
- # error "Non MMU requires ENABLE_INFO to work"
-# endif
-#endif
-
#ifdef ENABLE_IPV4LL
# ifndef ENABLE_ARP
# error "IPv4LL requires ENABLE_ARP to work"
lease->frominfo = 0;
}
-#ifdef ENABLE_INFO
static int
get_old_lease(struct if_state *state, const struct options *options)
{
state->dhcp = dhcp;
return 0;
}
-#endif
static int
client_setup(struct if_state *state, const struct options *options)
options->options & DHCPCD_REQUEST ||
options->options & DHCPCD_DAEMONISED))
{
-#ifdef ENABLE_INFO
if (!get_old_lease(state, options))
-#endif
return -1;
state->timeout = 0;
if (options->options & DHCPCD_INFORM)
return -1;
-#ifdef ENABLE_INFO
if (!(state->options & DHCPCD_TEST) &&
(state->options & DHCPCD_IPV4LL ||
state->options & DHCPCD_LASTLEASE))
} else if (errno == EINTR)
return 0;
}
-#endif
#ifdef ENABLE_IPV4LL
if (!(state->options & DHCPCD_TEST) &&
}
#endif
-#if defined (ENABLE_INFO) || defined (ENABLE_IPV4LL)
if (lease->addr.s_addr) {
if (!(state->options & DHCPCD_DAEMONISED) &&
IN_LINKLOCAL(ntohl(lease->addr.s_addr)))
state->xid = 0;
return 0;
}
-#endif
if (!(state->options & DHCPCD_DAEMONISED))
return -1;
logger(LOG_INFO, "offered %s", addr);
free(addr);
-#ifdef ENABLE_INFO
if (options->options & DHCPCD_TEST) {
write_info(iface, dhcp, lease, options, 0);
errno = 0;
return -1;
}
-#endif
free(dhcp);
send_message(state, DHCP_REQUEST, options);
/* You can enable/disable various chunks of optional code here.
* You would only do this to try and shrink the end binary if dhcpcd
* was running on a low memory device */
-
#define ENABLE_ARP
-#define ENABLE_NTP
-#define ENABLE_NIS
-#define ENABLE_INFO
/* IPV4LL, aka ZeroConf, aka APIPA, aka RFC 3927.
* Needs ARP. */
* See RFC 3315 for details on this. */
#define ENABLE_DUID
-/* resolvconf is framework for multiple interfaces to manage resolv.conf */
-#define ENABLE_RESOLVCONF
-
/* Some systems do not have a working fork. */
/* #define THERE_IS_NO_FORK */
#define ETCDIR "/etc"
#define RESOLVFILE ETCDIR "/resolv.conf"
-
-#define NISFILE ETCDIR "/yp.conf"
-
-#define NTPFILE ETCDIR "/ntp.conf"
-#define NTPDRIFTFILE ETCDIR "/ntp.drift"
-#define NTPLOGFILE "/var/log/ntp.log"
-
-#define OPENNTPFILE ETCDIR "/ntpd.conf"
-
#define DEFAULT_SCRIPT ETCDIR "/" PACKAGE ".sh"
#define STATEDIR "/var"
#define INFOFILE INFODIR "/" PACKAGE "-%s.info"
#define DUIDFILE INFODIR "/" PACKAGE ".duid"
-/* OPENRC is Open Run Control, forked from Gentoo's baselayout package
- * BSDRC is BSD style Run Control
- * SLACKRC is Slackware Run Control
- * SERVICE is RedHat service command
- * SYSV should cover everthing else */
-#ifdef ENABLE_OPENRC
-# define SERVICE "OPENRC"
-# define NISSERVICE ETCDIR "/init.d/ypbind"
-# define NISRESTARTARGS "--nodeps", "--quiet", "conditionalrestart"
-# define NTPSERVICE ETCDIR "/init.d/ntpd"
-# define NTPRESTARTARGS "--nodeps", "--quiet", "conditionalrestart"
-#endif
-#if ENABLE_BSDRC
-# define SERVICE "BSDRC"
-# define NISSERVICE ETCDIR "/rc.d/ypbind"
-# define NISRESTARTARGS "restart"
-# define NTPSERVICE ETCDIR "/rc.d/ntpd"
-# define NTPRESTARTARGS "restart"
-#endif
-#if ENABLE_SLACKRC
-# define SERVICE "SLACKRC"
-# define NISSERVICE ETCDIR "/rc.d/rc.ypbind"
-# define NISRESTARTARGS "restart"
-# define NTPSERVICE ETCDIR "/rc.d/rc.ntpd"
-# define NTPRESTARTARGS "restart"
-#endif
-#if ENABLE_SERVICE
-# define SERVICE "SERVICE"
-# define NISSERVICE "service"
-# define NISRESTARTARGS "ypbind", "restart"
-# define NTPSERVICE "service"
-# define NTPRESTARTARGS "ntpd", "restart"
-#endif
-#if ENABLE_SYSV
-# define SERVICE "SYSV"
-# define NISSERVICE ETCDIR "/init.d/ypbind"
-# define NISRESTARTARGS "restart"
-# define NTPSERVICE ETCDIR "/init.d/ntpd"
-# define NTPRESTARTARGS "restart"
-#endif
-
-#ifndef NISSERVICE
-# undef ENABLE_NIS
-#endif
-#ifndef NTPSERVICE
-# undef ENABLE_NTP
-#endif
-
#endif
*/
#include <sys/stat.h>
+#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <ctype.h>
#include <errno.h>
-#include <netdb.h>
-#include <resolv.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
int n = 1;
int ret = 0;
pid_t pid;
+ pid_t wpid;
+ int status = 0;
sigset_t full;
sigset_t old;
/* Restore our signals */
sigprocmask(SIG_SETMASK, &old, NULL);
-
free(argv);
+
+ /* Wait for the script to finish */
+ do {
+ wpid = waitpid(pid, &status, 0);
+ if (wpid < 1)
+ logger(LOG_ERR, "waitpid: %s", strerror(errno));
+ } while (!WIFEXITED(status) && !WIFSIGNALED(status));
+
+ if (WIFEXITED(status))
+ ret = WEXITSTATUS(status);
+ else
+ ret = -1;
+ if (ret != 0)
+ logger(LOG_ERR, "%s exited non zero", cmd);
return ret;
}
return;
}
-#ifdef ENABLE_INFO
logger(LOG_DEBUG, "exec \"%s\" \"%s\" \"%s\"", script, infofile, arg);
exec_cmd(script, infofile, arg, (char *)NULL);
-#else
- logger(LOG_DEBUG, "exec \"%s\" \"\" \"%s\"", script, arg);
- exec_cmd(script, "", arg, (char *)NULL);
-#endif
-}
-
-static char *
-lookuphostname(in_addr_t addr)
-{
- union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- } su;
- socklen_t salen;
- char *name;
- struct addrinfo hints;
- struct addrinfo *res = NULL;
- int r;
-
- name = xmalloc(sizeof(char) * NI_MAXHOST);
- salen = sizeof(su.sa);
- memset(&su.sa, 0, salen);
- su.sin.sin_family = AF_INET;
- su.sin.sin_addr.s_addr = addr;
-
- r = getnameinfo(&su.sa, salen, name, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
- if (r != 0) {
- free(name);
- switch (r) {
-#ifdef EAI_NODATA
- case EAI_NODATA: /* FALLTHROUGH */
-#endif
- case EAI_NONAME:
- errno = ENOENT;
- break;
- case EAI_SYSTEM:
- break;
- default:
- errno = EIO;
- break;
- }
- return NULL;
- }
-
- /* Check for a malicious PTR record */
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = AI_NUMERICHOST;
- r = getaddrinfo(name, "0", &hints, &res);
- if (res)
- freeaddrinfo(res);
- if (r == 0 || !*name) {
- free(name);
- errno = ENOENT;
- return NULL;
- }
-
- return name;
-}
-
-static int
-configure_hostname(const struct dhcp_message *dhcp, in_addr_t addr, int h)
-{
- char *newhostname;
- char *curhostname;
-
- curhostname = xmalloc(sizeof(char) * MAXHOSTNAMELEN);
- *curhostname = '\0';
-
- gethostname(curhostname, MAXHOSTNAMELEN);
- if (h ||
- strlen(curhostname) == 0 ||
- strcmp(curhostname, "(none)") == 0 ||
- strcmp(curhostname, "localhost") == 0)
- {
- newhostname = get_option_string(dhcp, DHCP_HOSTNAME);
- if (!newhostname || h)
- newhostname = lookuphostname(addr);
-
- if (newhostname) {
- logger(LOG_INFO, "setting hostname to `%s'", newhostname);
- sethostname(newhostname, (int)strlen(newhostname));
- free(newhostname);
- }
- }
-
- free(curhostname);
- return 0;
-}
-
-#ifdef ENABLE_NIS
-#define PREFIXSIZE 300
-static int
-configure_nis(const char *ifname, const struct dhcp_message *dhcp)
-{
- const uint8_t *servers;
- char *domain;
- FILE *f;
- char *prefix;
- const uint8_t *e;
- uint8_t l;
- struct in_addr addr;
-
- servers = get_option(dhcp, DHCP_NISSERVER);
- domain = get_option_string(dhcp, DHCP_NISDOMAIN);
-
- if (!servers && !domain) {
- if (errno == ENOENT)
- return 0;
- return -1;
- }
-
- if (!(f = fopen(NISFILE, "w")))
- return -1;
-
- prefix = xmalloc(sizeof(char) * PREFIXSIZE);
- *prefix = '\0';
- fprintf(f, "# Generated by dhcpcd for interface %s\n", ifname);
-
- if (domain) {
- setdomainname(domain, (int)strlen(domain));
- if (servers)
- snprintf(prefix, PREFIXSIZE, "domain %s server",
- domain);
- else
- fprintf(f, "domain %s broadcast\n", domain);
- free(domain);
- }
- else
- strlcpy(prefix, "ypserver", PREFIXSIZE);
-
- if (servers) {
- l = *servers++;
- e = servers + l;
- for(; servers < e; servers += sizeof(uint32_t)) {
- memcpy(&addr.s_addr, servers, sizeof(uint32_t));
- fprintf(f, "%s %s\n", prefix, inet_ntoa(addr));
- }
- }
-
- free(prefix);
- fclose(f);
-
- return exec_cmd(NISSERVICE, NISRESTARTARGS, (char *)NULL);
-}
-#endif
-
-#ifdef ENABLE_NTP
-static int
-in_addresses(const uint8_t *addresses, uint32_t addr)
-{
- uint8_t l = *addresses++;
- const uint8_t *e = addresses + l;
- uint32_t a;
-
- for (; addresses < e; addresses += sizeof(a)) {
- memcpy(&a, addresses, sizeof(a));
- if (a == addr)
- return 0;
- }
- return -1;
-}
-
-static int
-_make_ntp(const char *file, const char *ifname, const uint8_t *ntp)
-{
- FILE *f;
- char *a;
- char *line = NULL;
- size_t len = 0;
- char *token;
- struct in_addr addr;
- uint8_t tomatch = *ntp;
- const uint8_t *e;
-#ifdef NTPFILE
- int ntpfile;
-#endif
-
- /* Check that we really need to update the servers.
- * We do this because ntp has to be restarted to
- * work with a changed config. */
- if (!(f = fopen(file, "r"))) {
- if (errno != ENOENT)
- return -1;
- } else {
- while (tomatch != 0 && (get_line(&line, &len, f))) {
- a = line;
- token = strsep(&a, " ");
- if (!token || strcmp(token, "server") != 0)
- continue;
- if ((token = strsep(&a, " \n")) == NULL)
- continue;
- if (inet_aton(token, &addr) == 1 &&
- in_addresses(ntp, addr.s_addr) == 0)
- tomatch--;
- }
- fclose(f);
- free(line);
-
- /* File has the same name servers that we do,
- * so no need to restart ntp */
- if (tomatch == 0)
- return 0;
- }
-
- if (!(f = fopen(file, "w")))
- return -1;
-
- fprintf(f, "# Generated by dhcpcd for interface %s\n", ifname);
-#ifdef NTPFILE
- if ((ntpfile = strcmp(file, NTPFILE)) == 0) {
- fprintf(f, "restrict default noquery notrust nomodify\n");
- fprintf(f, "restrict 127.0.0.1\n");
- }
-#endif
-
- tomatch = *ntp++;
- e = ntp + tomatch;
- for (; ntp < e; ntp += sizeof(uint32_t)) {
- memcpy(&addr.s_addr, ntp, sizeof(uint32_t));
- a = inet_ntoa(addr);
-#ifdef NTPFILE
- if (ntpfile == 0)
- fprintf(f, "restrict %s nomodify notrap noquery\n", a);
-#endif
- fprintf(f, "server %s\n", a);
- }
- fclose(f);
-
- return 1;
-}
-#endif
-
-static int
-configure_ntp(const char *ifname, const struct dhcp_message *dhcp)
-{
- const uint8_t *ntp = get_option(dhcp, DHCP_NTPSERVER);
- int restart = 0;
- int r;
-
- if (!ntp) {
- if (errno == ENOENT)
- return 0;
- return -1;
- }
-
-#ifdef NTPFILE
- r = _make_ntp(NTPFILE, ifname, ntp);
- if (r == -1)
- return -1;
- if (r > 0)
- restart |= 1;
-#endif
-
-#ifdef OPENNTPFILE
- r = _make_ntp(OPENNTPFILE, ifname, ntp);
- if (r == -1)
- return -1;
- if (r > 0)
- restart |= 2;
-#endif
-
- if (restart)
- return exec_cmd(NTPSERVICE, NTPRESTARTARGS, (char *)NULL);
- return 0;
-}
-
-#ifdef ENABLE_RESOLVCONF
-static int
-file_in_path(const char *file)
-{
- char *p = getenv("PATH");
- char *path;
- char *token;
- struct stat s;
- char mypath[PATH_MAX];
- int retval = -1;
-
- if (!p) {
- errno = ENOENT;
- return -1;
- }
-
- path = strdup(p);
- p = path;
- while ((token = strsep(&p, ":"))) {
- snprintf(mypath, PATH_MAX, "%s/%s", token, file);
- if (stat(mypath, &s) == 0) {
- retval = 0;
- break;
- }
- }
- free(path);
- return(retval);
-}
-#endif
-
-static int
-configure_resolv(const char *ifname, const struct dhcp_message *dhcp)
-{
- FILE *f = NULL;
- const uint8_t *servers;
- const uint8_t *e;
- uint8_t l;
- struct in_addr addr;
- char *p;
-
-#ifdef ENABLE_RESOLVCONF
- char *resolvconf = NULL;
- size_t len;
-#endif
-
- servers = get_option(dhcp, DHCP_DNSSERVER);
- if (!servers) {
- if (errno == ENOENT)
- return 0;
- return -1;
- }
-
-#ifdef ENABLE_RESOLVCONF
- if (file_in_path("resolvconf") == 0) {
- len = strlen("resolvconf -a ") + strlen(ifname) + 1;
- resolvconf = xmalloc(sizeof(char) * len);
- snprintf(resolvconf, len, "resolvconf -a %s", ifname);
- f = popen(resolvconf , "w");
- free(resolvconf);
- }
-#endif
- if (!f && !(f = fopen(RESOLVFILE, "w")))
- return -1;
-
- fprintf(f, "# Generated by dhcpcd for interface %s\n", ifname);
- p = get_option_string(dhcp, DHCP_DNSSEARCH);
- if (!p)
- p = get_option_string(dhcp, DHCP_DNSDOMAIN);
- if (p) {
- fprintf(f, "search %s\n", p);
- free(p);
- }
-
- l = *servers++;
- e = servers + l;
- for (; servers < e; servers += sizeof(uint32_t)) {
- memcpy(&addr.s_addr, servers, sizeof(uint32_t));
- fprintf(f, "nameserver %s\n", inet_ntoa(addr));
- }
-
-#ifdef ENABLE_RESOLVCONF
- if (resolvconf)
- pclose(f);
- else
-#endif
- fclose(f);
-
- /* Refresh the local resolver */
- res_init();
- return 0;
}
-#ifdef ENABLE_RESOLVCONF
-static int
-restore_resolv(const char *ifname)
-{
- if (file_in_path("resolvconf") != 0)
- return 0;
-
- return exec_cmd("resolvconf", "-d", ifname, (char *)NULL);
-}
-#endif
-
-
static struct rt *
reverse_routes(struct rt *routes)
{
return retval;
}
-#ifdef ENABLE_INFO
static void
print_clean(FILE *f, const char *name, const char *value)
{
fclose(f);
return 0;
}
-#endif
int
configure(struct interface *iface, const struct dhcp_message *dhcp,
iface->mtu = iface->initial_mtu;
}
-#ifdef ENABLE_INFO
/* 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));
}
-#endif
/* Only reset things if we had set them before */
if (iface->addr.s_addr != 0) {
iface->addr.s_addr = 0;
iface->net.s_addr = 0;
}
-#ifdef ENABLE_RESOLVCONF
- if (options->options & DHCPCD_DNS)
- restore_resolv(iface->name);
-#endif
}
exec_script(options->script, iface->infofile, "down");
#endif
configure_routes(iface, dhcp, options);
- if (options->options & DHCPCD_DNS)
- configure_resolv(iface->name, dhcp);
-#ifdef ENABLE_NTP
- if (options->options & DHCPCD_NTP)
- configure_ntp(iface->name, dhcp);
-#endif
-#ifdef ENABLE_NIS
- if (options->options & DHCPCD_NIS)
- configure_nis(iface->name, dhcp);
-#endif
- configure_hostname(dhcp, addr.s_addr,
- options->options & DHCPCD_HOSTNAME);
-
up = (iface->addr.s_addr != addr.s_addr ||
iface->net.s_addr != net.s_addr);
-
iface->addr.s_addr = addr.s_addr;
iface->net.s_addr = net.s_addr;
-#ifdef ENABLE_INFO
- //if (!lease->frominfo)
+ if (!lease->frominfo)
write_info(iface, dhcp, lease, options, 1);
if (write_lease(iface, dhcp) == -1)
logger(LOG_ERR, "write_lease: %s", strerror(errno));
-#endif
-
+
exec_script(options->script, iface->infofile, up ? "new" : "up");
return 0;
{ DHCP_NETMASK, OPT_IPV4R, NULL },
{ DHCP_BROADCAST, OPT_IPV4R, NULL },
{ DHCP_LEASETIME, OPT_UINT32, NULL },
- { DHCP_RENEWALTIME, OPT_UINT32R, "RENEWALTIME" },
- { DHCP_REBINDTIME, OPT_UINT32R, "REBINDTIME" },
+ { DHCP_RENEWALTIME, OPT_UINT32R, NULL },
+ { DHCP_REBINDTIME, OPT_UINT32R, NULL },
{ DHCP_MTU, OPT_UINT16R, "MTU" },
{ DHCP_STATICROUTE, OPT_IPV4R, NULL },
{ DHCP_ROUTER, OPT_IPV4R, NULL },
{ DHCP_DNSSERVER, OPT_IPV4R, "DNSSERVER" },
{ DHCP_DNSDOMAIN, OPT_STRINGR, "DNSDOMAIN" },
{ DHCP_DNSSEARCH, OPT_STRINGR | OPT_RFC3397, "DNSSEARCH" },
-#ifdef ENABLE_NTP
{ DHCP_NTPSERVER, OPT_IPV4R, "NTPSERVER" },
-#endif
-#ifdef ENABLE_NIS
{ DHCP_NISSERVER, OPT_IPV4R, "NISSERVER" },
{ DHCP_NISDOMAIN, OPT_IPV4R, "NISDOMAIN" },
-#endif
-#ifdef ENABLE_INFO
{ DHCP_ROOTPATH, OPT_STRINGR, "ROOTPATH" },
{ DHCP_SIPSERVER, OPT_STRINGR | OPT_RFC3361, "SIPSERVER" },
-#endif
{ DHCP_MESSAGE, OPT_STRING, NULL},
{ 0, 0, NULL }
};
return routes;
}
-#ifdef ENABLE_INFO
static char *
decode_rfc3361(const uint8_t *data)
{
return sip;
}
-#endif
char *
get_option_string(const struct dhcp_message *dhcp, uint8_t option)
return dhcp;
}
-#ifdef ENABLE_INFO
/* Create a malloced string of cstr, changing ' to '\''
* so the contents work in a shell */
char *
}
return retval;
}
-#endif
ssize_t write_lease(const struct interface *, const struct dhcp_message *);
struct dhcp_message *read_lease(const struct interface *iface);
-#ifdef ENABLE_INFO
char *clean_metas(const char *cstr);
ssize_t write_options(FILE *f, const struct dhcp_message *dhcp);
#endif
-#endif
snprintf(options->classid, CLASS_ID_MAX_LEN, "%s %s",
PACKAGE, VERSION);
- options->options |= DHCPCD_ARP | DHCPCD_DNS | DHCPCD_MTU |
- DHCPCD_NIS | DHCPCD_NTP | DHCPCD_GATEWAY |
- DHCPCD_DAEMONISE | DHCPCD_IPV4LL | DHCPCD_DUID;
+ options->options |= DHCPCD_GATEWAY | DHCPCD_IPV4LL | DHCPCD_DUID |
+ DHCPCD_DAEMONISE;
options->timeout = DEFAULT_TIMEOUT;
gethostname(options->hostname, sizeof(options->hostname));
strcmp(options->hostname, "localhost") == 0)
*options->hostname = '\0';
+ setenv("PEERDNS", "yes", 1);
+ setenv("PEERHOSTNAME", "no", 1);
+ setenv("PEERNIS", "yes", 1);
+ setenv("PEERNTP", "yes", 1);
+
/* Don't set any optional arguments here so we retain POSIX
* compatibility with getopt */
while ((opt = getopt_long(argc, argv, EXTRA_OPTS
options->options &= ~DHCPCD_IPV4LL;
break;
case 'E':
-#ifndef ENABLE_INFO
- logger (LOG_ERR, "info not compiled into dhcpcd");
- goto abort;
-#endif
options->options |= DHCPCD_LASTLEASE;
break;
case 'F':
options->options &= ~DHCPCD_GATEWAY;
break;
case 'H':
- options->options |= DHCPCD_HOSTNAME;
+ setenv("PEERHOSTNAME", "yes", 1);
break;
case 'I':
if (optarg) {
options->options &= ~DHCPCD_MTU;
break;
case 'N':
- options->options &= ~DHCPCD_NTP;
+ setenv("PEERNTP", "no", 1);
break;
case 'R':
- options->options &= ~DHCPCD_DNS;
+ setenv("PEERDNS", "no", 1);
break;
case 'S':
options->domscsr++;
break;
case 'T':
-#ifndef ENABLE_INFO
- logger(LOG_ERR, "info support not compiled into dhcpcd");
- goto abort;
-#endif
options->options |= DHCPCD_TEST | DHCPCD_PERSISTENT;
break;
case 'Y':
- options->options &= ~DHCPCD_NIS;
+ setenv("PEERNIS", "no", 1);
break;
case '?':
usage();
#ifdef ENABLE_DUID
" DUID"
#endif
-#ifdef ENABLE_INFO
- " INFO"
-#endif
#ifdef ENABLE_INFO_COMPAT
" INFO_COMPAT"
#endif
#ifdef ENABLE_IPV4LL
" IPV4LL"
#endif
-#ifdef ENABLE_NIS
- " NIS"
-#endif
-#ifdef ENABLE_NTP
- " NTP"
-#endif
-#ifdef SERVICE
- " " SERVICE
-#endif
-#ifdef ENABLE_RESOLVCONF
- " RESOLVCONF"
-#endif
#ifdef THERE_IS_NO_FORK
" THERE_IS_NO_FORK"
#endif
/* Seed random */
srandomdev();
-#ifdef __linux
+#ifdef __linux__
/* Massage our filters per platform */
setup_packet_filters();
#endif
#endif
#define DHCPCD_ARP (1 << 0)
-#define DHCPCD_DNS (1 << 1)
#define DHCPCD_DOMAIN (1 << 2)
#define DHCPCD_GATEWAY (1 << 3)
#define DHCPCD_MTU (1 << 4)
-#define DHCPCD_NIS (1 << 5)
-#define DHCPCD_NTP (1 << 6)
#define DHCPCD_LASTLEASE (1 << 7)
#define DHCPCD_INFORM (1 << 8)
#define DHCPCD_REQUEST (1 << 9)
#!/bin/sh
+#
+# dhcpcd - DHCP client daemon
+# Copyright 2006-2008 Roy Marples <roy@marples.name>
+# All rights reserved
#
-# This is a sample /etc/dhcpcd.sh script.
-# /etc/dhcpcd.sh script is executed by dhcpcd daemon
-# any time it configures or shuts down interface.
-# The following parameters are passed to dhcpcd.exe script:
-# $1 = HostInfoFilePath, e.g "/var/lib/dhcpcd/dhcpcd-eth0.info"
-# $2 = "up" if interface has been configured with the same
-# IP address as before reboot;
-# $2 = "down" if interface has been shut down;
-# $2 = "new" if interface has been configured with new IP address;
+# 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.
#
-# Sanity checks
+# 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.
-if [ $# -lt 2 ]; then
- logger -s -p local0.err -t dhcpcd.sh "wrong usage"
- exit 1
+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_nis_conf() {
+ yesno "${PEERNIS}" || return 0
+ [ -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()
+{
+ yesno "${PEERNIS}" || return 0
+ restore_conf /etc/yp.conf || return 0
+ pidfile="$(service_pidfile ypbind)"
+ if [ -s "${pidfile}" ]; then
+ kill -HUP "${pidfile}"
+ fi
+}
+
+make_ntp_conf()
+{
+ yesno "${PEERNTP}" || return 0
+ [ -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 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()
+{
+ yesno "${PEERNTP}" || return 0
+ restore_conf /etc/ntp.conf || return 0
+ do_service ntp restart
+}
+
+make_resolv_conf()
+{
+ yesno "${PEERDNS}" || return 0
+ 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()
+{
+ yesno "${PEERDNS}" || return 0
+ 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
+}
+
+make_hostname()
+{
+ [ -z "${HOSTNAME}" ] && return 0
+ if need_hostname || yesno "${PEERHOSTNAME}"; then
+ hostname "${HOSTNAME}"
+ 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
-hostinfo="$1"
-state="$2"
+make_resolv_conf
+make_hostname
+make_nis_conf
+make_ntp_conf
-# Reading HostInfo file for configuration parameters
-[ -e "${hostinfo}" ] && . "${hostinfo}"
-
-case "${state}" in
- up)
- logger -s -p local0.info -t dhcpcd.sh \
- "interface ${INTERFACE} has been configured with old IP=${IPADDR}"
- # Put your code here for when the interface has been brought up with an
- # old IP address here
- ;;
-
- new)
- logger -s -p local0.info -t dhcpcd.sh \
- "interface ${INTERFACE} has been configured with new IP=${IPADDR}"
- # Put your code here for when the interface has been brought up with a
- # new IP address
- ;;
-
- down) logger -s -p local0.info -t dhcpcd.sh \
- "interface ${INTERFACE} has been brought down"
- # Put your code here for the when the interface has been shut down
- ;;
-esac
-exit 0
+do_hooks exit
${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${BINDIR}
${INSTALL} -d ${DESTDIR}${INFODIR}
+_scriptinstall: ${SCRIPT}
+ ${INSTALL} -d ${DESTDIR}${SCRIPTDIR}
+ ${INSTALL} -m ${BINMODE} ${SCRIPT} ${DESTDIR}${SCRIPTDIR}
+
include ${MK}/depend.mk
include ${MK}/man.mk
include ${MK}/dist.mk
-install: _proginstall maninstall
+install: _proginstall _scriptinstall maninstall
clean:
rm -f ${OBJS} ${PROG} _${PROG}.c _${PROG}.o ${CLEANFILES}
iface = xzalloc(sizeof(*iface));
strlcpy(iface->name, ifname, IF_NAMESIZE);
snprintf(iface->leasefile, PATH_MAX, LEASEFILE, ifname);
-#ifdef ENABLE_INFO
snprintf(iface->infofile, PATH_MAX, INFOFILE, ifname);
-#endif
memcpy(&iface->hwaddr, hwaddr, hwlen);
iface->hwlen = hwlen;
int
signal_init(void)
{
- struct sigaction sa;
-
if (pipe(signal_pipe) == -1)
return -1;
close_on_exec(signal_pipe[0]);
close_on_exec(signal_pipe[1]);
- /* Ignore child signals and don't make zombies.
- * Because we do this, we don't need to be in signal_setup */
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = SIG_DFL;
- sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT;
- if (sigaction(SIGCHLD, &sa, NULL) == -1)
- return -1;
-
memset(signals, 0, sizeof(signals));
return 0;
}