📄 dhcp-rawnet.c
字号:
/* $Header: /cvsroot/dhcp-agent/dhcp-agent/src/dhcp-rawnet.c,v 1.12 2003/07/06 05:37:23 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-local.h"#include "dhcp-limits.h"#include "dhcp-libutil.h"#include "dhcp-librawnet.h"#include "dhcp-interface.h"/************************ * Address Manipulation.* ************************//* get IP address. */ip_addr_t rawnet_get_ip_addr(rawnet_t *net){ return net->cip_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);}/* 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 *rawnet_network_address_to_string_static(uint32_t addr){ struct in_addr in; in.s_addr = addr; return (inet_ntoa(in));}/* * * * * * * * * * * * * * * Interface 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, ETH_ADDR_LEN); return 0; } else { memcpy(addr, &net->chw_addr, ETH_ADDR_LEN); return 0; }}/* 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));}/* 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, int set_address){ if(interface_up(net->intf_handle, addr, netmask, mtu, set_address)) { ERROR_MESSAGE("could not bring interface up."); return -1; } interface_get_ip_addr(net->intf_handle, &net->cip_addr); xfree(net->packet_data); net->packet_data = xmalloc(mtu); 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;}uint16_t rawnet_get_mtu(rawnet_t *net){ return interface_get_mtu(net->intf_handle);}list_t *rawnet_list_active_interfaces(void){ return (interface_get_active_interfaces());}list_t *rawnet_list_inactive_interfaces(void){ return (interface_get_inactive_interfaces());}/* * Initialization of packet capturing device. * */static pcap_t *initialize_pcap_device(char *interface_name, int snaplen, 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; } /* looks like NetBSD ships with a libpcap that does not have * pcap_freecode there's nothing we can do except not compile * against it. this unfortunately will probably introduce * memory leaks :| */#ifdef HAVE_PCAP_FREECODE pcap_freecode(&filter);#endif /* HAVE_PCAP_FREECODE */#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;}/* Create the workhorse raw network module. */rawnet_t *rawnet_create(const char *device, const char *filter, int mtu, int dhcp_src_port, int dhcp_dst_port, int promiscuous, int clear_address){ 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->promiscuous = promiscuous; net->mtu = mtu; /* 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, 0, net->mtu, clear_address)) { ERROR_MESSAGE("error trying to bring device up: %s", device); rawnet_destroy(net); return NULL; } } else if(clear_address) { /* interface down but we've been told to clear its address, * so our caller wants us to initialize it either way. */ if(rawnet_interface_up(net, 0, 0, net->mtu, clear_address)) { ERROR_MESSAGE("error trying to bring device up: %s", device); rawnet_destroy(net); return NULL; } } if(net->mtu == -1) { /* were we passed an mtu? */ /* if not get it from the interface that was just brought up. */ net->mtu = rawnet_get_mtu(net); } /* now allocate packet data since we know the mtu. */ net->packet_data = xcalloc(net->mtu); /* 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->mtu, 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; } /* store a copy of our hardware and ip address. */ eth_get(net->eth, &net->chw_addr); interface_get_ip_addr(net->intf_handle, &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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -