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

📄 dhcp-icmp-discovery.c

📁 this is sample about DHCP-agent
💻 C
字号:
/* $Header: /cvsroot/dhcp-agent/dhcp-agent/src/dhcp-icmp-discovery.c,v 1.5 2003/06/08 22:14:16 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. * * ICMP discovery routines: *  * subnet discovery, and rtt discovery by icmp echo requests. *  */#define MODULE_NAME "dhcp-icmp-discovery"#include "dhcp-local.h"#include "dhcp-libutil.h"#include "dhcp-librawnet.h"/* Check for icmp mask response. */static int icmp_check_mask_reply(void *arg){    rawnet_t *net = arg;    if((net->type = RAWNET_ICMP) && (icmp_get_type(net->icmp_p) == ICMP_MASKREPLY))        return 1;    else        return 0;}/* Discover subnet mask: * If discovered fill in subnet_mask and return 0. * Otherwise return 1 */int icmp_subnet_mask_discovery(rawnet_t *net, int retries, uint32_t *subnet_mask){    uint32_t reply_mask;    int retval;    /* Build ICMP mask request packet. We don't actually care     * about sequence or IDs since we'll accept the first     * response on our subnet regardless. Still let's be nice to     * the mask repliers and set them up anyway. */    build_icmp_mask_request(net, 0, 0);    if(retries <= 0) { /* let's not get hosed shall we? */        ERROR_MESSAGE("bad number of retries: %d", retries);        return -1;    }    while(retries--) {        retval =            rawnet_packet_transact(net, net, NULL, icmp_check_mask_reply,                                   RECOMMENDED_MAX_SECS_WAIT);        switch (retval) {        case RAWNET_TIMEOUT:            break;        case RAWNET_ERROR:            ERROR_MESSAGE("received error from raw network handler.");            return -1;        case RAWNET_OK:            /* A reply should contain the subnet mask. If we're actually             * doing subnet mask discovery we assume any subnet mask             * returned is valid. */            reply_mask = icmp_mask_get_mask(net->icmp_p);            memcpy(subnet_mask, &reply_mask, IP_ADDR_LEN);            return 0;        case RAWNET_USER_INTERRUPT:            FATAL_MESSAGE("user interrupt. bailing out!");        default:            FATAL_MESSAGE("invalid return value from raw network handler -- this a bug report it.");        }    }    ERROR_MESSAGE("timeout on icmp subnet discovery.");    return -1;}/* Check for icmp echo reply. */static int icmp_check_echo_reply(void *arg){    rawnet_t *net = arg;    if((net->type == RAWNET_ICMP) && (icmp_get_type(net->icmp_p) == ICMP_ECHOREPLY))        return 1;    else        return 0;}/* Send out an echo request per retries to get latency of host. */int icmp_do_echo(rawnet_t *net, ip_addr_t dest_addr, eth_addr_t dest_mac){    uint16_t id, seq;    struct timeval before, after, difference;    int latency;    id = get_random_uint16();    seq = 1;    build_icmp_echo_request(net, net->cip_addr, dest_addr, net->chw_addr, dest_mac, id, seq);    gettimeofday(&before, NULL);    if(rawnet_packet_transact(net, net, NULL, icmp_check_echo_reply, RECOMMENDED_MAX_SECS_WAIT)) {        /* on a timeout we set the latency to -1 */        return -1;    }    gettimeofday(&after, NULL);    difference = timeval_diff(before, after);    latency = (difference.tv_sec * 1000);    latency += (difference.tv_usec / 1000);    return latency;}/*  * ICMP Round Trip Time (RTT) Discovery: Here we're interested in * how long it takes to get a response from a list of addresses. * We return a list of unsigned integers representing the latency * of each host followed by the address of the host. * */list_t *icmp_rtt_discovery(rawnet_t *net, int sends, int timeout, int arp_retries, int arp_timeout, list_t *addresses){    list_t *rtts;    int *latency, *average_latency;    int send_count, unreachable_count, highest_latency;    ip_addr_t *host_addr, *host_addr_copy;    eth_addr_t dest_mac;    rtts = list_create();    /* Our algorithm works as such: send out an ICMP echo request     * and wait for a reply. We count the total number of     * milliseconds we waited as the latency time. We keep doing     * this per the packet_count. If we don't get a reply we keep     * doing per number of retries. If we run out of retries we     * return -1 as the latency signifying an unreliable     * address. */    list_rewind(addresses);    while((host_addr = list_next(addresses)) != NULL) {        /* We need to arp for MAC address first. Call         * arp_discover_hardware_address for that. */        if(route_find(net, arp_retries, arp_timeout, *host_addr, &dest_mac)) {            WARN_MESSAGE("could not find route for address for %s -- skipping",                         rawnet_network_address_to_string_static(*host_addr));            continue;        }        /* allocate latency array. */        latency = xmalloc(sizeof(int) * sends);        send_count = 0;        /* fill up our latency array. */        for(send_count = 0; send_count < sends; send_count++)            latency[send_count] = icmp_do_echo(net, *(host_addr), dest_mac);        /* This part is a little tricky. We want to make sure         * the host is actually up first. So if we got all -1's         * we know it wasn't. Then if it is up we set the -1         * latencies (indicating we never got an answer) to the         * largest latency multiplied by two. This severely hurts         * a host's average, but it's the right thing to do as         * long as we're doing it fairly to everyone. */        /* check our latency if it's all -1 */        unreachable_count = 0;        for(send_count = 0; send_count < sends; send_count++) {            if(latency[send_count] == -1)                unreachable_count++;        }        average_latency = xmalloc(sizeof(int));        if(unreachable_count == send_count) { /* the host is                                               * unreachable. */            /* host is unreachable give it an average of -1. */            *average_latency = -1;        } else {            if(unreachable_count) { /* the host didn't                                       respond to some of our                                       packets in time. */                /* get highest. */                highest_latency = 0;                for(send_count = 0; send_count < sends; send_count++) {                    if(latency[send_count] > highest_latency)                        highest_latency = latency[send_count];                }                /* replace unreachables with highest multiplied by two */                for(send_count = 0; send_count < sends; send_count++) {                    if(latency[send_count] == -1)                        latency[send_count] = highest_latency * 2;                }            }            /* now we can get the average. */            *average_latency = 0;            for(send_count = 0; send_count < sends; send_count++) {                *average_latency += latency[send_count];            }            *average_latency /= sends;        }        xfree(latency); /* free our latency array. */        list_add_to_end(rtts, average_latency);        host_addr_copy = xmalloc(sizeof(IP_ADDR_LEN));        memcpy(host_addr_copy, host_addr, IP_ADDR_LEN);        list_add_to_end(rtts, host_addr_copy);    }    return rtts;}

⌨️ 快捷键说明

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