perform_carrier() should not cause ifchd to terminate on failure.

This requires execute_buffer() and its callers to distinguish between
fatal and non-fatal errors.  The -99 return value was already used for
non-recoverable errors that should force the daemon to restart, but the
execute_buffer() callers treated any non-success return as a fatal
error.

There a judgement call here on how to handle various error types.  I
choose to assume that failures to set the IP address, netmask, broadcast
address, or default router are fatal errors.  ndhc should be run from
process supervision, and this will trigger a daemon restart, which will
allow the machine to recover as soon as the problem (probably on the
dhcp server or local kernel state outside of ndhc's control) is
corrected.

This change corrects errors such as:

Discovering DHCP servers...
(process_client_socket) received invalid commands: 'carrier:;'
(send_dhcp_raw) carrier down; sendto would fail
Failed to send a discover request packet.

which happened if ndhc is started on a machine where the network
interface is down.  After this change, ndhc should function as intended
by going to sleep until the carrier returns rather than terminating
itself to be restarted by the process supervisor until carrier returns.
This commit is contained in:
Nicholas J. Kain 2015-07-03 00:49:13 -04:00
parent 12d8af4c67
commit e0b5ff8eaf
3 changed files with 26 additions and 19 deletions

View File

@ -129,23 +129,27 @@ static int perform_ip4set(const char buf[static 1], size_t len)
}
action Dispatch {
int pr = 0;
switch (cl.state) {
case STATE_IP4SET: cmdf |= perform_ip4set(tb, arg_len); break;
case STATE_TIMEZONE: cmdf |= perform_timezone( tb, arg_len); break;
case STATE_ROUTER: cmdf |= perform_router(tb, arg_len); break;
case STATE_DNS: cmdf |= perform_dns(tb, arg_len); break;
case STATE_LPRSVR: cmdf |= perform_lprsvr(tb, arg_len); break;
case STATE_HOSTNAME: cmdf |= perform_hostname(tb, arg_len); break;
case STATE_DOMAIN: cmdf |= perform_domain(tb, arg_len); break;
case STATE_IPTTL: cmdf |= perform_ipttl(tb, arg_len); break;
case STATE_MTU: cmdf |= perform_mtu(tb, arg_len); break;
case STATE_NTPSVR: cmdf |= perform_ntpsrv(tb, arg_len); break;
case STATE_WINS: cmdf |= perform_wins(tb, arg_len); break;
case STATE_CARRIER: cmdf |= perform_carrier(); break;
case STATE_IP4SET: pr = perform_ip4set(tb, arg_len); break;
case STATE_TIMEZONE: pr = perform_timezone( tb, arg_len); break;
case STATE_ROUTER: pr = perform_router(tb, arg_len); break;
case STATE_DNS: pr = perform_dns(tb, arg_len); break;
case STATE_LPRSVR: pr = perform_lprsvr(tb, arg_len); break;
case STATE_HOSTNAME: pr = perform_hostname(tb, arg_len); break;
case STATE_DOMAIN: pr = perform_domain(tb, arg_len); break;
case STATE_IPTTL: pr = perform_ipttl(tb, arg_len); break;
case STATE_MTU: pr = perform_mtu(tb, arg_len); break;
case STATE_NTPSVR: pr = perform_ntpsrv(tb, arg_len); break;
case STATE_WINS: pr = perform_wins(tb, arg_len); break;
case STATE_CARRIER: pr = perform_carrier(); break;
default:
log_line("error: invalid state in dispatch_work");
return -99;
}
if (pr == -99)
return -99;
cmdf |= pr;
}
terminator = ';' > Dispatch;

View File

@ -292,10 +292,12 @@ static void process_client_socket(void)
client_config.interface, __func__, strerror(errno));
}
if (execute_buffer(buf) < 0) {
int ebr = execute_buffer(buf);
if (ebr < 0) {
inform_execute('-');
suicide("%s: (%s) received invalid commands: '%s'",
client_config.interface, __func__, buf);
if (ebr == -99)
suicide("%s: (%s) received invalid commands: '%s'",
client_config.interface, __func__, buf);
} else
inform_execute('+');
}

View File

@ -339,7 +339,7 @@ int perform_carrier(void)
}
if (link_flags_get(fd, &flags) < 0)
goto fail_fd;;
goto fail_fd;
if ((flags & IFF_RUNNING) && (flags & IFF_UP))
ret = 0;
fail_fd:
@ -519,7 +519,7 @@ int perform_ip_subnet_bcast(const char str_ipaddr[static 1],
const char *str_bcast)
{
struct in_addr ipaddr, subnet, bcast;
int fd, r, ret = -1;
int fd, r, ret = -99;
uint8_t prefixlen;
if (inet_pton(AF_INET, str_ipaddr, &ipaddr) <= 0) {
@ -583,6 +583,7 @@ int perform_ip_subnet_bcast(const char str_ipaddr[static 1],
client_config.interface);
if (link_set_flags(fd, IFF_UP | IFF_RUNNING) < 0) {
ret = -1;
log_error("%s: (%s) Failed to set link to be up and running.",
client_config.interface, __func__);
goto fail_fd;
@ -597,7 +598,7 @@ fail:
int perform_router(const char str_router[static 1], size_t len)
{
int ret = -1;
int ret = -99;
if (len < 7)
goto fail;
struct in_addr router;
@ -631,7 +632,7 @@ fail:
int perform_mtu(const char str[static 1], size_t len)
{
unsigned int mtu;
int fd, ret = -1;
int fd, ret = -99;
if (len < 2)
goto fail;