Thread: [Dhcp-agent-commits] CVS: dhcp-agent dhcp-arp-discovery.c,NONE,1.1 COST,1.5,1.6 Makefile.am,1.12,1.1
Status: Alpha
Brought to you by:
actmodern
From: Thamer Al-H. <act...@us...> - 2002-02-25 01:39:33
|
Update of /cvsroot/dhcp-agent/dhcp-agent In directory usw-pr-cvs1:/tmp/cvs-serv26529 Modified Files: COST Makefile.am Makefile.in THANKS TODO dhcp-agent.h dhcp-arp.c dhcp-icmp-discovery.c dhcp-interface.c dhcp-net.c dhcp-packet-build.c dhcp-util.c Added Files: dhcp-arp-discovery.c Log Message: now working with libdnet-current; added more icmp discovery routines and arping routines; small fixes and some code clean up (need more); --- NEW FILE: dhcp-arp-discovery.c --- /* $Header: /cvsroot/dhcp-agent/dhcp-agent/dhcp-arp-discovery.c,v 1.1 2002/02/25 01:39:29 actmodern Exp $ * * Copyright 2001 Thamer Alharbash <tm...@wh...> * * 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. * */ #include <dhcp-agent.h> /* Accept a list of arguments. Will contain rawnet first, and * then the ip address we're interested in. */ static int check_for_arp_reply(void *data) { rawnet_t *net; unsigned char *addr, *received_addr; list_t *argument_list = data; net = argument_list->data; if(argument_list->next) addr = argument_list->next->data; else { warn_message("check arp reply: no address passed to function -- skipping"); return 0; } received_addr = arp_get_sender_protocol_address(net->arp_p); /* check for arp type, header length, type, address lengths, * and op type. */ if((net->type == RAWNET_ARP) && (arp_get_hardware_type(net->arp_p) == ARP_HRD_ETH) && (arp_get_protocol_type(net->arp_p) == ARP_PRO_IP) && (arp_get_hardware_len(net->arp_p) == ETH_ADDR_LEN) && (arp_get_protocol_len(net->arp_p) == IP_ADDR_LEN) && (arp_get_op(net->arp_p) == ARP_OP_REPLY)) { /* now check if its the address we're looking for */ if(!memcmp(addr, received_addr, IP_ADDR_LEN)) return 1; /* yes! address match */ else return 0; /* nope we got another response. */ } return 0; /* not the right kind of packet. */ } extern int arp_discover_hardware_address(rawnet_t *net, int retries, uint32_t address, eth_addr_t *mac_addr) { list_t *arg_list = NULL; unsigned char *sender_addr; arg_list = add_to_list(arg_list, &address); arg_list = add_to_list(arg_list, net); build_arp_request(net, 0, address, net->hw_addr); /* 0 for source ip, address to discover for dest, * our hardware address so we get a reply back. */ while(retries--) { if(rawnet_packet_transact(net, arg_list, NULL, check_for_arp_reply)) continue; /* Yummy! We got a valid reply! */ sender_addr = arp_get_sender_hardware_address(net->arp_p); memcpy(mac_addr->data, &sender_addr, ETH_ADDR_LEN); /* just free up pair. FIXME: this isn't good because we're * breaking the list blackbox. we need a better way to do this. * the datums don't need to be freed since we keep them on the stack. */ xfree(arg_list->next); xfree(arg_list); return 0; } /* FIXME: ditto (see above) */ xfree(arg_list->next); xfree(arg_list); /* no response, return error. */ return 1; } Index: COST =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/COST,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** COST 15 Feb 2002 09:19:52 -0000 1.5 --- COST 25 Feb 2002 01:39:29 -0000 1.6 *************** *** 1,10 **** In writing dhcp-agent I suffered the following: ! Feb - March 2001 (Current values as of the Feb 14) ! 24 pots of coffee; 132 camel filter cigarettes; 12 diet cokes (cutting down); 845 mp3s (thanks stephanie); 18 historical trips to the wash room; 16 showers; lost one pretty geekette; got one ! job offer; moving up in the world... Jan - Feb 2001 --- 1,11 ---- In writing dhcp-agent I suffered the following: ! Feb - March 2001 (Current values as of the Feb 24) ! 83 pots of coffee; 211 camel filter cigarettes; 35 diet cokes (cutting down); 845 mp3s (thanks stephanie); 18 historical trips to the wash room; 16 showers; lost one pretty geekette; got one ! job offer; got one pretty geekette; startin' to feel some justice ! in this world; Jan - Feb 2001 Index: Makefile.am =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/Makefile.am,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** Makefile.am 17 Feb 2002 04:37:35 -0000 1.12 --- Makefile.am 25 Feb 2002 01:39:29 -0000 1.13 *************** *** 20,26 **** dhcp-interface.c dhcp-client-conf.c @DHCP_SNPRINTF@ dhcp-files.c \ dhcp-client-states.c dhcp-options-strings.c dhcp-convert.c \ ! dhcp-sysconf.c dhcp-rtt.c dhcp-packet-build.c dhcp-icmp-discovery.c ! dhcpclient_LDADD = @PCAP_LIB@ @DNET_LIB@ -lefence noinst_HEADERS = dhcp-agent.h config.h --- 20,27 ---- dhcp-interface.c dhcp-client-conf.c @DHCP_SNPRINTF@ dhcp-files.c \ dhcp-client-states.c dhcp-options-strings.c dhcp-convert.c \ ! dhcp-sysconf.c dhcp-rtt.c dhcp-packet-build.c dhcp-icmp-discovery.c \ ! dhcp-arp-discovery.c ! dhcpclient_LDADD = @PCAP_LIB@ @DNET_LIB@ noinst_HEADERS = dhcp-agent.h config.h Index: Makefile.in =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/Makefile.in,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** Makefile.in 17 Feb 2002 04:37:35 -0000 1.12 --- Makefile.in 25 Feb 2002 01:39:29 -0000 1.13 *************** *** 83,90 **** dhcpsniff_LDADD = @PCAP_LIB@ @DNET_LIB@ ! dhcpclient_SOURCES = dhcp-client.c dhcp-util.c dhcp-align.c dhcp-net.c dhcp-list.c dhcp-com.c dhcp-eth.c dhcp-ip.c dhcp-udp.c dhcp-arp.c dhcp-icmp.c dhcp-log.c dhcp-daemon.c dhcp-client-cache.c dhcp-cache-entry.c dhcp-client-control.c dhcp-interface.c dhcp-client-conf.c @DHCP_SNPRINTF@ dhcp-files.c dhcp-client-states.c dhcp-options-strings.c dhcp-convert.c dhcp-sysconf.c dhcp-rtt.c dhcp-packet-build.c dhcp-icmp-discovery.c ! dhcpclient_LDADD = @PCAP_LIB@ @DNET_LIB@ -lefence noinst_HEADERS = dhcp-agent.h config.h --- 83,90 ---- dhcpsniff_LDADD = @PCAP_LIB@ @DNET_LIB@ ! dhcpclient_SOURCES = dhcp-client.c dhcp-util.c dhcp-align.c dhcp-net.c dhcp-list.c dhcp-com.c dhcp-eth.c dhcp-ip.c dhcp-udp.c dhcp-arp.c dhcp-icmp.c dhcp-log.c dhcp-daemon.c dhcp-client-cache.c dhcp-cache-entry.c dhcp-client-control.c dhcp-interface.c dhcp-client-conf.c @DHCP_SNPRINTF@ dhcp-files.c dhcp-client-states.c dhcp-options-strings.c dhcp-convert.c dhcp-sysconf.c dhcp-rtt.c dhcp-packet-build.c dhcp-icmp-discovery.c dhcp-arp-discovery.c ! dhcpclient_LDADD = @PCAP_LIB@ @DNET_LIB@ noinst_HEADERS = dhcp-agent.h config.h *************** *** 115,119 **** dhcp-client-conf.o dhcp-files.o dhcp-client-states.o \ dhcp-options-strings.o dhcp-convert.o dhcp-sysconf.o dhcp-rtt.o \ ! dhcp-packet-build.o dhcp-icmp-discovery.o dhcpclient_DEPENDENCIES = dhcpclient_LDFLAGS = --- 115,119 ---- dhcp-client-conf.o dhcp-files.o dhcp-client-states.o \ dhcp-options-strings.o dhcp-convert.o dhcp-sysconf.o dhcp-rtt.o \ ! dhcp-packet-build.o dhcp-icmp-discovery.o dhcp-arp-discovery.o dhcpclient_DEPENDENCIES = dhcpclient_LDFLAGS = *************** *** 136,141 **** TAR = tar GZIP_ENV = --best ! DEP_FILES = .deps/dhcp-align.P .deps/dhcp-arp.P \ ! .deps/dhcp-cache-entry.P .deps/dhcp-client-cache.P \ .deps/dhcp-client-conf.P .deps/dhcp-client-control.P \ .deps/dhcp-client-states.P .deps/dhcp-client.P .deps/dhcp-com.P \ --- 136,141 ---- TAR = tar GZIP_ENV = --best ! DEP_FILES = .deps/dhcp-align.P .deps/dhcp-arp-discovery.P \ ! .deps/dhcp-arp.P .deps/dhcp-cache-entry.P .deps/dhcp-client-cache.P \ .deps/dhcp-client-conf.P .deps/dhcp-client-control.P \ .deps/dhcp-client-states.P .deps/dhcp-client.P .deps/dhcp-com.P \ Index: THANKS =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/THANKS,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** THANKS 15 Feb 2002 02:00:24 -0000 1.3 --- THANKS 25 Feb 2002 01:39:29 -0000 1.4 *************** *** 9,13 **** http://www.fiction.net/blong/programs/snprintf.c ! -- Dug Song, and the others behind libdnet. -- The Tcpdump Group for their work on libpcap --- 9,14 ---- http://www.fiction.net/blong/programs/snprintf.c ! -- Dug Song, and the others behind libdnet for their code and the ! support given to make sure dhcp-agent worked well with libdnet. -- The Tcpdump Group for their work on libpcap Index: TODO =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/TODO,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** TODO 16 Feb 2002 17:54:33 -0000 1.10 --- TODO 25 Feb 2002 01:39:29 -0000 1.11 *************** *** 51,53 **** address. check, fix, clean. -- clean up dhcp-packet-build.c ! -- need a proper rtt featured re/send/accept routine for raw packets. \ No newline at end of file --- 51,66 ---- address. check, fix, clean. -- clean up dhcp-packet-build.c ! -- need a proper rtt featured re/send/accept routine for raw packets. ! -- in arp discovery we're using a list to pass two arguments. we ! should use something else, or have list routines specific to ! this. ! -- the rawnet routines should be a shared library due to too many ! dependencies. the sniffer for example, only needs the packet ! parsing routines. ! -- net->hw_addr is broken. i don't like it being at that level. ! we should always specify our hardware address at a higher ! level on a per-use basis and thus give us control over ! how much Marla is faking it. ! -- would be nice to have more unpredictable random numbers ! by using devices like /dev/urandom explicitly if available. ! -- fix overflow issue in dhcp-icmp-discovery (icmp_do_echo) Index: dhcp-agent.h =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/dhcp-agent.h,v retrieving revision 1.30 retrieving revision 1.31 diff -C2 -d -r1.30 -r1.31 *** dhcp-agent.h 17 Feb 2002 04:37:35 -0000 1.30 --- dhcp-agent.h 25 Feb 2002 01:39:29 -0000 1.31 *************** *** 162,165 **** --- 162,169 ---- #define MAX_VERBOSITY_LEVEL DEBUG_VERBOSITY_LEVEL + /* default configuration */ + + #define DISCOVER_OFFER_RETRIES 3 + /* * * * * * * * * * * * Data structures. * *************** *** 217,230 **** typedef struct { ! dhcphdr fixedheader; ! uint32_t magic_cookie; ! list_t *options; ! list_t *options_seek; } dhcp_obj; - /* default configuration */ - - #define DISCOVER_OFFER_RETRIES 3 - /* * Other packet objects. --- 221,230 ---- typedef struct { ! dhcphdr fixedheader; /* DHCP fixed header. */ ! uint32_t magic_cookie; /* Magic cookie. */ ! list_t *options; /* Option list. */ ! list_t *options_seek; /* Seek pointer to option list. */ } dhcp_obj; /* * Other packet objects. *************** *** 266,283 **** typedef struct { - - /* Internal members. - * Not to be messed about with directly. */ ! pcap_t *pcap; /* packet capturing device. */ ! int pcap_fd; /* file des we can select on */ ! eth_t *eth; /* ethernet device. */ ! char *device; /* device name. */ ! char *packet_data; /* internal packet data. */ ! int packet_len; /* total length of packet. */ ! struct timeval tstamp; /* timestamp. */ ! uint16_t src_port, ! dst_port; /* udp ports for writing packets. */ ! eth_addr_t hw_addr; /* used for faking client mac address. */ int promiscious; /* run in promiscious mode flag. */ --- 266,287 ---- typedef struct { ! /* we should not interface directly with any of these members ! * above the rawnet layer. */ ! ! pcap_t *pcap; /* packet capturing device (pcap). */ ! int pcap_fd; /* file descriptor we can select on for pcap. */ ! eth_t *eth; /* ethernet device handler (libdnet). */ ! ! uint16_t src_port, dst_port; /* udp ports for writing packets. */ ! char *device; /* device name. */ ! ! char *packet_data; /* packet data. */ ! int packet_len; /* total length of packet. */ ! ! struct timeval tstamp; /* timestamp. */ ! ! eth_addr_t hw_addr; /* our hardware address. */ ! ip_addr_t ip_addr; /* our ip address. */ int promiscious; /* run in promiscious mode flag. */ *************** *** 326,330 **** unsigned char options[MAX_OPTIONS_HANDLED]; /* which options should we handle. */ ! int discover_offer_retries; /* amount of times we're willing to keep rediscovering before giving up. */ } client_conf_t; --- 330,336 ---- unsigned char options[MAX_OPTIONS_HANDLED]; /* which options should we handle. */ ! int discover_offer_retries; /* amount of times we're willing to keep ! * rediscovering before giving up. */ ! } client_conf_t; *************** *** 346,351 **** rawnet_t *rawnet; /* raw network handle */ ! client_cache_t *cache; /* cache */ ! client_conf_t *conf; /* configuration. */ uint32_t xid; /* unique xid */ --- 352,357 ---- rawnet_t *rawnet; /* raw network handle */ ! client_cache_t *cache; /* cache */ ! client_conf_t *conf; /* configuration. */ uint32_t xid; /* unique xid */ *************** *** 354,363 **** uint32_t renewal_time; /* when to renew lease (secs). */ ! interface_control_t *interface_control; ! char *interface; ! unsigned char *class_id, *client_id; ! unsigned char *client_hw_addr; ! int state; ! int discover_offer_retries; } dhcp_client_control_t; --- 360,369 ---- uint32_t renewal_time; /* when to renew lease (secs). */ ! interface_control_t *interface_control; /* interface handler. */ ! char *interface; /* interface name. */ ! unsigned char *class_id, *client_id; /* client_id, class_id */ ! unsigned char *client_hw_addr; /* our hardware address. */ ! int state; /* our current state. */ ! int discover_offer_retries; /* how many times we should discover/offer before giving up. */ } dhcp_client_control_t; *************** *** 498,509 **** extern void build_dhcp_request(rawnet_t *net, uint32_t xid, time_t secs, list_t *options); extern void build_arp_reply_broadcast(rawnet_t *net, uint32_t source_addr, ! eth_addr_t source_hw_addr); extern void build_arp_reply(rawnet_t *net, ! uint32_t source_addr, ! uint32_t dest_addr, ! eth_addr_t source_hw_addr, ! eth_addr_t dest_hw_addr); extern void build_unarp(rawnet_t *net, uint32_t source_addr, ! eth_addr_t source_hw_addr); extern void rawnet_dhcp_update(rawnet_t *net, time_t seconds); --- 504,522 ---- extern void build_dhcp_request(rawnet_t *net, uint32_t xid, time_t secs, list_t *options); extern void build_arp_reply_broadcast(rawnet_t *net, uint32_t source_addr, ! eth_addr_t source_hw_addr); ! extern void build_arp_reply(rawnet_t *net, ! uint32_t source_addr, ! uint32_t dest_addr, ! eth_addr_t source_hw_addr, ! eth_addr_t dest_hw_addr); ! ! extern void build_arp_request(rawnet_t *net, ! uint32_t source_addr, ! uint32_t dest_addr, ! eth_addr_t source_hw_addr); ! extern void build_unarp(rawnet_t *net, uint32_t source_addr, ! eth_addr_t source_hw_addr); extern void rawnet_dhcp_update(rawnet_t *net, time_t seconds); *************** *** 514,517 **** --- 527,533 ---- extern void build_icmp_mask_request(rawnet_t *net, uint32_t id, uint32_t seq); extern void build_icmp_mask_reply(rawnet_t *net, uint32_t id, uint32_t seq, uint32_t subnet_mask); + extern void build_icmp_echo_request(rawnet_t *net, ip_addr_t source_addr, ip_addr_t dest_addr, + eth_addr_t source_mac, eth_addr_t dest_mac, uint32_t id, + uint32_t seq); extern int rawnet_up(rawnet_t *net); *************** *** 522,525 **** --- 538,550 ---- int (*check)(void *arg)); + /* droppage in rawnet is probably wrong -- but we'll clean up later (FIXME) */ + extern char *network_address_to_string_static(uint32_t addr); + + /* ICMP discovery routines. */ + extern int icmp_subnet_mask_discovery(rawnet_t *net, int retries, uint32_t *subnet_mask); + + /* ARP discovery routines. */ + extern int arp_discover_hardware_address(rawnet_t *net, int retries, uint32_t address, eth_addr_t *mac_addr); + /* Daemon routines. */ *************** *** 558,561 **** --- 583,587 ---- extern int is_string(const char *string, int len); extern int get_random(void); + extern struct timeval timeval_diff(struct timeval begin, struct timeval end); /* Replacement vsnprintf, snprintf if needed. */ *************** *** 717,720 **** --- 743,754 ---- extern void arp_set_target_hardware_address(arp_obj *arp, eth_addr_t addr); extern void arp_set_target_protocol_address(arp_obj *arp, uint32_t addr); + + extern uint16_t arp_get_op(arp_obj *arp); + extern uint16_t arp_get_hardware_type(arp_obj *arp); + extern uint16_t arp_get_protocol_type(arp_obj *arp); + extern uint8_t arp_get_hardware_len(arp_obj *arp); + extern uint8_t arp_get_protocol_len(arp_obj *arp); + extern unsigned char *arp_get_sender_hardware_address(arp_obj *arp); + extern unsigned char *arp_get_sender_protocol_address(arp_obj *arp); /* UDP obj routines. */ Index: dhcp-arp.c =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/dhcp-arp.c,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** dhcp-arp.c 3 Feb 2002 16:56:00 -0000 1.6 --- dhcp-arp.c 25 Feb 2002 01:39:29 -0000 1.7 *************** *** 96,99 **** --- 96,136 ---- } + /* get routines. */ + + uint16_t arp_get_op(arp_obj *arp) + { + return(arp->header.ar_op); + } + + uint16_t arp_get_hardware_type(arp_obj *arp) + { + return(ntohs(arp->header.ar_hrd)); + } + + uint16_t arp_get_protocol_type(arp_obj *arp) + { + return(ntohs(arp->header.ar_pro)); + } + + uint8_t arp_get_hardware_len(arp_obj *arp) + { + return(arp->header.ar_hln); + } + + uint8_t arp_get_protocol_len(arp_obj *arp) + { + return(arp->header.ar_pln); + } + + unsigned char *arp_get_sender_hardware_address(arp_obj *arp) + { + return(arp->arp_data.ar_sha); + } + + unsigned char *arp_get_sender_protocol_address(arp_obj *arp) + { + return(arp->arp_data.ar_spa); + } + /* dump image to packet. */ void arp_write_packet_image(arp_obj *arp, unsigned char *packet) Index: dhcp-icmp-discovery.c =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/dhcp-icmp-discovery.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** dhcp-icmp-discovery.c 17 Feb 2002 04:37:35 -0000 1.1 --- dhcp-icmp-discovery.c 25 Feb 2002 01:39:29 -0000 1.2 *************** *** 1,3 **** --- 1,4 ---- /* $Header$ + * * Copyright 2001 Thamer Alharbash <tm...@wh...> * *************** *** 22,27 **** * ICMP discovery routines: * ! * We currently have code for subnet mask discovery, and ! * discovery of host with least latency. * */ --- 23,27 ---- * ICMP discovery routines: * ! * subnet discovery, and rtt discovery by icmp echo requests. * */ *************** *** 47,51 **** */ ! int icmp_subnet_mask_discovery(rawnet_t *net, uint32_t *subnet_mask) { uint32_t reply_mask; --- 47,51 ---- */ ! int icmp_subnet_mask_discovery(rawnet_t *net, int retries, uint32_t *subnet_mask) { uint32_t reply_mask; *************** *** 58,66 **** build_icmp_mask_request(net, 0, 0); ! if(rawnet_packet_transact(net, net, NULL, icmp_check_mask_reply)) { ! error_message("icmp mask discovery: timeout on discovery"); return -1; } /* A reply should contain the subnet mask. If we're actually * doing subnet mask discovery we assume any subnet mask --- 58,73 ---- build_icmp_mask_request(net, 0, 0); ! if(retries <= 0) /* let's not get hosed shall we? */ { ! error_message("icmp mask discovery: bad number of retries"); return -1; } + while(retries--) { + if(rawnet_packet_transact(net, net, NULL, icmp_check_mask_reply)) { + error_message("icmp mask discovery: timeout on discovery"); + return -1; + } + } + /* A reply should contain the subnet mask. If we're actually * doing subnet mask discovery we assume any subnet mask *************** *** 71,73 **** --- 78,251 ---- return 0; + } + + /* Check for icmp mask response. */ + + 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, int retries) + { + uint32_t id, seq; + struct timeval before, after, difference; + int latency; + + id = get_random(); + seq = 0; + + while(retries--) { + + /* we need to rebuild each time for different sequence + numbers. */ + + seq++; + build_icmp_echo_request(net, net->ip_addr, dest_addr, net->hw_addr, dest_mac, id, seq); + + gettimeofday(&before, NULL); + if(rawnet_packet_transact(net, net, NULL, icmp_check_echo_reply)) { + /* on a timeout we set the latency to -1 */ + continue; + } + gettimeofday(&after, NULL); + difference = timeval_diff(before, after); + + /* milliseconds are accurate enough for us. + * FIXME: the integer may overflow if our + * rtt mechanism is setup to wait for too long before a + * timeout. */ + + latency = (difference.tv_sec * 1000); + latency += (difference.tv_usec/1000); + + return latency; + } + + return -1; + + } + + /* + * 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 giving + * us the average rtt time for each address. + * + */ + + /* FIXME: we need to underengineer this code. */ + list_t *icmp_rtt_discovery(rawnet_t *net, int retries, int sends, list_t *addresses) + { + list_t *rtts = NULL; + int *latency, *average_latency; + int send_count, unreachable_count, highest_latency; + ip_addr_t *host_addr; + eth_addr_t dest_mac; + + if(retries <= 0 || sends <= 0) { /* let's not get hosed shall we? */ + error_message("icmp rtt discovery: received invalid retry or send count."); + return NULL; + } + + /* 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. */ + + /* loop per address. */ + for(;addresses;addresses = addresses->next) { + + host_addr = addresses->data; + + /* We need to arp for MAC address first. Call + * arp_discover_hardware_address for that. */ + + if(arp_discover_hardware_address(net, retries, *host_addr, &dest_mac)) { + /* No arp reply. Skip. */ + warn_message("icmp rtt discovery: could not ARP for address for %s -- skipping", network_address_to_string_static(*host_addr)); + break; + } + + /* We have the MAC address here. Run + * icmp_get_echo_latency to get latency. This also tells + * us if the host is up. */ + + + /* 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, retries); + + /* This part is a little tricky. We want to make sure + * the host is actually up first. So if we got al -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. + * FIXME: we do need a better way to deal with this. */ + + /* 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; + } + + rtts = add_to_list(rtts, average_latency); + } + + return rtts; } Index: dhcp-interface.c =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/dhcp-interface.c,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** dhcp-interface.c 16 Feb 2002 17:54:33 -0000 1.12 --- dhcp-interface.c 25 Feb 2002 01:39:29 -0000 1.13 *************** *** 93,99 **** if(addr != INADDR_ANY) { ! ic->interface_entry.intf_addr->addr_type = ADDR_TYPE_IP; ! addr_mtob(&netmask, IP_ADDR_LEN, &ic->interface_entry.intf_addr->addr_bits); ! memcpy(&ic->interface_entry.intf_addr->addr_ip, &addr, IP_ADDR_LEN); } --- 93,100 ---- if(addr != INADDR_ANY) { ! ic->interface_entry.intf_addr.addr_type = ADDR_TYPE_IP; ! addr_mtob(&netmask, IP_ADDR_LEN, ! &ic->interface_entry.intf_addr.addr_bits); ! memcpy(&ic->interface_entry.intf_addr.addr_ip, &addr, IP_ADDR_LEN); } *************** *** 133,139 **** if(interface_get_info(ic)) return -1; ! ! memcpy(addr, &ic->interface_entry.intf_addr->addr_ip, IP_ADDR_LEN); ! return 0; } --- 134,140 ---- if(interface_get_info(ic)) return -1; ! ! memcpy(addr, &ic->interface_entry.intf_addr.addr_ip, IP_ADDR_LEN); ! return 0; } Index: dhcp-net.c =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/dhcp-net.c,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** dhcp-net.c 16 Feb 2002 17:54:33 -0000 1.15 --- dhcp-net.c 25 Feb 2002 01:39:30 -0000 1.16 *************** *** 63,66 **** --- 63,79 ---- #include <dhcp-agent.h> + /* variation on network_addr_to_string in dhcp-convert.c we use + * this when we don't want to run around freeing results up, and + * know that it will be statically stored. Useful for insertion + * in message log routines. */ + + char *network_address_to_string_static(uint32_t addr) + { + struct in_addr in; + in.s_addr = addr; + + return(inet_ntoa(in)); + } + /* Get port number for named service. */ Index: dhcp-packet-build.c =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/dhcp-packet-build.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** dhcp-packet-build.c 15 Feb 2002 02:00:24 -0000 1.1 --- dhcp-packet-build.c 25 Feb 2002 01:39:30 -0000 1.2 *************** *** 133,144 **** * * * * * * * * * * * */ ! /* build ethernet header with broadcast destination address. */ ! static void build_eth_broadcast(rawnet_t *net, ! eth_addr_t client_hw_addr, ! uint16_t type) ! { ! eth_set_dst_address(net->ether_p, eth_broadcast); ! eth_set_src_address(net->ether_p, client_hw_addr); eth_set_type(net->ether_p, type); --- 133,143 ---- * * * * * * * * * * * */ ! static void build_eth(rawnet_t *net, ! eth_addr_t source_hw_addr, ! eth_addr_t dest_hw_addr, ! uint16_t type) { ! eth_set_dst_address(net->ether_p, dest_hw_addr); ! eth_set_src_address(net->ether_p, source_hw_addr); eth_set_type(net->ether_p, type); *************** *** 146,149 **** --- 145,156 ---- } + /* build ethernet header with broadcast destination address. */ + static void build_eth_broadcast(rawnet_t *net, eth_addr_t source_hw_addr, uint16_t type) + + { + build_eth(net, source_hw_addr, eth_broadcast, type); + return; + } + /* * * * * * * * * * * * * ARP/UNARP Routines. * *************** *** 196,203 **** /* Build ARP reply. */ void build_arp_reply(rawnet_t *net, ! uint32_t source_addr, ! uint32_t dest_addr, ! eth_addr_t source_hw_addr, ! eth_addr_t dest_hw_addr) { build_arp_proc(net, ARP_OP_REPLY, source_hw_addr, source_addr, dest_hw_addr, dest_addr); --- 203,210 ---- /* Build ARP reply. */ void build_arp_reply(rawnet_t *net, ! uint32_t source_addr, ! uint32_t dest_addr, ! eth_addr_t source_hw_addr, ! eth_addr_t dest_hw_addr) { build_arp_proc(net, ARP_OP_REPLY, source_hw_addr, source_addr, dest_hw_addr, dest_addr); *************** *** 205,208 **** --- 212,226 ---- } + /* Build ARP request. */ + void build_arp_request(rawnet_t *net, + uint32_t source_addr, + uint32_t dest_addr, + eth_addr_t source_hw_addr) + + { + build_arp_proc(net, ARP_OP_REQUEST, source_hw_addr, source_addr, eth_broadcast, dest_addr); + return; + } + /* Build ARP reply with broadcast destination hardware address. */ void build_arp_reply_broadcast(rawnet_t *net, uint32_t source_addr, eth_addr_t source_hw_addr) *************** *** 210,214 **** build_arp_reply(net, source_addr, ip_addr_broadcast, ! source_hw_addr, eth_broadcast); return; } --- 228,232 ---- build_arp_reply(net, source_addr, ip_addr_broadcast, ! source_hw_addr, eth_broadcast); return; } *************** *** 232,236 **** * * * * * * * * * * * * * * * */ ! static void build_ip_broadcast(rawnet_t *net, uint16_t ip_len, uint8_t protocol) { ip_set_hl(net->ip_p, IP_HDR_LEN); --- 250,255 ---- * * * * * * * * * * * * * * * */ ! static void build_ip(rawnet_t *net, uint16_t ip_len, uint8_t protocol, ! ip_addr_t source_addr, ip_addr_t dest_addr) { ip_set_hl(net->ip_p, IP_HDR_LEN); *************** *** 244,249 **** /* Do checksum later. */ ! ip_set_source_addr(net->ip_p, 0); ! ip_set_dest_addr(net->ip_p, ip_addr_broadcast); return; --- 263,276 ---- /* Do checksum later. */ ! ip_set_source_addr(net->ip_p, source_addr); ! ip_set_dest_addr(net->ip_p, dest_addr); ! ! return; ! } ! ! static void build_ip_broadcast(rawnet_t *net, uint16_t ip_len, uint8_t protocol, ip_addr_t source_addr) ! { ! ! build_ip(net, ip_len, protocol, source_addr, ip_addr_broadcast); return; *************** *** 345,349 **** build_eth_broadcast(net, net->hw_addr, ETH_TYPE_IP); ! build_ip_broadcast(net, ip_len, IP_PROTO_UDP); build_udp(net, udp_len); build_dhcp(net, xid, secs, net->hw_addr, ciaddr, yiaddr, siaddr, giaddr, options, bootp_type); --- 372,376 ---- build_eth_broadcast(net, net->hw_addr, ETH_TYPE_IP); ! build_ip_broadcast(net, ip_len, IP_PROTO_UDP, 0); build_udp(net, udp_len); build_dhcp(net, xid, secs, net->hw_addr, ciaddr, yiaddr, siaddr, giaddr, options, bootp_type); *************** *** 402,406 **** build_eth_broadcast(net, net->hw_addr, ETH_TYPE_IP); ! build_ip_broadcast(net, ip_len, IP_PROTO_ICMP); build_icmp_mask_proc(net, ICMP_MASK, id, seq, 0); --- 429,433 ---- build_eth_broadcast(net, net->hw_addr, ETH_TYPE_IP); ! build_ip_broadcast(net, ip_len, IP_PROTO_ICMP, 0); build_icmp_mask_proc(net, ICMP_MASK, id, seq, 0); *************** *** 417,422 **** build_eth_broadcast(net, net->hw_addr, ETH_TYPE_IP); ! build_ip_broadcast(net, ip_len, IP_PROTO_ICMP); build_icmp_mask_proc(net, ICMP_MASK, id, seq, subnet_mask); net->type = RAWNET_ICMP; --- 444,476 ---- build_eth_broadcast(net, net->hw_addr, ETH_TYPE_IP); ! build_ip_broadcast(net, ip_len, IP_PROTO_ICMP, 0); build_icmp_mask_proc(net, ICMP_MASK, id, seq, subnet_mask); + + net->type = RAWNET_ICMP; + net->packet_len = ETH_HDR_LEN + ip_len; + + write_packet(net); + } + + static void build_icmp_echo_request_proc(rawnet_t *net, uint32_t id, uint32_t seq) + { + icmp_echo_set_id(net->icmp_p, seq); + icmp_echo_set_seq(net->icmp_p, seq); + + return; + } + + /* build icmp echo request. */ + void build_icmp_echo_request(rawnet_t *net, ip_addr_t source_addr, ip_addr_t dest_addr, + eth_addr_t source_mac, eth_addr_t dest_mac, uint32_t id, + uint32_t seq) + { + int ip_len = IP_HDR_LEN + + ICMP_HDR_LEN + 4; /* 4 bytes for vanilla icmp echo + request packet. */ + build_eth(net, source_mac, dest_mac, ETH_TYPE_IP); + build_ip(net, ip_len, IP_PROTO_ICMP, source_addr, dest_addr); + build_icmp_header_proc(net, ICMP_ECHO, 0); + build_icmp_echo_request_proc(net, id, seq); net->type = RAWNET_ICMP; Index: dhcp-util.c =================================================================== RCS file: /cvsroot/dhcp-agent/dhcp-agent/dhcp-util.c,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** dhcp-util.c 9 Feb 2002 15:50:30 -0000 1.8 --- dhcp-util.c 25 Feb 2002 01:39:30 -0000 1.9 *************** *** 439,440 **** --- 439,455 ---- return(random()); } + + struct timeval timeval_diff(struct timeval begin, struct timeval end) + { + struct timeval difference; + + if(begin.tv_usec > end.tv_usec) { + end.tv_sec--; + end.tv_usec += 1000000; + } + + difference.tv_sec = end.tv_sec - begin.tv_sec; + difference.tv_usec = end.tv_usec - begin.tv_usec; + + return difference; + } |