📄 dhcp-client-states.c
字号:
/* sleep for up to ten seconds: fixme: make this configurable. */ INFO_MESSAGE("sleeping before retry (for %"PRIu16" seconds)", 10); sleep_random(10); INFO_MESSAGE("retrying."); return STATE_INIT; } } else { /* we timed out. retry immediately. */ INFO_MESSAGE("timed out on DHCP REQUEST. attempting DISCOVER again."); client_cache_delete_tmp_cache(dc->cache); return STATE_INIT; }}/* init-reboot state: lease exists, try to acquire it. */int client_init_reboot(dhcp_client_control_t *dc){ return client_requesting_proc(dc, STATE_INIT_REBOOT);}/* request: request a lease. */int client_requesting(dhcp_client_control_t *dc){ return client_requesting_proc(dc, STATE_INIT);}/* inform: we've assigned ourselves an IP address, try to inform a dhcp server. */int client_inform(dhcp_client_control_t *dc){ /* not implemented. */ return 0;}/* rebind: try to reacquire the lease. */int client_rebinding(dhcp_client_control_t *dc){ list_t *options; int retval; ip_addr_t my_addr; INFO_MESSAGE("attempting DHCP REBIND"); my_addr = rawnet_get_ip_addr(dc->rawnet); options = client_build_rebind_option_list(dc); build_dhcp_request_broadcast(dc->rawnet, dc->xid, dc->secs, my_addr, 0, options); retval = rawnet_packet_transact(dc->rawnet, dc, NULL, client_check_rebind, compensate_timeout_with_timer(dc)); switch (retval) { case RAWNET_TIMEOUT: return STATE_BOUND; /* no response. we've timed out. */ case RAWNET_OK: break; case RAWNET_ERROR: ERROR_MESSAGE("received error from raw network handler."); return STATE_FATAL_ERROR; case RAWNET_USER_INTERRUPT: ERROR_MESSAGE("caught user interrupt."); return STATE_USER_INTERRUPT; default: FATAL_MESSAGE("invalid return value from raw network handler -- this a bug report it."); } if(dhcp_is_type(dc->rawnet->dhcp_p, DHCP_DHCPACK_TM)) { /* our lease is OK. reconfigure timers. */ client_setup_timers(dc); return STATE_BOUND; } else if(dhcp_is_type(dc->rawnet->dhcp_p, DHCP_DHCPNAK_TM)) { /* we've been told our lease is no good. */ /* unconfigure everything including our interface. */ client_unconfigure(dc); /* delete our cache. */ client_cache_delete_cache(dc->cache); return STATE_INIT; } else { ERROR_MESSAGE("received neither NACK nor ACK -- this should never happen because of higher filters."); FATAL_MESSAGE("I shouldn't be here. this is a bug report me."); exit(1); /* get rid of compiler warning. */ }}/* renew: try to renew the lease. */int client_renewing(dhcp_client_control_t *dc){ list_t *options; int retval; ip_addr_t my_addr; INFO_MESSAGE("attempting DHCP RENEW"); my_addr = rawnet_get_ip_addr(dc->rawnet); options = client_build_renew_option_list(dc); build_dhcp_request_unicast(dc->rawnet, dc->xid, dc->secs, options, my_addr, dhcp_client_get_server_ip_address(dc), 0, dhcp_client_get_server_hw_address(dc)); /* find out how much time we have until the next timer. * if we have no other timers it's an error, however * it will be caught later now just do our best. */ retval = rawnet_packet_transact(dc->rawnet, dc, NULL, client_check_renew, compensate_timeout_with_timer(dc)); switch (retval) { case RAWNET_TIMEOUT: return STATE_BOUND; /* no response: we've timed out. */ case RAWNET_OK: break; case RAWNET_ERROR: ERROR_MESSAGE("received error from raw network handler."); return STATE_FATAL_ERROR; case RAWNET_USER_INTERRUPT: ERROR_MESSAGE("caught user interrupt."); return STATE_USER_INTERRUPT; default: FATAL_MESSAGE ("dhcp-client-states: invalid return value from raw network handler -- this a bug report it."); } if(dhcp_is_type(dc->rawnet->dhcp_p, DHCP_DHCPACK_TM)) { /* our lease is OK. reconfigure timers. */ client_setup_timers(dc); return STATE_BOUND; } else if(dhcp_is_type(dc->rawnet->dhcp_p, DHCP_DHCPNAK_TM)) { /* we've been told our lease is no good. */ /* unconfigure everything including our interface. */ client_unconfigure(dc); /* delete our cache. */ client_cache_delete_cache(dc->cache); return STATE_INIT; } else { ERROR_MESSAGE("received neither NACK nor ACK -- this should never happen because of higher filters."); FATAL_MESSAGE("I shouldn't be here. this is a bug report me."); exit(1); /* get rid of compiler warning. */ }}/* we're bound and should wait for lease expiry or timers. */int client_bound(dhcp_client_control_t *dc){ uint32_t next_timer = 0; /* get rid of compiler warnings. */ time_t time_before = 0; /* get rid of compiler warnings. */ time_t time_after, time_interval; INFO_MESSAGE("entering WAIT stage"); /* take our raw network connection down. */ rawnet_down(dc->rawnet); if(dc->lease_time_is_infinite) { INFO_MESSAGE("lease time is infinite. waiting forever."); /* wait for any interrupts. */ suspend_for_interrupts(); } else { /* peek and store our next timer in case we get an interrupt * which is not a timer interrupt. */ next_timer = timer_peek_next_timer(dc->context->timer); time_before = time(NULL); /* now fire off the next timer. */ if(timer_set_next(dc->context->timer)) { FATAL_MESSAGE("no timers set. we should have at least one for lease expiry sent to us from the server."); } /* wait for any interrupts: we're OK. there is no race * condition here since our suspension will unmask us * and allow any previous signals to affect us here. */ suspend_for_interrupts(); } /* at this point we may or may not have received a timer * interrupt. if we have not then setup a timer to go off * once we return by storing a new timer with the time * difference. */ if(peek_interrupt_type() != INTERRUPT_ALARM && !dc->lease_time_is_infinite) { time_after = time(NULL); time_interval = time_after - time_before; /* number of seconds elapsed. */ if(time_interval < 0) { /* someone has been b0rking the system clock. */ WARN_MESSAGE("the system clock is skewed or you've been messing with it. i'm going to just use the next timer and hope for the best."); } else { /* we did not receive a timer interrupt. * put the difference as the next timer to go off. */ next_timer -= time_interval; /* this is safe since we're promoting the type * and it can never be < 0 */ if(next_timer == 0) next_timer = 1; /* give at least one second. */ /* we just set our next timer to atleast one. this * has one implication. if we're firing off other * signals to the daemon (HUP for example) all the * time it will never get the alarm. opinion: you * shouldn't HUP your daemon constantly. otherwise * we at most lag by one second which is not bad. */ timer_add_trigger(dc->context->timer, next_timer, timer_get_current_id(dc->context->timer)); } } /* bring the raw network devices back up. we'll probably * need them: FIXME, revamp into one network module that uses * raw or user level networking depending on our interface's * state. */ rawnet_up(dc->rawnet); return STATE_BOUND; /* we want to return back to this state if the interrupt wasn't an alarm. */}/* release a lease. */int client_release(dhcp_client_control_t *dc){ list_t *cache_options, *options; ip_addr_t *my_addr = NULL; ip_addr_t ciaddr; dhcp_opt_t *option; INFO_MESSAGE("sending DHCP RELEASE"); cache_options = client_cache_load_options(dc->cache, 0); list_rewind(cache_options); while((option = list_next(cache_options)) != NULL) { if(dhcp_opt_get_tag(option) == TAG_DHCP_REQUESTED_IP_ADDRESS) { my_addr = dhcp_opt_get_host_data(option); break; } } if(my_addr == NULL) { /* if empty, don't release. */ dhcp_opt_destroy_option_list(cache_options); return STATE_FATAL_ERROR; } ciaddr = *my_addr; dhcp_opt_destroy_option_list(cache_options); options = client_build_release_option_list(dc); build_dhcp_release(dc->rawnet, dc->xid, options, ciaddr, dhcp_client_get_server_ip_address(dc), dhcp_client_get_server_hw_address(dc)); if(rawnet_send_packet(dc->rawnet) < 0) { ERROR_MESSAGE("could not send RELEASE."); return STATE_FATAL_ERROR; } /* called from do_shutdown() so no real state returned. * however if we do take the return value into consideration * we should handle it as an error. */ return STATE_FATAL_ERROR;}/* perform system configuration. */int client_setup(dhcp_client_control_t *dc){ INFO_MESSAGE("entering SETUP stage"); return client_configure(dc);}/* do a shutdown. */int client_shutdown(dhcp_client_control_t *dc){ INFO_MESSAGE("shutting down."); if(dc) { /* only do clean up if we can. */ /* send our a release only if we have a cache. */ if(!client_cache_is_empty(dc->cache)) client_release(dc); /* unconfigure everything including our interface. */ client_unconfigure(dc); /* since we're releasing the lease we should down the interface */ INFO_MESSAGE("bringing down interface."); rawnet_down(dc->rawnet); rawnet_interface_down(dc->rawnet); /* delete the PID file. */ file_delete_pid(dc->interface); /* delete our cache. */ client_cache_delete_cache(dc->cache); client_cache_delete_tmp_cache(dc->cache); dhcp_client_control_destroy(dc); } exit(0);}/* decline a lease. */int client_decline(dhcp_client_control_t *dc){ list_t *options, *decline_options; dhcp_opt_t *option; ip_addr_t *passed_ip = NULL; INFO_MESSAGE("performing DHCP decline"); options = client_cache_load_options(dc->cache, 0); list_rewind(options); while((option = list_next(options)) != NULL) { if(dhcp_opt_get_tag(option) == TAG_DHCP_REQUESTED_IP_ADDRESS) { passed_ip = dhcp_opt_get_host_data(option); break; } } if(passed_ip == NULL) { FATAL_MESSAGE("no address assigned and we're trying to decline. this is a bug, report me."); } decline_options = client_build_decline_option_list(dc, *passed_ip); dhcp_opt_destroy_option_list(options); build_dhcp_decline(dc->rawnet, dc->xid, dc->secs, decline_options); if(rawnet_send_packet(dc->rawnet) < 0) { ERROR_MESSAGE("could not send DECLINE."); return STATE_FATAL_ERROR; } /* a lot like release, our return here shouldn't matter since * we are most likely called within a state. if not then the * state simply shouldn't be handled. */ return STATE_FATAL_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -