summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.c26
-rw-r--r--dhcp.c25
-rw-r--r--dhcp.h1
-rw-r--r--dhcpcd.c42
-rw-r--r--dhcpcd.h1
5 files changed, 60 insertions, 35 deletions
diff --git a/configure.c b/configure.c
index 159f1479..dbb9118d 100644
--- a/configure.c
+++ b/configure.c
@@ -42,6 +42,7 @@
#include "config.h"
#include "common.h"
#include "configure.h"
+#include "dhcp.h"
#include "if-options.h"
#include "if-pref.h"
#include "net.h"
@@ -513,7 +514,8 @@ add_subnet_route(struct rt *rt, const struct interface *iface)
}
static struct rt *
-get_routes(const struct interface *iface) {
+get_routes(const struct interface *iface)
+{
struct rt *rt, *nrt = NULL, *r = NULL;
if (iface->state->options->routes != NULL) {
@@ -538,6 +540,22 @@ get_routes(const struct interface *iface) {
return get_option_routes(iface->state->new);
}
+static struct rt *
+add_destination_route(struct rt *rt, const struct interface *iface)
+{
+ struct rt *r;
+
+ if (!(iface->flags & IFF_POINTOPOINT) ||
+ !has_option_mask(iface->state->options->dstmask, DHO_ROUTER))
+ return rt;
+ r = xmalloc(sizeof(*r));
+ r->dest.s_addr = INADDR_ANY;
+ r->net.s_addr = INADDR_ANY;
+ r->gate.s_addr = iface->dst.s_addr;
+ r->next = rt;
+ return r;
+}
+
void
build_routes(void)
{
@@ -549,6 +567,7 @@ build_routes(void)
continue;
dnr = get_routes(ifp);
dnr = add_subnet_route(dnr, ifp);
+ dnr = add_destination_route(dnr, ifp);
for (rt = dnr; rt && (rtn = rt->next, 1); lrt = rt, rt = rtn) {
rt->iface = ifp;
/* Is this route already in our table? */
@@ -618,6 +637,7 @@ configure(struct interface *iface)
{
struct dhcp_message *dhcp = iface->state->new;
struct dhcp_lease *lease = &iface->state->lease;
+ struct if_options *ifo = iface->state->options;
struct rt *rt;
/* As we are now adjusting an interface, we need to ensure
@@ -633,7 +653,7 @@ configure(struct interface *iface)
}
/* This also changes netmask */
- if (!(iface->state->options->options & DHCPCD_INFORM) ||
+ if (!(ifo->options & DHCPCD_INFORM) ||
!has_address(iface->name, &lease->addr, &lease->net))
{
syslog(LOG_DEBUG, "%s: adding IP address %s/%d",
@@ -668,7 +688,7 @@ configure(struct interface *iface)
build_routes();
if (!iface->state->lease.frominfo &&
- !(iface->state->options->options & DHCPCD_INFORM))
+ !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
if (write_lease(iface, dhcp) == -1)
syslog(LOG_ERR, "write_lease: %m");
run_script(iface);
diff --git a/dhcp.c b/dhcp.c
index 203dc939..c5feccad 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -759,6 +759,31 @@ encode_rfc1035(const char *src, uint8_t *dst)
memcpy(p, &_val.s_addr, 4); \
p += 4; \
}
+
+int
+dhcp_message_add_addr(struct dhcp_message *dhcp,
+ uint8_t type, struct in_addr addr)
+{
+ uint8_t *p;
+ size_t len;
+
+ p = dhcp->options;
+ while (*p != DHO_END) {
+ p++;
+ p += *p + 1;
+ }
+
+ len = p - (uint8_t *)dhcp;
+ if (len + 6 > sizeof(*dhcp)) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ PUTADDR(type, addr);
+ *p = DHO_END;
+ return 0;
+}
+
ssize_t
make_message(struct dhcp_message **message,
const struct interface *iface,
diff --git a/dhcp.h b/dhcp.h
index c8d8d6fe..90e69f52 100644
--- a/dhcp.h
+++ b/dhcp.h
@@ -186,6 +186,7 @@ struct rt *get_option_routes(const struct dhcp_message *);
ssize_t configure_env(char **, const char *, const struct dhcp_message *,
const struct if_options *);
+int dhcp_message_add_addr(struct dhcp_message *, uint8_t, struct in_addr);
ssize_t make_message(struct dhcp_message **, const struct interface *,
uint8_t);
int valid_dhcp_packet(unsigned char *);
diff --git a/dhcpcd.c b/dhcpcd.c
index f3ab5ee9..f3b96a9d 100644
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -600,7 +600,7 @@ handle_dhcp_packet(void *arg)
continue;
}
if (iface->flags & IFF_POINTOPOINT &&
- iface->state->lease.server.s_addr != from.s_addr)
+ iface->dst.s_addr != from.s_addr)
{
syslog(LOG_WARNING,
"%s: server %s is not destination",
@@ -687,10 +687,11 @@ configure_interface(struct interface *iface, int argc, char **argv)
free_options(ifs->options);
ifo = ifs->options = read_config(cffile, iface->name, iface->ssid);
add_options(ifo, argc, argv);
- if (iface->flags & IFF_NOARP)
- ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL);
if (iface->flags & IFF_POINTOPOINT && !(ifo->options & DHCPCD_INFORM))
ifo->options |= DHCPCD_STATIC;
+ if (iface->flags & IFF_NOARP ||
+ ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))
+ ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL);
if (ifo->options & DHCPCD_LINK && carrier_status(iface->name) == -1)
ifo->options &= ~DHCPCD_LINK;
@@ -1132,32 +1133,6 @@ handle_interface(int action, const char *ifname)
}
}
-static int
-dhcp_message_add_addr(struct dhcp_message *dhcp, char c, struct in_addr *addr)
-{
- uint8_t *p;
- size_t len;
-
- p = dhcp->options;
- while (*p != DHO_END) {
- p++;
- p += *p + 1;
- }
-
- len = p - (uint8_t *)dhcp;
- if (len + 6 > sizeof(*dhcp)) {
- errno = ENOMEM;
- return -1;
- }
-
- *p++ = c;
- *p++ = sizeof(addr->s_addr);
- memcpy(p, &addr->s_addr, sizeof(addr->s_addr));
- p += sizeof(addr->s_addr);
- *p = DHO_END;
- return 0;
-}
-
void
handle_ifa(int type, const char *ifname,
struct in_addr *addr, struct in_addr *net, struct in_addr *dst)
@@ -1188,12 +1163,14 @@ handle_ifa(int type, const char *ifname,
free(ifp->state->old);
ifp->state->old = ifp->state->new;
ifp->state->new = dhcp_message_new(addr, net);
+ ifp->dst.s_addr = dst ? dst->s_addr : INADDR_ANY;
if (dst) {
for (i = 1; i < 255; i++)
- if (has_option_mask(ifo->dstmask, i))
+ if (i != DHO_ROUTER &&
+ has_option_mask(ifo->dstmask, i))
dhcp_message_add_addr(
ifp->state->new,
- i, dst);
+ i, *dst);
}
ifp->state->reason = "STATIC";
build_routes();
@@ -1201,9 +1178,10 @@ handle_ifa(int type, const char *ifname,
if (ifo->options & DHCPCD_INFORM) {
ifp->state->state = DHS_INFORM;
ifp->state->xid = arc4random();
+ ifp->state->lease.server.s_addr =
+ dst ? dst->s_addr : INADDR_ANY;
ifp->addr = *addr;
ifp->net = *net;
- ifp->state->lease.server = *dst;
open_sockets(ifp);
send_inform(ifp);
}
diff --git a/dhcpcd.h b/dhcpcd.h
index 927f019f..a65e8633 100644
--- a/dhcpcd.h
+++ b/dhcpcd.h
@@ -100,6 +100,7 @@ struct interface {
struct in_addr addr;
struct in_addr net;
+ struct in_addr dst;
char leasefile[PATH_MAX];
time_t start_uptime;