File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_write.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:11:38 2023 UTC (9 months, 1 week ago) by misho
Branches: libnet, MAIN
CVS tags: v1_2p1, HEAD
Version 1.2p1

    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.
    7:  *  win32 specific code
    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: 
   33: #include "common.h"
   34: 
   35: int
   36: libnet_write(libnet_t *l)
   37: {
   38:     int c;
   39:     uint32_t len;
   40:     uint8_t *packet = NULL;
   41: 
   42:     if (l == NULL)
   43:     {
   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,
   63:                         "%s(): packet is too large (%d bytes)",
   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,
   79:                         "%s(): unsupported injection type", __func__);
   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
  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)
  119: {
  120:     struct libnet_ethernet_hdr eth_hdr;
  121: 
  122:     if (!packet)
  123:     {
  124:         return (-1);
  125:     }
  126: 
  127:     memset(&eth_hdr, 0, sizeof(eth_hdr));
  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
  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)
  148: {
  149:     struct libnet_token_ring_hdr token_ring_hdr;
  150: 
  151:     if (!packet)
  152:     {
  153:         return (-1);
  154:     }
  155: 
  156:     memset(&token_ring_hdr, 0, sizeof(token_ring_hdr));
  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);
  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: 
  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
  180: libnet_win32_write_raw_ipv4(libnet_t *l, const uint8_t *payload, uint32_t payload_s)
  181: {
  182:     static BYTE dst[ETHER_ADDR_LEN];
  183:     static BYTE src[ETHER_ADDR_LEN];
  184: 
  185:     uint8_t *packet;
  186:     uint32_t packet_s;
  187: 
  188:     DWORD remoteip = 0;
  189:     NetType type;
  190:     struct libnet_ipv4_hdr *ip_hdr = NULL;
  191: 
  192:     memset(dst, 0, sizeof(dst));
  193:     memset(src, 0, sizeof(src));
  194: 
  195:     packet_s = payload_s + l->link_offset;
  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)
  203:     {
  204:         /* error msg set in libnet_do_checksum */
  205:         return (-1);
  206:     }
  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;
  212: 
  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);
  224: 
  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,
  242:                 "%s(): network type (%d) is not supported", __func__,
  243:                 type.LinkType);
  244:             return (-1);
  245:     }
  246:     return libnet_write_link (l, packet, packet_s);
  247: }
  248: 
  249: int
  250: libnet_write_raw_ipv4(libnet_t *l, const uint8_t *packet, uint32_t size)
  251: {
  252:     return (libnet_win32_write_raw_ipv4(l, packet, size));
  253: }
  254: 
  255: int
  256: libnet_write_raw_ipv6(libnet_t *l, const uint8_t *packet, uint32_t size)
  257: {
  258:     /* no difference in win32 */
  259:     return (libnet_write_raw_ipv4(l, packet, size));
  260: }
  261: 
  262: #else /* __WIN32__ */
  263: 
  264: int
  265: libnet_write_raw_ipv4(libnet_t *l, const uint8_t *packet, uint32_t size)
  266: {
  267:     int c;
  268:     struct sockaddr_in sin;
  269:     struct libnet_ipv4_hdr *ip_hdr;
  270: 
  271:     if (l == NULL)
  272:     {
  273:         return (-1);
  274:     }
  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
  282:      *  BSD implementations require the ip_len and ip_off fields to be in host
  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,
  294:             sizeof(sin));
  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,
  304:                 "%s(): %d bytes written (%s)", __func__, c,
  305:                 strerror(errno));
  306:     }
  307:     return (c);
  308: }
  309: 
  310: int
  311: libnet_write_raw_ipv6(libnet_t *l, const uint8_t *packet, uint32_t size)
  312: {
  313:     int c = -1;
  314: 
  315: #if defined HAVE_SOLARIS && !defined HAVE_SOLARIS_IPV6
  316:     snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): no IPv6 support",
  317:             __func__, strerror(errno));
  318: #else
  319:     struct sockaddr_in6 sin;
  320:     struct libnet_ipv6_hdr *ip_hdr;
  321: 
  322:     if (l == NULL)
  323:     {
  324:         return (-1);
  325:     }
  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));
  333: 
  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,
  338:                 "%s(): %d bytes written (%s)", __func__, c,
  339:                 strerror(errno));
  340:     }
  341: #endif  /* HAVE_SOLARIS && !HAVE_SOLARIS_IPV6 */
  342:     return (c);
  343: }
  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>