Annotation of embedaddon/libnet/src/libnet_write.c, revision 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>