summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2013-02-15 20:14:32 +0000
committerRoy Marples <roy@marples.name>2013-02-15 20:14:32 +0000
commit09421f5aa94a143388d96002b5a99ae09b53eb05 (patch)
treecd16433b922b845fbee620f66035d0aadb5c48ee
parentb0c740ab784ed6d852646f583c91ea423bbf46f9 (diff)
downloaddhcpcd-09421f5aa94a143388d96002b5a99ae09b53eb05.tar.xz
Instead of opening link, ipv6, ipv6rs and ipv6ns sockets globally,
only open when the first link wanting this features needs it. Hopefully fixes #263 and #264.
-rw-r--r--dhcpcd.c69
-rw-r--r--ipv6.c15
-rw-r--r--ipv6ns.c49
-rw-r--r--ipv6rs.c59
4 files changed, 116 insertions, 76 deletions
diff --git a/dhcpcd.c b/dhcpcd.c
index 7046a4dc..669eb959 100644
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -96,7 +96,7 @@ static char **ifv;
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 {
@@ -1268,10 +1268,19 @@ start_interface(void *arg)
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;
@@ -1282,6 +1291,23 @@ init_state(struct interface *iface, int argc, char **argv)
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
@@ -1452,14 +1478,6 @@ handle_ifa(int type, const char *ifname,
}
}
-/* 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)
{
@@ -2023,13 +2041,6 @@ main(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) {
@@ -2038,32 +2049,6 @@ main(int argc, char **argv)
}
#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;
diff --git a/ipv6.c b/ipv6.c
index c20d98ad..971f84da 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -35,6 +35,7 @@
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <unistd.h>
#include "common.h"
#include "configure.h"
@@ -47,7 +48,7 @@
# define s6_addr32 __u6_addr.__u6_addr32
#endif
-int socket_afnet6;
+int socket_afnet6 = -1;
static struct rt6head *routes;
#ifdef DEBUG_MEMORY
@@ -67,11 +68,21 @@ ipv6_cleanup()
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);
diff --git a/ipv6ns.c b/ipv6ns.c
index c66770c2..8bfac4c8 100644
--- a/ipv6ns.c
+++ b/ipv6ns.c
@@ -39,6 +39,7 @@
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <unistd.h>
#ifdef __linux__
# define _LINUX_IN6_H
@@ -59,7 +60,7 @@
/* 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];
@@ -92,19 +93,19 @@ ipv6ns_open(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
@@ -112,17 +113,17 @@ ipv6ns_open(void)
#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;
@@ -132,6 +133,15 @@ ipv6ns_open(void)
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
@@ -142,7 +152,7 @@ ipv6ns_makeprobe(struct ra *rap)
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;
@@ -182,9 +192,17 @@ ipv6ns_sendprobe(void *arg)
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));
@@ -220,7 +238,8 @@ ipv6ns_sendprobe(void *arg)
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);
diff --git a/ipv6rs.c b/ipv6rs.c
index 8e371a8f..c6b4102a 100644
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <unistd.h>
#ifdef __linux__
# define _LINUX_IN6_H
@@ -101,7 +102,7 @@ struct nd_opt_dnssl { /* DNSSL option RFC 6106 */
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];
@@ -129,31 +130,32 @@ ipv6rs_open(void)
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
@@ -161,17 +163,17 @@ ipv6rs_open(void)
#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;
@@ -181,6 +183,15 @@ ipv6rs_open(void)
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
@@ -462,7 +473,7 @@ ipv6rs_handledata(_unused void *arg)
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);
@@ -798,8 +809,8 @@ ipv6rs_handledata(_unused void *arg)
/* 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);
@@ -1067,19 +1078,33 @@ ipv6rs_start(struct interface *ifp)
{
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);