Annotation of embedaddon/libnet/src/libnet_write.c, revision 1.1.1.1
1.1 misho 1: /*
2: * $Id: libnet_write.c,v 1.13 2004/02/20 18:53:50 mike Exp $
3: *
4: * libnet
5: * libnet_write.c - writes a prebuilt packet to the network
6: *
7: * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
8: * All rights reserved.
9: * win32 specific code
10: * Copyright (c) 2002 - 2003 Roberto Larcher <roberto.larcher@libero.it>
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: */
34:
35: #if (HAVE_CONFIG_H)
36: #include "../include/config.h"
37: #endif
38: #if (!(_WIN32) || (__CYGWIN__))
39: #include "../include/libnet.h"
40: #else
41: #include "../include/win32/libnet.h"
42: #include "../include/win32/config.h"
43: #include "packet32.h"
44: #include "Ntddndis.h"
45: #endif
46:
47: int
48: libnet_write(libnet_t *l)
49: {
50: int c;
51: u_int32_t len;
52: u_int8_t *packet = NULL;
53:
54: if (l == NULL)
55: {
56: return (-1);
57: }
58:
59: c = libnet_pblock_coalesce(l, &packet, &len);
60: if (c == - 1)
61: {
62: /* err msg set in libnet_pblock_coalesce() */
63: return (-1);
64: }
65:
66: /* assume error */
67: c = -1;
68: switch (l->injection_type)
69: {
70: case LIBNET_RAW4:
71: case LIBNET_RAW4_ADV:
72: if (len > LIBNET_MAX_PACKET)
73: {
74: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
75: "%s(): packet is too large (%d bytes)\n",
76: __func__, len);
77: goto done;
78: }
79: c = libnet_write_raw_ipv4(l, packet, len);
80: break;
81: case LIBNET_RAW6:
82: case LIBNET_RAW6_ADV:
83: c = libnet_write_raw_ipv6(l, packet, len);
84: break;
85: case LIBNET_LINK:
86: case LIBNET_LINK_ADV:
87: c = libnet_write_link(l, packet, len);
88: break;
89: default:
90: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
91: "%s(): unsuported injection type\n", __func__);
92: goto done;
93: }
94:
95: /* do statistics */
96: if (c == len)
97: {
98: l->stats.packets_sent++;
99: l->stats.bytes_written += c;
100: }
101: else
102: {
103: l->stats.packet_errors++;
104: /*
105: * XXX - we probably should have a way to retrieve the number of
106: * bytes actually written (since we might have written something).
107: */
108: if (c > 0)
109: {
110: l->stats.bytes_written += c;
111: }
112: }
113: done:
114: /*
115: * Restore original pointer address so free won't complain about a
116: * modified chunk pointer.
117: */
118: if (l->aligner > 0)
119: {
120: packet = packet - l->aligner;
121: }
122: free(packet);
123: return (c);
124: }
125:
126: #if defined (__WIN32__)
127: libnet_ptag_t
128: libnet_win32_build_fake_ethernet(u_int8_t *dst, u_int8_t *src, u_int16_t type,
129: u_int8_t *payload, u_int32_t payload_s, u_int8_t *packet, libnet_t *l,
130: libnet_ptag_t ptag)
131: {
132: struct libnet_ethernet_hdr eth_hdr;
133:
134: if (!packet)
135: {
136: return (-1);
137: }
138:
139: memset(ð_hdr, 0, sizeof(eth_hdr));
140: eth_hdr.ether_type = htons(type);
141: memcpy(eth_hdr.ether_dhost, dst, ETHER_ADDR_LEN); /* destination address */
142: memcpy(eth_hdr.ether_shost, src, ETHER_ADDR_LEN); /* source address */
143:
144: if (payload && payload_s)
145: {
146: /*
147: * Unchecked runtime error for buf + ETH_H payload to be greater than
148: * the allocated heap memory.
149: */
150: memcpy(packet + LIBNET_ETH_H, payload, payload_s);
151: }
152: memcpy(packet, ð_hdr, sizeof(eth_hdr));
153: return (1);
154: }
155:
156: libnet_ptag_t
157: libnet_win32_build_fake_token(u_int8_t *dst, u_int8_t *src, u_int16_t type,
158: u_int8_t *payload, u_int32_t payload_s, u_int8_t *packet, libnet_t *l,
159: libnet_ptag_t ptag)
160: {
161: struct libnet_token_ring_hdr token_ring_hdr;
162:
163: if (!packet)
164: {
165: return (-1);
166: }
167:
168: memset(&token_ring_hdr, 0, sizeof(token_ring_hdr));
169: token_ring_hdr.token_ring_access_control = 0x10;
170: token_ring_hdr.token_ring_frame_control = 0x40;
171: token_ring_hdr.token_ring_llc_dsap = 0xaa;
172: token_ring_hdr.token_ring_llc_ssap = 0xaa;
173: token_ring_hdr.token_ring_llc_control_field = 0x03;
174: token_ring_hdr.token_ring_type = htons(type);
175: memcpy(token_ring_hdr.token_ring_dhost, dst, ETHER_ADDR_LEN);
176: memcpy(token_ring_hdr.token_ring_shost, libnet_get_hwaddr(l),
177: ETHER_ADDR_LEN);
178:
179: if (payload && payload_s)
180: {
181: /*
182: * Unchecked runtime error for buf + ETH_H payload to be greater than
183: * the allocated heap memory.
184: */
185: memcpy(packet + LIBNET_TOKEN_RING_H, payload, payload_s);
186: }
187: memcpy(packet, &token_ring_hdr, sizeof(token_ring_hdr));
188: return (1);
189: }
190:
191:
192: int
193: libnet_win32_write_raw_ipv4(libnet_t *l, u_int8_t *payload, u_int32_t payload_s)
194: {
195: static BYTE dst[ETHER_ADDR_LEN];
196: static BYTE src[ETHER_ADDR_LEN];
197:
198: u_int8_t *packet = NULL;
199: u_int32_t packet_s;
200:
201: LPPACKET lpPacket = NULL;
202: DWORD remoteip = 0;
203: DWORD BytesTransfered;
204: NetType type;
205: struct libnet_ipv4_hdr *ip_hdr = NULL;
206:
207: memset(dst, 0, sizeof(dst));
208: memset(src, 0, sizeof(src));
209:
210: packet_s = payload_s + l->link_offset;
211: packet = (u_int8_t *)malloc(packet_s);
212: if (packet == NULL)
213: {
214: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
215: "%s(): failed to allocate packet\n", __func__);
216: return (-1);
217: }
218:
219: /* we have to do the IP checksum */
220: if (libnet_do_checksum(l, payload, IPPROTO_IP, LIBNET_IPV4_H) == -1)
221: {
222: /* error msg set in libnet_do_checksum */
223: return (-1);
224: }
225:
226: /* MACs, IPs and other stuff... */
227: ip_hdr = (struct libnet_ipv4_hdr *)payload;
228: memcpy(src, libnet_get_hwaddr(l), sizeof(src));
229: remoteip = ip_hdr->ip_dst.S_un.S_addr;
230:
231: /* check if the remote station is the local station */
232: if (remoteip == libnet_get_ipaddr4(l))
233: {
234: memcpy(dst, src, sizeof(dst));
235: }
236: else
237: {
238: memcpy(dst, libnet_win32_get_remote_mac(l, remoteip), sizeof(dst));
239: }
240:
241: PacketGetNetType(l->lpAdapter, &type);
242:
243: switch(type.LinkType)
244: {
245: case NdisMedium802_3:
246: libnet_win32_build_fake_ethernet(dst, src, ETHERTYPE_IP, payload,
247: payload_s, packet, l , 0);
248: break;
249: case NdisMedium802_5:
250: libnet_win32_build_fake_token(dst, src, ETHERTYPE_IP, payload,
251: payload_s, packet, l, 0);
252: break;
253: case NdisMediumFddi:
254: break;
255: case NdisMediumWan:
256: case NdisMediumAtm:
257: case NdisMediumArcnet878_2:
258: default:
259: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
260: "%s(): network type (%d) is not supported\n", __func__,
261: type.LinkType);
262: return (-1);
263: break;
264: }
265:
266: BytesTransfered = -1;
267: if ((lpPacket = PacketAllocatePacket()) == NULL)
268: {
269: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
270: "%s(): failed to allocate the LPPACKET structure\n", __func__);
271: return (-1);
272: }
273:
274: PacketInitPacket(lpPacket, packet, packet_s);
275:
276: /* PacketSendPacket returns a BOOLEAN */
277: if (PacketSendPacket(l->lpAdapter, lpPacket, TRUE))
278: {
279: BytesTransfered = packet_s;
280: }
281:
282: PacketFreePacket(lpPacket);
283: free(packet);
284:
285: return (BytesTransfered);
286: }
287:
288: int
289: libnet_write_raw_ipv4(libnet_t *l, u_int8_t *packet, u_int32_t size)
290: {
291: return (libnet_win32_write_raw_ipv4(l, packet, size));
292: }
293:
294: int
295: libnet_write_raw_ipv6(libnet_t *l, u_int8_t *packet, u_int32_t size)
296: {
297: /* no difference in win32 */
298: return (libnet_write_raw_ipv4(l, packet, size));
299: }
300:
301: #else /* __WIN32__ */
302:
303: int
304: libnet_write_raw_ipv4(libnet_t *l, u_int8_t *packet, u_int32_t size)
305: {
306: int c;
307: struct sockaddr_in sin;
308: struct libnet_ipv4_hdr *ip_hdr;
309:
310: if (l == NULL)
311: {
312: return (-1);
313: }
314:
315: ip_hdr = (struct libnet_ipv4_hdr *)packet;
316:
317: #if (LIBNET_BSD_BYTE_SWAP)
318: /*
319: * For link access, we don't need to worry about the inconsistencies of
320: * certain BSD kernels. However, raw socket nuances abound. Certain
321: * BSD implmentations require the ip_len and ip_off fields to be in host
322: * byte order.
323: */
324: ip_hdr->ip_len = FIX(ip_hdr->ip_len);
325: ip_hdr->ip_off = FIX(ip_hdr->ip_off);
326: #endif /* LIBNET_BSD_BYTE_SWAP */
327:
328: memset(&sin, 0, sizeof(sin));
329: sin.sin_family = AF_INET;
330: sin.sin_addr.s_addr = ip_hdr->ip_dst.s_addr;
331: #if (__WIN32__)
332: /* set port for TCP */
333: /*
334: * XXX - should first check to see if there's a pblock for a TCP
335: * header, if not we can use a dummy value for the port.
336: */
337: if (ip_hdr->ip_p == 6)
338: {
339: struct libnet_tcp_hdr *tcph_p =
340: (struct libnet_tcp_hdr *)(packet + (ip_hdr->ip_hl << 2));
341: sin.sin_port = tcph_p->th_dport;
342: }
343: /* set port for UDP */
344: /*
345: * XXX - should first check to see if there's a pblock for a UDP
346: * header, if not we can use a dummy value for the port.
347: */
348: else if (ip_hdr->ip_p == 17)
349: {
350: struct libnet_udp_hdr *udph_p =
351: (struct libnet_udp_hdr *)(packet + (ip_hdr->ip_hl << 2));
352: sin.sin_port = udph_p->uh_dport;
353: }
354: #endif /* __WIN32__ */
355:
356: c = sendto(l->fd, packet, size, 0, (struct sockaddr *)&sin,
357: sizeof(struct sockaddr));
358:
359: #if (LIBNET_BSD_BYTE_SWAP)
360: ip_hdr->ip_len = UNFIX(ip_hdr->ip_len);
361: ip_hdr->ip_off = UNFIX(ip_hdr->ip_off);
362: #endif /* LIBNET_BSD_BYTE_SWAP */
363:
364: if (c != size)
365: {
366: #if !(__WIN32__)
367: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
368: "%s(): %d bytes written (%s)\n", __func__, c,
369: strerror(errno));
370: #else /* __WIN32__ */
371: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
372: "%s(): %d bytes written (%d)\n", __func__, c,
373: WSAGetLastError());
374: #endif /* !__WIN32__ */
375: }
376: return (c);
377: }
378:
379: int
380: libnet_write_raw_ipv6(libnet_t *l, u_int8_t *packet, u_int32_t size)
381: {
382: #if defined HAVE_SOLARIS && !defined HAVE_SOLARIS_IPV6
383: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): no IPv6 support\n",
384: __func__, strerror(errno));
385: return (-1);
386: }
387: #else
388: int c;
389: struct sockaddr_in6 sin;
390: struct libnet_ipv6_hdr *ip_hdr;
391:
392: if (l == NULL)
393: {
394: return (-1);
395: }
396:
397: ip_hdr = (struct libnet_ipv6_hdr *)packet;
398:
399: memset(&sin, 0, sizeof(sin));
400: sin.sin6_family = AF_INET6;
401: memcpy(sin.sin6_addr.s6_addr, ip_hdr->ip_dst.libnet_s6_addr,
402: sizeof(ip_hdr->ip_dst.libnet_s6_addr));
403:
404: c = sendto(l->fd, packet, size, 0, (struct sockaddr *)&sin, sizeof(sin));
405: if (c != size)
406: {
407: #if !(__WIN32__)
408: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
409: "%s(): %d bytes written (%s)\n", __func__, c,
410: strerror(errno));
411: #else /* __WIN32__ */
412: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
413: "%s(): %d bytes written (%d)\n", __func__, c,
414: WSAGetLastError());
415: #endif /* !__WIN32__ */
416: }
417: return (c);
418: }
419: #endif
420: #endif
421: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>