My latest pet project has been building a robot with my
daughter using the BeagleBone black. You can see our robot on my robotics blog.
While I wait for a new part to arrive, I started wondering if I could
install libnet and libpcap on the BeagleBone Black so I could write some
network analysis tools that could run on it.
It turned out to be pretty straightforward.
If you are not familiar with the BeagleBone black or just
getting started with it, you can take a look at the beagleboard.org site. You can also
take a look at my “I just got my beagleBone Black now what” post to see how I have my BeagleBone setup.
I started off by downloading the libnet library from http://sourceforge.net/projects/libnet-dev/. Once the download was complete, I ran the
following commands to install it:
gunzip libnet-1.2-rc3.tar.gz
tar –xvf libnet-1.2-rc3.tar
cd libnet libnet-1.2-rc3
./configure
make
make install
This will install the libnet header files to /usr/local/include and
the libnet library files to /usr/local/lib. You will need to set the LD_LIBRARY_PATH to
include /usr/local/lib
or copy the libnet library files from /usr/local/lib to /lib (I strongly recommend setting the
LD_LIBRARY_PATH). To set the
LD_LIBRARY_PATH, I edited the /etc/profile
file and added the following line near the end of the file:
export
LD_LIBRARY_PATH=/usr/local/lib
To test the libnet installations we can use the same libnet
library that I wrote in two earlier blog posts.
To save you from going back and forth between the two posts, I am
reposting the code here but I will not re-explain it. You can look at the posts if you want to
review how the library works or want to review the network packet headers. Here are the links to the posts:
Lets begin by looking at the libnet_lib.h file. This is the header file for my custom libnet
library to make injecting packets into the network very easy:
#include <sys/types.h>
#include <stdbool.h>
#ifndef LIBNET_LIB_H
#define LIBNET_LIB_H
bool sendICMPEcho(char *addr, char *payload, int type, char *interface);
bool sendTCP(char *addr, int port, u_int8_t
flags, char *payload, char *interface);
bool sendUDP(char* addr, int port, char *payload, char *interface);
#endif // LIBNET_LIB_H
Now lets look at the libnet_lib.c file. This is the implementation of my custom
libnet library:
#include "libnet_lib.h"
#include <libnet.h>
bool build_ipv4(char *addr, u_int8_t
proto, u_int32_t psize, libnet_t *lnet)
{
u_int32_t target, source;
u_int16_t id;
target = libnet_name2addr4(lnet, addr, LIBNET_DONT_RESOLVE);
source =
libnet_get_ipaddr4(lnet);
if ( source == -1 ) {
printf("Error retrieving IP
address: %s\n",libnet_geterror(lnet));
libnet_destroy(lnet);
return false;
}
libnet_seed_prand (lnet);
id =
(u_int16_t)libnet_get_prand(LIBNET_PR16);
if( libnet_build_ipv4(LIBNET_IPV4_H + psize,
0,
id,
0,
64,
proto,
0,
source,
target,
NULL,
0,
lnet,
0) == -1)
{
printf("Error building IP header:
%s\n",libnet_geterror(lnet));
libnet_destroy(lnet);
return false;
}
return true;
}
bool
write_packet(libnet_t *lnet) {
int bytes_written = libnet_write(lnet);
if ( bytes_written != -1 ) {
printf("%d bytes
written to device %s.\n", bytes_written, libnet_getdevice(lnet));
return true;
} else {
printf("Error
writing packet: %s\n",libnet_geterror(lnet));
return false;
}
}
bool sendICMPEcho(char *addr, char *payload, int type, char *interface)
{
libnet_t *lnet;
u_int16_t id,seq;
char errbuf[LIBNET_ERRBUF_SIZE];
lnet = libnet_init(LIBNET_RAW4, interface, errbuf);
if ( lnet == NULL ) {
printf("Error with
libnet_init(): %s\n", errbuf);
return false;
}
/* Generating a random id */
libnet_seed_prand (lnet);
id = (u_int16_t)libnet_get_prand(LIBNET_PR16);
/* Building ICMP header */
seq = 1;
if (libnet_build_icmpv4_echo(type,
0,
0,
id,
seq,
(u_int8_t*)payload,
sizeof(payload),
lnet,
0) == -1)
{
printf("Error building UDP header:
%s\n",libnet_geterror(lnet));
libnet_destroy(lnet);
return false;
}
if (!build_ipv4 (addr, IPPROTO_ICMP, sizeof(payload) +
LIBNET_ICMPV4_ECHO_H, lnet))
return false;
bool success = write_packet (lnet);
libnet_destroy(lnet);
return success;
}
bool sendTCP(char *addr, int port, u_int8_t
flags, char* payload, char *interface)
{
libnet_t *lnet;
u_int16_t id,seq;
char errbuf[LIBNET_ERRBUF_SIZE];
lnet = libnet_init(LIBNET_RAW4, interface, errbuf);
if ( lnet == NULL ) {
printf("Error with
libnet_init(): %s", errbuf);
return false;
}
/* Generating a random id */
libnet_seed_prand (lnet);
id = (u_int16_t)libnet_get_prand(LIBNET_PR16);
/* Building TCP header */
seq = 1;
if (libnet_build_tcp (libnet_get_prand (LIBNET_PRu16),
port,
0,
0,
flags,
1024,
0,
0,
LIBNET_TCP_H,
(u_int8_t*)payload,
sizeof(payload),
lnet,
0) == -1)
{
printf("Error building TCP header:
%s\n",libnet_geterror(lnet));
libnet_destroy(lnet);
return false;
}
build_ipv4 (addr, IPPROTO_TCP, sizeof(payload) + LIBNET_TCP_H, lnet);
bool success = write_packet (lnet);
libnet_destroy(lnet);
return success;
}
bool sendUDP(char* addr, int port, char *payload, char *interface) {
libnet_t *lnet;
u_int16_t id,seq;
char errbuf[LIBNET_ERRBUF_SIZE];
lnet = libnet_init(LIBNET_RAW4, interface, errbuf);
if ( lnet == NULL ) {
printf("Error with
libnet_init(): %s", errbuf);
return false;
}
/* Generating a random id */
libnet_seed_prand (lnet);
id = (u_int16_t)libnet_get_prand(LIBNET_PR16);
/* Building UDP header */
seq = 1;
if (libnet_build_udp(
libnet_get_prand
(LIBNET_PRu16),
port,
LIBNET_UDP_H+ sizeof(payload),
0,
(u_int8_t*)payload,
sizeof(payload),
lnet,
0) == -1)
{
printf("Error building UDP header:
%s\n",libnet_geterror(lnet));
libnet_destroy(lnet);
return false;
}
build_ipv4 (addr, IPPROTO_UDP, sizeof(payload) + LIBNET_UDP_H, lnet);
bool success = write_packet (lnet);
libnet_destroy(lnet);
return success;
}
Now lets look at the main.c file that will create an ICMP
Echo (ping) packet and a TCP packet.
#include <stdio.h>
#include "libnet_lib.h"
#include "libnet.h"
int main(void)
{
printf("ICMP!\n");
bool success = sendICMPEcho("10.0.1.4", "Hello
from libnet", ICMP_ECHO, "eth0");
if (success) {
printf("Success");
} else {
printf("Failed");
}
printf("\nTCP\n");
bool success1 = sendTCP("10.0.1.4", 3535, TH_SYN|TH_ACK,"Hello
from libnet","eth0");
if (success1) {
printf("Success1");
} else {
printf("Failed1");
}
return 0;
}
To compile this we run the following command:
gcc -I/usr/local/include -o libnettest -lnet libnet_lib.c main.c
If all is well we should have a libnettest executable. If you run libnettest, you should see output
that is similar to this:
To verify that the packets went out correctly, you can run
Wireshark (http://www.wireshark.org) on the host that you are sending the
packets too.
Libnet is a very powerful library that can allow you to
write several really cool networking tools especially if you combine libnet
with libpcap (packet capture library).
One of my favorite tools that I have wrote was a heartbeat application
that was written in Java using jpcap.
This application would send out a bad TCP packet and if it received a
reset packet back from the host, it knew the host was alive. I wrote an article about the application and
it was published in the September 2006 edition of the Unix Sys Admin magazine.
Excellent content, great guidance thank you
ReplyDeleteoracle database jobs
job opportunities for oracle dba