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