Implement renew & rebind.
authorflorian <florian@openbsd.org>
Sun, 2 Jun 2024 12:41:46 +0000 (12:41 +0000)
committerflorian <florian@openbsd.org>
Sun, 2 Jun 2024 12:41:46 +0000 (12:41 +0000)
Missed in previous.

sbin/dhcp6leased/dhcp6leased.h
sbin/dhcp6leased/engine.c
sbin/dhcp6leased/frontend.c

index e58cbe2..dc3c825 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dhcp6leased.h,v 1.1 2024/06/02 12:28:05 florian Exp $ */
+/*     $OpenBSD: dhcp6leased.h,v 1.2 2024/06/02 12:41:46 florian Exp $ */
 
 /*
  * Copyright (c) 2017, 2021 Florian Obser <florian@openbsd.org>
@@ -156,8 +156,10 @@ enum imsg_type {
        IMSG_RECONF_IFACE_IA_END,
        IMSG_RECONF_IFACE_END,
        IMSG_RECONF_END,
-       IMSG_SEND_DISCOVER,
+       IMSG_SEND_SOLICIT,
        IMSG_SEND_REQUEST,
+       IMSG_SEND_RENEW,
+       IMSG_SEND_REBIND,
        IMSG_SOCKET_IPC,
        IMSG_OPEN_UDPSOCK,
        IMSG_UDPSOCK,
index 56fd120..96514fe 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: engine.c,v 1.1 2024/06/02 12:28:05 florian Exp $      */
+/*     $OpenBSD: engine.c,v 1.2 2024/06/02 12:41:46 florian Exp $      */
 
 /*
  * Copyright (c) 2017, 2021, 2024 Florian Obser <florian@openbsd.org>
@@ -686,7 +686,7 @@ parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp)
        struct dhcp_iapd         iapd;
        struct prefix            *pds = NULL;
        size_t                   rem;
-       uint32_t                 t1, t2;
+       uint32_t                 t1, t2, lease_time;
        int                      serverid_len;
        uint8_t                  serverid[SERVERID_SIZE];
        uint8_t                 *p;
@@ -712,7 +712,7 @@ parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp)
        if (pds == NULL)
                fatal("%s: calloc", __func__);
 
-       serverid_len = t1 = t2 = 0;
+       serverid_len = t1 = t2 = lease_time = 0;
 
        p = dhcp->packet;
        rem = dhcp->len;
@@ -828,6 +828,10 @@ parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp)
                            ia_conf->prefix_len);
                        goto out;
                }
+
+               if (lease_time < pd->vltime)
+                       lease_time = pd->vltime;
+
                log_debug("%s: pltime: %u, vltime: %u, prefix: %s/%u",
                    __func__, pd->pltime, pd->vltime, inet_ntop(AF_INET6,
                    &pd->prefix, ntopbuf, INET6_ADDRSTRLEN), pd->prefix_len);
@@ -864,8 +868,13 @@ parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp)
                state_transition(iface, IF_REQUESTING);
                break;
        case DHCPREPLY:
-               /* XXX rapid commit, rebinding, renewing */
-               if (iface->state != IF_REQUESTING) {
+               /* XXX rapid commit */
+               switch(iface->state) {
+               case IF_REQUESTING:
+               case IF_RENEWING:
+               case IF_REBINDING:
+                       break;
+               default:
                        log_debug("%s: ignoring unexpected %s", __func__,
                            dhcp_message_type2str(hdr.msg_type));
                        goto out;
@@ -878,6 +887,8 @@ parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp)
                /* XXX handle t1 = 0 or t2 = 0 */
                iface->t1 = t1;
                iface->t2 = t2;
+               iface->lease_time = lease_time;
+               clock_gettime(CLOCK_MONOTONIC, &iface->request_time);
                state_transition(iface, IF_BOUND);
                break;
        case DHCPRECONFIGURE:
@@ -1054,8 +1065,15 @@ XXXX
                break;
        case IF_BOUND:
                iface->timo.tv_sec = iface->t1;
-               if (old_state == IF_REQUESTING || old_state == IF_REBOOTING) {
+               switch(old_state) {
+               case IF_REQUESTING:
+               case IF_RENEWING:
+               case IF_REBINDING:
+               case IF_REBOOTING:
                        configure_interfaces(iface);
+                       break;
+               default:
+                       break;
                }
                break;
        case IF_RENEWING:
@@ -1128,7 +1146,7 @@ iface_timeout(int fd, short events, void *arg)
                timespecsub(&now, &iface->request_time, &res);
                log_debug("%s: res.tv_sec: %lld, t2: %u", __func__,
                    res.tv_sec, iface->t2);
-               if (res.tv_sec > iface->t2)
+               if (res.tv_sec >= iface->t2)
                        state_transition(iface, IF_REBINDING);
                else
                        state_transition(iface, IF_RENEWING);
@@ -1146,6 +1164,7 @@ iface_timeout(int fd, short events, void *arg)
        }
 }
 
+/* XXX can this be merged into dhcp_request()? */
 void
 request_dhcp_discover(struct dhcp6leased_iface *iface)
 {
@@ -1161,7 +1180,7 @@ request_dhcp_discover(struct dhcp6leased_iface *iface)
                imsg.elapsed_time = 0xffff;
        else
                imsg.elapsed_time = res.tv_sec * 100;
-       engine_imsg_compose_frontend(IMSG_SEND_DISCOVER, 0, &imsg, sizeof(imsg));
+       engine_imsg_compose_frontend(IMSG_SEND_SOLICIT, 0, &imsg, sizeof(imsg));
 }
 
 void
@@ -1195,19 +1214,29 @@ request_dhcp_request(struct dhcp6leased_iface *iface)
                fatalx("XXX state IF_REBOOTING in %s not IMPL", __func__);
                break;
        case IF_REQUESTING:
+       case IF_RENEWING:
+       case IF_REBINDING:
                imsg.serverid_len = iface->serverid_len;
                memcpy(imsg.serverid, iface->serverid, SERVERID_SIZE);
                memcpy(imsg.pds, iface->pds, sizeof(iface->pds));
                break;
+       }
+       switch (iface->state) {
+       case IF_REQUESTING:
+               engine_imsg_compose_frontend(IMSG_SEND_REQUEST, 0, &imsg,
+                   sizeof(imsg));
+               break;
        case IF_RENEWING:
-               fatalx("XXX state IF_RENEWING in %s not IMPL", __func__);
+               engine_imsg_compose_frontend(IMSG_SEND_RENEW, 0, &imsg,
+                   sizeof(imsg));
                break;
        case IF_REBINDING:
-               fatalx("XXX state IF_REBINDING in %s not IMPL", __func__);
+               engine_imsg_compose_frontend(IMSG_SEND_REBIND, 0, &imsg,
+                   sizeof(imsg));
                break;
+       default:
+               fatalx("%s: wrong state", __func__);
        }
-
-       engine_imsg_compose_frontend(IMSG_SEND_REQUEST, 0, &imsg, sizeof(imsg));
 }
 
 void
index 5e2e54c..3fd768f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: frontend.c,v 1.1 2024/06/02 12:28:05 florian Exp $    */
+/*     $OpenBSD: frontend.c,v 1.2 2024/06/02 12:41:46 florian Exp $    */
 
 /*
  * Copyright (c) 2017, 2021, 2024 Florian Obser <florian@openbsd.org>
@@ -459,7 +459,10 @@ frontend_dispatch_engine(int fd, short event, void *bula)
                case IMSG_CTL_SHOW_INTERFACE_INFO:
                        control_imsg_relay(&imsg);
                        break;
-               case IMSG_SEND_DISCOVER: {
+               case IMSG_SEND_SOLICIT:
+               case IMSG_SEND_REQUEST:
+               case IMSG_SEND_RENEW:
+               case IMSG_SEND_REBIND: {
                        struct imsg_req_dhcp     imsg_req_dhcp;
                        if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_req_dhcp))
                                fatalx("%s: IMSG_SEND_DISCOVER wrong "
@@ -474,25 +477,20 @@ frontend_dispatch_engine(int fd, short event, void *bula)
                                break;
 
                        iface_data_from_imsg(iface, &imsg_req_dhcp);
-                       send_packet(DHCPSOLICIT, iface);
-                       break;
-               }
-               case IMSG_SEND_REQUEST: {
-                       struct imsg_req_dhcp     imsg_req_dhcp;
-                       if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_req_dhcp))
-                               fatalx("%s: IMSG_SEND_REQUEST wrong "
-                                   "length: %lu", __func__,
-                                   IMSG_DATA_SIZE(imsg));
-                       memcpy(&imsg_req_dhcp, imsg.data,
-                           sizeof(imsg_req_dhcp));
-
-                       iface = get_iface_by_id(imsg_req_dhcp.if_index);
-
-                       if (iface == NULL)
+                       switch (imsg.hdr.type) {
+                       case IMSG_SEND_SOLICIT:
+                               send_packet(DHCPSOLICIT, iface);
                                break;
-
-                       iface_data_from_imsg(iface, &imsg_req_dhcp);
-                       send_packet(DHCPREQUEST, iface);
+                       case IMSG_SEND_REQUEST:
+                               send_packet(DHCPREQUEST, iface);
+                               break;
+                       case IMSG_SEND_RENEW:
+                               send_packet(DHCPRENEW, iface);
+                               break;
+                       case IMSG_SEND_REBIND:
+                               send_packet(DHCPREBIND, iface);
+                               break;
+                       }
                        break;
                }
                default:
@@ -811,6 +809,8 @@ build_packet(uint8_t message_type, struct iface *iface, char *if_name)
        switch(message_type) {
        case DHCPSOLICIT:
        case DHCPREQUEST:
+       case DHCPRENEW:
+       case DHCPREBIND:
                break;
        default:
                fatalx("%s: %s not implemented", __func__,
@@ -834,13 +834,22 @@ build_packet(uint8_t message_type, struct iface *iface, char *if_name)
        memcpy(p, &duid, sizeof(struct dhcp_duid));
        p += sizeof(struct dhcp_duid);
 
-       if (message_type == DHCPREQUEST) {
+       switch(message_type) {
+       case DHCPSOLICIT:
+       case DHCPREBIND:
+               break;
+       case DHCPREQUEST:
+       case DHCPRENEW:
                opt_hdr.code = htons(DHO_SERVERID);
                opt_hdr.len = htons(iface->serverid_len);
                memcpy(p, &opt_hdr, sizeof(struct dhcp_option_hdr));
                p += sizeof(struct dhcp_option_hdr);
                memcpy(p, iface->serverid, iface->serverid_len);
                p += iface->serverid_len;
+               break;
+       default:
+               fatalx("%s: %s not implemented", __func__,
+                   dhcp_message_type2str(message_type));
        }
        SIMPLEQ_FOREACH(ia_conf, &iface_conf->iface_ia_list, entry) {
                struct prefix *pd;
@@ -869,6 +878,8 @@ build_packet(uint8_t message_type, struct iface *iface, char *if_name)
                        iaprefix.prefix_len = ia_conf->prefix_len;
                        break;
                case DHCPREQUEST:
+               case DHCPRENEW:
+               case DHCPREBIND:
                        pd = &iface->pds[ia_conf->id - 1];
                        iaprefix.prefix_len = pd->prefix_len;
                        memcpy(&iaprefix.prefix, &pd->prefix,