PDA

View Full Version : Raw networking library


penguin_to_bits
02-29-2008, 01:37 AM
I've been programming in C and C++ for some time but I'm new to network programming.

I started using Berkeley sockets today and I managed to handcraft my own ethernet frames (i.e. I was able to send a raw byte buffer). I was playing around with sending arp request and arp replies today, and I got it working.

Before I go any further with Berkeley sockets tho, I'd like to make sure that it's the best choice. I've heard that a lot of programs, such as nmap, use pcap. Which one's better, pcap or Berkeley? I suppose I should be more specific -- these are the criteria I'm looking at:
1) Portability (I hear Berkeley is the most portable... that right?)
2) Best at low-level stuff (e.g. handcrafting your own Ethernet frames)
3) Best at high-level stuff (e.g. communicating over TCP)

I found some sample code on the web for sending raw ethernet frames with Berkeley, and I took hints from it to write my own code. The following is the code I produced for sending arp requests and replies. If anyone here is familiar with Berkeley, I'd like to ask why I have to make a call to "ioctl" to get the index of the NIC? I mean, the socket's already open, so why should I need the index of the NIC? (I've tried doing it without getting the NIC's index and it doesn't work)

Here's my code, maybe someone can enlighten me on how I can do it better:

#include <stdlib.h> /* EXIT_FAILURE */
#include <string.h> /* memcpy, memset */
#include <stdio.h> /* puts */

#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>
#include <netpacket/packet.h>

typedef char unsigned uint8;

typedef struct HeaderFrame {
uint8 dest[6], src[6], proto[2];
} HeaderFrame;

typedef struct HeaderARP {
uint8 hard_type[2],
proto_type[2],
hard_len,
proto_len,
op[2],
src_MAC[6],
src_IP[4],
dest_MAC[6],
dest_IP[4];
} HeaderARP;

typedef struct EntireARPFrame {
HeaderFrame hframe;
HeaderARP harp;
} EntireARPFrame;

void SetCommonARPFields(EntireARPFrame *const p)
{
# define frame (p->hframe)
# define arp (p->harp)

frame.proto[0] = 0x08; frame.proto[1] = 0x06;

arp.hard_type[0] = 0x00; arp.hard_type[1] = 0x01;
arp.proto_type[0] = 0x08; arp.proto_type[1] = 0x00;
arp.hard_len = 6;
arp.proto_len = 4;
arp.op[0] = 0x00;

# undef frame
# undef arp
}

void SendARPRequest(int const s, struct sockaddr_ll const *const nic_dev,
uint8 const (*const pdest_IP)[4],
uint8 const (*const psrc_IP)[4],
uint8 const (*const psrc_MAC)[6])
{
EntireARPFrame eaf;

SetCommonARPFields(&eaf);

# define frame (eaf.hframe)
# define arp (eaf.harp)

memset(frame.dest,0xFF,sizeof frame.dest);
memcpy(frame.src,psrc_MAC,sizeof frame.src);

arp.op[1] = 0x01; /* 1 == Request */

memcpy(arp.src_MAC,psrc_MAC,sizeof arp.src_MAC);
memcpy(arp.src_IP,psrc_IP,sizeof arp.src_IP);
memset(arp.dest_MAC,0x00,sizeof arp.dest_MAC);
memcpy(arp.dest_IP,pdest_IP,sizeof arp.dest_IP);

# undef frame
# undef arp

puts("Sending frame");
sendto(s, &eaf, sizeof eaf, 0, (struct sockaddr const*)nic_dev,sizeof *nic_dev);
puts("Frame sent");
}

void SendARPReply(int const s, struct sockaddr_ll const *const nic_dev,
uint8 const (*const pdest_IP)[4],
uint8 const (*const pdest_MAC)[6],
uint8 const (*const psrc_IP)[4],
uint8 const (*const psrc_MAC)[6])
{
EntireARPFrame eaf;

SetCommonARPFields(&eaf);

# define frame (eaf.hframe)
# define arp (eaf.harp)

memcpy(frame.dest,pdest_MAC,sizeof frame.dest);
memcpy(frame.src,psrc_MAC,sizeof frame.src);

arp.op[1] = 0x02; /* 2 == reply */

memcpy(arp.src_MAC,psrc_MAC,sizeof arp.src_MAC);
memcpy(arp.src_IP,psrc_IP,sizeof arp.src_IP);
memcpy(arp.dest_MAC,pdest_MAC,sizeof arp.dest_MAC);
memcpy(arp.dest_IP,pdest_IP,sizeof arp.dest_IP);

# undef frame
# undef arp

puts("Sending frame");
sendto(s, &eaf, sizeof eaf, 0, (struct sockaddr const*)nic_dev,sizeof *nic_dev);
//sendto(s,&eaf,sizeof eaf,0,0,0);
puts("Frame sent");
}

void PrepareDevice(int const s,struct sockaddr_ll *const p)
{
# define device (*p)

//uint8 const src_MAC[6] = {0x00,0x19,0xE0,0x68,0x8A,0x71};
//uint8 const src_MAC[6] = {0xEE,0x01,0x02,0x03,0x04,0x05};

struct ifreq card;

strcpy(card.ifr_name, "rausb0");

puts("Attempting to get NIC index");

if (-1 == ioctl(s, SIOCGIFINDEX, &card)) return;

puts("Got NIC index");

memset(&device, 0, sizeof device);

device.sll_ifindex = card.ifr_ifindex;
//device.sll_family = AF_PACKET;
//memcpy(device.sll_addr, src_MAC, 6);
//device.sll_halen = htons(6);

/* I commented the above crap out coz it turned out I didn't need it */

# undef device
}

uint8 const src_MAC[6] = {0x00,0x19,0xE0,0x78,0x7D,0x82};
uint8 const dest_MAC[6] = {0x00,0x19,0xE0,0x64,0xBB,0x32};
uint8 src_IP[4] = {10,9,8,35};
uint8 dest_IP[4] = {10,9,8,1};

int main(void)
{
struct sockaddr_ll nic_dev = {0};

int s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

puts("Attempting to open socket");

if (s < 0) return EXIT_FAILURE;

puts("Socket is open");

PrepareDevice(s,&nic_dev);

for (src_IP[3] = 100; 255 != dest_IP[3]; ++dest_IP[3])
{
if (35 == dest_IP[3]) continue;

SendARPReply(s,&nic_dev,&dest_IP,&dest_MAC,&src_IP,&src_MAC);
}

return 0;
}

Don't mind the code I wrote in main, what I'm curious about is whether I went about writing the other functions correctly.

Thanks for reading!

MOD EDIT: please use code tags

shamanvirtuel
02-29-2008, 01:23 PM
you may used pcapy+impacket decoder

that's free py apis from core security

penguin_to_bits
02-29-2008, 07:10 PM
Berkeley sockets lets me write my own Ethernet frames, and when I send these over a wireless NIC they get encapsulated in 802.11 frames.

Is there any networking library that will let me write my own 802.11 frames, for instance so that I can send out beacon frames?

Thorn
02-29-2008, 07:35 PM
Berkeley sockets lets me write my own Ethernet frames, and when I send these over a wireless NIC they get encapsulated in 802.11 frames.As they are supposed to; this is the way it works, by design.

Is there any networking library that will let me write my own 802.11 frames, for instance so that I can send out beacon frames?Here's one:

http://nixbit.com/cat/programming/libraries/libradiate/

Googling for "802.11 frames programming" and similar terms will no doubt generate more possibilities for you.

penguin_to_bits
02-29-2008, 08:35 PM
Thanks for the link Thorn, I had a little look at it. Unfortunately, that particular library only works on Linux and also only works with one kind of chipset.

Is there any cross-platform wireless library that will work with pretty much any wireless card, one which will allow me to shape my own 802.11 frames?