summaryrefslogtreecommitdiff
path: root/sbin/dhcp6leased
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2024-07-10 12:52:52 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2024-07-10 12:52:52 +0000
commit77ca455d5e2b0dfe4b1d6cf9c3ca226e33a46c08 (patch)
tree7e3262ff78bf1e845b408ea396b2698357054fc6 /sbin/dhcp6leased
parentb8d1be7246d99c7ec63e3069b5b4d37866321319 (diff)
Pass status option up.
If we are in state "renewing" and the DHCPv6 server returns an unsuccessful status go to "rebinding", i.e. ask any DHCPv6 server for a lease not just the one we got the lease from. This likely fixes a problem reported by Brian Conway where the ISP returned "NoBinding - Prefix not bound to this interface." for a renew. dhcp6leased recovered once T1 expired and we went to "rebinding" after some time.
Diffstat (limited to 'sbin/dhcp6leased')
-rw-r--r--sbin/dhcp6leased/engine.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/sbin/dhcp6leased/engine.c b/sbin/dhcp6leased/engine.c
index 113be3c32fb..c8997b37d0b 100644
--- a/sbin/dhcp6leased/engine.c
+++ b/sbin/dhcp6leased/engine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: engine.c,v 1.19 2024/07/10 12:44:46 florian Exp $ */
+/* $OpenBSD: engine.c,v 1.20 2024/07/10 12:52:51 florian Exp $ */
/*
* Copyright (c) 2017, 2021, 2024 Florian Obser <florian@openbsd.org>
@@ -127,7 +127,7 @@ struct dhcp6leased_iface *get_dhcp6leased_iface_by_id(uint32_t);
void remove_dhcp6leased_iface(uint32_t);
void parse_dhcp(struct dhcp6leased_iface *,
struct imsg_dhcp *);
-void parse_ia_pd_options(uint8_t *, size_t, struct prefix *);
+int parse_ia_pd_options(uint8_t *, size_t, struct prefix *);
void state_transition(struct dhcp6leased_iface *, enum
if_state);
void iface_timeout(int, short, void *);
@@ -812,11 +812,19 @@ parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp)
log_debug("%s: IA_PD, IAID: %08x, T1: %u, T2: %u",
__func__, ntohl(iapd.iaid), ntohl(iapd.t1),
ntohl(iapd.t2));
- if (ntohl(iapd.iaid) < iface_conf->ia_count)
- parse_ia_pd_options(p +
+ if (ntohl(iapd.iaid) < iface_conf->ia_count) {
+ int status_code;
+ status_code = parse_ia_pd_options(p +
sizeof(struct dhcp_iapd), opt_hdr.len -
sizeof(struct dhcp_iapd),
&iface->new_pds[ntohl(iapd.iaid)]);
+
+ if (status_code != DHCP_STATUS_SUCCESS &&
+ iface->state == IF_RENEWING) {
+ state_transition(iface, IF_REBINDING);
+ goto out;
+ }
+ }
break;
case DHO_RAPID_COMMIT:
if (opt_hdr.len != 0) {
@@ -932,7 +940,7 @@ parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp)
return;
}
-void
+int
parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix)
{
struct dhcp_option_hdr opt_hdr;
@@ -953,7 +961,7 @@ parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix)
dhcp_option_type2str(opt_hdr.code), opt_hdr.len);
if (len < opt_hdr.len) {
log_warnx("%s: malformed packet, ignoring", __func__);
- return;
+ return DHCP_STATUS_UNSPECFAIL;
}
switch (opt_hdr.code) {
@@ -961,7 +969,7 @@ parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix)
if (len < sizeof(struct dhcp_iaprefix)) {
log_warnx("%s: malformed packet, ignoring",
__func__);
- return;
+ return DHCP_STATUS_UNSPECFAIL;
}
memcpy(&iaprefix, p, sizeof(struct dhcp_iaprefix));
@@ -996,15 +1004,11 @@ parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix)
break;
case DHO_STATUS_CODE:
- /*
- * XXX handle STATUS_CODE if not success
- * STATUS_CODE can also appear in other parts of
- * the packet.
- */
+ /* XXX STATUS_CODE can also appear outside of options */
if (len < 2) {
log_warnx("%s: malformed packet, ignoring",
__func__);
- return;
+ return DHCP_STATUS_UNSPECFAIL;
}
memcpy(&status_code, p, sizeof(uint16_t));
status_code = ntohs(status_code);
@@ -1024,6 +1028,7 @@ parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix)
p += opt_hdr.len;
len -= opt_hdr.len;
}
+ return status_code;
}
/* XXX check valid transitions */