📄 dhcp-client-states.c
字号:
/* $Header: /cvsroot/dhcp-agent/dhcp-agent/src/dhcp-client-states.c,v 1.44 2003/06/28 17:50:06 actmodern Exp $ * * Copyright 2002 Thamer Alharbash <tmh@whitefang.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * These are the individual client state functions, * along with their utility routines. * */#define MODULE_NAME "dhcp-client-states"#include "dhcp-local.h"#include "dhcp-limits.h"#include "dhcp-libutil.h"#include "dhcp-librawnet.h"#include "dhcp-option.h"#include "dhcp-options-strings.h"#include "dhcp-client-conf.h"#include "dhcp-client-cache.h"#include "dhcp-client.h"#include "dhcp-sysconf.h"/*************************** * option list generation * ***************************//* create DISCOVER and REQUEST option list. */static list_t *client_build_option_list(dhcp_client_control_t *dc){ list_t *options; dhcp_opt_t *option; char *hostname_tmp; const char *hostname; uint16_t max_message_opt_data = MAX_MESSAGE_SIZE; options = list_create(); option = dhcp_opt_create_from_internal_data(TAG_DHCP_MAX_DHCP_SIZE, &max_message_opt_data, sizeof(max_message_opt_data)); list_add(options, option); /* client_id */ option = dhcp_opt_create_from_internal_data(TAG_DHCP_CLIENT_ID, dc->client_id, (ETH_ADDR_LEN + 1)); list_add(options, option); /* class_id */ option = dhcp_opt_create_from_internal_data(TAG_DHCP_VENDOR_CLASS_ID, dc->class_id, (strlen(dc->class_id) + 1)); list_add(options, option); /* hostname if available */ hostname = client_conf_get_hostname(dc->conf); if(hostname != NULL) { /* if we have one set it. */ /* can't pass const char pointer so copy to char pointer. * FIXME: audit types and fix any const propogation * problems like these properly. */ hostname_tmp = xstrdup(hostname); option = dhcp_opt_create_from_internal_data(TAG_DHCP_HOST_NAME, hostname_tmp, (strlen(hostname_tmp) + 1)); xfree(hostname_tmp); list_add(options, option); } return options;}/* create DHCP DISCOVER option list. */static list_t *client_build_discover_option_list(dhcp_client_control_t *dc){ list_t *options; list_t *requested_options; dhcp_opt_t *option; options = list_create(); option = dhcp_opt_create_parameter_request_list(client_conf_get_request_opt_bit_array(dc->conf)); if(option == NULL) { WARN_MESSAGE("sending without parameter request list"); } else { list_add(options, option); } /* dhcp message type. */ option = dhcp_opt_create_message_type(DHCP_DISCOVER_TM); list_add(options, option); requested_options = client_build_option_list(dc); list_join(options, requested_options); /* this destroys requested_options */ return options;}/* create DHCP REQUEST option list. */static list_t *client_build_request_option_list(dhcp_client_control_t *dc){ list_t *options; list_t *requested_options; dhcp_opt_t *option; options = list_create(); /* dhcp message type. */ option = dhcp_opt_create_message_type(DHCP_REQUEST_TM); list_add(options, option); requested_options = client_build_option_list(dc); list_join(options, requested_options); /* this destroys requested_options */ return options;}/* create DHCP RELEASE option list. */static list_t *client_build_release_option_list(dhcp_client_control_t *dc){ list_t *options; dhcp_opt_t *option; options = list_create(); /* client_id: RFC2131 says we MAY */ option = dhcp_opt_create_from_internal_data(TAG_DHCP_CLIENT_ID, dc->client_id, (ETH_ADDR_LEN + 1)); list_add(options, option); /* dhcp message type. */ option = dhcp_opt_create_message_type(DHCP_RELEASE_TM); list_add(options, option); return options;}static list_t *client_build_decline_option_list(dhcp_client_control_t *dc, ip_addr_t ip_address){ list_t *options; dhcp_opt_t *option; options = list_create(); /* client_id: RFC2131 says we MAY */ option = dhcp_opt_create_from_internal_data(TAG_DHCP_CLIENT_ID, dc->client_id, (ETH_ADDR_LEN + 1)); list_add(options, option); /* requested ip address: RFC2131 MUST. */ option = dhcp_opt_create_from_internal_data(TAG_DHCP_REQUESTED_IP_ADDRESS, &ip_address, IP_ADDR_LEN); list_add(options, option); /* dhcp message type. */ option = dhcp_opt_create_message_type(DHCP_DECLINE_TM); list_add(options, option); return options;}/* create DHCP RENEW option list. */static list_t *client_build_renew_option_list(dhcp_client_control_t *dc){ list_t *options; dhcp_opt_t *option; options = list_create(); /* dhcp message type. */ option = dhcp_opt_create_message_type(DHCP_REQUEST_TM); list_add(options, option); /* client_id */ option = dhcp_opt_create_from_internal_data(TAG_DHCP_CLIENT_ID, dc->client_id, (ETH_ADDR_LEN + 1)); list_add(options, option); return options;}/* create DHCP REBIND option list. */static list_t *client_build_rebind_option_list(dhcp_client_control_t *dc){ /* just call renew_option_list since it's the same. */ return (client_build_renew_option_list(dc));}/************* * ARP/UNARP * *************//* * Use this to send out a broadcast reply claiming that we own the * IP. To prevent a poisoned cache we use the actual interface hw * addr as opposed to any fake one we may have been passed. * */static int client_broadcast_arp_reply(dhcp_client_control_t *dc, ip_addr_t client_ip_addr){ eth_addr_t client_hw_addr; client_ip_addr = rawnet_get_ip_addr(dc->rawnet); rawnet_get_real_hw_addr(dc->rawnet, &client_hw_addr); build_arp_reply_broadcast(dc->rawnet, client_ip_addr, client_hw_addr); if(rawnet_send_packet(dc->rawnet) < 0) { ERROR_MESSAGE("could not transmit arp reply."); return -1; } return 0;}/* UNARP (rfc 1868). This makes us more network friendly. */static int client_broadcast_unarp(dhcp_client_control_t *dc){ ip_addr_t client_ip_addr; eth_addr_t client_hw_addr; client_ip_addr = rawnet_get_ip_addr(dc->rawnet); rawnet_get_real_hw_addr(dc->rawnet, &client_hw_addr); build_unarp(dc->rawnet, client_ip_addr, client_hw_addr); if(rawnet_send_packet(dc->rawnet) < 0) { ERROR_MESSAGE("could not transmit unarp."); return -1; } return 0;}/*************************** * utility routines * ***************************//* update secs field. can be called from rawnet_packet_transact */static void client_update_packet(void *arg){ dhcp_client_control_t *dc = arg; dhcp_client_update_secs(dc); rawnet_dhcp_update(dc->rawnet, (uint16_t)dc->secs); /* FIXME: this may be an integer overflow. */ return;}/* setup our timers. */static void client_setup_timers(dhcp_client_control_t *dc){ list_t *timer_options; timer_options = client_cache_load_timer_options(dc->cache, 0); if(list_get_len(timer_options) == 0) { FATAL_MESSAGE("no timers to setup. we should have least one: lease time"); exit(1); } do_sysconf_setup_timers(timer_options, dc); dhcp_opt_destroy_option_list(timer_options); return;}static time_t compensate_timeout_with_timer(dhcp_client_control_t *dc){ uint32_t next_timer; time_t timeout; /* we realize time_t may not be uint32_t, however we're only * going to set the max timeout if it is lower so this is * safe. we shouldn't overflow. */ next_timer = timer_peek_next_timer(dc->context->timer); if(next_timer < RECOMMENDED_MAX_SECS_WAIT) { if(next_timer != 0) timeout = next_timer / 2; else timeout = next_timer; } else { timeout = RECOMMENDED_MAX_SECS_WAIT; } return timeout;}/* make a new copy without options which are meant for protocol purposes only. */static list_t *client_remove_protocol_only_options(list_t *options){ dhcp_opt_t *option, *option_copy; list_t *non_protocol_opts; non_protocol_opts = list_create(); list_rewind(options); while((option = list_next(options)) != NULL) { switch(dhcp_opt_get_tag(option)) { case TAG_DHCP_MAX_DHCP_SIZE: case TAG_DHCP_MESSAGE_TYPE: case TAG_DHCP_OVERLOAD: break; default: option_copy = dhcp_option_copy(option); list_add(non_protocol_opts, option_copy); break; } } return non_protocol_opts;}/* utility routine that should zap our configuration and leave us * with an interface with no real address on it. */static void client_unconfigure(dhcp_client_control_t *dc){ list_t *options; ip_addr_t ip_addr; /* load our cache and call sysconf with DO_SHUTDOWN to * unconfigure us. */ options = client_cache_load_options(dc->cache, 0); do_sysconf(options, dc, STATE_SHUTDOWN); dhcp_opt_destroy_option_list(options); ip_addr = rawnet_get_ip_addr(dc->rawnet); /* check if we have a real address or not. */ if(ip_addr != 0) { /* call UNARP first. */ client_broadcast_unarp(dc); /* zap our ip address. */ rawnet_interface_up(dc->rawnet, 0, 0, CLIENT_DEFAULT_MTU, 1); } /* we're done. */ return;}/* this is called from setup: we should have a lease in our cache. */static int client_configure(dhcp_client_control_t *dc){ list_t *options; ip_addr_t interface_ip; ip_addr_t *passed_ip = NULL; eth_addr_t eth_addr; dhcp_opt_t *option; INFO_MESSAGE("performing system configuration"); options = client_cache_load_options(dc->cache, 0); if(list_get_len(options) == 0) { ERROR_MESSAGE("received empty configuration cache! cannot configure host"); return STATE_FATAL_ERROR; } /* Check if the address we've been assigned is in use. only * check if our interface address does not match the address * in our lease cache.*/ interface_ip = rawnet_get_ip_addr(dc->rawnet); 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; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -