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>