Annotation of embedaddon/libnet/src/libnet_write.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  *  libnet
                      3:  *  libnet_write.c - writes a prebuilt packet to the network
                      4:  *
                      5:  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
                      6:  *  All rights reserved.
1.1.1.3 ! misho       7:  *  win32 specific code
1.1       misho       8:  *  Copyright (c) 2002 - 2003 Roberto Larcher <roberto.larcher@libero.it>
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  *
                     31:  */
                     32: 
1.1.1.3 ! misho      33: #include "common.h"
1.1       misho      34: 
                     35: int
                     36: libnet_write(libnet_t *l)
                     37: {
                     38:     int c;
1.1.1.2   misho      39:     uint32_t len;
                     40:     uint8_t *packet = NULL;
1.1       misho      41: 
                     42:     if (l == NULL)
1.1.1.3 ! misho      43:     {
1.1       misho      44:         return (-1);
                     45:     }
                     46: 
                     47:     c = libnet_pblock_coalesce(l, &packet, &len);
                     48:     if (c == - 1)
                     49:     {
                     50:         /* err msg set in libnet_pblock_coalesce() */
                     51:         return (-1);
                     52:     }
                     53: 
                     54:     /* assume error */
                     55:     c = -1;
                     56:     switch (l->injection_type)
                     57:     {
                     58:         case LIBNET_RAW4:
                     59:         case LIBNET_RAW4_ADV:
                     60:             if (len > LIBNET_MAX_PACKET)
                     61:             {
                     62:                 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho      63:                         "%s(): packet is too large (%d bytes)",
1.1       misho      64:                         __func__, len);
                     65:                 goto done;
                     66:             }
                     67:             c = libnet_write_raw_ipv4(l, packet, len);
                     68:             break;
                     69:         case LIBNET_RAW6:
                     70:         case LIBNET_RAW6_ADV:
                     71:             c = libnet_write_raw_ipv6(l, packet, len);
                     72:             break;
                     73:         case LIBNET_LINK:
                     74:         case LIBNET_LINK_ADV:
                     75:             c = libnet_write_link(l, packet, len);
                     76:             break;
                     77:         default:
                     78:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho      79:                         "%s(): unsupported injection type", __func__);
1.1       misho      80:             goto done;
                     81:     }
                     82: 
                     83:     /* do statistics */
                     84:     if (c == len)
                     85:     {
                     86:         l->stats.packets_sent++;
                     87:         l->stats.bytes_written += c;
                     88:     }
                     89:     else
                     90:     {
                     91:         l->stats.packet_errors++;
                     92:         /*
                     93:          *  XXX - we probably should have a way to retrieve the number of
                     94:          *  bytes actually written (since we might have written something).
                     95:          */
                     96:         if (c > 0)
                     97:         {
                     98:             l->stats.bytes_written += c;
                     99:         }
                    100:     }
                    101: done:
                    102:     /*
                    103:      *  Restore original pointer address so free won't complain about a
                    104:      *  modified chunk pointer.
                    105:      */
                    106:     if (l->aligner > 0)
                    107:     {
                    108:         packet = packet - l->aligner;
                    109:     }
                    110:     free(packet);
                    111:     return (c);
                    112: }
                    113: 
                    114: #if defined (__WIN32__)
                    115: libnet_ptag_t
1.1.1.3 ! misho     116: libnet_win32_build_fake_ethernet (uint8_t *dst, uint8_t *src, uint16_t type,
        !           117:                                   const uint8_t *payload, uint32_t payload_s,
        !           118:                                   uint8_t *packet, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     119: {
                    120:     struct libnet_ethernet_hdr eth_hdr;
                    121: 
                    122:     if (!packet)
                    123:     {
                    124:         return (-1);
                    125:     }
                    126: 
1.1.1.3 ! misho     127:     memset(&eth_hdr, 0, sizeof(eth_hdr));
1.1       misho     128:     eth_hdr.ether_type = htons(type);
                    129:     memcpy(eth_hdr.ether_dhost, dst, ETHER_ADDR_LEN);  /* destination address */
                    130:     memcpy(eth_hdr.ether_shost, src, ETHER_ADDR_LEN);  /* source address */
                    131: 
                    132:     if (payload && payload_s)
                    133:     {
                    134:         /*
                    135:          *  Unchecked runtime error for buf + ETH_H payload to be greater than
                    136:          *  the allocated heap memory.
                    137:          */
                    138:         memcpy(packet + LIBNET_ETH_H, payload, payload_s);
                    139:     }
                    140:     memcpy(packet, &eth_hdr, sizeof(eth_hdr));
                    141:     return (1);
                    142: }
                    143: 
                    144: libnet_ptag_t
1.1.1.3 ! misho     145: libnet_win32_build_fake_token (uint8_t *dst, uint8_t *src, uint16_t type,
        !           146:                                const uint8_t *payload, uint32_t payload_s,
        !           147:                                uint8_t *packet, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     148: {
                    149:     struct libnet_token_ring_hdr token_ring_hdr;
1.1.1.3 ! misho     150: 
1.1       misho     151:     if (!packet)
                    152:     {
                    153:         return (-1);
                    154:     }
                    155: 
1.1.1.3 ! misho     156:     memset(&token_ring_hdr, 0, sizeof(token_ring_hdr));
1.1       misho     157:     token_ring_hdr.token_ring_access_control    = 0x10;
                    158:     token_ring_hdr.token_ring_frame_control     = 0x40;
                    159:     token_ring_hdr.token_ring_llc_dsap          = 0xaa;
                    160:     token_ring_hdr.token_ring_llc_ssap          = 0xaa;
                    161:     token_ring_hdr.token_ring_llc_control_field = 0x03;
                    162:     token_ring_hdr.token_ring_type              = htons(type);
1.1.1.3 ! misho     163:     memcpy(token_ring_hdr.token_ring_dhost, dst, ETHER_ADDR_LEN);
        !           164:     memcpy(token_ring_hdr.token_ring_shost, libnet_get_hwaddr(l),
        !           165:            ETHER_ADDR_LEN);
        !           166: 
1.1       misho     167:     if (payload && payload_s)
                    168:     {
                    169:         /*
                    170:          *  Unchecked runtime error for buf + ETH_H payload to be greater than
                    171:          *  the allocated heap memory.
                    172:          */
                    173:         memcpy(packet + LIBNET_TOKEN_RING_H, payload, payload_s);
                    174:     }
                    175:     memcpy(packet, &token_ring_hdr, sizeof(token_ring_hdr));
                    176:     return (1);
                    177: }
                    178: 
                    179: int
1.1.1.2   misho     180: libnet_win32_write_raw_ipv4(libnet_t *l, const uint8_t *payload, uint32_t payload_s)
1.1.1.3 ! misho     181: {
1.1       misho     182:     static BYTE dst[ETHER_ADDR_LEN];
                    183:     static BYTE src[ETHER_ADDR_LEN];
1.1.1.3 ! misho     184: 
        !           185:     uint8_t *packet;
1.1.1.2   misho     186:     uint32_t packet_s;
1.1       misho     187: 
1.1.1.3 ! misho     188:     DWORD remoteip = 0;
1.1       misho     189:     NetType type;
                    190:     struct libnet_ipv4_hdr *ip_hdr = NULL;
1.1.1.3 ! misho     191: 
1.1       misho     192:     memset(dst, 0, sizeof(dst));
                    193:     memset(src, 0, sizeof(src));
                    194: 
                    195:     packet_s = payload_s + l->link_offset;
1.1.1.3 ! misho     196:     packet = (uint8_t*) alloca(packet_s);
        !           197: 
        !           198:     /* we have to do the IP checksum
        !           199:      * FIXME: warning is correct, checksum modifies its input.
        !           200:      *        Fix is to build checksum inside the allocated 'packet'
        !           201:      */
        !           202:     if (libnet_inet_checksum(l, (uint8_t*)payload, IPPROTO_IP, LIBNET_IPV4_H, payload, payload+payload_s) == -1)
1.1       misho     203:     {
                    204:         /* error msg set in libnet_do_checksum */
                    205:         return (-1);
1.1.1.3 ! misho     206:     }
1.1       misho     207: 
                    208:     /* MACs, IPs and other stuff... */
                    209:     ip_hdr = (struct libnet_ipv4_hdr *)payload;
                    210:     memcpy(src, libnet_get_hwaddr(l), sizeof(src));
                    211:     remoteip = ip_hdr->ip_dst.S_un.S_addr;
1.1.1.3 ! misho     212: 
1.1       misho     213:     /* check if the remote station is the local station */
                    214:     if (remoteip == libnet_get_ipaddr4(l))
                    215:     {
                    216:         memcpy(dst, src, sizeof(dst));
                    217:     }
                    218:     else
                    219:     {
                    220:         memcpy(dst, libnet_win32_get_remote_mac(l, remoteip), sizeof(dst));
                    221:     }
                    222: 
                    223:     PacketGetNetType(l->lpAdapter, &type);
1.1.1.3 ! misho     224: 
1.1       misho     225:     switch(type.LinkType)
                    226:     {
                    227:         case NdisMedium802_3:
                    228:             libnet_win32_build_fake_ethernet(dst, src, ETHERTYPE_IP, payload,
                    229:                     payload_s, packet, l , 0);
                    230:             break;
                    231:         case NdisMedium802_5:
                    232:             libnet_win32_build_fake_token(dst, src, ETHERTYPE_IP, payload,
                    233:                     payload_s, packet, l, 0);
                    234:             break;
                    235:         case NdisMediumFddi:
                    236:             break;
                    237:         case NdisMediumWan:
                    238:         case NdisMediumAtm:
                    239:         case NdisMediumArcnet878_2:
                    240:         default:
                    241:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     242:                 "%s(): network type (%d) is not supported", __func__,
1.1       misho     243:                 type.LinkType);
                    244:             return (-1);
                    245:     }
1.1.1.3 ! misho     246:     return libnet_write_link (l, packet, packet_s);
1.1       misho     247: }
                    248: 
                    249: int
1.1.1.2   misho     250: libnet_write_raw_ipv4(libnet_t *l, const uint8_t *packet, uint32_t size)
1.1       misho     251: {
                    252:     return (libnet_win32_write_raw_ipv4(l, packet, size));
                    253: }
                    254: 
                    255: int
1.1.1.2   misho     256: libnet_write_raw_ipv6(libnet_t *l, const uint8_t *packet, uint32_t size)
1.1       misho     257: {
                    258:     /* no difference in win32 */
                    259:     return (libnet_write_raw_ipv4(l, packet, size));
                    260: }
                    261: 
                    262: #else /* __WIN32__ */
                    263: 
                    264: int
1.1.1.2   misho     265: libnet_write_raw_ipv4(libnet_t *l, const uint8_t *packet, uint32_t size)
1.1       misho     266: {
                    267:     int c;
                    268:     struct sockaddr_in sin;
                    269:     struct libnet_ipv4_hdr *ip_hdr;
                    270: 
                    271:     if (l == NULL)
1.1.1.3 ! misho     272:     {
1.1       misho     273:         return (-1);
1.1.1.3 ! misho     274:     }
1.1       misho     275: 
                    276:     ip_hdr = (struct libnet_ipv4_hdr *)packet;
                    277: 
                    278: #if (LIBNET_BSD_BYTE_SWAP)
                    279:     /*
                    280:      *  For link access, we don't need to worry about the inconsistencies of
                    281:      *  certain BSD kernels.  However, raw socket nuances abound.  Certain
1.1.1.3 ! misho     282:      *  BSD implementations require the ip_len and ip_off fields to be in host
1.1       misho     283:      *  byte order.
                    284:      */
                    285:     ip_hdr->ip_len = FIX(ip_hdr->ip_len);
                    286:     ip_hdr->ip_off = FIX(ip_hdr->ip_off);
                    287: #endif /* LIBNET_BSD_BYTE_SWAP */
                    288: 
                    289:     memset(&sin, 0, sizeof(sin));
                    290:     sin.sin_family  = AF_INET;
                    291:     sin.sin_addr.s_addr = ip_hdr->ip_dst.s_addr;
                    292: 
                    293:     c = sendto(l->fd, packet, size, 0, (struct sockaddr *)&sin,
1.1.1.2   misho     294:             sizeof(sin));
1.1       misho     295: 
                    296: #if (LIBNET_BSD_BYTE_SWAP)
                    297:     ip_hdr->ip_len = UNFIX(ip_hdr->ip_len);
                    298:     ip_hdr->ip_off = UNFIX(ip_hdr->ip_off);
                    299: #endif /* LIBNET_BSD_BYTE_SWAP */
                    300: 
                    301:     if (c != size)
                    302:     {
                    303:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     304:                 "%s(): %d bytes written (%s)", __func__, c,
1.1       misho     305:                 strerror(errno));
                    306:     }
                    307:     return (c);
                    308: }
                    309: 
                    310: int
1.1.1.2   misho     311: libnet_write_raw_ipv6(libnet_t *l, const uint8_t *packet, uint32_t size)
1.1       misho     312: {
1.1.1.3 ! misho     313:     int c = -1;
        !           314: 
1.1       misho     315: #if defined HAVE_SOLARIS && !defined HAVE_SOLARIS_IPV6
1.1.1.3 ! misho     316:     snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): no IPv6 support",
1.1       misho     317:             __func__, strerror(errno));
                    318: #else
                    319:     struct sockaddr_in6 sin;
                    320:     struct libnet_ipv6_hdr *ip_hdr;
                    321: 
                    322:     if (l == NULL)
1.1.1.3 ! misho     323:     {
1.1       misho     324:         return (-1);
1.1.1.3 ! misho     325:     }
1.1       misho     326: 
                    327:     ip_hdr = (struct libnet_ipv6_hdr *)packet;
                    328: 
                    329:     memset(&sin, 0, sizeof(sin));
                    330:     sin.sin6_family  = AF_INET6;
                    331:     memcpy(sin.sin6_addr.s6_addr, ip_hdr->ip_dst.libnet_s6_addr,
                    332:             sizeof(ip_hdr->ip_dst.libnet_s6_addr));
1.1.1.3 ! misho     333: 
1.1       misho     334:     c = sendto(l->fd, packet, size, 0, (struct sockaddr *)&sin, sizeof(sin));
                    335:     if (c != size)
                    336:     {
                    337:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     338:                 "%s(): %d bytes written (%s)", __func__, c,
1.1       misho     339:                 strerror(errno));
                    340:     }
1.1.1.3 ! misho     341: #endif  /* HAVE_SOLARIS && !HAVE_SOLARIS_IPV6 */
1.1       misho     342:     return (c);
                    343: }
1.1.1.3 ! misho     344: #endif /* __WIN32__ */
        !           345: 
        !           346: /**
        !           347:  * Local Variables:
        !           348:  *  indent-tabs-mode: nil
        !           349:  *  c-file-style: "stroustrup"
        !           350:  * End:
        !           351:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>