File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcdrop / src / net_functions.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:25:35 2012 UTC (13 years, 9 months ago) by misho
Branches: dhcdrop, MAIN
CVS tags: v0_5, HEAD
dhcdrop

    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>