only open when the first link wanting this features needs it.
Hopefully fixes #263 and #264.
static int ifc;
static char *cffile;
static char *pidfile;
-static int linkfd = -1, ipv6rsfd = -1, ipv6nsfd = -1;
+static int linkfd = -1;
static uint8_t *packet;
struct dhcp_op {
start_reboot(iface);
}
+/* 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 *iface, int argc, char **argv)
{
struct if_state *ifs;
+ struct if_options *ifo;
if (iface->state)
ifs = iface->state;
ifs->reason = "PREINIT";
ifs->nakoff = 0;
configure_interface(iface, argc, argv);
+ ifo = ifs->options;
+
+ if (if_options->options & DHCPCD_LINK && linkfd == -1) {
+ linkfd = open_link_socket();
+ if (linkfd == -1)
+ syslog(LOG_ERR, "open_link_socket: %m");
+ else
+ add_event(linkfd, handle_link, NULL);
+ }
+
+ if (ifo->options & DHCPCD_IPV6RS && !check_ipv6(NULL))
+ options &= ~DHCPCD_IPV6RS;
+ if (ifo->options & DHCPCD_IPV6RS && ipv6_open() == -1) {
+ options &= ~DHCPCD_IPV6RS;
+ syslog(LOG_ERR, "ipv6_open: %m");
+ }
+
if (!(options & DHCPCD_TEST))
run_script(iface);
/* We need to drop the leasefile so that start_interface
}
}
-/* 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 *iface, int argc, char **argv)
{
syslog(LOG_ERR, "init_socket: %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
- add_event(linkfd, handle_link, NULL);
- }
#if 0
if (options & DHCPCD_IPV6RS && disable_rtadv() == -1) {
}
#endif
- if (options & DHCPCD_IPV6RS && !check_ipv6(NULL))
- options &= ~DHCPCD_IPV6RS;
- if (options & DHCPCD_IPV6RS && ipv6_open() == -1) {
- options &= ~DHCPCD_IPV6RS;
- syslog(LOG_ERR, "ipv6_open: %m");
- }
- if (options & DHCPCD_IPV6RS) {
- ipv6rsfd = ipv6rs_open();
- if (ipv6rsfd == -1) {
- syslog(LOG_ERR, "ipv6rs: %m");
- options &= ~DHCPCD_IPV6RS;
- } else {
- add_event(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
- add_event(ipv6nsfd, ipv6ns_handledata, NULL);
- }
- }
-
ifc = argc - optind;
ifv = argv + optind;
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <unistd.h>
#include "common.h"
#include "configure.h"
# define s6_addr32 __u6_addr.__u6_addr32
#endif
-int socket_afnet6;
+int socket_afnet6 = -1;
static struct rt6head *routes;
#ifdef DEBUG_MEMORY
int
ipv6_open(void)
{
+
+ if (socket_afnet6 != -1)
+ return socket_afnet6;
+
socket_afnet6 = socket(AF_INET6, SOCK_DGRAM, 0);
if (socket_afnet6 == -1)
return -1;
set_cloexec(socket_afnet6);
- routes = xmalloc(sizeof(*routes));
+ routes = malloc(sizeof(*routes));
+ if (routes == NULL) {
+ close(socket_afnet6);
+ socket_afnet6 = -1;
+ return -1;
+ }
+
TAILQ_INIT(routes);
#ifdef DEBUG_MEMORY
atexit(ipv6_cleanup);
#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];
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;
+ }
+ add_event(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 ? rap->retrans : RETRANS_TIMER);
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <unistd.h>
#ifdef __linux__
# define _LINUX_IN6_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
syslog(LOG_ERR, "RA for unexpected interface from %s", sfrom);
return;
}
- if (!(ifp->options->options & DHCPCD_IPV6RS)) {
+ if (!(ifp->state->options->options & DHCPCD_IPV6RS)) {
#ifdef DEBUG_RS
syslog(LOG_DEBUG, "%s: unexpected RA from %s",
ifp->name, sfrom);
/* 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->state->options->options & DHCPCD_IPV6RA_OWN ||
+ ifp->state->options->options & DHCPCD_IPV6RA_OWN_DEFAULT)
{
rap->nsprobes = 0;
ipv6ns_sendprobe(rap);
{
struct rs_state *state;
+ if (sock == -1) {
+ if (ipv6rs_open() == -1) {
+ syslog(LOG_ERR, "%s: ipv6rs_open: %m", __func__);
+ return -1;
+ }
+ add_event(sock, ipv6rs_handledata, NULL);
+ }
+
delete_timeout(NULL, ifp);
state = RS_STATE(ifp);
if (state == NULL) {
- ifp->if_data[IF_DATA_IPV6RS] = xzalloc(sizeof(*state));
+ 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)
+ if (state->rs == NULL) {
+ syslog(LOG_ERR, "%s: ipv6rs_makeprobe: %m", __func__);
return -1;
+ }
state->rsprobes = 0;
ipv6rs_sendprobe(ifp);