Annotation of embedaddon/dhcdrop/src/net_functions.c, revision 1.1.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>