Download raw body.
dhcp6leased(8): Install reject route for prefix delegation.
This prevents routing loops in case only parts of the delegated prefix
are configured on interfaces.
OK?
diff --git dhcp6leased.c dhcp6leased.c
index ae29f5a9436..90333592b95 100644
--- dhcp6leased.c
+++ dhcp6leased.c
@@ -76,6 +76,7 @@ void main_dispatch_engine(int, short, void *);
void open_udpsock(uint32_t);
void configure_address(struct imsg_configure_address *);
void deconfigure_address(struct imsg_configure_address *);
+void configure_reject_route(struct imsg_configure_reject_route *, uint8_t);
void read_lease_file(struct imsg_ifinfo *);
uint8_t *get_uuid(void);
void write_lease_file(struct imsg_lease_info *);
@@ -553,6 +554,26 @@ main_dispatch_engine(int fd, short event, void *bula)
deconfigure_address(&imsg_configure_address);
break;
}
+ case IMSG_CONFIGURE_REJECT_ROUTE: {
+ struct imsg_configure_reject_route imsg_crr;
+ if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_crr))
+ fatalx("%s: IMSG_CONFIGURE_REJECT_ROUTE wrong "
+ "length: %lu", __func__,
+ IMSG_DATA_SIZE(imsg));
+ memcpy(&imsg_crr, imsg.data, sizeof(imsg_crr));
+ configure_reject_route(&imsg_crr, RTM_ADD);
+ break;
+ }
+ case IMSG_DECONFIGURE_REJECT_ROUTE: {
+ struct imsg_configure_reject_route imsg_crr;
+ if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_crr))
+ fatalx("%s: IMSG_CONFIGURE_REJECT_ROUTE wrong "
+ "length: %lu", __func__,
+ IMSG_DATA_SIZE(imsg));
+ memcpy(&imsg_crr, imsg.data, sizeof(imsg_crr));
+ configure_reject_route(&imsg_crr, RTM_DELETE);
+ break;
+ }
case IMSG_WRITE_LEASE: {
struct imsg_lease_info imsg_lease_info;
if (IMSG_DATA_SIZE(imsg) !=
@@ -771,6 +792,99 @@ deconfigure_address(struct imsg_configure_address *address)
log_warn("%s: cannot remove address", __func__);
}
+#define ROUNDUP(a) \
+ (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a))
+
+void
+configure_reject_route(struct imsg_configure_reject_route *reject_route,
+ uint8_t rtm_type)
+{
+ struct rt_msghdr rtm;
+ struct sockaddr_rtlabel rl;
+ struct sockaddr_in6 dst, gw, mask;
+ struct iovec iov[10];
+ long pad = 0;
+ int iovcnt = 0, padlen;
+
+ memset(&rtm, 0, sizeof(rtm));
+
+ rtm.rtm_version = RTM_VERSION;
+ rtm.rtm_type = rtm_type;
+ rtm.rtm_msglen = sizeof(rtm);
+ rtm.rtm_tableid = reject_route->rdomain;
+ rtm.rtm_index = reject_route->if_index;
+ rtm.rtm_seq = ++rtm_seq;
+ rtm.rtm_priority = RTP_DEFAULT;
+ rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_LABEL;
+ rtm.rtm_flags = RTF_UP | RTF_REJECT | RTF_GATEWAY | RTF_STATIC;
+
+ iov[iovcnt].iov_base = &rtm;
+ iov[iovcnt++].iov_len = sizeof(rtm);
+
+ memset(&dst, 0, sizeof(dst));
+ dst.sin6_family = AF_INET6;
+ dst.sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&dst.sin6_addr, &reject_route->prefix, sizeof(dst.sin6_addr));
+
+ iov[iovcnt].iov_base = &dst;
+ iov[iovcnt++].iov_len = sizeof(dst);
+ rtm.rtm_msglen += sizeof(dst);
+ padlen = ROUNDUP(sizeof(dst)) - sizeof(dst);
+ if (padlen > 0) {
+ iov[iovcnt].iov_base = &pad;
+ iov[iovcnt++].iov_len = padlen;
+ rtm.rtm_msglen += padlen;
+ }
+
+ memset(&gw, 0, sizeof(gw));
+ gw.sin6_family = AF_INET6;
+ gw.sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&gw.sin6_addr, &in6addr_loopback, sizeof(gw.sin6_addr));
+
+ iov[iovcnt].iov_base = &gw;
+ iov[iovcnt++].iov_len = sizeof(gw);
+ rtm.rtm_msglen += sizeof(gw);
+ padlen = ROUNDUP(sizeof(gw)) - sizeof(gw);
+ if (padlen > 0) {
+ iov[iovcnt].iov_base = &pad;
+ iov[iovcnt++].iov_len = padlen;
+ rtm.rtm_msglen += padlen;
+ }
+
+ memset(&mask, 0, sizeof(mask));
+ mask.sin6_family = AF_INET6;
+ mask.sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&mask.sin6_addr, &reject_route->mask, sizeof(mask.sin6_addr));
+
+ iov[iovcnt].iov_base = &mask;
+ iov[iovcnt++].iov_len = sizeof(mask);
+ rtm.rtm_msglen += sizeof(mask);
+ padlen = ROUNDUP(sizeof(mask)) - sizeof(mask);
+ if (padlen > 0) {
+ iov[iovcnt].iov_base = &pad;
+ iov[iovcnt++].iov_len = padlen;
+ rtm.rtm_msglen += padlen;
+ }
+
+ memset(&rl, 0, sizeof(rl));
+ rl.sr_len = sizeof(rl);
+ rl.sr_family = AF_UNSPEC;
+ (void)snprintf(rl.sr_label, sizeof(rl.sr_label), "%s",
+ DHCP6LEASED_RTA_LABEL);
+ iov[iovcnt].iov_base = &rl;
+ iov[iovcnt++].iov_len = sizeof(rl);
+ rtm.rtm_msglen += sizeof(rl);
+ padlen = ROUNDUP(sizeof(rl)) - sizeof(rl);
+ if (padlen > 0) {
+ iov[iovcnt].iov_base = &pad;
+ iov[iovcnt++].iov_len = padlen;
+ rtm.rtm_msglen += padlen;
+ }
+
+ if (writev(routesock, iov, iovcnt) == -1)
+ log_warn("failed to send route message");
+}
+
const char*
sin6_to_str(struct sockaddr_in6 *sin6)
{
diff --git dhcp6leased.h dhcp6leased.h
index 977a4cbfaee..c229e95a7ef 100644
--- dhcp6leased.h
+++ dhcp6leased.h
@@ -171,6 +171,8 @@ enum imsg_type {
IMSG_DHCP,
IMSG_CONFIGURE_ADDRESS,
IMSG_DECONFIGURE_ADDRESS,
+ IMSG_CONFIGURE_REJECT_ROUTE,
+ IMSG_DECONFIGURE_REJECT_ROUTE,
IMSG_REQUEST_REBOOT,
IMSG_WRITE_LEASE,
};
diff --git engine.c engine.c
index 6b660983818..98784ca9b90 100644
--- engine.c
+++ engine.c
@@ -139,6 +139,9 @@ void deprecate_interfaces(struct dhcp6leased_iface *);
int prefixcmp(struct prefix *, struct prefix *, int);
void send_reconfigure_interface(struct iface_pd_conf *,
struct prefix *, enum reconfigure_action);
+void send_reconfigure_reject_route(
+ struct dhcp6leased_iface *, struct in6_addr *,
+ uint8_t, enum reconfigure_action);
int engine_imsg_compose_main(int, pid_t, void *, uint16_t);
const char *dhcp_option_type2str(int);
const char *dhcp_duid2str(int, uint8_t *);
@@ -1305,7 +1308,6 @@ request_dhcp_request(struct dhcp6leased_iface *iface)
}
}
-/* XXX we need to install a reject route for the delegated prefix */
void
configure_interfaces(struct dhcp6leased_iface *iface)
{
@@ -1336,6 +1338,9 @@ configure_interfaces(struct dhcp6leased_iface *iface)
"server %s", i, inet_ntop(AF_INET6, &pd->prefix, ntopbuf,
INET6_ADDRSTRLEN), pd->prefix_len, if_name,
dhcp_duid2str(iface->serverid_len, iface->serverid));
+
+ send_reconfigure_reject_route(iface, &pd->prefix,
+ pd->prefix_len, CONFIGURE);
}
SIMPLEQ_FOREACH(ia_conf, &iface_conf->iface_ia_list, entry) {
@@ -1402,6 +1407,8 @@ deconfigure_interfaces(struct dhcp6leased_iface *iface)
"server %s", i, inet_ntop(AF_INET6, &pd->prefix, ntopbuf,
INET6_ADDRSTRLEN), pd->prefix_len, if_name,
dhcp_duid2str(iface->serverid_len, iface->serverid));
+ send_reconfigure_reject_route(iface, &pd->prefix,
+ pd->prefix_len, DECONFIGURE);
}
SIMPLEQ_FOREACH(ia_conf, &iface_conf->iface_ia_list, entry) {
@@ -1531,6 +1538,27 @@ send_reconfigure_interface(struct iface_pd_conf *pd_conf, struct prefix *pd,
sizeof(address));
}
+void
+send_reconfigure_reject_route(struct dhcp6leased_iface *iface,
+ struct in6_addr *prefix, uint8_t prefix_len, enum reconfigure_action action)
+{
+ struct imsg_configure_reject_route imsg;
+
+ memset(&imsg, 0, sizeof(imsg));
+
+ imsg.if_index = iface->if_index;
+ imsg.rdomain = iface->rdomain;
+ memcpy(&imsg.prefix, prefix, sizeof(imsg.prefix));
+ in6_prefixlen2mask(&imsg.mask, prefix_len);
+
+ if (action == CONFIGURE)
+ engine_imsg_compose_main(IMSG_CONFIGURE_REJECT_ROUTE, 0, &imsg,
+ sizeof(imsg));
+ else
+ engine_imsg_compose_main(IMSG_DECONFIGURE_REJECT_ROUTE, 0,
+ &imsg, sizeof(imsg));
+}
+
const char *
dhcp_message_type2str(int type)
{
diff --git engine.h engine.h
index 61c0fd15f7a..add40126924 100644
--- engine.h
+++ engine.h
@@ -24,5 +24,12 @@ struct imsg_configure_address {
uint32_t pltime;
};
+struct imsg_configure_reject_route {
+ uint32_t if_index;
+ int rdomain;
+ struct in6_addr prefix;
+ struct in6_addr mask;
+};
+
void engine(int, int);
int engine_imsg_compose_frontend(int, pid_t, void *, uint16_t);
--
In my defence, I have been left unsupervised.
dhcp6leased(8): Install reject route for prefix delegation.