diff --git a/hooks/dhcpcd-run-hooks.8.in b/hooks/dhcpcd-run-hooks.8.in index 8672a22f..12c091a4 100644 --- a/hooks/dhcpcd-run-hooks.8.in +++ b/hooks/dhcpcd-run-hooks.8.in @@ -124,6 +124,30 @@ dhcpcd's lease or state expired and it failed to obtain a new one. .It Dv NAK dhcpcd received a NAK from the DHCP server. This should be treated as EXPIRE. +.It Dv DISC_NO_OFFER +dhcpcd retransmitted a DHCP DISCOVER because no OFFER was received. +This is a notification only and does not configure or deconfigure. +.It Dv SOLICIT_NO_ADVERT +dhcpcd retransmitted a DHCPv6 Solicit because no Advertise was received. +This is a notification only and does not configure or deconfigure. +.It Dv REQ_NO_RESP +dhcpcd failed to receive a response to a DHCP REQUEST and is falling back +to DISCOVER. +This is a notification only and does not configure or deconfigure. +.It Dv REQ6_NO_REPLY +dhcpcd failed to receive a Reply to a DHCPv6 Request and is falling back +to Solicit. +This is a notification only and does not configure or deconfigure. +.It Dv RENEW_NO_RESP +dhcpcd failed to renew its DHCPv4 lease at T2 and is entering REBIND. +This is a notification only and does not configure or deconfigure. +.It Dv RENEW6_NO_RESP +dhcpcd failed to renew its DHCPv6 lease at T2 and is entering REBIND. +This is a notification only and does not configure or deconfigure. +.It Dv RS_TIMEOUT_NO_RA +dhcpcd sent the maximum number of Router Solicitations without receiving +a Router Advertisement. +This is a notification only and does not configure or deconfigure. .It Dv RECONFIGURE dhcpcd has been instructed to reconfigure an interface. .It Dv ROUTERADVERT diff --git a/src/dhcp.c b/src/dhcp.c index 078f6927..ffbb754c 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -1944,7 +1944,15 @@ send_inform(void *arg) static void send_discover(void *arg) { - send_message((struct interface *)arg, DHCP_DISCOVER, send_discover); + struct interface *ifp = arg; + struct dhcp_state *state = D_STATE(ifp); + /* First call: interval==0 (set to 4 inside send_message). + * Retransmits: interval already 4/8/... - mirror ISC's dhclient. */ + int retransmit = state->interval != 0; + + send_message(ifp, DHCP_DISCOVER, send_discover); + if (retransmit) + script_runreason(ifp, "DISC_NO_OFFER"); } static void @@ -2005,6 +2013,7 @@ dhcp_requestfailed(void *arg) state->offer = NULL; state->offer_len = 0; state->interval = 0; + script_runreason(ifp, "REQ_NO_RESP"); dhcp_discover(ifp); } @@ -2096,6 +2105,7 @@ dhcp_rebind(void *arg) struct dhcp_lease *lease = &state->lease; logwarnx("%s: failed to renew DHCP, rebinding", ifp->name); + script_runreason(ifp, "RENEW_NO_RESP"); logdebugx("%s: expire in %" PRIu32 " seconds", ifp->name, lease->leasetime - lease->rebindtime); state->state = DHS_REBIND; diff --git a/src/dhcp6.c b/src/dhcp6.c index 07ffeb50..21692346 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -1481,7 +1481,10 @@ dhcp6_sendinform(void *arg) static void dhcp6_senddiscover2(void *arg) { - dhcp6_sendmessage(arg, dhcp6_senddiscover2); + struct interface *ifp = arg; + + dhcp6_sendmessage(ifp, dhcp6_senddiscover2); + script_runreason(ifp, "SOLICIT_NO_ADVERT"); } static void @@ -1495,9 +1498,10 @@ dhcp6_senddiscover1(void *arg) struct interface *ifp = arg; struct dhcp6_state *state = D6_STATE(ifp); - if (state->recv == NULL || state->recv->type != DHCP6_ADVERTISE) - dhcp6_sendmessage(arg, dhcp6_senddiscover2); - else + if (state->recv == NULL || state->recv->type != DHCP6_ADVERTISE) { + dhcp6_sendmessage(ifp, dhcp6_senddiscover2); + script_runreason(ifp, "SOLICIT_NO_ADVERT"); + } else dhcp6_startrequest(ifp); } @@ -1863,6 +1867,7 @@ dhcp6_failrequest(void *arg) int llevel = dhcp6_failloglevel(ifp); logmessage(llevel, "%s: failed to request DHCPv6 address", ifp->name); + script_runreason(ifp, "REQ6_NO_REPLY"); dhcp6_fail(ifp, true); } @@ -1927,9 +1932,10 @@ dhcp6_startrebind(void *arg) state->RTC = 0; state->MRC = 0; - if (state->state == DH6S_RENEW) + if (state->state == DH6S_RENEW) { logwarnx("%s: failed to renew DHCPv6, rebinding", ifp->name); - else { + script_runreason(ifp, "RENEW6_NO_RESP"); + } else { loginfox("%s: rebinding prior DHCPv6 lease", ifp->name); #ifndef SMALL diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 0004b1b5..4cde6244 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -434,8 +434,10 @@ ipv6nd_sendrsprobe(void *arg) if (state->rsprobes++ < MAX_RTR_SOLICITATIONS) eloop_timeout_add_sec(ifp->ctx->eloop, RTR_SOLICITATION_INTERVAL, ipv6nd_sendrsprobe, ifp); - else + else { logwarnx("%s: no IPv6 Routers available", ifp->name); + script_runreason(ifp, "RS_TIMEOUT_NO_RA"); + } } static void diff --git a/src/script.c b/src/script.c index e059472e..30620ab0 100644 --- a/src/script.c +++ b/src/script.c @@ -325,7 +325,21 @@ make_env(struct dhcpcd_ctx *ctx, const struct interface *ifp, protocol = PROTO_DHCP; #endif } +#ifdef INET + else if (strcmp(reason, "DISC_NO_OFFER") == 0 || + strcmp(reason, "REQ_NO_RESP") == 0 || + strcmp(reason, "RENEW_NO_RESP") == 0) + protocol = PROTO_DHCP; +#endif #ifdef INET6 +#ifdef DHCP6 + else if (strcmp(reason, "SOLICIT_NO_ADVERT") == 0 || + strcmp(reason, "REQ6_NO_REPLY") == 0 || + strcmp(reason, "RENEW6_NO_RESP") == 0) + protocol = PROTO_DHCP6; +#endif + else if (strcmp(reason, "RS_TIMEOUT_NO_RA") == 0) + protocol = PROTO_RA; else if (strcmp(reason, "STATIC6") == 0) protocol = PROTO_STATIC6; #ifdef DHCP6 @@ -440,7 +454,14 @@ make_env(struct dhcpcd_ctx *ctx, const struct interface *ifp, if_down = ifo->options & DHCPCD_RELEASE ? true_str : false_str; } else if (strcmp(reason, "TEST") == 0 || strcmp(reason, "PREINIT") == 0 || strcmp(reason, "CARRIER") == 0 || - strcmp(reason, "STOP") == 0 || strcmp(reason, "UNKNOWN") == 0) { + strcmp(reason, "STOP") == 0 || strcmp(reason, "UNKNOWN") == 0 || + strcmp(reason, "DISC_NO_OFFER") == 0 || + strcmp(reason, "REQ_NO_RESP") == 0 || + strcmp(reason, "RENEW_NO_RESP") == 0 || + strcmp(reason, "SOLICIT_NO_ADVERT") == 0 || + strcmp(reason, "REQ6_NO_REPLY") == 0 || + strcmp(reason, "RENEW6_NO_RESP") == 0 || + strcmp(reason, "RS_TIMEOUT_NO_RA") == 0) { if_up = false_str; if_down = false_str; } else if (strcmp(reason, "NOCARRIER") == 0) {