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(&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
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>