LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 11-21-2006, 04:39 AM   #1
arabindav
LQ Newbie
 
Registered: Oct 2006
Posts: 9

Rep: Reputation: 0
Question Raw socket programming with C


Hello All,

I am facing problem with code to send and receive packets using RAW sockets. The packets are layer 2 control packets. Your help in this regard is highly appreciated.

Following is the code used to send the packets:
==============================================================================================
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if_ether.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <netinet/ether.h>

#define ETHERTYPE_LEN 2
#define MAC_ADDR_LEN 6

typedef unsigned char MacAddress[MAC_ADDR_LEN];
extern int errno;

int main()
{
int sockFd = 0, retValue = 0;
char buffer[BUFFER_LEN], dummyBuf[50];
struct sockaddr_ll destAddr;
short int etherTypeT = htons(0x8200);
MacAddress localMac = {0x00, 0x08, 0xA1, 0x8E, 0xE4, 0x52};
MacAddress destMac = {0x00, 0x17, 0x9A, 0xB3, 0x9E, 0x16};

memset(&destAddr, 0, sizeof(struct sockaddr_ll));
memset(buffer, 0, BUFFER_LEN);

if((sockFd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
printf("ERROR! socket() call failed (Error No: %d \"%s\").\n", errno, trerror(errno));
exit(1);
}
printf("Socket creation success.\n");

destAddr.sll_family = htons(PF_PACKET);
destAddr.sll_protocol = htons(ETH_P_ALL);
destAddr.sll_halen = 6;
destAddr.sll_ifindex = 2;
memcpy(&(destAddr.sll_addr), destMac, MAC_ADDR_LEN);

/* Ethernet Header Construction */
memcpy(buffer, localMac, MAC_ADDR_LEN);
memcpy((buffer+MAC_ADDR_LEN), destMac, MAC_ADDR_LEN);
memcpy((buffer+(2*MAC_ADDR_LEN)), &(etherTypeT), sizeof(etherTypeT));

/* Add some data */
memset(dummyBuf, 0xa0, sizeof(dummyBuf));
memcpy((buffer+ETHERTYPE_LEN+(2*MAC_ADDR_LEN)), dummyBuf, 50);

if((retValue = sendto(sockFd, buffer, 64, 0, (struct sockaddr *)&(destAddr), sizeof(struct sockaddr_ll))) < 0) {
printf("ERROR! sendto() call failed (Error No: %d \"%s\").\n", errno, strerror(errno));
exit(1);
}
printf("Send success (%d).\n", retValue);

return(0);
}
==========================================================================================

The queries are as follows:
1. The sll_addr in struct sockaddr_ll is of length 8. Is this where we assign the destination mac address? If yes, why is it 8 bytes not 6 bytes and is the assignment done fine?

2. Is sll_ifindex in struct sockaddr_ll interface index? How to get interface index from the OS?

3. The code executes perfectly ( no errors). However, the packet is not received (using recvfrom) at the destination. Do I have to construct the complete packet from preamble to FCS?

4. What about binding the socket to some address?

Please let me know what is the problem in the above code. I used tcpdump to capture the packet but it does not.

Thanks.

Last edited by arabindav; 11-21-2006 at 04:54 AM.
 
Old 11-21-2006, 11:12 AM   #2
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,396
Blog Entries: 2

Rep: Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903
Have you used a packet sniffer, such as ethereal, or whatever it is called now, to see if the packet actually makes it onto the wire? Are you sure you have permission to transmit at this low level as a non-root user? A quick scan of your source code doesn't reveal anything obvious to me. It is helpful, when posting source code, to wrap the code in
Code:
#include <your source code>
tags to preserve the formatting and readability.

--- rod.

Last edited by theNbomr; 11-21-2006 at 11:16 AM.
 
Old 11-21-2006, 11:24 AM   #3
Shioni
Member
 
Registered: Mar 2006
Posts: 182

Rep: Reputation: 30
You need to be root to use raw sockets!
 
Old 11-21-2006, 10:44 PM   #4
arabindav
LQ Newbie
 
Registered: Oct 2006
Posts: 9

Original Poster
Rep: Reputation: 0
Thanks for your reply.

Yes, I am using tcpdump to check the packet transmission.

The command: tcpdump -n -i eth1 ether dst <destination MAC>

It's not capturing the packet. And yes, I am executing the code and tcpdump command in superuser mode.

Any suggestions?

Arabinda
 
Old 11-23-2006, 01:24 AM   #5
primo
Member
 
Registered: Jun 2005
Posts: 542

Rep: Reputation: 34
There's a SIOCGIFINDEX ioctl() to get interface index. You're better using libpcap. Linux has changed a lot of things through kernel versions to rely on a single way to get packets straight. In some versions you'd get duplicated packets for the loopback interface, etc. Libpcap is surprisingly easy to learn, just try it.
 
Old 12-28-2006, 11:29 AM   #6
Son_of_Merlin
LQ Newbie
 
Registered: Dec 2006
Posts: 6

Rep: Reputation: 0
I'm having exactly the same problem but ...

Hi Arabindav!

I'm having exactly the same problems as you with code that used to work perfectly under my old distro SuSE 8. I'm not an expert (yet) but I can help you with some of your questions:-

1) The sll_addr field in a low level socket address has to accommodate ALL interfaces - not just Ether. So 8 chars are used as other addresses may require more than 6. Your assignment is quite correct. The destination MAC goes into this field starting at location 0.

2) Yes. The sll_ifindex field is the interface index (PCI bus active slot position)+2 of the NIC you are using. Index 0 is the loopback device and 1 is the 'default' device. Real hardware always starts at 2. You can scan your PCI bus using ioctl with SIOCGIFCONF. You need to call it twice. Once to get the size of the result buffer and then again to populate the buffer. I've got working code if you need it.

3) No. You do not need preamble and FCS. This is the bit we both have in common. Are you using Fedora Core by any chance? Like you, I get no errors on transmission (sendto) but nothing valid appears to be leaving my socket. The recipient machine's indicators blink but they do not respond and tcpdump shows nothing leaving my interface.

4) Naming the socket (binding) is not mandatory and will not affect your results. It will only serve to filter out traffic from a specific interface. The sending address (struct sockaddr_ll) is the bit that sets up the link layer - which for RAW PACKET sockets has always had me confused since we are constructing the full protocol stack from Ether right down to application data ourselves complete with header checksums and options!

On another point - you have network-oriented your address family field:

"destAddr.sll_family = htons(PF_PACKET);"

You do not need to do this. The family is host order. It is only network-facing values that need to be in net order.

If you get a working result (and mine always did work under SuSE 8 and prior) please could you let me know.

If you want to see the PCI bus scan I can post it for you but it's rather a lot of kit for one bulletin. It's ever so simple though.

If you get working before me can you let me know what you did - if I before you I'll post the relevant mods here.

Cheers,
SOM
 
Old 10-22-2007, 05:48 AM   #7
can26_manish
LQ Newbie
 
Registered: Oct 2007
Posts: 4

Rep: Reputation: 0
Hi Arabindav,

Is your prob solved. Actually I saw this post and I am doing the same thing. For my case also there is no compilation error but I am not able to capture the packet through ethereal.
I want to ask one thing. I am creating a packet a sending it through interface eth0. If i run ethereal on eth0 will it capture the packet.
 
Old 08-10-2009, 04:10 AM   #8
chandan_raka
Member
 
Registered: Apr 2005
Location: BC
Distribution: Centos
Posts: 34

Rep: Reputation: 16
RAW socket

Hey,

I also used your program and faces similar issue.

However, another version of the similar program atleast sends some data though not in format of tcp dump..

sock=socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
if(sock < 0)
{
perror("socket:");
}

struct ifreq ifReq;
memset(&ifReq, 0, sizeof(ifReq));
strncpy(ifReq.ifr_name, devname, sizeof(ifReq.ifr_name));
if (ioctl(sock,SIOCGIFINDEX,&ifReq)) {
printf("unable to get index\n");
return -1;
}

struct sockaddr_ll sockAddress;
sockAddress.sll_ifindex = ifReq.ifr_ifindex;
sockAddress.sll_family = AF_PACKET;
sockAddress.sll_protocol = htons(ETH_P_IP);
sockAddress.sll_halen = 6;
readmac(sockAddress.sll_addr, destmac);

a = sendto(sock,&buf,len,0,(struct sockaddr*) &sockAddress, sizeof(sockAddress));
if (a < 0)
printf("sendto failed \n");
return a;



here we are reading the MAC from command line..
 
Old 08-10-2009, 01:47 PM   #9
orgcandman
Member
 
Registered: May 2002
Location: dracut MA
Distribution: Ubuntu; PNE-LE; LFS (no book)
Posts: 594

Rep: Reputation: 102Reputation: 102
Code:
/* Ethernet Header Construction */
memcpy(buffer, localMac, MAC_ADDR_LEN);
memcpy((buffer+MAC_ADDR_LEN), destMac, MAC_ADDR_LEN);
memcpy((buffer+(2*MAC_ADDR_LEN)), &(etherTypeT), sizeof(etherTypeT));
This is probably not what you wanted to write. I'll let you peruse the ethernet specification to see why.


Code:
   destAddr.sll_pkttype  = PACKET_OTHERHOST;
I have things working using this.
 
Old 06-08-2011, 04:07 PM   #10
mezo_36
LQ Newbie
 
Registered: Jun 2011
Posts: 4

Rep: Reputation: Disabled
hey guys plz help about my problem i wanna to make a syn scanner with

and this my code but it get me segmentation fault

can any one help me plz



#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<linux/ip.h>
#include<linux/tcp.h>
#include<features.h>
#include<errno.h>

#define SRC_IP "192.168.72.128"
#define DST_IP "192.168.1.1"
#define SRC_PORT 1234

#define SA struct sockaddr

unsigned short ComputeChecksum(unsigned char *data, int len)
{
long sum = 0;
unsigned short *temp = (unsigned short *)data;

while(len>1)
{
sum = *temp++;
if(sum & 0x80000000)
sum = (sum & 0xFFFF) + (sum >> 16);
len -= 2;
}

if(len)
sum = (unsigned short *) *((unsigned char *)temp);

while(sum>>16)
sum = (sum & 0xFFFF) + (sum >> 16);

return ~sum;
}

typedef struct PseudoHeader
{
unsigned long int source;
unsigned long int dest;
unsigned char reserved;
unsigned char protocol;
unsigned short int tcp_len;
}PseudoHeader;

int main(int argc, char **argv)
{
int send_socket;
int pkt_len;
struct iphdr *ip_header;
struct tcphdr *tcp_header;
unsigned char *packet;
unsigned char *psh;
struct sockaddr_in sin;

int range_1;
int range_2 = atoi(argv[1]);

ip_header = (struct iphdr *)packet;
tcp_header = (struct tcphdr *)(packet + sizeof(struct iphdr));
PseudoHeader *pseudo_header;

for(range_1 = 0 ; range_1 < range_2 ; range_1++)
{
sleep(1);
ip_header->version = 4;
ip_header->ihl = (sizeof(struct iphdr))/4;
ip_header->tos = 0;
ip_header->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
ip_header->id = htons(1234);
ip_header->frag_off = 0;
ip_header->ttl = 255;
ip_header->protocol = IPPROTO_TCP;
ip_header->check = 0;
ip_header->saddr = inet_addr(SRC_IP);
ip_header->daddr = inet_addr(DST_IP);

ip_header->check = ComputeChecksum((unsigned char *)ip_header, ip_header->ihl*4);

tcp_header->source = htons(SRC_PORT);
tcp_header->dest = htons(range_1);
tcp_header->seq = htonl(1234);
tcp_header->ack_seq = htonl(4321);
tcp_header->res1 = 0;
tcp_header->doff = (sizeof(struct tcphdr))/4;
tcp_header->syn = 1;
tcp_header->window = htons(512);
tcp_header->check = 0;
tcp_header->urg_ptr = 0;

pseudo_header->source = ip_header->saddr;
pseudo_header->dest = ip_header->daddr;
pseudo_header->reserved = 0;
pseudo_header->protocol = IPPROTO_TCP;
pseudo_header->tcp_len = htons(tcp_header->doff*4);

memcpy(psh, pseudo_header, sizeof(PseudoHeader));
memcpy((psh + sizeof(PseudoHeader)), tcp_header, tcp_header->doff*4);


tcp_header->check = ComputeChecksum(psh, sizeof(psh));

sin.sin_family = AF_INET;
sin.sin_port = tcp_header->dest;
sin.sin_addr.s_addr = ip_header->daddr;

send_socket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if(send_socket == -1)
{
perror("cannot open the socket\n");
exit(-1);
}
pkt_len = ntohs(ip_header->tot_len);

if(sendto(send_socket, packet, pkt_len, 0, (SA *)&sin, sizeof(sin)) == -1)
{
perror("cannot send the packet\n");
exit(-1);
}
else
printf("packet sent to port %d\n", range_1);

close(send_socket);
}
}

plz help realy guys wana to know where my fault
 
Old 06-08-2011, 04:21 PM   #11
primo
Member
 
Registered: Jun 2005
Posts: 542

Rep: Reputation: 34
Your program segfaults because this pointer isn't initialized.

unsigned char *packet;

It must be:

unsigned char packet[IP_MAXPACKET]; /* #define'd in <netinet/ip.h> */
 
Old 06-08-2011, 04:29 PM   #12
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,523

Rep: Reputation: 332Reputation: 332Reputation: 332Reputation: 332
Welcome to LQ.

Rather than resurrect this old thread, you should have thought about creating a new one. Anyhow, it would seem that your first issue is with the following line of code:
Code:
unsigned char *packet;
You will need to allocate space for the packet before you can begin to use it. Try something like:
Code:
unsigned char *packet = malloc(sizeof(struct ip) + sizeof(struct tcphdr) + sizeOfTheData);
I did not see you working with any data (payload), thus I guess it is safe to assume that sizeOfTheData is zero (0) in your case.


P.S. I see that you are using struct iphdr, whereas in code I've developed in the past, I used struct ip.
 
Old 06-08-2011, 06:26 PM   #13
mezo_36
LQ Newbie
 
Registered: Jun 2011
Posts: 4

Rep: Reputation: Disabled
am realy thx you guys realy and hope to keep in touch with us brothers
 
Old 06-09-2011, 05:51 AM   #14
mezo_36
LQ Newbie
 
Registered: Jun 2011
Posts: 4

Rep: Reputation: Disabled
sorry i have another segfault the program seg fault in pseudoheader

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<linux/ip.h>
#include<linux/tcp.h>
#include<features.h>
#include<errno.h>

#define SRC_IP "192.168.72.128"
#define DST_IP "192.168.1.1"
#define SRC_PORT 1234

#define SA struct sockaddr

unsigned short ComputeChecksum(unsigned char *data, int len)
{
long sum = 0;
unsigned short *temp = (unsigned short *)data;

while(len>1)
{
sum = *temp++;
if(sum & 0x80000000)
sum = (sum & 0xFFFF) + (sum >> 16);
len -= 2;
}

if(len)
sum = (unsigned short *) *((unsigned char *)temp);

while(sum>>16)
sum = (sum & 0xFFFF) + (sum >> 16);

return ~sum;
}

typedef struct PseudoHeader
{
unsigned long int source;
unsigned long int dest;
unsigned char reserved;
unsigned char protocol;
unsigned short int tcp_len;
}PseudoHeader;

int main(int argc, char **argv)
{
int send_socket;
int pkt_len;
struct iphdr *ip_header;
struct tcphdr *tcp_header;
unsigned char *packet;
unsigned char *psh;
struct sockaddr_in sin;

int range_1;
int range_2 = atoi(argv[1]);

ip_header = (struct iphdr *)packet;
tcp_header = (struct tcphdr *)(packet + sizeof(struct iphdr));
PseudoHeader *pseudo_header;

for(range_1 = 0 ; range_1 < range_2 ; range_1++)
{
sleep(1);
ip_header->version = 4;
ip_header->ihl = (sizeof(struct iphdr))/4;
ip_header->tos = 0;
ip_header->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
ip_header->id = htons(1234);
ip_header->frag_off = 0;
ip_header->ttl = 255;
ip_header->protocol = IPPROTO_TCP;
ip_header->check = 0;
ip_header->saddr = inet_addr(SRC_IP);
ip_header->daddr = inet_addr(DST_IP);

ip_header->check = ComputeChecksum((unsigned char *)ip_header, ip_header->ihl*4);

tcp_header->source = htons(SRC_PORT);
tcp_header->dest = htons(range_1);
tcp_header->seq = htonl(1234);
tcp_header->ack_seq = htonl(4321);
tcp_header->res1 = 0;
tcp_header->doff = (sizeof(struct tcphdr))/4;
tcp_header->syn = 1;
tcp_header->window = htons(512);
tcp_header->check = 0;
tcp_header->urg_ptr = 0;

pseudo_header->source = ip_header->saddr;
pseudo_header->dest = ip_header->daddr;
pseudo_header->reserved = 0;
pseudo_header->protocol = IPPROTO_TCP;
pseudo_header->tcp_len = htons(tcp_header->doff*4);

memcpy(psh, pseudo_header, sizeof(PseudoHeader));
memcpy((psh + sizeof(PseudoHeader)), tcp_header, tcp_header->doff*4);


tcp_header->check = ComputeChecksum(psh, sizeof(psh));

sin.sin_family = AF_INET;
sin.sin_port = tcp_header->dest;
sin.sin_addr.s_addr = ip_header->daddr;

send_socket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if(send_socket == -1)
{
perror("cannot open the socket\n");
exit(-1);
}
pkt_len = ntohs(ip_header->tot_len);

if(sendto(send_socket, packet, pkt_len, 0, (SA *)&sin, sizeof(sin)) == -1)
{
perror("cannot send the packet\n");
exit(-1);
}
else
printf("packet sent to port %d\n", range_1);

close(send_socket);
}
}
 
Old 06-09-2011, 06:46 AM   #15
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,523

Rep: Reputation: 332Reputation: 332Reputation: 332Reputation: 332
"Give a person a fish, and you feed them for the night. Teach them to fish, and you feed them for a lifetime."


It appears that you did not learn anything from the previous problem you had; it is identical to your new one.
Code:
PseudoHeader *pseudo_header;
You need to allocate space for the pseudo_header, either on the heap or on the stack.

P.S. IMHO, you should take a step back from playing with raw sockets, and learn the basics of C programming first. I still see the same error (first one you had) in the latest code you posted.

Last edited by dwhitney67; 06-09-2011 at 06:48 AM.
 
  


Reply

Tags
socket


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
raw socket/ip packet help shouup Programming 14 04-24-2006 05:54 PM
Raw socket with perl Whiteghost Linux - General 1 10-14-2005 11:29 AM
Help with raw socket programming tuxfood Programming 2 07-25-2005 02:17 PM
Raw Socket Programing djgerbavore Programming 2 08-18-2004 01:58 PM
Socket Raw linuxanswer Programming 1 04-01-2004 10:43 PM


All times are GMT -5. The time now is 08:51 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration