-.\" $OpenBSD: dhcpleased.conf.5,v 1.12 2023/03/02 17:09:52 jmc Exp $
+.\" $OpenBSD: dhcpleased.conf.5,v 1.13 2023/11/25 12:00:39 florian Exp $
.\"
.\" Copyright (c) 2018, 2021 Florian Obser <florian@openbsd.org>
.\" Copyright (c) 2005 Esben Norby <norby@openbsd.org>
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: March 2 2023 $
+.Dd $Mdocdate: November 25 2023 $
.Dt DHCPLEASED.CONF 5
.Os
.Sh NAME
.Ar server-ip .
This option can be listed multiple times.
The default is to not ignore servers.
+.It Ic prefer ipv6
+Send the IPv6-Only preferred option to the server.
+If the server responds with the option, no lease is configured.
.It Ic send client id Ar client-id
Send the DHCP client identifier option with a value of
.Ar client-id .
-/* $OpenBSD: dhcpleased.h,v 1.14 2022/03/21 04:35:41 dlg Exp $ */
+/* $OpenBSD: dhcpleased.h,v 1.15 2023/11/25 12:00:39 florian Exp $ */
/*
* Copyright (c) 2017, 2021 Florian Obser <florian@openbsd.org>
#define DHO_NDS_SERVERS 85
#define DHO_NDS_TREE_NAME 86
#define DHO_NDS_CONTEXT 87
+#define DHO_IPV6_ONLY_PREFERRED 108
#define DHO_DOMAIN_SEARCH 119
#define DHO_CLASSLESS_STATIC_ROUTES 121
#define DHO_TFTP_CONFIG_FILE 144
int ignore;
struct in_addr ignore_servers[MAX_SERVERS];
int ignore_servers_len;
+ int prefer_ipv6;
};
struct dhcpleased_conf {
-/* $OpenBSD: engine.c,v 1.39 2023/11/03 15:02:06 tb Exp $ */
+/* $OpenBSD: engine.c,v 1.40 2023/11/25 12:00:39 florian Exp $ */
/*
* Copyright (c) 2017, 2021 Florian Obser <florian@openbsd.org>
IF_REBINDING,
/* IF_INIT_REBOOT, */
IF_REBOOTING,
+ IF_IPV6_ONLY,
};
const char* if_state_name[] = {
"Rebinding",
/* "Init-Reboot", */
"Rebooting",
+ "IPv6 only",
};
struct dhcpleased_iface {
uint32_t lease_time;
uint32_t renewal_time;
uint32_t rebinding_time;
+ uint32_t ipv6_only_time;
};
LIST_HEAD(, dhcpleased_iface) dhcpleased_interfaces;
case IF_REBINDING:
case IF_REBOOTING:
case IF_BOUND:
+ case IF_IPV6_ONLY:
state_transition(iface, IF_REBOOTING);
break;
}
size_t rem, i;
uint32_t sum, usum, lease_time = 0, renewal_time = 0;
uint32_t rebinding_time = 0;
+ uint32_t ipv6_only_time = 0;
uint8_t *p, dho = DHO_PAD, dho_len, slen;
uint8_t dhcp_message_type = 0;
int routes_len = 0, routers = 0, csr = 0;
}
break;
}
+ case DHO_IPV6_ONLY_PREFERRED:
+ if (dho_len != sizeof(ipv6_only_time))
+ goto wrong_length;
+ memcpy(&ipv6_only_time, p, sizeof(ipv6_only_time));
+ ipv6_only_time = ntohl(ipv6_only_time);
+ if (log_getverbose() > 1) {
+ log_debug("DHO_IPV6_ONLY_PREFERRED %us",
+ ipv6_only_time);
+ }
+ p += dho_len;
+ rem -= dho_len;
+ break;
default:
if (log_getverbose() > 1)
log_debug("DHO_%u, len: %u", dho, dho_len);
"offered IP address", __func__);
return;
}
+#ifndef SMALL
+ if (iface_conf != NULL && iface_conf->prefer_ipv6 &&
+ ipv6_only_time > 0) {
+ iface->ipv6_only_time = ipv6_only_time;
+ state_transition(iface, IF_IPV6_ONLY);
+ break;
+ }
+#endif
iface->server_identifier = server_identifier;
iface->dhcp_server = server_identifier;
iface->requested_ip = dhcp_hdr->yiaddr;
strlcpy(iface->domainname, domainname,
sizeof(iface->domainname));
strlcpy(iface->hostname, hostname, sizeof(iface->hostname));
+#ifndef SMALL
+ if (iface_conf != NULL && iface_conf->prefer_ipv6 &&
+ ipv6_only_time > 0) {
+ iface->ipv6_only_time = ipv6_only_time;
+ state_transition(iface, IF_IPV6_ONLY);
+ break;
+ }
+#endif
state_transition(iface, IF_BOUND);
break;
case DHCPNAK:
send_deconfigure_interface(iface);
/* fall through */
case IF_DOWN:
+ case IF_IPV6_ONLY:
iface->timo.tv_sec = START_EXP_BACKOFF;
break;
case IF_BOUND:
iface->timo.tv_sec /= 2;
request_dhcp_request(iface);
break;
+ case IF_IPV6_ONLY:
+ switch (old_state) {
+ case IF_REQUESTING:
+ case IF_RENEWING:
+ case IF_REBINDING:
+ case IF_REBOOTING:
+ /* going IPv6 only: delete legacy IP */
+ send_rdns_withdraw(iface);
+ send_deconfigure_interface(iface);
+ /* fall through */
+ case IF_INIT:
+ case IF_DOWN:
+ case IF_IPV6_ONLY:
+ iface->timo.tv_sec = iface->ipv6_only_time;
+ break;
+ case IF_BOUND:
+ fatal("invalid transition Bound -> IPv6 only");
+ break;
+ }
}
if_name = if_indextoname(iface->if_index, ifnamebuf);
else
state_transition(iface, IF_REBINDING);
break;
+ case IF_IPV6_ONLY:
+ state_transition(iface, IF_REQUESTING);
+ break;
}
}
imsg.requested_ip.s_addr = INADDR_ANY; /* MUST NOT */
imsg.ciaddr = iface->requested_ip; /* IP address */
break;
+ case IF_IPV6_ONLY:
+ fatalx("invalid state IF_IPV6_ONLY in %s", __func__);
+ break;
}
engine_imsg_compose_frontend(IMSG_SEND_REQUEST, 0, &imsg, sizeof(imsg));
-/* $OpenBSD: frontend.c,v 1.30 2022/07/14 15:23:09 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.31 2023/11/25 12:00:39 florian Exp $ */
/*
* Copyright (c) 2017, 2021 Florian Obser <florian@openbsd.org>
8, DHO_SUBNET_MASK, DHO_ROUTERS, DHO_DOMAIN_NAME_SERVERS,
DHO_HOST_NAME, DHO_DOMAIN_NAME, DHO_BROADCAST_ADDRESS,
DHO_DOMAIN_SEARCH, DHO_CLASSLESS_STATIC_ROUTES};
+ static uint8_t dhcp_req_list_v6[] = {DHO_DHCP_PARAMETER_REQUEST_LIST,
+ 9, DHO_SUBNET_MASK, DHO_ROUTERS, DHO_DOMAIN_NAME_SERVERS,
+ DHO_HOST_NAME, DHO_DOMAIN_NAME, DHO_BROADCAST_ADDRESS,
+ DHO_DOMAIN_SEARCH, DHO_CLASSLESS_STATIC_ROUTES,
+ DHO_IPV6_ONLY_PREFERRED};
static uint8_t dhcp_requested_address[] = {DHO_DHCP_REQUESTED_ADDRESS,
4, 0, 0, 0, 0};
static uint8_t dhcp_server_identifier[] = {DHO_DHCP_SERVER_IDENTIFIER,
memcpy(p, iface_conf->vc_id, iface_conf->vc_id_len);
p += iface_conf->vc_id_len;
}
+ if (iface_conf->prefer_ipv6) {
+ memcpy(p, dhcp_req_list_v6, sizeof(dhcp_req_list_v6));
+ p += sizeof(dhcp_req_list_v6);
+
+ } else {
+ memcpy(p, dhcp_req_list, sizeof(dhcp_req_list));
+ p += sizeof(dhcp_req_list);
+ }
} else
#endif /* SMALL */
{
memcpy(dhcp_client_id + 3, hw_address, sizeof(*hw_address));
memcpy(p, dhcp_client_id, sizeof(dhcp_client_id));
p += sizeof(dhcp_client_id);
+ memcpy(p, dhcp_req_list, sizeof(dhcp_req_list));
+ p += sizeof(dhcp_req_list);
}
- memcpy(p, dhcp_req_list, sizeof(dhcp_req_list));
- p += sizeof(dhcp_req_list);
if (requested_ip->s_addr != INADDR_ANY) {
memcpy(dhcp_requested_address + 2, requested_ip,
-/* $OpenBSD: parse.y,v 1.7 2022/03/21 04:35:41 dlg Exp $ */
+/* $OpenBSD: parse.y,v 1.8 2023/11/25 12:00:39 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
%}
%token DHCP_IFACE ERROR SEND VENDOR CLASS ID CLIENT IGNORE DNS ROUTES HOST NAME
-%token NO
+%token NO PREFER IPV6
%token <v.string> STRING
%token <v.number> NUMBER
}
free($2);
}
+ | PREFER IPV6 {
+ iface_conf->prefer_ipv6 = 1;
+ }
;
%%
{"id", ID},
{"ignore", IGNORE},
{"interface", DHCP_IFACE},
+ {"ipv6", IPV6},
{"name", NAME},
{"no", NO},
+ {"prefer", PREFER},
{"routes", ROUTES},
{"send", SEND},
{"vendor", VENDOR},
-/* $OpenBSD: printconf.c,v 1.4 2022/01/04 06:20:37 florian Exp $ */
+/* $OpenBSD: printconf.c,v 1.5 2023/11/25 12:00:39 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
printf("\tignore %s\n", hbuf);
}
+ if (iface->prefer_ipv6)
+ printf("\t prefer ipv6\n");
printf("}\n");
}
}