diff --git a/hooks/dhcpcd-run-hooks.8.in b/hooks/dhcpcd-run-hooks.8.in index 8672a22f..935dfd90 100644 --- a/hooks/dhcpcd-run-hooks.8.in +++ b/hooks/dhcpcd-run-hooks.8.in @@ -124,6 +124,9 @@ 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. +If the server included a Message option (RFC 2132 option 56), +.Ev $message +is set to that text. .It Dv RECONFIGURE dhcpcd has been instructed to reconfigure an interface. .It Dv ROUTERADVERT @@ -158,6 +161,10 @@ the name of the interface. the protocol that triggered the event. .It Ev $reason as described above. +.It Ev $message +the RFC 2132 Message option (code 56) included with a +.Dv NAK +reason, if present. .It Ev $pid the pid of .Nm dhcpcd . diff --git a/src/dhcp.c b/src/dhcp.c index 078f6927..adbc48c1 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -3271,6 +3271,10 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len, if (state->state == DHS_INFORM) /* INFORM should not be NAKed */ return; if (!(ifp->ctx->options & DHCPCD_TEST)) { + if (state->message) + free(state->message); + state->message = get_option_string(ifp->ctx, bootp, + bootp_len, DHO_MESSAGE); dhcp_drop(ifp, "NAK"); dhcp_unlink(ifp->ctx, state->leasefile); } @@ -3914,6 +3918,7 @@ dhcp_free(struct interface *ifp) free(state->new); free(state->offer); free(state->clientid); + free(state->message); free(state); ifp->if_data[IF_DATA_DHCP] = NULL; } diff --git a/src/dhcp.h b/src/dhcp.h index 5dbea7d5..0cc6566d 100644 --- a/src/dhcp.h +++ b/src/dhcp.h @@ -236,6 +236,7 @@ struct dhcp_state { #ifdef ARPING ssize_t arping_index; #endif + char *message; /* RFC 2132 option 56 from DHCPv4 NAK */ }; #ifdef INET diff --git a/src/script.c b/src/script.c index e059472e..3108aea8 100644 --- a/src/script.c +++ b/src/script.c @@ -470,6 +470,18 @@ make_env(struct dhcpcd_ctx *ctx, const struct interface *ifp, if_up = false_str; if_down = true_str; } +#ifdef INET + if (strcmp(reason, "NAK") == 0) { + struct dhcp_state *dstate = D_STATE(ifp); + + if (dstate != NULL && dstate->message != NULL) { + if (efprintf(fp, "message=%s", dstate->message) == -1) + goto eexit; + free(dstate->message); + dstate->message = NULL; + } + } +#endif if (efprintf(fp, "if_up=%s", if_up) == -1) goto eexit; if (efprintf(fp, "if_down=%s", if_down) == -1)