summaryrefslogtreecommitdiffstats
path: root/dhcpcd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2012-07-05 16:37:41 +0000
committerRoy Marples <roy@marples.name>2012-07-05 16:37:41 +0000
commiteebe9a1887bbf2f3bbb4fdb72e8d46ece25cdd0c (patch)
treeda2e3069767ce09c41eb2b32e6a3b7f01b164eca /dhcpcd.c
parent359e9d397807079db8d68d5e60eb4396f41d1738 (diff)
downloaddhcpcd-eebe9a1887bbf2f3bbb4fdb72e8d46ece25cdd0c.tar.xz
Improve IPv6 RA support by allowing dhcpcd to manage the address and routesdhcpcd-5.6.0
instead of the kernel. dhcpcd will only do this if RA is disabled in the kernel or dhcpcd has been instructed to do this via dhcpcd.conf(5) ipv6ra_own and ipv6ra_own_default directives. Send and process IPv6 Neighbor Solicitions and Adverts to prove router reachability. If a router cannot be reached in this way then it is expired. When debugging, all ND messages are displayed which will create a lot of log spam. To ease packaging, ./configure now accepts LDFLAGS and --enable-static.
Diffstat (limited to 'dhcpcd.c')
-rw-r--r--dhcpcd.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/dhcpcd.c b/dhcpcd.c
index b6595fea..4b318cac 100644
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -67,6 +67,8 @@ const char copyright[] = "Copyright (c) 2006-2012 Roy Marples";
#include "if-options.h"
#include "if-pref.h"
#include "ipv4ll.h"
+#include "ipv6.h"
+#include "ipv6ns.h"
#include "ipv6rs.h"
#include "net.h"
#include "platform.h"
@@ -80,7 +82,6 @@ const char copyright[] = "Copyright (c) 2006-2012 Roy Marples";
#define RELEASE_DELAY_S 0
#define RELEASE_DELAY_NS 10000000
-unsigned long long options = 0;
int pidfd = -1;
struct interface *ifaces = NULL;
int ifac = 0;
@@ -95,7 +96,7 @@ static char **ifv;
static int ifc;
static char *cffile;
static char *pidfile;
-static int linkfd = -1, ipv6rsfd = -1;
+static int linkfd = -1, ipv6rsfd = -1, ipv6nsfd = -1;
struct dhcp_op {
uint8_t value;
@@ -254,15 +255,8 @@ stop_interface(struct interface *iface)
struct interface *ifp, *ifl = NULL;
syslog(LOG_INFO, "%s: removing interface", iface->name);
- if (iface->ras) {
- ipv6rs_free(iface);
- iface->ras = NULL;
- run_script_reason(iface, "ROUTERADVERT");
- }
- if (strcmp(iface->state->reason, "RELEASE") != 0)
- drop_dhcp(iface, "STOP");
- close_sockets(iface);
- delete_timeout(NULL, iface);
+
+ // Remove the interface from our list
for (ifp = ifaces; ifp; ifp = ifp->next) {
if (ifp == iface)
break;
@@ -272,6 +266,12 @@ stop_interface(struct interface *iface)
ifl->next = ifp->next;
else
ifaces = ifp->next;
+
+ ipv6rs_drop(iface);
+ if (strcmp(iface->state->reason, "RELEASE") != 0)
+ drop_dhcp(iface, "STOP");
+ close_sockets(iface);
+ delete_timeout(NULL, iface);
free_interface(ifp);
if (!(options & (DHCPCD_MASTER | DHCPCD_TEST)))
exit(EXIT_FAILURE);
@@ -922,11 +922,7 @@ handle_carrier(int action, int flags, const char *ifname)
syslog(LOG_INFO, "%s: carrier lost", iface->name);
close_sockets(iface);
delete_timeouts(iface, start_expire, NULL);
- if (iface->ras) {
- ipv6rs_free(iface);
- iface->ras = NULL;
- run_script_reason(iface, "ROUTERADVERT");
- }
+ ipv6rs_drop(iface);
drop_dhcp(iface, "NOCARRIER");
}
} else if (carrier == 1 && !(~iface->flags & IFF_UP)) {
@@ -1616,7 +1612,7 @@ handle_args(struct fd_list *fd, int argc, char **argv)
if (argc == 1) {
for (ifp = ifaces; ifp; ifp = ifp->next) {
len++;
- if (ifp->ras)
+ if (ipv6rs_has_ra(ifp))
len++;
}
len = write(fd->fd, &len, sizeof(len));
@@ -1631,7 +1627,7 @@ handle_args(struct fd_list *fd, int argc, char **argv)
for (ifp = ifaces; ifp; ifp = ifp->next)
if (strcmp(argv[opt], ifp->name) == 0) {
len++;
- if (ifp->ras)
+ if (ipv6rs_has_ra(ifp))
len++;
}
}
@@ -1914,7 +1910,7 @@ main(int argc, char **argv)
syslog(LOG_INFO, "sending signal %d to pid %d",
sig, pid);
if (pid == 0 || kill(pid, sig) != 0) {
- if (sig != SIGALRM)
+ if (sig != SIGALRM && errno != EPERM)
syslog(LOG_ERR, ""PACKAGE" not running");
if (pid != 0 && errno != ESRCH) {
syslog(LOG_ERR, "kill: %m");
@@ -2006,6 +2002,10 @@ main(int argc, char **argv)
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) {
@@ -2015,6 +2015,15 @@ main(int argc, char **argv)
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;