only open when the first link wanting this features needs it.
Hopefully fixes #263 and #264.
dhcp_start(ifp);
}
+/* ARGSUSED */
+static void
+handle_link(_unused void *arg)
+{
+
+ if (manage_link(linkfd) == -1)
+ syslog(LOG_ERR, "manage_link: %m");
+}
+
static void
init_state(struct interface *ifp, int argc, char **argv)
{
+ struct if_options *ifo;
const char *reason = NULL;
configure_interface(ifp, argc, argv);
+ ifo = ifp->options;
+
+ if (if_options->options & DHCPCD_LINK && linkfd == -1) {
+ linkfd = open_link_socket();
+ if (linkfd == -1) {
+ syslog(LOG_ERR, "open_link_socket: %m");
+ ifo->options &= ~DHCPCD_LINK;
+ } else
+ eloop_event_add(linkfd, handle_link, NULL);
+ }
+
+ if (ifo->options & DHCPCD_IPV6RS && !check_ipv6(NULL))
+ ifo->options &= ~DHCPCD_IPV6RS;
+ if (ifo->options & DHCPCD_IPV6RS && ipv6_init() == -1) {
+ ifo->options &= ~DHCPCD_IPV6RS;
+ syslog(LOG_ERR, "ipv6_init: %m");
+ }
+
+
if (!(options & DHCPCD_TEST))
script_runreason(ifp, "PREINIT");
- if (ifp->options->options & DHCPCD_LINK) {
+ if (ifo->options & DHCPCD_LINK) {
switch (carrier_status(ifp)) {
case 0:
ifp->carrier = LINK_DOWN;
}
#endif
-/* ARGSUSED */
-static void
-handle_link(_unused void *arg)
-{
-
- if (manage_link(linkfd) == -1)
- syslog(LOG_ERR, "manage_link: %m");
-}
-
static void
if_reboot(struct interface *ifp, int argc, char **argv)
{
syslog(LOG_ERR, "open_sockets: %m");
exit(EXIT_FAILURE);
}
- if (if_options->options & DHCPCD_LINK) {
- linkfd = open_link_socket();
- if (linkfd == -1)
- syslog(LOG_ERR, "open_link_socket: %m");
- else
- eloop_event_add(linkfd, handle_link, NULL);
- }
#if 0
if (options & DHCPCD_IPV6RS && disable_rtadv() == -1) {
}
#endif
- if (options & DHCPCD_IPV6 && ipv6_init() == -1) {
- options &= ~DHCPCD_IPV6;
- syslog(LOG_ERR, "ipv6_init: %m");
- }
- if (options & DHCPCD_IPV6RS && !check_ipv6(NULL))
- options &= ~DHCPCD_IPV6RS;
- if (options & DHCPCD_IPV6RS)
- ipv6rs_init();
-
ifc = argc - optind;
ifv = argv + optind;
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <unistd.h>
#include "common.h"
#include "dhcpcd.h"
int ipv6_init(void)
{
- routes = malloc(sizeof(*routes));
- if (routes == NULL)
- return -1;
-
- TAILQ_INIT(routes);
+ if (routes == NULL) {
+ routes = malloc(sizeof(*routes));
+ if (routes == NULL)
+ return -1;
+ TAILQ_INIT(routes);
#ifdef DEBUG_MEMORY
- atexit(ipv6_cleanup);
+ atexit(ipv6_cleanup);
#endif
+ }
return 0;
}
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <unistd.h>
#ifdef __linux__
# define _LINUX_IN6_H
/* Debugging Neighbor Solicitations is a lot of spam, so disable it */
//#define DEBUG_NS
-static int sock;
+static int sock = -1;
static struct sockaddr_in6 from;
static struct msghdr sndhdr;
static struct iovec sndiov[2];
static unsigned char ansbuf[1500];
static char ntopbuf[INET6_ADDRSTRLEN];
+static void ipv6ns_handledata(_unused void *arg);
+
#if DEBUG_MEMORY
static void
ipv6ns_cleanup(void)
return -1;
on = 1;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
- &on, sizeof(on)) == -1)
- return -1;
+ &on, sizeof(on)) == -1)
+ goto eexit;
on = 1;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
- &on, sizeof(on)) == -1)
- return -1;
+ &on, sizeof(on)) == -1)
+ goto eexit;
ICMP6_FILTER_SETBLOCKALL(&filt);
ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
- &filt, sizeof(filt)) == -1)
- return -1;
+ &filt, sizeof(filt)) == -1)
+ goto eexit;
set_cloexec(sock);
#if DEBUG_MEMORY
#endif
len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
- sndbuf = xzalloc(len);
+ sndbuf = calloc(1, len);
if (sndbuf == NULL)
- return -1;
+ goto eexit;
sndhdr.msg_namelen = sizeof(struct sockaddr_in6);
sndhdr.msg_iov = sndiov;
sndhdr.msg_iovlen = 1;
sndhdr.msg_control = sndbuf;
sndhdr.msg_controllen = len;
- rcvbuf = xzalloc(len);
+ rcvbuf = calloc(1, len);
if (rcvbuf == NULL)
- return -1;
+ goto eexit;
rcvhdr.msg_name = &from;
rcvhdr.msg_namelen = sizeof(from);
rcvhdr.msg_iov = rcviov;
rcviov[0].iov_base = ansbuf;
rcviov[0].iov_len = sizeof(ansbuf);
return sock;
+
+eexit:
+ close(sock);
+ sock = -1;
+ free(sndbuf);
+ sndbuf = NULL;
+ free(rcvbuf);
+ rcvbuf = NULL;
+ return -1;
}
static int
free(rap->ns);
rap->nslen = sizeof(*ns) + ROUNDUP8(rap->iface->hwlen + 2);
- rap->ns = xzalloc(rap->nslen);
+ rap->ns = calloc(1, rap->nslen);
if (rap->ns == NULL)
return -1;
ns = (struct nd_neighbor_solicit *)(void *)rap->ns;
int hoplimit = HOPLIMIT;
struct timeval tv, rtv;
- if (!rap->ns) {
- if (ipv6ns_makeprobe(rap) == -1)
+ if (sock == -1) {
+ if (ipv6ns_open() == -1) {
+ syslog(LOG_ERR, "%s: ipv6ns_open: %m", __func__);
return;
+ }
+ eloop_event_add(sock, ipv6ns_handledata, NULL);
+ }
+
+ if (!rap->ns && ipv6ns_makeprobe(rap) == -1) {
+ syslog(LOG_ERR, "%s: ipv6ns_makeprobe: %m", __func__);
+ return;
}
memset(&dst, 0, sizeof(dst));
rap->iface->name, rap->sfrom);
#endif
if (sendmsg(sock, &sndhdr, 0) == -1)
- syslog(LOG_ERR, "%s: sendmsg: %m", rap->iface->name);
+ syslog(LOG_ERR, "%s: %s: sendmsg: %m",
+ __func__, rap->iface->name);
ms_to_tv(&tv, rap->retrans == 0 ? RETRANS_TIMER : rap->retrans);
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <unistd.h>
#define ELOOP_QUEUE 1
#include "common.h"
struct rahead ipv6_routers = TAILQ_HEAD_INITIALIZER(ipv6_routers);
-static int sock;
+static int sock = -1;
static struct sockaddr_in6 allrouters, from;
static struct msghdr sndhdr;
static struct iovec sndiov[2];
int len;
struct icmp6_filter filt;
+ sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ if (sock == -1)
+ return -1;
+
memset(&allrouters, 0, sizeof(allrouters));
allrouters.sin6_family = AF_INET6;
#ifdef SIN6_LEN
allrouters.sin6_len = sizeof(allrouters);
#endif
if (inet_pton(AF_INET6, ALLROUTERS, &allrouters.sin6_addr.s6_addr) != 1)
- return -1;
- sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
- if (sock == -1)
- return -1;
+ goto eexit;
on = 1;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
&on, sizeof(on)) == -1)
- return -1;
+ goto eexit;
on = 1;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
&on, sizeof(on)) == -1)
- return -1;
+ goto eexit;
ICMP6_FILTER_SETBLOCKALL(&filt);
ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
&filt, sizeof(filt)) == -1)
- return -1;
+ goto eexit;
set_cloexec(sock);
#if DEBUG_MEMORY
#endif
len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
- sndbuf = xzalloc(len);
+ sndbuf = calloc(1, len);
if (sndbuf == NULL)
- return -1;
+ goto eexit;
sndhdr.msg_namelen = sizeof(struct sockaddr_in6);
sndhdr.msg_iov = sndiov;
sndhdr.msg_iovlen = 1;
sndhdr.msg_control = sndbuf;
sndhdr.msg_controllen = len;
- rcvbuf = xzalloc(len);
+ rcvbuf = calloc(1, len);
if (rcvbuf == NULL)
- return -1;
+ goto eexit;
rcvhdr.msg_name = &from;
rcvhdr.msg_namelen = sizeof(from);
rcvhdr.msg_iov = rcviov;
rcviov[0].iov_base = ansbuf;
rcviov[0].iov_len = sizeof(ansbuf);
return sock;
+
+eexit:
+ close(sock);
+ sock = -1;
+ free(sndbuf);
+ sndbuf = NULL;
+ free(rcvbuf);
+ rcvbuf = NULL;
+ return -1;
}
static int
/* If we're owning the RA then we need to try and ensure the
* router is actually reachable */
- if (options & DHCPCD_IPV6RA_OWN ||
- options & DHCPCD_IPV6RA_OWN_DEFAULT)
+ if (ifp->options->options & DHCPCD_IPV6RA_OWN ||
+ ifp->options->options & DHCPCD_IPV6RA_OWN_DEFAULT)
{
rap->nsprobes = 0;
ipv6ns_sendprobe(rap);
{
struct rs_state *state;
- eloop_timeout_delete(NULL, ifp);
-
- state = RS_STATE(ifp);
- if (state == NULL) {
- ifp->if_data[IF_DATA_IPV6RS] = xzalloc(sizeof(*state));
- state = RS_STATE(ifp);
+ if (sock == -1) {
+ if (ipv6rs_open() == -1) {
+ syslog(LOG_ERR, "%s: ipv6rs_open: %m", __func__);
+ return -1;
+ }
+ eloop_event_add(sock, ipv6rs_handledata, NULL);
}
- /* Always make a new probe as the underlying hardware
- * address could have changed. */
- ipv6rs_makeprobe(ifp);
- if (state->rs == NULL)
- return -1;
+ eloop_timeout_delete(NULL, ifp);
+
+ state = RS_STATE(ifp);
+ if (state == NULL) {
+ ifp->if_data[IF_DATA_IPV6RS] = calloc(1, sizeof(*state));
+ state = RS_STATE(ifp);
+ if (state == NULL) {
+ syslog(LOG_ERR, "%s: %m", __func__);
+ return -1;
+ }
+ }
+
+ /* Always make a new probe as the underlying hardware
+ * address could have changed. */
+ ipv6rs_makeprobe(ifp);
+ if (state->rs == NULL) {
+ syslog(LOG_ERR, "%s: ipv6rs_makeprobe: %m", __func__);
+ return -1;
+ }
state->rsprobes = 0;
ipv6rs_sendprobe(ifp);