File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_write.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 11:54:42 2013 UTC (11 years ago) by misho
Branches: libnet, MAIN
CVS tags: v1_1_6p5, v1_1_6p4, v1_1_6p0, v1_1_6, HEAD
1.1.6

    1: /*
    2:  *  $Id: libnet_write.c,v 1.1.1.2 2013/07/22 11:54:42 misho 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: #include <netinet/in.h>
   36: #include <sys/types.h>
   37: #include <netinet/udp.h>
   38: 
   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;
   55:     uint32_t len;
   56:     uint8_t *packet = NULL;
   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
  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,
  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(&eth_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, &eth_hdr, sizeof(eth_hdr));
  157:     return (1);
  158: }
  159: 
  160: libnet_ptag_t
  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,
  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
  196: libnet_win32_write_raw_ipv4(libnet_t *l, const uint8_t *payload, uint32_t payload_s)
  197: {    
  198:     static BYTE dst[ETHER_ADDR_LEN];
  199:     static BYTE src[ETHER_ADDR_LEN];
  200: 	
  201:     uint8_t *packet      = NULL;
  202:     uint32_t packet_s;
  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;
  214:     packet = (uint8_t *)malloc(packet_s);
  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
  292: libnet_write_raw_ipv4(libnet_t *l, const uint8_t *packet, uint32_t size)
  293: {
  294:     return (libnet_win32_write_raw_ipv4(l, packet, size));
  295: }
  296: 
  297: int
  298: libnet_write_raw_ipv6(libnet_t *l, const uint8_t *packet, uint32_t size)
  299: {
  300:     /* no difference in win32 */
  301:     return (libnet_write_raw_ipv4(l, packet, size));
  302: }
  303: 
  304: #else /* __WIN32__ */
  305: 
  306: int
  307: libnet_write_raw_ipv4(libnet_t *l, const uint8_t *packet, uint32_t size)
  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,
  360:             sizeof(sin));
  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
  383: libnet_write_raw_ipv6(libnet_t *l, const uint8_t *packet, uint32_t size)
  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>