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