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