[dhcp-agent-commits] dhcp-agent/src dhcp-rawnet.c,NONE,1.1 dhcp-librawnet.h,NONE,1.1
Status: Alpha
Brought to you by:
actmodern
From: <act...@us...> - 2002-11-03 16:39:25
|
Update of /cvsroot/dhcp-agent/dhcp-agent/src In directory usw-pr-cvs1:/tmp/cvs-serv32071 Added Files: dhcp-rawnet.c dhcp-librawnet.h Log Message: new rawnet code --- NEW FILE: dhcp-rawnet.c --- /* $Header: /cvsroot/dhcp-agent/dhcp-agent/src/dhcp-rawnet.c,v 1.1 2002/11/03 16:39:22 actmodern Exp $ * * Copyright 2002 Thamer Alharbash * * 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. * * Raw network module. * */ #define MODULE_NAME "dhcp-rawnet" #include <dhcp-rawnet.h> #include <dhcp-libutil.h> #include <dhcp-librawnet.h> #include <sys/ioctl.h> #include <sys/uio.h> #include <net/bpf.h> /************************ * Address Manipulation.* ************************/ /* get interface address. */ int rawnet_get_hw_addr(rawnet_t *net, eth_addr_t *addr) { /* are we using a fake address? */ if(net->fake_hw_addr != NULL) { memcpy(addr, net->fake_hw_addr->data, ETH_ADDR_LEN); return 0; } else { return(eth_get(net->eth, addr)); } } /* get real interface address skipping fake even if its available. */ int rawnet_get_real_hw_addr(rawnet_t *net, eth_addr_t *addr) { return(eth_get(net->eth, addr)); } /* get IP address. */ int rawnet_get_ip_addr(rawnet_t *net, ip_addr_t *addr) { return(interface_get_ip_addr(net->intf_handle, addr)); } /* get port number for named service. */ int rawnet_port_for_service(const char *serv, const char *proto) { struct servent *sv; setservent(0); if((sv = getservbyname(serv, proto)) == NULL) { ERROR_MESSAGE("rawnet: could not get service listing: %d", strerror(errno)); return -1; } return(sv->s_port); } /* * Initialization of packet capturing device. * */ static pcap_t *initialize_pcap_device(char *interface_name, char *filter_string, int promiscuous) { pcap_t *pcap; struct bpf_program filter; char errbuf[PCAP_ERRBUF_SIZE]; uint32_t mask = 0xffffffff; #if defined(HAVE_BPF_IMMEDIATE) int fd; u_int on = 1; #endif /* HAVE_BPF_IMMEDIATE */ /* Open packet capturing device. */ pcap = pcap_open_live(interface_name, SNAPLEN, promiscuous, 0, errbuf); if(pcap == NULL) { ERROR_MESSAGE("could not open pcap device: %s", pcap_geterr(pcap)); return NULL; } if(pcap_compile(pcap, &filter, filter_string, 1, mask) == -1) { ERROR_MESSAGE("could not compile pcap filter: %s", pcap_geterr(pcap)); pcap_close(pcap); return NULL; } if(pcap_setfilter(pcap, &filter) == -1) { ERROR_MESSAGE("could not compile pcap filter: %s", pcap_geterr(pcap)); pcap_close(pcap); return NULL; } pcap_freecode(&filter); #if defined(HAVE_BPF_IMMEDIATE) /* FreeBSD, and possibly other flavors with BPF need us to * set the descriptor non blocking with BIOCIMMEDIATE. */ if((fd = pcap_fileno(pcap)) < 0) { ERROR_MESSAGE("could not obtain pcap descriptor: %s", pcap_geterr(pcap)); pcap_close(pcap); return NULL; } if(ioctl(fd, BIOCIMMEDIATE, &on) < 0) { ERROR_MESSAGE("initialize_pcap_device", "could not set BIOCIMMEDIATE: %s", strerror(errno)); pcap_close(pcap); return NULL; } #endif /* HAVE_BPF_IMMEDIATE */ return pcap; } /* wrapper around interface handler routines. */ /* bring up interface, and assign ourselves the address passed. */ int rawnet_interface_up(rawnet_t *net, ip_addr_t addr, ip_addr_t netmask, int mtu) { if(interface_up(net->intf_handle, addr, netmask, mtu)) { ERROR_MESSAGE("could not bring interface up."); return -1; } memcpy(&net->cip_addr, &addr, IP_ADDR_LEN); /* set our IP address. */ return 0; } /* bring down interface. */ int rawnet_interface_down(rawnet_t *net) { if(interface_down(net->intf_handle)) { ERROR_MESSAGE("could not bring interface down."); return -1; } memset(&net->cip_addr, 0, IP_ADDR_LEN); /* clear our IP address -- this isn't very useful though. */ return 0; } /* Create the workhorse network module. */ rawnet_t *rawnet_create(const char *device, const char *filter, int dhcp_src_port, int dhcp_dst_port, int promiscuous) { rawnet_t *net; int retval; net = xcalloc(sizeof(rawnet_t)); net->src_port = dhcp_src_port; net->dst_port = dhcp_dst_port; net->device = xstrdup(device); net->pcap_filter = xstrdup(filter); net->packet_data = xcalloc(DEFAULT_MTU); /* XXX -- fixme make mtu configurable. */ net->promiscuous = promiscuous; /* get the interface handle for bringing it up or down and querying it. */ net->intf_handle = create_interface_control(net->device); if(net->intf_handle == NULL) { ERROR_MESSAGE("could not acquire interface handle"); rawnet_destroy(net); return NULL; } /* Is the interface up? */ retval = interface_is_up(net->intf_handle); if(retval == -1) { /* error on interface detection */ ERROR_MESSAGE("error on interface detection for device: %s", device); rawnet_destroy(net); return NULL; } if(retval == 0) { /* interface down */ /* bring it up with dum values. */ if(rawnet_interface_up(net, 0, 0xffffff, -1)) { ERROR_MESSAGE("error trying to bring device up: %s", device); rawnet_destroy(net); return NULL; } } /* any other value of retval and the interface is already up. */ /* Get the interface and make sure its an ethernet interface or * else we're hosed. */ net->eth = eth_open(device); if(net->eth == NULL) { ERROR_MESSAGE("device not available or supported: %s : %s", device, strerror(errno)); rawnet_destroy(net); return NULL; } /* get pcap handler */ net->pcap = initialize_pcap_device(net->device, net->pcap_filter, promiscuous); if(net->pcap == NULL) { ERROR_MESSAGE("could not initialize pcap device for: %s", device); return NULL; } net->pcap_fd = pcap_fileno(net->pcap); if(net->pcap_fd < 0) { ERROR_MESSAGE("could not get pcap descriptor for: %s: %s", device, pcap_geterr(net->pcap)); rawnet_destroy(net); return NULL; } /* When we first initialize we use a real hardware * address. This can be changed later to a fake hardware * address if the system supports it. */ rawnet_get_hw_addr(net, &net->chw_addr); rawnet_get_ip_addr(net, &net->cip_addr); /* Packet handler objects. * * These exit on failure. * */ net->ether_p = eth_create(); net->ip_p = ip_create(); net->arp_p = arp_create(); net->icmp_p = icmp_create(); net->udp_p = udp_create(); net->dhcp_p = dhcp_create(); return net; } /* Use a fake hardware address (diagnostic purposes). We need to * reinitialize our rawnet to use promiscuous packet capturing * since we do want to accept packets for this hardware * address. */ int rawnet_use_fake_hw_addr(rawnet_t *net, char *mac_string) { unsigned char mac_addr[ETH_ADDR_LEN]; net->fake_hw_addr = xmalloc(sizeof(eth_addr_t)); if(hex_string_to_value(mac_string, mac_addr)) { ERROR_MESSAGE("malformed mac address: %s", mac_string); xfree(net->fake_hw_addr); net->fake_hw_addr = NULL; return -1; } memcpy(net->chw_addr.data, mac_addr, ETH_ADDR_LEN); /* now reinitialize in promiscuous mode */ reinitialize_rawnet(net, 1); return 0; } void rawnet_destroy(rawnet_t *net) { if(net->eth != NULL) eth_close(net->eth); if(net->intf_handle) destroy_interface_control(net->intf_handle); if(net->pcap != NULL) pcap_close(net->pcap); if(net->device) xfree(net->device); if(net->packet_data) xfree(net->packet_data); if(net->pcap_filter) xfree(net->pcap_filter); if(net->ether_p) eth_destroy(net->ether_p); if(net->ip_p) ip_destroy(net->ip_p); if(net->arp_p) arp_destroy(net->arp_p); if(net->icmp_p) icmp_destroy(net->icmp_p); if(net->udp_p) udp_destroy(net->udp_p); if(net->dhcp_p) dhcp_destroy(net->dhcp_p); xfree(net); return; } /* The rawnet up and down routines don't mess with the interface * intentionally. They're meant only to close our packet capturing * and sending devices so as to free up system resources. */ /* Bring pcap/dnet up and down. * Useful for wait states when * we don't want our packet buffers * to fill up. */ void rawnet_down(rawnet_t *net) { if(net->pcap != NULL) { pcap_close(net->pcap); net->pcap = NULL; } if(net->eth != NULL) { eth_close(net->eth); net->eth = NULL; } return; } int rawnet_up(rawnet_t *net) { net->pcap = initialize_pcap_device(net->device, net->pcap_filter, net->promiscuous); if(net->pcap == NULL) { ERROR_MESSAGE("could not initialize pcap on device: %s", net->device); return -1; } if((net->pcap_fd = pcap_fileno(net->pcap)) < 0) { ERROR_MESSAGE("could not get pcap descriptor for: %s: %s", net->device, pcap_geterr(net->pcap)); rawnet_down(net); return -1; } net->eth = eth_open(net->device); if(net->eth == NULL) { ERROR_MESSAGE("could not get ethernet handler on device: %s", net->device); rawnet_down(net); return -1; } return 0; } void reinitialize_rawnet(rawnet_t *net, int promiscuous) { net->promiscuous = promiscuous; rawnet_down(net); rawnet_up(net); return; } /* * rawnet get packet: * we already expect a filter to only allow * the following types of packets: * ARP, UDP, and ICMP. * * Anything else is considered malformed. * */ int rawnet_get_packet(rawnet_t *net, struct timeval *tm) { const unsigned char *packet; struct pcap_pkthdr pkthdr; int len; fd_set read_set; int retval; net->type = RAWNET_UNKNOWN; while(1) { FD_ZERO(&read_set); FD_SET(net->pcap_fd, &read_set); retval = select((net->pcap_fd + 1), &read_set, NULL, NULL, tm); if(retval == 0) return RAWNET_TIMEOUT; if(retval < 0) return RAWNET_PCAP_ERROR; packet = pcap_next(net->pcap, &pkthdr); if(packet == NULL) continue; /* BPF may return 1 when there really isn't any packet for us. * is this because we're notified prior to filtering? * pcap only returns NULL on EWOULDBLOCK for bpf -- even though * in debugging I *never* get that errno value :| */ else break; } /* Set timestamp. */ #if defined(HAVE_BPF_TIMEVAL) /* This is an ugly hack -- why oh why did OpenBSD insist on * creating its own bpf_timeval struct with unsigned values * as opposed to the common UNIX timeval which has signed values. * * * *sigh* * * There really isn't any clean way around this apart from grabbing * our own timestamp instead of using the bpf one. This is inaccurate * but until OpenBSD fixes their braindamage they'll just have to * deal with the inaccuracy. Anything else would be too damaging * to the other UNIX flavors. */ gettimeofday(&net->tstamp, NULL); #else /* HAVE_BPF_TIMEVAL */ net->tstamp = pkthdr.ts; #endif /* HAVE_BPF_TIMEVAL */ /* Read ethernet header and switch on type. * * Fails if malformed or insufficient length. */ if(eth_read_packet_image(net->ether_p, packet, pkthdr.caplen) < 0) return RAWNET_MALFORMED_PACKET; packet += ETH_HDR_LEN; pkthdr.caplen -= ETH_HDR_LEN; switch(eth_get_type(net->ether_p)) { case ETH_TYPE_ARP: if(arp_read_packet_image(net->arp_p, packet, pkthdr.caplen) < 0) return RAWNET_MALFORMED_PACKET; net->type = RAWNET_ARP; return RAWNET_OK; case ETH_TYPE_IP: if(ip_read_packet_image(net->ip_p, packet, pkthdr.caplen) < 0) return RAWNET_MALFORMED_PACKET; len = ip_get_hl(net->ip_p); packet += len; pkthdr.caplen -= len; switch(ip_get_proto(net->ip_p)) { case IP_PROTO_UDP: if(udp_read_packet_image(net->udp_p, packet, pkthdr.caplen) < 0) return RAWNET_MALFORMED_PACKET; /* We assume any UDP packet does contain a DHCP packet. * So try and grab it here. */ packet += UDP_HDR_LEN; pkthdr.caplen -= UDP_HDR_LEN; /* purge dhcp so we get rid of old options. */ dhcp_purge(net->dhcp_p); if(dhcp_read_packet_image(net->dhcp_p, packet, pkthdr.caplen) < 0) return RAWNET_MALFORMED_PACKET; net->type = RAWNET_DHCP; return RAWNET_OK; case IP_PROTO_ICMP: if(icmp_read_packet_image(net->icmp_p, packet, pkthdr.caplen) < 0) return RAWNET_MALFORMED_PACKET; net->type = RAWNET_ICMP; return RAWNET_OK; default: break; } default: break; } return RAWNET_UNHANDLED; } int rawnet_send_packet(rawnet_t *net) { if(eth_send(net->eth, net->packet_data, net->packet_len) != net->packet_len) { ERROR_MESSAGE("could not write to device: %s : %s", net->device, strerror(errno)); return -1; } return 0; } /* Just update the seconds field. * * FIXME: mod this so that it hooks * into the rest of the framework. * right now it's error prone. */ void rawnet_dhcp_update(rawnet_t *net, time_t seconds) { unsigned char *packet; uint16_t secs = htons(seconds); /* FIX ME: we're assuming the ip packet header * has no options. */ packet = (net->packet_data + ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN); packet += 8; /* to seconds field. */ memcpy(packet, &secs, 2); ip_checksum((net->packet_data + ETH_HDR_LEN), (net->packet_len - ETH_HDR_LEN)); return; } /* * We can ask rawnet to validate for us. * Insert checks here to make sure * the packet is as kosher as christmas * (chicken soup). * */ int rawnet_is_valid(rawnet_t *net) { switch(net->type) { case RAWNET_DHCP: if(!dhcp_valid_magic_cookie(net->dhcp_p)) break; else return 1; default: /* todo: we need more validation on other packets. */ break; } return 0; } /* Generic send and wait for reply: * * Calls update() after timeout. * Calls check() on every packet coming in. * */ int rawnet_packet_transact(rawnet_t *net, void *arg, void (*update)(void *arg), int (*check)(void *arg), time_t max_timeout) { rtt_t *rtt; int retval; unsigned char send_packet = 1; struct timeval timeout; /* create rtt mechanism. */ rtt = rtt_create(max_timeout); /* We loop here and re-send packets if we timeout, or fail a * check on an incoming packets. */ while(1) { if(send_packet) { send_packet = 0; if(rawnet_send_packet(net) < 0) { rtt_destroy(rtt); ERROR_MESSAGE("could not dispatch packet"); return RAWNET_ERROR; } } timeout = rtt_get_timeout(rtt); retval = rawnet_get_packet(net, &timeout); switch(retval) { case RAWNET_PCAP_ERROR: rtt_destroy(rtt); ERROR_MESSAGE("could not wait for packets on: %s", net->device); return RAWNET_ERROR; case RAWNET_TIMEOUT: rtt_timeout(rtt); if(!rtt_can_retry(rtt)) { rtt_destroy(rtt); return RAWNET_TIMEOUT; } if(update) /* update if needed. only called after timeout. */ update(arg); send_packet = 1; break; case RAWNET_OK: if(!check) /* no check? return 0 anyway (we want * any packet it seems). */ return 0; if(check(arg)) { /* if we have a check * then check packet. */ rtt_destroy(rtt); return RAWNET_OK; /* it's good. let's return. */ } /* otherwise we should just continue. */ break; case RAWNET_UNHANDLED: case RAWNET_MALFORMED_PACKET: break; default: FATAL_MESSAGE("rawnet: invalid return from rawnet_get_packet() -- this is a bug report it please"); } } } const char *rawnet_get_device_name(rawnet_t *net) { return net->device; } --- NEW FILE: dhcp-librawnet.h --- /* $Header: /cvsroot/dhcp-agent/dhcp-agent/src/dhcp-librawnet.h,v 1.1 2002/11/03 16:39:22 actmodern Exp $ * * Copyright 2002 Thamer Alharbash * * 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. * */ #ifndef DHCP_LIBRAWNET_H #define DHCP_LIBRAWNET_H /* data structures. */ /* rtt struct. */ typedef struct rtt { struct timeval timeout; time_t max_timeout; time_t start_time; time_t elapsed_time; } rtt_t; /* interface control object: * we store dnet's interface handle, * and interface_entry structure. * We need the entry structure */ typedef struct { intf_t *interface_handle; struct intf_entry *interface_entry; } interface_control_t; /* DHCP fixed header -- before dhcp options. */ /* Size of header independant of any padding * sizeof() the structure may return. */ #define DHCP_FIXEDHDR_LEN 236 typedef struct { uint8_t op; uint8_t htype; uint8_t hlen; uint8_t hops; uint32_t xid; uint16_t secs; uint16_t flags; uint32_t ciaddr; uint32_t yiaddr; uint32_t siaddr; uint32_t giaddr; #define DHCP_CHADDR_SIZE 16 unsigned char chaddr[DHCP_CHADDR_SIZE]; #define DHCP_SNAME_SIZE 64 unsigned char sname[DHCP_SNAME_SIZE]; #define DHCP_FILE_SIZE 128 unsigned char file[DHCP_FILE_SIZE]; /* options go here. */ } dhcphdr; /* dhcp option structure for internal * dhcp object representation. */ typedef struct { unsigned char tag; unsigned char len; unsigned char *data; } dhcp_option_t; /* DHCP object * * for packet assembly/disassembly. */ 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. * * We use these to create a single interface * for creating custom packeting. * */ typedef struct { struct eth_hdr header; } eth_obj; typedef struct { struct ip_hdr header; } ip_obj; typedef struct { struct arp_hdr header; struct arp_ethip arp_data; } arp_obj; typedef struct { struct icmp_hdr icmp_header; union icmp_msg icmp_msg; } icmp_obj; typedef struct { struct udp_hdr header; } udp_obj; /* * DHCP raw network object. * * We do all our network transmission * through this data structure. * */ typedef struct { /* we should not interface directly with any of these members * above the rawnet layer: FIXME -- unfortunately we do. */ 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 chw_addr; /* our hardware address. */ ip_addr_t cip_addr; /* our ip address. */ eth_addr_t *fake_hw_addr; /* our fake hardware address. */ int promiscuous; /* run in promiscuous mode flag. */ interface_control_t *intf_handle; /* interface control handle. */ /* * Data objects * * After reception of packets on the wire * they're aligned and placed into these * objects. * */ uint8_t type; /* Type of data: * ARP, ICMP DHCP */ char *pcap_filter; /* low level pcap filter. */ /* Packet data. */ eth_obj *ether_p; ip_obj *ip_p; arp_obj *arp_p; icmp_obj *icmp_p; udp_obj *udp_p; dhcp_obj *dhcp_p; } rawnet_t; /* constants. */ /* mtu -- this is a broken guessing game right now.*/ # define DEFAULT_MTU 1500 # define SNAPLEN DEFAULT_MTU /* XXX -- should be called DEFAULT_SNAPLEN. * rawnet makes an assumption on incoming * packets this is broken. fixme. * */ /* Max message size option default. */ # define MAX_MESSAGE_SIZE 576 /* max options handled. */ # define MAX_OPTIONS_HANDLED 62 /* Reasonable defaults in case services db isn't up to date. */ #define BOOTP_CLIENT 68 #define BOOTP_SERVER 67 /* timeout as per rfc2131 */ #define MILLISECOND_TIMEOUT 4000 #define MILLISECOND_RAND_TIMEOUT 1000 /* macros. */ /* time macros. */ #define SECS_TO_MSECS(x) (x * 1000) #define MSECS_TO_SECS(x) (x/1000) #define MSECS_TO_SECS_REM(x) (x%1000) /* prototypes. */ /* DHCP obj routines. */ extern dhcp_obj *dhcp_create(void); extern void dhcp_purge(dhcp_obj *dhcp); extern void dhcp_purge_option_list(list_t *options); /* only use on network list. */ extern void dhcp_destroy(dhcp_obj *dhcp); extern int dhcp_read_packet_image(dhcp_obj *dhcp, const unsigned char *dhcp_packet, int len); extern void dhcp_write_packet_image(dhcp_obj *dhcp, unsigned char *packet); extern unsigned char dhcp_get_op(dhcp_obj *dhcp); extern unsigned char dhcp_get_hlen(dhcp_obj *dhcp); extern unsigned char dhcp_get_htype(dhcp_obj *dhcp); extern unsigned char dhcp_get_hops(dhcp_obj *dhcp); extern uint32_t dhcp_get_xid(dhcp_obj *dhcp); extern uint16_t dhcp_get_secs(dhcp_obj *dhcp); extern uint16_t dhcp_get_flags(dhcp_obj *dhcp); extern uint32_t dhcp_get_ciaddr(dhcp_obj *dhcp); extern uint32_t dhcp_get_yiaddr(dhcp_obj *dhcp); extern uint32_t dhcp_get_siaddr(dhcp_obj *dhcp); extern uint32_t dhcp_get_giaddr(dhcp_obj *dhcp); extern unsigned char *dhcp_get_chaddr(dhcp_obj *dhcp); extern unsigned char *dhcp_get_sname(dhcp_obj *dhcp); extern unsigned char *dhcp_get_filename(dhcp_obj *dhcp); extern uint32_t dhcp_get_magic_cookie(dhcp_obj *dhcp); extern void dhcp_set_op(dhcp_obj *dhcp, unsigned char op); extern void dhcp_set_htype(dhcp_obj *dhcp, unsigned char htype); extern void dhcp_set_hlen(dhcp_obj *dhcp, unsigned char hlen); extern void dhcp_set_hops(dhcp_obj *dhcp, unsigned char hops); extern void dhcp_set_xid(dhcp_obj *dhcp, uint32_t xid); extern void dhcp_set_secs(dhcp_obj *dhcp, uint16_t secs); extern void dhcp_set_flag_broadcast(dhcp_obj *dhcp); extern void dhcp_unset_flag_broadcast(dhcp_obj *dhcp); extern void dhcp_set_ciaddr(dhcp_obj *dhcp, uint32_t ciaddr); extern void dhcp_set_yiaddr(dhcp_obj *dhcp, uint32_t yiaddr); extern void dhcp_set_siaddr(dhcp_obj *dhcp, uint32_t siaddr); extern void dhcp_set_giaddr(dhcp_obj *dhcp, uint32_t giaddr); extern void dhcp_set_sname(dhcp_obj *dhcp, unsigned char *sname); extern void dhcp_set_filename(dhcp_obj *dhcp, unsigned char *file); extern void dhcp_set_magic_cookie(dhcp_obj *dhcp); extern void dhcp_set_options(dhcp_obj *dhcp, list_t *options); extern void dhcp_set_chaddr(dhcp_obj *dhcp, unsigned char *chaddr, int len); extern void dhcp_clear_sname(dhcp_obj *dhcp); extern void dhcp_clear_filename(dhcp_obj *dhcp); extern void dhcp_clear_chaddr(dhcp_obj *dhcp); extern void dhcp_reset_option_seek(dhcp_obj *dhcp); extern dhcp_option_t *dhcp_get_next_option(dhcp_obj *dhcp); extern dhcp_option_t *create_dhcp_option(const unsigned char *opt_data, unsigned char len, unsigned char tag); extern void destroy_dhcp_option(dhcp_option_t *option); extern uint16_t dhcp_get_options_len(list_t *options); extern int dhcp_valid_magic_cookie(dhcp_obj *dhcp); extern int dhcp_is_type(dhcp_obj *dhcp, unsigned char type); extern int dhcp_option_is_valid(unsigned char tag, unsigned char tag_len); extern int dhcp_have_atleast_requested_options(dhcp_obj *dhcp, unsigned char *option); extern int dhcp_have_exact_requested_options(dhcp_obj *dhcp, unsigned char *options); extern int dhcp_have_option(dhcp_obj *dhcp, unsigned char tag); extern int dhcp_is_file_overload(dhcp_obj *dhcp); extern int dhcp_is_sname_overload(dhcp_obj *dhcp); extern uint32_t dhcp_gen_xid(void); extern dhcp_option_t *dhcp_build_parameter_request_list_option(unsigned char *requested_options); extern dhcp_option_t *dhcp_build_max_message_size_option(uint16_t max); extern dhcp_option_t *dhcp_build_message_type(unsigned char type); extern dhcp_option_t *dhcp_build_class_id(unsigned char *class_id); extern dhcp_option_t *dhcp_build_client_id(unsigned char *client_id, unsigned char len); extern dhcp_option_t *dhcp_build_requested_ip_address(uint32_t address); extern dhcp_option_t *dhcp_build_server_identifier(uint32_t address); extern dhcp_option_t *dhcp_build_hostname(char *hostname); /* Ether obj routines. */ extern eth_obj *eth_create(void); extern void eth_destroy(eth_obj *eth); extern int eth_read_packet_image(eth_obj *eth, const unsigned char *packet, int len); extern void eth_write_packet_image(eth_obj *eth, unsigned char *packet); extern eth_addr_t eth_get_src_address(eth_obj *eth); extern eth_addr_t eth_get_dst_address(eth_obj *eth); extern uint16_t eth_get_type(eth_obj *eth); extern void eth_set_src_address(eth_obj *eth, eth_addr_t addr); extern void eth_set_dst_address(eth_obj *eth, eth_addr_t addr); extern void eth_set_type(eth_obj *eth, uint16_t type); /* IP obj routines. */ extern ip_obj *ip_create(void); extern void ip_destroy(ip_obj *ip); extern int ip_read_packet_image(ip_obj *ip, const unsigned char *packet, int len); extern void ip_write_packet_image(ip_obj *ip, unsigned char *packet); extern uint32_t ip_get_source_addr(ip_obj *ip); extern uint32_t ip_get_dest_addr(ip_obj *ip); extern unsigned char ip_get_hl(ip_obj *ip); extern uint8_t ip_get_proto(ip_obj *ip); extern void ip_set_hl(ip_obj *ip, uint16_t header_len); extern void ip_set_tos(ip_obj *ip, unsigned char ip_tos); extern void ip_set_len(ip_obj *ip, uint16_t ip_len); extern void ip_set_id(ip_obj *ip, uint16_t ip_id); extern void ip_set_off(ip_obj *ip, uint16_t ip_off); extern void ip_set_ttl(ip_obj *ip, uint8_t ip_ttl); extern void ip_set_proto(ip_obj *ip, unsigned char ip_proto); extern void ip_set_source_addr(ip_obj *ip, uint32_t ip_src); extern void ip_set_dest_addr(ip_obj *ip, uint32_t ip_src); /* ARP obj routines. */ extern arp_obj *arp_create(void); extern void arp_destroy(arp_obj *arp); extern void arp_write_packet_image(arp_obj *arp, unsigned char *packet); extern void arp_set_hardware_type(arp_obj *arp, uint16_t hdr_addr); extern void arp_set_protocol_type(arp_obj *arp, uint16_t pro); extern void arp_set_hardware_len(arp_obj *arp, uint8_t len); extern void arp_set_protocol_len(arp_obj *arp, uint8_t len); extern void arp_set_op(arp_obj *arp, uint16_t op); extern void arp_set_sender_hardware_address(arp_obj *arp, eth_addr_t addr); extern void arp_set_sender_protocol_address(arp_obj *arp, uint32_t addr); 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); extern int arp_read_packet_image(arp_obj *arp, const unsigned char *packet, int len); /* UDP obj routines. */ extern udp_obj *udp_create(void); extern void udp_destroy(udp_obj *udp); extern int udp_read_packet_image(udp_obj *udp, const unsigned char *packet, int len); extern void udp_write_packet_image(udp_obj *udp, unsigned char *packet); extern uint16_t udp_get_src_port(udp_obj *udp); extern uint16_t udp_get_dst_port(udp_obj *udp); extern uint16_t udp_get_len(udp_obj *udp); extern void udp_set_src_port(udp_obj *udp, uint16_t src_port); extern void udp_set_dst_port(udp_obj *udp, uint16_t dst_port); extern void udp_set_len(udp_obj *udp, uint16_t len); extern void udp_set_cksum(udp_obj *udp, uint16_t cksum); /* ICMP obj routines. */ extern icmp_obj *icmp_create(void); extern void icmp_destroy(icmp_obj *icmp); extern void icmp_set_type(icmp_obj *icmp, uint8_t type); extern void icmp_set_code(icmp_obj *icmp, uint8_t code); extern void icmp_clear_cksum(icmp_obj *icmp); extern void icmp_mask_set_id(icmp_obj *icmp, uint32_t id); extern void icmp_mask_set_seq(icmp_obj *icmp, uint32_t seq); extern void icmp_mask_set_mask(icmp_obj *icmp, uint32_t mask); extern void icmp_echo_set_id(icmp_obj *icmp, uint16_t id); extern void icmp_echo_set_seq(icmp_obj *icmp, uint16_t seq); extern uint8_t icmp_get_type(icmp_obj *icmp); extern uint32_t icmp_mask_get_mask(icmp_obj *icmp_p); extern void icmp_write_packet_image(icmp_obj *icmp, unsigned char *packet); extern int icmp_read_packet_image(icmp_obj *icmp, const unsigned char *packet, int len); /* Interface control */ extern interface_control_t *create_interface_control(char *name); extern int interface_is_up(interface_control_t *ic); extern int interface_up(interface_control_t *ic, uint32_t addr, uint32_t netmask, int mtu); extern int interface_down(interface_control_t *ic); extern void destroy_interface_control(interface_control_t *ic); extern int interface_get_ip_addr(interface_control_t *ic, uint32_t *addr); extern list_t *interface_get_active_interfaces(void); extern list_t *interface_get_inactive_interfaces(void); extern int port_for_service(const char *serv, const char *proto); /* RTT mechanism. */ extern rtt_t *rtt_create(time_t max_timeout); extern struct timeval rtt_get_timeout(rtt_t *rtt); extern void rtt_timeout(rtt_t *rtt); extern int rtt_can_retry(rtt_t *rtt); extern void rtt_destroy(rtt_t *rtt); #endif /* DHCP_LIBRAWNET_H */ |