ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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};
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.
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
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.
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.
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.
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;
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:
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;
"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 05:48 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.