--disable-ipv4 or --disable-ipv6 to configure.
# dhcpcd Makefile
PROG= dhcpcd
-SRCS= arp.c common.c control.c dhcpcd.c duid.c eloop.c
+SRCS= common.c control.c dhcpcd.c duid.c eloop.c
SRCS+= if-options.c if-pref.c net.c script.c signals.c
SRCS+= dhcp-common.c
-SRCS+= ipv4.c dhcp.c ipv4ll.c
-SRCS+= ipv6.c ipv6rs.c ipv6ns.c dhcp6.c
CFLAGS?= -O2
CSTD?= c99
dhcpcd - DHCP client daemon
-Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
+Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
Installation
# Ensure that we do not inherit these from env
HOOKSET=false
+INET=
+INET6=
ARC4RANDOM=
CLOSEFROM=
GETLINE=
--enable-fork) FORK=yes;;
--disable-static) STATIC=no;;
--enable-static) STATIC=yes;;
+ --disable-ipv4) INET=no;;
+ --enable-ipv4) INET=yes;;
+ --disable-ipv6) INET6=no;;
+ --enable-ipv6) INET6=yes;;
--prefix) prefix=$var;;
--sysconfdir) SYSCONFDIR=$var;;
--bindir|--sbindir) SBINDIR=$var;;
case "$OS" in
linux)
echo "CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=700" >>$CONFIG_MK
- echo "SRCS+= if-linux.c if-linux-wireless.c lpf.c" >>$CONFIG_MK
+ if [ -z "$INET" -o "$INET" = yes ]; then
+ echo "SRCS+= lpf.c" >>$CONFIG_MK
+ fi
+ echo "SRCS+= if-linux.c if-linux-wireless.c" >>$CONFIG_MK
echo "SRCS+= platform-linux.c" >>$CONFIG_MK
echo "LDADD+= -lrt" >>$CONFIG_MK
;;
kfreebsd)
echo "CPPFLAGS+= -D_GNU_SOURCE" >>$CONFIG_MK
- echo "SRCS+= bpf.c if-bsd.c platform-bsd.c" >>$CONFIG_MK
+ if [ -z "$INET" -o "$INET" = yes ]; then
+ echo "SRCS+= bpf.c" >>$CONFIG_MK
+ fi
+ echo "SRCS+= if-bsd.c platform-bsd.c" >>$CONFIG_MK
echo "COMPAT_SRCS+= compat/linkaddr.c" >>$CONFIG_MK
echo "LDADD+= -lrt" >>$CONFIG_MK
;;
*)
- echo "SRCS+= bpf.c if-bsd.c platform-bsd.c" >>$CONFIG_MK
+ if [ -z "$INET" -o "$INET" = yes ]; then
+ echo "SRCS+= bpf.c" >>$CONFIG_MK
+ fi
+ echo "SRCS+= if-bsd.c platform-bsd.c" >>$CONFIG_MK
;;
esac
+if [ -z "$INET" -o "$INET" = yes ]; then
+ echo "CPPFLAGS+= -DINET" >>$CONFIG_MK
+ echo "SRCS+= arp.c dhcp.c ipv4.c ipv4ll.c" >>$CONFIG_MK
+fi
+if [ -z "$INET6" -o "$INET6" = yes ]; then
+ echo "CPPFLAGS+= -DINET6" >>$CONFIG_MK
+ echo "SRCS+= ipv6.c ipv6rs.c ipv6ns.c dhcp6.c" >>$CONFIG_MK
+fi
+
# NetBSD: Even if we build for $PREFIX, the clueless user might move us to /
LDELF=/libexec/ld.elf_so
if [ -e "$LDELF" ]; then
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
return l;
}
+#ifdef INET
if (type & RFC3361) {
if ((tmp = decode_rfc3361(dl, data)) == NULL)
return -1;
if (type & RFC5969)
return decode_rfc5969(s, len, dl, data);
+#endif
if (type & STRING) {
/* Some DHCP servers return NULL strings */
} else if (type & ADDRIPV4) {
l = 16;
dl /= 4;
- } else if (type & ADDRIPV6) {
+ }
+#ifdef INET6
+ else if (type & ADDRIPV6) {
e = data + dl;
l = 0;
while (data < e) {
data += 16;
}
return l + 1;
- } else if (type & BINHEX) {
+ }
+#endif
+ else if (type & BINHEX) {
l = 2;
} else {
errno = EINVAL;
memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
l = snprintf(s, len, "%s", inet_ntoa(addr));
data += sizeof(addr.s_addr);
- } else if (type & ADDRIPV6) {
+ }
+#ifdef INET6
+ else if (type & ADDRIPV6) {
dl = ipv6_printaddr(s, len, data, ifname);
if (dl != -1)
l = dl;
else
l = 0;
data += 16;
- } else if (type & BINHEX) {
+ }
+#endif
+ else if (type & BINHEX) {
l = snprintf(s, len, "%.2x", data[0]);
data++;
} else
static int dhcp_open(struct interface *);
void
-print_options(void)
+dhcp_printoptions(void)
{
const struct dhcp_opt *opt;
const char **p;
}
ssize_t
-configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
+dhcp_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
const struct interface *ifp)
{
const struct if_options *ifo;
#include "if-options.h"
#include "net.h"
+#ifdef INET
extern const struct dhcp_opt const dhcp_opts[];
char *decode_rfc3361(int dl, const uint8_t *data);
ssize_t decode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p);
ssize_t decode_rfc5969(char *out, ssize_t len, int pl, const uint8_t *p);
-void print_options(void);
+void dhcp_printoptions(void);
char *get_option_string(const struct dhcp_message *, uint8_t);
int get_option_addr(struct in_addr *, const struct dhcp_message *, uint8_t);
int get_option_uint32(uint32_t *, const struct dhcp_message *, uint8_t);
!IN_LINKLOCAL(htonl((m)->yiaddr)) && \
get_option_uint8(NULL, m, DHO_MESSAGETYPE) == -1)
struct rt *get_option_routes(struct interface *, const struct dhcp_message *);
-ssize_t configure_env(char **, const char *, const struct dhcp_message *,
+ssize_t dhcp_env(char **, const char *, const struct dhcp_message *,
const struct interface *);
uint32_t dhcp_xid(const struct interface *);
void dhcp_close(struct interface *);
void dhcp_free(struct interface *);
int dhcp_dump(const char *);
+#else
+#define dhcp_printoptions
+#define dhcp_drop(a, b)
+#define dhcp_start(a) {}
+#define dhcp_release(a) {}
+#define dhcp_reboot(a, b) b = b
+#define dhcp_close(a)
+#define dhcp_free(a)
+#define dhcp_dump(a) -1
+#endif
#endif
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
#define D6_COPTION_DATA(o) \
((const uint8_t *)(o) + sizeof(struct dhcp6_option))
+#ifdef INET6
void dhcp6_printoptions(void);
int dhcp6_addrexists(const struct ipv6_addr *);
int dhcp6_start(struct interface *, int);
const struct dhcp6_message *, ssize_t);
void dhcp6_free(struct interface *);
void dhcp6_drop(struct interface *, const char *);
+#else
+#define dhcp6_printoptions()
+#define dhcp6_addrexists(a)
+#define dhcp6_start(a, b) 0
+#define dhcp6_env(a, b, c, d, e)
+#define dhcp6_free(a)
+#define dhcp6_drop(a, b)
+#endif
#endif
static char *cffile;
static char *pidfile;
-static int linkfd = -1, ipv6rsfd = -1, ipv6nsfd = -1;
+static int linkfd = -1;
static char **ifv;
static int ifc;
static char **margv;
case 'V':
printf("Interface options:\n");
if_printoptions();
+#ifdef INET
if (family == 0 || family == AF_INET) {
printf("\nDHCPv4 options:\n");
- print_options();
+ dhcp_printoptions();
}
+#endif
+#ifdef INET6
if (family == 0 || family == AF_INET6) {
printf("\nDHCPv6 options:\n");
dhcp6_printoptions();
}
+#endif
exit(EXIT_SUCCESS);
case '?':
usage();
}
if (options & DHCPCD_IPV6RS && !check_ipv6(NULL))
options &= ~DHCPCD_IPV6RS;
- if (options & DHCPCD_IPV6RS) {
- ipv6rsfd = ipv6rs_open();
- if (ipv6rsfd == -1) {
- syslog(LOG_ERR, "ipv6rs: %m");
- options &= ~(DHCPCD_IPV6RS |
- DHCPCD_IPV6RA_OWN | DHCPCD_IPV6RA_OWN_DEFAULT);
- } else {
- eloop_event_add(ipv6rsfd, ipv6rs_handledata, NULL);
-// atexit(restore_rtadv);
- }
- if (options & DHCPCD_IPV6RA_OWN ||
- options & DHCPCD_IPV6RA_OWN_DEFAULT)
- {
- ipv6nsfd = ipv6ns_open();
- if (ipv6nsfd == -1)
- syslog(LOG_ERR, "ipv6nd: %m");
- else
- eloop_event_add(ipv6nsfd, ipv6ns_handledata, NULL);
- }
- }
+ if (options & DHCPCD_IPV6RS)
+ ipv6rs_init();
ifc = argc - optind;
ifv = argv + optind;
}
if (rt.iface != NULL) {
if (metric == rt.iface->metric) {
+#ifdef INET
inet_cidrtoaddr(rtm->rtm_dst_len, &rt.net);
ipv4_routedeleted(&rt);
+#endif
}
}
return 1;
static int
link_addr(struct nlmsghdr *nlm)
{
+#ifdef INET
int len;
struct rtattr *rta;
struct ifaddrmsg *ifa;
rta = RTA_NEXT(rta, len);
}
ipv4_handleifa(nlm->nlmsg_type, ifn, &addr, &net, &dest);
+#endif
return 1;
}
char buffer[256];
};
+#ifdef INET
int
if_address(const struct interface *iface,
const struct in_addr *address, const struct in_addr *netmask,
free(nlm);
return retval;
}
+#endif
+#ifdef INET6
int
if_address6(const struct interface *ifp, const struct ipv6_addr *ap, int action)
{
errno = ENOTSUP;
return -1;
}
+#endif
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
static int
parse_addr(struct in_addr *addr, struct in_addr *net, const char *arg)
{
+#ifdef INET
char *p;
int i;
else if (net != NULL)
net->s_addr = ipv4_getnetmask(addr->s_addr);
return 0;
+#else
+ syslog(LOG_ERR, "No IPv4 support");
+ return -1;
+#endif
}
static const char *
uint8_t *request[], uint8_t *require[], uint8_t *no[])
{
+#ifdef INET6
if (strncmp(arg, "dhcp6_", strlen("dhcp6_")) == 0) {
*d = dhcp6_opts;
*request = ifo->requestmask6;
*no = ifo->nomask6;
return arg + strlen("dhcp6_");
}
+#endif
+
+#ifdef INET
*d = dhcp_opts;
+#else
+ *d = NULL;
+#endif
*request = ifo->requestmask;
*require = ifo->requiremask;
*no = ifo->nomask;
ifo->options &= ~DHCPCD_IPV4;
ifo->options |= DHCPCD_IPV6 | DHCPCD_IPV6RS;
break;
+#ifdef INET
case O_ARPING:
if (parse_addr(&addr, NULL, arg) != 0)
return -1;
free(ifo->fallback);
ifo->fallback = xstrdup(arg);
break;
+#endif
case O_IPV6RS:
ifo->options |= DHCPCD_IPV6RS;
break;
/* Seed our default options */
ifo = xzalloc(sizeof(*ifo));
+ ifo->options |= DHCPCD_DAEMONISE | DHCPCD_LINK;
+#ifdef INET
ifo->options |= DHCPCD_IPV4 | DHCPCD_IPV4LL;
- ifo->options |= DHCPCD_GATEWAY | DHCPCD_DAEMONISE | DHCPCD_LINK;
- ifo->options |= DHCPCD_ARP;
+ ifo->options |= DHCPCD_GATEWAY | DHCPCD_ARP;
+#endif
+#ifdef INET6
ifo->options |= DHCPCD_IPV6 | DHCPCD_IPV6RS | DHCPCD_IPV6RA_REQRDNSS;
+#endif
ifo->timeout = DEFAULT_TIMEOUT;
ifo->reboot = DEFAULT_REBOOT;
ifo->metric = -1;
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
#include "net.h"
#include "script.h"
-int socket_afnet = -1;
-
static struct rt *routes;
int
struct rt *next;
};
+#ifdef INET
int inet_ntocidr(struct in_addr);
int inet_cidrtoaddr(int, struct in_addr *);
uint32_t ipv4_getnetmask(uint32_t);
ssize_t ipv4_sendrawpacket(const struct interface *,
int, const void *, ssize_t);
ssize_t ipv4_getrawpacket(struct interface *, int, void *, ssize_t, int *);
+#else
+#define ipv4_applyaddr(a) {}
+#define ipv4_freeroutes(a) {}
+#endif
#endif
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
};
TAILQ_HEAD(rt6head, rt6);
+#ifdef INET6
int ipv6_init(void);
ssize_t ipv6_printaddr(char *, ssize_t, const uint8_t *, const char *);
struct in6_addr *ipv6_linklocal(const char *);
int ipv6_removesubnet(const struct interface *, struct ipv6_addr *);
void ipv6_buildroutes(void);
void ipv6_drop(struct interface *);
+#else
+#define ipv6_init() -1
+#endif
#endif
}
#endif
-int
+static int
ipv6ns_open(void)
{
int on;
}
/* ARGSUSED */
-void
+static void
ipv6ns_handledata(_unused void *arg)
{
ssize_t len;
eloop_timeout_delete(ipv6ns_unreachable, rap);
}
}
+
+int
+ipv6ns_init(void)
+{
+ int fd;
+
+ fd = ipv6ns_open();
+ if (fd == -1) {
+ syslog(LOG_ERR, "ipv6ns_open: %m");
+ return -1;
+ }
+ eloop_event_add(fd, ipv6ns_handledata, NULL);
+ return 0;
+}
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2011 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
#define RETRANS_TIMER 1 /* second */
#define DELAY_FIRST_PROBE_TIME 5 /* seconds */
-int ipv6ns_open(void);
+int ipv6ns_init(void);
void ipv6ns_sendprobe(void *);
-void ipv6ns_handledata(void *);
#endif
}
#endif
-int
+static int
ipv6rs_open(void)
{
int on;
}
/* ARGSUSED */
-void
+static void
ipv6rs_handledata(_unused void *arg)
{
ssize_t len, l, m, n, olen;
script_runreason(ifp, "ROUTERADVERT");
}
}
+
+int
+ipv6rs_init(void)
+{
+ int fd;
+
+ fd = ipv6rs_open();
+ if (fd == -1) {
+ syslog(LOG_ERR, "ipv6rs: %m");
+ options &= ~(DHCPCD_IPV6RS |
+ DHCPCD_IPV6RA_OWN | DHCPCD_IPV6RA_OWN_DEFAULT);
+ return -1;
+ }
+
+ eloop_event_add(fd, ipv6rs_handledata, NULL);
+ // atexit(restore_rtadv);
+
+ if (options & DHCPCD_IPV6RA_OWN ||
+ options & DHCPCD_IPV6RA_OWN_DEFAULT)
+ return ipv6ns_init();
+
+ return 0;
+}
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2011 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
#define RS_STATE(a) ((struct rs_state *)(ifp)->if_data[IF_DATA_IPV6RS])
-int ipv6rs_open(void);
-void ipv6rs_handledata(void *);
+#ifdef INET6
+int ipv6rs_init(void);
int ipv6rs_start(struct interface *);
ssize_t ipv6rs_env(char **, const char *, const struct interface *);
const struct ipv6_addr * ipv6rs_findprefix(const struct ipv6_addr *);
void ipv6rs_expire(void *arg);
int ipv6rs_has_ra(const struct interface *);
void ipv6rs_drop(struct interface *);
+#else
+#define ipv6rs_init() {}
+#define ipv6rs_start(a) {}
+#define ipv6rs_free(a)
+#define ipv6rs_has_ra(a) 0
+#define ipv6rs_drop(a)
+#endif
+
#endif
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2011 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
};
+#ifdef INET
int
ipv4_opensocket(struct interface *ifp, int protocol)
{
}
return bytes;
}
+#endif
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2011 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
#include "ipv6rs.h"
#include "net.h"
+int socket_afnet = -1;
+
static char hwaddr_buffer[(HWADDR_LEN * 3) + 1 + 1024];
char *
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2011 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
return pid;
}
+#ifdef INET
static char *
make_var(const char *prefix, const char *var)
{
}
*env = ne;
}
+#endif
static size_t
arraytostr(const char *const *argv, char **s)
const struct interface *ifp2;
int dhcp, dhcp6, ra;
const struct dhcp_state *state;
+#ifdef INET6
const struct dhcp6_state *d6_state;
+#endif
dhcp = dhcp6 = ra = 0;
state = D_STATE(ifp);
+#ifdef INET6
d6_state = D6_CSTATE(ifp);
+#endif
if (strcmp(reason, "TEST") == 0) {
+#ifdef INET6
if (d6_state && d6_state->new)
dhcp6 = 1;
else if (ipv6rs_has_ra(ifp))
ra = 1;
else
+#endif
dhcp = 1;
} else if (reason[strlen(reason) - 1] == '6')
dhcp6 = 1;
if (strcmp(reason, "TEST") == 0) {
env[8] = strdup("if_up=false");
env[9] = strdup("if_down=false");
- } else if ((dhcp && state && state->new) ||
- (dhcp6 && d6_state && d6_state->new) ||
- (ra && ipv6rs_has_ra(ifp)))
+ } else if ((dhcp && state && state->new)
+#ifdef INET6
+ || (dhcp6 && d6_state && d6_state->new)
+ || (ra && ipv6rs_has_ra(ifp))
+#endif
+ )
{
env[8] = strdup("if_up=true");
env[9] = strdup("if_down=false");
snprintf(env[elen++], e, "old_ssid=%s", ifp->ssid);
}
}
+#ifdef INET
if (dhcp && state && state->old) {
- e = configure_env(NULL, NULL, state->old, ifp);
+ e = dhcp_env(NULL, NULL, state->old, ifp);
if (e > 0) {
env = xrealloc(env, sizeof(char *) * (elen + e + 1));
- elen += configure_env(env + elen, "old",
+ elen += dhcp_env(env + elen, "old",
state->old, ifp);
}
append_config(&env, &elen, "old",
(const char *const *)ifo->config);
}
+#endif
+#ifdef INET6
if (dhcp6 && d6_state && d6_state->old) {
e = dhcp6_env(NULL, NULL, ifp,
d6_state->old, d6_state->old_len);
d6_state->old, d6_state->old_len);
}
}
+#endif
dumplease:
+#ifdef INET
if (dhcp && state && state->new) {
- e = configure_env(NULL, NULL, state->new, ifp);
+ e = dhcp_env(NULL, NULL, state->new, ifp);
if (e > 0) {
env = xrealloc(env, sizeof(char *) * (elen + e + 1));
- elen += configure_env(env + elen, "new",
+ elen += dhcp_env(env + elen, "new",
state->new, ifp);
}
append_config(&env, &elen, "new",
(const char *const *)ifo->config);
}
+#endif
+#ifdef INET6
if (dhcp6 && d6_state && d6_state->new) {
e = dhcp6_env(NULL, NULL, ifp,
d6_state->new, d6_state->new_len);
elen += ipv6rs_env(env + elen, NULL, ifp);
}
}
+#endif
/* Add our base environment */
if (ifo->environ) {
send_interface(int fd, const struct interface *iface)
{
int retval = 0;
+#ifdef INET
const struct dhcp_state *state = D_CSTATE(iface);
if (state && send_interface1(fd, iface, state->reason) == -1)
retval = -1;
+#endif
+
+#ifdef INET6
if (ipv6rs_has_ra(iface)) {
if (send_interface1(fd, iface, "ROUTERADVERT") == -1)
retval = -1;
if (send_interface1(fd, iface, "INFORM6") == -1)
retval = -1;
}
+#endif
return retval;
}
ifp->options->script[0] == '\0' ||
strcmp(ifp->options->script, "/dev/null") == 0)
return 0;
-
- if (reason == NULL) {
- const struct dhcp_state *state = D_CSTATE(ifp);
- if (state)
- reason = state->reason;
- }
+
syslog(LOG_DEBUG, "%s: executing `%s', reason %s",
ifp->name, argv[0], reason);