⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcp-client-states.c

📁 this is sample about DHCP-agent
💻 C
📖 第 1 页 / 共 3 页
字号:
    if(passed_ip == NULL) {        FATAL_MESSAGE("No IP address passed. Cannot perform system configuration.");    }    if(memcmp(&interface_ip,  passed_ip, IP_ADDR_LEN)) {        INFO_MESSAGE("using ARP to detect address collision");        if(!arp_discover_hardware_address(dc->rawnet, 1, 5, *passed_ip,                                          &eth_addr)) {            ERROR_MESSAGE("DHCP server assigned us a used address. Declining.");            client_decline(dc);            /* sleep for up to ten seconds: fixme: make this configurable. */            INFO_MESSAGE("sleeping before retry (for %"PRIu16" seconds)", 10);            client_cache_delete_cache(dc->cache);            sleep_random(10);            return STATE_INIT;        }    }    /* since we're going to use this address, let's reply for it     * and let everyone know we're using it. */    if(client_broadcast_arp_reply(dc, *passed_ip) < 0) {        return STATE_FATAL_ERROR;    }    client_setup_timers(dc);    do_sysconf(options, dc, STATE_SETUP);    dhcp_opt_destroy_option_list(options);    return STATE_BOUND;}/* utility state: call this if reinitializing our client control * useful when recreating the control (e.g. after a fork). */int client_reinitialize(dhcp_client_control_t *dc){    client_setup_timers(dc);    return 0;}/****************** * check routines * ******************//* check the requested options */static int client_check_requested_options(dhcp_client_control_t *dc){    eth_addr_t eth_addr;    ip_addr_t ip_addr;    char *eth_addr_string;    char *ip_addr_string;    uint8_t *required_options;    uint8_t received_options[MAX_OPTIONS_HANDLED_NUM];    dhcp_opt_t *dhcp_option;    int i;    /* get the mac address, and ip address from the packet. */    ip_addr = ip_get_src_addr(dc->rawnet->ip_p);    eth_addr = eth_get_src_addr(dc->rawnet->ether_p);    /* find out if we have a list of required options. */    required_options = client_conf_get_opt_required_bit_array(dc->conf, ip_addr, eth_addr);    if(required_options == NULL) {        WARN_MESSAGE("no required options set. accepting first response.");        return 1;    }     /* build our received options array. */    memset(received_options, 0, sizeof(received_options));    dhcp_reset_option_seek(dc->rawnet->dhcp_p);    while((dhcp_option = dhcp_get_next_option(dc->rawnet->dhcp_p)) != NULL) {                /* if it's in our range fill it in or ignore it and give a warning. */        if(dhcp_opt_get_tag(dhcp_option) > MAX_OPTIONS_HANDLED) {            WARN_MESSAGE("ignoring received option tag which is out of our range: %d", dhcp_opt_get_tag(dhcp_option));            continue;        }        received_options[dhcp_opt_get_tag(dhcp_option)] = 1;    }    /* make sure everything in our required option list is in our requested option list. */    for(i = 0;i < MAX_OPTIONS_HANDLED;i++) {        if(required_options[i] && !received_options[i]) {            /* make the strings of the addresses. */            eth_addr_string = eth_addr_to_string(eth_addr);            ip_addr_string = ip_addr_to_string(ip_addr);            WARN_MESSAGE("ignoring offer from server (%s : %s) : failed to supply required option: %s",                          ip_addr_string, eth_addr_string, dhcp_option_printable_string_get(i));            xfree(ip_addr_string);            xfree(eth_addr_string);            return 0;        }    }    return 1;}/* basic DHCP test on incoming rawnet packet. */static int client_check_dhcp(dhcp_client_control_t *dc){    /* check for generic dhcp response.       * we check for type,     * validity, matching xid, and      * matching server source port  */    /* is rawnet happy with the packet? */    if(((!rawnet_is_valid(dc->rawnet)) &&        /* is it a DHCP packet? */        (dc->rawnet->type != RAWNET_DHCP) &&        /* does the XID match up? */        (dhcp_get_xid(dc->rawnet->dhcp_p) != dc->xid) &&        /* is it from a server? */        (udp_get_src_port(dc->rawnet->udp_p) != dc->server_port)))        return 0;    /* great: valid dhcp response. */    return 1;}/* check for valid discover responses. */static int client_check_discover(void *arg){    dhcp_client_control_t *dc = arg;    /* check for a valid dhcp packet. */    if(client_check_dhcp(dc) &&       /* check that the type is an offer. */       dhcp_is_type(dc->rawnet->dhcp_p, DHCP_OFFER_TM) &&       /* check if the requested options match what we want. */       client_check_requested_options(dc)) {        return 1;    }  else  {        return 0;    }}/* check for valid request responses. */static int client_check_request(void *arg){    dhcp_client_control_t *dc = arg;    if(client_check_dhcp(dc) &&       (dhcp_is_type(dc->rawnet->dhcp_p, DHCP_DHCPACK_TM) ||        dhcp_is_type(dc->rawnet->dhcp_p, DHCP_DHCPNAK_TM)))        return 1;    else        return 0;}/* check for valid renew response. */static int client_check_renew(void *arg){    /* we're expecting the same as request :-) */    return (client_check_request(arg));}/* check for valid renew response. */static int client_check_rebind(void *arg){    /* we're expecting the same as request :-) */    return (client_check_request(arg));}/*************************** * client states           * ***************************//* we have an offered lease we want and are selecting it. */int client_select(dhcp_client_control_t *dc){       list_t *dump_options;    ip_addr_t yiaddr, siaddr;    INFO_MESSAGE("performing DHCP SELECT");    /* This is not relay agent friendly: FIXME later. */    /* get the address on the packet as the server ip and hardware address. */    dhcp_client_set_server_ip_address(dc, ip_get_src_addr(dc->rawnet->ip_p));    dhcp_client_set_server_hw_address(dc, eth_get_src_addr(dc->rawnet->ether_p));    /* get the yiaddr/siaddr fields. */    yiaddr = dhcp_get_yiaddr(dc->rawnet->dhcp_p);    siaddr = dhcp_get_siaddr(dc->rawnet->dhcp_p);    /* if these options haven't been set, we can set them ourselves from the yiaddr/siaddr. */    if(!dhcp_have_option(dc->rawnet->dhcp_p, TAG_DHCP_REQUESTED_IP_ADDRESS)) {                list_add(dc->rawnet->dhcp_p->options,                 dhcp_opt_create_from_internal_data(TAG_DHCP_REQUESTED_IP_ADDRESS,                                                    &yiaddr,                                                     IP_ADDR_LEN));    }    if(!dhcp_have_option(dc->rawnet->dhcp_p, TAG_DHCP_SERVER_IDENTIFIER)) {        list_add(dc->rawnet->dhcp_p->options,                  dhcp_opt_create_from_internal_data(TAG_DHCP_SERVER_IDENTIFIER,                                                    &siaddr,                                                    IP_ADDR_LEN));    }    /* before dumping options strip options we never want to dump */    dump_options = client_remove_protocol_only_options(dc->rawnet->dhcp_p->options);    /* dump cache file. */    if(client_cache_dump_options(dc->cache, dump_options)) {        ERROR_MESSAGE("could not create temporary cache.");        return STATE_FATAL_ERROR;    }    dhcp_opt_destroy_option_list(dump_options);    return STATE_REQUEST;}/* init state: no lease exists. */int client_init(dhcp_client_control_t *dc){    list_t *options;    int retval;    int retries, timeout;    uint8_t received_response = 0;    INFO_MESSAGE("attempting DHCP DISCOVER");    /* get the number of retries we will attempt. */    retries = client_conf_get_dhcp_discovery_retries(dc->conf);    timeout = client_conf_get_dhcp_discover_timeout(dc->conf);    /* build discovery option list. */    options = client_build_discover_option_list(dc);    /* when we begin transmitting discover we setup our secs     * field.  this is because relay agents and dhcp servers can     * use this to see how bad off we are. */    dhcp_client_reset_secs(dc);    /* update new xid per start of discovery . */    dhcp_client_update_xid(dc);    /* build our dhcp discover packet. */    build_dhcp_discover(dc->rawnet, dc->xid, dc->secs, options);    while(retries--) {        retval = rawnet_packet_transact(dc->rawnet, dc, client_update_packet,                                        client_check_discover, timeout);        switch (retval) {        case RAWNET_TIMEOUT:            break;        case RAWNET_OK:            received_response = 1;            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(received_response) /* if we got a response that passed our filters (and is good enough)                                 then break here. */            break;    }    if(received_response) {        /* just call client_select to select the lease and store the information. */        return client_select(dc);    } else {        /* otherwise we're out of retries and have not received a lease. */        return STATE_NO_LEASES;    }}static int client_requesting_proc(dhcp_client_control_t *dc, int state){    list_t *options, *cache_options;    int retval;    int retries, timeout;    uint8_t received_response = 0;    INFO_MESSAGE("attempting DHCP REQUEST");    /* get number of retries we should attempt with DHCP REQUEST. */    retries = client_conf_get_dhcp_request_retries(dc->conf);    timeout = client_conf_get_dhcp_request_timeout(dc->conf);    /* Build options along with the options in our cache. */    options = client_build_request_option_list(dc);    if(state == STATE_INIT_REBOOT)        cache_options = client_cache_load_options(dc->cache, 0); /* get cache. */    else        cache_options = client_cache_load_options(dc->cache, 1); /* get temporary cache. */    list_join(options, cache_options); /* destroys cache_options. */    build_dhcp_request_broadcast(dc->rawnet, dc->xid, dc->secs, 0, 0, options);    while(retries--) {        retval =            rawnet_packet_transact(dc->rawnet, dc, NULL, client_check_request,                                   timeout);        switch (retval) {        case RAWNET_TIMEOUT:            break; /* timeout, do a retry. */        case RAWNET_OK:            received_response = 1;            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(received_response)            break;    }    /* check for a valid response. */    if(received_response) {        /* if we got a pack we're good to go, if we haven't         * then we need to revert to discover state after waiting at least ten seconds. */        if(dhcp_is_type(dc->rawnet->dhcp_p, DHCP_DHCPACK_TM)) {            /* if init-reboot then record the server which replied. */            if(state == STATE_INIT_REBOOT) {                dhcp_client_set_server_ip_address(dc, ip_get_src_addr(dc->rawnet->ip_p));                dhcp_client_set_server_hw_address(dc, eth_get_src_addr(dc->rawnet->ether_p));            } else                client_cache_update(dc->cache);            return STATE_SETUP;        } else {            /* anything is else NACK because of our earlier test on the packet. */            INFO_MESSAGE("received NACK response to request. waiting for retry.");            client_cache_delete_tmp_cache(dc->cache);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -