* $Id: libnet_pkt.c,v 1.19 2005/11/29 22:48:29 carlosc Exp $
* libnet_pkt.c - routines.
* Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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
#include "../include/config.h"
#if (!(_WIN32) || (__CYGWIN__))
#include "../include/libnet.h"
#include "../include/win32/libnet.h"
libnet_init_pkt(int injection_type
, char *device
, char *err_buf
)
if (getuid() && geteuid())
snprintf(err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): UID or EUID of 0 required\n", __func__
);
if ((WSAStartup(0x0202, &wsaData
)) != 0)
snprintf(err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): unable to initialize winsock 2\n", __func__
);
l
= (libnet_t
*)malloc(sizeof (libnet_t
));
snprintf(err_buf
, LIBNET_ERRBUF_SIZE
, "%s(): malloc(): %s\n", __func__
,
memset(l
, 0, sizeof (*l
));
l
->injection_type
= injection_type
;
l
->ptag_state
= LIBNET_PTAG_INITIALIZER
;
l
->device
= (device
? strdup(device
) : NULL
);
strncpy(l
->label
, LIBNET_LABEL_DEFAULT
, LIBNET_LABEL_SIZE
);
l
->label
[sizeof(l
->label
)] = '\0';
switch (l
->injection_type
)
if (libnet_select_device(l
) == -1)
snprintf(err_buf
, LIBNET_ERRBUF_SIZE
, l
->err_buf
);
if (libnet_open_link(l
) == -1)
snprintf(err_buf
, LIBNET_ERRBUF_SIZE
, l
->err_buf
);
if (libnet_open_raw4(l
) == -1)
snprintf(err_buf
, LIBNET_ERRBUF_SIZE
, l
->err_buf
);
if (libnet_open_raw6(l
) == -1)
snprintf(err_buf
, LIBNET_ERRBUF_SIZE
, l
->err_buf
);
snprintf(err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): unsupported injection type\n", __func__
);
libnet_pblock_coalesce_pkt(libnet_t
*l
, u_int8_t
**packet
, u_int32_t
*size
, u_int32_t align
);
libnet_print_pkt(u_int8_t
*pktbuf
, u_int32_t pktlen
)
fprintf(stderr
, "pktbuf = 0x%p, pktlen = %d\n", pktbuf
, pktlen
);
for (i
=0; i
<pktlen
; i
++) {
if(!(i
%16)) fprintf (stderr
,"\n %06d\t\t",i
);
fprintf(stderr
,"%02x ", pktbuf
[i
]);
libnet_write_pkt(libnet_t
*l
, u_int8_t
**packet
, u_int32_t
*len
, u_int32_t align
)
c
= libnet_pblock_coalesce_pkt(l
, packet
, len
, align
);
/* err msg set in libnet_pblock_coalesce() */
switch (l
->injection_type
)
if (len
> LIBNET_MAX_PACKET
)
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): packet is too large (%d bytes)\n",
c
= libnet_write_raw_ipv4(l
, packet
, len
);
c
= libnet_write_raw_ipv6(l
, packet
, len
);
c
= libnet_write_link(l
, packet
, len
);
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): unsuported injection type\n", __func__
);
l
->stats
.bytes_written
+= c
;
l
->stats
.packet_errors
++;
* XXX - we probably should have a way to retrieve the number of
* bytes actually written (since we might have written something).
l
->stats
.bytes_written
+= c
;
* Restore original pointer address so free won't complain about a
* modified chunk pointer.
*packet
= *packet
- l
->aligner
;
libnet_pblock_coalesce_pkt(libnet_t
*l
, u_int8_t
**packet
, u_int32_t
*size
, u_int32_t align
)
* 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
= align
- (l
->link_offset
% align
);
/********** fprintf(stderr, "libnet_pblock_coalesce_pkt: aligner = %d\n", l->aligner);***/
*packet
= malloc(l
->aligner
+ l
->total_size
);
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
, "%s(): malloc(): %s\n",
__func__
, strerror(errno
));
memset(*packet
, 0, l
->aligner
+ l
->total_size
);
if (l
->injection_type
== LIBNET_RAW4
&&
l
->pblock_end
->type
== LIBNET_PBLOCK_IPV4_H
)
libnet_pblock_setflags(l
->pblock_end
, LIBNET_PBLOCK_DO_CHECKSUM
);
libnet_pblock_setflags(l
->pblock_end
, 0x0);
/* additional sanity checks to perform if we're not in advanced mode */
if (!(l
->injection_type
& LIBNET_ADV_MASK
))
switch (l
->injection_type
)
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_1Q_H
) &&
(l
->pblock_end
->type
!= LIBNET_PBLOCK_ISL_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\n",
if ((l
->pblock_end
->type
!= LIBNET_PBLOCK_IPV4_H
))
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): packet assembly cannot find an IPv4 header\n",
if ((l
->pblock_end
->type
!= LIBNET_PBLOCK_IPV6_H
))
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): packet assembly cannot find an IPv6 header\n",
/* we should not end up here ever */
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): suddenly the dungeon collapses -- you die\n",
for (n
= l
->aligner
+ l
->total_size
, p
= l
->protocol_blocks
; p
|| q
; )
/***********/fprintf(stderr
, "libnet_pblock_coalesce_pkt: p(%d) proto=%d, p->next(%d)\n", p
, libnet_pblock_p2p(p
->type
), p
->next
);
fprintf(stderr
, "libnet_pblock_coalesce_pkt: p is null");
/* copy over the packet chunk */
memcpy(*packet
+ n
, p
->buf
, p
->b_len
);
/*************fprintf(stderr, "libnet_pblock_coalesce_pkt: Copying over %d bytes from the end\n", p->b_len);*/
if (p
== NULL
|| ((p
->flags
) & LIBNET_PBLOCK_DO_CHECKSUM
))
if (p
== NULL
|| ((p
->flags
) & 0x0))
if ((q
->flags
) & LIBNET_PBLOCK_DO_CHECKSUM
)
int offset
= (l
->total_size
+ l
->aligner
) - q
->ip_offset
;
/******fprintf(stderr, "libnet_pblock_coalesce_pkt: Calling libnet_do_checksum with the packet offset set at %d, ip_offset being %d, and buf %d, proto %d, len %d\n", offset, q->ip_offset, (unsigned int)(*packet + offset), libnet_pblock_p2p(q->type), q->h_len);*/
c
= libnet_do_checksum(l
, *packet
+ offset
,
libnet_pblock_p2p(q
->type
), q
->h_len
);
/* err msg set in libnet_do_checksum() */
*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
)