summaryrefslogtreecommitdiff
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
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.
-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 */