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>