summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2021-09-14 07:51:52 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2021-09-14 07:51:52 +0000
commit90c8f892e599e1cc7acdb9cc1004e8883ad576bb (patch)
treeef4d3fbfb6ab464a1aac9e251f6186d960d005bf
parent781850460c884ebbafa6d1cb976c8ab30bf1f22e (diff)
When the dhcp server is unreachable via unicast UDP retry broadcast.
The only indication we get is sendto(2) failing, so if our UDP packet is silently dropped somewhere we won't notice. This has been observed in the wild with a dhcp server at the remote end of a VPN. The dhcp server is reachable via broadcast so we get an initial lease. However the server is not in the same subnet as the lease we are getting so to reach it unicast we depend on a default route being set. When the VPN goes down we lose the default route [*] and when dhcpleased then tries to renew the lease (unicast), sendto(2) fails with "network unreachable". [*] The exact mechanics on how this happens are unclear. I.e. why didn't dhcpleased(8) see a link-state change and transitioned to REBOOTING / INIT? Regardless, we shouldn't ignore sendto(2) errors. Reported by stsp, OK benno
-rw-r--r--sbin/dhcpleased/frontend.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/sbin/dhcpleased/frontend.c b/sbin/dhcpleased/frontend.c
index 6d3bf825737..aecdfd72911 100644
--- a/sbin/dhcpleased/frontend.c
+++ b/sbin/dhcpleased/frontend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frontend.c,v 1.21 2021/08/24 14:54:02 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.22 2021/09/14 07:51:51 florian Exp $ */
/*
* Copyright (c) 2017, 2021 Florian Obser <florian@openbsd.org>
@@ -95,7 +95,7 @@ ssize_t build_packet(uint8_t, char *, uint32_t, struct ether_addr *,
void send_discover(struct iface *);
void send_request(struct iface *);
void bpf_send_packet(struct iface *, uint8_t *, ssize_t);
-void udp_send_packet(struct iface *, uint8_t *, ssize_t);
+int udp_send_packet(struct iface *, uint8_t *, ssize_t);
#ifndef SMALL
int iface_conf_cmp(struct iface_conf *, struct iface_conf *);
#endif /* SMALL */
@@ -1021,13 +1021,14 @@ send_request(struct iface *iface)
pkt_len = build_packet(DHCPREQUEST, if_name, iface->xid,
&iface->ifinfo.hw_address, &iface->requested_ip,
&iface->server_identifier);
- if (iface->dhcp_server.s_addr != INADDR_ANY)
- udp_send_packet(iface, dhcp_packet, pkt_len);
- else
+ if (iface->dhcp_server.s_addr != INADDR_ANY) {
+ if (udp_send_packet(iface, dhcp_packet, pkt_len) == -1)
+ bpf_send_packet(iface, dhcp_packet, pkt_len);
+ } else
bpf_send_packet(iface, dhcp_packet, pkt_len);
}
-void
+int
udp_send_packet(struct iface *iface, uint8_t *packet, ssize_t len)
{
struct sockaddr_in to;
@@ -1039,8 +1040,11 @@ udp_send_packet(struct iface *iface, uint8_t *packet, ssize_t len)
to.sin_port = ntohs(SERVER_PORT);
if (sendto(iface->udpsock, packet, len, 0, (struct sockaddr *)&to,
- sizeof(to)) == -1)
+ sizeof(to)) == -1) {
log_warn("sendto");
+ return -1;
+ }
+ return 0;
}
void
bpf_send_packet(struct iface *iface, uint8_t *packet, ssize_t len)