int
libnet_adv_cull_header(libnet_t *l, libnet_ptag_t ptag, uint8_t **header,
        uint32_t *header_s)
{
    libnet_pblock_t *p;

    *header = NULL;
    *header_s = 0;

    if (l->injection_type != LIBNET_LINK_ADV)
    {
        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
                "%s(): advanced link mode not enabled\n", __func__);
        return (-1);
    }

    p = libnet_pblock_find(l, ptag);
    if (p == NULL)
    {
        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
            "%s(): ptag not found, you sure it exists?\n", __func__);
        return (-1);
    }
    *header   = p->buf;
    *header_s = p->b_len;

    return (1);
}
Exemple #2
0
static libnet_pblock_t* checkpblock(lua_State* L, libnet_t* ud, int narg)
{
    int ptag = luaL_checkint(L, narg);
    libnet_pblock_t* pblock = libnet_pblock_find(ud, ptag);
    luaL_argcheck(L, pblock, narg, "ptag cannot be found");
    return pblock;
}
Exemple #3
0
/*-
- ptag = n:ipv4{len=int, protocol=int, src=ipaddr, dst=ipaddr, payload=str, ptag=int, options=ip_options}

ptag is optional, defaults to creating a new protocol block
options is optional
*/
static int lnet_ipv4 (lua_State *L)
{
    libnet_t** ud = luaL_checkudata(L, 1, L_NET_REGID);
    luaL_argcheck(L, *ud, 1, "net has been destroyed");

    int len = v_arg_integer(L, 2, "len"); // FIXME - should be optional!
    int tos = 0;
    int id = 0;
    int offset = 0;
    int ttl = 64;
    int protocol = v_arg_integer(L, 2, "protocol");
    int cksum = 0; // 0 is a flag requesting libnet to fill in correct cksum
    const char* src = v_arg_string(L, 2, "src");
    const char* dst = v_arg_string(L, 2, "dst");
    size_t payloadsz = 0;
    const char* payload = v_arg_lstring(L, 2, "payload", &payloadsz, "");
    int ptag = lnet_arg_ptag(L, 2);
    int options_ptag = 0;
    size_t optionsz = 0;
    const char* options = v_arg_lstring(L, 2, "options", &optionsz, "");

    if(payloadsz == 0) {
        payload = NULL;
    }

#ifdef NET_DUMP
    printf("net ipv4 src %s dst %s len %d payloadsz %lu ptag %d optionsz %lu\n", src, dst, len, payloadsz, ptag, optionsz);
#endif

    uint32_t src_n = check_ip_pton(L, src, "src");
    uint32_t dst_n = check_ip_pton(L, dst, "dst");

    if(ptag) {
        /* Modifying exist IPv4 packet, so find the preceeding options block (we
         * _always_ push an options block, perhaps empty, to make this easy).
         */
        libnet_pblock_t* p = libnet_pblock_find(*ud, ptag);

        if(!p)
            return check_error(L, *ud, -1);

        options_ptag = p->prev->ptag;
    }

#ifdef NET_DUMP
    printf("  options_ptag %d optionsz %lu\n", options_ptag, optionsz);
#endif

    options_ptag = libnet_build_ipv4_options((uint8_t*) options,
            optionsz, *ud, options_ptag);

    check_error(L, *ud, options_ptag);

    ptag = libnet_build_ipv4(len, tos, id, offset, ttl, protocol, cksum, src_n,
            dst_n, (uint8_t*) payload, payloadsz, *ud, ptag);
    check_error(L, *ud, ptag);
    lua_pushinteger(L, ptag);
    return 1;
}
Exemple #4
0
/* check ptag argument is zero, or refers to a pblock of the expected type */
static int lnet_arg_ptag(lua_State* L, libnet_t* ud, int targ, int type)
{
    int ptag = v_arg_integer_opt(L, targ, "ptag", LIBNET_PTAG_INITIALIZER);

    if(ptag) {
        libnet_pblock_t* pblock = libnet_pblock_find(ud, ptag);
        luaL_argcheck(L, pblock, targ,
                lua_pushfstring(L, "ptag %d cannot be found", ptag));
        luaL_argcheck(L, pblock->type == type, targ,
                lua_pushfstring(L, "ptag %d of type %s/%s is not %s/%s",
                ptag,
                pushistring(L, "%#x", pblock->type), libnet_diag_dump_pblock_type(pblock->type),
                pushistring(L, "%#x", type), libnet_diag_dump_pblock_type(type)
                ));
    }

    return ptag;
}
Exemple #5
0
uint32_t
libnet_getpbuf_size(libnet_t *l, libnet_ptag_t ptag)
{
    libnet_pblock_t *p;

    if (l == NULL)
    { 
        return (0);
    } 

    p = libnet_pblock_find(l, ptag);
    if (p == NULL)
    {
        /* err msg set in libnet_pblock_find() */
        return (0);
    }
    else
    {
        return (p->b_len);
    }
}
Exemple #6
0
uint8_t *
libnet_getpbuf(libnet_t *l, libnet_ptag_t ptag)
{
    libnet_pblock_t *p;

    if (l == NULL)
    { 
        return (NULL);
    }

    p = libnet_pblock_find(l, ptag);
    if (p == NULL)
    {
        /* err msg set in libnet_pblock_find() */
        return (NULL);
    }
    else
    {
        return (p->buf);
    }
}
int
libnet_toggle_checksum(libnet_t *l, libnet_ptag_t ptag, int mode)
{
    libnet_pblock_t *p;

    p = libnet_pblock_find(l, ptag);
    if (p == NULL)
    {
        /* err msg set in libnet_pblock_find() */
        return (-1);
    }
    if (mode == LIBNET_ON)
    {
        if ((p->flags) & LIBNET_PBLOCK_DO_CHECKSUM)
        {
            return (1);
        }
        else
        {
            (p->flags) |= LIBNET_PBLOCK_DO_CHECKSUM;
            return (1);
        }
    }
    else
    {
        if ((p->flags) & LIBNET_PBLOCK_DO_CHECKSUM)
        {
            (p->flags) &= ~LIBNET_PBLOCK_DO_CHECKSUM;
            return (1);
        }
        else
        {
            return (1);
        }
    }
}
Exemple #8
0
libnet_ptag_t
libnet_build_tcp(u_int16_t sp, u_int16_t dp, u_int32_t seq, u_int32_t ack,
u_int8_t control, u_int16_t win, u_int16_t sum, u_int16_t urg, u_int16_t len,
u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
{
    int n, offset;
    u_int32_t i, j;
    libnet_pblock_t *p, *p_data, *p_temp;
    libnet_ptag_t ptag_hold, ptag_data;
    struct libnet_tcp_hdr tcp_hdr;
    struct libnet_ipv4_hdr *ip_hdr;

    if (l == NULL)
    { 
        return (-1);
    } 

    ptag_data = 0;                      /* for possible options */

    /*
     *  Find the existing protocol block if a ptag is specified, or create
     *  a new one.
     */
    p = libnet_pblock_probe(l, ptag, LIBNET_TCP_H, LIBNET_PBLOCK_TCP_H);
    if (p == NULL)
    {
        return (-1);
    }

    memset(&tcp_hdr, 0, sizeof(tcp_hdr));
    tcp_hdr.th_sport   = htons(sp);    /* source port */
    tcp_hdr.th_dport   = htons(dp);    /* destination port */
    tcp_hdr.th_seq     = htonl(seq);   /* sequence number */
    tcp_hdr.th_ack     = htonl(ack);   /* acknowledgement number */
    tcp_hdr.th_flags   = control;      /* control flags */
    tcp_hdr.th_x2      = 0;            /* UNUSED */
    tcp_hdr.th_off     = 5;            /* 20 byte header */

    /* check to see if there are TCP options to include */
    if (p->prev)
    {
        p_temp = p->prev;
        while ((p_temp->prev) && (p_temp->type != LIBNET_PBLOCK_TCPO_H))
        {
            p_temp = p_temp->prev;
        }
        if (p_temp->type == LIBNET_PBLOCK_TCPO_H)
        {
            /*
             *  Count up number of 32-bit words in options list, padding if
             *  neccessary.
             */
            for (i = 0, j = 0; i < p_temp->b_len; i++)
            {
                (i % 4) ? j : j++;
            }
            tcp_hdr.th_off += j;
        }
    }

    tcp_hdr.th_win     = htons(win);   /* window size */
    tcp_hdr.th_sum     = (sum ? htons(sum) : 0);   /* checksum */ 
    tcp_hdr.th_urp     = htons(urg);          /* urgent pointer */

    n = libnet_pblock_append(l, p, (u_int8_t *)&tcp_hdr, LIBNET_TCP_H);
    if (n == -1)
    {
        goto bad;
    }

    ptag_hold = ptag;
    if (ptag == LIBNET_PTAG_INITIALIZER)
    {
        ptag = libnet_pblock_update(l, p, len, LIBNET_PBLOCK_TCP_H);
    }

    /* find and set the appropriate ptag, or else use the default of 0 */
    offset = payload_s;
    if (ptag_hold && p->prev)
    {
        p_temp = p->prev;
        while (p_temp->prev &&
              (p_temp->type != LIBNET_PBLOCK_TCPDATA) &&
              (p_temp->type != LIBNET_PBLOCK_TCP_H))
        {
           p_temp = p_temp->prev;
        }

        if (p_temp->type == LIBNET_PBLOCK_TCPDATA)
        {
            ptag_data = p_temp->ptag;
            offset -=  p_temp->b_len;
            p->h_len += offset;
        }
        else
        {
            snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
				    "%s(): TCP data pblock not found\n", __func__);
        }
     }

    /* update ip_len if present */
    if (ptag_hold && p->next)
    {
        p_temp = p->next;
        while (p_temp->next && (p_temp->type != LIBNET_PBLOCK_IPV4_H))
        {
            p_temp = p_temp->next;
        }
        if (p_temp->type == LIBNET_PBLOCK_IPV4_H)
        {
            ip_hdr = (struct libnet_ipv4_hdr *)p_temp->buf;
            n = ntohs(ip_hdr->ip_len) + offset;
            ip_hdr->ip_len = htons(n);
        }
    }

    if ((payload && !payload_s) || (!payload && payload_s))
    {
        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
			    "%s(): payload inconsistency\n", __func__);
        goto bad;
    }

    /* if there is a payload, add it in the context */
    if (payload && payload_s)
    {
        /* update ptag_data with the new payload */
        p_data = libnet_pblock_probe(l, ptag_data, payload_s,
                LIBNET_PBLOCK_TCPDATA);
        if (p_data == NULL) 
        {
            return (-1);
        }

        if (libnet_pblock_append(l, p_data, payload, payload_s) == -1)
        {
            goto bad;
        }

        if (ptag_data == LIBNET_PTAG_INITIALIZER)
        {
            if (p_data->prev->type == LIBNET_PBLOCK_TCP_H)
            {
                libnet_pblock_update(l, p_data, payload_s,
                        LIBNET_PBLOCK_TCPDATA);
                /* swap pblocks to correct the protocol order */
                libnet_pblock_swap(l, p->ptag, p_data->ptag);
            }
            else
            {
                /* update without setting this as the final pblock */
                p_data->type  =  LIBNET_PBLOCK_TCPDATA;
                p_data->ptag  =  ++(l->ptag_state);
                p_data->h_len =  payload_s;

                /* Adjust h_len for checksum. */
                p->h_len += payload_s;

                /* data was added after the initial construction */
                for (p_temp = l->protocol_blocks;
                        p_temp->type == LIBNET_PBLOCK_TCP_H ||
                        p_temp->type == LIBNET_PBLOCK_TCPO_H;
                        p_temp = p_temp->next)
                {
                    libnet_pblock_insert_before(l, p_temp->ptag, p_data->ptag);
                    break;
                }
                /* The end block needs to have its next pointer cleared. */
                l->pblock_end->next = NULL;
            }

            if (p_data->prev && p_data->prev->type == LIBNET_PBLOCK_TCPO_H)
            {
                libnet_pblock_swap(l, p_data->prev->ptag, p_data->ptag);
            }
        }
    }
    else
    {
        p_data = libnet_pblock_find(l, ptag_data);
        if (p_data) 
        {
            libnet_pblock_delete(l, p_data);
        }
    }

    if (sum == 0)
    {
        /*
         *  If checksum is zero, by default libnet will compute a checksum
         *  for the user.  The programmer can override this by calling
         *  libnet_toggle_checksum(l, ptag, 1);
         */
        libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
    }
    return (ptag);
bad:
    libnet_pblock_delete(l, p);
    return (-1);
}
Exemple #9
0
libnet_ptag_t
libnet_build_tcp_options(u_int8_t *options, u_int32_t options_s, libnet_t *l, 
libnet_ptag_t ptag)
{
    int offset, underflow;
    u_int32_t i, j, n, adj_size;
    libnet_pblock_t *p, *p_temp;
    struct libnet_ipv4_hdr *ip_hdr;
    struct libnet_tcp_hdr *tcp_hdr;

    if (l == NULL)
    { 
        return (-1);
    }

    underflow = 0;
    offset = 0;

    /* check options list size */
    if (options_s > LIBNET_MAXOPTION_SIZE)
    {
        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
            "%s(): options list is too large %d\n", __func__, options_s);
        return (-1);
    }

    adj_size = options_s;
    if (adj_size % 4)
    {
        /* size of memory block with padding */
        adj_size += 4 - (options_s % 4);
    }

    /* if this pblock already exists, determine if there is a size diff */
    if (ptag)
    {
        p_temp = libnet_pblock_find(l, ptag);
        if (p_temp)
        {
            if (adj_size >= p_temp->b_len)
            {
                offset = adj_size - p_temp->b_len;
            }
            else
            {
                offset = p_temp->b_len - adj_size;
                underflow = 1;
            }
        }
    }

    /*
     *  Find the existing protocol block if a ptag is specified, or create
     *  a new one.
     */
    p = libnet_pblock_probe(l, ptag, adj_size, LIBNET_PBLOCK_TCPO_H);
    if (p == NULL)
    {
        return (-1);
    }
	
    n = libnet_pblock_append(l, p, options, adj_size);
    if (n == -1)
    {
        goto bad;
    }
	
    if (ptag && p->next)
    {
        p_temp = p->next;
        while ((p_temp->next) && (p_temp->type != LIBNET_PBLOCK_TCP_H))
        {
           p_temp = p_temp->next;
        }
        if (p_temp->type == LIBNET_PBLOCK_TCP_H)
        {
            /*
             *  Count up number of 32-bit words in options list, padding if
             *  neccessary.
             */
            for (i = 0, j = 0; i < p->b_len; i++)
            {
                (i % 4) ? j : j++;
            }
            tcp_hdr = (struct libnet_tcp_hdr *)p_temp->buf;
            tcp_hdr->th_off = j + 5;
            if (!underflow)
            {
                p_temp->h_len += offset;
            }
            else
            {
                p_temp->h_len -= offset;
            }
        }
        while ((p_temp->next) && (p_temp->type != LIBNET_PBLOCK_IPV4_H))
        {
            p_temp = p_temp->next;
        }
        if (p_temp->type == LIBNET_PBLOCK_IPV4_H)
        {
            ip_hdr = (struct libnet_ipv4_hdr *)p_temp->buf;
            if (!underflow)
            {
                ip_hdr->ip_len += htons(offset);
            }
            else
            {
                ip_hdr->ip_len -= htons(offset);
            }
        }
    }

    return (ptag ? ptag : libnet_pblock_update(l, p, adj_size,
            LIBNET_PBLOCK_TCPO_H));
bad:
    libnet_pblock_delete(l, p);
    return (-1);
}
Exemple #10
0
libnet_ptag_t
libnet_build_tcp(
            uint16_t sp, uint16_t dp, uint32_t seq, uint32_t ack,
            uint8_t control, uint16_t win, uint16_t sum, uint16_t urg, uint16_t h_len,
            const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
{
    int n, offset;
    libnet_pblock_t *p = NULL;
    libnet_ptag_t ptag_data = 0;
    struct libnet_tcp_hdr tcp_hdr;

    if (l == NULL)
        return -1;

    if (payload_s && !payload)
    {
        snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
			    "%s(): payload inconsistency", __func__);
        return -1;
    }

    p = libnet_pblock_probe(l, ptag, LIBNET_TCP_H, LIBNET_PBLOCK_TCP_H);
    if (p == NULL)
        return -1;

    memset(&tcp_hdr, 0, sizeof(tcp_hdr));
    tcp_hdr.th_sport   = htons(sp);    /* source port */
    tcp_hdr.th_dport   = htons(dp);    /* destination port */
    tcp_hdr.th_seq     = htonl(seq);   /* sequence number */
    tcp_hdr.th_ack     = htonl(ack);   /* acknowledgement number */
    tcp_hdr.th_flags   = control;      /* control flags */
    tcp_hdr.th_x2      = 0;            /* UNUSED */
    tcp_hdr.th_off     = 5;            /* 20 byte header */

    /* check to see if there are TCP options to include */
    if (p->prev && p->prev->type == LIBNET_PBLOCK_TCPO_H)
    {
        /* Note that the tcp options pblock is already padded */
        tcp_hdr.th_off += (p->prev->b_len/4);
    }

    tcp_hdr.th_win     = htons(win);   /* window size */
    tcp_hdr.th_sum     = (sum ? htons(sum) : 0);   /* checksum */ 
    tcp_hdr.th_urp     = htons(urg);          /* urgent pointer */

    n = libnet_pblock_append(l, p, (uint8_t *)&tcp_hdr, LIBNET_TCP_H);
    if (n == -1)
    {
        goto bad;
    }

    if (ptag == LIBNET_PTAG_INITIALIZER)
    {
        libnet_pblock_update(l, p, h_len, LIBNET_PBLOCK_TCP_H);
    }

    offset = payload_s;

    /* If we are going to modify a TCP data block, find it, and figure out the
     * "offset", the possibly negative amount by which we are increasing the ip
     * data length. */
    if (ptag)
    {
        libnet_pblock_t* datablock = p->prev;

        if (datablock && datablock->type == LIBNET_PBLOCK_TCPO_H)
            datablock = datablock->prev;

        if (datablock && datablock->type == LIBNET_PBLOCK_TCPDATA)
        {
            ptag_data = datablock->ptag;
            offset -=  datablock->b_len;
        }
        p->h_len += offset;
    }

    /* If we are modifying a TCP block, we should look forward and apply the offset
     * to our IPv4 header, if we have one.
     */
    if (p->next)
    {
        libnet_pblock_t* ipblock = p->next;

        if(ipblock->type == LIBNET_PBLOCK_IPO_H)
            ipblock = ipblock->next;

        if(ipblock && ipblock->type == LIBNET_PBLOCK_IPV4_H)
        {
            struct libnet_ipv4_hdr * ip_hdr = (struct libnet_ipv4_hdr *)ipblock->buf;
            int ip_len = ntohs(ip_hdr->ip_len) + offset;
            ip_hdr->ip_len = htons(ip_len);
        }
    }

    /* if there is a payload, add it in the context */
    if (payload_s)
    {
        /* update ptag_data with the new payload */
        libnet_pblock_t* p_data = libnet_pblock_probe(l, ptag_data, payload_s, LIBNET_PBLOCK_TCPDATA);
        if (!p_data)
        {
            goto bad;
        }

        n = libnet_pblock_append(l, p_data, payload, payload_s);
        if (n == -1)
        {
            goto bad;
        }

        if (ptag_data == LIBNET_PTAG_INITIALIZER)
        {
            int insertbefore = p->ptag;

            /* Then we created it, and we need to shuffle it back until it's before
             * the tcp header and options. */
            libnet_pblock_update(l, p_data, payload_s, LIBNET_PBLOCK_TCPDATA);

            if(p->prev && p->prev->type == LIBNET_PBLOCK_TCPO_H)
                insertbefore = p->prev->ptag;

            libnet_pblock_insert_before(l, insertbefore, p_data->ptag);
        }
    }
    else
    {
        libnet_pblock_t* p_data = libnet_pblock_find(l, ptag_data);
        libnet_pblock_delete(l, p_data);
    }

    if (sum == 0)
    {
        /*
         *  If checksum is zero, by default libnet will compute a checksum
         *  for the user.  The programmer can override this by calling
         *  libnet_toggle_checksum(l, ptag, 1);
         */
        libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
    }
    return (p->ptag);
bad:
    libnet_pblock_delete(l, p);
    return (-1);
}
Exemple #11
0
int
/* Not Yet Implemented */
libnet_build_cdp_value(uint16_t type, uint16_t len, uint8_t *value, libnet_t *l,
        libnet_ptag_t ptag)
{
    uint32_t n;
    libnet_pblock_t *p;
    struct libnet_cdp_value_hdr cdp_value_hdr;

    if (l == NULL)
    { 
        return (-1); 
    }

    /*
     *  Find the existing protocol block.
     */
    p = libnet_pblock_find(l, ptag);
    if (p == NULL)
    {
        /* err msg set in libnet_pblock_find */
        return (-1);
    }
    if (p->type != LIBNET_PBLOCK_CDP_H)
    {
         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
            "libnet_build_cdp_value: ptag references different type than expected");
        return (-1);
    }

    memset(&cdp_value_hdr, 0, sizeof(cdp_value_hdr));
    cdp_value_hdr.cdp_type  = htons(type);
    cdp_value_hdr.cdp_len   = htons(len + LIBNET_CDP_VALUE_H);   /* 4 bytes for len and type */

    switch (type)
    {
        case LIBNET_CDP_DEVID:
            break;
        case LIBNET_CDP_ADDRESS:
            break;
        case LIBNET_CDP_PORTID:
            break;
        case LIBNET_CDP_CAPABIL:
            break;
        case LIBNET_CDP_VERSION:
            break;
        case LIBNET_CDP_PLATFORM:
            break;
        case LIBNET_CDP_IPPREFIX:
            break;
        default:
            break;
    }

    n = libnet_pblock_append(l, p, (uint8_t *)&cdp_value_hdr, LIBNET_CDP_VALUE_H);
    if (n == -1)
    {
        return (-1);
    }

    n = libnet_pblock_append(l, p, value, len);
    if (n == -1)
    {
        /* err msg set in libnet_pblock_append() */
        return (-1);
    }

    return (1);
}
Exemple #12
0
/*-
-- ptag = n:ipv4{
    -- required arguments
      src=ipaddr,
      dst=ipaddr,
      protocol=int,
    -- optional arguments
      ptag=int,
      payload=str,
      options=ip_options,
      len=int, -- default is correct length
      tos=int,
      id=int,
      frag=int,
      ttl=int, -- defaults to 64
  }

ptag is optional, defaults to creating a new protocol block
options is optional
*/
static int lnet_ipv4 (lua_State *L)
{
    libnet_t* ud = checkudata(L);
    const char* src = v_arg_string(L, 2, "src");
    const char* dst = v_arg_string(L, 2, "dst");
    uint32_t src_n = check_ip_pton(L, src, "src");
    uint32_t dst_n = check_ip_pton(L, dst, "dst");
    int protocol = v_arg_integer(L, 2, "protocol"); /* TODO make optional */
    int ptag = lnet_arg_ptag(L, ud, 2, LIBNET_PBLOCK_IPV4_H);
    uint32_t payloadsz = 0;
    const uint8_t* payload = checkpayload(L, 2, &payloadsz);
    int options_ptag = 0;
    uint32_t optionsz = 0;
    const uint8_t* options = checklbuffer(L, 2, "options", &optionsz);
    int len = v_arg_integer_opt(L, 2, "len", -1);
    int tos = v_arg_integer_opt(L, 2, "tos", 0);
    int id = v_arg_integer_opt(L, 2, "id", 0);
    int frag = v_arg_integer_opt(L, 2, "frag", 0);
    int ttl = v_arg_integer_opt(L, 2, "ttl", 64);
    int cksum = 0; /* 0 is a flag requesting libnet to fill in correct cksum */
    libnet_pblock_t* oblock = NULL;

#ifdef NET_DUMP
    printf("net ipv4 src %s dst %s len %d payloadsz %lu ptag %d optionsz %lu\n", src, dst, len, payloadsz, ptag, optionsz);
#endif

    oblock = ptag ? libnet_pblock_find(ud, ptag)->prev : ud->pblock_end;

    if(!oblock || oblock->type != LIBNET_PBLOCK_IPO_H)
      oblock = NULL;
    else
      options_ptag = oblock->ptag;

#ifdef NET_DUMP
    printf("  options_ptag %d optionsz from %lu to %lu\n",
            options_ptag, oblock ? oblock->b_len : 0, optionsz);
#endif

    /* Two initial states possible:
     *   - has prev ip options block, or not
     * Two final states desired:
     *   - has prev ip options block, or not
     */

    if(!options) {
      libnet_pblock_delete(ud, oblock);
    } else {
      options_ptag = libnet_build_ipv4_options(options, optionsz, ud, options_ptag);

      check_error(L, ud, options_ptag);

      if(oblock) {
	/* we replaced an existing block that was correctly placed */
      } else if(ptag) {
	libnet_pblock_insert_before(ud, ptag, options_ptag);
      } else {
          /* we just pushed a new options block, and are about to push a new ip block */
      }
    }

    /* If len unspecified, rewrite it to be len of ipv4 pblock + previous blocks. */
    /* FIXME I don't think defaulting to end is correct

-- libnet doesn't have a generic icmp construction api, see bug#1373
local function build_icmp(n, icmp)
    local typecode = string.char(assert(icmp.type), assert(icmp.code))
    local data = icmp.data or ""
    local checksum = net.checksum(typecode, "\0\0", data)
    local packet = typecode..checksum..data

    return n:ipv4{
        src      = arg.localip,
        dst      = arg.dutip,
        protocol = 1, -- ICMP is protocol 1 FIXME get from iana.ip.types.icmp
        payload  = packet,
        len      = 20 + #packet,
        ptag     = icmp.ptag
    }
end

getmetatable(n).icmp = build_icmp

-- set up the pblock stack, top to bottom
local ptag = n:icmp{type=0, code=0}
n:eth{src=arg.localmac, dst=arg.dutmac}

   n:icmp{ptag=ptag, type=type, code=code, payload=data}

print(n:dump())
print(n:get_ipv4())


~/w/wt/achilles-engine/data/Plugins/Grammar % sudo ./icmp-data-grammar-l2 dutip=1.1.1.1 localdev=lo localip=2.2.2.2 dutmac=11:11:11:11:11:11 localmac=22:22:22:22:22:22 pcap=pc.pcap
tag 2 flags 0 type ipdata/0xf buf 0x6541e0 b_len  4 h_len  4 copied 4 prev -1 next 1
tag 1 flags 1 type ipv4/0xd buf 0x6582f0 b_len 20 h_len 20 copied 20 prev 2 next 3
tag 3 flags 0 type eth/0x4 buf 0x647580 b_len 14 h_len  0 copied 14 prev 1 next -1
link_offset 14 aligner 0 total_size 38 nblocks 3

Total:1
Subtest 1: ICMP type 0 code 1 with payload size 1
tag 2 flags 0 type ipdata/0xf buf 0x6541e0 b_len  4 h_len  4 copied 4 prev -1 next 1
tag 1 flags 1 type ipv4/0xd buf 0x6582f0 b_len 20 h_len 20 copied 20 prev 2 next 3
tag 3 flags 0 type eth/0x4 buf 0x647580 b_len 14 h_len  0 copied 14 prev 1 next -1
link_offset 14 aligner 0 total_size 38 nblocks 3

{
ptag = 1, protocol = 1, _iphl = 5, id = 0, options = "", dst = "1.1.1.1", src = "2.2.2.2", _sum = 0, _ipv = 4, tos = 0, _len = 28, ttl = 64, frag = 0
}


============>> note that _len is 28, it should be 24
    
    */
    if(len < 0) {
        libnet_pblock_t* p = ptag ? libnet_pblock_find(ud, ptag)->prev : ud->pblock_end;

        len = LIBNET_IPV4_H + payloadsz;

        while(p) {
            len += p->b_len;
            p = p->prev;
        }
    }

    ptag = libnet_build_ipv4(
            len, tos, id, frag, ttl, protocol, cksum,
            src_n, dst_n,
            payload, payloadsz,
            ud, ptag);

    check_error(L, ud, ptag);

    lua_pushinteger(L, ptag);

    return 1;
}
Exemple #13
0
/*-
-- ptag = n:tcp{
    -- required arguments
      src=port,
      dst=port,
      seq=int,
      ack=int,
      flags=int,
      win=int,
      urg=int,
    -- optional arguments
      ptag=int,
      payload=str,
      options=tcp_options,
  }

ptag is optional, defaults to creating a new protocol block
options is optional
*/
static int lnet_tcp (lua_State *L)
{
    libnet_t* ud = checkudata(L);
    int src = v_arg_integer(L, 2, "src");
    int dst = v_arg_integer(L, 2, "dst");
    int seq = v_arg_integer(L, 2, "seq");
    int ack = v_arg_integer(L, 2, "ack");
    int flags = v_arg_integer(L, 2, "flags");
    int win = v_arg_integer(L, 2, "win");
    int urg = v_arg_integer(L, 2, "urg");
    int ptag = lnet_arg_ptag(L, ud, 2, LIBNET_PBLOCK_TCP_H);
    uint32_t payloadsz = 0;
    const uint8_t* payload = checkpayload(L, 2, &payloadsz);
    int options_ptag = 0;
    uint32_t optionsz = 0;
    const uint8_t* options = checklbuffer(L, 2, "options", &optionsz);
    int cksum = 0; /* 0 is a flag requesting libnet to fill in correct cksum */
    libnet_pblock_t* oblock = NULL;
    int len = 0; /* libnet needs len for checksum calculation */

    oblock = ptag ? libnet_pblock_find(ud, ptag)->prev : ud->pblock_end;

    if(!oblock || oblock->type != LIBNET_PBLOCK_TCPO_H)
      oblock = NULL;
    else
      options_ptag = oblock->ptag;

    /* Two initial states possible:
     *   - has prev ip options block, or not
     * Two final states desired:
     *   - has prev ip options block, or not
     */

    if(!options) {
      libnet_pblock_delete(ud, oblock);
    } else {
      options_ptag = libnet_build_tcp_options(options, optionsz, ud, options_ptag);

      check_error(L, ud, options_ptag);

      if(oblock) {
	/* we replaced an existing block that was correctly placed */
      } else if(ptag) {
	libnet_pblock_insert_before(ud, ptag, options_ptag);
      } else {
          /* we just pushed a new options block, and are about to push a new ip block */
      }
    }

    /* Rewrite len to be len of tcp pblock + previous blocks. */
    {
        libnet_pblock_t* p = ptag ? libnet_pblock_find(ud, ptag)->prev : ud->pblock_end;

        len = LIBNET_TCP_H + payloadsz;

        while(p) {
            /* don't count tcpdata pblock... we will replace it payloadsz data below */
            if(p->type != LIBNET_PBLOCK_TCPDATA)
                len += p->b_len;
            p = p->prev;
        }
    }

    ptag = libnet_build_tcp(
            src, dst, seq, ack, flags, win, cksum, urg,
            len,
            payload, payloadsz,
            ud, ptag);

    check_error(L, ud, ptag);

    lua_pushinteger(L, ptag);

    return 1;
}
Exemple #14
0
/* Note: len is in bytes, not 16-bit words! */
int
libnet_in_cksum(uint16_t *addr, int len)
{
    int sum;
#ifdef DEBIAN
    uint16_t last_byte;

    sum = 0;
    last_byte = 0;
#else
    union
    {
        uint16_t s;
        uint8_t b[2];
    }pad;

    sum = 0;
#endif

    while (len > 1)
    {
        sum += *addr++;
        len -= 2;
    }
#ifdef DEBIAN
    if (len == 1)
    {
        *(uint8_t *)&last_byte = *(uint8_t *)addr;
        sum += last_byte;
#else
    if (len == 1)
    {
        pad.b[0] = *(uint8_t *)addr;
        pad.b[1] = 0;
        sum += pad.s;
#endif
    }

    return (sum);
}

int
libnet_toggle_checksum(libnet_t *l, libnet_ptag_t ptag, int mode)
{
    libnet_pblock_t *p;

    p = libnet_pblock_find(l, ptag);
    if (p == NULL)
    {
        /* err msg set in libnet_pblock_find() */
        return (-1);
    }
    if (mode == LIBNET_ON)
    {
        if ((p->flags) & LIBNET_PBLOCK_DO_CHECKSUM)
        {
            return (1);
        }
        else
        {
            (p->flags) |= LIBNET_PBLOCK_DO_CHECKSUM;
            return (1);
        }
    }
    else
    {
        if ((p->flags) & LIBNET_PBLOCK_DO_CHECKSUM)
        {
            (p->flags) &= ~LIBNET_PBLOCK_DO_CHECKSUM;
            return (1);
        }
        else
        {
            return (1);
        }
    }
}