⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libnet_pblock.c

📁 tcp数据流重放工具
💻 C
字号:
/* *  $Id: libnet_pblock.c,v 1.6 2003/09/23 22:36:55 mike Exp $ * *  libnet *  libnet_pblock.c - Memory protocol block routines. * *  Copyright (c) 1998 - 2003 Mike D. Schiffman <mike@infonexus.com> *  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#if (HAVE_CONFIG_H)#include "../include/config.h"#endif#if (!(_WIN32) || (__CYGWIN__)) 
#include "../include/libnet.h"
#else
#include "../include/win32/libnet.h"
#endiflibnet_pblock_t *libnet_pblock_probe(libnet_t *l, libnet_ptag_t ptag, u_int32_t n, u_int8_t type){    int offset;    libnet_pblock_t *p;    if (ptag == LIBNET_PTAG_INITIALIZER)    {        /*         *  Create a new pblock and enough buffer space for the packet.         */        p = libnet_pblock_new(l, n);        if (p == NULL)        {            /* err msg set in libnet_pblock_new() */            return (NULL);        }    }    else    {        /*         *  Update this pblock, don't create a new one.  Note that if the         *  new packet size is larger than the old one we will do a malloc.         */        p = libnet_pblock_find(l, ptag);        if (p == NULL)        {            /* err msg set in libnet_pblock_find() */            return (NULL);        }        if (p->type != type)        {            snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,            "%s(): ptag references different type than expected (%d != %d)",                    __func__, p->type, type);            return (NULL);         }        /*         *  If size is greater than the original block of memory, we need          *  to malloc more memory.  Should we use realloc?         */        if (n > p->b_len)        {            offset = n - p->b_len;  /* how many bytes larger new pblock is */            free(p->buf);            p->buf = malloc(n);            if (p->buf == NULL)            {                snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                        "%s(): can't resize pblock buffer: %s", __func__,                        strerror(errno));                return (NULL);            }            memset(p->buf, 0, n);            p->h_len += offset; /* new length for checksums */            p->b_len = n;       /* new buf len */            l->total_size += offset;        }        else        {            offset = p->b_len - n;            p->h_len -= offset; /* new length for checksums */            p->b_len = n;       /* new buf len */            l->total_size -= offset;        }        p->copied = 0;      /* reset copied counter */    }    return (p);}libnet_pblock_t *libnet_pblock_new(libnet_t *l, u_int32_t size){    libnet_pblock_t *p;    /*     *  Should we do error checking the size of the pblock here, or     *  should we rely on the underlying operating system to complain when     *  the user tries to write some ridiculously huge packet?     */    /* make the head node if it doesn't exist */    if (l->protocol_blocks == NULL)    {        l->protocol_blocks = malloc(sizeof (libnet_pblock_t));        if (l->protocol_blocks == NULL)        {            goto bad;        }        memset(l->protocol_blocks, 0, sizeof (libnet_pblock_t));        l->protocol_blocks->buf = malloc(size);        if (l->protocol_blocks->buf == NULL)        {            free(l->protocol_blocks);            l->protocol_blocks = NULL;            goto bad;        }        memset(l->protocol_blocks->buf, 0, size);        l->protocol_blocks->b_len   = size;        l->protocol_blocks->copied  = 0;        l->protocol_blocks->next    = NULL;        l->protocol_blocks->prev    = NULL;        l->total_size               = size;        l->protocol_blocks->flags   = 0;        return (l->protocol_blocks);    }    else    {        /* walk to the end of the list */        for (p = l->protocol_blocks; p->next; p = p->next) ;        p->next = malloc(sizeof (libnet_pblock_t));        if (p->next == NULL)        {            goto bad;        }        memset(p->next, 0, sizeof (libnet_pblock_t));        p->next->prev = p;        p = p->next;        p->buf = malloc(size);        if (p->buf == NULL)        {            free(p);            p = NULL;            goto bad;        }        memset(p->buf, 0, size);        p->b_len    = size;        p->copied   = 0;        p->next     = NULL;        l->total_size += size;        p->flags    = 0;        return (p);    }    bad:    snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): %s", __func__,             strerror(errno));    return (NULL);}intlibnet_pblock_swap(libnet_t *l, libnet_ptag_t ptag1, libnet_ptag_t ptag2){    libnet_pblock_t *p1, *p2;    p1 = libnet_pblock_find(l, ptag1);    p2 = libnet_pblock_find(l, ptag2);    if (p1 == NULL || p2 == NULL)    {        /* error set elsewhere */        return (-1);    }    p2->prev = p1->prev;    p1->next = p2->next;    p2->next = p1;    p1->prev = p2;    if (p1->next)    {        p1->next->prev = p1;    }    if (p2->prev)    {        p2->prev->next = p2;    }    else    {        /* first node on the list */        l->protocol_blocks = p2;    }    if (l->pblock_end == p2)    {        l->pblock_end = p1;    }    return (1);}intlibnet_pblock_insert_before(libnet_t *l, libnet_ptag_t ptag1,        libnet_ptag_t ptag2){    libnet_pblock_t *p1, *p2;    p1 = libnet_pblock_find(l, ptag1);    p2 = libnet_pblock_find(l, ptag2);    if (p1 == NULL || p2 == NULL)    {        /* error set elsewhere */        return (-1);    }    p2->prev = p1->prev;    p2->next = p1;    p1->prev = p2;    if (p2->prev)      {        p2->prev->next = p2;    }    else    {        /* first node on the list */        l->protocol_blocks = p2;    }        return (1);}libnet_pblock_t *libnet_pblock_find(libnet_t *l, libnet_ptag_t ptag){    libnet_pblock_t *p;    for (p = l->protocol_blocks; p; p = p->next)    {        if (p->ptag == ptag)        {            return (p);         }    }    snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,            "%s(): couldn't find protocol block", __func__);    return (NULL);}intlibnet_pblock_append(libnet_t *l, libnet_pblock_t *p, u_int8_t *buf,            u_int32_t len){    if (p->copied + len > p->b_len)    {        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                "%s(): memcpy would overflow buffer", __func__);        return (-1);    }    memcpy(p->buf + p->copied, buf, len);    p->copied += len;    return (1);}voidlibnet_pblock_setflags(libnet_pblock_t *p, u_int8_t flags){    p->flags = flags;}libnet_ptag_tlibnet_pblock_update(libnet_t *l, libnet_pblock_t *p, u_int32_t h, u_int8_t type){    p->type  =  type;    p->ptag  =  ++(l->ptag_state);    p->h_len = h;    l->pblock_end = p;              /* point end of pblock list here */    return (p->ptag);}intlibnet_pblock_coalesce(libnet_t *l, u_int8_t **packet, u_int32_t *size){    libnet_pblock_t *p, *q;    u_int32_t c, n;    /*     *  Determine the offset required to keep memory aligned (strict     *  architectures like solaris enforce this, but's a good practice     *  either way).  This is only required on the link layer with the     *  14 byte ethernet offset (others are similarly unkind).     */    if (l->injection_type == LIBNET_LINK ||         l->injection_type == LIBNET_LINK_ADV)    {        /* 8 byte alignment should work */       l->aligner = 8 - (l->link_offset % 8);    }    else    {        l->aligner = 0;    }    *packet = malloc(l->aligner + l->total_size);    if (*packet == NULL)    {        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): %s",                __func__, strerror(errno));        return (-1);    }    if (l->injection_type == LIBNET_RAW4 &&         l->pblock_end->type == LIBNET_PBLOCK_IPV4_H)    {        libnet_pblock_setflags(l->pblock_end, LIBNET_PBLOCK_DO_CHECKSUM);     }        /* additional sanity checks to perform if we're not in advanced mode */    if (!(l->injection_type & LIBNET_ADV_MASK))    {    	switch (l->injection_type)    	{            case LIBNET_LINK:                if ((l->pblock_end->type != LIBNET_PBLOCK_TOKEN_RING_H) &&                    (l->pblock_end->type != LIBNET_PBLOCK_FDDI_H)       &&                    (l->pblock_end->type != LIBNET_PBLOCK_ETH_H)        &&                    (l->pblock_end->type != LIBNET_PBLOCK_802_3_H))                {                    snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                     "%s(): packet assembly cannot find a layer 2 header",                    __func__);                    return (-1);                }                break;            case LIBNET_RAW4:                if ((l->pblock_end->type != LIBNET_PBLOCK_IPV4_H))                {                    snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                     "%s(): packet assembly cannot find an IPv4 header",                     __func__);                    return (-1);                }                break;            case LIBNET_RAW6:                if ((l->pblock_end->type != LIBNET_PBLOCK_IPV6_H))                {                    snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                     "%s(): packet assembly cannot find an IPv6 header",                     __func__);                    return (-1);                }                break;            default:                /* we should not end up here ever */                snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,                 "%s(): suddenly the dungeon collapses on your head -- you die",                 __func__);                return (-1);            break;        }    }    q = NULL;     for (n = l->aligner + l->total_size, p = l->protocol_blocks; p || q; )    {        if (q)        {            p = p->next;        }        if (p)        {            n -= p->b_len;            /* copy over the packet chunk */            memcpy(*packet + n, p->buf, p->b_len);        }        if (q)        {            if (p == NULL || ((p->flags) & LIBNET_PBLOCK_DO_CHECKSUM))            {                if ((q->flags) & LIBNET_PBLOCK_DO_CHECKSUM)                {                    c = libnet_do_checksum(l, (l->injection_type == LIBNET_LINK                            || l->injection_type == LIBNET_LINK_ADV) ?                            *packet + l->link_offset + l->aligner : *packet,                            libnet_pblock_p2p(q->type), q->h_len);                    if (c == -1)                    {                        /* err msg set in libnet_do_checksum() */                        return (-1);                    }                }                q = p;            }        }        else        {            q = p;        }    }    *size = l->aligner + l->total_size;    /*     *  Set the packet pointer to the true beginning of the packet and set     *  the size for transmission.     */    if ((l->injection_type == LIBNET_LINK ||        l->injection_type == LIBNET_LINK_ADV) && l->aligner)    {        *packet += l->aligner;        *size -= l->aligner;    }    return (1);}voidlibnet_pblock_delete(libnet_t *l, libnet_pblock_t *p){    if (p)    {        l->total_size -= p->b_len;        if (p->prev)         {            p->prev->next = p->next;        }        else        {            l->protocol_blocks = p->next;        }        if (p->next)        {            p->next->prev = p->prev;        }        else        {            l->pblock_end = p->prev;        }        if (p->buf)        {          free(p->buf);        }        free(p);        p = NULL;    }}intlibnet_pblock_p2p(u_int8_t type){    /* for checksum; return the protocol number given a pblock type*/    switch (type)    {        case LIBNET_PBLOCK_CDP_H:            return (LIBNET_PROTO_CDP);        case LIBNET_PBLOCK_ICMPV4_H:        case LIBNET_PBLOCK_ICMPV4_ECHO_H:        case LIBNET_PBLOCK_ICMPV4_MASK_H:        case LIBNET_PBLOCK_ICMPV4_UNREACH_H:        case LIBNET_PBLOCK_ICMPV4_TIMXCEED_H:        case LIBNET_PBLOCK_ICMPV4_REDIRECT_H:        case LIBNET_PBLOCK_ICMPV4_TS_H:            return (IPPROTO_ICMP);        case LIBNET_PBLOCK_IGMP_H:            return (IPPROTO_IGMP);        case LIBNET_PBLOCK_IPV4_H:            return (IPPROTO_IP);        case LIBNET_ISL_H:            return (LIBNET_PROTO_ISL);        case LIBNET_PBLOCK_OSPF_H:            return (IPPROTO_OSPF);        case LIBNET_PBLOCK_LS_RTR_H:            return (IPPROTO_OSPF_LSA);        case LIBNET_PBLOCK_TCP_H:            return (IPPROTO_TCP);        case LIBNET_PBLOCK_UDP_H:            return (IPPROTO_UDP);        case LIBNET_PBLOCK_VRRP_H:            return (IPPROTO_VRRP);        case LIBNET_PBLOCK_GRE_H:            return (IPPROTO_GRE);        default:            return (-1);    }}/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -