mirror of
https://github.com/rsmarples/dhcpcd.git
synced 2024-11-24 02:24:35 +08:00
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.
This commit is contained in:
parent
cebe222c56
commit
fbbb0875dd
56
dhcpcd.c
56
dhcpcd.c
@ -453,16 +453,45 @@ start_interface(void *arg)
|
||||
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;
|
||||
@ -573,15 +602,6 @@ handle_hwaddr(const char *ifname, unsigned char *hwaddr, size_t hwlen)
|
||||
}
|
||||
#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)
|
||||
{
|
||||
@ -1105,13 +1125,6 @@ main(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) {
|
||||
@ -1120,15 +1133,6 @@ main(int argc, char **argv)
|
||||
}
|
||||
#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;
|
||||
|
||||
|
14
ipv6.c
14
ipv6.c
@ -35,6 +35,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "dhcpcd.h"
|
||||
@ -66,14 +67,15 @@ ipv6_cleanup()
|
||||
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;
|
||||
}
|
||||
|
||||
|
51
ipv6ns.c
51
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];
|
||||
@ -70,6 +71,8 @@ static unsigned char *rcvbuf;
|
||||
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)
|
||||
@ -92,19 +95,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 +115,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 +135,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 +154,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 +194,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;
|
||||
}
|
||||
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));
|
||||
@ -220,7 +240,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 == 0 ? RETRANS_TIMER : rap->retrans);
|
||||
|
75
ipv6rs.c
75
ipv6rs.c
@ -43,6 +43,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ELOOP_QUEUE 1
|
||||
#include "common.h"
|
||||
@ -104,7 +105,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];
|
||||
@ -132,31 +133,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
|
||||
@ -164,17 +166,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;
|
||||
@ -184,6 +186,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
|
||||
@ -786,8 +797,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->options->options & DHCPCD_IPV6RA_OWN ||
|
||||
ifp->options->options & DHCPCD_IPV6RA_OWN_DEFAULT)
|
||||
{
|
||||
rap->nsprobes = 0;
|
||||
ipv6ns_sendprobe(rap);
|
||||
@ -1085,19 +1096,33 @@ ipv6rs_start(struct interface *ifp)
|
||||
{
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user