Annotation of embedaddon/dhcdrop/src/net_functions.c, revision 1.1
1.1 ! misho 1: /*
! 2: * net_functios.c
! 3: *
! 4: * Created on: 30.07.2009
! 5: * Copyright (C) 2009 by Chebotarev Roman <roma@ultranet.ru>
! 6: *
! 7: * This program is free software; you can redistribute it and/or modify
! 8: * it under the terms of the GNU General Public License as published by
! 9: * the Free Software Foundation; either version 2 of the License.
! 10: *
! 11: * This program is distributed in the hope that it will be useful,
! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 14: * GNU General Public License for more details.
! 15: *
! 16: * You should have received a copy of the GNU General Public License
! 17: * along with this program; if not, write to the Free Software
! 18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
! 19: */
! 20:
! 21: #include "common_includes.h"
! 22: #include "dhcp.h"
! 23: #include "dhcdrop_types.h"
! 24: #include "net_functions.h"
! 25:
! 26: int is_timeout;
! 27:
! 28: uint16_t rs_crc(const unsigned short *buffer, int length)
! 29: {
! 30: uint32_t crc = 0;
! 31: /* Calculate CRC */
! 32: while (length > 1)
! 33: {
! 34: crc += *buffer++;
! 35: length -= sizeof (unsigned short);
! 36: }
! 37: if (length)
! 38: crc += *(unsigned char*) buffer;
! 39:
! 40: crc = (crc >> 16) + (crc & 0xFFFF);
! 41: crc += (crc >> 16);
! 42:
! 43: return (uint16_t)(~crc);
! 44: }
! 45:
! 46: void assemble_net_header_arp(struct arp_packet_net_header * net_header,
! 47: const uint8_t * ether_src,
! 48: uint16_t op_code)
! 49: {
! 50: /* Fill ethernet header */
! 51: memcpy(net_header->eth_head.ether_shost, ether_src, sizeof(net_header->eth_head.ether_shost));
! 52: memset(net_header->eth_head.ether_dhost, 0xFF, sizeof(net_header->eth_head.ether_dhost));
! 53: net_header->eth_head.ether_type = htons(ETHERTYPE_ARP);
! 54: /* Fill ARP header */
! 55: net_header->arp_head.arp_hwtype = htons(1); /* Ethernet */
! 56: net_header->arp_head.arp_proto = htons(ETHERTYPE_IP);
! 57: net_header->arp_head.arp_hwlen = ETH_ALEN;
! 58: net_header->arp_head.arp_palen = IPV4_ALEN;
! 59: net_header->arp_head.arp_oper = op_code;
! 60: }
! 61:
! 62: void assemble_net_header_dhcp
! 63: (
! 64: struct dhcp_packet_net_header * header,
! 65: const int data_len,
! 66: const struct config_params * params,
! 67: const uint8_t * ether_src,
! 68: const uint32_t dst_ip,
! 69: const uint32_t src_ip
! 70: )
! 71: {
! 72: /* Fill ethernet header */
! 73: memcpy(header->eth_head.ether_shost, ether_src, sizeof(header->eth_head.ether_shost));
! 74: memset(header->eth_head.ether_dhost, 0xFF, sizeof(header->eth_head.ether_dhost));
! 75: header->eth_head.ether_type = htons(ETHERTYPE_IP);
! 76: /* Fill IP header */
! 77: bzero(&header->ip_header, sizeof(struct iphdr));
! 78: header->ip_header.ihl = IP_HDR_LEN;
! 79: header->ip_header.version = 4;
! 80: header->ip_header.tos = 0x10;
! 81: header->ip_header.tot_len = htons(B_IP_HDR_LEN + sizeof(struct udphdr) + data_len);
! 82: header->ip_header.id = (uint16_t) rand();
! 83: header->ip_header.frag_off = 0;
! 84: header->ip_header.ttl = DEF_TTL;
! 85: header->ip_header.protocol = IPPROTO_UDP;
! 86: header->ip_header.check = 0;
! 87: header->ip_header.saddr = src_ip;
! 88: if(dst_ip)
! 89: header->ip_header.daddr = dst_ip;
! 90: else
! 91: memset(&header->ip_header.daddr, 0xFF, sizeof(uint32_t)); /*Set dst IP = 255.255.255.255*/
! 92:
! 93: header->ip_header.check = rs_crc((unsigned short*)&header->ip_header, sizeof(struct iphdr));
! 94: header->udp_header.source = htons(params->client_port);
! 95: header->udp_header.dest = htons(params->server_port);
! 96: header->udp_header.len = htons(sizeof(struct udphdr) + data_len);
! 97: header->udp_header.check = 0; /* Don't use because CRC for UDP - optional parametr */
! 98:
! 99: return;
! 100: }
! 101:
! 102: int send_packet(pcap_t* descr, enum packet_types packet_type, const uint8_t *snd_data, const int data_len,
! 103: const struct config_params * config,
! 104: const uint8_t * ether_src, const uint32_t dst_ip)
! 105: {
! 106: int header_size = 0;
! 107: static unsigned char pack_buf[DHCP_MTU_MAX];
! 108:
! 109: bzero(pack_buf, sizeof(pack_buf));
! 110:
! 111: /* Create net-header */
! 112: switch(packet_type)
! 113: {
! 114: case dhcp_packet:
! 115: if(!config)
! 116: return 0;
! 117: assemble_net_header_dhcp((struct dhcp_packet_net_header *)pack_buf,
! 118: data_len, config, ether_src, dst_ip, 0);//((struct dhcp_packet *) snd_data)->ciaddr.s_addr);
! 119: header_size = sizeof(struct dhcp_packet_net_header);
! 120: break;
! 121: case arp_packet:
! 122: assemble_net_header_arp((struct arp_packet_net_header *) pack_buf, ether_src, ARP_OP_REQ);
! 123: header_size = sizeof(struct arp_packet_net_header);
! 124: break;
! 125: default:
! 126: printf("send_packet(): unknown type of packet.\n");
! 127: return 0;
! 128: }
! 129:
! 130: /* Copy user data to send buffer */
! 131: memcpy(pack_buf + header_size, snd_data, data_len);
! 132:
! 133: if(pcap_inject(descr, pack_buf, header_size + data_len) == -1)
! 134: {
! 135: pcap_perror(descr, "pcap_inject");
! 136: return 0;
! 137: }
! 138:
! 139: return 1;
! 140: }
! 141:
! 142: void packet_handler(u_char *out_packet, const struct pcap_pkthdr *h,
! 143: const u_char *packet)
! 144: {
! 145: if(h->len > DHCP_MTU_MAX)
! 146: {
! 147: printf("Received too long packet: %d. Can't dispatch!\n", h->len);
! 148: return;
! 149: }
! 150:
! 151: memcpy(out_packet, (u_char*)packet, h->len);
! 152: return;
! 153: }
! 154:
! 155: int get_packet(pcap_t * descr, u_char * ether_packet, const int wait_seconds)
! 156: {
! 157: int ret = 0;
! 158: uint32_t t;
! 159:
! 160: if(wait_seconds > 0)
! 161: {
! 162: is_timeout = 0;
! 163: t = timer_start(wait_seconds, timeout);
! 164: }
! 165: else
! 166: is_timeout = 1;
! 167: while(1)
! 168: {
! 169: if(wait_seconds)
! 170: usleep(CAP_TIMEOUT); /* Waiting 100 microseconds for avoid CPU overload */
! 171:
! 172: ret = pcap_dispatch(descr, 1, packet_handler, (u_char*)ether_packet);
! 173: if(ret < 0)
! 174: {
! 175: perror("pcap_dispatch");
! 176: return -1;
! 177: }
! 178:
! 179: if(is_timeout || ret)
! 180: {
! 181: timer_stop(t);
! 182: break;
! 183: }
! 184: }
! 185: return ret;
! 186: }
! 187:
! 188:
! 189: #ifdef _WIN32
! 190: void CALLBACK timeout(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
! 191: #else
! 192: void timeout(int signal)
! 193: #endif
! 194: {
! 195: is_timeout = 1;
! 196: }
! 197:
! 198: /* Opening and testing device */
! 199: pcap_t * get_device(const struct config_params * params)
! 200: {
! 201: char errbuf[PCAP_ERRBUF_SIZE];
! 202: pcap_t * pcap_socket = pcap_open_live(params->if_name, DHCP_MTU_MAX, 1,
! 203: PCAP_OPEN_LIVE_TIMEOUT, errbuf);
! 204:
! 205: if(pcap_socket == NULL)
! 206: {
! 207: printf("Opening device error! %s\n",errbuf);
! 208: exit(ERR_OPENDEV);
! 209: }
! 210:
! 211: if(pcap_datalink(pcap_socket) != DLT_EN10MB)
! 212: {
! 213: printf("Can't work on this link layer type! Exit.\n");
! 214: exit(ERR_INVALID_DEV);
! 215: }
! 216:
! 217: #ifdef __linux__
! 218: /* Set nonblock mode for processing DHCP timeouts */
! 219: if(pcap_setnonblock(pcap_socket, 1, errbuf) == -1)
! 220: {
! 221: printf("pcap_setnoblock error: '%s'\n", errbuf);
! 222: pcap_close(pcap_socket);
! 223: exit(ERR_SETNOBLOCK);
! 224: }
! 225: #endif
! 226:
! 227: return pcap_socket;
! 228: }
! 229:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>