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